cirrusfb: add noaccel module parameter
[safe/jmp/linux-2.6] / 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_DIRECTCOLOR;
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                         if (var->xres >= 1024)
1182                                 vga_wseq(regbase, CL_SEQR7, 0xa7);
1183                         else
1184                                 vga_wseq(regbase, CL_SEQR7, 0xa3);
1185                         cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
1186                         break;
1187
1188                 case BT_GD5480:
1189                         DPRINTK(" (for GD5480)\n");
1190                         vga_wseq(regbase, CL_SEQR7, 0x17);
1191                         /* We already set SRF and SR1F */
1192                         break;
1193
1194                 case BT_LAGUNA:
1195                         DPRINTK(" (for GD546x)\n");
1196                         vga_wseq(regbase, CL_SEQR7,
1197                                 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1198                         break;
1199
1200                 default:
1201                         printk(KERN_WARNING "CIRRUSFB: unknown Board\n");
1202                         break;
1203                 }
1204
1205                 /* mode register: 256 color mode */
1206                 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1207                 /* pixel mask: pass-through all planes */
1208                 WGen(cinfo, VGA_PEL_MSK, 0xff);
1209 #ifdef CONFIG_PCI
1210                 WHDR(cinfo, 0xc0);      /* Copy Xbh */
1211 #elif defined(CONFIG_ZORRO)
1212                 /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
1213                 WHDR(cinfo, 0xa0);      /* hidden dac reg: nothing special */
1214 #endif
1215                 /* memory mode: chain4, ext. memory */
1216                 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1217                 /* plane mask: enable writing to all 4 planes */
1218                 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1219                 offset = var->xres_virtual / 4;
1220         }
1221
1222         /******************************************************
1223          *
1224          * 32 bpp
1225          *
1226          */
1227
1228         else if (var->bits_per_pixel == 32) {
1229                 DPRINTK("cirrusfb: preparing for 32 bit deep display\n");
1230                 switch (cinfo->btype) {
1231                 case BT_SD64:
1232                         /* Extended Sequencer Mode: 256c col. mode */
1233                         vga_wseq(regbase, CL_SEQR7, 0xf9);
1234                         /* MCLK select */
1235                         vga_wseq(regbase, CL_SEQR1F, 0x1e);
1236                         break;
1237
1238                 case BT_PICCOLO:
1239                 case BT_SPECTRUM:
1240                         vga_wseq(regbase, CL_SEQR7, 0x85);
1241                         /* Fast Page-Mode writes */
1242                         vga_wseq(regbase, CL_SEQRF, 0xb0);
1243                         /* MCLK select */
1244                         vga_wseq(regbase, CL_SEQR1F, 0x22);
1245                         break;
1246
1247                 case BT_PICASSO:
1248                         vga_wseq(regbase, CL_SEQR7, 0x25);
1249                         /* Fast Page-Mode writes */
1250                         vga_wseq(regbase, CL_SEQRF, 0xb0);
1251                         /* MCLK select */
1252                         vga_wseq(regbase, CL_SEQR1F, 0x22);
1253                         break;
1254
1255                 case BT_PICASSO4:
1256                         vga_wseq(regbase, CL_SEQR7, 0x25);
1257 /*                      vga_wseq(regbase, CL_SEQR1F, 0x1c);  */
1258                         break;
1259
1260                 case BT_ALPINE:
1261                         DPRINTK(" (for GD543x)\n");
1262                         vga_wseq(regbase, CL_SEQR7, 0xa9);
1263                         cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
1264                         break;
1265
1266                 case BT_GD5480:
1267                         DPRINTK(" (for GD5480)\n");
1268                         vga_wseq(regbase, CL_SEQR7, 0x19);
1269                         /* We already set SRF and SR1F */
1270                         break;
1271
1272                 case BT_LAGUNA:
1273                         DPRINTK(" (for GD546x)\n");
1274                         vga_wseq(regbase, CL_SEQR7,
1275                                 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1276                         break;
1277
1278                 default:
1279                         printk(KERN_WARNING "cirrusfb: unknown Board\n");
1280                         break;
1281                 }
1282
1283                 /* mode register: 256 color mode */
1284                 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1285                 /* pixel mask: pass-through all planes */
1286                 WGen(cinfo, VGA_PEL_MSK, 0xff);
1287                 /* hidden dac reg: 8-8-8 mode (24 or 32) */
1288                 WHDR(cinfo, 0xc5);
1289                 /* memory mode: chain4, ext. memory */
1290                 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1291                 /* plane mask: enable writing to all 4 planes */
1292                 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1293                 offset = var->xres_virtual / 4;
1294         }
1295
1296         /******************************************************
1297          *
1298          * unknown/unsupported bpp
1299          *
1300          */
1301
1302         else
1303                 printk(KERN_ERR "cirrusfb: What's this?? "
1304                         " requested color depth == %d.\n",
1305                         var->bits_per_pixel);
1306
1307         vga_wcrt(regbase, VGA_CRTC_OFFSET, offset & 0xff);
1308         tmp = 0x22;
1309         if (offset & 0x100)
1310                 tmp |= 0x10;    /* offset overflow bit */
1311
1312         /* screen start addr #16-18, fastpagemode cycles */
1313         vga_wcrt(regbase, CL_CRT1B, tmp);
1314
1315         if (cinfo->btype == BT_SD64 ||
1316             cinfo->btype == BT_PICASSO4 ||
1317             cinfo->btype == BT_ALPINE ||
1318             cinfo->btype == BT_GD5480)
1319                 /* screen start address bit 19 */
1320                 vga_wcrt(regbase, CL_CRT1D, 0x00);
1321
1322         /* text cursor location high */
1323         vga_wcrt(regbase, VGA_CRTC_CURSOR_HI, 0);
1324         /* text cursor location low */
1325         vga_wcrt(regbase, VGA_CRTC_CURSOR_LO, 0);
1326         /* underline row scanline = at very bottom */
1327         vga_wcrt(regbase, VGA_CRTC_UNDERLINE, 0);
1328
1329         /* controller mode */
1330         vga_wattr(regbase, VGA_ATC_MODE, 1);
1331         /* overscan (border) color */
1332         vga_wattr(regbase, VGA_ATC_OVERSCAN, 0);
1333         /* color plane enable */
1334         vga_wattr(regbase, VGA_ATC_PLANE_ENABLE, 15);
1335         /* pixel panning */
1336         vga_wattr(regbase, CL_AR33, 0);
1337         /* color select */
1338         vga_wattr(regbase, VGA_ATC_COLOR_PAGE, 0);
1339
1340         /* [ EGS: SetOffset(); ] */
1341         /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
1342         AttrOn(cinfo);
1343
1344         /* set/reset register */
1345         vga_wgfx(regbase, VGA_GFX_SR_VALUE, 0);
1346         /* set/reset enable */
1347         vga_wgfx(regbase, VGA_GFX_SR_ENABLE, 0);
1348         /* color compare */
1349         vga_wgfx(regbase, VGA_GFX_COMPARE_VALUE, 0);
1350         /* data rotate */
1351         vga_wgfx(regbase, VGA_GFX_DATA_ROTATE, 0);
1352         /* read map select */
1353         vga_wgfx(regbase, VGA_GFX_PLANE_READ, 0);
1354         /* miscellaneous register */
1355         vga_wgfx(regbase, VGA_GFX_MISC, 1);
1356         /* color don't care */
1357         vga_wgfx(regbase, VGA_GFX_COMPARE_MASK, 15);
1358         /* bit mask */
1359         vga_wgfx(regbase, VGA_GFX_BIT_MASK, 255);
1360
1361         /* graphics cursor attributes: nothing special */
1362         vga_wseq(regbase, CL_SEQR12, 0x0);
1363
1364         /* finally, turn on everything - turn off "FullBandwidth" bit */
1365         /* also, set "DotClock%2" bit where requested */
1366         tmp = 0x01;
1367
1368 /*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
1369     if (var->vmode & FB_VMODE_CLOCK_HALVE)
1370         tmp |= 0x08;
1371 */
1372
1373         vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp);
1374         DPRINTK("CL_SEQR1: %d\n", tmp);
1375
1376         cinfo->currentmode = regs;
1377
1378         /* pan to requested offset */
1379         cirrusfb_pan_display(var, info);
1380
1381 #ifdef CIRRUSFB_DEBUG
1382         cirrusfb_dump();
1383 #endif
1384
1385         DPRINTK("EXIT\n");
1386         return 0;
1387 }
1388
1389 /* for some reason incomprehensible to me, cirrusfb requires that you write
1390  * the registers twice for the settings to take..grr. -dte */
1391 static int cirrusfb_set_par(struct fb_info *info)
1392 {
1393         cirrusfb_set_par_foo(info);
1394         return cirrusfb_set_par_foo(info);
1395 }
1396
1397 static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1398                               unsigned blue, unsigned transp,
1399                               struct fb_info *info)
1400 {
1401         struct cirrusfb_info *cinfo = info->par;
1402
1403         if (regno > 255)
1404                 return -EINVAL;
1405
1406         if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
1407                 u32 v;
1408                 red >>= (16 - info->var.red.length);
1409                 green >>= (16 - info->var.green.length);
1410                 blue >>= (16 - info->var.blue.length);
1411
1412                 if (regno >= 16)
1413                         return 1;
1414                 v = (red << info->var.red.offset) |
1415                     (green << info->var.green.offset) |
1416                     (blue << info->var.blue.offset);
1417
1418                 cinfo->pseudo_palette[regno] = v;
1419                 return 0;
1420         }
1421
1422         if (info->var.bits_per_pixel == 8)
1423                 WClut(cinfo, regno, red >> 10, green >> 10, blue >> 10);
1424
1425         return 0;
1426
1427 }
1428
1429 /*************************************************************************
1430         cirrusfb_pan_display()
1431
1432         performs display panning - provided hardware permits this
1433 **************************************************************************/
1434 static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
1435                                 struct fb_info *info)
1436 {
1437         int xoffset = 0;
1438         int yoffset = 0;
1439         unsigned long base;
1440         unsigned char tmp = 0, tmp2 = 0, xpix;
1441         struct cirrusfb_info *cinfo = info->par;
1442
1443         DPRINTK("ENTER\n");
1444         DPRINTK("virtual offset: (%d,%d)\n", var->xoffset, var->yoffset);
1445
1446         /* no range checks for xoffset and yoffset,   */
1447         /* as fb_pan_display has already done this */
1448         if (var->vmode & FB_VMODE_YWRAP)
1449                 return -EINVAL;
1450
1451         info->var.xoffset = var->xoffset;
1452         info->var.yoffset = var->yoffset;
1453
1454         xoffset = var->xoffset * info->var.bits_per_pixel / 8;
1455         yoffset = var->yoffset;
1456
1457         base = yoffset * info->fix.line_length + xoffset;
1458
1459         if (info->var.bits_per_pixel == 1) {
1460                 /* base is already correct */
1461                 xpix = (unsigned char) (var->xoffset % 8);
1462         } else {
1463                 base /= 4;
1464                 xpix = (unsigned char) ((xoffset % 4) * 2);
1465         }
1466
1467         cirrusfb_WaitBLT(cinfo->regbase); /* make sure all the BLT's are done */
1468
1469         /* lower 8 + 8 bits of screen start address */
1470         vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO,
1471                  (unsigned char) (base & 0xff));
1472         vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI,
1473                  (unsigned char) (base >> 8));
1474
1475         /* construct bits 16, 17 and 18 of screen start address */
1476         if (base & 0x10000)
1477                 tmp |= 0x01;
1478         if (base & 0x20000)
1479                 tmp |= 0x04;
1480         if (base & 0x40000)
1481                 tmp |= 0x08;
1482
1483         /* 0xf2 is %11110010, exclude tmp bits */
1484         tmp2 = (vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2) | tmp;
1485         vga_wcrt(cinfo->regbase, CL_CRT1B, tmp2);
1486
1487         /* construct bit 19 of screen start address */
1488         if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19)
1489                 vga_wcrt(cinfo->regbase, CL_CRT1D, (base >> 12) & 0x80);
1490
1491         /* write pixel panning value to AR33; this does not quite work in 8bpp
1492          *
1493          * ### Piccolo..? Will this work?
1494          */
1495         if (info->var.bits_per_pixel == 1)
1496                 vga_wattr(cinfo->regbase, CL_AR33, xpix);
1497
1498         cirrusfb_WaitBLT(cinfo->regbase);
1499
1500         DPRINTK("EXIT\n");
1501         return 0;
1502 }
1503
1504 static int cirrusfb_blank(int blank_mode, struct fb_info *info)
1505 {
1506         /*
1507          * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
1508          * then the caller blanks by setting the CLUT (Color Look Up Table)
1509          * to all black. Return 0 if blanking succeeded, != 0 if un-/blanking
1510          * failed due to e.g. a video mode which doesn't support it.
1511          * Implements VESA suspend and powerdown modes on hardware that
1512          * supports disabling hsync/vsync:
1513          *   blank_mode == 2: suspend vsync
1514          *   blank_mode == 3: suspend hsync
1515          *   blank_mode == 4: powerdown
1516          */
1517         unsigned char val;
1518         struct cirrusfb_info *cinfo = info->par;
1519         int current_mode = cinfo->blank_mode;
1520
1521         DPRINTK("ENTER, blank mode = %d\n", blank_mode);
1522
1523         if (info->state != FBINFO_STATE_RUNNING ||
1524             current_mode == blank_mode) {
1525                 DPRINTK("EXIT, returning 0\n");
1526                 return 0;
1527         }
1528
1529         /* Undo current */
1530         if (current_mode == FB_BLANK_NORMAL ||
1531             current_mode == FB_BLANK_UNBLANK) {
1532                 /* unblank the screen */
1533                 val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1534                 /* clear "FullBandwidth" bit */
1535                 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val & 0xdf);
1536                 /* and undo VESA suspend trickery */
1537                 vga_wgfx(cinfo->regbase, CL_GRE, 0x00);
1538         }
1539
1540         /* set new */
1541         if (blank_mode > FB_BLANK_NORMAL) {
1542                 /* blank the screen */
1543                 val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1544                 /* set "FullBandwidth" bit */
1545                 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val | 0x20);
1546         }
1547
1548         switch (blank_mode) {
1549         case FB_BLANK_UNBLANK:
1550         case FB_BLANK_NORMAL:
1551                 break;
1552         case FB_BLANK_VSYNC_SUSPEND:
1553                 vga_wgfx(cinfo->regbase, CL_GRE, 0x04);
1554                 break;
1555         case FB_BLANK_HSYNC_SUSPEND:
1556                 vga_wgfx(cinfo->regbase, CL_GRE, 0x02);
1557                 break;
1558         case FB_BLANK_POWERDOWN:
1559                 vga_wgfx(cinfo->regbase, CL_GRE, 0x06);
1560                 break;
1561         default:
1562                 DPRINTK("EXIT, returning 1\n");
1563                 return 1;
1564         }
1565
1566         cinfo->blank_mode = blank_mode;
1567         DPRINTK("EXIT, returning 0\n");
1568
1569         /* Let fbcon do a soft blank for us */
1570         return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
1571 }
1572 /**** END   Hardware specific Routines **************************************/
1573 /****************************************************************************/
1574 /**** BEGIN Internal Routines ***********************************************/
1575
1576 static void init_vgachip(struct fb_info *info)
1577 {
1578         struct cirrusfb_info *cinfo = info->par;
1579         const struct cirrusfb_board_info_rec *bi;
1580
1581         DPRINTK("ENTER\n");
1582
1583         assert(cinfo != NULL);
1584
1585         bi = &cirrusfb_board_info[cinfo->btype];
1586
1587         /* reset board globally */
1588         switch (cinfo->btype) {
1589         case BT_PICCOLO:
1590                 WSFR(cinfo, 0x01);
1591                 udelay(500);
1592                 WSFR(cinfo, 0x51);
1593                 udelay(500);
1594                 break;
1595         case BT_PICASSO:
1596                 WSFR2(cinfo, 0xff);
1597                 udelay(500);
1598                 break;
1599         case BT_SD64:
1600         case BT_SPECTRUM:
1601                 WSFR(cinfo, 0x1f);
1602                 udelay(500);
1603                 WSFR(cinfo, 0x4f);
1604                 udelay(500);
1605                 break;
1606         case BT_PICASSO4:
1607                 /* disable flickerfixer */
1608                 vga_wcrt(cinfo->regbase, CL_CRT51, 0x00);
1609                 mdelay(100);
1610                 /* from Klaus' NetBSD driver: */
1611                 vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
1612                 /* put blitter into 542x compat */
1613                 vga_wgfx(cinfo->regbase, CL_GR33, 0x00);
1614                 /* mode */
1615                 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1616                 break;
1617
1618         case BT_GD5480:
1619                 /* from Klaus' NetBSD driver: */
1620                 vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
1621                 break;
1622
1623         case BT_ALPINE:
1624                 /* Nothing to do to reset the board. */
1625                 break;
1626
1627         default:
1628                 printk(KERN_ERR "cirrusfb: Warning: Unknown board type\n");
1629                 break;
1630         }
1631
1632         /* make sure RAM size set by this point */
1633         assert(info->screen_size > 0);
1634
1635         /* the P4 is not fully initialized here; I rely on it having been */
1636         /* inited under AmigaOS already, which seems to work just fine    */
1637         /* (Klaus advised to do it this way)                          */
1638
1639         if (cinfo->btype != BT_PICASSO4) {
1640                 WGen(cinfo, CL_VSSM, 0x10);     /* EGS: 0x16 */
1641                 WGen(cinfo, CL_POS102, 0x01);
1642                 WGen(cinfo, CL_VSSM, 0x08);     /* EGS: 0x0e */
1643
1644                 if (cinfo->btype != BT_SD64)
1645                         WGen(cinfo, CL_VSSM2, 0x01);
1646
1647                 /* reset sequencer logic */
1648                 vga_wseq(cinfo->regbase, CL_SEQR0, 0x03);
1649
1650                 /* FullBandwidth (video off) and 8/9 dot clock */
1651                 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21);
1652                 /* polarity (-/-), disable access to display memory,
1653                  * VGA_CRTC_START_HI base address: color
1654                  */
1655                 WGen(cinfo, VGA_MIS_W, 0xc1);
1656
1657                 /* "magic cookie" - doesn't make any sense to me.. */
1658 /*      vga_wgfx(cinfo->regbase, CL_GRA, 0xce);   */
1659                 /* unlock all extension registers */
1660                 vga_wseq(cinfo->regbase, CL_SEQR6, 0x12);
1661
1662                 /* reset blitter */
1663                 vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
1664
1665                 switch (cinfo->btype) {
1666                 case BT_GD5480:
1667                         vga_wseq(cinfo->regbase, CL_SEQRF, 0x98);
1668                         break;
1669                 case BT_ALPINE:
1670                         break;
1671                 case BT_SD64:
1672                         vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8);
1673                         break;
1674                 default:
1675                         vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f);
1676                         vga_wseq(cinfo->regbase, CL_SEQRF, 0xb0);
1677                         break;
1678                 }
1679         }
1680         /* plane mask: nothing */
1681         vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1682         /* character map select: doesn't even matter in gx mode */
1683         vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00);
1684         /* memory mode: chain-4, no odd/even, ext. memory */
1685         vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0e);
1686
1687         /* controller-internal base address of video memory */
1688         if (bi->init_sr07)
1689                 vga_wseq(cinfo->regbase, CL_SEQR7, bi->sr07);
1690
1691         /*  vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */
1692         /* EEPROM control: shouldn't be necessary to write to this at all.. */
1693
1694         /* graphics cursor X position (incomplete; position gives rem. 3 bits */
1695         vga_wseq(cinfo->regbase, CL_SEQR10, 0x00);
1696         /* graphics cursor Y position (..."... ) */
1697         vga_wseq(cinfo->regbase, CL_SEQR11, 0x00);
1698         /* graphics cursor attributes */
1699         vga_wseq(cinfo->regbase, CL_SEQR12, 0x00);
1700         /* graphics cursor pattern address */
1701         vga_wseq(cinfo->regbase, CL_SEQR13, 0x00);
1702
1703         /* writing these on a P4 might give problems..  */
1704         if (cinfo->btype != BT_PICASSO4) {
1705                 /* configuration readback and ext. color */
1706                 vga_wseq(cinfo->regbase, CL_SEQR17, 0x00);
1707                 /* signature generator */
1708                 vga_wseq(cinfo->regbase, CL_SEQR18, 0x02);
1709         }
1710
1711         /* MCLK select etc. */
1712         if (bi->init_sr1f)
1713                 vga_wseq(cinfo->regbase, CL_SEQR1F, bi->sr1f);
1714
1715         /* Screen A preset row scan: none */
1716         vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00);
1717         /* Text cursor start: disable text cursor */
1718         vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20);
1719         /* Text cursor end: - */
1720         vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00);
1721         /* Screen start address high: 0 */
1722         vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, 0x00);
1723         /* Screen start address low: 0 */
1724         vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, 0x00);
1725         /* text cursor location high: 0 */
1726         vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00);
1727         /* text cursor location low: 0 */
1728         vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00);
1729
1730         /* Underline Row scanline: - */
1731         vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00);
1732         /* mode control: timing enable, byte mode, no compat modes */
1733         vga_wcrt(cinfo->regbase, VGA_CRTC_MODE, 0xc3);
1734         /* Line Compare: not needed */
1735         vga_wcrt(cinfo->regbase, VGA_CRTC_LINE_COMPARE, 0x00);
1736         /* ### add 0x40 for text modes with > 30 MHz pixclock */
1737         /* ext. display controls: ext.adr. wrap */
1738         vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02);
1739
1740         /* Set/Reset registes: - */
1741         vga_wgfx(cinfo->regbase, VGA_GFX_SR_VALUE, 0x00);
1742         /* Set/Reset enable: - */
1743         vga_wgfx(cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00);
1744         /* Color Compare: - */
1745         vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00);
1746         /* Data Rotate: - */
1747         vga_wgfx(cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00);
1748         /* Read Map Select: - */
1749         vga_wgfx(cinfo->regbase, VGA_GFX_PLANE_READ, 0x00);
1750         /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
1751         vga_wgfx(cinfo->regbase, VGA_GFX_MODE, 0x00);
1752         /* Miscellaneous: memory map base address, graphics mode */
1753         vga_wgfx(cinfo->regbase, VGA_GFX_MISC, 0x01);
1754         /* Color Don't care: involve all planes */
1755         vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f);
1756         /* Bit Mask: no mask at all */
1757         vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff);
1758         if (cinfo->btype == BT_ALPINE)
1759                 /* (5434 can't have bit 3 set for bitblt) */
1760                 vga_wgfx(cinfo->regbase, CL_GRB, 0x20);
1761         else
1762         /* Graphics controller mode extensions: finer granularity,
1763          * 8byte data latches
1764          */
1765                 vga_wgfx(cinfo->regbase, CL_GRB, 0x28);
1766
1767         vga_wgfx(cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */
1768         vga_wgfx(cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */
1769         vga_wgfx(cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */
1770         /* Background color byte 1: - */
1771         /*  vga_wgfx (cinfo->regbase, CL_GR10, 0x00); */
1772         /*  vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
1773
1774         /* Attribute Controller palette registers: "identity mapping" */
1775         vga_wattr(cinfo->regbase, VGA_ATC_PALETTE0, 0x00);
1776         vga_wattr(cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
1777         vga_wattr(cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
1778         vga_wattr(cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
1779         vga_wattr(cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
1780         vga_wattr(cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
1781         vga_wattr(cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
1782         vga_wattr(cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
1783         vga_wattr(cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
1784         vga_wattr(cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
1785         vga_wattr(cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
1786         vga_wattr(cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
1787         vga_wattr(cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
1788         vga_wattr(cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
1789         vga_wattr(cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
1790         vga_wattr(cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
1791
1792         /* Attribute Controller mode: graphics mode */
1793         vga_wattr(cinfo->regbase, VGA_ATC_MODE, 0x01);
1794         /* Overscan color reg.: reg. 0 */
1795         vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00);
1796         /* Color Plane enable: Enable all 4 planes */
1797         vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f);
1798 /* ###  vga_wattr(cinfo->regbase, CL_AR33, 0x00); * Pixel Panning: - */
1799         /* Color Select: - */
1800         vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00);
1801
1802         WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
1803
1804         if (cinfo->btype != BT_ALPINE && cinfo->btype != BT_GD5480)
1805         /* polarity (-/-), enable display mem,
1806          * VGA_CRTC_START_HI i/o base = color
1807          */
1808                 WGen(cinfo, VGA_MIS_W, 0xc3);
1809
1810         /* BLT Start/status: Blitter reset */
1811         vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
1812         /* - " -           : "end-of-reset" */
1813         vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1814
1815         /* misc... */
1816         WHDR(cinfo, 0); /* Hidden DAC register: - */
1817
1818         DPRINTK("EXIT\n");
1819         return;
1820 }
1821
1822 static void switch_monitor(struct cirrusfb_info *cinfo, int on)
1823 {
1824 #ifdef CONFIG_ZORRO /* only works on Zorro boards */
1825         static int IsOn = 0;    /* XXX not ok for multiple boards */
1826
1827         DPRINTK("ENTER\n");
1828
1829         if (cinfo->btype == BT_PICASSO4)
1830                 return;         /* nothing to switch */
1831         if (cinfo->btype == BT_ALPINE)
1832                 return;         /* nothing to switch */
1833         if (cinfo->btype == BT_GD5480)
1834                 return;         /* nothing to switch */
1835         if (cinfo->btype == BT_PICASSO) {
1836                 if ((on && !IsOn) || (!on && IsOn))
1837                         WSFR(cinfo, 0xff);
1838
1839                 DPRINTK("EXIT\n");
1840                 return;
1841         }
1842         if (on) {
1843                 switch (cinfo->btype) {
1844                 case BT_SD64:
1845                         WSFR(cinfo, cinfo->SFR | 0x21);
1846                         break;
1847                 case BT_PICCOLO:
1848                         WSFR(cinfo, cinfo->SFR | 0x28);
1849                         break;
1850                 case BT_SPECTRUM:
1851                         WSFR(cinfo, 0x6f);
1852                         break;
1853                 default: /* do nothing */ break;
1854                 }
1855         } else {
1856                 switch (cinfo->btype) {
1857                 case BT_SD64:
1858                         WSFR(cinfo, cinfo->SFR & 0xde);
1859                         break;
1860                 case BT_PICCOLO:
1861                         WSFR(cinfo, cinfo->SFR & 0xd7);
1862                         break;
1863                 case BT_SPECTRUM:
1864                         WSFR(cinfo, 0x4f);
1865                         break;
1866                 default: /* do nothing */ break;
1867                 }
1868         }
1869
1870         DPRINTK("EXIT\n");
1871 #endif /* CONFIG_ZORRO */
1872 }
1873
1874 /******************************************/
1875 /* Linux 2.6-style  accelerated functions */
1876 /******************************************/
1877
1878 static void cirrusfb_fillrect(struct fb_info *info,
1879                               const struct fb_fillrect *region)
1880 {
1881         struct fb_fillrect modded;
1882         int vxres, vyres;
1883         struct cirrusfb_info *cinfo = info->par;
1884         int m = info->var.bits_per_pixel;
1885         u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
1886                 cinfo->pseudo_palette[region->color] : region->color;
1887
1888         if (info->state != FBINFO_STATE_RUNNING)
1889                 return;
1890         if (info->flags & FBINFO_HWACCEL_DISABLED) {
1891                 cfb_fillrect(info, region);
1892                 return;
1893         }
1894
1895         vxres = info->var.xres_virtual;
1896         vyres = info->var.yres_virtual;
1897
1898         memcpy(&modded, region, sizeof(struct fb_fillrect));
1899
1900         if (!modded.width || !modded.height ||
1901            modded.dx >= vxres || modded.dy >= vyres)
1902                 return;
1903
1904         if (modded.dx + modded.width  > vxres)
1905                 modded.width  = vxres - modded.dx;
1906         if (modded.dy + modded.height > vyres)
1907                 modded.height = vyres - modded.dy;
1908
1909         cirrusfb_RectFill(cinfo->regbase,
1910                           info->var.bits_per_pixel,
1911                           (region->dx * m) / 8, region->dy,
1912                           (region->width * m) / 8, region->height,
1913                           color,
1914                           info->fix.line_length);
1915 }
1916
1917 static void cirrusfb_copyarea(struct fb_info *info,
1918                               const struct fb_copyarea *area)
1919 {
1920         struct fb_copyarea modded;
1921         u32 vxres, vyres;
1922         struct cirrusfb_info *cinfo = info->par;
1923         int m = info->var.bits_per_pixel;
1924
1925         if (info->state != FBINFO_STATE_RUNNING)
1926                 return;
1927         if (info->flags & FBINFO_HWACCEL_DISABLED) {
1928                 cfb_copyarea(info, area);
1929                 return;
1930         }
1931
1932         vxres = info->var.xres_virtual;
1933         vyres = info->var.yres_virtual;
1934         memcpy(&modded, area, sizeof(struct fb_copyarea));
1935
1936         if (!modded.width || !modded.height ||
1937            modded.sx >= vxres || modded.sy >= vyres ||
1938            modded.dx >= vxres || modded.dy >= vyres)
1939                 return;
1940
1941         if (modded.sx + modded.width > vxres)
1942                 modded.width = vxres - modded.sx;
1943         if (modded.dx + modded.width > vxres)
1944                 modded.width = vxres - modded.dx;
1945         if (modded.sy + modded.height > vyres)
1946                 modded.height = vyres - modded.sy;
1947         if (modded.dy + modded.height > vyres)
1948                 modded.height = vyres - modded.dy;
1949
1950         cirrusfb_BitBLT(cinfo->regbase, info->var.bits_per_pixel,
1951                         (area->sx * m) / 8, area->sy,
1952                         (area->dx * m) / 8, area->dy,
1953                         (area->width * m) / 8, area->height,
1954                         info->fix.line_length);
1955
1956 }
1957
1958 static void cirrusfb_imageblit(struct fb_info *info,
1959                                const struct fb_image *image)
1960 {
1961         struct cirrusfb_info *cinfo = info->par;
1962
1963         cirrusfb_WaitBLT(cinfo->regbase);
1964         cfb_imageblit(info, image);
1965 }
1966
1967 #ifdef CONFIG_PPC_PREP
1968 #define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
1969 #define PREP_IO_BASE    ((volatile unsigned char *) 0x80000000)
1970 static void get_prep_addrs(unsigned long *display, unsigned long *registers)
1971 {
1972         DPRINTK("ENTER\n");
1973
1974         *display = PREP_VIDEO_BASE;
1975         *registers = (unsigned long) PREP_IO_BASE;
1976
1977         DPRINTK("EXIT\n");
1978 }
1979
1980 #endif                          /* CONFIG_PPC_PREP */
1981
1982 #ifdef CONFIG_PCI
1983 static int release_io_ports;
1984
1985 /* Pulled the logic from XFree86 Cirrus driver to get the memory size,
1986  * based on the DRAM bandwidth bit and DRAM bank switching bit.  This
1987  * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
1988  * seem to have. */
1989 static unsigned int __devinit cirrusfb_get_memsize(u8 __iomem *regbase)
1990 {
1991         unsigned long mem;
1992         unsigned char SRF;
1993
1994         DPRINTK("ENTER\n");
1995
1996         SRF = vga_rseq(regbase, CL_SEQRF);
1997         switch ((SRF & 0x18)) {
1998         case 0x08:
1999                 mem = 512 * 1024;
2000                 break;
2001         case 0x10:
2002                 mem = 1024 * 1024;
2003                 break;
2004         /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory
2005          * on the 5430.
2006          */
2007         case 0x18:
2008                 mem = 2048 * 1024;
2009                 break;
2010         default:
2011                 printk(KERN_WARNING "CLgenfb: Unknown memory size!\n");
2012                 mem = 1024 * 1024;
2013         }
2014         if (SRF & 0x80)
2015         /* If DRAM bank switching is enabled, there must be twice as much
2016          * memory installed. (4MB on the 5434)
2017          */
2018                 mem *= 2;
2019
2020         /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
2021
2022         DPRINTK("EXIT\n");
2023         return mem;
2024 }
2025
2026 static void get_pci_addrs(const struct pci_dev *pdev,
2027                           unsigned long *display, unsigned long *registers)
2028 {
2029         assert(pdev != NULL);
2030         assert(display != NULL);
2031         assert(registers != NULL);
2032
2033         DPRINTK("ENTER\n");
2034
2035         *display = 0;
2036         *registers = 0;
2037
2038         /* This is a best-guess for now */
2039
2040         if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
2041                 *display = pci_resource_start(pdev, 1);
2042                 *registers = pci_resource_start(pdev, 0);
2043         } else {
2044                 *display = pci_resource_start(pdev, 0);
2045                 *registers = pci_resource_start(pdev, 1);
2046         }
2047
2048         assert(*display != 0);
2049
2050         DPRINTK("EXIT\n");
2051 }
2052
2053 static void cirrusfb_pci_unmap(struct fb_info *info)
2054 {
2055         struct pci_dev *pdev = to_pci_dev(info->device);
2056
2057         iounmap(info->screen_base);
2058 #if 0 /* if system didn't claim this region, we would... */
2059         release_mem_region(0xA0000, 65535);
2060 #endif
2061         if (release_io_ports)
2062                 release_region(0x3C0, 32);
2063         pci_release_regions(pdev);
2064 }
2065 #endif /* CONFIG_PCI */
2066
2067 #ifdef CONFIG_ZORRO
2068 static void __devexit cirrusfb_zorro_unmap(struct fb_info *info)
2069 {
2070         struct cirrusfb_info *cinfo = info->par;
2071         struct zorro_dev *zdev = to_zorro_dev(info->device);
2072
2073         zorro_release_device(zdev);
2074
2075         if (cinfo->btype == BT_PICASSO4) {
2076                 cinfo->regbase -= 0x600000;
2077                 iounmap((void *)cinfo->regbase);
2078                 iounmap(info->screen_base);
2079         } else {
2080                 if (zorro_resource_start(zdev) > 0x01000000)
2081                         iounmap(info->screen_base);
2082         }
2083 }
2084 #endif /* CONFIG_ZORRO */
2085
2086 static int __devinit cirrusfb_set_fbinfo(struct fb_info *info)
2087 {
2088         struct cirrusfb_info *cinfo = info->par;
2089         struct fb_var_screeninfo *var = &info->var;
2090
2091         info->pseudo_palette = cinfo->pseudo_palette;
2092         info->flags = FBINFO_DEFAULT
2093                     | FBINFO_HWACCEL_XPAN
2094                     | FBINFO_HWACCEL_YPAN
2095                     | FBINFO_HWACCEL_FILLRECT
2096                     | FBINFO_HWACCEL_COPYAREA;
2097         if (noaccel)
2098                 info->flags |= FBINFO_HWACCEL_DISABLED;
2099         info->fbops = &cirrusfb_ops;
2100         if (cinfo->btype == BT_GD5480) {
2101                 if (var->bits_per_pixel == 16)
2102                         info->screen_base += 1 * MB_;
2103                 if (var->bits_per_pixel == 32)
2104                         info->screen_base += 2 * MB_;
2105         }
2106
2107         /* Fill fix common fields */
2108         strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
2109                 sizeof(info->fix.id));
2110
2111         /* monochrome: only 1 memory plane */
2112         /* 8 bit and above: Use whole memory area */
2113         info->fix.smem_len   = info->screen_size;
2114         if (var->bits_per_pixel == 1)
2115                 info->fix.smem_len /= 4;
2116         info->fix.type_aux   = 0;
2117         info->fix.xpanstep   = 1;
2118         info->fix.ypanstep   = 1;
2119         info->fix.ywrapstep  = 0;
2120
2121         /* FIXME: map region at 0xB8000 if available, fill in here */
2122         info->fix.mmio_len   = 0;
2123         info->fix.accel = FB_ACCEL_NONE;
2124
2125         fb_alloc_cmap(&info->cmap, 256, 0);
2126
2127         return 0;
2128 }
2129
2130 static int __devinit cirrusfb_register(struct fb_info *info)
2131 {
2132         struct cirrusfb_info *cinfo = info->par;
2133         int err;
2134         enum cirrus_board btype;
2135
2136         DPRINTK("ENTER\n");
2137
2138         printk(KERN_INFO "cirrusfb: Driver for Cirrus Logic based "
2139                 "graphic boards, v" CIRRUSFB_VERSION "\n");
2140
2141         btype = cinfo->btype;
2142
2143         /* sanity checks */
2144         assert(btype != BT_NONE);
2145
2146         /* set all the vital stuff */
2147         cirrusfb_set_fbinfo(info);
2148
2149         DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base);
2150
2151         err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
2152         if (!err) {
2153                 DPRINTK("wrong initial video mode\n");
2154                 err = -EINVAL;
2155                 goto err_dealloc_cmap;
2156         }
2157
2158         info->var.activate = FB_ACTIVATE_NOW;
2159
2160         err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
2161         if (err < 0) {
2162                 /* should never happen */
2163                 DPRINTK("choking on default var... umm, no good.\n");
2164                 goto err_dealloc_cmap;
2165         }
2166
2167         err = register_framebuffer(info);
2168         if (err < 0) {
2169                 printk(KERN_ERR "cirrusfb: could not register "
2170                         "fb device; err = %d!\n", err);
2171                 goto err_dealloc_cmap;
2172         }
2173
2174         DPRINTK("EXIT, returning 0\n");
2175         return 0;
2176
2177 err_dealloc_cmap:
2178         fb_dealloc_cmap(&info->cmap);
2179         cinfo->unmap(info);
2180         framebuffer_release(info);
2181         return err;
2182 }
2183
2184 static void __devexit cirrusfb_cleanup(struct fb_info *info)
2185 {
2186         struct cirrusfb_info *cinfo = info->par;
2187         DPRINTK("ENTER\n");
2188
2189         switch_monitor(cinfo, 0);
2190
2191         unregister_framebuffer(info);
2192         fb_dealloc_cmap(&info->cmap);
2193         printk("Framebuffer unregistered\n");
2194         cinfo->unmap(info);
2195         framebuffer_release(info);
2196
2197         DPRINTK("EXIT\n");
2198 }
2199
2200 #ifdef CONFIG_PCI
2201 static int __devinit cirrusfb_pci_register(struct pci_dev *pdev,
2202                                            const struct pci_device_id *ent)
2203 {
2204         struct cirrusfb_info *cinfo;
2205         struct fb_info *info;
2206         enum cirrus_board btype;
2207         unsigned long board_addr, board_size;
2208         int ret;
2209
2210         ret = pci_enable_device(pdev);
2211         if (ret < 0) {
2212                 printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
2213                 goto err_out;
2214         }
2215
2216         info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev);
2217         if (!info) {
2218                 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2219                 ret = -ENOMEM;
2220                 goto err_disable;
2221         }
2222
2223         cinfo = info->par;
2224         cinfo->btype = btype = (enum cirrus_board) ent->driver_data;
2225
2226         DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n",
2227                 pdev->resource[0].start, btype);
2228         DPRINTK(" base address 1 is 0x%x\n", pdev->resource[1].start);
2229
2230         if (isPReP) {
2231                 pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, 0x00000000);
2232 #ifdef CONFIG_PPC_PREP
2233                 get_prep_addrs(&board_addr, &info->fix.mmio_start);
2234 #endif
2235         /* PReP dies if we ioremap the IO registers, but it works w/out... */
2236                 cinfo->regbase = (char __iomem *) info->fix.mmio_start;
2237         } else {
2238                 DPRINTK("Attempt to get PCI info for Cirrus Graphics Card\n");
2239                 get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start);
2240                 /* FIXME: this forces VGA.  alternatives? */
2241                 cinfo->regbase = NULL;
2242         }
2243
2244         DPRINTK("Board address: 0x%lx, register address: 0x%lx\n",
2245                 board_addr, info->fix.mmio_start);
2246
2247         board_size = (btype == BT_GD5480) ?
2248                 32 * MB_ : cirrusfb_get_memsize(cinfo->regbase);
2249
2250         ret = pci_request_regions(pdev, "cirrusfb");
2251         if (ret < 0) {
2252                 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, "
2253                        "abort\n",
2254                        board_addr);
2255                 goto err_release_fb;
2256         }
2257 #if 0 /* if the system didn't claim this region, we would... */
2258         if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
2259                 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n"
2260 ,
2261                        0xA0000L);
2262                 ret = -EBUSY;
2263                 goto err_release_regions;
2264         }
2265 #endif
2266         if (request_region(0x3C0, 32, "cirrusfb"))
2267                 release_io_ports = 1;
2268
2269         info->screen_base = ioremap(board_addr, board_size);
2270         if (!info->screen_base) {
2271                 ret = -EIO;
2272                 goto err_release_legacy;
2273         }
2274
2275         info->fix.smem_start = board_addr;
2276         info->screen_size = board_size;
2277         cinfo->unmap = cirrusfb_pci_unmap;
2278
2279         printk(KERN_INFO "RAM (%lu kB) at 0x%lx, Cirrus "
2280                         "Logic chipset on PCI bus\n",
2281                         info->screen_size >> 10, board_addr);
2282         pci_set_drvdata(pdev, info);
2283
2284         ret = cirrusfb_register(info);
2285         if (ret)
2286                 iounmap(info->screen_base);
2287         return ret;
2288
2289 err_release_legacy:
2290         if (release_io_ports)
2291                 release_region(0x3C0, 32);
2292 #if 0
2293         release_mem_region(0xA0000, 65535);
2294 err_release_regions:
2295 #endif
2296         pci_release_regions(pdev);
2297 err_release_fb:
2298         framebuffer_release(info);
2299 err_disable:
2300 err_out:
2301         return ret;
2302 }
2303
2304 static void __devexit cirrusfb_pci_unregister(struct pci_dev *pdev)
2305 {
2306         struct fb_info *info = pci_get_drvdata(pdev);
2307         DPRINTK("ENTER\n");
2308
2309         cirrusfb_cleanup(info);
2310
2311         DPRINTK("EXIT\n");
2312 }
2313
2314 static struct pci_driver cirrusfb_pci_driver = {
2315         .name           = "cirrusfb",
2316         .id_table       = cirrusfb_pci_table,
2317         .probe          = cirrusfb_pci_register,
2318         .remove         = __devexit_p(cirrusfb_pci_unregister),
2319 #ifdef CONFIG_PM
2320 #if 0
2321         .suspend        = cirrusfb_pci_suspend,
2322         .resume         = cirrusfb_pci_resume,
2323 #endif
2324 #endif
2325 };
2326 #endif /* CONFIG_PCI */
2327
2328 #ifdef CONFIG_ZORRO
2329 static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
2330                                              const struct zorro_device_id *ent)
2331 {
2332         struct cirrusfb_info *cinfo;
2333         struct fb_info *info;
2334         enum cirrus_board btype;
2335         struct zorro_dev *z2 = NULL;
2336         unsigned long board_addr, board_size, size;
2337         int ret;
2338
2339         btype = ent->driver_data;
2340         if (cirrusfb_zorro_table2[btype].id2)
2341                 z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
2342         size = cirrusfb_zorro_table2[btype].size;
2343         printk(KERN_INFO "cirrusfb: %s board detected; ",
2344                cirrusfb_board_info[btype].name);
2345
2346         info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
2347         if (!info) {
2348                 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2349                 ret = -ENOMEM;
2350                 goto err_out;
2351         }
2352
2353         cinfo = info->par;
2354         cinfo->btype = btype;
2355
2356         assert(z);
2357         assert(btype != BT_NONE);
2358
2359         board_addr = zorro_resource_start(z);
2360         board_size = zorro_resource_len(z);
2361         info->screen_size = size;
2362
2363         if (!zorro_request_device(z, "cirrusfb")) {
2364                 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, "
2365                        "abort\n",
2366                        board_addr);
2367                 ret = -EBUSY;
2368                 goto err_release_fb;
2369         }
2370
2371         printk(" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr);
2372
2373         ret = -EIO;
2374
2375         if (btype == BT_PICASSO4) {
2376                 printk(KERN_INFO " REG at $%lx\n", board_addr + 0x600000);
2377
2378                 /* To be precise, for the P4 this is not the */
2379                 /* begin of the board, but the begin of RAM. */
2380                 /* for P4, map in its address space in 2 chunks (### TEST! ) */
2381                 /* (note the ugly hardcoded 16M number) */
2382                 cinfo->regbase = ioremap(board_addr, 16777216);
2383                 if (!cinfo->regbase)
2384                         goto err_release_region;
2385
2386                 DPRINTK("cirrusfb: Virtual address for board set to: $%p\n",
2387                         cinfo->regbase);
2388                 cinfo->regbase += 0x600000;
2389                 info->fix.mmio_start = board_addr + 0x600000;
2390
2391                 info->fix.smem_start = board_addr + 16777216;
2392                 info->screen_base = ioremap(info->fix.smem_start, 16777216);
2393                 if (!info->screen_base)
2394                         goto err_unmap_regbase;
2395         } else {
2396                 printk(KERN_INFO " REG at $%lx\n",
2397                         (unsigned long) z2->resource.start);
2398
2399                 info->fix.smem_start = board_addr;
2400                 if (board_addr > 0x01000000)
2401                         info->screen_base = ioremap(board_addr, board_size);
2402                 else
2403                         info->screen_base = (caddr_t) ZTWO_VADDR(board_addr);
2404                 if (!info->screen_base)
2405                         goto err_release_region;
2406
2407                 /* set address for REG area of board */
2408                 cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start);
2409                 info->fix.mmio_start = z2->resource.start;
2410
2411                 DPRINTK("cirrusfb: Virtual address for board set to: $%p\n",
2412                         cinfo->regbase);
2413         }
2414         cinfo->unmap = cirrusfb_zorro_unmap;
2415
2416         printk(KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
2417         zorro_set_drvdata(z, info);
2418
2419         ret = cirrusfb_register(info);
2420         if (ret) {
2421                 if (btype == BT_PICASSO4) {
2422                         iounmap(info->screen_base);
2423                         iounmap(cinfo->regbase - 0x600000);
2424                 } else if (board_addr > 0x01000000)
2425                         iounmap(info->screen_base);
2426         }
2427         return ret;
2428
2429 err_unmap_regbase:
2430         /* Parental advisory: explicit hack */
2431         iounmap(cinfo->regbase - 0x600000);
2432 err_release_region:
2433         release_region(board_addr, board_size);
2434 err_release_fb:
2435         framebuffer_release(info);
2436 err_out:
2437         return ret;
2438 }
2439
2440 void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
2441 {
2442         struct fb_info *info = zorro_get_drvdata(z);
2443         DPRINTK("ENTER\n");
2444
2445         cirrusfb_cleanup(info);
2446
2447         DPRINTK("EXIT\n");
2448 }
2449
2450 static struct zorro_driver cirrusfb_zorro_driver = {
2451         .name           = "cirrusfb",
2452         .id_table       = cirrusfb_zorro_table,
2453         .probe          = cirrusfb_zorro_register,
2454         .remove         = __devexit_p(cirrusfb_zorro_unregister),
2455 };
2456 #endif /* CONFIG_ZORRO */
2457
2458 static int __init cirrusfb_init(void)
2459 {
2460         int error = 0;
2461
2462 #ifndef MODULE
2463         char *option = NULL;
2464
2465         if (fb_get_options("cirrusfb", &option))
2466                 return -ENODEV;
2467         cirrusfb_setup(option);
2468 #endif
2469
2470 #ifdef CONFIG_ZORRO
2471         error |= zorro_register_driver(&cirrusfb_zorro_driver);
2472 #endif
2473 #ifdef CONFIG_PCI
2474         error |= pci_register_driver(&cirrusfb_pci_driver);
2475 #endif
2476         return error;
2477 }
2478
2479 #ifndef MODULE
2480 static int __init cirrusfb_setup(char *options) {
2481         char *this_opt, s[32];
2482         int i;
2483
2484         DPRINTK("ENTER\n");
2485
2486         if (!options || !*options)
2487                 return 0;
2488
2489         while ((this_opt = strsep(&options, ",")) != NULL) {
2490                 if (!*this_opt)
2491                         continue;
2492
2493                 DPRINTK("cirrusfb_setup: option '%s'\n", this_opt);
2494
2495                 if (!strcmp(this_opt, "noaccel"))
2496                         noaccel = 1;
2497                 else if (!strncmp(this_opt, "mode:", 5))
2498                         mode_option = this_opt + 5;
2499                 else
2500                         mode_option = this_opt;
2501         }
2502         return 0;
2503 }
2504 #endif
2505
2506     /*
2507      *  Modularization
2508      */
2509
2510 MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
2511 MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
2512 MODULE_LICENSE("GPL");
2513
2514 static void __exit cirrusfb_exit(void)
2515 {
2516 #ifdef CONFIG_PCI
2517         pci_unregister_driver(&cirrusfb_pci_driver);
2518 #endif
2519 #ifdef CONFIG_ZORRO
2520         zorro_unregister_driver(&cirrusfb_zorro_driver);
2521 #endif
2522 }
2523
2524 module_init(cirrusfb_init);
2525
2526 module_param(mode_option, charp, 0);
2527 MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
2528 module_param(noaccel, bool, 0);
2529 MODULE_PARM_DESC(noaccel, "Disable acceleration");
2530
2531 #ifdef MODULE
2532 module_exit(cirrusfb_exit);
2533 #endif
2534
2535 /**********************************************************************/
2536 /* about the following functions - I have used the same names for the */
2537 /* functions as Markus Wild did in his Retina driver for NetBSD as    */
2538 /* they just made sense for this purpose. Apart from that, I wrote    */
2539 /* these functions myself.                                          */
2540 /**********************************************************************/
2541
2542 /*** WGen() - write into one of the external/general registers ***/
2543 static void WGen(const struct cirrusfb_info *cinfo,
2544                   int regnum, unsigned char val)
2545 {
2546         unsigned long regofs = 0;
2547
2548         if (cinfo->btype == BT_PICASSO) {
2549                 /* Picasso II specific hack */
2550 /*            if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2551                   regnum == CL_VSSM2) */
2552                 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2553                         regofs = 0xfff;
2554         }
2555
2556         vga_w(cinfo->regbase, regofs + regnum, val);
2557 }
2558
2559 /*** RGen() - read out one of the external/general registers ***/
2560 static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum)
2561 {
2562         unsigned long regofs = 0;
2563
2564         if (cinfo->btype == BT_PICASSO) {
2565                 /* Picasso II specific hack */
2566 /*            if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2567                   regnum == CL_VSSM2) */
2568                 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2569                         regofs = 0xfff;
2570         }
2571
2572         return vga_r(cinfo->regbase, regofs + regnum);
2573 }
2574
2575 /*** AttrOn() - turn on VideoEnable for Attribute controller ***/
2576 static void AttrOn(const struct cirrusfb_info *cinfo)
2577 {
2578         assert(cinfo != NULL);
2579
2580         DPRINTK("ENTER\n");
2581
2582         if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) {
2583                 /* if we're just in "write value" mode, write back the */
2584                 /* same value as before to not modify anything */
2585                 vga_w(cinfo->regbase, VGA_ATT_IW,
2586                       vga_r(cinfo->regbase, VGA_ATT_R));
2587         }
2588         /* turn on video bit */
2589 /*      vga_w(cinfo->regbase, VGA_ATT_IW, 0x20); */
2590         vga_w(cinfo->regbase, VGA_ATT_IW, 0x33);
2591
2592         /* dummy write on Reg0 to be on "write index" mode next time */
2593         vga_w(cinfo->regbase, VGA_ATT_IW, 0x00);
2594
2595         DPRINTK("EXIT\n");
2596 }
2597
2598 /*** WHDR() - write into the Hidden DAC register ***/
2599 /* as the HDR is the only extension register that requires special treatment
2600  * (the other extension registers are accessible just like the "ordinary"
2601  * registers of their functional group) here is a specialized routine for
2602  * accessing the HDR
2603  */
2604 static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val)
2605 {
2606         unsigned char dummy;
2607
2608         if (cinfo->btype == BT_PICASSO) {
2609                 /* Klaus' hint for correct access to HDR on some boards */
2610                 /* first write 0 to pixel mask (3c6) */
2611                 WGen(cinfo, VGA_PEL_MSK, 0x00);
2612                 udelay(200);
2613                 /* next read dummy from pixel address (3c8) */
2614                 dummy = RGen(cinfo, VGA_PEL_IW);
2615                 udelay(200);
2616         }
2617         /* now do the usual stuff to access the HDR */
2618
2619         dummy = RGen(cinfo, VGA_PEL_MSK);
2620         udelay(200);
2621         dummy = RGen(cinfo, VGA_PEL_MSK);
2622         udelay(200);
2623         dummy = RGen(cinfo, VGA_PEL_MSK);
2624         udelay(200);
2625         dummy = RGen(cinfo, VGA_PEL_MSK);
2626         udelay(200);
2627
2628         WGen(cinfo, VGA_PEL_MSK, val);
2629         udelay(200);
2630
2631         if (cinfo->btype == BT_PICASSO) {
2632                 /* now first reset HDR access counter */
2633                 dummy = RGen(cinfo, VGA_PEL_IW);
2634                 udelay(200);
2635
2636                 /* and at the end, restore the mask value */
2637                 /* ## is this mask always 0xff? */
2638                 WGen(cinfo, VGA_PEL_MSK, 0xff);
2639                 udelay(200);
2640         }
2641 }
2642
2643 /*** WSFR() - write to the "special function register" (SFR) ***/
2644 static void WSFR(struct cirrusfb_info *cinfo, unsigned char val)
2645 {
2646 #ifdef CONFIG_ZORRO
2647         assert(cinfo->regbase != NULL);
2648         cinfo->SFR = val;
2649         z_writeb(val, cinfo->regbase + 0x8000);
2650 #endif
2651 }
2652
2653 /* The Picasso has a second register for switching the monitor bit */
2654 static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val)
2655 {
2656 #ifdef CONFIG_ZORRO
2657         /* writing an arbitrary value to this one causes the monitor switcher */
2658         /* to flip to Amiga display */
2659         assert(cinfo->regbase != NULL);
2660         cinfo->SFR = val;
2661         z_writeb(val, cinfo->regbase + 0x9000);
2662 #endif
2663 }
2664
2665 /*** WClut - set CLUT entry (range: 0..63) ***/
2666 static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
2667             unsigned char green, unsigned char blue)
2668 {
2669         unsigned int data = VGA_PEL_D;
2670
2671         /* address write mode register is not translated.. */
2672         vga_w(cinfo->regbase, VGA_PEL_IW, regnum);
2673
2674         if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2675             cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2676                 /* but DAC data register IS, at least for Picasso II */
2677                 if (cinfo->btype == BT_PICASSO)
2678                         data += 0xfff;
2679                 vga_w(cinfo->regbase, data, red);
2680                 vga_w(cinfo->regbase, data, green);
2681                 vga_w(cinfo->regbase, data, blue);
2682         } else {
2683                 vga_w(cinfo->regbase, data, blue);
2684                 vga_w(cinfo->regbase, data, green);
2685                 vga_w(cinfo->regbase, data, red);
2686         }
2687 }
2688
2689 #if 0
2690 /*** RClut - read CLUT entry (range 0..63) ***/
2691 static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
2692             unsigned char *green, unsigned char *blue)
2693 {
2694         unsigned int data = VGA_PEL_D;
2695
2696         vga_w(cinfo->regbase, VGA_PEL_IR, regnum);
2697
2698         if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2699             cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2700                 if (cinfo->btype == BT_PICASSO)
2701                         data += 0xfff;
2702                 *red = vga_r(cinfo->regbase, data);
2703                 *green = vga_r(cinfo->regbase, data);
2704                 *blue = vga_r(cinfo->regbase, data);
2705         } else {
2706                 *blue = vga_r(cinfo->regbase, data);
2707                 *green = vga_r(cinfo->regbase, data);
2708                 *red = vga_r(cinfo->regbase, data);
2709         }
2710 }
2711 #endif
2712
2713 /*******************************************************************
2714         cirrusfb_WaitBLT()
2715
2716         Wait for the BitBLT engine to complete a possible earlier job
2717 *********************************************************************/
2718
2719 /* FIXME: use interrupts instead */
2720 static void cirrusfb_WaitBLT(u8 __iomem *regbase)
2721 {
2722         /* now busy-wait until we're done */
2723         while (vga_rgfx(regbase, CL_GR31) & 0x08)
2724                 /* do nothing */ ;
2725 }
2726
2727 /*******************************************************************
2728         cirrusfb_BitBLT()
2729
2730         perform accelerated "scrolling"
2731 ********************************************************************/
2732
2733 static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
2734                             u_short curx, u_short cury,
2735                             u_short destx, u_short desty,
2736                             u_short width, u_short height,
2737                             u_short line_length)
2738 {
2739         u_short nwidth, nheight;
2740         u_long nsrc, ndest;
2741         u_char bltmode;
2742
2743         DPRINTK("ENTER\n");
2744
2745         nwidth = width - 1;
2746         nheight = height - 1;
2747
2748         bltmode = 0x00;
2749         /* if source adr < dest addr, do the Blt backwards */
2750         if (cury <= desty) {
2751                 if (cury == desty) {
2752                         /* if src and dest are on the same line, check x */
2753                         if (curx < destx)
2754                                 bltmode |= 0x01;
2755                 } else
2756                         bltmode |= 0x01;
2757         }
2758         if (!bltmode) {
2759                 /* standard case: forward blitting */
2760                 nsrc = (cury * line_length) + curx;
2761                 ndest = (desty * line_length) + destx;
2762         } else {
2763                 /* this means start addresses are at the end,
2764                  * counting backwards
2765                  */
2766                 nsrc = cury * line_length + curx +
2767                         nheight * line_length + nwidth;
2768                 ndest = desty * line_length + destx +
2769                         nheight * line_length + nwidth;
2770         }
2771
2772         /*
2773            run-down of registers to be programmed:
2774            destination pitch
2775            source pitch
2776            BLT width/height
2777            source start
2778            destination start
2779            BLT mode
2780            BLT ROP
2781            VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color"
2782            start/stop
2783          */
2784
2785         cirrusfb_WaitBLT(regbase);
2786
2787         /* pitch: set to line_length */
2788         /* dest pitch low */
2789         vga_wgfx(regbase, CL_GR24, line_length & 0xff);
2790         /* dest pitch hi */
2791         vga_wgfx(regbase, CL_GR25, line_length >> 8);
2792         /* source pitch low */
2793         vga_wgfx(regbase, CL_GR26, line_length & 0xff);
2794         /* source pitch hi */
2795         vga_wgfx(regbase, CL_GR27, line_length >> 8);
2796
2797         /* BLT width: actual number of pixels - 1 */
2798         /* BLT width low */
2799         vga_wgfx(regbase, CL_GR20, nwidth & 0xff);
2800         /* BLT width hi */
2801         vga_wgfx(regbase, CL_GR21, nwidth >> 8);
2802
2803         /* BLT height: actual number of lines -1 */
2804         /* BLT height low */
2805         vga_wgfx(regbase, CL_GR22, nheight & 0xff);
2806         /* BLT width hi */
2807         vga_wgfx(regbase, CL_GR23, nheight >> 8);
2808
2809         /* BLT destination */
2810         /* BLT dest low */
2811         vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
2812         /* BLT dest mid */
2813         vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
2814         /* BLT dest hi */
2815         vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
2816
2817         /* BLT source */
2818         /* BLT src low */
2819         vga_wgfx(regbase, CL_GR2C, (u_char) (nsrc & 0xff));
2820         /* BLT src mid */
2821         vga_wgfx(regbase, CL_GR2D, (u_char) (nsrc >> 8));
2822         /* BLT src hi */
2823         vga_wgfx(regbase, CL_GR2E, (u_char) (nsrc >> 16));
2824
2825         /* BLT mode */
2826         vga_wgfx(regbase, CL_GR30, bltmode);    /* BLT mode */
2827
2828         /* BLT ROP: SrcCopy */
2829         vga_wgfx(regbase, CL_GR32, 0x0d);       /* BLT ROP */
2830
2831         /* and finally: GO! */
2832         vga_wgfx(regbase, CL_GR31, 0x02);       /* BLT Start/status */
2833
2834         DPRINTK("EXIT\n");
2835 }
2836
2837 /*******************************************************************
2838         cirrusfb_RectFill()
2839
2840         perform accelerated rectangle fill
2841 ********************************************************************/
2842
2843 static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
2844                      u_short x, u_short y, u_short width, u_short height,
2845                      u_char color, u_short line_length)
2846 {
2847         u_short nwidth, nheight;
2848         u_long ndest;
2849         u_char op;
2850
2851         DPRINTK("ENTER\n");
2852
2853         nwidth = width - 1;
2854         nheight = height - 1;
2855
2856         ndest = (y * line_length) + x;
2857
2858         cirrusfb_WaitBLT(regbase);
2859
2860         /* pitch: set to line_length */
2861         vga_wgfx(regbase, CL_GR24, line_length & 0xff); /* dest pitch low */
2862         vga_wgfx(regbase, CL_GR25, line_length >> 8);   /* dest pitch hi */
2863         vga_wgfx(regbase, CL_GR26, line_length & 0xff); /* source pitch low */
2864         vga_wgfx(regbase, CL_GR27, line_length >> 8);   /* source pitch hi */
2865
2866         /* BLT width: actual number of pixels - 1 */
2867         vga_wgfx(regbase, CL_GR20, nwidth & 0xff);      /* BLT width low */
2868         vga_wgfx(regbase, CL_GR21, nwidth >> 8);        /* BLT width hi */
2869
2870         /* BLT height: actual number of lines -1 */
2871         vga_wgfx(regbase, CL_GR22, nheight & 0xff);     /* BLT height low */
2872         vga_wgfx(regbase, CL_GR23, nheight >> 8);       /* BLT width hi */
2873
2874         /* BLT destination */
2875         /* BLT dest low */
2876         vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
2877         /* BLT dest mid */
2878         vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
2879         /* BLT dest hi */
2880         vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
2881
2882         /* BLT source: set to 0 (is a dummy here anyway) */
2883         vga_wgfx(regbase, CL_GR2C, 0x00);       /* BLT src low */
2884         vga_wgfx(regbase, CL_GR2D, 0x00);       /* BLT src mid */
2885         vga_wgfx(regbase, CL_GR2E, 0x00);       /* BLT src hi */
2886
2887         /* This is a ColorExpand Blt, using the */
2888         /* same color for foreground and background */
2889         vga_wgfx(regbase, VGA_GFX_SR_VALUE, color);     /* foreground color */
2890         vga_wgfx(regbase, VGA_GFX_SR_ENABLE, color);    /* background color */
2891
2892         op = 0xc0;
2893         if (bits_per_pixel == 16) {
2894                 vga_wgfx(regbase, CL_GR10, color);      /* foreground color */
2895                 vga_wgfx(regbase, CL_GR11, color);      /* background color */
2896                 op = 0x50;
2897                 op = 0xd0;
2898         } else if (bits_per_pixel == 32) {
2899                 vga_wgfx(regbase, CL_GR10, color);      /* foreground color */
2900                 vga_wgfx(regbase, CL_GR11, color);      /* background color */
2901                 vga_wgfx(regbase, CL_GR12, color);      /* foreground color */
2902                 vga_wgfx(regbase, CL_GR13, color);      /* background color */
2903                 vga_wgfx(regbase, CL_GR14, 0);  /* foreground color */
2904                 vga_wgfx(regbase, CL_GR15, 0);  /* background color */
2905                 op = 0x50;
2906                 op = 0xf0;
2907         }
2908         /* BLT mode: color expand, Enable 8x8 copy (faster?) */
2909         vga_wgfx(regbase, CL_GR30, op); /* BLT mode */
2910
2911         /* BLT ROP: SrcCopy */
2912         vga_wgfx(regbase, CL_GR32, 0x0d);       /* BLT ROP */
2913
2914         /* and finally: GO! */
2915         vga_wgfx(regbase, CL_GR31, 0x02);       /* BLT Start/status */
2916
2917         DPRINTK("EXIT\n");
2918 }
2919
2920 /**************************************************************************
2921  * bestclock() - determine closest possible clock lower(?) than the
2922  * desired pixel clock
2923  **************************************************************************/
2924 static void bestclock(long freq, int *nom, int *den, int *div)
2925 {
2926         int n, d;
2927         long h, diff;
2928
2929         assert(nom != NULL);
2930         assert(den != NULL);
2931         assert(div != NULL);
2932
2933         *nom = 0;
2934         *den = 0;
2935         *div = 0;
2936
2937         DPRINTK("ENTER\n");
2938
2939         if (freq < 8000)
2940                 freq = 8000;
2941
2942         diff = freq;
2943
2944         for (n = 32; n < 128; n++) {
2945                 int s = 0;
2946
2947                 d = (14318 * n) / freq;
2948                 if ((d >= 7) && (d <= 63)) {
2949                         int temp = d;
2950
2951                         if (temp > 31) {
2952                                 s = 1;
2953                                 temp >>= 1;
2954                         }
2955                         h = ((14318 * n) / temp) >> s;
2956                         h = h > freq ? h - freq : freq - h;
2957                         if (h < diff) {
2958                                 diff = h;
2959                                 *nom = n;
2960                                 *den = temp;
2961                                 *div = s;
2962                         }
2963                 }
2964                 d++;
2965                 if ((d >= 7) && (d <= 63)) {
2966                         if (d > 31) {
2967                                 s = 1;
2968                                 d >>= 1;
2969                         }
2970                         h = ((14318 * n) / d) >> s;
2971                         h = h > freq ? h - freq : freq - h;
2972                         if (h < diff) {
2973                                 diff = h;
2974                                 *nom = n;
2975                                 *den = d;
2976                                 *div = s;
2977                         }
2978                 }
2979         }
2980
2981         DPRINTK("Best possible values for given frequency:\n");
2982         DPRINTK("       freq: %ld kHz  nom: %d  den: %d  div: %d\n",
2983                 freq, *nom, *den, *div);
2984
2985         DPRINTK("EXIT\n");
2986 }
2987
2988 /* -------------------------------------------------------------------------
2989  *
2990  * debugging functions
2991  *
2992  * -------------------------------------------------------------------------
2993  */
2994
2995 #ifdef CIRRUSFB_DEBUG
2996
2997 /**
2998  * cirrusfb_dbg_print_byte
2999  * @name: name associated with byte value to be displayed
3000  * @val: byte value to be displayed
3001  *
3002  * DESCRIPTION:
3003  * Display an indented string, along with a hexidecimal byte value, and
3004  * its decoded bits.  Bits 7 through 0 are listed in left-to-right
3005  * order.
3006  */
3007
3008 static
3009 void cirrusfb_dbg_print_byte(const char *name, unsigned char val)
3010 {
3011         DPRINTK("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n",
3012                 name, val,
3013                 val & 0x80 ? '1' : '0',
3014                 val & 0x40 ? '1' : '0',
3015                 val & 0x20 ? '1' : '0',
3016                 val & 0x10 ? '1' : '0',
3017                 val & 0x08 ? '1' : '0',
3018                 val & 0x04 ? '1' : '0',
3019                 val & 0x02 ? '1' : '0',
3020                 val & 0x01 ? '1' : '0');
3021 }
3022
3023 /**
3024  * cirrusfb_dbg_print_regs
3025  * @base: If using newmmio, the newmmio base address, otherwise %NULL
3026  * @reg_class: type of registers to read: %CRT, or %SEQ
3027  *
3028  * DESCRIPTION:
3029  * Dumps the given list of VGA CRTC registers.  If @base is %NULL,
3030  * old-style I/O ports are queried for information, otherwise MMIO is
3031  * used at the given @base address to query the information.
3032  */
3033
3034 static
3035 void cirrusfb_dbg_print_regs(caddr_t regbase,
3036                              enum cirrusfb_dbg_reg_class reg_class, ...)
3037 {
3038         va_list list;
3039         unsigned char val = 0;
3040         unsigned reg;
3041         char *name;
3042
3043         va_start(list, reg_class);
3044
3045         name = va_arg(list, char *);
3046         while (name != NULL) {
3047                 reg = va_arg(list, int);
3048
3049                 switch (reg_class) {
3050                 case CRT:
3051                         val = vga_rcrt(regbase, (unsigned char) reg);
3052                         break;
3053                 case SEQ:
3054                         val = vga_rseq(regbase, (unsigned char) reg);
3055                         break;
3056                 default:
3057                         /* should never occur */
3058                         assert(false);
3059                         break;
3060                 }
3061
3062                 cirrusfb_dbg_print_byte(name, val);
3063
3064                 name = va_arg(list, char *);
3065         }
3066
3067         va_end(list);
3068 }
3069
3070 /**
3071  * cirrusfb_dump
3072  * @cirrusfbinfo:
3073  *
3074  * DESCRIPTION:
3075  */
3076
3077 static void cirrusfb_dump(void)
3078 {
3079         cirrusfb_dbg_reg_dump(NULL);
3080 }
3081
3082 /**
3083  * cirrusfb_dbg_reg_dump
3084  * @base: If using newmmio, the newmmio base address, otherwise %NULL
3085  *
3086  * DESCRIPTION:
3087  * Dumps a list of interesting VGA and CIRRUSFB registers.  If @base is %NULL,
3088  * old-style I/O ports are queried for information, otherwise MMIO is
3089  * used at the given @base address to query the information.
3090  */
3091
3092 static
3093 void cirrusfb_dbg_reg_dump(caddr_t regbase)
3094 {
3095         DPRINTK("CIRRUSFB VGA CRTC register dump:\n");
3096
3097         cirrusfb_dbg_print_regs(regbase, CRT,
3098                            "CR00", 0x00,
3099                            "CR01", 0x01,
3100                            "CR02", 0x02,
3101                            "CR03", 0x03,
3102                            "CR04", 0x04,
3103                            "CR05", 0x05,
3104                            "CR06", 0x06,
3105                            "CR07", 0x07,
3106                            "CR08", 0x08,
3107                            "CR09", 0x09,
3108                            "CR0A", 0x0A,
3109                            "CR0B", 0x0B,
3110                            "CR0C", 0x0C,
3111                            "CR0D", 0x0D,
3112                            "CR0E", 0x0E,
3113                            "CR0F", 0x0F,
3114                            "CR10", 0x10,
3115                            "CR11", 0x11,
3116                            "CR12", 0x12,
3117                            "CR13", 0x13,
3118                            "CR14", 0x14,
3119                            "CR15", 0x15,
3120                            "CR16", 0x16,
3121                            "CR17", 0x17,
3122                            "CR18", 0x18,
3123                            "CR22", 0x22,
3124                            "CR24", 0x24,
3125                            "CR26", 0x26,
3126                            "CR2D", 0x2D,
3127                            "CR2E", 0x2E,
3128                            "CR2F", 0x2F,
3129                            "CR30", 0x30,
3130                            "CR31", 0x31,
3131                            "CR32", 0x32,
3132                            "CR33", 0x33,
3133                            "CR34", 0x34,
3134                            "CR35", 0x35,
3135                            "CR36", 0x36,
3136                            "CR37", 0x37,
3137                            "CR38", 0x38,
3138                            "CR39", 0x39,
3139                            "CR3A", 0x3A,
3140                            "CR3B", 0x3B,
3141                            "CR3C", 0x3C,
3142                            "CR3D", 0x3D,
3143                            "CR3E", 0x3E,
3144                            "CR3F", 0x3F,
3145                            NULL);
3146
3147         DPRINTK("\n");
3148
3149         DPRINTK("CIRRUSFB VGA SEQ register dump:\n");
3150
3151         cirrusfb_dbg_print_regs(regbase, SEQ,
3152                            "SR00", 0x00,
3153                            "SR01", 0x01,
3154                            "SR02", 0x02,
3155                            "SR03", 0x03,
3156                            "SR04", 0x04,
3157                            "SR08", 0x08,
3158                            "SR09", 0x09,
3159                            "SR0A", 0x0A,
3160                            "SR0B", 0x0B,
3161                            "SR0D", 0x0D,
3162                            "SR10", 0x10,
3163                            "SR11", 0x11,
3164                            "SR12", 0x12,
3165                            "SR13", 0x13,
3166                            "SR14", 0x14,
3167                            "SR15", 0x15,
3168                            "SR16", 0x16,
3169                            "SR17", 0x17,
3170                            "SR18", 0x18,
3171                            "SR19", 0x19,
3172                            "SR1A", 0x1A,
3173                            "SR1B", 0x1B,
3174                            "SR1C", 0x1C,
3175                            "SR1D", 0x1D,
3176                            "SR1E", 0x1E,
3177                            "SR1F", 0x1F,
3178                            NULL);
3179
3180         DPRINTK("\n");
3181 }
3182
3183 #endif                          /* CIRRUSFB_DEBUG */
3184