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