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