2 * linux/drivers/video/cyberfb.c -- CyberVision64 frame buffer device
3 * $Id: cyberfb.c,v 1.1.1.1 2005/04/11 02:50:41 jack 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.1.1.1 2005/04/11 02:50:41 jack
39 * Revision 1.1.1.1 2005/01/10 13:16:42 jack
42 * Revision 1.6 1998/09/11 04:54:58 abair
43 * Update for 2.1.120 change in include file location.
44 * Clean up for public release.
46 * Revision 1.5 1998/09/03 04:27:13 abair
47 * Move cv64_load_video_mode to cyber_set_video so a new video mode is install
48 * with each change of the 'var' data.
50 * Revision 1.4 1998/09/01 00:31:17 abair
51 * Put in a set of default 8,16,24 bpp modes and map cyber8,16 to them.
52 * Update operations with 'par' to handle a more complete set of parameter
53 * values for encode/decode process.
55 * Revision 1.3 1998/08/31 21:31:33 abair
56 * Swap 800x490 for 640x480 video mode and more cleanup.
57 * Abandon idea to resurrect "custom" mode setting via kernel opts,
58 * instead work on making use of fbset program to do this.
60 * Revision 1.2 1998/08/31 06:17:08 abair
61 * Make updates for changes in cyberfb.c released in 2.1.119
62 * and do some cleanup of the code.
64 * Revision 1.1 1998/08/29 18:38:31 abair
67 * Revision 1.3 1998/08/17 06:21:53 abair
68 * Remove more redundant code after merging in cvision_core.c
69 * Set blanking by colormap to pale red to detect this vs trying to
70 * use video blanking. More formating to Linux code style.
72 * Revision 1.2 1998/08/15 17:51:37 abair
73 * Added cvision_core.c code from 2.1.35 patches.
74 * Changed to compile correctly and switch to using initialization
75 * code. Added debugging and dropping of duplicate code.
79 * This file is subject to the terms and conditions of the GNU General Public
80 * License. See the file COPYING in the main directory of this archive
85 #include <linux/module.h>
86 #include <linux/kernel.h>
87 #include <linux/errno.h>
88 #include <linux/string.h>
90 #include <linux/tty.h>
91 #include <linux/slab.h>
92 #include <linux/delay.h>
93 #include <linux/zorro.h>
95 #include <linux/init.h>
96 #include <asm/uaccess.h>
97 #include <asm/system.h>
99 #include <asm/pgtable.h>
100 #include <asm/amigahw.h>
104 #include <video/fbcon.h>
105 #include <video/fbcon-cfb8.h>
106 #include <video/fbcon-cfb16.h>
108 /*#define CYBERFBDEBUG*/
110 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
111 static void cv64_dump(void);
113 #define DPRINTK(fmt, args...)
116 #define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat)
117 #define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg))
119 #define ww_64(regs,reg,dat) (*((volatile unsigned short *)(regs + reg) = dat)
122 struct fb_var_screeninfo var;
129 static struct cyberfb_par current_par;
131 static int current_par_valid = 0;
132 static int currcon = 0;
134 static struct display disp;
135 static struct fb_info fb_info;
142 static char cyberfb_name[16] = "Cybervision";
146 * CyberVision Graphics Board
149 static unsigned char Cyber_colour_table [256][3];
150 static unsigned long CyberSize;
151 static volatile unsigned char *CyberBase;
152 static volatile unsigned char *CyberMem;
153 static volatile unsigned char *CyberRegs;
154 static unsigned long CyberMem_phys;
155 static unsigned long CyberRegs_phys;
158 * Predefined Video Modes
163 struct fb_var_screeninfo var;
164 } cyberfb_predefined[] __initdata = {
165 { "640x480-8", { /* Default 8 BPP mode (cyber8) */
166 640, 480, 640, 480, 0, 0, 8, 0,
167 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
168 0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
169 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
170 FB_VMODE_NONINTERLACED
172 { "640x480-16", { /* Default 16 BPP mode (cyber16) */
173 640, 480, 640, 480, 0, 0, 16, 0,
174 {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
175 0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
176 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
177 FB_VMODE_NONINTERLACED
179 { "640x480-24", { /* Default 24 BPP mode */
180 640, 480, 640, 480, 0, 0, 24, 0,
181 {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {0, 0, 0},
182 0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
183 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
184 FB_VMODE_NONINTERLACED
186 { "800x490-8", { /* Cybervision 8 bpp */
187 /* NO Acceleration */
188 800, 490, 800, 490, 0, 0, 8, 0,
189 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
190 0, 0, -1, -1, FB_ACCEL_NONE, 33333, 80, 24, 23, 1, 56, 8,
191 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
192 FB_VMODE_NONINTERLACED
194 /* I can't test these with my monitor, but I suspect they will
195 * be OK, since Antonio Santos indicated he had tested them in
198 { "800x600-8", { /* Cybervision 8 bpp */
199 800, 600, 800, 600, 0, 0, 8, 0,
200 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
201 0, 0, -1, -1, FB_ACCELF_TEXT, 27778, 64, 24, 22, 1, 72, 2,
202 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
203 FB_VMODE_NONINTERLACED
205 { "1024x768-8", { /* Cybervision 8 bpp */
206 1024, 768, 1024, 768, 0, 0, 8, 0,
207 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
208 0, 0, -1, -1, FB_ACCELF_TEXT, 16667, 224, 72, 60, 12, 168, 4,
209 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
210 FB_VMODE_NONINTERLACED
212 { "1152x886-8", { /* Cybervision 8 bpp */
213 1152, 886, 1152, 886, 0, 0, 8, 0,
214 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
215 0, 0, -1, -1, FB_ACCELF_TEXT, 15873, 184, 40, 24, 1, 56, 16,
216 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
217 FB_VMODE_NONINTERLACED
219 { "1280x1024-8", { /* Cybervision 8 bpp */
220 1280, 1024, 1280, 1024, 0, 0, 8, 0,
221 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
222 0, 0, -1, -1, FB_ACCELF_TEXT, 16667, 256, 48, 50, 12, 72, 4,
223 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
228 #define NUM_TOTAL_MODES ARRAY_SIZE(cyberfb_predefined)
230 static int Cyberfb_inverse = 0;
236 #define CYBER8_DEFMODE (0)
237 #define CYBER16_DEFMODE (1)
239 static struct fb_var_screeninfo cyberfb_default;
240 static int cyberfb_usermode __initdata = 0;
243 * Interface used by the world
246 int cyberfb_setup(char *options);
248 static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
249 struct fb_info *info);
250 static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
251 struct fb_info *info);
252 static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
253 struct fb_info *info);
254 static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
255 struct fb_info *info);
256 static int cyberfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
257 struct fb_info *info);
260 * Interface to the low level console driver
263 int cyberfb_init(void);
264 static int Cyberfb_switch(int con, struct fb_info *info);
265 static int Cyberfb_updatevar(int con, struct fb_info *info);
266 static void Cyberfb_blank(int blank, struct fb_info *info);
269 * Text console acceleration
272 #ifdef FBCON_HAS_CFB8
273 static struct display_switch fbcon_cyber8;
277 * Accelerated Functions used by the low level console driver
280 static void Cyber_WaitQueue(u_short fifo);
281 static void Cyber_WaitBlit(void);
282 static void Cyber_BitBLT(u_short curx, u_short cury, u_short destx,
283 u_short desty, u_short width, u_short height,
285 static void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height,
286 u_short mode, u_short color);
288 static void Cyber_MoveCursor(u_short x, u_short y);
292 * Hardware Specific Routines
295 static int Cyber_init(void);
296 static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
297 struct cyberfb_par *par);
298 static int Cyber_decode_var(struct fb_var_screeninfo *var,
299 struct cyberfb_par *par);
300 static int Cyber_encode_var(struct fb_var_screeninfo *var,
301 struct cyberfb_par *par);
302 static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
303 u_int *transp, struct fb_info *info);
304 static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
305 u_int transp, struct fb_info *info);
311 static void cyberfb_get_par(struct cyberfb_par *par);
312 static void cyberfb_set_par(struct cyberfb_par *par);
313 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
314 static void do_install_cmap(int con, struct fb_info *info);
315 static void cyberfb_set_disp(int con, struct fb_info *info);
316 static int get_video_mode(const char *name);
318 /* For cvision_core.c */
319 static unsigned short cv64_compute_clock(unsigned long);
320 static int cv_has_4mb (volatile unsigned char *);
321 static void cv64_board_init (void);
322 static void cv64_load_video_mode (struct fb_var_screeninfo *);
325 /* -------------------- Hardware specific routines ------------------------- */
331 * Set the default video mode for this chipset. If a video mode was
332 * specified on the command line, it will override the default mode.
335 static int Cyber_init(void)
337 volatile unsigned char *regs = CyberRegs;
338 volatile unsigned long *CursorBase;
342 /* Init local cmap as greyscale levels */
343 for (i = 0; i < 256; i++) {
344 Cyber_colour_table [i][0] = i;
345 Cyber_colour_table [i][1] = i;
346 Cyber_colour_table [i][2] = i;
349 /* Initialize the board and determine fbmem size */
352 DPRINTK("Register state after initing board\n");
355 /* Clear framebuffer memory */
356 DPRINTK("Clear framebuffer memory\n");
357 memset ((char *)CyberMem, 0, CyberSize);
359 /* Disable hardware cursor */
360 DPRINTK("Disable HW cursor\n");
361 wb_64(regs, S3_CRTC_ADR, S3_REG_LOCK2);
362 wb_64(regs, S3_CRTC_DATA, 0xa0);
363 wb_64(regs, S3_CRTC_ADR, S3_HGC_MODE);
364 wb_64(regs, S3_CRTC_DATA, 0x00);
365 wb_64(regs, S3_CRTC_ADR, S3_HWGC_DX);
366 wb_64(regs, S3_CRTC_DATA, 0x00);
367 wb_64(regs, S3_CRTC_ADR, S3_HWGC_DY);
368 wb_64(regs, S3_CRTC_DATA, 0x00);
370 /* Initialize hardware cursor */
371 DPRINTK("Init HW cursor\n");
372 CursorBase = (u_long *)((char *)(CyberMem) + CyberSize - 0x400);
373 for (i=0; i < 8; i++)
375 *(CursorBase +(i*4)) = 0xffffff00;
376 *(CursorBase+1+(i*4)) = 0xffff0000;
377 *(CursorBase+2+(i*4)) = 0xffff0000;
378 *(CursorBase+3+(i*4)) = 0xffff0000;
380 for (i=8; i < 64; i++)
382 *(CursorBase +(i*4)) = 0xffff0000;
383 *(CursorBase+1+(i*4)) = 0xffff0000;
384 *(CursorBase+2+(i*4)) = 0xffff0000;
385 *(CursorBase+3+(i*4)) = 0xffff0000;
388 Cyber_setcolreg (255, 56<<8, 100<<8, 160<<8, 0, NULL /* unused */);
389 Cyber_setcolreg (254, 0, 0, 0, 0, NULL /* unused */);
397 * This function should fill in the `fix' structure based on the
398 * values in the `par' structure.
401 static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
402 struct cyberfb_par *par)
405 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
406 strcpy(fix->id, cyberfb_name);
407 fix->smem_start = CyberMem_phys;
408 fix->smem_len = CyberSize;
409 fix->mmio_start = CyberRegs_phys;
410 fix->mmio_len = 0x10000;
412 fix->type = FB_TYPE_PACKED_PIXELS;
414 if (par->var.bits_per_pixel == 15 || par->var.bits_per_pixel == 16 ||
415 par->var.bits_per_pixel == 24 || par->var.bits_per_pixel == 32) {
416 fix->visual = FB_VISUAL_DIRECTCOLOR;
418 fix->visual = FB_VISUAL_PSEUDOCOLOR;
424 fix->line_length = 0;
425 fix->accel = FB_ACCEL_S3_TRIO64;
433 * Fill the `par' structure based on the values in `var'.
434 * TODO: Verify and adjust values, return -EINVAL if bad.
437 static int Cyber_decode_var(struct fb_var_screeninfo *var,
438 struct cyberfb_par *par)
441 par->var.xres = var->xres;
442 par->var.yres = var->yres;
443 par->var.xres_virtual = var->xres_virtual;
444 par->var.yres_virtual = var->yres_virtual;
445 par->var.xoffset = var->xoffset;
446 par->var.yoffset = var->yoffset;
447 par->var.bits_per_pixel = var->bits_per_pixel;
448 par->var.grayscale = var->grayscale;
449 par->var.red = var->red;
450 par->var.green = var->green;
451 par->var.blue = var->blue;
452 par->var.transp = var->transp;
453 par->var.nonstd = var->nonstd;
454 par->var.activate = var->activate;
455 par->var.height = var->height;
456 par->var.width = var->width;
457 if (var->accel_flags & FB_ACCELF_TEXT) {
458 par->var.accel_flags = FB_ACCELF_TEXT;
460 par->var.accel_flags = 0;
462 par->var.pixclock = var->pixclock;
463 par->var.left_margin = var->left_margin;
464 par->var.right_margin = var->right_margin;
465 par->var.upper_margin = var->upper_margin;
466 par->var.lower_margin = var->lower_margin;
467 par->var.hsync_len = var->hsync_len;
468 par->var.vsync_len = var->vsync_len;
469 par->var.sync = var->sync;
470 par->var.vmode = var->vmode;
476 * Fill the `var' structure based on the values in `par' and maybe
477 * other values read out of the hardware.
480 static int Cyber_encode_var(struct fb_var_screeninfo *var,
481 struct cyberfb_par *par)
484 var->xres = par->var.xres;
485 var->yres = par->var.yres;
486 var->xres_virtual = par->var.xres_virtual;
487 var->yres_virtual = par->var.yres_virtual;
488 var->xoffset = par->var.xoffset;
489 var->yoffset = par->var.yoffset;
491 var->bits_per_pixel = par->var.bits_per_pixel;
492 var->grayscale = par->var.grayscale;
494 var->red = par->var.red;
495 var->green = par->var.green;
496 var->blue = par->var.blue;
497 var->transp = par->var.transp;
499 var->nonstd = par->var.nonstd;
500 var->activate = par->var.activate;
502 var->height = par->var.height;
503 var->width = par->var.width;
505 var->accel_flags = par->var.accel_flags;
507 var->pixclock = par->var.pixclock;
508 var->left_margin = par->var.left_margin;
509 var->right_margin = par->var.right_margin;
510 var->upper_margin = par->var.upper_margin;
511 var->lower_margin = par->var.lower_margin;
512 var->hsync_len = par->var.hsync_len;
513 var->vsync_len = par->var.vsync_len;
514 var->sync = par->var.sync;
515 var->vmode = par->var.vmode;
523 * Set a single color register. Return != 0 for invalid regno.
526 static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
527 u_int transp, struct fb_info *info)
529 volatile unsigned char *regs = CyberRegs;
531 /*DPRINTK("ENTER\n");*/
533 DPRINTK("EXIT - Register # > 255\n");
537 wb_64(regs, 0x3c8, (unsigned char) regno);
543 Cyber_colour_table [regno][0] = red;
544 Cyber_colour_table [regno][1] = green;
545 Cyber_colour_table [regno][2] = blue;
547 wb_64(regs, 0x3c9, red);
548 wb_64(regs, 0x3c9, green);
549 wb_64(regs, 0x3c9, blue);
551 /*DPRINTK("EXIT\n");*/
557 * Read a single color register and split it into
558 * colors/transparent. Return != 0 for invalid regno.
561 static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
562 u_int *transp, struct fb_info *info)
566 /*DPRINTK("ENTER\n");*/
568 DPRINTK("EXIT - Register # > 255\n");
571 /* ARB This shifting & oring seems VERY strange */
572 t = Cyber_colour_table [regno][0];
573 *red = (t<<10) | (t<<4) | (t>>2);
574 t = Cyber_colour_table [regno][1];
575 *green = (t<<10) | (t<<4) | (t>>2);
576 t = Cyber_colour_table [regno][2];
577 *blue = (t<<10) | (t<<4) | (t>>2);
579 /*DPRINTK("EXIT\n");*/
585 * (Un)Blank the screen
586 * blank: 1 = zero fb cmap
587 * 0 = restore fb cmap from local cmap
590 void Cyberfb_blank(int blank, struct fb_info *info)
592 volatile unsigned char *regs = CyberRegs;
597 /* Blank by turning gfx off */
598 gfx_on_off (1, regs);
601 for (i = 0; i < 256; i++) {
602 wb_64(regs, 0x3c8, (unsigned char) i);
603 /* ARB Pale red to detect this blanking method */
604 wb_64(regs, 0x3c9, 48);
605 wb_64(regs, 0x3c9, 0);
606 wb_64(regs, 0x3c9, 0);
609 for (i = 0; i < 256; i++) {
610 wb_64(regs, 0x3c8, (unsigned char) i);
611 wb_64(regs, 0x3c9, Cyber_colour_table[i][0]);
612 wb_64(regs, 0x3c9, Cyber_colour_table[i][1]);
613 wb_64(regs, 0x3c9, Cyber_colour_table[i][2]);
621 /**************************************************************
622 * We are waiting for "fifo" FIFO-slots empty
624 static void Cyber_WaitQueue (u_short fifo)
626 unsigned short status;
630 status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
631 } while (status & fifo);
635 /**************************************************************
636 * We are waiting for Hardware (Graphics Engine) not busy
638 static void Cyber_WaitBlit (void)
640 unsigned short status;
644 status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
645 } while (status & S3_HDW_BUSY);
649 /**************************************************************
650 * BitBLT - Through the Plane
652 static void Cyber_BitBLT (u_short curx, u_short cury, u_short destx,
653 u_short desty, u_short width, u_short height,
656 volatile unsigned char *regs = CyberRegs;
657 u_short blitcmd = S3_BITBLT;
660 /* Set drawing direction */
661 /* -Y, X maj, -X (default) */
663 blitcmd |= 0x0020; /* Drawing direction +X */
666 destx += (width - 1);
670 blitcmd |= 0x0080; /* Drawing direction +Y */
672 cury += (height - 1);
673 desty += (height - 1);
676 Cyber_WaitQueue (0x8000);
678 *((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
679 *((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0060 | mode);
681 *((u_short volatile *)(regs + S3_CUR_X)) = curx;
682 *((u_short volatile *)(regs + S3_CUR_Y)) = cury;
684 *((u_short volatile *)(regs + S3_DESTX_DIASTP)) = destx;
685 *((u_short volatile *)(regs + S3_DESTY_AXSTP)) = desty;
687 *((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
688 *((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width - 1;
690 *((u_short volatile *)(regs + S3_CMD)) = blitcmd;
694 /**************************************************************
695 * Rectangle Fill Solid
697 static void Cyber_RectFill (u_short x, u_short y, u_short width,
698 u_short height, u_short mode, u_short color)
700 volatile unsigned char *regs = CyberRegs;
701 u_short blitcmd = S3_FILLEDRECT;
704 Cyber_WaitQueue (0x8000);
706 *((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
707 *((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0020 | mode);
709 *((u_short volatile *)(regs + S3_MULT_MISC)) = 0xe000;
710 *((u_short volatile *)(regs + S3_FRGD_COLOR)) = color;
712 *((u_short volatile *)(regs + S3_CUR_X)) = x;
713 *((u_short volatile *)(regs + S3_CUR_Y)) = y;
715 *((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
716 *((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width - 1;
718 *((u_short volatile *)(regs + S3_CMD)) = blitcmd;
724 /**************************************************************
725 * Move cursor to x, y
727 static void Cyber_MoveCursor (u_short x, u_short y)
729 volatile unsigned char *regs = CyberRegs;
731 *(regs + S3_CRTC_ADR) = 0x39;
732 *(regs + S3_CRTC_DATA) = 0xa0;
734 *(regs + S3_CRTC_ADR) = S3_HWGC_ORGX_H;
735 *(regs + S3_CRTC_DATA) = (char)((x & 0x0700) >> 8);
736 *(regs + S3_CRTC_ADR) = S3_HWGC_ORGX_L;
737 *(regs + S3_CRTC_DATA) = (char)(x & 0x00ff);
739 *(regs + S3_CRTC_ADR) = S3_HWGC_ORGY_H;
740 *(regs + S3_CRTC_DATA) = (char)((y & 0x0700) >> 8);
741 *(regs + S3_CRTC_ADR) = S3_HWGC_ORGY_L;
742 *(regs + S3_CRTC_DATA) = (char)(y & 0x00ff);
748 /* -------------------- Generic routines ---------------------------------- */
752 * Fill the hardware's `par' structure.
755 static void cyberfb_get_par(struct cyberfb_par *par)
758 if (current_par_valid) {
761 Cyber_decode_var(&cyberfb_default, par);
767 static void cyberfb_set_par(struct cyberfb_par *par)
771 current_par_valid = 1;
776 static void cyber_set_video(struct fb_var_screeninfo *var)
779 /* Load the video mode defined by the 'var' data */
780 cv64_load_video_mode (var);
782 DPRINTK("Register state after loading video mode\n");
788 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
791 struct cyberfb_par par;
794 if ((err = Cyber_decode_var(var, &par))) {
795 DPRINTK("EXIT - decode_var failed\n");
798 activate = var->activate;
799 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
800 cyberfb_set_par(&par);
801 Cyber_encode_var(var, &par);
802 var->activate = activate;
804 cyber_set_video(var);
810 static void do_install_cmap(int con, struct fb_info *info)
813 if (con != currcon) {
814 DPRINTK("EXIT - Not current console\n");
817 if (fb_display[con].cmap.len) {
818 DPRINTK("Use console cmap\n");
819 fb_set_cmap(&fb_display[con].cmap, 1, Cyber_setcolreg, info);
821 DPRINTK("Use default cmap\n");
822 fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
823 1, Cyber_setcolreg, info);
829 * Get the Fixed Part of the Display
832 static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
833 struct fb_info *info)
835 struct cyberfb_par par;
840 cyberfb_get_par(&par);
842 error = Cyber_decode_var(&fb_display[con].var, &par);
845 return(error ? error : Cyber_encode_fix(fix, &par));
850 * Get the User Defined Part of the Display
853 static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
854 struct fb_info *info)
856 struct cyberfb_par par;
861 cyberfb_get_par(&par);
862 error = Cyber_encode_var(var, &par);
863 disp.var = *var; /* ++Andre: don't know if this is the right place */
865 *var = fb_display[con].var;
873 static void cyberfb_set_disp(int con, struct fb_info *info)
875 struct fb_fix_screeninfo fix;
876 struct display *display;
880 display = &fb_display[con];
882 display = &disp; /* used during initialization */
884 cyberfb_get_fix(&fix, con, info);
887 display->screen_base = (unsigned char *)CyberMem;
888 display->visual = fix.visual;
889 display->type = fix.type;
890 display->type_aux = fix.type_aux;
891 display->ypanstep = fix.ypanstep;
892 display->ywrapstep = fix.ywrapstep;
893 display->can_soft_blank = 1;
894 display->inverse = Cyberfb_inverse;
895 switch (display->var.bits_per_pixel) {
896 #ifdef FBCON_HAS_CFB8
898 if (display->var.accel_flags & FB_ACCELF_TEXT) {
899 display->dispsw = &fbcon_cyber8;
900 #warning FIXME: We should reinit the graphics engine here
902 display->dispsw = &fbcon_cfb8;
905 #ifdef FBCON_HAS_CFB16
907 display->dispsw = &fbcon_cfb16;
911 display->dispsw = NULL;
919 * Set the User Defined Part of the Display
922 static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
923 struct fb_info *info)
925 int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
928 if ((err = do_fb_set_var(var, con == currcon))) {
929 DPRINTK("EXIT - do_fb_set_var failed\n");
932 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
933 oldxres = fb_display[con].var.xres;
934 oldyres = fb_display[con].var.yres;
935 oldvxres = fb_display[con].var.xres_virtual;
936 oldvyres = fb_display[con].var.yres_virtual;
937 oldbpp = fb_display[con].var.bits_per_pixel;
938 oldaccel = fb_display[con].var.accel_flags;
939 fb_display[con].var = *var;
940 if (oldxres != var->xres || oldyres != var->yres ||
941 oldvxres != var->xres_virtual ||
942 oldvyres != var->yres_virtual ||
943 oldbpp != var->bits_per_pixel ||
944 oldaccel != var->accel_flags) {
945 cyberfb_set_disp(con, info);
946 (*fb_info.changevar)(con);
947 fb_alloc_cmap(&fb_display[con].cmap, 0, 0);
948 do_install_cmap(con, info);
961 static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
962 struct fb_info *info)
965 if (con == currcon) { /* current console? */
966 DPRINTK("EXIT - console is current console\n");
967 return(fb_get_cmap(cmap, kspc, Cyber_getcolreg, info));
968 } else if (fb_display[con].cmap.len) { /* non default colormap? */
969 DPRINTK("Use console cmap\n");
970 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
972 DPRINTK("Use default cmap\n");
973 fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
985 static int cyberfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
986 struct fb_info *info)
991 if (!fb_display[con].cmap.len) { /* no colormap allocated? */
992 if ((err = fb_alloc_cmap(&fb_display[con].cmap,
993 1<<fb_display[con].var.bits_per_pixel,
995 DPRINTK("EXIT - fb_alloc_cmap failed\n");
999 if (con == currcon) { /* current console? */
1000 DPRINTK("EXIT - Current console\n");
1001 return(fb_set_cmap(cmap, kspc, Cyber_setcolreg, info));
1003 fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
1010 static struct fb_ops cyberfb_ops = {
1012 fb_get_fix: cyberfb_get_fix,
1013 fb_get_var: cyberfb_get_var,
1014 fb_set_var: cyberfb_set_var,
1015 fb_get_cmap: cyberfb_get_cmap,
1016 fb_set_cmap: cyberfb_set_cmap,
1019 int __init cyberfb_setup(char *options)
1024 fb_info.fontname[0] = '\0';
1026 if (!options || !*options) {
1027 DPRINTK("EXIT - no options\n");
1031 while ((this_opt = strsep(&options, ",")) != NULL) {
1034 if (!strcmp(this_opt, "inverse")) {
1035 Cyberfb_inverse = 1;
1037 } else if (!strncmp(this_opt, "font:", 5)) {
1038 strcpy(fb_info.fontname, this_opt+5);
1039 } else if (!strcmp (this_opt, "cyber8")) {
1040 cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
1041 cyberfb_usermode = 1;
1042 } else if (!strcmp (this_opt, "cyber16")) {
1043 cyberfb_default = cyberfb_predefined[CYBER16_DEFMODE].var;
1044 cyberfb_usermode = 1;
1045 } else get_video_mode(this_opt);
1048 DPRINTK("default mode: xres=%d, yres=%d, bpp=%d\n",
1049 cyberfb_default.xres,
1050 cyberfb_default.yres,
1051 cyberfb_default.bits_per_pixel);
1060 int __init cyberfb_init(void)
1062 unsigned long board_addr, board_size;
1063 struct cyberfb_par par;
1064 struct zorro_dev *z = NULL;
1067 while ((z = zorro_find_device(ZORRO_PROD_PHASE5_CYBERVISION64, z))) {
1068 board_addr = z->resource.start;
1069 board_size = z->resource.end-z->resource.start+1;
1070 CyberMem_phys = board_addr + 0x01400000;
1071 CyberRegs_phys = CyberMem_phys + 0x00c00000;
1072 if (!request_mem_region(CyberRegs_phys, 0x10000, "S3 Trio64"))
1074 if (!request_mem_region(CyberMem_phys, 0x400000, "RAM")) {
1075 release_mem_region(CyberRegs_phys, 0x10000);
1078 DPRINTK("board_addr=%08lx\n", board_addr);
1079 DPRINTK("board_size=%08lx\n", board_size);
1081 CyberBase = ioremap(board_addr, board_size);
1082 CyberRegs = CyberBase + 0x02000000;
1083 CyberMem = CyberBase + 0x01400000;
1084 DPRINTK("CyberBase=%08lx CyberRegs=%08lx CyberMem=%08lx\n",
1085 CyberBase, (long unsigned int)CyberRegs, CyberMem);
1088 DPRINTK("Register state just after mapping memory\n");
1092 strcpy(fb_info.modename, cyberfb_name);
1093 fb_info.changevar = NULL;
1095 fb_info.fbops = &cyberfb_ops;
1096 fb_info.disp = &disp;
1097 fb_info.switch_con = &Cyberfb_switch;
1098 fb_info.updatevar = &Cyberfb_updatevar;
1099 fb_info.blank = &Cyberfb_blank;
1102 /* ++Andre: set cyberfb default mode */
1103 if (!cyberfb_usermode) {
1104 cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
1105 DPRINTK("Use default cyber8 mode\n");
1107 Cyber_decode_var(&cyberfb_default, &par);
1108 Cyber_encode_var(&cyberfb_default, &par);
1110 do_fb_set_var(&cyberfb_default, 1);
1111 cyberfb_get_var(&fb_display[0].var, -1, &fb_info);
1112 cyberfb_set_disp(-1, &fb_info);
1113 do_install_cmap(0, &fb_info);
1115 if (register_framebuffer(&fb_info) < 0) {
1116 DPRINTK("EXIT - register_framebuffer failed\n");
1117 release_mem_region(CyberMem_phys, 0x400000);
1118 release_mem_region(CyberRegs_phys, 0x10000);
1122 printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
1123 GET_FB_IDX(fb_info.node), fb_info.modename, CyberSize>>10);
1125 /* TODO: This driver cannot be unloaded yet */
1134 static int Cyberfb_switch(int con, struct fb_info *info)
1137 /* Do we have to save the colormap? */
1138 if (fb_display[currcon].cmap.len) {
1139 fb_get_cmap(&fb_display[currcon].cmap, 1, Cyber_getcolreg,
1143 do_fb_set_var(&fb_display[con].var, 1);
1145 /* Install new colormap */
1146 do_install_cmap(con, info);
1153 * Update the `var' structure (called by fbcon.c)
1155 * This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
1156 * Since it's called by a kernel driver, no range checking is done.
1159 static int Cyberfb_updatevar(int con, struct fb_info *info)
1161 DPRINTK("Enter - Exit\n");
1170 static int __init get_video_mode(const char *name)
1175 for (i = 0; i < NUM_TOTAL_MODES; i++) {
1176 if (!strcmp(name, cyberfb_predefined[i].name)) {
1177 cyberfb_default = cyberfb_predefined[i].var;
1178 cyberfb_usermode = 1;
1179 DPRINTK("EXIT - Matched predefined mode\n");
1188 * Text console acceleration
1191 #ifdef FBCON_HAS_CFB8
1192 static void fbcon_cyber8_bmove(struct display *p, int sy, int sx, int dy,
1193 int dx, int height, int width)
1196 sx *= 8; dx *= 8; width *= 8;
1197 Cyber_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
1198 (u_short)(dy*fontheight(p)), (u_short)width,
1199 (u_short)(height*fontheight(p)), (u_short)S3_NEW);
1203 static void fbcon_cyber8_clear(struct vc_data *conp, struct display *p, int sy,
1204 int sx, int height, int width)
1209 sx *= 8; width *= 8;
1210 bg = attr_bgcol_ec(p,conp);
1211 Cyber_RectFill((u_short)sx,
1212 (u_short)(sy*fontheight(p)),
1214 (u_short)(height*fontheight(p)),
1220 static void fbcon_cyber8_putc(struct vc_data *conp, struct display *p, int c,
1225 fbcon_cfb8_putc(conp, p, c, yy, xx);
1229 static void fbcon_cyber8_putcs(struct vc_data *conp, struct display *p,
1230 const unsigned short *s, int count,
1235 fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
1239 static void fbcon_cyber8_revc(struct display *p, int xx, int yy)
1243 fbcon_cfb8_revc(p, xx, yy);
1247 static struct display_switch fbcon_cyber8 = {
1248 setup: fbcon_cfb8_setup,
1249 bmove: fbcon_cyber8_bmove,
1250 clear: fbcon_cyber8_clear,
1251 putc: fbcon_cyber8_putc,
1252 putcs: fbcon_cyber8_putcs,
1253 revc: fbcon_cyber8_revc,
1254 clear_margins: fbcon_cfb8_clear_margins,
1255 fontwidthmask: FONTWIDTH(8)
1261 MODULE_LICENSE("GPL");
1263 int init_module(void)
1265 return cyberfb_init();
1268 void cleanup_module(void)
1270 /* Not reached because the usecount will never be
1271 decremented to zero */
1272 unregister_framebuffer(&fb_info);
1273 /* TODO: clean up ... */
1279 * Low level initialization routines for the CyberVision64 graphics card
1281 * Most of the following code is from cvision_core.c
1285 #define MAXPIXELCLOCK 135000000 /* safety */
1287 #ifdef CV_AGGRESSIVE_TIMING
1288 long cv64_memclk = 55000000;
1290 long cv64_memclk = 50000000;
1293 /*********************/
1295 static unsigned char clocks[]={
1296 0x13, 0x61, 0x6b, 0x6d, 0x51, 0x69, 0x54, 0x69,
1297 0x4f, 0x68, 0x6b, 0x6b, 0x18, 0x61, 0x7b, 0x6c,
1298 0x51, 0x67, 0x24, 0x62, 0x56, 0x67, 0x77, 0x6a,
1299 0x1d, 0x61, 0x53, 0x66, 0x6b, 0x68, 0x79, 0x69,
1300 0x7c, 0x69, 0x7f, 0x69, 0x22, 0x61, 0x54, 0x65,
1301 0x56, 0x65, 0x58, 0x65, 0x67, 0x66, 0x41, 0x63,
1302 0x27, 0x61, 0x13, 0x41, 0x37, 0x62, 0x6b, 0x4d,
1303 0x23, 0x43, 0x51, 0x49, 0x79, 0x66, 0x54, 0x49,
1304 0x7d, 0x66, 0x34, 0x56, 0x4f, 0x63, 0x1f, 0x42,
1305 0x6b, 0x4b, 0x7e, 0x4d, 0x18, 0x41, 0x2a, 0x43,
1306 0x7b, 0x4c, 0x74, 0x4b, 0x51, 0x47, 0x65, 0x49,
1307 0x24, 0x42, 0x68, 0x49, 0x56, 0x47, 0x75, 0x4a,
1308 0x77, 0x4a, 0x31, 0x43, 0x1d, 0x41, 0x71, 0x49,
1309 0x53, 0x46, 0x29, 0x42, 0x6b, 0x48, 0x1f, 0x41,
1310 0x79, 0x49, 0x6f, 0x48, 0x7c, 0x49, 0x38, 0x43,
1311 0x7f, 0x49, 0x5d, 0x46, 0x22, 0x41, 0x53, 0x45,
1312 0x54, 0x45, 0x55, 0x45, 0x56, 0x45, 0x57, 0x45,
1313 0x58, 0x45, 0x25, 0x41, 0x67, 0x46, 0x5b, 0x45,
1314 0x41, 0x43, 0x78, 0x47, 0x27, 0x41, 0x51, 0x44,
1315 0x13, 0x21, 0x7d, 0x47, 0x37, 0x42, 0x71, 0x46,
1316 0x6b, 0x2d, 0x14, 0x21, 0x23, 0x23, 0x7d, 0x2f,
1317 0x51, 0x29, 0x61, 0x2b, 0x79, 0x46, 0x1d, 0x22,
1318 0x54, 0x29, 0x45, 0x27, 0x7d, 0x46, 0x7f, 0x46,
1319 0x4f, 0x43, 0x2f, 0x41, 0x1f, 0x22, 0x6a, 0x2b,
1320 0x6b, 0x2b, 0x5b, 0x29, 0x7e, 0x2d, 0x65, 0x44,
1321 0x18, 0x21, 0x5e, 0x29, 0x2a, 0x23, 0x45, 0x26,
1322 0x7b, 0x2c, 0x19, 0x21, 0x74, 0x2b, 0x75, 0x2b,
1323 0x51, 0x27, 0x3f, 0x25, 0x65, 0x29, 0x40, 0x25,
1324 0x24, 0x22, 0x41, 0x25, 0x68, 0x29, 0x42, 0x25,
1325 0x56, 0x27, 0x7e, 0x2b, 0x75, 0x2a, 0x1c, 0x21,
1326 0x77, 0x2a, 0x4f, 0x26, 0x31, 0x23, 0x6f, 0x29,
1327 0x1d, 0x21, 0x32, 0x23, 0x71, 0x29, 0x72, 0x29,
1328 0x53, 0x26, 0x69, 0x28, 0x29, 0x22, 0x75, 0x29,
1329 0x6b, 0x28, 0x1f, 0x21, 0x1f, 0x21, 0x6d, 0x28,
1330 0x79, 0x29, 0x2b, 0x22, 0x6f, 0x28, 0x59, 0x26,
1331 0x7c, 0x29, 0x7d, 0x29, 0x38, 0x23, 0x21, 0x21,
1332 0x7f, 0x29, 0x39, 0x23, 0x5d, 0x26, 0x75, 0x28,
1333 0x22, 0x21, 0x77, 0x28, 0x53, 0x25, 0x6c, 0x27,
1334 0x54, 0x25, 0x61, 0x26, 0x55, 0x25, 0x30, 0x22,
1335 0x56, 0x25, 0x63, 0x26, 0x57, 0x25, 0x71, 0x27,
1336 0x58, 0x25, 0x7f, 0x28, 0x25, 0x21, 0x74, 0x27,
1337 0x67, 0x26, 0x40, 0x23, 0x5b, 0x25, 0x26, 0x21,
1338 0x41, 0x23, 0x34, 0x22, 0x78, 0x27, 0x6b, 0x26,
1339 0x27, 0x21, 0x35, 0x22, 0x51, 0x24, 0x7b, 0x27,
1340 0x13, 0x1, 0x13, 0x1, 0x7d, 0x27, 0x4c, 0x9,
1341 0x37, 0x22, 0x5b, 0xb, 0x71, 0x26, 0x5c, 0xb,
1342 0x6b, 0xd, 0x47, 0x23, 0x14, 0x1, 0x4f, 0x9,
1343 0x23, 0x3, 0x75, 0x26, 0x7d, 0xf, 0x1c, 0x2,
1344 0x51, 0x9, 0x59, 0x24, 0x61, 0xb, 0x69, 0x25,
1345 0x79, 0x26, 0x34, 0x5, 0x1d, 0x2, 0x6b, 0x25,
1346 0x54, 0x9, 0x35, 0x5, 0x45, 0x7, 0x6d, 0x25,
1347 0x7d, 0x26, 0x16, 0x1, 0x7f, 0x26, 0x77, 0xd,
1348 0x4f, 0x23, 0x78, 0xd, 0x2f, 0x21, 0x27, 0x3,
1349 0x1f, 0x2, 0x59, 0x9, 0x6a, 0xb, 0x73, 0x25,
1350 0x6b, 0xb, 0x63, 0x24, 0x5b, 0x9, 0x20, 0x2,
1351 0x7e, 0xd, 0x4b, 0x7, 0x65, 0x24, 0x43, 0x22,
1352 0x18, 0x1, 0x6f, 0xb, 0x5e, 0x9, 0x70, 0xb,
1353 0x2a, 0x3, 0x33, 0x4, 0x45, 0x6, 0x60, 0x9,
1354 0x7b, 0xc, 0x19, 0x1, 0x19, 0x1, 0x7d, 0xc,
1355 0x74, 0xb, 0x50, 0x7, 0x75, 0xb, 0x63, 0x9,
1356 0x51, 0x7, 0x23, 0x2, 0x3f, 0x5, 0x1a, 0x1,
1357 0x65, 0x9, 0x2d, 0x3, 0x40, 0x5, 0x0, 0x0,
1360 /* Console colors */
1361 unsigned char cvconscolors[16][3] = { /* background, foreground, hilite */
1381 /* -------------------- Hardware specific routines ------------------------- */
1383 /* Read Attribute Controller Register=idx */
1384 inline unsigned char RAttr (volatile unsigned char *regs, short idx)
1386 wb_64 (regs, ACT_ADDRESS_W, idx);
1389 return (rb_64(regs, ACT_ADDRESS_R));
1392 /* Read Sequencer Register=idx */
1393 inline unsigned char RSeq (volatile unsigned char *regs, short idx)
1395 wb_64 (regs, SEQ_ADDRESS, idx);
1397 return (rb_64(regs, SEQ_ADDRESS_R));
1400 /* Read CRT Controller Register=idx */
1401 inline unsigned char RCrt (volatile unsigned char *regs, short idx)
1403 wb_64 (regs, CRT_ADDRESS, idx);
1405 return (rb_64(regs, CRT_ADDRESS_R));
1408 /* Read Graphics Controller Register=idx */
1409 inline unsigned char RGfx (volatile unsigned char *regs, short idx)
1411 wb_64 (regs, GCT_ADDRESS, idx);
1413 return (rb_64(regs, GCT_ADDRESS_R));
1417 * Special wakeup/passthrough registers on graphics boards
1420 inline void cv64_write_port (unsigned short bits,
1421 volatile unsigned char *base)
1423 volatile unsigned char *addr;
1424 static unsigned char cvportbits = 0; /* Mirror port bits here */
1427 addr = base + 0x40001;
1428 if (bits & 0x8000) {
1429 cvportbits |= bits & 0xff; /* Set bits */
1430 DPRINTK("Set bits: %04x\n", bits);
1433 bits = (~bits) & 0xff;
1434 cvportbits &= bits; /* Clear bits */
1435 DPRINTK("Clear bits: %04x\n", bits);
1443 * Monitor switch on CyberVision board
1446 * 0 = CyberVision Signal
1448 * board = board addr
1451 inline void cvscreen (int toggle, volatile unsigned char *board)
1455 DPRINTK("Show Amiga video\n");
1456 cv64_write_port (0x10, board);
1458 DPRINTK("Show CyberVision video\n");
1459 cv64_write_port (0x8010, board);
1464 /* Control screen display */
1465 /* toggle: 0 = on, 1 = off */
1466 /* board = registerbase */
1467 inline void gfx_on_off(int toggle, volatile unsigned char *regs)
1473 toggle = toggle << 5;
1474 DPRINTK("Turn display %s\n", (toggle ? "off" : "on"));
1476 r = (int) RSeq(regs, SEQ_ID_CLOCKING_MODE);
1477 r &= 0xdf; /* Set bit 5 to 0 */
1479 WSeq (regs, SEQ_ID_CLOCKING_MODE, r | toggle);
1484 * Computes M, N, and R values from
1485 * given input frequency. It uses a table of
1486 * precomputed values, to keep CPU time low.
1488 * The return value consist of:
1489 * lower byte: Bits 4-0: N Divider Value
1490 * Bits 5-6: R Value for e.g. SR10 or SR12
1491 * higher byte: Bits 0-6: M divider value for e.g. SR11 or SR13
1493 static unsigned short cv64_compute_clock(unsigned long freq)
1495 static unsigned char *mnr, *save; /* M, N + R vals */
1496 unsigned long work_freq, r;
1501 if (freq < 12500000 || freq > MAXPIXELCLOCK) {
1502 printk("CV64 driver: Illegal clock frequency %ld, using 25MHz\n",
1506 DPRINTK("Freq = %ld\n", freq);
1507 mnr = clocks; /* there the vals are stored */
1510 while (*mnr) { /* mnr vals are 0-terminated */
1511 work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2);
1513 r = (mnr[1] >> 5) & 0x03;
1515 work_freq = work_freq >> r; /* r is the freq divider */
1518 work_freq *= 0x3E8; /* 2nd part of OSC */
1520 diff = abs(freq - work_freq);
1524 /* In save are the vals for minimal diff */
1529 erg = *((unsigned short *)save);
1535 static int cv_has_4mb (volatile unsigned char *fb)
1537 volatile unsigned long *tr, *tw;
1540 /* write patterns in memory and test if they can be read */
1541 tw = (volatile unsigned long *) fb;
1542 tr = (volatile unsigned long *) (fb + 0x02000000);
1546 if (*tr != 0x87654321) {
1547 DPRINTK("EXIT - <4MB\n");
1551 /* upper memory region */
1552 tw = (volatile unsigned long *) (fb + 0x00200000);
1553 tr = (volatile unsigned long *) (fb + 0x02200000);
1557 if (*tr != 0x87654321) {
1558 DPRINTK("EXIT - <4MB\n");
1564 if (*tr != 0xAAAAAAAA) {
1565 DPRINTK("EXIT - <4MB\n");
1571 if (*tr != 0x55555555) {
1572 DPRINTK("EXIT - <4MB\n");
1580 static void cv64_board_init (void)
1582 volatile unsigned char *regs = CyberRegs;
1584 unsigned int clockpar;
1590 * Special CyberVision 64 board operations
1593 for (i = 0; i < 6; i++) {
1594 cv64_write_port (0xff, CyberBase);
1596 /* Return to operational mode */
1597 cv64_write_port (0x8004, CyberBase);
1600 * Generic (?) S3 chip wakeup
1602 /* Disable I/O & memory decoders, video in setup mode */
1603 wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x10);
1604 /* Video responds to cmds, addrs & data */
1605 wb_64 (regs, SREG_OPTION_SELECT, 0x1);
1606 /* Enable I/O & memory decoders, video in operational mode */
1607 wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x8);
1608 /* VGA color emulation, enable cpu access to display mem */
1609 wb_64 (regs, GREG_MISC_OUTPUT_W, 0x03);
1610 /* Unlock S3 VGA regs */
1611 WCrt (regs, CRT_ID_REGISTER_LOCK_1, 0x48);
1612 /* Unlock system control & extension registers */
1613 WCrt (regs, CRT_ID_REGISTER_LOCK_2, 0xA5);
1614 /* GRF - Enable interrupts */
1615 /* Enable enhanced regs access, Ready cntl 0 wait states */
1616 test = RCrt (regs, CRT_ID_SYSTEM_CONFIG);
1617 test = test | 0x01; /* enable enhanced register access */
1618 test = test & 0xEF; /* clear bit 4, 0 wait state */
1619 WCrt (regs, CRT_ID_SYSTEM_CONFIG, test);
1621 * bit 0=1: Enable enhaced mode functions
1622 * bit 2=0: Enhanced mode 8+ bits/pixel
1623 * bit 4=1: Enable linear addressing
1624 * bit 5=1: Enable MMIO
1626 wb_64 (regs, ECR_ADV_FUNC_CNTL, 0x31);
1628 * bit 0=1: Color emulation
1629 * bit 1=1: Enable CPU access to display memory
1630 * bit 5=1: Select high 64K memory page
1633 wb_64 (regs, GREG_MISC_OUTPUT_W, 0x23);
1636 WCrt (regs, CRT_ID_EXT_SYS_CNTL_4, 0x0);
1638 /* Reset. This does nothing on Trio, but standard VGA practice */
1639 /* WSeq (CyberRegs, SEQ_ID_RESET, 0x03); */
1640 /* Character clocks 8 dots wide */
1641 WSeq (regs, SEQ_ID_CLOCKING_MODE, 0x01);
1642 /* Enable cpu write to all color planes */
1643 WSeq (regs, SEQ_ID_MAP_MASK, 0x0F);
1644 /* Font table in 1st 8k of plane 2, font A=B disables swtich */
1645 WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x0);
1646 /* Allow mem access to 256kb */
1647 WSeq (regs, SEQ_ID_MEMORY_MODE, 0x2);
1648 /* Unlock S3 extensions to VGA Sequencer regs */
1649 WSeq (regs, SEQ_ID_UNLOCK_EXT, 0x6);
1651 /* Enable 4MB fast page mode */
1652 test = RSeq (regs, SEQ_ID_BUS_REQ_CNTL);
1653 test = test | 1 << 6;
1654 WSeq (regs, SEQ_ID_BUS_REQ_CNTL, test);
1656 /* Faster LUT write: 1 DCLK LUT write cycle, RAMDAC clk doubled */
1657 WSeq (regs, SEQ_ID_RAMDAC_CNTL, 0xC0);
1659 /* Clear immediate clock load bit */
1660 test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
1662 /* If > 55MHz, enable 2 cycle memory write */
1663 if (cv64_memclk >= 55000000) {
1666 WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
1668 /* Set MCLK value */
1669 clockpar = cv64_compute_clock (cv64_memclk);
1670 test = (clockpar & 0xFF00) >> 8;
1671 WSeq (regs, SEQ_ID_MCLK_HI, test);
1672 test = clockpar & 0xFF;
1673 WSeq (regs, SEQ_ID_MCLK_LO, test);
1675 /* Chip rev specific: Not in my Trio manual!!! */
1676 if (RCrt (regs, CRT_ID_REVISION) == 0x10)
1677 WSeq (regs, SEQ_ID_MORE_MAGIC, test);
1679 /* We now load an 25 MHz, 31kHz, 640x480 standard VGA Mode. */
1681 /* Set DCLK value */
1682 WSeq (regs, SEQ_ID_DCLK_HI, 0x13);
1683 WSeq (regs, SEQ_ID_DCLK_LO, 0x41);
1685 /* Load DCLK (and MCLK?) immediately */
1686 test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
1688 WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
1690 /* Enable loading of DCLK */
1691 test = rb_64(regs, GREG_MISC_OUTPUT_R);
1693 wb_64 (regs, GREG_MISC_OUTPUT_W, test);
1695 /* Turn off immediate xCLK load */
1696 WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, 0x2);
1698 /* Horizontal character clock counts */
1699 /* 8 LSB of 9 bits = total line - 5 */
1700 WCrt (regs, CRT_ID_HOR_TOTAL, 0x5F);
1701 /* Active display line */
1702 WCrt (regs, CRT_ID_HOR_DISP_ENA_END, 0x4F);
1703 /* Blank assertion start */
1704 WCrt (regs, CRT_ID_START_HOR_BLANK, 0x50);
1705 /* Blank assertion end */
1706 WCrt (regs, CRT_ID_END_HOR_BLANK, 0x82);
1707 /* HSYNC assertion start */
1708 WCrt (regs, CRT_ID_START_HOR_RETR, 0x54);
1709 /* HSYNC assertion end */
1710 WCrt (regs, CRT_ID_END_HOR_RETR, 0x80);
1711 WCrt (regs, CRT_ID_VER_TOTAL, 0xBF);
1712 WCrt (regs, CRT_ID_OVERFLOW, 0x1F);
1713 WCrt (regs, CRT_ID_PRESET_ROW_SCAN, 0x0);
1714 WCrt (regs, CRT_ID_MAX_SCAN_LINE, 0x40);
1715 WCrt (regs, CRT_ID_CURSOR_START, 0x00);
1716 WCrt (regs, CRT_ID_CURSOR_END, 0x00);
1717 WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00);
1718 WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00);
1719 WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1720 WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
1721 WCrt (regs, CRT_ID_START_VER_RETR, 0x9C);
1722 WCrt (regs, CRT_ID_END_VER_RETR, 0x0E);
1723 WCrt (regs, CRT_ID_VER_DISP_ENA_END, 0x8F);
1724 WCrt (regs, CRT_ID_SCREEN_OFFSET, 0x50);
1725 WCrt (regs, CRT_ID_UNDERLINE_LOC, 0x00);
1726 WCrt (regs, CRT_ID_START_VER_BLANK, 0x96);
1727 WCrt (regs, CRT_ID_END_VER_BLANK, 0xB9);
1728 WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3);
1729 WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF);
1730 WCrt (regs, CRT_ID_BACKWAD_COMP_3, 0x10); /* FIFO enabled */
1731 WCrt (regs, CRT_ID_MISC_1, 0x35);
1732 WCrt (regs, CRT_ID_DISPLAY_FIFO, 0x5A);
1733 WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, 0x70);
1734 WCrt (regs, CRT_ID_LAW_POS_LO, 0x40);
1735 WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, 0xFF);
1737 WGfx (regs, GCT_ID_SET_RESET, 0x0);
1738 WGfx (regs, GCT_ID_ENABLE_SET_RESET, 0x0);
1739 WGfx (regs, GCT_ID_COLOR_COMPARE, 0x0);
1740 WGfx (regs, GCT_ID_DATA_ROTATE, 0x0);
1741 WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x0);
1742 WGfx (regs, GCT_ID_GRAPHICS_MODE, 0x40);
1743 WGfx (regs, GCT_ID_MISC, 0x01);
1744 WGfx (regs, GCT_ID_COLOR_XCARE, 0x0F);
1745 WGfx (regs, GCT_ID_BITMASK, 0xFF);
1747 /* Colors for text mode */
1748 for (i = 0; i < 0xf; i++)
1751 WAttr (regs, ACT_ID_ATTR_MODE_CNTL, 0x41);
1752 WAttr (regs, ACT_ID_OVERSCAN_COLOR, 0x01);
1753 WAttr (regs, ACT_ID_COLOR_PLANE_ENA, 0x0F);
1754 WAttr (regs, ACT_ID_HOR_PEL_PANNING, 0x0);
1755 WAttr (regs, ACT_ID_COLOR_SELECT, 0x0);
1757 wb_64 (regs, VDAC_MASK, 0xFF);
1759 *((unsigned long *) (regs + ECR_FRGD_COLOR)) = 0xFF;
1760 *((unsigned long *) (regs + ECR_BKGD_COLOR)) = 0;
1762 /* Colors initially set to grayscale */
1764 wb_64 (regs, VDAC_ADDRESS_W, 0);
1765 for (i = 255; i >= 0; i--) {
1766 wb_64(regs, VDAC_DATA, i);
1767 wb_64(regs, VDAC_DATA, i);
1768 wb_64(regs, VDAC_DATA, i);
1771 /* GFx hardware cursor off */
1772 WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
1774 /* Set first to 4MB, so test will work */
1775 WCrt (regs, CRT_ID_LAW_CNTL, 0x13);
1776 /* Find "correct" size of fbmem of Z3 board */
1777 if (cv_has_4mb (CyberMem)) {
1778 CyberSize = 1024 * 1024 * 4;
1779 WCrt (regs, CRT_ID_LAW_CNTL, 0x13);
1780 DPRINTK("4MB board\n");
1782 CyberSize = 1024 * 1024 * 2;
1783 WCrt (regs, CRT_ID_LAW_CNTL, 0x12);
1784 DPRINTK("2MB board\n");
1787 /* Initialize graphics engine */
1789 vgaw16 (regs, ECR_FRGD_MIX, 0x27);
1790 vgaw16 (regs, ECR_BKGD_MIX, 0x07);
1791 vgaw16 (regs, ECR_READ_REG_DATA, 0x1000);
1793 vgaw16 (regs, ECR_READ_REG_DATA, 0x2000);
1795 vgaw16 (regs, ECR_READ_REG_DATA, 0x3FFF);
1798 vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF);
1800 vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, ~0);
1802 vgaw16 (regs, ECR_READ_REG_DATA, 0xE000);
1803 vgaw16 (regs, ECR_CURRENT_Y_POS2, 0x00);
1804 vgaw16 (regs, ECR_CURRENT_X_POS2, 0x00);
1805 vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
1806 vgaw16 (regs, ECR_DEST_Y__AX_STEP, 0x00);
1807 vgaw16 (regs, ECR_DEST_Y2__AX_STEP2, 0x00);
1808 vgaw16 (regs, ECR_DEST_X__DIA_STEP, 0x00);
1809 vgaw16 (regs, ECR_DEST_X2__DIA_STEP2, 0x00);
1810 vgaw16 (regs, ECR_SHORT_STROKE, 0x00);
1811 vgaw16 (regs, ECR_DRAW_CMD, 0x01);
1815 vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF);
1816 vgaw16 (regs, ECR_BKGD_COLOR, 0x01);
1817 vgaw16 (regs, ECR_FRGD_COLOR, 0x00);
1820 /* Enable video display (set bit 5) */
1821 /* ARB - Would also seem to write to AR13.
1822 * May want to use parts of WAttr to set JUST bit 5
1824 WAttr (regs, 0x33, 0);
1826 /* GRF - function code ended here */
1828 /* Turn gfx on again */
1829 gfx_on_off (0, regs);
1832 cvscreen (0, CyberBase);
1837 static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
1839 volatile unsigned char *regs = CyberRegs;
1842 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, VSE, VT;
1843 char LACE, DBLSCAN, TEXT, CONSOLE;
1844 int cr50, sr15, sr18, clock_mode, test;
1846 int tfillm, temptym;
1849 /* ---------------- */
1850 int xres, hfront, hsync, hback;
1851 int yres, vfront, vsync, vback;
1857 /* ---------------- */
1860 TEXT = 0; /* if depth == 4 */
1861 CONSOLE = 0; /* mode num == 255 (console) */
1862 fx = fy = 8; /* force 8x8 font */
1864 /* GRF - Disable interrupts */
1866 gfx_on_off (1, regs);
1868 switch (video_mode->bits_per_pixel) {
1879 bpp = video_mode->bits_per_pixel;
1880 xres = video_mode->xres;
1881 hfront = video_mode->right_margin;
1882 hsync = video_mode->hsync_len;
1883 hback = video_mode->left_margin;
1888 if (video_mode->vmode & FB_VMODE_DOUBLE) {
1889 yres = video_mode->yres * 2;
1890 vfront = video_mode->lower_margin * 2;
1891 vsync = video_mode->vsync_len * 2;
1892 vback = video_mode->upper_margin * 2;
1894 } else if (video_mode->vmode & FB_VMODE_INTERLACED) {
1895 yres = (video_mode->yres + 1) / 2;
1896 vfront = (video_mode->lower_margin + 1) / 2;
1897 vsync = (video_mode->vsync_len + 1) / 2;
1898 vback = (video_mode->upper_margin + 1) / 2;
1901 yres = video_mode->yres;
1902 vfront = video_mode->lower_margin;
1903 vsync = video_mode->vsync_len;
1904 vback = video_mode->upper_margin;
1907 /* ARB Dropping custom setup method from cvision.c */
1909 if (cvision_custom_mode) {
1910 HBS = hbs / 8 * hmul;
1911 HBE = hbe / 8 * hmul;
1912 HSS = hss / 8 * hmul;
1913 HSE = hse / 8 * hmul;
1914 HT = ht / 8 * hmul - 5;
1925 HBS = hmul * (xres / 8);
1926 HBE = hmul * ((xres/8) + (hfront/8) + (hsync/8) + (hback/8) - 2);
1927 HSS = hmul * ((xres/8) + (hfront/8) + 2);
1928 HSE = hmul * ((xres/8) + (hfront/8) + (hsync/8) + 1);
1929 HT = hmul * ((xres/8) + (hfront/8) + (hsync/8) + (hback/8));
1932 VBE = yres + vfront + vsync + vback - 2;
1933 VSS = yres + vfront - 1;
1934 VSE = yres + vfront + vsync - 1;
1935 VT = yres + vfront + vsync + vback - 2;
1938 wb_64 (regs, ECR_ADV_FUNC_CNTL, (TEXT ? 0x00 : 0x31));
1941 HDE = ((video_mode->xres + fx - 1) / fx) - 1;
1943 HDE = (video_mode->xres + 3) * hmul / 8 - 1;
1945 VDE = video_mode->yres - 1;
1947 WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
1948 WCrt (regs, CRT_ID_EXT_DAC_CNTL, 0x00);
1950 WSeq (regs, SEQ_ID_MEMORY_MODE,
1951 (TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x0e);
1952 WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x00);
1953 WSeq (regs, SEQ_ID_MAP_MASK,
1954 (video_mode->bits_per_pixel == 1) ? 0x01 : 0xFF);
1955 WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1957 /* cv64_compute_clock accepts arguments in Hz */
1958 /* pixclock is in ps ... convert to Hz */
1961 freq_f = (1.0 / (float) video_mode->pixclock) * 1000000000;
1962 freq = ((long) freq_f) * 1000;
1964 /* freq = (long) ((long long)1000000000000 / (long long) video_mode->pixclock);
1966 freq = (1000000000 / video_mode->pixclock) * 1000;
1969 mnr = cv64_compute_clock (freq);
1970 WSeq (regs, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8));
1971 WSeq (regs, SEQ_ID_DCLK_LO, (mnr & 0xFF));
1973 /* Load display parameters into board */
1974 WCrt (regs, CRT_ID_EXT_HOR_OVF,
1975 ((HT & 0x100) ? 0x01 : 0x00) |
1976 ((HDE & 0x100) ? 0x02 : 0x00) |
1977 ((HBS & 0x100) ? 0x04 : 0x00) |
1978 /* ((HBE & 0x40) ? 0x08 : 0x00) | */
1979 ((HSS & 0x100) ? 0x10 : 0x00) |
1980 /* ((HSE & 0x20) ? 0x20 : 0x00) | */
1981 (((HT-5) & 0x100) ? 0x40 : 0x00)
1984 WCrt (regs, CRT_ID_EXT_VER_OVF,
1986 ((VT & 0x400) ? 0x01 : 0x00) |
1987 ((VDE & 0x400) ? 0x02 : 0x00) |
1988 ((VBS & 0x400) ? 0x04 : 0x00) |
1989 ((VSS & 0x400) ? 0x10 : 0x00)
1992 WCrt (regs, CRT_ID_HOR_TOTAL, HT);
1993 WCrt (regs, CRT_ID_DISPLAY_FIFO, HT - 5);
1994 WCrt (regs, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE));
1995 WCrt (regs, CRT_ID_START_HOR_BLANK, HBS);
1996 WCrt (regs, CRT_ID_END_HOR_BLANK, ((HBE & 0x1F) | 0x80));
1997 WCrt (regs, CRT_ID_START_HOR_RETR, HSS);
1998 WCrt (regs, CRT_ID_END_HOR_RETR,
2000 ((HBE & 0x20) ? 0x80 : 0x00)
2002 WCrt (regs, CRT_ID_VER_TOTAL, VT);
2003 WCrt (regs, CRT_ID_OVERFLOW,
2005 ((VT & 0x100) ? 0x01 : 0x00) |
2006 ((VDE & 0x100) ? 0x02 : 0x00) |
2007 ((VSS & 0x100) ? 0x04 : 0x00) |
2008 ((VBS & 0x100) ? 0x08 : 0x00) |
2009 ((VT & 0x200) ? 0x20 : 0x00) |
2010 ((VDE & 0x200) ? 0x40 : 0x00) |
2011 ((VSS & 0x200) ? 0x80 : 0x00)
2013 WCrt (regs, CRT_ID_MAX_SCAN_LINE,
2015 (DBLSCAN ? 0x80 : 0x00) |
2016 ((VBS & 0x200) ? 0x20 : 0x00) |
2017 (TEXT ? ((fy - 1) & 0x1F) : 0x00)
2020 WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3);
2026 WCrt (regs, CRT_ID_CURSOR_START, (fy & 0x1f) - 2);
2027 WCrt (regs, CRT_ID_CURSOR_END, (fy & 0x1F) - 1);
2029 WCrt (regs, CRT_ID_CURSOR_START, 0x00);
2030 WCrt (regs, CRT_ID_CURSOR_END, fy & 0x1F);
2032 WCrt (regs, CRT_ID_UNDERLINE_LOC, (fy - 1) & 0x1F);
2033 WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
2034 WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
2037 WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00);
2038 WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00);
2039 WCrt (regs, CRT_ID_START_VER_RETR, VSS);
2040 WCrt (regs, CRT_ID_END_VER_RETR, (VSE & 0x0F));
2041 WCrt (regs, CRT_ID_VER_DISP_ENA_END, VDE);
2042 WCrt (regs, CRT_ID_START_VER_BLANK, VBS);
2043 WCrt (regs, CRT_ID_END_VER_BLANK, VBE);
2044 WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF);
2045 WCrt (regs, CRT_ID_LACE_RETR_START, HT / 2);
2046 WCrt (regs, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00));
2047 WGfx (regs, GCT_ID_GRAPHICS_MODE,
2048 ((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x00 : 0x40));
2049 WGfx (regs, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
2050 WSeq (regs, SEQ_ID_MEMORY_MODE,
2051 ((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x02));
2053 wb_64 (regs, VDAC_MASK, 0xFF);
2056 test = RCrt (regs, CRT_ID_BACKWAD_COMP_2);
2057 WCrt (regs, CRT_ID_BACKWAD_COMP_2, (test | 0x20));
2059 sr15 = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
2061 sr18 = RSeq (regs, SEQ_ID_RAMDAC_CNTL);
2066 test = RCrt (regs, CRT_ID_EXT_MISC_CNTL_2);
2069 /* Clear roxxler byte-swapping... */
2070 cv64_write_port (0x0040, CyberBase);
2071 cv64_write_port (0x0020, CyberBase);
2073 switch (video_mode->bits_per_pixel) {
2076 HDE = video_mode->xres / 16;
2080 if (freq > 80000000) {
2081 clock_mode = 0x10 | 0x02;
2085 HDE = video_mode->xres / 8;
2090 cv64_write_port (0x8020, CyberBase);
2092 HDE = video_mode->xres / 4;
2097 cv64_write_port (0x8020, CyberBase);
2099 HDE = video_mode->xres / 4;
2105 cv64_write_port (0x8040, CyberBase);
2107 HDE = video_mode->xres / 2;
2112 WCrt (regs, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test);
2113 WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, sr15);
2114 WSeq (regs, SEQ_ID_RAMDAC_CNTL, sr18);
2115 WCrt (regs, CRT_ID_SCREEN_OFFSET, HDE);
2117 WCrt (regs, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35));
2119 test = RCrt (regs, CRT_ID_EXT_SYS_CNTL_2);
2121 test |= (HDE >> 4) & 0x30;
2122 WCrt (regs, CRT_ID_EXT_SYS_CNTL_2, test);
2124 /* Set up graphics engine */
2125 switch (video_mode->xres) {
2154 WCrt (regs, CRT_ID_EXT_SYS_CNTL_1, cr50);
2157 WAttr (regs, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41));
2159 WAttr (regs, ACT_ID_COLOR_PLANE_ENA,
2160 (video_mode->bits_per_pixel == 1) ? 0x01 : 0x0F);
2163 tfillm = (96 * (cv64_memclk / 1000)) / 240000;
2165 switch (video_mode->bits_per_pixel) {
2168 temptym = (24 * (cv64_memclk / 1000)) / (freq / 1000);
2172 temptym = (48 * (cv64_memclk / 1000)) / (freq / 1000);
2175 temptym = (192 * (cv64_memclk / 1000)) / (freq / 1000);
2178 temptym = (96 * (cv64_memclk / 1000)) / (freq / 1000);
2182 m = (temptym - tfillm - 9) / 2;
2185 m = (m & 0x1F) << 3;
2190 WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, m);
2191 WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, n);
2194 /* Text initialization */
2197 /* Do text initialization here ! */
2202 wb_64 (regs, VDAC_ADDRESS_W, 0);
2203 for (i = 0; i < 4; i++) {
2204 wb_64 (regs, VDAC_DATA, cvconscolors [i][0]);
2205 wb_64 (regs, VDAC_DATA, cvconscolors [i][1]);
2206 wb_64 (regs, VDAC_DATA, cvconscolors [i][2]);
2210 WAttr (regs, 0x33, 0);
2212 /* Turn gfx on again */
2213 gfx_on_off (0, (volatile unsigned char *) regs);
2216 cvscreen (0, CyberBase);
2221 void cvision_bitblt (u_short sx, u_short sy, u_short dx, u_short dy,
2222 u_short w, u_short h)
2224 volatile unsigned char *regs = CyberRegs;
2225 unsigned short drawdir = 0;
2243 vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
2244 vgaw16 (regs, ECR_BKGD_MIX, 0x7);
2245 vgaw16 (regs, ECR_FRGD_MIX, 0x67);
2246 vgaw16 (regs, ECR_BKGD_COLOR, 0x0);
2247 vgaw16 (regs, ECR_FRGD_COLOR, 0x1);
2248 vgaw16 (regs, ECR_BITPLANE_READ_MASK, 0x1);
2249 vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, 0xFFF);
2250 vgaw16 (regs, ECR_CURRENT_Y_POS, sy);
2251 vgaw16 (regs, ECR_CURRENT_X_POS, sx);
2252 vgaw16 (regs, ECR_DEST_Y__AX_STEP, dy);
2253 vgaw16 (regs, ECR_DEST_X__DIA_STEP, dx);
2254 vgaw16 (regs, ECR_READ_REG_DATA, h - 1);
2255 vgaw16 (regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
2256 vgaw16 (regs, ECR_DRAW_CMD, 0xC051 | drawdir);
2260 void cvision_clear (u_short dx, u_short dy, u_short w, u_short h, u_short bg)
2262 volatile unsigned char *regs = CyberRegs;
2265 vgaw16 (regs, ECR_FRGD_MIX, 0x0027);
2266 vgaw16 (regs, ECR_FRGD_COLOR, bg);
2267 vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
2268 vgaw16 (regs, ECR_CURRENT_Y_POS, dy);
2269 vgaw16 (regs, ECR_CURRENT_X_POS, dx);
2270 vgaw16 (regs, ECR_READ_REG_DATA, h - 1);
2271 vgaw16 (regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
2272 vgaw16 (regs, ECR_DRAW_CMD, 0x40B1);
2278 * Dump internal settings of CyberVision board
2280 static void cv64_dump (void)
2282 volatile unsigned char *regs = CyberRegs;
2284 /* Dump the VGA setup values */
2285 *(regs + S3_CRTC_ADR) = 0x00;
2286 DPRINTK("CR00 = %x\n", *(regs + S3_CRTC_DATA));
2287 *(regs + S3_CRTC_ADR) = 0x01;
2288 DPRINTK("CR01 = %x\n", *(regs + S3_CRTC_DATA));
2289 *(regs + S3_CRTC_ADR) = 0x02;
2290 DPRINTK("CR02 = %x\n", *(regs + S3_CRTC_DATA));
2291 *(regs + S3_CRTC_ADR) = 0x03;
2292 DPRINTK("CR03 = %x\n", *(regs + S3_CRTC_DATA));
2293 *(regs + S3_CRTC_ADR) = 0x04;
2294 DPRINTK("CR04 = %x\n", *(regs + S3_CRTC_DATA));
2295 *(regs + S3_CRTC_ADR) = 0x05;
2296 DPRINTK("CR05 = %x\n", *(regs + S3_CRTC_DATA));
2297 *(regs + S3_CRTC_ADR) = 0x06;
2298 DPRINTK("CR06 = %x\n", *(regs + S3_CRTC_DATA));
2299 *(regs + S3_CRTC_ADR) = 0x07;
2300 DPRINTK("CR07 = %x\n", *(regs + S3_CRTC_DATA));
2301 *(regs + S3_CRTC_ADR) = 0x08;
2302 DPRINTK("CR08 = %x\n", *(regs + S3_CRTC_DATA));
2303 *(regs + S3_CRTC_ADR) = 0x09;
2304 DPRINTK("CR09 = %x\n", *(regs + S3_CRTC_DATA));
2305 *(regs + S3_CRTC_ADR) = 0x10;
2306 DPRINTK("CR10 = %x\n", *(regs + S3_CRTC_DATA));
2307 *(regs + S3_CRTC_ADR) = 0x11;
2308 DPRINTK("CR11 = %x\n", *(regs + S3_CRTC_DATA));
2309 *(regs + S3_CRTC_ADR) = 0x12;
2310 DPRINTK("CR12 = %x\n", *(regs + S3_CRTC_DATA));
2311 *(regs + S3_CRTC_ADR) = 0x13;
2312 DPRINTK("CR13 = %x\n", *(regs + S3_CRTC_DATA));
2313 *(regs + S3_CRTC_ADR) = 0x15;
2314 DPRINTK("CR15 = %x\n", *(regs + S3_CRTC_DATA));
2315 *(regs + S3_CRTC_ADR) = 0x16;
2316 DPRINTK("CR16 = %x\n", *(regs + S3_CRTC_DATA));
2317 *(regs + S3_CRTC_ADR) = 0x36;
2318 DPRINTK("CR36 = %x\n", *(regs + S3_CRTC_DATA));
2319 *(regs + S3_CRTC_ADR) = 0x37;
2320 DPRINTK("CR37 = %x\n", *(regs + S3_CRTC_DATA));
2321 *(regs + S3_CRTC_ADR) = 0x42;
2322 DPRINTK("CR42 = %x\n", *(regs + S3_CRTC_DATA));
2323 *(regs + S3_CRTC_ADR) = 0x43;
2324 DPRINTK("CR43 = %x\n", *(regs + S3_CRTC_DATA));
2325 *(regs + S3_CRTC_ADR) = 0x50;
2326 DPRINTK("CR50 = %x\n", *(regs + S3_CRTC_DATA));
2327 *(regs + S3_CRTC_ADR) = 0x51;
2328 DPRINTK("CR51 = %x\n", *(regs + S3_CRTC_DATA));
2329 *(regs + S3_CRTC_ADR) = 0x53;
2330 DPRINTK("CR53 = %x\n", *(regs + S3_CRTC_DATA));
2331 *(regs + S3_CRTC_ADR) = 0x58;
2332 DPRINTK("CR58 = %x\n", *(regs + S3_CRTC_DATA));
2333 *(regs + S3_CRTC_ADR) = 0x59;
2334 DPRINTK("CR59 = %x\n", *(regs + S3_CRTC_DATA));
2335 *(regs + S3_CRTC_ADR) = 0x5A;
2336 DPRINTK("CR5A = %x\n", *(regs + S3_CRTC_DATA));
2337 *(regs + S3_CRTC_ADR) = 0x5D;
2338 DPRINTK("CR5D = %x\n", *(regs + S3_CRTC_DATA));
2339 *(regs + S3_CRTC_ADR) = 0x5E;
2340 DPRINTK("CR5E = %x\n", *(regs + S3_CRTC_DATA));
2341 DPRINTK("MISC = %x\n", *(regs + GREG_MISC_OUTPUT_R));
2342 *(regs + SEQ_ADDRESS) = 0x01;
2343 DPRINTK("SR01 = %x\n", *(regs + SEQ_ADDRESS_R));
2344 *(regs + SEQ_ADDRESS) = 0x02;
2345 DPRINTK("SR02 = %x\n", *(regs + SEQ_ADDRESS_R));
2346 *(regs + SEQ_ADDRESS) = 0x03;
2347 DPRINTK("SR03 = %x\n", *(regs + SEQ_ADDRESS_R));
2348 *(regs + SEQ_ADDRESS) = 0x09;
2349 DPRINTK("SR09 = %x\n", *(regs + SEQ_ADDRESS_R));
2350 *(regs + SEQ_ADDRESS) = 0x10;
2351 DPRINTK("SR10 = %x\n", *(regs + SEQ_ADDRESS_R));
2352 *(regs + SEQ_ADDRESS) = 0x11;
2353 DPRINTK("SR11 = %x\n", *(regs + SEQ_ADDRESS_R));
2354 *(regs + SEQ_ADDRESS) = 0x12;
2355 DPRINTK("SR12 = %x\n", *(regs + SEQ_ADDRESS_R));
2356 *(regs + SEQ_ADDRESS) = 0x13;
2357 DPRINTK("SR13 = %x\n", *(regs + SEQ_ADDRESS_R));
2358 *(regs + SEQ_ADDRESS) = 0x15;
2359 DPRINTK("SR15 = %x\n", *(regs + SEQ_ADDRESS_R));