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