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