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