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