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