Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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