make oldconfig will rebuild these...
[linux-2.4.21-pre4.git] / drivers / video / cyberfb.c
1 /*
2 * linux/drivers/video/cyberfb.c -- CyberVision64 frame buffer device
3 * $Id: cyberfb.c,v 1.1.1.1 2005/04/11 02:50:41 jack Exp $
4 *
5 *    Copyright (C) 1998 Alan Bair
6 *
7 * This file is based on two CyberVision64 frame buffer device drivers
8 *
9 * The second CyberVision64 frame buffer device (cvision.c cvision_core.c):
10 *
11 *   Copyright (c) 1997 Antonio Santos
12 *
13 * Released as a patch to 2.1.35, but never included in the source tree.
14 * This is based on work from the NetBSD CyberVision64 frame buffer driver 
15 * and support files (grf_cv.c, grf_cvreg.h, ite_cv.c):
16 * Permission to use the source of this driver was obtained from the
17 * author Michael Teske by Alan Bair.
18 *
19 *   Copyright (c) 1995 Michael Teske
20 *
21 * The first CyberVision64 frame buffer device (cyberfb.c):
22 *
23 *    Copyright (C) 1996 Martin Apel
24 *                       Geert Uytterhoeven
25 *
26 * Which is based on the Amiga frame buffer device (amifb.c):
27 *
28 *    Copyright (C) 1995 Geert Uytterhoeven
29 *
30 *
31 * History:
32 *   - 22 Dec 95: Original version by Martin Apel
33 *   - 05 Jan 96: Geert: integration into the current source tree
34 *   - 01 Aug 98: Alan: Merge in code from cvision.c and cvision_core.c
35 * $Log: cyberfb.c,v $
36 * Revision 1.1.1.1  2005/04/11 02:50:41  jack
37 * first release
38 *
39 * Revision 1.1.1.1  2005/01/10 13:16:42  jack
40 * First release
41 *
42 * Revision 1.6  1998/09/11 04:54:58  abair
43 * Update for 2.1.120 change in include file location.
44 * Clean up for public release.
45 *
46 * Revision 1.5  1998/09/03 04:27:13  abair
47 * Move cv64_load_video_mode to cyber_set_video so a new video mode is install
48 * with each change of the 'var' data.
49 *
50 * Revision 1.4  1998/09/01 00:31:17  abair
51 * Put in a set of default 8,16,24 bpp modes and map cyber8,16 to them.
52 * Update operations with 'par' to handle a more complete set of parameter
53 * values for encode/decode process.
54 *
55 * Revision 1.3  1998/08/31 21:31:33  abair
56 * Swap 800x490 for 640x480 video mode and more cleanup.
57 * Abandon idea to resurrect "custom" mode setting via kernel opts,
58 * instead work on making use of fbset program to do this.
59 *
60 * Revision 1.2  1998/08/31 06:17:08  abair
61 * Make updates for changes in cyberfb.c released in 2.1.119
62 * and do some cleanup of the code.
63 *
64 * Revision 1.1  1998/08/29 18:38:31  abair
65 * Initial revision
66 *
67 * Revision 1.3  1998/08/17 06:21:53  abair
68 * Remove more redundant code after merging in cvision_core.c
69 * Set blanking by colormap to pale red to detect this vs trying to
70 * use video blanking. More formating to Linux code style.
71 *
72 * Revision 1.2  1998/08/15 17:51:37  abair
73 * Added cvision_core.c code from 2.1.35 patches.
74 * Changed to compile correctly and switch to using initialization
75 * code. Added debugging and dropping of duplicate code.
76 *
77 *
78 *
79 * This file is subject to the terms and conditions of the GNU General Public
80 * License.  See the file COPYING in the main directory of this archive
81 * for more details.
82 */
83
84
85 #include <linux/module.h>
86 #include <linux/kernel.h>
87 #include <linux/errno.h>
88 #include <linux/string.h>
89 #include <linux/mm.h>
90 #include <linux/tty.h>
91 #include <linux/slab.h>
92 #include <linux/delay.h>
93 #include <linux/zorro.h>
94 #include <linux/fb.h>
95 #include <linux/init.h>
96 #include <asm/uaccess.h>
97 #include <asm/system.h>
98 #include <asm/irq.h>
99 #include <asm/pgtable.h>
100 #include <asm/amigahw.h>
101 #include <asm/io.h>
102
103 #include "cyberfb.h"
104 #include <video/fbcon.h>
105 #include <video/fbcon-cfb8.h>
106 #include <video/fbcon-cfb16.h>
107
108 /*#define CYBERFBDEBUG*/
109 #ifdef CYBERFBDEBUG
110 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
111 static void cv64_dump(void);
112 #else
113 #define DPRINTK(fmt, args...)
114 #endif
115
116 #define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat)
117 #define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg))
118
119 #define ww_64(regs,reg,dat) (*((volatile unsigned short *)(regs + reg) = dat)
120
121 struct cyberfb_par {
122         struct fb_var_screeninfo var;
123         __u32 type;
124         __u32 type_aux;
125         __u32 visual;
126         __u32 line_length;
127 };
128
129 static struct cyberfb_par current_par;
130
131 static int current_par_valid = 0;
132 static int currcon = 0;
133
134 static struct display disp;
135 static struct fb_info fb_info;
136
137
138 /*
139  *    Frame Buffer Name
140  */
141
142 static char cyberfb_name[16] = "Cybervision";
143
144
145 /*
146  *    CyberVision Graphics Board
147  */
148
149 static unsigned char Cyber_colour_table [256][3];
150 static unsigned long CyberSize;
151 static volatile unsigned char *CyberBase;
152 static volatile unsigned char *CyberMem;
153 static volatile unsigned char *CyberRegs;
154 static unsigned long CyberMem_phys;
155 static unsigned long CyberRegs_phys;
156
157 /*
158  *    Predefined Video Modes
159  */
160
161 static struct {
162     const char *name;
163     struct fb_var_screeninfo var;
164 } cyberfb_predefined[] __initdata = {
165         { "640x480-8", {                /* Default 8 BPP mode (cyber8) */
166                 640, 480, 640, 480, 0, 0, 8, 0,
167                 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
168                 0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
169                 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, 
170                 FB_VMODE_NONINTERLACED
171         }}, 
172         { "640x480-16", {               /* Default 16 BPP mode (cyber16) */
173                 640, 480, 640, 480, 0, 0, 16, 0,
174                 {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
175                 0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
176                 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, 
177                 FB_VMODE_NONINTERLACED
178         }}, 
179         { "640x480-24", {               /* Default 24 BPP mode */
180                 640, 480, 640, 480, 0, 0, 24, 0,
181                 {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {0, 0, 0},
182                 0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
183                 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, 
184                 FB_VMODE_NONINTERLACED
185         }}, 
186         { "800x490-8", {                /* Cybervision 8 bpp */
187                 /* NO Acceleration */
188                 800, 490, 800, 490, 0, 0, 8, 0,
189                 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
190                 0, 0, -1, -1, FB_ACCEL_NONE, 33333, 80, 24, 23, 1, 56, 8,
191                 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
192                 FB_VMODE_NONINTERLACED
193         }},
194 /* I can't test these with my monitor, but I suspect they will
195  * be OK, since Antonio Santos indicated he had tested them in
196  * his system.
197  */
198         { "800x600-8", {                /* Cybervision 8 bpp */
199                 800, 600, 800, 600, 0, 0, 8, 0,
200                 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
201                 0, 0, -1, -1, FB_ACCELF_TEXT, 27778, 64, 24, 22, 1, 72, 2,
202                 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
203                 FB_VMODE_NONINTERLACED
204         }},
205         { "1024x768-8", {               /* Cybervision 8 bpp */
206                 1024, 768, 1024, 768, 0, 0, 8, 0,
207                 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
208                 0, 0, -1, -1, FB_ACCELF_TEXT, 16667, 224, 72, 60, 12, 168, 4,
209                 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
210                 FB_VMODE_NONINTERLACED
211         }},
212         { "1152x886-8", {               /* Cybervision 8 bpp */
213                 1152, 886, 1152, 886, 0, 0, 8, 0,
214                 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
215                 0, 0, -1, -1, FB_ACCELF_TEXT, 15873, 184, 40, 24, 1, 56, 16,
216                 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
217                 FB_VMODE_NONINTERLACED
218         }},
219         { "1280x1024-8", {      /* Cybervision 8 bpp */
220                 1280, 1024, 1280, 1024, 0, 0, 8, 0,
221                 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
222                 0, 0, -1, -1, FB_ACCELF_TEXT, 16667, 256, 48, 50, 12, 72, 4,
223                 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
224                 FB_VMODE_INTERLACED
225         }}
226 };
227
228 #define NUM_TOTAL_MODES    ARRAY_SIZE(cyberfb_predefined)
229
230 static int Cyberfb_inverse = 0;
231
232 /*
233  *    Some default modes
234  */
235
236 #define CYBER8_DEFMODE     (0)
237 #define CYBER16_DEFMODE    (1)
238
239 static struct fb_var_screeninfo cyberfb_default;
240 static int cyberfb_usermode __initdata = 0;
241
242 /*
243  *    Interface used by the world
244  */
245
246 int cyberfb_setup(char *options);
247
248 static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
249                            struct fb_info *info);
250 static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
251                            struct fb_info *info);
252 static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
253                            struct fb_info *info);
254 static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
255                             struct fb_info *info);
256 static int cyberfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
257                             struct fb_info *info);
258
259 /*
260  *    Interface to the low level console driver
261  */
262
263 int cyberfb_init(void);
264 static int Cyberfb_switch(int con, struct fb_info *info);
265 static int Cyberfb_updatevar(int con, struct fb_info *info);
266 static void Cyberfb_blank(int blank, struct fb_info *info);
267
268 /*
269  *    Text console acceleration
270  */
271
272 #ifdef FBCON_HAS_CFB8
273 static struct display_switch fbcon_cyber8;
274 #endif
275
276 /*
277  *    Accelerated Functions used by the low level console driver
278  */
279
280 static void Cyber_WaitQueue(u_short fifo);
281 static void Cyber_WaitBlit(void);
282 static void Cyber_BitBLT(u_short curx, u_short cury, u_short destx,
283                          u_short desty, u_short width, u_short height,
284                          u_short mode);
285 static void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height,
286                            u_short mode, u_short color);
287 #if 0
288 static void Cyber_MoveCursor(u_short x, u_short y);
289 #endif
290
291 /*
292  *   Hardware Specific Routines
293  */
294
295 static int Cyber_init(void);
296 static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
297                             struct cyberfb_par *par);
298 static int Cyber_decode_var(struct fb_var_screeninfo *var,
299                             struct cyberfb_par *par);
300 static int Cyber_encode_var(struct fb_var_screeninfo *var,
301                             struct cyberfb_par *par);
302 static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
303                            u_int *transp, struct fb_info *info);
304 static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
305                            u_int transp, struct fb_info *info);
306
307 /*
308  *    Internal routines
309  */
310
311 static void cyberfb_get_par(struct cyberfb_par *par);
312 static void cyberfb_set_par(struct cyberfb_par *par);
313 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
314 static void do_install_cmap(int con, struct fb_info *info);
315 static void cyberfb_set_disp(int con, struct fb_info *info);
316 static int get_video_mode(const char *name);
317
318 /* For cvision_core.c */
319 static unsigned short cv64_compute_clock(unsigned long);
320 static int cv_has_4mb (volatile unsigned char *);
321 static void cv64_board_init (void);
322 static void cv64_load_video_mode (struct fb_var_screeninfo *);
323
324
325 /* -------------------- Hardware specific routines ------------------------- */
326
327
328 /*
329  *    Initialization
330  *
331  *    Set the default video mode for this chipset. If a video mode was
332  *    specified on the command line, it will override the default mode.
333  */
334
335 static int Cyber_init(void)
336 {
337         volatile unsigned char *regs = CyberRegs;
338         volatile unsigned long *CursorBase;
339         int i;
340         DPRINTK("ENTER\n");
341
342 /* Init local cmap as greyscale levels */
343         for (i = 0; i < 256; i++) {
344                 Cyber_colour_table [i][0] = i;
345                 Cyber_colour_table [i][1] = i;
346                 Cyber_colour_table [i][2] = i;
347         }
348
349 /* Initialize the board and determine fbmem size */
350         cv64_board_init(); 
351 #ifdef CYBERFBDEBUG
352         DPRINTK("Register state after initing board\n");
353         cv64_dump();
354 #endif
355 /* Clear framebuffer memory */
356         DPRINTK("Clear framebuffer memory\n");
357         memset ((char *)CyberMem, 0, CyberSize);
358
359 /* Disable hardware cursor */
360         DPRINTK("Disable HW cursor\n");
361         wb_64(regs, S3_CRTC_ADR, S3_REG_LOCK2);
362         wb_64(regs, S3_CRTC_DATA, 0xa0);
363         wb_64(regs, S3_CRTC_ADR, S3_HGC_MODE);
364         wb_64(regs, S3_CRTC_DATA, 0x00);
365         wb_64(regs, S3_CRTC_ADR, S3_HWGC_DX);
366         wb_64(regs, S3_CRTC_DATA, 0x00);
367         wb_64(regs, S3_CRTC_ADR, S3_HWGC_DY);
368         wb_64(regs, S3_CRTC_DATA, 0x00);
369
370 /* Initialize hardware cursor */
371         DPRINTK("Init HW cursor\n");
372         CursorBase = (u_long *)((char *)(CyberMem) + CyberSize - 0x400);
373         for (i=0; i < 8; i++)
374         {
375                 *(CursorBase  +(i*4)) = 0xffffff00;
376                 *(CursorBase+1+(i*4)) = 0xffff0000;
377                 *(CursorBase+2+(i*4)) = 0xffff0000;
378                 *(CursorBase+3+(i*4)) = 0xffff0000;
379         }
380         for (i=8; i < 64; i++)
381         {
382                 *(CursorBase  +(i*4)) = 0xffff0000;
383                 *(CursorBase+1+(i*4)) = 0xffff0000;
384                 *(CursorBase+2+(i*4)) = 0xffff0000;
385                 *(CursorBase+3+(i*4)) = 0xffff0000;
386         }
387
388         Cyber_setcolreg (255, 56<<8, 100<<8, 160<<8, 0, NULL /* unused */);
389         Cyber_setcolreg (254, 0, 0, 0, 0, NULL /* unused */);
390
391         DPRINTK("EXIT\n");
392         return 0;
393 }
394
395
396 /*
397  *    This function should fill in the `fix' structure based on the
398  *    values in the `par' structure.
399  */
400
401 static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
402                             struct cyberfb_par *par)
403 {
404         DPRINTK("ENTER\n");
405         memset(fix, 0, sizeof(struct fb_fix_screeninfo));
406         strcpy(fix->id, cyberfb_name);
407         fix->smem_start = CyberMem_phys;
408         fix->smem_len = CyberSize;
409         fix->mmio_start = CyberRegs_phys;
410         fix->mmio_len = 0x10000;
411
412         fix->type = FB_TYPE_PACKED_PIXELS;
413         fix->type_aux = 0;
414         if (par->var.bits_per_pixel == 15 || par->var.bits_per_pixel == 16 ||
415             par->var.bits_per_pixel == 24 || par->var.bits_per_pixel == 32) {
416                 fix->visual = FB_VISUAL_DIRECTCOLOR;
417         } else {
418                 fix->visual = FB_VISUAL_PSEUDOCOLOR;
419         }
420
421         fix->xpanstep = 0;
422         fix->ypanstep = 0;
423         fix->ywrapstep = 0;
424         fix->line_length = 0;
425         fix->accel = FB_ACCEL_S3_TRIO64;
426
427         DPRINTK("EXIT\n");
428         return(0);
429 }
430
431
432 /*
433 *    Fill the `par' structure based on the values in `var'.
434 *    TODO: Verify and adjust values, return -EINVAL if bad.
435 */
436
437 static int Cyber_decode_var(struct fb_var_screeninfo *var,
438                             struct cyberfb_par *par)
439 {
440         DPRINTK("ENTER\n");
441         par->var.xres = var->xres;
442         par->var.yres = var->yres;
443         par->var.xres_virtual = var->xres_virtual;
444         par->var.yres_virtual = var->yres_virtual;
445         par->var.xoffset = var->xoffset;
446         par->var.yoffset = var->yoffset;
447         par->var.bits_per_pixel = var->bits_per_pixel;
448         par->var.grayscale = var->grayscale;
449         par->var.red = var->red;
450         par->var.green = var->green;
451         par->var.blue = var->blue;
452         par->var.transp = var->transp;
453         par->var.nonstd = var->nonstd;
454         par->var.activate = var->activate;
455         par->var.height = var->height;
456         par->var.width = var->width;
457         if (var->accel_flags & FB_ACCELF_TEXT) {
458                 par->var.accel_flags = FB_ACCELF_TEXT;
459         } else {
460                 par->var.accel_flags = 0;
461         }
462         par->var.pixclock = var->pixclock;
463         par->var.left_margin = var->left_margin;
464         par->var.right_margin = var->right_margin;
465         par->var.upper_margin = var->upper_margin;
466         par->var.lower_margin = var->lower_margin;
467         par->var.hsync_len = var->hsync_len;
468         par->var.vsync_len = var->vsync_len;
469         par->var.sync = var->sync;
470         par->var.vmode = var->vmode;
471         DPRINTK("EXIT\n");
472         return(0);
473 }
474
475 /*
476 *    Fill the `var' structure based on the values in `par' and maybe
477 *    other values read out of the hardware.
478 */
479
480 static int Cyber_encode_var(struct fb_var_screeninfo *var,
481                             struct cyberfb_par *par)
482 {
483         DPRINTK("ENTER\n");
484         var->xres = par->var.xres;
485         var->yres = par->var.yres;
486         var->xres_virtual = par->var.xres_virtual;
487         var->yres_virtual = par->var.yres_virtual;
488         var->xoffset = par->var.xoffset;
489         var->yoffset = par->var.yoffset;
490
491         var->bits_per_pixel = par->var.bits_per_pixel;
492         var->grayscale = par->var.grayscale;
493
494         var->red = par->var.red;
495         var->green = par->var.green;
496         var->blue = par->var.blue;
497         var->transp = par->var.transp;
498
499         var->nonstd = par->var.nonstd;
500         var->activate = par->var.activate;
501
502         var->height = par->var.height;
503         var->width = par->var.width;
504
505         var->accel_flags = par->var.accel_flags;
506
507         var->pixclock = par->var.pixclock;
508         var->left_margin = par->var.left_margin;
509         var->right_margin = par->var.right_margin;
510         var->upper_margin = par->var.upper_margin;
511         var->lower_margin = par->var.lower_margin;
512         var->hsync_len = par->var.hsync_len;
513         var->vsync_len = par->var.vsync_len;
514         var->sync = par->var.sync;
515         var->vmode = par->var.vmode;
516         
517         DPRINTK("EXIT\n");
518         return(0);
519 }
520
521
522 /*
523  *    Set a single color register. Return != 0 for invalid regno.
524  */
525
526 static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
527                            u_int transp, struct fb_info *info)
528 {
529         volatile unsigned char *regs = CyberRegs;
530
531         /*DPRINTK("ENTER\n");*/
532         if (regno > 255) {
533                 DPRINTK("EXIT - Register # > 255\n");
534                 return (1);
535         }
536
537         wb_64(regs, 0x3c8, (unsigned char) regno);
538
539         red >>= 10;
540         green >>= 10;
541         blue >>= 10;
542
543         Cyber_colour_table [regno][0] = red;
544         Cyber_colour_table [regno][1] = green;
545         Cyber_colour_table [regno][2] = blue;
546
547         wb_64(regs, 0x3c9, red);
548         wb_64(regs, 0x3c9, green);
549         wb_64(regs, 0x3c9, blue);
550
551         /*DPRINTK("EXIT\n");*/
552         return (0);
553 }
554
555
556 /*
557 *    Read a single color register and split it into
558 *    colors/transparent. Return != 0 for invalid regno.
559 */
560
561 static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
562                            u_int *transp, struct fb_info *info)
563 {
564         int t;
565
566         /*DPRINTK("ENTER\n");*/
567         if (regno > 255) {
568                 DPRINTK("EXIT - Register # > 255\n");
569                 return (1);
570         }
571         /* ARB This shifting & oring seems VERY strange */
572         t       = Cyber_colour_table [regno][0];
573         *red    = (t<<10) | (t<<4) | (t>>2);
574         t       = Cyber_colour_table [regno][1];
575         *green  = (t<<10) | (t<<4) | (t>>2);
576         t       = Cyber_colour_table [regno][2];
577         *blue   = (t<<10) | (t<<4) | (t>>2);
578         *transp = 0;
579         /*DPRINTK("EXIT\n");*/
580         return (0);
581 }
582
583
584 /*
585 *    (Un)Blank the screen
586 *    blank: 1 = zero fb cmap
587 *           0 = restore fb cmap from local cmap
588 */
589
590 void Cyberfb_blank(int blank, struct fb_info *info)
591 {
592         volatile unsigned char *regs = CyberRegs;
593         int i;
594
595         DPRINTK("ENTER\n");
596 #if 0
597 /* Blank by turning gfx off */
598         gfx_on_off (1, regs);
599 #else
600         if (blank) {
601                 for (i = 0; i < 256; i++) {
602                         wb_64(regs, 0x3c8, (unsigned char) i);
603                         /* ARB Pale red to detect this blanking method */
604                         wb_64(regs, 0x3c9, 48); 
605                         wb_64(regs, 0x3c9, 0);
606                         wb_64(regs, 0x3c9, 0);
607                 }
608         } else {
609                 for (i = 0; i < 256; i++) {
610                         wb_64(regs, 0x3c8, (unsigned char) i);
611                         wb_64(regs, 0x3c9, Cyber_colour_table[i][0]);
612                         wb_64(regs, 0x3c9, Cyber_colour_table[i][1]);
613                         wb_64(regs, 0x3c9, Cyber_colour_table[i][2]);
614                 }
615         }
616 #endif
617         DPRINTK("EXIT\n");
618 }
619
620
621 /**************************************************************
622  * We are waiting for "fifo" FIFO-slots empty
623  */
624 static void Cyber_WaitQueue (u_short fifo)
625 {
626         unsigned short status;
627
628         DPRINTK("ENTER\n");
629         do {
630                 status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
631         } while (status & fifo);
632         DPRINTK("EXIT\n");
633 }
634
635 /**************************************************************
636  * We are waiting for Hardware (Graphics Engine) not busy
637  */
638 static void Cyber_WaitBlit (void)
639 {
640         unsigned short status;
641
642         DPRINTK("ENTER\n");
643         do {
644                 status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
645         } while (status & S3_HDW_BUSY);
646         DPRINTK("EXIT\n");
647 }
648
649 /**************************************************************
650  * BitBLT - Through the Plane
651  */
652 static void Cyber_BitBLT (u_short curx, u_short cury, u_short destx,
653                           u_short desty, u_short width, u_short height,
654                           u_short mode)
655 {
656         volatile unsigned char *regs = CyberRegs;
657         u_short blitcmd = S3_BITBLT;
658
659         DPRINTK("ENTER\n");
660         /* Set drawing direction */
661         /* -Y, X maj, -X (default) */
662         if (curx > destx) {
663                 blitcmd |= 0x0020;  /* Drawing direction +X */
664         } else {
665                 curx  += (width - 1);
666                 destx += (width - 1);
667         }
668
669         if (cury > desty) {
670                 blitcmd |= 0x0080;  /* Drawing direction +Y */
671         } else {
672                 cury  += (height - 1);
673                 desty += (height - 1);
674         }
675
676         Cyber_WaitQueue (0x8000);
677
678         *((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
679         *((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0060 | mode);
680
681         *((u_short volatile *)(regs + S3_CUR_X)) = curx;
682         *((u_short volatile *)(regs + S3_CUR_Y)) = cury;
683
684         *((u_short volatile *)(regs + S3_DESTX_DIASTP)) = destx;
685         *((u_short volatile *)(regs + S3_DESTY_AXSTP)) = desty;
686
687         *((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
688         *((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width  - 1;
689
690         *((u_short volatile *)(regs + S3_CMD)) = blitcmd;
691         DPRINTK("EXIT\n");
692 }
693
694 /**************************************************************
695  * Rectangle Fill Solid
696  */
697 static void Cyber_RectFill (u_short x, u_short y, u_short width,
698                             u_short height, u_short mode, u_short color)
699 {
700         volatile unsigned char *regs = CyberRegs;
701         u_short blitcmd = S3_FILLEDRECT;
702
703         DPRINTK("ENTER\n");
704         Cyber_WaitQueue (0x8000);
705
706         *((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
707         *((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0020 | mode);
708
709         *((u_short volatile *)(regs + S3_MULT_MISC)) = 0xe000;
710         *((u_short volatile *)(regs + S3_FRGD_COLOR)) = color;
711
712         *((u_short volatile *)(regs + S3_CUR_X)) = x;
713         *((u_short volatile *)(regs + S3_CUR_Y)) = y;
714
715         *((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
716         *((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width  - 1;
717
718         *((u_short volatile *)(regs + S3_CMD)) = blitcmd;
719         DPRINTK("EXIT\n");
720 }
721
722
723 #if 0
724 /**************************************************************
725  * Move cursor to x, y
726  */
727 static void Cyber_MoveCursor (u_short x, u_short y)
728 {
729         volatile unsigned char *regs = CyberRegs;
730         DPRINTK("ENTER\n");
731         *(regs + S3_CRTC_ADR)  = 0x39;
732         *(regs + S3_CRTC_DATA) = 0xa0;
733
734         *(regs + S3_CRTC_ADR)  = S3_HWGC_ORGX_H;
735         *(regs + S3_CRTC_DATA) = (char)((x & 0x0700) >> 8);
736         *(regs + S3_CRTC_ADR)  = S3_HWGC_ORGX_L;
737         *(regs + S3_CRTC_DATA) = (char)(x & 0x00ff);
738
739         *(regs + S3_CRTC_ADR)  = S3_HWGC_ORGY_H;
740         *(regs + S3_CRTC_DATA) = (char)((y & 0x0700) >> 8);
741         *(regs + S3_CRTC_ADR)  = S3_HWGC_ORGY_L;
742         *(regs + S3_CRTC_DATA) = (char)(y & 0x00ff);
743         DPRINTK("EXIT\n");
744 }
745 #endif
746
747
748 /* -------------------- Generic routines ---------------------------------- */
749
750
751 /*
752  *    Fill the hardware's `par' structure.
753  */
754
755 static void cyberfb_get_par(struct cyberfb_par *par)
756 {
757         DPRINTK("ENTER\n");
758         if (current_par_valid) {
759                 *par = current_par;
760         } else {
761                 Cyber_decode_var(&cyberfb_default, par);
762         }
763         DPRINTK("EXIT\n");
764 }
765
766
767 static void cyberfb_set_par(struct cyberfb_par *par)
768 {
769         DPRINTK("ENTER\n");
770         current_par = *par;
771         current_par_valid = 1;
772         DPRINTK("EXIT\n");
773 }
774
775
776 static void cyber_set_video(struct fb_var_screeninfo *var)
777 {
778
779         /* Load the video mode defined by the 'var' data */
780         cv64_load_video_mode (var);
781 #ifdef CYBERFBDEBUG
782         DPRINTK("Register state after loading video mode\n");
783         cv64_dump();
784 #endif
785 }
786
787
788 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
789 {
790         int err, activate;
791         struct cyberfb_par par;
792
793         DPRINTK("ENTER\n");
794         if ((err = Cyber_decode_var(var, &par))) {
795                 DPRINTK("EXIT - decode_var failed\n");
796                 return(err);
797         }
798         activate = var->activate;
799         if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
800                 cyberfb_set_par(&par);
801         Cyber_encode_var(var, &par);
802         var->activate = activate;
803
804         cyber_set_video(var);
805         DPRINTK("EXIT\n");
806         return 0;
807 }
808
809
810 static void do_install_cmap(int con, struct fb_info *info)
811 {
812         DPRINTK("ENTER\n");
813         if (con != currcon) {
814                 DPRINTK("EXIT - Not current console\n");
815                 return;
816         }
817         if (fb_display[con].cmap.len) {
818                 DPRINTK("Use console cmap\n");
819                 fb_set_cmap(&fb_display[con].cmap, 1, Cyber_setcolreg, info);
820         } else {
821                 DPRINTK("Use default cmap\n");
822                 fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
823                             1, Cyber_setcolreg, info);
824         }
825         DPRINTK("EXIT\n");
826 }
827
828 /*
829  *    Get the Fixed Part of the Display
830  */
831
832 static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
833                            struct fb_info *info)
834 {
835         struct cyberfb_par par;
836         int error = 0;
837
838         DPRINTK("ENTER\n");
839         if (con == -1) {
840                 cyberfb_get_par(&par);
841         } else {
842                 error = Cyber_decode_var(&fb_display[con].var, &par);
843         }
844         DPRINTK("EXIT\n");
845         return(error ? error : Cyber_encode_fix(fix, &par));
846 }
847
848
849 /*
850  *    Get the User Defined Part of the Display
851  */
852
853 static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
854                            struct fb_info *info)
855 {
856         struct cyberfb_par par;
857         int error = 0;
858
859         DPRINTK("ENTER\n");
860         if (con == -1) {
861                 cyberfb_get_par(&par);
862                 error = Cyber_encode_var(var, &par);
863                 disp.var = *var;   /* ++Andre: don't know if this is the right place */
864         } else {
865                 *var = fb_display[con].var;
866         }
867
868         DPRINTK("EXIT\n");
869         return(error);
870 }
871
872
873 static void cyberfb_set_disp(int con, struct fb_info *info)
874 {
875         struct fb_fix_screeninfo fix;
876         struct display *display;
877
878         DPRINTK("ENTER\n");
879         if (con >= 0)
880                 display = &fb_display[con];
881         else
882                 display = &disp;        /* used during initialization */
883
884         cyberfb_get_fix(&fix, con, info);
885         if (con == -1)
886                 con = 0;
887         display->screen_base = (unsigned char *)CyberMem;
888         display->visual = fix.visual;
889         display->type = fix.type;
890         display->type_aux = fix.type_aux;
891         display->ypanstep = fix.ypanstep;
892         display->ywrapstep = fix.ywrapstep;
893         display->can_soft_blank = 1;
894         display->inverse = Cyberfb_inverse;
895         switch (display->var.bits_per_pixel) {
896 #ifdef FBCON_HAS_CFB8
897             case 8:
898                 if (display->var.accel_flags & FB_ACCELF_TEXT) {
899                     display->dispsw = &fbcon_cyber8;
900 #warning FIXME: We should reinit the graphics engine here
901                 } else
902                     display->dispsw = &fbcon_cfb8;
903                 break;
904 #endif
905 #ifdef FBCON_HAS_CFB16
906             case 16:
907                 display->dispsw = &fbcon_cfb16;
908                 break;
909 #endif
910             default:
911                 display->dispsw = NULL;
912                 break;
913         }
914         DPRINTK("EXIT\n");
915 }
916
917
918 /*
919  *    Set the User Defined Part of the Display
920  */
921
922 static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
923                            struct fb_info *info)
924 {
925         int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
926
927         DPRINTK("ENTER\n");
928         if ((err = do_fb_set_var(var, con == currcon))) {
929                 DPRINTK("EXIT - do_fb_set_var failed\n");
930                 return(err);
931         }
932         if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
933                 oldxres = fb_display[con].var.xres;
934                 oldyres = fb_display[con].var.yres;
935                 oldvxres = fb_display[con].var.xres_virtual;
936                 oldvyres = fb_display[con].var.yres_virtual;
937                 oldbpp = fb_display[con].var.bits_per_pixel;
938                 oldaccel = fb_display[con].var.accel_flags;
939                 fb_display[con].var = *var;
940                 if (oldxres != var->xres || oldyres != var->yres ||
941                     oldvxres != var->xres_virtual ||
942                     oldvyres != var->yres_virtual ||
943                     oldbpp != var->bits_per_pixel ||
944                     oldaccel != var->accel_flags) {
945                         cyberfb_set_disp(con, info);
946                         (*fb_info.changevar)(con);
947                         fb_alloc_cmap(&fb_display[con].cmap, 0, 0);
948                         do_install_cmap(con, info);
949                 }
950         }
951         var->activate = 0;
952         DPRINTK("EXIT\n");
953         return(0);
954 }
955
956
957 /*
958  *    Get the Colormap
959  */
960
961 static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
962                             struct fb_info *info)
963 {
964         DPRINTK("ENTER\n");
965         if (con == currcon) { /* current console? */
966                 DPRINTK("EXIT - console is current console\n");
967                 return(fb_get_cmap(cmap, kspc, Cyber_getcolreg, info));
968         } else if (fb_display[con].cmap.len) { /* non default colormap? */
969                 DPRINTK("Use console cmap\n");
970                 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
971         } else {
972                 DPRINTK("Use default cmap\n");
973                 fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
974                              cmap, kspc ? 0 : 2);
975         }
976         DPRINTK("EXIT\n");
977         return(0);
978 }
979
980
981 /*
982  *    Set the Colormap
983  */
984
985 static int cyberfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
986                             struct fb_info *info)
987 {
988         int err;
989
990         DPRINTK("ENTER\n");
991         if (!fb_display[con].cmap.len) {       /* no colormap allocated? */
992                 if ((err = fb_alloc_cmap(&fb_display[con].cmap,
993                                          1<<fb_display[con].var.bits_per_pixel,
994                                          0))) {
995                         DPRINTK("EXIT - fb_alloc_cmap failed\n");
996                         return(err);
997                 }
998         }
999         if (con == currcon) {            /* current console? */
1000                 DPRINTK("EXIT - Current console\n");
1001                 return(fb_set_cmap(cmap, kspc, Cyber_setcolreg, info));
1002         } else {
1003                 fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
1004         }
1005         DPRINTK("EXIT\n");
1006         return(0);
1007 }
1008
1009
1010 static struct fb_ops cyberfb_ops = {
1011         owner:          THIS_MODULE,
1012         fb_get_fix:     cyberfb_get_fix,
1013         fb_get_var:     cyberfb_get_var,
1014         fb_set_var:     cyberfb_set_var,
1015         fb_get_cmap:    cyberfb_get_cmap,
1016         fb_set_cmap:    cyberfb_set_cmap,
1017 };
1018
1019 int __init cyberfb_setup(char *options)
1020 {
1021         char *this_opt;
1022         DPRINTK("ENTER\n");
1023
1024         fb_info.fontname[0] = '\0';
1025
1026         if (!options || !*options) {
1027                 DPRINTK("EXIT - no options\n");
1028                 return 0;
1029         }
1030
1031         while ((this_opt = strsep(&options, ",")) != NULL) {
1032                 if (!*this_opt)
1033                         continue;
1034                 if (!strcmp(this_opt, "inverse")) {
1035                         Cyberfb_inverse = 1;
1036                         fb_invert_cmaps();
1037                 } else if (!strncmp(this_opt, "font:", 5)) {
1038                         strcpy(fb_info.fontname, this_opt+5);
1039                 } else if (!strcmp (this_opt, "cyber8")) {
1040                         cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
1041                         cyberfb_usermode = 1;
1042                 } else if (!strcmp (this_opt, "cyber16")) {
1043                         cyberfb_default = cyberfb_predefined[CYBER16_DEFMODE].var;
1044                         cyberfb_usermode = 1;
1045                 } else get_video_mode(this_opt);
1046         }
1047
1048         DPRINTK("default mode: xres=%d, yres=%d, bpp=%d\n",
1049                 cyberfb_default.xres,
1050                 cyberfb_default.yres,
1051                 cyberfb_default.bits_per_pixel);
1052         DPRINTK("EXIT\n");
1053         return 0;
1054 }
1055
1056 /*
1057  *    Initialization
1058  */
1059
1060 int __init cyberfb_init(void)
1061 {
1062         unsigned long board_addr, board_size;
1063         struct cyberfb_par par;
1064         struct zorro_dev *z = NULL;
1065         DPRINTK("ENTER\n");
1066
1067         while ((z = zorro_find_device(ZORRO_PROD_PHASE5_CYBERVISION64, z))) {
1068             board_addr = z->resource.start;
1069             board_size = z->resource.end-z->resource.start+1;
1070             CyberMem_phys = board_addr + 0x01400000;
1071             CyberRegs_phys = CyberMem_phys + 0x00c00000;
1072             if (!request_mem_region(CyberRegs_phys, 0x10000, "S3 Trio64"))
1073                 continue;
1074             if (!request_mem_region(CyberMem_phys, 0x400000, "RAM")) {
1075                 release_mem_region(CyberRegs_phys, 0x10000);
1076                 continue;
1077             }
1078             DPRINTK("board_addr=%08lx\n", board_addr);
1079             DPRINTK("board_size=%08lx\n", board_size);
1080
1081             CyberBase = ioremap(board_addr, board_size);
1082             CyberRegs = CyberBase + 0x02000000;
1083             CyberMem = CyberBase + 0x01400000;
1084             DPRINTK("CyberBase=%08lx CyberRegs=%08lx CyberMem=%08lx\n",
1085                     CyberBase, (long unsigned int)CyberRegs, CyberMem);
1086
1087 #ifdef CYBERFBDEBUG
1088             DPRINTK("Register state just after mapping memory\n");
1089             cv64_dump();
1090 #endif
1091
1092             strcpy(fb_info.modename, cyberfb_name);
1093             fb_info.changevar = NULL;
1094             fb_info.node = -1;
1095             fb_info.fbops = &cyberfb_ops;
1096             fb_info.disp = &disp;
1097             fb_info.switch_con = &Cyberfb_switch;
1098             fb_info.updatevar = &Cyberfb_updatevar;
1099             fb_info.blank = &Cyberfb_blank;
1100
1101             Cyber_init();
1102             /* ++Andre: set cyberfb default mode */
1103             if (!cyberfb_usermode) {
1104                     cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
1105                     DPRINTK("Use default cyber8 mode\n");
1106             }
1107             Cyber_decode_var(&cyberfb_default, &par);
1108             Cyber_encode_var(&cyberfb_default, &par);
1109
1110             do_fb_set_var(&cyberfb_default, 1);
1111             cyberfb_get_var(&fb_display[0].var, -1, &fb_info);
1112             cyberfb_set_disp(-1, &fb_info);
1113             do_install_cmap(0, &fb_info);
1114
1115             if (register_framebuffer(&fb_info) < 0) {
1116                     DPRINTK("EXIT - register_framebuffer failed\n");
1117                     release_mem_region(CyberMem_phys, 0x400000);
1118                     release_mem_region(CyberRegs_phys, 0x10000);
1119                     return -EINVAL;
1120             }
1121
1122             printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
1123                    GET_FB_IDX(fb_info.node), fb_info.modename, CyberSize>>10);
1124
1125             /* TODO: This driver cannot be unloaded yet */
1126             MOD_INC_USE_COUNT;
1127             DPRINTK("EXIT\n");
1128             return 0;
1129         }
1130         return -ENXIO;
1131 }
1132
1133
1134 static int Cyberfb_switch(int con, struct fb_info *info)
1135 {
1136         DPRINTK("ENTER\n");
1137         /* Do we have to save the colormap? */
1138         if (fb_display[currcon].cmap.len) {
1139                 fb_get_cmap(&fb_display[currcon].cmap, 1, Cyber_getcolreg,
1140                             info);
1141         }
1142
1143         do_fb_set_var(&fb_display[con].var, 1);
1144         currcon = con;
1145         /* Install new colormap */
1146         do_install_cmap(con, info);
1147         DPRINTK("EXIT\n");
1148         return(0);
1149 }
1150
1151
1152 /*
1153  *    Update the `var' structure (called by fbcon.c)
1154  *
1155  *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
1156  *    Since it's called by a kernel driver, no range checking is done.
1157  */
1158
1159 static int Cyberfb_updatevar(int con, struct fb_info *info)
1160 {
1161         DPRINTK("Enter - Exit\n");
1162         return(0);
1163 }
1164
1165
1166 /*
1167  *    Get a Video Mode
1168  */
1169
1170 static int __init get_video_mode(const char *name)
1171 {
1172         int i;
1173
1174         DPRINTK("ENTER\n");
1175         for (i = 0; i < NUM_TOTAL_MODES; i++) {
1176                 if (!strcmp(name, cyberfb_predefined[i].name)) {
1177                         cyberfb_default = cyberfb_predefined[i].var;
1178                         cyberfb_usermode = 1;
1179                         DPRINTK("EXIT - Matched predefined mode\n");
1180                         return(i);
1181                 }
1182         }
1183         return(0);
1184 }
1185
1186
1187 /*
1188  *    Text console acceleration
1189  */
1190
1191 #ifdef FBCON_HAS_CFB8
1192 static void fbcon_cyber8_bmove(struct display *p, int sy, int sx, int dy,
1193                                int dx, int height, int width)
1194 {
1195         DPRINTK("ENTER\n");
1196         sx *= 8; dx *= 8; width *= 8;
1197         Cyber_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
1198                      (u_short)(dy*fontheight(p)), (u_short)width,
1199                      (u_short)(height*fontheight(p)), (u_short)S3_NEW);
1200         DPRINTK("EXIT\n");
1201 }
1202
1203 static void fbcon_cyber8_clear(struct vc_data *conp, struct display *p, int sy,
1204                                int sx, int height, int width)
1205 {
1206         unsigned char bg;
1207
1208         DPRINTK("ENTER\n");
1209         sx *= 8; width *= 8;
1210         bg = attr_bgcol_ec(p,conp);
1211         Cyber_RectFill((u_short)sx,
1212                        (u_short)(sy*fontheight(p)),
1213                        (u_short)width,
1214                        (u_short)(height*fontheight(p)),
1215                        (u_short)S3_NEW,
1216                        (u_short)bg);
1217         DPRINTK("EXIT\n");
1218 }
1219
1220 static void fbcon_cyber8_putc(struct vc_data *conp, struct display *p, int c,
1221                               int yy, int xx)
1222 {
1223         DPRINTK("ENTER\n");
1224         Cyber_WaitBlit();
1225         fbcon_cfb8_putc(conp, p, c, yy, xx);
1226         DPRINTK("EXIT\n");
1227 }
1228
1229 static void fbcon_cyber8_putcs(struct vc_data *conp, struct display *p,
1230                                const unsigned short *s, int count,
1231                                int yy, int xx)
1232 {
1233         DPRINTK("ENTER\n");
1234         Cyber_WaitBlit();
1235         fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
1236         DPRINTK("EXIT\n");
1237 }
1238
1239 static void fbcon_cyber8_revc(struct display *p, int xx, int yy)
1240 {
1241         DPRINTK("ENTER\n");
1242         Cyber_WaitBlit();
1243         fbcon_cfb8_revc(p, xx, yy);
1244         DPRINTK("EXIT\n");
1245 }
1246
1247 static struct display_switch fbcon_cyber8 = {
1248         setup:          fbcon_cfb8_setup,
1249         bmove:          fbcon_cyber8_bmove,
1250         clear:          fbcon_cyber8_clear,
1251         putc:           fbcon_cyber8_putc,
1252         putcs:          fbcon_cyber8_putcs,
1253         revc:           fbcon_cyber8_revc,
1254         clear_margins:  fbcon_cfb8_clear_margins,
1255         fontwidthmask:  FONTWIDTH(8)
1256 };
1257 #endif
1258
1259
1260 #ifdef MODULE
1261 MODULE_LICENSE("GPL");
1262
1263 int init_module(void)
1264 {
1265         return cyberfb_init();
1266 }
1267
1268 void cleanup_module(void)
1269 {
1270         /* Not reached because the usecount will never be
1271            decremented to zero */
1272         unregister_framebuffer(&fb_info);
1273         /* TODO: clean up ... */
1274 }
1275 #endif /* MODULE */
1276
1277 /*
1278  *
1279  * Low level initialization routines for the CyberVision64 graphics card
1280  *
1281  * Most of the following code is from cvision_core.c
1282  *
1283  */
1284
1285 #define MAXPIXELCLOCK 135000000 /* safety */
1286
1287 #ifdef CV_AGGRESSIVE_TIMING
1288 long cv64_memclk = 55000000;
1289 #else
1290 long cv64_memclk = 50000000;
1291 #endif
1292
1293 /*********************/
1294
1295 static unsigned char clocks[]={
1296   0x13, 0x61, 0x6b, 0x6d, 0x51, 0x69, 0x54, 0x69,
1297   0x4f, 0x68, 0x6b, 0x6b, 0x18, 0x61, 0x7b, 0x6c,
1298   0x51, 0x67, 0x24, 0x62, 0x56, 0x67, 0x77, 0x6a,
1299   0x1d, 0x61, 0x53, 0x66, 0x6b, 0x68, 0x79, 0x69,
1300   0x7c, 0x69, 0x7f, 0x69, 0x22, 0x61, 0x54, 0x65,
1301   0x56, 0x65, 0x58, 0x65, 0x67, 0x66, 0x41, 0x63,
1302   0x27, 0x61, 0x13, 0x41, 0x37, 0x62, 0x6b, 0x4d,
1303   0x23, 0x43, 0x51, 0x49, 0x79, 0x66, 0x54, 0x49,
1304   0x7d, 0x66, 0x34, 0x56, 0x4f, 0x63, 0x1f, 0x42,
1305   0x6b, 0x4b, 0x7e, 0x4d, 0x18, 0x41, 0x2a, 0x43,
1306   0x7b, 0x4c, 0x74, 0x4b, 0x51, 0x47, 0x65, 0x49,
1307   0x24, 0x42, 0x68, 0x49, 0x56, 0x47, 0x75, 0x4a,
1308   0x77, 0x4a, 0x31, 0x43, 0x1d, 0x41, 0x71, 0x49,
1309   0x53, 0x46, 0x29, 0x42, 0x6b, 0x48, 0x1f, 0x41,
1310   0x79, 0x49, 0x6f, 0x48, 0x7c, 0x49, 0x38, 0x43,
1311   0x7f, 0x49, 0x5d, 0x46, 0x22, 0x41, 0x53, 0x45,
1312   0x54, 0x45, 0x55, 0x45, 0x56, 0x45, 0x57, 0x45,
1313   0x58, 0x45, 0x25, 0x41, 0x67, 0x46, 0x5b, 0x45,
1314   0x41, 0x43, 0x78, 0x47, 0x27, 0x41, 0x51, 0x44,
1315   0x13, 0x21, 0x7d, 0x47, 0x37, 0x42, 0x71, 0x46,
1316   0x6b, 0x2d, 0x14, 0x21, 0x23, 0x23, 0x7d, 0x2f,
1317   0x51, 0x29, 0x61, 0x2b, 0x79, 0x46, 0x1d, 0x22,
1318   0x54, 0x29, 0x45, 0x27, 0x7d, 0x46, 0x7f, 0x46,
1319   0x4f, 0x43, 0x2f, 0x41, 0x1f, 0x22, 0x6a, 0x2b,
1320   0x6b, 0x2b, 0x5b, 0x29, 0x7e, 0x2d, 0x65, 0x44,
1321   0x18, 0x21, 0x5e, 0x29, 0x2a, 0x23, 0x45, 0x26,
1322   0x7b, 0x2c, 0x19, 0x21, 0x74, 0x2b, 0x75, 0x2b,
1323   0x51, 0x27, 0x3f, 0x25, 0x65, 0x29, 0x40, 0x25,
1324   0x24, 0x22, 0x41, 0x25, 0x68, 0x29, 0x42, 0x25,
1325   0x56, 0x27, 0x7e, 0x2b, 0x75, 0x2a, 0x1c, 0x21,
1326   0x77, 0x2a, 0x4f, 0x26, 0x31, 0x23, 0x6f, 0x29,
1327   0x1d, 0x21, 0x32, 0x23, 0x71, 0x29, 0x72, 0x29,
1328   0x53, 0x26, 0x69, 0x28, 0x29, 0x22, 0x75, 0x29,
1329   0x6b, 0x28, 0x1f, 0x21, 0x1f, 0x21, 0x6d, 0x28,
1330   0x79, 0x29, 0x2b, 0x22, 0x6f, 0x28, 0x59, 0x26,
1331   0x7c, 0x29, 0x7d, 0x29, 0x38, 0x23, 0x21, 0x21,
1332   0x7f, 0x29, 0x39, 0x23, 0x5d, 0x26, 0x75, 0x28,
1333   0x22, 0x21, 0x77, 0x28, 0x53, 0x25, 0x6c, 0x27,
1334   0x54, 0x25, 0x61, 0x26, 0x55, 0x25, 0x30, 0x22,
1335   0x56, 0x25, 0x63, 0x26, 0x57, 0x25, 0x71, 0x27,
1336   0x58, 0x25, 0x7f, 0x28, 0x25, 0x21, 0x74, 0x27,
1337   0x67, 0x26, 0x40, 0x23, 0x5b, 0x25, 0x26, 0x21,
1338   0x41, 0x23, 0x34, 0x22, 0x78, 0x27, 0x6b, 0x26,
1339   0x27, 0x21, 0x35, 0x22, 0x51, 0x24, 0x7b, 0x27,
1340   0x13, 0x1,  0x13, 0x1,  0x7d, 0x27, 0x4c, 0x9,
1341   0x37, 0x22, 0x5b, 0xb,  0x71, 0x26, 0x5c, 0xb,
1342   0x6b, 0xd,  0x47, 0x23, 0x14, 0x1,  0x4f, 0x9,
1343   0x23, 0x3,  0x75, 0x26, 0x7d, 0xf,  0x1c, 0x2,
1344   0x51, 0x9,  0x59, 0x24, 0x61, 0xb,  0x69, 0x25,
1345   0x79, 0x26, 0x34, 0x5,  0x1d, 0x2,  0x6b, 0x25,
1346   0x54, 0x9,  0x35, 0x5,  0x45, 0x7,  0x6d, 0x25,
1347   0x7d, 0x26, 0x16, 0x1,  0x7f, 0x26, 0x77, 0xd,
1348   0x4f, 0x23, 0x78, 0xd,  0x2f, 0x21, 0x27, 0x3,
1349   0x1f, 0x2,  0x59, 0x9,  0x6a, 0xb,  0x73, 0x25,
1350   0x6b, 0xb,  0x63, 0x24, 0x5b, 0x9,  0x20, 0x2,
1351   0x7e, 0xd,  0x4b, 0x7,  0x65, 0x24, 0x43, 0x22,
1352   0x18, 0x1,  0x6f, 0xb,  0x5e, 0x9,  0x70, 0xb,
1353   0x2a, 0x3,  0x33, 0x4,  0x45, 0x6,  0x60, 0x9,
1354   0x7b, 0xc,  0x19, 0x1,  0x19, 0x1,  0x7d, 0xc,
1355   0x74, 0xb,  0x50, 0x7,  0x75, 0xb,  0x63, 0x9,
1356   0x51, 0x7,  0x23, 0x2,  0x3f, 0x5,  0x1a, 0x1,
1357   0x65, 0x9,  0x2d, 0x3,  0x40, 0x5,  0x0,  0x0,
1358 };
1359
1360 /* Console colors */
1361 unsigned char cvconscolors[16][3] = {   /* background, foreground, hilite */
1362   /*  R     G     B  */
1363   {0x30, 0x30, 0x30},
1364   {0x00, 0x00, 0x00},
1365   {0x80, 0x00, 0x00},
1366   {0x00, 0x80, 0x00},
1367   {0x00, 0x00, 0x80},
1368   {0x80, 0x80, 0x00},
1369   {0x00, 0x80, 0x80},
1370   {0x80, 0x00, 0x80},
1371   {0xff, 0xff, 0xff},
1372   {0x40, 0x40, 0x40},
1373   {0xff, 0x00, 0x00},
1374   {0x00, 0xff, 0x00},
1375   {0x00, 0x00, 0xff},
1376   {0xff, 0xff, 0x00},
1377   {0x00, 0xff, 0xff},
1378   {0x00, 0x00, 0xff}
1379 };
1380
1381 /* -------------------- Hardware specific routines ------------------------- */
1382
1383 /* Read Attribute Controller Register=idx */
1384 inline unsigned char RAttr (volatile unsigned char *regs, short idx)
1385 {
1386         wb_64 (regs, ACT_ADDRESS_W, idx);
1387         mb();
1388         udelay(100);
1389         return (rb_64(regs, ACT_ADDRESS_R));
1390 }
1391
1392 /* Read Sequencer Register=idx */
1393 inline unsigned char RSeq (volatile unsigned char *regs, short idx)
1394 {
1395         wb_64 (regs, SEQ_ADDRESS, idx);
1396         mb();
1397         return (rb_64(regs, SEQ_ADDRESS_R));
1398 }
1399
1400 /* Read CRT Controller Register=idx */
1401 inline unsigned char RCrt (volatile unsigned char *regs, short idx)
1402 {
1403         wb_64 (regs, CRT_ADDRESS, idx);
1404         mb();
1405         return (rb_64(regs, CRT_ADDRESS_R));
1406 }
1407
1408 /* Read Graphics Controller Register=idx */
1409 inline unsigned char RGfx (volatile unsigned char *regs, short idx)
1410 {
1411         wb_64 (regs, GCT_ADDRESS, idx);
1412         mb();
1413         return (rb_64(regs, GCT_ADDRESS_R));
1414 }
1415
1416 /*
1417  * Special wakeup/passthrough registers on graphics boards
1418  */
1419
1420 inline void cv64_write_port (unsigned short bits,
1421                              volatile unsigned char *base)
1422 {
1423         volatile unsigned char *addr;
1424         static unsigned char cvportbits = 0; /* Mirror port bits here */
1425         DPRINTK("ENTER\n");
1426
1427         addr = base + 0x40001;
1428         if (bits & 0x8000) {
1429                 cvportbits |= bits & 0xff; /* Set bits */
1430                 DPRINTK("Set bits: %04x\n", bits);
1431         } else {
1432                 bits = bits & 0xff;
1433                 bits = (~bits) & 0xff;
1434                 cvportbits &= bits; /* Clear bits */
1435                 DPRINTK("Clear bits: %04x\n", bits);
1436         }
1437
1438         *addr = cvportbits;
1439         DPRINTK("EXIT\n");
1440 }
1441
1442 /*
1443  * Monitor switch on CyberVision board
1444  *
1445  *  toggle:
1446  *    0 = CyberVision Signal
1447  *    1 = Amiga Signal
1448  *  board = board addr
1449  *
1450  */
1451 inline void cvscreen (int toggle, volatile unsigned char *board)
1452 {
1453         DPRINTK("ENTER\n");
1454         if (toggle == 1) {
1455                 DPRINTK("Show Amiga video\n");
1456                 cv64_write_port (0x10, board);
1457         } else {
1458                 DPRINTK("Show CyberVision video\n");
1459                 cv64_write_port (0x8010, board);
1460         }
1461         DPRINTK("EXIT\n");
1462 }
1463
1464 /* Control screen display */
1465 /* toggle: 0 = on, 1 = off */
1466 /* board = registerbase */
1467 inline void gfx_on_off(int toggle, volatile unsigned char *regs)
1468 {
1469         int r;
1470         DPRINTK("ENTER\n");
1471         
1472         toggle &= 0x1;
1473         toggle = toggle << 5;
1474         DPRINTK("Turn display %s\n", (toggle ? "off" : "on"));
1475         
1476         r = (int) RSeq(regs, SEQ_ID_CLOCKING_MODE);
1477         r &= 0xdf;      /* Set bit 5 to 0 */
1478         
1479         WSeq (regs, SEQ_ID_CLOCKING_MODE, r | toggle);
1480         DPRINTK("EXIT\n");
1481 }
1482
1483 /*
1484  * Computes M, N, and R values from
1485  * given input frequency. It uses a table of
1486  * precomputed values, to keep CPU time low.
1487  *
1488  * The return value consist of:
1489  * lower byte:  Bits 4-0: N Divider Value
1490  *              Bits 5-6: R Value          for e.g. SR10 or SR12
1491  * higher byte: Bits 0-6: M divider value  for e.g. SR11 or SR13
1492  */
1493 static unsigned short cv64_compute_clock(unsigned long freq)
1494 {
1495         static unsigned char *mnr, *save;       /* M, N + R vals */
1496         unsigned long work_freq, r;
1497         unsigned short erg;
1498         long diff, d2;
1499
1500         DPRINTK("ENTER\n");
1501         if (freq < 12500000 || freq > MAXPIXELCLOCK) {
1502                 printk("CV64 driver: Illegal clock frequency %ld, using 25MHz\n",
1503                        freq);
1504                 freq = 25000000;
1505         }
1506         DPRINTK("Freq = %ld\n", freq);
1507         mnr = clocks;   /* there the vals are stored */
1508         d2 = 0x7fffffff;
1509
1510         while (*mnr) {  /* mnr vals are 0-terminated */
1511                 work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2);
1512
1513                 r = (mnr[1] >> 5) & 0x03;
1514                 if (r != 0) {
1515                         work_freq = work_freq >> r;     /* r is the freq divider */
1516                 }
1517
1518                 work_freq *= 0x3E8;     /* 2nd part of OSC */
1519
1520                 diff = abs(freq - work_freq);
1521
1522                 if (d2 >= diff) {
1523                         d2 = diff;
1524                         /* In save are the vals for minimal diff */
1525                         save = mnr;
1526                 }
1527                 mnr += 2;
1528         }
1529         erg = *((unsigned short *)save);
1530
1531         DPRINTK("EXIT\n");
1532         return (erg);
1533 }
1534
1535 static int cv_has_4mb (volatile unsigned char *fb)
1536 {
1537         volatile unsigned long *tr, *tw;
1538         DPRINTK("ENTER\n");
1539
1540         /* write patterns in memory and test if they can be read */
1541         tw = (volatile unsigned long *) fb;
1542         tr = (volatile unsigned long *) (fb + 0x02000000);
1543
1544         *tw = 0x87654321;
1545         
1546         if (*tr != 0x87654321) {
1547                 DPRINTK("EXIT - <4MB\n");
1548                 return (0);
1549         }
1550
1551         /* upper memory region */
1552         tw = (volatile unsigned long *) (fb + 0x00200000);
1553         tr = (volatile unsigned long *) (fb + 0x02200000);
1554
1555         *tw = 0x87654321;
1556
1557         if (*tr != 0x87654321) {
1558                 DPRINTK("EXIT - <4MB\n");
1559                 return (0);
1560         }
1561
1562         *tw = 0xAAAAAAAA;
1563
1564         if (*tr != 0xAAAAAAAA) {
1565                 DPRINTK("EXIT - <4MB\n");
1566                 return (0);
1567         }
1568
1569         *tw = 0x55555555;
1570
1571         if (*tr != 0x55555555) {
1572                 DPRINTK("EXIT - <4MB\n");
1573                 return (0);
1574         }
1575
1576         DPRINTK("EXIT\n");
1577         return (1);
1578 }
1579
1580 static void cv64_board_init (void)
1581 {
1582         volatile unsigned char *regs = CyberRegs;
1583         int i;
1584         unsigned int clockpar;
1585         unsigned char test;
1586         
1587         DPRINTK("ENTER\n");
1588
1589         /*
1590          * Special CyberVision 64 board operations
1591          */
1592         /* Reset board */
1593         for (i = 0; i < 6; i++) {
1594                 cv64_write_port (0xff, CyberBase);
1595         }
1596         /* Return to operational mode */
1597         cv64_write_port (0x8004, CyberBase);
1598         
1599         /*
1600          * Generic (?) S3 chip wakeup
1601          */
1602         /* Disable I/O & memory decoders, video in setup mode */
1603         wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x10);
1604         /* Video responds to cmds, addrs & data */
1605         wb_64 (regs, SREG_OPTION_SELECT, 0x1);
1606         /* Enable I/O & memory decoders, video in operational mode */
1607         wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x8);
1608         /* VGA color emulation, enable cpu access to display mem */ 
1609         wb_64 (regs, GREG_MISC_OUTPUT_W, 0x03);
1610         /* Unlock S3 VGA regs */
1611         WCrt (regs, CRT_ID_REGISTER_LOCK_1, 0x48); 
1612         /* Unlock system control & extension registers */
1613         WCrt (regs, CRT_ID_REGISTER_LOCK_2, 0xA5);
1614 /* GRF - Enable interrupts */
1615         /* Enable enhanced regs access, Ready cntl 0 wait states */
1616         test = RCrt (regs, CRT_ID_SYSTEM_CONFIG);
1617         test = test | 0x01;             /* enable enhanced register access */
1618         test = test & 0xEF;             /* clear bit 4, 0 wait state */
1619         WCrt (regs, CRT_ID_SYSTEM_CONFIG, test);
1620         /*
1621          * bit 0=1: Enable enhaced mode functions
1622          * bit 2=0: Enhanced mode 8+ bits/pixel
1623          * bit 4=1: Enable linear addressing
1624          * bit 5=1: Enable MMIO
1625          */
1626         wb_64 (regs, ECR_ADV_FUNC_CNTL, 0x31);
1627         /*
1628          * bit 0=1: Color emulation
1629          * bit 1=1: Enable CPU access to display memory
1630          * bit 5=1: Select high 64K memory page
1631          */
1632 /* GRF - 0xE3 */
1633         wb_64 (regs, GREG_MISC_OUTPUT_W, 0x23);
1634         
1635         /* Cpu base addr */
1636         WCrt (regs, CRT_ID_EXT_SYS_CNTL_4, 0x0);
1637         
1638         /* Reset. This does nothing on Trio, but standard VGA practice */
1639         /* WSeq (CyberRegs, SEQ_ID_RESET, 0x03); */
1640         /* Character clocks 8 dots wide */
1641         WSeq (regs, SEQ_ID_CLOCKING_MODE, 0x01);
1642         /* Enable cpu write to all color planes */
1643         WSeq (regs, SEQ_ID_MAP_MASK, 0x0F);
1644         /* Font table in 1st 8k of plane 2, font A=B disables swtich */
1645         WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x0);
1646         /* Allow mem access to 256kb */
1647         WSeq (regs, SEQ_ID_MEMORY_MODE, 0x2);
1648         /* Unlock S3 extensions to VGA Sequencer regs */
1649         WSeq (regs, SEQ_ID_UNLOCK_EXT, 0x6);
1650         
1651         /* Enable 4MB fast page mode */
1652         test = RSeq (regs, SEQ_ID_BUS_REQ_CNTL);
1653         test = test | 1 << 6;
1654         WSeq (regs, SEQ_ID_BUS_REQ_CNTL, test);
1655         
1656         /* Faster LUT write: 1 DCLK LUT write cycle, RAMDAC clk doubled */
1657         WSeq (regs, SEQ_ID_RAMDAC_CNTL, 0xC0);
1658
1659         /* Clear immediate clock load bit */
1660         test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
1661         test = test & 0xDF;
1662         /* If > 55MHz, enable 2 cycle memory write */
1663         if (cv64_memclk >= 55000000) {
1664                 test |= 0x80;
1665         }
1666         WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
1667
1668         /* Set MCLK value */
1669         clockpar = cv64_compute_clock (cv64_memclk);
1670         test = (clockpar & 0xFF00) >> 8;
1671         WSeq (regs, SEQ_ID_MCLK_HI, test);
1672         test = clockpar & 0xFF;
1673         WSeq (regs, SEQ_ID_MCLK_LO, test);
1674
1675         /* Chip rev specific: Not in my Trio manual!!! */
1676         if (RCrt (regs, CRT_ID_REVISION) == 0x10)
1677                 WSeq (regs, SEQ_ID_MORE_MAGIC, test);
1678
1679         /* We now load an 25 MHz, 31kHz, 640x480 standard VGA Mode. */
1680
1681         /* Set DCLK value */
1682         WSeq (regs, SEQ_ID_DCLK_HI, 0x13);
1683         WSeq (regs, SEQ_ID_DCLK_LO, 0x41);
1684
1685         /* Load DCLK (and MCLK?) immediately */
1686         test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
1687         test = test | 0x22;
1688         WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
1689
1690         /* Enable loading of DCLK */
1691         test = rb_64(regs, GREG_MISC_OUTPUT_R);
1692         test = test | 0x0C;
1693         wb_64 (regs, GREG_MISC_OUTPUT_W, test);
1694
1695         /* Turn off immediate xCLK load */
1696         WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, 0x2);
1697
1698         /* Horizontal character clock counts */
1699         /* 8 LSB of 9 bits = total line - 5 */
1700         WCrt (regs, CRT_ID_HOR_TOTAL, 0x5F);
1701         /* Active display line */
1702         WCrt (regs, CRT_ID_HOR_DISP_ENA_END, 0x4F);
1703         /* Blank assertion start */
1704         WCrt (regs, CRT_ID_START_HOR_BLANK, 0x50);
1705         /* Blank assertion end */
1706         WCrt (regs, CRT_ID_END_HOR_BLANK, 0x82);
1707         /* HSYNC assertion start */
1708         WCrt (regs, CRT_ID_START_HOR_RETR, 0x54);
1709         /* HSYNC assertion end */
1710         WCrt (regs, CRT_ID_END_HOR_RETR, 0x80);
1711         WCrt (regs, CRT_ID_VER_TOTAL, 0xBF);
1712         WCrt (regs, CRT_ID_OVERFLOW, 0x1F);
1713         WCrt (regs, CRT_ID_PRESET_ROW_SCAN, 0x0);
1714         WCrt (regs, CRT_ID_MAX_SCAN_LINE, 0x40);
1715         WCrt (regs, CRT_ID_CURSOR_START, 0x00);
1716         WCrt (regs, CRT_ID_CURSOR_END, 0x00);
1717         WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00);
1718         WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00);
1719         WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1720         WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
1721         WCrt (regs, CRT_ID_START_VER_RETR, 0x9C);
1722         WCrt (regs, CRT_ID_END_VER_RETR, 0x0E);
1723         WCrt (regs, CRT_ID_VER_DISP_ENA_END, 0x8F);
1724         WCrt (regs, CRT_ID_SCREEN_OFFSET, 0x50);
1725         WCrt (regs, CRT_ID_UNDERLINE_LOC, 0x00);
1726         WCrt (regs, CRT_ID_START_VER_BLANK, 0x96);
1727         WCrt (regs, CRT_ID_END_VER_BLANK, 0xB9);
1728         WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3);
1729         WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF);
1730         WCrt (regs, CRT_ID_BACKWAD_COMP_3, 0x10);       /* FIFO enabled */
1731         WCrt (regs, CRT_ID_MISC_1, 0x35);
1732         WCrt (regs, CRT_ID_DISPLAY_FIFO, 0x5A);
1733         WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, 0x70);
1734         WCrt (regs, CRT_ID_LAW_POS_LO, 0x40);
1735         WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, 0xFF);
1736
1737         WGfx (regs, GCT_ID_SET_RESET, 0x0);
1738         WGfx (regs, GCT_ID_ENABLE_SET_RESET, 0x0);
1739         WGfx (regs, GCT_ID_COLOR_COMPARE, 0x0);
1740         WGfx (regs, GCT_ID_DATA_ROTATE, 0x0);
1741         WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x0);
1742         WGfx (regs, GCT_ID_GRAPHICS_MODE, 0x40);
1743         WGfx (regs, GCT_ID_MISC, 0x01);
1744         WGfx (regs, GCT_ID_COLOR_XCARE, 0x0F);
1745         WGfx (regs, GCT_ID_BITMASK, 0xFF);
1746
1747         /* Colors for text mode */
1748         for (i = 0; i < 0xf; i++)
1749                 WAttr (regs, i, i);
1750
1751         WAttr (regs, ACT_ID_ATTR_MODE_CNTL, 0x41);
1752         WAttr (regs, ACT_ID_OVERSCAN_COLOR, 0x01);
1753         WAttr (regs, ACT_ID_COLOR_PLANE_ENA, 0x0F);
1754         WAttr (regs, ACT_ID_HOR_PEL_PANNING, 0x0);
1755         WAttr (regs, ACT_ID_COLOR_SELECT, 0x0);
1756
1757         wb_64 (regs, VDAC_MASK, 0xFF);
1758
1759         *((unsigned long *) (regs + ECR_FRGD_COLOR)) = 0xFF;
1760         *((unsigned long *) (regs + ECR_BKGD_COLOR)) = 0;
1761
1762         /* Colors initially set to grayscale */
1763
1764         wb_64 (regs, VDAC_ADDRESS_W, 0);
1765         for (i = 255; i >= 0; i--) {
1766                 wb_64(regs, VDAC_DATA, i);
1767                 wb_64(regs, VDAC_DATA, i);
1768                 wb_64(regs, VDAC_DATA, i);
1769         }
1770
1771         /* GFx hardware cursor off */
1772         WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
1773
1774         /* Set first to 4MB, so test will work */
1775         WCrt (regs, CRT_ID_LAW_CNTL, 0x13);
1776         /* Find "correct" size of fbmem of Z3 board */
1777         if (cv_has_4mb (CyberMem)) {
1778                 CyberSize = 1024 * 1024 * 4;
1779                 WCrt (regs, CRT_ID_LAW_CNTL, 0x13);
1780                 DPRINTK("4MB board\n");
1781         } else {
1782                 CyberSize = 1024 * 1024 * 2;
1783                 WCrt (regs, CRT_ID_LAW_CNTL, 0x12);
1784                 DPRINTK("2MB board\n");
1785         }
1786
1787         /* Initialize graphics engine */
1788         Cyber_WaitBlit();
1789         vgaw16 (regs, ECR_FRGD_MIX, 0x27);
1790         vgaw16 (regs, ECR_BKGD_MIX, 0x07);
1791         vgaw16 (regs, ECR_READ_REG_DATA, 0x1000);
1792         udelay(200);
1793         vgaw16 (regs, ECR_READ_REG_DATA, 0x2000);
1794         Cyber_WaitBlit();
1795         vgaw16 (regs, ECR_READ_REG_DATA, 0x3FFF);
1796         Cyber_WaitBlit();
1797         udelay(200);
1798         vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF);
1799         Cyber_WaitBlit();
1800         vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, ~0);
1801         Cyber_WaitBlit();
1802         vgaw16 (regs, ECR_READ_REG_DATA, 0xE000);
1803         vgaw16 (regs, ECR_CURRENT_Y_POS2, 0x00);
1804         vgaw16 (regs, ECR_CURRENT_X_POS2, 0x00);
1805         vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
1806         vgaw16 (regs, ECR_DEST_Y__AX_STEP, 0x00);
1807         vgaw16 (regs, ECR_DEST_Y2__AX_STEP2, 0x00);
1808         vgaw16 (regs, ECR_DEST_X__DIA_STEP, 0x00);
1809         vgaw16 (regs, ECR_DEST_X2__DIA_STEP2, 0x00);
1810         vgaw16 (regs, ECR_SHORT_STROKE, 0x00);
1811         vgaw16 (regs, ECR_DRAW_CMD, 0x01);
1812
1813         Cyber_WaitBlit();
1814
1815         vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF);
1816         vgaw16 (regs, ECR_BKGD_COLOR, 0x01);
1817         vgaw16 (regs, ECR_FRGD_COLOR, 0x00);
1818
1819
1820         /* Enable video display (set bit 5) */
1821 /* ARB - Would also seem to write to AR13.
1822  *       May want to use parts of WAttr to set JUST bit 5
1823  */
1824         WAttr (regs, 0x33, 0);
1825         
1826 /* GRF - function code ended here */
1827
1828         /* Turn gfx on again */
1829         gfx_on_off (0, regs);
1830
1831         /* Pass-through */
1832         cvscreen (0, CyberBase);
1833
1834         DPRINTK("EXIT\n");
1835 }
1836
1837 static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
1838 {
1839   volatile unsigned char *regs = CyberRegs;
1840   int fx, fy;
1841   unsigned short mnr;
1842   unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, VSE, VT;
1843   char LACE, DBLSCAN, TEXT, CONSOLE;
1844   int cr50, sr15, sr18, clock_mode, test;
1845   int m, n;
1846   int tfillm, temptym;
1847   int hmul;
1848         
1849   /* ---------------- */
1850   int xres, hfront, hsync, hback;
1851   int yres, vfront, vsync, vback;
1852   int bpp;
1853 #if 0
1854   float freq_f;
1855 #endif
1856   long freq;
1857   /* ---------------- */
1858         
1859   DPRINTK("ENTER\n");
1860   TEXT = 0;     /* if depth == 4 */
1861   CONSOLE = 0;  /* mode num == 255 (console) */
1862   fx = fy = 8;  /* force 8x8 font */
1863
1864 /* GRF - Disable interrupts */  
1865         
1866   gfx_on_off (1, regs);
1867         
1868   switch (video_mode->bits_per_pixel) {
1869   case 15:
1870   case 16:
1871     hmul = 2;
1872     break;
1873                 
1874   default:
1875     hmul = 1;
1876     break;
1877   }
1878         
1879   bpp = video_mode->bits_per_pixel;
1880   xres = video_mode->xres;
1881   hfront = video_mode->right_margin;
1882   hsync = video_mode->hsync_len;
1883   hback = video_mode->left_margin;
1884
1885   LACE = 0;
1886   DBLSCAN = 0;
1887
1888   if (video_mode->vmode & FB_VMODE_DOUBLE) {
1889     yres = video_mode->yres * 2;
1890     vfront = video_mode->lower_margin * 2;
1891     vsync = video_mode->vsync_len * 2;
1892     vback = video_mode->upper_margin * 2;
1893     DBLSCAN = 1;
1894   } else if (video_mode->vmode & FB_VMODE_INTERLACED) {
1895     yres = (video_mode->yres + 1) / 2;
1896     vfront = (video_mode->lower_margin + 1) / 2;
1897     vsync = (video_mode->vsync_len + 1) / 2;
1898     vback = (video_mode->upper_margin + 1) / 2;
1899     LACE = 1;
1900   } else {
1901     yres = video_mode->yres;
1902     vfront = video_mode->lower_margin;
1903     vsync = video_mode->vsync_len;
1904     vback = video_mode->upper_margin;
1905   }
1906
1907   /* ARB Dropping custom setup method from cvision.c */
1908 #if 0
1909   if (cvision_custom_mode) {
1910     HBS = hbs / 8 * hmul;
1911     HBE = hbe / 8 * hmul;
1912     HSS = hss / 8 * hmul;
1913     HSE = hse / 8 * hmul;
1914     HT  = ht / 8 * hmul - 5;
1915                 
1916     VBS = vbs - 1;
1917     VSS = vss;
1918     VSE = vse;
1919     VBE = vbe;
1920     VT  = vt - 2;
1921   } else {
1922 #else
1923     {
1924 #endif
1925     HBS = hmul * (xres / 8);
1926     HBE = hmul * ((xres/8) + (hfront/8) + (hsync/8) + (hback/8) - 2);
1927     HSS = hmul * ((xres/8) + (hfront/8) + 2);
1928     HSE = hmul * ((xres/8) + (hfront/8) + (hsync/8) + 1);
1929     HT  = hmul * ((xres/8) + (hfront/8) + (hsync/8) + (hback/8));
1930         
1931     VBS = yres;
1932     VBE = yres + vfront + vsync + vback - 2;
1933     VSS = yres + vfront - 1;
1934     VSE = yres + vfront + vsync - 1;
1935     VT  = yres + vfront + vsync + vback - 2;
1936   }
1937
1938   wb_64 (regs, ECR_ADV_FUNC_CNTL, (TEXT ? 0x00 : 0x31));
1939         
1940   if (TEXT)
1941     HDE = ((video_mode->xres + fx - 1) / fx) - 1;
1942   else
1943     HDE = (video_mode->xres + 3) * hmul / 8 - 1;
1944         
1945   VDE = video_mode->yres - 1;
1946
1947   WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
1948   WCrt (regs, CRT_ID_EXT_DAC_CNTL, 0x00);
1949         
1950   WSeq (regs, SEQ_ID_MEMORY_MODE,
1951         (TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x0e);
1952   WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x00);
1953   WSeq (regs, SEQ_ID_MAP_MASK,
1954         (video_mode->bits_per_pixel == 1) ? 0x01 : 0xFF);
1955   WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1956         
1957   /* cv64_compute_clock accepts arguments in Hz */
1958   /* pixclock is in ps ... convert to Hz */
1959         
1960 #if 0
1961   freq_f = (1.0 / (float) video_mode->pixclock) * 1000000000;
1962   freq = ((long) freq_f) * 1000;
1963 #else
1964 /* freq = (long) ((long long)1000000000000 / (long long) video_mode->pixclock);
1965  */
1966   freq = (1000000000 / video_mode->pixclock) * 1000;
1967 #endif
1968
1969   mnr = cv64_compute_clock (freq);
1970   WSeq (regs, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8));
1971   WSeq (regs, SEQ_ID_DCLK_LO, (mnr & 0xFF));
1972         
1973   /* Load display parameters into board */
1974   WCrt (regs, CRT_ID_EXT_HOR_OVF,
1975         ((HT & 0x100) ? 0x01 : 0x00) |
1976         ((HDE & 0x100) ? 0x02 : 0x00) |
1977         ((HBS & 0x100) ? 0x04 : 0x00) |
1978         /* ((HBE & 0x40) ? 0x08 : 0x00) | */
1979         ((HSS & 0x100) ? 0x10 : 0x00) |
1980         /* ((HSE & 0x20) ? 0x20 : 0x00) | */
1981         (((HT-5) & 0x100) ? 0x40 : 0x00)
1982         );
1983         
1984   WCrt (regs, CRT_ID_EXT_VER_OVF,
1985         0x40 |
1986         ((VT & 0x400) ? 0x01 : 0x00) |
1987         ((VDE & 0x400) ? 0x02 : 0x00) |
1988         ((VBS & 0x400) ? 0x04 : 0x00) |
1989         ((VSS & 0x400) ? 0x10 : 0x00)
1990         );
1991         
1992   WCrt (regs, CRT_ID_HOR_TOTAL, HT);
1993   WCrt (regs, CRT_ID_DISPLAY_FIFO, HT - 5);
1994   WCrt (regs, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE));
1995   WCrt (regs, CRT_ID_START_HOR_BLANK, HBS);
1996   WCrt (regs, CRT_ID_END_HOR_BLANK, ((HBE & 0x1F) | 0x80));
1997   WCrt (regs, CRT_ID_START_HOR_RETR, HSS);
1998   WCrt (regs, CRT_ID_END_HOR_RETR,
1999         (HSE & 0x1F) |
2000         ((HBE & 0x20) ? 0x80 : 0x00)
2001         );
2002   WCrt (regs, CRT_ID_VER_TOTAL, VT);
2003   WCrt (regs, CRT_ID_OVERFLOW,
2004         0x10 |
2005         ((VT & 0x100) ? 0x01 : 0x00) |
2006         ((VDE & 0x100) ? 0x02 : 0x00) |
2007         ((VSS & 0x100) ? 0x04 : 0x00) |
2008         ((VBS & 0x100) ? 0x08 : 0x00) |
2009         ((VT & 0x200) ? 0x20 : 0x00) |
2010         ((VDE & 0x200) ? 0x40 : 0x00) |
2011         ((VSS & 0x200) ? 0x80 : 0x00)
2012         );
2013   WCrt (regs, CRT_ID_MAX_SCAN_LINE,
2014         0x40 |
2015         (DBLSCAN ? 0x80 : 0x00) |
2016         ((VBS & 0x200) ? 0x20 : 0x00) |
2017         (TEXT ? ((fy - 1) & 0x1F) : 0x00)
2018         );
2019         
2020   WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3);
2021
2022   /* Text cursor */
2023         
2024   if (TEXT) {
2025 #if 1
2026     WCrt (regs, CRT_ID_CURSOR_START, (fy & 0x1f) - 2);
2027     WCrt (regs, CRT_ID_CURSOR_END, (fy & 0x1F) - 1);
2028 #else
2029     WCrt (regs, CRT_ID_CURSOR_START, 0x00);
2030     WCrt (regs, CRT_ID_CURSOR_END, fy & 0x1F);
2031 #endif
2032     WCrt (regs, CRT_ID_UNDERLINE_LOC, (fy - 1) & 0x1F);
2033     WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
2034     WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
2035   }
2036         
2037   WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00);
2038   WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00);
2039   WCrt (regs, CRT_ID_START_VER_RETR, VSS);
2040   WCrt (regs, CRT_ID_END_VER_RETR, (VSE & 0x0F));
2041   WCrt (regs, CRT_ID_VER_DISP_ENA_END, VDE);
2042   WCrt (regs, CRT_ID_START_VER_BLANK, VBS);
2043   WCrt (regs, CRT_ID_END_VER_BLANK, VBE);
2044   WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF);
2045   WCrt (regs, CRT_ID_LACE_RETR_START, HT / 2);
2046   WCrt (regs, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00));
2047   WGfx (regs, GCT_ID_GRAPHICS_MODE,
2048         ((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x00 : 0x40));
2049   WGfx (regs, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
2050   WSeq (regs, SEQ_ID_MEMORY_MODE,
2051         ((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x02));
2052         
2053   wb_64 (regs, VDAC_MASK, 0xFF);
2054         
2055   /* Blank border */
2056   test = RCrt (regs, CRT_ID_BACKWAD_COMP_2);
2057   WCrt (regs, CRT_ID_BACKWAD_COMP_2, (test | 0x20));
2058         
2059   sr15 = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
2060   sr15 &= 0xEF;
2061   sr18 = RSeq (regs, SEQ_ID_RAMDAC_CNTL);
2062   sr18 &= 0x7F;
2063   clock_mode = 0x00;
2064   cr50 = 0x00;
2065         
2066   test = RCrt (regs, CRT_ID_EXT_MISC_CNTL_2);
2067   test &= 0xD;
2068         
2069   /* Clear roxxler byte-swapping... */
2070   cv64_write_port (0x0040, CyberBase);
2071   cv64_write_port (0x0020, CyberBase);
2072         
2073   switch (video_mode->bits_per_pixel) {
2074   case 1:
2075   case 4:       /* text */
2076     HDE = video_mode->xres / 16;
2077     break;
2078                 
2079   case 8:
2080     if (freq > 80000000) {
2081       clock_mode = 0x10 | 0x02;
2082       sr15 |= 0x10;
2083       sr18 |= 0x80;
2084     }
2085     HDE = video_mode->xres / 8;
2086     cr50 |= 0x00;
2087     break;
2088                 
2089   case 15:
2090     cv64_write_port (0x8020, CyberBase);
2091     clock_mode = 0x30;
2092     HDE = video_mode->xres / 4;
2093     cr50 |= 0x10;
2094     break;
2095                 
2096   case 16:
2097     cv64_write_port (0x8020, CyberBase);
2098     clock_mode = 0x50;
2099     HDE = video_mode->xres / 4;
2100     cr50 |= 0x10;
2101     break;
2102                 
2103   case 24:
2104   case 32:
2105     cv64_write_port (0x8040, CyberBase);
2106     clock_mode = 0xD0;
2107     HDE = video_mode->xres / 2;
2108     cr50 |= 0x30;
2109     break;
2110   }
2111
2112   WCrt (regs, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test);
2113   WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, sr15);
2114   WSeq (regs, SEQ_ID_RAMDAC_CNTL, sr18);
2115   WCrt (regs, CRT_ID_SCREEN_OFFSET, HDE);
2116
2117   WCrt (regs, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35));
2118         
2119   test = RCrt (regs, CRT_ID_EXT_SYS_CNTL_2);
2120   test &= ~0x30;
2121   test |= (HDE >> 4) & 0x30;
2122   WCrt (regs, CRT_ID_EXT_SYS_CNTL_2, test);
2123         
2124   /* Set up graphics engine */
2125   switch (video_mode->xres) {
2126   case 1024:
2127     cr50 |= 0x00;
2128     break;
2129                 
2130   case 640:
2131     cr50 |= 0x40;
2132     break;
2133                 
2134   case 800:
2135     cr50 |= 0x80;
2136     break;
2137                 
2138   case 1280:
2139     cr50 |= 0xC0;
2140     break;
2141                 
2142   case 1152:
2143     cr50 |= 0x01;
2144     break;
2145                 
2146   case 1600:
2147     cr50 |= 0x81;
2148     break;
2149                 
2150   default:      /* XXX */
2151     break;
2152   }
2153         
2154   WCrt (regs, CRT_ID_EXT_SYS_CNTL_1, cr50);
2155         
2156   udelay(100);
2157   WAttr (regs, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41));
2158   udelay(100);
2159   WAttr (regs, ACT_ID_COLOR_PLANE_ENA,
2160          (video_mode->bits_per_pixel == 1) ? 0x01 : 0x0F);
2161   udelay(100);
2162         
2163   tfillm = (96 * (cv64_memclk / 1000)) / 240000;
2164         
2165   switch (video_mode->bits_per_pixel) {
2166   case 32:
2167   case 24:
2168     temptym = (24 * (cv64_memclk / 1000)) / (freq / 1000);
2169     break;
2170   case 15:
2171   case 16:
2172     temptym = (48 * (cv64_memclk / 1000)) / (freq / 1000);
2173     break;
2174   case 4:
2175     temptym = (192 * (cv64_memclk / 1000)) / (freq / 1000);
2176     break;
2177   default:
2178     temptym = (96 * (cv64_memclk / 1000)) / (freq / 1000);
2179     break;
2180   }
2181         
2182   m = (temptym - tfillm - 9) / 2;
2183   if (m < 0)
2184     m = 0;
2185   m = (m & 0x1F) << 3;
2186   if (m < 0x18)
2187     m = 0x18;
2188   n = 0xFF;
2189         
2190   WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, m);
2191   WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, n);
2192   udelay(10);
2193         
2194   /* Text initialization */
2195         
2196   if (TEXT) {
2197     /* Do text initialization here ! */
2198   }
2199         
2200   if (CONSOLE) {
2201     int i;
2202     wb_64 (regs, VDAC_ADDRESS_W, 0);
2203     for (i = 0; i < 4; i++) {
2204       wb_64 (regs, VDAC_DATA, cvconscolors [i][0]);
2205       wb_64 (regs, VDAC_DATA, cvconscolors [i][1]);
2206       wb_64 (regs, VDAC_DATA, cvconscolors [i][2]);
2207     }
2208   }
2209         
2210   WAttr (regs, 0x33, 0);
2211         
2212   /* Turn gfx on again */
2213   gfx_on_off (0, (volatile unsigned char *) regs);
2214         
2215   /* Pass-through */
2216   cvscreen (0, CyberBase);
2217
2218 DPRINTK("EXIT\n");
2219 }
2220
2221 void cvision_bitblt (u_short sx, u_short sy, u_short dx, u_short dy,
2222                      u_short w, u_short h)
2223 {
2224         volatile unsigned char *regs = CyberRegs;
2225         unsigned short drawdir = 0;
2226         
2227         DPRINTK("ENTER\n");
2228         if (sx > dx) {
2229                 drawdir |= 1 << 5;
2230         } else {
2231                 sx += w - 1;
2232                 dx += w - 1;
2233         }
2234         
2235         if (sy > dy) {
2236                 drawdir |= 1 << 7;
2237         } else {
2238                 sy += h - 1;
2239                 dy += h - 1;
2240         }
2241         
2242         Cyber_WaitBlit();
2243         vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
2244         vgaw16 (regs, ECR_BKGD_MIX, 0x7);
2245         vgaw16 (regs, ECR_FRGD_MIX, 0x67);
2246         vgaw16 (regs, ECR_BKGD_COLOR, 0x0);
2247         vgaw16 (regs, ECR_FRGD_COLOR, 0x1);
2248         vgaw16 (regs, ECR_BITPLANE_READ_MASK, 0x1);
2249         vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, 0xFFF);
2250         vgaw16 (regs, ECR_CURRENT_Y_POS, sy);
2251         vgaw16 (regs, ECR_CURRENT_X_POS, sx);
2252         vgaw16 (regs, ECR_DEST_Y__AX_STEP, dy);
2253         vgaw16 (regs, ECR_DEST_X__DIA_STEP, dx);
2254         vgaw16 (regs, ECR_READ_REG_DATA, h - 1);
2255         vgaw16 (regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
2256         vgaw16 (regs, ECR_DRAW_CMD, 0xC051 | drawdir);
2257         DPRINTK("EXIT\n");
2258 }
2259
2260 void cvision_clear (u_short dx, u_short dy, u_short w, u_short h, u_short bg)
2261 {
2262         volatile unsigned char *regs = CyberRegs;
2263         DPRINTK("ENTER\n");
2264         Cyber_WaitBlit();
2265         vgaw16 (regs, ECR_FRGD_MIX, 0x0027);
2266         vgaw16 (regs, ECR_FRGD_COLOR, bg);
2267         vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
2268         vgaw16 (regs, ECR_CURRENT_Y_POS, dy);
2269         vgaw16 (regs, ECR_CURRENT_X_POS, dx);
2270         vgaw16 (regs, ECR_READ_REG_DATA, h - 1);
2271         vgaw16 (regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
2272         vgaw16 (regs, ECR_DRAW_CMD, 0x40B1);    
2273         DPRINTK("EXIT\n");
2274 }
2275
2276 #ifdef CYBERFBDEBUG
2277 /*
2278  * Dump internal settings of CyberVision board
2279  */
2280 static void cv64_dump (void)
2281 {
2282         volatile unsigned char *regs = CyberRegs;
2283         DPRINTK("ENTER\n");
2284         /* Dump the VGA setup values */
2285         *(regs + S3_CRTC_ADR) = 0x00;
2286         DPRINTK("CR00 = %x\n", *(regs + S3_CRTC_DATA));
2287         *(regs + S3_CRTC_ADR) = 0x01;
2288         DPRINTK("CR01 = %x\n", *(regs + S3_CRTC_DATA));
2289         *(regs + S3_CRTC_ADR) = 0x02;
2290         DPRINTK("CR02 = %x\n", *(regs + S3_CRTC_DATA));
2291         *(regs + S3_CRTC_ADR) = 0x03;
2292         DPRINTK("CR03 = %x\n", *(regs + S3_CRTC_DATA));
2293         *(regs + S3_CRTC_ADR) = 0x04;
2294         DPRINTK("CR04 = %x\n", *(regs + S3_CRTC_DATA));
2295         *(regs + S3_CRTC_ADR) = 0x05;
2296         DPRINTK("CR05 = %x\n", *(regs + S3_CRTC_DATA));
2297         *(regs + S3_CRTC_ADR) = 0x06;
2298         DPRINTK("CR06 = %x\n", *(regs + S3_CRTC_DATA));
2299         *(regs + S3_CRTC_ADR) = 0x07;
2300         DPRINTK("CR07 = %x\n", *(regs + S3_CRTC_DATA));
2301         *(regs + S3_CRTC_ADR) = 0x08;
2302         DPRINTK("CR08 = %x\n", *(regs + S3_CRTC_DATA));
2303         *(regs + S3_CRTC_ADR) = 0x09;
2304         DPRINTK("CR09 = %x\n", *(regs + S3_CRTC_DATA));
2305         *(regs + S3_CRTC_ADR) = 0x10;
2306         DPRINTK("CR10 = %x\n", *(regs + S3_CRTC_DATA));
2307         *(regs + S3_CRTC_ADR) = 0x11;
2308         DPRINTK("CR11 = %x\n", *(regs + S3_CRTC_DATA));
2309         *(regs + S3_CRTC_ADR) = 0x12;
2310         DPRINTK("CR12 = %x\n", *(regs + S3_CRTC_DATA));
2311         *(regs + S3_CRTC_ADR) = 0x13;
2312         DPRINTK("CR13 = %x\n", *(regs + S3_CRTC_DATA));
2313         *(regs + S3_CRTC_ADR) = 0x15;
2314         DPRINTK("CR15 = %x\n", *(regs + S3_CRTC_DATA));
2315         *(regs + S3_CRTC_ADR) = 0x16;
2316         DPRINTK("CR16 = %x\n", *(regs + S3_CRTC_DATA));
2317         *(regs + S3_CRTC_ADR) = 0x36;
2318         DPRINTK("CR36 = %x\n", *(regs + S3_CRTC_DATA));
2319         *(regs + S3_CRTC_ADR) = 0x37;
2320         DPRINTK("CR37 = %x\n", *(regs + S3_CRTC_DATA));
2321         *(regs + S3_CRTC_ADR) = 0x42;
2322         DPRINTK("CR42 = %x\n", *(regs + S3_CRTC_DATA));
2323         *(regs + S3_CRTC_ADR) = 0x43;
2324         DPRINTK("CR43 = %x\n", *(regs + S3_CRTC_DATA));
2325         *(regs + S3_CRTC_ADR) = 0x50;
2326         DPRINTK("CR50 = %x\n", *(regs + S3_CRTC_DATA));
2327         *(regs + S3_CRTC_ADR) = 0x51;
2328         DPRINTK("CR51 = %x\n", *(regs + S3_CRTC_DATA));
2329         *(regs + S3_CRTC_ADR) = 0x53;
2330         DPRINTK("CR53 = %x\n", *(regs + S3_CRTC_DATA));
2331         *(regs + S3_CRTC_ADR) = 0x58;
2332         DPRINTK("CR58 = %x\n", *(regs + S3_CRTC_DATA));
2333         *(regs + S3_CRTC_ADR) = 0x59;
2334         DPRINTK("CR59 = %x\n", *(regs + S3_CRTC_DATA));
2335         *(regs + S3_CRTC_ADR) = 0x5A;
2336         DPRINTK("CR5A = %x\n", *(regs + S3_CRTC_DATA));
2337         *(regs + S3_CRTC_ADR) = 0x5D;
2338         DPRINTK("CR5D = %x\n", *(regs + S3_CRTC_DATA));
2339         *(regs + S3_CRTC_ADR) = 0x5E;
2340         DPRINTK("CR5E = %x\n", *(regs + S3_CRTC_DATA));
2341         DPRINTK("MISC = %x\n", *(regs + GREG_MISC_OUTPUT_R));
2342         *(regs + SEQ_ADDRESS) = 0x01;
2343         DPRINTK("SR01 = %x\n", *(regs + SEQ_ADDRESS_R));
2344         *(regs + SEQ_ADDRESS) = 0x02;
2345         DPRINTK("SR02 = %x\n", *(regs + SEQ_ADDRESS_R));
2346         *(regs + SEQ_ADDRESS) = 0x03;
2347         DPRINTK("SR03 = %x\n", *(regs + SEQ_ADDRESS_R));
2348         *(regs + SEQ_ADDRESS) = 0x09;
2349         DPRINTK("SR09 = %x\n", *(regs + SEQ_ADDRESS_R));
2350         *(regs + SEQ_ADDRESS) = 0x10;
2351         DPRINTK("SR10 = %x\n", *(regs + SEQ_ADDRESS_R));
2352         *(regs + SEQ_ADDRESS) = 0x11;
2353         DPRINTK("SR11 = %x\n", *(regs + SEQ_ADDRESS_R));
2354         *(regs + SEQ_ADDRESS) = 0x12;
2355         DPRINTK("SR12 = %x\n", *(regs + SEQ_ADDRESS_R));
2356         *(regs + SEQ_ADDRESS) = 0x13;
2357         DPRINTK("SR13 = %x\n", *(regs + SEQ_ADDRESS_R));
2358         *(regs + SEQ_ADDRESS) = 0x15;
2359         DPRINTK("SR15 = %x\n", *(regs + SEQ_ADDRESS_R));
2360         
2361         return;
2362 }
2363 #endif