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