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