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