1/* 2 * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets 3 * 4 * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com> 5 * 6 * Contributors (thanks, all!) 7 * 8 * David Eger: 9 * Overhaul for Linux 2.6 10 * 11 * Jeff Rugen: 12 * Major contributions; Motorola PowerStack (PPC and PCI) support, 13 * GD54xx, 1280x1024 mode support, change MCLK based on VCLK. 14 * 15 * Geert Uytterhoeven: 16 * Excellent code review. 17 * 18 * Lars Hecking: 19 * Amiga updates and testing. 20 * 21 * Original cirrusfb author: Frank Neumann 22 * 23 * Based on retz3fb.c and cirrusfb.c: 24 * Copyright (C) 1997 Jes Sorensen 25 * Copyright (C) 1996 Frank Neumann 26 * 27 *************************************************************** 28 * 29 * Format this code with GNU indent '-kr -i8 -pcs' options. 30 * 31 * This file is subject to the terms and conditions of the GNU General Public 32 * License. See the file COPYING in the main directory of this archive 33 * for more details. 34 * 35 */ 36 37#define CIRRUSFB_VERSION "2.0-pre2" 38 39#include <linux/module.h> 40#include <linux/kernel.h> 41#include <linux/errno.h> 42#include <linux/string.h> 43#include <linux/mm.h> 44#include <linux/slab.h> 45#include <linux/delay.h> 46#include <linux/fb.h> 47#include <linux/init.h> 48#include <linux/selection.h> 49#include <asm/pgtable.h> 50 51#ifdef CONFIG_ZORRO 52#include <linux/zorro.h> 53#endif 54#ifdef CONFIG_PCI 55#include <linux/pci.h> 56#endif 57#ifdef CONFIG_AMIGA 58#include <asm/amigahw.h> 59#endif 60#ifdef CONFIG_PPC_PREP 61#include <asm/machdep.h> 62#define isPReP (machine_is(prep)) 63#else 64#define isPReP 0 65#endif 66 67#include "video/vga.h" 68#include "video/cirrus.h" 69 70 71/***************************************************************** 72 * 73 * debugging and utility macros 74 * 75 */ 76 77/* enable debug output? */ 78/* #define CIRRUSFB_DEBUG 1 */ 79 80/* disable runtime assertions? */ 81/* #define CIRRUSFB_NDEBUG */ 82 83/* debug output */ 84#ifdef CIRRUSFB_DEBUG 85#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) 86#else 87#define DPRINTK(fmt, args...) 88#endif 89 90/* debugging assertions */ 91#ifndef CIRRUSFB_NDEBUG 92#define assert(expr) \ 93 if(!(expr)) { \ 94 printk( "Assertion failed! %s,%s,%s,line=%d\n",\ 95 #expr,__FILE__,__FUNCTION__,__LINE__); \ 96 } 97#else 98#define assert(expr) 99#endif 100 101#define MB_ (1024*1024) 102#define KB_ (1024) 103 104#define MAX_NUM_BOARDS 7 105 106 107/***************************************************************** 108 * 109 * chipset information 110 * 111 */ 112 113/* board types */ 114typedef enum { 115 BT_NONE = 0, 116 BT_SD64, 117 BT_PICCOLO, 118 BT_PICASSO, 119 BT_SPECTRUM, 120 BT_PICASSO4, /* GD5446 */ 121 BT_ALPINE, /* GD543x/4x */ 122 BT_GD5480, 123 BT_LAGUNA, /* GD546x */ 124} cirrusfb_board_t; 125 126 127/* 128 * per-board-type information, used for enumerating and abstracting 129 * chip-specific information 130 * NOTE: MUST be in the same order as cirrusfb_board_t in order to 131 * use direct indexing on this array 132 * NOTE: '__initdata' cannot be used as some of this info 133 * is required at runtime. Maybe separate into an init-only and 134 * a run-time table? 135 */ 136static const struct cirrusfb_board_info_rec { 137 char *name; /* ASCII name of chipset */ 138 long maxclock[5]; /* maximum video clock */ 139 /* for 1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */ 140 bool init_sr07 : 1; /* init SR07 during init_vgachip() */ 141 bool init_sr1f : 1; /* write SR1F during init_vgachip() */ 142 bool scrn_start_bit19 : 1; /* construct bit 19 of screen start address */ 143 144 /* initial SR07 value, then for each mode */ 145 unsigned char sr07; 146 unsigned char sr07_1bpp; 147 unsigned char sr07_1bpp_mux; 148 unsigned char sr07_8bpp; 149 unsigned char sr07_8bpp_mux; 150 151 unsigned char sr1f; /* SR1F VGA initial register value */ 152} cirrusfb_board_info[] = { 153 [BT_SD64] = { 154 .name = "CL SD64", 155 .maxclock = { 156 /* guess */ 157 /* the SD64/P4 have a higher max. videoclock */ 158 140000, 140000, 140000, 140000, 140000, 159 }, 160 .init_sr07 = true, 161 .init_sr1f = true, 162 .scrn_start_bit19 = true, 163 .sr07 = 0xF0, 164 .sr07_1bpp = 0xF0, 165 .sr07_8bpp = 0xF1, 166 .sr1f = 0x20 167 }, 168 [BT_PICCOLO] = { 169 .name = "CL Piccolo", 170 .maxclock = { 171 /* guess */ 172 90000, 90000, 90000, 90000, 90000 173 }, 174 .init_sr07 = true, 175 .init_sr1f = true, 176 .scrn_start_bit19 = false, 177 .sr07 = 0x80, 178 .sr07_1bpp = 0x80, 179 .sr07_8bpp = 0x81, 180 .sr1f = 0x22 181 }, 182 [BT_PICASSO] = { 183 .name = "CL Picasso", 184 .maxclock = { 185 /* guess */ 186 90000, 90000, 90000, 90000, 90000 187 }, 188 .init_sr07 = true, 189 .init_sr1f = true, 190 .scrn_start_bit19 = false, 191 .sr07 = 0x20, 192 .sr07_1bpp = 0x20, 193 .sr07_8bpp = 0x21, 194 .sr1f = 0x22 195 }, 196 [BT_SPECTRUM] = { 197 .name = "CL Spectrum", 198 .maxclock = { 199 /* guess */ 200 90000, 90000, 90000, 90000, 90000 201 }, 202 .init_sr07 = true, 203 .init_sr1f = true, 204 .scrn_start_bit19 = false, 205 .sr07 = 0x80, 206 .sr07_1bpp = 0x80, 207 .sr07_8bpp = 0x81, 208 .sr1f = 0x22 209 }, 210 [BT_PICASSO4] = { 211 .name = "CL Picasso4", 212 .maxclock = { 213 135100, 135100, 85500, 85500, 0 214 }, 215 .init_sr07 = true, 216 .init_sr1f = false, 217 .scrn_start_bit19 = true, 218 .sr07 = 0x20, 219 .sr07_1bpp = 0x20, 220 .sr07_8bpp = 0x21, 221 .sr1f = 0 222 }, 223 [BT_ALPINE] = { 224 .name = "CL Alpine", 225 .maxclock = { 226 /* for the GD5430. GD5446 can do more... */ 227 85500, 85500, 50000, 28500, 0 228 }, 229 .init_sr07 = true, 230 .init_sr1f = true, 231 .scrn_start_bit19 = true, 232 .sr07 = 0xA0, 233 .sr07_1bpp = 0xA1, 234 .sr07_1bpp_mux = 0xA7, 235 .sr07_8bpp = 0xA1, 236 .sr07_8bpp_mux = 0xA7, 237 .sr1f = 0x1C 238 }, 239 [BT_GD5480] = { 240 .name = "CL GD5480", 241 .maxclock = { 242 135100, 200000, 200000, 135100, 135100 243 }, 244 .init_sr07 = true, 245 .init_sr1f = true, 246 .scrn_start_bit19 = true, 247 .sr07 = 0x10, 248 .sr07_1bpp = 0x11, 249 .sr07_8bpp = 0x11, 250 .sr1f = 0x1C 251 }, 252 [BT_LAGUNA] = { 253 .name = "CL Laguna", 254 .maxclock = { 255 /* guess */ 256 135100, 135100, 135100, 135100, 135100, 257 }, 258 .init_sr07 = false, 259 .init_sr1f = false, 260 .scrn_start_bit19 = true, 261 } 262}; 263 264 265#ifdef CONFIG_PCI 266#define CHIP(id, btype) \ 267 { PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) } 268 269static struct pci_device_id cirrusfb_pci_table[] = { 270 CHIP( PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE ), 271 CHIP( PCI_DEVICE_ID_CIRRUS_5434_8, BT_ALPINE ), 272 CHIP( PCI_DEVICE_ID_CIRRUS_5434_4, BT_ALPINE ), 273 CHIP( PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE ), /* GD-5440 is same id */ 274 CHIP( PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE ), 275 CHIP( PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE ), 276 CHIP( PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480 ), /* MacPicasso likely */ 277 CHIP( PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4 ), /* Picasso 4 is 5446 */ 278 CHIP( PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA ), /* CL Laguna */ 279 CHIP( PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA ), /* CL Laguna 3D */ 280 CHIP( PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNA ), /* CL Laguna 3DA*/ 281 { 0, } 282}; 283MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table); 284#undef CHIP 285#endif /* CONFIG_PCI */ 286 287 288#ifdef CONFIG_ZORRO 289static const struct zorro_device_id cirrusfb_zorro_table[] = { 290 { 291 .id = ZORRO_PROD_HELFRICH_SD64_RAM, 292 .driver_data = BT_SD64, 293 }, { 294 .id = ZORRO_PROD_HELFRICH_PICCOLO_RAM, 295 .driver_data = BT_PICCOLO, 296 }, { 297 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM, 298 .driver_data = BT_PICASSO, 299 }, { 300 .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM, 301 .driver_data = BT_SPECTRUM, 302 }, { 303 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3, 304 .driver_data = BT_PICASSO4, 305 }, 306 { 0 } 307}; 308 309static const struct { 310 zorro_id id2; 311 unsigned long size; 312} cirrusfb_zorro_table2[] = { 313 [BT_SD64] = { 314 .id2 = ZORRO_PROD_HELFRICH_SD64_REG, 315 .size = 0x400000 316 }, 317 [BT_PICCOLO] = { 318 .id2 = ZORRO_PROD_HELFRICH_PICCOLO_REG, 319 .size = 0x200000 320 }, 321 [BT_PICASSO] = { 322 .id2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG, 323 .size = 0x200000 324 }, 325 [BT_SPECTRUM] = { 326 .id2 = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG, 327 .size = 0x200000 328 }, 329 [BT_PICASSO4] = { 330 .id2 = 0, 331 .size = 0x400000 332 } 333}; 334#endif /* CONFIG_ZORRO */ 335 336 337struct cirrusfb_regs { 338 __u32 line_length; /* in BYTES! */ 339 __u32 visual; 340 __u32 type; 341 342 long freq; 343 long nom; 344 long den; 345 long div; 346 long multiplexing; 347 long mclk; 348 long divMCLK; 349 350 long HorizRes; /* The x resolution in pixel */ 351 long HorizTotal; 352 long HorizDispEnd; 353 long HorizBlankStart; 354 long HorizBlankEnd; 355 long HorizSyncStart; 356 long HorizSyncEnd; 357 358 long VertRes; /* the physical y resolution in scanlines */ 359 long VertTotal; 360 long VertDispEnd; 361 long VertSyncStart; 362 long VertSyncEnd; 363 long VertBlankStart; 364 long VertBlankEnd; 365}; 366 367 368 369#ifdef CIRRUSFB_DEBUG 370typedef enum { 371 CRT, 372 SEQ 373} cirrusfb_dbg_reg_class_t; 374#endif /* CIRRUSFB_DEBUG */ 375 376 377 378 379/* info about board */ 380struct cirrusfb_info { 381 struct fb_info *info; 382 383 u8 __iomem *fbmem; 384 u8 __iomem *regbase; 385 u8 __iomem *mem; 386 unsigned long size; 387 cirrusfb_board_t btype; 388 unsigned char SFR; /* Shadow of special function register */ 389 390 unsigned long fbmem_phys; 391 unsigned long fbregs_phys; 392 393 struct cirrusfb_regs currentmode; 394 int blank_mode; 395 396 u32 pseudo_palette[16]; 397 struct { u8 red, green, blue, pad; } palette[256]; 398 399#ifdef CONFIG_ZORRO 400 struct zorro_dev *zdev; 401#endif 402#ifdef CONFIG_PCI 403 struct pci_dev *pdev; 404#endif 405 void (*unmap)(struct cirrusfb_info *cinfo); 406}; 407 408 409static unsigned cirrusfb_def_mode = 1; 410static int noaccel = 0; 411 412/* 413 * Predefined Video Modes 414 */ 415 416static const struct { 417 const char *name; 418 struct fb_var_screeninfo var; 419} cirrusfb_predefined[] = { 420 { 421 /* autodetect mode */ 422 .name = "Autodetect", 423 }, { 424 /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */ 425 .name = "640x480", 426 .var = { 427 .xres = 640, 428 .yres = 480, 429 .xres_virtual = 640, 430 .yres_virtual = 480, 431 .bits_per_pixel = 8, 432 .red = { .length = 8 }, 433 .green = { .length = 8 }, 434 .blue = { .length = 8 }, 435 .width = -1, 436 .height = -1, 437 .pixclock = 40000, 438 .left_margin = 48, 439 .right_margin = 16, 440 .upper_margin = 32, 441 .lower_margin = 8, 442 .hsync_len = 96, 443 .vsync_len = 4, 444 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 445 .vmode = FB_VMODE_NONINTERLACED 446 } 447 }, { 448 /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */ 449 .name = "800x600", 450 .var = { 451 .xres = 800, 452 .yres = 600, 453 .xres_virtual = 800, 454 .yres_virtual = 600, 455 .bits_per_pixel = 8, 456 .red = { .length = 8 }, 457 .green = { .length = 8 }, 458 .blue = { .length = 8 }, 459 .width = -1, 460 .height = -1, 461 .pixclock = 20000, 462 .left_margin = 128, 463 .right_margin = 16, 464 .upper_margin = 24, 465 .lower_margin = 2, 466 .hsync_len = 96, 467 .vsync_len = 6, 468 .vmode = FB_VMODE_NONINTERLACED 469 } 470 }, { 471 /* 472 * Modeline from XF86Config: 473 * Mode "1024x768" 80 1024 1136 1340 1432 768 770 774 805 474 */ 475 /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */ 476 .name = "1024x768", 477 .var = { 478 .xres = 1024, 479 .yres = 768, 480 .xres_virtual = 1024, 481 .yres_virtual = 768, 482 .bits_per_pixel = 8, 483 .red = { .length = 8 }, 484 .green = { .length = 8 }, 485 .blue = { .length = 8 }, 486 .width = -1, 487 .height = -1, 488 .pixclock = 12500, 489 .left_margin = 144, 490 .right_margin = 32, 491 .upper_margin = 30, 492 .lower_margin = 2, 493 .hsync_len = 192, 494 .vsync_len = 6, 495 .vmode = FB_VMODE_NONINTERLACED 496 } 497 } 498}; 499 500#define NUM_TOTAL_MODES ARRAY_SIZE(cirrusfb_predefined) 501 502/****************************************************************************/ 503/**** BEGIN PROTOTYPES ******************************************************/ 504 505 506/*--- Interface used by the world ------------------------------------------*/ 507static int cirrusfb_init (void); 508#ifndef MODULE 509static int cirrusfb_setup (char *options); 510#endif 511 512static int cirrusfb_open (struct fb_info *info, int user); 513static int cirrusfb_release (struct fb_info *info, int user); 514static int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green, 515 unsigned blue, unsigned transp, 516 struct fb_info *info); 517static int cirrusfb_check_var (struct fb_var_screeninfo *var, 518 struct fb_info *info); 519static int cirrusfb_set_par (struct fb_info *info); 520static int cirrusfb_pan_display (struct fb_var_screeninfo *var, 521 struct fb_info *info); 522static int cirrusfb_blank (int blank_mode, struct fb_info *info); 523static void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *region); 524static void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); 525static void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image); 526 527/* function table of the above functions */ 528static struct fb_ops cirrusfb_ops = { 529 .owner = THIS_MODULE, 530 .fb_open = cirrusfb_open, 531 .fb_release = cirrusfb_release, 532 .fb_setcolreg = cirrusfb_setcolreg, 533 .fb_check_var = cirrusfb_check_var, 534 .fb_set_par = cirrusfb_set_par, 535 .fb_pan_display = cirrusfb_pan_display, 536 .fb_blank = cirrusfb_blank, 537 .fb_fillrect = cirrusfb_fillrect, 538 .fb_copyarea = cirrusfb_copyarea, 539 .fb_imageblit = cirrusfb_imageblit, 540}; 541 542/*--- Hardware Specific Routines -------------------------------------------*/ 543static int cirrusfb_decode_var (const struct fb_var_screeninfo *var, 544 struct cirrusfb_regs *regs, 545 const struct fb_info *info); 546/*--- Internal routines ----------------------------------------------------*/ 547static void init_vgachip (struct cirrusfb_info *cinfo); 548static void switch_monitor (struct cirrusfb_info *cinfo, int on); 549static void WGen (const struct cirrusfb_info *cinfo, 550 int regnum, unsigned char val); 551static unsigned char RGen (const struct cirrusfb_info *cinfo, int regnum); 552static void AttrOn (const struct cirrusfb_info *cinfo); 553static void WHDR (const struct cirrusfb_info *cinfo, unsigned char val); 554static void WSFR (struct cirrusfb_info *cinfo, unsigned char val); 555static void WSFR2 (struct cirrusfb_info *cinfo, unsigned char val); 556static void WClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red, 557 unsigned char green, 558 unsigned char blue); 559static void cirrusfb_WaitBLT (u8 __iomem *regbase); 560static void cirrusfb_BitBLT (u8 __iomem *regbase, int bits_per_pixel, 561 u_short curx, u_short cury, 562 u_short destx, u_short desty, 563 u_short width, u_short height, 564 u_short line_length); 565static void cirrusfb_RectFill (u8 __iomem *regbase, int bits_per_pixel, 566 u_short x, u_short y, 567 u_short width, u_short height, 568 u_char color, u_short line_length); 569 570static void bestclock (long freq, long *best, 571 long *nom, long *den, 572 long *div, long maxfreq); 573 574#ifdef CIRRUSFB_DEBUG 575static void cirrusfb_dump (void); 576static void cirrusfb_dbg_reg_dump (caddr_t regbase); 577static void cirrusfb_dbg_print_regs (caddr_t regbase, cirrusfb_dbg_reg_class_t reg_class,...); 578static void cirrusfb_dbg_print_byte (const char *name, unsigned char val); 579#endif /* CIRRUSFB_DEBUG */ 580 581/*** END PROTOTYPES ********************************************************/ 582/*****************************************************************************/ 583/*** BEGIN Interface Used by the World ***************************************/ 584 585static int opencount = 0; 586 587/*--- Open /dev/fbx ---------------------------------------------------------*/ 588static int cirrusfb_open (struct fb_info *info, int user) 589{ 590 if (opencount++ == 0) 591 switch_monitor (info->par, 1); 592 return 0; 593} 594 595/*--- Close /dev/fbx --------------------------------------------------------*/ 596static int cirrusfb_release (struct fb_info *info, int user) 597{ 598 if (--opencount == 0) 599 switch_monitor (info->par, 0); 600 return 0; 601} 602 603/**** END Interface used by the World *************************************/ 604/****************************************************************************/ 605/**** BEGIN Hardware specific Routines **************************************/ 606 607/* Get a good MCLK value */ 608static long cirrusfb_get_mclk (long freq, int bpp, long *div) 609{ 610 long mclk; 611 612 assert (div != NULL); 613 614 /* Calculate MCLK, in case VCLK is high enough to require > 50MHz. 615 * Assume a 64-bit data path for now. The formula is: 616 * ((B * PCLK * 2)/W) * 1.2 617 * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */ 618 mclk = ((bpp / 8) * freq * 2) / 4; 619 mclk = (mclk * 12) / 10; 620 if (mclk < 50000) 621 mclk = 50000; 622 DPRINTK ("Use MCLK of %ld kHz\n", mclk); 623 624 /* Calculate value for SR1F. Multiply by 2 so we can round up. */ 625 mclk = ((mclk * 16) / 14318); 626 mclk = (mclk + 1) / 2; 627 DPRINTK ("Set SR1F[5:0] to 0x%lx\n", mclk); 628 629 /* Determine if we should use MCLK instead of VCLK, and if so, what we 630 * should divide it by to get VCLK */ 631 switch (freq) { 632 case 24751 ... 25249: 633 *div = 2; 634 DPRINTK ("Using VCLK = MCLK/2\n"); 635 break; 636 case 49501 ... 50499: 637 *div = 1; 638 DPRINTK ("Using VCLK = MCLK\n"); 639 break; 640 default: 641 *div = 0; 642 break; 643 } 644 645 return mclk; 646} 647 648static int cirrusfb_check_var(struct fb_var_screeninfo *var, 649 struct fb_info *info) 650{ 651 struct cirrusfb_info *cinfo = info->par; 652 int nom, den; /* translyting from pixels->bytes */ 653 int yres, i; 654 static struct { int xres, yres; } modes[] = 655 { { 1600, 1280 }, 656 { 1280, 1024 }, 657 { 1024, 768 }, 658 { 800, 600 }, 659 { 640, 480 }, 660 { -1, -1 } }; 661 662 switch (var->bits_per_pixel) { 663 case 0 ... 1: 664 var->bits_per_pixel = 1; 665 nom = 4; 666 den = 8; 667 break; /* 8 pixel per byte, only 1/4th of mem usable */ 668 case 2 ... 8: 669 var->bits_per_pixel = 8; 670 nom = 1; 671 den = 1; 672 break; /* 1 pixel == 1 byte */ 673 case 9 ... 16: 674 var->bits_per_pixel = 16; 675 nom = 2; 676 den = 1; 677 break; /* 2 bytes per pixel */ 678 case 17 ... 24: 679 var->bits_per_pixel = 24; 680 nom = 3; 681 den = 1; 682 break; /* 3 bytes per pixel */ 683 case 25 ... 32: 684 var->bits_per_pixel = 32; 685 nom = 4; 686 den = 1; 687 break; /* 4 bytes per pixel */ 688 default: 689 printk ("cirrusfb: mode %dx%dx%d rejected...color depth not supported.\n", 690 var->xres, var->yres, var->bits_per_pixel); 691 DPRINTK ("EXIT - EINVAL error\n"); 692 return -EINVAL; 693 } 694 695 if (var->xres * nom / den * var->yres > cinfo->size) { 696 printk ("cirrusfb: mode %dx%dx%d rejected...resolution too high to fit into video memory!\n", 697 var->xres, var->yres, var->bits_per_pixel); 698 DPRINTK ("EXIT - EINVAL error\n"); 699 return -EINVAL; 700 } 701 702 /* use highest possible virtual resolution */ 703 if (var->xres_virtual == -1 && 704 var->yres_virtual == -1) { 705 printk ("cirrusfb: using maximum available virtual resolution\n"); 706 for (i = 0; modes[i].xres != -1; i++) { 707 if (modes[i].xres * nom / den * modes[i].yres < cinfo->size / 2) 708 break; 709 } 710 if (modes[i].xres == -1) { 711 printk ("cirrusfb: could not find a virtual resolution that fits into video memory!!\n"); 712 DPRINTK ("EXIT - EINVAL error\n"); 713 return -EINVAL; 714 } 715 var->xres_virtual = modes[i].xres; 716 var->yres_virtual = modes[i].yres; 717 718 printk ("cirrusfb: virtual resolution set to maximum of %dx%d\n", 719 var->xres_virtual, var->yres_virtual); 720 } 721 722 if (var->xres_virtual < var->xres) 723 var->xres_virtual = var->xres; 724 if (var->yres_virtual < var->yres) 725 var->yres_virtual = var->yres; 726 727 if (var->xoffset < 0) 728 var->xoffset = 0; 729 if (var->yoffset < 0) 730 var->yoffset = 0; 731 732 /* truncate xoffset and yoffset to maximum if too high */ 733 if (var->xoffset > var->xres_virtual - var->xres) 734 var->xoffset = var->xres_virtual - var->xres - 1; 735 if (var->yoffset > var->yres_virtual - var->yres) 736 var->yoffset = var->yres_virtual - var->yres - 1; 737 738 switch (var->bits_per_pixel) { 739 case 1: 740 var->red.offset = 0; 741 var->red.length = 1; 742 var->green.offset = 0; 743 var->green.length = 1; 744 var->blue.offset = 0; 745 var->blue.length = 1; 746 break; 747 748 case 8: 749 var->red.offset = 0; 750 var->red.length = 6; 751 var->green.offset = 0; 752 var->green.length = 6; 753 var->blue.offset = 0; 754 var->blue.length = 6; 755 break; 756 757 case 16: 758 if(isPReP) { 759 var->red.offset = 2; 760 var->green.offset = -3; 761 var->blue.offset = 8; 762 } else { 763 var->red.offset = 10; 764 var->green.offset = 5; 765 var->blue.offset = 0; 766 } 767 var->red.length = 5; 768 var->green.length = 5; 769 var->blue.length = 5; 770 break; 771 772 case 24: 773 if(isPReP) { 774 var->red.offset = 8; 775 var->green.offset = 16; 776 var->blue.offset = 24; 777 } else { 778 var->red.offset = 16; 779 var->green.offset = 8; 780 var->blue.offset = 0; 781 } 782 var->red.length = 8; 783 var->green.length = 8; 784 var->blue.length = 8; 785 break; 786 787 case 32: 788 if(isPReP) { 789 var->red.offset = 8; 790 var->green.offset = 16; 791 var->blue.offset = 24; 792 } else { 793 var->red.offset = 16; 794 var->green.offset = 8; 795 var->blue.offset = 0; 796 } 797 var->red.length = 8; 798 var->green.length = 8; 799 var->blue.length = 8; 800 break; 801 802 default: 803 DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel); 804 assert(false); 805 /* should never occur */ 806 break; 807 } 808 809 var->red.msb_right = 810 var->green.msb_right = 811 var->blue.msb_right = 812 var->transp.offset = 813 var->transp.length = 814 var->transp.msb_right = 0; 815 816 yres = var->yres; 817 if (var->vmode & FB_VMODE_DOUBLE) 818 yres *= 2; 819 else if (var->vmode & FB_VMODE_INTERLACED) 820 yres = (yres + 1) / 2; 821 822 if (yres >= 1280) { 823 printk (KERN_WARNING "cirrusfb: ERROR: VerticalTotal >= 1280; special treatment required! (TODO)\n"); 824 DPRINTK ("EXIT - EINVAL error\n"); 825 return -EINVAL; 826 } 827 828 return 0; 829} 830 831static int cirrusfb_decode_var (const struct fb_var_screeninfo *var, 832 struct cirrusfb_regs *regs, 833 const struct fb_info *info) 834{ 835 long freq; 836 long maxclock; 837 int maxclockidx = 0; 838 struct cirrusfb_info *cinfo = info->par; 839 int xres, hfront, hsync, hback; 840 int yres, vfront, vsync, vback; 841 842 switch(var->bits_per_pixel) { 843 case 1: 844 regs->line_length = var->xres_virtual / 8; 845 regs->visual = FB_VISUAL_MONO10; 846 maxclockidx = 0; 847 break; 848 849 case 8: 850 regs->line_length = var->xres_virtual; 851 regs->visual = FB_VISUAL_PSEUDOCOLOR; 852 maxclockidx = 1; 853 break; 854 855 case 16: 856 regs->line_length = var->xres_virtual * 2; 857 regs->visual = FB_VISUAL_DIRECTCOLOR; 858 maxclockidx = 2; 859 break; 860 861 case 24: 862 regs->line_length = var->xres_virtual * 3; 863 regs->visual = FB_VISUAL_DIRECTCOLOR; 864 maxclockidx = 3; 865 break; 866 867 case 32: 868 regs->line_length = var->xres_virtual * 4; 869 regs->visual = FB_VISUAL_DIRECTCOLOR; 870 maxclockidx = 4; 871 break; 872 873 default: 874 DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel); 875 assert(false); 876 /* should never occur */ 877 break; 878 } 879 880 regs->type = FB_TYPE_PACKED_PIXELS; 881 882 /* convert from ps to kHz */ 883 freq = 1000000000 / var->pixclock; 884 885 DPRINTK ("desired pixclock: %ld kHz\n", freq); 886 887 maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx]; 888 regs->multiplexing = 0; 889 890 /* If the frequency is greater than we can support, we might be able 891 * to use multiplexing for the video mode */ 892 if (freq > maxclock) { 893 switch (cinfo->btype) { 894 case BT_ALPINE: 895 case BT_GD5480: 896 regs->multiplexing = 1; 897 break; 898 899 default: 900 printk (KERN_WARNING "cirrusfb: ERROR: Frequency greater than maxclock (%ld kHz)\n", maxclock); 901 DPRINTK ("EXIT - return -EINVAL\n"); 902 return -EINVAL; 903 } 904 } 905 906 bestclock (freq, ®s->freq, ®s->nom, ®s->den, ®s->div, 907 maxclock); 908 regs->mclk = cirrusfb_get_mclk (freq, var->bits_per_pixel, ®s->divMCLK); 909 910 xres = var->xres; 911 hfront = var->right_margin; 912 hsync = var->hsync_len; 913 hback = var->left_margin; 914 915 yres = var->yres; 916 vfront = var->lower_margin; 917 vsync = var->vsync_len; 918 vback = var->upper_margin; 919 920 if (var->vmode & FB_VMODE_DOUBLE) { 921 yres *= 2; 922 vfront *= 2; 923 vsync *= 2; 924 vback *= 2; 925 } else if (var->vmode & FB_VMODE_INTERLACED) { 926 yres = (yres + 1) / 2; 927 vfront = (vfront + 1) / 2; 928 vsync = (vsync + 1) / 2; 929 vback = (vback + 1) / 2; 930 } 931 regs->HorizRes = xres; 932 regs->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5; 933 regs->HorizDispEnd = xres / 8 - 1; 934 regs->HorizBlankStart = xres / 8; 935 regs->HorizBlankEnd = regs->HorizTotal + 5; /* does not count with "-5" */ 936 regs->HorizSyncStart = (xres + hfront) / 8 + 1; 937 regs->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1; 938 939 regs->VertRes = yres; 940 regs->VertTotal = yres + vfront + vsync + vback - 2; 941 regs->VertDispEnd = yres - 1; 942 regs->VertBlankStart = yres; 943 regs->VertBlankEnd = regs->VertTotal; 944 regs->VertSyncStart = yres + vfront - 1; 945 regs->VertSyncEnd = yres + vfront + vsync - 1; 946 947 if (regs->VertRes >= 1024) { 948 regs->VertTotal /= 2; 949 regs->VertSyncStart /= 2; 950 regs->VertSyncEnd /= 2; 951 regs->VertDispEnd /= 2; 952 } 953 if (regs->multiplexing) { 954 regs->HorizTotal /= 2; 955 regs->HorizSyncStart /= 2; 956 regs->HorizSyncEnd /= 2; 957 regs->HorizDispEnd /= 2; 958 } 959 960 return 0; 961} 962 963 964static void cirrusfb_set_mclk (const struct cirrusfb_info *cinfo, int val, int div) 965{ 966 assert (cinfo != NULL); 967 968 if (div == 2) { 969 /* VCLK = MCLK/2 */ 970 unsigned char old = vga_rseq (cinfo->regbase, CL_SEQR1E); 971 vga_wseq (cinfo->regbase, CL_SEQR1E, old | 0x1); 972 vga_wseq (cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f)); 973 } else if (div == 1) { 974 /* VCLK = MCLK */ 975 unsigned char old = vga_rseq (cinfo->regbase, CL_SEQR1E); 976 vga_wseq (cinfo->regbase, CL_SEQR1E, old & ~0x1); 977 vga_wseq (cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f)); 978 } else { 979 vga_wseq (cinfo->regbase, CL_SEQR1F, val & 0x3f); 980 } 981} 982 983/************************************************************************* 984 cirrusfb_set_par_foo() 985 986 actually writes the values for a new video mode into the hardware, 987**************************************************************************/ 988static int cirrusfb_set_par_foo (struct fb_info *info) 989{ 990 struct cirrusfb_info *cinfo = info->par; 991 struct fb_var_screeninfo *var = &info->var; 992 struct cirrusfb_regs regs; 993 u8 __iomem *regbase = cinfo->regbase; 994 unsigned char tmp; 995 int offset = 0, err; 996 const struct cirrusfb_board_info_rec *bi; 997 998 DPRINTK ("ENTER\n"); 999 DPRINTK ("Requested mode: %dx%dx%d\n", 1000 var->xres, var->yres, var->bits_per_pixel); 1001 DPRINTK ("pixclock: %d\n", var->pixclock); 1002 1003 init_vgachip (cinfo); 1004 1005 err = cirrusfb_decode_var(var, ®s, info); 1006 if(err) { 1007 /* should never happen */ 1008 DPRINTK("mode change aborted. invalid var.\n"); 1009 return -EINVAL; 1010 } 1011 1012 bi = &cirrusfb_board_info[cinfo->btype]; 1013 1014 1015 /* unlock register VGA_CRTC_H_TOTAL..CRT7 */ 1016 vga_wcrt (regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */ 1017 1018 /* if debugging is enabled, all parameters get output before writing */ 1019 DPRINTK ("CRT0: %ld\n", regs.HorizTotal); 1020 vga_wcrt (regbase, VGA_CRTC_H_TOTAL, regs.HorizTotal); 1021 1022 DPRINTK ("CRT1: %ld\n", regs.HorizDispEnd); 1023 vga_wcrt (regbase, VGA_CRTC_H_DISP, regs.HorizDispEnd); 1024 1025 DPRINTK ("CRT2: %ld\n", regs.HorizBlankStart); 1026 vga_wcrt (regbase, VGA_CRTC_H_BLANK_START, regs.HorizBlankStart); 1027 1028 DPRINTK ("CRT3: 128+%ld\n", regs.HorizBlankEnd % 32); /* + 128: Compatible read */ 1029 vga_wcrt (regbase, VGA_CRTC_H_BLANK_END, 128 + (regs.HorizBlankEnd % 32)); 1030 1031 DPRINTK ("CRT4: %ld\n", regs.HorizSyncStart); 1032 vga_wcrt (regbase, VGA_CRTC_H_SYNC_START, regs.HorizSyncStart); 1033 1034 tmp = regs.HorizSyncEnd % 32; 1035 if (regs.HorizBlankEnd & 32) 1036 tmp += 128; 1037 DPRINTK ("CRT5: %d\n", tmp); 1038 vga_wcrt (regbase, VGA_CRTC_H_SYNC_END, tmp); 1039 1040 DPRINTK ("CRT6: %ld\n", regs.VertTotal & 0xff); 1041 vga_wcrt (regbase, VGA_CRTC_V_TOTAL, (regs.VertTotal & 0xff)); 1042 1043 tmp = 16; /* LineCompare bit #9 */ 1044 if (regs.VertTotal & 256) 1045 tmp |= 1; 1046 if (regs.VertDispEnd & 256) 1047 tmp |= 2; 1048 if (regs.VertSyncStart & 256) 1049 tmp |= 4; 1050 if (regs.VertBlankStart & 256) 1051 tmp |= 8; 1052 if (regs.VertTotal & 512) 1053 tmp |= 32; 1054 if (regs.VertDispEnd & 512) 1055 tmp |= 64; 1056 if (regs.VertSyncStart & 512) 1057 tmp |= 128; 1058 DPRINTK ("CRT7: %d\n", tmp); 1059 vga_wcrt (regbase, VGA_CRTC_OVERFLOW, tmp); 1060 1061 tmp = 0x40; /* LineCompare bit #8 */ 1062 if (regs.VertBlankStart & 512) 1063 tmp |= 0x20; 1064 if (var->vmode & FB_VMODE_DOUBLE) 1065 tmp |= 0x80; 1066 DPRINTK ("CRT9: %d\n", tmp); 1067 vga_wcrt (regbase, VGA_CRTC_MAX_SCAN, tmp); 1068 1069 DPRINTK ("CRT10: %ld\n", regs.VertSyncStart & 0xff); 1070 vga_wcrt (regbase, VGA_CRTC_V_SYNC_START, (regs.VertSyncStart & 0xff)); 1071 1072 DPRINTK ("CRT11: 64+32+%ld\n", regs.VertSyncEnd % 16); 1073 vga_wcrt (regbase, VGA_CRTC_V_SYNC_END, (regs.VertSyncEnd % 16 + 64 + 32)); 1074 1075 DPRINTK ("CRT12: %ld\n", regs.VertDispEnd & 0xff); 1076 vga_wcrt (regbase, VGA_CRTC_V_DISP_END, (regs.VertDispEnd & 0xff)); 1077 1078 DPRINTK ("CRT15: %ld\n", regs.VertBlankStart & 0xff); 1079 vga_wcrt (regbase, VGA_CRTC_V_BLANK_START, (regs.VertBlankStart & 0xff)); 1080 1081 DPRINTK ("CRT16: %ld\n", regs.VertBlankEnd & 0xff); 1082 vga_wcrt (regbase, VGA_CRTC_V_BLANK_END, (regs.VertBlankEnd & 0xff)); 1083 1084 DPRINTK ("CRT18: 0xff\n"); 1085 vga_wcrt (regbase, VGA_CRTC_LINE_COMPARE, 0xff); 1086 1087 tmp = 0; 1088 if (var->vmode & FB_VMODE_INTERLACED) 1089 tmp |= 1; 1090 if (regs.HorizBlankEnd & 64) 1091 tmp |= 16; 1092 if (regs.HorizBlankEnd & 128) 1093 tmp |= 32; 1094 if (regs.VertBlankEnd & 256) 1095 tmp |= 64; 1096 if (regs.VertBlankEnd & 512) 1097 tmp |= 128; 1098 1099 DPRINTK ("CRT1a: %d\n", tmp); 1100 vga_wcrt (regbase, CL_CRT1A, tmp); 1101 1102 /* set VCLK0 */ 1103 /* hardware RefClock: 14.31818 MHz */ 1104 /* formula: VClk = (OSC * N) / (D * (1+P)) */ 1105 /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */ 1106 1107 vga_wseq (regbase, CL_SEQRB, regs.nom); 1108 tmp = regs.den << 1; 1109 if (regs.div != 0) 1110 tmp |= 1; 1111 1112 if ((cinfo->btype == BT_SD64) || 1113 (cinfo->btype == BT_ALPINE) || 1114 (cinfo->btype == BT_GD5480)) 1115 tmp |= 0x80; /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */ 1116 1117 DPRINTK ("CL_SEQR1B: %ld\n", (long) tmp); 1118 vga_wseq (regbase, CL_SEQR1B, tmp); 1119 1120 if (regs.VertRes >= 1024) 1121 /* 1280x1024 */ 1122 vga_wcrt (regbase, VGA_CRTC_MODE, 0xc7); 1123 else 1124 /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit 1125 * address wrap, no compat. */ 1126 vga_wcrt (regbase, VGA_CRTC_MODE, 0xc3); 1127 1128/* HAEH? vga_wcrt (regbase, VGA_CRTC_V_SYNC_END, 0x20); * previously: 0x00 unlock VGA_CRTC_H_TOTAL..CRT7 */ 1129 1130 /* don't know if it would hurt to also program this if no interlaced */ 1131 /* mode is used, but I feel better this way.. :-) */ 1132 if (var->vmode & FB_VMODE_INTERLACED) 1133 vga_wcrt (regbase, VGA_CRTC_REGS, regs.HorizTotal / 2); 1134 else 1135 vga_wcrt (regbase, VGA_CRTC_REGS, 0x00); /* interlace control */ 1136 1137 vga_wseq (regbase, VGA_SEQ_CHARACTER_MAP, 0); 1138 1139 /* adjust horizontal/vertical sync type (low/high) */ 1140 tmp = 0x03; /* enable display memory & CRTC I/O address for color mode */ 1141 if (var->sync & FB_SYNC_HOR_HIGH_ACT) 1142 tmp |= 0x40; 1143 if (var->sync & FB_SYNC_VERT_HIGH_ACT) 1144 tmp |= 0x80; 1145 WGen (cinfo, VGA_MIS_W, tmp); 1146 1147 vga_wcrt (regbase, VGA_CRTC_PRESET_ROW, 0); /* Screen A Preset Row-Scan register */ 1148 vga_wcrt (regbase, VGA_CRTC_CURSOR_START, 0); /* text cursor on and start line */ 1149 vga_wcrt (regbase, VGA_CRTC_CURSOR_END, 31); /* text cursor end line */ 1150 1151 /****************************************************** 1152 * 1153 * 1 bpp 1154 * 1155 */ 1156 1157 /* programming for different color depths */ 1158 if (var->bits_per_pixel == 1) { 1159 DPRINTK ("cirrusfb: preparing for 1 bit deep display\n"); 1160 vga_wgfx (regbase, VGA_GFX_MODE, 0); /* mode register */ 1161 1162 /* SR07 */ 1163 switch (cinfo->btype) { 1164 case BT_SD64: 1165 case BT_PICCOLO: 1166 case BT_PICASSO: 1167 case BT_SPECTRUM: 1168 case BT_PICASSO4: 1169 case BT_ALPINE: 1170 case BT_GD5480: 1171 DPRINTK (" (for GD54xx)\n"); 1172 vga_wseq (regbase, CL_SEQR7, 1173 regs.multiplexing ? 1174 bi->sr07_1bpp_mux : bi->sr07_1bpp); 1175 break; 1176 1177 case BT_LAGUNA: 1178 DPRINTK (" (for GD546x)\n"); 1179 vga_wseq (regbase, CL_SEQR7, 1180 vga_rseq (regbase, CL_SEQR7) & ~0x01); 1181 break; 1182 1183 default: 1184 printk (KERN_WARNING "cirrusfb: unknown Board\n"); 1185 break; 1186 } 1187 1188 /* Extended Sequencer Mode */ 1189 switch (cinfo->btype) { 1190 case BT_SD64: 1191 /* setting the SEQRF on SD64 is not necessary (only during init) */ 1192 DPRINTK ("(for SD64)\n"); 1193 vga_wseq (regbase, CL_SEQR1F, 0x1a); /* MCLK select */ 1194 break; 1195 1196 case BT_PICCOLO: 1197 DPRINTK ("(for Piccolo)\n"); 1198/* ### ueberall 0x22? */ 1199 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ##vorher 1c MCLK select */ 1200 vga_wseq (regbase, CL_SEQRF, 0xb0); /* evtl d0 bei 1 bit? avoid FIFO underruns..? */ 1201 break; 1202 1203 case BT_PICASSO: 1204 DPRINTK ("(for Picasso)\n"); 1205 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ##vorher 22 MCLK select */ 1206 vga_wseq (regbase, CL_SEQRF, 0xd0); /* ## vorher d0 avoid FIFO underruns..? */ 1207 break; 1208 1209 case BT_SPECTRUM: 1210 DPRINTK ("(for Spectrum)\n"); 1211/* ### ueberall 0x22? */ 1212 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ##vorher 1c MCLK select */ 1213 vga_wseq (regbase, CL_SEQRF, 0xb0); /* evtl d0? avoid FIFO underruns..? */ 1214 break; 1215 1216 case BT_PICASSO4: 1217 case BT_ALPINE: 1218 case BT_GD5480: 1219 case BT_LAGUNA: 1220 DPRINTK (" (for GD54xx)\n"); 1221 /* do nothing */ 1222 break; 1223 1224 default: 1225 printk (KERN_WARNING "cirrusfb: unknown Board\n"); 1226 break; 1227 } 1228 1229 WGen (cinfo, VGA_PEL_MSK, 0x01); /* pixel mask: pass-through for first plane */ 1230 if (regs.multiplexing) 1231 WHDR (cinfo, 0x4a); /* hidden dac reg: 1280x1024 */ 1232 else 1233 WHDR (cinfo, 0); /* hidden dac: nothing */ 1234 vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x06); /* memory mode: odd/even, ext. memory */ 1235 vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0x01); /* plane mask: only write to first plane */ 1236 offset = var->xres_virtual / 16; 1237 } 1238 1239 /****************************************************** 1240 * 1241 * 8 bpp 1242 * 1243 */ 1244 1245 else if (var->bits_per_pixel == 8) { 1246 DPRINTK ("cirrusfb: preparing for 8 bit deep display\n"); 1247 switch (cinfo->btype) { 1248 case BT_SD64: 1249 case BT_PICCOLO: 1250 case BT_PICASSO: 1251 case BT_SPECTRUM: 1252 case BT_PICASSO4: 1253 case BT_ALPINE: 1254 case BT_GD5480: 1255 DPRINTK (" (for GD54xx)\n"); 1256 vga_wseq (regbase, CL_SEQR7, 1257 regs.multiplexing ? 1258 bi->sr07_8bpp_mux : bi->sr07_8bpp); 1259 break; 1260 1261 case BT_LAGUNA: 1262 DPRINTK (" (for GD546x)\n"); 1263 vga_wseq (regbase, CL_SEQR7, 1264 vga_rseq (regbase, CL_SEQR7) | 0x01); 1265 break; 1266 1267 default: 1268 printk (KERN_WARNING "cirrusfb: unknown Board\n"); 1269 break; 1270 } 1271 1272 switch (cinfo->btype) { 1273 case BT_SD64: 1274 vga_wseq (regbase, CL_SEQR1F, 0x1d); /* MCLK select */ 1275 break; 1276 1277 case BT_PICCOLO: 1278 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */ 1279 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ 1280 break; 1281 1282 case BT_PICASSO: 1283 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */ 1284 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ 1285 break; 1286 1287 case BT_SPECTRUM: 1288 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */ 1289 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ 1290 break; 1291 1292 case BT_PICASSO4: 1293#ifdef CONFIG_ZORRO 1294 vga_wseq (regbase, CL_SEQRF, 0xb8); /* ### INCOMPLETE!! */ 1295#endif 1296/* vga_wseq (regbase, CL_SEQR1F, 0x1c); */ 1297 break; 1298 1299 case BT_ALPINE: 1300 DPRINTK (" (for GD543x)\n"); 1301 cirrusfb_set_mclk (cinfo, regs.mclk, regs.divMCLK); 1302 /* We already set SRF and SR1F */ 1303 break; 1304 1305 case BT_GD5480: 1306 case BT_LAGUNA: 1307 DPRINTK (" (for GD54xx)\n"); 1308 /* do nothing */ 1309 break; 1310 1311 default: 1312 printk (KERN_WARNING "cirrusfb: unknown Board\n"); 1313 break; 1314 } 1315 1316 vga_wgfx (regbase, VGA_GFX_MODE, 64); /* mode register: 256 color mode */ 1317 WGen (cinfo, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */ 1318 if (regs.multiplexing) 1319 WHDR (cinfo, 0x4a); /* hidden dac reg: 1280x1024 */ 1320 else 1321 WHDR (cinfo, 0); /* hidden dac: nothing */ 1322 vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */ 1323 vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */ 1324 offset = var->xres_virtual / 8; 1325 } 1326 1327 /****************************************************** 1328 * 1329 * 16 bpp 1330 * 1331 */ 1332 1333 else if (var->bits_per_pixel == 16) { 1334 DPRINTK ("cirrusfb: preparing for 16 bit deep display\n"); 1335 switch (cinfo->btype) { 1336 case BT_SD64: 1337 vga_wseq (regbase, CL_SEQR7, 0xf7); /* Extended Sequencer Mode: 256c col. mode */ 1338 vga_wseq (regbase, CL_SEQR1F, 0x1e); /* MCLK select */ 1339 break; 1340 1341 case BT_PICCOLO: 1342 vga_wseq (regbase, CL_SEQR7, 0x87); 1343 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ 1344 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */ 1345 break; 1346 1347 case BT_PICASSO: 1348 vga_wseq (regbase, CL_SEQR7, 0x27); 1349 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ 1350 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */ 1351 break; 1352 1353 case BT_SPECTRUM: 1354 vga_wseq (regbase, CL_SEQR7, 0x87); 1355 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ 1356 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */ 1357 break; 1358 1359 case BT_PICASSO4: 1360 vga_wseq (regbase, CL_SEQR7, 0x27); 1361/* vga_wseq (regbase, CL_SEQR1F, 0x1c); */ 1362 break; 1363 1364 case BT_ALPINE: 1365 DPRINTK (" (for GD543x)\n"); 1366 if (regs.HorizRes >= 1024) 1367 vga_wseq (regbase, CL_SEQR7, 0xa7); 1368 else 1369 vga_wseq (regbase, CL_SEQR7, 0xa3); 1370 cirrusfb_set_mclk (cinfo, regs.mclk, regs.divMCLK); 1371 break; 1372 1373 case BT_GD5480: 1374 DPRINTK (" (for GD5480)\n"); 1375 vga_wseq (regbase, CL_SEQR7, 0x17); 1376 /* We already set SRF and SR1F */ 1377 break; 1378 1379 case BT_LAGUNA: 1380 DPRINTK (" (for GD546x)\n"); 1381 vga_wseq (regbase, CL_SEQR7, 1382 vga_rseq (regbase, CL_SEQR7) & ~0x01); 1383 break; 1384 1385 default: 1386 printk (KERN_WARNING "CIRRUSFB: unknown Board\n"); 1387 break; 1388 } 1389 1390 vga_wgfx (regbase, VGA_GFX_MODE, 64); /* mode register: 256 color mode */ 1391 WGen (cinfo, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */ 1392#ifdef CONFIG_PCI 1393 WHDR (cinfo, 0xc0); /* Copy Xbh */ 1394#elif defined(CONFIG_ZORRO) 1395 WHDR (cinfo, 0xa0); /* hidden dac reg: nothing special */ 1396#endif 1397 vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */ 1398 vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */ 1399 offset = var->xres_virtual / 4; 1400 } 1401 1402 /****************************************************** 1403 * 1404 * 32 bpp 1405 * 1406 */ 1407 1408 else if (var->bits_per_pixel == 32) { 1409 DPRINTK ("cirrusfb: preparing for 24/32 bit deep display\n"); 1410 switch (cinfo->btype) { 1411 case BT_SD64: 1412 vga_wseq (regbase, CL_SEQR7, 0xf9); /* Extended Sequencer Mode: 256c col. mode */ 1413 vga_wseq (regbase, CL_SEQR1F, 0x1e); /* MCLK select */ 1414 break; 1415 1416 case BT_PICCOLO: 1417 vga_wseq (regbase, CL_SEQR7, 0x85); 1418 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ 1419 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */ 1420 break; 1421 1422 case BT_PICASSO: 1423 vga_wseq (regbase, CL_SEQR7, 0x25); 1424 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ 1425 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */ 1426 break; 1427 1428 case BT_SPECTRUM: 1429 vga_wseq (regbase, CL_SEQR7, 0x85); 1430 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ 1431 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */ 1432 break; 1433 1434 case BT_PICASSO4: 1435 vga_wseq (regbase, CL_SEQR7, 0x25); 1436/* vga_wseq (regbase, CL_SEQR1F, 0x1c); */ 1437 break; 1438 1439 case BT_ALPINE: 1440 DPRINTK (" (for GD543x)\n"); 1441 vga_wseq (regbase, CL_SEQR7, 0xa9); 1442 cirrusfb_set_mclk (cinfo, regs.mclk, regs.divMCLK); 1443 break; 1444 1445 case BT_GD5480: 1446 DPRINTK (" (for GD5480)\n"); 1447 vga_wseq (regbase, CL_SEQR7, 0x19); 1448 /* We already set SRF and SR1F */ 1449 break; 1450 1451 case BT_LAGUNA: 1452 DPRINTK (" (for GD546x)\n"); 1453 vga_wseq (regbase, CL_SEQR7, 1454 vga_rseq (regbase, CL_SEQR7) & ~0x01); 1455 break; 1456 1457 default: 1458 printk (KERN_WARNING "cirrusfb: unknown Board\n"); 1459 break; 1460 } 1461 1462 vga_wgfx (regbase, VGA_GFX_MODE, 64); /* mode register: 256 color mode */ 1463 WGen (cinfo, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */ 1464 WHDR (cinfo, 0xc5); /* hidden dac reg: 8-8-8 mode (24 or 32) */ 1465 vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */ 1466 vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */ 1467 offset = var->xres_virtual / 4; 1468 } 1469 1470 /****************************************************** 1471 * 1472 * unknown/unsupported bpp 1473 * 1474 */ 1475 1476 else { 1477 printk (KERN_ERR "cirrusfb: What's this?? requested color depth == %d.\n", 1478 var->bits_per_pixel); 1479 } 1480 1481 vga_wcrt (regbase, VGA_CRTC_OFFSET, offset & 0xff); 1482 tmp = 0x22; 1483 if (offset & 0x100) 1484 tmp |= 0x10; /* offset overflow bit */ 1485 1486 vga_wcrt (regbase, CL_CRT1B, tmp); /* screen start addr #16-18, fastpagemode cycles */ 1487 1488 if (cinfo->btype == BT_SD64 || 1489 cinfo->btype == BT_PICASSO4 || 1490 cinfo->btype == BT_ALPINE || 1491 cinfo->btype == BT_GD5480) 1492 vga_wcrt (regbase, CL_CRT1D, 0x00); /* screen start address bit 19 */ 1493 1494 vga_wcrt (regbase, VGA_CRTC_CURSOR_HI, 0); /* text cursor location high */ 1495 vga_wcrt (regbase, VGA_CRTC_CURSOR_LO, 0); /* text cursor location low */ 1496 vga_wcrt (regbase, VGA_CRTC_UNDERLINE, 0); /* underline row scanline = at very bottom */ 1497 1498 vga_wattr (regbase, VGA_ATC_MODE, 1); /* controller mode */ 1499 vga_wattr (regbase, VGA_ATC_OVERSCAN, 0); /* overscan (border) color */ 1500 vga_wattr (regbase, VGA_ATC_PLANE_ENABLE, 15); /* color plane enable */ 1501 vga_wattr (regbase, CL_AR33, 0); /* pixel panning */ 1502 vga_wattr (regbase, VGA_ATC_COLOR_PAGE, 0); /* color select */ 1503 1504 /* [ EGS: SetOffset(); ] */ 1505 /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */ 1506 AttrOn (cinfo); 1507 1508 vga_wgfx (regbase, VGA_GFX_SR_VALUE, 0); /* set/reset register */ 1509 vga_wgfx (regbase, VGA_GFX_SR_ENABLE, 0); /* set/reset enable */ 1510 vga_wgfx (regbase, VGA_GFX_COMPARE_VALUE, 0); /* color compare */ 1511 vga_wgfx (regbase, VGA_GFX_DATA_ROTATE, 0); /* data rotate */ 1512 vga_wgfx (regbase, VGA_GFX_PLANE_READ, 0); /* read map select */ 1513 vga_wgfx (regbase, VGA_GFX_MISC, 1); /* miscellaneous register */ 1514 vga_wgfx (regbase, VGA_GFX_COMPARE_MASK, 15); /* color don't care */ 1515 vga_wgfx (regbase, VGA_GFX_BIT_MASK, 255); /* bit mask */ 1516 1517 vga_wseq (regbase, CL_SEQR12, 0x0); /* graphics cursor attributes: nothing special */ 1518 1519 /* finally, turn on everything - turn off "FullBandwidth" bit */ 1520 /* also, set "DotClock%2" bit where requested */ 1521 tmp = 0x01; 1522 1523/*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ? 1524 if (var->vmode & FB_VMODE_CLOCK_HALVE) 1525 tmp |= 0x08; 1526*/ 1527 1528 vga_wseq (regbase, VGA_SEQ_CLOCK_MODE, tmp); 1529 DPRINTK ("CL_SEQR1: %d\n", tmp); 1530 1531 cinfo->currentmode = regs; 1532 info->fix.type = regs.type; 1533 info->fix.visual = regs.visual; 1534 info->fix.line_length = regs.line_length; 1535 1536 /* pan to requested offset */ 1537 cirrusfb_pan_display (var, info); 1538 1539#ifdef CIRRUSFB_DEBUG 1540 cirrusfb_dump (); 1541#endif 1542 1543 DPRINTK ("EXIT\n"); 1544 return 0; 1545} 1546 1547/* for some reason incomprehensible to me, cirrusfb requires that you write 1548 * the registers twice for the settings to take..grr. -dte */ 1549static int cirrusfb_set_par (struct fb_info *info) 1550{ 1551 cirrusfb_set_par_foo (info); 1552 return cirrusfb_set_par_foo (info); 1553} 1554 1555static int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green, 1556 unsigned blue, unsigned transp, 1557 struct fb_info *info) 1558{ 1559 struct cirrusfb_info *cinfo = info->par; 1560 1561 if (regno > 255) 1562 return -EINVAL; 1563 1564 if (info->fix.visual == FB_VISUAL_TRUECOLOR) { 1565 u32 v; 1566 red >>= (16 - info->var.red.length); 1567 green >>= (16 - info->var.green.length); 1568 blue >>= (16 - info->var.blue.length); 1569 1570 if (regno>=16) 1571 return 1; 1572 v = (red << info->var.red.offset) | 1573 (green << info->var.green.offset) | 1574 (blue << info->var.blue.offset); 1575 1576 switch (info->var.bits_per_pixel) { 1577 case 8: 1578 cinfo->pseudo_palette[regno] = v; 1579 break; 1580 case 16: 1581 cinfo->pseudo_palette[regno] = v; 1582 break; 1583 case 24: 1584 case 32: 1585 cinfo->pseudo_palette[regno] = v; 1586 break; 1587 } 1588 return 0; 1589 } 1590 1591 cinfo->palette[regno].red = red; 1592 cinfo->palette[regno].green = green; 1593 cinfo->palette[regno].blue = blue; 1594 1595 if (info->var.bits_per_pixel == 8) { 1596 WClut (cinfo, regno, red >> 10, green >> 10, blue >> 10); 1597 } 1598 1599 return 0; 1600 1601} 1602 1603/************************************************************************* 1604 cirrusfb_pan_display() 1605 1606 performs display panning - provided hardware permits this 1607**************************************************************************/ 1608static int cirrusfb_pan_display (struct fb_var_screeninfo *var, 1609 struct fb_info *info) 1610{ 1611 int xoffset = 0; 1612 int yoffset = 0; 1613 unsigned long base; 1614 unsigned char tmp = 0, tmp2 = 0, xpix; 1615 struct cirrusfb_info *cinfo = info->par; 1616 1617 DPRINTK ("ENTER\n"); 1618 DPRINTK ("virtual offset: (%d,%d)\n", var->xoffset, var->yoffset); 1619 1620 /* no range checks for xoffset and yoffset, */ 1621 /* as fb_pan_display has already done this */ 1622 if (var->vmode & FB_VMODE_YWRAP) 1623 return -EINVAL; 1624 1625 info->var.xoffset = var->xoffset; 1626 info->var.yoffset = var->yoffset; 1627 1628 xoffset = var->xoffset * info->var.bits_per_pixel / 8; 1629 yoffset = var->yoffset; 1630 1631 base = yoffset * cinfo->currentmode.line_length + xoffset; 1632 1633 if (info->var.bits_per_pixel == 1) { 1634 /* base is already correct */ 1635 xpix = (unsigned char) (var->xoffset % 8); 1636 } else { 1637 base /= 4; 1638 xpix = (unsigned char) ((xoffset % 4) * 2); 1639 } 1640 1641 cirrusfb_WaitBLT(cinfo->regbase); /* make sure all the BLT's are done */ 1642 1643 /* lower 8 + 8 bits of screen start address */ 1644 vga_wcrt (cinfo->regbase, VGA_CRTC_START_LO, (unsigned char) (base & 0xff)); 1645 vga_wcrt (cinfo->regbase, VGA_CRTC_START_HI, (unsigned char) (base >> 8)); 1646 1647 /* construct bits 16, 17 and 18 of screen start address */ 1648 if (base & 0x10000) 1649 tmp |= 0x01; 1650 if (base & 0x20000) 1651 tmp |= 0x04; 1652 if (base & 0x40000) 1653 tmp |= 0x08; 1654 1655 tmp2 = (vga_rcrt (cinfo->regbase, CL_CRT1B) & 0xf2) | tmp; /* 0xf2 is %11110010, exclude tmp bits */ 1656 vga_wcrt (cinfo->regbase, CL_CRT1B, tmp2); 1657 1658 /* construct bit 19 of screen start address */ 1659 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) { 1660 tmp2 = 0; 1661 if (base & 0x80000) 1662 tmp2 = 0x80; 1663 vga_wcrt (cinfo->regbase, CL_CRT1D, tmp2); 1664 } 1665 1666 /* write pixel panning value to AR33; this does not quite work in 8bpp */ 1667 /* ### Piccolo..? Will this work? */ 1668 if (info->var.bits_per_pixel == 1) 1669 vga_wattr (cinfo->regbase, CL_AR33, xpix); 1670 1671 cirrusfb_WaitBLT (cinfo->regbase); 1672 1673 DPRINTK ("EXIT\n"); 1674 return (0); 1675} 1676 1677 1678static int cirrusfb_blank (int blank_mode, struct fb_info *info) 1679{ 1680 /* 1681 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL 1682 * then the caller blanks by setting the CLUT (Color Look Up Table) to all 1683 * black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due 1684 * to e.g. a video mode which doesn't support it. Implements VESA suspend 1685 * and powerdown modes on hardware that supports disabling hsync/vsync: 1686 * blank_mode == 2: suspend vsync 1687 * blank_mode == 3: suspend hsync 1688 * blank_mode == 4: powerdown 1689 */ 1690 unsigned char val; 1691 struct cirrusfb_info *cinfo = info->par; 1692 int current_mode = cinfo->blank_mode; 1693 1694 DPRINTK ("ENTER, blank mode = %d\n", blank_mode); 1695 1696 if (info->state != FBINFO_STATE_RUNNING || 1697 current_mode == blank_mode) { 1698 DPRINTK ("EXIT, returning 0\n"); 1699 return 0; 1700 } 1701 1702 /* Undo current */ 1703 if (current_mode == FB_BLANK_NORMAL || 1704 current_mode == FB_BLANK_UNBLANK) { 1705 /* unblank the screen */ 1706 val = vga_rseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE); 1707 vga_wseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE, val & 0xdf); /* clear "FullBandwidth" bit */ 1708 /* and undo VESA suspend trickery */ 1709 vga_wgfx (cinfo->regbase, CL_GRE, 0x00); 1710 } 1711 1712 /* set new */ 1713 if(blank_mode > FB_BLANK_NORMAL) { 1714 /* blank the screen */ 1715 val = vga_rseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE); 1716 vga_wseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE, val | 0x20); /* set "FullBandwidth" bit */ 1717 } 1718 1719 switch (blank_mode) { 1720 case FB_BLANK_UNBLANK: 1721 case FB_BLANK_NORMAL: 1722 break; 1723 case FB_BLANK_VSYNC_SUSPEND: 1724 vga_wgfx (cinfo->regbase, CL_GRE, 0x04); 1725 break; 1726 case FB_BLANK_HSYNC_SUSPEND: 1727 vga_wgfx (cinfo->regbase, CL_GRE, 0x02); 1728 break; 1729 case FB_BLANK_POWERDOWN: 1730 vga_wgfx (cinfo->regbase, CL_GRE, 0x06); 1731 break; 1732 default: 1733 DPRINTK ("EXIT, returning 1\n"); 1734 return 1; 1735 } 1736 1737 cinfo->blank_mode = blank_mode; 1738 DPRINTK ("EXIT, returning 0\n"); 1739 1740 /* Let fbcon do a soft blank for us */ 1741 return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0; 1742} 1743/**** END Hardware specific Routines **************************************/ 1744/****************************************************************************/ 1745/**** BEGIN Internal Routines ***********************************************/ 1746 1747static void init_vgachip (struct cirrusfb_info *cinfo) 1748{ 1749 const struct cirrusfb_board_info_rec *bi; 1750 1751 DPRINTK ("ENTER\n"); 1752 1753 assert (cinfo != NULL); 1754 1755 bi = &cirrusfb_board_info[cinfo->btype]; 1756 1757 /* reset board globally */ 1758 switch (cinfo->btype) { 1759 case BT_PICCOLO: 1760 WSFR (cinfo, 0x01); 1761 udelay (500); 1762 WSFR (cinfo, 0x51); 1763 udelay (500); 1764 break; 1765 case BT_PICASSO: 1766 WSFR2 (cinfo, 0xff); 1767 udelay (500); 1768 break; 1769 case BT_SD64: 1770 case BT_SPECTRUM: 1771 WSFR (cinfo, 0x1f); 1772 udelay (500); 1773 WSFR (cinfo, 0x4f); 1774 udelay (500); 1775 break; 1776 case BT_PICASSO4: 1777 vga_wcrt (cinfo->regbase, CL_CRT51, 0x00); /* disable flickerfixer */ 1778 mdelay (100); 1779 vga_wgfx (cinfo->regbase, CL_GR2F, 0x00); /* from Klaus' NetBSD driver: */ 1780 vga_wgfx (cinfo->regbase, CL_GR33, 0x00); /* put blitter into 542x compat */ 1781 vga_wgfx (cinfo->regbase, CL_GR31, 0x00); /* mode */ 1782 break; 1783 1784 case BT_GD5480: 1785 vga_wgfx (cinfo->regbase, CL_GR2F, 0x00); /* from Klaus' NetBSD driver: */ 1786 break; 1787 1788 case BT_ALPINE: 1789 /* Nothing to do to reset the board. */ 1790 break; 1791 1792 default: 1793 printk (KERN_ERR "cirrusfb: Warning: Unknown board type\n"); 1794 break; 1795 } 1796 1797 assert (cinfo->size > 0); /* make sure RAM size set by this point */ 1798 1799 /* the P4 is not fully initialized here; I rely on it having been */ 1800 /* inited under AmigaOS already, which seems to work just fine */ 1801 /* (Klaus advised to do it this way) */ 1802 1803 if (cinfo->btype != BT_PICASSO4) { 1804 WGen (cinfo, CL_VSSM, 0x10); /* EGS: 0x16 */ 1805 WGen (cinfo, CL_POS102, 0x01); 1806 WGen (cinfo, CL_VSSM, 0x08); /* EGS: 0x0e */ 1807 1808 if (cinfo->btype != BT_SD64) 1809 WGen (cinfo, CL_VSSM2, 0x01); 1810 1811 vga_wseq (cinfo->regbase, CL_SEQR0, 0x03); /* reset sequencer logic */ 1812 1813 vga_wseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21); /* FullBandwidth (video off) and 8/9 dot clock */ 1814 WGen (cinfo, VGA_MIS_W, 0xc1); /* polarity (-/-), disable access to display memory, VGA_CRTC_START_HI base address: color */ 1815 1816/* vga_wgfx (cinfo->regbase, CL_GRA, 0xce); "magic cookie" - doesn't make any sense to me.. */ 1817 vga_wseq (cinfo->regbase, CL_SEQR6, 0x12); /* unlock all extension registers */ 1818 1819 vga_wgfx (cinfo->regbase, CL_GR31, 0x04); /* reset blitter */ 1820 1821 switch (cinfo->btype) { 1822 case BT_GD5480: 1823 vga_wseq (cinfo->regbase, CL_SEQRF, 0x98); 1824 break; 1825 case BT_ALPINE: 1826 break; 1827 case BT_SD64: 1828 vga_wseq (cinfo->regbase, CL_SEQRF, 0xb8); 1829 break; 1830 default: 1831 vga_wseq (cinfo->regbase, CL_SEQR16, 0x0f); 1832 vga_wseq (cinfo->regbase, CL_SEQRF, 0xb0); 1833 break; 1834 } 1835 } 1836 vga_wseq (cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: nothing */ 1837 vga_wseq (cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00); /* character map select: doesn't even matter in gx mode */ 1838 vga_wseq (cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0e); /* memory mode: chain-4, no odd/even, ext. memory */ 1839 1840 /* controller-internal base address of video memory */ 1841 if (bi->init_sr07) 1842 vga_wseq (cinfo->regbase, CL_SEQR7, bi->sr07); 1843 1844 /* vga_wseq (cinfo->regbase, CL_SEQR8, 0x00); *//* EEPROM control: shouldn't be necessary to write to this at all.. */ 1845 1846 vga_wseq (cinfo->regbase, CL_SEQR10, 0x00); /* graphics cursor X position (incomplete; position gives rem. 3 bits */ 1847 vga_wseq (cinfo->regbase, CL_SEQR11, 0x00); /* graphics cursor Y position (..."... ) */ 1848 vga_wseq (cinfo->regbase, CL_SEQR12, 0x00); /* graphics cursor attributes */ 1849 vga_wseq (cinfo->regbase, CL_SEQR13, 0x00); /* graphics cursor pattern address */ 1850 1851 /* writing these on a P4 might give problems.. */ 1852 if (cinfo->btype != BT_PICASSO4) { 1853 vga_wseq (cinfo->regbase, CL_SEQR17, 0x00); /* configuration readback and ext. color */ 1854 vga_wseq (cinfo->regbase, CL_SEQR18, 0x02); /* signature generator */ 1855 } 1856 1857 /* MCLK select etc. */ 1858 if (bi->init_sr1f) 1859 vga_wseq (cinfo->regbase, CL_SEQR1F, bi->sr1f); 1860 1861 vga_wcrt (cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00); /* Screen A preset row scan: none */ 1862 vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20); /* Text cursor start: disable text cursor */ 1863 vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00); /* Text cursor end: - */ 1864 vga_wcrt (cinfo->regbase, VGA_CRTC_START_HI, 0x00); /* Screen start address high: 0 */ 1865 vga_wcrt (cinfo->regbase, VGA_CRTC_START_LO, 0x00); /* Screen start address low: 0 */ 1866 vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00); /* text cursor location high: 0 */ 1867 vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00); /* text cursor location low: 0 */ 1868 1869 vga_wcrt (cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00); /* Underline Row scanline: - */ 1870 vga_wcrt (cinfo->regbase, VGA_CRTC_MODE, 0xc3); /* mode control: timing enable, byte mode, no compat modes */ 1871 vga_wcrt (cinfo->regbase, VGA_CRTC_LINE_COMPARE, 0x00); /* Line Compare: not needed */ 1872 /* ### add 0x40 for text modes with > 30 MHz pixclock */ 1873 vga_wcrt (cinfo->regbase, CL_CRT1B, 0x02); /* ext. display controls: ext.adr. wrap */ 1874 1875 vga_wgfx (cinfo->regbase, VGA_GFX_SR_VALUE, 0x00); /* Set/Reset registes: - */ 1876 vga_wgfx (cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00); /* Set/Reset enable: - */ 1877 vga_wgfx (cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00); /* Color Compare: - */ 1878 vga_wgfx (cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00); /* Data Rotate: - */ 1879 vga_wgfx (cinfo->regbase, VGA_GFX_PLANE_READ, 0x00); /* Read Map Select: - */ 1880 vga_wgfx (cinfo->regbase, VGA_GFX_MODE, 0x00); /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */ 1881 vga_wgfx (cinfo->regbase, VGA_GFX_MISC, 0x01); /* Miscellaneous: memory map base address, graphics mode */ 1882 vga_wgfx (cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f); /* Color Don't care: involve all planes */ 1883 vga_wgfx (cinfo->regbase, VGA_GFX_BIT_MASK, 0xff); /* Bit Mask: no mask at all */ 1884 if (cinfo->btype == BT_ALPINE) 1885 vga_wgfx (cinfo->regbase, CL_GRB, 0x20); /* (5434 can't have bit 3 set for bitblt) */ 1886 else 1887 vga_wgfx (cinfo->regbase, CL_GRB, 0x28); /* Graphics controller mode extensions: finer granularity, 8byte data latches */ 1888 1889 vga_wgfx (cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */ 1890 vga_wgfx (cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */ 1891 vga_wgfx (cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */ 1892 /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); *//* Background color byte 1: - */ 1893/* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */ 1894 1895 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE0, 0x00); /* Attribute Controller palette registers: "identity mapping" */ 1896 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE1, 0x01); 1897 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE2, 0x02); 1898 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE3, 0x03); 1899 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE4, 0x04); 1900 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE5, 0x05); 1901 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE6, 0x06); 1902 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE7, 0x07); 1903 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE8, 0x08); 1904 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE9, 0x09); 1905 vga_wattr (cinfo->regbase, VGA_ATC_PALETTEA, 0x0a); 1906 vga_wattr (cinfo->regbase, VGA_ATC_PALETTEB, 0x0b); 1907 vga_wattr (cinfo->regbase, VGA_ATC_PALETTEC, 0x0c); 1908 vga_wattr (cinfo->regbase, VGA_ATC_PALETTED, 0x0d); 1909 vga_wattr (cinfo->regbase, VGA_ATC_PALETTEE, 0x0e); 1910 vga_wattr (cinfo->regbase, VGA_ATC_PALETTEF, 0x0f); 1911 1912 vga_wattr (cinfo->regbase, VGA_ATC_MODE, 0x01); /* Attribute Controller mode: graphics mode */ 1913 vga_wattr (cinfo->regbase, VGA_ATC_OVERSCAN, 0x00); /* Overscan color reg.: reg. 0 */ 1914 vga_wattr (cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f); /* Color Plane enable: Enable all 4 planes */ 1915/* ### vga_wattr (cinfo->regbase, CL_AR33, 0x00); * Pixel Panning: - */ 1916 vga_wattr (cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00); /* Color Select: - */ 1917 1918 WGen (cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */ 1919 1920 if (cinfo->btype != BT_ALPINE && cinfo->btype != BT_GD5480) 1921 WGen (cinfo, VGA_MIS_W, 0xc3); /* polarity (-/-), enable display mem, VGA_CRTC_START_HI i/o base = color */ 1922 1923 vga_wgfx (cinfo->regbase, CL_GR31, 0x04); /* BLT Start/status: Blitter reset */ 1924 vga_wgfx (cinfo->regbase, CL_GR31, 0x00); /* - " - : "end-of-reset" */ 1925 1926 /* misc... */ 1927 WHDR (cinfo, 0); /* Hidden DAC register: - */ 1928 1929 printk (KERN_DEBUG "cirrusfb: This board has %ld bytes of DRAM memory\n", cinfo->size); 1930 DPRINTK ("EXIT\n"); 1931 return; 1932} 1933 1934static void switch_monitor (struct cirrusfb_info *cinfo, int on) 1935{ 1936#ifdef CONFIG_ZORRO /* only works on Zorro boards */ 1937 static int IsOn = 0; 1938 1939 DPRINTK ("ENTER\n"); 1940 1941 if (cinfo->btype == BT_PICASSO4) 1942 return; /* nothing to switch */ 1943 if (cinfo->btype == BT_ALPINE) 1944 return; /* nothing to switch */ 1945 if (cinfo->btype == BT_GD5480) 1946 return; /* nothing to switch */ 1947 if (cinfo->btype == BT_PICASSO) { 1948 if ((on && !IsOn) || (!on && IsOn)) 1949 WSFR (cinfo, 0xff); 1950 1951 DPRINTK ("EXIT\n"); 1952 return; 1953 } 1954 if (on) { 1955 switch (cinfo->btype) { 1956 case BT_SD64: 1957 WSFR (cinfo, cinfo->SFR | 0x21); 1958 break; 1959 case BT_PICCOLO: 1960 WSFR (cinfo, cinfo->SFR | 0x28); 1961 break; 1962 case BT_SPECTRUM: 1963 WSFR (cinfo, 0x6f); 1964 break; 1965 default: /* do nothing */ break; 1966 } 1967 } else { 1968 switch (cinfo->btype) { 1969 case BT_SD64: 1970 WSFR (cinfo, cinfo->SFR & 0xde); 1971 break; 1972 case BT_PICCOLO: 1973 WSFR (cinfo, cinfo->SFR & 0xd7); 1974 break; 1975 case BT_SPECTRUM: 1976 WSFR (cinfo, 0x4f); 1977 break; 1978 default: /* do nothing */ break; 1979 } 1980 } 1981 1982 DPRINTK ("EXIT\n"); 1983#endif /* CONFIG_ZORRO */ 1984} 1985 1986 1987/******************************************/ 1988/* Linux 2.6-style accelerated functions */ 1989/******************************************/ 1990 1991static void cirrusfb_prim_fillrect(struct cirrusfb_info *cinfo, 1992 const struct fb_fillrect *region) 1993{ 1994 int m; /* bytes per pixel */ 1995 u32 color = (cinfo->info->fix.visual == FB_VISUAL_TRUECOLOR) ? 1996 cinfo->pseudo_palette[region->color] : region->color; 1997 1998 if(cinfo->info->var.bits_per_pixel == 1) { 1999 cirrusfb_RectFill(cinfo->regbase, cinfo->info->var.bits_per_pixel, 2000 region->dx / 8, region->dy, 2001 region->width / 8, region->height, 2002 color, 2003 cinfo->currentmode.line_length); 2004 } else { 2005 m = ( cinfo->info->var.bits_per_pixel + 7 ) / 8; 2006 cirrusfb_RectFill(cinfo->regbase, cinfo->info->var.bits_per_pixel, 2007 region->dx * m, region->dy, 2008 region->width * m, region->height, 2009 color, 2010 cinfo->currentmode.line_length); 2011 } 2012 return; 2013} 2014 2015static void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *region) 2016{ 2017 struct cirrusfb_info *cinfo = info->par; 2018 struct fb_fillrect modded; 2019 int vxres, vyres; 2020 2021 if (info->state != FBINFO_STATE_RUNNING) 2022 return; 2023 if (info->flags & FBINFO_HWACCEL_DISABLED) { 2024 cfb_fillrect(info, region); 2025 return; 2026 } 2027 2028 vxres = info->var.xres_virtual; 2029 vyres = info->var.yres_virtual; 2030 2031 memcpy(&modded, region, sizeof(struct fb_fillrect)); 2032 2033 if(!modded.width || !modded.height || 2034 modded.dx >= vxres || modded.dy >= vyres) 2035 return; 2036 2037 if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx; 2038 if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy; 2039 2040 cirrusfb_prim_fillrect(cinfo, &modded); 2041} 2042 2043static void cirrusfb_prim_copyarea(struct cirrusfb_info *cinfo, 2044 const struct fb_copyarea *area) 2045{ 2046 int m; /* bytes per pixel */ 2047 if(cinfo->info->var.bits_per_pixel == 1) { 2048 cirrusfb_BitBLT(cinfo->regbase, cinfo->info->var.bits_per_pixel, 2049 area->sx / 8, area->sy, 2050 area->dx / 8, area->dy, 2051 area->width / 8, area->height, 2052 cinfo->currentmode.line_length); 2053 } else { 2054 m = ( cinfo->info->var.bits_per_pixel + 7 ) / 8; 2055 cirrusfb_BitBLT(cinfo->regbase, cinfo->info->var.bits_per_pixel, 2056 area->sx * m, area->sy, 2057 area->dx * m, area->dy, 2058 area->width * m, area->height, 2059 cinfo->currentmode.line_length); 2060 } 2061 return; 2062} 2063 2064 2065static void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) 2066{ 2067 struct cirrusfb_info *cinfo = info->par; 2068 struct fb_copyarea modded; 2069 u32 vxres, vyres; 2070 modded.sx = area->sx; 2071 modded.sy = area->sy; 2072 modded.dx = area->dx; 2073 modded.dy = area->dy; 2074 modded.width = area->width; 2075 modded.height = area->height; 2076 2077 if (info->state != FBINFO_STATE_RUNNING) 2078 return; 2079 if (info->flags & FBINFO_HWACCEL_DISABLED) { 2080 cfb_copyarea(info, area); 2081 return; 2082 } 2083 2084 vxres = info->var.xres_virtual; 2085 vyres = info->var.yres_virtual; 2086 2087 if(!modded.width || !modded.height || 2088 modded.sx >= vxres || modded.sy >= vyres || 2089 modded.dx >= vxres || modded.dy >= vyres) 2090 return; 2091 2092 if(modded.sx + modded.width > vxres) modded.width = vxres - modded.sx; 2093 if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx; 2094 if(modded.sy + modded.height > vyres) modded.height = vyres - modded.sy; 2095 if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy; 2096 2097 cirrusfb_prim_copyarea(cinfo, &modded); 2098} 2099 2100static void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image) 2101{ 2102 struct cirrusfb_info *cinfo = info->par; 2103 2104 cirrusfb_WaitBLT(cinfo->regbase); 2105 cfb_imageblit(info, image); 2106} 2107 2108 2109#ifdef CONFIG_PPC_PREP 2110#define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000) 2111#define PREP_IO_BASE ((volatile unsigned char *) 0x80000000) 2112static void get_prep_addrs (unsigned long *display, unsigned long *registers) 2113{ 2114 DPRINTK ("ENTER\n"); 2115 2116 *display = PREP_VIDEO_BASE; 2117 *registers = (unsigned long) PREP_IO_BASE; 2118 2119 DPRINTK ("EXIT\n"); 2120} 2121 2122#endif /* CONFIG_PPC_PREP */ 2123 2124 2125#ifdef CONFIG_PCI 2126static int release_io_ports = 0; 2127 2128/* Pulled the logic from XFree86 Cirrus driver to get the memory size, 2129 * based on the DRAM bandwidth bit and DRAM bank switching bit. This 2130 * works with 1MB, 2MB and 4MB configurations (which the Motorola boards 2131 * seem to have. */ 2132static unsigned int cirrusfb_get_memsize (u8 __iomem *regbase) 2133{ 2134 unsigned long mem; 2135 unsigned char SRF; 2136 2137 DPRINTK ("ENTER\n"); 2138 2139 SRF = vga_rseq (regbase, CL_SEQRF); 2140 switch ((SRF & 0x18)) { 2141 case 0x08: mem = 512 * 1024; break; 2142 case 0x10: mem = 1024 * 1024; break; 2143 /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory 2144 * on the 5430. */ 2145 case 0x18: mem = 2048 * 1024; break; 2146 default: printk ("CLgenfb: Unknown memory size!\n"); 2147 mem = 1024 * 1024; 2148 } 2149 if (SRF & 0x80) { 2150 /* If DRAM bank switching is enabled, there must be twice as much 2151 * memory installed. (4MB on the 5434) */ 2152 mem *= 2; 2153 } 2154 /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */ 2155 2156 DPRINTK ("EXIT\n"); 2157 return mem; 2158} 2159 2160 2161 2162static void get_pci_addrs (const struct pci_dev *pdev, 2163 unsigned long *display, unsigned long *registers) 2164{ 2165 assert (pdev != NULL); 2166 assert (display != NULL); 2167 assert (registers != NULL); 2168 2169 DPRINTK ("ENTER\n"); 2170 2171 *display = 0; 2172 *registers = 0; 2173 2174 /* This is a best-guess for now */ 2175 2176 if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) { 2177 *display = pci_resource_start(pdev, 1); 2178 *registers = pci_resource_start(pdev, 0); 2179 } else { 2180 *display = pci_resource_start(pdev, 0); 2181 *registers = pci_resource_start(pdev, 1); 2182 } 2183 2184 assert (*display != 0); 2185 2186 DPRINTK ("EXIT\n"); 2187} 2188 2189 2190static void cirrusfb_pci_unmap (struct cirrusfb_info *cinfo) 2191{ 2192 struct pci_dev *pdev = cinfo->pdev; 2193 2194 iounmap(cinfo->fbmem); 2195 if (release_io_ports) 2196 release_region(0x3C0, 32); 2197 pci_release_regions(pdev); 2198 framebuffer_release(cinfo->info); 2199} 2200#endif /* CONFIG_PCI */ 2201 2202 2203#ifdef CONFIG_ZORRO 2204static void __devexit cirrusfb_zorro_unmap (struct cirrusfb_info *cinfo) 2205{ 2206 zorro_release_device(cinfo->zdev); 2207 2208 if (cinfo->btype == BT_PICASSO4) { 2209 cinfo->regbase -= 0x600000; 2210 iounmap ((void *)cinfo->regbase); 2211 iounmap ((void *)cinfo->fbmem); 2212 } else { 2213 if (zorro_resource_start(cinfo->zdev) > 0x01000000) 2214 iounmap ((void *)cinfo->fbmem); 2215 } 2216 framebuffer_release(cinfo->info); 2217} 2218#endif /* CONFIG_ZORRO */ 2219 2220static int cirrusfb_set_fbinfo(struct cirrusfb_info *cinfo) 2221{ 2222 struct fb_info *info = cinfo->info; 2223 struct fb_var_screeninfo *var = &info->var; 2224 2225 info->par = cinfo; 2226 info->pseudo_palette = cinfo->pseudo_palette; 2227 info->flags = FBINFO_DEFAULT 2228 | FBINFO_HWACCEL_XPAN 2229 | FBINFO_HWACCEL_YPAN 2230 | FBINFO_HWACCEL_FILLRECT 2231 | FBINFO_HWACCEL_COPYAREA; 2232 if (noaccel) 2233 info->flags |= FBINFO_HWACCEL_DISABLED; 2234 info->fbops = &cirrusfb_ops; 2235 info->screen_base = cinfo->fbmem; 2236 if (cinfo->btype == BT_GD5480) { 2237 if (var->bits_per_pixel == 16) 2238 info->screen_base += 1 * MB_; 2239 if (var->bits_per_pixel == 24 || var->bits_per_pixel == 32) 2240 info->screen_base += 2 * MB_; 2241 } 2242 2243 /* Fill fix common fields */ 2244 strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name, 2245 sizeof(info->fix.id)); 2246 2247 /* monochrome: only 1 memory plane */ 2248 /* 8 bit and above: Use whole memory area */ 2249 info->fix.smem_start = cinfo->fbmem_phys; 2250 info->fix.smem_len = (var->bits_per_pixel == 1) ? cinfo->size / 4 : cinfo->size; 2251 info->fix.type = cinfo->currentmode.type; 2252 info->fix.type_aux = 0; 2253 info->fix.visual = cinfo->currentmode.visual; 2254 info->fix.xpanstep = 1; 2255 info->fix.ypanstep = 1; 2256 info->fix.ywrapstep = 0; 2257 info->fix.line_length = cinfo->currentmode.line_length; 2258 2259 info->fix.mmio_start = cinfo->fbregs_phys; 2260 info->fix.mmio_len = 0; 2261 info->fix.accel = FB_ACCEL_NONE; 2262 2263 fb_alloc_cmap(&info->cmap, 256, 0); 2264 2265 return 0; 2266} 2267 2268static int cirrusfb_register(struct cirrusfb_info *cinfo) 2269{ 2270 struct fb_info *info; 2271 int err; 2272 cirrusfb_board_t btype; 2273 2274 DPRINTK ("ENTER\n"); 2275 2276 printk (KERN_INFO "cirrusfb: Driver for Cirrus Logic based graphic boards, v" CIRRUSFB_VERSION "\n"); 2277 2278 info = cinfo->info; 2279 btype = cinfo->btype; 2280 2281 /* sanity checks */ 2282 assert (btype != BT_NONE); 2283 2284 DPRINTK ("cirrusfb: (RAM start set to: 0x%p)\n", cinfo->fbmem); 2285 2286 /* Make pretend we've set the var so our structures are in a "good" */ 2287 /* state, even though we haven't written the mode to the hw yet... */ 2288 info->var = cirrusfb_predefined[cirrusfb_def_mode].var; 2289 info->var.activate = FB_ACTIVATE_NOW; 2290 2291 err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info); 2292 if (err < 0) { 2293 /* should never happen */ 2294 DPRINTK("choking on default var... umm, no good.\n"); 2295 goto err_unmap_cirrusfb; 2296 } 2297 2298 /* set all the vital stuff */ 2299 cirrusfb_set_fbinfo(cinfo); 2300 2301 err = register_framebuffer(info); 2302 if (err < 0) { 2303 printk (KERN_ERR "cirrusfb: could not register fb device; err = %d!\n", err); 2304 goto err_dealloc_cmap; 2305 } 2306 2307 DPRINTK ("EXIT, returning 0\n"); 2308 return 0; 2309 2310err_dealloc_cmap: 2311 fb_dealloc_cmap(&info->cmap); 2312err_unmap_cirrusfb: 2313 cinfo->unmap(cinfo); 2314 return err; 2315} 2316 2317static void __devexit cirrusfb_cleanup (struct fb_info *info) 2318{ 2319 struct cirrusfb_info *cinfo = info->par; 2320 DPRINTK ("ENTER\n"); 2321 2322 switch_monitor (cinfo, 0); 2323 2324 unregister_framebuffer (info); 2325 fb_dealloc_cmap (&info->cmap); 2326 printk ("Framebuffer unregistered\n"); 2327 cinfo->unmap(cinfo); 2328 2329 DPRINTK ("EXIT\n"); 2330} 2331 2332 2333#ifdef CONFIG_PCI 2334static int cirrusfb_pci_register (struct pci_dev *pdev, 2335 const struct pci_device_id *ent) 2336{ 2337 struct cirrusfb_info *cinfo; 2338 struct fb_info *info; 2339 cirrusfb_board_t btype; 2340 unsigned long board_addr, board_size; 2341 int ret; 2342 2343 ret = pci_enable_device(pdev); 2344 if (ret < 0) { 2345 printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n"); 2346 goto err_out; 2347 } 2348 2349 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev); 2350 if (!info) { 2351 printk(KERN_ERR "cirrusfb: could not allocate memory\n"); 2352 ret = -ENOMEM; 2353 goto err_disable; 2354 } 2355 2356 cinfo = info->par; 2357 cinfo->info = info; 2358 cinfo->pdev = pdev; 2359 cinfo->btype = btype = (cirrusfb_board_t) ent->driver_data; 2360 2361 DPRINTK (" Found PCI device, base address 0 is 0x%lx, btype set to %d\n", 2362 pdev->resource[0].start, btype); 2363 DPRINTK (" base address 1 is 0x%lx\n", pdev->resource[1].start); 2364 2365 if(isPReP) { 2366 pci_write_config_dword (pdev, PCI_BASE_ADDRESS_0, 0x00000000); 2367#ifdef CONFIG_PPC_PREP 2368 get_prep_addrs (&board_addr, &cinfo->fbregs_phys); 2369#endif 2370 /* PReP dies if we ioremap the IO registers, but it works w/out... */ 2371 cinfo->regbase = (char __iomem *) cinfo->fbregs_phys; 2372 } else { 2373 DPRINTK ("Attempt to get PCI info for Cirrus Graphics Card\n"); 2374 get_pci_addrs (pdev, &board_addr, &cinfo->fbregs_phys); 2375 cinfo->regbase = NULL; 2376 } 2377 2378 DPRINTK ("Board address: 0x%lx, register address: 0x%lx\n", board_addr, cinfo->fbregs_phys); 2379 2380 board_size = (btype == BT_GD5480) ? 2381 32 * MB_ : cirrusfb_get_memsize (cinfo->regbase); 2382 2383 ret = pci_request_regions(pdev, "cirrusfb"); 2384 if (ret <0) { 2385 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n", 2386 board_addr); 2387 goto err_release_fb; 2388 } 2389 if (request_region(0x3C0, 32, "cirrusfb")) 2390 release_io_ports = 1; 2391 2392 cinfo->fbmem = ioremap(board_addr, board_size); 2393 if (!cinfo->fbmem) { 2394 ret = -EIO; 2395 goto err_release_legacy; 2396 } 2397 2398 cinfo->fbmem_phys = board_addr; 2399 cinfo->size = board_size; 2400 cinfo->unmap = cirrusfb_pci_unmap; 2401 2402 printk (" RAM (%lu kB) at 0xx%lx, ", cinfo->size / KB_, board_addr); 2403 printk ("Cirrus Logic chipset on PCI bus\n"); 2404 pci_set_drvdata(pdev, info); 2405 2406 ret = cirrusfb_register(cinfo); 2407 if (ret) 2408 iounmap(cinfo->fbmem); 2409 return ret; 2410 2411err_release_legacy: 2412 if (release_io_ports) 2413 release_region(0x3C0, 32); 2414 pci_release_regions(pdev); 2415err_release_fb: 2416 framebuffer_release(info); 2417err_disable: 2418err_out: 2419 return ret; 2420} 2421 2422static void __devexit cirrusfb_pci_unregister (struct pci_dev *pdev) 2423{ 2424 struct fb_info *info = pci_get_drvdata(pdev); 2425 DPRINTK ("ENTER\n"); 2426 2427 cirrusfb_cleanup (info); 2428 2429 DPRINTK ("EXIT\n"); 2430} 2431 2432static struct pci_driver cirrusfb_pci_driver = { 2433 .name = "cirrusfb", 2434 .id_table = cirrusfb_pci_table, 2435 .probe = cirrusfb_pci_register, 2436 .remove = __devexit_p(cirrusfb_pci_unregister), 2437#ifdef CONFIG_PM 2438#endif 2439}; 2440#endif /* CONFIG_PCI */ 2441 2442 2443#ifdef CONFIG_ZORRO 2444static int cirrusfb_zorro_register(struct zorro_dev *z, 2445 const struct zorro_device_id *ent) 2446{ 2447 struct cirrusfb_info *cinfo; 2448 struct fb_info *info; 2449 cirrusfb_board_t btype; 2450 struct zorro_dev *z2 = NULL; 2451 unsigned long board_addr, board_size, size; 2452 int ret; 2453 2454 btype = ent->driver_data; 2455 if (cirrusfb_zorro_table2[btype].id2) 2456 z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL); 2457 size = cirrusfb_zorro_table2[btype].size; 2458 printk(KERN_INFO "cirrusfb: %s board detected; ", 2459 cirrusfb_board_info[btype].name); 2460 2461 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev); 2462 if (!info) { 2463 printk (KERN_ERR "cirrusfb: could not allocate memory\n"); 2464 ret = -ENOMEM; 2465 goto err_out; 2466 } 2467 2468 cinfo = info->par; 2469 cinfo->info = info; 2470 cinfo->btype = btype; 2471 2472 assert (z > 0); 2473 assert (z2 >= 0); 2474 assert (btype != BT_NONE); 2475 2476 cinfo->zdev = z; 2477 board_addr = zorro_resource_start(z); 2478 board_size = zorro_resource_len(z); 2479 cinfo->size = size; 2480 2481 if (!zorro_request_device(z, "cirrusfb")) { 2482 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n", 2483 board_addr); 2484 ret = -EBUSY; 2485 goto err_release_fb; 2486 } 2487 2488 printk (" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr); 2489 2490 ret = -EIO; 2491 2492 if (btype == BT_PICASSO4) { 2493 printk (" REG at $%lx\n", board_addr + 0x600000); 2494 2495 /* To be precise, for the P4 this is not the */ 2496 /* begin of the board, but the begin of RAM. */ 2497 /* for P4, map in its address space in 2 chunks (### TEST! ) */ 2498 /* (note the ugly hardcoded 16M number) */ 2499 cinfo->regbase = ioremap (board_addr, 16777216); 2500 if (!cinfo->regbase) 2501 goto err_release_region; 2502 2503 DPRINTK ("cirrusfb: Virtual address for board set to: $%p\n", cinfo->regbase); 2504 cinfo->regbase += 0x600000; 2505 cinfo->fbregs_phys = board_addr + 0x600000; 2506 2507 cinfo->fbmem_phys = board_addr + 16777216; 2508 cinfo->fbmem = ioremap (cinfo->fbmem_phys, 16777216); 2509 if (!cinfo->fbmem) 2510 goto err_unmap_regbase; 2511 } else { 2512 printk (" REG at $%lx\n", (unsigned long) z2->resource.start); 2513 2514 cinfo->fbmem_phys = board_addr; 2515 if (board_addr > 0x01000000) 2516 cinfo->fbmem = ioremap (board_addr, board_size); 2517 else 2518 cinfo->fbmem = (caddr_t) ZTWO_VADDR (board_addr); 2519 if (!cinfo->fbmem) 2520 goto err_release_region; 2521 2522 /* set address for REG area of board */ 2523 cinfo->regbase = (caddr_t) ZTWO_VADDR (z2->resource.start); 2524 cinfo->fbregs_phys = z2->resource.start; 2525 2526 DPRINTK ("cirrusfb: Virtual address for board set to: $%p\n", cinfo->regbase); 2527 } 2528 cinfo->unmap = cirrusfb_zorro_unmap; 2529 2530 printk (KERN_INFO "Cirrus Logic chipset on Zorro bus\n"); 2531 zorro_set_drvdata(z, info); 2532 2533 ret = cirrusfb_register(cinfo); 2534 if (ret) { 2535 if (btype == BT_PICASSO4) { 2536 iounmap(cinfo->fbmem); 2537 iounmap(cinfo->regbase - 0x600000); 2538 } else if (board_addr > 0x01000000) 2539 iounmap(cinfo->fbmem); 2540 } 2541 return ret; 2542 2543err_unmap_regbase: 2544 /* Parental advisory: explicit hack */ 2545 iounmap(cinfo->regbase - 0x600000); 2546err_release_region: 2547 release_region(board_addr, board_size); 2548err_release_fb: 2549 framebuffer_release(info); 2550err_out: 2551 return ret; 2552} 2553 2554void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z) 2555{ 2556 struct fb_info *info = zorro_get_drvdata(z); 2557 DPRINTK ("ENTER\n"); 2558 2559 cirrusfb_cleanup (info); 2560 2561 DPRINTK ("EXIT\n"); 2562} 2563 2564static struct zorro_driver cirrusfb_zorro_driver = { 2565 .name = "cirrusfb", 2566 .id_table = cirrusfb_zorro_table, 2567 .probe = cirrusfb_zorro_register, 2568 .remove = __devexit_p(cirrusfb_zorro_unregister), 2569}; 2570#endif /* CONFIG_ZORRO */ 2571 2572static int __init cirrusfb_init(void) 2573{ 2574 int error = 0; 2575 2576#ifndef MODULE 2577 char *option = NULL; 2578 2579 if (fb_get_options("cirrusfb", &option)) 2580 return -ENODEV; 2581 cirrusfb_setup(option); 2582#endif 2583 2584#ifdef CONFIG_ZORRO 2585 error |= zorro_register_driver(&cirrusfb_zorro_driver); 2586#endif 2587#ifdef CONFIG_PCI 2588 error |= pci_register_driver(&cirrusfb_pci_driver); 2589#endif 2590 return error; 2591} 2592 2593 2594 2595#ifndef MODULE 2596static int __init cirrusfb_setup(char *options) { 2597 char *this_opt, s[32]; 2598 int i; 2599 2600 DPRINTK ("ENTER\n"); 2601 2602 if (!options || !*options) 2603 return 0; 2604 2605 while ((this_opt = strsep (&options, ",")) != NULL) { 2606 if (!*this_opt) continue; 2607 2608 DPRINTK("cirrusfb_setup: option '%s'\n", this_opt); 2609 2610 for (i = 0; i < NUM_TOTAL_MODES; i++) { 2611 sprintf (s, "mode:%s", cirrusfb_predefined[i].name); 2612 if (strcmp (this_opt, s) == 0) 2613 cirrusfb_def_mode = i; 2614 } 2615 if (!strcmp(this_opt, "noaccel")) 2616 noaccel = 1; 2617 } 2618 return 0; 2619} 2620#endif 2621 2622 2623 /* 2624 * Modularization 2625 */ 2626 2627MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>"); 2628MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips"); 2629MODULE_LICENSE("GPL"); 2630 2631static void __exit cirrusfb_exit (void) 2632{ 2633#ifdef CONFIG_PCI 2634 pci_unregister_driver(&cirrusfb_pci_driver); 2635#endif 2636#ifdef CONFIG_ZORRO 2637 zorro_unregister_driver(&cirrusfb_zorro_driver); 2638#endif 2639} 2640 2641module_init(cirrusfb_init); 2642 2643#ifdef MODULE 2644module_exit(cirrusfb_exit); 2645#endif 2646 2647 2648/**********************************************************************/ 2649/* about the following functions - I have used the same names for the */ 2650/* functions as Markus Wild did in his Retina driver for NetBSD as */ 2651/* they just made sense for this purpose. Apart from that, I wrote */ 2652/* these functions myself. */ 2653/**********************************************************************/ 2654 2655/*** WGen() - write into one of the external/general registers ***/ 2656static void WGen (const struct cirrusfb_info *cinfo, 2657 int regnum, unsigned char val) 2658{ 2659 unsigned long regofs = 0; 2660 2661 if (cinfo->btype == BT_PICASSO) { 2662 /* Picasso II specific hack */ 2663/* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */ 2664 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D) 2665 regofs = 0xfff; 2666 } 2667 2668 vga_w (cinfo->regbase, regofs + regnum, val); 2669} 2670 2671/*** RGen() - read out one of the external/general registers ***/ 2672static unsigned char RGen (const struct cirrusfb_info *cinfo, int regnum) 2673{ 2674 unsigned long regofs = 0; 2675 2676 if (cinfo->btype == BT_PICASSO) { 2677 /* Picasso II specific hack */ 2678/* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */ 2679 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D) 2680 regofs = 0xfff; 2681 } 2682 2683 return vga_r (cinfo->regbase, regofs + regnum); 2684} 2685 2686/*** AttrOn() - turn on VideoEnable for Attribute controller ***/ 2687static void AttrOn (const struct cirrusfb_info *cinfo) 2688{ 2689 assert (cinfo != NULL); 2690 2691 DPRINTK ("ENTER\n"); 2692 2693 if (vga_rcrt (cinfo->regbase, CL_CRT24) & 0x80) { 2694 /* if we're just in "write value" mode, write back the */ 2695 /* same value as before to not modify anything */ 2696 vga_w (cinfo->regbase, VGA_ATT_IW, 2697 vga_r (cinfo->regbase, VGA_ATT_R)); 2698 } 2699 /* turn on video bit */ 2700/* vga_w (cinfo->regbase, VGA_ATT_IW, 0x20); */ 2701 vga_w (cinfo->regbase, VGA_ATT_IW, 0x33); 2702 2703 /* dummy write on Reg0 to be on "write index" mode next time */ 2704 vga_w (cinfo->regbase, VGA_ATT_IW, 0x00); 2705 2706 DPRINTK ("EXIT\n"); 2707} 2708 2709/*** WHDR() - write into the Hidden DAC register ***/ 2710/* as the HDR is the only extension register that requires special treatment 2711 * (the other extension registers are accessible just like the "ordinary" 2712 * registers of their functional group) here is a specialized routine for 2713 * accessing the HDR 2714 */ 2715static void WHDR (const struct cirrusfb_info *cinfo, unsigned char val) 2716{ 2717 unsigned char dummy; 2718 2719 if (cinfo->btype == BT_PICASSO) { 2720 /* Klaus' hint for correct access to HDR on some boards */ 2721 /* first write 0 to pixel mask (3c6) */ 2722 WGen (cinfo, VGA_PEL_MSK, 0x00); 2723 udelay (200); 2724 /* next read dummy from pixel address (3c8) */ 2725 dummy = RGen (cinfo, VGA_PEL_IW); 2726 udelay (200); 2727 } 2728 /* now do the usual stuff to access the HDR */ 2729 2730 dummy = RGen (cinfo, VGA_PEL_MSK); 2731 udelay (200); 2732 dummy = RGen (cinfo, VGA_PEL_MSK); 2733 udelay (200); 2734 dummy = RGen (cinfo, VGA_PEL_MSK); 2735 udelay (200); 2736 dummy = RGen (cinfo, VGA_PEL_MSK); 2737 udelay (200); 2738 2739 WGen (cinfo, VGA_PEL_MSK, val); 2740 udelay (200); 2741 2742 if (cinfo->btype == BT_PICASSO) { 2743 /* now first reset HDR access counter */ 2744 dummy = RGen (cinfo, VGA_PEL_IW); 2745 udelay (200); 2746 2747 /* and at the end, restore the mask value */ 2748 /* ## is this mask always 0xff? */ 2749 WGen (cinfo, VGA_PEL_MSK, 0xff); 2750 udelay (200); 2751 } 2752} 2753 2754 2755/*** WSFR() - write to the "special function register" (SFR) ***/ 2756static void WSFR (struct cirrusfb_info *cinfo, unsigned char val) 2757{ 2758#ifdef CONFIG_ZORRO 2759 assert (cinfo->regbase != NULL); 2760 cinfo->SFR = val; 2761 z_writeb (val, cinfo->regbase + 0x8000); 2762#endif 2763} 2764 2765/* The Picasso has a second register for switching the monitor bit */ 2766static void WSFR2 (struct cirrusfb_info *cinfo, unsigned char val) 2767{ 2768#ifdef CONFIG_ZORRO 2769 /* writing an arbitrary value to this one causes the monitor switcher */ 2770 /* to flip to Amiga display */ 2771 assert (cinfo->regbase != NULL); 2772 cinfo->SFR = val; 2773 z_writeb (val, cinfo->regbase + 0x9000); 2774#endif 2775} 2776 2777 2778/*** WClut - set CLUT entry (range: 0..63) ***/ 2779static void WClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red, 2780 unsigned char green, unsigned char blue) 2781{ 2782 unsigned int data = VGA_PEL_D; 2783 2784 /* address write mode register is not translated.. */ 2785 vga_w (cinfo->regbase, VGA_PEL_IW, regnum); 2786 2787 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 || 2788 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) { 2789 /* but DAC data register IS, at least for Picasso II */ 2790 if (cinfo->btype == BT_PICASSO) 2791 data += 0xfff; 2792 vga_w (cinfo->regbase, data, red); 2793 vga_w (cinfo->regbase, data, green); 2794 vga_w (cinfo->regbase, data, blue); 2795 } else { 2796 vga_w (cinfo->regbase, data, blue); 2797 vga_w (cinfo->regbase, data, green); 2798 vga_w (cinfo->regbase, data, red); 2799 } 2800} 2801 2802 2803 2804 2805/******************************************************************* 2806 cirrusfb_WaitBLT() 2807 2808 Wait for the BitBLT engine to complete a possible earlier job 2809*********************************************************************/ 2810 2811static void cirrusfb_WaitBLT (u8 __iomem *regbase) 2812{ 2813 /* now busy-wait until we're done */ 2814 while (vga_rgfx (regbase, CL_GR31) & 0x08) 2815 /* do nothing */ ; 2816} 2817 2818/******************************************************************* 2819 cirrusfb_BitBLT() 2820 2821 perform accelerated "scrolling" 2822********************************************************************/ 2823 2824static void cirrusfb_BitBLT (u8 __iomem *regbase, int bits_per_pixel, 2825 u_short curx, u_short cury, u_short destx, u_short desty, 2826 u_short width, u_short height, u_short line_length) 2827{ 2828 u_short nwidth, nheight; 2829 u_long nsrc, ndest; 2830 u_char bltmode; 2831 2832 DPRINTK ("ENTER\n"); 2833 2834 nwidth = width - 1; 2835 nheight = height - 1; 2836 2837 bltmode = 0x00; 2838 /* if source adr < dest addr, do the Blt backwards */ 2839 if (cury <= desty) { 2840 if (cury == desty) { 2841 /* if src and dest are on the same line, check x */ 2842 if (curx < destx) 2843 bltmode |= 0x01; 2844 } else 2845 bltmode |= 0x01; 2846 } 2847 if (!bltmode) { 2848 /* standard case: forward blitting */ 2849 nsrc = (cury * line_length) + curx; 2850 ndest = (desty * line_length) + destx; 2851 } else { 2852 /* this means start addresses are at the end, counting backwards */ 2853 nsrc = cury * line_length + curx + nheight * line_length + nwidth; 2854 ndest = desty * line_length + destx + nheight * line_length + nwidth; 2855 } 2856 2857 /* 2858 run-down of registers to be programmed: 2859 destination pitch 2860 source pitch 2861 BLT width/height 2862 source start 2863 destination start 2864 BLT mode 2865 BLT ROP 2866 VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color" 2867 start/stop 2868 */ 2869 2870 cirrusfb_WaitBLT(regbase); 2871 2872 /* pitch: set to line_length */ 2873 vga_wgfx (regbase, CL_GR24, line_length & 0xff); /* dest pitch low */ 2874 vga_wgfx (regbase, CL_GR25, (line_length >> 8)); /* dest pitch hi */ 2875 vga_wgfx (regbase, CL_GR26, line_length & 0xff); /* source pitch low */ 2876 vga_wgfx (regbase, CL_GR27, (line_length >> 8)); /* source pitch hi */ 2877 2878 /* BLT width: actual number of pixels - 1 */ 2879 vga_wgfx (regbase, CL_GR20, nwidth & 0xff); /* BLT width low */ 2880 vga_wgfx (regbase, CL_GR21, (nwidth >> 8)); /* BLT width hi */ 2881 2882 /* BLT height: actual number of lines -1 */ 2883 vga_wgfx (regbase, CL_GR22, nheight & 0xff); /* BLT height low */ 2884 vga_wgfx (regbase, CL_GR23, (nheight >> 8)); /* BLT width hi */ 2885 2886 /* BLT destination */ 2887 vga_wgfx (regbase, CL_GR28, (u_char) (ndest & 0xff)); /* BLT dest low */ 2888 vga_wgfx (regbase, CL_GR29, (u_char) (ndest >> 8)); /* BLT dest mid */ 2889 vga_wgfx (regbase, CL_GR2A, (u_char) (ndest >> 16)); /* BLT dest hi */ 2890 2891 /* BLT source */ 2892 vga_wgfx (regbase, CL_GR2C, (u_char) (nsrc & 0xff)); /* BLT src low */ 2893 vga_wgfx (regbase, CL_GR2D, (u_char) (nsrc >> 8)); /* BLT src mid */ 2894 vga_wgfx (regbase, CL_GR2E, (u_char) (nsrc >> 16)); /* BLT src hi */ 2895 2896 /* BLT mode */ 2897 vga_wgfx (regbase, CL_GR30, bltmode); /* BLT mode */ 2898 2899 /* BLT ROP: SrcCopy */ 2900 vga_wgfx (regbase, CL_GR32, 0x0d); /* BLT ROP */ 2901 2902 /* and finally: GO! */ 2903 vga_wgfx (regbase, CL_GR31, 0x02); /* BLT Start/status */ 2904 2905 DPRINTK ("EXIT\n"); 2906} 2907 2908 2909/******************************************************************* 2910 cirrusfb_RectFill() 2911 2912 perform accelerated rectangle fill 2913********************************************************************/ 2914 2915static void cirrusfb_RectFill (u8 __iomem *regbase, int bits_per_pixel, 2916 u_short x, u_short y, u_short width, u_short height, 2917 u_char color, u_short line_length) 2918{ 2919 u_short nwidth, nheight; 2920 u_long ndest; 2921 u_char op; 2922 2923 DPRINTK ("ENTER\n"); 2924 2925 nwidth = width - 1; 2926 nheight = height - 1; 2927 2928 ndest = (y * line_length) + x; 2929 2930 cirrusfb_WaitBLT(regbase); 2931 2932 /* pitch: set to line_length */ 2933 vga_wgfx (regbase, CL_GR24, line_length & 0xff); /* dest pitch low */ 2934 vga_wgfx (regbase, CL_GR25, (line_length >> 8)); /* dest pitch hi */ 2935 vga_wgfx (regbase, CL_GR26, line_length & 0xff); /* source pitch low */ 2936 vga_wgfx (regbase, CL_GR27, (line_length >> 8)); /* source pitch hi */ 2937 2938 /* BLT width: actual number of pixels - 1 */ 2939 vga_wgfx (regbase, CL_GR20, nwidth & 0xff); /* BLT width low */ 2940 vga_wgfx (regbase, CL_GR21, (nwidth >> 8)); /* BLT width hi */ 2941 2942 /* BLT height: actual number of lines -1 */ 2943 vga_wgfx (regbase, CL_GR22, nheight & 0xff); /* BLT height low */ 2944 vga_wgfx (regbase, CL_GR23, (nheight >> 8)); /* BLT width hi */ 2945 2946 /* BLT destination */ 2947 vga_wgfx (regbase, CL_GR28, (u_char) (ndest & 0xff)); /* BLT dest low */ 2948 vga_wgfx (regbase, CL_GR29, (u_char) (ndest >> 8)); /* BLT dest mid */ 2949 vga_wgfx (regbase, CL_GR2A, (u_char) (ndest >> 16)); /* BLT dest hi */ 2950 2951 /* BLT source: set to 0 (is a dummy here anyway) */ 2952 vga_wgfx (regbase, CL_GR2C, 0x00); /* BLT src low */ 2953 vga_wgfx (regbase, CL_GR2D, 0x00); /* BLT src mid */ 2954 vga_wgfx (regbase, CL_GR2E, 0x00); /* BLT src hi */ 2955 2956 /* This is a ColorExpand Blt, using the */ 2957 /* same color for foreground and background */ 2958 vga_wgfx (regbase, VGA_GFX_SR_VALUE, color); /* foreground color */ 2959 vga_wgfx (regbase, VGA_GFX_SR_ENABLE, color); /* background color */ 2960 2961 op = 0xc0; 2962 if (bits_per_pixel == 16) { 2963 vga_wgfx (regbase, CL_GR10, color); /* foreground color */ 2964 vga_wgfx (regbase, CL_GR11, color); /* background color */ 2965 op = 0x50; 2966 op = 0xd0; 2967 } else if (bits_per_pixel == 32) { 2968 vga_wgfx (regbase, CL_GR10, color); /* foreground color */ 2969 vga_wgfx (regbase, CL_GR11, color); /* background color */ 2970 vga_wgfx (regbase, CL_GR12, color); /* foreground color */ 2971 vga_wgfx (regbase, CL_GR13, color); /* background color */ 2972 vga_wgfx (regbase, CL_GR14, 0); /* foreground color */ 2973 vga_wgfx (regbase, CL_GR15, 0); /* background color */ 2974 op = 0x50; 2975 op = 0xf0; 2976 } 2977 /* BLT mode: color expand, Enable 8x8 copy (faster?) */ 2978 vga_wgfx (regbase, CL_GR30, op); /* BLT mode */ 2979 2980 /* BLT ROP: SrcCopy */ 2981 vga_wgfx (regbase, CL_GR32, 0x0d); /* BLT ROP */ 2982 2983 /* and finally: GO! */ 2984 vga_wgfx (regbase, CL_GR31, 0x02); /* BLT Start/status */ 2985 2986 DPRINTK ("EXIT\n"); 2987} 2988 2989 2990/************************************************************************** 2991 * bestclock() - determine closest possible clock lower(?) than the 2992 * desired pixel clock 2993 **************************************************************************/ 2994static void bestclock (long freq, long *best, long *nom, 2995 long *den, long *div, long maxfreq) 2996{ 2997 long n, h, d, f; 2998 2999 assert (best != NULL); 3000 assert (nom != NULL); 3001 assert (den != NULL); 3002 assert (div != NULL); 3003 assert (maxfreq > 0); 3004 3005 *nom = 0; 3006 *den = 0; 3007 *div = 0; 3008 3009 DPRINTK ("ENTER\n"); 3010 3011 if (freq < 8000) 3012 freq = 8000; 3013 3014 if (freq > maxfreq) 3015 freq = maxfreq; 3016 3017 *best = 0; 3018 f = freq * 10; 3019 3020 for (n = 32; n < 128; n++) { 3021 d = (143181 * n) / f; 3022 if ((d >= 7) && (d <= 63)) { 3023 if (d > 31) 3024 d = (d / 2) * 2; 3025 h = (14318 * n) / d; 3026 if (abs (h - freq) < abs (*best - freq)) { 3027 *best = h; 3028 *nom = n; 3029 if (d < 32) { 3030 *den = d; 3031 *div = 0; 3032 } else { 3033 *den = d / 2; 3034 *div = 1; 3035 } 3036 } 3037 } 3038 d = ((143181 * n) + f - 1) / f; 3039 if ((d >= 7) && (d <= 63)) { 3040 if (d > 31) 3041 d = (d / 2) * 2; 3042 h = (14318 * n) / d; 3043 if (abs (h - freq) < abs (*best - freq)) { 3044 *best = h; 3045 *nom = n; 3046 if (d < 32) { 3047 *den = d; 3048 *div = 0; 3049 } else { 3050 *den = d / 2; 3051 *div = 1; 3052 } 3053 } 3054 } 3055 } 3056 3057 DPRINTK ("Best possible values for given frequency:\n"); 3058 DPRINTK (" best: %ld kHz nom: %ld den: %ld div: %ld\n", 3059 freq, *nom, *den, *div); 3060 3061 DPRINTK ("EXIT\n"); 3062} 3063 3064 3065/* ------------------------------------------------------------------------- 3066 * 3067 * debugging functions 3068 * 3069 * ------------------------------------------------------------------------- 3070 */ 3071 3072#ifdef CIRRUSFB_DEBUG 3073 3074/** 3075 * cirrusfb_dbg_print_byte 3076 * @name: name associated with byte value to be displayed 3077 * @val: byte value to be displayed 3078 * 3079 * DESCRIPTION: 3080 * Display an indented string, along with a hexidecimal byte value, and 3081 * its decoded bits. Bits 7 through 0 are listed in left-to-right 3082 * order. 3083 */ 3084 3085static 3086void cirrusfb_dbg_print_byte (const char *name, unsigned char val) 3087{ 3088 DPRINTK ("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n", 3089 name, val, 3090 val & 0x80 ? '1' : '0', 3091 val & 0x40 ? '1' : '0', 3092 val & 0x20 ? '1' : '0', 3093 val & 0x10 ? '1' : '0', 3094 val & 0x08 ? '1' : '0', 3095 val & 0x04 ? '1' : '0', 3096 val & 0x02 ? '1' : '0', 3097 val & 0x01 ? '1' : '0'); 3098} 3099 3100 3101/** 3102 * cirrusfb_dbg_print_regs 3103 * @base: If using newmmio, the newmmio base address, otherwise %NULL 3104 * @reg_class: type of registers to read: %CRT, or %SEQ 3105 * 3106 * DESCRIPTION: 3107 * Dumps the given list of VGA CRTC registers. If @base is %NULL, 3108 * old-style I/O ports are queried for information, otherwise MMIO is 3109 * used at the given @base address to query the information. 3110 */ 3111 3112static 3113void cirrusfb_dbg_print_regs (caddr_t regbase, cirrusfb_dbg_reg_class_t reg_class,...) 3114{ 3115 va_list list; 3116 unsigned char val = 0; 3117 unsigned reg; 3118 char *name; 3119 3120 va_start (list, reg_class); 3121 3122 name = va_arg (list, char *); 3123 while (name != NULL) { 3124 reg = va_arg (list, int); 3125 3126 switch (reg_class) { 3127 case CRT: 3128 val = vga_rcrt (regbase, (unsigned char) reg); 3129 break; 3130 case SEQ: 3131 val = vga_rseq (regbase, (unsigned char) reg); 3132 break; 3133 default: 3134 /* should never occur */ 3135 assert(false); 3136 break; 3137 } 3138 3139 cirrusfb_dbg_print_byte (name, val); 3140 3141 name = va_arg (list, char *); 3142 } 3143 3144 va_end (list); 3145} 3146 3147 3148/** 3149 * cirrusfb_dump 3150 * @cirrusfbinfo: 3151 * 3152 * DESCRIPTION: 3153 */ 3154 3155static 3156void cirrusfb_dump (void) 3157{ 3158 cirrusfb_dbg_reg_dump (NULL); 3159} 3160 3161 3162/** 3163 * cirrusfb_dbg_reg_dump 3164 * @base: If using newmmio, the newmmio base address, otherwise %NULL 3165 * 3166 * DESCRIPTION: 3167 * Dumps a list of interesting VGA and CIRRUSFB registers. If @base is %NULL, 3168 * old-style I/O ports are queried for information, otherwise MMIO is 3169 * used at the given @base address to query the information. 3170 */ 3171 3172static 3173void cirrusfb_dbg_reg_dump (caddr_t regbase) 3174{ 3175 DPRINTK ("CIRRUSFB VGA CRTC register dump:\n"); 3176 3177 cirrusfb_dbg_print_regs (regbase, CRT, 3178 "CR00", 0x00, 3179 "CR01", 0x01, 3180 "CR02", 0x02, 3181 "CR03", 0x03, 3182 "CR04", 0x04, 3183 "CR05", 0x05, 3184 "CR06", 0x06, 3185 "CR07", 0x07, 3186 "CR08", 0x08, 3187 "CR09", 0x09, 3188 "CR0A", 0x0A, 3189 "CR0B", 0x0B, 3190 "CR0C", 0x0C, 3191 "CR0D", 0x0D, 3192 "CR0E", 0x0E, 3193 "CR0F", 0x0F, 3194 "CR10", 0x10, 3195 "CR11", 0x11, 3196 "CR12", 0x12, 3197 "CR13", 0x13, 3198 "CR14", 0x14, 3199 "CR15", 0x15, 3200 "CR16", 0x16, 3201 "CR17", 0x17, 3202 "CR18", 0x18, 3203 "CR22", 0x22, 3204 "CR24", 0x24, 3205 "CR26", 0x26, 3206 "CR2D", 0x2D, 3207 "CR2E", 0x2E, 3208 "CR2F", 0x2F, 3209 "CR30", 0x30, 3210 "CR31", 0x31, 3211 "CR32", 0x32, 3212 "CR33", 0x33, 3213 "CR34", 0x34, 3214 "CR35", 0x35, 3215 "CR36", 0x36, 3216 "CR37", 0x37, 3217 "CR38", 0x38, 3218 "CR39", 0x39, 3219 "CR3A", 0x3A, 3220 "CR3B", 0x3B, 3221 "CR3C", 0x3C, 3222 "CR3D", 0x3D, 3223 "CR3E", 0x3E, 3224 "CR3F", 0x3F, 3225 NULL); 3226 3227 DPRINTK ("\n"); 3228 3229 DPRINTK ("CIRRUSFB VGA SEQ register dump:\n"); 3230 3231 cirrusfb_dbg_print_regs (regbase, SEQ, 3232 "SR00", 0x00, 3233 "SR01", 0x01, 3234 "SR02", 0x02, 3235 "SR03", 0x03, 3236 "SR04", 0x04, 3237 "SR08", 0x08, 3238 "SR09", 0x09, 3239 "SR0A", 0x0A, 3240 "SR0B", 0x0B, 3241 "SR0D", 0x0D, 3242 "SR10", 0x10, 3243 "SR11", 0x11, 3244 "SR12", 0x12, 3245 "SR13", 0x13, 3246 "SR14", 0x14, 3247 "SR15", 0x15, 3248 "SR16", 0x16, 3249 "SR17", 0x17, 3250 "SR18", 0x18, 3251 "SR19", 0x19, 3252 "SR1A", 0x1A, 3253 "SR1B", 0x1B, 3254 "SR1C", 0x1C, 3255 "SR1D", 0x1D, 3256 "SR1E", 0x1E, 3257 "SR1F", 0x1F, 3258 NULL); 3259 3260 DPRINTK ("\n"); 3261} 3262 3263#endif /* CIRRUSFB_DEBUG */ 3264