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