cirrusfb: remove 24 bpp mode
[linux-2.6/mini2440.git] / drivers / video / cirrusfb.c
blob4888ff69f802e643892e253e5de42453908a25f1
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 32:
642 break; /* 1 pixel == 1 byte */
643 default:
644 printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..."
645 "color depth not supported.\n",
646 var->xres, var->yres, var->bits_per_pixel);
647 DPRINTK("EXIT - EINVAL error\n");
648 return -EINVAL;
651 if (var->xres_virtual < var->xres)
652 var->xres_virtual = var->xres;
653 /* use highest possible virtual resolution */
654 if (var->yres_virtual == -1) {
655 var->yres_virtual = pixels / var->xres_virtual;
657 printk(KERN_INFO "cirrusfb: virtual resolution set to "
658 "maximum of %dx%d\n", var->xres_virtual,
659 var->yres_virtual);
661 if (var->yres_virtual < var->yres)
662 var->yres_virtual = var->yres;
664 if (var->xres_virtual * var->yres_virtual > pixels) {
665 printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected... "
666 "virtual resolution too high to fit into video memory!\n",
667 var->xres_virtual, var->yres_virtual,
668 var->bits_per_pixel);
669 DPRINTK("EXIT - EINVAL error\n");
670 return -EINVAL;
674 if (var->xoffset < 0)
675 var->xoffset = 0;
676 if (var->yoffset < 0)
677 var->yoffset = 0;
679 /* truncate xoffset and yoffset to maximum if too high */
680 if (var->xoffset > var->xres_virtual - var->xres)
681 var->xoffset = var->xres_virtual - var->xres - 1;
682 if (var->yoffset > var->yres_virtual - var->yres)
683 var->yoffset = var->yres_virtual - var->yres - 1;
685 switch (var->bits_per_pixel) {
686 case 1:
687 var->red.offset = 0;
688 var->red.length = 1;
689 var->green = var->red;
690 var->blue = var->red;
691 break;
693 case 8:
694 var->red.offset = 0;
695 var->red.length = 6;
696 var->green = var->red;
697 var->blue = var->red;
698 break;
700 case 16:
701 if (isPReP) {
702 var->red.offset = 2;
703 var->green.offset = -3;
704 var->blue.offset = 8;
705 } else {
706 var->red.offset = 10;
707 var->green.offset = 5;
708 var->blue.offset = 0;
710 var->red.length = 5;
711 var->green.length = 5;
712 var->blue.length = 5;
713 break;
715 case 32:
716 if (isPReP) {
717 var->red.offset = 8;
718 var->green.offset = 16;
719 var->blue.offset = 24;
720 } else {
721 var->red.offset = 16;
722 var->green.offset = 8;
723 var->blue.offset = 0;
725 var->red.length = 8;
726 var->green.length = 8;
727 var->blue.length = 8;
728 break;
730 default:
731 DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);
732 assert(false);
733 /* should never occur */
734 break;
737 var->red.msb_right =
738 var->green.msb_right =
739 var->blue.msb_right =
740 var->transp.offset =
741 var->transp.length =
742 var->transp.msb_right = 0;
744 yres = var->yres;
745 if (var->vmode & FB_VMODE_DOUBLE)
746 yres *= 2;
747 else if (var->vmode & FB_VMODE_INTERLACED)
748 yres = (yres + 1) / 2;
750 if (yres >= 1280) {
751 printk(KERN_ERR "cirrusfb: ERROR: VerticalTotal >= 1280; "
752 "special treatment required! (TODO)\n");
753 DPRINTK("EXIT - EINVAL error\n");
754 return -EINVAL;
757 return 0;
760 static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
761 struct cirrusfb_regs *regs,
762 struct fb_info *info)
764 long freq;
765 long maxclock;
766 int maxclockidx = var->bits_per_pixel >> 3;
767 struct cirrusfb_info *cinfo = info->par;
768 int xres, hfront, hsync, hback;
769 int yres, vfront, vsync, vback;
771 switch (var->bits_per_pixel) {
772 case 1:
773 info->fix.line_length = var->xres_virtual / 8;
774 info->fix.visual = FB_VISUAL_MONO10;
775 break;
777 case 8:
778 info->fix.line_length = var->xres_virtual;
779 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
780 break;
782 case 16:
783 case 32:
784 info->fix.line_length = var->xres_virtual * maxclockidx;
785 info->fix.visual = FB_VISUAL_DIRECTCOLOR;
786 break;
788 default:
789 DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);
790 assert(false);
791 /* should never occur */
792 break;
795 info->fix.type = FB_TYPE_PACKED_PIXELS;
797 /* convert from ps to kHz */
798 freq = PICOS2KHZ(var->pixclock);
800 DPRINTK("desired pixclock: %ld kHz\n", freq);
802 maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
803 regs->multiplexing = 0;
805 /* If the frequency is greater than we can support, we might be able
806 * to use multiplexing for the video mode */
807 if (freq > maxclock) {
808 switch (cinfo->btype) {
809 case BT_ALPINE:
810 case BT_GD5480:
811 regs->multiplexing = 1;
812 break;
814 default:
815 printk(KERN_ERR "cirrusfb: Frequency greater "
816 "than maxclock (%ld kHz)\n", maxclock);
817 DPRINTK("EXIT - return -EINVAL\n");
818 return -EINVAL;
821 #if 0
822 /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
823 * the VCLK is double the pixel clock. */
824 switch (var->bits_per_pixel) {
825 case 16:
826 case 32:
827 if (regs->HorizRes <= 800)
828 /* Xbh has this type of clock for 32-bit */
829 freq /= 2;
830 break;
832 #endif
834 bestclock(freq, &regs->freq, &regs->nom, &regs->den, &regs->div,
835 maxclock);
836 regs->mclk = cirrusfb_get_mclk(freq, var->bits_per_pixel,
837 &regs->divMCLK);
839 xres = var->xres;
840 hfront = var->right_margin;
841 hsync = var->hsync_len;
842 hback = var->left_margin;
844 yres = var->yres;
845 vfront = var->lower_margin;
846 vsync = var->vsync_len;
847 vback = var->upper_margin;
849 if (var->vmode & FB_VMODE_DOUBLE) {
850 yres *= 2;
851 vfront *= 2;
852 vsync *= 2;
853 vback *= 2;
854 } else if (var->vmode & FB_VMODE_INTERLACED) {
855 yres = (yres + 1) / 2;
856 vfront = (vfront + 1) / 2;
857 vsync = (vsync + 1) / 2;
858 vback = (vback + 1) / 2;
860 regs->HorizRes = xres;
861 regs->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5;
862 regs->HorizDispEnd = xres / 8 - 1;
863 regs->HorizBlankStart = xres / 8;
864 /* does not count with "-5" */
865 regs->HorizBlankEnd = regs->HorizTotal + 5;
866 regs->HorizSyncStart = (xres + hfront) / 8 + 1;
867 regs->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1;
869 regs->VertRes = yres;
870 regs->VertTotal = yres + vfront + vsync + vback - 2;
871 regs->VertDispEnd = yres - 1;
872 regs->VertBlankStart = yres;
873 regs->VertBlankEnd = regs->VertTotal;
874 regs->VertSyncStart = yres + vfront - 1;
875 regs->VertSyncEnd = yres + vfront + vsync - 1;
877 if (regs->VertRes >= 1024) {
878 regs->VertTotal /= 2;
879 regs->VertSyncStart /= 2;
880 regs->VertSyncEnd /= 2;
881 regs->VertDispEnd /= 2;
883 if (regs->multiplexing) {
884 regs->HorizTotal /= 2;
885 regs->HorizSyncStart /= 2;
886 regs->HorizSyncEnd /= 2;
887 regs->HorizDispEnd /= 2;
890 return 0;
893 static void cirrusfb_set_mclk(const struct cirrusfb_info *cinfo, int val,
894 int div)
896 assert(cinfo != NULL);
898 if (div == 2) {
899 /* VCLK = MCLK/2 */
900 unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E);
901 vga_wseq(cinfo->regbase, CL_SEQR1E, old | 0x1);
902 vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
903 } else if (div == 1) {
904 /* VCLK = MCLK */
905 unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E);
906 vga_wseq(cinfo->regbase, CL_SEQR1E, old & ~0x1);
907 vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
908 } else {
909 vga_wseq(cinfo->regbase, CL_SEQR1F, val & 0x3f);
913 /*************************************************************************
914 cirrusfb_set_par_foo()
916 actually writes the values for a new video mode into the hardware,
917 **************************************************************************/
918 static int cirrusfb_set_par_foo(struct fb_info *info)
920 struct cirrusfb_info *cinfo = info->par;
921 struct fb_var_screeninfo *var = &info->var;
922 struct cirrusfb_regs regs;
923 u8 __iomem *regbase = cinfo->regbase;
924 unsigned char tmp;
925 int offset = 0, err;
926 const struct cirrusfb_board_info_rec *bi;
928 DPRINTK("ENTER\n");
929 DPRINTK("Requested mode: %dx%dx%d\n",
930 var->xres, var->yres, var->bits_per_pixel);
931 DPRINTK("pixclock: %d\n", var->pixclock);
933 init_vgachip(info);
935 err = cirrusfb_decode_var(var, &regs, info);
936 if (err) {
937 /* should never happen */
938 DPRINTK("mode change aborted. invalid var.\n");
939 return -EINVAL;
942 bi = &cirrusfb_board_info[cinfo->btype];
944 /* unlock register VGA_CRTC_H_TOTAL..CRT7 */
945 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */
947 /* if debugging is enabled, all parameters get output before writing */
948 DPRINTK("CRT0: %ld\n", regs.HorizTotal);
949 vga_wcrt(regbase, VGA_CRTC_H_TOTAL, regs.HorizTotal);
951 DPRINTK("CRT1: %ld\n", regs.HorizDispEnd);
952 vga_wcrt(regbase, VGA_CRTC_H_DISP, regs.HorizDispEnd);
954 DPRINTK("CRT2: %ld\n", regs.HorizBlankStart);
955 vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, regs.HorizBlankStart);
957 /* + 128: Compatible read */
958 DPRINTK("CRT3: 128+%ld\n", regs.HorizBlankEnd % 32);
959 vga_wcrt(regbase, VGA_CRTC_H_BLANK_END,
960 128 + (regs.HorizBlankEnd % 32));
962 DPRINTK("CRT4: %ld\n", regs.HorizSyncStart);
963 vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, regs.HorizSyncStart);
965 tmp = regs.HorizSyncEnd % 32;
966 if (regs.HorizBlankEnd & 32)
967 tmp += 128;
968 DPRINTK("CRT5: %d\n", tmp);
969 vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp);
971 DPRINTK("CRT6: %ld\n", regs.VertTotal & 0xff);
972 vga_wcrt(regbase, VGA_CRTC_V_TOTAL, (regs.VertTotal & 0xff));
974 tmp = 16; /* LineCompare bit #9 */
975 if (regs.VertTotal & 256)
976 tmp |= 1;
977 if (regs.VertDispEnd & 256)
978 tmp |= 2;
979 if (regs.VertSyncStart & 256)
980 tmp |= 4;
981 if (regs.VertBlankStart & 256)
982 tmp |= 8;
983 if (regs.VertTotal & 512)
984 tmp |= 32;
985 if (regs.VertDispEnd & 512)
986 tmp |= 64;
987 if (regs.VertSyncStart & 512)
988 tmp |= 128;
989 DPRINTK("CRT7: %d\n", tmp);
990 vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp);
992 tmp = 0x40; /* LineCompare bit #8 */
993 if (regs.VertBlankStart & 512)
994 tmp |= 0x20;
995 if (var->vmode & FB_VMODE_DOUBLE)
996 tmp |= 0x80;
997 DPRINTK("CRT9: %d\n", tmp);
998 vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp);
1000 DPRINTK("CRT10: %ld\n", regs.VertSyncStart & 0xff);
1001 vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, regs.VertSyncStart & 0xff);
1003 DPRINTK("CRT11: 64+32+%ld\n", regs.VertSyncEnd % 16);
1004 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, regs.VertSyncEnd % 16 + 64 + 32);
1006 DPRINTK("CRT12: %ld\n", regs.VertDispEnd & 0xff);
1007 vga_wcrt(regbase, VGA_CRTC_V_DISP_END, regs.VertDispEnd & 0xff);
1009 DPRINTK("CRT15: %ld\n", regs.VertBlankStart & 0xff);
1010 vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, regs.VertBlankStart & 0xff);
1012 DPRINTK("CRT16: %ld\n", regs.VertBlankEnd & 0xff);
1013 vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, regs.VertBlankEnd & 0xff);
1015 DPRINTK("CRT18: 0xff\n");
1016 vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff);
1018 tmp = 0;
1019 if (var->vmode & FB_VMODE_INTERLACED)
1020 tmp |= 1;
1021 if (regs.HorizBlankEnd & 64)
1022 tmp |= 16;
1023 if (regs.HorizBlankEnd & 128)
1024 tmp |= 32;
1025 if (regs.VertBlankEnd & 256)
1026 tmp |= 64;
1027 if (regs.VertBlankEnd & 512)
1028 tmp |= 128;
1030 DPRINTK("CRT1a: %d\n", tmp);
1031 vga_wcrt(regbase, CL_CRT1A, tmp);
1033 /* set VCLK0 */
1034 /* hardware RefClock: 14.31818 MHz */
1035 /* formula: VClk = (OSC * N) / (D * (1+P)) */
1036 /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
1038 vga_wseq(regbase, CL_SEQRB, regs.nom);
1039 tmp = regs.den << 1;
1040 if (regs.div != 0)
1041 tmp |= 1;
1043 /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
1044 if ((cinfo->btype == BT_SD64) ||
1045 (cinfo->btype == BT_ALPINE) ||
1046 (cinfo->btype == BT_GD5480))
1047 tmp |= 0x80;
1049 DPRINTK("CL_SEQR1B: %ld\n", (long) tmp);
1050 vga_wseq(regbase, CL_SEQR1B, tmp);
1052 if (regs.VertRes >= 1024)
1053 /* 1280x1024 */
1054 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7);
1055 else
1056 /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
1057 * address wrap, no compat. */
1058 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3);
1060 /* HAEH? vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20);
1061 * previously: 0x00 unlock VGA_CRTC_H_TOTAL..CRT7 */
1063 /* don't know if it would hurt to also program this if no interlaced */
1064 /* mode is used, but I feel better this way.. :-) */
1065 if (var->vmode & FB_VMODE_INTERLACED)
1066 vga_wcrt(regbase, VGA_CRTC_REGS, regs.HorizTotal / 2);
1067 else
1068 vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
1070 vga_wseq(regbase, VGA_SEQ_CHARACTER_MAP, 0);
1072 /* adjust horizontal/vertical sync type (low/high) */
1073 /* enable display memory & CRTC I/O address for color mode */
1074 tmp = 0x03;
1075 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1076 tmp |= 0x40;
1077 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1078 tmp |= 0x80;
1079 WGen(cinfo, VGA_MIS_W, tmp);
1081 /* Screen A Preset Row-Scan register */
1082 vga_wcrt(regbase, VGA_CRTC_PRESET_ROW, 0);
1083 /* text cursor on and start line */
1084 vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0);
1085 /* text cursor end line */
1086 vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 31);
1088 /******************************************************
1090 * 1 bpp
1094 /* programming for different color depths */
1095 if (var->bits_per_pixel == 1) {
1096 DPRINTK("cirrusfb: preparing for 1 bit deep display\n");
1097 vga_wgfx(regbase, VGA_GFX_MODE, 0); /* mode register */
1099 /* SR07 */
1100 switch (cinfo->btype) {
1101 case BT_SD64:
1102 case BT_PICCOLO:
1103 case BT_PICASSO:
1104 case BT_SPECTRUM:
1105 case BT_PICASSO4:
1106 case BT_ALPINE:
1107 case BT_GD5480:
1108 DPRINTK(" (for GD54xx)\n");
1109 vga_wseq(regbase, CL_SEQR7,
1110 regs.multiplexing ?
1111 bi->sr07_1bpp_mux : bi->sr07_1bpp);
1112 break;
1114 case BT_LAGUNA:
1115 DPRINTK(" (for GD546x)\n");
1116 vga_wseq(regbase, CL_SEQR7,
1117 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1118 break;
1120 default:
1121 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1122 break;
1125 /* Extended Sequencer Mode */
1126 switch (cinfo->btype) {
1127 case BT_SD64:
1128 /* setting the SEQRF on SD64 is not necessary
1129 * (only during init)
1131 DPRINTK("(for SD64)\n");
1132 /* MCLK select */
1133 vga_wseq(regbase, CL_SEQR1F, 0x1a);
1134 break;
1136 case BT_PICCOLO:
1137 case BT_SPECTRUM:
1138 DPRINTK("(for Piccolo/Spectrum)\n");
1139 /* ### ueberall 0x22? */
1140 /* ##vorher 1c MCLK select */
1141 vga_wseq(regbase, CL_SEQR1F, 0x22);
1142 /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
1143 vga_wseq(regbase, CL_SEQRF, 0xb0);
1144 break;
1146 case BT_PICASSO:
1147 DPRINTK("(for Picasso)\n");
1148 /* ##vorher 22 MCLK select */
1149 vga_wseq(regbase, CL_SEQR1F, 0x22);
1150 /* ## vorher d0 avoid FIFO underruns..? */
1151 vga_wseq(regbase, CL_SEQRF, 0xd0);
1152 break;
1154 case BT_PICASSO4:
1155 case BT_ALPINE:
1156 case BT_GD5480:
1157 case BT_LAGUNA:
1158 DPRINTK(" (for GD54xx)\n");
1159 /* do nothing */
1160 break;
1162 default:
1163 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1164 break;
1167 /* pixel mask: pass-through for first plane */
1168 WGen(cinfo, VGA_PEL_MSK, 0x01);
1169 if (regs.multiplexing)
1170 /* hidden dac reg: 1280x1024 */
1171 WHDR(cinfo, 0x4a);
1172 else
1173 /* hidden dac: nothing */
1174 WHDR(cinfo, 0);
1175 /* memory mode: odd/even, ext. memory */
1176 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06);
1177 /* plane mask: only write to first plane */
1178 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01);
1179 offset = var->xres_virtual / 16;
1182 /******************************************************
1184 * 8 bpp
1188 else if (var->bits_per_pixel == 8) {
1189 DPRINTK("cirrusfb: preparing for 8 bit deep display\n");
1190 switch (cinfo->btype) {
1191 case BT_SD64:
1192 case BT_PICCOLO:
1193 case BT_PICASSO:
1194 case BT_SPECTRUM:
1195 case BT_PICASSO4:
1196 case BT_ALPINE:
1197 case BT_GD5480:
1198 DPRINTK(" (for GD54xx)\n");
1199 vga_wseq(regbase, CL_SEQR7,
1200 regs.multiplexing ?
1201 bi->sr07_8bpp_mux : bi->sr07_8bpp);
1202 break;
1204 case BT_LAGUNA:
1205 DPRINTK(" (for GD546x)\n");
1206 vga_wseq(regbase, CL_SEQR7,
1207 vga_rseq(regbase, CL_SEQR7) | 0x01);
1208 break;
1210 default:
1211 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1212 break;
1215 switch (cinfo->btype) {
1216 case BT_SD64:
1217 /* MCLK select */
1218 vga_wseq(regbase, CL_SEQR1F, 0x1d);
1219 break;
1221 case BT_PICCOLO:
1222 case BT_PICASSO:
1223 case BT_SPECTRUM:
1224 /* ### vorher 1c MCLK select */
1225 vga_wseq(regbase, CL_SEQR1F, 0x22);
1226 /* Fast Page-Mode writes */
1227 vga_wseq(regbase, CL_SEQRF, 0xb0);
1228 break;
1230 case BT_PICASSO4:
1231 #ifdef CONFIG_ZORRO
1232 /* ### INCOMPLETE!! */
1233 vga_wseq(regbase, CL_SEQRF, 0xb8);
1234 #endif
1235 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1236 break;
1238 case BT_ALPINE:
1239 DPRINTK(" (for GD543x)\n");
1240 cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
1241 /* We already set SRF and SR1F */
1242 break;
1244 case BT_GD5480:
1245 case BT_LAGUNA:
1246 DPRINTK(" (for GD54xx)\n");
1247 /* do nothing */
1248 break;
1250 default:
1251 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1252 break;
1255 /* mode register: 256 color mode */
1256 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1257 /* pixel mask: pass-through all planes */
1258 WGen(cinfo, VGA_PEL_MSK, 0xff);
1259 if (regs.multiplexing)
1260 /* hidden dac reg: 1280x1024 */
1261 WHDR(cinfo, 0x4a);
1262 else
1263 /* hidden dac: nothing */
1264 WHDR(cinfo, 0);
1265 /* memory mode: chain4, ext. memory */
1266 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1267 /* plane mask: enable writing to all 4 planes */
1268 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1269 offset = var->xres_virtual / 8;
1272 /******************************************************
1274 * 16 bpp
1278 else if (var->bits_per_pixel == 16) {
1279 DPRINTK("cirrusfb: preparing for 16 bit deep display\n");
1280 switch (cinfo->btype) {
1281 case BT_SD64:
1282 /* Extended Sequencer Mode: 256c col. mode */
1283 vga_wseq(regbase, CL_SEQR7, 0xf7);
1284 /* MCLK select */
1285 vga_wseq(regbase, CL_SEQR1F, 0x1e);
1286 break;
1288 case BT_PICCOLO:
1289 case BT_SPECTRUM:
1290 vga_wseq(regbase, CL_SEQR7, 0x87);
1291 /* Fast Page-Mode writes */
1292 vga_wseq(regbase, CL_SEQRF, 0xb0);
1293 /* MCLK select */
1294 vga_wseq(regbase, CL_SEQR1F, 0x22);
1295 break;
1297 case BT_PICASSO:
1298 vga_wseq(regbase, CL_SEQR7, 0x27);
1299 /* Fast Page-Mode writes */
1300 vga_wseq(regbase, CL_SEQRF, 0xb0);
1301 /* MCLK select */
1302 vga_wseq(regbase, CL_SEQR1F, 0x22);
1303 break;
1305 case BT_PICASSO4:
1306 vga_wseq(regbase, CL_SEQR7, 0x27);
1307 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1308 break;
1310 case BT_ALPINE:
1311 DPRINTK(" (for GD543x)\n");
1312 if (regs.HorizRes >= 1024)
1313 vga_wseq(regbase, CL_SEQR7, 0xa7);
1314 else
1315 vga_wseq(regbase, CL_SEQR7, 0xa3);
1316 cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
1317 break;
1319 case BT_GD5480:
1320 DPRINTK(" (for GD5480)\n");
1321 vga_wseq(regbase, CL_SEQR7, 0x17);
1322 /* We already set SRF and SR1F */
1323 break;
1325 case BT_LAGUNA:
1326 DPRINTK(" (for GD546x)\n");
1327 vga_wseq(regbase, CL_SEQR7,
1328 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1329 break;
1331 default:
1332 printk(KERN_WARNING "CIRRUSFB: unknown Board\n");
1333 break;
1336 /* mode register: 256 color mode */
1337 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1338 /* pixel mask: pass-through all planes */
1339 WGen(cinfo, VGA_PEL_MSK, 0xff);
1340 #ifdef CONFIG_PCI
1341 WHDR(cinfo, 0xc0); /* Copy Xbh */
1342 #elif defined(CONFIG_ZORRO)
1343 /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
1344 WHDR(cinfo, 0xa0); /* hidden dac reg: nothing special */
1345 #endif
1346 /* memory mode: chain4, ext. memory */
1347 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1348 /* plane mask: enable writing to all 4 planes */
1349 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1350 offset = var->xres_virtual / 4;
1353 /******************************************************
1355 * 32 bpp
1359 else if (var->bits_per_pixel == 32) {
1360 DPRINTK("cirrusfb: preparing for 32 bit deep display\n");
1361 switch (cinfo->btype) {
1362 case BT_SD64:
1363 /* Extended Sequencer Mode: 256c col. mode */
1364 vga_wseq(regbase, CL_SEQR7, 0xf9);
1365 /* MCLK select */
1366 vga_wseq(regbase, CL_SEQR1F, 0x1e);
1367 break;
1369 case BT_PICCOLO:
1370 case BT_SPECTRUM:
1371 vga_wseq(regbase, CL_SEQR7, 0x85);
1372 /* Fast Page-Mode writes */
1373 vga_wseq(regbase, CL_SEQRF, 0xb0);
1374 /* MCLK select */
1375 vga_wseq(regbase, CL_SEQR1F, 0x22);
1376 break;
1378 case BT_PICASSO:
1379 vga_wseq(regbase, CL_SEQR7, 0x25);
1380 /* Fast Page-Mode writes */
1381 vga_wseq(regbase, CL_SEQRF, 0xb0);
1382 /* MCLK select */
1383 vga_wseq(regbase, CL_SEQR1F, 0x22);
1384 break;
1386 case BT_PICASSO4:
1387 vga_wseq(regbase, CL_SEQR7, 0x25);
1388 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1389 break;
1391 case BT_ALPINE:
1392 DPRINTK(" (for GD543x)\n");
1393 vga_wseq(regbase, CL_SEQR7, 0xa9);
1394 cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
1395 break;
1397 case BT_GD5480:
1398 DPRINTK(" (for GD5480)\n");
1399 vga_wseq(regbase, CL_SEQR7, 0x19);
1400 /* We already set SRF and SR1F */
1401 break;
1403 case BT_LAGUNA:
1404 DPRINTK(" (for GD546x)\n");
1405 vga_wseq(regbase, CL_SEQR7,
1406 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1407 break;
1409 default:
1410 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1411 break;
1414 /* mode register: 256 color mode */
1415 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1416 /* pixel mask: pass-through all planes */
1417 WGen(cinfo, VGA_PEL_MSK, 0xff);
1418 /* hidden dac reg: 8-8-8 mode (24 or 32) */
1419 WHDR(cinfo, 0xc5);
1420 /* memory mode: chain4, ext. memory */
1421 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1422 /* plane mask: enable writing to all 4 planes */
1423 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1424 offset = var->xres_virtual / 4;
1427 /******************************************************
1429 * unknown/unsupported bpp
1433 else
1434 printk(KERN_ERR "cirrusfb: What's this?? "
1435 " requested color depth == %d.\n",
1436 var->bits_per_pixel);
1438 vga_wcrt(regbase, VGA_CRTC_OFFSET, offset & 0xff);
1439 tmp = 0x22;
1440 if (offset & 0x100)
1441 tmp |= 0x10; /* offset overflow bit */
1443 /* screen start addr #16-18, fastpagemode cycles */
1444 vga_wcrt(regbase, CL_CRT1B, tmp);
1446 if (cinfo->btype == BT_SD64 ||
1447 cinfo->btype == BT_PICASSO4 ||
1448 cinfo->btype == BT_ALPINE ||
1449 cinfo->btype == BT_GD5480)
1450 /* screen start address bit 19 */
1451 vga_wcrt(regbase, CL_CRT1D, 0x00);
1453 /* text cursor location high */
1454 vga_wcrt(regbase, VGA_CRTC_CURSOR_HI, 0);
1455 /* text cursor location low */
1456 vga_wcrt(regbase, VGA_CRTC_CURSOR_LO, 0);
1457 /* underline row scanline = at very bottom */
1458 vga_wcrt(regbase, VGA_CRTC_UNDERLINE, 0);
1460 /* controller mode */
1461 vga_wattr(regbase, VGA_ATC_MODE, 1);
1462 /* overscan (border) color */
1463 vga_wattr(regbase, VGA_ATC_OVERSCAN, 0);
1464 /* color plane enable */
1465 vga_wattr(regbase, VGA_ATC_PLANE_ENABLE, 15);
1466 /* pixel panning */
1467 vga_wattr(regbase, CL_AR33, 0);
1468 /* color select */
1469 vga_wattr(regbase, VGA_ATC_COLOR_PAGE, 0);
1471 /* [ EGS: SetOffset(); ] */
1472 /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
1473 AttrOn(cinfo);
1475 /* set/reset register */
1476 vga_wgfx(regbase, VGA_GFX_SR_VALUE, 0);
1477 /* set/reset enable */
1478 vga_wgfx(regbase, VGA_GFX_SR_ENABLE, 0);
1479 /* color compare */
1480 vga_wgfx(regbase, VGA_GFX_COMPARE_VALUE, 0);
1481 /* data rotate */
1482 vga_wgfx(regbase, VGA_GFX_DATA_ROTATE, 0);
1483 /* read map select */
1484 vga_wgfx(regbase, VGA_GFX_PLANE_READ, 0);
1485 /* miscellaneous register */
1486 vga_wgfx(regbase, VGA_GFX_MISC, 1);
1487 /* color don't care */
1488 vga_wgfx(regbase, VGA_GFX_COMPARE_MASK, 15);
1489 /* bit mask */
1490 vga_wgfx(regbase, VGA_GFX_BIT_MASK, 255);
1492 /* graphics cursor attributes: nothing special */
1493 vga_wseq(regbase, CL_SEQR12, 0x0);
1495 /* finally, turn on everything - turn off "FullBandwidth" bit */
1496 /* also, set "DotClock%2" bit where requested */
1497 tmp = 0x01;
1499 /*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
1500 if (var->vmode & FB_VMODE_CLOCK_HALVE)
1501 tmp |= 0x08;
1504 vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp);
1505 DPRINTK("CL_SEQR1: %d\n", tmp);
1507 cinfo->currentmode = regs;
1509 /* pan to requested offset */
1510 cirrusfb_pan_display(var, info);
1512 #ifdef CIRRUSFB_DEBUG
1513 cirrusfb_dump();
1514 #endif
1516 DPRINTK("EXIT\n");
1517 return 0;
1520 /* for some reason incomprehensible to me, cirrusfb requires that you write
1521 * the registers twice for the settings to take..grr. -dte */
1522 static int cirrusfb_set_par(struct fb_info *info)
1524 cirrusfb_set_par_foo(info);
1525 return cirrusfb_set_par_foo(info);
1528 static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1529 unsigned blue, unsigned transp,
1530 struct fb_info *info)
1532 struct cirrusfb_info *cinfo = info->par;
1534 if (regno > 255)
1535 return -EINVAL;
1537 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
1538 u32 v;
1539 red >>= (16 - info->var.red.length);
1540 green >>= (16 - info->var.green.length);
1541 blue >>= (16 - info->var.blue.length);
1543 if (regno >= 16)
1544 return 1;
1545 v = (red << info->var.red.offset) |
1546 (green << info->var.green.offset) |
1547 (blue << info->var.blue.offset);
1549 cinfo->pseudo_palette[regno] = v;
1550 return 0;
1553 if (info->var.bits_per_pixel == 8)
1554 WClut(cinfo, regno, red >> 10, green >> 10, blue >> 10);
1556 return 0;
1560 /*************************************************************************
1561 cirrusfb_pan_display()
1563 performs display panning - provided hardware permits this
1564 **************************************************************************/
1565 static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
1566 struct fb_info *info)
1568 int xoffset = 0;
1569 int yoffset = 0;
1570 unsigned long base;
1571 unsigned char tmp = 0, tmp2 = 0, xpix;
1572 struct cirrusfb_info *cinfo = info->par;
1574 DPRINTK("ENTER\n");
1575 DPRINTK("virtual offset: (%d,%d)\n", var->xoffset, var->yoffset);
1577 /* no range checks for xoffset and yoffset, */
1578 /* as fb_pan_display has already done this */
1579 if (var->vmode & FB_VMODE_YWRAP)
1580 return -EINVAL;
1582 info->var.xoffset = var->xoffset;
1583 info->var.yoffset = var->yoffset;
1585 xoffset = var->xoffset * info->var.bits_per_pixel / 8;
1586 yoffset = var->yoffset;
1588 base = yoffset * info->fix.line_length + xoffset;
1590 if (info->var.bits_per_pixel == 1) {
1591 /* base is already correct */
1592 xpix = (unsigned char) (var->xoffset % 8);
1593 } else {
1594 base /= 4;
1595 xpix = (unsigned char) ((xoffset % 4) * 2);
1598 cirrusfb_WaitBLT(cinfo->regbase); /* make sure all the BLT's are done */
1600 /* lower 8 + 8 bits of screen start address */
1601 vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO,
1602 (unsigned char) (base & 0xff));
1603 vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI,
1604 (unsigned char) (base >> 8));
1606 /* construct bits 16, 17 and 18 of screen start address */
1607 if (base & 0x10000)
1608 tmp |= 0x01;
1609 if (base & 0x20000)
1610 tmp |= 0x04;
1611 if (base & 0x40000)
1612 tmp |= 0x08;
1614 /* 0xf2 is %11110010, exclude tmp bits */
1615 tmp2 = (vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2) | tmp;
1616 vga_wcrt(cinfo->regbase, CL_CRT1B, tmp2);
1618 /* construct bit 19 of screen start address */
1619 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19)
1620 vga_wcrt(cinfo->regbase, CL_CRT1D, (base >> 12) & 0x80);
1622 /* write pixel panning value to AR33; this does not quite work in 8bpp
1624 * ### Piccolo..? Will this work?
1626 if (info->var.bits_per_pixel == 1)
1627 vga_wattr(cinfo->regbase, CL_AR33, xpix);
1629 cirrusfb_WaitBLT(cinfo->regbase);
1631 DPRINTK("EXIT\n");
1632 return 0;
1635 static int cirrusfb_blank(int blank_mode, struct fb_info *info)
1638 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
1639 * then the caller blanks by setting the CLUT (Color Look Up Table)
1640 * to all black. Return 0 if blanking succeeded, != 0 if un-/blanking
1641 * failed due to e.g. a video mode which doesn't support it.
1642 * Implements VESA suspend and powerdown modes on hardware that
1643 * supports disabling hsync/vsync:
1644 * blank_mode == 2: suspend vsync
1645 * blank_mode == 3: suspend hsync
1646 * blank_mode == 4: powerdown
1648 unsigned char val;
1649 struct cirrusfb_info *cinfo = info->par;
1650 int current_mode = cinfo->blank_mode;
1652 DPRINTK("ENTER, blank mode = %d\n", blank_mode);
1654 if (info->state != FBINFO_STATE_RUNNING ||
1655 current_mode == blank_mode) {
1656 DPRINTK("EXIT, returning 0\n");
1657 return 0;
1660 /* Undo current */
1661 if (current_mode == FB_BLANK_NORMAL ||
1662 current_mode == FB_BLANK_UNBLANK) {
1663 /* unblank the screen */
1664 val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1665 /* clear "FullBandwidth" bit */
1666 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val & 0xdf);
1667 /* and undo VESA suspend trickery */
1668 vga_wgfx(cinfo->regbase, CL_GRE, 0x00);
1671 /* set new */
1672 if (blank_mode > FB_BLANK_NORMAL) {
1673 /* blank the screen */
1674 val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1675 /* set "FullBandwidth" bit */
1676 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val | 0x20);
1679 switch (blank_mode) {
1680 case FB_BLANK_UNBLANK:
1681 case FB_BLANK_NORMAL:
1682 break;
1683 case FB_BLANK_VSYNC_SUSPEND:
1684 vga_wgfx(cinfo->regbase, CL_GRE, 0x04);
1685 break;
1686 case FB_BLANK_HSYNC_SUSPEND:
1687 vga_wgfx(cinfo->regbase, CL_GRE, 0x02);
1688 break;
1689 case FB_BLANK_POWERDOWN:
1690 vga_wgfx(cinfo->regbase, CL_GRE, 0x06);
1691 break;
1692 default:
1693 DPRINTK("EXIT, returning 1\n");
1694 return 1;
1697 cinfo->blank_mode = blank_mode;
1698 DPRINTK("EXIT, returning 0\n");
1700 /* Let fbcon do a soft blank for us */
1701 return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
1703 /**** END Hardware specific Routines **************************************/
1704 /****************************************************************************/
1705 /**** BEGIN Internal Routines ***********************************************/
1707 static void init_vgachip(struct fb_info *info)
1709 struct cirrusfb_info *cinfo = info->par;
1710 const struct cirrusfb_board_info_rec *bi;
1712 DPRINTK("ENTER\n");
1714 assert(cinfo != NULL);
1716 bi = &cirrusfb_board_info[cinfo->btype];
1718 /* reset board globally */
1719 switch (cinfo->btype) {
1720 case BT_PICCOLO:
1721 WSFR(cinfo, 0x01);
1722 udelay(500);
1723 WSFR(cinfo, 0x51);
1724 udelay(500);
1725 break;
1726 case BT_PICASSO:
1727 WSFR2(cinfo, 0xff);
1728 udelay(500);
1729 break;
1730 case BT_SD64:
1731 case BT_SPECTRUM:
1732 WSFR(cinfo, 0x1f);
1733 udelay(500);
1734 WSFR(cinfo, 0x4f);
1735 udelay(500);
1736 break;
1737 case BT_PICASSO4:
1738 /* disable flickerfixer */
1739 vga_wcrt(cinfo->regbase, CL_CRT51, 0x00);
1740 mdelay(100);
1741 /* from Klaus' NetBSD driver: */
1742 vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
1743 /* put blitter into 542x compat */
1744 vga_wgfx(cinfo->regbase, CL_GR33, 0x00);
1745 /* mode */
1746 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1747 break;
1749 case BT_GD5480:
1750 /* from Klaus' NetBSD driver: */
1751 vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
1752 break;
1754 case BT_ALPINE:
1755 /* Nothing to do to reset the board. */
1756 break;
1758 default:
1759 printk(KERN_ERR "cirrusfb: Warning: Unknown board type\n");
1760 break;
1763 /* make sure RAM size set by this point */
1764 assert(info->screen_size > 0);
1766 /* the P4 is not fully initialized here; I rely on it having been */
1767 /* inited under AmigaOS already, which seems to work just fine */
1768 /* (Klaus advised to do it this way) */
1770 if (cinfo->btype != BT_PICASSO4) {
1771 WGen(cinfo, CL_VSSM, 0x10); /* EGS: 0x16 */
1772 WGen(cinfo, CL_POS102, 0x01);
1773 WGen(cinfo, CL_VSSM, 0x08); /* EGS: 0x0e */
1775 if (cinfo->btype != BT_SD64)
1776 WGen(cinfo, CL_VSSM2, 0x01);
1778 /* reset sequencer logic */
1779 vga_wseq(cinfo->regbase, CL_SEQR0, 0x03);
1781 /* FullBandwidth (video off) and 8/9 dot clock */
1782 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21);
1783 /* polarity (-/-), disable access to display memory,
1784 * VGA_CRTC_START_HI base address: color
1786 WGen(cinfo, VGA_MIS_W, 0xc1);
1788 /* "magic cookie" - doesn't make any sense to me.. */
1789 /* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */
1790 /* unlock all extension registers */
1791 vga_wseq(cinfo->regbase, CL_SEQR6, 0x12);
1793 /* reset blitter */
1794 vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
1796 switch (cinfo->btype) {
1797 case BT_GD5480:
1798 vga_wseq(cinfo->regbase, CL_SEQRF, 0x98);
1799 break;
1800 case BT_ALPINE:
1801 break;
1802 case BT_SD64:
1803 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8);
1804 break;
1805 default:
1806 vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f);
1807 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb0);
1808 break;
1811 /* plane mask: nothing */
1812 vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1813 /* character map select: doesn't even matter in gx mode */
1814 vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00);
1815 /* memory mode: chain-4, no odd/even, ext. memory */
1816 vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0e);
1818 /* controller-internal base address of video memory */
1819 if (bi->init_sr07)
1820 vga_wseq(cinfo->regbase, CL_SEQR7, bi->sr07);
1822 /* vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */
1823 /* EEPROM control: shouldn't be necessary to write to this at all.. */
1825 /* graphics cursor X position (incomplete; position gives rem. 3 bits */
1826 vga_wseq(cinfo->regbase, CL_SEQR10, 0x00);
1827 /* graphics cursor Y position (..."... ) */
1828 vga_wseq(cinfo->regbase, CL_SEQR11, 0x00);
1829 /* graphics cursor attributes */
1830 vga_wseq(cinfo->regbase, CL_SEQR12, 0x00);
1831 /* graphics cursor pattern address */
1832 vga_wseq(cinfo->regbase, CL_SEQR13, 0x00);
1834 /* writing these on a P4 might give problems.. */
1835 if (cinfo->btype != BT_PICASSO4) {
1836 /* configuration readback and ext. color */
1837 vga_wseq(cinfo->regbase, CL_SEQR17, 0x00);
1838 /* signature generator */
1839 vga_wseq(cinfo->regbase, CL_SEQR18, 0x02);
1842 /* MCLK select etc. */
1843 if (bi->init_sr1f)
1844 vga_wseq(cinfo->regbase, CL_SEQR1F, bi->sr1f);
1846 /* Screen A preset row scan: none */
1847 vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00);
1848 /* Text cursor start: disable text cursor */
1849 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20);
1850 /* Text cursor end: - */
1851 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00);
1852 /* Screen start address high: 0 */
1853 vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, 0x00);
1854 /* Screen start address low: 0 */
1855 vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, 0x00);
1856 /* text cursor location high: 0 */
1857 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00);
1858 /* text cursor location low: 0 */
1859 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00);
1861 /* Underline Row scanline: - */
1862 vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00);
1863 /* mode control: timing enable, byte mode, no compat modes */
1864 vga_wcrt(cinfo->regbase, VGA_CRTC_MODE, 0xc3);
1865 /* Line Compare: not needed */
1866 vga_wcrt(cinfo->regbase, VGA_CRTC_LINE_COMPARE, 0x00);
1867 /* ### add 0x40 for text modes with > 30 MHz pixclock */
1868 /* ext. display controls: ext.adr. wrap */
1869 vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02);
1871 /* Set/Reset registes: - */
1872 vga_wgfx(cinfo->regbase, VGA_GFX_SR_VALUE, 0x00);
1873 /* Set/Reset enable: - */
1874 vga_wgfx(cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00);
1875 /* Color Compare: - */
1876 vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00);
1877 /* Data Rotate: - */
1878 vga_wgfx(cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00);
1879 /* Read Map Select: - */
1880 vga_wgfx(cinfo->regbase, VGA_GFX_PLANE_READ, 0x00);
1881 /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
1882 vga_wgfx(cinfo->regbase, VGA_GFX_MODE, 0x00);
1883 /* Miscellaneous: memory map base address, graphics mode */
1884 vga_wgfx(cinfo->regbase, VGA_GFX_MISC, 0x01);
1885 /* Color Don't care: involve all planes */
1886 vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f);
1887 /* Bit Mask: no mask at all */
1888 vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff);
1889 if (cinfo->btype == BT_ALPINE)
1890 /* (5434 can't have bit 3 set for bitblt) */
1891 vga_wgfx(cinfo->regbase, CL_GRB, 0x20);
1892 else
1893 /* Graphics controller mode extensions: finer granularity,
1894 * 8byte data latches
1896 vga_wgfx(cinfo->regbase, CL_GRB, 0x28);
1898 vga_wgfx(cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */
1899 vga_wgfx(cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */
1900 vga_wgfx(cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */
1901 /* Background color byte 1: - */
1902 /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); */
1903 /* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
1905 /* Attribute Controller palette registers: "identity mapping" */
1906 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE0, 0x00);
1907 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
1908 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
1909 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
1910 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
1911 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
1912 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
1913 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
1914 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
1915 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
1916 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
1917 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
1918 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
1919 vga_wattr(cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
1920 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
1921 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
1923 /* Attribute Controller mode: graphics mode */
1924 vga_wattr(cinfo->regbase, VGA_ATC_MODE, 0x01);
1925 /* Overscan color reg.: reg. 0 */
1926 vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00);
1927 /* Color Plane enable: Enable all 4 planes */
1928 vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f);
1929 /* ### vga_wattr(cinfo->regbase, CL_AR33, 0x00); * Pixel Panning: - */
1930 /* Color Select: - */
1931 vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00);
1933 WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
1935 if (cinfo->btype != BT_ALPINE && cinfo->btype != BT_GD5480)
1936 /* polarity (-/-), enable display mem,
1937 * VGA_CRTC_START_HI i/o base = color
1939 WGen(cinfo, VGA_MIS_W, 0xc3);
1941 /* BLT Start/status: Blitter reset */
1942 vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
1943 /* - " - : "end-of-reset" */
1944 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1946 /* misc... */
1947 WHDR(cinfo, 0); /* Hidden DAC register: - */
1949 DPRINTK("EXIT\n");
1950 return;
1953 static void switch_monitor(struct cirrusfb_info *cinfo, int on)
1955 #ifdef CONFIG_ZORRO /* only works on Zorro boards */
1956 static int IsOn = 0; /* XXX not ok for multiple boards */
1958 DPRINTK("ENTER\n");
1960 if (cinfo->btype == BT_PICASSO4)
1961 return; /* nothing to switch */
1962 if (cinfo->btype == BT_ALPINE)
1963 return; /* nothing to switch */
1964 if (cinfo->btype == BT_GD5480)
1965 return; /* nothing to switch */
1966 if (cinfo->btype == BT_PICASSO) {
1967 if ((on && !IsOn) || (!on && IsOn))
1968 WSFR(cinfo, 0xff);
1970 DPRINTK("EXIT\n");
1971 return;
1973 if (on) {
1974 switch (cinfo->btype) {
1975 case BT_SD64:
1976 WSFR(cinfo, cinfo->SFR | 0x21);
1977 break;
1978 case BT_PICCOLO:
1979 WSFR(cinfo, cinfo->SFR | 0x28);
1980 break;
1981 case BT_SPECTRUM:
1982 WSFR(cinfo, 0x6f);
1983 break;
1984 default: /* do nothing */ break;
1986 } else {
1987 switch (cinfo->btype) {
1988 case BT_SD64:
1989 WSFR(cinfo, cinfo->SFR & 0xde);
1990 break;
1991 case BT_PICCOLO:
1992 WSFR(cinfo, cinfo->SFR & 0xd7);
1993 break;
1994 case BT_SPECTRUM:
1995 WSFR(cinfo, 0x4f);
1996 break;
1997 default: /* do nothing */ break;
2001 DPRINTK("EXIT\n");
2002 #endif /* CONFIG_ZORRO */
2005 /******************************************/
2006 /* Linux 2.6-style accelerated functions */
2007 /******************************************/
2009 static void cirrusfb_fillrect(struct fb_info *info,
2010 const struct fb_fillrect *region)
2012 struct fb_fillrect modded;
2013 int vxres, vyres;
2014 struct cirrusfb_info *cinfo = info->par;
2015 int m = info->var.bits_per_pixel;
2016 u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
2017 cinfo->pseudo_palette[region->color] : region->color;
2019 if (info->state != FBINFO_STATE_RUNNING)
2020 return;
2021 if (info->flags & FBINFO_HWACCEL_DISABLED) {
2022 cfb_fillrect(info, region);
2023 return;
2026 vxres = info->var.xres_virtual;
2027 vyres = info->var.yres_virtual;
2029 memcpy(&modded, region, sizeof(struct fb_fillrect));
2031 if (!modded.width || !modded.height ||
2032 modded.dx >= vxres || modded.dy >= vyres)
2033 return;
2035 if (modded.dx + modded.width > vxres)
2036 modded.width = vxres - modded.dx;
2037 if (modded.dy + modded.height > vyres)
2038 modded.height = vyres - modded.dy;
2040 cirrusfb_RectFill(cinfo->regbase,
2041 info->var.bits_per_pixel,
2042 (region->dx * m) / 8, region->dy,
2043 (region->width * m) / 8, region->height,
2044 color,
2045 info->fix.line_length);
2048 static void cirrusfb_copyarea(struct fb_info *info,
2049 const struct fb_copyarea *area)
2051 struct fb_copyarea modded;
2052 u32 vxres, vyres;
2053 struct cirrusfb_info *cinfo = info->par;
2054 int m = info->var.bits_per_pixel;
2056 if (info->state != FBINFO_STATE_RUNNING)
2057 return;
2058 if (info->flags & FBINFO_HWACCEL_DISABLED) {
2059 cfb_copyarea(info, area);
2060 return;
2063 vxres = info->var.xres_virtual;
2064 vyres = info->var.yres_virtual;
2065 memcpy(&modded, area, sizeof(struct fb_copyarea));
2067 if (!modded.width || !modded.height ||
2068 modded.sx >= vxres || modded.sy >= vyres ||
2069 modded.dx >= vxres || modded.dy >= vyres)
2070 return;
2072 if (modded.sx + modded.width > vxres)
2073 modded.width = vxres - modded.sx;
2074 if (modded.dx + modded.width > vxres)
2075 modded.width = vxres - modded.dx;
2076 if (modded.sy + modded.height > vyres)
2077 modded.height = vyres - modded.sy;
2078 if (modded.dy + modded.height > vyres)
2079 modded.height = vyres - modded.dy;
2081 cirrusfb_BitBLT(cinfo->regbase, info->var.bits_per_pixel,
2082 (area->sx * m) / 8, area->sy,
2083 (area->dx * m) / 8, area->dy,
2084 (area->width * m) / 8, area->height,
2085 info->fix.line_length);
2089 static void cirrusfb_imageblit(struct fb_info *info,
2090 const struct fb_image *image)
2092 struct cirrusfb_info *cinfo = info->par;
2094 cirrusfb_WaitBLT(cinfo->regbase);
2095 cfb_imageblit(info, image);
2098 #ifdef CONFIG_PPC_PREP
2099 #define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
2100 #define PREP_IO_BASE ((volatile unsigned char *) 0x80000000)
2101 static void get_prep_addrs(unsigned long *display, unsigned long *registers)
2103 DPRINTK("ENTER\n");
2105 *display = PREP_VIDEO_BASE;
2106 *registers = (unsigned long) PREP_IO_BASE;
2108 DPRINTK("EXIT\n");
2111 #endif /* CONFIG_PPC_PREP */
2113 #ifdef CONFIG_PCI
2114 static int release_io_ports;
2116 /* Pulled the logic from XFree86 Cirrus driver to get the memory size,
2117 * based on the DRAM bandwidth bit and DRAM bank switching bit. This
2118 * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
2119 * seem to have. */
2120 static unsigned int cirrusfb_get_memsize(u8 __iomem *regbase)
2122 unsigned long mem;
2123 unsigned char SRF;
2125 DPRINTK("ENTER\n");
2127 SRF = vga_rseq(regbase, CL_SEQRF);
2128 switch ((SRF & 0x18)) {
2129 case 0x08:
2130 mem = 512 * 1024;
2131 break;
2132 case 0x10:
2133 mem = 1024 * 1024;
2134 break;
2135 /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory
2136 * on the 5430.
2138 case 0x18:
2139 mem = 2048 * 1024;
2140 break;
2141 default:
2142 printk(KERN_WARNING "CLgenfb: Unknown memory size!\n");
2143 mem = 1024 * 1024;
2145 if (SRF & 0x80)
2146 /* If DRAM bank switching is enabled, there must be twice as much
2147 * memory installed. (4MB on the 5434)
2149 mem *= 2;
2151 /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
2153 DPRINTK("EXIT\n");
2154 return mem;
2157 static void get_pci_addrs(const struct pci_dev *pdev,
2158 unsigned long *display, unsigned long *registers)
2160 assert(pdev != NULL);
2161 assert(display != NULL);
2162 assert(registers != NULL);
2164 DPRINTK("ENTER\n");
2166 *display = 0;
2167 *registers = 0;
2169 /* This is a best-guess for now */
2171 if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
2172 *display = pci_resource_start(pdev, 1);
2173 *registers = pci_resource_start(pdev, 0);
2174 } else {
2175 *display = pci_resource_start(pdev, 0);
2176 *registers = pci_resource_start(pdev, 1);
2179 assert(*display != 0);
2181 DPRINTK("EXIT\n");
2184 static void cirrusfb_pci_unmap(struct fb_info *info)
2186 struct cirrusfb_info *cinfo = info->par;
2187 struct pci_dev *pdev = cinfo->pdev;
2189 iounmap(info->screen_base);
2190 #if 0 /* if system didn't claim this region, we would... */
2191 release_mem_region(0xA0000, 65535);
2192 #endif
2193 if (release_io_ports)
2194 release_region(0x3C0, 32);
2195 pci_release_regions(pdev);
2197 #endif /* CONFIG_PCI */
2199 #ifdef CONFIG_ZORRO
2200 static void __devexit cirrusfb_zorro_unmap(struct fb_info *info)
2202 struct cirrusfb_info *cinfo = info->par;
2203 zorro_release_device(cinfo->zdev);
2205 if (cinfo->btype == BT_PICASSO4) {
2206 cinfo->regbase -= 0x600000;
2207 iounmap((void *)cinfo->regbase);
2208 iounmap(info->screen_base);
2209 } else {
2210 if (zorro_resource_start(cinfo->zdev) > 0x01000000)
2211 iounmap(info->screen_base);
2214 #endif /* CONFIG_ZORRO */
2216 static int cirrusfb_set_fbinfo(struct fb_info *info)
2218 struct cirrusfb_info *cinfo = info->par;
2219 struct fb_var_screeninfo *var = &info->var;
2221 info->pseudo_palette = cinfo->pseudo_palette;
2222 info->flags = FBINFO_DEFAULT
2223 | FBINFO_HWACCEL_XPAN
2224 | FBINFO_HWACCEL_YPAN
2225 | FBINFO_HWACCEL_FILLRECT
2226 | FBINFO_HWACCEL_COPYAREA;
2227 if (noaccel)
2228 info->flags |= FBINFO_HWACCEL_DISABLED;
2229 info->fbops = &cirrusfb_ops;
2230 if (cinfo->btype == BT_GD5480) {
2231 if (var->bits_per_pixel == 16)
2232 info->screen_base += 1 * MB_;
2233 if (var->bits_per_pixel == 32)
2234 info->screen_base += 2 * MB_;
2237 /* Fill fix common fields */
2238 strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
2239 sizeof(info->fix.id));
2241 /* monochrome: only 1 memory plane */
2242 /* 8 bit and above: Use whole memory area */
2243 info->fix.smem_len = info->screen_size;
2244 if (var->bits_per_pixel == 1)
2245 info->fix.smem_len /= 4;
2246 info->fix.type_aux = 0;
2247 info->fix.xpanstep = 1;
2248 info->fix.ypanstep = 1;
2249 info->fix.ywrapstep = 0;
2251 /* FIXME: map region at 0xB8000 if available, fill in here */
2252 info->fix.mmio_len = 0;
2253 info->fix.accel = FB_ACCEL_NONE;
2255 fb_alloc_cmap(&info->cmap, 256, 0);
2257 return 0;
2260 static int cirrusfb_register(struct fb_info *info)
2262 struct cirrusfb_info *cinfo = info->par;
2263 int err;
2264 enum cirrus_board btype;
2266 DPRINTK("ENTER\n");
2268 printk(KERN_INFO "cirrusfb: Driver for Cirrus Logic based "
2269 "graphic boards, v" CIRRUSFB_VERSION "\n");
2271 btype = cinfo->btype;
2273 /* sanity checks */
2274 assert(btype != BT_NONE);
2276 DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base);
2278 /* Make pretend we've set the var so our structures are in a "good" */
2279 /* state, even though we haven't written the mode to the hw yet... */
2280 info->var = cirrusfb_predefined[cirrusfb_def_mode].var;
2281 info->var.activate = FB_ACTIVATE_NOW;
2283 err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
2284 if (err < 0) {
2285 /* should never happen */
2286 DPRINTK("choking on default var... umm, no good.\n");
2287 goto err_unmap_cirrusfb;
2290 /* set all the vital stuff */
2291 cirrusfb_set_fbinfo(info);
2293 err = register_framebuffer(info);
2294 if (err < 0) {
2295 printk(KERN_ERR "cirrusfb: could not register "
2296 "fb device; err = %d!\n", err);
2297 goto err_dealloc_cmap;
2300 DPRINTK("EXIT, returning 0\n");
2301 return 0;
2303 err_dealloc_cmap:
2304 fb_dealloc_cmap(&info->cmap);
2305 err_unmap_cirrusfb:
2306 cinfo->unmap(info);
2307 framebuffer_release(info);
2308 return err;
2311 static void __devexit cirrusfb_cleanup(struct fb_info *info)
2313 struct cirrusfb_info *cinfo = info->par;
2314 DPRINTK("ENTER\n");
2316 switch_monitor(cinfo, 0);
2318 unregister_framebuffer(info);
2319 fb_dealloc_cmap(&info->cmap);
2320 printk("Framebuffer unregistered\n");
2321 cinfo->unmap(info);
2322 framebuffer_release(info);
2324 DPRINTK("EXIT\n");
2327 #ifdef CONFIG_PCI
2328 static int cirrusfb_pci_register(struct pci_dev *pdev,
2329 const struct pci_device_id *ent)
2331 struct cirrusfb_info *cinfo;
2332 struct fb_info *info;
2333 enum cirrus_board btype;
2334 unsigned long board_addr, board_size;
2335 int ret;
2337 ret = pci_enable_device(pdev);
2338 if (ret < 0) {
2339 printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
2340 goto err_out;
2343 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev);
2344 if (!info) {
2345 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2346 ret = -ENOMEM;
2347 goto err_disable;
2350 cinfo = info->par;
2351 cinfo->pdev = pdev;
2352 cinfo->btype = btype = (enum cirrus_board) ent->driver_data;
2354 DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n",
2355 pdev->resource[0].start, btype);
2356 DPRINTK(" base address 1 is 0x%x\n", pdev->resource[1].start);
2358 if (isPReP) {
2359 pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, 0x00000000);
2360 #ifdef CONFIG_PPC_PREP
2361 get_prep_addrs(&board_addr, &info->fix.mmio_start);
2362 #endif
2363 /* PReP dies if we ioremap the IO registers, but it works w/out... */
2364 cinfo->regbase = (char __iomem *) info->fix.mmio_start;
2365 } else {
2366 DPRINTK("Attempt to get PCI info for Cirrus Graphics Card\n");
2367 get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start);
2368 /* FIXME: this forces VGA. alternatives? */
2369 cinfo->regbase = NULL;
2372 DPRINTK("Board address: 0x%lx, register address: 0x%lx\n",
2373 board_addr, info->fix.mmio_start);
2375 board_size = (btype == BT_GD5480) ?
2376 32 * MB_ : cirrusfb_get_memsize(cinfo->regbase);
2378 ret = pci_request_regions(pdev, "cirrusfb");
2379 if (ret < 0) {
2380 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, "
2381 "abort\n",
2382 board_addr);
2383 goto err_release_fb;
2385 #if 0 /* if the system didn't claim this region, we would... */
2386 if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
2387 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n"
2389 0xA0000L);
2390 ret = -EBUSY;
2391 goto err_release_regions;
2393 #endif
2394 if (request_region(0x3C0, 32, "cirrusfb"))
2395 release_io_ports = 1;
2397 info->screen_base = ioremap(board_addr, board_size);
2398 if (!info->screen_base) {
2399 ret = -EIO;
2400 goto err_release_legacy;
2403 info->fix.smem_start = board_addr;
2404 info->screen_size = board_size;
2405 cinfo->unmap = cirrusfb_pci_unmap;
2407 printk(KERN_INFO "RAM (%lu kB) at 0x%lx, Cirrus "
2408 "Logic chipset on PCI bus\n",
2409 info->screen_size >> 10, board_addr);
2410 pci_set_drvdata(pdev, info);
2412 ret = cirrusfb_register(info);
2413 if (ret)
2414 iounmap(info->screen_base);
2415 return ret;
2417 err_release_legacy:
2418 if (release_io_ports)
2419 release_region(0x3C0, 32);
2420 #if 0
2421 release_mem_region(0xA0000, 65535);
2422 err_release_regions:
2423 #endif
2424 pci_release_regions(pdev);
2425 err_release_fb:
2426 framebuffer_release(info);
2427 err_disable:
2428 err_out:
2429 return ret;
2432 static void __devexit cirrusfb_pci_unregister(struct pci_dev *pdev)
2434 struct fb_info *info = pci_get_drvdata(pdev);
2435 DPRINTK("ENTER\n");
2437 cirrusfb_cleanup(info);
2439 DPRINTK("EXIT\n");
2442 static struct pci_driver cirrusfb_pci_driver = {
2443 .name = "cirrusfb",
2444 .id_table = cirrusfb_pci_table,
2445 .probe = cirrusfb_pci_register,
2446 .remove = __devexit_p(cirrusfb_pci_unregister),
2447 #ifdef CONFIG_PM
2448 #if 0
2449 .suspend = cirrusfb_pci_suspend,
2450 .resume = cirrusfb_pci_resume,
2451 #endif
2452 #endif
2454 #endif /* CONFIG_PCI */
2456 #ifdef CONFIG_ZORRO
2457 static int cirrusfb_zorro_register(struct zorro_dev *z,
2458 const struct zorro_device_id *ent)
2460 struct cirrusfb_info *cinfo;
2461 struct fb_info *info;
2462 enum cirrus_board btype;
2463 struct zorro_dev *z2 = NULL;
2464 unsigned long board_addr, board_size, size;
2465 int ret;
2467 btype = ent->driver_data;
2468 if (cirrusfb_zorro_table2[btype].id2)
2469 z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
2470 size = cirrusfb_zorro_table2[btype].size;
2471 printk(KERN_INFO "cirrusfb: %s board detected; ",
2472 cirrusfb_board_info[btype].name);
2474 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
2475 if (!info) {
2476 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2477 ret = -ENOMEM;
2478 goto err_out;
2481 cinfo = info->par;
2482 cinfo->btype = btype;
2484 assert(z);
2485 assert(btype != BT_NONE);
2487 cinfo->zdev = z;
2488 board_addr = zorro_resource_start(z);
2489 board_size = zorro_resource_len(z);
2490 info->screen_size = size;
2492 if (!zorro_request_device(z, "cirrusfb")) {
2493 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, "
2494 "abort\n",
2495 board_addr);
2496 ret = -EBUSY;
2497 goto err_release_fb;
2500 printk(" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr);
2502 ret = -EIO;
2504 if (btype == BT_PICASSO4) {
2505 printk(KERN_INFO " REG at $%lx\n", board_addr + 0x600000);
2507 /* To be precise, for the P4 this is not the */
2508 /* begin of the board, but the begin of RAM. */
2509 /* for P4, map in its address space in 2 chunks (### TEST! ) */
2510 /* (note the ugly hardcoded 16M number) */
2511 cinfo->regbase = ioremap(board_addr, 16777216);
2512 if (!cinfo->regbase)
2513 goto err_release_region;
2515 DPRINTK("cirrusfb: Virtual address for board set to: $%p\n",
2516 cinfo->regbase);
2517 cinfo->regbase += 0x600000;
2518 info->fix.mmio_start = board_addr + 0x600000;
2520 info->fix.smem_start = board_addr + 16777216;
2521 info->screen_base = ioremap(info->fix.smem_start, 16777216);
2522 if (!info->screen_base)
2523 goto err_unmap_regbase;
2524 } else {
2525 printk(KERN_INFO " REG at $%lx\n",
2526 (unsigned long) z2->resource.start);
2528 info->fix.smem_start = board_addr;
2529 if (board_addr > 0x01000000)
2530 info->screen_base = ioremap(board_addr, board_size);
2531 else
2532 info->screen_base = (caddr_t) ZTWO_VADDR(board_addr);
2533 if (!info->screen_base)
2534 goto err_release_region;
2536 /* set address for REG area of board */
2537 cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start);
2538 info->fix.mmio_start = z2->resource.start;
2540 DPRINTK("cirrusfb: Virtual address for board set to: $%p\n",
2541 cinfo->regbase);
2543 cinfo->unmap = cirrusfb_zorro_unmap;
2545 printk(KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
2546 zorro_set_drvdata(z, info);
2548 ret = cirrusfb_register(info);
2549 if (ret) {
2550 if (btype == BT_PICASSO4) {
2551 iounmap(info->screen_base);
2552 iounmap(cinfo->regbase - 0x600000);
2553 } else if (board_addr > 0x01000000)
2554 iounmap(info->screen_base);
2556 return ret;
2558 err_unmap_regbase:
2559 /* Parental advisory: explicit hack */
2560 iounmap(cinfo->regbase - 0x600000);
2561 err_release_region:
2562 release_region(board_addr, board_size);
2563 err_release_fb:
2564 framebuffer_release(info);
2565 err_out:
2566 return ret;
2569 void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
2571 struct fb_info *info = zorro_get_drvdata(z);
2572 DPRINTK("ENTER\n");
2574 cirrusfb_cleanup(info);
2576 DPRINTK("EXIT\n");
2579 static struct zorro_driver cirrusfb_zorro_driver = {
2580 .name = "cirrusfb",
2581 .id_table = cirrusfb_zorro_table,
2582 .probe = cirrusfb_zorro_register,
2583 .remove = __devexit_p(cirrusfb_zorro_unregister),
2585 #endif /* CONFIG_ZORRO */
2587 static int __init cirrusfb_init(void)
2589 int error = 0;
2591 #ifndef MODULE
2592 char *option = NULL;
2594 if (fb_get_options("cirrusfb", &option))
2595 return -ENODEV;
2596 cirrusfb_setup(option);
2597 #endif
2599 #ifdef CONFIG_ZORRO
2600 error |= zorro_register_driver(&cirrusfb_zorro_driver);
2601 #endif
2602 #ifdef CONFIG_PCI
2603 error |= pci_register_driver(&cirrusfb_pci_driver);
2604 #endif
2605 return error;
2608 #ifndef MODULE
2609 static int __init cirrusfb_setup(char *options) {
2610 char *this_opt, s[32];
2611 int i;
2613 DPRINTK("ENTER\n");
2615 if (!options || !*options)
2616 return 0;
2618 while ((this_opt = strsep(&options, ",")) != NULL) {
2619 if (!*this_opt) continue;
2621 DPRINTK("cirrusfb_setup: option '%s'\n", this_opt);
2623 for (i = 0; i < NUM_TOTAL_MODES; i++) {
2624 sprintf(s, "mode:%s", cirrusfb_predefined[i].name);
2625 if (strcmp(this_opt, s) == 0)
2626 cirrusfb_def_mode = i;
2628 if (!strcmp(this_opt, "noaccel"))
2629 noaccel = 1;
2631 return 0;
2633 #endif
2636 * Modularization
2639 MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
2640 MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
2641 MODULE_LICENSE("GPL");
2643 static void __exit cirrusfb_exit(void)
2645 #ifdef CONFIG_PCI
2646 pci_unregister_driver(&cirrusfb_pci_driver);
2647 #endif
2648 #ifdef CONFIG_ZORRO
2649 zorro_unregister_driver(&cirrusfb_zorro_driver);
2650 #endif
2653 module_init(cirrusfb_init);
2655 #ifdef MODULE
2656 module_exit(cirrusfb_exit);
2657 #endif
2659 /**********************************************************************/
2660 /* about the following functions - I have used the same names for the */
2661 /* functions as Markus Wild did in his Retina driver for NetBSD as */
2662 /* they just made sense for this purpose. Apart from that, I wrote */
2663 /* these functions myself. */
2664 /**********************************************************************/
2666 /*** WGen() - write into one of the external/general registers ***/
2667 static void WGen(const struct cirrusfb_info *cinfo,
2668 int regnum, unsigned char val)
2670 unsigned long regofs = 0;
2672 if (cinfo->btype == BT_PICASSO) {
2673 /* Picasso II specific hack */
2674 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2675 regnum == CL_VSSM2) */
2676 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2677 regofs = 0xfff;
2680 vga_w(cinfo->regbase, regofs + regnum, val);
2683 /*** RGen() - read out one of the external/general registers ***/
2684 static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum)
2686 unsigned long regofs = 0;
2688 if (cinfo->btype == BT_PICASSO) {
2689 /* Picasso II specific hack */
2690 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2691 regnum == CL_VSSM2) */
2692 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2693 regofs = 0xfff;
2696 return vga_r(cinfo->regbase, regofs + regnum);
2699 /*** AttrOn() - turn on VideoEnable for Attribute controller ***/
2700 static void AttrOn(const struct cirrusfb_info *cinfo)
2702 assert(cinfo != NULL);
2704 DPRINTK("ENTER\n");
2706 if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) {
2707 /* if we're just in "write value" mode, write back the */
2708 /* same value as before to not modify anything */
2709 vga_w(cinfo->regbase, VGA_ATT_IW,
2710 vga_r(cinfo->regbase, VGA_ATT_R));
2712 /* turn on video bit */
2713 /* vga_w(cinfo->regbase, VGA_ATT_IW, 0x20); */
2714 vga_w(cinfo->regbase, VGA_ATT_IW, 0x33);
2716 /* dummy write on Reg0 to be on "write index" mode next time */
2717 vga_w(cinfo->regbase, VGA_ATT_IW, 0x00);
2719 DPRINTK("EXIT\n");
2722 /*** WHDR() - write into the Hidden DAC register ***/
2723 /* as the HDR is the only extension register that requires special treatment
2724 * (the other extension registers are accessible just like the "ordinary"
2725 * registers of their functional group) here is a specialized routine for
2726 * accessing the HDR
2728 static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val)
2730 unsigned char dummy;
2732 if (cinfo->btype == BT_PICASSO) {
2733 /* Klaus' hint for correct access to HDR on some boards */
2734 /* first write 0 to pixel mask (3c6) */
2735 WGen(cinfo, VGA_PEL_MSK, 0x00);
2736 udelay(200);
2737 /* next read dummy from pixel address (3c8) */
2738 dummy = RGen(cinfo, VGA_PEL_IW);
2739 udelay(200);
2741 /* now do the usual stuff to access the HDR */
2743 dummy = RGen(cinfo, VGA_PEL_MSK);
2744 udelay(200);
2745 dummy = RGen(cinfo, VGA_PEL_MSK);
2746 udelay(200);
2747 dummy = RGen(cinfo, VGA_PEL_MSK);
2748 udelay(200);
2749 dummy = RGen(cinfo, VGA_PEL_MSK);
2750 udelay(200);
2752 WGen(cinfo, VGA_PEL_MSK, val);
2753 udelay(200);
2755 if (cinfo->btype == BT_PICASSO) {
2756 /* now first reset HDR access counter */
2757 dummy = RGen(cinfo, VGA_PEL_IW);
2758 udelay(200);
2760 /* and at the end, restore the mask value */
2761 /* ## is this mask always 0xff? */
2762 WGen(cinfo, VGA_PEL_MSK, 0xff);
2763 udelay(200);
2767 /*** WSFR() - write to the "special function register" (SFR) ***/
2768 static void WSFR(struct cirrusfb_info *cinfo, unsigned char val)
2770 #ifdef CONFIG_ZORRO
2771 assert(cinfo->regbase != NULL);
2772 cinfo->SFR = val;
2773 z_writeb(val, cinfo->regbase + 0x8000);
2774 #endif
2777 /* The Picasso has a second register for switching the monitor bit */
2778 static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val)
2780 #ifdef CONFIG_ZORRO
2781 /* writing an arbitrary value to this one causes the monitor switcher */
2782 /* to flip to Amiga display */
2783 assert(cinfo->regbase != NULL);
2784 cinfo->SFR = val;
2785 z_writeb(val, cinfo->regbase + 0x9000);
2786 #endif
2789 /*** WClut - set CLUT entry (range: 0..63) ***/
2790 static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
2791 unsigned char green, unsigned char blue)
2793 unsigned int data = VGA_PEL_D;
2795 /* address write mode register is not translated.. */
2796 vga_w(cinfo->regbase, VGA_PEL_IW, regnum);
2798 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2799 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2800 /* but DAC data register IS, at least for Picasso II */
2801 if (cinfo->btype == BT_PICASSO)
2802 data += 0xfff;
2803 vga_w(cinfo->regbase, data, red);
2804 vga_w(cinfo->regbase, data, green);
2805 vga_w(cinfo->regbase, data, blue);
2806 } else {
2807 vga_w(cinfo->regbase, data, blue);
2808 vga_w(cinfo->regbase, data, green);
2809 vga_w(cinfo->regbase, data, red);
2813 #if 0
2814 /*** RClut - read CLUT entry (range 0..63) ***/
2815 static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
2816 unsigned char *green, unsigned char *blue)
2818 unsigned int data = VGA_PEL_D;
2820 vga_w(cinfo->regbase, VGA_PEL_IR, regnum);
2822 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2823 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2824 if (cinfo->btype == BT_PICASSO)
2825 data += 0xfff;
2826 *red = vga_r(cinfo->regbase, data);
2827 *green = vga_r(cinfo->regbase, data);
2828 *blue = vga_r(cinfo->regbase, data);
2829 } else {
2830 *blue = vga_r(cinfo->regbase, data);
2831 *green = vga_r(cinfo->regbase, data);
2832 *red = vga_r(cinfo->regbase, data);
2835 #endif
2837 /*******************************************************************
2838 cirrusfb_WaitBLT()
2840 Wait for the BitBLT engine to complete a possible earlier job
2841 *********************************************************************/
2843 /* FIXME: use interrupts instead */
2844 static void cirrusfb_WaitBLT(u8 __iomem *regbase)
2846 /* now busy-wait until we're done */
2847 while (vga_rgfx(regbase, CL_GR31) & 0x08)
2848 /* do nothing */ ;
2851 /*******************************************************************
2852 cirrusfb_BitBLT()
2854 perform accelerated "scrolling"
2855 ********************************************************************/
2857 static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
2858 u_short curx, u_short cury,
2859 u_short destx, u_short desty,
2860 u_short width, u_short height,
2861 u_short line_length)
2863 u_short nwidth, nheight;
2864 u_long nsrc, ndest;
2865 u_char bltmode;
2867 DPRINTK("ENTER\n");
2869 nwidth = width - 1;
2870 nheight = height - 1;
2872 bltmode = 0x00;
2873 /* if source adr < dest addr, do the Blt backwards */
2874 if (cury <= desty) {
2875 if (cury == desty) {
2876 /* if src and dest are on the same line, check x */
2877 if (curx < destx)
2878 bltmode |= 0x01;
2879 } else
2880 bltmode |= 0x01;
2882 if (!bltmode) {
2883 /* standard case: forward blitting */
2884 nsrc = (cury * line_length) + curx;
2885 ndest = (desty * line_length) + destx;
2886 } else {
2887 /* this means start addresses are at the end,
2888 * counting backwards
2890 nsrc = cury * line_length + curx +
2891 nheight * line_length + nwidth;
2892 ndest = desty * line_length + destx +
2893 nheight * line_length + nwidth;
2897 run-down of registers to be programmed:
2898 destination pitch
2899 source pitch
2900 BLT width/height
2901 source start
2902 destination start
2903 BLT mode
2904 BLT ROP
2905 VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color"
2906 start/stop
2909 cirrusfb_WaitBLT(regbase);
2911 /* pitch: set to line_length */
2912 /* dest pitch low */
2913 vga_wgfx(regbase, CL_GR24, line_length & 0xff);
2914 /* dest pitch hi */
2915 vga_wgfx(regbase, CL_GR25, line_length >> 8);
2916 /* source pitch low */
2917 vga_wgfx(regbase, CL_GR26, line_length & 0xff);
2918 /* source pitch hi */
2919 vga_wgfx(regbase, CL_GR27, line_length >> 8);
2921 /* BLT width: actual number of pixels - 1 */
2922 /* BLT width low */
2923 vga_wgfx(regbase, CL_GR20, nwidth & 0xff);
2924 /* BLT width hi */
2925 vga_wgfx(regbase, CL_GR21, nwidth >> 8);
2927 /* BLT height: actual number of lines -1 */
2928 /* BLT height low */
2929 vga_wgfx(regbase, CL_GR22, nheight & 0xff);
2930 /* BLT width hi */
2931 vga_wgfx(regbase, CL_GR23, nheight >> 8);
2933 /* BLT destination */
2934 /* BLT dest low */
2935 vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
2936 /* BLT dest mid */
2937 vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
2938 /* BLT dest hi */
2939 vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
2941 /* BLT source */
2942 /* BLT src low */
2943 vga_wgfx(regbase, CL_GR2C, (u_char) (nsrc & 0xff));
2944 /* BLT src mid */
2945 vga_wgfx(regbase, CL_GR2D, (u_char) (nsrc >> 8));
2946 /* BLT src hi */
2947 vga_wgfx(regbase, CL_GR2E, (u_char) (nsrc >> 16));
2949 /* BLT mode */
2950 vga_wgfx(regbase, CL_GR30, bltmode); /* BLT mode */
2952 /* BLT ROP: SrcCopy */
2953 vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */
2955 /* and finally: GO! */
2956 vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */
2958 DPRINTK("EXIT\n");
2961 /*******************************************************************
2962 cirrusfb_RectFill()
2964 perform accelerated rectangle fill
2965 ********************************************************************/
2967 static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
2968 u_short x, u_short y, u_short width, u_short height,
2969 u_char color, u_short line_length)
2971 u_short nwidth, nheight;
2972 u_long ndest;
2973 u_char op;
2975 DPRINTK("ENTER\n");
2977 nwidth = width - 1;
2978 nheight = height - 1;
2980 ndest = (y * line_length) + x;
2982 cirrusfb_WaitBLT(regbase);
2984 /* pitch: set to line_length */
2985 vga_wgfx(regbase, CL_GR24, line_length & 0xff); /* dest pitch low */
2986 vga_wgfx(regbase, CL_GR25, line_length >> 8); /* dest pitch hi */
2987 vga_wgfx(regbase, CL_GR26, line_length & 0xff); /* source pitch low */
2988 vga_wgfx(regbase, CL_GR27, line_length >> 8); /* source pitch hi */
2990 /* BLT width: actual number of pixels - 1 */
2991 vga_wgfx(regbase, CL_GR20, nwidth & 0xff); /* BLT width low */
2992 vga_wgfx(regbase, CL_GR21, nwidth >> 8); /* BLT width hi */
2994 /* BLT height: actual number of lines -1 */
2995 vga_wgfx(regbase, CL_GR22, nheight & 0xff); /* BLT height low */
2996 vga_wgfx(regbase, CL_GR23, nheight >> 8); /* BLT width hi */
2998 /* BLT destination */
2999 /* BLT dest low */
3000 vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
3001 /* BLT dest mid */
3002 vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
3003 /* BLT dest hi */
3004 vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
3006 /* BLT source: set to 0 (is a dummy here anyway) */
3007 vga_wgfx(regbase, CL_GR2C, 0x00); /* BLT src low */
3008 vga_wgfx(regbase, CL_GR2D, 0x00); /* BLT src mid */
3009 vga_wgfx(regbase, CL_GR2E, 0x00); /* BLT src hi */
3011 /* This is a ColorExpand Blt, using the */
3012 /* same color for foreground and background */
3013 vga_wgfx(regbase, VGA_GFX_SR_VALUE, color); /* foreground color */
3014 vga_wgfx(regbase, VGA_GFX_SR_ENABLE, color); /* background color */
3016 op = 0xc0;
3017 if (bits_per_pixel == 16) {
3018 vga_wgfx(regbase, CL_GR10, color); /* foreground color */
3019 vga_wgfx(regbase, CL_GR11, color); /* background color */
3020 op = 0x50;
3021 op = 0xd0;
3022 } else if (bits_per_pixel == 32) {
3023 vga_wgfx(regbase, CL_GR10, color); /* foreground color */
3024 vga_wgfx(regbase, CL_GR11, color); /* background color */
3025 vga_wgfx(regbase, CL_GR12, color); /* foreground color */
3026 vga_wgfx(regbase, CL_GR13, color); /* background color */
3027 vga_wgfx(regbase, CL_GR14, 0); /* foreground color */
3028 vga_wgfx(regbase, CL_GR15, 0); /* background color */
3029 op = 0x50;
3030 op = 0xf0;
3032 /* BLT mode: color expand, Enable 8x8 copy (faster?) */
3033 vga_wgfx(regbase, CL_GR30, op); /* BLT mode */
3035 /* BLT ROP: SrcCopy */
3036 vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */
3038 /* and finally: GO! */
3039 vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */
3041 DPRINTK("EXIT\n");
3044 /**************************************************************************
3045 * bestclock() - determine closest possible clock lower(?) than the
3046 * desired pixel clock
3047 **************************************************************************/
3048 static void bestclock(long freq, long *best, long *nom,
3049 long *den, long *div, long maxfreq)
3051 long n, h, d, f;
3053 assert(best != NULL);
3054 assert(nom != NULL);
3055 assert(den != NULL);
3056 assert(div != NULL);
3057 assert(maxfreq > 0);
3059 *nom = 0;
3060 *den = 0;
3061 *div = 0;
3063 DPRINTK("ENTER\n");
3065 if (freq < 8000)
3066 freq = 8000;
3068 if (freq > maxfreq)
3069 freq = maxfreq;
3071 *best = 0;
3072 f = freq * 10;
3074 for (n = 32; n < 128; n++) {
3075 int s = 0;
3077 d = (143181 * n) / f;
3078 if ((d >= 7) && (d <= 63)) {
3079 int temp = d;
3081 if (temp > 31) {
3082 s = 1;
3083 temp >>= 1;
3085 h = ((14318 * n) / temp) >> s;
3086 if (abs(h - freq) < abs(*best - freq)) {
3087 *best = h;
3088 *nom = n;
3089 *den = temp;
3090 *div = s;
3093 d++;
3094 if ((d >= 7) && (d <= 63)) {
3095 if (d > 31) {
3096 s = 1;
3097 d >>= 1;
3099 h = ((14318 * n) / d) >> s;
3100 if (abs(h - freq) < abs(*best - freq)) {
3101 *best = h;
3102 *nom = n;
3103 *den = d;
3104 *div = s;
3109 DPRINTK("Best possible values for given frequency:\n");
3110 DPRINTK(" best: %ld kHz nom: %ld den: %ld div: %ld\n",
3111 freq, *nom, *den, *div);
3113 DPRINTK("EXIT\n");
3116 /* -------------------------------------------------------------------------
3118 * debugging functions
3120 * -------------------------------------------------------------------------
3123 #ifdef CIRRUSFB_DEBUG
3126 * cirrusfb_dbg_print_byte
3127 * @name: name associated with byte value to be displayed
3128 * @val: byte value to be displayed
3130 * DESCRIPTION:
3131 * Display an indented string, along with a hexidecimal byte value, and
3132 * its decoded bits. Bits 7 through 0 are listed in left-to-right
3133 * order.
3136 static
3137 void cirrusfb_dbg_print_byte(const char *name, unsigned char val)
3139 DPRINTK("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n",
3140 name, val,
3141 val & 0x80 ? '1' : '0',
3142 val & 0x40 ? '1' : '0',
3143 val & 0x20 ? '1' : '0',
3144 val & 0x10 ? '1' : '0',
3145 val & 0x08 ? '1' : '0',
3146 val & 0x04 ? '1' : '0',
3147 val & 0x02 ? '1' : '0',
3148 val & 0x01 ? '1' : '0');
3152 * cirrusfb_dbg_print_regs
3153 * @base: If using newmmio, the newmmio base address, otherwise %NULL
3154 * @reg_class: type of registers to read: %CRT, or %SEQ
3156 * DESCRIPTION:
3157 * Dumps the given list of VGA CRTC registers. If @base is %NULL,
3158 * old-style I/O ports are queried for information, otherwise MMIO is
3159 * used at the given @base address to query the information.
3162 static
3163 void cirrusfb_dbg_print_regs(caddr_t regbase,
3164 enum cirrusfb_dbg_reg_class reg_class, ...)
3166 va_list list;
3167 unsigned char val = 0;
3168 unsigned reg;
3169 char *name;
3171 va_start(list, reg_class);
3173 name = va_arg(list, char *);
3174 while (name != NULL) {
3175 reg = va_arg(list, int);
3177 switch (reg_class) {
3178 case CRT:
3179 val = vga_rcrt(regbase, (unsigned char) reg);
3180 break;
3181 case SEQ:
3182 val = vga_rseq(regbase, (unsigned char) reg);
3183 break;
3184 default:
3185 /* should never occur */
3186 assert(false);
3187 break;
3190 cirrusfb_dbg_print_byte(name, val);
3192 name = va_arg(list, char *);
3195 va_end(list);
3199 * cirrusfb_dump
3200 * @cirrusfbinfo:
3202 * DESCRIPTION:
3205 static void cirrusfb_dump(void)
3207 cirrusfb_dbg_reg_dump(NULL);
3211 * cirrusfb_dbg_reg_dump
3212 * @base: If using newmmio, the newmmio base address, otherwise %NULL
3214 * DESCRIPTION:
3215 * Dumps a list of interesting VGA and CIRRUSFB registers. If @base is %NULL,
3216 * old-style I/O ports are queried for information, otherwise MMIO is
3217 * used at the given @base address to query the information.
3220 static
3221 void cirrusfb_dbg_reg_dump(caddr_t regbase)
3223 DPRINTK("CIRRUSFB VGA CRTC register dump:\n");
3225 cirrusfb_dbg_print_regs(regbase, CRT,
3226 "CR00", 0x00,
3227 "CR01", 0x01,
3228 "CR02", 0x02,
3229 "CR03", 0x03,
3230 "CR04", 0x04,
3231 "CR05", 0x05,
3232 "CR06", 0x06,
3233 "CR07", 0x07,
3234 "CR08", 0x08,
3235 "CR09", 0x09,
3236 "CR0A", 0x0A,
3237 "CR0B", 0x0B,
3238 "CR0C", 0x0C,
3239 "CR0D", 0x0D,
3240 "CR0E", 0x0E,
3241 "CR0F", 0x0F,
3242 "CR10", 0x10,
3243 "CR11", 0x11,
3244 "CR12", 0x12,
3245 "CR13", 0x13,
3246 "CR14", 0x14,
3247 "CR15", 0x15,
3248 "CR16", 0x16,
3249 "CR17", 0x17,
3250 "CR18", 0x18,
3251 "CR22", 0x22,
3252 "CR24", 0x24,
3253 "CR26", 0x26,
3254 "CR2D", 0x2D,
3255 "CR2E", 0x2E,
3256 "CR2F", 0x2F,
3257 "CR30", 0x30,
3258 "CR31", 0x31,
3259 "CR32", 0x32,
3260 "CR33", 0x33,
3261 "CR34", 0x34,
3262 "CR35", 0x35,
3263 "CR36", 0x36,
3264 "CR37", 0x37,
3265 "CR38", 0x38,
3266 "CR39", 0x39,
3267 "CR3A", 0x3A,
3268 "CR3B", 0x3B,
3269 "CR3C", 0x3C,
3270 "CR3D", 0x3D,
3271 "CR3E", 0x3E,
3272 "CR3F", 0x3F,
3273 NULL);
3275 DPRINTK("\n");
3277 DPRINTK("CIRRUSFB VGA SEQ register dump:\n");
3279 cirrusfb_dbg_print_regs(regbase, SEQ,
3280 "SR00", 0x00,
3281 "SR01", 0x01,
3282 "SR02", 0x02,
3283 "SR03", 0x03,
3284 "SR04", 0x04,
3285 "SR08", 0x08,
3286 "SR09", 0x09,
3287 "SR0A", 0x0A,
3288 "SR0B", 0x0B,
3289 "SR0D", 0x0D,
3290 "SR10", 0x10,
3291 "SR11", 0x11,
3292 "SR12", 0x12,
3293 "SR13", 0x13,
3294 "SR14", 0x14,
3295 "SR15", 0x15,
3296 "SR16", 0x16,
3297 "SR17", 0x17,
3298 "SR18", 0x18,
3299 "SR19", 0x19,
3300 "SR1A", 0x1A,
3301 "SR1B", 0x1B,
3302 "SR1C", 0x1C,
3303 "SR1D", 0x1D,
3304 "SR1E", 0x1E,
3305 "SR1F", 0x1F,
3306 NULL);
3308 DPRINTK("\n");
3311 #endif /* CIRRUSFB_DEBUG */