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