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/tty.h>
85 #include <linux/slab.h>
86 #include <linux/delay.h>
87 #include <linux/zorro.h>
89 #include <linux/init.h>
90 #include <asm/uaccess.h>
91 #include <asm/system.h>
93 #include <asm/pgtable.h>
94 #include <asm/amigahw.h>
98 #include <video/fbcon.h>
99 #include <video/fbcon-cfb8.h>
100 #include <video/fbcon-cfb16.h>
102 /*#define CYBERFBDEBUG*/
104 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
105 static void cv64_dump(void);
107 #define DPRINTK(fmt, args...)
110 #define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat)
111 #define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg))
113 #define ww_64(regs,reg,dat) (*((volatile unsigned short *)(regs + reg) = dat)
116 struct fb_var_screeninfo var;
123 static struct cyberfb_par current_par;
125 static int current_par_valid = 0;
127 static struct display disp;
128 static struct fb_info fb_info;
135 static char cyberfb_name[16] = "Cybervision";
139 * CyberVision Graphics Board
142 static unsigned char Cyber_colour_table [256][3];
143 static unsigned long CyberSize;
144 static volatile unsigned char *CyberBase;
145 static volatile unsigned char *CyberMem;
146 static volatile unsigned char *CyberRegs;
147 static unsigned long CyberMem_phys;
148 static unsigned long CyberRegs_phys;
151 * Predefined Video Modes
156 struct fb_var_screeninfo var;
157 } cyberfb_predefined[] __initdata = {
158 { "640x480-8", { /* Default 8 BPP mode (cyber8) */
159 640, 480, 640, 480, 0, 0, 8, 0,
160 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
161 0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
162 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
163 FB_VMODE_NONINTERLACED
165 { "640x480-16", { /* Default 16 BPP mode (cyber16) */
166 640, 480, 640, 480, 0, 0, 16, 0,
167 {11, 5, 0}, {5, 6, 0}, {0, 5, 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-24", { /* Default 24 BPP mode */
173 640, 480, 640, 480, 0, 0, 24, 0,
174 {16, 8, 0}, {8, 8, 0}, {0, 8, 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 { "800x490-8", { /* Cybervision 8 bpp */
180 /* NO Acceleration */
181 800, 490, 800, 490, 0, 0, 8, 0,
182 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
183 0, 0, -1, -1, FB_ACCEL_NONE, 33333, 80, 24, 23, 1, 56, 8,
184 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
185 FB_VMODE_NONINTERLACED
187 /* I can't test these with my monitor, but I suspect they will
188 * be OK, since Antonio Santos indicated he had tested them in
191 { "800x600-8", { /* Cybervision 8 bpp */
192 800, 600, 800, 600, 0, 0, 8, 0,
193 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
194 0, 0, -1, -1, FB_ACCELF_TEXT, 27778, 64, 24, 22, 1, 72, 2,
195 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
196 FB_VMODE_NONINTERLACED
198 { "1024x768-8", { /* Cybervision 8 bpp */
199 1024, 768, 1024, 768, 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, 16667, 224, 72, 60, 12, 168, 4,
202 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
203 FB_VMODE_NONINTERLACED
205 { "1152x886-8", { /* Cybervision 8 bpp */
206 1152, 886, 1152, 886, 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, 15873, 184, 40, 24, 1, 56, 16,
209 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
210 FB_VMODE_NONINTERLACED
212 { "1280x1024-8", { /* Cybervision 8 bpp */
213 1280, 1024, 1280, 1024, 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, 16667, 256, 48, 50, 12, 72, 4,
216 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
221 #define NUM_TOTAL_MODES ARRAY_SIZE(cyberfb_predefined)
223 static int Cyberfb_inverse = 0;
229 #define CYBER8_DEFMODE (0)
230 #define CYBER16_DEFMODE (1)
232 static struct fb_var_screeninfo cyberfb_default;
233 static int cyberfb_usermode __initdata = 0;
236 * Interface used by the world
239 int cyberfb_setup(char *options);
241 static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
242 struct fb_info *info);
243 static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
244 struct fb_info *info);
245 static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
246 struct fb_info *info);
247 static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
248 struct fb_info *info);
249 static int cyberfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
250 u_int transp, struct fb_info *info);
251 static int cyberfb_blank(int blank, struct fb_info *info);
254 * Interface to the low level console driver
257 int cyberfb_init(void);
258 static int Cyberfb_switch(int con, struct fb_info *info);
259 static int Cyberfb_updatevar(int con, struct fb_info *info);
262 * Text console acceleration
265 #ifdef FBCON_HAS_CFB8
266 static struct display_switch fbcon_cyber8;
270 * Accelerated Functions used by the low level console driver
273 static void Cyber_WaitQueue(u_short fifo);
274 static void Cyber_WaitBlit(void);
275 static void Cyber_BitBLT(u_short curx, u_short cury, u_short destx,
276 u_short desty, u_short width, u_short height,
278 static void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height,
279 u_short mode, u_short color);
281 static void Cyber_MoveCursor(u_short x, u_short y);
285 * Hardware Specific Routines
288 static int Cyber_init(void);
289 static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
290 struct cyberfb_par *par);
291 static int Cyber_decode_var(struct fb_var_screeninfo *var,
292 struct cyberfb_par *par);
293 static int Cyber_encode_var(struct fb_var_screeninfo *var,
294 struct cyberfb_par *par);
295 static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
296 u_int *transp, struct fb_info *info);
302 static void cyberfb_get_par(struct cyberfb_par *par);
303 static void cyberfb_set_par(struct cyberfb_par *par);
304 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
305 static void cyberfb_set_disp(int con, struct fb_info *info);
306 static int get_video_mode(const char *name);
308 /* For cvision_core.c */
309 static unsigned short cv64_compute_clock(unsigned long);
310 static int cv_has_4mb (volatile unsigned char *);
311 static void cv64_board_init (void);
312 static void cv64_load_video_mode (struct fb_var_screeninfo *);
315 /* -------------------- Hardware specific routines ------------------------- */
321 * Set the default video mode for this chipset. If a video mode was
322 * specified on the command line, it will override the default mode.
325 static int Cyber_init(void)
327 volatile unsigned char *regs = CyberRegs;
328 volatile unsigned long *CursorBase;
332 /* Init local cmap as greyscale levels */
333 for (i = 0; i < 256; i++) {
334 Cyber_colour_table [i][0] = i;
335 Cyber_colour_table [i][1] = i;
336 Cyber_colour_table [i][2] = i;
339 /* Initialize the board and determine fbmem size */
342 DPRINTK("Register state after initing board\n");
345 /* Clear framebuffer memory */
346 DPRINTK("Clear framebuffer memory\n");
347 memset ((char *)CyberMem, 0, CyberSize);
349 /* Disable hardware cursor */
350 DPRINTK("Disable HW cursor\n");
351 wb_64(regs, S3_CRTC_ADR, S3_REG_LOCK2);
352 wb_64(regs, S3_CRTC_DATA, 0xa0);
353 wb_64(regs, S3_CRTC_ADR, S3_HGC_MODE);
354 wb_64(regs, S3_CRTC_DATA, 0x00);
355 wb_64(regs, S3_CRTC_ADR, S3_HWGC_DX);
356 wb_64(regs, S3_CRTC_DATA, 0x00);
357 wb_64(regs, S3_CRTC_ADR, S3_HWGC_DY);
358 wb_64(regs, S3_CRTC_DATA, 0x00);
360 /* Initialize hardware cursor */
361 DPRINTK("Init HW cursor\n");
362 CursorBase = (u_long *)((char *)(CyberMem) + CyberSize - 0x400);
363 for (i=0; i < 8; i++)
365 *(CursorBase +(i*4)) = 0xffffff00;
366 *(CursorBase+1+(i*4)) = 0xffff0000;
367 *(CursorBase+2+(i*4)) = 0xffff0000;
368 *(CursorBase+3+(i*4)) = 0xffff0000;
370 for (i=8; i < 64; i++)
372 *(CursorBase +(i*4)) = 0xffff0000;
373 *(CursorBase+1+(i*4)) = 0xffff0000;
374 *(CursorBase+2+(i*4)) = 0xffff0000;
375 *(CursorBase+3+(i*4)) = 0xffff0000;
378 cyberfb_setcolreg (255, 56<<8, 100<<8, 160<<8, 0, NULL /* unused */);
379 cyberfb_setcolreg (254, 0, 0, 0, 0, NULL /* unused */);
387 * This function should fill in the `fix' structure based on the
388 * values in the `par' structure.
391 static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
392 struct cyberfb_par *par)
395 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
396 strcpy(fix->id, cyberfb_name);
397 fix->smem_start = CyberMem_phys;
398 fix->smem_len = CyberSize;
399 fix->mmio_start = CyberRegs_phys;
400 fix->mmio_len = 0x10000;
402 fix->type = FB_TYPE_PACKED_PIXELS;
404 if (par->var.bits_per_pixel == 15 || par->var.bits_per_pixel == 16 ||
405 par->var.bits_per_pixel == 24 || par->var.bits_per_pixel == 32) {
406 fix->visual = FB_VISUAL_DIRECTCOLOR;
408 fix->visual = FB_VISUAL_PSEUDOCOLOR;
414 fix->line_length = 0;
415 fix->accel = FB_ACCEL_S3_TRIO64;
423 * Fill the `par' structure based on the values in `var'.
424 * TODO: Verify and adjust values, return -EINVAL if bad.
427 static int Cyber_decode_var(struct fb_var_screeninfo *var,
428 struct cyberfb_par *par)
431 par->var.xres = var->xres;
432 par->var.yres = var->yres;
433 par->var.xres_virtual = var->xres_virtual;
434 par->var.yres_virtual = var->yres_virtual;
435 par->var.xoffset = var->xoffset;
436 par->var.yoffset = var->yoffset;
437 par->var.bits_per_pixel = var->bits_per_pixel;
438 par->var.grayscale = var->grayscale;
439 par->var.red = var->red;
440 par->var.green = var->green;
441 par->var.blue = var->blue;
442 par->var.transp = var->transp;
443 par->var.nonstd = var->nonstd;
444 par->var.activate = var->activate;
445 par->var.height = var->height;
446 par->var.width = var->width;
447 if (var->accel_flags & FB_ACCELF_TEXT) {
448 par->var.accel_flags = FB_ACCELF_TEXT;
450 par->var.accel_flags = 0;
452 par->var.pixclock = var->pixclock;
453 par->var.left_margin = var->left_margin;
454 par->var.right_margin = var->right_margin;
455 par->var.upper_margin = var->upper_margin;
456 par->var.lower_margin = var->lower_margin;
457 par->var.hsync_len = var->hsync_len;
458 par->var.vsync_len = var->vsync_len;
459 par->var.sync = var->sync;
460 par->var.vmode = var->vmode;
466 * Fill the `var' structure based on the values in `par' and maybe
467 * other values read out of the hardware.
470 static int Cyber_encode_var(struct fb_var_screeninfo *var,
471 struct cyberfb_par *par)
474 var->xres = par->var.xres;
475 var->yres = par->var.yres;
476 var->xres_virtual = par->var.xres_virtual;
477 var->yres_virtual = par->var.yres_virtual;
478 var->xoffset = par->var.xoffset;
479 var->yoffset = par->var.yoffset;
481 var->bits_per_pixel = par->var.bits_per_pixel;
482 var->grayscale = par->var.grayscale;
484 var->red = par->var.red;
485 var->green = par->var.green;
486 var->blue = par->var.blue;
487 var->transp = par->var.transp;
489 var->nonstd = par->var.nonstd;
490 var->activate = par->var.activate;
492 var->height = par->var.height;
493 var->width = par->var.width;
495 var->accel_flags = par->var.accel_flags;
497 var->pixclock = par->var.pixclock;
498 var->left_margin = par->var.left_margin;
499 var->right_margin = par->var.right_margin;
500 var->upper_margin = par->var.upper_margin;
501 var->lower_margin = par->var.lower_margin;
502 var->hsync_len = par->var.hsync_len;
503 var->vsync_len = par->var.vsync_len;
504 var->sync = par->var.sync;
505 var->vmode = par->var.vmode;
513 * Set a single color register. Return != 0 for invalid regno.
516 static int cyberfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
517 u_int transp, struct fb_info *info)
519 volatile unsigned char *regs = CyberRegs;
521 /*DPRINTK("ENTER\n");*/
523 DPRINTK("EXIT - Register # > 255\n");
527 wb_64(regs, 0x3c8, (unsigned char) regno);
533 Cyber_colour_table [regno][0] = red;
534 Cyber_colour_table [regno][1] = green;
535 Cyber_colour_table [regno][2] = blue;
537 wb_64(regs, 0x3c9, red);
538 wb_64(regs, 0x3c9, green);
539 wb_64(regs, 0x3c9, blue);
541 /*DPRINTK("EXIT\n");*/
547 * Read a single color register and split it into
548 * colors/transparent. Return != 0 for invalid regno.
551 static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
552 u_int *transp, struct fb_info *info)
556 /*DPRINTK("ENTER\n");*/
558 DPRINTK("EXIT - Register # > 255\n");
561 /* ARB This shifting & oring seems VERY strange */
562 t = Cyber_colour_table [regno][0];
563 *red = (t<<10) | (t<<4) | (t>>2);
564 t = Cyber_colour_table [regno][1];
565 *green = (t<<10) | (t<<4) | (t>>2);
566 t = Cyber_colour_table [regno][2];
567 *blue = (t<<10) | (t<<4) | (t>>2);
569 /*DPRINTK("EXIT\n");*/
575 * (Un)Blank the screen
576 * blank: 1 = zero fb cmap
577 * 0 = restore fb cmap from local cmap
579 static int cyberfb_blank(int blank, struct fb_info *info)
581 volatile unsigned char *regs = CyberRegs;
586 /* Blank by turning gfx off */
587 gfx_on_off (1, regs);
590 for (i = 0; i < 256; i++) {
591 wb_64(regs, 0x3c8, (unsigned char) i);
592 /* ARB Pale red to detect this blanking method */
593 wb_64(regs, 0x3c9, 48);
594 wb_64(regs, 0x3c9, 0);
595 wb_64(regs, 0x3c9, 0);
598 for (i = 0; i < 256; i++) {
599 wb_64(regs, 0x3c8, (unsigned char) i);
600 wb_64(regs, 0x3c9, Cyber_colour_table[i][0]);
601 wb_64(regs, 0x3c9, Cyber_colour_table[i][1]);
602 wb_64(regs, 0x3c9, Cyber_colour_table[i][2]);
611 /**************************************************************
612 * We are waiting for "fifo" FIFO-slots empty
614 static void Cyber_WaitQueue (u_short fifo)
616 unsigned short status;
620 status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
621 } while (status & fifo);
625 /**************************************************************
626 * We are waiting for Hardware (Graphics Engine) not busy
628 static void Cyber_WaitBlit (void)
630 unsigned short status;
634 status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
635 } while (status & S3_HDW_BUSY);
639 /**************************************************************
640 * BitBLT - Through the Plane
642 static void Cyber_BitBLT (u_short curx, u_short cury, u_short destx,
643 u_short desty, u_short width, u_short height,
646 volatile unsigned char *regs = CyberRegs;
647 u_short blitcmd = S3_BITBLT;
650 /* Set drawing direction */
651 /* -Y, X maj, -X (default) */
653 blitcmd |= 0x0020; /* Drawing direction +X */
656 destx += (width - 1);
660 blitcmd |= 0x0080; /* Drawing direction +Y */
662 cury += (height - 1);
663 desty += (height - 1);
666 Cyber_WaitQueue (0x8000);
668 *((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
669 *((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0060 | mode);
671 *((u_short volatile *)(regs + S3_CUR_X)) = curx;
672 *((u_short volatile *)(regs + S3_CUR_Y)) = cury;
674 *((u_short volatile *)(regs + S3_DESTX_DIASTP)) = destx;
675 *((u_short volatile *)(regs + S3_DESTY_AXSTP)) = desty;
677 *((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
678 *((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width - 1;
680 *((u_short volatile *)(regs + S3_CMD)) = blitcmd;
684 /**************************************************************
685 * Rectangle Fill Solid
687 static void Cyber_RectFill (u_short x, u_short y, u_short width,
688 u_short height, u_short mode, u_short color)
690 volatile unsigned char *regs = CyberRegs;
691 u_short blitcmd = S3_FILLEDRECT;
694 Cyber_WaitQueue (0x8000);
696 *((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
697 *((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0020 | mode);
699 *((u_short volatile *)(regs + S3_MULT_MISC)) = 0xe000;
700 *((u_short volatile *)(regs + S3_FRGD_COLOR)) = color;
702 *((u_short volatile *)(regs + S3_CUR_X)) = x;
703 *((u_short volatile *)(regs + S3_CUR_Y)) = y;
705 *((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
706 *((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width - 1;
708 *((u_short volatile *)(regs + S3_CMD)) = blitcmd;
714 /**************************************************************
715 * Move cursor to x, y
717 static void Cyber_MoveCursor (u_short x, u_short y)
719 volatile unsigned char *regs = CyberRegs;
721 *(regs + S3_CRTC_ADR) = 0x39;
722 *(regs + S3_CRTC_DATA) = 0xa0;
724 *(regs + S3_CRTC_ADR) = S3_HWGC_ORGX_H;
725 *(regs + S3_CRTC_DATA) = (char)((x & 0x0700) >> 8);
726 *(regs + S3_CRTC_ADR) = S3_HWGC_ORGX_L;
727 *(regs + S3_CRTC_DATA) = (char)(x & 0x00ff);
729 *(regs + S3_CRTC_ADR) = S3_HWGC_ORGY_H;
730 *(regs + S3_CRTC_DATA) = (char)((y & 0x0700) >> 8);
731 *(regs + S3_CRTC_ADR) = S3_HWGC_ORGY_L;
732 *(regs + S3_CRTC_DATA) = (char)(y & 0x00ff);
738 /* -------------------- Generic routines ---------------------------------- */
742 * Fill the hardware's `par' structure.
745 static void cyberfb_get_par(struct cyberfb_par *par)
748 if (current_par_valid) {
751 Cyber_decode_var(&cyberfb_default, par);
757 static void cyberfb_set_par(struct cyberfb_par *par)
761 current_par_valid = 1;
766 static void cyber_set_video(struct fb_var_screeninfo *var)
769 /* Load the video mode defined by the 'var' data */
770 cv64_load_video_mode (var);
772 DPRINTK("Register state after loading video mode\n");
778 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
781 struct cyberfb_par par;
784 if ((err = Cyber_decode_var(var, &par))) {
785 DPRINTK("EXIT - decode_var failed\n");
788 activate = var->activate;
789 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
790 cyberfb_set_par(&par);
791 Cyber_encode_var(var, &par);
792 var->activate = activate;
794 cyber_set_video(var);
800 * Get the Fixed Part of the Display
803 static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
804 struct fb_info *info)
806 struct cyberfb_par par;
811 cyberfb_get_par(&par);
813 error = Cyber_decode_var(&fb_display[con].var, &par);
816 return(error ? error : Cyber_encode_fix(fix, &par));
821 * Get the User Defined Part of the Display
824 static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
825 struct fb_info *info)
827 struct cyberfb_par par;
832 cyberfb_get_par(&par);
833 error = Cyber_encode_var(var, &par);
834 disp.var = *var; /* ++Andre: don't know if this is the right place */
836 *var = fb_display[con].var;
844 static void cyberfb_set_disp(int con, struct fb_info *info)
846 struct fb_fix_screeninfo fix;
847 struct display *display;
851 display = &fb_display[con];
853 display = &disp; /* used during initialization */
855 cyberfb_get_fix(&fix, con, info);
858 display->visual = fix.visual;
859 display->type = fix.type;
860 display->type_aux = fix.type_aux;
861 display->ypanstep = fix.ypanstep;
862 display->ywrapstep = fix.ywrapstep;
863 display->can_soft_blank = 1;
864 display->inverse = Cyberfb_inverse;
865 switch (display->var.bits_per_pixel) {
866 #ifdef FBCON_HAS_CFB8
868 if (display->var.accel_flags & FB_ACCELF_TEXT) {
869 display->dispsw = &fbcon_cyber8;
870 #warning FIXME: We should reinit the graphics engine here
872 display->dispsw = &fbcon_cfb8;
875 #ifdef FBCON_HAS_CFB16
877 display->dispsw = &fbcon_cfb16;
881 display->dispsw = NULL;
889 * Set the User Defined Part of the Display
892 static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
893 struct fb_info *info)
895 int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
898 if ((err = do_fb_set_var(var, con == info->currcon))) {
899 DPRINTK("EXIT - do_fb_set_var failed\n");
902 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
903 oldxres = fb_display[con].var.xres;
904 oldyres = fb_display[con].var.yres;
905 oldvxres = fb_display[con].var.xres_virtual;
906 oldvyres = fb_display[con].var.yres_virtual;
907 oldbpp = fb_display[con].var.bits_per_pixel;
908 oldaccel = fb_display[con].var.accel_flags;
909 fb_display[con].var = *var;
910 if (oldxres != var->xres || oldyres != var->yres ||
911 oldvxres != var->xres_virtual ||
912 oldvyres != var->yres_virtual ||
913 oldbpp != var->bits_per_pixel ||
914 oldaccel != var->accel_flags) {
915 cyberfb_set_disp(con, info);
916 (*fb_info.changevar)(con);
917 fb_alloc_cmap(&fb_display[con].cmap, 0, 0);
918 do_install_cmap(con, info);
931 static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
932 struct fb_info *info)
935 if (con == info->currcon) { /* current console? */
936 DPRINTK("EXIT - console is current console\n");
937 return(fb_get_cmap(cmap, kspc, Cyber_getcolreg, info));
938 } else if (fb_display[con].cmap.len) { /* non default colormap? */
939 DPRINTK("Use console cmap\n");
940 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
942 DPRINTK("Use default cmap\n");
943 fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
950 static struct fb_ops cyberfb_ops = {
951 .owner = THIS_MODULE,
952 .fb_get_fix = cyberfb_get_fix,
953 .fb_get_var = cyberfb_get_var,
954 .fb_set_var = cyberfb_set_var,
955 .fb_get_cmap = cyberfb_get_cmap,
956 .fb_set_cmap = gen_set_cmap,
957 .fb_setcolreg = cyberfb_setcolreg,
958 .fb_blank = cyberfb_blank,
961 int __init cyberfb_setup(char *options)
966 fb_info.fontname[0] = '\0';
968 if (!options || !*options) {
969 DPRINTK("EXIT - no options\n");
973 while ((this_opt = strsep(&options, ",")) != NULL) {
976 if (!strcmp(this_opt, "inverse")) {
979 } else if (!strncmp(this_opt, "font:", 5)) {
980 strcpy(fb_info.fontname, this_opt+5);
981 } else if (!strcmp (this_opt, "cyber8")) {
982 cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
983 cyberfb_usermode = 1;
984 } else if (!strcmp (this_opt, "cyber16")) {
985 cyberfb_default = cyberfb_predefined[CYBER16_DEFMODE].var;
986 cyberfb_usermode = 1;
987 } else get_video_mode(this_opt);
990 DPRINTK("default mode: xres=%d, yres=%d, bpp=%d\n",
991 cyberfb_default.xres,
992 cyberfb_default.yres,
993 cyberfb_default.bits_per_pixel);
1002 int __init cyberfb_init(void)
1004 unsigned long board_addr, board_size;
1005 struct cyberfb_par par;
1006 struct zorro_dev *z = NULL;
1009 while ((z = zorro_find_device(ZORRO_PROD_PHASE5_CYBERVISION64, z))) {
1010 board_addr = z->resource.start;
1011 board_size = z->resource.end-z->resource.start+1;
1012 CyberMem_phys = board_addr + 0x01400000;
1013 CyberRegs_phys = CyberMem_phys + 0x00c00000;
1014 if (!request_mem_region(CyberRegs_phys, 0x10000, "S3 Trio64"))
1016 if (!request_mem_region(CyberMem_phys, 0x400000, "RAM")) {
1017 release_mem_region(CyberRegs_phys, 0x10000);
1020 DPRINTK("board_addr=%08lx\n", board_addr);
1021 DPRINTK("board_size=%08lx\n", board_size);
1023 CyberBase = ioremap(board_addr, board_size);
1024 CyberRegs = CyberBase + 0x02000000;
1025 CyberMem = CyberBase + 0x01400000;
1026 DPRINTK("CyberBase=%08lx CyberRegs=%08lx CyberMem=%08lx\n",
1027 CyberBase, (long unsigned int)CyberRegs, CyberMem);
1030 DPRINTK("Register state just after mapping memory\n");
1034 strcpy(fb_info.modename, cyberfb_name);
1035 fb_info.changevar = NULL;
1036 fb_info.fbops = &cyberfb_ops;
1037 fb_info.screen_base = (unsigned char *)CyberMem;
1038 fb_info.disp = &disp;
1039 fb_info.currcon = -1;
1040 fb_info.switch_con = &Cyberfb_switch;
1041 fb_info.updatevar = &Cyberfb_updatevar;
1044 /* ++Andre: set cyberfb default mode */
1045 if (!cyberfb_usermode) {
1046 cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
1047 DPRINTK("Use default cyber8 mode\n");
1049 Cyber_decode_var(&cyberfb_default, &par);
1050 Cyber_encode_var(&cyberfb_default, &par);
1052 do_fb_set_var(&cyberfb_default, 1);
1053 cyberfb_get_var(&fb_display[0].var, -1, &fb_info);
1054 cyberfb_set_disp(-1, &fb_info);
1055 do_install_cmap(0, &fb_info);
1057 if (register_framebuffer(&fb_info) < 0) {
1058 DPRINTK("EXIT - register_framebuffer failed\n");
1059 release_mem_region(CyberMem_phys, 0x400000);
1060 release_mem_region(CyberRegs_phys, 0x10000);
1064 printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
1065 fb_info.node, fb_info.modename, CyberSize>>10);
1067 /* TODO: This driver cannot be unloaded yet */
1076 static int Cyberfb_switch(int con, struct fb_info *info)
1079 /* Do we have to save the colormap? */
1080 if (fb_display[info->currcon].cmap.len) {
1081 fb_get_cmap(&fb_display[info->currcon].cmap, 1, Cyber_getcolreg,
1085 do_fb_set_var(&fb_display[con].var, 1);
1086 info->currcon = con;
1087 /* Install new colormap */
1088 do_install_cmap(con, info);
1095 * Update the `var' structure (called by fbcon.c)
1097 * This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
1098 * Since it's called by a kernel driver, no range checking is done.
1101 static int Cyberfb_updatevar(int con, struct fb_info *info)
1103 DPRINTK("Enter - Exit\n");
1112 static int __init get_video_mode(const char *name)
1117 for (i = 0; i < NUM_TOTAL_MODES; i++) {
1118 if (!strcmp(name, cyberfb_predefined[i].name)) {
1119 cyberfb_default = cyberfb_predefined[i].var;
1120 cyberfb_usermode = 1;
1121 DPRINTK("EXIT - Matched predefined mode\n");
1130 * Text console acceleration
1133 #ifdef FBCON_HAS_CFB8
1134 static void fbcon_cyber8_bmove(struct display *p, int sy, int sx, int dy,
1135 int dx, int height, int width)
1138 sx *= 8; dx *= 8; width *= 8;
1139 Cyber_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
1140 (u_short)(dy*fontheight(p)), (u_short)width,
1141 (u_short)(height*fontheight(p)), (u_short)S3_NEW);
1145 static void fbcon_cyber8_clear(struct vc_data *conp, struct display *p, int sy,
1146 int sx, int height, int width)
1151 sx *= 8; width *= 8;
1152 bg = attr_bgcol_ec(p,conp);
1153 Cyber_RectFill((u_short)sx,
1154 (u_short)(sy*fontheight(p)),
1156 (u_short)(height*fontheight(p)),
1162 static void fbcon_cyber8_putc(struct vc_data *conp, struct display *p, int c,
1167 fbcon_cfb8_putc(conp, p, c, yy, xx);
1171 static void fbcon_cyber8_putcs(struct vc_data *conp, struct display *p,
1172 const unsigned short *s, int count,
1177 fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
1181 static void fbcon_cyber8_revc(struct display *p, int xx, int yy)
1185 fbcon_cfb8_revc(p, xx, yy);
1189 static struct display_switch fbcon_cyber8 = {
1190 .setup = fbcon_cfb8_setup,
1191 .bmove = fbcon_cyber8_bmove,
1192 .clear = fbcon_cyber8_clear,
1193 .putc = fbcon_cyber8_putc,
1194 .putcs = fbcon_cyber8_putcs,
1195 .revc = fbcon_cyber8_revc,
1196 .clear_margins =fbcon_cfb8_clear_margins,
1197 .fontwidthmask =FONTWIDTH(8)
1203 MODULE_LICENSE("GPL");
1205 int init_module(void)
1207 return cyberfb_init();
1210 void cleanup_module(void)
1212 /* Not reached because the usecount will never be
1213 decremented to zero */
1214 unregister_framebuffer(&fb_info);
1215 /* TODO: clean up ... */
1221 * Low level initialization routines for the CyberVision64 graphics card
1223 * Most of the following code is from cvision_core.c
1227 #define MAXPIXELCLOCK 135000000 /* safety */
1229 #ifdef CV_AGGRESSIVE_TIMING
1230 long cv64_memclk = 55000000;
1232 long cv64_memclk = 50000000;
1235 /*********************/
1237 static unsigned char clocks[]={
1238 0x13, 0x61, 0x6b, 0x6d, 0x51, 0x69, 0x54, 0x69,
1239 0x4f, 0x68, 0x6b, 0x6b, 0x18, 0x61, 0x7b, 0x6c,
1240 0x51, 0x67, 0x24, 0x62, 0x56, 0x67, 0x77, 0x6a,
1241 0x1d, 0x61, 0x53, 0x66, 0x6b, 0x68, 0x79, 0x69,
1242 0x7c, 0x69, 0x7f, 0x69, 0x22, 0x61, 0x54, 0x65,
1243 0x56, 0x65, 0x58, 0x65, 0x67, 0x66, 0x41, 0x63,
1244 0x27, 0x61, 0x13, 0x41, 0x37, 0x62, 0x6b, 0x4d,
1245 0x23, 0x43, 0x51, 0x49, 0x79, 0x66, 0x54, 0x49,
1246 0x7d, 0x66, 0x34, 0x56, 0x4f, 0x63, 0x1f, 0x42,
1247 0x6b, 0x4b, 0x7e, 0x4d, 0x18, 0x41, 0x2a, 0x43,
1248 0x7b, 0x4c, 0x74, 0x4b, 0x51, 0x47, 0x65, 0x49,
1249 0x24, 0x42, 0x68, 0x49, 0x56, 0x47, 0x75, 0x4a,
1250 0x77, 0x4a, 0x31, 0x43, 0x1d, 0x41, 0x71, 0x49,
1251 0x53, 0x46, 0x29, 0x42, 0x6b, 0x48, 0x1f, 0x41,
1252 0x79, 0x49, 0x6f, 0x48, 0x7c, 0x49, 0x38, 0x43,
1253 0x7f, 0x49, 0x5d, 0x46, 0x22, 0x41, 0x53, 0x45,
1254 0x54, 0x45, 0x55, 0x45, 0x56, 0x45, 0x57, 0x45,
1255 0x58, 0x45, 0x25, 0x41, 0x67, 0x46, 0x5b, 0x45,
1256 0x41, 0x43, 0x78, 0x47, 0x27, 0x41, 0x51, 0x44,
1257 0x13, 0x21, 0x7d, 0x47, 0x37, 0x42, 0x71, 0x46,
1258 0x6b, 0x2d, 0x14, 0x21, 0x23, 0x23, 0x7d, 0x2f,
1259 0x51, 0x29, 0x61, 0x2b, 0x79, 0x46, 0x1d, 0x22,
1260 0x54, 0x29, 0x45, 0x27, 0x7d, 0x46, 0x7f, 0x46,
1261 0x4f, 0x43, 0x2f, 0x41, 0x1f, 0x22, 0x6a, 0x2b,
1262 0x6b, 0x2b, 0x5b, 0x29, 0x7e, 0x2d, 0x65, 0x44,
1263 0x18, 0x21, 0x5e, 0x29, 0x2a, 0x23, 0x45, 0x26,
1264 0x7b, 0x2c, 0x19, 0x21, 0x74, 0x2b, 0x75, 0x2b,
1265 0x51, 0x27, 0x3f, 0x25, 0x65, 0x29, 0x40, 0x25,
1266 0x24, 0x22, 0x41, 0x25, 0x68, 0x29, 0x42, 0x25,
1267 0x56, 0x27, 0x7e, 0x2b, 0x75, 0x2a, 0x1c, 0x21,
1268 0x77, 0x2a, 0x4f, 0x26, 0x31, 0x23, 0x6f, 0x29,
1269 0x1d, 0x21, 0x32, 0x23, 0x71, 0x29, 0x72, 0x29,
1270 0x53, 0x26, 0x69, 0x28, 0x29, 0x22, 0x75, 0x29,
1271 0x6b, 0x28, 0x1f, 0x21, 0x1f, 0x21, 0x6d, 0x28,
1272 0x79, 0x29, 0x2b, 0x22, 0x6f, 0x28, 0x59, 0x26,
1273 0x7c, 0x29, 0x7d, 0x29, 0x38, 0x23, 0x21, 0x21,
1274 0x7f, 0x29, 0x39, 0x23, 0x5d, 0x26, 0x75, 0x28,
1275 0x22, 0x21, 0x77, 0x28, 0x53, 0x25, 0x6c, 0x27,
1276 0x54, 0x25, 0x61, 0x26, 0x55, 0x25, 0x30, 0x22,
1277 0x56, 0x25, 0x63, 0x26, 0x57, 0x25, 0x71, 0x27,
1278 0x58, 0x25, 0x7f, 0x28, 0x25, 0x21, 0x74, 0x27,
1279 0x67, 0x26, 0x40, 0x23, 0x5b, 0x25, 0x26, 0x21,
1280 0x41, 0x23, 0x34, 0x22, 0x78, 0x27, 0x6b, 0x26,
1281 0x27, 0x21, 0x35, 0x22, 0x51, 0x24, 0x7b, 0x27,
1282 0x13, 0x1, 0x13, 0x1, 0x7d, 0x27, 0x4c, 0x9,
1283 0x37, 0x22, 0x5b, 0xb, 0x71, 0x26, 0x5c, 0xb,
1284 0x6b, 0xd, 0x47, 0x23, 0x14, 0x1, 0x4f, 0x9,
1285 0x23, 0x3, 0x75, 0x26, 0x7d, 0xf, 0x1c, 0x2,
1286 0x51, 0x9, 0x59, 0x24, 0x61, 0xb, 0x69, 0x25,
1287 0x79, 0x26, 0x34, 0x5, 0x1d, 0x2, 0x6b, 0x25,
1288 0x54, 0x9, 0x35, 0x5, 0x45, 0x7, 0x6d, 0x25,
1289 0x7d, 0x26, 0x16, 0x1, 0x7f, 0x26, 0x77, 0xd,
1290 0x4f, 0x23, 0x78, 0xd, 0x2f, 0x21, 0x27, 0x3,
1291 0x1f, 0x2, 0x59, 0x9, 0x6a, 0xb, 0x73, 0x25,
1292 0x6b, 0xb, 0x63, 0x24, 0x5b, 0x9, 0x20, 0x2,
1293 0x7e, 0xd, 0x4b, 0x7, 0x65, 0x24, 0x43, 0x22,
1294 0x18, 0x1, 0x6f, 0xb, 0x5e, 0x9, 0x70, 0xb,
1295 0x2a, 0x3, 0x33, 0x4, 0x45, 0x6, 0x60, 0x9,
1296 0x7b, 0xc, 0x19, 0x1, 0x19, 0x1, 0x7d, 0xc,
1297 0x74, 0xb, 0x50, 0x7, 0x75, 0xb, 0x63, 0x9,
1298 0x51, 0x7, 0x23, 0x2, 0x3f, 0x5, 0x1a, 0x1,
1299 0x65, 0x9, 0x2d, 0x3, 0x40, 0x5, 0x0, 0x0,
1302 /* Console colors */
1303 unsigned char cvconscolors[16][3] = { /* background, foreground, hilite */
1323 /* -------------------- Hardware specific routines ------------------------- */
1325 /* Read Attribute Controller Register=idx */
1326 inline unsigned char RAttr (volatile unsigned char *regs, short idx)
1328 wb_64 (regs, ACT_ADDRESS_W, idx);
1331 return (rb_64(regs, ACT_ADDRESS_R));
1334 /* Read Sequencer Register=idx */
1335 inline unsigned char RSeq (volatile unsigned char *regs, short idx)
1337 wb_64 (regs, SEQ_ADDRESS, idx);
1339 return (rb_64(regs, SEQ_ADDRESS_R));
1342 /* Read CRT Controller Register=idx */
1343 inline unsigned char RCrt (volatile unsigned char *regs, short idx)
1345 wb_64 (regs, CRT_ADDRESS, idx);
1347 return (rb_64(regs, CRT_ADDRESS_R));
1350 /* Read Graphics Controller Register=idx */
1351 inline unsigned char RGfx (volatile unsigned char *regs, short idx)
1353 wb_64 (regs, GCT_ADDRESS, idx);
1355 return (rb_64(regs, GCT_ADDRESS_R));
1359 * Special wakeup/passthrough registers on graphics boards
1362 inline void cv64_write_port (unsigned short bits,
1363 volatile unsigned char *base)
1365 volatile unsigned char *addr;
1366 static unsigned char cvportbits = 0; /* Mirror port bits here */
1369 addr = base + 0x40001;
1370 if (bits & 0x8000) {
1371 cvportbits |= bits & 0xff; /* Set bits */
1372 DPRINTK("Set bits: %04x\n", bits);
1375 bits = (~bits) & 0xff;
1376 cvportbits &= bits; /* Clear bits */
1377 DPRINTK("Clear bits: %04x\n", bits);
1385 * Monitor switch on CyberVision board
1388 * 0 = CyberVision Signal
1390 * board = board addr
1393 inline void cvscreen (int toggle, volatile unsigned char *board)
1397 DPRINTK("Show Amiga video\n");
1398 cv64_write_port (0x10, board);
1400 DPRINTK("Show CyberVision video\n");
1401 cv64_write_port (0x8010, board);
1406 /* Control screen display */
1407 /* toggle: 0 = on, 1 = off */
1408 /* board = registerbase */
1409 inline void gfx_on_off(int toggle, volatile unsigned char *regs)
1415 toggle = toggle << 5;
1416 DPRINTK("Turn display %s\n", (toggle ? "off" : "on"));
1418 r = (int) RSeq(regs, SEQ_ID_CLOCKING_MODE);
1419 r &= 0xdf; /* Set bit 5 to 0 */
1421 WSeq (regs, SEQ_ID_CLOCKING_MODE, r | toggle);
1426 * Computes M, N, and R values from
1427 * given input frequency. It uses a table of
1428 * precomputed values, to keep CPU time low.
1430 * The return value consist of:
1431 * lower byte: Bits 4-0: N Divider Value
1432 * Bits 5-6: R Value for e.g. SR10 or SR12
1433 * higher byte: Bits 0-6: M divider value for e.g. SR11 or SR13
1435 static unsigned short cv64_compute_clock(unsigned long freq)
1437 static unsigned char *mnr, *save; /* M, N + R vals */
1438 unsigned long work_freq, r;
1443 if (freq < 12500000 || freq > MAXPIXELCLOCK) {
1444 printk("CV64 driver: Illegal clock frequency %ld, using 25MHz\n",
1448 DPRINTK("Freq = %ld\n", freq);
1449 mnr = clocks; /* there the vals are stored */
1452 while (*mnr) { /* mnr vals are 0-terminated */
1453 work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2);
1455 r = (mnr[1] >> 5) & 0x03;
1457 work_freq = work_freq >> r; /* r is the freq divider */
1460 work_freq *= 0x3E8; /* 2nd part of OSC */
1462 diff = abs(freq - work_freq);
1466 /* In save are the vals for minimal diff */
1471 erg = *((unsigned short *)save);
1477 static int cv_has_4mb (volatile unsigned char *fb)
1479 volatile unsigned long *tr, *tw;
1482 /* write patterns in memory and test if they can be read */
1483 tw = (volatile unsigned long *) fb;
1484 tr = (volatile unsigned long *) (fb + 0x02000000);
1488 if (*tr != 0x87654321) {
1489 DPRINTK("EXIT - <4MB\n");
1493 /* upper memory region */
1494 tw = (volatile unsigned long *) (fb + 0x00200000);
1495 tr = (volatile unsigned long *) (fb + 0x02200000);
1499 if (*tr != 0x87654321) {
1500 DPRINTK("EXIT - <4MB\n");
1506 if (*tr != 0xAAAAAAAA) {
1507 DPRINTK("EXIT - <4MB\n");
1513 if (*tr != 0x55555555) {
1514 DPRINTK("EXIT - <4MB\n");
1522 static void cv64_board_init (void)
1524 volatile unsigned char *regs = CyberRegs;
1526 unsigned int clockpar;
1532 * Special CyberVision 64 board operations
1535 for (i = 0; i < 6; i++) {
1536 cv64_write_port (0xff, CyberBase);
1538 /* Return to operational mode */
1539 cv64_write_port (0x8004, CyberBase);
1542 * Generic (?) S3 chip wakeup
1544 /* Disable I/O & memory decoders, video in setup mode */
1545 wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x10);
1546 /* Video responds to cmds, addrs & data */
1547 wb_64 (regs, SREG_OPTION_SELECT, 0x1);
1548 /* Enable I/O & memory decoders, video in operational mode */
1549 wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x8);
1550 /* VGA color emulation, enable cpu access to display mem */
1551 wb_64 (regs, GREG_MISC_OUTPUT_W, 0x03);
1552 /* Unlock S3 VGA regs */
1553 WCrt (regs, CRT_ID_REGISTER_LOCK_1, 0x48);
1554 /* Unlock system control & extension registers */
1555 WCrt (regs, CRT_ID_REGISTER_LOCK_2, 0xA5);
1556 /* GRF - Enable interrupts */
1557 /* Enable enhanced regs access, Ready cntl 0 wait states */
1558 test = RCrt (regs, CRT_ID_SYSTEM_CONFIG);
1559 test = test | 0x01; /* enable enhanced register access */
1560 test = test & 0xEF; /* clear bit 4, 0 wait state */
1561 WCrt (regs, CRT_ID_SYSTEM_CONFIG, test);
1563 * bit 0=1: Enable enhaced mode functions
1564 * bit 2=0: Enhanced mode 8+ bits/pixel
1565 * bit 4=1: Enable linear addressing
1566 * bit 5=1: Enable MMIO
1568 wb_64 (regs, ECR_ADV_FUNC_CNTL, 0x31);
1570 * bit 0=1: Color emulation
1571 * bit 1=1: Enable CPU access to display memory
1572 * bit 5=1: Select high 64K memory page
1575 wb_64 (regs, GREG_MISC_OUTPUT_W, 0x23);
1578 WCrt (regs, CRT_ID_EXT_SYS_CNTL_4, 0x0);
1580 /* Reset. This does nothing on Trio, but standard VGA practice */
1581 /* WSeq (CyberRegs, SEQ_ID_RESET, 0x03); */
1582 /* Character clocks 8 dots wide */
1583 WSeq (regs, SEQ_ID_CLOCKING_MODE, 0x01);
1584 /* Enable cpu write to all color planes */
1585 WSeq (regs, SEQ_ID_MAP_MASK, 0x0F);
1586 /* Font table in 1st 8k of plane 2, font A=B disables swtich */
1587 WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x0);
1588 /* Allow mem access to 256kb */
1589 WSeq (regs, SEQ_ID_MEMORY_MODE, 0x2);
1590 /* Unlock S3 extensions to VGA Sequencer regs */
1591 WSeq (regs, SEQ_ID_UNLOCK_EXT, 0x6);
1593 /* Enable 4MB fast page mode */
1594 test = RSeq (regs, SEQ_ID_BUS_REQ_CNTL);
1595 test = test | 1 << 6;
1596 WSeq (regs, SEQ_ID_BUS_REQ_CNTL, test);
1598 /* Faster LUT write: 1 DCLK LUT write cycle, RAMDAC clk doubled */
1599 WSeq (regs, SEQ_ID_RAMDAC_CNTL, 0xC0);
1601 /* Clear immediate clock load bit */
1602 test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
1604 /* If > 55MHz, enable 2 cycle memory write */
1605 if (cv64_memclk >= 55000000) {
1608 WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
1610 /* Set MCLK value */
1611 clockpar = cv64_compute_clock (cv64_memclk);
1612 test = (clockpar & 0xFF00) >> 8;
1613 WSeq (regs, SEQ_ID_MCLK_HI, test);
1614 test = clockpar & 0xFF;
1615 WSeq (regs, SEQ_ID_MCLK_LO, test);
1617 /* Chip rev specific: Not in my Trio manual!!! */
1618 if (RCrt (regs, CRT_ID_REVISION) == 0x10)
1619 WSeq (regs, SEQ_ID_MORE_MAGIC, test);
1621 /* We now load an 25 MHz, 31kHz, 640x480 standard VGA Mode. */
1623 /* Set DCLK value */
1624 WSeq (regs, SEQ_ID_DCLK_HI, 0x13);
1625 WSeq (regs, SEQ_ID_DCLK_LO, 0x41);
1627 /* Load DCLK (and MCLK?) immediately */
1628 test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
1630 WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
1632 /* Enable loading of DCLK */
1633 test = rb_64(regs, GREG_MISC_OUTPUT_R);
1635 wb_64 (regs, GREG_MISC_OUTPUT_W, test);
1637 /* Turn off immediate xCLK load */
1638 WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, 0x2);
1640 /* Horizontal character clock counts */
1641 /* 8 LSB of 9 bits = total line - 5 */
1642 WCrt (regs, CRT_ID_HOR_TOTAL, 0x5F);
1643 /* Active display line */
1644 WCrt (regs, CRT_ID_HOR_DISP_ENA_END, 0x4F);
1645 /* Blank assertion start */
1646 WCrt (regs, CRT_ID_START_HOR_BLANK, 0x50);
1647 /* Blank assertion end */
1648 WCrt (regs, CRT_ID_END_HOR_BLANK, 0x82);
1649 /* HSYNC assertion start */
1650 WCrt (regs, CRT_ID_START_HOR_RETR, 0x54);
1651 /* HSYNC assertion end */
1652 WCrt (regs, CRT_ID_END_HOR_RETR, 0x80);
1653 WCrt (regs, CRT_ID_VER_TOTAL, 0xBF);
1654 WCrt (regs, CRT_ID_OVERFLOW, 0x1F);
1655 WCrt (regs, CRT_ID_PRESET_ROW_SCAN, 0x0);
1656 WCrt (regs, CRT_ID_MAX_SCAN_LINE, 0x40);
1657 WCrt (regs, CRT_ID_CURSOR_START, 0x00);
1658 WCrt (regs, CRT_ID_CURSOR_END, 0x00);
1659 WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00);
1660 WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00);
1661 WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1662 WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
1663 WCrt (regs, CRT_ID_START_VER_RETR, 0x9C);
1664 WCrt (regs, CRT_ID_END_VER_RETR, 0x0E);
1665 WCrt (regs, CRT_ID_VER_DISP_ENA_END, 0x8F);
1666 WCrt (regs, CRT_ID_SCREEN_OFFSET, 0x50);
1667 WCrt (regs, CRT_ID_UNDERLINE_LOC, 0x00);
1668 WCrt (regs, CRT_ID_START_VER_BLANK, 0x96);
1669 WCrt (regs, CRT_ID_END_VER_BLANK, 0xB9);
1670 WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3);
1671 WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF);
1672 WCrt (regs, CRT_ID_BACKWAD_COMP_3, 0x10); /* FIFO enabled */
1673 WCrt (regs, CRT_ID_MISC_1, 0x35);
1674 WCrt (regs, CRT_ID_DISPLAY_FIFO, 0x5A);
1675 WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, 0x70);
1676 WCrt (regs, CRT_ID_LAW_POS_LO, 0x40);
1677 WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, 0xFF);
1679 WGfx (regs, GCT_ID_SET_RESET, 0x0);
1680 WGfx (regs, GCT_ID_ENABLE_SET_RESET, 0x0);
1681 WGfx (regs, GCT_ID_COLOR_COMPARE, 0x0);
1682 WGfx (regs, GCT_ID_DATA_ROTATE, 0x0);
1683 WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x0);
1684 WGfx (regs, GCT_ID_GRAPHICS_MODE, 0x40);
1685 WGfx (regs, GCT_ID_MISC, 0x01);
1686 WGfx (regs, GCT_ID_COLOR_XCARE, 0x0F);
1687 WGfx (regs, GCT_ID_BITMASK, 0xFF);
1689 /* Colors for text mode */
1690 for (i = 0; i < 0xf; i++)
1693 WAttr (regs, ACT_ID_ATTR_MODE_CNTL, 0x41);
1694 WAttr (regs, ACT_ID_OVERSCAN_COLOR, 0x01);
1695 WAttr (regs, ACT_ID_COLOR_PLANE_ENA, 0x0F);
1696 WAttr (regs, ACT_ID_HOR_PEL_PANNING, 0x0);
1697 WAttr (regs, ACT_ID_COLOR_SELECT, 0x0);
1699 wb_64 (regs, VDAC_MASK, 0xFF);
1701 *((unsigned long *) (regs + ECR_FRGD_COLOR)) = 0xFF;
1702 *((unsigned long *) (regs + ECR_BKGD_COLOR)) = 0;
1704 /* Colors initially set to grayscale */
1706 wb_64 (regs, VDAC_ADDRESS_W, 0);
1707 for (i = 255; i >= 0; i--) {
1708 wb_64(regs, VDAC_DATA, i);
1709 wb_64(regs, VDAC_DATA, i);
1710 wb_64(regs, VDAC_DATA, i);
1713 /* GFx hardware cursor off */
1714 WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
1716 /* Set first to 4MB, so test will work */
1717 WCrt (regs, CRT_ID_LAW_CNTL, 0x13);
1718 /* Find "correct" size of fbmem of Z3 board */
1719 if (cv_has_4mb (CyberMem)) {
1720 CyberSize = 1024 * 1024 * 4;
1721 WCrt (regs, CRT_ID_LAW_CNTL, 0x13);
1722 DPRINTK("4MB board\n");
1724 CyberSize = 1024 * 1024 * 2;
1725 WCrt (regs, CRT_ID_LAW_CNTL, 0x12);
1726 DPRINTK("2MB board\n");
1729 /* Initialize graphics engine */
1731 vgaw16 (regs, ECR_FRGD_MIX, 0x27);
1732 vgaw16 (regs, ECR_BKGD_MIX, 0x07);
1733 vgaw16 (regs, ECR_READ_REG_DATA, 0x1000);
1735 vgaw16 (regs, ECR_READ_REG_DATA, 0x2000);
1737 vgaw16 (regs, ECR_READ_REG_DATA, 0x3FFF);
1740 vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF);
1742 vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, ~0);
1744 vgaw16 (regs, ECR_READ_REG_DATA, 0xE000);
1745 vgaw16 (regs, ECR_CURRENT_Y_POS2, 0x00);
1746 vgaw16 (regs, ECR_CURRENT_X_POS2, 0x00);
1747 vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
1748 vgaw16 (regs, ECR_DEST_Y__AX_STEP, 0x00);
1749 vgaw16 (regs, ECR_DEST_Y2__AX_STEP2, 0x00);
1750 vgaw16 (regs, ECR_DEST_X__DIA_STEP, 0x00);
1751 vgaw16 (regs, ECR_DEST_X2__DIA_STEP2, 0x00);
1752 vgaw16 (regs, ECR_SHORT_STROKE, 0x00);
1753 vgaw16 (regs, ECR_DRAW_CMD, 0x01);
1757 vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF);
1758 vgaw16 (regs, ECR_BKGD_COLOR, 0x01);
1759 vgaw16 (regs, ECR_FRGD_COLOR, 0x00);
1762 /* Enable video display (set bit 5) */
1763 /* ARB - Would also seem to write to AR13.
1764 * May want to use parts of WAttr to set JUST bit 5
1766 WAttr (regs, 0x33, 0);
1768 /* GRF - function code ended here */
1770 /* Turn gfx on again */
1771 gfx_on_off (0, regs);
1774 cvscreen (0, CyberBase);
1779 static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
1781 volatile unsigned char *regs = CyberRegs;
1784 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, VSE, VT;
1785 char LACE, DBLSCAN, TEXT, CONSOLE;
1786 int cr50, sr15, sr18, clock_mode, test;
1788 int tfillm, temptym;
1791 /* ---------------- */
1792 int xres, hfront, hsync, hback;
1793 int yres, vfront, vsync, vback;
1799 /* ---------------- */
1802 TEXT = 0; /* if depth == 4 */
1803 CONSOLE = 0; /* mode num == 255 (console) */
1804 fx = fy = 8; /* force 8x8 font */
1806 /* GRF - Disable interrupts */
1808 gfx_on_off (1, regs);
1810 switch (video_mode->bits_per_pixel) {
1821 bpp = video_mode->bits_per_pixel;
1822 xres = video_mode->xres;
1823 hfront = video_mode->right_margin;
1824 hsync = video_mode->hsync_len;
1825 hback = video_mode->left_margin;
1830 if (video_mode->vmode & FB_VMODE_DOUBLE) {
1831 yres = video_mode->yres * 2;
1832 vfront = video_mode->lower_margin * 2;
1833 vsync = video_mode->vsync_len * 2;
1834 vback = video_mode->upper_margin * 2;
1836 } else if (video_mode->vmode & FB_VMODE_INTERLACED) {
1837 yres = (video_mode->yres + 1) / 2;
1838 vfront = (video_mode->lower_margin + 1) / 2;
1839 vsync = (video_mode->vsync_len + 1) / 2;
1840 vback = (video_mode->upper_margin + 1) / 2;
1843 yres = video_mode->yres;
1844 vfront = video_mode->lower_margin;
1845 vsync = video_mode->vsync_len;
1846 vback = video_mode->upper_margin;
1849 /* ARB Dropping custom setup method from cvision.c */
1851 if (cvision_custom_mode) {
1852 HBS = hbs / 8 * hmul;
1853 HBE = hbe / 8 * hmul;
1854 HSS = hss / 8 * hmul;
1855 HSE = hse / 8 * hmul;
1856 HT = ht / 8 * hmul - 5;
1867 HBS = hmul * (xres / 8);
1868 HBE = hmul * ((xres/8) + (hfront/8) + (hsync/8) + (hback/8) - 2);
1869 HSS = hmul * ((xres/8) + (hfront/8) + 2);
1870 HSE = hmul * ((xres/8) + (hfront/8) + (hsync/8) + 1);
1871 HT = hmul * ((xres/8) + (hfront/8) + (hsync/8) + (hback/8));
1874 VBE = yres + vfront + vsync + vback - 2;
1875 VSS = yres + vfront - 1;
1876 VSE = yres + vfront + vsync - 1;
1877 VT = yres + vfront + vsync + vback - 2;
1880 wb_64 (regs, ECR_ADV_FUNC_CNTL, (TEXT ? 0x00 : 0x31));
1883 HDE = ((video_mode->xres + fx - 1) / fx) - 1;
1885 HDE = (video_mode->xres + 3) * hmul / 8 - 1;
1887 VDE = video_mode->yres - 1;
1889 WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
1890 WCrt (regs, CRT_ID_EXT_DAC_CNTL, 0x00);
1892 WSeq (regs, SEQ_ID_MEMORY_MODE,
1893 (TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x0e);
1894 WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x00);
1895 WSeq (regs, SEQ_ID_MAP_MASK,
1896 (video_mode->bits_per_pixel == 1) ? 0x01 : 0xFF);
1897 WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1899 /* cv64_compute_clock accepts arguments in Hz */
1900 /* pixclock is in ps ... convert to Hz */
1903 freq_f = (1.0 / (float) video_mode->pixclock) * 1000000000;
1904 freq = ((long) freq_f) * 1000;
1906 /* freq = (long) ((long long)1000000000000 / (long long) video_mode->pixclock);
1908 freq = (1000000000 / video_mode->pixclock) * 1000;
1911 mnr = cv64_compute_clock (freq);
1912 WSeq (regs, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8));
1913 WSeq (regs, SEQ_ID_DCLK_LO, (mnr & 0xFF));
1915 /* Load display parameters into board */
1916 WCrt (regs, CRT_ID_EXT_HOR_OVF,
1917 ((HT & 0x100) ? 0x01 : 0x00) |
1918 ((HDE & 0x100) ? 0x02 : 0x00) |
1919 ((HBS & 0x100) ? 0x04 : 0x00) |
1920 /* ((HBE & 0x40) ? 0x08 : 0x00) | */
1921 ((HSS & 0x100) ? 0x10 : 0x00) |
1922 /* ((HSE & 0x20) ? 0x20 : 0x00) | */
1923 (((HT-5) & 0x100) ? 0x40 : 0x00)
1926 WCrt (regs, CRT_ID_EXT_VER_OVF,
1928 ((VT & 0x400) ? 0x01 : 0x00) |
1929 ((VDE & 0x400) ? 0x02 : 0x00) |
1930 ((VBS & 0x400) ? 0x04 : 0x00) |
1931 ((VSS & 0x400) ? 0x10 : 0x00)
1934 WCrt (regs, CRT_ID_HOR_TOTAL, HT);
1935 WCrt (regs, CRT_ID_DISPLAY_FIFO, HT - 5);
1936 WCrt (regs, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE));
1937 WCrt (regs, CRT_ID_START_HOR_BLANK, HBS);
1938 WCrt (regs, CRT_ID_END_HOR_BLANK, ((HBE & 0x1F) | 0x80));
1939 WCrt (regs, CRT_ID_START_HOR_RETR, HSS);
1940 WCrt (regs, CRT_ID_END_HOR_RETR,
1942 ((HBE & 0x20) ? 0x80 : 0x00)
1944 WCrt (regs, CRT_ID_VER_TOTAL, VT);
1945 WCrt (regs, CRT_ID_OVERFLOW,
1947 ((VT & 0x100) ? 0x01 : 0x00) |
1948 ((VDE & 0x100) ? 0x02 : 0x00) |
1949 ((VSS & 0x100) ? 0x04 : 0x00) |
1950 ((VBS & 0x100) ? 0x08 : 0x00) |
1951 ((VT & 0x200) ? 0x20 : 0x00) |
1952 ((VDE & 0x200) ? 0x40 : 0x00) |
1953 ((VSS & 0x200) ? 0x80 : 0x00)
1955 WCrt (regs, CRT_ID_MAX_SCAN_LINE,
1957 (DBLSCAN ? 0x80 : 0x00) |
1958 ((VBS & 0x200) ? 0x20 : 0x00) |
1959 (TEXT ? ((fy - 1) & 0x1F) : 0x00)
1962 WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3);
1968 WCrt (regs, CRT_ID_CURSOR_START, (fy & 0x1f) - 2);
1969 WCrt (regs, CRT_ID_CURSOR_END, (fy & 0x1F) - 1);
1971 WCrt (regs, CRT_ID_CURSOR_START, 0x00);
1972 WCrt (regs, CRT_ID_CURSOR_END, fy & 0x1F);
1974 WCrt (regs, CRT_ID_UNDERLINE_LOC, (fy - 1) & 0x1F);
1975 WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1976 WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
1979 WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00);
1980 WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00);
1981 WCrt (regs, CRT_ID_START_VER_RETR, VSS);
1982 WCrt (regs, CRT_ID_END_VER_RETR, (VSE & 0x0F));
1983 WCrt (regs, CRT_ID_VER_DISP_ENA_END, VDE);
1984 WCrt (regs, CRT_ID_START_VER_BLANK, VBS);
1985 WCrt (regs, CRT_ID_END_VER_BLANK, VBE);
1986 WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF);
1987 WCrt (regs, CRT_ID_LACE_RETR_START, HT / 2);
1988 WCrt (regs, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00));
1989 WGfx (regs, GCT_ID_GRAPHICS_MODE,
1990 ((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x00 : 0x40));
1991 WGfx (regs, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
1992 WSeq (regs, SEQ_ID_MEMORY_MODE,
1993 ((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x02));
1995 wb_64 (regs, VDAC_MASK, 0xFF);
1998 test = RCrt (regs, CRT_ID_BACKWAD_COMP_2);
1999 WCrt (regs, CRT_ID_BACKWAD_COMP_2, (test | 0x20));
2001 sr15 = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
2003 sr18 = RSeq (regs, SEQ_ID_RAMDAC_CNTL);
2008 test = RCrt (regs, CRT_ID_EXT_MISC_CNTL_2);
2011 /* Clear roxxler byte-swapping... */
2012 cv64_write_port (0x0040, CyberBase);
2013 cv64_write_port (0x0020, CyberBase);
2015 switch (video_mode->bits_per_pixel) {
2018 HDE = video_mode->xres / 16;
2022 if (freq > 80000000) {
2023 clock_mode = 0x10 | 0x02;
2027 HDE = video_mode->xres / 8;
2032 cv64_write_port (0x8020, CyberBase);
2034 HDE = video_mode->xres / 4;
2039 cv64_write_port (0x8020, CyberBase);
2041 HDE = video_mode->xres / 4;
2047 cv64_write_port (0x8040, CyberBase);
2049 HDE = video_mode->xres / 2;
2054 WCrt (regs, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test);
2055 WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, sr15);
2056 WSeq (regs, SEQ_ID_RAMDAC_CNTL, sr18);
2057 WCrt (regs, CRT_ID_SCREEN_OFFSET, HDE);
2059 WCrt (regs, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35));
2061 test = RCrt (regs, CRT_ID_EXT_SYS_CNTL_2);
2063 test |= (HDE >> 4) & 0x30;
2064 WCrt (regs, CRT_ID_EXT_SYS_CNTL_2, test);
2066 /* Set up graphics engine */
2067 switch (video_mode->xres) {
2096 WCrt (regs, CRT_ID_EXT_SYS_CNTL_1, cr50);
2099 WAttr (regs, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41));
2101 WAttr (regs, ACT_ID_COLOR_PLANE_ENA,
2102 (video_mode->bits_per_pixel == 1) ? 0x01 : 0x0F);
2105 tfillm = (96 * (cv64_memclk / 1000)) / 240000;
2107 switch (video_mode->bits_per_pixel) {
2110 temptym = (24 * (cv64_memclk / 1000)) / (freq / 1000);
2114 temptym = (48 * (cv64_memclk / 1000)) / (freq / 1000);
2117 temptym = (192 * (cv64_memclk / 1000)) / (freq / 1000);
2120 temptym = (96 * (cv64_memclk / 1000)) / (freq / 1000);
2124 m = (temptym - tfillm - 9) / 2;
2127 m = (m & 0x1F) << 3;
2132 WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, m);
2133 WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, n);
2136 /* Text initialization */
2139 /* Do text initialization here ! */
2144 wb_64 (regs, VDAC_ADDRESS_W, 0);
2145 for (i = 0; i < 4; i++) {
2146 wb_64 (regs, VDAC_DATA, cvconscolors [i][0]);
2147 wb_64 (regs, VDAC_DATA, cvconscolors [i][1]);
2148 wb_64 (regs, VDAC_DATA, cvconscolors [i][2]);
2152 WAttr (regs, 0x33, 0);
2154 /* Turn gfx on again */
2155 gfx_on_off (0, (volatile unsigned char *) regs);
2158 cvscreen (0, CyberBase);
2163 void cvision_bitblt (u_short sx, u_short sy, u_short dx, u_short dy,
2164 u_short w, u_short h)
2166 volatile unsigned char *regs = CyberRegs;
2167 unsigned short drawdir = 0;
2185 vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
2186 vgaw16 (regs, ECR_BKGD_MIX, 0x7);
2187 vgaw16 (regs, ECR_FRGD_MIX, 0x67);
2188 vgaw16 (regs, ECR_BKGD_COLOR, 0x0);
2189 vgaw16 (regs, ECR_FRGD_COLOR, 0x1);
2190 vgaw16 (regs, ECR_BITPLANE_READ_MASK, 0x1);
2191 vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, 0xFFF);
2192 vgaw16 (regs, ECR_CURRENT_Y_POS, sy);
2193 vgaw16 (regs, ECR_CURRENT_X_POS, sx);
2194 vgaw16 (regs, ECR_DEST_Y__AX_STEP, dy);
2195 vgaw16 (regs, ECR_DEST_X__DIA_STEP, dx);
2196 vgaw16 (regs, ECR_READ_REG_DATA, h - 1);
2197 vgaw16 (regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
2198 vgaw16 (regs, ECR_DRAW_CMD, 0xC051 | drawdir);
2202 void cvision_clear (u_short dx, u_short dy, u_short w, u_short h, u_short bg)
2204 volatile unsigned char *regs = CyberRegs;
2207 vgaw16 (regs, ECR_FRGD_MIX, 0x0027);
2208 vgaw16 (regs, ECR_FRGD_COLOR, bg);
2209 vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
2210 vgaw16 (regs, ECR_CURRENT_Y_POS, dy);
2211 vgaw16 (regs, ECR_CURRENT_X_POS, dx);
2212 vgaw16 (regs, ECR_READ_REG_DATA, h - 1);
2213 vgaw16 (regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
2214 vgaw16 (regs, ECR_DRAW_CMD, 0x40B1);
2220 * Dump internal settings of CyberVision board
2222 static void cv64_dump (void)
2224 volatile unsigned char *regs = CyberRegs;
2226 /* Dump the VGA setup values */
2227 *(regs + S3_CRTC_ADR) = 0x00;
2228 DPRINTK("CR00 = %x\n", *(regs + S3_CRTC_DATA));
2229 *(regs + S3_CRTC_ADR) = 0x01;
2230 DPRINTK("CR01 = %x\n", *(regs + S3_CRTC_DATA));
2231 *(regs + S3_CRTC_ADR) = 0x02;
2232 DPRINTK("CR02 = %x\n", *(regs + S3_CRTC_DATA));
2233 *(regs + S3_CRTC_ADR) = 0x03;
2234 DPRINTK("CR03 = %x\n", *(regs + S3_CRTC_DATA));
2235 *(regs + S3_CRTC_ADR) = 0x04;
2236 DPRINTK("CR04 = %x\n", *(regs + S3_CRTC_DATA));
2237 *(regs + S3_CRTC_ADR) = 0x05;
2238 DPRINTK("CR05 = %x\n", *(regs + S3_CRTC_DATA));
2239 *(regs + S3_CRTC_ADR) = 0x06;
2240 DPRINTK("CR06 = %x\n", *(regs + S3_CRTC_DATA));
2241 *(regs + S3_CRTC_ADR) = 0x07;
2242 DPRINTK("CR07 = %x\n", *(regs + S3_CRTC_DATA));
2243 *(regs + S3_CRTC_ADR) = 0x08;
2244 DPRINTK("CR08 = %x\n", *(regs + S3_CRTC_DATA));
2245 *(regs + S3_CRTC_ADR) = 0x09;
2246 DPRINTK("CR09 = %x\n", *(regs + S3_CRTC_DATA));
2247 *(regs + S3_CRTC_ADR) = 0x10;
2248 DPRINTK("CR10 = %x\n", *(regs + S3_CRTC_DATA));
2249 *(regs + S3_CRTC_ADR) = 0x11;
2250 DPRINTK("CR11 = %x\n", *(regs + S3_CRTC_DATA));
2251 *(regs + S3_CRTC_ADR) = 0x12;
2252 DPRINTK("CR12 = %x\n", *(regs + S3_CRTC_DATA));
2253 *(regs + S3_CRTC_ADR) = 0x13;
2254 DPRINTK("CR13 = %x\n", *(regs + S3_CRTC_DATA));
2255 *(regs + S3_CRTC_ADR) = 0x15;
2256 DPRINTK("CR15 = %x\n", *(regs + S3_CRTC_DATA));
2257 *(regs + S3_CRTC_ADR) = 0x16;
2258 DPRINTK("CR16 = %x\n", *(regs + S3_CRTC_DATA));
2259 *(regs + S3_CRTC_ADR) = 0x36;
2260 DPRINTK("CR36 = %x\n", *(regs + S3_CRTC_DATA));
2261 *(regs + S3_CRTC_ADR) = 0x37;
2262 DPRINTK("CR37 = %x\n", *(regs + S3_CRTC_DATA));
2263 *(regs + S3_CRTC_ADR) = 0x42;
2264 DPRINTK("CR42 = %x\n", *(regs + S3_CRTC_DATA));
2265 *(regs + S3_CRTC_ADR) = 0x43;
2266 DPRINTK("CR43 = %x\n", *(regs + S3_CRTC_DATA));
2267 *(regs + S3_CRTC_ADR) = 0x50;
2268 DPRINTK("CR50 = %x\n", *(regs + S3_CRTC_DATA));
2269 *(regs + S3_CRTC_ADR) = 0x51;
2270 DPRINTK("CR51 = %x\n", *(regs + S3_CRTC_DATA));
2271 *(regs + S3_CRTC_ADR) = 0x53;
2272 DPRINTK("CR53 = %x\n", *(regs + S3_CRTC_DATA));
2273 *(regs + S3_CRTC_ADR) = 0x58;
2274 DPRINTK("CR58 = %x\n", *(regs + S3_CRTC_DATA));
2275 *(regs + S3_CRTC_ADR) = 0x59;
2276 DPRINTK("CR59 = %x\n", *(regs + S3_CRTC_DATA));
2277 *(regs + S3_CRTC_ADR) = 0x5A;
2278 DPRINTK("CR5A = %x\n", *(regs + S3_CRTC_DATA));
2279 *(regs + S3_CRTC_ADR) = 0x5D;
2280 DPRINTK("CR5D = %x\n", *(regs + S3_CRTC_DATA));
2281 *(regs + S3_CRTC_ADR) = 0x5E;
2282 DPRINTK("CR5E = %x\n", *(regs + S3_CRTC_DATA));
2283 DPRINTK("MISC = %x\n", *(regs + GREG_MISC_OUTPUT_R));
2284 *(regs + SEQ_ADDRESS) = 0x01;
2285 DPRINTK("SR01 = %x\n", *(regs + SEQ_ADDRESS_R));
2286 *(regs + SEQ_ADDRESS) = 0x02;
2287 DPRINTK("SR02 = %x\n", *(regs + SEQ_ADDRESS_R));
2288 *(regs + SEQ_ADDRESS) = 0x03;
2289 DPRINTK("SR03 = %x\n", *(regs + SEQ_ADDRESS_R));
2290 *(regs + SEQ_ADDRESS) = 0x09;
2291 DPRINTK("SR09 = %x\n", *(regs + SEQ_ADDRESS_R));
2292 *(regs + SEQ_ADDRESS) = 0x10;
2293 DPRINTK("SR10 = %x\n", *(regs + SEQ_ADDRESS_R));
2294 *(regs + SEQ_ADDRESS) = 0x11;
2295 DPRINTK("SR11 = %x\n", *(regs + SEQ_ADDRESS_R));
2296 *(regs + SEQ_ADDRESS) = 0x12;
2297 DPRINTK("SR12 = %x\n", *(regs + SEQ_ADDRESS_R));
2298 *(regs + SEQ_ADDRESS) = 0x13;
2299 DPRINTK("SR13 = %x\n", *(regs + SEQ_ADDRESS_R));
2300 *(regs + SEQ_ADDRESS) = 0x15;
2301 DPRINTK("SR15 = %x\n", *(regs + SEQ_ADDRESS_R));