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 $
5 * Copyright (C) 1998 Alan Bair
7 * This file is based on two CyberVision64 frame buffer device drivers
9 * The second CyberVision64 frame buffer device (cvision.c cvision_core.c):
11 * Copyright (c) 1997 Antonio Santos
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.
19 * Copyright (c) 1995 Michael Teske
21 * The first CyberVision64 frame buffer device (cyberfb.c):
23 * Copyright (C) 1996 Martin Apel
26 * Which is based on the Amiga frame buffer device (amifb.c):
28 * Copyright (C) 1995 Geert Uytterhoeven
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
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.
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.
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.
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.
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.
58 * Revision 1.1 1998/08/29 18:38:31 abair
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.
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.
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
79 #include <linux/module.h>
80 #include <linux/kernel.h>
81 #include <linux/errno.h>
82 #include <linux/string.h>
84 #include <linux/slab.h>
85 #include <linux/delay.h>
86 #include <linux/zorro.h>
88 #include <linux/init.h>
89 #include <asm/uaccess.h>
90 #include <asm/system.h>
92 #include <asm/pgtable.h>
93 #include <asm/amigahw.h>
97 #include <video/fbcon.h>
98 #include <video/fbcon-cfb8.h>
99 #include <video/fbcon-cfb16.h>
101 /*#define CYBERFBDEBUG*/
103 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
104 static void cv64_dump(void);
106 #define DPRINTK(fmt, args...)
109 #define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat)
110 #define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg))
112 #define ww_64(regs,reg,dat) (*((volatile unsigned short *)(regs + reg) = dat)
115 struct fb_var_screeninfo var;
122 static struct cyberfb_par current_par;
124 static int current_par_valid = 0;
126 static struct display disp;
127 static struct fb_info fb_info;
134 static char cyberfb_name[16] = "Cybervision";
138 * CyberVision Graphics Board
141 static unsigned char Cyber_colour_table [256][3];
142 static unsigned long CyberSize;
143 static volatile unsigned char *CyberBase;
144 static volatile unsigned char *CyberMem;
145 static volatile unsigned char *CyberRegs;
146 static unsigned long CyberMem_phys;
147 static unsigned long CyberRegs_phys;
150 * Predefined Video Modes
155 struct fb_var_screeninfo var;
156 } cyberfb_predefined[] __initdata = {
157 { "640x480-8", { /* Default 8 BPP mode (cyber8) */
158 640, 480, 640, 480, 0, 0, 8, 0,
159 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
160 0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
161 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
162 FB_VMODE_NONINTERLACED
164 { "640x480-16", { /* Default 16 BPP mode (cyber16) */
165 640, 480, 640, 480, 0, 0, 16, 0,
166 {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
167 0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
168 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
169 FB_VMODE_NONINTERLACED
171 { "640x480-24", { /* Default 24 BPP mode */
172 640, 480, 640, 480, 0, 0, 24, 0,
173 {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {0, 0, 0},
174 0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
175 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
176 FB_VMODE_NONINTERLACED
178 { "800x490-8", { /* Cybervision 8 bpp */
179 /* NO Acceleration */
180 800, 490, 800, 490, 0, 0, 8, 0,
181 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
182 0, 0, -1, -1, FB_ACCEL_NONE, 33333, 80, 24, 23, 1, 56, 8,
183 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
184 FB_VMODE_NONINTERLACED
186 /* I can't test these with my monitor, but I suspect they will
187 * be OK, since Antonio Santos indicated he had tested them in
190 { "800x600-8", { /* Cybervision 8 bpp */
191 800, 600, 800, 600, 0, 0, 8, 0,
192 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
193 0, 0, -1, -1, FB_ACCELF_TEXT, 27778, 64, 24, 22, 1, 72, 2,
194 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
195 FB_VMODE_NONINTERLACED
197 { "1024x768-8", { /* Cybervision 8 bpp */
198 1024, 768, 1024, 768, 0, 0, 8, 0,
199 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
200 0, 0, -1, -1, FB_ACCELF_TEXT, 16667, 224, 72, 60, 12, 168, 4,
201 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
202 FB_VMODE_NONINTERLACED
204 { "1152x886-8", { /* Cybervision 8 bpp */
205 1152, 886, 1152, 886, 0, 0, 8, 0,
206 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
207 0, 0, -1, -1, FB_ACCELF_TEXT, 15873, 184, 40, 24, 1, 56, 16,
208 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
209 FB_VMODE_NONINTERLACED
211 { "1280x1024-8", { /* Cybervision 8 bpp */
212 1280, 1024, 1280, 1024, 0, 0, 8, 0,
213 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
214 0, 0, -1, -1, FB_ACCELF_TEXT, 16667, 256, 48, 50, 12, 72, 4,
215 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
220 #define NUM_TOTAL_MODES ARRAY_SIZE(cyberfb_predefined)
222 static int Cyberfb_inverse = 0;
228 #define CYBER8_DEFMODE (0)
229 #define CYBER16_DEFMODE (1)
231 static struct fb_var_screeninfo cyberfb_default;
232 static int cyberfb_usermode __initdata = 0;
235 * Interface used by the world
238 int cyberfb_setup(char *options);
240 static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
241 struct fb_info *info);
242 static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
243 struct fb_info *info);
244 static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
245 struct fb_info *info);
246 static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
247 struct fb_info *info);
248 static int cyberfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
249 u_int transp, struct fb_info *info);
250 static int cyberfb_blank(int blank, struct fb_info *info);
253 * Interface to the low level console driver
256 int cyberfb_init(void);
257 static int Cyberfb_switch(int con, struct fb_info *info);
258 static int Cyberfb_updatevar(int con, struct fb_info *info);
261 * Text console acceleration
264 #ifdef FBCON_HAS_CFB8
265 static struct display_switch fbcon_cyber8;
269 * Accelerated Functions used by the low level console driver
272 static void Cyber_WaitQueue(u_short fifo);
273 static void Cyber_WaitBlit(void);
274 static void Cyber_BitBLT(u_short curx, u_short cury, u_short destx,
275 u_short desty, u_short width, u_short height,
277 static void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height,
278 u_short mode, u_short color);
280 static void Cyber_MoveCursor(u_short x, u_short y);
284 * Hardware Specific Routines
287 static int Cyber_init(void);
288 static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
289 struct cyberfb_par *par);
290 static int Cyber_decode_var(struct fb_var_screeninfo *var,
291 struct cyberfb_par *par);
292 static int Cyber_encode_var(struct fb_var_screeninfo *var,
293 struct cyberfb_par *par);
294 static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
295 u_int *transp, struct fb_info *info);
301 static void cyberfb_get_par(struct cyberfb_par *par);
302 static void cyberfb_set_par(struct cyberfb_par *par);
303 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
304 static void cyberfb_set_disp(int con, struct fb_info *info);
305 static int get_video_mode(const char *name);
307 /* For cvision_core.c */
308 static unsigned short cv64_compute_clock(unsigned long);
309 static int cv_has_4mb (volatile unsigned char *);
310 static void cv64_board_init (void);
311 static void cv64_load_video_mode (struct fb_var_screeninfo *);
314 /* -------------------- Hardware specific routines ------------------------- */
320 * Set the default video mode for this chipset. If a video mode was
321 * specified on the command line, it will override the default mode.
324 static int Cyber_init(void)
326 volatile unsigned char *regs = CyberRegs;
327 volatile unsigned long *CursorBase;
331 /* Init local cmap as greyscale levels */
332 for (i = 0; i < 256; i++) {
333 Cyber_colour_table [i][0] = i;
334 Cyber_colour_table [i][1] = i;
335 Cyber_colour_table [i][2] = i;
338 /* Initialize the board and determine fbmem size */
341 DPRINTK("Register state after initing board\n");
344 /* Clear framebuffer memory */
345 DPRINTK("Clear framebuffer memory\n");
346 memset ((char *)CyberMem, 0, CyberSize);
348 /* Disable hardware cursor */
349 DPRINTK("Disable HW cursor\n");
350 wb_64(regs, S3_CRTC_ADR, S3_REG_LOCK2);
351 wb_64(regs, S3_CRTC_DATA, 0xa0);
352 wb_64(regs, S3_CRTC_ADR, S3_HGC_MODE);
353 wb_64(regs, S3_CRTC_DATA, 0x00);
354 wb_64(regs, S3_CRTC_ADR, S3_HWGC_DX);
355 wb_64(regs, S3_CRTC_DATA, 0x00);
356 wb_64(regs, S3_CRTC_ADR, S3_HWGC_DY);
357 wb_64(regs, S3_CRTC_DATA, 0x00);
359 /* Initialize hardware cursor */
360 DPRINTK("Init HW cursor\n");
361 CursorBase = (u_long *)((char *)(CyberMem) + CyberSize - 0x400);
362 for (i=0; i < 8; i++)
364 *(CursorBase +(i*4)) = 0xffffff00;
365 *(CursorBase+1+(i*4)) = 0xffff0000;
366 *(CursorBase+2+(i*4)) = 0xffff0000;
367 *(CursorBase+3+(i*4)) = 0xffff0000;
369 for (i=8; i < 64; i++)
371 *(CursorBase +(i*4)) = 0xffff0000;
372 *(CursorBase+1+(i*4)) = 0xffff0000;
373 *(CursorBase+2+(i*4)) = 0xffff0000;
374 *(CursorBase+3+(i*4)) = 0xffff0000;
377 cyberfb_setcolreg (255, 56<<8, 100<<8, 160<<8, 0, NULL /* unused */);
378 cyberfb_setcolreg (254, 0, 0, 0, 0, NULL /* unused */);
386 * This function should fill in the `fix' structure based on the
387 * values in the `par' structure.
390 static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
391 struct cyberfb_par *par)
394 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
395 strcpy(fix->id, cyberfb_name);
396 fix->smem_start = CyberMem_phys;
397 fix->smem_len = CyberSize;
398 fix->mmio_start = CyberRegs_phys;
399 fix->mmio_len = 0x10000;
401 fix->type = FB_TYPE_PACKED_PIXELS;
403 if (par->var.bits_per_pixel == 15 || par->var.bits_per_pixel == 16 ||
404 par->var.bits_per_pixel == 24 || par->var.bits_per_pixel == 32) {
405 fix->visual = FB_VISUAL_DIRECTCOLOR;
407 fix->visual = FB_VISUAL_PSEUDOCOLOR;
413 fix->line_length = 0;
414 fix->accel = FB_ACCEL_S3_TRIO64;
422 * Fill the `par' structure based on the values in `var'.
423 * TODO: Verify and adjust values, return -EINVAL if bad.
426 static int Cyber_decode_var(struct fb_var_screeninfo *var,
427 struct cyberfb_par *par)
430 par->var.xres = var->xres;
431 par->var.yres = var->yres;
432 par->var.xres_virtual = var->xres_virtual;
433 par->var.yres_virtual = var->yres_virtual;
434 par->var.xoffset = var->xoffset;
435 par->var.yoffset = var->yoffset;
436 par->var.bits_per_pixel = var->bits_per_pixel;
437 par->var.grayscale = var->grayscale;
438 par->var.red = var->red;
439 par->var.green = var->green;
440 par->var.blue = var->blue;
441 par->var.transp = var->transp;
442 par->var.nonstd = var->nonstd;
443 par->var.activate = var->activate;
444 par->var.height = var->height;
445 par->var.width = var->width;
446 if (var->accel_flags & FB_ACCELF_TEXT) {
447 par->var.accel_flags = FB_ACCELF_TEXT;
449 par->var.accel_flags = 0;
451 par->var.pixclock = var->pixclock;
452 par->var.left_margin = var->left_margin;
453 par->var.right_margin = var->right_margin;
454 par->var.upper_margin = var->upper_margin;
455 par->var.lower_margin = var->lower_margin;
456 par->var.hsync_len = var->hsync_len;
457 par->var.vsync_len = var->vsync_len;
458 par->var.sync = var->sync;
459 par->var.vmode = var->vmode;
465 * Fill the `var' structure based on the values in `par' and maybe
466 * other values read out of the hardware.
469 static int Cyber_encode_var(struct fb_var_screeninfo *var,
470 struct cyberfb_par *par)
473 var->xres = par->var.xres;
474 var->yres = par->var.yres;
475 var->xres_virtual = par->var.xres_virtual;
476 var->yres_virtual = par->var.yres_virtual;
477 var->xoffset = par->var.xoffset;
478 var->yoffset = par->var.yoffset;
480 var->bits_per_pixel = par->var.bits_per_pixel;
481 var->grayscale = par->var.grayscale;
483 var->red = par->var.red;
484 var->green = par->var.green;
485 var->blue = par->var.blue;
486 var->transp = par->var.transp;
488 var->nonstd = par->var.nonstd;
489 var->activate = par->var.activate;
491 var->height = par->var.height;
492 var->width = par->var.width;
494 var->accel_flags = par->var.accel_flags;
496 var->pixclock = par->var.pixclock;
497 var->left_margin = par->var.left_margin;
498 var->right_margin = par->var.right_margin;
499 var->upper_margin = par->var.upper_margin;
500 var->lower_margin = par->var.lower_margin;
501 var->hsync_len = par->var.hsync_len;
502 var->vsync_len = par->var.vsync_len;
503 var->sync = par->var.sync;
504 var->vmode = par->var.vmode;
512 * Set a single color register. Return != 0 for invalid regno.
515 static int cyberfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
516 u_int transp, struct fb_info *info)
518 volatile unsigned char *regs = CyberRegs;
520 /*DPRINTK("ENTER\n");*/
522 DPRINTK("EXIT - Register # > 255\n");
526 wb_64(regs, 0x3c8, (unsigned char) regno);
532 Cyber_colour_table [regno][0] = red;
533 Cyber_colour_table [regno][1] = green;
534 Cyber_colour_table [regno][2] = blue;
536 wb_64(regs, 0x3c9, red);
537 wb_64(regs, 0x3c9, green);
538 wb_64(regs, 0x3c9, blue);
540 /*DPRINTK("EXIT\n");*/
546 * Read a single color register and split it into
547 * colors/transparent. Return != 0 for invalid regno.
550 static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
551 u_int *transp, struct fb_info *info)
555 /*DPRINTK("ENTER\n");*/
557 DPRINTK("EXIT - Register # > 255\n");
560 /* ARB This shifting & oring seems VERY strange */
561 t = Cyber_colour_table [regno][0];
562 *red = (t<<10) | (t<<4) | (t>>2);
563 t = Cyber_colour_table [regno][1];
564 *green = (t<<10) | (t<<4) | (t>>2);
565 t = Cyber_colour_table [regno][2];
566 *blue = (t<<10) | (t<<4) | (t>>2);
568 /*DPRINTK("EXIT\n");*/
574 * (Un)Blank the screen
575 * blank: 1 = zero fb cmap
576 * 0 = restore fb cmap from local cmap
578 static int cyberfb_blank(int blank, struct fb_info *info)
580 volatile unsigned char *regs = CyberRegs;
585 /* Blank by turning gfx off */
586 gfx_on_off (1, regs);
589 for (i = 0; i < 256; i++) {
590 wb_64(regs, 0x3c8, (unsigned char) i);
591 /* ARB Pale red to detect this blanking method */
592 wb_64(regs, 0x3c9, 48);
593 wb_64(regs, 0x3c9, 0);
594 wb_64(regs, 0x3c9, 0);
597 for (i = 0; i < 256; i++) {
598 wb_64(regs, 0x3c8, (unsigned char) i);
599 wb_64(regs, 0x3c9, Cyber_colour_table[i][0]);
600 wb_64(regs, 0x3c9, Cyber_colour_table[i][1]);
601 wb_64(regs, 0x3c9, Cyber_colour_table[i][2]);
610 /**************************************************************
611 * We are waiting for "fifo" FIFO-slots empty
613 static void Cyber_WaitQueue (u_short fifo)
615 unsigned short status;
619 status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
620 } while (status & fifo);
624 /**************************************************************
625 * We are waiting for Hardware (Graphics Engine) not busy
627 static void Cyber_WaitBlit (void)
629 unsigned short status;
633 status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
634 } while (status & S3_HDW_BUSY);
638 /**************************************************************
639 * BitBLT - Through the Plane
641 static void Cyber_BitBLT (u_short curx, u_short cury, u_short destx,
642 u_short desty, u_short width, u_short height,
645 volatile unsigned char *regs = CyberRegs;
646 u_short blitcmd = S3_BITBLT;
649 /* Set drawing direction */
650 /* -Y, X maj, -X (default) */
652 blitcmd |= 0x0020; /* Drawing direction +X */
655 destx += (width - 1);
659 blitcmd |= 0x0080; /* Drawing direction +Y */
661 cury += (height - 1);
662 desty += (height - 1);
665 Cyber_WaitQueue (0x8000);
667 *((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
668 *((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0060 | mode);
670 *((u_short volatile *)(regs + S3_CUR_X)) = curx;
671 *((u_short volatile *)(regs + S3_CUR_Y)) = cury;
673 *((u_short volatile *)(regs + S3_DESTX_DIASTP)) = destx;
674 *((u_short volatile *)(regs + S3_DESTY_AXSTP)) = desty;
676 *((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
677 *((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width - 1;
679 *((u_short volatile *)(regs + S3_CMD)) = blitcmd;
683 /**************************************************************
684 * Rectangle Fill Solid
686 static void Cyber_RectFill (u_short x, u_short y, u_short width,
687 u_short height, u_short mode, u_short color)
689 volatile unsigned char *regs = CyberRegs;
690 u_short blitcmd = S3_FILLEDRECT;
693 Cyber_WaitQueue (0x8000);
695 *((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
696 *((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0020 | mode);
698 *((u_short volatile *)(regs + S3_MULT_MISC)) = 0xe000;
699 *((u_short volatile *)(regs + S3_FRGD_COLOR)) = color;
701 *((u_short volatile *)(regs + S3_CUR_X)) = x;
702 *((u_short volatile *)(regs + S3_CUR_Y)) = y;
704 *((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
705 *((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width - 1;
707 *((u_short volatile *)(regs + S3_CMD)) = blitcmd;
713 /**************************************************************
714 * Move cursor to x, y
716 static void Cyber_MoveCursor (u_short x, u_short y)
718 volatile unsigned char *regs = CyberRegs;
720 *(regs + S3_CRTC_ADR) = 0x39;
721 *(regs + S3_CRTC_DATA) = 0xa0;
723 *(regs + S3_CRTC_ADR) = S3_HWGC_ORGX_H;
724 *(regs + S3_CRTC_DATA) = (char)((x & 0x0700) >> 8);
725 *(regs + S3_CRTC_ADR) = S3_HWGC_ORGX_L;
726 *(regs + S3_CRTC_DATA) = (char)(x & 0x00ff);
728 *(regs + S3_CRTC_ADR) = S3_HWGC_ORGY_H;
729 *(regs + S3_CRTC_DATA) = (char)((y & 0x0700) >> 8);
730 *(regs + S3_CRTC_ADR) = S3_HWGC_ORGY_L;
731 *(regs + S3_CRTC_DATA) = (char)(y & 0x00ff);
737 /* -------------------- Generic routines ---------------------------------- */
741 * Fill the hardware's `par' structure.
744 static void cyberfb_get_par(struct cyberfb_par *par)
747 if (current_par_valid) {
750 Cyber_decode_var(&cyberfb_default, par);
756 static void cyberfb_set_par(struct cyberfb_par *par)
760 current_par_valid = 1;
765 static void cyber_set_video(struct fb_var_screeninfo *var)
768 /* Load the video mode defined by the 'var' data */
769 cv64_load_video_mode (var);
771 DPRINTK("Register state after loading video mode\n");
777 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
780 struct cyberfb_par par;
783 if ((err = Cyber_decode_var(var, &par))) {
784 DPRINTK("EXIT - decode_var failed\n");
787 activate = var->activate;
788 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
789 cyberfb_set_par(&par);
790 Cyber_encode_var(var, &par);
791 var->activate = activate;
793 cyber_set_video(var);
799 * Get the Fixed Part of the Display
802 static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
803 struct fb_info *info)
805 struct cyberfb_par par;
810 cyberfb_get_par(&par);
812 error = Cyber_decode_var(&fb_display[con].var, &par);
815 return(error ? error : Cyber_encode_fix(fix, &par));
820 * Get the User Defined Part of the Display
823 static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
824 struct fb_info *info)
826 struct cyberfb_par par;
831 cyberfb_get_par(&par);
832 error = Cyber_encode_var(var, &par);
833 disp.var = *var; /* ++Andre: don't know if this is the right place */
835 *var = fb_display[con].var;
843 static void cyberfb_set_disp(int con, struct fb_info *info)
845 struct fb_fix_screeninfo fix;
846 struct display *display;
850 display = &fb_display[con];
852 display = &disp; /* used during initialization */
854 cyberfb_get_fix(&fix, con, info);
857 display->visual = fix.visual;
858 display->type = fix.type;
859 display->type_aux = fix.type_aux;
860 display->ypanstep = fix.ypanstep;
861 display->ywrapstep = fix.ywrapstep;
862 display->can_soft_blank = 1;
863 display->inverse = Cyberfb_inverse;
864 switch (display->var.bits_per_pixel) {
865 #ifdef FBCON_HAS_CFB8
867 if (display->var.accel_flags & FB_ACCELF_TEXT) {
868 display->dispsw = &fbcon_cyber8;
869 #warning FIXME: We should reinit the graphics engine here
871 display->dispsw = &fbcon_cfb8;
874 #ifdef FBCON_HAS_CFB16
876 display->dispsw = &fbcon_cfb16;
880 display->dispsw = NULL;
888 * Set the User Defined Part of the Display
891 static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
892 struct fb_info *info)
894 int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
897 if ((err = do_fb_set_var(var, con == info->currcon))) {
898 DPRINTK("EXIT - do_fb_set_var failed\n");
901 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
902 oldxres = fb_display[con].var.xres;
903 oldyres = fb_display[con].var.yres;
904 oldvxres = fb_display[con].var.xres_virtual;
905 oldvyres = fb_display[con].var.yres_virtual;
906 oldbpp = fb_display[con].var.bits_per_pixel;
907 oldaccel = fb_display[con].var.accel_flags;
908 fb_display[con].var = *var;
909 if (oldxres != var->xres || oldyres != var->yres ||
910 oldvxres != var->xres_virtual ||
911 oldvyres != var->yres_virtual ||
912 oldbpp != var->bits_per_pixel ||
913 oldaccel != var->accel_flags) {
914 cyberfb_set_disp(con, info);
915 (*fb_info.changevar)(con);
916 fb_alloc_cmap(&fb_display[con].cmap, 0, 0);
917 do_install_cmap(con, info);
930 static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
931 struct fb_info *info)
934 if (con == info->currcon) { /* current console? */
935 DPRINTK("EXIT - console is current console\n");
936 return(fb_get_cmap(cmap, kspc, Cyber_getcolreg, info));
937 } else if (fb_display[con].cmap.len) { /* non default colormap? */
938 DPRINTK("Use console cmap\n");
939 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
941 DPRINTK("Use default cmap\n");
942 fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
949 static struct fb_ops cyberfb_ops = {
950 .owner = THIS_MODULE,
951 .fb_get_fix = cyberfb_get_fix,
952 .fb_get_var = cyberfb_get_var,
953 .fb_set_var = cyberfb_set_var,
954 .fb_get_cmap = cyberfb_get_cmap,
955 .fb_set_cmap = gen_set_cmap,
956 .fb_setcolreg = cyberfb_setcolreg,
957 .fb_blank = cyberfb_blank,
960 int __init cyberfb_setup(char *options)
965 fb_info.fontname[0] = '\0';
967 if (!options || !*options) {
968 DPRINTK("EXIT - no options\n");
972 while ((this_opt = strsep(&options, ",")) != NULL) {
975 if (!strcmp(this_opt, "inverse")) {
978 } else if (!strncmp(this_opt, "font:", 5)) {
979 strcpy(fb_info.fontname, this_opt+5);
980 } else if (!strcmp (this_opt, "cyber8")) {
981 cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
982 cyberfb_usermode = 1;
983 } else if (!strcmp (this_opt, "cyber16")) {
984 cyberfb_default = cyberfb_predefined[CYBER16_DEFMODE].var;
985 cyberfb_usermode = 1;
986 } else get_video_mode(this_opt);
989 DPRINTK("default mode: xres=%d, yres=%d, bpp=%d\n",
990 cyberfb_default.xres,
991 cyberfb_default.yres,
992 cyberfb_default.bits_per_pixel);
1001 int __init cyberfb_init(void)
1003 unsigned long board_addr, board_size;
1004 struct cyberfb_par par;
1005 struct zorro_dev *z = NULL;
1008 while ((z = zorro_find_device(ZORRO_PROD_PHASE5_CYBERVISION64, z))) {
1009 board_addr = z->resource.start;
1010 board_size = z->resource.end-z->resource.start+1;
1011 CyberMem_phys = board_addr + 0x01400000;
1012 CyberRegs_phys = CyberMem_phys + 0x00c00000;
1013 if (!request_mem_region(CyberRegs_phys, 0x10000, "S3 Trio64"))
1015 if (!request_mem_region(CyberMem_phys, 0x400000, "RAM")) {
1016 release_mem_region(CyberRegs_phys, 0x10000);
1019 DPRINTK("board_addr=%08lx\n", board_addr);
1020 DPRINTK("board_size=%08lx\n", board_size);
1022 CyberBase = ioremap(board_addr, board_size);
1023 CyberRegs = CyberBase + 0x02000000;
1024 CyberMem = CyberBase + 0x01400000;
1025 DPRINTK("CyberBase=%08lx CyberRegs=%08lx CyberMem=%08lx\n",
1026 CyberBase, (long unsigned int)CyberRegs, CyberMem);
1029 DPRINTK("Register state just after mapping memory\n");
1033 strcpy(fb_info.modename, cyberfb_name);
1034 fb_info.changevar = NULL;
1035 fb_info.fbops = &cyberfb_ops;
1036 fb_info.screen_base = (unsigned char *)CyberMem;
1037 fb_info.disp = &disp;
1038 fb_info.currcon = -1;
1039 fb_info.switch_con = &Cyberfb_switch;
1040 fb_info.updatevar = &Cyberfb_updatevar;
1043 /* ++Andre: set cyberfb default mode */
1044 if (!cyberfb_usermode) {
1045 cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
1046 DPRINTK("Use default cyber8 mode\n");
1048 Cyber_decode_var(&cyberfb_default, &par);
1049 Cyber_encode_var(&cyberfb_default, &par);
1051 do_fb_set_var(&cyberfb_default, 1);
1052 cyberfb_get_var(&fb_display[0].var, -1, &fb_info);
1053 cyberfb_set_disp(-1, &fb_info);
1054 do_install_cmap(0, &fb_info);
1056 if (register_framebuffer(&fb_info) < 0) {
1057 DPRINTK("EXIT - register_framebuffer failed\n");
1058 release_mem_region(CyberMem_phys, 0x400000);
1059 release_mem_region(CyberRegs_phys, 0x10000);
1063 printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
1064 fb_info.node, fb_info.modename, CyberSize>>10);
1066 /* TODO: This driver cannot be unloaded yet */
1074 static int Cyberfb_switch(int con, struct fb_info *info)
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,
1083 do_fb_set_var(&fb_display[con].var, 1);
1084 info->currcon = con;
1085 /* Install new colormap */
1086 do_install_cmap(con, info);
1093 * Update the `var' structure (called by fbcon.c)
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.
1099 static int Cyberfb_updatevar(int con, struct fb_info *info)
1101 DPRINTK("Enter - Exit\n");
1110 static int __init get_video_mode(const char *name)
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");
1128 * Text console acceleration
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)
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);
1143 static void fbcon_cyber8_clear(struct vc_data *conp, struct display *p, int sy,
1144 int sx, int height, int width)
1149 sx *= 8; width *= 8;
1150 bg = attr_bgcol_ec(p,conp);
1151 Cyber_RectFill((u_short)sx,
1152 (u_short)(sy*fontheight(p)),
1154 (u_short)(height*fontheight(p)),
1160 static void fbcon_cyber8_putc(struct vc_data *conp, struct display *p, int c,
1165 fbcon_cfb8_putc(conp, p, c, yy, xx);
1169 static void fbcon_cyber8_putcs(struct vc_data *conp, struct display *p,
1170 const unsigned short *s, int count,
1175 fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
1179 static void fbcon_cyber8_revc(struct display *p, int xx, int yy)
1183 fbcon_cfb8_revc(p, xx, yy);
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)
1201 MODULE_LICENSE("GPL");
1203 int init_module(void)
1205 return cyberfb_init();
1211 * Low level initialization routines for the CyberVision64 graphics card
1213 * Most of the following code is from cvision_core.c
1217 #define MAXPIXELCLOCK 135000000 /* safety */
1219 #ifdef CV_AGGRESSIVE_TIMING
1220 long cv64_memclk = 55000000;
1222 long cv64_memclk = 50000000;
1225 /*********************/
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,
1292 /* Console colors */
1293 unsigned char cvconscolors[16][3] = { /* background, foreground, hilite */
1313 /* -------------------- Hardware specific routines ------------------------- */
1315 /* Read Attribute Controller Register=idx */
1316 inline unsigned char RAttr (volatile unsigned char *regs, short idx)
1318 wb_64 (regs, ACT_ADDRESS_W, idx);
1321 return (rb_64(regs, ACT_ADDRESS_R));
1324 /* Read Sequencer Register=idx */
1325 inline unsigned char RSeq (volatile unsigned char *regs, short idx)
1327 wb_64 (regs, SEQ_ADDRESS, idx);
1329 return (rb_64(regs, SEQ_ADDRESS_R));
1332 /* Read CRT Controller Register=idx */
1333 inline unsigned char RCrt (volatile unsigned char *regs, short idx)
1335 wb_64 (regs, CRT_ADDRESS, idx);
1337 return (rb_64(regs, CRT_ADDRESS_R));
1340 /* Read Graphics Controller Register=idx */
1341 inline unsigned char RGfx (volatile unsigned char *regs, short idx)
1343 wb_64 (regs, GCT_ADDRESS, idx);
1345 return (rb_64(regs, GCT_ADDRESS_R));
1349 * Special wakeup/passthrough registers on graphics boards
1352 inline void cv64_write_port (unsigned short bits,
1353 volatile unsigned char *base)
1355 volatile unsigned char *addr;
1356 static unsigned char cvportbits = 0; /* Mirror port bits here */
1359 addr = base + 0x40001;
1360 if (bits & 0x8000) {
1361 cvportbits |= bits & 0xff; /* Set bits */
1362 DPRINTK("Set bits: %04x\n", bits);
1365 bits = (~bits) & 0xff;
1366 cvportbits &= bits; /* Clear bits */
1367 DPRINTK("Clear bits: %04x\n", bits);
1375 * Monitor switch on CyberVision board
1378 * 0 = CyberVision Signal
1380 * board = board addr
1383 inline void cvscreen (int toggle, volatile unsigned char *board)
1387 DPRINTK("Show Amiga video\n");
1388 cv64_write_port (0x10, board);
1390 DPRINTK("Show CyberVision video\n");
1391 cv64_write_port (0x8010, board);
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)
1405 toggle = toggle << 5;
1406 DPRINTK("Turn display %s\n", (toggle ? "off" : "on"));
1408 r = (int) RSeq(regs, SEQ_ID_CLOCKING_MODE);
1409 r &= 0xdf; /* Set bit 5 to 0 */
1411 WSeq (regs, SEQ_ID_CLOCKING_MODE, r | toggle);
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.
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
1425 static unsigned short cv64_compute_clock(unsigned long freq)
1427 static unsigned char *mnr, *save; /* M, N + R vals */
1428 unsigned long work_freq, r;
1433 if (freq < 12500000 || freq > MAXPIXELCLOCK) {
1434 printk("CV64 driver: Illegal clock frequency %ld, using 25MHz\n",
1438 DPRINTK("Freq = %ld\n", freq);
1439 mnr = clocks; /* there the vals are stored */
1442 while (*mnr) { /* mnr vals are 0-terminated */
1443 work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2);
1445 r = (mnr[1] >> 5) & 0x03;
1447 work_freq = work_freq >> r; /* r is the freq divider */
1450 work_freq *= 0x3E8; /* 2nd part of OSC */
1452 diff = abs(freq - work_freq);
1456 /* In save are the vals for minimal diff */
1461 erg = *((unsigned short *)save);
1467 static int cv_has_4mb (volatile unsigned char *fb)
1469 volatile unsigned long *tr, *tw;
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);
1478 if (*tr != 0x87654321) {
1479 DPRINTK("EXIT - <4MB\n");
1483 /* upper memory region */
1484 tw = (volatile unsigned long *) (fb + 0x00200000);
1485 tr = (volatile unsigned long *) (fb + 0x02200000);
1489 if (*tr != 0x87654321) {
1490 DPRINTK("EXIT - <4MB\n");
1496 if (*tr != 0xAAAAAAAA) {
1497 DPRINTK("EXIT - <4MB\n");
1503 if (*tr != 0x55555555) {
1504 DPRINTK("EXIT - <4MB\n");
1512 static void cv64_board_init (void)
1514 volatile unsigned char *regs = CyberRegs;
1516 unsigned int clockpar;
1522 * Special CyberVision 64 board operations
1525 for (i = 0; i < 6; i++) {
1526 cv64_write_port (0xff, CyberBase);
1528 /* Return to operational mode */
1529 cv64_write_port (0x8004, CyberBase);
1532 * Generic (?) S3 chip wakeup
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);
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
1558 wb_64 (regs, ECR_ADV_FUNC_CNTL, 0x31);
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
1565 wb_64 (regs, GREG_MISC_OUTPUT_W, 0x23);
1568 WCrt (regs, CRT_ID_EXT_SYS_CNTL_4, 0x0);
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);
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);
1588 /* Faster LUT write: 1 DCLK LUT write cycle, RAMDAC clk doubled */
1589 WSeq (regs, SEQ_ID_RAMDAC_CNTL, 0xC0);
1591 /* Clear immediate clock load bit */
1592 test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
1594 /* If > 55MHz, enable 2 cycle memory write */
1595 if (cv64_memclk >= 55000000) {
1598 WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
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);
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);
1611 /* We now load an 25 MHz, 31kHz, 640x480 standard VGA Mode. */
1613 /* Set DCLK value */
1614 WSeq (regs, SEQ_ID_DCLK_HI, 0x13);
1615 WSeq (regs, SEQ_ID_DCLK_LO, 0x41);
1617 /* Load DCLK (and MCLK?) immediately */
1618 test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
1620 WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
1622 /* Enable loading of DCLK */
1623 test = rb_64(regs, GREG_MISC_OUTPUT_R);
1625 wb_64 (regs, GREG_MISC_OUTPUT_W, test);
1627 /* Turn off immediate xCLK load */
1628 WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, 0x2);
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);
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);
1679 /* Colors for text mode */
1680 for (i = 0; i < 0xf; i++)
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);
1689 wb_64 (regs, VDAC_MASK, 0xFF);
1691 *((unsigned long *) (regs + ECR_FRGD_COLOR)) = 0xFF;
1692 *((unsigned long *) (regs + ECR_BKGD_COLOR)) = 0;
1694 /* Colors initially set to grayscale */
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);
1703 /* GFx hardware cursor off */
1704 WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
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");
1714 CyberSize = 1024 * 1024 * 2;
1715 WCrt (regs, CRT_ID_LAW_CNTL, 0x12);
1716 DPRINTK("2MB board\n");
1719 /* Initialize graphics engine */
1721 vgaw16 (regs, ECR_FRGD_MIX, 0x27);
1722 vgaw16 (regs, ECR_BKGD_MIX, 0x07);
1723 vgaw16 (regs, ECR_READ_REG_DATA, 0x1000);
1725 vgaw16 (regs, ECR_READ_REG_DATA, 0x2000);
1727 vgaw16 (regs, ECR_READ_REG_DATA, 0x3FFF);
1730 vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF);
1732 vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, ~0);
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);
1747 vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF);
1748 vgaw16 (regs, ECR_BKGD_COLOR, 0x01);
1749 vgaw16 (regs, ECR_FRGD_COLOR, 0x00);
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
1756 WAttr (regs, 0x33, 0);
1758 /* GRF - function code ended here */
1760 /* Turn gfx on again */
1761 gfx_on_off (0, regs);
1764 cvscreen (0, CyberBase);
1769 static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
1771 volatile unsigned char *regs = CyberRegs;
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;
1778 int tfillm, temptym;
1781 /* ---------------- */
1782 int xres, hfront, hsync, hback;
1783 int yres, vfront, vsync, vback;
1789 /* ---------------- */
1792 TEXT = 0; /* if depth == 4 */
1793 CONSOLE = 0; /* mode num == 255 (console) */
1794 fx = fy = 8; /* force 8x8 font */
1796 /* GRF - Disable interrupts */
1798 gfx_on_off (1, regs);
1800 switch (video_mode->bits_per_pixel) {
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;
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;
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;
1833 yres = video_mode->yres;
1834 vfront = video_mode->lower_margin;
1835 vsync = video_mode->vsync_len;
1836 vback = video_mode->upper_margin;
1839 /* ARB Dropping custom setup method from cvision.c */
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;
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));
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;
1870 wb_64 (regs, ECR_ADV_FUNC_CNTL, (TEXT ? 0x00 : 0x31));
1873 HDE = ((video_mode->xres + fx - 1) / fx) - 1;
1875 HDE = (video_mode->xres + 3) * hmul / 8 - 1;
1877 VDE = video_mode->yres - 1;
1879 WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
1880 WCrt (regs, CRT_ID_EXT_DAC_CNTL, 0x00);
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);
1889 /* cv64_compute_clock accepts arguments in Hz */
1890 /* pixclock is in ps ... convert to Hz */
1893 freq_f = (1.0 / (float) video_mode->pixclock) * 1000000000;
1894 freq = ((long) freq_f) * 1000;
1896 /* freq = (long) ((long long)1000000000000 / (long long) video_mode->pixclock);
1898 freq = (1000000000 / video_mode->pixclock) * 1000;
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));
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)
1916 WCrt (regs, CRT_ID_EXT_VER_OVF,
1918 ((VT & 0x400) ? 0x01 : 0x00) |
1919 ((VDE & 0x400) ? 0x02 : 0x00) |
1920 ((VBS & 0x400) ? 0x04 : 0x00) |
1921 ((VSS & 0x400) ? 0x10 : 0x00)
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,
1932 ((HBE & 0x20) ? 0x80 : 0x00)
1934 WCrt (regs, CRT_ID_VER_TOTAL, VT);
1935 WCrt (regs, CRT_ID_OVERFLOW,
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)
1945 WCrt (regs, CRT_ID_MAX_SCAN_LINE,
1947 (DBLSCAN ? 0x80 : 0x00) |
1948 ((VBS & 0x200) ? 0x20 : 0x00) |
1949 (TEXT ? ((fy - 1) & 0x1F) : 0x00)
1952 WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3);
1958 WCrt (regs, CRT_ID_CURSOR_START, (fy & 0x1f) - 2);
1959 WCrt (regs, CRT_ID_CURSOR_END, (fy & 0x1F) - 1);
1961 WCrt (regs, CRT_ID_CURSOR_START, 0x00);
1962 WCrt (regs, CRT_ID_CURSOR_END, fy & 0x1F);
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);
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));
1985 wb_64 (regs, VDAC_MASK, 0xFF);
1988 test = RCrt (regs, CRT_ID_BACKWAD_COMP_2);
1989 WCrt (regs, CRT_ID_BACKWAD_COMP_2, (test | 0x20));
1991 sr15 = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
1993 sr18 = RSeq (regs, SEQ_ID_RAMDAC_CNTL);
1998 test = RCrt (regs, CRT_ID_EXT_MISC_CNTL_2);
2001 /* Clear roxxler byte-swapping... */
2002 cv64_write_port (0x0040, CyberBase);
2003 cv64_write_port (0x0020, CyberBase);
2005 switch (video_mode->bits_per_pixel) {
2008 HDE = video_mode->xres / 16;
2012 if (freq > 80000000) {
2013 clock_mode = 0x10 | 0x02;
2017 HDE = video_mode->xres / 8;
2022 cv64_write_port (0x8020, CyberBase);
2024 HDE = video_mode->xres / 4;
2029 cv64_write_port (0x8020, CyberBase);
2031 HDE = video_mode->xres / 4;
2037 cv64_write_port (0x8040, CyberBase);
2039 HDE = video_mode->xres / 2;
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);
2049 WCrt (regs, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35));
2051 test = RCrt (regs, CRT_ID_EXT_SYS_CNTL_2);
2053 test |= (HDE >> 4) & 0x30;
2054 WCrt (regs, CRT_ID_EXT_SYS_CNTL_2, test);
2056 /* Set up graphics engine */
2057 switch (video_mode->xres) {
2086 WCrt (regs, CRT_ID_EXT_SYS_CNTL_1, cr50);
2089 WAttr (regs, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41));
2091 WAttr (regs, ACT_ID_COLOR_PLANE_ENA,
2092 (video_mode->bits_per_pixel == 1) ? 0x01 : 0x0F);
2095 tfillm = (96 * (cv64_memclk / 1000)) / 240000;
2097 switch (video_mode->bits_per_pixel) {
2100 temptym = (24 * (cv64_memclk / 1000)) / (freq / 1000);
2104 temptym = (48 * (cv64_memclk / 1000)) / (freq / 1000);
2107 temptym = (192 * (cv64_memclk / 1000)) / (freq / 1000);
2110 temptym = (96 * (cv64_memclk / 1000)) / (freq / 1000);
2114 m = (temptym - tfillm - 9) / 2;
2117 m = (m & 0x1F) << 3;
2122 WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, m);
2123 WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, n);
2126 /* Text initialization */
2129 /* Do text initialization here ! */
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]);
2142 WAttr (regs, 0x33, 0);
2144 /* Turn gfx on again */
2145 gfx_on_off (0, (volatile unsigned char *) regs);
2148 cvscreen (0, CyberBase);
2153 void cvision_bitblt (u_short sx, u_short sy, u_short dx, u_short dy,
2154 u_short w, u_short h)
2156 volatile unsigned char *regs = CyberRegs;
2157 unsigned short drawdir = 0;
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);
2192 void cvision_clear (u_short dx, u_short dy, u_short w, u_short h, u_short bg)
2194 volatile unsigned char *regs = CyberRegs;
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);
2210 * Dump internal settings of CyberVision board
2212 static void cv64_dump (void)
2214 volatile unsigned char *regs = CyberRegs;
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));