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