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/malloc.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;
126 static int currcon
= 0;
128 static struct display disp
;
129 static struct fb_info fb_info
;
136 static char cyberfb_name
[16] = "Cybervision";
140 * CyberVision Graphics Board
143 static unsigned char Cyber_colour_table
[256][3];
144 static unsigned long CyberSize
;
145 static volatile unsigned char *CyberBase
;
146 static volatile unsigned char *CyberMem
;
147 static volatile unsigned char *CyberRegs
;
148 static unsigned long CyberMem_phys
;
149 static unsigned long CyberRegs_phys
;
152 * Predefined Video Modes
157 struct fb_var_screeninfo var
;
158 } cyberfb_predefined
[] __initdata
= {
159 { "640x480-8", { /* Default 8 BPP mode (cyber8) */
160 640, 480, 640, 480, 0, 0, 8, 0,
161 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
162 0, 0, -1, -1, FB_ACCELF_TEXT
, 39722, 40, 24, 32, 11, 96, 2,
163 FB_SYNC_COMP_HIGH_ACT
|FB_SYNC_VERT_HIGH_ACT
,
164 FB_VMODE_NONINTERLACED
166 { "640x480-16", { /* Default 16 BPP mode (cyber16) */
167 640, 480, 640, 480, 0, 0, 16, 0,
168 {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
169 0, 0, -1, -1, FB_ACCELF_TEXT
, 39722, 40, 24, 32, 11, 96, 2,
170 FB_SYNC_COMP_HIGH_ACT
|FB_SYNC_VERT_HIGH_ACT
,
171 FB_VMODE_NONINTERLACED
173 { "640x480-24", { /* Default 24 BPP mode */
174 640, 480, 640, 480, 0, 0, 24, 0,
175 {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {0, 0, 0},
176 0, 0, -1, -1, FB_ACCELF_TEXT
, 39722, 40, 24, 32, 11, 96, 2,
177 FB_SYNC_COMP_HIGH_ACT
|FB_SYNC_VERT_HIGH_ACT
,
178 FB_VMODE_NONINTERLACED
180 { "800x490-8", { /* Cybervision 8 bpp */
181 /* NO Acceleration */
182 800, 490, 800, 490, 0, 0, 8, 0,
183 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
184 0, 0, -1, -1, FB_ACCEL_NONE
, 33333, 80, 24, 23, 1, 56, 8,
185 FB_SYNC_COMP_HIGH_ACT
|FB_SYNC_VERT_HIGH_ACT
,
186 FB_VMODE_NONINTERLACED
188 /* I can't test these with my monitor, but I suspect they will
189 * be OK, since Antonio Santos indicated he had tested them in
192 { "800x600-8", { /* Cybervision 8 bpp */
193 800, 600, 800, 600, 0, 0, 8, 0,
194 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
195 0, 0, -1, -1, FB_ACCELF_TEXT
, 27778, 64, 24, 22, 1, 72, 2,
196 FB_SYNC_COMP_HIGH_ACT
|FB_SYNC_VERT_HIGH_ACT
,
197 FB_VMODE_NONINTERLACED
199 { "1024x768-8", { /* Cybervision 8 bpp */
200 1024, 768, 1024, 768, 0, 0, 8, 0,
201 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
202 0, 0, -1, -1, FB_ACCELF_TEXT
, 16667, 224, 72, 60, 12, 168, 4,
203 FB_SYNC_COMP_HIGH_ACT
|FB_SYNC_VERT_HIGH_ACT
,
204 FB_VMODE_NONINTERLACED
206 { "1152x886-8", { /* Cybervision 8 bpp */
207 1152, 886, 1152, 886, 0, 0, 8, 0,
208 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
209 0, 0, -1, -1, FB_ACCELF_TEXT
, 15873, 184, 40, 24, 1, 56, 16,
210 FB_SYNC_COMP_HIGH_ACT
|FB_SYNC_VERT_HIGH_ACT
,
211 FB_VMODE_NONINTERLACED
213 { "1280x1024-8", { /* Cybervision 8 bpp */
214 1280, 1024, 1280, 1024, 0, 0, 8, 0,
215 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
216 0, 0, -1, -1, FB_ACCELF_TEXT
, 16667, 256, 48, 50, 12, 72, 4,
217 FB_SYNC_COMP_HIGH_ACT
|FB_SYNC_VERT_HIGH_ACT
,
222 #define NUM_TOTAL_MODES ARRAY_SIZE(cyberfb_predefined)
224 static int Cyberfb_inverse
= 0;
230 #define CYBER8_DEFMODE (0)
231 #define CYBER16_DEFMODE (1)
233 static struct fb_var_screeninfo cyberfb_default
;
234 static int cyberfb_usermode __initdata
= 0;
237 * Interface used by the world
240 int cyberfb_setup(char *options
);
242 static int cyberfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
243 struct fb_info
*info
);
244 static int cyberfb_get_var(struct fb_var_screeninfo
*var
, int con
,
245 struct fb_info
*info
);
246 static int cyberfb_set_var(struct fb_var_screeninfo
*var
, int con
,
247 struct fb_info
*info
);
248 static int cyberfb_get_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
249 struct fb_info
*info
);
250 static int cyberfb_set_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
251 struct fb_info
*info
);
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
);
260 static void Cyberfb_blank(int blank
, struct fb_info
*info
);
263 * Text console acceleration
266 #ifdef FBCON_HAS_CFB8
267 static struct display_switch fbcon_cyber8
;
271 * Accelerated Functions used by the low level console driver
274 static void Cyber_WaitQueue(u_short fifo
);
275 static void Cyber_WaitBlit(void);
276 static void Cyber_BitBLT(u_short curx
, u_short cury
, u_short destx
,
277 u_short desty
, u_short width
, u_short height
,
279 static void Cyber_RectFill(u_short x
, u_short y
, u_short width
, u_short height
,
280 u_short mode
, u_short color
);
282 static void Cyber_MoveCursor(u_short x
, u_short y
);
286 * Hardware Specific Routines
289 static int Cyber_init(void);
290 static int Cyber_encode_fix(struct fb_fix_screeninfo
*fix
,
291 struct cyberfb_par
*par
);
292 static int Cyber_decode_var(struct fb_var_screeninfo
*var
,
293 struct cyberfb_par
*par
);
294 static int Cyber_encode_var(struct fb_var_screeninfo
*var
,
295 struct cyberfb_par
*par
);
296 static int Cyber_getcolreg(u_int regno
, u_int
*red
, u_int
*green
, u_int
*blue
,
297 u_int
*transp
, struct fb_info
*info
);
298 static int Cyber_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
299 u_int transp
, struct fb_info
*info
);
305 static void cyberfb_get_par(struct cyberfb_par
*par
);
306 static void cyberfb_set_par(struct cyberfb_par
*par
);
307 static int do_fb_set_var(struct fb_var_screeninfo
*var
, int isactive
);
308 static void do_install_cmap(int con
, struct fb_info
*info
);
309 static void cyberfb_set_disp(int con
, struct fb_info
*info
);
310 static int get_video_mode(const char *name
);
312 /* For cvision_core.c */
313 static unsigned short cv64_compute_clock(unsigned long);
314 static int cv_has_4mb (volatile unsigned char *);
315 static void cv64_board_init (void);
316 static void cv64_load_video_mode (struct fb_var_screeninfo
*);
319 /* -------------------- Hardware specific routines ------------------------- */
325 * Set the default video mode for this chipset. If a video mode was
326 * specified on the command line, it will override the default mode.
329 static int Cyber_init(void)
331 volatile unsigned char *regs
= CyberRegs
;
332 volatile unsigned long *CursorBase
;
336 /* Init local cmap as greyscale levels */
337 for (i
= 0; i
< 256; i
++) {
338 Cyber_colour_table
[i
][0] = i
;
339 Cyber_colour_table
[i
][1] = i
;
340 Cyber_colour_table
[i
][2] = i
;
343 /* Initialize the board and determine fbmem size */
346 DPRINTK("Register state after initing board\n");
349 /* Clear framebuffer memory */
350 DPRINTK("Clear framebuffer memory\n");
351 memset ((char *)CyberMem
, 0, CyberSize
);
353 /* Disable hardware cursor */
354 DPRINTK("Disable HW cursor\n");
355 wb_64(regs
, S3_CRTC_ADR
, S3_REG_LOCK2
);
356 wb_64(regs
, S3_CRTC_DATA
, 0xa0);
357 wb_64(regs
, S3_CRTC_ADR
, S3_HGC_MODE
);
358 wb_64(regs
, S3_CRTC_DATA
, 0x00);
359 wb_64(regs
, S3_CRTC_ADR
, S3_HWGC_DX
);
360 wb_64(regs
, S3_CRTC_DATA
, 0x00);
361 wb_64(regs
, S3_CRTC_ADR
, S3_HWGC_DY
);
362 wb_64(regs
, S3_CRTC_DATA
, 0x00);
364 /* Initialize hardware cursor */
365 DPRINTK("Init HW cursor\n");
366 CursorBase
= (u_long
*)((char *)(CyberMem
) + CyberSize
- 0x400);
367 for (i
=0; i
< 8; i
++)
369 *(CursorBase
+(i
*4)) = 0xffffff00;
370 *(CursorBase
+1+(i
*4)) = 0xffff0000;
371 *(CursorBase
+2+(i
*4)) = 0xffff0000;
372 *(CursorBase
+3+(i
*4)) = 0xffff0000;
374 for (i
=8; i
< 64; i
++)
376 *(CursorBase
+(i
*4)) = 0xffff0000;
377 *(CursorBase
+1+(i
*4)) = 0xffff0000;
378 *(CursorBase
+2+(i
*4)) = 0xffff0000;
379 *(CursorBase
+3+(i
*4)) = 0xffff0000;
382 Cyber_setcolreg (255, 56<<8, 100<<8, 160<<8, 0, NULL
/* unused */);
383 Cyber_setcolreg (254, 0, 0, 0, 0, NULL
/* unused */);
391 * This function should fill in the `fix' structure based on the
392 * values in the `par' structure.
395 static int Cyber_encode_fix(struct fb_fix_screeninfo
*fix
,
396 struct cyberfb_par
*par
)
399 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
400 strcpy(fix
->id
, cyberfb_name
);
401 fix
->smem_start
= CyberMem_phys
;
402 fix
->smem_len
= CyberSize
;
403 fix
->mmio_start
= CyberRegs_phys
;
404 fix
->mmio_len
= 0x10000;
406 fix
->type
= FB_TYPE_PACKED_PIXELS
;
408 if (par
->var
.bits_per_pixel
== 15 || par
->var
.bits_per_pixel
== 16 ||
409 par
->var
.bits_per_pixel
== 24 || par
->var
.bits_per_pixel
== 32) {
410 fix
->visual
= FB_VISUAL_DIRECTCOLOR
;
412 fix
->visual
= FB_VISUAL_PSEUDOCOLOR
;
418 fix
->line_length
= 0;
419 fix
->accel
= FB_ACCEL_S3_TRIO64
;
427 * Fill the `par' structure based on the values in `var'.
428 * TODO: Verify and adjust values, return -EINVAL if bad.
431 static int Cyber_decode_var(struct fb_var_screeninfo
*var
,
432 struct cyberfb_par
*par
)
435 par
->var
.xres
= var
->xres
;
436 par
->var
.yres
= var
->yres
;
437 par
->var
.xres_virtual
= var
->xres_virtual
;
438 par
->var
.yres_virtual
= var
->yres_virtual
;
439 par
->var
.xoffset
= var
->xoffset
;
440 par
->var
.yoffset
= var
->yoffset
;
441 par
->var
.bits_per_pixel
= var
->bits_per_pixel
;
442 par
->var
.grayscale
= var
->grayscale
;
443 par
->var
.red
= var
->red
;
444 par
->var
.green
= var
->green
;
445 par
->var
.blue
= var
->blue
;
446 par
->var
.transp
= var
->transp
;
447 par
->var
.nonstd
= var
->nonstd
;
448 par
->var
.activate
= var
->activate
;
449 par
->var
.height
= var
->height
;
450 par
->var
.width
= var
->width
;
451 if (var
->accel_flags
& FB_ACCELF_TEXT
) {
452 par
->var
.accel_flags
= FB_ACCELF_TEXT
;
454 par
->var
.accel_flags
= 0;
456 par
->var
.pixclock
= var
->pixclock
;
457 par
->var
.left_margin
= var
->left_margin
;
458 par
->var
.right_margin
= var
->right_margin
;
459 par
->var
.upper_margin
= var
->upper_margin
;
460 par
->var
.lower_margin
= var
->lower_margin
;
461 par
->var
.hsync_len
= var
->hsync_len
;
462 par
->var
.vsync_len
= var
->vsync_len
;
463 par
->var
.sync
= var
->sync
;
464 par
->var
.vmode
= var
->vmode
;
470 * Fill the `var' structure based on the values in `par' and maybe
471 * other values read out of the hardware.
474 static int Cyber_encode_var(struct fb_var_screeninfo
*var
,
475 struct cyberfb_par
*par
)
478 var
->xres
= par
->var
.xres
;
479 var
->yres
= par
->var
.yres
;
480 var
->xres_virtual
= par
->var
.xres_virtual
;
481 var
->yres_virtual
= par
->var
.yres_virtual
;
482 var
->xoffset
= par
->var
.xoffset
;
483 var
->yoffset
= par
->var
.yoffset
;
485 var
->bits_per_pixel
= par
->var
.bits_per_pixel
;
486 var
->grayscale
= par
->var
.grayscale
;
488 var
->red
= par
->var
.red
;
489 var
->green
= par
->var
.green
;
490 var
->blue
= par
->var
.blue
;
491 var
->transp
= par
->var
.transp
;
493 var
->nonstd
= par
->var
.nonstd
;
494 var
->activate
= par
->var
.activate
;
496 var
->height
= par
->var
.height
;
497 var
->width
= par
->var
.width
;
499 var
->accel_flags
= par
->var
.accel_flags
;
501 var
->pixclock
= par
->var
.pixclock
;
502 var
->left_margin
= par
->var
.left_margin
;
503 var
->right_margin
= par
->var
.right_margin
;
504 var
->upper_margin
= par
->var
.upper_margin
;
505 var
->lower_margin
= par
->var
.lower_margin
;
506 var
->hsync_len
= par
->var
.hsync_len
;
507 var
->vsync_len
= par
->var
.vsync_len
;
508 var
->sync
= par
->var
.sync
;
509 var
->vmode
= par
->var
.vmode
;
517 * Set a single color register. Return != 0 for invalid regno.
520 static int Cyber_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
521 u_int transp
, struct fb_info
*info
)
523 volatile unsigned char *regs
= CyberRegs
;
525 /*DPRINTK("ENTER\n");*/
527 DPRINTK("EXIT - Register # > 255\n");
531 wb_64(regs
, 0x3c8, (unsigned char) regno
);
537 Cyber_colour_table
[regno
][0] = red
;
538 Cyber_colour_table
[regno
][1] = green
;
539 Cyber_colour_table
[regno
][2] = blue
;
541 wb_64(regs
, 0x3c9, red
);
542 wb_64(regs
, 0x3c9, green
);
543 wb_64(regs
, 0x3c9, blue
);
545 /*DPRINTK("EXIT\n");*/
551 * Read a single color register and split it into
552 * colors/transparent. Return != 0 for invalid regno.
555 static int Cyber_getcolreg(u_int regno
, u_int
*red
, u_int
*green
, u_int
*blue
,
556 u_int
*transp
, struct fb_info
*info
)
560 /*DPRINTK("ENTER\n");*/
562 DPRINTK("EXIT - Register # > 255\n");
565 /* ARB This shifting & oring seems VERY strange */
566 t
= Cyber_colour_table
[regno
][0];
567 *red
= (t
<<10) | (t
<<4) | (t
>>2);
568 t
= Cyber_colour_table
[regno
][1];
569 *green
= (t
<<10) | (t
<<4) | (t
>>2);
570 t
= Cyber_colour_table
[regno
][2];
571 *blue
= (t
<<10) | (t
<<4) | (t
>>2);
573 /*DPRINTK("EXIT\n");*/
579 * (Un)Blank the screen
580 * blank: 1 = zero fb cmap
581 * 0 = restore fb cmap from local cmap
584 void Cyberfb_blank(int blank
, struct fb_info
*info
)
586 volatile unsigned char *regs
= CyberRegs
;
591 /* Blank by turning gfx off */
592 gfx_on_off (1, regs
);
595 for (i
= 0; i
< 256; i
++) {
596 wb_64(regs
, 0x3c8, (unsigned char) i
);
597 /* ARB Pale red to detect this blanking method */
598 wb_64(regs
, 0x3c9, 48);
599 wb_64(regs
, 0x3c9, 0);
600 wb_64(regs
, 0x3c9, 0);
603 for (i
= 0; i
< 256; i
++) {
604 wb_64(regs
, 0x3c8, (unsigned char) i
);
605 wb_64(regs
, 0x3c9, Cyber_colour_table
[i
][0]);
606 wb_64(regs
, 0x3c9, Cyber_colour_table
[i
][1]);
607 wb_64(regs
, 0x3c9, Cyber_colour_table
[i
][2]);
615 /**************************************************************
616 * We are waiting for "fifo" FIFO-slots empty
618 static void Cyber_WaitQueue (u_short fifo
)
620 unsigned short status
;
624 status
= *((u_short
volatile *)(CyberRegs
+ S3_GP_STAT
));
625 } while (status
& fifo
);
629 /**************************************************************
630 * We are waiting for Hardware (Graphics Engine) not busy
632 static void Cyber_WaitBlit (void)
634 unsigned short status
;
638 status
= *((u_short
volatile *)(CyberRegs
+ S3_GP_STAT
));
639 } while (status
& S3_HDW_BUSY
);
643 /**************************************************************
644 * BitBLT - Through the Plane
646 static void Cyber_BitBLT (u_short curx
, u_short cury
, u_short destx
,
647 u_short desty
, u_short width
, u_short height
,
650 volatile unsigned char *regs
= CyberRegs
;
651 u_short blitcmd
= S3_BITBLT
;
654 /* Set drawing direction */
655 /* -Y, X maj, -X (default) */
657 blitcmd
|= 0x0020; /* Drawing direction +X */
660 destx
+= (width
- 1);
664 blitcmd
|= 0x0080; /* Drawing direction +Y */
666 cury
+= (height
- 1);
667 desty
+= (height
- 1);
670 Cyber_WaitQueue (0x8000);
672 *((u_short
volatile *)(regs
+ S3_PIXEL_CNTL
)) = 0xa000;
673 *((u_short
volatile *)(regs
+ S3_FRGD_MIX
)) = (0x0060 | mode
);
675 *((u_short
volatile *)(regs
+ S3_CUR_X
)) = curx
;
676 *((u_short
volatile *)(regs
+ S3_CUR_Y
)) = cury
;
678 *((u_short
volatile *)(regs
+ S3_DESTX_DIASTP
)) = destx
;
679 *((u_short
volatile *)(regs
+ S3_DESTY_AXSTP
)) = desty
;
681 *((u_short
volatile *)(regs
+ S3_MIN_AXIS_PCNT
)) = height
- 1;
682 *((u_short
volatile *)(regs
+ S3_MAJ_AXIS_PCNT
)) = width
- 1;
684 *((u_short
volatile *)(regs
+ S3_CMD
)) = blitcmd
;
688 /**************************************************************
689 * Rectangle Fill Solid
691 static void Cyber_RectFill (u_short x
, u_short y
, u_short width
,
692 u_short height
, u_short mode
, u_short color
)
694 volatile unsigned char *regs
= CyberRegs
;
695 u_short blitcmd
= S3_FILLEDRECT
;
698 Cyber_WaitQueue (0x8000);
700 *((u_short
volatile *)(regs
+ S3_PIXEL_CNTL
)) = 0xa000;
701 *((u_short
volatile *)(regs
+ S3_FRGD_MIX
)) = (0x0020 | mode
);
703 *((u_short
volatile *)(regs
+ S3_MULT_MISC
)) = 0xe000;
704 *((u_short
volatile *)(regs
+ S3_FRGD_COLOR
)) = color
;
706 *((u_short
volatile *)(regs
+ S3_CUR_X
)) = x
;
707 *((u_short
volatile *)(regs
+ S3_CUR_Y
)) = y
;
709 *((u_short
volatile *)(regs
+ S3_MIN_AXIS_PCNT
)) = height
- 1;
710 *((u_short
volatile *)(regs
+ S3_MAJ_AXIS_PCNT
)) = width
- 1;
712 *((u_short
volatile *)(regs
+ S3_CMD
)) = blitcmd
;
718 /**************************************************************
719 * Move cursor to x, y
721 static void Cyber_MoveCursor (u_short x
, u_short y
)
723 volatile unsigned char *regs
= CyberRegs
;
725 *(regs
+ S3_CRTC_ADR
) = 0x39;
726 *(regs
+ S3_CRTC_DATA
) = 0xa0;
728 *(regs
+ S3_CRTC_ADR
) = S3_HWGC_ORGX_H
;
729 *(regs
+ S3_CRTC_DATA
) = (char)((x
& 0x0700) >> 8);
730 *(regs
+ S3_CRTC_ADR
) = S3_HWGC_ORGX_L
;
731 *(regs
+ S3_CRTC_DATA
) = (char)(x
& 0x00ff);
733 *(regs
+ S3_CRTC_ADR
) = S3_HWGC_ORGY_H
;
734 *(regs
+ S3_CRTC_DATA
) = (char)((y
& 0x0700) >> 8);
735 *(regs
+ S3_CRTC_ADR
) = S3_HWGC_ORGY_L
;
736 *(regs
+ S3_CRTC_DATA
) = (char)(y
& 0x00ff);
742 /* -------------------- Generic routines ---------------------------------- */
746 * Fill the hardware's `par' structure.
749 static void cyberfb_get_par(struct cyberfb_par
*par
)
752 if (current_par_valid
) {
755 Cyber_decode_var(&cyberfb_default
, par
);
761 static void cyberfb_set_par(struct cyberfb_par
*par
)
765 current_par_valid
= 1;
770 static void cyber_set_video(struct fb_var_screeninfo
*var
)
773 /* Load the video mode defined by the 'var' data */
774 cv64_load_video_mode (var
);
776 DPRINTK("Register state after loading video mode\n");
782 static int do_fb_set_var(struct fb_var_screeninfo
*var
, int isactive
)
785 struct cyberfb_par par
;
788 if ((err
= Cyber_decode_var(var
, &par
))) {
789 DPRINTK("EXIT - decode_var failed\n");
792 activate
= var
->activate
;
793 if ((var
->activate
& FB_ACTIVATE_MASK
) == FB_ACTIVATE_NOW
&& isactive
)
794 cyberfb_set_par(&par
);
795 Cyber_encode_var(var
, &par
);
796 var
->activate
= activate
;
798 cyber_set_video(var
);
804 static void do_install_cmap(int con
, struct fb_info
*info
)
807 if (con
!= currcon
) {
808 DPRINTK("EXIT - Not current console\n");
811 if (fb_display
[con
].cmap
.len
) {
812 DPRINTK("Use console cmap\n");
813 fb_set_cmap(&fb_display
[con
].cmap
, 1, Cyber_setcolreg
, info
);
815 DPRINTK("Use default cmap\n");
816 fb_set_cmap(fb_default_cmap(1<<fb_display
[con
].var
.bits_per_pixel
),
817 1, Cyber_setcolreg
, info
);
823 * Get the Fixed Part of the Display
826 static int cyberfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
827 struct fb_info
*info
)
829 struct cyberfb_par par
;
834 cyberfb_get_par(&par
);
836 error
= Cyber_decode_var(&fb_display
[con
].var
, &par
);
839 return(error
? error
: Cyber_encode_fix(fix
, &par
));
844 * Get the User Defined Part of the Display
847 static int cyberfb_get_var(struct fb_var_screeninfo
*var
, int con
,
848 struct fb_info
*info
)
850 struct cyberfb_par par
;
855 cyberfb_get_par(&par
);
856 error
= Cyber_encode_var(var
, &par
);
857 disp
.var
= *var
; /* ++Andre: don't know if this is the right place */
859 *var
= fb_display
[con
].var
;
867 static void cyberfb_set_disp(int con
, struct fb_info
*info
)
869 struct fb_fix_screeninfo fix
;
870 struct display
*display
;
874 display
= &fb_display
[con
];
876 display
= &disp
; /* used during initialization */
878 cyberfb_get_fix(&fix
, con
, info
);
881 display
->screen_base
= (unsigned char *)CyberMem
;
882 display
->visual
= fix
.visual
;
883 display
->type
= fix
.type
;
884 display
->type_aux
= fix
.type_aux
;
885 display
->ypanstep
= fix
.ypanstep
;
886 display
->ywrapstep
= fix
.ywrapstep
;
887 display
->can_soft_blank
= 1;
888 display
->inverse
= Cyberfb_inverse
;
889 switch (display
->var
.bits_per_pixel
) {
890 #ifdef FBCON_HAS_CFB8
892 if (display
->var
.accel_flags
& FB_ACCELF_TEXT
) {
893 display
->dispsw
= &fbcon_cyber8
;
894 #warning FIXME: We should reinit the graphics engine here
896 display
->dispsw
= &fbcon_cfb8
;
899 #ifdef FBCON_HAS_CFB16
901 display
->dispsw
= &fbcon_cfb16
;
905 display
->dispsw
= NULL
;
913 * Set the User Defined Part of the Display
916 static int cyberfb_set_var(struct fb_var_screeninfo
*var
, int con
,
917 struct fb_info
*info
)
919 int err
, oldxres
, oldyres
, oldvxres
, oldvyres
, oldbpp
, oldaccel
;
922 if ((err
= do_fb_set_var(var
, con
== currcon
))) {
923 DPRINTK("EXIT - do_fb_set_var failed\n");
926 if ((var
->activate
& FB_ACTIVATE_MASK
) == FB_ACTIVATE_NOW
) {
927 oldxres
= fb_display
[con
].var
.xres
;
928 oldyres
= fb_display
[con
].var
.yres
;
929 oldvxres
= fb_display
[con
].var
.xres_virtual
;
930 oldvyres
= fb_display
[con
].var
.yres_virtual
;
931 oldbpp
= fb_display
[con
].var
.bits_per_pixel
;
932 oldaccel
= fb_display
[con
].var
.accel_flags
;
933 fb_display
[con
].var
= *var
;
934 if (oldxres
!= var
->xres
|| oldyres
!= var
->yres
||
935 oldvxres
!= var
->xres_virtual
||
936 oldvyres
!= var
->yres_virtual
||
937 oldbpp
!= var
->bits_per_pixel
||
938 oldaccel
!= var
->accel_flags
) {
939 cyberfb_set_disp(con
, info
);
940 (*fb_info
.changevar
)(con
);
941 fb_alloc_cmap(&fb_display
[con
].cmap
, 0, 0);
942 do_install_cmap(con
, info
);
955 static int cyberfb_get_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
956 struct fb_info
*info
)
959 if (con
== currcon
) { /* current console? */
960 DPRINTK("EXIT - console is current console\n");
961 return(fb_get_cmap(cmap
, kspc
, Cyber_getcolreg
, info
));
962 } else if (fb_display
[con
].cmap
.len
) { /* non default colormap? */
963 DPRINTK("Use console cmap\n");
964 fb_copy_cmap(&fb_display
[con
].cmap
, cmap
, kspc
? 0 : 2);
966 DPRINTK("Use default cmap\n");
967 fb_copy_cmap(fb_default_cmap(1<<fb_display
[con
].var
.bits_per_pixel
),
979 static int cyberfb_set_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
980 struct fb_info
*info
)
985 if (!fb_display
[con
].cmap
.len
) { /* no colormap allocated? */
986 if ((err
= fb_alloc_cmap(&fb_display
[con
].cmap
,
987 1<<fb_display
[con
].var
.bits_per_pixel
,
989 DPRINTK("EXIT - fb_alloc_cmap failed\n");
993 if (con
== currcon
) { /* current console? */
994 DPRINTK("EXIT - Current console\n");
995 return(fb_set_cmap(cmap
, kspc
, Cyber_setcolreg
, info
));
997 fb_copy_cmap(cmap
, &fb_display
[con
].cmap
, kspc
? 0 : 1);
1004 static struct fb_ops cyberfb_ops
= {
1006 fb_get_fix
: cyberfb_get_fix
,
1007 fb_get_var
: cyberfb_get_var
,
1008 fb_set_var
: cyberfb_set_var
,
1009 fb_get_cmap
: cyberfb_get_cmap
,
1010 fb_set_cmap
: cyberfb_set_cmap
,
1013 int __init
cyberfb_setup(char *options
)
1018 fb_info
.fontname
[0] = '\0';
1020 if (!options
|| !*options
) {
1021 DPRINTK("EXIT - no options\n");
1025 for (this_opt
= strtok(options
, ","); this_opt
;
1026 this_opt
= strtok(NULL
, ",")) {
1027 if (!strcmp(this_opt
, "inverse")) {
1028 Cyberfb_inverse
= 1;
1030 } else if (!strncmp(this_opt
, "font:", 5)) {
1031 strcpy(fb_info
.fontname
, this_opt
+5);
1032 } else if (!strcmp (this_opt
, "cyber8")) {
1033 cyberfb_default
= cyberfb_predefined
[CYBER8_DEFMODE
].var
;
1034 cyberfb_usermode
= 1;
1035 } else if (!strcmp (this_opt
, "cyber16")) {
1036 cyberfb_default
= cyberfb_predefined
[CYBER16_DEFMODE
].var
;
1037 cyberfb_usermode
= 1;
1038 } else get_video_mode(this_opt
);
1041 DPRINTK("default mode: xres=%d, yres=%d, bpp=%d\n",
1042 cyberfb_default
.xres
,
1043 cyberfb_default
.yres
,
1044 cyberfb_default
.bits_per_pixel
);
1053 int __init
cyberfb_init(void)
1055 unsigned long board_addr
, board_size
;
1056 struct cyberfb_par par
;
1057 struct zorro_dev
*z
= NULL
;
1060 while ((z
= zorro_find_device(ZORRO_PROD_PHASE5_CYBERVISION64
, z
))) {
1061 board_addr
= z
->resource
.start
;
1062 board_size
= z
->resource
.end
-z
->resource
.start
+1;
1063 CyberMem_phys
= board_addr
+ 0x01400000;
1064 CyberRegs_phys
= CyberMem_phys
+ 0x00c00000;
1065 if (!request_mem_region(CyberRegs_phys
, 0x10000, "S3 Trio64"))
1067 if (!request_mem_region(CyberMem_phys
, 0x400000, "RAM")) {
1068 release_mem_region(CyberRegs_phys
, 0x10000);
1071 DPRINTK("board_addr=%08lx\n", board_addr
);
1072 DPRINTK("board_size=%08lx\n", board_size
);
1074 CyberBase
= ioremap(board_addr
, board_size
);
1075 CyberRegs
= CyberBase
+ 0x02000000;
1076 CyberMem
= CyberBase
+ 0x01400000;
1077 DPRINTK("CyberBase=%08lx CyberRegs=%08lx CyberMem=%08lx\n",
1078 CyberBase
, (long unsigned int)CyberRegs
, CyberMem
);
1081 DPRINTK("Register state just after mapping memory\n");
1085 strcpy(fb_info
.modename
, cyberfb_name
);
1086 fb_info
.changevar
= NULL
;
1088 fb_info
.fbops
= &cyberfb_ops
;
1089 fb_info
.disp
= &disp
;
1090 fb_info
.switch_con
= &Cyberfb_switch
;
1091 fb_info
.updatevar
= &Cyberfb_updatevar
;
1092 fb_info
.blank
= &Cyberfb_blank
;
1095 /* ++Andre: set cyberfb default mode */
1096 if (!cyberfb_usermode
) {
1097 cyberfb_default
= cyberfb_predefined
[CYBER8_DEFMODE
].var
;
1098 DPRINTK("Use default cyber8 mode\n");
1100 Cyber_decode_var(&cyberfb_default
, &par
);
1101 Cyber_encode_var(&cyberfb_default
, &par
);
1103 do_fb_set_var(&cyberfb_default
, 1);
1104 cyberfb_get_var(&fb_display
[0].var
, -1, &fb_info
);
1105 cyberfb_set_disp(-1, &fb_info
);
1106 do_install_cmap(0, &fb_info
);
1108 if (register_framebuffer(&fb_info
) < 0) {
1109 DPRINTK("EXIT - register_framebuffer failed\n");
1110 release_mem_region(CyberMem_phys
, 0x400000);
1111 release_mem_region(CyberRegs_phys
, 0x10000);
1115 printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
1116 GET_FB_IDX(fb_info
.node
), fb_info
.modename
, CyberSize
>>10);
1118 /* TODO: This driver cannot be unloaded yet */
1127 static int Cyberfb_switch(int con
, struct fb_info
*info
)
1130 /* Do we have to save the colormap? */
1131 if (fb_display
[currcon
].cmap
.len
) {
1132 fb_get_cmap(&fb_display
[currcon
].cmap
, 1, Cyber_getcolreg
,
1136 do_fb_set_var(&fb_display
[con
].var
, 1);
1138 /* Install new colormap */
1139 do_install_cmap(con
, info
);
1146 * Update the `var' structure (called by fbcon.c)
1148 * This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
1149 * Since it's called by a kernel driver, no range checking is done.
1152 static int Cyberfb_updatevar(int con
, struct fb_info
*info
)
1154 DPRINTK("Enter - Exit\n");
1163 static int __init
get_video_mode(const char *name
)
1168 for (i
= 0; i
< NUM_TOTAL_MODES
; i
++) {
1169 if (!strcmp(name
, cyberfb_predefined
[i
].name
)) {
1170 cyberfb_default
= cyberfb_predefined
[i
].var
;
1171 cyberfb_usermode
= 1;
1172 DPRINTK("EXIT - Matched predefined mode\n");
1181 * Text console acceleration
1184 #ifdef FBCON_HAS_CFB8
1185 static void fbcon_cyber8_bmove(struct display
*p
, int sy
, int sx
, int dy
,
1186 int dx
, int height
, int width
)
1189 sx
*= 8; dx
*= 8; width
*= 8;
1190 Cyber_BitBLT((u_short
)sx
, (u_short
)(sy
*fontheight(p
)), (u_short
)dx
,
1191 (u_short
)(dy
*fontheight(p
)), (u_short
)width
,
1192 (u_short
)(height
*fontheight(p
)), (u_short
)S3_NEW
);
1196 static void fbcon_cyber8_clear(struct vc_data
*conp
, struct display
*p
, int sy
,
1197 int sx
, int height
, int width
)
1202 sx
*= 8; width
*= 8;
1203 bg
= attr_bgcol_ec(p
,conp
);
1204 Cyber_RectFill((u_short
)sx
,
1205 (u_short
)(sy
*fontheight(p
)),
1207 (u_short
)(height
*fontheight(p
)),
1213 static void fbcon_cyber8_putc(struct vc_data
*conp
, struct display
*p
, int c
,
1218 fbcon_cfb8_putc(conp
, p
, c
, yy
, xx
);
1222 static void fbcon_cyber8_putcs(struct vc_data
*conp
, struct display
*p
,
1223 const unsigned short *s
, int count
,
1228 fbcon_cfb8_putcs(conp
, p
, s
, count
, yy
, xx
);
1232 static void fbcon_cyber8_revc(struct display
*p
, int xx
, int yy
)
1236 fbcon_cfb8_revc(p
, xx
, yy
);
1240 static struct display_switch fbcon_cyber8
= {
1241 setup
: fbcon_cfb8_setup
,
1242 bmove
: fbcon_cyber8_bmove
,
1243 clear
: fbcon_cyber8_clear
,
1244 putc
: fbcon_cyber8_putc
,
1245 putcs
: fbcon_cyber8_putcs
,
1246 revc
: fbcon_cyber8_revc
,
1247 clear_margins
: fbcon_cfb8_clear_margins
,
1248 fontwidthmask
: FONTWIDTH(8)
1254 int init_module(void)
1256 return cyberfb_init();
1259 void cleanup_module(void)
1261 /* Not reached because the usecount will never be
1262 decremented to zero */
1263 unregister_framebuffer(&fb_info
);
1264 /* TODO: clean up ... */
1270 * Low level initialization routines for the CyberVision64 graphics card
1272 * Most of the following code is from cvision_core.c
1276 #define MAXPIXELCLOCK 135000000 /* safety */
1278 #ifdef CV_AGGRESSIVE_TIMING
1279 long cv64_memclk
= 55000000;
1281 long cv64_memclk
= 50000000;
1284 /*********************/
1286 static unsigned char clocks
[]={
1287 0x13, 0x61, 0x6b, 0x6d, 0x51, 0x69, 0x54, 0x69,
1288 0x4f, 0x68, 0x6b, 0x6b, 0x18, 0x61, 0x7b, 0x6c,
1289 0x51, 0x67, 0x24, 0x62, 0x56, 0x67, 0x77, 0x6a,
1290 0x1d, 0x61, 0x53, 0x66, 0x6b, 0x68, 0x79, 0x69,
1291 0x7c, 0x69, 0x7f, 0x69, 0x22, 0x61, 0x54, 0x65,
1292 0x56, 0x65, 0x58, 0x65, 0x67, 0x66, 0x41, 0x63,
1293 0x27, 0x61, 0x13, 0x41, 0x37, 0x62, 0x6b, 0x4d,
1294 0x23, 0x43, 0x51, 0x49, 0x79, 0x66, 0x54, 0x49,
1295 0x7d, 0x66, 0x34, 0x56, 0x4f, 0x63, 0x1f, 0x42,
1296 0x6b, 0x4b, 0x7e, 0x4d, 0x18, 0x41, 0x2a, 0x43,
1297 0x7b, 0x4c, 0x74, 0x4b, 0x51, 0x47, 0x65, 0x49,
1298 0x24, 0x42, 0x68, 0x49, 0x56, 0x47, 0x75, 0x4a,
1299 0x77, 0x4a, 0x31, 0x43, 0x1d, 0x41, 0x71, 0x49,
1300 0x53, 0x46, 0x29, 0x42, 0x6b, 0x48, 0x1f, 0x41,
1301 0x79, 0x49, 0x6f, 0x48, 0x7c, 0x49, 0x38, 0x43,
1302 0x7f, 0x49, 0x5d, 0x46, 0x22, 0x41, 0x53, 0x45,
1303 0x54, 0x45, 0x55, 0x45, 0x56, 0x45, 0x57, 0x45,
1304 0x58, 0x45, 0x25, 0x41, 0x67, 0x46, 0x5b, 0x45,
1305 0x41, 0x43, 0x78, 0x47, 0x27, 0x41, 0x51, 0x44,
1306 0x13, 0x21, 0x7d, 0x47, 0x37, 0x42, 0x71, 0x46,
1307 0x6b, 0x2d, 0x14, 0x21, 0x23, 0x23, 0x7d, 0x2f,
1308 0x51, 0x29, 0x61, 0x2b, 0x79, 0x46, 0x1d, 0x22,
1309 0x54, 0x29, 0x45, 0x27, 0x7d, 0x46, 0x7f, 0x46,
1310 0x4f, 0x43, 0x2f, 0x41, 0x1f, 0x22, 0x6a, 0x2b,
1311 0x6b, 0x2b, 0x5b, 0x29, 0x7e, 0x2d, 0x65, 0x44,
1312 0x18, 0x21, 0x5e, 0x29, 0x2a, 0x23, 0x45, 0x26,
1313 0x7b, 0x2c, 0x19, 0x21, 0x74, 0x2b, 0x75, 0x2b,
1314 0x51, 0x27, 0x3f, 0x25, 0x65, 0x29, 0x40, 0x25,
1315 0x24, 0x22, 0x41, 0x25, 0x68, 0x29, 0x42, 0x25,
1316 0x56, 0x27, 0x7e, 0x2b, 0x75, 0x2a, 0x1c, 0x21,
1317 0x77, 0x2a, 0x4f, 0x26, 0x31, 0x23, 0x6f, 0x29,
1318 0x1d, 0x21, 0x32, 0x23, 0x71, 0x29, 0x72, 0x29,
1319 0x53, 0x26, 0x69, 0x28, 0x29, 0x22, 0x75, 0x29,
1320 0x6b, 0x28, 0x1f, 0x21, 0x1f, 0x21, 0x6d, 0x28,
1321 0x79, 0x29, 0x2b, 0x22, 0x6f, 0x28, 0x59, 0x26,
1322 0x7c, 0x29, 0x7d, 0x29, 0x38, 0x23, 0x21, 0x21,
1323 0x7f, 0x29, 0x39, 0x23, 0x5d, 0x26, 0x75, 0x28,
1324 0x22, 0x21, 0x77, 0x28, 0x53, 0x25, 0x6c, 0x27,
1325 0x54, 0x25, 0x61, 0x26, 0x55, 0x25, 0x30, 0x22,
1326 0x56, 0x25, 0x63, 0x26, 0x57, 0x25, 0x71, 0x27,
1327 0x58, 0x25, 0x7f, 0x28, 0x25, 0x21, 0x74, 0x27,
1328 0x67, 0x26, 0x40, 0x23, 0x5b, 0x25, 0x26, 0x21,
1329 0x41, 0x23, 0x34, 0x22, 0x78, 0x27, 0x6b, 0x26,
1330 0x27, 0x21, 0x35, 0x22, 0x51, 0x24, 0x7b, 0x27,
1331 0x13, 0x1, 0x13, 0x1, 0x7d, 0x27, 0x4c, 0x9,
1332 0x37, 0x22, 0x5b, 0xb, 0x71, 0x26, 0x5c, 0xb,
1333 0x6b, 0xd, 0x47, 0x23, 0x14, 0x1, 0x4f, 0x9,
1334 0x23, 0x3, 0x75, 0x26, 0x7d, 0xf, 0x1c, 0x2,
1335 0x51, 0x9, 0x59, 0x24, 0x61, 0xb, 0x69, 0x25,
1336 0x79, 0x26, 0x34, 0x5, 0x1d, 0x2, 0x6b, 0x25,
1337 0x54, 0x9, 0x35, 0x5, 0x45, 0x7, 0x6d, 0x25,
1338 0x7d, 0x26, 0x16, 0x1, 0x7f, 0x26, 0x77, 0xd,
1339 0x4f, 0x23, 0x78, 0xd, 0x2f, 0x21, 0x27, 0x3,
1340 0x1f, 0x2, 0x59, 0x9, 0x6a, 0xb, 0x73, 0x25,
1341 0x6b, 0xb, 0x63, 0x24, 0x5b, 0x9, 0x20, 0x2,
1342 0x7e, 0xd, 0x4b, 0x7, 0x65, 0x24, 0x43, 0x22,
1343 0x18, 0x1, 0x6f, 0xb, 0x5e, 0x9, 0x70, 0xb,
1344 0x2a, 0x3, 0x33, 0x4, 0x45, 0x6, 0x60, 0x9,
1345 0x7b, 0xc, 0x19, 0x1, 0x19, 0x1, 0x7d, 0xc,
1346 0x74, 0xb, 0x50, 0x7, 0x75, 0xb, 0x63, 0x9,
1347 0x51, 0x7, 0x23, 0x2, 0x3f, 0x5, 0x1a, 0x1,
1348 0x65, 0x9, 0x2d, 0x3, 0x40, 0x5, 0x0, 0x0,
1351 /* Console colors */
1352 unsigned char cvconscolors
[16][3] = { /* background, foreground, hilite */
1372 /* -------------------- Hardware specific routines ------------------------- */
1374 /* Read Attribute Controller Register=idx */
1375 inline unsigned char RAttr (volatile unsigned char *regs
, short idx
)
1377 wb_64 (regs
, ACT_ADDRESS_W
, idx
);
1380 return (rb_64(regs
, ACT_ADDRESS_R
));
1383 /* Read Sequencer Register=idx */
1384 inline unsigned char RSeq (volatile unsigned char *regs
, short idx
)
1386 wb_64 (regs
, SEQ_ADDRESS
, idx
);
1388 return (rb_64(regs
, SEQ_ADDRESS_R
));
1391 /* Read CRT Controller Register=idx */
1392 inline unsigned char RCrt (volatile unsigned char *regs
, short idx
)
1394 wb_64 (regs
, CRT_ADDRESS
, idx
);
1396 return (rb_64(regs
, CRT_ADDRESS_R
));
1399 /* Read Graphics Controller Register=idx */
1400 inline unsigned char RGfx (volatile unsigned char *regs
, short idx
)
1402 wb_64 (regs
, GCT_ADDRESS
, idx
);
1404 return (rb_64(regs
, GCT_ADDRESS_R
));
1408 * Special wakeup/passthrough registers on graphics boards
1411 inline void cv64_write_port (unsigned short bits
,
1412 volatile unsigned char *base
)
1414 volatile unsigned char *addr
;
1415 static unsigned char cvportbits
= 0; /* Mirror port bits here */
1418 addr
= base
+ 0x40001;
1419 if (bits
& 0x8000) {
1420 cvportbits
|= bits
& 0xff; /* Set bits */
1421 DPRINTK("Set bits: %04x\n", bits
);
1424 bits
= (~bits
) & 0xff;
1425 cvportbits
&= bits
; /* Clear bits */
1426 DPRINTK("Clear bits: %04x\n", bits
);
1434 * Monitor switch on CyberVision board
1437 * 0 = CyberVision Signal
1439 * board = board addr
1442 inline void cvscreen (int toggle
, volatile unsigned char *board
)
1446 DPRINTK("Show Amiga video\n");
1447 cv64_write_port (0x10, board
);
1449 DPRINTK("Show CyberVision video\n");
1450 cv64_write_port (0x8010, board
);
1455 /* Control screen display */
1456 /* toggle: 0 = on, 1 = off */
1457 /* board = registerbase */
1458 inline void gfx_on_off(int toggle
, volatile unsigned char *regs
)
1464 toggle
= toggle
<< 5;
1465 DPRINTK("Turn display %s\n", (toggle
? "off" : "on"));
1467 r
= (int) RSeq(regs
, SEQ_ID_CLOCKING_MODE
);
1468 r
&= 0xdf; /* Set bit 5 to 0 */
1470 WSeq (regs
, SEQ_ID_CLOCKING_MODE
, r
| toggle
);
1475 * Computes M, N, and R values from
1476 * given input frequency. It uses a table of
1477 * precomputed values, to keep CPU time low.
1479 * The return value consist of:
1480 * lower byte: Bits 4-0: N Divider Value
1481 * Bits 5-6: R Value for e.g. SR10 or SR12
1482 * higher byte: Bits 0-6: M divider value for e.g. SR11 or SR13
1484 static unsigned short cv64_compute_clock(unsigned long freq
)
1486 static unsigned char *mnr
, *save
; /* M, N + R vals */
1487 unsigned long work_freq
, r
;
1492 if (freq
< 12500000 || freq
> MAXPIXELCLOCK
) {
1493 printk("CV64 driver: Illegal clock frequency %ld, using 25MHz\n",
1497 DPRINTK("Freq = %ld\n", freq
);
1498 mnr
= clocks
; /* there the vals are stored */
1501 while (*mnr
) { /* mnr vals are 0-terminated */
1502 work_freq
= (0x37EE * (mnr
[0] + 2)) / ((mnr
[1] & 0x1F) + 2);
1504 r
= (mnr
[1] >> 5) & 0x03;
1506 work_freq
= work_freq
>> r
; /* r is the freq divider */
1509 work_freq
*= 0x3E8; /* 2nd part of OSC */
1511 diff
= abs(freq
- work_freq
);
1515 /* In save are the vals for minimal diff */
1520 erg
= *((unsigned short *)save
);
1526 static int cv_has_4mb (volatile unsigned char *fb
)
1528 volatile unsigned long *tr
, *tw
;
1531 /* write patterns in memory and test if they can be read */
1532 tw
= (volatile unsigned long *) fb
;
1533 tr
= (volatile unsigned long *) (fb
+ 0x02000000);
1537 if (*tr
!= 0x87654321) {
1538 DPRINTK("EXIT - <4MB\n");
1542 /* upper memory region */
1543 tw
= (volatile unsigned long *) (fb
+ 0x00200000);
1544 tr
= (volatile unsigned long *) (fb
+ 0x02200000);
1548 if (*tr
!= 0x87654321) {
1549 DPRINTK("EXIT - <4MB\n");
1555 if (*tr
!= 0xAAAAAAAA) {
1556 DPRINTK("EXIT - <4MB\n");
1562 if (*tr
!= 0x55555555) {
1563 DPRINTK("EXIT - <4MB\n");
1571 static void cv64_board_init (void)
1573 volatile unsigned char *regs
= CyberRegs
;
1575 unsigned int clockpar
;
1581 * Special CyberVision 64 board operations
1584 for (i
= 0; i
< 6; i
++) {
1585 cv64_write_port (0xff, CyberBase
);
1587 /* Return to operational mode */
1588 cv64_write_port (0x8004, CyberBase
);
1591 * Generic (?) S3 chip wakeup
1593 /* Disable I/O & memory decoders, video in setup mode */
1594 wb_64 (regs
, SREG_VIDEO_SUBS_ENABLE
, 0x10);
1595 /* Video responds to cmds, addrs & data */
1596 wb_64 (regs
, SREG_OPTION_SELECT
, 0x1);
1597 /* Enable I/O & memory decoders, video in operational mode */
1598 wb_64 (regs
, SREG_VIDEO_SUBS_ENABLE
, 0x8);
1599 /* VGA color emulation, enable cpu access to display mem */
1600 wb_64 (regs
, GREG_MISC_OUTPUT_W
, 0x03);
1601 /* Unlock S3 VGA regs */
1602 WCrt (regs
, CRT_ID_REGISTER_LOCK_1
, 0x48);
1603 /* Unlock system control & extension registers */
1604 WCrt (regs
, CRT_ID_REGISTER_LOCK_2
, 0xA5);
1605 /* GRF - Enable interrupts */
1606 /* Enable enhanced regs access, Ready cntl 0 wait states */
1607 test
= RCrt (regs
, CRT_ID_SYSTEM_CONFIG
);
1608 test
= test
| 0x01; /* enable enhanced register access */
1609 test
= test
& 0xEF; /* clear bit 4, 0 wait state */
1610 WCrt (regs
, CRT_ID_SYSTEM_CONFIG
, test
);
1612 * bit 0=1: Enable enhaced mode functions
1613 * bit 2=0: Enhanced mode 8+ bits/pixel
1614 * bit 4=1: Enable linear addressing
1615 * bit 5=1: Enable MMIO
1617 wb_64 (regs
, ECR_ADV_FUNC_CNTL
, 0x31);
1619 * bit 0=1: Color emulation
1620 * bit 1=1: Enable CPU access to display memory
1621 * bit 5=1: Select high 64K memory page
1624 wb_64 (regs
, GREG_MISC_OUTPUT_W
, 0x23);
1627 WCrt (regs
, CRT_ID_EXT_SYS_CNTL_4
, 0x0);
1629 /* Reset. This does nothing on Trio, but standard VGA practice */
1630 /* WSeq (CyberRegs, SEQ_ID_RESET, 0x03); */
1631 /* Character clocks 8 dots wide */
1632 WSeq (regs
, SEQ_ID_CLOCKING_MODE
, 0x01);
1633 /* Enable cpu write to all color planes */
1634 WSeq (regs
, SEQ_ID_MAP_MASK
, 0x0F);
1635 /* Font table in 1st 8k of plane 2, font A=B disables swtich */
1636 WSeq (regs
, SEQ_ID_CHAR_MAP_SELECT
, 0x0);
1637 /* Allow mem access to 256kb */
1638 WSeq (regs
, SEQ_ID_MEMORY_MODE
, 0x2);
1639 /* Unlock S3 extensions to VGA Sequencer regs */
1640 WSeq (regs
, SEQ_ID_UNLOCK_EXT
, 0x6);
1642 /* Enable 4MB fast page mode */
1643 test
= RSeq (regs
, SEQ_ID_BUS_REQ_CNTL
);
1644 test
= test
| 1 << 6;
1645 WSeq (regs
, SEQ_ID_BUS_REQ_CNTL
, test
);
1647 /* Faster LUT write: 1 DCLK LUT write cycle, RAMDAC clk doubled */
1648 WSeq (regs
, SEQ_ID_RAMDAC_CNTL
, 0xC0);
1650 /* Clear immediate clock load bit */
1651 test
= RSeq (regs
, SEQ_ID_CLKSYN_CNTL_2
);
1653 /* If > 55MHz, enable 2 cycle memory write */
1654 if (cv64_memclk
>= 55000000) {
1657 WSeq (regs
, SEQ_ID_CLKSYN_CNTL_2
, test
);
1659 /* Set MCLK value */
1660 clockpar
= cv64_compute_clock (cv64_memclk
);
1661 test
= (clockpar
& 0xFF00) >> 8;
1662 WSeq (regs
, SEQ_ID_MCLK_HI
, test
);
1663 test
= clockpar
& 0xFF;
1664 WSeq (regs
, SEQ_ID_MCLK_LO
, test
);
1666 /* Chip rev specific: Not in my Trio manual!!! */
1667 if (RCrt (regs
, CRT_ID_REVISION
) == 0x10)
1668 WSeq (regs
, SEQ_ID_MORE_MAGIC
, test
);
1670 /* We now load an 25 MHz, 31kHz, 640x480 standard VGA Mode. */
1672 /* Set DCLK value */
1673 WSeq (regs
, SEQ_ID_DCLK_HI
, 0x13);
1674 WSeq (regs
, SEQ_ID_DCLK_LO
, 0x41);
1676 /* Load DCLK (and MCLK?) immediately */
1677 test
= RSeq (regs
, SEQ_ID_CLKSYN_CNTL_2
);
1679 WSeq (regs
, SEQ_ID_CLKSYN_CNTL_2
, test
);
1681 /* Enable loading of DCLK */
1682 test
= rb_64(regs
, GREG_MISC_OUTPUT_R
);
1684 wb_64 (regs
, GREG_MISC_OUTPUT_W
, test
);
1686 /* Turn off immediate xCLK load */
1687 WSeq (regs
, SEQ_ID_CLKSYN_CNTL_2
, 0x2);
1689 /* Horizontal character clock counts */
1690 /* 8 LSB of 9 bits = total line - 5 */
1691 WCrt (regs
, CRT_ID_HOR_TOTAL
, 0x5F);
1692 /* Active display line */
1693 WCrt (regs
, CRT_ID_HOR_DISP_ENA_END
, 0x4F);
1694 /* Blank assertion start */
1695 WCrt (regs
, CRT_ID_START_HOR_BLANK
, 0x50);
1696 /* Blank assertion end */
1697 WCrt (regs
, CRT_ID_END_HOR_BLANK
, 0x82);
1698 /* HSYNC assertion start */
1699 WCrt (regs
, CRT_ID_START_HOR_RETR
, 0x54);
1700 /* HSYNC assertion end */
1701 WCrt (regs
, CRT_ID_END_HOR_RETR
, 0x80);
1702 WCrt (regs
, CRT_ID_VER_TOTAL
, 0xBF);
1703 WCrt (regs
, CRT_ID_OVERFLOW
, 0x1F);
1704 WCrt (regs
, CRT_ID_PRESET_ROW_SCAN
, 0x0);
1705 WCrt (regs
, CRT_ID_MAX_SCAN_LINE
, 0x40);
1706 WCrt (regs
, CRT_ID_CURSOR_START
, 0x00);
1707 WCrt (regs
, CRT_ID_CURSOR_END
, 0x00);
1708 WCrt (regs
, CRT_ID_START_ADDR_HIGH
, 0x00);
1709 WCrt (regs
, CRT_ID_START_ADDR_LOW
, 0x00);
1710 WCrt (regs
, CRT_ID_CURSOR_LOC_HIGH
, 0x00);
1711 WCrt (regs
, CRT_ID_CURSOR_LOC_LOW
, 0x00);
1712 WCrt (regs
, CRT_ID_START_VER_RETR
, 0x9C);
1713 WCrt (regs
, CRT_ID_END_VER_RETR
, 0x0E);
1714 WCrt (regs
, CRT_ID_VER_DISP_ENA_END
, 0x8F);
1715 WCrt (regs
, CRT_ID_SCREEN_OFFSET
, 0x50);
1716 WCrt (regs
, CRT_ID_UNDERLINE_LOC
, 0x00);
1717 WCrt (regs
, CRT_ID_START_VER_BLANK
, 0x96);
1718 WCrt (regs
, CRT_ID_END_VER_BLANK
, 0xB9);
1719 WCrt (regs
, CRT_ID_MODE_CONTROL
, 0xE3);
1720 WCrt (regs
, CRT_ID_LINE_COMPARE
, 0xFF);
1721 WCrt (regs
, CRT_ID_BACKWAD_COMP_3
, 0x10); /* FIFO enabled */
1722 WCrt (regs
, CRT_ID_MISC_1
, 0x35);
1723 WCrt (regs
, CRT_ID_DISPLAY_FIFO
, 0x5A);
1724 WCrt (regs
, CRT_ID_EXT_MEM_CNTL_2
, 0x70);
1725 WCrt (regs
, CRT_ID_LAW_POS_LO
, 0x40);
1726 WCrt (regs
, CRT_ID_EXT_MEM_CNTL_3
, 0xFF);
1728 WGfx (regs
, GCT_ID_SET_RESET
, 0x0);
1729 WGfx (regs
, GCT_ID_ENABLE_SET_RESET
, 0x0);
1730 WGfx (regs
, GCT_ID_COLOR_COMPARE
, 0x0);
1731 WGfx (regs
, GCT_ID_DATA_ROTATE
, 0x0);
1732 WGfx (regs
, GCT_ID_READ_MAP_SELECT
, 0x0);
1733 WGfx (regs
, GCT_ID_GRAPHICS_MODE
, 0x40);
1734 WGfx (regs
, GCT_ID_MISC
, 0x01);
1735 WGfx (regs
, GCT_ID_COLOR_XCARE
, 0x0F);
1736 WGfx (regs
, GCT_ID_BITMASK
, 0xFF);
1738 /* Colors for text mode */
1739 for (i
= 0; i
< 0xf; i
++)
1742 WAttr (regs
, ACT_ID_ATTR_MODE_CNTL
, 0x41);
1743 WAttr (regs
, ACT_ID_OVERSCAN_COLOR
, 0x01);
1744 WAttr (regs
, ACT_ID_COLOR_PLANE_ENA
, 0x0F);
1745 WAttr (regs
, ACT_ID_HOR_PEL_PANNING
, 0x0);
1746 WAttr (regs
, ACT_ID_COLOR_SELECT
, 0x0);
1748 wb_64 (regs
, VDAC_MASK
, 0xFF);
1750 *((unsigned long *) (regs
+ ECR_FRGD_COLOR
)) = 0xFF;
1751 *((unsigned long *) (regs
+ ECR_BKGD_COLOR
)) = 0;
1753 /* Colors initially set to grayscale */
1755 wb_64 (regs
, VDAC_ADDRESS_W
, 0);
1756 for (i
= 255; i
>= 0; i
--) {
1757 wb_64(regs
, VDAC_DATA
, i
);
1758 wb_64(regs
, VDAC_DATA
, i
);
1759 wb_64(regs
, VDAC_DATA
, i
);
1762 /* GFx hardware cursor off */
1763 WCrt (regs
, CRT_ID_HWGC_MODE
, 0x00);
1765 /* Set first to 4MB, so test will work */
1766 WCrt (regs
, CRT_ID_LAW_CNTL
, 0x13);
1767 /* Find "correct" size of fbmem of Z3 board */
1768 if (cv_has_4mb (CyberMem
)) {
1769 CyberSize
= 1024 * 1024 * 4;
1770 WCrt (regs
, CRT_ID_LAW_CNTL
, 0x13);
1771 DPRINTK("4MB board\n");
1773 CyberSize
= 1024 * 1024 * 2;
1774 WCrt (regs
, CRT_ID_LAW_CNTL
, 0x12);
1775 DPRINTK("2MB board\n");
1778 /* Initialize graphics engine */
1780 vgaw16 (regs
, ECR_FRGD_MIX
, 0x27);
1781 vgaw16 (regs
, ECR_BKGD_MIX
, 0x07);
1782 vgaw16 (regs
, ECR_READ_REG_DATA
, 0x1000);
1784 vgaw16 (regs
, ECR_READ_REG_DATA
, 0x2000);
1786 vgaw16 (regs
, ECR_READ_REG_DATA
, 0x3FFF);
1789 vgaw16 (regs
, ECR_READ_REG_DATA
, 0x4FFF);
1791 vgaw16 (regs
, ECR_BITPLANE_WRITE_MASK
, ~0);
1793 vgaw16 (regs
, ECR_READ_REG_DATA
, 0xE000);
1794 vgaw16 (regs
, ECR_CURRENT_Y_POS2
, 0x00);
1795 vgaw16 (regs
, ECR_CURRENT_X_POS2
, 0x00);
1796 vgaw16 (regs
, ECR_READ_REG_DATA
, 0xA000);
1797 vgaw16 (regs
, ECR_DEST_Y__AX_STEP
, 0x00);
1798 vgaw16 (regs
, ECR_DEST_Y2__AX_STEP2
, 0x00);
1799 vgaw16 (regs
, ECR_DEST_X__DIA_STEP
, 0x00);
1800 vgaw16 (regs
, ECR_DEST_X2__DIA_STEP2
, 0x00);
1801 vgaw16 (regs
, ECR_SHORT_STROKE
, 0x00);
1802 vgaw16 (regs
, ECR_DRAW_CMD
, 0x01);
1806 vgaw16 (regs
, ECR_READ_REG_DATA
, 0x4FFF);
1807 vgaw16 (regs
, ECR_BKGD_COLOR
, 0x01);
1808 vgaw16 (regs
, ECR_FRGD_COLOR
, 0x00);
1811 /* Enable video display (set bit 5) */
1812 /* ARB - Would also seem to write to AR13.
1813 * May want to use parts of WAttr to set JUST bit 5
1815 WAttr (regs
, 0x33, 0);
1817 /* GRF - function code ended here */
1819 /* Turn gfx on again */
1820 gfx_on_off (0, regs
);
1823 cvscreen (0, CyberBase
);
1828 static void cv64_load_video_mode (struct fb_var_screeninfo
*video_mode
)
1830 volatile unsigned char *regs
= CyberRegs
;
1833 unsigned short HT
, HDE
, HBS
, HBE
, HSS
, HSE
, VDE
, VBS
, VBE
, VSS
, VSE
, VT
;
1834 char LACE
, DBLSCAN
, TEXT
, CONSOLE
;
1835 int cr50
, sr15
, sr18
, clock_mode
, test
;
1837 int tfillm
, temptym
;
1840 /* ---------------- */
1841 int xres
, hfront
, hsync
, hback
;
1842 int yres
, vfront
, vsync
, vback
;
1848 /* ---------------- */
1851 TEXT
= 0; /* if depth == 4 */
1852 CONSOLE
= 0; /* mode num == 255 (console) */
1853 fx
= fy
= 8; /* force 8x8 font */
1855 /* GRF - Disable interrupts */
1857 gfx_on_off (1, regs
);
1859 switch (video_mode
->bits_per_pixel
) {
1870 bpp
= video_mode
->bits_per_pixel
;
1871 xres
= video_mode
->xres
;
1872 hfront
= video_mode
->right_margin
;
1873 hsync
= video_mode
->hsync_len
;
1874 hback
= video_mode
->left_margin
;
1879 if (video_mode
->vmode
& FB_VMODE_DOUBLE
) {
1880 yres
= video_mode
->yres
* 2;
1881 vfront
= video_mode
->lower_margin
* 2;
1882 vsync
= video_mode
->vsync_len
* 2;
1883 vback
= video_mode
->upper_margin
* 2;
1885 } else if (video_mode
->vmode
& FB_VMODE_INTERLACED
) {
1886 yres
= (video_mode
->yres
+ 1) / 2;
1887 vfront
= (video_mode
->lower_margin
+ 1) / 2;
1888 vsync
= (video_mode
->vsync_len
+ 1) / 2;
1889 vback
= (video_mode
->upper_margin
+ 1) / 2;
1892 yres
= video_mode
->yres
;
1893 vfront
= video_mode
->lower_margin
;
1894 vsync
= video_mode
->vsync_len
;
1895 vback
= video_mode
->upper_margin
;
1898 /* ARB Dropping custom setup method from cvision.c */
1900 if (cvision_custom_mode
) {
1901 HBS
= hbs
/ 8 * hmul
;
1902 HBE
= hbe
/ 8 * hmul
;
1903 HSS
= hss
/ 8 * hmul
;
1904 HSE
= hse
/ 8 * hmul
;
1905 HT
= ht
/ 8 * hmul
- 5;
1916 HBS
= hmul
* (xres
/ 8);
1917 HBE
= hmul
* ((xres
/8) + (hfront
/8) + (hsync
/8) + (hback
/8) - 2);
1918 HSS
= hmul
* ((xres
/8) + (hfront
/8) + 2);
1919 HSE
= hmul
* ((xres
/8) + (hfront
/8) + (hsync
/8) + 1);
1920 HT
= hmul
* ((xres
/8) + (hfront
/8) + (hsync
/8) + (hback
/8));
1923 VBE
= yres
+ vfront
+ vsync
+ vback
- 2;
1924 VSS
= yres
+ vfront
- 1;
1925 VSE
= yres
+ vfront
+ vsync
- 1;
1926 VT
= yres
+ vfront
+ vsync
+ vback
- 2;
1929 wb_64 (regs
, ECR_ADV_FUNC_CNTL
, (TEXT
? 0x00 : 0x31));
1932 HDE
= ((video_mode
->xres
+ fx
- 1) / fx
) - 1;
1934 HDE
= (video_mode
->xres
+ 3) * hmul
/ 8 - 1;
1936 VDE
= video_mode
->yres
- 1;
1938 WCrt (regs
, CRT_ID_HWGC_MODE
, 0x00);
1939 WCrt (regs
, CRT_ID_EXT_DAC_CNTL
, 0x00);
1941 WSeq (regs
, SEQ_ID_MEMORY_MODE
,
1942 (TEXT
|| (video_mode
->bits_per_pixel
== 1)) ? 0x06 : 0x0e);
1943 WGfx (regs
, GCT_ID_READ_MAP_SELECT
, 0x00);
1944 WSeq (regs
, SEQ_ID_MAP_MASK
,
1945 (video_mode
->bits_per_pixel
== 1) ? 0x01 : 0xFF);
1946 WSeq (regs
, SEQ_ID_CHAR_MAP_SELECT
, 0x00);
1948 /* cv64_compute_clock accepts arguments in Hz */
1949 /* pixclock is in ps ... convert to Hz */
1952 freq_f
= (1.0 / (float) video_mode
->pixclock
) * 1000000000;
1953 freq
= ((long) freq_f
) * 1000;
1955 /* freq = (long) ((long long)1000000000000 / (long long) video_mode->pixclock);
1957 freq
= (1000000000 / video_mode
->pixclock
) * 1000;
1960 mnr
= cv64_compute_clock (freq
);
1961 WSeq (regs
, SEQ_ID_DCLK_HI
, ((mnr
& 0xFF00) >> 8));
1962 WSeq (regs
, SEQ_ID_DCLK_LO
, (mnr
& 0xFF));
1964 /* Load display parameters into board */
1965 WCrt (regs
, CRT_ID_EXT_HOR_OVF
,
1966 ((HT
& 0x100) ? 0x01 : 0x00) |
1967 ((HDE
& 0x100) ? 0x02 : 0x00) |
1968 ((HBS
& 0x100) ? 0x04 : 0x00) |
1969 /* ((HBE & 0x40) ? 0x08 : 0x00) | */
1970 ((HSS
& 0x100) ? 0x10 : 0x00) |
1971 /* ((HSE & 0x20) ? 0x20 : 0x00) | */
1972 (((HT
-5) & 0x100) ? 0x40 : 0x00)
1975 WCrt (regs
, CRT_ID_EXT_VER_OVF
,
1977 ((VT
& 0x400) ? 0x01 : 0x00) |
1978 ((VDE
& 0x400) ? 0x02 : 0x00) |
1979 ((VBS
& 0x400) ? 0x04 : 0x00) |
1980 ((VSS
& 0x400) ? 0x10 : 0x00)
1983 WCrt (regs
, CRT_ID_HOR_TOTAL
, HT
);
1984 WCrt (regs
, CRT_ID_DISPLAY_FIFO
, HT
- 5);
1985 WCrt (regs
, CRT_ID_HOR_DISP_ENA_END
, ((HDE
>= HBS
) ? (HBS
- 1) : HDE
));
1986 WCrt (regs
, CRT_ID_START_HOR_BLANK
, HBS
);
1987 WCrt (regs
, CRT_ID_END_HOR_BLANK
, ((HBE
& 0x1F) | 0x80));
1988 WCrt (regs
, CRT_ID_START_HOR_RETR
, HSS
);
1989 WCrt (regs
, CRT_ID_END_HOR_RETR
,
1991 ((HBE
& 0x20) ? 0x80 : 0x00)
1993 WCrt (regs
, CRT_ID_VER_TOTAL
, VT
);
1994 WCrt (regs
, CRT_ID_OVERFLOW
,
1996 ((VT
& 0x100) ? 0x01 : 0x00) |
1997 ((VDE
& 0x100) ? 0x02 : 0x00) |
1998 ((VSS
& 0x100) ? 0x04 : 0x00) |
1999 ((VBS
& 0x100) ? 0x08 : 0x00) |
2000 ((VT
& 0x200) ? 0x20 : 0x00) |
2001 ((VDE
& 0x200) ? 0x40 : 0x00) |
2002 ((VSS
& 0x200) ? 0x80 : 0x00)
2004 WCrt (regs
, CRT_ID_MAX_SCAN_LINE
,
2006 (DBLSCAN
? 0x80 : 0x00) |
2007 ((VBS
& 0x200) ? 0x20 : 0x00) |
2008 (TEXT
? ((fy
- 1) & 0x1F) : 0x00)
2011 WCrt (regs
, CRT_ID_MODE_CONTROL
, 0xE3);
2017 WCrt (regs
, CRT_ID_CURSOR_START
, (fy
& 0x1f) - 2);
2018 WCrt (regs
, CRT_ID_CURSOR_END
, (fy
& 0x1F) - 1);
2020 WCrt (regs
, CRT_ID_CURSOR_START
, 0x00);
2021 WCrt (regs
, CRT_ID_CURSOR_END
, fy
& 0x1F);
2023 WCrt (regs
, CRT_ID_UNDERLINE_LOC
, (fy
- 1) & 0x1F);
2024 WCrt (regs
, CRT_ID_CURSOR_LOC_HIGH
, 0x00);
2025 WCrt (regs
, CRT_ID_CURSOR_LOC_LOW
, 0x00);
2028 WCrt (regs
, CRT_ID_START_ADDR_HIGH
, 0x00);
2029 WCrt (regs
, CRT_ID_START_ADDR_LOW
, 0x00);
2030 WCrt (regs
, CRT_ID_START_VER_RETR
, VSS
);
2031 WCrt (regs
, CRT_ID_END_VER_RETR
, (VSE
& 0x0F));
2032 WCrt (regs
, CRT_ID_VER_DISP_ENA_END
, VDE
);
2033 WCrt (regs
, CRT_ID_START_VER_BLANK
, VBS
);
2034 WCrt (regs
, CRT_ID_END_VER_BLANK
, VBE
);
2035 WCrt (regs
, CRT_ID_LINE_COMPARE
, 0xFF);
2036 WCrt (regs
, CRT_ID_LACE_RETR_START
, HT
/ 2);
2037 WCrt (regs
, CRT_ID_LACE_CONTROL
, (LACE
? 0x20 : 0x00));
2038 WGfx (regs
, GCT_ID_GRAPHICS_MODE
,
2039 ((TEXT
|| (video_mode
->bits_per_pixel
== 1)) ? 0x00 : 0x40));
2040 WGfx (regs
, GCT_ID_MISC
, (TEXT
? 0x04 : 0x01));
2041 WSeq (regs
, SEQ_ID_MEMORY_MODE
,
2042 ((TEXT
|| (video_mode
->bits_per_pixel
== 1)) ? 0x06 : 0x02));
2044 wb_64 (regs
, VDAC_MASK
, 0xFF);
2047 test
= RCrt (regs
, CRT_ID_BACKWAD_COMP_2
);
2048 WCrt (regs
, CRT_ID_BACKWAD_COMP_2
, (test
| 0x20));
2050 sr15
= RSeq (regs
, SEQ_ID_CLKSYN_CNTL_2
);
2052 sr18
= RSeq (regs
, SEQ_ID_RAMDAC_CNTL
);
2057 test
= RCrt (regs
, CRT_ID_EXT_MISC_CNTL_2
);
2060 /* Clear roxxler byte-swapping... */
2061 cv64_write_port (0x0040, CyberBase
);
2062 cv64_write_port (0x0020, CyberBase
);
2064 switch (video_mode
->bits_per_pixel
) {
2067 HDE
= video_mode
->xres
/ 16;
2071 if (freq
> 80000000) {
2072 clock_mode
= 0x10 | 0x02;
2076 HDE
= video_mode
->xres
/ 8;
2081 cv64_write_port (0x8020, CyberBase
);
2083 HDE
= video_mode
->xres
/ 4;
2088 cv64_write_port (0x8020, CyberBase
);
2090 HDE
= video_mode
->xres
/ 4;
2096 cv64_write_port (0x8040, CyberBase
);
2098 HDE
= video_mode
->xres
/ 2;
2103 WCrt (regs
, CRT_ID_EXT_MISC_CNTL_2
, clock_mode
| test
);
2104 WSeq (regs
, SEQ_ID_CLKSYN_CNTL_2
, sr15
);
2105 WSeq (regs
, SEQ_ID_RAMDAC_CNTL
, sr18
);
2106 WCrt (regs
, CRT_ID_SCREEN_OFFSET
, HDE
);
2108 WCrt (regs
, CRT_ID_MISC_1
, (TEXT
? 0x05 : 0x35));
2110 test
= RCrt (regs
, CRT_ID_EXT_SYS_CNTL_2
);
2112 test
|= (HDE
>> 4) & 0x30;
2113 WCrt (regs
, CRT_ID_EXT_SYS_CNTL_2
, test
);
2115 /* Set up graphics engine */
2116 switch (video_mode
->xres
) {
2145 WCrt (regs
, CRT_ID_EXT_SYS_CNTL_1
, cr50
);
2148 WAttr (regs
, ACT_ID_ATTR_MODE_CNTL
, (TEXT
? 0x08 : 0x41));
2150 WAttr (regs
, ACT_ID_COLOR_PLANE_ENA
,
2151 (video_mode
->bits_per_pixel
== 1) ? 0x01 : 0x0F);
2154 tfillm
= (96 * (cv64_memclk
/ 1000)) / 240000;
2156 switch (video_mode
->bits_per_pixel
) {
2159 temptym
= (24 * (cv64_memclk
/ 1000)) / (freq
/ 1000);
2163 temptym
= (48 * (cv64_memclk
/ 1000)) / (freq
/ 1000);
2166 temptym
= (192 * (cv64_memclk
/ 1000)) / (freq
/ 1000);
2169 temptym
= (96 * (cv64_memclk
/ 1000)) / (freq
/ 1000);
2173 m
= (temptym
- tfillm
- 9) / 2;
2176 m
= (m
& 0x1F) << 3;
2181 WCrt (regs
, CRT_ID_EXT_MEM_CNTL_2
, m
);
2182 WCrt (regs
, CRT_ID_EXT_MEM_CNTL_3
, n
);
2185 /* Text initialization */
2188 /* Do text initialization here ! */
2193 wb_64 (regs
, VDAC_ADDRESS_W
, 0);
2194 for (i
= 0; i
< 4; i
++) {
2195 wb_64 (regs
, VDAC_DATA
, cvconscolors
[i
][0]);
2196 wb_64 (regs
, VDAC_DATA
, cvconscolors
[i
][1]);
2197 wb_64 (regs
, VDAC_DATA
, cvconscolors
[i
][2]);
2201 WAttr (regs
, 0x33, 0);
2203 /* Turn gfx on again */
2204 gfx_on_off (0, (volatile unsigned char *) regs
);
2207 cvscreen (0, CyberBase
);
2212 void cvision_bitblt (u_short sx
, u_short sy
, u_short dx
, u_short dy
,
2213 u_short w
, u_short h
)
2215 volatile unsigned char *regs
= CyberRegs
;
2216 unsigned short drawdir
= 0;
2234 vgaw16 (regs
, ECR_READ_REG_DATA
, 0xA000);
2235 vgaw16 (regs
, ECR_BKGD_MIX
, 0x7);
2236 vgaw16 (regs
, ECR_FRGD_MIX
, 0x67);
2237 vgaw16 (regs
, ECR_BKGD_COLOR
, 0x0);
2238 vgaw16 (regs
, ECR_FRGD_COLOR
, 0x1);
2239 vgaw16 (regs
, ECR_BITPLANE_READ_MASK
, 0x1);
2240 vgaw16 (regs
, ECR_BITPLANE_WRITE_MASK
, 0xFFF);
2241 vgaw16 (regs
, ECR_CURRENT_Y_POS
, sy
);
2242 vgaw16 (regs
, ECR_CURRENT_X_POS
, sx
);
2243 vgaw16 (regs
, ECR_DEST_Y__AX_STEP
, dy
);
2244 vgaw16 (regs
, ECR_DEST_X__DIA_STEP
, dx
);
2245 vgaw16 (regs
, ECR_READ_REG_DATA
, h
- 1);
2246 vgaw16 (regs
, ECR_MAJ_AXIS_PIX_CNT
, w
- 1);
2247 vgaw16 (regs
, ECR_DRAW_CMD
, 0xC051 | drawdir
);
2251 void cvision_clear (u_short dx
, u_short dy
, u_short w
, u_short h
, u_short bg
)
2253 volatile unsigned char *regs
= CyberRegs
;
2256 vgaw16 (regs
, ECR_FRGD_MIX
, 0x0027);
2257 vgaw16 (regs
, ECR_FRGD_COLOR
, bg
);
2258 vgaw16 (regs
, ECR_READ_REG_DATA
, 0xA000);
2259 vgaw16 (regs
, ECR_CURRENT_Y_POS
, dy
);
2260 vgaw16 (regs
, ECR_CURRENT_X_POS
, dx
);
2261 vgaw16 (regs
, ECR_READ_REG_DATA
, h
- 1);
2262 vgaw16 (regs
, ECR_MAJ_AXIS_PIX_CNT
, w
- 1);
2263 vgaw16 (regs
, ECR_DRAW_CMD
, 0x40B1);
2269 * Dump internal settings of CyberVision board
2271 static void cv64_dump (void)
2273 volatile unsigned char *regs
= CyberRegs
;
2275 /* Dump the VGA setup values */
2276 *(regs
+ S3_CRTC_ADR
) = 0x00;
2277 DPRINTK("CR00 = %x\n", *(regs
+ S3_CRTC_DATA
));
2278 *(regs
+ S3_CRTC_ADR
) = 0x01;
2279 DPRINTK("CR01 = %x\n", *(regs
+ S3_CRTC_DATA
));
2280 *(regs
+ S3_CRTC_ADR
) = 0x02;
2281 DPRINTK("CR02 = %x\n", *(regs
+ S3_CRTC_DATA
));
2282 *(regs
+ S3_CRTC_ADR
) = 0x03;
2283 DPRINTK("CR03 = %x\n", *(regs
+ S3_CRTC_DATA
));
2284 *(regs
+ S3_CRTC_ADR
) = 0x04;
2285 DPRINTK("CR04 = %x\n", *(regs
+ S3_CRTC_DATA
));
2286 *(regs
+ S3_CRTC_ADR
) = 0x05;
2287 DPRINTK("CR05 = %x\n", *(regs
+ S3_CRTC_DATA
));
2288 *(regs
+ S3_CRTC_ADR
) = 0x06;
2289 DPRINTK("CR06 = %x\n", *(regs
+ S3_CRTC_DATA
));
2290 *(regs
+ S3_CRTC_ADR
) = 0x07;
2291 DPRINTK("CR07 = %x\n", *(regs
+ S3_CRTC_DATA
));
2292 *(regs
+ S3_CRTC_ADR
) = 0x08;
2293 DPRINTK("CR08 = %x\n", *(regs
+ S3_CRTC_DATA
));
2294 *(regs
+ S3_CRTC_ADR
) = 0x09;
2295 DPRINTK("CR09 = %x\n", *(regs
+ S3_CRTC_DATA
));
2296 *(regs
+ S3_CRTC_ADR
) = 0x10;
2297 DPRINTK("CR10 = %x\n", *(regs
+ S3_CRTC_DATA
));
2298 *(regs
+ S3_CRTC_ADR
) = 0x11;
2299 DPRINTK("CR11 = %x\n", *(regs
+ S3_CRTC_DATA
));
2300 *(regs
+ S3_CRTC_ADR
) = 0x12;
2301 DPRINTK("CR12 = %x\n", *(regs
+ S3_CRTC_DATA
));
2302 *(regs
+ S3_CRTC_ADR
) = 0x13;
2303 DPRINTK("CR13 = %x\n", *(regs
+ S3_CRTC_DATA
));
2304 *(regs
+ S3_CRTC_ADR
) = 0x15;
2305 DPRINTK("CR15 = %x\n", *(regs
+ S3_CRTC_DATA
));
2306 *(regs
+ S3_CRTC_ADR
) = 0x16;
2307 DPRINTK("CR16 = %x\n", *(regs
+ S3_CRTC_DATA
));
2308 *(regs
+ S3_CRTC_ADR
) = 0x36;
2309 DPRINTK("CR36 = %x\n", *(regs
+ S3_CRTC_DATA
));
2310 *(regs
+ S3_CRTC_ADR
) = 0x37;
2311 DPRINTK("CR37 = %x\n", *(regs
+ S3_CRTC_DATA
));
2312 *(regs
+ S3_CRTC_ADR
) = 0x42;
2313 DPRINTK("CR42 = %x\n", *(regs
+ S3_CRTC_DATA
));
2314 *(regs
+ S3_CRTC_ADR
) = 0x43;
2315 DPRINTK("CR43 = %x\n", *(regs
+ S3_CRTC_DATA
));
2316 *(regs
+ S3_CRTC_ADR
) = 0x50;
2317 DPRINTK("CR50 = %x\n", *(regs
+ S3_CRTC_DATA
));
2318 *(regs
+ S3_CRTC_ADR
) = 0x51;
2319 DPRINTK("CR51 = %x\n", *(regs
+ S3_CRTC_DATA
));
2320 *(regs
+ S3_CRTC_ADR
) = 0x53;
2321 DPRINTK("CR53 = %x\n", *(regs
+ S3_CRTC_DATA
));
2322 *(regs
+ S3_CRTC_ADR
) = 0x58;
2323 DPRINTK("CR58 = %x\n", *(regs
+ S3_CRTC_DATA
));
2324 *(regs
+ S3_CRTC_ADR
) = 0x59;
2325 DPRINTK("CR59 = %x\n", *(regs
+ S3_CRTC_DATA
));
2326 *(regs
+ S3_CRTC_ADR
) = 0x5A;
2327 DPRINTK("CR5A = %x\n", *(regs
+ S3_CRTC_DATA
));
2328 *(regs
+ S3_CRTC_ADR
) = 0x5D;
2329 DPRINTK("CR5D = %x\n", *(regs
+ S3_CRTC_DATA
));
2330 *(regs
+ S3_CRTC_ADR
) = 0x5E;
2331 DPRINTK("CR5E = %x\n", *(regs
+ S3_CRTC_DATA
));
2332 DPRINTK("MISC = %x\n", *(regs
+ GREG_MISC_OUTPUT_R
));
2333 *(regs
+ SEQ_ADDRESS
) = 0x01;
2334 DPRINTK("SR01 = %x\n", *(regs
+ SEQ_ADDRESS_R
));
2335 *(regs
+ SEQ_ADDRESS
) = 0x02;
2336 DPRINTK("SR02 = %x\n", *(regs
+ SEQ_ADDRESS_R
));
2337 *(regs
+ SEQ_ADDRESS
) = 0x03;
2338 DPRINTK("SR03 = %x\n", *(regs
+ SEQ_ADDRESS_R
));
2339 *(regs
+ SEQ_ADDRESS
) = 0x09;
2340 DPRINTK("SR09 = %x\n", *(regs
+ SEQ_ADDRESS_R
));
2341 *(regs
+ SEQ_ADDRESS
) = 0x10;
2342 DPRINTK("SR10 = %x\n", *(regs
+ SEQ_ADDRESS_R
));
2343 *(regs
+ SEQ_ADDRESS
) = 0x11;
2344 DPRINTK("SR11 = %x\n", *(regs
+ SEQ_ADDRESS_R
));
2345 *(regs
+ SEQ_ADDRESS
) = 0x12;
2346 DPRINTK("SR12 = %x\n", *(regs
+ SEQ_ADDRESS_R
));
2347 *(regs
+ SEQ_ADDRESS
) = 0x13;
2348 DPRINTK("SR13 = %x\n", *(regs
+ SEQ_ADDRESS_R
));
2349 *(regs
+ SEQ_ADDRESS
) = 0x15;
2350 DPRINTK("SR15 = %x\n", *(regs
+ SEQ_ADDRESS_R
));