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