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 arraysize(x) (sizeof(x)/sizeof(*(x)))
112 #define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat)
113 #define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg))
115 #define ww_64(regs,reg,dat) (*((volatile unsigned short *)(regs + reg) = dat)
118 struct fb_var_screeninfo var
;
125 static struct cyberfb_par current_par
;
127 static int current_par_valid
= 0;
128 static int currcon
= 0;
130 static struct display disp
;
131 static struct fb_info fb_info
;
138 static char cyberfb_name
[16] = "Cybervision";
142 * CyberVision Graphics Board
145 static unsigned char Cyber_colour_table
[256][3];
146 static unsigned long CyberSize
;
147 static volatile unsigned char *CyberBase
;
148 static volatile unsigned char *CyberMem
;
149 static volatile unsigned char *CyberRegs
;
150 static unsigned long CyberMem_phys
;
151 static unsigned long CyberRegs_phys
;
154 * Predefined Video Modes
159 struct fb_var_screeninfo var
;
160 } cyberfb_predefined
[] __initdata
= {
161 { "640x480-8", { /* Default 8 BPP mode (cyber8) */
162 640, 480, 640, 480, 0, 0, 8, 0,
163 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
164 0, 0, -1, -1, FB_ACCELF_TEXT
, 39722, 40, 24, 32, 11, 96, 2,
165 FB_SYNC_COMP_HIGH_ACT
|FB_SYNC_VERT_HIGH_ACT
,
166 FB_VMODE_NONINTERLACED
168 { "640x480-16", { /* Default 16 BPP mode (cyber16) */
169 640, 480, 640, 480, 0, 0, 16, 0,
170 {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
171 0, 0, -1, -1, FB_ACCELF_TEXT
, 39722, 40, 24, 32, 11, 96, 2,
172 FB_SYNC_COMP_HIGH_ACT
|FB_SYNC_VERT_HIGH_ACT
,
173 FB_VMODE_NONINTERLACED
175 { "640x480-24", { /* Default 24 BPP mode */
176 640, 480, 640, 480, 0, 0, 24, 0,
177 {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {0, 0, 0},
178 0, 0, -1, -1, FB_ACCELF_TEXT
, 39722, 40, 24, 32, 11, 96, 2,
179 FB_SYNC_COMP_HIGH_ACT
|FB_SYNC_VERT_HIGH_ACT
,
180 FB_VMODE_NONINTERLACED
182 { "800x490-8", { /* Cybervision 8 bpp */
183 /* NO Acceleration */
184 800, 490, 800, 490, 0, 0, 8, 0,
185 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
186 0, 0, -1, -1, FB_ACCEL_NONE
, 33333, 80, 24, 23, 1, 56, 8,
187 FB_SYNC_COMP_HIGH_ACT
|FB_SYNC_VERT_HIGH_ACT
,
188 FB_VMODE_NONINTERLACED
190 /* I can't test these with my monitor, but I suspect they will
191 * be OK, since Antonio Santos indicated he had tested them in
194 { "800x600-8", { /* Cybervision 8 bpp */
195 800, 600, 800, 600, 0, 0, 8, 0,
196 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
197 0, 0, -1, -1, FB_ACCELF_TEXT
, 27778, 64, 24, 22, 1, 72, 2,
198 FB_SYNC_COMP_HIGH_ACT
|FB_SYNC_VERT_HIGH_ACT
,
199 FB_VMODE_NONINTERLACED
201 { "1024x768-8", { /* Cybervision 8 bpp */
202 1024, 768, 1024, 768, 0, 0, 8, 0,
203 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
204 0, 0, -1, -1, FB_ACCELF_TEXT
, 16667, 224, 72, 60, 12, 168, 4,
205 FB_SYNC_COMP_HIGH_ACT
|FB_SYNC_VERT_HIGH_ACT
,
206 FB_VMODE_NONINTERLACED
208 { "1152x886-8", { /* Cybervision 8 bpp */
209 1152, 886, 1152, 886, 0, 0, 8, 0,
210 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
211 0, 0, -1, -1, FB_ACCELF_TEXT
, 15873, 184, 40, 24, 1, 56, 16,
212 FB_SYNC_COMP_HIGH_ACT
|FB_SYNC_VERT_HIGH_ACT
,
213 FB_VMODE_NONINTERLACED
215 { "1280x1024-8", { /* Cybervision 8 bpp */
216 1280, 1024, 1280, 1024, 0, 0, 8, 0,
217 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
218 0, 0, -1, -1, FB_ACCELF_TEXT
, 16667, 256, 48, 50, 12, 72, 4,
219 FB_SYNC_COMP_HIGH_ACT
|FB_SYNC_VERT_HIGH_ACT
,
224 #define NUM_TOTAL_MODES arraysize(cyberfb_predefined)
226 static int Cyberfb_inverse
= 0;
232 #define CYBER8_DEFMODE (0)
233 #define CYBER16_DEFMODE (1)
235 static struct fb_var_screeninfo cyberfb_default
;
236 static int cyberfb_usermode __initdata
= 0;
239 * Interface used by the world
242 int cyberfb_setup(char *options
);
244 static int cyberfb_open(struct fb_info
*info
, int user
);
245 static int cyberfb_release(struct fb_info
*info
, int user
);
246 static int cyberfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
247 struct fb_info
*info
);
248 static int cyberfb_get_var(struct fb_var_screeninfo
*var
, int con
,
249 struct fb_info
*info
);
250 static int cyberfb_set_var(struct fb_var_screeninfo
*var
, int con
,
251 struct fb_info
*info
);
252 static int cyberfb_get_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
253 struct fb_info
*info
);
254 static int cyberfb_set_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
255 struct fb_info
*info
);
256 static int cyberfb_pan_display(struct fb_var_screeninfo
*var
, int con
,
257 struct fb_info
*info
);
258 static int cyberfb_ioctl(struct inode
*inode
, struct file
*file
, u_int cmd
,
259 u_long arg
, int con
, struct fb_info
*info
);
262 * Interface to the low level console driver
265 int cyberfb_init(void);
266 static int Cyberfb_switch(int con
, struct fb_info
*info
);
267 static int Cyberfb_updatevar(int con
, struct fb_info
*info
);
268 static void Cyberfb_blank(int blank
, struct fb_info
*info
);
271 * Text console acceleration
274 #ifdef FBCON_HAS_CFB8
275 static struct display_switch fbcon_cyber8
;
279 * Accelerated Functions used by the low level console driver
282 static void Cyber_WaitQueue(u_short fifo
);
283 static void Cyber_WaitBlit(void);
284 static void Cyber_BitBLT(u_short curx
, u_short cury
, u_short destx
,
285 u_short desty
, u_short width
, u_short height
,
287 static void Cyber_RectFill(u_short x
, u_short y
, u_short width
, u_short height
,
288 u_short mode
, u_short color
);
290 static void Cyber_MoveCursor(u_short x
, u_short y
);
294 * Hardware Specific Routines
297 static int Cyber_init(void);
298 static int Cyber_encode_fix(struct fb_fix_screeninfo
*fix
,
299 struct cyberfb_par
*par
);
300 static int Cyber_decode_var(struct fb_var_screeninfo
*var
,
301 struct cyberfb_par
*par
);
302 static int Cyber_encode_var(struct fb_var_screeninfo
*var
,
303 struct cyberfb_par
*par
);
304 static int Cyber_getcolreg(u_int regno
, u_int
*red
, u_int
*green
, u_int
*blue
,
305 u_int
*transp
, struct fb_info
*info
);
306 static int Cyber_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
307 u_int transp
, struct fb_info
*info
);
313 static void cyberfb_get_par(struct cyberfb_par
*par
);
314 static void cyberfb_set_par(struct cyberfb_par
*par
);
315 static int do_fb_set_var(struct fb_var_screeninfo
*var
, int isactive
);
316 static void do_install_cmap(int con
, struct fb_info
*info
);
317 static void cyberfb_set_disp(int con
, struct fb_info
*info
);
318 static int get_video_mode(const char *name
);
320 /* For cvision_core.c */
321 static unsigned short cv64_compute_clock(unsigned long);
322 static int cv_has_4mb (volatile unsigned char *);
323 static void cv64_board_init (void);
324 static void cv64_load_video_mode (struct fb_var_screeninfo
*);
327 /* -------------------- Hardware specific routines ------------------------- */
333 * Set the default video mode for this chipset. If a video mode was
334 * specified on the command line, it will override the default mode.
337 static int Cyber_init(void)
339 volatile unsigned char *regs
= CyberRegs
;
340 volatile unsigned long *CursorBase
;
344 /* Init local cmap as greyscale levels */
345 for (i
= 0; i
< 256; i
++) {
346 Cyber_colour_table
[i
][0] = i
;
347 Cyber_colour_table
[i
][1] = i
;
348 Cyber_colour_table
[i
][2] = i
;
351 /* Initialize the board and determine fbmem size */
354 DPRINTK("Register state after initing board\n");
357 /* Clear framebuffer memory */
358 DPRINTK("Clear framebuffer memory\n");
359 memset ((char *)CyberMem
, 0, CyberSize
);
361 /* Disable hardware cursor */
362 DPRINTK("Disable HW cursor\n");
363 wb_64(regs
, S3_CRTC_ADR
, S3_REG_LOCK2
);
364 wb_64(regs
, S3_CRTC_DATA
, 0xa0);
365 wb_64(regs
, S3_CRTC_ADR
, S3_HGC_MODE
);
366 wb_64(regs
, S3_CRTC_DATA
, 0x00);
367 wb_64(regs
, S3_CRTC_ADR
, S3_HWGC_DX
);
368 wb_64(regs
, S3_CRTC_DATA
, 0x00);
369 wb_64(regs
, S3_CRTC_ADR
, S3_HWGC_DY
);
370 wb_64(regs
, S3_CRTC_DATA
, 0x00);
372 /* Initialize hardware cursor */
373 DPRINTK("Init HW cursor\n");
374 CursorBase
= (u_long
*)((char *)(CyberMem
) + CyberSize
- 0x400);
375 for (i
=0; i
< 8; i
++)
377 *(CursorBase
+(i
*4)) = 0xffffff00;
378 *(CursorBase
+1+(i
*4)) = 0xffff0000;
379 *(CursorBase
+2+(i
*4)) = 0xffff0000;
380 *(CursorBase
+3+(i
*4)) = 0xffff0000;
382 for (i
=8; i
< 64; i
++)
384 *(CursorBase
+(i
*4)) = 0xffff0000;
385 *(CursorBase
+1+(i
*4)) = 0xffff0000;
386 *(CursorBase
+2+(i
*4)) = 0xffff0000;
387 *(CursorBase
+3+(i
*4)) = 0xffff0000;
390 Cyber_setcolreg (255, 56<<8, 100<<8, 160<<8, 0, NULL
/* unused */);
391 Cyber_setcolreg (254, 0, 0, 0, 0, NULL
/* unused */);
399 * This function should fill in the `fix' structure based on the
400 * values in the `par' structure.
403 static int Cyber_encode_fix(struct fb_fix_screeninfo
*fix
,
404 struct cyberfb_par
*par
)
407 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
408 strcpy(fix
->id
, cyberfb_name
);
409 fix
->smem_start
= CyberMem_phys
;
410 fix
->smem_len
= CyberSize
;
411 fix
->mmio_start
= CyberRegs_phys
;
412 fix
->mmio_len
= 0x10000;
414 fix
->type
= FB_TYPE_PACKED_PIXELS
;
416 if (par
->var
.bits_per_pixel
== 15 || par
->var
.bits_per_pixel
== 16 ||
417 par
->var
.bits_per_pixel
== 24 || par
->var
.bits_per_pixel
== 32) {
418 fix
->visual
= FB_VISUAL_DIRECTCOLOR
;
420 fix
->visual
= FB_VISUAL_PSEUDOCOLOR
;
426 fix
->line_length
= 0;
427 fix
->accel
= FB_ACCEL_S3_TRIO64
;
435 * Fill the `par' structure based on the values in `var'.
436 * TODO: Verify and adjust values, return -EINVAL if bad.
439 static int Cyber_decode_var(struct fb_var_screeninfo
*var
,
440 struct cyberfb_par
*par
)
443 par
->var
.xres
= var
->xres
;
444 par
->var
.yres
= var
->yres
;
445 par
->var
.xres_virtual
= var
->xres_virtual
;
446 par
->var
.yres_virtual
= var
->yres_virtual
;
447 par
->var
.xoffset
= var
->xoffset
;
448 par
->var
.yoffset
= var
->yoffset
;
449 par
->var
.bits_per_pixel
= var
->bits_per_pixel
;
450 par
->var
.grayscale
= var
->grayscale
;
451 par
->var
.red
= var
->red
;
452 par
->var
.green
= var
->green
;
453 par
->var
.blue
= var
->blue
;
454 par
->var
.transp
= var
->transp
;
455 par
->var
.nonstd
= var
->nonstd
;
456 par
->var
.activate
= var
->activate
;
457 par
->var
.height
= var
->height
;
458 par
->var
.width
= var
->width
;
459 if (var
->accel_flags
& FB_ACCELF_TEXT
) {
460 par
->var
.accel_flags
= FB_ACCELF_TEXT
;
462 par
->var
.accel_flags
= 0;
464 par
->var
.pixclock
= var
->pixclock
;
465 par
->var
.left_margin
= var
->left_margin
;
466 par
->var
.right_margin
= var
->right_margin
;
467 par
->var
.upper_margin
= var
->upper_margin
;
468 par
->var
.lower_margin
= var
->lower_margin
;
469 par
->var
.hsync_len
= var
->hsync_len
;
470 par
->var
.vsync_len
= var
->vsync_len
;
471 par
->var
.sync
= var
->sync
;
472 par
->var
.vmode
= var
->vmode
;
478 * Fill the `var' structure based on the values in `par' and maybe
479 * other values read out of the hardware.
482 static int Cyber_encode_var(struct fb_var_screeninfo
*var
,
483 struct cyberfb_par
*par
)
486 var
->xres
= par
->var
.xres
;
487 var
->yres
= par
->var
.yres
;
488 var
->xres_virtual
= par
->var
.xres_virtual
;
489 var
->yres_virtual
= par
->var
.yres_virtual
;
490 var
->xoffset
= par
->var
.xoffset
;
491 var
->yoffset
= par
->var
.yoffset
;
493 var
->bits_per_pixel
= par
->var
.bits_per_pixel
;
494 var
->grayscale
= par
->var
.grayscale
;
496 var
->red
= par
->var
.red
;
497 var
->green
= par
->var
.green
;
498 var
->blue
= par
->var
.blue
;
499 var
->transp
= par
->var
.transp
;
501 var
->nonstd
= par
->var
.nonstd
;
502 var
->activate
= par
->var
.activate
;
504 var
->height
= par
->var
.height
;
505 var
->width
= par
->var
.width
;
507 var
->accel_flags
= par
->var
.accel_flags
;
509 var
->pixclock
= par
->var
.pixclock
;
510 var
->left_margin
= par
->var
.left_margin
;
511 var
->right_margin
= par
->var
.right_margin
;
512 var
->upper_margin
= par
->var
.upper_margin
;
513 var
->lower_margin
= par
->var
.lower_margin
;
514 var
->hsync_len
= par
->var
.hsync_len
;
515 var
->vsync_len
= par
->var
.vsync_len
;
516 var
->sync
= par
->var
.sync
;
517 var
->vmode
= par
->var
.vmode
;
525 * Set a single color register. Return != 0 for invalid regno.
528 static int Cyber_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
529 u_int transp
, struct fb_info
*info
)
531 volatile unsigned char *regs
= CyberRegs
;
533 /*DPRINTK("ENTER\n");*/
535 DPRINTK("EXIT - Register # > 255\n");
539 wb_64(regs
, 0x3c8, (unsigned char) regno
);
545 Cyber_colour_table
[regno
][0] = red
;
546 Cyber_colour_table
[regno
][1] = green
;
547 Cyber_colour_table
[regno
][2] = blue
;
549 wb_64(regs
, 0x3c9, red
);
550 wb_64(regs
, 0x3c9, green
);
551 wb_64(regs
, 0x3c9, blue
);
553 /*DPRINTK("EXIT\n");*/
559 * Read a single color register and split it into
560 * colors/transparent. Return != 0 for invalid regno.
563 static int Cyber_getcolreg(u_int regno
, u_int
*red
, u_int
*green
, u_int
*blue
,
564 u_int
*transp
, struct fb_info
*info
)
568 /*DPRINTK("ENTER\n");*/
570 DPRINTK("EXIT - Register # > 255\n");
573 /* ARB This shifting & oring seems VERY strange */
574 t
= Cyber_colour_table
[regno
][0];
575 *red
= (t
<<10) | (t
<<4) | (t
>>2);
576 t
= Cyber_colour_table
[regno
][1];
577 *green
= (t
<<10) | (t
<<4) | (t
>>2);
578 t
= Cyber_colour_table
[regno
][2];
579 *blue
= (t
<<10) | (t
<<4) | (t
>>2);
581 /*DPRINTK("EXIT\n");*/
587 * (Un)Blank the screen
588 * blank: 1 = zero fb cmap
589 * 0 = restore fb cmap from local cmap
592 void Cyberfb_blank(int blank
, struct fb_info
*info
)
594 volatile unsigned char *regs
= CyberRegs
;
599 /* Blank by turning gfx off */
600 gfx_on_off (1, regs
);
603 for (i
= 0; i
< 256; i
++) {
604 wb_64(regs
, 0x3c8, (unsigned char) i
);
605 /* ARB Pale red to detect this blanking method */
606 wb_64(regs
, 0x3c9, 48);
607 wb_64(regs
, 0x3c9, 0);
608 wb_64(regs
, 0x3c9, 0);
611 for (i
= 0; i
< 256; i
++) {
612 wb_64(regs
, 0x3c8, (unsigned char) i
);
613 wb_64(regs
, 0x3c9, Cyber_colour_table
[i
][0]);
614 wb_64(regs
, 0x3c9, Cyber_colour_table
[i
][1]);
615 wb_64(regs
, 0x3c9, Cyber_colour_table
[i
][2]);
623 /**************************************************************
624 * We are waiting for "fifo" FIFO-slots empty
626 static void Cyber_WaitQueue (u_short fifo
)
628 unsigned short status
;
632 status
= *((u_short
volatile *)(CyberRegs
+ S3_GP_STAT
));
633 } while (status
& fifo
);
637 /**************************************************************
638 * We are waiting for Hardware (Graphics Engine) not busy
640 static void Cyber_WaitBlit (void)
642 unsigned short status
;
646 status
= *((u_short
volatile *)(CyberRegs
+ S3_GP_STAT
));
647 } while (status
& S3_HDW_BUSY
);
651 /**************************************************************
652 * BitBLT - Through the Plane
654 static void Cyber_BitBLT (u_short curx
, u_short cury
, u_short destx
,
655 u_short desty
, u_short width
, u_short height
,
658 volatile unsigned char *regs
= CyberRegs
;
659 u_short blitcmd
= S3_BITBLT
;
662 /* Set drawing direction */
663 /* -Y, X maj, -X (default) */
665 blitcmd
|= 0x0020; /* Drawing direction +X */
668 destx
+= (width
- 1);
672 blitcmd
|= 0x0080; /* Drawing direction +Y */
674 cury
+= (height
- 1);
675 desty
+= (height
- 1);
678 Cyber_WaitQueue (0x8000);
680 *((u_short
volatile *)(regs
+ S3_PIXEL_CNTL
)) = 0xa000;
681 *((u_short
volatile *)(regs
+ S3_FRGD_MIX
)) = (0x0060 | mode
);
683 *((u_short
volatile *)(regs
+ S3_CUR_X
)) = curx
;
684 *((u_short
volatile *)(regs
+ S3_CUR_Y
)) = cury
;
686 *((u_short
volatile *)(regs
+ S3_DESTX_DIASTP
)) = destx
;
687 *((u_short
volatile *)(regs
+ S3_DESTY_AXSTP
)) = desty
;
689 *((u_short
volatile *)(regs
+ S3_MIN_AXIS_PCNT
)) = height
- 1;
690 *((u_short
volatile *)(regs
+ S3_MAJ_AXIS_PCNT
)) = width
- 1;
692 *((u_short
volatile *)(regs
+ S3_CMD
)) = blitcmd
;
696 /**************************************************************
697 * Rectangle Fill Solid
699 static void Cyber_RectFill (u_short x
, u_short y
, u_short width
,
700 u_short height
, u_short mode
, u_short color
)
702 volatile unsigned char *regs
= CyberRegs
;
703 u_short blitcmd
= S3_FILLEDRECT
;
706 Cyber_WaitQueue (0x8000);
708 *((u_short
volatile *)(regs
+ S3_PIXEL_CNTL
)) = 0xa000;
709 *((u_short
volatile *)(regs
+ S3_FRGD_MIX
)) = (0x0020 | mode
);
711 *((u_short
volatile *)(regs
+ S3_MULT_MISC
)) = 0xe000;
712 *((u_short
volatile *)(regs
+ S3_FRGD_COLOR
)) = color
;
714 *((u_short
volatile *)(regs
+ S3_CUR_X
)) = x
;
715 *((u_short
volatile *)(regs
+ S3_CUR_Y
)) = y
;
717 *((u_short
volatile *)(regs
+ S3_MIN_AXIS_PCNT
)) = height
- 1;
718 *((u_short
volatile *)(regs
+ S3_MAJ_AXIS_PCNT
)) = width
- 1;
720 *((u_short
volatile *)(regs
+ S3_CMD
)) = blitcmd
;
726 /**************************************************************
727 * Move cursor to x, y
729 static void Cyber_MoveCursor (u_short x
, u_short y
)
731 volatile unsigned char *regs
= CyberRegs
;
733 *(regs
+ S3_CRTC_ADR
) = 0x39;
734 *(regs
+ S3_CRTC_DATA
) = 0xa0;
736 *(regs
+ S3_CRTC_ADR
) = S3_HWGC_ORGX_H
;
737 *(regs
+ S3_CRTC_DATA
) = (char)((x
& 0x0700) >> 8);
738 *(regs
+ S3_CRTC_ADR
) = S3_HWGC_ORGX_L
;
739 *(regs
+ S3_CRTC_DATA
) = (char)(x
& 0x00ff);
741 *(regs
+ S3_CRTC_ADR
) = S3_HWGC_ORGY_H
;
742 *(regs
+ S3_CRTC_DATA
) = (char)((y
& 0x0700) >> 8);
743 *(regs
+ S3_CRTC_ADR
) = S3_HWGC_ORGY_L
;
744 *(regs
+ S3_CRTC_DATA
) = (char)(y
& 0x00ff);
750 /* -------------------- Generic routines ---------------------------------- */
754 * Fill the hardware's `par' structure.
757 static void cyberfb_get_par(struct cyberfb_par
*par
)
760 if (current_par_valid
) {
763 Cyber_decode_var(&cyberfb_default
, par
);
769 static void cyberfb_set_par(struct cyberfb_par
*par
)
773 current_par_valid
= 1;
778 static void cyber_set_video(struct fb_var_screeninfo
*var
)
781 /* Load the video mode defined by the 'var' data */
782 cv64_load_video_mode (var
);
784 DPRINTK("Register state after loading video mode\n");
790 static int do_fb_set_var(struct fb_var_screeninfo
*var
, int isactive
)
793 struct cyberfb_par par
;
796 if ((err
= Cyber_decode_var(var
, &par
))) {
797 DPRINTK("EXIT - decode_var failed\n");
800 activate
= var
->activate
;
801 if ((var
->activate
& FB_ACTIVATE_MASK
) == FB_ACTIVATE_NOW
&& isactive
)
802 cyberfb_set_par(&par
);
803 Cyber_encode_var(var
, &par
);
804 var
->activate
= activate
;
806 cyber_set_video(var
);
812 static void do_install_cmap(int con
, struct fb_info
*info
)
815 if (con
!= currcon
) {
816 DPRINTK("EXIT - Not current console\n");
819 if (fb_display
[con
].cmap
.len
) {
820 DPRINTK("Use console cmap\n");
821 fb_set_cmap(&fb_display
[con
].cmap
, 1, Cyber_setcolreg
, info
);
823 DPRINTK("Use default cmap\n");
824 fb_set_cmap(fb_default_cmap(1<<fb_display
[con
].var
.bits_per_pixel
),
825 1, Cyber_setcolreg
, info
);
832 * Open/Release the frame buffer device
835 static int cyberfb_open(struct fb_info
*info
, int user
)
838 * Nothing, only a usage count for the moment
845 static int cyberfb_release(struct fb_info
*info
, int user
)
853 * Get the Fixed Part of the Display
856 static int cyberfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
857 struct fb_info
*info
)
859 struct cyberfb_par par
;
864 cyberfb_get_par(&par
);
866 error
= Cyber_decode_var(&fb_display
[con
].var
, &par
);
869 return(error
? error
: Cyber_encode_fix(fix
, &par
));
874 * Get the User Defined Part of the Display
877 static int cyberfb_get_var(struct fb_var_screeninfo
*var
, int con
,
878 struct fb_info
*info
)
880 struct cyberfb_par par
;
885 cyberfb_get_par(&par
);
886 error
= Cyber_encode_var(var
, &par
);
887 disp
.var
= *var
; /* ++Andre: don't know if this is the right place */
889 *var
= fb_display
[con
].var
;
897 static void cyberfb_set_disp(int con
, struct fb_info
*info
)
899 struct fb_fix_screeninfo fix
;
900 struct display
*display
;
904 display
= &fb_display
[con
];
906 display
= &disp
; /* used during initialization */
908 cyberfb_get_fix(&fix
, con
, info
);
911 display
->screen_base
= (unsigned char *)CyberMem
;
912 display
->visual
= fix
.visual
;
913 display
->type
= fix
.type
;
914 display
->type_aux
= fix
.type_aux
;
915 display
->ypanstep
= fix
.ypanstep
;
916 display
->ywrapstep
= fix
.ywrapstep
;
917 display
->can_soft_blank
= 1;
918 display
->inverse
= Cyberfb_inverse
;
919 switch (display
->var
.bits_per_pixel
) {
920 #ifdef FBCON_HAS_CFB8
922 if (display
->var
.accel_flags
& FB_ACCELF_TEXT
) {
923 display
->dispsw
= &fbcon_cyber8
;
924 #warning FIXME: We should reinit the graphics engine here
926 display
->dispsw
= &fbcon_cfb8
;
929 #ifdef FBCON_HAS_CFB16
931 display
->dispsw
= &fbcon_cfb16
;
935 display
->dispsw
= NULL
;
943 * Set the User Defined Part of the Display
946 static int cyberfb_set_var(struct fb_var_screeninfo
*var
, int con
,
947 struct fb_info
*info
)
949 int err
, oldxres
, oldyres
, oldvxres
, oldvyres
, oldbpp
, oldaccel
;
952 if ((err
= do_fb_set_var(var
, con
== currcon
))) {
953 DPRINTK("EXIT - do_fb_set_var failed\n");
956 if ((var
->activate
& FB_ACTIVATE_MASK
) == FB_ACTIVATE_NOW
) {
957 oldxres
= fb_display
[con
].var
.xres
;
958 oldyres
= fb_display
[con
].var
.yres
;
959 oldvxres
= fb_display
[con
].var
.xres_virtual
;
960 oldvyres
= fb_display
[con
].var
.yres_virtual
;
961 oldbpp
= fb_display
[con
].var
.bits_per_pixel
;
962 oldaccel
= fb_display
[con
].var
.accel_flags
;
963 fb_display
[con
].var
= *var
;
964 if (oldxres
!= var
->xres
|| oldyres
!= var
->yres
||
965 oldvxres
!= var
->xres_virtual
||
966 oldvyres
!= var
->yres_virtual
||
967 oldbpp
!= var
->bits_per_pixel
||
968 oldaccel
!= var
->accel_flags
) {
969 cyberfb_set_disp(con
, info
);
970 (*fb_info
.changevar
)(con
);
971 fb_alloc_cmap(&fb_display
[con
].cmap
, 0, 0);
972 do_install_cmap(con
, info
);
985 static int cyberfb_get_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
986 struct fb_info
*info
)
989 if (con
== currcon
) { /* current console? */
990 DPRINTK("EXIT - console is current console\n");
991 return(fb_get_cmap(cmap
, kspc
, Cyber_getcolreg
, info
));
992 } else if (fb_display
[con
].cmap
.len
) { /* non default colormap? */
993 DPRINTK("Use console cmap\n");
994 fb_copy_cmap(&fb_display
[con
].cmap
, cmap
, kspc
? 0 : 2);
996 DPRINTK("Use default cmap\n");
997 fb_copy_cmap(fb_default_cmap(1<<fb_display
[con
].var
.bits_per_pixel
),
1009 static int cyberfb_set_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
1010 struct fb_info
*info
)
1015 if (!fb_display
[con
].cmap
.len
) { /* no colormap allocated? */
1016 if ((err
= fb_alloc_cmap(&fb_display
[con
].cmap
,
1017 1<<fb_display
[con
].var
.bits_per_pixel
,
1019 DPRINTK("EXIT - fb_alloc_cmap failed\n");
1023 if (con
== currcon
) { /* current console? */
1024 DPRINTK("EXIT - Current console\n");
1025 return(fb_set_cmap(cmap
, kspc
, Cyber_setcolreg
, info
));
1027 fb_copy_cmap(cmap
, &fb_display
[con
].cmap
, kspc
? 0 : 1);
1035 * Pan or Wrap the Display
1037 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
1040 static int cyberfb_pan_display(struct fb_var_screeninfo
*var
, int con
,
1041 struct fb_info
*info
)
1048 * Cybervision Frame Buffer Specific ioctls
1051 static int cyberfb_ioctl(struct inode
*inode
, struct file
*file
,
1052 u_int cmd
, u_long arg
, int con
, struct fb_info
*info
)
1058 static struct fb_ops cyberfb_ops
= {
1059 cyberfb_open
, cyberfb_release
, cyberfb_get_fix
, cyberfb_get_var
,
1060 cyberfb_set_var
, cyberfb_get_cmap
, cyberfb_set_cmap
,
1061 cyberfb_pan_display
, cyberfb_ioctl
1065 int __init
cyberfb_setup(char *options
)
1070 fb_info
.fontname
[0] = '\0';
1072 if (!options
|| !*options
) {
1073 DPRINTK("EXIT - no options\n");
1077 for (this_opt
= strtok(options
, ","); this_opt
;
1078 this_opt
= strtok(NULL
, ",")) {
1079 if (!strcmp(this_opt
, "inverse")) {
1080 Cyberfb_inverse
= 1;
1082 } else if (!strncmp(this_opt
, "font:", 5)) {
1083 strcpy(fb_info
.fontname
, this_opt
+5);
1084 } else if (!strcmp (this_opt
, "cyber8")) {
1085 cyberfb_default
= cyberfb_predefined
[CYBER8_DEFMODE
].var
;
1086 cyberfb_usermode
= 1;
1087 } else if (!strcmp (this_opt
, "cyber16")) {
1088 cyberfb_default
= cyberfb_predefined
[CYBER16_DEFMODE
].var
;
1089 cyberfb_usermode
= 1;
1090 } else get_video_mode(this_opt
);
1093 DPRINTK("default mode: xres=%d, yres=%d, bpp=%d\n",
1094 cyberfb_default
.xres
,
1095 cyberfb_default
.yres
,
1096 cyberfb_default
.bits_per_pixel
);
1105 int __init
cyberfb_init(void)
1107 struct cyberfb_par par
;
1108 unsigned long board_addr
;
1109 unsigned long board_size
;
1110 const struct ConfigDev
*cd
;
1111 unsigned int CyberKey
= 0;
1114 if (!(CyberKey
= zorro_find(ZORRO_PROD_PHASE5_CYBERVISION64
, 0, 0))) {
1115 DPRINTK("EXIT - zorro_find failed\n");
1119 cd
= zorro_get_board (CyberKey
);
1120 zorro_config_board (CyberKey
, 0);
1121 board_addr
= (unsigned long)cd
->cd_BoardAddr
;
1122 board_size
= (unsigned long)cd
->cd_BoardSize
;
1123 DPRINTK("board_addr=%08lx\n", board_addr
);
1124 DPRINTK("board_size=%08lx\n", board_size
);
1126 CyberBase
= ioremap(board_addr
, board_size
);
1127 CyberRegs
= CyberBase
+ 0x02000000;
1128 CyberMem
= CyberBase
+ 0x01400000;
1129 DPRINTK("CyberBase=%08lx CyberRegs=%08lx CyberMem=%08lx\n",
1130 CyberBase
, (long unsigned int)CyberRegs
, CyberMem
);
1132 CyberMem_phys
= board_addr
+ 0x01400000;
1133 CyberRegs_phys
= CyberMem_phys
+ 0x00c00000;
1134 DPRINTK("CyberMem=%08lx CyberRegs=%08lx\n", CyberMem
,
1135 (long unsigned int)CyberRegs
);
1138 DPRINTK("Register state just after mapping memory\n");
1142 strcpy(fb_info
.modename
, cyberfb_name
);
1143 fb_info
.changevar
= NULL
;
1145 fb_info
.fbops
= &cyberfb_ops
;
1146 fb_info
.disp
= &disp
;
1147 fb_info
.switch_con
= &Cyberfb_switch
;
1148 fb_info
.updatevar
= &Cyberfb_updatevar
;
1149 fb_info
.blank
= &Cyberfb_blank
;
1152 /* ++Andre: set cyberfb default mode */
1153 if (!cyberfb_usermode
) {
1154 cyberfb_default
= cyberfb_predefined
[CYBER8_DEFMODE
].var
;
1155 DPRINTK("Use default cyber8 mode\n");
1157 Cyber_decode_var(&cyberfb_default
, &par
);
1158 Cyber_encode_var(&cyberfb_default
, &par
);
1160 do_fb_set_var(&cyberfb_default
, 1);
1161 cyberfb_get_var(&fb_display
[0].var
, -1, &fb_info
);
1162 cyberfb_set_disp(-1, &fb_info
);
1163 do_install_cmap(0, &fb_info
);
1165 if (register_framebuffer(&fb_info
) < 0) {
1166 DPRINTK("EXIT - register_framebuffer failed\n");
1170 printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
1171 GET_FB_IDX(fb_info
.node
), fb_info
.modename
, CyberSize
>>10);
1173 /* TODO: This driver cannot be unloaded yet */
1180 static int Cyberfb_switch(int con
, struct fb_info
*info
)
1183 /* Do we have to save the colormap? */
1184 if (fb_display
[currcon
].cmap
.len
) {
1185 fb_get_cmap(&fb_display
[currcon
].cmap
, 1, Cyber_getcolreg
,
1189 do_fb_set_var(&fb_display
[con
].var
, 1);
1191 /* Install new colormap */
1192 do_install_cmap(con
, info
);
1199 * Update the `var' structure (called by fbcon.c)
1201 * This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
1202 * Since it's called by a kernel driver, no range checking is done.
1205 static int Cyberfb_updatevar(int con
, struct fb_info
*info
)
1207 DPRINTK("Enter - Exit\n");
1216 static int __init
get_video_mode(const char *name
)
1221 for (i
= 0; i
< NUM_TOTAL_MODES
; i
++) {
1222 if (!strcmp(name
, cyberfb_predefined
[i
].name
)) {
1223 cyberfb_default
= cyberfb_predefined
[i
].var
;
1224 cyberfb_usermode
= 1;
1225 DPRINTK("EXIT - Matched predefined mode\n");
1234 * Text console acceleration
1237 #ifdef FBCON_HAS_CFB8
1238 static void fbcon_cyber8_bmove(struct display
*p
, int sy
, int sx
, int dy
,
1239 int dx
, int height
, int width
)
1242 sx
*= 8; dx
*= 8; width
*= 8;
1243 Cyber_BitBLT((u_short
)sx
, (u_short
)(sy
*fontheight(p
)), (u_short
)dx
,
1244 (u_short
)(dy
*fontheight(p
)), (u_short
)width
,
1245 (u_short
)(height
*fontheight(p
)), (u_short
)S3_NEW
);
1249 static void fbcon_cyber8_clear(struct vc_data
*conp
, struct display
*p
, int sy
,
1250 int sx
, int height
, int width
)
1255 sx
*= 8; width
*= 8;
1256 bg
= attr_bgcol_ec(p
,conp
);
1257 Cyber_RectFill((u_short
)sx
,
1258 (u_short
)(sy
*fontheight(p
)),
1260 (u_short
)(height
*fontheight(p
)),
1266 static void fbcon_cyber8_putc(struct vc_data
*conp
, struct display
*p
, int c
,
1271 fbcon_cfb8_putc(conp
, p
, c
, yy
, xx
);
1275 static void fbcon_cyber8_putcs(struct vc_data
*conp
, struct display
*p
,
1276 const unsigned short *s
, int count
,
1281 fbcon_cfb8_putcs(conp
, p
, s
, count
, yy
, xx
);
1285 static void fbcon_cyber8_revc(struct display
*p
, int xx
, int yy
)
1289 fbcon_cfb8_revc(p
, xx
, yy
);
1293 static struct display_switch fbcon_cyber8
= {
1294 fbcon_cfb8_setup
, fbcon_cyber8_bmove
, fbcon_cyber8_clear
, fbcon_cyber8_putc
,
1295 fbcon_cyber8_putcs
, fbcon_cyber8_revc
, NULL
, NULL
, fbcon_cfb8_clear_margins
,
1302 int init_module(void)
1304 return cyberfb_init();
1307 void cleanup_module(void)
1309 /* Not reached because the usecount will never be
1310 decremented to zero */
1311 unregister_framebuffer(&fb_info
);
1312 /* TODO: clean up ... */
1318 * Low level initialization routines for the CyberVision64 graphics card
1320 * Most of the following code is from cvision_core.c
1324 #define MAXPIXELCLOCK 135000000 /* safety */
1326 #ifdef CV_AGGRESSIVE_TIMING
1327 long cv64_memclk
= 55000000;
1329 long cv64_memclk
= 50000000;
1332 /*********************/
1334 static unsigned char clocks
[]={
1335 0x13, 0x61, 0x6b, 0x6d, 0x51, 0x69, 0x54, 0x69,
1336 0x4f, 0x68, 0x6b, 0x6b, 0x18, 0x61, 0x7b, 0x6c,
1337 0x51, 0x67, 0x24, 0x62, 0x56, 0x67, 0x77, 0x6a,
1338 0x1d, 0x61, 0x53, 0x66, 0x6b, 0x68, 0x79, 0x69,
1339 0x7c, 0x69, 0x7f, 0x69, 0x22, 0x61, 0x54, 0x65,
1340 0x56, 0x65, 0x58, 0x65, 0x67, 0x66, 0x41, 0x63,
1341 0x27, 0x61, 0x13, 0x41, 0x37, 0x62, 0x6b, 0x4d,
1342 0x23, 0x43, 0x51, 0x49, 0x79, 0x66, 0x54, 0x49,
1343 0x7d, 0x66, 0x34, 0x56, 0x4f, 0x63, 0x1f, 0x42,
1344 0x6b, 0x4b, 0x7e, 0x4d, 0x18, 0x41, 0x2a, 0x43,
1345 0x7b, 0x4c, 0x74, 0x4b, 0x51, 0x47, 0x65, 0x49,
1346 0x24, 0x42, 0x68, 0x49, 0x56, 0x47, 0x75, 0x4a,
1347 0x77, 0x4a, 0x31, 0x43, 0x1d, 0x41, 0x71, 0x49,
1348 0x53, 0x46, 0x29, 0x42, 0x6b, 0x48, 0x1f, 0x41,
1349 0x79, 0x49, 0x6f, 0x48, 0x7c, 0x49, 0x38, 0x43,
1350 0x7f, 0x49, 0x5d, 0x46, 0x22, 0x41, 0x53, 0x45,
1351 0x54, 0x45, 0x55, 0x45, 0x56, 0x45, 0x57, 0x45,
1352 0x58, 0x45, 0x25, 0x41, 0x67, 0x46, 0x5b, 0x45,
1353 0x41, 0x43, 0x78, 0x47, 0x27, 0x41, 0x51, 0x44,
1354 0x13, 0x21, 0x7d, 0x47, 0x37, 0x42, 0x71, 0x46,
1355 0x6b, 0x2d, 0x14, 0x21, 0x23, 0x23, 0x7d, 0x2f,
1356 0x51, 0x29, 0x61, 0x2b, 0x79, 0x46, 0x1d, 0x22,
1357 0x54, 0x29, 0x45, 0x27, 0x7d, 0x46, 0x7f, 0x46,
1358 0x4f, 0x43, 0x2f, 0x41, 0x1f, 0x22, 0x6a, 0x2b,
1359 0x6b, 0x2b, 0x5b, 0x29, 0x7e, 0x2d, 0x65, 0x44,
1360 0x18, 0x21, 0x5e, 0x29, 0x2a, 0x23, 0x45, 0x26,
1361 0x7b, 0x2c, 0x19, 0x21, 0x74, 0x2b, 0x75, 0x2b,
1362 0x51, 0x27, 0x3f, 0x25, 0x65, 0x29, 0x40, 0x25,
1363 0x24, 0x22, 0x41, 0x25, 0x68, 0x29, 0x42, 0x25,
1364 0x56, 0x27, 0x7e, 0x2b, 0x75, 0x2a, 0x1c, 0x21,
1365 0x77, 0x2a, 0x4f, 0x26, 0x31, 0x23, 0x6f, 0x29,
1366 0x1d, 0x21, 0x32, 0x23, 0x71, 0x29, 0x72, 0x29,
1367 0x53, 0x26, 0x69, 0x28, 0x29, 0x22, 0x75, 0x29,
1368 0x6b, 0x28, 0x1f, 0x21, 0x1f, 0x21, 0x6d, 0x28,
1369 0x79, 0x29, 0x2b, 0x22, 0x6f, 0x28, 0x59, 0x26,
1370 0x7c, 0x29, 0x7d, 0x29, 0x38, 0x23, 0x21, 0x21,
1371 0x7f, 0x29, 0x39, 0x23, 0x5d, 0x26, 0x75, 0x28,
1372 0x22, 0x21, 0x77, 0x28, 0x53, 0x25, 0x6c, 0x27,
1373 0x54, 0x25, 0x61, 0x26, 0x55, 0x25, 0x30, 0x22,
1374 0x56, 0x25, 0x63, 0x26, 0x57, 0x25, 0x71, 0x27,
1375 0x58, 0x25, 0x7f, 0x28, 0x25, 0x21, 0x74, 0x27,
1376 0x67, 0x26, 0x40, 0x23, 0x5b, 0x25, 0x26, 0x21,
1377 0x41, 0x23, 0x34, 0x22, 0x78, 0x27, 0x6b, 0x26,
1378 0x27, 0x21, 0x35, 0x22, 0x51, 0x24, 0x7b, 0x27,
1379 0x13, 0x1, 0x13, 0x1, 0x7d, 0x27, 0x4c, 0x9,
1380 0x37, 0x22, 0x5b, 0xb, 0x71, 0x26, 0x5c, 0xb,
1381 0x6b, 0xd, 0x47, 0x23, 0x14, 0x1, 0x4f, 0x9,
1382 0x23, 0x3, 0x75, 0x26, 0x7d, 0xf, 0x1c, 0x2,
1383 0x51, 0x9, 0x59, 0x24, 0x61, 0xb, 0x69, 0x25,
1384 0x79, 0x26, 0x34, 0x5, 0x1d, 0x2, 0x6b, 0x25,
1385 0x54, 0x9, 0x35, 0x5, 0x45, 0x7, 0x6d, 0x25,
1386 0x7d, 0x26, 0x16, 0x1, 0x7f, 0x26, 0x77, 0xd,
1387 0x4f, 0x23, 0x78, 0xd, 0x2f, 0x21, 0x27, 0x3,
1388 0x1f, 0x2, 0x59, 0x9, 0x6a, 0xb, 0x73, 0x25,
1389 0x6b, 0xb, 0x63, 0x24, 0x5b, 0x9, 0x20, 0x2,
1390 0x7e, 0xd, 0x4b, 0x7, 0x65, 0x24, 0x43, 0x22,
1391 0x18, 0x1, 0x6f, 0xb, 0x5e, 0x9, 0x70, 0xb,
1392 0x2a, 0x3, 0x33, 0x4, 0x45, 0x6, 0x60, 0x9,
1393 0x7b, 0xc, 0x19, 0x1, 0x19, 0x1, 0x7d, 0xc,
1394 0x74, 0xb, 0x50, 0x7, 0x75, 0xb, 0x63, 0x9,
1395 0x51, 0x7, 0x23, 0x2, 0x3f, 0x5, 0x1a, 0x1,
1396 0x65, 0x9, 0x2d, 0x3, 0x40, 0x5, 0x0, 0x0,
1399 /* Console colors */
1400 unsigned char cvconscolors
[16][3] = { /* background, foreground, hilite */
1420 /* -------------------- Hardware specific routines ------------------------- */
1422 /* Read Attribute Controller Register=idx */
1423 inline unsigned char RAttr (volatile unsigned char *regs
, short idx
)
1425 wb_64 (regs
, ACT_ADDRESS_W
, idx
);
1428 return (rb_64(regs
, ACT_ADDRESS_R
));
1431 /* Read Sequencer Register=idx */
1432 inline unsigned char RSeq (volatile unsigned char *regs
, short idx
)
1434 wb_64 (regs
, SEQ_ADDRESS
, idx
);
1436 return (rb_64(regs
, SEQ_ADDRESS_R
));
1439 /* Read CRT Controller Register=idx */
1440 inline unsigned char RCrt (volatile unsigned char *regs
, short idx
)
1442 wb_64 (regs
, CRT_ADDRESS
, idx
);
1444 return (rb_64(regs
, CRT_ADDRESS_R
));
1447 /* Read Graphics Controller Register=idx */
1448 inline unsigned char RGfx (volatile unsigned char *regs
, short idx
)
1450 wb_64 (regs
, GCT_ADDRESS
, idx
);
1452 return (rb_64(regs
, GCT_ADDRESS_R
));
1456 * Special wakeup/passthrough registers on graphics boards
1459 inline void cv64_write_port (unsigned short bits
,
1460 volatile unsigned char *base
)
1462 volatile unsigned char *addr
;
1463 static unsigned char cvportbits
= 0; /* Mirror port bits here */
1466 addr
= base
+ 0x40001;
1467 if (bits
& 0x8000) {
1468 cvportbits
|= bits
& 0xff; /* Set bits */
1469 DPRINTK("Set bits: %04x\n", bits
);
1472 bits
= (~bits
) & 0xff;
1473 cvportbits
&= bits
; /* Clear bits */
1474 DPRINTK("Clear bits: %04x\n", bits
);
1482 * Monitor switch on CyberVision board
1485 * 0 = CyberVision Signal
1487 * board = board addr
1490 inline void cvscreen (int toggle
, volatile unsigned char *board
)
1494 DPRINTK("Show Amiga video\n");
1495 cv64_write_port (0x10, board
);
1497 DPRINTK("Show CyberVision video\n");
1498 cv64_write_port (0x8010, board
);
1503 /* Control screen display */
1504 /* toggle: 0 = on, 1 = off */
1505 /* board = registerbase */
1506 inline void gfx_on_off(int toggle
, volatile unsigned char *regs
)
1512 toggle
= toggle
<< 5;
1513 DPRINTK("Turn display %s\n", (toggle
? "off" : "on"));
1515 r
= (int) RSeq(regs
, SEQ_ID_CLOCKING_MODE
);
1516 r
&= 0xdf; /* Set bit 5 to 0 */
1518 WSeq (regs
, SEQ_ID_CLOCKING_MODE
, r
| toggle
);
1523 * Computes M, N, and R values from
1524 * given input frequency. It uses a table of
1525 * precomputed values, to keep CPU time low.
1527 * The return value consist of:
1528 * lower byte: Bits 4-0: N Divider Value
1529 * Bits 5-6: R Value for e.g. SR10 or SR12
1530 * higher byte: Bits 0-6: M divider value for e.g. SR11 or SR13
1532 static unsigned short cv64_compute_clock(unsigned long freq
)
1534 static unsigned char *mnr
, *save
; /* M, N + R vals */
1535 unsigned long work_freq
, r
;
1540 if (freq
< 12500000 || freq
> MAXPIXELCLOCK
) {
1541 printk("CV64 driver: Illegal clock frequency %ld, using 25MHz\n",
1545 DPRINTK("Freq = %ld\n", freq
);
1546 mnr
= clocks
; /* there the vals are stored */
1549 while (*mnr
) { /* mnr vals are 0-terminated */
1550 work_freq
= (0x37EE * (mnr
[0] + 2)) / ((mnr
[1] & 0x1F) + 2);
1552 r
= (mnr
[1] >> 5) & 0x03;
1554 work_freq
= work_freq
>> r
; /* r is the freq divider */
1557 work_freq
*= 0x3E8; /* 2nd part of OSC */
1559 diff
= abs(freq
- work_freq
);
1563 /* In save are the vals for minimal diff */
1568 erg
= *((unsigned short *)save
);
1574 static int cv_has_4mb (volatile unsigned char *fb
)
1576 volatile unsigned long *tr
, *tw
;
1579 /* write patterns in memory and test if they can be read */
1580 tw
= (volatile unsigned long *) fb
;
1581 tr
= (volatile unsigned long *) (fb
+ 0x02000000);
1585 if (*tr
!= 0x87654321) {
1586 DPRINTK("EXIT - <4MB\n");
1590 /* upper memory region */
1591 tw
= (volatile unsigned long *) (fb
+ 0x00200000);
1592 tr
= (volatile unsigned long *) (fb
+ 0x02200000);
1596 if (*tr
!= 0x87654321) {
1597 DPRINTK("EXIT - <4MB\n");
1603 if (*tr
!= 0xAAAAAAAA) {
1604 DPRINTK("EXIT - <4MB\n");
1610 if (*tr
!= 0x55555555) {
1611 DPRINTK("EXIT - <4MB\n");
1619 static void cv64_board_init (void)
1621 volatile unsigned char *regs
= CyberRegs
;
1623 unsigned int clockpar
;
1629 * Special CyberVision 64 board operations
1632 for (i
= 0; i
< 6; i
++) {
1633 cv64_write_port (0xff, CyberBase
);
1635 /* Return to operational mode */
1636 cv64_write_port (0x8004, CyberBase
);
1639 * Generic (?) S3 chip wakeup
1641 /* Disable I/O & memory decoders, video in setup mode */
1642 wb_64 (regs
, SREG_VIDEO_SUBS_ENABLE
, 0x10);
1643 /* Video responds to cmds, addrs & data */
1644 wb_64 (regs
, SREG_OPTION_SELECT
, 0x1);
1645 /* Enable I/O & memory decoders, video in operational mode */
1646 wb_64 (regs
, SREG_VIDEO_SUBS_ENABLE
, 0x8);
1647 /* VGA color emulation, enable cpu access to display mem */
1648 wb_64 (regs
, GREG_MISC_OUTPUT_W
, 0x03);
1649 /* Unlock S3 VGA regs */
1650 WCrt (regs
, CRT_ID_REGISTER_LOCK_1
, 0x48);
1651 /* Unlock system control & extension registers */
1652 WCrt (regs
, CRT_ID_REGISTER_LOCK_2
, 0xA5);
1653 /* GRF - Enable interrupts */
1654 /* Enable enhanced regs access, Ready cntl 0 wait states */
1655 test
= RCrt (regs
, CRT_ID_SYSTEM_CONFIG
);
1656 test
= test
| 0x01; /* enable enhanced register access */
1657 test
= test
& 0xEF; /* clear bit 4, 0 wait state */
1658 WCrt (regs
, CRT_ID_SYSTEM_CONFIG
, test
);
1660 * bit 0=1: Enable enhaced mode functions
1661 * bit 2=0: Enhanced mode 8+ bits/pixel
1662 * bit 4=1: Enable linear addressing
1663 * bit 5=1: Enable MMIO
1665 wb_64 (regs
, ECR_ADV_FUNC_CNTL
, 0x31);
1667 * bit 0=1: Color emulation
1668 * bit 1=1: Enable CPU access to display memory
1669 * bit 5=1: Select high 64K memory page
1672 wb_64 (regs
, GREG_MISC_OUTPUT_W
, 0x23);
1675 WCrt (regs
, CRT_ID_EXT_SYS_CNTL_4
, 0x0);
1677 /* Reset. This does nothing on Trio, but standard VGA practice */
1678 /* WSeq (CyberRegs, SEQ_ID_RESET, 0x03); */
1679 /* Character clocks 8 dots wide */
1680 WSeq (regs
, SEQ_ID_CLOCKING_MODE
, 0x01);
1681 /* Enable cpu write to all color planes */
1682 WSeq (regs
, SEQ_ID_MAP_MASK
, 0x0F);
1683 /* Font table in 1st 8k of plane 2, font A=B disables swtich */
1684 WSeq (regs
, SEQ_ID_CHAR_MAP_SELECT
, 0x0);
1685 /* Allow mem access to 256kb */
1686 WSeq (regs
, SEQ_ID_MEMORY_MODE
, 0x2);
1687 /* Unlock S3 extensions to VGA Sequencer regs */
1688 WSeq (regs
, SEQ_ID_UNLOCK_EXT
, 0x6);
1690 /* Enable 4MB fast page mode */
1691 test
= RSeq (regs
, SEQ_ID_BUS_REQ_CNTL
);
1692 test
= test
| 1 << 6;
1693 WSeq (regs
, SEQ_ID_BUS_REQ_CNTL
, test
);
1695 /* Faster LUT write: 1 DCLK LUT write cycle, RAMDAC clk doubled */
1696 WSeq (regs
, SEQ_ID_RAMDAC_CNTL
, 0xC0);
1698 /* Clear immediate clock load bit */
1699 test
= RSeq (regs
, SEQ_ID_CLKSYN_CNTL_2
);
1701 /* If > 55MHz, enable 2 cycle memory write */
1702 if (cv64_memclk
>= 55000000) {
1705 WSeq (regs
, SEQ_ID_CLKSYN_CNTL_2
, test
);
1707 /* Set MCLK value */
1708 clockpar
= cv64_compute_clock (cv64_memclk
);
1709 test
= (clockpar
& 0xFF00) >> 8;
1710 WSeq (regs
, SEQ_ID_MCLK_HI
, test
);
1711 test
= clockpar
& 0xFF;
1712 WSeq (regs
, SEQ_ID_MCLK_LO
, test
);
1714 /* Chip rev specific: Not in my Trio manual!!! */
1715 if (RCrt (regs
, CRT_ID_REVISION
) == 0x10)
1716 WSeq (regs
, SEQ_ID_MORE_MAGIC
, test
);
1718 /* We now load an 25 MHz, 31kHz, 640x480 standard VGA Mode. */
1720 /* Set DCLK value */
1721 WSeq (regs
, SEQ_ID_DCLK_HI
, 0x13);
1722 WSeq (regs
, SEQ_ID_DCLK_LO
, 0x41);
1724 /* Load DCLK (and MCLK?) immediately */
1725 test
= RSeq (regs
, SEQ_ID_CLKSYN_CNTL_2
);
1727 WSeq (regs
, SEQ_ID_CLKSYN_CNTL_2
, test
);
1729 /* Enable loading of DCLK */
1730 test
= rb_64(regs
, GREG_MISC_OUTPUT_R
);
1732 wb_64 (regs
, GREG_MISC_OUTPUT_W
, test
);
1734 /* Turn off immediate xCLK load */
1735 WSeq (regs
, SEQ_ID_CLKSYN_CNTL_2
, 0x2);
1737 /* Horizontal character clock counts */
1738 /* 8 LSB of 9 bits = total line - 5 */
1739 WCrt (regs
, CRT_ID_HOR_TOTAL
, 0x5F);
1740 /* Active display line */
1741 WCrt (regs
, CRT_ID_HOR_DISP_ENA_END
, 0x4F);
1742 /* Blank assertion start */
1743 WCrt (regs
, CRT_ID_START_HOR_BLANK
, 0x50);
1744 /* Blank assertion end */
1745 WCrt (regs
, CRT_ID_END_HOR_BLANK
, 0x82);
1746 /* HSYNC assertion start */
1747 WCrt (regs
, CRT_ID_START_HOR_RETR
, 0x54);
1748 /* HSYNC assertion end */
1749 WCrt (regs
, CRT_ID_END_HOR_RETR
, 0x80);
1750 WCrt (regs
, CRT_ID_VER_TOTAL
, 0xBF);
1751 WCrt (regs
, CRT_ID_OVERFLOW
, 0x1F);
1752 WCrt (regs
, CRT_ID_PRESET_ROW_SCAN
, 0x0);
1753 WCrt (regs
, CRT_ID_MAX_SCAN_LINE
, 0x40);
1754 WCrt (regs
, CRT_ID_CURSOR_START
, 0x00);
1755 WCrt (regs
, CRT_ID_CURSOR_END
, 0x00);
1756 WCrt (regs
, CRT_ID_START_ADDR_HIGH
, 0x00);
1757 WCrt (regs
, CRT_ID_START_ADDR_LOW
, 0x00);
1758 WCrt (regs
, CRT_ID_CURSOR_LOC_HIGH
, 0x00);
1759 WCrt (regs
, CRT_ID_CURSOR_LOC_LOW
, 0x00);
1760 WCrt (regs
, CRT_ID_START_VER_RETR
, 0x9C);
1761 WCrt (regs
, CRT_ID_END_VER_RETR
, 0x0E);
1762 WCrt (regs
, CRT_ID_VER_DISP_ENA_END
, 0x8F);
1763 WCrt (regs
, CRT_ID_SCREEN_OFFSET
, 0x50);
1764 WCrt (regs
, CRT_ID_UNDERLINE_LOC
, 0x00);
1765 WCrt (regs
, CRT_ID_START_VER_BLANK
, 0x96);
1766 WCrt (regs
, CRT_ID_END_VER_BLANK
, 0xB9);
1767 WCrt (regs
, CRT_ID_MODE_CONTROL
, 0xE3);
1768 WCrt (regs
, CRT_ID_LINE_COMPARE
, 0xFF);
1769 WCrt (regs
, CRT_ID_BACKWAD_COMP_3
, 0x10); /* FIFO enabled */
1770 WCrt (regs
, CRT_ID_MISC_1
, 0x35);
1771 WCrt (regs
, CRT_ID_DISPLAY_FIFO
, 0x5A);
1772 WCrt (regs
, CRT_ID_EXT_MEM_CNTL_2
, 0x70);
1773 WCrt (regs
, CRT_ID_LAW_POS_LO
, 0x40);
1774 WCrt (regs
, CRT_ID_EXT_MEM_CNTL_3
, 0xFF);
1776 WGfx (regs
, GCT_ID_SET_RESET
, 0x0);
1777 WGfx (regs
, GCT_ID_ENABLE_SET_RESET
, 0x0);
1778 WGfx (regs
, GCT_ID_COLOR_COMPARE
, 0x0);
1779 WGfx (regs
, GCT_ID_DATA_ROTATE
, 0x0);
1780 WGfx (regs
, GCT_ID_READ_MAP_SELECT
, 0x0);
1781 WGfx (regs
, GCT_ID_GRAPHICS_MODE
, 0x40);
1782 WGfx (regs
, GCT_ID_MISC
, 0x01);
1783 WGfx (regs
, GCT_ID_COLOR_XCARE
, 0x0F);
1784 WGfx (regs
, GCT_ID_BITMASK
, 0xFF);
1786 /* Colors for text mode */
1787 for (i
= 0; i
< 0xf; i
++)
1790 WAttr (regs
, ACT_ID_ATTR_MODE_CNTL
, 0x41);
1791 WAttr (regs
, ACT_ID_OVERSCAN_COLOR
, 0x01);
1792 WAttr (regs
, ACT_ID_COLOR_PLANE_ENA
, 0x0F);
1793 WAttr (regs
, ACT_ID_HOR_PEL_PANNING
, 0x0);
1794 WAttr (regs
, ACT_ID_COLOR_SELECT
, 0x0);
1796 wb_64 (regs
, VDAC_MASK
, 0xFF);
1798 *((unsigned long *) (regs
+ ECR_FRGD_COLOR
)) = 0xFF;
1799 *((unsigned long *) (regs
+ ECR_BKGD_COLOR
)) = 0;
1801 /* Colors initially set to grayscale */
1803 wb_64 (regs
, VDAC_ADDRESS_W
, 0);
1804 for (i
= 255; i
>= 0; i
--) {
1805 wb_64(regs
, VDAC_DATA
, i
);
1806 wb_64(regs
, VDAC_DATA
, i
);
1807 wb_64(regs
, VDAC_DATA
, i
);
1810 /* GFx hardware cursor off */
1811 WCrt (regs
, CRT_ID_HWGC_MODE
, 0x00);
1813 /* Set first to 4MB, so test will work */
1814 WCrt (regs
, CRT_ID_LAW_CNTL
, 0x13);
1815 /* Find "correct" size of fbmem of Z3 board */
1816 if (cv_has_4mb (CyberMem
)) {
1817 CyberSize
= 1024 * 1024 * 4;
1818 WCrt (regs
, CRT_ID_LAW_CNTL
, 0x13);
1819 DPRINTK("4MB board\n");
1821 CyberSize
= 1024 * 1024 * 2;
1822 WCrt (regs
, CRT_ID_LAW_CNTL
, 0x12);
1823 DPRINTK("2MB board\n");
1826 /* Initialize graphics engine */
1828 vgaw16 (regs
, ECR_FRGD_MIX
, 0x27);
1829 vgaw16 (regs
, ECR_BKGD_MIX
, 0x07);
1830 vgaw16 (regs
, ECR_READ_REG_DATA
, 0x1000);
1832 vgaw16 (regs
, ECR_READ_REG_DATA
, 0x2000);
1834 vgaw16 (regs
, ECR_READ_REG_DATA
, 0x3FFF);
1837 vgaw16 (regs
, ECR_READ_REG_DATA
, 0x4FFF);
1839 vgaw16 (regs
, ECR_BITPLANE_WRITE_MASK
, ~0);
1841 vgaw16 (regs
, ECR_READ_REG_DATA
, 0xE000);
1842 vgaw16 (regs
, ECR_CURRENT_Y_POS2
, 0x00);
1843 vgaw16 (regs
, ECR_CURRENT_X_POS2
, 0x00);
1844 vgaw16 (regs
, ECR_READ_REG_DATA
, 0xA000);
1845 vgaw16 (regs
, ECR_DEST_Y__AX_STEP
, 0x00);
1846 vgaw16 (regs
, ECR_DEST_Y2__AX_STEP2
, 0x00);
1847 vgaw16 (regs
, ECR_DEST_X__DIA_STEP
, 0x00);
1848 vgaw16 (regs
, ECR_DEST_X2__DIA_STEP2
, 0x00);
1849 vgaw16 (regs
, ECR_SHORT_STROKE
, 0x00);
1850 vgaw16 (regs
, ECR_DRAW_CMD
, 0x01);
1854 vgaw16 (regs
, ECR_READ_REG_DATA
, 0x4FFF);
1855 vgaw16 (regs
, ECR_BKGD_COLOR
, 0x01);
1856 vgaw16 (regs
, ECR_FRGD_COLOR
, 0x00);
1859 /* Enable video display (set bit 5) */
1860 /* ARB - Would also seem to write to AR13.
1861 * May want to use parts of WAttr to set JUST bit 5
1863 WAttr (regs
, 0x33, 0);
1865 /* GRF - function code ended here */
1867 /* Turn gfx on again */
1868 gfx_on_off (0, regs
);
1871 cvscreen (0, CyberBase
);
1876 static void cv64_load_video_mode (struct fb_var_screeninfo
*video_mode
)
1878 volatile unsigned char *regs
= CyberRegs
;
1881 unsigned short HT
, HDE
, HBS
, HBE
, HSS
, HSE
, VDE
, VBS
, VBE
, VSS
, VSE
, VT
;
1882 char LACE
, DBLSCAN
, TEXT
, CONSOLE
;
1883 int cr50
, sr15
, sr18
, clock_mode
, test
;
1885 int tfillm
, temptym
;
1888 /* ---------------- */
1889 int xres
, hfront
, hsync
, hback
;
1890 int yres
, vfront
, vsync
, vback
;
1896 /* ---------------- */
1899 TEXT
= 0; /* if depth == 4 */
1900 CONSOLE
= 0; /* mode num == 255 (console) */
1901 fx
= fy
= 8; /* force 8x8 font */
1903 /* GRF - Disable interrupts */
1905 gfx_on_off (1, regs
);
1907 switch (video_mode
->bits_per_pixel
) {
1918 bpp
= video_mode
->bits_per_pixel
;
1919 xres
= video_mode
->xres
;
1920 hfront
= video_mode
->right_margin
;
1921 hsync
= video_mode
->hsync_len
;
1922 hback
= video_mode
->left_margin
;
1927 if (video_mode
->vmode
& FB_VMODE_DOUBLE
) {
1928 yres
= video_mode
->yres
* 2;
1929 vfront
= video_mode
->lower_margin
* 2;
1930 vsync
= video_mode
->vsync_len
* 2;
1931 vback
= video_mode
->upper_margin
* 2;
1933 } else if (video_mode
->vmode
& FB_VMODE_INTERLACED
) {
1934 yres
= (video_mode
->yres
+ 1) / 2;
1935 vfront
= (video_mode
->lower_margin
+ 1) / 2;
1936 vsync
= (video_mode
->vsync_len
+ 1) / 2;
1937 vback
= (video_mode
->upper_margin
+ 1) / 2;
1940 yres
= video_mode
->yres
;
1941 vfront
= video_mode
->lower_margin
;
1942 vsync
= video_mode
->vsync_len
;
1943 vback
= video_mode
->upper_margin
;
1946 /* ARB Dropping custom setup method from cvision.c */
1948 if (cvision_custom_mode
) {
1949 HBS
= hbs
/ 8 * hmul
;
1950 HBE
= hbe
/ 8 * hmul
;
1951 HSS
= hss
/ 8 * hmul
;
1952 HSE
= hse
/ 8 * hmul
;
1953 HT
= ht
/ 8 * hmul
- 5;
1964 HBS
= hmul
* (xres
/ 8);
1965 HBE
= hmul
* ((xres
/8) + (hfront
/8) + (hsync
/8) + (hback
/8) - 2);
1966 HSS
= hmul
* ((xres
/8) + (hfront
/8) + 2);
1967 HSE
= hmul
* ((xres
/8) + (hfront
/8) + (hsync
/8) + 1);
1968 HT
= hmul
* ((xres
/8) + (hfront
/8) + (hsync
/8) + (hback
/8));
1971 VBE
= yres
+ vfront
+ vsync
+ vback
- 2;
1972 VSS
= yres
+ vfront
- 1;
1973 VSE
= yres
+ vfront
+ vsync
- 1;
1974 VT
= yres
+ vfront
+ vsync
+ vback
- 2;
1977 wb_64 (regs
, ECR_ADV_FUNC_CNTL
, (TEXT
? 0x00 : 0x31));
1980 HDE
= ((video_mode
->xres
+ fx
- 1) / fx
) - 1;
1982 HDE
= (video_mode
->xres
+ 3) * hmul
/ 8 - 1;
1984 VDE
= video_mode
->yres
- 1;
1986 WCrt (regs
, CRT_ID_HWGC_MODE
, 0x00);
1987 WCrt (regs
, CRT_ID_EXT_DAC_CNTL
, 0x00);
1989 WSeq (regs
, SEQ_ID_MEMORY_MODE
,
1990 (TEXT
|| (video_mode
->bits_per_pixel
== 1)) ? 0x06 : 0x0e);
1991 WGfx (regs
, GCT_ID_READ_MAP_SELECT
, 0x00);
1992 WSeq (regs
, SEQ_ID_MAP_MASK
,
1993 (video_mode
->bits_per_pixel
== 1) ? 0x01 : 0xFF);
1994 WSeq (regs
, SEQ_ID_CHAR_MAP_SELECT
, 0x00);
1996 /* cv64_compute_clock accepts arguments in Hz */
1997 /* pixclock is in ps ... convert to Hz */
2000 freq_f
= (1.0 / (float) video_mode
->pixclock
) * 1000000000;
2001 freq
= ((long) freq_f
) * 1000;
2003 /* freq = (long) ((long long)1000000000000 / (long long) video_mode->pixclock);
2005 freq
= (1000000000 / video_mode
->pixclock
) * 1000;
2008 mnr
= cv64_compute_clock (freq
);
2009 WSeq (regs
, SEQ_ID_DCLK_HI
, ((mnr
& 0xFF00) >> 8));
2010 WSeq (regs
, SEQ_ID_DCLK_LO
, (mnr
& 0xFF));
2012 /* Load display parameters into board */
2013 WCrt (regs
, CRT_ID_EXT_HOR_OVF
,
2014 ((HT
& 0x100) ? 0x01 : 0x00) |
2015 ((HDE
& 0x100) ? 0x02 : 0x00) |
2016 ((HBS
& 0x100) ? 0x04 : 0x00) |
2017 /* ((HBE & 0x40) ? 0x08 : 0x00) | */
2018 ((HSS
& 0x100) ? 0x10 : 0x00) |
2019 /* ((HSE & 0x20) ? 0x20 : 0x00) | */
2020 (((HT
-5) & 0x100) ? 0x40 : 0x00)
2023 WCrt (regs
, CRT_ID_EXT_VER_OVF
,
2025 ((VT
& 0x400) ? 0x01 : 0x00) |
2026 ((VDE
& 0x400) ? 0x02 : 0x00) |
2027 ((VBS
& 0x400) ? 0x04 : 0x00) |
2028 ((VSS
& 0x400) ? 0x10 : 0x00)
2031 WCrt (regs
, CRT_ID_HOR_TOTAL
, HT
);
2032 WCrt (regs
, CRT_ID_DISPLAY_FIFO
, HT
- 5);
2033 WCrt (regs
, CRT_ID_HOR_DISP_ENA_END
, ((HDE
>= HBS
) ? (HBS
- 1) : HDE
));
2034 WCrt (regs
, CRT_ID_START_HOR_BLANK
, HBS
);
2035 WCrt (regs
, CRT_ID_END_HOR_BLANK
, ((HBE
& 0x1F) | 0x80));
2036 WCrt (regs
, CRT_ID_START_HOR_RETR
, HSS
);
2037 WCrt (regs
, CRT_ID_END_HOR_RETR
,
2039 ((HBE
& 0x20) ? 0x80 : 0x00)
2041 WCrt (regs
, CRT_ID_VER_TOTAL
, VT
);
2042 WCrt (regs
, CRT_ID_OVERFLOW
,
2044 ((VT
& 0x100) ? 0x01 : 0x00) |
2045 ((VDE
& 0x100) ? 0x02 : 0x00) |
2046 ((VSS
& 0x100) ? 0x04 : 0x00) |
2047 ((VBS
& 0x100) ? 0x08 : 0x00) |
2048 ((VT
& 0x200) ? 0x20 : 0x00) |
2049 ((VDE
& 0x200) ? 0x40 : 0x00) |
2050 ((VSS
& 0x200) ? 0x80 : 0x00)
2052 WCrt (regs
, CRT_ID_MAX_SCAN_LINE
,
2054 (DBLSCAN
? 0x80 : 0x00) |
2055 ((VBS
& 0x200) ? 0x20 : 0x00) |
2056 (TEXT
? ((fy
- 1) & 0x1F) : 0x00)
2059 WCrt (regs
, CRT_ID_MODE_CONTROL
, 0xE3);
2065 WCrt (regs
, CRT_ID_CURSOR_START
, (fy
& 0x1f) - 2);
2066 WCrt (regs
, CRT_ID_CURSOR_END
, (fy
& 0x1F) - 1);
2068 WCrt (regs
, CRT_ID_CURSOR_START
, 0x00);
2069 WCrt (regs
, CRT_ID_CURSOR_END
, fy
& 0x1F);
2071 WCrt (regs
, CRT_ID_UNDERLINE_LOC
, (fy
- 1) & 0x1F);
2072 WCrt (regs
, CRT_ID_CURSOR_LOC_HIGH
, 0x00);
2073 WCrt (regs
, CRT_ID_CURSOR_LOC_LOW
, 0x00);
2076 WCrt (regs
, CRT_ID_START_ADDR_HIGH
, 0x00);
2077 WCrt (regs
, CRT_ID_START_ADDR_LOW
, 0x00);
2078 WCrt (regs
, CRT_ID_START_VER_RETR
, VSS
);
2079 WCrt (regs
, CRT_ID_END_VER_RETR
, (VSE
& 0x0F));
2080 WCrt (regs
, CRT_ID_VER_DISP_ENA_END
, VDE
);
2081 WCrt (regs
, CRT_ID_START_VER_BLANK
, VBS
);
2082 WCrt (regs
, CRT_ID_END_VER_BLANK
, VBE
);
2083 WCrt (regs
, CRT_ID_LINE_COMPARE
, 0xFF);
2084 WCrt (regs
, CRT_ID_LACE_RETR_START
, HT
/ 2);
2085 WCrt (regs
, CRT_ID_LACE_CONTROL
, (LACE
? 0x20 : 0x00));
2086 WGfx (regs
, GCT_ID_GRAPHICS_MODE
,
2087 ((TEXT
|| (video_mode
->bits_per_pixel
== 1)) ? 0x00 : 0x40));
2088 WGfx (regs
, GCT_ID_MISC
, (TEXT
? 0x04 : 0x01));
2089 WSeq (regs
, SEQ_ID_MEMORY_MODE
,
2090 ((TEXT
|| (video_mode
->bits_per_pixel
== 1)) ? 0x06 : 0x02));
2092 wb_64 (regs
, VDAC_MASK
, 0xFF);
2095 test
= RCrt (regs
, CRT_ID_BACKWAD_COMP_2
);
2096 WCrt (regs
, CRT_ID_BACKWAD_COMP_2
, (test
| 0x20));
2098 sr15
= RSeq (regs
, SEQ_ID_CLKSYN_CNTL_2
);
2100 sr18
= RSeq (regs
, SEQ_ID_RAMDAC_CNTL
);
2105 test
= RCrt (regs
, CRT_ID_EXT_MISC_CNTL_2
);
2108 /* Clear roxxler byte-swapping... */
2109 cv64_write_port (0x0040, CyberBase
);
2110 cv64_write_port (0x0020, CyberBase
);
2112 switch (video_mode
->bits_per_pixel
) {
2115 HDE
= video_mode
->xres
/ 16;
2119 if (freq
> 80000000) {
2120 clock_mode
= 0x10 | 0x02;
2124 HDE
= video_mode
->xres
/ 8;
2129 cv64_write_port (0x8020, CyberBase
);
2131 HDE
= video_mode
->xres
/ 4;
2136 cv64_write_port (0x8020, CyberBase
);
2138 HDE
= video_mode
->xres
/ 4;
2144 cv64_write_port (0x8040, CyberBase
);
2146 HDE
= video_mode
->xres
/ 2;
2151 WCrt (regs
, CRT_ID_EXT_MISC_CNTL_2
, clock_mode
| test
);
2152 WSeq (regs
, SEQ_ID_CLKSYN_CNTL_2
, sr15
);
2153 WSeq (regs
, SEQ_ID_RAMDAC_CNTL
, sr18
);
2154 WCrt (regs
, CRT_ID_SCREEN_OFFSET
, HDE
);
2156 WCrt (regs
, CRT_ID_MISC_1
, (TEXT
? 0x05 : 0x35));
2158 test
= RCrt (regs
, CRT_ID_EXT_SYS_CNTL_2
);
2160 test
|= (HDE
>> 4) & 0x30;
2161 WCrt (regs
, CRT_ID_EXT_SYS_CNTL_2
, test
);
2163 /* Set up graphics engine */
2164 switch (video_mode
->xres
) {
2193 WCrt (regs
, CRT_ID_EXT_SYS_CNTL_1
, cr50
);
2196 WAttr (regs
, ACT_ID_ATTR_MODE_CNTL
, (TEXT
? 0x08 : 0x41));
2198 WAttr (regs
, ACT_ID_COLOR_PLANE_ENA
,
2199 (video_mode
->bits_per_pixel
== 1) ? 0x01 : 0x0F);
2202 tfillm
= (96 * (cv64_memclk
/ 1000)) / 240000;
2204 switch (video_mode
->bits_per_pixel
) {
2207 temptym
= (24 * (cv64_memclk
/ 1000)) / (freq
/ 1000);
2211 temptym
= (48 * (cv64_memclk
/ 1000)) / (freq
/ 1000);
2214 temptym
= (192 * (cv64_memclk
/ 1000)) / (freq
/ 1000);
2217 temptym
= (96 * (cv64_memclk
/ 1000)) / (freq
/ 1000);
2221 m
= (temptym
- tfillm
- 9) / 2;
2224 m
= (m
& 0x1F) << 3;
2229 WCrt (regs
, CRT_ID_EXT_MEM_CNTL_2
, m
);
2230 WCrt (regs
, CRT_ID_EXT_MEM_CNTL_3
, n
);
2233 /* Text initialization */
2236 /* Do text initialization here ! */
2241 wb_64 (regs
, VDAC_ADDRESS_W
, 0);
2242 for (i
= 0; i
< 4; i
++) {
2243 wb_64 (regs
, VDAC_DATA
, cvconscolors
[i
][0]);
2244 wb_64 (regs
, VDAC_DATA
, cvconscolors
[i
][1]);
2245 wb_64 (regs
, VDAC_DATA
, cvconscolors
[i
][2]);
2249 WAttr (regs
, 0x33, 0);
2251 /* Turn gfx on again */
2252 gfx_on_off (0, (volatile unsigned char *) regs
);
2255 cvscreen (0, CyberBase
);
2260 void cvision_bitblt (u_short sx
, u_short sy
, u_short dx
, u_short dy
,
2261 u_short w
, u_short h
)
2263 volatile unsigned char *regs
= CyberRegs
;
2264 unsigned short drawdir
= 0;
2282 vgaw16 (regs
, ECR_READ_REG_DATA
, 0xA000);
2283 vgaw16 (regs
, ECR_BKGD_MIX
, 0x7);
2284 vgaw16 (regs
, ECR_FRGD_MIX
, 0x67);
2285 vgaw16 (regs
, ECR_BKGD_COLOR
, 0x0);
2286 vgaw16 (regs
, ECR_FRGD_COLOR
, 0x1);
2287 vgaw16 (regs
, ECR_BITPLANE_READ_MASK
, 0x1);
2288 vgaw16 (regs
, ECR_BITPLANE_WRITE_MASK
, 0xFFF);
2289 vgaw16 (regs
, ECR_CURRENT_Y_POS
, sy
);
2290 vgaw16 (regs
, ECR_CURRENT_X_POS
, sx
);
2291 vgaw16 (regs
, ECR_DEST_Y__AX_STEP
, dy
);
2292 vgaw16 (regs
, ECR_DEST_X__DIA_STEP
, dx
);
2293 vgaw16 (regs
, ECR_READ_REG_DATA
, h
- 1);
2294 vgaw16 (regs
, ECR_MAJ_AXIS_PIX_CNT
, w
- 1);
2295 vgaw16 (regs
, ECR_DRAW_CMD
, 0xC051 | drawdir
);
2299 void cvision_clear (u_short dx
, u_short dy
, u_short w
, u_short h
, u_short bg
)
2301 volatile unsigned char *regs
= CyberRegs
;
2304 vgaw16 (regs
, ECR_FRGD_MIX
, 0x0027);
2305 vgaw16 (regs
, ECR_FRGD_COLOR
, bg
);
2306 vgaw16 (regs
, ECR_READ_REG_DATA
, 0xA000);
2307 vgaw16 (regs
, ECR_CURRENT_Y_POS
, dy
);
2308 vgaw16 (regs
, ECR_CURRENT_X_POS
, dx
);
2309 vgaw16 (regs
, ECR_READ_REG_DATA
, h
- 1);
2310 vgaw16 (regs
, ECR_MAJ_AXIS_PIX_CNT
, w
- 1);
2311 vgaw16 (regs
, ECR_DRAW_CMD
, 0x40B1);
2317 * Dump internal settings of CyberVision board
2319 static void cv64_dump (void)
2321 volatile unsigned char *regs
= CyberRegs
;
2323 /* Dump the VGA setup values */
2324 *(regs
+ S3_CRTC_ADR
) = 0x00;
2325 DPRINTK("CR00 = %x\n", *(regs
+ S3_CRTC_DATA
));
2326 *(regs
+ S3_CRTC_ADR
) = 0x01;
2327 DPRINTK("CR01 = %x\n", *(regs
+ S3_CRTC_DATA
));
2328 *(regs
+ S3_CRTC_ADR
) = 0x02;
2329 DPRINTK("CR02 = %x\n", *(regs
+ S3_CRTC_DATA
));
2330 *(regs
+ S3_CRTC_ADR
) = 0x03;
2331 DPRINTK("CR03 = %x\n", *(regs
+ S3_CRTC_DATA
));
2332 *(regs
+ S3_CRTC_ADR
) = 0x04;
2333 DPRINTK("CR04 = %x\n", *(regs
+ S3_CRTC_DATA
));
2334 *(regs
+ S3_CRTC_ADR
) = 0x05;
2335 DPRINTK("CR05 = %x\n", *(regs
+ S3_CRTC_DATA
));
2336 *(regs
+ S3_CRTC_ADR
) = 0x06;
2337 DPRINTK("CR06 = %x\n", *(regs
+ S3_CRTC_DATA
));
2338 *(regs
+ S3_CRTC_ADR
) = 0x07;
2339 DPRINTK("CR07 = %x\n", *(regs
+ S3_CRTC_DATA
));
2340 *(regs
+ S3_CRTC_ADR
) = 0x08;
2341 DPRINTK("CR08 = %x\n", *(regs
+ S3_CRTC_DATA
));
2342 *(regs
+ S3_CRTC_ADR
) = 0x09;
2343 DPRINTK("CR09 = %x\n", *(regs
+ S3_CRTC_DATA
));
2344 *(regs
+ S3_CRTC_ADR
) = 0x10;
2345 DPRINTK("CR10 = %x\n", *(regs
+ S3_CRTC_DATA
));
2346 *(regs
+ S3_CRTC_ADR
) = 0x11;
2347 DPRINTK("CR11 = %x\n", *(regs
+ S3_CRTC_DATA
));
2348 *(regs
+ S3_CRTC_ADR
) = 0x12;
2349 DPRINTK("CR12 = %x\n", *(regs
+ S3_CRTC_DATA
));
2350 *(regs
+ S3_CRTC_ADR
) = 0x13;
2351 DPRINTK("CR13 = %x\n", *(regs
+ S3_CRTC_DATA
));
2352 *(regs
+ S3_CRTC_ADR
) = 0x15;
2353 DPRINTK("CR15 = %x\n", *(regs
+ S3_CRTC_DATA
));
2354 *(regs
+ S3_CRTC_ADR
) = 0x16;
2355 DPRINTK("CR16 = %x\n", *(regs
+ S3_CRTC_DATA
));
2356 *(regs
+ S3_CRTC_ADR
) = 0x36;
2357 DPRINTK("CR36 = %x\n", *(regs
+ S3_CRTC_DATA
));
2358 *(regs
+ S3_CRTC_ADR
) = 0x37;
2359 DPRINTK("CR37 = %x\n", *(regs
+ S3_CRTC_DATA
));
2360 *(regs
+ S3_CRTC_ADR
) = 0x42;
2361 DPRINTK("CR42 = %x\n", *(regs
+ S3_CRTC_DATA
));
2362 *(regs
+ S3_CRTC_ADR
) = 0x43;
2363 DPRINTK("CR43 = %x\n", *(regs
+ S3_CRTC_DATA
));
2364 *(regs
+ S3_CRTC_ADR
) = 0x50;
2365 DPRINTK("CR50 = %x\n", *(regs
+ S3_CRTC_DATA
));
2366 *(regs
+ S3_CRTC_ADR
) = 0x51;
2367 DPRINTK("CR51 = %x\n", *(regs
+ S3_CRTC_DATA
));
2368 *(regs
+ S3_CRTC_ADR
) = 0x53;
2369 DPRINTK("CR53 = %x\n", *(regs
+ S3_CRTC_DATA
));
2370 *(regs
+ S3_CRTC_ADR
) = 0x58;
2371 DPRINTK("CR58 = %x\n", *(regs
+ S3_CRTC_DATA
));
2372 *(regs
+ S3_CRTC_ADR
) = 0x59;
2373 DPRINTK("CR59 = %x\n", *(regs
+ S3_CRTC_DATA
));
2374 *(regs
+ S3_CRTC_ADR
) = 0x5A;
2375 DPRINTK("CR5A = %x\n", *(regs
+ S3_CRTC_DATA
));
2376 *(regs
+ S3_CRTC_ADR
) = 0x5D;
2377 DPRINTK("CR5D = %x\n", *(regs
+ S3_CRTC_DATA
));
2378 *(regs
+ S3_CRTC_ADR
) = 0x5E;
2379 DPRINTK("CR5E = %x\n", *(regs
+ S3_CRTC_DATA
));
2380 DPRINTK("MISC = %x\n", *(regs
+ GREG_MISC_OUTPUT_R
));
2381 *(regs
+ SEQ_ADDRESS
) = 0x01;
2382 DPRINTK("SR01 = %x\n", *(regs
+ SEQ_ADDRESS_R
));
2383 *(regs
+ SEQ_ADDRESS
) = 0x02;
2384 DPRINTK("SR02 = %x\n", *(regs
+ SEQ_ADDRESS_R
));
2385 *(regs
+ SEQ_ADDRESS
) = 0x03;
2386 DPRINTK("SR03 = %x\n", *(regs
+ SEQ_ADDRESS_R
));
2387 *(regs
+ SEQ_ADDRESS
) = 0x09;
2388 DPRINTK("SR09 = %x\n", *(regs
+ SEQ_ADDRESS_R
));
2389 *(regs
+ SEQ_ADDRESS
) = 0x10;
2390 DPRINTK("SR10 = %x\n", *(regs
+ SEQ_ADDRESS_R
));
2391 *(regs
+ SEQ_ADDRESS
) = 0x11;
2392 DPRINTK("SR11 = %x\n", *(regs
+ SEQ_ADDRESS_R
));
2393 *(regs
+ SEQ_ADDRESS
) = 0x12;
2394 DPRINTK("SR12 = %x\n", *(regs
+ SEQ_ADDRESS_R
));
2395 *(regs
+ SEQ_ADDRESS
) = 0x13;
2396 DPRINTK("SR13 = %x\n", *(regs
+ SEQ_ADDRESS_R
));
2397 *(regs
+ SEQ_ADDRESS
) = 0x15;
2398 DPRINTK("SR15 = %x\n", *(regs
+ SEQ_ADDRESS_R
));