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