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