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