x86, cpa: no need to check alias for __set_pages_p/__set_pages_np
[linux-2.6/verdex.git] / drivers / video / cirrusfb.c
blobe729fb279645dd34f634be1fb0ddaea60396a7bb
1 /*
2 * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
4 * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
6 * Contributors (thanks, all!)
8 * David Eger:
9 * Overhaul for Linux 2.6
11 * Jeff Rugen:
12 * Major contributions; Motorola PowerStack (PPC and PCI) support,
13 * GD54xx, 1280x1024 mode support, change MCLK based on VCLK.
15 * Geert Uytterhoeven:
16 * Excellent code review.
18 * Lars Hecking:
19 * Amiga updates and testing.
21 * Original cirrusfb author: Frank Neumann
23 * Based on retz3fb.c and cirrusfb.c:
24 * Copyright (C) 1997 Jes Sorensen
25 * Copyright (C) 1996 Frank Neumann
27 ***************************************************************
29 * Format this code with GNU indent '-kr -i8 -pcs' options.
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.
37 #define CIRRUSFB_VERSION "2.0-pre2"
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>
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
66 #include <video/vga.h>
67 #include <video/cirrus.h>
69 /*****************************************************************
71 * debugging and utility macros
75 /* enable debug output? */
76 /* #define CIRRUSFB_DEBUG 1 */
78 /* disable runtime assertions? */
79 /* #define CIRRUSFB_NDEBUG */
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
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__); \
96 #else
97 #define assert(expr)
98 #endif
100 #define MB_ (1024 * 1024)
102 /*****************************************************************
104 * chipset information
108 /* board types */
109 enum 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 */
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?
130 static 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;
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;
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,
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
163 [BT_PICCOLO] = {
164 .name = "CL Piccolo",
165 .maxclock = {
166 /* guess */
167 90000, 90000, 90000, 90000, 90000
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
177 [BT_PICASSO] = {
178 .name = "CL Picasso",
179 .maxclock = {
180 /* guess */
181 90000, 90000, 90000, 90000, 90000
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
191 [BT_SPECTRUM] = {
192 .name = "CL Spectrum",
193 .maxclock = {
194 /* guess */
195 90000, 90000, 90000, 90000, 90000
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
205 [BT_PICASSO4] = {
206 .name = "CL Picasso4",
207 .maxclock = {
208 135100, 135100, 85500, 85500, 0
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
218 [BT_ALPINE] = {
219 .name = "CL Alpine",
220 .maxclock = {
221 /* for the GD5430. GD5446 can do more... */
222 85500, 85500, 50000, 28500, 0
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
234 [BT_GD5480] = {
235 .name = "CL GD5480",
236 .maxclock = {
237 135100, 200000, 200000, 135100, 135100
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
247 [BT_LAGUNA] = {
248 .name = "CL Laguna",
249 .maxclock = {
250 /* guess */
251 135100, 135100, 135100, 135100, 135100,
253 .init_sr07 = false,
254 .init_sr1f = false,
255 .scrn_start_bit19 = true,
259 #ifdef CONFIG_PCI
260 #define CHIP(id, btype) \
261 { PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
263 static 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, }
277 MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
278 #undef CHIP
279 #endif /* CONFIG_PCI */
281 #ifdef CONFIG_ZORRO
282 static const struct zorro_device_id cirrusfb_zorro_table[] = {
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,
299 { 0 }
302 static 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
310 [BT_PICCOLO] = {
311 .id2 = ZORRO_PROD_HELFRICH_PICCOLO_REG,
312 .size = 0x200000
314 [BT_PICASSO] = {
315 .id2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
316 .size = 0x200000
318 [BT_SPECTRUM] = {
319 .id2 = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
320 .size = 0x200000
322 [BT_PICASSO4] = {
323 .id2 = 0,
324 .size = 0x400000
327 #endif /* CONFIG_ZORRO */
329 struct cirrusfb_regs {
330 long freq;
331 long nom;
332 long den;
333 long div;
334 long multiplexing;
335 long mclk;
336 long divMCLK;
338 long HorizRes; /* The x resolution in pixel */
339 long HorizTotal;
340 long HorizDispEnd;
341 long HorizBlankStart;
342 long HorizBlankEnd;
343 long HorizSyncStart;
344 long HorizSyncEnd;
346 long VertRes; /* the physical y resolution in scanlines */
347 long VertTotal;
348 long VertDispEnd;
349 long VertSyncStart;
350 long VertSyncEnd;
351 long VertBlankStart;
352 long VertBlankEnd;
355 #ifdef CIRRUSFB_DEBUG
356 enum cirrusfb_dbg_reg_class {
357 CRT,
360 #endif /* CIRRUSFB_DEBUG */
362 /* info about board */
363 struct cirrusfb_info {
364 u8 __iomem *regbase;
365 enum cirrus_board btype;
366 unsigned char SFR; /* Shadow of special function register */
368 struct cirrusfb_regs currentmode;
369 int blank_mode;
371 u32 pseudo_palette[16];
373 #ifdef CONFIG_ZORRO
374 struct zorro_dev *zdev;
375 #endif
376 #ifdef CONFIG_PCI
377 struct pci_dev *pdev;
378 #endif
379 void (*unmap)(struct fb_info *info);
382 static unsigned cirrusfb_def_mode = 1;
383 static int noaccel;
386 * Predefined Video Modes
389 static const struct {
390 const char *name;
391 struct fb_var_screeninfo var;
392 } cirrusfb_predefined[] = {
394 /* autodetect mode */
395 .name = "Autodetect",
396 }, {
397 /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
398 .name = "640x480",
399 .var = {
400 .xres = 640,
401 .yres = 480,
402 .xres_virtual = 640,
403 .yres_virtual = 480,
404 .bits_per_pixel = 8,
405 .red = { .length = 8 },
406 .green = { .length = 8 },
407 .blue = { .length = 8 },
408 .width = -1,
409 .height = -1,
410 .pixclock = 40000,
411 .left_margin = 48,
412 .right_margin = 16,
413 .upper_margin = 32,
414 .lower_margin = 8,
415 .hsync_len = 96,
416 .vsync_len = 4,
417 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
418 .vmode = FB_VMODE_NONINTERLACED
420 }, {
421 /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */
422 .name = "800x600",
423 .var = {
424 .xres = 800,
425 .yres = 600,
426 .xres_virtual = 800,
427 .yres_virtual = 600,
428 .bits_per_pixel = 8,
429 .red = { .length = 8 },
430 .green = { .length = 8 },
431 .blue = { .length = 8 },
432 .width = -1,
433 .height = -1,
434 .pixclock = 20000,
435 .left_margin = 128,
436 .right_margin = 16,
437 .upper_margin = 24,
438 .lower_margin = 2,
439 .hsync_len = 96,
440 .vsync_len = 6,
441 .vmode = FB_VMODE_NONINTERLACED
443 }, {
445 * Modeline from XF86Config:
446 * Mode "1024x768" 80 1024 1136 1340 1432 768 770 774 805
448 /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
449 .name = "1024x768",
450 .var = {
451 .xres = 1024,
452 .yres = 768,
453 .xres_virtual = 1024,
454 .yres_virtual = 768,
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 = 12500,
462 .left_margin = 144,
463 .right_margin = 32,
464 .upper_margin = 30,
465 .lower_margin = 2,
466 .hsync_len = 192,
467 .vsync_len = 6,
468 .vmode = FB_VMODE_NONINTERLACED
473 #define NUM_TOTAL_MODES ARRAY_SIZE(cirrusfb_predefined)
475 /****************************************************************************/
476 /**** BEGIN PROTOTYPES ******************************************************/
478 /*--- Interface used by the world ------------------------------------------*/
479 static int cirrusfb_init(void);
480 #ifndef MODULE
481 static int cirrusfb_setup(char *options);
482 #endif
484 static int cirrusfb_open(struct fb_info *info, int user);
485 static int cirrusfb_release(struct fb_info *info, int user);
486 static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
487 unsigned blue, unsigned transp,
488 struct fb_info *info);
489 static int cirrusfb_check_var(struct fb_var_screeninfo *var,
490 struct fb_info *info);
491 static int cirrusfb_set_par(struct fb_info *info);
492 static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
493 struct fb_info *info);
494 static int cirrusfb_blank(int blank_mode, struct fb_info *info);
495 static void cirrusfb_fillrect(struct fb_info *info,
496 const struct fb_fillrect *region);
497 static void cirrusfb_copyarea(struct fb_info *info,
498 const struct fb_copyarea *area);
499 static void cirrusfb_imageblit(struct fb_info *info,
500 const struct fb_image *image);
502 /* function table of the above functions */
503 static struct fb_ops cirrusfb_ops = {
504 .owner = THIS_MODULE,
505 .fb_open = cirrusfb_open,
506 .fb_release = cirrusfb_release,
507 .fb_setcolreg = cirrusfb_setcolreg,
508 .fb_check_var = cirrusfb_check_var,
509 .fb_set_par = cirrusfb_set_par,
510 .fb_pan_display = cirrusfb_pan_display,
511 .fb_blank = cirrusfb_blank,
512 .fb_fillrect = cirrusfb_fillrect,
513 .fb_copyarea = cirrusfb_copyarea,
514 .fb_imageblit = cirrusfb_imageblit,
517 /*--- Hardware Specific Routines -------------------------------------------*/
518 static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
519 struct cirrusfb_regs *regs,
520 struct fb_info *info);
521 /*--- Internal routines ----------------------------------------------------*/
522 static void init_vgachip(struct fb_info *info);
523 static void switch_monitor(struct cirrusfb_info *cinfo, int on);
524 static void WGen(const struct cirrusfb_info *cinfo,
525 int regnum, unsigned char val);
526 static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum);
527 static void AttrOn(const struct cirrusfb_info *cinfo);
528 static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val);
529 static void WSFR(struct cirrusfb_info *cinfo, unsigned char val);
530 static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val);
531 static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum,
532 unsigned char red, unsigned char green, unsigned char blue);
533 #if 0
534 static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum,
535 unsigned char *red, unsigned char *green,
536 unsigned char *blue);
537 #endif
538 static void cirrusfb_WaitBLT(u8 __iomem *regbase);
539 static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
540 u_short curx, u_short cury,
541 u_short destx, u_short desty,
542 u_short width, u_short height,
543 u_short line_length);
544 static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
545 u_short x, u_short y,
546 u_short width, u_short height,
547 u_char color, u_short line_length);
549 static void bestclock(long freq, long *best,
550 long *nom, long *den,
551 long *div, long maxfreq);
553 #ifdef CIRRUSFB_DEBUG
554 static void cirrusfb_dump(void);
555 static void cirrusfb_dbg_reg_dump(caddr_t regbase);
556 static void cirrusfb_dbg_print_regs(caddr_t regbase,
557 enum cirrusfb_dbg_reg_class reg_class, ...);
558 static void cirrusfb_dbg_print_byte(const char *name, unsigned char val);
559 #endif /* CIRRUSFB_DEBUG */
561 /*** END PROTOTYPES ********************************************************/
562 /*****************************************************************************/
563 /*** BEGIN Interface Used by the World ***************************************/
565 static int opencount;
567 /*--- Open /dev/fbx ---------------------------------------------------------*/
568 static int cirrusfb_open(struct fb_info *info, int user)
570 if (opencount++ == 0)
571 switch_monitor(info->par, 1);
572 return 0;
575 /*--- Close /dev/fbx --------------------------------------------------------*/
576 static int cirrusfb_release(struct fb_info *info, int user)
578 if (--opencount == 0)
579 switch_monitor(info->par, 0);
580 return 0;
583 /**** END Interface used by the World *************************************/
584 /****************************************************************************/
585 /**** BEGIN Hardware specific Routines **************************************/
587 /* Get a good MCLK value */
588 static long cirrusfb_get_mclk(long freq, int bpp, long *div)
590 long mclk;
592 assert(div != NULL);
594 /* Calculate MCLK, in case VCLK is high enough to require > 50MHz.
595 * Assume a 64-bit data path for now. The formula is:
596 * ((B * PCLK * 2)/W) * 1.2
597 * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */
598 mclk = ((bpp / 8) * freq * 2) / 4;
599 mclk = (mclk * 12) / 10;
600 if (mclk < 50000)
601 mclk = 50000;
602 DPRINTK("Use MCLK of %ld kHz\n", mclk);
604 /* Calculate value for SR1F. Multiply by 2 so we can round up. */
605 mclk = ((mclk * 16) / 14318);
606 mclk = (mclk + 1) / 2;
607 DPRINTK("Set SR1F[5:0] to 0x%lx\n", mclk);
609 /* Determine if we should use MCLK instead of VCLK, and if so, what we
610 * should divide it by to get VCLK */
611 switch (freq) {
612 case 24751 ... 25249:
613 *div = 2;
614 DPRINTK("Using VCLK = MCLK/2\n");
615 break;
616 case 49501 ... 50499:
617 *div = 1;
618 DPRINTK("Using VCLK = MCLK\n");
619 break;
620 default:
621 *div = 0;
622 break;
625 return mclk;
628 static int cirrusfb_check_var(struct fb_var_screeninfo *var,
629 struct fb_info *info)
631 int yres;
632 /* memory size in pixels */
633 unsigned pixels = info->screen_size * 8 / var->bits_per_pixel;
635 switch (var->bits_per_pixel) {
636 case 1:
637 pixels /= 4;
638 break; /* 8 pixel per byte, only 1/4th of mem usable */
639 case 8:
640 case 16:
641 case 24:
642 case 32:
643 break; /* 1 pixel == 1 byte */
644 default:
645 printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..."
646 "color depth not supported.\n",
647 var->xres, var->yres, var->bits_per_pixel);
648 DPRINTK("EXIT - EINVAL error\n");
649 return -EINVAL;
652 if (var->xres_virtual < var->xres)
653 var->xres_virtual = var->xres;
654 /* use highest possible virtual resolution */
655 if (var->yres_virtual == -1) {
656 var->yres_virtual = pixels / var->xres_virtual;
658 printk(KERN_INFO "cirrusfb: virtual resolution set to "
659 "maximum of %dx%d\n", var->xres_virtual,
660 var->yres_virtual);
662 if (var->yres_virtual < var->yres)
663 var->yres_virtual = var->yres;
665 if (var->xres_virtual * var->yres_virtual > pixels) {
666 printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected... "
667 "virtual resolution too high to fit into video memory!\n",
668 var->xres_virtual, var->yres_virtual,
669 var->bits_per_pixel);
670 DPRINTK("EXIT - EINVAL error\n");
671 return -EINVAL;
675 if (var->xoffset < 0)
676 var->xoffset = 0;
677 if (var->yoffset < 0)
678 var->yoffset = 0;
680 /* truncate xoffset and yoffset to maximum if too high */
681 if (var->xoffset > var->xres_virtual - var->xres)
682 var->xoffset = var->xres_virtual - var->xres - 1;
683 if (var->yoffset > var->yres_virtual - var->yres)
684 var->yoffset = var->yres_virtual - var->yres - 1;
686 switch (var->bits_per_pixel) {
687 case 1:
688 var->red.offset = 0;
689 var->red.length = 1;
690 var->green = var->red;
691 var->blue = var->red;
692 break;
694 case 8:
695 var->red.offset = 0;
696 var->red.length = 6;
697 var->green = var->red;
698 var->blue = var->red;
699 break;
701 case 16:
702 if (isPReP) {
703 var->red.offset = 2;
704 var->green.offset = -3;
705 var->blue.offset = 8;
706 } else {
707 var->red.offset = 10;
708 var->green.offset = 5;
709 var->blue.offset = 0;
711 var->red.length = 5;
712 var->green.length = 5;
713 var->blue.length = 5;
714 break;
716 case 24:
717 case 32:
718 if (isPReP) {
719 var->red.offset = 8;
720 var->green.offset = 16;
721 var->blue.offset = 24;
722 } else {
723 var->red.offset = 16;
724 var->green.offset = 8;
725 var->blue.offset = 0;
727 var->red.length = 8;
728 var->green.length = 8;
729 var->blue.length = 8;
730 break;
732 default:
733 DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);
734 assert(false);
735 /* should never occur */
736 break;
739 var->red.msb_right =
740 var->green.msb_right =
741 var->blue.msb_right =
742 var->transp.offset =
743 var->transp.length =
744 var->transp.msb_right = 0;
746 yres = var->yres;
747 if (var->vmode & FB_VMODE_DOUBLE)
748 yres *= 2;
749 else if (var->vmode & FB_VMODE_INTERLACED)
750 yres = (yres + 1) / 2;
752 if (yres >= 1280) {
753 printk(KERN_ERR "cirrusfb: ERROR: VerticalTotal >= 1280; "
754 "special treatment required! (TODO)\n");
755 DPRINTK("EXIT - EINVAL error\n");
756 return -EINVAL;
759 return 0;
762 static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
763 struct cirrusfb_regs *regs,
764 struct fb_info *info)
766 long freq;
767 long maxclock;
768 int maxclockidx = var->bits_per_pixel >> 3;
769 struct cirrusfb_info *cinfo = info->par;
770 int xres, hfront, hsync, hback;
771 int yres, vfront, vsync, vback;
773 switch (var->bits_per_pixel) {
774 case 1:
775 info->fix.line_length = var->xres_virtual / 8;
776 info->fix.visual = FB_VISUAL_MONO10;
777 break;
779 case 8:
780 info->fix.line_length = var->xres_virtual;
781 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
782 break;
784 case 16:
785 case 24:
786 case 32:
787 info->fix.line_length = var->xres_virtual * maxclockidx;
788 info->fix.visual = FB_VISUAL_DIRECTCOLOR;
789 break;
791 default:
792 DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);
793 assert(false);
794 /* should never occur */
795 break;
798 info->fix.type = FB_TYPE_PACKED_PIXELS;
800 /* convert from ps to kHz */
801 freq = PICOS2KHZ(var->pixclock);
803 DPRINTK("desired pixclock: %ld kHz\n", freq);
805 maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
806 regs->multiplexing = 0;
808 /* If the frequency is greater than we can support, we might be able
809 * to use multiplexing for the video mode */
810 if (freq > maxclock) {
811 switch (cinfo->btype) {
812 case BT_ALPINE:
813 case BT_GD5480:
814 regs->multiplexing = 1;
815 break;
817 default:
818 printk(KERN_ERR "cirrusfb: Frequency greater "
819 "than maxclock (%ld kHz)\n", maxclock);
820 DPRINTK("EXIT - return -EINVAL\n");
821 return -EINVAL;
824 #if 0
825 /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
826 * the VCLK is double the pixel clock. */
827 switch (var->bits_per_pixel) {
828 case 16:
829 case 32:
830 if (regs->HorizRes <= 800)
831 /* Xbh has this type of clock for 32-bit */
832 freq /= 2;
833 break;
835 #endif
837 bestclock(freq, &regs->freq, &regs->nom, &regs->den, &regs->div,
838 maxclock);
839 regs->mclk = cirrusfb_get_mclk(freq, var->bits_per_pixel,
840 &regs->divMCLK);
842 xres = var->xres;
843 hfront = var->right_margin;
844 hsync = var->hsync_len;
845 hback = var->left_margin;
847 yres = var->yres;
848 vfront = var->lower_margin;
849 vsync = var->vsync_len;
850 vback = var->upper_margin;
852 if (var->vmode & FB_VMODE_DOUBLE) {
853 yres *= 2;
854 vfront *= 2;
855 vsync *= 2;
856 vback *= 2;
857 } else if (var->vmode & FB_VMODE_INTERLACED) {
858 yres = (yres + 1) / 2;
859 vfront = (vfront + 1) / 2;
860 vsync = (vsync + 1) / 2;
861 vback = (vback + 1) / 2;
863 regs->HorizRes = xres;
864 regs->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5;
865 regs->HorizDispEnd = xres / 8 - 1;
866 regs->HorizBlankStart = xres / 8;
867 /* does not count with "-5" */
868 regs->HorizBlankEnd = regs->HorizTotal + 5;
869 regs->HorizSyncStart = (xres + hfront) / 8 + 1;
870 regs->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1;
872 regs->VertRes = yres;
873 regs->VertTotal = yres + vfront + vsync + vback - 2;
874 regs->VertDispEnd = yres - 1;
875 regs->VertBlankStart = yres;
876 regs->VertBlankEnd = regs->VertTotal;
877 regs->VertSyncStart = yres + vfront - 1;
878 regs->VertSyncEnd = yres + vfront + vsync - 1;
880 if (regs->VertRes >= 1024) {
881 regs->VertTotal /= 2;
882 regs->VertSyncStart /= 2;
883 regs->VertSyncEnd /= 2;
884 regs->VertDispEnd /= 2;
886 if (regs->multiplexing) {
887 regs->HorizTotal /= 2;
888 regs->HorizSyncStart /= 2;
889 regs->HorizSyncEnd /= 2;
890 regs->HorizDispEnd /= 2;
893 return 0;
896 static void cirrusfb_set_mclk(const struct cirrusfb_info *cinfo, int val,
897 int div)
899 assert(cinfo != NULL);
901 if (div == 2) {
902 /* VCLK = MCLK/2 */
903 unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E);
904 vga_wseq(cinfo->regbase, CL_SEQR1E, old | 0x1);
905 vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
906 } else if (div == 1) {
907 /* VCLK = MCLK */
908 unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E);
909 vga_wseq(cinfo->regbase, CL_SEQR1E, old & ~0x1);
910 vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
911 } else {
912 vga_wseq(cinfo->regbase, CL_SEQR1F, val & 0x3f);
916 /*************************************************************************
917 cirrusfb_set_par_foo()
919 actually writes the values for a new video mode into the hardware,
920 **************************************************************************/
921 static int cirrusfb_set_par_foo(struct fb_info *info)
923 struct cirrusfb_info *cinfo = info->par;
924 struct fb_var_screeninfo *var = &info->var;
925 struct cirrusfb_regs regs;
926 u8 __iomem *regbase = cinfo->regbase;
927 unsigned char tmp;
928 int offset = 0, err;
929 const struct cirrusfb_board_info_rec *bi;
931 DPRINTK("ENTER\n");
932 DPRINTK("Requested mode: %dx%dx%d\n",
933 var->xres, var->yres, var->bits_per_pixel);
934 DPRINTK("pixclock: %d\n", var->pixclock);
936 init_vgachip(info);
938 err = cirrusfb_decode_var(var, &regs, info);
939 if (err) {
940 /* should never happen */
941 DPRINTK("mode change aborted. invalid var.\n");
942 return -EINVAL;
945 bi = &cirrusfb_board_info[cinfo->btype];
947 /* unlock register VGA_CRTC_H_TOTAL..CRT7 */
948 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */
950 /* if debugging is enabled, all parameters get output before writing */
951 DPRINTK("CRT0: %ld\n", regs.HorizTotal);
952 vga_wcrt(regbase, VGA_CRTC_H_TOTAL, regs.HorizTotal);
954 DPRINTK("CRT1: %ld\n", regs.HorizDispEnd);
955 vga_wcrt(regbase, VGA_CRTC_H_DISP, regs.HorizDispEnd);
957 DPRINTK("CRT2: %ld\n", regs.HorizBlankStart);
958 vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, regs.HorizBlankStart);
960 /* + 128: Compatible read */
961 DPRINTK("CRT3: 128+%ld\n", regs.HorizBlankEnd % 32);
962 vga_wcrt(regbase, VGA_CRTC_H_BLANK_END,
963 128 + (regs.HorizBlankEnd % 32));
965 DPRINTK("CRT4: %ld\n", regs.HorizSyncStart);
966 vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, regs.HorizSyncStart);
968 tmp = regs.HorizSyncEnd % 32;
969 if (regs.HorizBlankEnd & 32)
970 tmp += 128;
971 DPRINTK("CRT5: %d\n", tmp);
972 vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp);
974 DPRINTK("CRT6: %ld\n", regs.VertTotal & 0xff);
975 vga_wcrt(regbase, VGA_CRTC_V_TOTAL, (regs.VertTotal & 0xff));
977 tmp = 16; /* LineCompare bit #9 */
978 if (regs.VertTotal & 256)
979 tmp |= 1;
980 if (regs.VertDispEnd & 256)
981 tmp |= 2;
982 if (regs.VertSyncStart & 256)
983 tmp |= 4;
984 if (regs.VertBlankStart & 256)
985 tmp |= 8;
986 if (regs.VertTotal & 512)
987 tmp |= 32;
988 if (regs.VertDispEnd & 512)
989 tmp |= 64;
990 if (regs.VertSyncStart & 512)
991 tmp |= 128;
992 DPRINTK("CRT7: %d\n", tmp);
993 vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp);
995 tmp = 0x40; /* LineCompare bit #8 */
996 if (regs.VertBlankStart & 512)
997 tmp |= 0x20;
998 if (var->vmode & FB_VMODE_DOUBLE)
999 tmp |= 0x80;
1000 DPRINTK("CRT9: %d\n", tmp);
1001 vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp);
1003 DPRINTK("CRT10: %ld\n", regs.VertSyncStart & 0xff);
1004 vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, regs.VertSyncStart & 0xff);
1006 DPRINTK("CRT11: 64+32+%ld\n", regs.VertSyncEnd % 16);
1007 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, regs.VertSyncEnd % 16 + 64 + 32);
1009 DPRINTK("CRT12: %ld\n", regs.VertDispEnd & 0xff);
1010 vga_wcrt(regbase, VGA_CRTC_V_DISP_END, regs.VertDispEnd & 0xff);
1012 DPRINTK("CRT15: %ld\n", regs.VertBlankStart & 0xff);
1013 vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, regs.VertBlankStart & 0xff);
1015 DPRINTK("CRT16: %ld\n", regs.VertBlankEnd & 0xff);
1016 vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, regs.VertBlankEnd & 0xff);
1018 DPRINTK("CRT18: 0xff\n");
1019 vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff);
1021 tmp = 0;
1022 if (var->vmode & FB_VMODE_INTERLACED)
1023 tmp |= 1;
1024 if (regs.HorizBlankEnd & 64)
1025 tmp |= 16;
1026 if (regs.HorizBlankEnd & 128)
1027 tmp |= 32;
1028 if (regs.VertBlankEnd & 256)
1029 tmp |= 64;
1030 if (regs.VertBlankEnd & 512)
1031 tmp |= 128;
1033 DPRINTK("CRT1a: %d\n", tmp);
1034 vga_wcrt(regbase, CL_CRT1A, tmp);
1036 /* set VCLK0 */
1037 /* hardware RefClock: 14.31818 MHz */
1038 /* formula: VClk = (OSC * N) / (D * (1+P)) */
1039 /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
1041 vga_wseq(regbase, CL_SEQRB, regs.nom);
1042 tmp = regs.den << 1;
1043 if (regs.div != 0)
1044 tmp |= 1;
1046 /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
1047 if ((cinfo->btype == BT_SD64) ||
1048 (cinfo->btype == BT_ALPINE) ||
1049 (cinfo->btype == BT_GD5480))
1050 tmp |= 0x80;
1052 DPRINTK("CL_SEQR1B: %ld\n", (long) tmp);
1053 vga_wseq(regbase, CL_SEQR1B, tmp);
1055 if (regs.VertRes >= 1024)
1056 /* 1280x1024 */
1057 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7);
1058 else
1059 /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
1060 * address wrap, no compat. */
1061 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3);
1063 /* HAEH? vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20);
1064 * previously: 0x00 unlock VGA_CRTC_H_TOTAL..CRT7 */
1066 /* don't know if it would hurt to also program this if no interlaced */
1067 /* mode is used, but I feel better this way.. :-) */
1068 if (var->vmode & FB_VMODE_INTERLACED)
1069 vga_wcrt(regbase, VGA_CRTC_REGS, regs.HorizTotal / 2);
1070 else
1071 vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
1073 vga_wseq(regbase, VGA_SEQ_CHARACTER_MAP, 0);
1075 /* adjust horizontal/vertical sync type (low/high) */
1076 /* enable display memory & CRTC I/O address for color mode */
1077 tmp = 0x03;
1078 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1079 tmp |= 0x40;
1080 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1081 tmp |= 0x80;
1082 WGen(cinfo, VGA_MIS_W, tmp);
1084 /* Screen A Preset Row-Scan register */
1085 vga_wcrt(regbase, VGA_CRTC_PRESET_ROW, 0);
1086 /* text cursor on and start line */
1087 vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0);
1088 /* text cursor end line */
1089 vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 31);
1091 /******************************************************
1093 * 1 bpp
1097 /* programming for different color depths */
1098 if (var->bits_per_pixel == 1) {
1099 DPRINTK("cirrusfb: preparing for 1 bit deep display\n");
1100 vga_wgfx(regbase, VGA_GFX_MODE, 0); /* mode register */
1102 /* SR07 */
1103 switch (cinfo->btype) {
1104 case BT_SD64:
1105 case BT_PICCOLO:
1106 case BT_PICASSO:
1107 case BT_SPECTRUM:
1108 case BT_PICASSO4:
1109 case BT_ALPINE:
1110 case BT_GD5480:
1111 DPRINTK(" (for GD54xx)\n");
1112 vga_wseq(regbase, CL_SEQR7,
1113 regs.multiplexing ?
1114 bi->sr07_1bpp_mux : bi->sr07_1bpp);
1115 break;
1117 case BT_LAGUNA:
1118 DPRINTK(" (for GD546x)\n");
1119 vga_wseq(regbase, CL_SEQR7,
1120 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1121 break;
1123 default:
1124 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1125 break;
1128 /* Extended Sequencer Mode */
1129 switch (cinfo->btype) {
1130 case BT_SD64:
1131 /* setting the SEQRF on SD64 is not necessary
1132 * (only during init)
1134 DPRINTK("(for SD64)\n");
1135 /* MCLK select */
1136 vga_wseq(regbase, CL_SEQR1F, 0x1a);
1137 break;
1139 case BT_PICCOLO:
1140 case BT_SPECTRUM:
1141 DPRINTK("(for Piccolo/Spectrum)\n");
1142 /* ### ueberall 0x22? */
1143 /* ##vorher 1c MCLK select */
1144 vga_wseq(regbase, CL_SEQR1F, 0x22);
1145 /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
1146 vga_wseq(regbase, CL_SEQRF, 0xb0);
1147 break;
1149 case BT_PICASSO:
1150 DPRINTK("(for Picasso)\n");
1151 /* ##vorher 22 MCLK select */
1152 vga_wseq(regbase, CL_SEQR1F, 0x22);
1153 /* ## vorher d0 avoid FIFO underruns..? */
1154 vga_wseq(regbase, CL_SEQRF, 0xd0);
1155 break;
1157 case BT_PICASSO4:
1158 case BT_ALPINE:
1159 case BT_GD5480:
1160 case BT_LAGUNA:
1161 DPRINTK(" (for GD54xx)\n");
1162 /* do nothing */
1163 break;
1165 default:
1166 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1167 break;
1170 /* pixel mask: pass-through for first plane */
1171 WGen(cinfo, VGA_PEL_MSK, 0x01);
1172 if (regs.multiplexing)
1173 /* hidden dac reg: 1280x1024 */
1174 WHDR(cinfo, 0x4a);
1175 else
1176 /* hidden dac: nothing */
1177 WHDR(cinfo, 0);
1178 /* memory mode: odd/even, ext. memory */
1179 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06);
1180 /* plane mask: only write to first plane */
1181 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01);
1182 offset = var->xres_virtual / 16;
1185 /******************************************************
1187 * 8 bpp
1191 else if (var->bits_per_pixel == 8) {
1192 DPRINTK("cirrusfb: preparing for 8 bit deep display\n");
1193 switch (cinfo->btype) {
1194 case BT_SD64:
1195 case BT_PICCOLO:
1196 case BT_PICASSO:
1197 case BT_SPECTRUM:
1198 case BT_PICASSO4:
1199 case BT_ALPINE:
1200 case BT_GD5480:
1201 DPRINTK(" (for GD54xx)\n");
1202 vga_wseq(regbase, CL_SEQR7,
1203 regs.multiplexing ?
1204 bi->sr07_8bpp_mux : bi->sr07_8bpp);
1205 break;
1207 case BT_LAGUNA:
1208 DPRINTK(" (for GD546x)\n");
1209 vga_wseq(regbase, CL_SEQR7,
1210 vga_rseq(regbase, CL_SEQR7) | 0x01);
1211 break;
1213 default:
1214 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1215 break;
1218 switch (cinfo->btype) {
1219 case BT_SD64:
1220 /* MCLK select */
1221 vga_wseq(regbase, CL_SEQR1F, 0x1d);
1222 break;
1224 case BT_PICCOLO:
1225 case BT_PICASSO:
1226 case BT_SPECTRUM:
1227 /* ### vorher 1c MCLK select */
1228 vga_wseq(regbase, CL_SEQR1F, 0x22);
1229 /* Fast Page-Mode writes */
1230 vga_wseq(regbase, CL_SEQRF, 0xb0);
1231 break;
1233 case BT_PICASSO4:
1234 #ifdef CONFIG_ZORRO
1235 /* ### INCOMPLETE!! */
1236 vga_wseq(regbase, CL_SEQRF, 0xb8);
1237 #endif
1238 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1239 break;
1241 case BT_ALPINE:
1242 DPRINTK(" (for GD543x)\n");
1243 cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
1244 /* We already set SRF and SR1F */
1245 break;
1247 case BT_GD5480:
1248 case BT_LAGUNA:
1249 DPRINTK(" (for GD54xx)\n");
1250 /* do nothing */
1251 break;
1253 default:
1254 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1255 break;
1258 /* mode register: 256 color mode */
1259 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1260 /* pixel mask: pass-through all planes */
1261 WGen(cinfo, VGA_PEL_MSK, 0xff);
1262 if (regs.multiplexing)
1263 /* hidden dac reg: 1280x1024 */
1264 WHDR(cinfo, 0x4a);
1265 else
1266 /* hidden dac: nothing */
1267 WHDR(cinfo, 0);
1268 /* memory mode: chain4, ext. memory */
1269 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1270 /* plane mask: enable writing to all 4 planes */
1271 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1272 offset = var->xres_virtual / 8;
1275 /******************************************************
1277 * 16 bpp
1281 else if (var->bits_per_pixel == 16) {
1282 DPRINTK("cirrusfb: preparing for 16 bit deep display\n");
1283 switch (cinfo->btype) {
1284 case BT_SD64:
1285 /* Extended Sequencer Mode: 256c col. mode */
1286 vga_wseq(regbase, CL_SEQR7, 0xf7);
1287 /* MCLK select */
1288 vga_wseq(regbase, CL_SEQR1F, 0x1e);
1289 break;
1291 case BT_PICCOLO:
1292 case BT_SPECTRUM:
1293 vga_wseq(regbase, CL_SEQR7, 0x87);
1294 /* Fast Page-Mode writes */
1295 vga_wseq(regbase, CL_SEQRF, 0xb0);
1296 /* MCLK select */
1297 vga_wseq(regbase, CL_SEQR1F, 0x22);
1298 break;
1300 case BT_PICASSO:
1301 vga_wseq(regbase, CL_SEQR7, 0x27);
1302 /* Fast Page-Mode writes */
1303 vga_wseq(regbase, CL_SEQRF, 0xb0);
1304 /* MCLK select */
1305 vga_wseq(regbase, CL_SEQR1F, 0x22);
1306 break;
1308 case BT_PICASSO4:
1309 vga_wseq(regbase, CL_SEQR7, 0x27);
1310 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1311 break;
1313 case BT_ALPINE:
1314 DPRINTK(" (for GD543x)\n");
1315 if (regs.HorizRes >= 1024)
1316 vga_wseq(regbase, CL_SEQR7, 0xa7);
1317 else
1318 vga_wseq(regbase, CL_SEQR7, 0xa3);
1319 cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
1320 break;
1322 case BT_GD5480:
1323 DPRINTK(" (for GD5480)\n");
1324 vga_wseq(regbase, CL_SEQR7, 0x17);
1325 /* We already set SRF and SR1F */
1326 break;
1328 case BT_LAGUNA:
1329 DPRINTK(" (for GD546x)\n");
1330 vga_wseq(regbase, CL_SEQR7,
1331 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1332 break;
1334 default:
1335 printk(KERN_WARNING "CIRRUSFB: unknown Board\n");
1336 break;
1339 /* mode register: 256 color mode */
1340 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1341 /* pixel mask: pass-through all planes */
1342 WGen(cinfo, VGA_PEL_MSK, 0xff);
1343 #ifdef CONFIG_PCI
1344 WHDR(cinfo, 0xc0); /* Copy Xbh */
1345 #elif defined(CONFIG_ZORRO)
1346 /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
1347 WHDR(cinfo, 0xa0); /* hidden dac reg: nothing special */
1348 #endif
1349 /* memory mode: chain4, ext. memory */
1350 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1351 /* plane mask: enable writing to all 4 planes */
1352 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1353 offset = var->xres_virtual / 4;
1356 /******************************************************
1358 * 32 bpp
1362 else if (var->bits_per_pixel == 32) {
1363 DPRINTK("cirrusfb: preparing for 24/32 bit deep display\n");
1364 switch (cinfo->btype) {
1365 case BT_SD64:
1366 /* Extended Sequencer Mode: 256c col. mode */
1367 vga_wseq(regbase, CL_SEQR7, 0xf9);
1368 /* MCLK select */
1369 vga_wseq(regbase, CL_SEQR1F, 0x1e);
1370 break;
1372 case BT_PICCOLO:
1373 case BT_SPECTRUM:
1374 vga_wseq(regbase, CL_SEQR7, 0x85);
1375 /* Fast Page-Mode writes */
1376 vga_wseq(regbase, CL_SEQRF, 0xb0);
1377 /* MCLK select */
1378 vga_wseq(regbase, CL_SEQR1F, 0x22);
1379 break;
1381 case BT_PICASSO:
1382 vga_wseq(regbase, CL_SEQR7, 0x25);
1383 /* Fast Page-Mode writes */
1384 vga_wseq(regbase, CL_SEQRF, 0xb0);
1385 /* MCLK select */
1386 vga_wseq(regbase, CL_SEQR1F, 0x22);
1387 break;
1389 case BT_PICASSO4:
1390 vga_wseq(regbase, CL_SEQR7, 0x25);
1391 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1392 break;
1394 case BT_ALPINE:
1395 DPRINTK(" (for GD543x)\n");
1396 vga_wseq(regbase, CL_SEQR7, 0xa9);
1397 cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
1398 break;
1400 case BT_GD5480:
1401 DPRINTK(" (for GD5480)\n");
1402 vga_wseq(regbase, CL_SEQR7, 0x19);
1403 /* We already set SRF and SR1F */
1404 break;
1406 case BT_LAGUNA:
1407 DPRINTK(" (for GD546x)\n");
1408 vga_wseq(regbase, CL_SEQR7,
1409 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1410 break;
1412 default:
1413 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1414 break;
1417 /* mode register: 256 color mode */
1418 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1419 /* pixel mask: pass-through all planes */
1420 WGen(cinfo, VGA_PEL_MSK, 0xff);
1421 /* hidden dac reg: 8-8-8 mode (24 or 32) */
1422 WHDR(cinfo, 0xc5);
1423 /* memory mode: chain4, ext. memory */
1424 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1425 /* plane mask: enable writing to all 4 planes */
1426 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1427 offset = var->xres_virtual / 4;
1430 /******************************************************
1432 * unknown/unsupported bpp
1436 else
1437 printk(KERN_ERR "cirrusfb: What's this?? "
1438 " requested color depth == %d.\n",
1439 var->bits_per_pixel);
1441 vga_wcrt(regbase, VGA_CRTC_OFFSET, offset & 0xff);
1442 tmp = 0x22;
1443 if (offset & 0x100)
1444 tmp |= 0x10; /* offset overflow bit */
1446 /* screen start addr #16-18, fastpagemode cycles */
1447 vga_wcrt(regbase, CL_CRT1B, tmp);
1449 if (cinfo->btype == BT_SD64 ||
1450 cinfo->btype == BT_PICASSO4 ||
1451 cinfo->btype == BT_ALPINE ||
1452 cinfo->btype == BT_GD5480)
1453 /* screen start address bit 19 */
1454 vga_wcrt(regbase, CL_CRT1D, 0x00);
1456 /* text cursor location high */
1457 vga_wcrt(regbase, VGA_CRTC_CURSOR_HI, 0);
1458 /* text cursor location low */
1459 vga_wcrt(regbase, VGA_CRTC_CURSOR_LO, 0);
1460 /* underline row scanline = at very bottom */
1461 vga_wcrt(regbase, VGA_CRTC_UNDERLINE, 0);
1463 /* controller mode */
1464 vga_wattr(regbase, VGA_ATC_MODE, 1);
1465 /* overscan (border) color */
1466 vga_wattr(regbase, VGA_ATC_OVERSCAN, 0);
1467 /* color plane enable */
1468 vga_wattr(regbase, VGA_ATC_PLANE_ENABLE, 15);
1469 /* pixel panning */
1470 vga_wattr(regbase, CL_AR33, 0);
1471 /* color select */
1472 vga_wattr(regbase, VGA_ATC_COLOR_PAGE, 0);
1474 /* [ EGS: SetOffset(); ] */
1475 /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
1476 AttrOn(cinfo);
1478 /* set/reset register */
1479 vga_wgfx(regbase, VGA_GFX_SR_VALUE, 0);
1480 /* set/reset enable */
1481 vga_wgfx(regbase, VGA_GFX_SR_ENABLE, 0);
1482 /* color compare */
1483 vga_wgfx(regbase, VGA_GFX_COMPARE_VALUE, 0);
1484 /* data rotate */
1485 vga_wgfx(regbase, VGA_GFX_DATA_ROTATE, 0);
1486 /* read map select */
1487 vga_wgfx(regbase, VGA_GFX_PLANE_READ, 0);
1488 /* miscellaneous register */
1489 vga_wgfx(regbase, VGA_GFX_MISC, 1);
1490 /* color don't care */
1491 vga_wgfx(regbase, VGA_GFX_COMPARE_MASK, 15);
1492 /* bit mask */
1493 vga_wgfx(regbase, VGA_GFX_BIT_MASK, 255);
1495 /* graphics cursor attributes: nothing special */
1496 vga_wseq(regbase, CL_SEQR12, 0x0);
1498 /* finally, turn on everything - turn off "FullBandwidth" bit */
1499 /* also, set "DotClock%2" bit where requested */
1500 tmp = 0x01;
1502 /*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
1503 if (var->vmode & FB_VMODE_CLOCK_HALVE)
1504 tmp |= 0x08;
1507 vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp);
1508 DPRINTK("CL_SEQR1: %d\n", tmp);
1510 cinfo->currentmode = regs;
1512 /* pan to requested offset */
1513 cirrusfb_pan_display(var, info);
1515 #ifdef CIRRUSFB_DEBUG
1516 cirrusfb_dump();
1517 #endif
1519 DPRINTK("EXIT\n");
1520 return 0;
1523 /* for some reason incomprehensible to me, cirrusfb requires that you write
1524 * the registers twice for the settings to take..grr. -dte */
1525 static int cirrusfb_set_par(struct fb_info *info)
1527 cirrusfb_set_par_foo(info);
1528 return cirrusfb_set_par_foo(info);
1531 static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1532 unsigned blue, unsigned transp,
1533 struct fb_info *info)
1535 struct cirrusfb_info *cinfo = info->par;
1537 if (regno > 255)
1538 return -EINVAL;
1540 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
1541 u32 v;
1542 red >>= (16 - info->var.red.length);
1543 green >>= (16 - info->var.green.length);
1544 blue >>= (16 - info->var.blue.length);
1546 if (regno >= 16)
1547 return 1;
1548 v = (red << info->var.red.offset) |
1549 (green << info->var.green.offset) |
1550 (blue << info->var.blue.offset);
1552 cinfo->pseudo_palette[regno] = v;
1553 return 0;
1556 if (info->var.bits_per_pixel == 8)
1557 WClut(cinfo, regno, red >> 10, green >> 10, blue >> 10);
1559 return 0;
1563 /*************************************************************************
1564 cirrusfb_pan_display()
1566 performs display panning - provided hardware permits this
1567 **************************************************************************/
1568 static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
1569 struct fb_info *info)
1571 int xoffset = 0;
1572 int yoffset = 0;
1573 unsigned long base;
1574 unsigned char tmp = 0, tmp2 = 0, xpix;
1575 struct cirrusfb_info *cinfo = info->par;
1577 DPRINTK("ENTER\n");
1578 DPRINTK("virtual offset: (%d,%d)\n", var->xoffset, var->yoffset);
1580 /* no range checks for xoffset and yoffset, */
1581 /* as fb_pan_display has already done this */
1582 if (var->vmode & FB_VMODE_YWRAP)
1583 return -EINVAL;
1585 info->var.xoffset = var->xoffset;
1586 info->var.yoffset = var->yoffset;
1588 xoffset = var->xoffset * info->var.bits_per_pixel / 8;
1589 yoffset = var->yoffset;
1591 base = yoffset * info->fix.line_length + xoffset;
1593 if (info->var.bits_per_pixel == 1) {
1594 /* base is already correct */
1595 xpix = (unsigned char) (var->xoffset % 8);
1596 } else {
1597 base /= 4;
1598 xpix = (unsigned char) ((xoffset % 4) * 2);
1601 cirrusfb_WaitBLT(cinfo->regbase); /* make sure all the BLT's are done */
1603 /* lower 8 + 8 bits of screen start address */
1604 vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO,
1605 (unsigned char) (base & 0xff));
1606 vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI,
1607 (unsigned char) (base >> 8));
1609 /* construct bits 16, 17 and 18 of screen start address */
1610 if (base & 0x10000)
1611 tmp |= 0x01;
1612 if (base & 0x20000)
1613 tmp |= 0x04;
1614 if (base & 0x40000)
1615 tmp |= 0x08;
1617 /* 0xf2 is %11110010, exclude tmp bits */
1618 tmp2 = (vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2) | tmp;
1619 vga_wcrt(cinfo->regbase, CL_CRT1B, tmp2);
1621 /* construct bit 19 of screen start address */
1622 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19)
1623 vga_wcrt(cinfo->regbase, CL_CRT1D, (base >> 12) & 0x80);
1625 /* write pixel panning value to AR33; this does not quite work in 8bpp
1627 * ### Piccolo..? Will this work?
1629 if (info->var.bits_per_pixel == 1)
1630 vga_wattr(cinfo->regbase, CL_AR33, xpix);
1632 cirrusfb_WaitBLT(cinfo->regbase);
1634 DPRINTK("EXIT\n");
1635 return 0;
1638 static int cirrusfb_blank(int blank_mode, struct fb_info *info)
1641 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
1642 * then the caller blanks by setting the CLUT (Color Look Up Table)
1643 * to all black. Return 0 if blanking succeeded, != 0 if un-/blanking
1644 * failed due to e.g. a video mode which doesn't support it.
1645 * Implements VESA suspend and powerdown modes on hardware that
1646 * supports disabling hsync/vsync:
1647 * blank_mode == 2: suspend vsync
1648 * blank_mode == 3: suspend hsync
1649 * blank_mode == 4: powerdown
1651 unsigned char val;
1652 struct cirrusfb_info *cinfo = info->par;
1653 int current_mode = cinfo->blank_mode;
1655 DPRINTK("ENTER, blank mode = %d\n", blank_mode);
1657 if (info->state != FBINFO_STATE_RUNNING ||
1658 current_mode == blank_mode) {
1659 DPRINTK("EXIT, returning 0\n");
1660 return 0;
1663 /* Undo current */
1664 if (current_mode == FB_BLANK_NORMAL ||
1665 current_mode == FB_BLANK_UNBLANK) {
1666 /* unblank the screen */
1667 val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1668 /* clear "FullBandwidth" bit */
1669 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val & 0xdf);
1670 /* and undo VESA suspend trickery */
1671 vga_wgfx(cinfo->regbase, CL_GRE, 0x00);
1674 /* set new */
1675 if (blank_mode > FB_BLANK_NORMAL) {
1676 /* blank the screen */
1677 val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1678 /* set "FullBandwidth" bit */
1679 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val | 0x20);
1682 switch (blank_mode) {
1683 case FB_BLANK_UNBLANK:
1684 case FB_BLANK_NORMAL:
1685 break;
1686 case FB_BLANK_VSYNC_SUSPEND:
1687 vga_wgfx(cinfo->regbase, CL_GRE, 0x04);
1688 break;
1689 case FB_BLANK_HSYNC_SUSPEND:
1690 vga_wgfx(cinfo->regbase, CL_GRE, 0x02);
1691 break;
1692 case FB_BLANK_POWERDOWN:
1693 vga_wgfx(cinfo->regbase, CL_GRE, 0x06);
1694 break;
1695 default:
1696 DPRINTK("EXIT, returning 1\n");
1697 return 1;
1700 cinfo->blank_mode = blank_mode;
1701 DPRINTK("EXIT, returning 0\n");
1703 /* Let fbcon do a soft blank for us */
1704 return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
1706 /**** END Hardware specific Routines **************************************/
1707 /****************************************************************************/
1708 /**** BEGIN Internal Routines ***********************************************/
1710 static void init_vgachip(struct fb_info *info)
1712 struct cirrusfb_info *cinfo = info->par;
1713 const struct cirrusfb_board_info_rec *bi;
1715 DPRINTK("ENTER\n");
1717 assert(cinfo != NULL);
1719 bi = &cirrusfb_board_info[cinfo->btype];
1721 /* reset board globally */
1722 switch (cinfo->btype) {
1723 case BT_PICCOLO:
1724 WSFR(cinfo, 0x01);
1725 udelay(500);
1726 WSFR(cinfo, 0x51);
1727 udelay(500);
1728 break;
1729 case BT_PICASSO:
1730 WSFR2(cinfo, 0xff);
1731 udelay(500);
1732 break;
1733 case BT_SD64:
1734 case BT_SPECTRUM:
1735 WSFR(cinfo, 0x1f);
1736 udelay(500);
1737 WSFR(cinfo, 0x4f);
1738 udelay(500);
1739 break;
1740 case BT_PICASSO4:
1741 /* disable flickerfixer */
1742 vga_wcrt(cinfo->regbase, CL_CRT51, 0x00);
1743 mdelay(100);
1744 /* from Klaus' NetBSD driver: */
1745 vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
1746 /* put blitter into 542x compat */
1747 vga_wgfx(cinfo->regbase, CL_GR33, 0x00);
1748 /* mode */
1749 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1750 break;
1752 case BT_GD5480:
1753 /* from Klaus' NetBSD driver: */
1754 vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
1755 break;
1757 case BT_ALPINE:
1758 /* Nothing to do to reset the board. */
1759 break;
1761 default:
1762 printk(KERN_ERR "cirrusfb: Warning: Unknown board type\n");
1763 break;
1766 /* make sure RAM size set by this point */
1767 assert(info->screen_size > 0);
1769 /* the P4 is not fully initialized here; I rely on it having been */
1770 /* inited under AmigaOS already, which seems to work just fine */
1771 /* (Klaus advised to do it this way) */
1773 if (cinfo->btype != BT_PICASSO4) {
1774 WGen(cinfo, CL_VSSM, 0x10); /* EGS: 0x16 */
1775 WGen(cinfo, CL_POS102, 0x01);
1776 WGen(cinfo, CL_VSSM, 0x08); /* EGS: 0x0e */
1778 if (cinfo->btype != BT_SD64)
1779 WGen(cinfo, CL_VSSM2, 0x01);
1781 /* reset sequencer logic */
1782 vga_wseq(cinfo->regbase, CL_SEQR0, 0x03);
1784 /* FullBandwidth (video off) and 8/9 dot clock */
1785 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21);
1786 /* polarity (-/-), disable access to display memory,
1787 * VGA_CRTC_START_HI base address: color
1789 WGen(cinfo, VGA_MIS_W, 0xc1);
1791 /* "magic cookie" - doesn't make any sense to me.. */
1792 /* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */
1793 /* unlock all extension registers */
1794 vga_wseq(cinfo->regbase, CL_SEQR6, 0x12);
1796 /* reset blitter */
1797 vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
1799 switch (cinfo->btype) {
1800 case BT_GD5480:
1801 vga_wseq(cinfo->regbase, CL_SEQRF, 0x98);
1802 break;
1803 case BT_ALPINE:
1804 break;
1805 case BT_SD64:
1806 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8);
1807 break;
1808 default:
1809 vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f);
1810 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb0);
1811 break;
1814 /* plane mask: nothing */
1815 vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1816 /* character map select: doesn't even matter in gx mode */
1817 vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00);
1818 /* memory mode: chain-4, no odd/even, ext. memory */
1819 vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0e);
1821 /* controller-internal base address of video memory */
1822 if (bi->init_sr07)
1823 vga_wseq(cinfo->regbase, CL_SEQR7, bi->sr07);
1825 /* vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */
1826 /* EEPROM control: shouldn't be necessary to write to this at all.. */
1828 /* graphics cursor X position (incomplete; position gives rem. 3 bits */
1829 vga_wseq(cinfo->regbase, CL_SEQR10, 0x00);
1830 /* graphics cursor Y position (..."... ) */
1831 vga_wseq(cinfo->regbase, CL_SEQR11, 0x00);
1832 /* graphics cursor attributes */
1833 vga_wseq(cinfo->regbase, CL_SEQR12, 0x00);
1834 /* graphics cursor pattern address */
1835 vga_wseq(cinfo->regbase, CL_SEQR13, 0x00);
1837 /* writing these on a P4 might give problems.. */
1838 if (cinfo->btype != BT_PICASSO4) {
1839 /* configuration readback and ext. color */
1840 vga_wseq(cinfo->regbase, CL_SEQR17, 0x00);
1841 /* signature generator */
1842 vga_wseq(cinfo->regbase, CL_SEQR18, 0x02);
1845 /* MCLK select etc. */
1846 if (bi->init_sr1f)
1847 vga_wseq(cinfo->regbase, CL_SEQR1F, bi->sr1f);
1849 /* Screen A preset row scan: none */
1850 vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00);
1851 /* Text cursor start: disable text cursor */
1852 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20);
1853 /* Text cursor end: - */
1854 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00);
1855 /* Screen start address high: 0 */
1856 vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, 0x00);
1857 /* Screen start address low: 0 */
1858 vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, 0x00);
1859 /* text cursor location high: 0 */
1860 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00);
1861 /* text cursor location low: 0 */
1862 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00);
1864 /* Underline Row scanline: - */
1865 vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00);
1866 /* mode control: timing enable, byte mode, no compat modes */
1867 vga_wcrt(cinfo->regbase, VGA_CRTC_MODE, 0xc3);
1868 /* Line Compare: not needed */
1869 vga_wcrt(cinfo->regbase, VGA_CRTC_LINE_COMPARE, 0x00);
1870 /* ### add 0x40 for text modes with > 30 MHz pixclock */
1871 /* ext. display controls: ext.adr. wrap */
1872 vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02);
1874 /* Set/Reset registes: - */
1875 vga_wgfx(cinfo->regbase, VGA_GFX_SR_VALUE, 0x00);
1876 /* Set/Reset enable: - */
1877 vga_wgfx(cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00);
1878 /* Color Compare: - */
1879 vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00);
1880 /* Data Rotate: - */
1881 vga_wgfx(cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00);
1882 /* Read Map Select: - */
1883 vga_wgfx(cinfo->regbase, VGA_GFX_PLANE_READ, 0x00);
1884 /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
1885 vga_wgfx(cinfo->regbase, VGA_GFX_MODE, 0x00);
1886 /* Miscellaneous: memory map base address, graphics mode */
1887 vga_wgfx(cinfo->regbase, VGA_GFX_MISC, 0x01);
1888 /* Color Don't care: involve all planes */
1889 vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f);
1890 /* Bit Mask: no mask at all */
1891 vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff);
1892 if (cinfo->btype == BT_ALPINE)
1893 /* (5434 can't have bit 3 set for bitblt) */
1894 vga_wgfx(cinfo->regbase, CL_GRB, 0x20);
1895 else
1896 /* Graphics controller mode extensions: finer granularity,
1897 * 8byte data latches
1899 vga_wgfx(cinfo->regbase, CL_GRB, 0x28);
1901 vga_wgfx(cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */
1902 vga_wgfx(cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */
1903 vga_wgfx(cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */
1904 /* Background color byte 1: - */
1905 /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); */
1906 /* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
1908 /* Attribute Controller palette registers: "identity mapping" */
1909 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE0, 0x00);
1910 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
1911 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
1912 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
1913 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
1914 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
1915 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
1916 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
1917 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
1918 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
1919 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
1920 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
1921 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
1922 vga_wattr(cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
1923 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
1924 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
1926 /* Attribute Controller mode: graphics mode */
1927 vga_wattr(cinfo->regbase, VGA_ATC_MODE, 0x01);
1928 /* Overscan color reg.: reg. 0 */
1929 vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00);
1930 /* Color Plane enable: Enable all 4 planes */
1931 vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f);
1932 /* ### vga_wattr(cinfo->regbase, CL_AR33, 0x00); * Pixel Panning: - */
1933 /* Color Select: - */
1934 vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00);
1936 WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
1938 if (cinfo->btype != BT_ALPINE && cinfo->btype != BT_GD5480)
1939 /* polarity (-/-), enable display mem,
1940 * VGA_CRTC_START_HI i/o base = color
1942 WGen(cinfo, VGA_MIS_W, 0xc3);
1944 /* BLT Start/status: Blitter reset */
1945 vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
1946 /* - " - : "end-of-reset" */
1947 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1949 /* misc... */
1950 WHDR(cinfo, 0); /* Hidden DAC register: - */
1952 printk(KERN_DEBUG "cirrusfb: This board has %ld bytes of DRAM memory\n",
1953 info->screen_size);
1954 DPRINTK("EXIT\n");
1955 return;
1958 static void switch_monitor(struct cirrusfb_info *cinfo, int on)
1960 #ifdef CONFIG_ZORRO /* only works on Zorro boards */
1961 static int IsOn = 0; /* XXX not ok for multiple boards */
1963 DPRINTK("ENTER\n");
1965 if (cinfo->btype == BT_PICASSO4)
1966 return; /* nothing to switch */
1967 if (cinfo->btype == BT_ALPINE)
1968 return; /* nothing to switch */
1969 if (cinfo->btype == BT_GD5480)
1970 return; /* nothing to switch */
1971 if (cinfo->btype == BT_PICASSO) {
1972 if ((on && !IsOn) || (!on && IsOn))
1973 WSFR(cinfo, 0xff);
1975 DPRINTK("EXIT\n");
1976 return;
1978 if (on) {
1979 switch (cinfo->btype) {
1980 case BT_SD64:
1981 WSFR(cinfo, cinfo->SFR | 0x21);
1982 break;
1983 case BT_PICCOLO:
1984 WSFR(cinfo, cinfo->SFR | 0x28);
1985 break;
1986 case BT_SPECTRUM:
1987 WSFR(cinfo, 0x6f);
1988 break;
1989 default: /* do nothing */ break;
1991 } else {
1992 switch (cinfo->btype) {
1993 case BT_SD64:
1994 WSFR(cinfo, cinfo->SFR & 0xde);
1995 break;
1996 case BT_PICCOLO:
1997 WSFR(cinfo, cinfo->SFR & 0xd7);
1998 break;
1999 case BT_SPECTRUM:
2000 WSFR(cinfo, 0x4f);
2001 break;
2002 default: /* do nothing */ break;
2006 DPRINTK("EXIT\n");
2007 #endif /* CONFIG_ZORRO */
2010 /******************************************/
2011 /* Linux 2.6-style accelerated functions */
2012 /******************************************/
2014 static void cirrusfb_fillrect(struct fb_info *info,
2015 const struct fb_fillrect *region)
2017 struct fb_fillrect modded;
2018 int vxres, vyres;
2019 struct cirrusfb_info *cinfo = info->par;
2020 int m = info->var.bits_per_pixel;
2021 u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
2022 cinfo->pseudo_palette[region->color] : region->color;
2024 if (info->state != FBINFO_STATE_RUNNING)
2025 return;
2026 if (info->flags & FBINFO_HWACCEL_DISABLED) {
2027 cfb_fillrect(info, region);
2028 return;
2031 vxres = info->var.xres_virtual;
2032 vyres = info->var.yres_virtual;
2034 memcpy(&modded, region, sizeof(struct fb_fillrect));
2036 if (!modded.width || !modded.height ||
2037 modded.dx >= vxres || modded.dy >= vyres)
2038 return;
2040 if (modded.dx + modded.width > vxres)
2041 modded.width = vxres - modded.dx;
2042 if (modded.dy + modded.height > vyres)
2043 modded.height = vyres - modded.dy;
2045 cirrusfb_RectFill(cinfo->regbase,
2046 info->var.bits_per_pixel,
2047 (region->dx * m) / 8, region->dy,
2048 (region->width * m) / 8, region->height,
2049 color,
2050 info->fix.line_length);
2053 static void cirrusfb_copyarea(struct fb_info *info,
2054 const struct fb_copyarea *area)
2056 struct fb_copyarea modded;
2057 u32 vxres, vyres;
2058 struct cirrusfb_info *cinfo = info->par;
2059 int m = info->var.bits_per_pixel;
2061 if (info->state != FBINFO_STATE_RUNNING)
2062 return;
2063 if (info->flags & FBINFO_HWACCEL_DISABLED) {
2064 cfb_copyarea(info, area);
2065 return;
2068 vxres = info->var.xres_virtual;
2069 vyres = info->var.yres_virtual;
2070 memcpy(&modded, area, sizeof(struct fb_copyarea));
2072 if (!modded.width || !modded.height ||
2073 modded.sx >= vxres || modded.sy >= vyres ||
2074 modded.dx >= vxres || modded.dy >= vyres)
2075 return;
2077 if (modded.sx + modded.width > vxres)
2078 modded.width = vxres - modded.sx;
2079 if (modded.dx + modded.width > vxres)
2080 modded.width = vxres - modded.dx;
2081 if (modded.sy + modded.height > vyres)
2082 modded.height = vyres - modded.sy;
2083 if (modded.dy + modded.height > vyres)
2084 modded.height = vyres - modded.dy;
2086 cirrusfb_BitBLT(cinfo->regbase, info->var.bits_per_pixel,
2087 (area->sx * m) / 8, area->sy,
2088 (area->dx * m) / 8, area->dy,
2089 (area->width * m) / 8, area->height,
2090 info->fix.line_length);
2094 static void cirrusfb_imageblit(struct fb_info *info,
2095 const struct fb_image *image)
2097 struct cirrusfb_info *cinfo = info->par;
2099 cirrusfb_WaitBLT(cinfo->regbase);
2100 cfb_imageblit(info, image);
2103 #ifdef CONFIG_PPC_PREP
2104 #define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
2105 #define PREP_IO_BASE ((volatile unsigned char *) 0x80000000)
2106 static void get_prep_addrs(unsigned long *display, unsigned long *registers)
2108 DPRINTK("ENTER\n");
2110 *display = PREP_VIDEO_BASE;
2111 *registers = (unsigned long) PREP_IO_BASE;
2113 DPRINTK("EXIT\n");
2116 #endif /* CONFIG_PPC_PREP */
2118 #ifdef CONFIG_PCI
2119 static int release_io_ports;
2121 /* Pulled the logic from XFree86 Cirrus driver to get the memory size,
2122 * based on the DRAM bandwidth bit and DRAM bank switching bit. This
2123 * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
2124 * seem to have. */
2125 static unsigned int cirrusfb_get_memsize(u8 __iomem *regbase)
2127 unsigned long mem;
2128 unsigned char SRF;
2130 DPRINTK("ENTER\n");
2132 SRF = vga_rseq(regbase, CL_SEQRF);
2133 switch ((SRF & 0x18)) {
2134 case 0x08:
2135 mem = 512 * 1024;
2136 break;
2137 case 0x10:
2138 mem = 1024 * 1024;
2139 break;
2140 /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory
2141 * on the 5430.
2143 case 0x18:
2144 mem = 2048 * 1024;
2145 break;
2146 default:
2147 printk(KERN_WARNING "CLgenfb: Unknown memory size!\n");
2148 mem = 1024 * 1024;
2150 if (SRF & 0x80)
2151 /* If DRAM bank switching is enabled, there must be twice as much
2152 * memory installed. (4MB on the 5434)
2154 mem *= 2;
2156 /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
2158 DPRINTK("EXIT\n");
2159 return mem;
2162 static void get_pci_addrs(const struct pci_dev *pdev,
2163 unsigned long *display, unsigned long *registers)
2165 assert(pdev != NULL);
2166 assert(display != NULL);
2167 assert(registers != NULL);
2169 DPRINTK("ENTER\n");
2171 *display = 0;
2172 *registers = 0;
2174 /* This is a best-guess for now */
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);
2184 assert(*display != 0);
2186 DPRINTK("EXIT\n");
2189 static void cirrusfb_pci_unmap(struct fb_info *info)
2191 struct cirrusfb_info *cinfo = info->par;
2192 struct pci_dev *pdev = cinfo->pdev;
2194 iounmap(info->screen_base);
2195 #if 0 /* if system didn't claim this region, we would... */
2196 release_mem_region(0xA0000, 65535);
2197 #endif
2198 if (release_io_ports)
2199 release_region(0x3C0, 32);
2200 pci_release_regions(pdev);
2202 #endif /* CONFIG_PCI */
2204 #ifdef CONFIG_ZORRO
2205 static void __devexit cirrusfb_zorro_unmap(struct fb_info *info)
2207 struct cirrusfb_info *cinfo = info->par;
2208 zorro_release_device(cinfo->zdev);
2210 if (cinfo->btype == BT_PICASSO4) {
2211 cinfo->regbase -= 0x600000;
2212 iounmap((void *)cinfo->regbase);
2213 iounmap(info->screen_base);
2214 } else {
2215 if (zorro_resource_start(cinfo->zdev) > 0x01000000)
2216 iounmap(info->screen_base);
2219 #endif /* CONFIG_ZORRO */
2221 static int cirrusfb_set_fbinfo(struct fb_info *info)
2223 struct cirrusfb_info *cinfo = info->par;
2224 struct fb_var_screeninfo *var = &info->var;
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 if (cinfo->btype == BT_GD5480) {
2236 if (var->bits_per_pixel == 16)
2237 info->screen_base += 1 * MB_;
2238 if (var->bits_per_pixel == 24 || var->bits_per_pixel == 32)
2239 info->screen_base += 2 * MB_;
2242 /* Fill fix common fields */
2243 strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
2244 sizeof(info->fix.id));
2246 /* monochrome: only 1 memory plane */
2247 /* 8 bit and above: Use whole memory area */
2248 info->fix.smem_len = info->screen_size;
2249 if (var->bits_per_pixel == 1)
2250 info->fix.smem_len /= 4;
2251 info->fix.type_aux = 0;
2252 info->fix.xpanstep = 1;
2253 info->fix.ypanstep = 1;
2254 info->fix.ywrapstep = 0;
2256 /* FIXME: map region at 0xB8000 if available, fill in here */
2257 info->fix.mmio_len = 0;
2258 info->fix.accel = FB_ACCEL_NONE;
2260 fb_alloc_cmap(&info->cmap, 256, 0);
2262 return 0;
2265 static int cirrusfb_register(struct fb_info *info)
2267 struct cirrusfb_info *cinfo = info->par;
2268 int err;
2269 enum cirrus_board btype;
2271 DPRINTK("ENTER\n");
2273 printk(KERN_INFO "cirrusfb: Driver for Cirrus Logic based "
2274 "graphic boards, v" CIRRUSFB_VERSION "\n");
2276 btype = cinfo->btype;
2278 /* sanity checks */
2279 assert(btype != BT_NONE);
2281 DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base);
2283 /* Make pretend we've set the var so our structures are in a "good" */
2284 /* state, even though we haven't written the mode to the hw yet... */
2285 info->var = cirrusfb_predefined[cirrusfb_def_mode].var;
2286 info->var.activate = FB_ACTIVATE_NOW;
2288 err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
2289 if (err < 0) {
2290 /* should never happen */
2291 DPRINTK("choking on default var... umm, no good.\n");
2292 goto err_unmap_cirrusfb;
2295 /* set all the vital stuff */
2296 cirrusfb_set_fbinfo(info);
2298 err = register_framebuffer(info);
2299 if (err < 0) {
2300 printk(KERN_ERR "cirrusfb: could not register "
2301 "fb device; err = %d!\n", err);
2302 goto err_dealloc_cmap;
2305 DPRINTK("EXIT, returning 0\n");
2306 return 0;
2308 err_dealloc_cmap:
2309 fb_dealloc_cmap(&info->cmap);
2310 err_unmap_cirrusfb:
2311 cinfo->unmap(info);
2312 framebuffer_release(info);
2313 return err;
2316 static void __devexit cirrusfb_cleanup(struct fb_info *info)
2318 struct cirrusfb_info *cinfo = info->par;
2319 DPRINTK("ENTER\n");
2321 switch_monitor(cinfo, 0);
2323 unregister_framebuffer(info);
2324 fb_dealloc_cmap(&info->cmap);
2325 printk("Framebuffer unregistered\n");
2326 cinfo->unmap(info);
2327 framebuffer_release(info);
2329 DPRINTK("EXIT\n");
2332 #ifdef CONFIG_PCI
2333 static int cirrusfb_pci_register(struct pci_dev *pdev,
2334 const struct pci_device_id *ent)
2336 struct cirrusfb_info *cinfo;
2337 struct fb_info *info;
2338 enum cirrus_board btype;
2339 unsigned long board_addr, board_size;
2340 int ret;
2342 ret = pci_enable_device(pdev);
2343 if (ret < 0) {
2344 printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
2345 goto err_out;
2348 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev);
2349 if (!info) {
2350 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2351 ret = -ENOMEM;
2352 goto err_disable;
2355 cinfo = info->par;
2356 cinfo->pdev = pdev;
2357 cinfo->btype = btype = (enum cirrus_board) ent->driver_data;
2359 DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n",
2360 pdev->resource[0].start, btype);
2361 DPRINTK(" base address 1 is 0x%x\n", pdev->resource[1].start);
2363 if (isPReP) {
2364 pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, 0x00000000);
2365 #ifdef CONFIG_PPC_PREP
2366 get_prep_addrs(&board_addr, &info->fix.mmio_start);
2367 #endif
2368 /* PReP dies if we ioremap the IO registers, but it works w/out... */
2369 cinfo->regbase = (char __iomem *) info->fix.mmio_start;
2370 } else {
2371 DPRINTK("Attempt to get PCI info for Cirrus Graphics Card\n");
2372 get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start);
2373 /* FIXME: this forces VGA. alternatives? */
2374 cinfo->regbase = NULL;
2377 DPRINTK("Board address: 0x%lx, register address: 0x%lx\n",
2378 board_addr, info->fix.mmio_start);
2380 board_size = (btype == BT_GD5480) ?
2381 32 * MB_ : cirrusfb_get_memsize(cinfo->regbase);
2383 ret = pci_request_regions(pdev, "cirrusfb");
2384 if (ret < 0) {
2385 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, "
2386 "abort\n",
2387 board_addr);
2388 goto err_release_fb;
2390 #if 0 /* if the system didn't claim this region, we would... */
2391 if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
2392 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n"
2394 0xA0000L);
2395 ret = -EBUSY;
2396 goto err_release_regions;
2398 #endif
2399 if (request_region(0x3C0, 32, "cirrusfb"))
2400 release_io_ports = 1;
2402 info->screen_base = ioremap(board_addr, board_size);
2403 if (!info->screen_base) {
2404 ret = -EIO;
2405 goto err_release_legacy;
2408 info->fix.smem_start = board_addr;
2409 info->screen_size = board_size;
2410 cinfo->unmap = cirrusfb_pci_unmap;
2412 printk(KERN_INFO "RAM (%lu kB) at 0x%lx, Cirrus "
2413 "Logic chipset on PCI bus\n",
2414 info->screen_size >> 10, board_addr);
2415 pci_set_drvdata(pdev, info);
2417 ret = cirrusfb_register(info);
2418 if (ret)
2419 iounmap(info->screen_base);
2420 return ret;
2422 err_release_legacy:
2423 if (release_io_ports)
2424 release_region(0x3C0, 32);
2425 #if 0
2426 release_mem_region(0xA0000, 65535);
2427 err_release_regions:
2428 #endif
2429 pci_release_regions(pdev);
2430 err_release_fb:
2431 framebuffer_release(info);
2432 err_disable:
2433 err_out:
2434 return ret;
2437 static void __devexit cirrusfb_pci_unregister(struct pci_dev *pdev)
2439 struct fb_info *info = pci_get_drvdata(pdev);
2440 DPRINTK("ENTER\n");
2442 cirrusfb_cleanup(info);
2444 DPRINTK("EXIT\n");
2447 static struct pci_driver cirrusfb_pci_driver = {
2448 .name = "cirrusfb",
2449 .id_table = cirrusfb_pci_table,
2450 .probe = cirrusfb_pci_register,
2451 .remove = __devexit_p(cirrusfb_pci_unregister),
2452 #ifdef CONFIG_PM
2453 #if 0
2454 .suspend = cirrusfb_pci_suspend,
2455 .resume = cirrusfb_pci_resume,
2456 #endif
2457 #endif
2459 #endif /* CONFIG_PCI */
2461 #ifdef CONFIG_ZORRO
2462 static int cirrusfb_zorro_register(struct zorro_dev *z,
2463 const struct zorro_device_id *ent)
2465 struct cirrusfb_info *cinfo;
2466 struct fb_info *info;
2467 enum cirrus_board btype;
2468 struct zorro_dev *z2 = NULL;
2469 unsigned long board_addr, board_size, size;
2470 int ret;
2472 btype = ent->driver_data;
2473 if (cirrusfb_zorro_table2[btype].id2)
2474 z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
2475 size = cirrusfb_zorro_table2[btype].size;
2476 printk(KERN_INFO "cirrusfb: %s board detected; ",
2477 cirrusfb_board_info[btype].name);
2479 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
2480 if (!info) {
2481 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2482 ret = -ENOMEM;
2483 goto err_out;
2486 cinfo = info->par;
2487 cinfo->btype = btype;
2489 assert(z);
2490 assert(btype != BT_NONE);
2492 cinfo->zdev = z;
2493 board_addr = zorro_resource_start(z);
2494 board_size = zorro_resource_len(z);
2495 info->screen_size = size;
2497 if (!zorro_request_device(z, "cirrusfb")) {
2498 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, "
2499 "abort\n",
2500 board_addr);
2501 ret = -EBUSY;
2502 goto err_release_fb;
2505 printk(" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr);
2507 ret = -EIO;
2509 if (btype == BT_PICASSO4) {
2510 printk(KERN_INFO " REG at $%lx\n", board_addr + 0x600000);
2512 /* To be precise, for the P4 this is not the */
2513 /* begin of the board, but the begin of RAM. */
2514 /* for P4, map in its address space in 2 chunks (### TEST! ) */
2515 /* (note the ugly hardcoded 16M number) */
2516 cinfo->regbase = ioremap(board_addr, 16777216);
2517 if (!cinfo->regbase)
2518 goto err_release_region;
2520 DPRINTK("cirrusfb: Virtual address for board set to: $%p\n",
2521 cinfo->regbase);
2522 cinfo->regbase += 0x600000;
2523 info->fix.mmio_start = board_addr + 0x600000;
2525 info->fix.smem_start = board_addr + 16777216;
2526 info->screen_base = ioremap(info->fix.smem_start, 16777216);
2527 if (!info->screen_base)
2528 goto err_unmap_regbase;
2529 } else {
2530 printk(KERN_INFO " REG at $%lx\n",
2531 (unsigned long) z2->resource.start);
2533 info->fix.smem_start = board_addr;
2534 if (board_addr > 0x01000000)
2535 info->screen_base = ioremap(board_addr, board_size);
2536 else
2537 info->screen_base = (caddr_t) ZTWO_VADDR(board_addr);
2538 if (!info->screen_base)
2539 goto err_release_region;
2541 /* set address for REG area of board */
2542 cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start);
2543 info->fix.mmio_start = z2->resource.start;
2545 DPRINTK("cirrusfb: Virtual address for board set to: $%p\n",
2546 cinfo->regbase);
2548 cinfo->unmap = cirrusfb_zorro_unmap;
2550 printk(KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
2551 zorro_set_drvdata(z, info);
2553 ret = cirrusfb_register(info);
2554 if (ret) {
2555 if (btype == BT_PICASSO4) {
2556 iounmap(info->screen_base);
2557 iounmap(cinfo->regbase - 0x600000);
2558 } else if (board_addr > 0x01000000)
2559 iounmap(info->screen_base);
2561 return ret;
2563 err_unmap_regbase:
2564 /* Parental advisory: explicit hack */
2565 iounmap(cinfo->regbase - 0x600000);
2566 err_release_region:
2567 release_region(board_addr, board_size);
2568 err_release_fb:
2569 framebuffer_release(info);
2570 err_out:
2571 return ret;
2574 void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
2576 struct fb_info *info = zorro_get_drvdata(z);
2577 DPRINTK("ENTER\n");
2579 cirrusfb_cleanup(info);
2581 DPRINTK("EXIT\n");
2584 static struct zorro_driver cirrusfb_zorro_driver = {
2585 .name = "cirrusfb",
2586 .id_table = cirrusfb_zorro_table,
2587 .probe = cirrusfb_zorro_register,
2588 .remove = __devexit_p(cirrusfb_zorro_unregister),
2590 #endif /* CONFIG_ZORRO */
2592 static int __init cirrusfb_init(void)
2594 int error = 0;
2596 #ifndef MODULE
2597 char *option = NULL;
2599 if (fb_get_options("cirrusfb", &option))
2600 return -ENODEV;
2601 cirrusfb_setup(option);
2602 #endif
2604 #ifdef CONFIG_ZORRO
2605 error |= zorro_register_driver(&cirrusfb_zorro_driver);
2606 #endif
2607 #ifdef CONFIG_PCI
2608 error |= pci_register_driver(&cirrusfb_pci_driver);
2609 #endif
2610 return error;
2613 #ifndef MODULE
2614 static int __init cirrusfb_setup(char *options) {
2615 char *this_opt, s[32];
2616 int i;
2618 DPRINTK("ENTER\n");
2620 if (!options || !*options)
2621 return 0;
2623 while ((this_opt = strsep(&options, ",")) != NULL) {
2624 if (!*this_opt) continue;
2626 DPRINTK("cirrusfb_setup: option '%s'\n", this_opt);
2628 for (i = 0; i < NUM_TOTAL_MODES; i++) {
2629 sprintf(s, "mode:%s", cirrusfb_predefined[i].name);
2630 if (strcmp(this_opt, s) == 0)
2631 cirrusfb_def_mode = i;
2633 if (!strcmp(this_opt, "noaccel"))
2634 noaccel = 1;
2636 return 0;
2638 #endif
2641 * Modularization
2644 MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
2645 MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
2646 MODULE_LICENSE("GPL");
2648 static void __exit cirrusfb_exit(void)
2650 #ifdef CONFIG_PCI
2651 pci_unregister_driver(&cirrusfb_pci_driver);
2652 #endif
2653 #ifdef CONFIG_ZORRO
2654 zorro_unregister_driver(&cirrusfb_zorro_driver);
2655 #endif
2658 module_init(cirrusfb_init);
2660 #ifdef MODULE
2661 module_exit(cirrusfb_exit);
2662 #endif
2664 /**********************************************************************/
2665 /* about the following functions - I have used the same names for the */
2666 /* functions as Markus Wild did in his Retina driver for NetBSD as */
2667 /* they just made sense for this purpose. Apart from that, I wrote */
2668 /* these functions myself. */
2669 /**********************************************************************/
2671 /*** WGen() - write into one of the external/general registers ***/
2672 static void WGen(const struct cirrusfb_info *cinfo,
2673 int regnum, unsigned char val)
2675 unsigned long regofs = 0;
2677 if (cinfo->btype == BT_PICASSO) {
2678 /* Picasso II specific hack */
2679 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2680 regnum == CL_VSSM2) */
2681 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2682 regofs = 0xfff;
2685 vga_w(cinfo->regbase, regofs + regnum, val);
2688 /*** RGen() - read out one of the external/general registers ***/
2689 static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum)
2691 unsigned long regofs = 0;
2693 if (cinfo->btype == BT_PICASSO) {
2694 /* Picasso II specific hack */
2695 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2696 regnum == CL_VSSM2) */
2697 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2698 regofs = 0xfff;
2701 return vga_r(cinfo->regbase, regofs + regnum);
2704 /*** AttrOn() - turn on VideoEnable for Attribute controller ***/
2705 static void AttrOn(const struct cirrusfb_info *cinfo)
2707 assert(cinfo != NULL);
2709 DPRINTK("ENTER\n");
2711 if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) {
2712 /* if we're just in "write value" mode, write back the */
2713 /* same value as before to not modify anything */
2714 vga_w(cinfo->regbase, VGA_ATT_IW,
2715 vga_r(cinfo->regbase, VGA_ATT_R));
2717 /* turn on video bit */
2718 /* vga_w(cinfo->regbase, VGA_ATT_IW, 0x20); */
2719 vga_w(cinfo->regbase, VGA_ATT_IW, 0x33);
2721 /* dummy write on Reg0 to be on "write index" mode next time */
2722 vga_w(cinfo->regbase, VGA_ATT_IW, 0x00);
2724 DPRINTK("EXIT\n");
2727 /*** WHDR() - write into the Hidden DAC register ***/
2728 /* as the HDR is the only extension register that requires special treatment
2729 * (the other extension registers are accessible just like the "ordinary"
2730 * registers of their functional group) here is a specialized routine for
2731 * accessing the HDR
2733 static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val)
2735 unsigned char dummy;
2737 if (cinfo->btype == BT_PICASSO) {
2738 /* Klaus' hint for correct access to HDR on some boards */
2739 /* first write 0 to pixel mask (3c6) */
2740 WGen(cinfo, VGA_PEL_MSK, 0x00);
2741 udelay(200);
2742 /* next read dummy from pixel address (3c8) */
2743 dummy = RGen(cinfo, VGA_PEL_IW);
2744 udelay(200);
2746 /* now do the usual stuff to access the HDR */
2748 dummy = RGen(cinfo, VGA_PEL_MSK);
2749 udelay(200);
2750 dummy = RGen(cinfo, VGA_PEL_MSK);
2751 udelay(200);
2752 dummy = RGen(cinfo, VGA_PEL_MSK);
2753 udelay(200);
2754 dummy = RGen(cinfo, VGA_PEL_MSK);
2755 udelay(200);
2757 WGen(cinfo, VGA_PEL_MSK, val);
2758 udelay(200);
2760 if (cinfo->btype == BT_PICASSO) {
2761 /* now first reset HDR access counter */
2762 dummy = RGen(cinfo, VGA_PEL_IW);
2763 udelay(200);
2765 /* and at the end, restore the mask value */
2766 /* ## is this mask always 0xff? */
2767 WGen(cinfo, VGA_PEL_MSK, 0xff);
2768 udelay(200);
2772 /*** WSFR() - write to the "special function register" (SFR) ***/
2773 static void WSFR(struct cirrusfb_info *cinfo, unsigned char val)
2775 #ifdef CONFIG_ZORRO
2776 assert(cinfo->regbase != NULL);
2777 cinfo->SFR = val;
2778 z_writeb(val, cinfo->regbase + 0x8000);
2779 #endif
2782 /* The Picasso has a second register for switching the monitor bit */
2783 static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val)
2785 #ifdef CONFIG_ZORRO
2786 /* writing an arbitrary value to this one causes the monitor switcher */
2787 /* to flip to Amiga display */
2788 assert(cinfo->regbase != NULL);
2789 cinfo->SFR = val;
2790 z_writeb(val, cinfo->regbase + 0x9000);
2791 #endif
2794 /*** WClut - set CLUT entry (range: 0..63) ***/
2795 static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
2796 unsigned char green, unsigned char blue)
2798 unsigned int data = VGA_PEL_D;
2800 /* address write mode register is not translated.. */
2801 vga_w(cinfo->regbase, VGA_PEL_IW, regnum);
2803 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2804 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2805 /* but DAC data register IS, at least for Picasso II */
2806 if (cinfo->btype == BT_PICASSO)
2807 data += 0xfff;
2808 vga_w(cinfo->regbase, data, red);
2809 vga_w(cinfo->regbase, data, green);
2810 vga_w(cinfo->regbase, data, blue);
2811 } else {
2812 vga_w(cinfo->regbase, data, blue);
2813 vga_w(cinfo->regbase, data, green);
2814 vga_w(cinfo->regbase, data, red);
2818 #if 0
2819 /*** RClut - read CLUT entry (range 0..63) ***/
2820 static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
2821 unsigned char *green, unsigned char *blue)
2823 unsigned int data = VGA_PEL_D;
2825 vga_w(cinfo->regbase, VGA_PEL_IR, regnum);
2827 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2828 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2829 if (cinfo->btype == BT_PICASSO)
2830 data += 0xfff;
2831 *red = vga_r(cinfo->regbase, data);
2832 *green = vga_r(cinfo->regbase, data);
2833 *blue = vga_r(cinfo->regbase, data);
2834 } else {
2835 *blue = vga_r(cinfo->regbase, data);
2836 *green = vga_r(cinfo->regbase, data);
2837 *red = vga_r(cinfo->regbase, data);
2840 #endif
2842 /*******************************************************************
2843 cirrusfb_WaitBLT()
2845 Wait for the BitBLT engine to complete a possible earlier job
2846 *********************************************************************/
2848 /* FIXME: use interrupts instead */
2849 static void cirrusfb_WaitBLT(u8 __iomem *regbase)
2851 /* now busy-wait until we're done */
2852 while (vga_rgfx(regbase, CL_GR31) & 0x08)
2853 /* do nothing */ ;
2856 /*******************************************************************
2857 cirrusfb_BitBLT()
2859 perform accelerated "scrolling"
2860 ********************************************************************/
2862 static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
2863 u_short curx, u_short cury,
2864 u_short destx, u_short desty,
2865 u_short width, u_short height,
2866 u_short line_length)
2868 u_short nwidth, nheight;
2869 u_long nsrc, ndest;
2870 u_char bltmode;
2872 DPRINTK("ENTER\n");
2874 nwidth = width - 1;
2875 nheight = height - 1;
2877 bltmode = 0x00;
2878 /* if source adr < dest addr, do the Blt backwards */
2879 if (cury <= desty) {
2880 if (cury == desty) {
2881 /* if src and dest are on the same line, check x */
2882 if (curx < destx)
2883 bltmode |= 0x01;
2884 } else
2885 bltmode |= 0x01;
2887 if (!bltmode) {
2888 /* standard case: forward blitting */
2889 nsrc = (cury * line_length) + curx;
2890 ndest = (desty * line_length) + destx;
2891 } else {
2892 /* this means start addresses are at the end,
2893 * counting backwards
2895 nsrc = cury * line_length + curx +
2896 nheight * line_length + nwidth;
2897 ndest = desty * line_length + destx +
2898 nheight * line_length + nwidth;
2902 run-down of registers to be programmed:
2903 destination pitch
2904 source pitch
2905 BLT width/height
2906 source start
2907 destination start
2908 BLT mode
2909 BLT ROP
2910 VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color"
2911 start/stop
2914 cirrusfb_WaitBLT(regbase);
2916 /* pitch: set to line_length */
2917 /* dest pitch low */
2918 vga_wgfx(regbase, CL_GR24, line_length & 0xff);
2919 /* dest pitch hi */
2920 vga_wgfx(regbase, CL_GR25, line_length >> 8);
2921 /* source pitch low */
2922 vga_wgfx(regbase, CL_GR26, line_length & 0xff);
2923 /* source pitch hi */
2924 vga_wgfx(regbase, CL_GR27, line_length >> 8);
2926 /* BLT width: actual number of pixels - 1 */
2927 /* BLT width low */
2928 vga_wgfx(regbase, CL_GR20, nwidth & 0xff);
2929 /* BLT width hi */
2930 vga_wgfx(regbase, CL_GR21, nwidth >> 8);
2932 /* BLT height: actual number of lines -1 */
2933 /* BLT height low */
2934 vga_wgfx(regbase, CL_GR22, nheight & 0xff);
2935 /* BLT width hi */
2936 vga_wgfx(regbase, CL_GR23, nheight >> 8);
2938 /* BLT destination */
2939 /* BLT dest low */
2940 vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
2941 /* BLT dest mid */
2942 vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
2943 /* BLT dest hi */
2944 vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
2946 /* BLT source */
2947 /* BLT src low */
2948 vga_wgfx(regbase, CL_GR2C, (u_char) (nsrc & 0xff));
2949 /* BLT src mid */
2950 vga_wgfx(regbase, CL_GR2D, (u_char) (nsrc >> 8));
2951 /* BLT src hi */
2952 vga_wgfx(regbase, CL_GR2E, (u_char) (nsrc >> 16));
2954 /* BLT mode */
2955 vga_wgfx(regbase, CL_GR30, bltmode); /* BLT mode */
2957 /* BLT ROP: SrcCopy */
2958 vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */
2960 /* and finally: GO! */
2961 vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */
2963 DPRINTK("EXIT\n");
2966 /*******************************************************************
2967 cirrusfb_RectFill()
2969 perform accelerated rectangle fill
2970 ********************************************************************/
2972 static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
2973 u_short x, u_short y, u_short width, u_short height,
2974 u_char color, u_short line_length)
2976 u_short nwidth, nheight;
2977 u_long ndest;
2978 u_char op;
2980 DPRINTK("ENTER\n");
2982 nwidth = width - 1;
2983 nheight = height - 1;
2985 ndest = (y * line_length) + x;
2987 cirrusfb_WaitBLT(regbase);
2989 /* pitch: set to line_length */
2990 vga_wgfx(regbase, CL_GR24, line_length & 0xff); /* dest pitch low */
2991 vga_wgfx(regbase, CL_GR25, line_length >> 8); /* dest pitch hi */
2992 vga_wgfx(regbase, CL_GR26, line_length & 0xff); /* source pitch low */
2993 vga_wgfx(regbase, CL_GR27, line_length >> 8); /* source pitch hi */
2995 /* BLT width: actual number of pixels - 1 */
2996 vga_wgfx(regbase, CL_GR20, nwidth & 0xff); /* BLT width low */
2997 vga_wgfx(regbase, CL_GR21, nwidth >> 8); /* BLT width hi */
2999 /* BLT height: actual number of lines -1 */
3000 vga_wgfx(regbase, CL_GR22, nheight & 0xff); /* BLT height low */
3001 vga_wgfx(regbase, CL_GR23, nheight >> 8); /* BLT width hi */
3003 /* BLT destination */
3004 /* BLT dest low */
3005 vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
3006 /* BLT dest mid */
3007 vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
3008 /* BLT dest hi */
3009 vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
3011 /* BLT source: set to 0 (is a dummy here anyway) */
3012 vga_wgfx(regbase, CL_GR2C, 0x00); /* BLT src low */
3013 vga_wgfx(regbase, CL_GR2D, 0x00); /* BLT src mid */
3014 vga_wgfx(regbase, CL_GR2E, 0x00); /* BLT src hi */
3016 /* This is a ColorExpand Blt, using the */
3017 /* same color for foreground and background */
3018 vga_wgfx(regbase, VGA_GFX_SR_VALUE, color); /* foreground color */
3019 vga_wgfx(regbase, VGA_GFX_SR_ENABLE, color); /* background color */
3021 op = 0xc0;
3022 if (bits_per_pixel == 16) {
3023 vga_wgfx(regbase, CL_GR10, color); /* foreground color */
3024 vga_wgfx(regbase, CL_GR11, color); /* background color */
3025 op = 0x50;
3026 op = 0xd0;
3027 } else if (bits_per_pixel == 32) {
3028 vga_wgfx(regbase, CL_GR10, color); /* foreground color */
3029 vga_wgfx(regbase, CL_GR11, color); /* background color */
3030 vga_wgfx(regbase, CL_GR12, color); /* foreground color */
3031 vga_wgfx(regbase, CL_GR13, color); /* background color */
3032 vga_wgfx(regbase, CL_GR14, 0); /* foreground color */
3033 vga_wgfx(regbase, CL_GR15, 0); /* background color */
3034 op = 0x50;
3035 op = 0xf0;
3037 /* BLT mode: color expand, Enable 8x8 copy (faster?) */
3038 vga_wgfx(regbase, CL_GR30, op); /* BLT mode */
3040 /* BLT ROP: SrcCopy */
3041 vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */
3043 /* and finally: GO! */
3044 vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */
3046 DPRINTK("EXIT\n");
3049 /**************************************************************************
3050 * bestclock() - determine closest possible clock lower(?) than the
3051 * desired pixel clock
3052 **************************************************************************/
3053 static void bestclock(long freq, long *best, long *nom,
3054 long *den, long *div, long maxfreq)
3056 long n, h, d, f;
3058 assert(best != NULL);
3059 assert(nom != NULL);
3060 assert(den != NULL);
3061 assert(div != NULL);
3062 assert(maxfreq > 0);
3064 *nom = 0;
3065 *den = 0;
3066 *div = 0;
3068 DPRINTK("ENTER\n");
3070 if (freq < 8000)
3071 freq = 8000;
3073 if (freq > maxfreq)
3074 freq = maxfreq;
3076 *best = 0;
3077 f = freq * 10;
3079 for (n = 32; n < 128; n++) {
3080 d = (143181 * n) / f;
3081 if ((d >= 7) && (d <= 63)) {
3082 if (d > 31)
3083 d = (d / 2) * 2;
3084 h = (14318 * n) / d;
3085 if (abs(h - freq) < abs(*best - freq)) {
3086 *best = h;
3087 *nom = n;
3088 if (d < 32) {
3089 *den = d;
3090 *div = 0;
3091 } else {
3092 *den = d / 2;
3093 *div = 1;
3097 d = DIV_ROUND_UP(143181 * n, f);
3098 if ((d >= 7) && (d <= 63)) {
3099 if (d > 31)
3100 d = (d / 2) * 2;
3101 h = (14318 * n) / d;
3102 if (abs(h - freq) < abs(*best - freq)) {
3103 *best = h;
3104 *nom = n;
3105 if (d < 32) {
3106 *den = d;
3107 *div = 0;
3108 } else {
3109 *den = d / 2;
3110 *div = 1;
3116 DPRINTK("Best possible values for given frequency:\n");
3117 DPRINTK(" best: %ld kHz nom: %ld den: %ld div: %ld\n",
3118 freq, *nom, *den, *div);
3120 DPRINTK("EXIT\n");
3123 /* -------------------------------------------------------------------------
3125 * debugging functions
3127 * -------------------------------------------------------------------------
3130 #ifdef CIRRUSFB_DEBUG
3133 * cirrusfb_dbg_print_byte
3134 * @name: name associated with byte value to be displayed
3135 * @val: byte value to be displayed
3137 * DESCRIPTION:
3138 * Display an indented string, along with a hexidecimal byte value, and
3139 * its decoded bits. Bits 7 through 0 are listed in left-to-right
3140 * order.
3143 static
3144 void cirrusfb_dbg_print_byte(const char *name, unsigned char val)
3146 DPRINTK("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n",
3147 name, val,
3148 val & 0x80 ? '1' : '0',
3149 val & 0x40 ? '1' : '0',
3150 val & 0x20 ? '1' : '0',
3151 val & 0x10 ? '1' : '0',
3152 val & 0x08 ? '1' : '0',
3153 val & 0x04 ? '1' : '0',
3154 val & 0x02 ? '1' : '0',
3155 val & 0x01 ? '1' : '0');
3159 * cirrusfb_dbg_print_regs
3160 * @base: If using newmmio, the newmmio base address, otherwise %NULL
3161 * @reg_class: type of registers to read: %CRT, or %SEQ
3163 * DESCRIPTION:
3164 * Dumps the given list of VGA CRTC registers. If @base is %NULL,
3165 * old-style I/O ports are queried for information, otherwise MMIO is
3166 * used at the given @base address to query the information.
3169 static
3170 void cirrusfb_dbg_print_regs(caddr_t regbase,
3171 enum cirrusfb_dbg_reg_class reg_class, ...)
3173 va_list list;
3174 unsigned char val = 0;
3175 unsigned reg;
3176 char *name;
3178 va_start(list, reg_class);
3180 name = va_arg(list, char *);
3181 while (name != NULL) {
3182 reg = va_arg(list, int);
3184 switch (reg_class) {
3185 case CRT:
3186 val = vga_rcrt(regbase, (unsigned char) reg);
3187 break;
3188 case SEQ:
3189 val = vga_rseq(regbase, (unsigned char) reg);
3190 break;
3191 default:
3192 /* should never occur */
3193 assert(false);
3194 break;
3197 cirrusfb_dbg_print_byte(name, val);
3199 name = va_arg(list, char *);
3202 va_end(list);
3206 * cirrusfb_dump
3207 * @cirrusfbinfo:
3209 * DESCRIPTION:
3212 static void cirrusfb_dump(void)
3214 cirrusfb_dbg_reg_dump(NULL);
3218 * cirrusfb_dbg_reg_dump
3219 * @base: If using newmmio, the newmmio base address, otherwise %NULL
3221 * DESCRIPTION:
3222 * Dumps a list of interesting VGA and CIRRUSFB registers. If @base is %NULL,
3223 * old-style I/O ports are queried for information, otherwise MMIO is
3224 * used at the given @base address to query the information.
3227 static
3228 void cirrusfb_dbg_reg_dump(caddr_t regbase)
3230 DPRINTK("CIRRUSFB VGA CRTC register dump:\n");
3232 cirrusfb_dbg_print_regs(regbase, CRT,
3233 "CR00", 0x00,
3234 "CR01", 0x01,
3235 "CR02", 0x02,
3236 "CR03", 0x03,
3237 "CR04", 0x04,
3238 "CR05", 0x05,
3239 "CR06", 0x06,
3240 "CR07", 0x07,
3241 "CR08", 0x08,
3242 "CR09", 0x09,
3243 "CR0A", 0x0A,
3244 "CR0B", 0x0B,
3245 "CR0C", 0x0C,
3246 "CR0D", 0x0D,
3247 "CR0E", 0x0E,
3248 "CR0F", 0x0F,
3249 "CR10", 0x10,
3250 "CR11", 0x11,
3251 "CR12", 0x12,
3252 "CR13", 0x13,
3253 "CR14", 0x14,
3254 "CR15", 0x15,
3255 "CR16", 0x16,
3256 "CR17", 0x17,
3257 "CR18", 0x18,
3258 "CR22", 0x22,
3259 "CR24", 0x24,
3260 "CR26", 0x26,
3261 "CR2D", 0x2D,
3262 "CR2E", 0x2E,
3263 "CR2F", 0x2F,
3264 "CR30", 0x30,
3265 "CR31", 0x31,
3266 "CR32", 0x32,
3267 "CR33", 0x33,
3268 "CR34", 0x34,
3269 "CR35", 0x35,
3270 "CR36", 0x36,
3271 "CR37", 0x37,
3272 "CR38", 0x38,
3273 "CR39", 0x39,
3274 "CR3A", 0x3A,
3275 "CR3B", 0x3B,
3276 "CR3C", 0x3C,
3277 "CR3D", 0x3D,
3278 "CR3E", 0x3E,
3279 "CR3F", 0x3F,
3280 NULL);
3282 DPRINTK("\n");
3284 DPRINTK("CIRRUSFB VGA SEQ register dump:\n");
3286 cirrusfb_dbg_print_regs(regbase, SEQ,
3287 "SR00", 0x00,
3288 "SR01", 0x01,
3289 "SR02", 0x02,
3290 "SR03", 0x03,
3291 "SR04", 0x04,
3292 "SR08", 0x08,
3293 "SR09", 0x09,
3294 "SR0A", 0x0A,
3295 "SR0B", 0x0B,
3296 "SR0D", 0x0D,
3297 "SR10", 0x10,
3298 "SR11", 0x11,
3299 "SR12", 0x12,
3300 "SR13", 0x13,
3301 "SR14", 0x14,
3302 "SR15", 0x15,
3303 "SR16", 0x16,
3304 "SR17", 0x17,
3305 "SR18", 0x18,
3306 "SR19", 0x19,
3307 "SR1A", 0x1A,
3308 "SR1B", 0x1B,
3309 "SR1C", 0x1C,
3310 "SR1D", 0x1D,
3311 "SR1E", 0x1E,
3312 "SR1F", 0x1F,
3313 NULL);
3315 DPRINTK("\n");
3318 #endif /* CIRRUSFB_DEBUG */