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