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