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