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