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