Merge branch 'master' into for_paulus
[linux-drm-fsl-dcu.git] / 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 struct cyberfb_par {
113         struct fb_var_screeninfo var;
114         __u32 type;
115         __u32 type_aux;
116         __u32 visual;
117         __u32 line_length;
118 };
119
120 static struct cyberfb_par current_par;
121
122 static int current_par_valid = 0;
123
124 static struct display disp;
125 static struct fb_info fb_info;
126
127
128 /*
129  *    Frame Buffer Name
130  */
131
132 static char cyberfb_name[16] = "Cybervision";
133
134
135 /*
136  *    CyberVision Graphics Board
137  */
138
139 static unsigned char Cyber_colour_table [256][3];
140 static unsigned long CyberSize;
141 static volatile unsigned char *CyberBase;
142 static volatile unsigned char *CyberMem;
143 static volatile unsigned char *CyberRegs;
144 static unsigned long CyberMem_phys;
145 static unsigned long CyberRegs_phys;
146
147 /*
148  *    Predefined Video Modes
149  */
150
151 static struct {
152     const char *name;
153     struct fb_var_screeninfo var;
154 } cyberfb_predefined[] __initdata = {
155         { "640x480-8", {                /* Default 8 BPP mode (cyber8) */
156                 640, 480, 640, 480, 0, 0, 8, 0,
157                 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
158                 0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
159                 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, 
160                 FB_VMODE_NONINTERLACED
161         }}, 
162         { "640x480-16", {               /* Default 16 BPP mode (cyber16) */
163                 640, 480, 640, 480, 0, 0, 16, 0,
164                 {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
165                 0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
166                 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, 
167                 FB_VMODE_NONINTERLACED
168         }}, 
169         { "640x480-24", {               /* Default 24 BPP mode */
170                 640, 480, 640, 480, 0, 0, 24, 0,
171                 {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {0, 0, 0},
172                 0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
173                 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, 
174                 FB_VMODE_NONINTERLACED
175         }}, 
176         { "800x490-8", {                /* Cybervision 8 bpp */
177                 /* NO Acceleration */
178                 800, 490, 800, 490, 0, 0, 8, 0,
179                 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
180                 0, 0, -1, -1, FB_ACCEL_NONE, 33333, 80, 24, 23, 1, 56, 8,
181                 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
182                 FB_VMODE_NONINTERLACED
183         }},
184 /* I can't test these with my monitor, but I suspect they will
185  * be OK, since Antonio Santos indicated he had tested them in
186  * his system.
187  */
188         { "800x600-8", {                /* Cybervision 8 bpp */
189                 800, 600, 800, 600, 0, 0, 8, 0,
190                 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
191                 0, 0, -1, -1, FB_ACCELF_TEXT, 27778, 64, 24, 22, 1, 72, 2,
192                 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
193                 FB_VMODE_NONINTERLACED
194         }},
195         { "1024x768-8", {               /* Cybervision 8 bpp */
196                 1024, 768, 1024, 768, 0, 0, 8, 0,
197                 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
198                 0, 0, -1, -1, FB_ACCELF_TEXT, 16667, 224, 72, 60, 12, 168, 4,
199                 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
200                 FB_VMODE_NONINTERLACED
201         }},
202         { "1152x886-8", {               /* Cybervision 8 bpp */
203                 1152, 886, 1152, 886, 0, 0, 8, 0,
204                 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
205                 0, 0, -1, -1, FB_ACCELF_TEXT, 15873, 184, 40, 24, 1, 56, 16,
206                 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
207                 FB_VMODE_NONINTERLACED
208         }},
209         { "1280x1024-8", {      /* Cybervision 8 bpp */
210                 1280, 1024, 1280, 1024, 0, 0, 8, 0,
211                 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
212                 0, 0, -1, -1, FB_ACCELF_TEXT, 16667, 256, 48, 50, 12, 72, 4,
213                 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
214                 FB_VMODE_INTERLACED
215         }}
216 };
217
218 #define NUM_TOTAL_MODES    ARRAY_SIZE(cyberfb_predefined)
219
220 static int Cyberfb_inverse = 0;
221
222 /*
223  *    Some default modes
224  */
225
226 #define CYBER8_DEFMODE     (0)
227 #define CYBER16_DEFMODE    (1)
228
229 static struct fb_var_screeninfo cyberfb_default;
230 static int cyberfb_usermode __initdata = 0;
231
232 /*
233  *    Interface used by the world
234  */
235
236 int cyberfb_setup(char *options);
237
238 static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
239                            struct fb_info *info);
240 static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
241                            struct fb_info *info);
242 static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
243                            struct fb_info *info);
244 static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
245                             struct fb_info *info);
246 static int cyberfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
247                              u_int transp, struct fb_info *info);
248 static int cyberfb_blank(int blank, struct fb_info *info);
249
250 /*
251  *    Interface to the low level console driver
252  */
253
254 int cyberfb_init(void);
255 static int Cyberfb_switch(int con, struct fb_info *info);
256 static int Cyberfb_updatevar(int con, struct fb_info *info);
257
258 /*
259  *    Text console acceleration
260  */
261
262 #ifdef FBCON_HAS_CFB8
263 static struct display_switch fbcon_cyber8;
264 #endif
265
266 /*
267  *    Accelerated Functions used by the low level console driver
268  */
269
270 static void Cyber_WaitQueue(u_short fifo);
271 static void Cyber_WaitBlit(void);
272 static void Cyber_BitBLT(u_short curx, u_short cury, u_short destx,
273                          u_short desty, u_short width, u_short height,
274                          u_short mode);
275 static void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height,
276                            u_short mode, u_short color);
277 #if 0
278 static void Cyber_MoveCursor(u_short x, u_short y);
279 #endif
280
281 /*
282  *   Hardware Specific Routines
283  */
284
285 static int Cyber_init(void);
286 static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
287                             struct cyberfb_par *par);
288 static int Cyber_decode_var(struct fb_var_screeninfo *var,
289                             struct cyberfb_par *par);
290 static int Cyber_encode_var(struct fb_var_screeninfo *var,
291                             struct cyberfb_par *par);
292 static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
293                            u_int *transp, struct fb_info *info);
294
295 /*
296  *    Internal routines
297  */
298
299 static void cyberfb_get_par(struct cyberfb_par *par);
300 static void cyberfb_set_par(struct cyberfb_par *par);
301 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
302 static void cyberfb_set_disp(int con, struct fb_info *info);
303 static int get_video_mode(const char *name);
304
305 /* For cvision_core.c */
306 static unsigned short cv64_compute_clock(unsigned long);
307 static int cv_has_4mb (volatile unsigned char *);
308 static void cv64_board_init (void);
309 static void cv64_load_video_mode (struct fb_var_screeninfo *);
310
311
312 /* -------------------- Hardware specific routines ------------------------- */
313
314
315 /*
316  *    Initialization
317  *
318  *    Set the default video mode for this chipset. If a video mode was
319  *    specified on the command line, it will override the default mode.
320  */
321
322 static int Cyber_init(void)
323 {
324         volatile unsigned char *regs = CyberRegs;
325         volatile unsigned long *CursorBase;
326         int i;
327         DPRINTK("ENTER\n");
328
329 /* Init local cmap as greyscale levels */
330         for (i = 0; i < 256; i++) {
331                 Cyber_colour_table [i][0] = i;
332                 Cyber_colour_table [i][1] = i;
333                 Cyber_colour_table [i][2] = i;
334         }
335
336 /* Initialize the board and determine fbmem size */
337         cv64_board_init(); 
338 #ifdef CYBERFBDEBUG
339         DPRINTK("Register state after initing board\n");
340         cv64_dump();
341 #endif
342 /* Clear framebuffer memory */
343         DPRINTK("Clear framebuffer memory\n");
344         memset ((char *)CyberMem, 0, CyberSize);
345
346 /* Disable hardware cursor */
347         DPRINTK("Disable HW cursor\n");
348         wb_64(regs, S3_CRTC_ADR, S3_REG_LOCK2);
349         wb_64(regs, S3_CRTC_DATA, 0xa0);
350         wb_64(regs, S3_CRTC_ADR, S3_HGC_MODE);
351         wb_64(regs, S3_CRTC_DATA, 0x00);
352         wb_64(regs, S3_CRTC_ADR, S3_HWGC_DX);
353         wb_64(regs, S3_CRTC_DATA, 0x00);
354         wb_64(regs, S3_CRTC_ADR, S3_HWGC_DY);
355         wb_64(regs, S3_CRTC_DATA, 0x00);
356
357 /* Initialize hardware cursor */
358         DPRINTK("Init HW cursor\n");
359         CursorBase = (u_long *)((char *)(CyberMem) + CyberSize - 0x400);
360         for (i=0; i < 8; i++)
361         {
362                 *(CursorBase  +(i*4)) = 0xffffff00;
363                 *(CursorBase+1+(i*4)) = 0xffff0000;
364                 *(CursorBase+2+(i*4)) = 0xffff0000;
365                 *(CursorBase+3+(i*4)) = 0xffff0000;
366         }
367         for (i=8; i < 64; i++)
368         {
369                 *(CursorBase  +(i*4)) = 0xffff0000;
370                 *(CursorBase+1+(i*4)) = 0xffff0000;
371                 *(CursorBase+2+(i*4)) = 0xffff0000;
372                 *(CursorBase+3+(i*4)) = 0xffff0000;
373         }
374
375         cyberfb_setcolreg (255, 56<<8, 100<<8, 160<<8, 0, NULL /* unused */);
376         cyberfb_setcolreg (254, 0, 0, 0, 0, NULL /* unused */);
377
378         DPRINTK("EXIT\n");
379         return 0;
380 }
381
382
383 /*
384  *    This function should fill in the `fix' structure based on the
385  *    values in the `par' structure.
386  */
387
388 static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
389                             struct cyberfb_par *par)
390 {
391         DPRINTK("ENTER\n");
392         memset(fix, 0, sizeof(struct fb_fix_screeninfo));
393         strcpy(fix->id, cyberfb_name);
394         fix->smem_start = CyberMem_phys;
395         fix->smem_len = CyberSize;
396         fix->mmio_start = CyberRegs_phys;
397         fix->mmio_len = 0x10000;
398
399         fix->type = FB_TYPE_PACKED_PIXELS;
400         fix->type_aux = 0;
401         if (par->var.bits_per_pixel == 15 || par->var.bits_per_pixel == 16 ||
402             par->var.bits_per_pixel == 24 || par->var.bits_per_pixel == 32) {
403                 fix->visual = FB_VISUAL_DIRECTCOLOR;
404         } else {
405                 fix->visual = FB_VISUAL_PSEUDOCOLOR;
406         }
407
408         fix->xpanstep = 0;
409         fix->ypanstep = 0;
410         fix->ywrapstep = 0;
411         fix->line_length = 0;
412         fix->accel = FB_ACCEL_S3_TRIO64;
413
414         DPRINTK("EXIT\n");
415         return(0);
416 }
417
418
419 /*
420 *    Fill the `par' structure based on the values in `var'.
421 *    TODO: Verify and adjust values, return -EINVAL if bad.
422 */
423
424 static int Cyber_decode_var(struct fb_var_screeninfo *var,
425                             struct cyberfb_par *par)
426 {
427         DPRINTK("ENTER\n");
428         par->var.xres = var->xres;
429         par->var.yres = var->yres;
430         par->var.xres_virtual = var->xres_virtual;
431         par->var.yres_virtual = var->yres_virtual;
432         par->var.xoffset = var->xoffset;
433         par->var.yoffset = var->yoffset;
434         par->var.bits_per_pixel = var->bits_per_pixel;
435         par->var.grayscale = var->grayscale;
436         par->var.red = var->red;
437         par->var.green = var->green;
438         par->var.blue = var->blue;
439         par->var.transp = var->transp;
440         par->var.nonstd = var->nonstd;
441         par->var.activate = var->activate;
442         par->var.height = var->height;
443         par->var.width = var->width;
444         if (var->accel_flags & FB_ACCELF_TEXT) {
445                 par->var.accel_flags = FB_ACCELF_TEXT;
446         } else {
447                 par->var.accel_flags = 0;
448         }
449         par->var.pixclock = var->pixclock;
450         par->var.left_margin = var->left_margin;
451         par->var.right_margin = var->right_margin;
452         par->var.upper_margin = var->upper_margin;
453         par->var.lower_margin = var->lower_margin;
454         par->var.hsync_len = var->hsync_len;
455         par->var.vsync_len = var->vsync_len;
456         par->var.sync = var->sync;
457         par->var.vmode = var->vmode;
458         DPRINTK("EXIT\n");
459         return(0);
460 }
461
462 /*
463 *    Fill the `var' structure based on the values in `par' and maybe
464 *    other values read out of the hardware.
465 */
466
467 static int Cyber_encode_var(struct fb_var_screeninfo *var,
468                             struct cyberfb_par *par)
469 {
470         DPRINTK("ENTER\n");
471         var->xres = par->var.xres;
472         var->yres = par->var.yres;
473         var->xres_virtual = par->var.xres_virtual;
474         var->yres_virtual = par->var.yres_virtual;
475         var->xoffset = par->var.xoffset;
476         var->yoffset = par->var.yoffset;
477
478         var->bits_per_pixel = par->var.bits_per_pixel;
479         var->grayscale = par->var.grayscale;
480
481         var->red = par->var.red;
482         var->green = par->var.green;
483         var->blue = par->var.blue;
484         var->transp = par->var.transp;
485
486         var->nonstd = par->var.nonstd;
487         var->activate = par->var.activate;
488
489         var->height = par->var.height;
490         var->width = par->var.width;
491
492         var->accel_flags = par->var.accel_flags;
493
494         var->pixclock = par->var.pixclock;
495         var->left_margin = par->var.left_margin;
496         var->right_margin = par->var.right_margin;
497         var->upper_margin = par->var.upper_margin;
498         var->lower_margin = par->var.lower_margin;
499         var->hsync_len = par->var.hsync_len;
500         var->vsync_len = par->var.vsync_len;
501         var->sync = par->var.sync;
502         var->vmode = par->var.vmode;
503         
504         DPRINTK("EXIT\n");
505         return(0);
506 }
507
508
509 /*
510  *    Set a single color register. Return != 0 for invalid regno.
511  */
512
513 static int cyberfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
514                            u_int transp, struct fb_info *info)
515 {
516         volatile unsigned char *regs = CyberRegs;
517
518         /*DPRINTK("ENTER\n");*/
519         if (regno > 255) {
520                 DPRINTK("EXIT - Register # > 255\n");
521                 return (1);
522         }
523
524         wb_64(regs, 0x3c8, (unsigned char) regno);
525
526         red >>= 10;
527         green >>= 10;
528         blue >>= 10;
529
530         Cyber_colour_table [regno][0] = red;
531         Cyber_colour_table [regno][1] = green;
532         Cyber_colour_table [regno][2] = blue;
533
534         wb_64(regs, 0x3c9, red);
535         wb_64(regs, 0x3c9, green);
536         wb_64(regs, 0x3c9, blue);
537
538         /*DPRINTK("EXIT\n");*/
539         return (0);
540 }
541
542
543 /*
544 *    Read a single color register and split it into
545 *    colors/transparent. Return != 0 for invalid regno.
546 */
547
548 static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
549                            u_int *transp, struct fb_info *info)
550 {
551         int t;
552
553         /*DPRINTK("ENTER\n");*/
554         if (regno > 255) {
555                 DPRINTK("EXIT - Register # > 255\n");
556                 return (1);
557         }
558         /* ARB This shifting & oring seems VERY strange */
559         t       = Cyber_colour_table [regno][0];
560         *red    = (t<<10) | (t<<4) | (t>>2);
561         t       = Cyber_colour_table [regno][1];
562         *green  = (t<<10) | (t<<4) | (t>>2);
563         t       = Cyber_colour_table [regno][2];
564         *blue   = (t<<10) | (t<<4) | (t>>2);
565         *transp = 0;
566         /*DPRINTK("EXIT\n");*/
567         return (0);
568 }
569
570
571 /*
572 *    (Un)Blank the screen
573 *    blank: 1 = zero fb cmap
574 *           0 = restore fb cmap from local cmap
575 */
576 static int cyberfb_blank(int blank, struct fb_info *info)
577 {
578         volatile unsigned char *regs = CyberRegs;
579         int i;
580
581         DPRINTK("ENTER\n");
582 #if 0
583 /* Blank by turning gfx off */
584         gfx_on_off (1, regs);
585 #else
586         if (blank) {
587                 for (i = 0; i < 256; i++) {
588                         wb_64(regs, 0x3c8, (unsigned char) i);
589                         /* ARB Pale red to detect this blanking method */
590                         wb_64(regs, 0x3c9, 48); 
591                         wb_64(regs, 0x3c9, 0);
592                         wb_64(regs, 0x3c9, 0);
593                 }
594         } else {
595                 for (i = 0; i < 256; i++) {
596                         wb_64(regs, 0x3c8, (unsigned char) i);
597                         wb_64(regs, 0x3c9, Cyber_colour_table[i][0]);
598                         wb_64(regs, 0x3c9, Cyber_colour_table[i][1]);
599                         wb_64(regs, 0x3c9, Cyber_colour_table[i][2]);
600                 }
601         }
602 #endif
603         DPRINTK("EXIT\n");
604         return 0;
605 }
606
607
608 /**************************************************************
609  * We are waiting for "fifo" FIFO-slots empty
610  */
611 static void Cyber_WaitQueue (u_short fifo)
612 {
613         unsigned short status;
614
615         DPRINTK("ENTER\n");
616         do {
617                 status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
618         } while (status & fifo);
619         DPRINTK("EXIT\n");
620 }
621
622 /**************************************************************
623  * We are waiting for Hardware (Graphics Engine) not busy
624  */
625 static void Cyber_WaitBlit (void)
626 {
627         unsigned short status;
628
629         DPRINTK("ENTER\n");
630         do {
631                 status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
632         } while (status & S3_HDW_BUSY);
633         DPRINTK("EXIT\n");
634 }
635
636 /**************************************************************
637  * BitBLT - Through the Plane
638  */
639 static void Cyber_BitBLT (u_short curx, u_short cury, u_short destx,
640                           u_short desty, u_short width, u_short height,
641                           u_short mode)
642 {
643         volatile unsigned char *regs = CyberRegs;
644         u_short blitcmd = S3_BITBLT;
645
646         DPRINTK("ENTER\n");
647         /* Set drawing direction */
648         /* -Y, X maj, -X (default) */
649         if (curx > destx) {
650                 blitcmd |= 0x0020;  /* Drawing direction +X */
651         } else {
652                 curx  += (width - 1);
653                 destx += (width - 1);
654         }
655
656         if (cury > desty) {
657                 blitcmd |= 0x0080;  /* Drawing direction +Y */
658         } else {
659                 cury  += (height - 1);
660                 desty += (height - 1);
661         }
662
663         Cyber_WaitQueue (0x8000);
664
665         *((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
666         *((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0060 | mode);
667
668         *((u_short volatile *)(regs + S3_CUR_X)) = curx;
669         *((u_short volatile *)(regs + S3_CUR_Y)) = cury;
670
671         *((u_short volatile *)(regs + S3_DESTX_DIASTP)) = destx;
672         *((u_short volatile *)(regs + S3_DESTY_AXSTP)) = desty;
673
674         *((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
675         *((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width  - 1;
676
677         *((u_short volatile *)(regs + S3_CMD)) = blitcmd;
678         DPRINTK("EXIT\n");
679 }
680
681 /**************************************************************
682  * Rectangle Fill Solid
683  */
684 static void Cyber_RectFill (u_short x, u_short y, u_short width,
685                             u_short height, u_short mode, u_short color)
686 {
687         volatile unsigned char *regs = CyberRegs;
688         u_short blitcmd = S3_FILLEDRECT;
689
690         DPRINTK("ENTER\n");
691         Cyber_WaitQueue (0x8000);
692
693         *((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
694         *((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0020 | mode);
695
696         *((u_short volatile *)(regs + S3_MULT_MISC)) = 0xe000;
697         *((u_short volatile *)(regs + S3_FRGD_COLOR)) = color;
698
699         *((u_short volatile *)(regs + S3_CUR_X)) = x;
700         *((u_short volatile *)(regs + S3_CUR_Y)) = y;
701
702         *((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
703         *((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width  - 1;
704
705         *((u_short volatile *)(regs + S3_CMD)) = blitcmd;
706         DPRINTK("EXIT\n");
707 }
708
709
710 #if 0
711 /**************************************************************
712  * Move cursor to x, y
713  */
714 static void Cyber_MoveCursor (u_short x, u_short y)
715 {
716         volatile unsigned char *regs = CyberRegs;
717         DPRINTK("ENTER\n");
718         *(regs + S3_CRTC_ADR)  = 0x39;
719         *(regs + S3_CRTC_DATA) = 0xa0;
720
721         *(regs + S3_CRTC_ADR)  = S3_HWGC_ORGX_H;
722         *(regs + S3_CRTC_DATA) = (char)((x & 0x0700) >> 8);
723         *(regs + S3_CRTC_ADR)  = S3_HWGC_ORGX_L;
724         *(regs + S3_CRTC_DATA) = (char)(x & 0x00ff);
725
726         *(regs + S3_CRTC_ADR)  = S3_HWGC_ORGY_H;
727         *(regs + S3_CRTC_DATA) = (char)((y & 0x0700) >> 8);
728         *(regs + S3_CRTC_ADR)  = S3_HWGC_ORGY_L;
729         *(regs + S3_CRTC_DATA) = (char)(y & 0x00ff);
730         DPRINTK("EXIT\n");
731 }
732 #endif
733
734
735 /* -------------------- Generic routines ---------------------------------- */
736
737
738 /*
739  *    Fill the hardware's `par' structure.
740  */
741
742 static void cyberfb_get_par(struct cyberfb_par *par)
743 {
744         DPRINTK("ENTER\n");
745         if (current_par_valid) {
746                 *par = current_par;
747         } else {
748                 Cyber_decode_var(&cyberfb_default, par);
749         }
750         DPRINTK("EXIT\n");
751 }
752
753
754 static void cyberfb_set_par(struct cyberfb_par *par)
755 {
756         DPRINTK("ENTER\n");
757         current_par = *par;
758         current_par_valid = 1;
759         DPRINTK("EXIT\n");
760 }
761
762
763 static void cyber_set_video(struct fb_var_screeninfo *var)
764 {
765
766         /* Load the video mode defined by the 'var' data */
767         cv64_load_video_mode (var);
768 #ifdef CYBERFBDEBUG
769         DPRINTK("Register state after loading video mode\n");
770         cv64_dump();
771 #endif
772 }
773
774
775 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
776 {
777         int err, activate;
778         struct cyberfb_par par;
779
780         DPRINTK("ENTER\n");
781         if ((err = Cyber_decode_var(var, &par))) {
782                 DPRINTK("EXIT - decode_var failed\n");
783                 return(err);
784         }
785         activate = var->activate;
786         if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
787                 cyberfb_set_par(&par);
788         Cyber_encode_var(var, &par);
789         var->activate = activate;
790
791         cyber_set_video(var);
792         DPRINTK("EXIT\n");
793         return 0;
794 }
795
796 /*
797  *    Get the Fixed Part of the Display
798  */
799
800 static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
801                            struct fb_info *info)
802 {
803         struct cyberfb_par par;
804         int error = 0;
805
806         DPRINTK("ENTER\n");
807         if (con == -1) {
808                 cyberfb_get_par(&par);
809         } else {
810                 error = Cyber_decode_var(&fb_display[con].var, &par);
811         }
812         DPRINTK("EXIT\n");
813         return(error ? error : Cyber_encode_fix(fix, &par));
814 }
815
816
817 /*
818  *    Get the User Defined Part of the Display
819  */
820
821 static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
822                            struct fb_info *info)
823 {
824         struct cyberfb_par par;
825         int error = 0;
826
827         DPRINTK("ENTER\n");
828         if (con == -1) {
829                 cyberfb_get_par(&par);
830                 error = Cyber_encode_var(var, &par);
831                 disp.var = *var;   /* ++Andre: don't know if this is the right place */
832         } else {
833                 *var = fb_display[con].var;
834         }
835
836         DPRINTK("EXIT\n");
837         return(error);
838 }
839
840
841 static void cyberfb_set_disp(int con, struct fb_info *info)
842 {
843         struct fb_fix_screeninfo fix;
844         struct display *display;
845
846         DPRINTK("ENTER\n");
847         if (con >= 0)
848                 display = &fb_display[con];
849         else
850                 display = &disp;        /* used during initialization */
851
852         cyberfb_get_fix(&fix, con, info);
853         if (con == -1)
854                 con = 0;
855         display->visual = fix.visual;
856         display->type = fix.type;
857         display->type_aux = fix.type_aux;
858         display->ypanstep = fix.ypanstep;
859         display->ywrapstep = fix.ywrapstep;
860         display->can_soft_blank = 1;
861         display->inverse = Cyberfb_inverse;
862         switch (display->var.bits_per_pixel) {
863 #ifdef FBCON_HAS_CFB8
864             case 8:
865                 if (display->var.accel_flags & FB_ACCELF_TEXT) {
866                     display->dispsw = &fbcon_cyber8;
867 #warning FIXME: We should reinit the graphics engine here
868                 } else
869                     display->dispsw = &fbcon_cfb8;
870                 break;
871 #endif
872 #ifdef FBCON_HAS_CFB16
873             case 16:
874                 display->dispsw = &fbcon_cfb16;
875                 break;
876 #endif
877             default:
878                 display->dispsw = NULL;
879                 break;
880         }
881         DPRINTK("EXIT\n");
882 }
883
884
885 /*
886  *    Set the User Defined Part of the Display
887  */
888
889 static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
890                            struct fb_info *info)
891 {
892         int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
893
894         DPRINTK("ENTER\n");
895         if ((err = do_fb_set_var(var, con == info->currcon))) {
896                 DPRINTK("EXIT - do_fb_set_var failed\n");
897                 return(err);
898         }
899         if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
900                 oldxres = fb_display[con].var.xres;
901                 oldyres = fb_display[con].var.yres;
902                 oldvxres = fb_display[con].var.xres_virtual;
903                 oldvyres = fb_display[con].var.yres_virtual;
904                 oldbpp = fb_display[con].var.bits_per_pixel;
905                 oldaccel = fb_display[con].var.accel_flags;
906                 fb_display[con].var = *var;
907                 if (oldxres != var->xres || oldyres != var->yres ||
908                     oldvxres != var->xres_virtual ||
909                     oldvyres != var->yres_virtual ||
910                     oldbpp != var->bits_per_pixel ||
911                     oldaccel != var->accel_flags) {
912                         cyberfb_set_disp(con, info);
913                         (*fb_info.changevar)(con);
914                         fb_alloc_cmap(&fb_display[con].cmap, 0, 0);
915                         do_install_cmap(con, info);
916                 }
917         }
918         var->activate = 0;
919         DPRINTK("EXIT\n");
920         return(0);
921 }
922
923
924 /*
925  *    Get the Colormap
926  */
927
928 static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
929                             struct fb_info *info)
930 {
931         DPRINTK("ENTER\n");
932         if (con == info->currcon) { /* current console? */
933                 DPRINTK("EXIT - console is current console\n");
934                 return(fb_get_cmap(cmap, kspc, Cyber_getcolreg, info));
935         } else if (fb_display[con].cmap.len) { /* non default colormap? */
936                 DPRINTK("Use console cmap\n");
937                 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
938         } else {
939                 DPRINTK("Use default cmap\n");
940                 fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
941                              cmap, kspc ? 0 : 2);
942         }
943         DPRINTK("EXIT\n");
944         return(0);
945 }
946
947 static struct fb_ops cyberfb_ops = {
948         .owner =        THIS_MODULE,
949         .fb_get_fix =   cyberfb_get_fix,
950         .fb_get_var =   cyberfb_get_var,
951         .fb_set_var =   cyberfb_set_var,
952         .fb_get_cmap =  cyberfb_get_cmap,
953         .fb_set_cmap =  gen_set_cmap,
954         .fb_setcolreg = cyberfb_setcolreg,
955         .fb_blank =     cyberfb_blank,
956 };
957
958 int __init cyberfb_setup(char *options)
959 {
960         char *this_opt;
961         DPRINTK("ENTER\n");
962
963         fb_info.fontname[0] = '\0';
964
965         if (!options || !*options) {
966                 DPRINTK("EXIT - no options\n");
967                 return 0;
968         }
969
970         while ((this_opt = strsep(&options, ",")) != NULL) {
971                 if (!*this_opt)
972                         continue;
973                 if (!strcmp(this_opt, "inverse")) {
974                         Cyberfb_inverse = 1;
975                         fb_invert_cmaps();
976                 } else if (!strncmp(this_opt, "font:", 5)) {
977                         strcpy(fb_info.fontname, this_opt+5);
978                 } else if (!strcmp (this_opt, "cyber8")) {
979                         cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
980                         cyberfb_usermode = 1;
981                 } else if (!strcmp (this_opt, "cyber16")) {
982                         cyberfb_default = cyberfb_predefined[CYBER16_DEFMODE].var;
983                         cyberfb_usermode = 1;
984                 } else get_video_mode(this_opt);
985         }
986
987         DPRINTK("default mode: xres=%d, yres=%d, bpp=%d\n",
988                 cyberfb_default.xres,
989                 cyberfb_default.yres,
990                 cyberfb_default.bits_per_pixel);
991         DPRINTK("EXIT\n");
992         return 0;
993 }
994
995 /*
996  *    Initialization
997  */
998
999 int __init cyberfb_init(void)
1000 {
1001         unsigned long board_addr, board_size;
1002         struct cyberfb_par par;
1003         struct zorro_dev *z = NULL;
1004         DPRINTK("ENTER\n");
1005
1006         while ((z = zorro_find_device(ZORRO_PROD_PHASE5_CYBERVISION64, z))) {
1007             board_addr = z->resource.start;
1008             board_size = z->resource.end-z->resource.start+1;
1009             CyberMem_phys = board_addr + 0x01400000;
1010             CyberRegs_phys = CyberMem_phys + 0x00c00000;
1011             if (!request_mem_region(CyberRegs_phys, 0x10000, "S3 Trio64"))
1012                 continue;
1013             if (!request_mem_region(CyberMem_phys, 0x400000, "RAM")) {
1014                 release_mem_region(CyberRegs_phys, 0x10000);
1015                 continue;
1016             }
1017             DPRINTK("board_addr=%08lx\n", board_addr);
1018             DPRINTK("board_size=%08lx\n", board_size);
1019
1020             CyberBase = ioremap(board_addr, board_size);
1021             CyberRegs = CyberBase + 0x02000000;
1022             CyberMem = CyberBase + 0x01400000;
1023             DPRINTK("CyberBase=%08lx CyberRegs=%08lx CyberMem=%08lx\n",
1024                     CyberBase, (long unsigned int)CyberRegs, CyberMem);
1025
1026 #ifdef CYBERFBDEBUG
1027             DPRINTK("Register state just after mapping memory\n");
1028             cv64_dump();
1029 #endif
1030
1031             strcpy(fb_info.modename, cyberfb_name);
1032             fb_info.changevar = NULL;
1033             fb_info.fbops = &cyberfb_ops;
1034             fb_info.screen_base = (unsigned char *)CyberMem;
1035             fb_info.disp = &disp;
1036             fb_info.currcon = -1;
1037             fb_info.switch_con = &Cyberfb_switch;
1038             fb_info.updatevar = &Cyberfb_updatevar;
1039
1040             Cyber_init();
1041             /* ++Andre: set cyberfb default mode */
1042             if (!cyberfb_usermode) {
1043                     cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
1044                     DPRINTK("Use default cyber8 mode\n");
1045             }
1046             Cyber_decode_var(&cyberfb_default, &par);
1047             Cyber_encode_var(&cyberfb_default, &par);
1048
1049             do_fb_set_var(&cyberfb_default, 1);
1050             cyberfb_get_var(&fb_display[0].var, -1, &fb_info);
1051             cyberfb_set_disp(-1, &fb_info);
1052             do_install_cmap(0, &fb_info);
1053
1054             if (register_framebuffer(&fb_info) < 0) {
1055                     DPRINTK("EXIT - register_framebuffer failed\n");
1056                         if (CyberBase)
1057                                 iounmap(CyberBase);
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