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