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