[PATCH] ioremap balanced with iounmap for drivers/video/cyberfb
[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                         if (CyberBase)
1059                                 iounmap(CyberBase);
1060                     release_mem_region(CyberMem_phys, 0x400000);
1061                     release_mem_region(CyberRegs_phys, 0x10000);
1062                     return -EINVAL;
1063             }
1064
1065             printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
1066                    fb_info.node, fb_info.modename, CyberSize>>10);
1067
1068             /* TODO: This driver cannot be unloaded yet */
1069             DPRINTK("EXIT\n");
1070             return 0;
1071         }
1072         return -ENXIO;
1073 }
1074
1075
1076 static int Cyberfb_switch(int con, struct fb_info *info)
1077 {
1078         DPRINTK("ENTER\n");
1079         /* Do we have to save the colormap? */
1080         if (fb_display[info->currcon].cmap.len) {
1081                 fb_get_cmap(&fb_display[info->currcon].cmap, 1, Cyber_getcolreg,
1082                             info);
1083         }
1084
1085         do_fb_set_var(&fb_display[con].var, 1);
1086         info->currcon = con;
1087         /* Install new colormap */
1088         do_install_cmap(con, info);
1089         DPRINTK("EXIT\n");
1090         return(0);
1091 }
1092
1093
1094 /*
1095  *    Update the `var' structure (called by fbcon.c)
1096  *
1097  *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
1098  *    Since it's called by a kernel driver, no range checking is done.
1099  */
1100
1101 static int Cyberfb_updatevar(int con, struct fb_info *info)
1102 {
1103         DPRINTK("Enter - Exit\n");
1104         return(0);
1105 }
1106
1107
1108 /*
1109  *    Get a Video Mode
1110  */
1111
1112 static int __init get_video_mode(const char *name)
1113 {
1114         int i;
1115
1116         DPRINTK("ENTER\n");
1117         for (i = 0; i < NUM_TOTAL_MODES; i++) {
1118                 if (!strcmp(name, cyberfb_predefined[i].name)) {
1119                         cyberfb_default = cyberfb_predefined[i].var;
1120                         cyberfb_usermode = 1;
1121                         DPRINTK("EXIT - Matched predefined mode\n");
1122                         return(i);
1123                 }
1124         }
1125         return(0);
1126 }
1127
1128
1129 /*
1130  *    Text console acceleration
1131  */
1132
1133 #ifdef FBCON_HAS_CFB8
1134 static void fbcon_cyber8_bmove(struct display *p, int sy, int sx, int dy,
1135                                int dx, int height, int width)
1136 {
1137         DPRINTK("ENTER\n");
1138         sx *= 8; dx *= 8; width *= 8;
1139         Cyber_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
1140                      (u_short)(dy*fontheight(p)), (u_short)width,
1141                      (u_short)(height*fontheight(p)), (u_short)S3_NEW);
1142         DPRINTK("EXIT\n");
1143 }
1144
1145 static void fbcon_cyber8_clear(struct vc_data *conp, struct display *p, int sy,
1146                                int sx, int height, int width)
1147 {
1148         unsigned char bg;
1149
1150         DPRINTK("ENTER\n");
1151         sx *= 8; width *= 8;
1152         bg = attr_bgcol_ec(p,conp);
1153         Cyber_RectFill((u_short)sx,
1154                        (u_short)(sy*fontheight(p)),
1155                        (u_short)width,
1156                        (u_short)(height*fontheight(p)),
1157                        (u_short)S3_NEW,
1158                        (u_short)bg);
1159         DPRINTK("EXIT\n");
1160 }
1161
1162 static void fbcon_cyber8_putc(struct vc_data *conp, struct display *p, int c,
1163                               int yy, int xx)
1164 {
1165         DPRINTK("ENTER\n");
1166         Cyber_WaitBlit();
1167         fbcon_cfb8_putc(conp, p, c, yy, xx);
1168         DPRINTK("EXIT\n");
1169 }
1170
1171 static void fbcon_cyber8_putcs(struct vc_data *conp, struct display *p,
1172                                const unsigned short *s, int count,
1173                                int yy, int xx)
1174 {
1175         DPRINTK("ENTER\n");
1176         Cyber_WaitBlit();
1177         fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
1178         DPRINTK("EXIT\n");
1179 }
1180
1181 static void fbcon_cyber8_revc(struct display *p, int xx, int yy)
1182 {
1183         DPRINTK("ENTER\n");
1184         Cyber_WaitBlit();
1185         fbcon_cfb8_revc(p, xx, yy);
1186         DPRINTK("EXIT\n");
1187 }
1188
1189 static struct display_switch fbcon_cyber8 = {
1190         .setup =        fbcon_cfb8_setup,
1191         .bmove =        fbcon_cyber8_bmove,
1192         .clear =        fbcon_cyber8_clear,
1193         .putc =         fbcon_cyber8_putc,
1194         .putcs =        fbcon_cyber8_putcs,
1195         .revc =         fbcon_cyber8_revc,
1196         .clear_margins =fbcon_cfb8_clear_margins,
1197         .fontwidthmask =FONTWIDTH(8)
1198 };
1199 #endif
1200
1201
1202 #ifdef MODULE
1203 MODULE_LICENSE("GPL");
1204
1205 int init_module(void)
1206 {
1207         return cyberfb_init();
1208 }
1209 #endif /* MODULE */
1210
1211 /*
1212  *
1213  * Low level initialization routines for the CyberVision64 graphics card
1214  *
1215  * Most of the following code is from cvision_core.c
1216  *
1217  */
1218
1219 #define MAXPIXELCLOCK 135000000 /* safety */
1220
1221 #ifdef CV_AGGRESSIVE_TIMING
1222 long cv64_memclk = 55000000;
1223 #else
1224 long cv64_memclk = 50000000;
1225 #endif
1226
1227 /*********************/
1228
1229 static unsigned char clocks[]={
1230   0x13, 0x61, 0x6b, 0x6d, 0x51, 0x69, 0x54, 0x69,
1231   0x4f, 0x68, 0x6b, 0x6b, 0x18, 0x61, 0x7b, 0x6c,
1232   0x51, 0x67, 0x24, 0x62, 0x56, 0x67, 0x77, 0x6a,
1233   0x1d, 0x61, 0x53, 0x66, 0x6b, 0x68, 0x79, 0x69,
1234   0x7c, 0x69, 0x7f, 0x69, 0x22, 0x61, 0x54, 0x65,
1235   0x56, 0x65, 0x58, 0x65, 0x67, 0x66, 0x41, 0x63,
1236   0x27, 0x61, 0x13, 0x41, 0x37, 0x62, 0x6b, 0x4d,
1237   0x23, 0x43, 0x51, 0x49, 0x79, 0x66, 0x54, 0x49,
1238   0x7d, 0x66, 0x34, 0x56, 0x4f, 0x63, 0x1f, 0x42,
1239   0x6b, 0x4b, 0x7e, 0x4d, 0x18, 0x41, 0x2a, 0x43,
1240   0x7b, 0x4c, 0x74, 0x4b, 0x51, 0x47, 0x65, 0x49,
1241   0x24, 0x42, 0x68, 0x49, 0x56, 0x47, 0x75, 0x4a,
1242   0x77, 0x4a, 0x31, 0x43, 0x1d, 0x41, 0x71, 0x49,
1243   0x53, 0x46, 0x29, 0x42, 0x6b, 0x48, 0x1f, 0x41,
1244   0x79, 0x49, 0x6f, 0x48, 0x7c, 0x49, 0x38, 0x43,
1245   0x7f, 0x49, 0x5d, 0x46, 0x22, 0x41, 0x53, 0x45,
1246   0x54, 0x45, 0x55, 0x45, 0x56, 0x45, 0x57, 0x45,
1247   0x58, 0x45, 0x25, 0x41, 0x67, 0x46, 0x5b, 0x45,
1248   0x41, 0x43, 0x78, 0x47, 0x27, 0x41, 0x51, 0x44,
1249   0x13, 0x21, 0x7d, 0x47, 0x37, 0x42, 0x71, 0x46,
1250   0x6b, 0x2d, 0x14, 0x21, 0x23, 0x23, 0x7d, 0x2f,
1251   0x51, 0x29, 0x61, 0x2b, 0x79, 0x46, 0x1d, 0x22,
1252   0x54, 0x29, 0x45, 0x27, 0x7d, 0x46, 0x7f, 0x46,
1253   0x4f, 0x43, 0x2f, 0x41, 0x1f, 0x22, 0x6a, 0x2b,
1254   0x6b, 0x2b, 0x5b, 0x29, 0x7e, 0x2d, 0x65, 0x44,
1255   0x18, 0x21, 0x5e, 0x29, 0x2a, 0x23, 0x45, 0x26,
1256   0x7b, 0x2c, 0x19, 0x21, 0x74, 0x2b, 0x75, 0x2b,
1257   0x51, 0x27, 0x3f, 0x25, 0x65, 0x29, 0x40, 0x25,
1258   0x24, 0x22, 0x41, 0x25, 0x68, 0x29, 0x42, 0x25,
1259   0x56, 0x27, 0x7e, 0x2b, 0x75, 0x2a, 0x1c, 0x21,
1260   0x77, 0x2a, 0x4f, 0x26, 0x31, 0x23, 0x6f, 0x29,
1261   0x1d, 0x21, 0x32, 0x23, 0x71, 0x29, 0x72, 0x29,
1262   0x53, 0x26, 0x69, 0x28, 0x29, 0x22, 0x75, 0x29,
1263   0x6b, 0x28, 0x1f, 0x21, 0x1f, 0x21, 0x6d, 0x28,
1264   0x79, 0x29, 0x2b, 0x22, 0x6f, 0x28, 0x59, 0x26,
1265   0x7c, 0x29, 0x7d, 0x29, 0x38, 0x23, 0x21, 0x21,
1266   0x7f, 0x29, 0x39, 0x23, 0x5d, 0x26, 0x75, 0x28,
1267   0x22, 0x21, 0x77, 0x28, 0x53, 0x25, 0x6c, 0x27,
1268   0x54, 0x25, 0x61, 0x26, 0x55, 0x25, 0x30, 0x22,
1269   0x56, 0x25, 0x63, 0x26, 0x57, 0x25, 0x71, 0x27,
1270   0x58, 0x25, 0x7f, 0x28, 0x25, 0x21, 0x74, 0x27,
1271   0x67, 0x26, 0x40, 0x23, 0x5b, 0x25, 0x26, 0x21,
1272   0x41, 0x23, 0x34, 0x22, 0x78, 0x27, 0x6b, 0x26,
1273   0x27, 0x21, 0x35, 0x22, 0x51, 0x24, 0x7b, 0x27,
1274   0x13, 0x1,  0x13, 0x1,  0x7d, 0x27, 0x4c, 0x9,
1275   0x37, 0x22, 0x5b, 0xb,  0x71, 0x26, 0x5c, 0xb,
1276   0x6b, 0xd,  0x47, 0x23, 0x14, 0x1,  0x4f, 0x9,
1277   0x23, 0x3,  0x75, 0x26, 0x7d, 0xf,  0x1c, 0x2,
1278   0x51, 0x9,  0x59, 0x24, 0x61, 0xb,  0x69, 0x25,
1279   0x79, 0x26, 0x34, 0x5,  0x1d, 0x2,  0x6b, 0x25,
1280   0x54, 0x9,  0x35, 0x5,  0x45, 0x7,  0x6d, 0x25,
1281   0x7d, 0x26, 0x16, 0x1,  0x7f, 0x26, 0x77, 0xd,
1282   0x4f, 0x23, 0x78, 0xd,  0x2f, 0x21, 0x27, 0x3,
1283   0x1f, 0x2,  0x59, 0x9,  0x6a, 0xb,  0x73, 0x25,
1284   0x6b, 0xb,  0x63, 0x24, 0x5b, 0x9,  0x20, 0x2,
1285   0x7e, 0xd,  0x4b, 0x7,  0x65, 0x24, 0x43, 0x22,
1286   0x18, 0x1,  0x6f, 0xb,  0x5e, 0x9,  0x70, 0xb,
1287   0x2a, 0x3,  0x33, 0x4,  0x45, 0x6,  0x60, 0x9,
1288   0x7b, 0xc,  0x19, 0x1,  0x19, 0x1,  0x7d, 0xc,
1289   0x74, 0xb,  0x50, 0x7,  0x75, 0xb,  0x63, 0x9,
1290   0x51, 0x7,  0x23, 0x2,  0x3f, 0x5,  0x1a, 0x1,
1291   0x65, 0x9,  0x2d, 0x3,  0x40, 0x5,  0x0,  0x0,
1292 };
1293
1294 /* Console colors */
1295 unsigned char cvconscolors[16][3] = {   /* background, foreground, hilite */
1296   /*  R     G     B  */
1297   {0x30, 0x30, 0x30},
1298   {0x00, 0x00, 0x00},
1299   {0x80, 0x00, 0x00},
1300   {0x00, 0x80, 0x00},
1301   {0x00, 0x00, 0x80},
1302   {0x80, 0x80, 0x00},
1303   {0x00, 0x80, 0x80},
1304   {0x80, 0x00, 0x80},
1305   {0xff, 0xff, 0xff},
1306   {0x40, 0x40, 0x40},
1307   {0xff, 0x00, 0x00},
1308   {0x00, 0xff, 0x00},
1309   {0x00, 0x00, 0xff},
1310   {0xff, 0xff, 0x00},
1311   {0x00, 0xff, 0xff},
1312   {0x00, 0x00, 0xff}
1313 };
1314
1315 /* -------------------- Hardware specific routines ------------------------- */
1316
1317 /* Read Attribute Controller Register=idx */
1318 inline unsigned char RAttr (volatile unsigned char *regs, short idx)
1319 {
1320         wb_64 (regs, ACT_ADDRESS_W, idx);
1321         mb();
1322         udelay(100);
1323         return (rb_64(regs, ACT_ADDRESS_R));
1324 }
1325
1326 /* Read Sequencer Register=idx */
1327 inline unsigned char RSeq (volatile unsigned char *regs, short idx)
1328 {
1329         wb_64 (regs, SEQ_ADDRESS, idx);
1330         mb();
1331         return (rb_64(regs, SEQ_ADDRESS_R));
1332 }
1333
1334 /* Read CRT Controller Register=idx */
1335 inline unsigned char RCrt (volatile unsigned char *regs, short idx)
1336 {
1337         wb_64 (regs, CRT_ADDRESS, idx);
1338         mb();
1339         return (rb_64(regs, CRT_ADDRESS_R));
1340 }
1341
1342 /* Read Graphics Controller Register=idx */
1343 inline unsigned char RGfx (volatile unsigned char *regs, short idx)
1344 {
1345         wb_64 (regs, GCT_ADDRESS, idx);
1346         mb();
1347         return (rb_64(regs, GCT_ADDRESS_R));
1348 }
1349
1350 /*
1351  * Special wakeup/passthrough registers on graphics boards
1352  */
1353
1354 inline void cv64_write_port (unsigned short bits,
1355                              volatile unsigned char *base)
1356 {
1357         volatile unsigned char *addr;
1358         static unsigned char cvportbits = 0; /* Mirror port bits here */
1359         DPRINTK("ENTER\n");
1360
1361         addr = base + 0x40001;
1362         if (bits & 0x8000) {
1363                 cvportbits |= bits & 0xff; /* Set bits */
1364                 DPRINTK("Set bits: %04x\n", bits);
1365         } else {
1366                 bits = bits & 0xff;
1367                 bits = (~bits) & 0xff;
1368                 cvportbits &= bits; /* Clear bits */
1369                 DPRINTK("Clear bits: %04x\n", bits);
1370         }
1371
1372         *addr = cvportbits;
1373         DPRINTK("EXIT\n");
1374 }
1375
1376 /*
1377  * Monitor switch on CyberVision board
1378  *
1379  *  toggle:
1380  *    0 = CyberVision Signal
1381  *    1 = Amiga Signal
1382  *  board = board addr
1383  *
1384  */
1385 inline void cvscreen (int toggle, volatile unsigned char *board)
1386 {
1387         DPRINTK("ENTER\n");
1388         if (toggle == 1) {
1389                 DPRINTK("Show Amiga video\n");
1390                 cv64_write_port (0x10, board);
1391         } else {
1392                 DPRINTK("Show CyberVision video\n");
1393                 cv64_write_port (0x8010, board);
1394         }
1395         DPRINTK("EXIT\n");
1396 }
1397
1398 /* Control screen display */
1399 /* toggle: 0 = on, 1 = off */
1400 /* board = registerbase */
1401 inline void gfx_on_off(int toggle, volatile unsigned char *regs)
1402 {
1403         int r;
1404         DPRINTK("ENTER\n");
1405         
1406         toggle &= 0x1;
1407         toggle = toggle << 5;
1408         DPRINTK("Turn display %s\n", (toggle ? "off" : "on"));
1409         
1410         r = (int) RSeq(regs, SEQ_ID_CLOCKING_MODE);
1411         r &= 0xdf;      /* Set bit 5 to 0 */
1412         
1413         WSeq (regs, SEQ_ID_CLOCKING_MODE, r | toggle);
1414         DPRINTK("EXIT\n");
1415 }
1416
1417 /*
1418  * Computes M, N, and R values from
1419  * given input frequency. It uses a table of
1420  * precomputed values, to keep CPU time low.
1421  *
1422  * The return value consist of:
1423  * lower byte:  Bits 4-0: N Divider Value
1424  *              Bits 5-6: R Value          for e.g. SR10 or SR12
1425  * higher byte: Bits 0-6: M divider value  for e.g. SR11 or SR13
1426  */
1427 static unsigned short cv64_compute_clock(unsigned long freq)
1428 {
1429         static unsigned char *mnr, *save;       /* M, N + R vals */
1430         unsigned long work_freq, r;
1431         unsigned short erg;
1432         long diff, d2;
1433
1434         DPRINTK("ENTER\n");
1435         if (freq < 12500000 || freq > MAXPIXELCLOCK) {
1436                 printk("CV64 driver: Illegal clock frequency %ld, using 25MHz\n",
1437                        freq);
1438                 freq = 25000000;
1439         }
1440         DPRINTK("Freq = %ld\n", freq);
1441         mnr = clocks;   /* there the vals are stored */
1442         d2 = 0x7fffffff;
1443
1444         while (*mnr) {  /* mnr vals are 0-terminated */
1445                 work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2);
1446
1447                 r = (mnr[1] >> 5) & 0x03;
1448                 if (r != 0) {
1449                         work_freq = work_freq >> r;     /* r is the freq divider */
1450                 }
1451
1452                 work_freq *= 0x3E8;     /* 2nd part of OSC */
1453
1454                 diff = abs(freq - work_freq);
1455
1456                 if (d2 >= diff) {
1457                         d2 = diff;
1458                         /* In save are the vals for minimal diff */
1459                         save = mnr;
1460                 }
1461                 mnr += 2;
1462         }
1463         erg = *((unsigned short *)save);
1464
1465         DPRINTK("EXIT\n");
1466         return (erg);
1467 }
1468
1469 static int cv_has_4mb (volatile unsigned char *fb)
1470 {
1471         volatile unsigned long *tr, *tw;
1472         DPRINTK("ENTER\n");
1473
1474         /* write patterns in memory and test if they can be read */
1475         tw = (volatile unsigned long *) fb;
1476         tr = (volatile unsigned long *) (fb + 0x02000000);
1477
1478         *tw = 0x87654321;
1479         
1480         if (*tr != 0x87654321) {
1481                 DPRINTK("EXIT - <4MB\n");
1482                 return (0);
1483         }
1484
1485         /* upper memory region */
1486         tw = (volatile unsigned long *) (fb + 0x00200000);
1487         tr = (volatile unsigned long *) (fb + 0x02200000);
1488
1489         *tw = 0x87654321;
1490
1491         if (*tr != 0x87654321) {
1492                 DPRINTK("EXIT - <4MB\n");
1493                 return (0);
1494         }
1495
1496         *tw = 0xAAAAAAAA;
1497
1498         if (*tr != 0xAAAAAAAA) {
1499                 DPRINTK("EXIT - <4MB\n");
1500                 return (0);
1501         }
1502
1503         *tw = 0x55555555;
1504
1505         if (*tr != 0x55555555) {
1506                 DPRINTK("EXIT - <4MB\n");
1507                 return (0);
1508         }
1509
1510         DPRINTK("EXIT\n");
1511         return (1);
1512 }
1513
1514 static void cv64_board_init (void)
1515 {
1516         volatile unsigned char *regs = CyberRegs;
1517         int i;
1518         unsigned int clockpar;
1519         unsigned char test;
1520         
1521         DPRINTK("ENTER\n");
1522
1523         /*
1524          * Special CyberVision 64 board operations
1525          */
1526         /* Reset board */
1527         for (i = 0; i < 6; i++) {
1528                 cv64_write_port (0xff, CyberBase);
1529         }
1530         /* Return to operational mode */
1531         cv64_write_port (0x8004, CyberBase);
1532         
1533         /*
1534          * Generic (?) S3 chip wakeup
1535          */
1536         /* Disable I/O & memory decoders, video in setup mode */
1537         wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x10);
1538         /* Video responds to cmds, addrs & data */
1539         wb_64 (regs, SREG_OPTION_SELECT, 0x1);
1540         /* Enable I/O & memory decoders, video in operational mode */
1541         wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x8);
1542         /* VGA color emulation, enable cpu access to display mem */ 
1543         wb_64 (regs, GREG_MISC_OUTPUT_W, 0x03);
1544         /* Unlock S3 VGA regs */
1545         WCrt (regs, CRT_ID_REGISTER_LOCK_1, 0x48); 
1546         /* Unlock system control & extension registers */
1547         WCrt (regs, CRT_ID_REGISTER_LOCK_2, 0xA5);
1548 /* GRF - Enable interrupts */
1549         /* Enable enhanced regs access, Ready cntl 0 wait states */
1550         test = RCrt (regs, CRT_ID_SYSTEM_CONFIG);
1551         test = test | 0x01;             /* enable enhanced register access */
1552         test = test & 0xEF;             /* clear bit 4, 0 wait state */
1553         WCrt (regs, CRT_ID_SYSTEM_CONFIG, test);
1554         /*
1555          * bit 0=1: Enable enhaced mode functions
1556          * bit 2=0: Enhanced mode 8+ bits/pixel
1557          * bit 4=1: Enable linear addressing
1558          * bit 5=1: Enable MMIO
1559          */
1560         wb_64 (regs, ECR_ADV_FUNC_CNTL, 0x31);
1561         /*
1562          * bit 0=1: Color emulation
1563          * bit 1=1: Enable CPU access to display memory
1564          * bit 5=1: Select high 64K memory page
1565          */
1566 /* GRF - 0xE3 */
1567         wb_64 (regs, GREG_MISC_OUTPUT_W, 0x23);
1568         
1569         /* Cpu base addr */
1570         WCrt (regs, CRT_ID_EXT_SYS_CNTL_4, 0x0);
1571         
1572         /* Reset. This does nothing on Trio, but standard VGA practice */
1573         /* WSeq (CyberRegs, SEQ_ID_RESET, 0x03); */
1574         /* Character clocks 8 dots wide */
1575         WSeq (regs, SEQ_ID_CLOCKING_MODE, 0x01);
1576         /* Enable cpu write to all color planes */
1577         WSeq (regs, SEQ_ID_MAP_MASK, 0x0F);
1578         /* Font table in 1st 8k of plane 2, font A=B disables swtich */
1579         WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x0);
1580         /* Allow mem access to 256kb */
1581         WSeq (regs, SEQ_ID_MEMORY_MODE, 0x2);
1582         /* Unlock S3 extensions to VGA Sequencer regs */
1583         WSeq (regs, SEQ_ID_UNLOCK_EXT, 0x6);
1584         
1585         /* Enable 4MB fast page mode */
1586         test = RSeq (regs, SEQ_ID_BUS_REQ_CNTL);
1587         test = test | 1 << 6;
1588         WSeq (regs, SEQ_ID_BUS_REQ_CNTL, test);
1589         
1590         /* Faster LUT write: 1 DCLK LUT write cycle, RAMDAC clk doubled */
1591         WSeq (regs, SEQ_ID_RAMDAC_CNTL, 0xC0);
1592
1593         /* Clear immediate clock load bit */
1594         test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
1595         test = test & 0xDF;
1596         /* If > 55MHz, enable 2 cycle memory write */
1597         if (cv64_memclk >= 55000000) {
1598                 test |= 0x80;
1599         }
1600         WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
1601
1602         /* Set MCLK value */
1603         clockpar = cv64_compute_clock (cv64_memclk);
1604         test = (clockpar & 0xFF00) >> 8;
1605         WSeq (regs, SEQ_ID_MCLK_HI, test);
1606         test = clockpar & 0xFF;
1607         WSeq (regs, SEQ_ID_MCLK_LO, test);
1608
1609         /* Chip rev specific: Not in my Trio manual!!! */
1610         if (RCrt (regs, CRT_ID_REVISION) == 0x10)
1611                 WSeq (regs, SEQ_ID_MORE_MAGIC, test);
1612
1613         /* We now load an 25 MHz, 31kHz, 640x480 standard VGA Mode. */
1614
1615         /* Set DCLK value */
1616         WSeq (regs, SEQ_ID_DCLK_HI, 0x13);
1617         WSeq (regs, SEQ_ID_DCLK_LO, 0x41);
1618
1619         /* Load DCLK (and MCLK?) immediately */
1620         test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
1621         test = test | 0x22;
1622         WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
1623
1624         /* Enable loading of DCLK */
1625         test = rb_64(regs, GREG_MISC_OUTPUT_R);
1626         test = test | 0x0C;
1627         wb_64 (regs, GREG_MISC_OUTPUT_W, test);
1628
1629         /* Turn off immediate xCLK load */
1630         WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, 0x2);
1631
1632         /* Horizontal character clock counts */
1633         /* 8 LSB of 9 bits = total line - 5 */
1634         WCrt (regs, CRT_ID_HOR_TOTAL, 0x5F);
1635         /* Active display line */
1636         WCrt (regs, CRT_ID_HOR_DISP_ENA_END, 0x4F);
1637         /* Blank assertion start */
1638         WCrt (regs, CRT_ID_START_HOR_BLANK, 0x50);
1639         /* Blank assertion end */
1640         WCrt (regs, CRT_ID_END_HOR_BLANK, 0x82);
1641         /* HSYNC assertion start */
1642         WCrt (regs, CRT_ID_START_HOR_RETR, 0x54);
1643         /* HSYNC assertion end */
1644         WCrt (regs, CRT_ID_END_HOR_RETR, 0x80);
1645         WCrt (regs, CRT_ID_VER_TOTAL, 0xBF);
1646         WCrt (regs, CRT_ID_OVERFLOW, 0x1F);
1647         WCrt (regs, CRT_ID_PRESET_ROW_SCAN, 0x0);
1648         WCrt (regs, CRT_ID_MAX_SCAN_LINE, 0x40);
1649         WCrt (regs, CRT_ID_CURSOR_START, 0x00);
1650         WCrt (regs, CRT_ID_CURSOR_END, 0x00);
1651         WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00);
1652         WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00);
1653         WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1654         WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
1655         WCrt (regs, CRT_ID_START_VER_RETR, 0x9C);
1656         WCrt (regs, CRT_ID_END_VER_RETR, 0x0E);
1657         WCrt (regs, CRT_ID_VER_DISP_ENA_END, 0x8F);
1658         WCrt (regs, CRT_ID_SCREEN_OFFSET, 0x50);
1659         WCrt (regs, CRT_ID_UNDERLINE_LOC, 0x00);
1660         WCrt (regs, CRT_ID_START_VER_BLANK, 0x96);
1661         WCrt (regs, CRT_ID_END_VER_BLANK, 0xB9);
1662         WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3);
1663         WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF);
1664         WCrt (regs, CRT_ID_BACKWAD_COMP_3, 0x10);       /* FIFO enabled */
1665         WCrt (regs, CRT_ID_MISC_1, 0x35);
1666         WCrt (regs, CRT_ID_DISPLAY_FIFO, 0x5A);
1667         WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, 0x70);
1668         WCrt (regs, CRT_ID_LAW_POS_LO, 0x40);
1669         WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, 0xFF);
1670
1671         WGfx (regs, GCT_ID_SET_RESET, 0x0);
1672         WGfx (regs, GCT_ID_ENABLE_SET_RESET, 0x0);
1673         WGfx (regs, GCT_ID_COLOR_COMPARE, 0x0);
1674         WGfx (regs, GCT_ID_DATA_ROTATE, 0x0);
1675         WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x0);
1676         WGfx (regs, GCT_ID_GRAPHICS_MODE, 0x40);
1677         WGfx (regs, GCT_ID_MISC, 0x01);
1678         WGfx (regs, GCT_ID_COLOR_XCARE, 0x0F);
1679         WGfx (regs, GCT_ID_BITMASK, 0xFF);
1680
1681         /* Colors for text mode */
1682         for (i = 0; i < 0xf; i++)
1683                 WAttr (regs, i, i);
1684
1685         WAttr (regs, ACT_ID_ATTR_MODE_CNTL, 0x41);
1686         WAttr (regs, ACT_ID_OVERSCAN_COLOR, 0x01);
1687         WAttr (regs, ACT_ID_COLOR_PLANE_ENA, 0x0F);
1688         WAttr (regs, ACT_ID_HOR_PEL_PANNING, 0x0);
1689         WAttr (regs, ACT_ID_COLOR_SELECT, 0x0);
1690
1691         wb_64 (regs, VDAC_MASK, 0xFF);
1692
1693         *((unsigned long *) (regs + ECR_FRGD_COLOR)) = 0xFF;
1694         *((unsigned long *) (regs + ECR_BKGD_COLOR)) = 0;
1695
1696         /* Colors initially set to grayscale */
1697
1698         wb_64 (regs, VDAC_ADDRESS_W, 0);
1699         for (i = 255; i >= 0; i--) {
1700                 wb_64(regs, VDAC_DATA, i);
1701                 wb_64(regs, VDAC_DATA, i);
1702                 wb_64(regs, VDAC_DATA, i);
1703         }
1704
1705         /* GFx hardware cursor off */
1706         WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
1707
1708         /* Set first to 4MB, so test will work */
1709         WCrt (regs, CRT_ID_LAW_CNTL, 0x13);
1710         /* Find "correct" size of fbmem of Z3 board */
1711         if (cv_has_4mb (CyberMem)) {
1712                 CyberSize = 1024 * 1024 * 4;
1713                 WCrt (regs, CRT_ID_LAW_CNTL, 0x13);
1714                 DPRINTK("4MB board\n");
1715         } else {
1716                 CyberSize = 1024 * 1024 * 2;
1717                 WCrt (regs, CRT_ID_LAW_CNTL, 0x12);
1718                 DPRINTK("2MB board\n");
1719         }
1720
1721         /* Initialize graphics engine */
1722         Cyber_WaitBlit();
1723         vgaw16 (regs, ECR_FRGD_MIX, 0x27);
1724         vgaw16 (regs, ECR_BKGD_MIX, 0x07);
1725         vgaw16 (regs, ECR_READ_REG_DATA, 0x1000);
1726         udelay(200);
1727         vgaw16 (regs, ECR_READ_REG_DATA, 0x2000);
1728         Cyber_WaitBlit();
1729         vgaw16 (regs, ECR_READ_REG_DATA, 0x3FFF);
1730         Cyber_WaitBlit();
1731         udelay(200);
1732         vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF);
1733         Cyber_WaitBlit();
1734         vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, ~0);
1735         Cyber_WaitBlit();
1736         vgaw16 (regs, ECR_READ_REG_DATA, 0xE000);
1737         vgaw16 (regs, ECR_CURRENT_Y_POS2, 0x00);
1738         vgaw16 (regs, ECR_CURRENT_X_POS2, 0x00);
1739         vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
1740         vgaw16 (regs, ECR_DEST_Y__AX_STEP, 0x00);
1741         vgaw16 (regs, ECR_DEST_Y2__AX_STEP2, 0x00);
1742         vgaw16 (regs, ECR_DEST_X__DIA_STEP, 0x00);
1743         vgaw16 (regs, ECR_DEST_X2__DIA_STEP2, 0x00);
1744         vgaw16 (regs, ECR_SHORT_STROKE, 0x00);
1745         vgaw16 (regs, ECR_DRAW_CMD, 0x01);
1746
1747         Cyber_WaitBlit();
1748
1749         vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF);
1750         vgaw16 (regs, ECR_BKGD_COLOR, 0x01);
1751         vgaw16 (regs, ECR_FRGD_COLOR, 0x00);
1752
1753
1754         /* Enable video display (set bit 5) */
1755 /* ARB - Would also seem to write to AR13.
1756  *       May want to use parts of WAttr to set JUST bit 5
1757  */
1758         WAttr (regs, 0x33, 0);
1759         
1760 /* GRF - function code ended here */
1761
1762         /* Turn gfx on again */
1763         gfx_on_off (0, regs);
1764
1765         /* Pass-through */
1766         cvscreen (0, CyberBase);
1767
1768         DPRINTK("EXIT\n");
1769 }
1770
1771 static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
1772 {
1773   volatile unsigned char *regs = CyberRegs;
1774   int fx, fy;
1775   unsigned short mnr;
1776   unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, VSE, VT;
1777   char LACE, DBLSCAN, TEXT, CONSOLE;
1778   int cr50, sr15, sr18, clock_mode, test;
1779   int m, n;
1780   int tfillm, temptym;
1781   int hmul;
1782         
1783   /* ---------------- */
1784   int xres, hfront, hsync, hback;
1785   int yres, vfront, vsync, vback;
1786   int bpp;
1787 #if 0
1788   float freq_f;
1789 #endif
1790   long freq;
1791   /* ---------------- */
1792         
1793   DPRINTK("ENTER\n");
1794   TEXT = 0;     /* if depth == 4 */
1795   CONSOLE = 0;  /* mode num == 255 (console) */
1796   fx = fy = 8;  /* force 8x8 font */
1797
1798 /* GRF - Disable interrupts */  
1799         
1800   gfx_on_off (1, regs);
1801         
1802   switch (video_mode->bits_per_pixel) {
1803   case 15:
1804   case 16:
1805     hmul = 2;
1806     break;
1807                 
1808   default:
1809     hmul = 1;
1810     break;
1811   }
1812         
1813   bpp = video_mode->bits_per_pixel;
1814   xres = video_mode->xres;
1815   hfront = video_mode->right_margin;
1816   hsync = video_mode->hsync_len;
1817   hback = video_mode->left_margin;
1818
1819   LACE = 0;
1820   DBLSCAN = 0;
1821
1822   if (video_mode->vmode & FB_VMODE_DOUBLE) {
1823     yres = video_mode->yres * 2;
1824     vfront = video_mode->lower_margin * 2;
1825     vsync = video_mode->vsync_len * 2;
1826     vback = video_mode->upper_margin * 2;
1827     DBLSCAN = 1;
1828   } else if (video_mode->vmode & FB_VMODE_INTERLACED) {
1829     yres = (video_mode->yres + 1) / 2;
1830     vfront = (video_mode->lower_margin + 1) / 2;
1831     vsync = (video_mode->vsync_len + 1) / 2;
1832     vback = (video_mode->upper_margin + 1) / 2;
1833     LACE = 1;
1834   } else {
1835     yres = video_mode->yres;
1836     vfront = video_mode->lower_margin;
1837     vsync = video_mode->vsync_len;
1838     vback = video_mode->upper_margin;
1839   }
1840
1841   /* ARB Dropping custom setup method from cvision.c */
1842 #if 0
1843   if (cvision_custom_mode) {
1844     HBS = hbs / 8 * hmul;
1845     HBE = hbe / 8 * hmul;
1846     HSS = hss / 8 * hmul;
1847     HSE = hse / 8 * hmul;
1848     HT  = ht / 8 * hmul - 5;
1849                 
1850     VBS = vbs - 1;
1851     VSS = vss;
1852     VSE = vse;
1853     VBE = vbe;
1854     VT  = vt - 2;
1855   } else {
1856 #else
1857     {
1858 #endif
1859     HBS = hmul * (xres / 8);
1860     HBE = hmul * ((xres/8) + (hfront/8) + (hsync/8) + (hback/8) - 2);
1861     HSS = hmul * ((xres/8) + (hfront/8) + 2);
1862     HSE = hmul * ((xres/8) + (hfront/8) + (hsync/8) + 1);
1863     HT  = hmul * ((xres/8) + (hfront/8) + (hsync/8) + (hback/8));
1864         
1865     VBS = yres;
1866     VBE = yres + vfront + vsync + vback - 2;
1867     VSS = yres + vfront - 1;
1868     VSE = yres + vfront + vsync - 1;
1869     VT  = yres + vfront + vsync + vback - 2;
1870   }
1871
1872   wb_64 (regs, ECR_ADV_FUNC_CNTL, (TEXT ? 0x00 : 0x31));
1873         
1874   if (TEXT)
1875     HDE = ((video_mode->xres + fx - 1) / fx) - 1;
1876   else
1877     HDE = (video_mode->xres + 3) * hmul / 8 - 1;
1878         
1879   VDE = video_mode->yres - 1;
1880
1881   WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
1882   WCrt (regs, CRT_ID_EXT_DAC_CNTL, 0x00);
1883         
1884   WSeq (regs, SEQ_ID_MEMORY_MODE,
1885         (TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x0e);
1886   WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x00);
1887   WSeq (regs, SEQ_ID_MAP_MASK,
1888         (video_mode->bits_per_pixel == 1) ? 0x01 : 0xFF);
1889   WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1890         
1891   /* cv64_compute_clock accepts arguments in Hz */
1892   /* pixclock is in ps ... convert to Hz */
1893         
1894 #if 0
1895   freq_f = (1.0 / (float) video_mode->pixclock) * 1000000000;
1896   freq = ((long) freq_f) * 1000;
1897 #else
1898 /* freq = (long) ((long long)1000000000000 / (long long) video_mode->pixclock);
1899  */
1900   freq = (1000000000 / video_mode->pixclock) * 1000;
1901 #endif
1902
1903   mnr = cv64_compute_clock (freq);
1904   WSeq (regs, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8));
1905   WSeq (regs, SEQ_ID_DCLK_LO, (mnr & 0xFF));
1906         
1907   /* Load display parameters into board */
1908   WCrt (regs, CRT_ID_EXT_HOR_OVF,
1909         ((HT & 0x100) ? 0x01 : 0x00) |
1910         ((HDE & 0x100) ? 0x02 : 0x00) |
1911         ((HBS & 0x100) ? 0x04 : 0x00) |
1912         /* ((HBE & 0x40) ? 0x08 : 0x00) | */
1913         ((HSS & 0x100) ? 0x10 : 0x00) |
1914         /* ((HSE & 0x20) ? 0x20 : 0x00) | */
1915         (((HT-5) & 0x100) ? 0x40 : 0x00)
1916         );
1917         
1918   WCrt (regs, CRT_ID_EXT_VER_OVF,
1919         0x40 |
1920         ((VT & 0x400) ? 0x01 : 0x00) |
1921         ((VDE & 0x400) ? 0x02 : 0x00) |
1922         ((VBS & 0x400) ? 0x04 : 0x00) |
1923         ((VSS & 0x400) ? 0x10 : 0x00)
1924         );
1925         
1926   WCrt (regs, CRT_ID_HOR_TOTAL, HT);
1927   WCrt (regs, CRT_ID_DISPLAY_FIFO, HT - 5);
1928   WCrt (regs, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE));
1929   WCrt (regs, CRT_ID_START_HOR_BLANK, HBS);
1930   WCrt (regs, CRT_ID_END_HOR_BLANK, ((HBE & 0x1F) | 0x80));
1931   WCrt (regs, CRT_ID_START_HOR_RETR, HSS);
1932   WCrt (regs, CRT_ID_END_HOR_RETR,
1933         (HSE & 0x1F) |
1934         ((HBE & 0x20) ? 0x80 : 0x00)
1935         );
1936   WCrt (regs, CRT_ID_VER_TOTAL, VT);
1937   WCrt (regs, CRT_ID_OVERFLOW,
1938         0x10 |
1939         ((VT & 0x100) ? 0x01 : 0x00) |
1940         ((VDE & 0x100) ? 0x02 : 0x00) |
1941         ((VSS & 0x100) ? 0x04 : 0x00) |
1942         ((VBS & 0x100) ? 0x08 : 0x00) |
1943         ((VT & 0x200) ? 0x20 : 0x00) |
1944         ((VDE & 0x200) ? 0x40 : 0x00) |
1945         ((VSS & 0x200) ? 0x80 : 0x00)
1946         );
1947   WCrt (regs, CRT_ID_MAX_SCAN_LINE,
1948         0x40 |
1949         (DBLSCAN ? 0x80 : 0x00) |
1950         ((VBS & 0x200) ? 0x20 : 0x00) |
1951         (TEXT ? ((fy - 1) & 0x1F) : 0x00)
1952         );
1953         
1954   WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3);
1955
1956   /* Text cursor */
1957         
1958   if (TEXT) {
1959 #if 1
1960     WCrt (regs, CRT_ID_CURSOR_START, (fy & 0x1f) - 2);
1961     WCrt (regs, CRT_ID_CURSOR_END, (fy & 0x1F) - 1);
1962 #else
1963     WCrt (regs, CRT_ID_CURSOR_START, 0x00);
1964     WCrt (regs, CRT_ID_CURSOR_END, fy & 0x1F);
1965 #endif
1966     WCrt (regs, CRT_ID_UNDERLINE_LOC, (fy - 1) & 0x1F);
1967     WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1968     WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
1969   }
1970         
1971   WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00);
1972   WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00);
1973   WCrt (regs, CRT_ID_START_VER_RETR, VSS);
1974   WCrt (regs, CRT_ID_END_VER_RETR, (VSE & 0x0F));
1975   WCrt (regs, CRT_ID_VER_DISP_ENA_END, VDE);
1976   WCrt (regs, CRT_ID_START_VER_BLANK, VBS);
1977   WCrt (regs, CRT_ID_END_VER_BLANK, VBE);
1978   WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF);
1979   WCrt (regs, CRT_ID_LACE_RETR_START, HT / 2);
1980   WCrt (regs, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00));
1981   WGfx (regs, GCT_ID_GRAPHICS_MODE,
1982         ((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x00 : 0x40));
1983   WGfx (regs, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
1984   WSeq (regs, SEQ_ID_MEMORY_MODE,
1985         ((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x02));
1986         
1987   wb_64 (regs, VDAC_MASK, 0xFF);
1988         
1989   /* Blank border */
1990   test = RCrt (regs, CRT_ID_BACKWAD_COMP_2);
1991   WCrt (regs, CRT_ID_BACKWAD_COMP_2, (test | 0x20));
1992         
1993   sr15 = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
1994   sr15 &= 0xEF;
1995   sr18 = RSeq (regs, SEQ_ID_RAMDAC_CNTL);
1996   sr18 &= 0x7F;
1997   clock_mode = 0x00;
1998   cr50 = 0x00;
1999         
2000   test = RCrt (regs, CRT_ID_EXT_MISC_CNTL_2);
2001   test &= 0xD;
2002         
2003   /* Clear roxxler byte-swapping... */
2004   cv64_write_port (0x0040, CyberBase);
2005   cv64_write_port (0x0020, CyberBase);
2006         
2007   switch (video_mode->bits_per_pixel) {
2008   case 1:
2009   case 4:       /* text */
2010     HDE = video_mode->xres / 16;
2011     break;
2012                 
2013   case 8:
2014     if (freq > 80000000) {
2015       clock_mode = 0x10 | 0x02;
2016       sr15 |= 0x10;
2017       sr18 |= 0x80;
2018     }
2019     HDE = video_mode->xres / 8;
2020     cr50 |= 0x00;
2021     break;
2022                 
2023   case 15:
2024     cv64_write_port (0x8020, CyberBase);
2025     clock_mode = 0x30;
2026     HDE = video_mode->xres / 4;
2027     cr50 |= 0x10;
2028     break;
2029                 
2030   case 16:
2031     cv64_write_port (0x8020, CyberBase);
2032     clock_mode = 0x50;
2033     HDE = video_mode->xres / 4;
2034     cr50 |= 0x10;
2035     break;
2036                 
2037   case 24:
2038   case 32:
2039     cv64_write_port (0x8040, CyberBase);
2040     clock_mode = 0xD0;
2041     HDE = video_mode->xres / 2;
2042     cr50 |= 0x30;
2043     break;
2044   }
2045
2046   WCrt (regs, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test);
2047   WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, sr15);
2048   WSeq (regs, SEQ_ID_RAMDAC_CNTL, sr18);
2049   WCrt (regs, CRT_ID_SCREEN_OFFSET, HDE);
2050
2051   WCrt (regs, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35));
2052         
2053   test = RCrt (regs, CRT_ID_EXT_SYS_CNTL_2);
2054   test &= ~0x30;
2055   test |= (HDE >> 4) & 0x30;
2056   WCrt (regs, CRT_ID_EXT_SYS_CNTL_2, test);
2057         
2058   /* Set up graphics engine */
2059   switch (video_mode->xres) {
2060   case 1024:
2061     cr50 |= 0x00;
2062     break;
2063                 
2064   case 640:
2065     cr50 |= 0x40;
2066     break;
2067                 
2068   case 800:
2069     cr50 |= 0x80;
2070     break;
2071                 
2072   case 1280:
2073     cr50 |= 0xC0;
2074     break;
2075                 
2076   case 1152:
2077     cr50 |= 0x01;
2078     break;
2079                 
2080   case 1600:
2081     cr50 |= 0x81;
2082     break;
2083                 
2084   default:      /* XXX */
2085     break;
2086   }
2087         
2088   WCrt (regs, CRT_ID_EXT_SYS_CNTL_1, cr50);
2089         
2090   udelay(100);
2091   WAttr (regs, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41));
2092   udelay(100);
2093   WAttr (regs, ACT_ID_COLOR_PLANE_ENA,
2094          (video_mode->bits_per_pixel == 1) ? 0x01 : 0x0F);
2095   udelay(100);
2096         
2097   tfillm = (96 * (cv64_memclk / 1000)) / 240000;
2098         
2099   switch (video_mode->bits_per_pixel) {
2100   case 32:
2101   case 24:
2102     temptym = (24 * (cv64_memclk / 1000)) / (freq / 1000);
2103     break;
2104   case 15:
2105   case 16:
2106     temptym = (48 * (cv64_memclk / 1000)) / (freq / 1000);
2107     break;
2108   case 4:
2109     temptym = (192 * (cv64_memclk / 1000)) / (freq / 1000);
2110     break;
2111   default:
2112     temptym = (96 * (cv64_memclk / 1000)) / (freq / 1000);
2113     break;
2114   }
2115         
2116   m = (temptym - tfillm - 9) / 2;
2117   if (m < 0)
2118     m = 0;
2119   m = (m & 0x1F) << 3;
2120   if (m < 0x18)
2121     m = 0x18;
2122   n = 0xFF;
2123         
2124   WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, m);
2125   WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, n);
2126   udelay(10);
2127         
2128   /* Text initialization */
2129         
2130   if (TEXT) {
2131     /* Do text initialization here ! */
2132   }
2133         
2134   if (CONSOLE) {
2135     int i;
2136     wb_64 (regs, VDAC_ADDRESS_W, 0);
2137     for (i = 0; i < 4; i++) {
2138       wb_64 (regs, VDAC_DATA, cvconscolors [i][0]);
2139       wb_64 (regs, VDAC_DATA, cvconscolors [i][1]);
2140       wb_64 (regs, VDAC_DATA, cvconscolors [i][2]);
2141     }
2142   }
2143         
2144   WAttr (regs, 0x33, 0);
2145         
2146   /* Turn gfx on again */
2147   gfx_on_off (0, (volatile unsigned char *) regs);
2148         
2149   /* Pass-through */
2150   cvscreen (0, CyberBase);
2151
2152 DPRINTK("EXIT\n");
2153 }
2154
2155 void cvision_bitblt (u_short sx, u_short sy, u_short dx, u_short dy,
2156                      u_short w, u_short h)
2157 {
2158         volatile unsigned char *regs = CyberRegs;
2159         unsigned short drawdir = 0;
2160         
2161         DPRINTK("ENTER\n");
2162         if (sx > dx) {
2163                 drawdir |= 1 << 5;
2164         } else {
2165                 sx += w - 1;
2166                 dx += w - 1;
2167         }
2168         
2169         if (sy > dy) {
2170                 drawdir |= 1 << 7;
2171         } else {
2172                 sy += h - 1;
2173                 dy += h - 1;
2174         }
2175         
2176         Cyber_WaitBlit();
2177         vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
2178         vgaw16 (regs, ECR_BKGD_MIX, 0x7);
2179         vgaw16 (regs, ECR_FRGD_MIX, 0x67);
2180         vgaw16 (regs, ECR_BKGD_COLOR, 0x0);
2181         vgaw16 (regs, ECR_FRGD_COLOR, 0x1);
2182         vgaw16 (regs, ECR_BITPLANE_READ_MASK, 0x1);
2183         vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, 0xFFF);
2184         vgaw16 (regs, ECR_CURRENT_Y_POS, sy);
2185         vgaw16 (regs, ECR_CURRENT_X_POS, sx);
2186         vgaw16 (regs, ECR_DEST_Y__AX_STEP, dy);
2187         vgaw16 (regs, ECR_DEST_X__DIA_STEP, dx);
2188         vgaw16 (regs, ECR_READ_REG_DATA, h - 1);
2189         vgaw16 (regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
2190         vgaw16 (regs, ECR_DRAW_CMD, 0xC051 | drawdir);
2191         DPRINTK("EXIT\n");
2192 }
2193
2194 void cvision_clear (u_short dx, u_short dy, u_short w, u_short h, u_short bg)
2195 {
2196         volatile unsigned char *regs = CyberRegs;
2197         DPRINTK("ENTER\n");
2198         Cyber_WaitBlit();
2199         vgaw16 (regs, ECR_FRGD_MIX, 0x0027);
2200         vgaw16 (regs, ECR_FRGD_COLOR, bg);
2201         vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
2202         vgaw16 (regs, ECR_CURRENT_Y_POS, dy);
2203         vgaw16 (regs, ECR_CURRENT_X_POS, dx);
2204         vgaw16 (regs, ECR_READ_REG_DATA, h - 1);
2205         vgaw16 (regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
2206         vgaw16 (regs, ECR_DRAW_CMD, 0x40B1);    
2207         DPRINTK("EXIT\n");
2208 }
2209
2210 #ifdef CYBERFBDEBUG
2211 /*
2212  * Dump internal settings of CyberVision board
2213  */
2214 static void cv64_dump (void)
2215 {
2216         volatile unsigned char *regs = CyberRegs;
2217         DPRINTK("ENTER\n");
2218         /* Dump the VGA setup values */
2219         *(regs + S3_CRTC_ADR) = 0x00;
2220         DPRINTK("CR00 = %x\n", *(regs + S3_CRTC_DATA));
2221         *(regs + S3_CRTC_ADR) = 0x01;
2222         DPRINTK("CR01 = %x\n", *(regs + S3_CRTC_DATA));
2223         *(regs + S3_CRTC_ADR) = 0x02;
2224         DPRINTK("CR02 = %x\n", *(regs + S3_CRTC_DATA));
2225         *(regs + S3_CRTC_ADR) = 0x03;
2226         DPRINTK("CR03 = %x\n", *(regs + S3_CRTC_DATA));
2227         *(regs + S3_CRTC_ADR) = 0x04;
2228         DPRINTK("CR04 = %x\n", *(regs + S3_CRTC_DATA));
2229         *(regs + S3_CRTC_ADR) = 0x05;
2230         DPRINTK("CR05 = %x\n", *(regs + S3_CRTC_DATA));
2231         *(regs + S3_CRTC_ADR) = 0x06;
2232         DPRINTK("CR06 = %x\n", *(regs + S3_CRTC_DATA));
2233         *(regs + S3_CRTC_ADR) = 0x07;
2234         DPRINTK("CR07 = %x\n", *(regs + S3_CRTC_DATA));
2235         *(regs + S3_CRTC_ADR) = 0x08;
2236         DPRINTK("CR08 = %x\n", *(regs + S3_CRTC_DATA));
2237         *(regs + S3_CRTC_ADR) = 0x09;
2238         DPRINTK("CR09 = %x\n", *(regs + S3_CRTC_DATA));
2239         *(regs + S3_CRTC_ADR) = 0x10;
2240         DPRINTK("CR10 = %x\n", *(regs + S3_CRTC_DATA));
2241         *(regs + S3_CRTC_ADR) = 0x11;
2242         DPRINTK("CR11 = %x\n", *(regs + S3_CRTC_DATA));
2243         *(regs + S3_CRTC_ADR) = 0x12;
2244         DPRINTK("CR12 = %x\n", *(regs + S3_CRTC_DATA));
2245         *(regs + S3_CRTC_ADR) = 0x13;
2246         DPRINTK("CR13 = %x\n", *(regs + S3_CRTC_DATA));
2247         *(regs + S3_CRTC_ADR) = 0x15;
2248         DPRINTK("CR15 = %x\n", *(regs + S3_CRTC_DATA));
2249         *(regs + S3_CRTC_ADR) = 0x16;
2250         DPRINTK("CR16 = %x\n", *(regs + S3_CRTC_DATA));
2251         *(regs + S3_CRTC_ADR) = 0x36;
2252         DPRINTK("CR36 = %x\n", *(regs + S3_CRTC_DATA));
2253         *(regs + S3_CRTC_ADR) = 0x37;
2254         DPRINTK("CR37 = %x\n", *(regs + S3_CRTC_DATA));
2255         *(regs + S3_CRTC_ADR) = 0x42;
2256         DPRINTK("CR42 = %x\n", *(regs + S3_CRTC_DATA));
2257         *(regs + S3_CRTC_ADR) = 0x43;
2258         DPRINTK("CR43 = %x\n", *(regs + S3_CRTC_DATA));
2259         *(regs + S3_CRTC_ADR) = 0x50;
2260         DPRINTK("CR50 = %x\n", *(regs + S3_CRTC_DATA));
2261         *(regs + S3_CRTC_ADR) = 0x51;
2262         DPRINTK("CR51 = %x\n", *(regs + S3_CRTC_DATA));
2263         *(regs + S3_CRTC_ADR) = 0x53;
2264         DPRINTK("CR53 = %x\n", *(regs + S3_CRTC_DATA));
2265         *(regs + S3_CRTC_ADR) = 0x58;
2266         DPRINTK("CR58 = %x\n", *(regs + S3_CRTC_DATA));
2267         *(regs + S3_CRTC_ADR) = 0x59;
2268         DPRINTK("CR59 = %x\n", *(regs + S3_CRTC_DATA));
2269         *(regs + S3_CRTC_ADR) = 0x5A;
2270         DPRINTK("CR5A = %x\n", *(regs + S3_CRTC_DATA));
2271         *(regs + S3_CRTC_ADR) = 0x5D;
2272         DPRINTK("CR5D = %x\n", *(regs + S3_CRTC_DATA));
2273         *(regs + S3_CRTC_ADR) = 0x5E;
2274         DPRINTK("CR5E = %x\n", *(regs + S3_CRTC_DATA));
2275         DPRINTK("MISC = %x\n", *(regs + GREG_MISC_OUTPUT_R));
2276         *(regs + SEQ_ADDRESS) = 0x01;
2277         DPRINTK("SR01 = %x\n", *(regs + SEQ_ADDRESS_R));
2278         *(regs + SEQ_ADDRESS) = 0x02;
2279         DPRINTK("SR02 = %x\n", *(regs + SEQ_ADDRESS_R));
2280         *(regs + SEQ_ADDRESS) = 0x03;
2281         DPRINTK("SR03 = %x\n", *(regs + SEQ_ADDRESS_R));
2282         *(regs + SEQ_ADDRESS) = 0x09;
2283         DPRINTK("SR09 = %x\n", *(regs + SEQ_ADDRESS_R));
2284         *(regs + SEQ_ADDRESS) = 0x10;
2285         DPRINTK("SR10 = %x\n", *(regs + SEQ_ADDRESS_R));
2286         *(regs + SEQ_ADDRESS) = 0x11;
2287         DPRINTK("SR11 = %x\n", *(regs + SEQ_ADDRESS_R));
2288         *(regs + SEQ_ADDRESS) = 0x12;
2289         DPRINTK("SR12 = %x\n", *(regs + SEQ_ADDRESS_R));
2290         *(regs + SEQ_ADDRESS) = 0x13;
2291         DPRINTK("SR13 = %x\n", *(regs + SEQ_ADDRESS_R));
2292         *(regs + SEQ_ADDRESS) = 0x15;
2293         DPRINTK("SR15 = %x\n", *(regs + SEQ_ADDRESS_R));
2294         
2295         return;
2296 }
2297 #endif