Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[linux-2.6] / drivers / video / cirrusfb.c
1 /*
2  * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
3  *
4  * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
5  *
6  * Contributors (thanks, all!)
7  *
8  *      David Eger:
9  *      Overhaul for Linux 2.6
10  *
11  *      Jeff Rugen:
12  *      Major contributions;  Motorola PowerStack (PPC and PCI) support,
13  *      GD54xx, 1280x1024 mode support, change MCLK based on VCLK.
14  *
15  *      Geert Uytterhoeven:
16  *      Excellent code review.
17  *
18  *      Lars Hecking:
19  *      Amiga updates and testing.
20  *
21  * Original cirrusfb author:  Frank Neumann
22  *
23  * Based on retz3fb.c and cirrusfb.c:
24  *      Copyright (C) 1997 Jes Sorensen
25  *      Copyright (C) 1996 Frank Neumann
26  *
27  ***************************************************************
28  *
29  * Format this code with GNU indent '-kr -i8 -pcs' options.
30  *
31  * This file is subject to the terms and conditions of the GNU General Public
32  * License.  See the file COPYING in the main directory of this archive
33  * for more details.
34  *
35  */
36
37 #define CIRRUSFB_VERSION "2.0-pre2"
38
39 #include <linux/module.h>
40 #include <linux/kernel.h>
41 #include <linux/errno.h>
42 #include <linux/string.h>
43 #include <linux/mm.h>
44 #include <linux/slab.h>
45 #include <linux/delay.h>
46 #include <linux/fb.h>
47 #include <linux/init.h>
48 #include <asm/pgtable.h>
49
50 #ifdef CONFIG_ZORRO
51 #include <linux/zorro.h>
52 #endif
53 #ifdef CONFIG_PCI
54 #include <linux/pci.h>
55 #endif
56 #ifdef CONFIG_AMIGA
57 #include <asm/amigahw.h>
58 #endif
59 #ifdef CONFIG_PPC_PREP
60 #include <asm/machdep.h>
61 #define isPReP machine_is(prep)
62 #else
63 #define isPReP 0
64 #endif
65
66 #include <video/vga.h>
67 #include <video/cirrus.h>
68
69 /*****************************************************************
70  *
71  * debugging and utility macros
72  *
73  */
74
75 /* enable debug output? */
76 /* #define CIRRUSFB_DEBUG 1 */
77
78 /* disable runtime assertions? */
79 /* #define CIRRUSFB_NDEBUG */
80
81 /* debug output */
82 #ifdef CIRRUSFB_DEBUG
83 #define DPRINTK(fmt, args...) \
84         printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
85 #else
86 #define DPRINTK(fmt, args...)
87 #endif
88
89 /* debugging assertions */
90 #ifndef CIRRUSFB_NDEBUG
91 #define assert(expr) \
92         if (!(expr)) { \
93                 printk("Assertion failed! %s,%s,%s,line=%d\n", \
94                 #expr, __FILE__, __func__, __LINE__); \
95         }
96 #else
97 #define assert(expr)
98 #endif
99
100 #define MB_ (1024 * 1024)
101
102 /*****************************************************************
103  *
104  * chipset information
105  *
106  */
107
108 /* board types */
109 enum cirrus_board {
110         BT_NONE = 0,
111         BT_SD64,
112         BT_PICCOLO,
113         BT_PICASSO,
114         BT_SPECTRUM,
115         BT_PICASSO4,    /* GD5446 */
116         BT_ALPINE,      /* GD543x/4x */
117         BT_GD5480,
118         BT_LAGUNA,      /* GD546x */
119 };
120
121 /*
122  * per-board-type information, used for enumerating and abstracting
123  * chip-specific information
124  * NOTE: MUST be in the same order as enum cirrus_board in order to
125  * use direct indexing on this array
126  * NOTE: '__initdata' cannot be used as some of this info
127  * is required at runtime.  Maybe separate into an init-only and
128  * a run-time table?
129  */
130 static const struct cirrusfb_board_info_rec {
131         char *name;             /* ASCII name of chipset */
132         long maxclock[5];               /* maximum video clock */
133         /* for  1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */
134         bool init_sr07 : 1; /* init SR07 during init_vgachip() */
135         bool init_sr1f : 1; /* write SR1F during init_vgachip() */
136         /* construct bit 19 of screen start address */
137         bool scrn_start_bit19 : 1;
138
139         /* initial SR07 value, then for each mode */
140         unsigned char sr07;
141         unsigned char sr07_1bpp;
142         unsigned char sr07_1bpp_mux;
143         unsigned char sr07_8bpp;
144         unsigned char sr07_8bpp_mux;
145
146         unsigned char sr1f;     /* SR1F VGA initial register value */
147 } cirrusfb_board_info[] = {
148         [BT_SD64] = {
149                 .name                   = "CL SD64",
150                 .maxclock               = {
151                         /* guess */
152                         /* the SD64/P4 have a higher max. videoclock */
153                         140000, 140000, 140000, 140000, 140000,
154                 },
155                 .init_sr07              = true,
156                 .init_sr1f              = true,
157                 .scrn_start_bit19       = true,
158                 .sr07                   = 0xF0,
159                 .sr07_1bpp              = 0xF0,
160                 .sr07_8bpp              = 0xF1,
161                 .sr1f                   = 0x20
162         },
163         [BT_PICCOLO] = {
164                 .name                   = "CL Piccolo",
165                 .maxclock               = {
166                         /* guess */
167                         90000, 90000, 90000, 90000, 90000
168                 },
169                 .init_sr07              = true,
170                 .init_sr1f              = true,
171                 .scrn_start_bit19       = false,
172                 .sr07                   = 0x80,
173                 .sr07_1bpp              = 0x80,
174                 .sr07_8bpp              = 0x81,
175                 .sr1f                   = 0x22
176         },
177         [BT_PICASSO] = {
178                 .name                   = "CL Picasso",
179                 .maxclock               = {
180                         /* guess */
181                         90000, 90000, 90000, 90000, 90000
182                 },
183                 .init_sr07              = true,
184                 .init_sr1f              = true,
185                 .scrn_start_bit19       = false,
186                 .sr07                   = 0x20,
187                 .sr07_1bpp              = 0x20,
188                 .sr07_8bpp              = 0x21,
189                 .sr1f                   = 0x22
190         },
191         [BT_SPECTRUM] = {
192                 .name                   = "CL Spectrum",
193                 .maxclock               = {
194                         /* guess */
195                         90000, 90000, 90000, 90000, 90000
196                 },
197                 .init_sr07              = true,
198                 .init_sr1f              = true,
199                 .scrn_start_bit19       = false,
200                 .sr07                   = 0x80,
201                 .sr07_1bpp              = 0x80,
202                 .sr07_8bpp              = 0x81,
203                 .sr1f                   = 0x22
204         },
205         [BT_PICASSO4] = {
206                 .name                   = "CL Picasso4",
207                 .maxclock               = {
208                         135100, 135100, 85500, 85500, 0
209                 },
210                 .init_sr07              = true,
211                 .init_sr1f              = false,
212                 .scrn_start_bit19       = true,
213                 .sr07                   = 0x20,
214                 .sr07_1bpp              = 0x20,
215                 .sr07_8bpp              = 0x21,
216                 .sr1f                   = 0
217         },
218         [BT_ALPINE] = {
219                 .name                   = "CL Alpine",
220                 .maxclock               = {
221                         /* for the GD5430.  GD5446 can do more... */
222                         85500, 85500, 50000, 28500, 0
223                 },
224                 .init_sr07              = true,
225                 .init_sr1f              = true,
226                 .scrn_start_bit19       = true,
227                 .sr07                   = 0xA0,
228                 .sr07_1bpp              = 0xA1,
229                 .sr07_1bpp_mux          = 0xA7,
230                 .sr07_8bpp              = 0xA1,
231                 .sr07_8bpp_mux          = 0xA7,
232                 .sr1f                   = 0x1C
233         },
234         [BT_GD5480] = {
235                 .name                   = "CL GD5480",
236                 .maxclock               = {
237                         135100, 200000, 200000, 135100, 135100
238                 },
239                 .init_sr07              = true,
240                 .init_sr1f              = true,
241                 .scrn_start_bit19       = true,
242                 .sr07                   = 0x10,
243                 .sr07_1bpp              = 0x11,
244                 .sr07_8bpp              = 0x11,
245                 .sr1f                   = 0x1C
246         },
247         [BT_LAGUNA] = {
248                 .name                   = "CL Laguna",
249                 .maxclock               = {
250                         /* guess */
251                         135100, 135100, 135100, 135100, 135100,
252                 },
253                 .init_sr07              = false,
254                 .init_sr1f              = false,
255                 .scrn_start_bit19       = true,
256         }
257 };
258
259 #ifdef CONFIG_PCI
260 #define CHIP(id, btype) \
261         { PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
262
263 static struct pci_device_id cirrusfb_pci_table[] = {
264         CHIP(PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE),
265         CHIP(PCI_DEVICE_ID_CIRRUS_5434_8, BT_ALPINE),
266         CHIP(PCI_DEVICE_ID_CIRRUS_5434_4, BT_ALPINE),
267         CHIP(PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE), /* GD-5440 is same id */
268         CHIP(PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE),
269         CHIP(PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE),
270         CHIP(PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480), /* MacPicasso likely */
271         CHIP(PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4), /* Picasso 4 is 5446 */
272         CHIP(PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA), /* CL Laguna */
273         CHIP(PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA), /* CL Laguna 3D */
274         CHIP(PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNA), /* CL Laguna 3DA*/
275         { 0, }
276 };
277 MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
278 #undef CHIP
279 #endif /* CONFIG_PCI */
280
281 #ifdef CONFIG_ZORRO
282 static const struct zorro_device_id cirrusfb_zorro_table[] = {
283         {
284                 .id             = ZORRO_PROD_HELFRICH_SD64_RAM,
285                 .driver_data    = BT_SD64,
286         }, {
287                 .id             = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
288                 .driver_data    = BT_PICCOLO,
289         }, {
290                 .id     = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
291                 .driver_data    = BT_PICASSO,
292         }, {
293                 .id             = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
294                 .driver_data    = BT_SPECTRUM,
295         }, {
296                 .id             = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
297                 .driver_data    = BT_PICASSO4,
298         },
299         { 0 }
300 };
301
302 static const struct {
303         zorro_id id2;
304         unsigned long size;
305 } cirrusfb_zorro_table2[] = {
306         [BT_SD64] = {
307                 .id2    = ZORRO_PROD_HELFRICH_SD64_REG,
308                 .size   = 0x400000
309         },
310         [BT_PICCOLO] = {
311                 .id2    = ZORRO_PROD_HELFRICH_PICCOLO_REG,
312                 .size   = 0x200000
313         },
314         [BT_PICASSO] = {
315                 .id2    = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
316                 .size   = 0x200000
317         },
318         [BT_SPECTRUM] = {
319                 .id2    = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
320                 .size   = 0x200000
321         },
322         [BT_PICASSO4] = {
323                 .id2    = 0,
324                 .size   = 0x400000
325         }
326 };
327 #endif /* CONFIG_ZORRO */
328
329 struct cirrusfb_regs {
330         long freq;
331         long nom;
332         long den;
333         long div;
334         long multiplexing;
335         long mclk;
336         long divMCLK;
337
338         long HorizRes;          /* The x resolution in pixel */
339         long HorizTotal;
340         long HorizDispEnd;
341         long HorizBlankStart;
342         long HorizBlankEnd;
343         long HorizSyncStart;
344         long HorizSyncEnd;
345
346         long VertRes;           /* the physical y resolution in scanlines */
347         long VertTotal;
348         long VertDispEnd;
349         long VertSyncStart;
350         long VertSyncEnd;
351         long VertBlankStart;
352         long VertBlankEnd;
353 };
354
355 #ifdef CIRRUSFB_DEBUG
356 enum cirrusfb_dbg_reg_class {
357         CRT,
358         SEQ
359 };
360 #endif          /* CIRRUSFB_DEBUG */
361
362 /* info about board */
363 struct cirrusfb_info {
364         u8 __iomem *regbase;
365         enum cirrus_board btype;
366         unsigned char SFR;      /* Shadow of special function register */
367
368         struct cirrusfb_regs currentmode;
369         int blank_mode;
370
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         printk(KERN_DEBUG "cirrusfb: This board has %ld bytes of DRAM memory\n",
1953                 info->screen_size);
1954         DPRINTK("EXIT\n");
1955         return;
1956 }
1957
1958 static void switch_monitor(struct cirrusfb_info *cinfo, int on)
1959 {
1960 #ifdef CONFIG_ZORRO /* only works on Zorro boards */
1961         static int IsOn = 0;    /* XXX not ok for multiple boards */
1962
1963         DPRINTK("ENTER\n");
1964
1965         if (cinfo->btype == BT_PICASSO4)
1966                 return;         /* nothing to switch */
1967         if (cinfo->btype == BT_ALPINE)
1968                 return;         /* nothing to switch */
1969         if (cinfo->btype == BT_GD5480)
1970                 return;         /* nothing to switch */
1971         if (cinfo->btype == BT_PICASSO) {
1972                 if ((on && !IsOn) || (!on && IsOn))
1973                         WSFR(cinfo, 0xff);
1974
1975                 DPRINTK("EXIT\n");
1976                 return;
1977         }
1978         if (on) {
1979                 switch (cinfo->btype) {
1980                 case BT_SD64:
1981                         WSFR(cinfo, cinfo->SFR | 0x21);
1982                         break;
1983                 case BT_PICCOLO:
1984                         WSFR(cinfo, cinfo->SFR | 0x28);
1985                         break;
1986                 case BT_SPECTRUM:
1987                         WSFR(cinfo, 0x6f);
1988                         break;
1989                 default: /* do nothing */ break;
1990                 }
1991         } else {
1992                 switch (cinfo->btype) {
1993                 case BT_SD64:
1994                         WSFR(cinfo, cinfo->SFR & 0xde);
1995                         break;
1996                 case BT_PICCOLO:
1997                         WSFR(cinfo, cinfo->SFR & 0xd7);
1998                         break;
1999                 case BT_SPECTRUM:
2000                         WSFR(cinfo, 0x4f);
2001                         break;
2002                 default: /* do nothing */ break;
2003                 }
2004         }
2005
2006         DPRINTK("EXIT\n");
2007 #endif /* CONFIG_ZORRO */
2008 }
2009
2010 /******************************************/
2011 /* Linux 2.6-style  accelerated functions */
2012 /******************************************/
2013
2014 static void cirrusfb_fillrect(struct fb_info *info,
2015                               const struct fb_fillrect *region)
2016 {
2017         struct fb_fillrect modded;
2018         int vxres, vyres;
2019         struct cirrusfb_info *cinfo = info->par;
2020         int m = info->var.bits_per_pixel;
2021         u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
2022                 cinfo->pseudo_palette[region->color] : region->color;
2023
2024         if (info->state != FBINFO_STATE_RUNNING)
2025                 return;
2026         if (info->flags & FBINFO_HWACCEL_DISABLED) {
2027                 cfb_fillrect(info, region);
2028                 return;
2029         }
2030
2031         vxres = info->var.xres_virtual;
2032         vyres = info->var.yres_virtual;
2033
2034         memcpy(&modded, region, sizeof(struct fb_fillrect));
2035
2036         if (!modded.width || !modded.height ||
2037            modded.dx >= vxres || modded.dy >= vyres)
2038                 return;
2039
2040         if (modded.dx + modded.width  > vxres)
2041                 modded.width  = vxres - modded.dx;
2042         if (modded.dy + modded.height > vyres)
2043                 modded.height = vyres - modded.dy;
2044
2045         cirrusfb_RectFill(cinfo->regbase,
2046                           info->var.bits_per_pixel,
2047                           (region->dx * m) / 8, region->dy,
2048                           (region->width * m) / 8, region->height,
2049                           color,
2050                           info->fix.line_length);
2051 }
2052
2053 static void cirrusfb_copyarea(struct fb_info *info,
2054                               const struct fb_copyarea *area)
2055 {
2056         struct fb_copyarea modded;
2057         u32 vxres, vyres;
2058         struct cirrusfb_info *cinfo = info->par;
2059         int m = info->var.bits_per_pixel;
2060
2061         if (info->state != FBINFO_STATE_RUNNING)
2062                 return;
2063         if (info->flags & FBINFO_HWACCEL_DISABLED) {
2064                 cfb_copyarea(info, area);
2065                 return;
2066         }
2067
2068         vxres = info->var.xres_virtual;
2069         vyres = info->var.yres_virtual;
2070         memcpy(&modded, area, sizeof(struct fb_copyarea));
2071
2072         if (!modded.width || !modded.height ||
2073            modded.sx >= vxres || modded.sy >= vyres ||
2074            modded.dx >= vxres || modded.dy >= vyres)
2075                 return;
2076
2077         if (modded.sx + modded.width > vxres)
2078                 modded.width = vxres - modded.sx;
2079         if (modded.dx + modded.width > vxres)
2080                 modded.width = vxres - modded.dx;
2081         if (modded.sy + modded.height > vyres)
2082                 modded.height = vyres - modded.sy;
2083         if (modded.dy + modded.height > vyres)
2084                 modded.height = vyres - modded.dy;
2085
2086         cirrusfb_BitBLT(cinfo->regbase, info->var.bits_per_pixel,
2087                         (area->sx * m) / 8, area->sy,
2088                         (area->dx * m) / 8, area->dy,
2089                         (area->width * m) / 8, area->height,
2090                         info->fix.line_length);
2091
2092 }
2093
2094 static void cirrusfb_imageblit(struct fb_info *info,
2095                                const struct fb_image *image)
2096 {
2097         struct cirrusfb_info *cinfo = info->par;
2098
2099         cirrusfb_WaitBLT(cinfo->regbase);
2100         cfb_imageblit(info, image);
2101 }
2102
2103 #ifdef CONFIG_PPC_PREP
2104 #define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
2105 #define PREP_IO_BASE    ((volatile unsigned char *) 0x80000000)
2106 static void get_prep_addrs(unsigned long *display, unsigned long *registers)
2107 {
2108         DPRINTK("ENTER\n");
2109
2110         *display = PREP_VIDEO_BASE;
2111         *registers = (unsigned long) PREP_IO_BASE;
2112
2113         DPRINTK("EXIT\n");
2114 }
2115
2116 #endif                          /* CONFIG_PPC_PREP */
2117
2118 #ifdef CONFIG_PCI
2119 static int release_io_ports;
2120
2121 /* Pulled the logic from XFree86 Cirrus driver to get the memory size,
2122  * based on the DRAM bandwidth bit and DRAM bank switching bit.  This
2123  * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
2124  * seem to have. */
2125 static unsigned int cirrusfb_get_memsize(u8 __iomem *regbase)
2126 {
2127         unsigned long mem;
2128         unsigned char SRF;
2129
2130         DPRINTK("ENTER\n");
2131
2132         SRF = vga_rseq(regbase, CL_SEQRF);
2133         switch ((SRF & 0x18)) {
2134         case 0x08:
2135                 mem = 512 * 1024;
2136                 break;
2137         case 0x10:
2138                 mem = 1024 * 1024;
2139                 break;
2140         /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory
2141          * on the 5430.
2142          */
2143         case 0x18:
2144                 mem = 2048 * 1024;
2145                 break;
2146         default:
2147                 printk(KERN_WARNING "CLgenfb: Unknown memory size!\n");
2148                 mem = 1024 * 1024;
2149         }
2150         if (SRF & 0x80)
2151         /* If DRAM bank switching is enabled, there must be twice as much
2152          * memory installed. (4MB on the 5434)
2153          */
2154                 mem *= 2;
2155
2156         /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
2157
2158         DPRINTK("EXIT\n");
2159         return mem;
2160 }
2161
2162 static void get_pci_addrs(const struct pci_dev *pdev,
2163                           unsigned long *display, unsigned long *registers)
2164 {
2165         assert(pdev != NULL);
2166         assert(display != NULL);
2167         assert(registers != NULL);
2168
2169         DPRINTK("ENTER\n");
2170
2171         *display = 0;
2172         *registers = 0;
2173
2174         /* This is a best-guess for now */
2175
2176         if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
2177                 *display = pci_resource_start(pdev, 1);
2178                 *registers = pci_resource_start(pdev, 0);
2179         } else {
2180                 *display = pci_resource_start(pdev, 0);
2181                 *registers = pci_resource_start(pdev, 1);
2182         }
2183
2184         assert(*display != 0);
2185
2186         DPRINTK("EXIT\n");
2187 }
2188
2189 static void cirrusfb_pci_unmap(struct fb_info *info)
2190 {
2191         struct cirrusfb_info *cinfo = info->par;
2192         struct pci_dev *pdev = cinfo->pdev;
2193
2194         iounmap(info->screen_base);
2195 #if 0 /* if system didn't claim this region, we would... */
2196         release_mem_region(0xA0000, 65535);
2197 #endif
2198         if (release_io_ports)
2199                 release_region(0x3C0, 32);
2200         pci_release_regions(pdev);
2201 }
2202 #endif /* CONFIG_PCI */
2203
2204 #ifdef CONFIG_ZORRO
2205 static void __devexit cirrusfb_zorro_unmap(struct fb_info *info)
2206 {
2207         struct cirrusfb_info *cinfo = info->par;
2208         zorro_release_device(cinfo->zdev);
2209
2210         if (cinfo->btype == BT_PICASSO4) {
2211                 cinfo->regbase -= 0x600000;
2212                 iounmap((void *)cinfo->regbase);
2213                 iounmap(info->screen_base);
2214         } else {
2215                 if (zorro_resource_start(cinfo->zdev) > 0x01000000)
2216                         iounmap(info->screen_base);
2217         }
2218 }
2219 #endif /* CONFIG_ZORRO */
2220
2221 static int cirrusfb_set_fbinfo(struct fb_info *info)
2222 {
2223         struct cirrusfb_info *cinfo = info->par;
2224         struct fb_var_screeninfo *var = &info->var;
2225
2226         info->pseudo_palette = cinfo->pseudo_palette;
2227         info->flags = FBINFO_DEFAULT
2228                     | FBINFO_HWACCEL_XPAN
2229                     | FBINFO_HWACCEL_YPAN
2230                     | FBINFO_HWACCEL_FILLRECT
2231                     | FBINFO_HWACCEL_COPYAREA;
2232         if (noaccel)
2233                 info->flags |= FBINFO_HWACCEL_DISABLED;
2234         info->fbops = &cirrusfb_ops;
2235         if (cinfo->btype == BT_GD5480) {
2236                 if (var->bits_per_pixel == 16)
2237                         info->screen_base += 1 * MB_;
2238                 if (var->bits_per_pixel == 24 || var->bits_per_pixel == 32)
2239                         info->screen_base += 2 * MB_;
2240         }
2241
2242         /* Fill fix common fields */
2243         strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
2244                 sizeof(info->fix.id));
2245
2246         /* monochrome: only 1 memory plane */
2247         /* 8 bit and above: Use whole memory area */
2248         info->fix.smem_len   = info->screen_size;
2249         if (var->bits_per_pixel == 1)
2250                 info->fix.smem_len /= 4;
2251         info->fix.type_aux   = 0;
2252         info->fix.xpanstep   = 1;
2253         info->fix.ypanstep   = 1;
2254         info->fix.ywrapstep  = 0;
2255
2256         /* FIXME: map region at 0xB8000 if available, fill in here */
2257         info->fix.mmio_len   = 0;
2258         info->fix.accel = FB_ACCEL_NONE;
2259
2260         fb_alloc_cmap(&info->cmap, 256, 0);
2261
2262         return 0;
2263 }
2264
2265 static int cirrusfb_register(struct fb_info *info)
2266 {
2267         struct cirrusfb_info *cinfo = info->par;
2268         int err;
2269         enum cirrus_board btype;
2270
2271         DPRINTK("ENTER\n");
2272
2273         printk(KERN_INFO "cirrusfb: Driver for Cirrus Logic based "
2274                 "graphic boards, v" CIRRUSFB_VERSION "\n");
2275
2276         btype = cinfo->btype;
2277
2278         /* sanity checks */
2279         assert(btype != BT_NONE);
2280
2281         DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base);
2282
2283         /* Make pretend we've set the var so our structures are in a "good" */
2284         /* state, even though we haven't written the mode to the hw yet...  */
2285         info->var = cirrusfb_predefined[cirrusfb_def_mode].var;
2286         info->var.activate = FB_ACTIVATE_NOW;
2287
2288         err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
2289         if (err < 0) {
2290                 /* should never happen */
2291                 DPRINTK("choking on default var... umm, no good.\n");
2292                 goto err_unmap_cirrusfb;
2293         }
2294
2295         /* set all the vital stuff */
2296         cirrusfb_set_fbinfo(info);
2297
2298         err = register_framebuffer(info);
2299         if (err < 0) {
2300                 printk(KERN_ERR "cirrusfb: could not register "
2301                         "fb device; err = %d!\n", err);
2302                 goto err_dealloc_cmap;
2303         }
2304
2305         DPRINTK("EXIT, returning 0\n");
2306         return 0;
2307
2308 err_dealloc_cmap:
2309         fb_dealloc_cmap(&info->cmap);
2310 err_unmap_cirrusfb:
2311         cinfo->unmap(info);
2312         framebuffer_release(info);
2313         return err;
2314 }
2315
2316 static void __devexit cirrusfb_cleanup(struct fb_info *info)
2317 {
2318         struct cirrusfb_info *cinfo = info->par;
2319         DPRINTK("ENTER\n");
2320
2321         switch_monitor(cinfo, 0);
2322
2323         unregister_framebuffer(info);
2324         fb_dealloc_cmap(&info->cmap);
2325         printk("Framebuffer unregistered\n");
2326         cinfo->unmap(info);
2327         framebuffer_release(info);
2328
2329         DPRINTK("EXIT\n");
2330 }
2331
2332 #ifdef CONFIG_PCI
2333 static int cirrusfb_pci_register(struct pci_dev *pdev,
2334                                   const struct pci_device_id *ent)
2335 {
2336         struct cirrusfb_info *cinfo;
2337         struct fb_info *info;
2338         enum cirrus_board btype;
2339         unsigned long board_addr, board_size;
2340         int ret;
2341
2342         ret = pci_enable_device(pdev);
2343         if (ret < 0) {
2344                 printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
2345                 goto err_out;
2346         }
2347
2348         info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev);
2349         if (!info) {
2350                 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2351                 ret = -ENOMEM;
2352                 goto err_disable;
2353         }
2354
2355         cinfo = info->par;
2356         cinfo->pdev = pdev;
2357         cinfo->btype = btype = (enum cirrus_board) ent->driver_data;
2358
2359         DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n",
2360                 pdev->resource[0].start, btype);
2361         DPRINTK(" base address 1 is 0x%x\n", pdev->resource[1].start);
2362
2363         if (isPReP) {
2364                 pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, 0x00000000);
2365 #ifdef CONFIG_PPC_PREP
2366                 get_prep_addrs(&board_addr, &info->fix.mmio_start);
2367 #endif
2368         /* PReP dies if we ioremap the IO registers, but it works w/out... */
2369                 cinfo->regbase = (char __iomem *) info->fix.mmio_start;
2370         } else {
2371                 DPRINTK("Attempt to get PCI info for Cirrus Graphics Card\n");
2372                 get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start);
2373                 /* FIXME: this forces VGA.  alternatives? */
2374                 cinfo->regbase = NULL;
2375         }
2376
2377         DPRINTK("Board address: 0x%lx, register address: 0x%lx\n",
2378                 board_addr, info->fix.mmio_start);
2379
2380         board_size = (btype == BT_GD5480) ?
2381                 32 * MB_ : cirrusfb_get_memsize(cinfo->regbase);
2382
2383         ret = pci_request_regions(pdev, "cirrusfb");
2384         if (ret < 0) {
2385                 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, "
2386                        "abort\n",
2387                        board_addr);
2388                 goto err_release_fb;
2389         }
2390 #if 0 /* if the system didn't claim this region, we would... */
2391         if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
2392                 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n"
2393 ,
2394                        0xA0000L);
2395                 ret = -EBUSY;
2396                 goto err_release_regions;
2397         }
2398 #endif
2399         if (request_region(0x3C0, 32, "cirrusfb"))
2400                 release_io_ports = 1;
2401
2402         info->screen_base = ioremap(board_addr, board_size);
2403         if (!info->screen_base) {
2404                 ret = -EIO;
2405                 goto err_release_legacy;
2406         }
2407
2408         info->fix.smem_start = board_addr;
2409         info->screen_size = board_size;
2410         cinfo->unmap = cirrusfb_pci_unmap;
2411
2412         printk(KERN_INFO "RAM (%lu kB) at 0x%lx, Cirrus "
2413                         "Logic chipset on PCI bus\n",
2414                         info->screen_size >> 10, board_addr);
2415         pci_set_drvdata(pdev, info);
2416
2417         ret = cirrusfb_register(info);
2418         if (ret)
2419                 iounmap(info->screen_base);
2420         return ret;
2421
2422 err_release_legacy:
2423         if (release_io_ports)
2424                 release_region(0x3C0, 32);
2425 #if 0
2426         release_mem_region(0xA0000, 65535);
2427 err_release_regions:
2428 #endif
2429         pci_release_regions(pdev);
2430 err_release_fb:
2431         framebuffer_release(info);
2432 err_disable:
2433 err_out:
2434         return ret;
2435 }
2436
2437 static void __devexit cirrusfb_pci_unregister(struct pci_dev *pdev)
2438 {
2439         struct fb_info *info = pci_get_drvdata(pdev);
2440         DPRINTK("ENTER\n");
2441
2442         cirrusfb_cleanup(info);
2443
2444         DPRINTK("EXIT\n");
2445 }
2446
2447 static struct pci_driver cirrusfb_pci_driver = {
2448         .name           = "cirrusfb",
2449         .id_table       = cirrusfb_pci_table,
2450         .probe          = cirrusfb_pci_register,
2451         .remove         = __devexit_p(cirrusfb_pci_unregister),
2452 #ifdef CONFIG_PM
2453 #if 0
2454         .suspend        = cirrusfb_pci_suspend,
2455         .resume         = cirrusfb_pci_resume,
2456 #endif
2457 #endif
2458 };
2459 #endif /* CONFIG_PCI */
2460
2461 #ifdef CONFIG_ZORRO
2462 static int cirrusfb_zorro_register(struct zorro_dev *z,
2463                                    const struct zorro_device_id *ent)
2464 {
2465         struct cirrusfb_info *cinfo;
2466         struct fb_info *info;
2467         enum cirrus_board btype;
2468         struct zorro_dev *z2 = NULL;
2469         unsigned long board_addr, board_size, size;
2470         int ret;
2471
2472         btype = ent->driver_data;
2473         if (cirrusfb_zorro_table2[btype].id2)
2474                 z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
2475         size = cirrusfb_zorro_table2[btype].size;
2476         printk(KERN_INFO "cirrusfb: %s board detected; ",
2477                cirrusfb_board_info[btype].name);
2478
2479         info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
2480         if (!info) {
2481                 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2482                 ret = -ENOMEM;
2483                 goto err_out;
2484         }
2485
2486         cinfo = info->par;
2487         cinfo->btype = btype;
2488
2489         assert(z);
2490         assert(btype != BT_NONE);
2491
2492         cinfo->zdev = z;
2493         board_addr = zorro_resource_start(z);
2494         board_size = zorro_resource_len(z);
2495         info->screen_size = size;
2496
2497         if (!zorro_request_device(z, "cirrusfb")) {
2498                 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, "
2499                        "abort\n",
2500                        board_addr);
2501                 ret = -EBUSY;
2502                 goto err_release_fb;
2503         }
2504
2505         printk(" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr);
2506
2507         ret = -EIO;
2508
2509         if (btype == BT_PICASSO4) {
2510                 printk(KERN_INFO " REG at $%lx\n", board_addr + 0x600000);
2511
2512                 /* To be precise, for the P4 this is not the */
2513                 /* begin of the board, but the begin of RAM. */
2514                 /* for P4, map in its address space in 2 chunks (### TEST! ) */
2515                 /* (note the ugly hardcoded 16M number) */
2516                 cinfo->regbase = ioremap(board_addr, 16777216);
2517                 if (!cinfo->regbase)
2518                         goto err_release_region;
2519
2520                 DPRINTK("cirrusfb: Virtual address for board set to: $%p\n",
2521                         cinfo->regbase);
2522                 cinfo->regbase += 0x600000;
2523                 info->fix.mmio_start = board_addr + 0x600000;
2524
2525                 info->fix.smem_start = board_addr + 16777216;
2526                 info->screen_base = ioremap(info->fix.smem_start, 16777216);
2527                 if (!info->screen_base)
2528                         goto err_unmap_regbase;
2529         } else {
2530                 printk(KERN_INFO " REG at $%lx\n",
2531                         (unsigned long) z2->resource.start);
2532
2533                 info->fix.smem_start = board_addr;
2534                 if (board_addr > 0x01000000)
2535                         info->screen_base = ioremap(board_addr, board_size);
2536                 else
2537                         info->screen_base = (caddr_t) ZTWO_VADDR(board_addr);
2538                 if (!info->screen_base)
2539                         goto err_release_region;
2540
2541                 /* set address for REG area of board */
2542                 cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start);
2543                 info->fix.mmio_start = z2->resource.start;
2544
2545                 DPRINTK("cirrusfb: Virtual address for board set to: $%p\n",
2546                         cinfo->regbase);
2547         }
2548         cinfo->unmap = cirrusfb_zorro_unmap;
2549
2550         printk(KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
2551         zorro_set_drvdata(z, info);
2552
2553         ret = cirrusfb_register(info);
2554         if (ret) {
2555                 if (btype == BT_PICASSO4) {
2556                         iounmap(info->screen_base);
2557                         iounmap(cinfo->regbase - 0x600000);
2558                 } else if (board_addr > 0x01000000)
2559                         iounmap(info->screen_base);
2560         }
2561         return ret;
2562
2563 err_unmap_regbase:
2564         /* Parental advisory: explicit hack */
2565         iounmap(cinfo->regbase - 0x600000);
2566 err_release_region:
2567         release_region(board_addr, board_size);
2568 err_release_fb:
2569         framebuffer_release(info);
2570 err_out:
2571         return ret;
2572 }
2573
2574 void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
2575 {
2576         struct fb_info *info = zorro_get_drvdata(z);
2577         DPRINTK("ENTER\n");
2578
2579         cirrusfb_cleanup(info);
2580
2581         DPRINTK("EXIT\n");
2582 }
2583
2584 static struct zorro_driver cirrusfb_zorro_driver = {
2585         .name           = "cirrusfb",
2586         .id_table       = cirrusfb_zorro_table,
2587         .probe          = cirrusfb_zorro_register,
2588         .remove         = __devexit_p(cirrusfb_zorro_unregister),
2589 };
2590 #endif /* CONFIG_ZORRO */
2591
2592 static int __init cirrusfb_init(void)
2593 {
2594         int error = 0;
2595
2596 #ifndef MODULE
2597         char *option = NULL;
2598
2599         if (fb_get_options("cirrusfb", &option))
2600                 return -ENODEV;
2601         cirrusfb_setup(option);
2602 #endif
2603
2604 #ifdef CONFIG_ZORRO
2605         error |= zorro_register_driver(&cirrusfb_zorro_driver);
2606 #endif
2607 #ifdef CONFIG_PCI
2608         error |= pci_register_driver(&cirrusfb_pci_driver);
2609 #endif
2610         return error;
2611 }
2612
2613 #ifndef MODULE
2614 static int __init cirrusfb_setup(char *options) {
2615         char *this_opt, s[32];
2616         int i;
2617
2618         DPRINTK("ENTER\n");
2619
2620         if (!options || !*options)
2621                 return 0;
2622
2623         while ((this_opt = strsep(&options, ",")) != NULL) {
2624                 if (!*this_opt) continue;
2625
2626                 DPRINTK("cirrusfb_setup: option '%s'\n", this_opt);
2627
2628                 for (i = 0; i < NUM_TOTAL_MODES; i++) {
2629                         sprintf(s, "mode:%s", cirrusfb_predefined[i].name);
2630                         if (strcmp(this_opt, s) == 0)
2631                                 cirrusfb_def_mode = i;
2632                 }
2633                 if (!strcmp(this_opt, "noaccel"))
2634                         noaccel = 1;
2635         }
2636         return 0;
2637 }
2638 #endif
2639
2640     /*
2641      *  Modularization
2642      */
2643
2644 MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
2645 MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
2646 MODULE_LICENSE("GPL");
2647
2648 static void __exit cirrusfb_exit(void)
2649 {
2650 #ifdef CONFIG_PCI
2651         pci_unregister_driver(&cirrusfb_pci_driver);
2652 #endif
2653 #ifdef CONFIG_ZORRO
2654         zorro_unregister_driver(&cirrusfb_zorro_driver);
2655 #endif
2656 }
2657
2658 module_init(cirrusfb_init);
2659
2660 #ifdef MODULE
2661 module_exit(cirrusfb_exit);
2662 #endif
2663
2664 /**********************************************************************/
2665 /* about the following functions - I have used the same names for the */
2666 /* functions as Markus Wild did in his Retina driver for NetBSD as    */
2667 /* they just made sense for this purpose. Apart from that, I wrote    */
2668 /* these functions myself.                                          */
2669 /**********************************************************************/
2670
2671 /*** WGen() - write into one of the external/general registers ***/
2672 static void WGen(const struct cirrusfb_info *cinfo,
2673                   int regnum, unsigned char val)
2674 {
2675         unsigned long regofs = 0;
2676
2677         if (cinfo->btype == BT_PICASSO) {
2678                 /* Picasso II specific hack */
2679 /*            if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2680                   regnum == CL_VSSM2) */
2681                 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2682                         regofs = 0xfff;
2683         }
2684
2685         vga_w(cinfo->regbase, regofs + regnum, val);
2686 }
2687
2688 /*** RGen() - read out one of the external/general registers ***/
2689 static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum)
2690 {
2691         unsigned long regofs = 0;
2692
2693         if (cinfo->btype == BT_PICASSO) {
2694                 /* Picasso II specific hack */
2695 /*            if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2696                   regnum == CL_VSSM2) */
2697                 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2698                         regofs = 0xfff;
2699         }
2700
2701         return vga_r(cinfo->regbase, regofs + regnum);
2702 }
2703
2704 /*** AttrOn() - turn on VideoEnable for Attribute controller ***/
2705 static void AttrOn(const struct cirrusfb_info *cinfo)
2706 {
2707         assert(cinfo != NULL);
2708
2709         DPRINTK("ENTER\n");
2710
2711         if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) {
2712                 /* if we're just in "write value" mode, write back the */
2713                 /* same value as before to not modify anything */
2714                 vga_w(cinfo->regbase, VGA_ATT_IW,
2715                       vga_r(cinfo->regbase, VGA_ATT_R));
2716         }
2717         /* turn on video bit */
2718 /*      vga_w(cinfo->regbase, VGA_ATT_IW, 0x20); */
2719         vga_w(cinfo->regbase, VGA_ATT_IW, 0x33);
2720
2721         /* dummy write on Reg0 to be on "write index" mode next time */
2722         vga_w(cinfo->regbase, VGA_ATT_IW, 0x00);
2723
2724         DPRINTK("EXIT\n");
2725 }
2726
2727 /*** WHDR() - write into the Hidden DAC register ***/
2728 /* as the HDR is the only extension register that requires special treatment
2729  * (the other extension registers are accessible just like the "ordinary"
2730  * registers of their functional group) here is a specialized routine for
2731  * accessing the HDR
2732  */
2733 static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val)
2734 {
2735         unsigned char dummy;
2736
2737         if (cinfo->btype == BT_PICASSO) {
2738                 /* Klaus' hint for correct access to HDR on some boards */
2739                 /* first write 0 to pixel mask (3c6) */
2740                 WGen(cinfo, VGA_PEL_MSK, 0x00);
2741                 udelay(200);
2742                 /* next read dummy from pixel address (3c8) */
2743                 dummy = RGen(cinfo, VGA_PEL_IW);
2744                 udelay(200);
2745         }
2746         /* now do the usual stuff to access the HDR */
2747
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         dummy = RGen(cinfo, VGA_PEL_MSK);
2755         udelay(200);
2756
2757         WGen(cinfo, VGA_PEL_MSK, val);
2758         udelay(200);
2759
2760         if (cinfo->btype == BT_PICASSO) {
2761                 /* now first reset HDR access counter */
2762                 dummy = RGen(cinfo, VGA_PEL_IW);
2763                 udelay(200);
2764
2765                 /* and at the end, restore the mask value */
2766                 /* ## is this mask always 0xff? */
2767                 WGen(cinfo, VGA_PEL_MSK, 0xff);
2768                 udelay(200);
2769         }
2770 }
2771
2772 /*** WSFR() - write to the "special function register" (SFR) ***/
2773 static void WSFR(struct cirrusfb_info *cinfo, unsigned char val)
2774 {
2775 #ifdef CONFIG_ZORRO
2776         assert(cinfo->regbase != NULL);
2777         cinfo->SFR = val;
2778         z_writeb(val, cinfo->regbase + 0x8000);
2779 #endif
2780 }
2781
2782 /* The Picasso has a second register for switching the monitor bit */
2783 static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val)
2784 {
2785 #ifdef CONFIG_ZORRO
2786         /* writing an arbitrary value to this one causes the monitor switcher */
2787         /* to flip to Amiga display */
2788         assert(cinfo->regbase != NULL);
2789         cinfo->SFR = val;
2790         z_writeb(val, cinfo->regbase + 0x9000);
2791 #endif
2792 }
2793
2794 /*** WClut - set CLUT entry (range: 0..63) ***/
2795 static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
2796             unsigned char green, unsigned char blue)
2797 {
2798         unsigned int data = VGA_PEL_D;
2799
2800         /* address write mode register is not translated.. */
2801         vga_w(cinfo->regbase, VGA_PEL_IW, regnum);
2802
2803         if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2804             cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2805                 /* but DAC data register IS, at least for Picasso II */
2806                 if (cinfo->btype == BT_PICASSO)
2807                         data += 0xfff;
2808                 vga_w(cinfo->regbase, data, red);
2809                 vga_w(cinfo->regbase, data, green);
2810                 vga_w(cinfo->regbase, data, blue);
2811         } else {
2812                 vga_w(cinfo->regbase, data, blue);
2813                 vga_w(cinfo->regbase, data, green);
2814                 vga_w(cinfo->regbase, data, red);
2815         }
2816 }
2817
2818 #if 0
2819 /*** RClut - read CLUT entry (range 0..63) ***/
2820 static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
2821             unsigned char *green, unsigned char *blue)
2822 {
2823         unsigned int data = VGA_PEL_D;
2824
2825         vga_w(cinfo->regbase, VGA_PEL_IR, regnum);
2826
2827         if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2828             cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2829                 if (cinfo->btype == BT_PICASSO)
2830                         data += 0xfff;
2831                 *red = vga_r(cinfo->regbase, data);
2832                 *green = vga_r(cinfo->regbase, data);
2833                 *blue = vga_r(cinfo->regbase, data);
2834         } else {
2835                 *blue = vga_r(cinfo->regbase, data);
2836                 *green = vga_r(cinfo->regbase, data);
2837                 *red = vga_r(cinfo->regbase, data);
2838         }
2839 }
2840 #endif
2841
2842 /*******************************************************************
2843         cirrusfb_WaitBLT()
2844
2845         Wait for the BitBLT engine to complete a possible earlier job
2846 *********************************************************************/
2847
2848 /* FIXME: use interrupts instead */
2849 static void cirrusfb_WaitBLT(u8 __iomem *regbase)
2850 {
2851         /* now busy-wait until we're done */
2852         while (vga_rgfx(regbase, CL_GR31) & 0x08)
2853                 /* do nothing */ ;
2854 }
2855
2856 /*******************************************************************
2857         cirrusfb_BitBLT()
2858
2859         perform accelerated "scrolling"
2860 ********************************************************************/
2861
2862 static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
2863                             u_short curx, u_short cury,
2864                             u_short destx, u_short desty,
2865                             u_short width, u_short height,
2866                             u_short line_length)
2867 {
2868         u_short nwidth, nheight;
2869         u_long nsrc, ndest;
2870         u_char bltmode;
2871
2872         DPRINTK("ENTER\n");
2873
2874         nwidth = width - 1;
2875         nheight = height - 1;
2876
2877         bltmode = 0x00;
2878         /* if source adr < dest addr, do the Blt backwards */
2879         if (cury <= desty) {
2880                 if (cury == desty) {
2881                         /* if src and dest are on the same line, check x */
2882                         if (curx < destx)
2883                                 bltmode |= 0x01;
2884                 } else
2885                         bltmode |= 0x01;
2886         }
2887         if (!bltmode) {
2888                 /* standard case: forward blitting */
2889                 nsrc = (cury * line_length) + curx;
2890                 ndest = (desty * line_length) + destx;
2891         } else {
2892                 /* this means start addresses are at the end,
2893                  * counting backwards
2894                  */
2895                 nsrc = cury * line_length + curx +
2896                         nheight * line_length + nwidth;
2897                 ndest = desty * line_length + destx +
2898                         nheight * line_length + nwidth;
2899         }
2900
2901         /*
2902            run-down of registers to be programmed:
2903            destination pitch
2904            source pitch
2905            BLT width/height
2906            source start
2907            destination start
2908            BLT mode
2909            BLT ROP
2910            VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color"
2911            start/stop
2912          */
2913
2914         cirrusfb_WaitBLT(regbase);
2915
2916         /* pitch: set to line_length */
2917         /* dest pitch low */
2918         vga_wgfx(regbase, CL_GR24, line_length & 0xff);
2919         /* dest pitch hi */
2920         vga_wgfx(regbase, CL_GR25, line_length >> 8);
2921         /* source pitch low */
2922         vga_wgfx(regbase, CL_GR26, line_length & 0xff);
2923         /* source pitch hi */
2924         vga_wgfx(regbase, CL_GR27, line_length >> 8);
2925
2926         /* BLT width: actual number of pixels - 1 */
2927         /* BLT width low */
2928         vga_wgfx(regbase, CL_GR20, nwidth & 0xff);
2929         /* BLT width hi */
2930         vga_wgfx(regbase, CL_GR21, nwidth >> 8);
2931
2932         /* BLT height: actual number of lines -1 */
2933         /* BLT height low */
2934         vga_wgfx(regbase, CL_GR22, nheight & 0xff);
2935         /* BLT width hi */
2936         vga_wgfx(regbase, CL_GR23, nheight >> 8);
2937
2938         /* BLT destination */
2939         /* BLT dest low */
2940         vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
2941         /* BLT dest mid */
2942         vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
2943         /* BLT dest hi */
2944         vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
2945
2946         /* BLT source */
2947         /* BLT src low */
2948         vga_wgfx(regbase, CL_GR2C, (u_char) (nsrc & 0xff));
2949         /* BLT src mid */
2950         vga_wgfx(regbase, CL_GR2D, (u_char) (nsrc >> 8));
2951         /* BLT src hi */
2952         vga_wgfx(regbase, CL_GR2E, (u_char) (nsrc >> 16));
2953
2954         /* BLT mode */
2955         vga_wgfx(regbase, CL_GR30, bltmode);    /* BLT mode */
2956
2957         /* BLT ROP: SrcCopy */
2958         vga_wgfx(regbase, CL_GR32, 0x0d);       /* BLT ROP */
2959
2960         /* and finally: GO! */
2961         vga_wgfx(regbase, CL_GR31, 0x02);       /* BLT Start/status */
2962
2963         DPRINTK("EXIT\n");
2964 }
2965
2966 /*******************************************************************
2967         cirrusfb_RectFill()
2968
2969         perform accelerated rectangle fill
2970 ********************************************************************/
2971
2972 static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
2973                      u_short x, u_short y, u_short width, u_short height,
2974                      u_char color, u_short line_length)
2975 {
2976         u_short nwidth, nheight;
2977         u_long ndest;
2978         u_char op;
2979
2980         DPRINTK("ENTER\n");
2981
2982         nwidth = width - 1;
2983         nheight = height - 1;
2984
2985         ndest = (y * line_length) + x;
2986
2987         cirrusfb_WaitBLT(regbase);
2988
2989         /* pitch: set to line_length */
2990         vga_wgfx(regbase, CL_GR24, line_length & 0xff); /* dest pitch low */
2991         vga_wgfx(regbase, CL_GR25, line_length >> 8);   /* dest pitch hi */
2992         vga_wgfx(regbase, CL_GR26, line_length & 0xff); /* source pitch low */
2993         vga_wgfx(regbase, CL_GR27, line_length >> 8);   /* source pitch hi */
2994
2995         /* BLT width: actual number of pixels - 1 */
2996         vga_wgfx(regbase, CL_GR20, nwidth & 0xff);      /* BLT width low */
2997         vga_wgfx(regbase, CL_GR21, nwidth >> 8);        /* BLT width hi */
2998
2999         /* BLT height: actual number of lines -1 */
3000         vga_wgfx(regbase, CL_GR22, nheight & 0xff);     /* BLT height low */
3001         vga_wgfx(regbase, CL_GR23, nheight >> 8);       /* BLT width hi */
3002
3003         /* BLT destination */
3004         /* BLT dest low */
3005         vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
3006         /* BLT dest mid */
3007         vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
3008         /* BLT dest hi */
3009         vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
3010
3011         /* BLT source: set to 0 (is a dummy here anyway) */
3012         vga_wgfx(regbase, CL_GR2C, 0x00);       /* BLT src low */
3013         vga_wgfx(regbase, CL_GR2D, 0x00);       /* BLT src mid */
3014         vga_wgfx(regbase, CL_GR2E, 0x00);       /* BLT src hi */
3015
3016         /* This is a ColorExpand Blt, using the */
3017         /* same color for foreground and background */
3018         vga_wgfx(regbase, VGA_GFX_SR_VALUE, color);     /* foreground color */
3019         vga_wgfx(regbase, VGA_GFX_SR_ENABLE, color);    /* background color */
3020
3021         op = 0xc0;
3022         if (bits_per_pixel == 16) {
3023                 vga_wgfx(regbase, CL_GR10, color);      /* foreground color */
3024                 vga_wgfx(regbase, CL_GR11, color);      /* background color */
3025                 op = 0x50;
3026                 op = 0xd0;
3027         } else if (bits_per_pixel == 32) {
3028                 vga_wgfx(regbase, CL_GR10, color);      /* foreground color */
3029                 vga_wgfx(regbase, CL_GR11, color);      /* background color */
3030                 vga_wgfx(regbase, CL_GR12, color);      /* foreground color */
3031                 vga_wgfx(regbase, CL_GR13, color);      /* background color */
3032                 vga_wgfx(regbase, CL_GR14, 0);  /* foreground color */
3033                 vga_wgfx(regbase, CL_GR15, 0);  /* background color */
3034                 op = 0x50;
3035                 op = 0xf0;
3036         }
3037         /* BLT mode: color expand, Enable 8x8 copy (faster?) */
3038         vga_wgfx(regbase, CL_GR30, op); /* BLT mode */
3039
3040         /* BLT ROP: SrcCopy */
3041         vga_wgfx(regbase, CL_GR32, 0x0d);       /* BLT ROP */
3042
3043         /* and finally: GO! */
3044         vga_wgfx(regbase, CL_GR31, 0x02);       /* BLT Start/status */
3045
3046         DPRINTK("EXIT\n");
3047 }
3048
3049 /**************************************************************************
3050  * bestclock() - determine closest possible clock lower(?) than the
3051  * desired pixel clock
3052  **************************************************************************/
3053 static void bestclock(long freq, long *best, long *nom,
3054                        long *den, long *div, long maxfreq)
3055 {
3056         long n, h, d, f;
3057
3058         assert(best != NULL);
3059         assert(nom != NULL);
3060         assert(den != NULL);
3061         assert(div != NULL);
3062         assert(maxfreq > 0);
3063
3064         *nom = 0;
3065         *den = 0;
3066         *div = 0;
3067
3068         DPRINTK("ENTER\n");
3069
3070         if (freq < 8000)
3071                 freq = 8000;
3072
3073         if (freq > maxfreq)
3074                 freq = maxfreq;
3075
3076         *best = 0;
3077         f = freq * 10;
3078
3079         for (n = 32; n < 128; n++) {
3080                 d = (143181 * n) / f;
3081                 if ((d >= 7) && (d <= 63)) {
3082                         if (d > 31)
3083                                 d = (d / 2) * 2;
3084                         h = (14318 * n) / d;
3085                         if (abs(h - freq) < abs(*best - freq)) {
3086                                 *best = h;
3087                                 *nom = n;
3088                                 if (d < 32) {
3089                                         *den = d;
3090                                         *div = 0;
3091                                 } else {
3092                                         *den = d / 2;
3093                                         *div = 1;
3094                                 }
3095                         }
3096                 }
3097                 d = DIV_ROUND_UP(143181 * n, f);
3098                 if ((d >= 7) && (d <= 63)) {
3099                         if (d > 31)
3100                                 d = (d / 2) * 2;
3101                         h = (14318 * n) / d;
3102                         if (abs(h - freq) < abs(*best - freq)) {
3103                                 *best = h;
3104                                 *nom = n;
3105                                 if (d < 32) {
3106                                         *den = d;
3107                                         *div = 0;
3108                                 } else {
3109                                         *den = d / 2;
3110                                         *div = 1;
3111                                 }
3112                         }
3113                 }
3114         }
3115
3116         DPRINTK("Best possible values for given frequency:\n");
3117         DPRINTK("       best: %ld kHz  nom: %ld  den: %ld  div: %ld\n",
3118                 freq, *nom, *den, *div);
3119
3120         DPRINTK("EXIT\n");
3121 }
3122
3123 /* -------------------------------------------------------------------------
3124  *
3125  * debugging functions
3126  *
3127  * -------------------------------------------------------------------------
3128  */
3129
3130 #ifdef CIRRUSFB_DEBUG
3131
3132 /**
3133  * cirrusfb_dbg_print_byte
3134  * @name: name associated with byte value to be displayed
3135  * @val: byte value to be displayed
3136  *
3137  * DESCRIPTION:
3138  * Display an indented string, along with a hexidecimal byte value, and
3139  * its decoded bits.  Bits 7 through 0 are listed in left-to-right
3140  * order.
3141  */
3142
3143 static
3144 void cirrusfb_dbg_print_byte(const char *name, unsigned char val)
3145 {
3146         DPRINTK("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n",
3147                 name, val,
3148                 val & 0x80 ? '1' : '0',
3149                 val & 0x40 ? '1' : '0',
3150                 val & 0x20 ? '1' : '0',
3151                 val & 0x10 ? '1' : '0',
3152                 val & 0x08 ? '1' : '0',
3153                 val & 0x04 ? '1' : '0',
3154                 val & 0x02 ? '1' : '0',
3155                 val & 0x01 ? '1' : '0');
3156 }
3157
3158 /**
3159  * cirrusfb_dbg_print_regs
3160  * @base: If using newmmio, the newmmio base address, otherwise %NULL
3161  * @reg_class: type of registers to read: %CRT, or %SEQ
3162  *
3163  * DESCRIPTION:
3164  * Dumps the given list of VGA CRTC registers.  If @base is %NULL,
3165  * old-style I/O ports are queried for information, otherwise MMIO is
3166  * used at the given @base address to query the information.
3167  */
3168
3169 static
3170 void cirrusfb_dbg_print_regs(caddr_t regbase,
3171                              enum cirrusfb_dbg_reg_class reg_class, ...)
3172 {
3173         va_list list;
3174         unsigned char val = 0;
3175         unsigned reg;
3176         char *name;
3177
3178         va_start(list, reg_class);
3179
3180         name = va_arg(list, char *);
3181         while (name != NULL) {
3182                 reg = va_arg(list, int);
3183
3184                 switch (reg_class) {
3185                 case CRT:
3186                         val = vga_rcrt(regbase, (unsigned char) reg);
3187                         break;
3188                 case SEQ:
3189                         val = vga_rseq(regbase, (unsigned char) reg);
3190                         break;
3191                 default:
3192                         /* should never occur */
3193                         assert(false);
3194                         break;
3195                 }
3196
3197                 cirrusfb_dbg_print_byte(name, val);
3198
3199                 name = va_arg(list, char *);
3200         }
3201
3202         va_end(list);
3203 }
3204
3205 /**
3206  * cirrusfb_dump
3207  * @cirrusfbinfo:
3208  *
3209  * DESCRIPTION:
3210  */
3211
3212 static void cirrusfb_dump(void)
3213 {
3214         cirrusfb_dbg_reg_dump(NULL);
3215 }
3216
3217 /**
3218  * cirrusfb_dbg_reg_dump
3219  * @base: If using newmmio, the newmmio base address, otherwise %NULL
3220  *
3221  * DESCRIPTION:
3222  * Dumps a list of interesting VGA and CIRRUSFB registers.  If @base is %NULL,
3223  * old-style I/O ports are queried for information, otherwise MMIO is
3224  * used at the given @base address to query the information.
3225  */
3226
3227 static
3228 void cirrusfb_dbg_reg_dump(caddr_t regbase)
3229 {
3230         DPRINTK("CIRRUSFB VGA CRTC register dump:\n");
3231
3232         cirrusfb_dbg_print_regs(regbase, CRT,
3233                            "CR00", 0x00,
3234                            "CR01", 0x01,
3235                            "CR02", 0x02,
3236                            "CR03", 0x03,
3237                            "CR04", 0x04,
3238                            "CR05", 0x05,
3239                            "CR06", 0x06,
3240                            "CR07", 0x07,
3241                            "CR08", 0x08,
3242                            "CR09", 0x09,
3243                            "CR0A", 0x0A,
3244                            "CR0B", 0x0B,
3245                            "CR0C", 0x0C,
3246                            "CR0D", 0x0D,
3247                            "CR0E", 0x0E,
3248                            "CR0F", 0x0F,
3249                            "CR10", 0x10,
3250                            "CR11", 0x11,
3251                            "CR12", 0x12,
3252                            "CR13", 0x13,
3253                            "CR14", 0x14,
3254                            "CR15", 0x15,
3255                            "CR16", 0x16,
3256                            "CR17", 0x17,
3257                            "CR18", 0x18,
3258                            "CR22", 0x22,
3259                            "CR24", 0x24,
3260                            "CR26", 0x26,
3261                            "CR2D", 0x2D,
3262                            "CR2E", 0x2E,
3263                            "CR2F", 0x2F,
3264                            "CR30", 0x30,
3265                            "CR31", 0x31,
3266                            "CR32", 0x32,
3267                            "CR33", 0x33,
3268                            "CR34", 0x34,
3269                            "CR35", 0x35,
3270                            "CR36", 0x36,
3271                            "CR37", 0x37,
3272                            "CR38", 0x38,
3273                            "CR39", 0x39,
3274                            "CR3A", 0x3A,
3275                            "CR3B", 0x3B,
3276                            "CR3C", 0x3C,
3277                            "CR3D", 0x3D,
3278                            "CR3E", 0x3E,
3279                            "CR3F", 0x3F,
3280                            NULL);
3281
3282         DPRINTK("\n");
3283
3284         DPRINTK("CIRRUSFB VGA SEQ register dump:\n");
3285
3286         cirrusfb_dbg_print_regs(regbase, SEQ,
3287                            "SR00", 0x00,
3288                            "SR01", 0x01,
3289                            "SR02", 0x02,
3290                            "SR03", 0x03,
3291                            "SR04", 0x04,
3292                            "SR08", 0x08,
3293                            "SR09", 0x09,
3294                            "SR0A", 0x0A,
3295                            "SR0B", 0x0B,
3296                            "SR0D", 0x0D,
3297                            "SR10", 0x10,
3298                            "SR11", 0x11,
3299                            "SR12", 0x12,
3300                            "SR13", 0x13,
3301                            "SR14", 0x14,
3302                            "SR15", 0x15,
3303                            "SR16", 0x16,
3304                            "SR17", 0x17,
3305                            "SR18", 0x18,
3306                            "SR19", 0x19,
3307                            "SR1A", 0x1A,
3308                            "SR1B", 0x1B,
3309                            "SR1C", 0x1C,
3310                            "SR1D", 0x1D,
3311                            "SR1E", 0x1E,
3312                            "SR1F", 0x1F,
3313                            NULL);
3314
3315         DPRINTK("\n");
3316 }
3317
3318 #endif                          /* CIRRUSFB_DEBUG */
3319