1 /*
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 $
4 *
5 *    Copyright (C) 1998 Alan Bair
6 *
7 * This file is based on two CyberVision64 frame buffer device drivers
8 *
9 * The second CyberVision64 frame buffer device (cvision.c cvision_core.c):
10 *
11 *   Copyright (c) 1997 Antonio Santos
12 *
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.
18 *
19 *   Copyright (c) 1995 Michael Teske
20 *
21 * The first CyberVision64 frame buffer device (cyberfb.c):
22 *
23 *    Copyright (C) 1996 Martin Apel
24 *                       Geert Uytterhoeven
25 *
26 * Which is based on the Amiga frame buffer device (amifb.c):
27 *
28 *    Copyright (C) 1995 Geert Uytterhoeven
29 *
30 *
31 * History:
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
35 * $Log: cyberfb.c,v $
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.
39 *
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.
43 *
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.
48 *
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.
53 *
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.
57 *
58 * Revision 1.1  1998/08/29 18:38:31  abair
59 * Initial revision
60 *
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.
65 *
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.
70 *
71 *
72 *
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
75 * for more details.
76 */
77 
78 
79 #include <linux/module.h>
80 #include <linux/kernel.h>
81 #include <linux/errno.h>
82 #include <linux/string.h>
83 #include <linux/mm.h>
84 #include <linux/tty.h>
85 #include <linux/slab.h>
86 #include <linux/delay.h>
87 #include <linux/zorro.h>
88 #include <linux/fb.h>
89 #include <linux/init.h>
90 #include <asm/uaccess.h>
91 #include <asm/system.h>
92 #include <asm/irq.h>
93 #include <asm/pgtable.h>
94 #include <asm/amigahw.h>
95 #include <asm/io.h>
96 
97 #include "cyberfb.h"
98 #include <video/fbcon.h>
99 #include <video/fbcon-cfb8.h>
100 #include <video/fbcon-cfb16.h>
101 
102 /*#define CYBERFBDEBUG*/
103 #ifdef CYBERFBDEBUG
104 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
105 static void cv64_dump(void);
106 #else
107 #define DPRINTK(fmt, args...)
108 #endif
109 
110 #define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat)
111 #define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg))
112 
113 #define ww_64(regs,reg,dat) (*(volatile unsigned short *)(regs + reg) = dat)
114 
115 struct cyberfb_par {
116 	struct fb_var_screeninfo var;
117 	__u32 type;
118 	__u32 type_aux;
119 	__u32 visual;
120 	__u32 line_length;
121 };
122 
123 static struct cyberfb_par current_par;
124 
125 static int current_par_valid = 0;
126 static int currcon = 0;
127 
128 static struct display disp;
129 static struct fb_info fb_info;
130 
131 
132 /*
133  *    Frame Buffer Name
134  */
135 
136 static char cyberfb_name[16] = "Cybervision";
137 
138 
139 /*
140  *    CyberVision Graphics Board
141  */
142 
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;
150 
151 /*
152  *    Predefined Video Modes
153  */
154 
155 static struct {
156     const char *name;
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
165 	}},
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
172 	}},
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
179 	}},
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
187 	}},
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
190  * his system.
191  */
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
198 	}},
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
205 	}},
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
212 	}},
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,
218 		FB_VMODE_INTERLACED
219 	}}
220 };
221 
222 #define NUM_TOTAL_MODES    ARRAY_SIZE(cyberfb_predefined)
223 
224 static int Cyberfb_inverse = 0;
225 
226 /*
227  *    Some default modes
228  */
229 
230 #define CYBER8_DEFMODE     (0)
231 #define CYBER16_DEFMODE    (1)
232 
233 static struct fb_var_screeninfo cyberfb_default;
234 static int cyberfb_usermode __initdata = 0;
235 
236 /*
237  *    Interface used by the world
238  */
239 
240 int cyberfb_setup(char *options);
241 
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);
252 
253 /*
254  *    Interface to the low level console driver
255  */
256 
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);
261 
262 /*
263  *    Text console acceleration
264  */
265 
266 #ifdef FBCON_HAS_CFB8
267 static struct display_switch fbcon_cyber8;
268 #endif
269 
270 /*
271  *    Accelerated Functions used by the low level console driver
272  */
273 
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,
278 			 u_short mode);
279 static void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height,
280 			   u_short mode, u_short color);
281 #if 0
282 static void Cyber_MoveCursor(u_short x, u_short y);
283 #endif
284 
285 /*
286  *   Hardware Specific Routines
287  */
288 
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);
300 
301 /*
302  *    Internal routines
303  */
304 
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);
311 
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 *);
317 
318 
319 /* -------------------- Hardware specific routines ------------------------- */
320 
321 
322 /*
323  *    Initialization
324  *
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.
327  */
328 
Cyber_init(void)329 static int Cyber_init(void)
330 {
331 	volatile unsigned char *regs = CyberRegs;
332 	volatile unsigned long *CursorBase;
333 	int i;
334 	DPRINTK("ENTER\n");
335 
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;
341 	}
342 
343 /* Initialize the board and determine fbmem size */
344 	cv64_board_init();
345 #ifdef CYBERFBDEBUG
346 	DPRINTK("Register state after initing board\n");
347 	cv64_dump();
348 #endif
349 /* Clear framebuffer memory */
350 	DPRINTK("Clear framebuffer memory\n");
351 	memset ((char *)CyberMem, 0, CyberSize);
352 
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);
363 
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++)
368 	{
369 		*(CursorBase  +(i*4)) = 0xffffff00;
370 		*(CursorBase+1+(i*4)) = 0xffff0000;
371 		*(CursorBase+2+(i*4)) = 0xffff0000;
372 		*(CursorBase+3+(i*4)) = 0xffff0000;
373 	}
374 	for (i=8; i < 64; i++)
375 	{
376 		*(CursorBase  +(i*4)) = 0xffff0000;
377 		*(CursorBase+1+(i*4)) = 0xffff0000;
378 		*(CursorBase+2+(i*4)) = 0xffff0000;
379 		*(CursorBase+3+(i*4)) = 0xffff0000;
380 	}
381 
382 	Cyber_setcolreg (255, 56<<8, 100<<8, 160<<8, 0, NULL /* unused */);
383 	Cyber_setcolreg (254, 0, 0, 0, 0, NULL /* unused */);
384 
385 	DPRINTK("EXIT\n");
386 	return 0;
387 }
388 
389 
390 /*
391  *    This function should fill in the `fix' structure based on the
392  *    values in the `par' structure.
393  */
394 
Cyber_encode_fix(struct fb_fix_screeninfo * fix,struct cyberfb_par * par)395 static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
396 			    struct cyberfb_par *par)
397 {
398 	DPRINTK("ENTER\n");
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;
405 
406 	fix->type = FB_TYPE_PACKED_PIXELS;
407 	fix->type_aux = 0;
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;
411 	} else {
412 		fix->visual = FB_VISUAL_PSEUDOCOLOR;
413 	}
414 
415 	fix->xpanstep = 0;
416 	fix->ypanstep = 0;
417 	fix->ywrapstep = 0;
418 	fix->line_length = 0;
419 	fix->accel = FB_ACCEL_S3_TRIO64;
420 
421 	DPRINTK("EXIT\n");
422 	return(0);
423 }
424 
425 
426 /*
427 *    Fill the `par' structure based on the values in `var'.
428 *    TODO: Verify and adjust values, return -EINVAL if bad.
429 */
430 
Cyber_decode_var(struct fb_var_screeninfo * var,struct cyberfb_par * par)431 static int Cyber_decode_var(struct fb_var_screeninfo *var,
432 			    struct cyberfb_par *par)
433 {
434 	DPRINTK("ENTER\n");
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;
453 	} else {
454 		par->var.accel_flags = 0;
455 	}
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;
465 	DPRINTK("EXIT\n");
466 	return(0);
467 }
468 
469 /*
470 *    Fill the `var' structure based on the values in `par' and maybe
471 *    other values read out of the hardware.
472 */
473 
Cyber_encode_var(struct fb_var_screeninfo * var,struct cyberfb_par * par)474 static int Cyber_encode_var(struct fb_var_screeninfo *var,
475 			    struct cyberfb_par *par)
476 {
477 	DPRINTK("ENTER\n");
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;
484 
485 	var->bits_per_pixel = par->var.bits_per_pixel;
486 	var->grayscale = par->var.grayscale;
487 
488 	var->red = par->var.red;
489 	var->green = par->var.green;
490 	var->blue = par->var.blue;
491 	var->transp = par->var.transp;
492 
493 	var->nonstd = par->var.nonstd;
494 	var->activate = par->var.activate;
495 
496 	var->height = par->var.height;
497 	var->width = par->var.width;
498 
499 	var->accel_flags = par->var.accel_flags;
500 
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;
510 
511 	DPRINTK("EXIT\n");
512 	return(0);
513 }
514 
515 
516 /*
517  *    Set a single color register. Return != 0 for invalid regno.
518  */
519 
Cyber_setcolreg(u_int regno,u_int red,u_int green,u_int blue,u_int transp,struct fb_info * info)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)
522 {
523 	volatile unsigned char *regs = CyberRegs;
524 
525 	/*DPRINTK("ENTER\n");*/
526 	if (regno > 255) {
527 		DPRINTK("EXIT - Register # > 255\n");
528 		return (1);
529 	}
530 
531 	wb_64(regs, 0x3c8, (unsigned char) regno);
532 
533  	red >>= 10;
534  	green >>= 10;
535  	blue >>= 10;
536 
537 	Cyber_colour_table [regno][0] = red;
538 	Cyber_colour_table [regno][1] = green;
539 	Cyber_colour_table [regno][2] = blue;
540 
541 	wb_64(regs, 0x3c9, red);
542 	wb_64(regs, 0x3c9, green);
543 	wb_64(regs, 0x3c9, blue);
544 
545 	/*DPRINTK("EXIT\n");*/
546 	return (0);
547 }
548 
549 
550 /*
551 *    Read a single color register and split it into
552 *    colors/transparent. Return != 0 for invalid regno.
553 */
554 
Cyber_getcolreg(u_int regno,u_int * red,u_int * green,u_int * blue,u_int * transp,struct fb_info * info)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)
557 {
558 	int t;
559 
560 	/*DPRINTK("ENTER\n");*/
561 	if (regno > 255) {
562 		DPRINTK("EXIT - Register # > 255\n");
563 		return (1);
564 	}
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);
572  	*transp = 0;
573 	/*DPRINTK("EXIT\n");*/
574 	return (0);
575 }
576 
577 
578 /*
579 *    (Un)Blank the screen
580 *    blank: 1 = zero fb cmap
581 *           0 = restore fb cmap from local cmap
582 */
583 
Cyberfb_blank(int blank,struct fb_info * info)584 void Cyberfb_blank(int blank, struct fb_info *info)
585 {
586 	volatile unsigned char *regs = CyberRegs;
587 	int i;
588 
589 	DPRINTK("ENTER\n");
590 #if 0
591 /* Blank by turning gfx off */
592 	gfx_on_off (1, regs);
593 #else
594 	if (blank) {
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);
601 		}
602 	} else {
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]);
608 		}
609 	}
610 #endif
611 	DPRINTK("EXIT\n");
612 }
613 
614 
615 /**************************************************************
616  * We are waiting for "fifo" FIFO-slots empty
617  */
Cyber_WaitQueue(u_short fifo)618 static void Cyber_WaitQueue (u_short fifo)
619 {
620 	unsigned short status;
621 
622 	DPRINTK("ENTER\n");
623 	do {
624 		status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
625 	} while (status & fifo);
626 	DPRINTK("EXIT\n");
627 }
628 
629 /**************************************************************
630  * We are waiting for Hardware (Graphics Engine) not busy
631  */
Cyber_WaitBlit(void)632 static void Cyber_WaitBlit (void)
633 {
634 	unsigned short status;
635 
636 	DPRINTK("ENTER\n");
637 	do {
638 		status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
639 	} while (status & S3_HDW_BUSY);
640 	DPRINTK("EXIT\n");
641 }
642 
643 /**************************************************************
644  * BitBLT - Through the Plane
645  */
Cyber_BitBLT(u_short curx,u_short cury,u_short destx,u_short desty,u_short width,u_short height,u_short mode)646 static void Cyber_BitBLT (u_short curx, u_short cury, u_short destx,
647 			  u_short desty, u_short width, u_short height,
648 			  u_short mode)
649 {
650 	volatile unsigned char *regs = CyberRegs;
651 	u_short blitcmd = S3_BITBLT;
652 
653 	DPRINTK("ENTER\n");
654 	/* Set drawing direction */
655 	/* -Y, X maj, -X (default) */
656 	if (curx > destx) {
657 		blitcmd |= 0x0020;  /* Drawing direction +X */
658 	} else {
659 		curx  += (width - 1);
660 		destx += (width - 1);
661 	}
662 
663 	if (cury > desty) {
664 		blitcmd |= 0x0080;  /* Drawing direction +Y */
665 	} else {
666 		cury  += (height - 1);
667 		desty += (height - 1);
668 	}
669 
670 	Cyber_WaitQueue (0x8000);
671 
672 	*((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
673 	*((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0060 | mode);
674 
675 	*((u_short volatile *)(regs + S3_CUR_X)) = curx;
676 	*((u_short volatile *)(regs + S3_CUR_Y)) = cury;
677 
678 	*((u_short volatile *)(regs + S3_DESTX_DIASTP)) = destx;
679 	*((u_short volatile *)(regs + S3_DESTY_AXSTP)) = desty;
680 
681 	*((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
682 	*((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width  - 1;
683 
684 	*((u_short volatile *)(regs + S3_CMD)) = blitcmd;
685 	DPRINTK("EXIT\n");
686 }
687 
688 /**************************************************************
689  * Rectangle Fill Solid
690  */
Cyber_RectFill(u_short x,u_short y,u_short width,u_short height,u_short mode,u_short color)691 static void Cyber_RectFill (u_short x, u_short y, u_short width,
692 			    u_short height, u_short mode, u_short color)
693 {
694 	volatile unsigned char *regs = CyberRegs;
695 	u_short blitcmd = S3_FILLEDRECT;
696 
697 	DPRINTK("ENTER\n");
698 	Cyber_WaitQueue (0x8000);
699 
700 	*((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
701 	*((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0020 | mode);
702 
703 	*((u_short volatile *)(regs + S3_MULT_MISC)) = 0xe000;
704 	*((u_short volatile *)(regs + S3_FRGD_COLOR)) = color;
705 
706 	*((u_short volatile *)(regs + S3_CUR_X)) = x;
707 	*((u_short volatile *)(regs + S3_CUR_Y)) = y;
708 
709 	*((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
710 	*((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width  - 1;
711 
712 	*((u_short volatile *)(regs + S3_CMD)) = blitcmd;
713 	DPRINTK("EXIT\n");
714 }
715 
716 
717 #if 0
718 /**************************************************************
719  * Move cursor to x, y
720  */
721 static void Cyber_MoveCursor (u_short x, u_short y)
722 {
723 	volatile unsigned char *regs = CyberRegs;
724 	DPRINTK("ENTER\n");
725 	*(regs + S3_CRTC_ADR)  = 0x39;
726 	*(regs + S3_CRTC_DATA) = 0xa0;
727 
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);
732 
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);
737 	DPRINTK("EXIT\n");
738 }
739 #endif
740 
741 
742 /* -------------------- Generic routines ---------------------------------- */
743 
744 
745 /*
746  *    Fill the hardware's `par' structure.
747  */
748 
cyberfb_get_par(struct cyberfb_par * par)749 static void cyberfb_get_par(struct cyberfb_par *par)
750 {
751 	DPRINTK("ENTER\n");
752 	if (current_par_valid) {
753 		*par = current_par;
754 	} else {
755 		Cyber_decode_var(&cyberfb_default, par);
756 	}
757 	DPRINTK("EXIT\n");
758 }
759 
760 
cyberfb_set_par(struct cyberfb_par * par)761 static void cyberfb_set_par(struct cyberfb_par *par)
762 {
763 	DPRINTK("ENTER\n");
764 	current_par = *par;
765 	current_par_valid = 1;
766 	DPRINTK("EXIT\n");
767 }
768 
769 
cyber_set_video(struct fb_var_screeninfo * var)770 static void cyber_set_video(struct fb_var_screeninfo *var)
771 {
772 
773 	/* Load the video mode defined by the 'var' data */
774 	cv64_load_video_mode (var);
775 #ifdef CYBERFBDEBUG
776 	DPRINTK("Register state after loading video mode\n");
777 	cv64_dump();
778 #endif
779 }
780 
781 
do_fb_set_var(struct fb_var_screeninfo * var,int isactive)782 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
783 {
784 	int err, activate;
785 	struct cyberfb_par par;
786 
787 	DPRINTK("ENTER\n");
788 	if ((err = Cyber_decode_var(var, &par))) {
789 		DPRINTK("EXIT - decode_var failed\n");
790 		return(err);
791 	}
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;
797 
798 	cyber_set_video(var);
799 	DPRINTK("EXIT\n");
800 	return 0;
801 }
802 
803 
do_install_cmap(int con,struct fb_info * info)804 static void do_install_cmap(int con, struct fb_info *info)
805 {
806 	DPRINTK("ENTER\n");
807 	if (con != currcon) {
808 		DPRINTK("EXIT - Not current console\n");
809 		return;
810 	}
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);
814 	} else {
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);
818 	}
819 	DPRINTK("EXIT\n");
820 }
821 
822 /*
823  *    Get the Fixed Part of the Display
824  */
825 
cyberfb_get_fix(struct fb_fix_screeninfo * fix,int con,struct fb_info * info)826 static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
827 			   struct fb_info *info)
828 {
829 	struct cyberfb_par par;
830 	int error = 0;
831 
832 	DPRINTK("ENTER\n");
833 	if (con == -1) {
834 		cyberfb_get_par(&par);
835 	} else {
836 		error = Cyber_decode_var(&fb_display[con].var, &par);
837 	}
838 	DPRINTK("EXIT\n");
839 	return(error ? error : Cyber_encode_fix(fix, &par));
840 }
841 
842 
843 /*
844  *    Get the User Defined Part of the Display
845  */
846 
cyberfb_get_var(struct fb_var_screeninfo * var,int con,struct fb_info * info)847 static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
848 			   struct fb_info *info)
849 {
850 	struct cyberfb_par par;
851 	int error = 0;
852 
853 	DPRINTK("ENTER\n");
854 	if (con == -1) {
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 */
858 	} else {
859 		*var = fb_display[con].var;
860 	}
861 
862 	DPRINTK("EXIT\n");
863 	return(error);
864 }
865 
866 
cyberfb_set_disp(int con,struct fb_info * info)867 static void cyberfb_set_disp(int con, struct fb_info *info)
868 {
869 	struct fb_fix_screeninfo fix;
870 	struct display *display;
871 
872 	DPRINTK("ENTER\n");
873 	if (con >= 0)
874 		display = &fb_display[con];
875 	else
876 		display = &disp;	/* used during initialization */
877 
878 	cyberfb_get_fix(&fix, con, info);
879 	if (con == -1)
880 		con = 0;
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
891 	    case 8:
892 		if (display->var.accel_flags & FB_ACCELF_TEXT) {
893 		    display->dispsw = &fbcon_cyber8;
894 #warning FIXME: We should reinit the graphics engine here
895 		} else
896 		    display->dispsw = &fbcon_cfb8;
897 		break;
898 #endif
899 #ifdef FBCON_HAS_CFB16
900 	    case 16:
901 		display->dispsw = &fbcon_cfb16;
902 		break;
903 #endif
904 	    default:
905 		display->dispsw = NULL;
906 		break;
907 	}
908 	DPRINTK("EXIT\n");
909 }
910 
911 
912 /*
913  *    Set the User Defined Part of the Display
914  */
915 
cyberfb_set_var(struct fb_var_screeninfo * var,int con,struct fb_info * info)916 static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
917 			   struct fb_info *info)
918 {
919 	int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
920 
921 	DPRINTK("ENTER\n");
922 	if ((err = do_fb_set_var(var, con == currcon))) {
923 		DPRINTK("EXIT - do_fb_set_var failed\n");
924 		return(err);
925 	}
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);
943 		}
944 	}
945 	var->activate = 0;
946 	DPRINTK("EXIT\n");
947 	return(0);
948 }
949 
950 
951 /*
952  *    Get the Colormap
953  */
954 
cyberfb_get_cmap(struct fb_cmap * cmap,int kspc,int con,struct fb_info * info)955 static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
956 			    struct fb_info *info)
957 {
958 	DPRINTK("ENTER\n");
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);
965 	} else {
966 		DPRINTK("Use default cmap\n");
967 		fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
968 			     cmap, kspc ? 0 : 2);
969 	}
970 	DPRINTK("EXIT\n");
971 	return(0);
972 }
973 
974 
975 /*
976  *    Set the Colormap
977  */
978 
cyberfb_set_cmap(struct fb_cmap * cmap,int kspc,int con,struct fb_info * info)979 static int cyberfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
980 			    struct fb_info *info)
981 {
982 	int err;
983 
984 	DPRINTK("ENTER\n");
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,
988 					 0))) {
989 			DPRINTK("EXIT - fb_alloc_cmap failed\n");
990 			return(err);
991 		}
992 	}
993 	if (con == currcon) {		 /* current console? */
994 		DPRINTK("EXIT - Current console\n");
995 		return(fb_set_cmap(cmap, kspc, Cyber_setcolreg, info));
996 	} else {
997 		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
998 	}
999 	DPRINTK("EXIT\n");
1000 	return(0);
1001 }
1002 
1003 
1004 static struct fb_ops cyberfb_ops = {
1005 	owner:		THIS_MODULE,
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,
1011 };
1012 
cyberfb_setup(char * options)1013 int __init cyberfb_setup(char *options)
1014 {
1015 	char *this_opt;
1016 	DPRINTK("ENTER\n");
1017 
1018 	fb_info.fontname[0] = '\0';
1019 
1020 	if (!options || !*options) {
1021 		DPRINTK("EXIT - no options\n");
1022 		return 0;
1023 	}
1024 
1025 	while ((this_opt = strsep(&options, ",")) != NULL) {
1026 		if (!*this_opt)
1027 			continue;
1028 		if (!strcmp(this_opt, "inverse")) {
1029 			Cyberfb_inverse = 1;
1030 			fb_invert_cmaps();
1031 		} else if (!strncmp(this_opt, "font:", 5)) {
1032 			strcpy(fb_info.fontname, this_opt+5);
1033 		} else if (!strcmp (this_opt, "cyber8")) {
1034 			cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
1035 			cyberfb_usermode = 1;
1036 		} else if (!strcmp (this_opt, "cyber16")) {
1037 			cyberfb_default = cyberfb_predefined[CYBER16_DEFMODE].var;
1038 			cyberfb_usermode = 1;
1039 		} else get_video_mode(this_opt);
1040 	}
1041 
1042 	DPRINTK("default mode: xres=%d, yres=%d, bpp=%d\n",
1043 		cyberfb_default.xres,
1044 		cyberfb_default.yres,
1045 		cyberfb_default.bits_per_pixel);
1046 	DPRINTK("EXIT\n");
1047 	return 0;
1048 }
1049 
1050 /*
1051  *    Initialization
1052  */
1053 
cyberfb_init(void)1054 int __init cyberfb_init(void)
1055 {
1056 	unsigned long board_addr, board_size;
1057 	struct cyberfb_par par;
1058 	struct zorro_dev *z = NULL;
1059 	DPRINTK("ENTER\n");
1060 
1061 	while ((z = zorro_find_device(ZORRO_PROD_PHASE5_CYBERVISION64, z))) {
1062 	    board_addr = z->resource.start;
1063 	    board_size = z->resource.end-z->resource.start+1;
1064 	    CyberMem_phys = board_addr + 0x01400000;
1065 	    CyberRegs_phys = CyberMem_phys + 0x00c00000;
1066 	    if (!request_mem_region(CyberRegs_phys, 0x10000, "S3 Trio64"))
1067 		continue;
1068 	    if (!request_mem_region(CyberMem_phys, 0x400000, "RAM")) {
1069 		release_mem_region(CyberRegs_phys, 0x10000);
1070 		continue;
1071 	    }
1072 	    DPRINTK("board_addr=%08lx\n", board_addr);
1073 	    DPRINTK("board_size=%08lx\n", board_size);
1074 
1075 	    CyberBase = ioremap(board_addr, board_size);
1076 	    CyberRegs = CyberBase + 0x02000000;
1077 	    CyberMem = CyberBase + 0x01400000;
1078 	    DPRINTK("CyberBase=%08lx CyberRegs=%08lx CyberMem=%08lx\n",
1079 		    CyberBase, (long unsigned int)CyberRegs, CyberMem);
1080 
1081 #ifdef CYBERFBDEBUG
1082 	    DPRINTK("Register state just after mapping memory\n");
1083 	    cv64_dump();
1084 #endif
1085 
1086 	    strcpy(fb_info.modename, cyberfb_name);
1087 	    fb_info.changevar = NULL;
1088 	    fb_info.node = -1;
1089 	    fb_info.fbops = &cyberfb_ops;
1090 	    fb_info.disp = &disp;
1091 	    fb_info.switch_con = &Cyberfb_switch;
1092 	    fb_info.updatevar = &Cyberfb_updatevar;
1093 	    fb_info.blank = &Cyberfb_blank;
1094 
1095 	    Cyber_init();
1096 	    /* ++Andre: set cyberfb default mode */
1097 	    if (!cyberfb_usermode) {
1098 		    cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
1099 		    DPRINTK("Use default cyber8 mode\n");
1100 	    }
1101 	    Cyber_decode_var(&cyberfb_default, &par);
1102 	    Cyber_encode_var(&cyberfb_default, &par);
1103 
1104 	    do_fb_set_var(&cyberfb_default, 1);
1105 	    cyberfb_get_var(&fb_display[0].var, -1, &fb_info);
1106 	    cyberfb_set_disp(-1, &fb_info);
1107 	    do_install_cmap(0, &fb_info);
1108 
1109 	    if (register_framebuffer(&fb_info) < 0) {
1110 		    DPRINTK("EXIT - register_framebuffer failed\n");
1111 		    release_mem_region(CyberMem_phys, 0x400000);
1112 		    release_mem_region(CyberRegs_phys, 0x10000);
1113 		    return -EINVAL;
1114 	    }
1115 
1116 	    printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
1117 		   GET_FB_IDX(fb_info.node), fb_info.modename, CyberSize>>10);
1118 
1119 	    /* TODO: This driver cannot be unloaded yet */
1120 	    MOD_INC_USE_COUNT;
1121 	    DPRINTK("EXIT\n");
1122 	    return 0;
1123 	}
1124 	return -ENXIO;
1125 }
1126 
1127 
Cyberfb_switch(int con,struct fb_info * info)1128 static int Cyberfb_switch(int con, struct fb_info *info)
1129 {
1130         DPRINTK("ENTER\n");
1131 	/* Do we have to save the colormap? */
1132 	if (fb_display[currcon].cmap.len) {
1133 		fb_get_cmap(&fb_display[currcon].cmap, 1, Cyber_getcolreg,
1134 			    info);
1135 	}
1136 
1137 	do_fb_set_var(&fb_display[con].var, 1);
1138 	currcon = con;
1139 	/* Install new colormap */
1140 	do_install_cmap(con, info);
1141 	DPRINTK("EXIT\n");
1142 	return(0);
1143 }
1144 
1145 
1146 /*
1147  *    Update the `var' structure (called by fbcon.c)
1148  *
1149  *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
1150  *    Since it's called by a kernel driver, no range checking is done.
1151  */
1152 
Cyberfb_updatevar(int con,struct fb_info * info)1153 static int Cyberfb_updatevar(int con, struct fb_info *info)
1154 {
1155 	DPRINTK("Enter - Exit\n");
1156 	return(0);
1157 }
1158 
1159 
1160 /*
1161  *    Get a Video Mode
1162  */
1163 
get_video_mode(const char * name)1164 static int __init get_video_mode(const char *name)
1165 {
1166 	int i;
1167 
1168 	DPRINTK("ENTER\n");
1169 	for (i = 0; i < NUM_TOTAL_MODES; i++) {
1170 		if (!strcmp(name, cyberfb_predefined[i].name)) {
1171 			cyberfb_default = cyberfb_predefined[i].var;
1172 			cyberfb_usermode = 1;
1173 			DPRINTK("EXIT - Matched predefined mode\n");
1174 			return(i);
1175 		}
1176 	}
1177 	return(0);
1178 }
1179 
1180 
1181 /*
1182  *    Text console acceleration
1183  */
1184 
1185 #ifdef FBCON_HAS_CFB8
fbcon_cyber8_bmove(struct display * p,int sy,int sx,int dy,int dx,int height,int width)1186 static void fbcon_cyber8_bmove(struct display *p, int sy, int sx, int dy,
1187 			       int dx, int height, int width)
1188 {
1189 	DPRINTK("ENTER\n");
1190 	sx *= 8; dx *= 8; width *= 8;
1191 	Cyber_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
1192 		     (u_short)(dy*fontheight(p)), (u_short)width,
1193 		     (u_short)(height*fontheight(p)), (u_short)S3_NEW);
1194 	DPRINTK("EXIT\n");
1195 }
1196 
fbcon_cyber8_clear(struct vc_data * conp,struct display * p,int sy,int sx,int height,int width)1197 static void fbcon_cyber8_clear(struct vc_data *conp, struct display *p, int sy,
1198 			       int sx, int height, int width)
1199 {
1200 	unsigned char bg;
1201 
1202 	DPRINTK("ENTER\n");
1203 	sx *= 8; width *= 8;
1204 	bg = attr_bgcol_ec(p,conp);
1205 	Cyber_RectFill((u_short)sx,
1206 		       (u_short)(sy*fontheight(p)),
1207 		       (u_short)width,
1208 		       (u_short)(height*fontheight(p)),
1209 		       (u_short)S3_NEW,
1210 		       (u_short)bg);
1211 	DPRINTK("EXIT\n");
1212 }
1213 
fbcon_cyber8_putc(struct vc_data * conp,struct display * p,int c,int yy,int xx)1214 static void fbcon_cyber8_putc(struct vc_data *conp, struct display *p, int c,
1215 			      int yy, int xx)
1216 {
1217 	DPRINTK("ENTER\n");
1218 	Cyber_WaitBlit();
1219 	fbcon_cfb8_putc(conp, p, c, yy, xx);
1220 	DPRINTK("EXIT\n");
1221 }
1222 
fbcon_cyber8_putcs(struct vc_data * conp,struct display * p,const unsigned short * s,int count,int yy,int xx)1223 static void fbcon_cyber8_putcs(struct vc_data *conp, struct display *p,
1224 			       const unsigned short *s, int count,
1225 			       int yy, int xx)
1226 {
1227 	DPRINTK("ENTER\n");
1228 	Cyber_WaitBlit();
1229 	fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
1230 	DPRINTK("EXIT\n");
1231 }
1232 
fbcon_cyber8_revc(struct display * p,int xx,int yy)1233 static void fbcon_cyber8_revc(struct display *p, int xx, int yy)
1234 {
1235 	DPRINTK("ENTER\n");
1236 	Cyber_WaitBlit();
1237 	fbcon_cfb8_revc(p, xx, yy);
1238 	DPRINTK("EXIT\n");
1239 }
1240 
1241 static struct display_switch fbcon_cyber8 = {
1242 	setup:		fbcon_cfb8_setup,
1243 	bmove:		fbcon_cyber8_bmove,
1244 	clear:		fbcon_cyber8_clear,
1245 	putc:		fbcon_cyber8_putc,
1246 	putcs:		fbcon_cyber8_putcs,
1247 	revc:		fbcon_cyber8_revc,
1248 	clear_margins:	fbcon_cfb8_clear_margins,
1249 	fontwidthmask:	FONTWIDTH(8)
1250 };
1251 #endif
1252 
1253 
1254 #ifdef MODULE
1255 MODULE_LICENSE("GPL");
1256 
init_module(void)1257 int init_module(void)
1258 {
1259 	return cyberfb_init();
1260 }
1261 
cleanup_module(void)1262 void cleanup_module(void)
1263 {
1264 	/* Not reached because the usecount will never be
1265 	   decremented to zero */
1266 	unregister_framebuffer(&fb_info);
1267 	/* TODO: clean up ... */
1268 }
1269 #endif /* MODULE */
1270 
1271 /*
1272  *
1273  * Low level initialization routines for the CyberVision64 graphics card
1274  *
1275  * Most of the following code is from cvision_core.c
1276  *
1277  */
1278 
1279 #define MAXPIXELCLOCK 135000000 /* safety */
1280 
1281 #ifdef CV_AGGRESSIVE_TIMING
1282 long cv64_memclk = 55000000;
1283 #else
1284 long cv64_memclk = 50000000;
1285 #endif
1286 
1287 /*********************/
1288 
1289 static unsigned char clocks[]={
1290   0x13, 0x61, 0x6b, 0x6d, 0x51, 0x69, 0x54, 0x69,
1291   0x4f, 0x68, 0x6b, 0x6b, 0x18, 0x61, 0x7b, 0x6c,
1292   0x51, 0x67, 0x24, 0x62, 0x56, 0x67, 0x77, 0x6a,
1293   0x1d, 0x61, 0x53, 0x66, 0x6b, 0x68, 0x79, 0x69,
1294   0x7c, 0x69, 0x7f, 0x69, 0x22, 0x61, 0x54, 0x65,
1295   0x56, 0x65, 0x58, 0x65, 0x67, 0x66, 0x41, 0x63,
1296   0x27, 0x61, 0x13, 0x41, 0x37, 0x62, 0x6b, 0x4d,
1297   0x23, 0x43, 0x51, 0x49, 0x79, 0x66, 0x54, 0x49,
1298   0x7d, 0x66, 0x34, 0x56, 0x4f, 0x63, 0x1f, 0x42,
1299   0x6b, 0x4b, 0x7e, 0x4d, 0x18, 0x41, 0x2a, 0x43,
1300   0x7b, 0x4c, 0x74, 0x4b, 0x51, 0x47, 0x65, 0x49,
1301   0x24, 0x42, 0x68, 0x49, 0x56, 0x47, 0x75, 0x4a,
1302   0x77, 0x4a, 0x31, 0x43, 0x1d, 0x41, 0x71, 0x49,
1303   0x53, 0x46, 0x29, 0x42, 0x6b, 0x48, 0x1f, 0x41,
1304   0x79, 0x49, 0x6f, 0x48, 0x7c, 0x49, 0x38, 0x43,
1305   0x7f, 0x49, 0x5d, 0x46, 0x22, 0x41, 0x53, 0x45,
1306   0x54, 0x45, 0x55, 0x45, 0x56, 0x45, 0x57, 0x45,
1307   0x58, 0x45, 0x25, 0x41, 0x67, 0x46, 0x5b, 0x45,
1308   0x41, 0x43, 0x78, 0x47, 0x27, 0x41, 0x51, 0x44,
1309   0x13, 0x21, 0x7d, 0x47, 0x37, 0x42, 0x71, 0x46,
1310   0x6b, 0x2d, 0x14, 0x21, 0x23, 0x23, 0x7d, 0x2f,
1311   0x51, 0x29, 0x61, 0x2b, 0x79, 0x46, 0x1d, 0x22,
1312   0x54, 0x29, 0x45, 0x27, 0x7d, 0x46, 0x7f, 0x46,
1313   0x4f, 0x43, 0x2f, 0x41, 0x1f, 0x22, 0x6a, 0x2b,
1314   0x6b, 0x2b, 0x5b, 0x29, 0x7e, 0x2d, 0x65, 0x44,
1315   0x18, 0x21, 0x5e, 0x29, 0x2a, 0x23, 0x45, 0x26,
1316   0x7b, 0x2c, 0x19, 0x21, 0x74, 0x2b, 0x75, 0x2b,
1317   0x51, 0x27, 0x3f, 0x25, 0x65, 0x29, 0x40, 0x25,
1318   0x24, 0x22, 0x41, 0x25, 0x68, 0x29, 0x42, 0x25,
1319   0x56, 0x27, 0x7e, 0x2b, 0x75, 0x2a, 0x1c, 0x21,
1320   0x77, 0x2a, 0x4f, 0x26, 0x31, 0x23, 0x6f, 0x29,
1321   0x1d, 0x21, 0x32, 0x23, 0x71, 0x29, 0x72, 0x29,
1322   0x53, 0x26, 0x69, 0x28, 0x29, 0x22, 0x75, 0x29,
1323   0x6b, 0x28, 0x1f, 0x21, 0x1f, 0x21, 0x6d, 0x28,
1324   0x79, 0x29, 0x2b, 0x22, 0x6f, 0x28, 0x59, 0x26,
1325   0x7c, 0x29, 0x7d, 0x29, 0x38, 0x23, 0x21, 0x21,
1326   0x7f, 0x29, 0x39, 0x23, 0x5d, 0x26, 0x75, 0x28,
1327   0x22, 0x21, 0x77, 0x28, 0x53, 0x25, 0x6c, 0x27,
1328   0x54, 0x25, 0x61, 0x26, 0x55, 0x25, 0x30, 0x22,
1329   0x56, 0x25, 0x63, 0x26, 0x57, 0x25, 0x71, 0x27,
1330   0x58, 0x25, 0x7f, 0x28, 0x25, 0x21, 0x74, 0x27,
1331   0x67, 0x26, 0x40, 0x23, 0x5b, 0x25, 0x26, 0x21,
1332   0x41, 0x23, 0x34, 0x22, 0x78, 0x27, 0x6b, 0x26,
1333   0x27, 0x21, 0x35, 0x22, 0x51, 0x24, 0x7b, 0x27,
1334   0x13, 0x1,  0x13, 0x1,  0x7d, 0x27, 0x4c, 0x9,
1335   0x37, 0x22, 0x5b, 0xb,  0x71, 0x26, 0x5c, 0xb,
1336   0x6b, 0xd,  0x47, 0x23, 0x14, 0x1,  0x4f, 0x9,
1337   0x23, 0x3,  0x75, 0x26, 0x7d, 0xf,  0x1c, 0x2,
1338   0x51, 0x9,  0x59, 0x24, 0x61, 0xb,  0x69, 0x25,
1339   0x79, 0x26, 0x34, 0x5,  0x1d, 0x2,  0x6b, 0x25,
1340   0x54, 0x9,  0x35, 0x5,  0x45, 0x7,  0x6d, 0x25,
1341   0x7d, 0x26, 0x16, 0x1,  0x7f, 0x26, 0x77, 0xd,
1342   0x4f, 0x23, 0x78, 0xd,  0x2f, 0x21, 0x27, 0x3,
1343   0x1f, 0x2,  0x59, 0x9,  0x6a, 0xb,  0x73, 0x25,
1344   0x6b, 0xb,  0x63, 0x24, 0x5b, 0x9,  0x20, 0x2,
1345   0x7e, 0xd,  0x4b, 0x7,  0x65, 0x24, 0x43, 0x22,
1346   0x18, 0x1,  0x6f, 0xb,  0x5e, 0x9,  0x70, 0xb,
1347   0x2a, 0x3,  0x33, 0x4,  0x45, 0x6,  0x60, 0x9,
1348   0x7b, 0xc,  0x19, 0x1,  0x19, 0x1,  0x7d, 0xc,
1349   0x74, 0xb,  0x50, 0x7,  0x75, 0xb,  0x63, 0x9,
1350   0x51, 0x7,  0x23, 0x2,  0x3f, 0x5,  0x1a, 0x1,
1351   0x65, 0x9,  0x2d, 0x3,  0x40, 0x5,  0x0,  0x0,
1352 };
1353 
1354 /* Console colors */
1355 unsigned char cvconscolors[16][3] = {	/* background, foreground, hilite */
1356   /*  R     G     B  */
1357   {0x30, 0x30, 0x30},
1358   {0x00, 0x00, 0x00},
1359   {0x80, 0x00, 0x00},
1360   {0x00, 0x80, 0x00},
1361   {0x00, 0x00, 0x80},
1362   {0x80, 0x80, 0x00},
1363   {0x00, 0x80, 0x80},
1364   {0x80, 0x00, 0x80},
1365   {0xff, 0xff, 0xff},
1366   {0x40, 0x40, 0x40},
1367   {0xff, 0x00, 0x00},
1368   {0x00, 0xff, 0x00},
1369   {0x00, 0x00, 0xff},
1370   {0xff, 0xff, 0x00},
1371   {0x00, 0xff, 0xff},
1372   {0x00, 0x00, 0xff}
1373 };
1374 
1375 /* -------------------- Hardware specific routines ------------------------- */
1376 
1377 /* Read Attribute Controller Register=idx */
RAttr(volatile unsigned char * regs,short idx)1378 inline unsigned char RAttr (volatile unsigned char *regs, short idx)
1379 {
1380 	wb_64 (regs, ACT_ADDRESS_W, idx);
1381 	mb();
1382 	udelay(100);
1383 	return (rb_64(regs, ACT_ADDRESS_R));
1384 }
1385 
1386 /* Read Sequencer Register=idx */
RSeq(volatile unsigned char * regs,short idx)1387 inline unsigned char RSeq (volatile unsigned char *regs, short idx)
1388 {
1389 	wb_64 (regs, SEQ_ADDRESS, idx);
1390 	mb();
1391 	return (rb_64(regs, SEQ_ADDRESS_R));
1392 }
1393 
1394 /* Read CRT Controller Register=idx */
RCrt(volatile unsigned char * regs,short idx)1395 inline unsigned char RCrt (volatile unsigned char *regs, short idx)
1396 {
1397 	wb_64 (regs, CRT_ADDRESS, idx);
1398 	mb();
1399 	return (rb_64(regs, CRT_ADDRESS_R));
1400 }
1401 
1402 /* Read Graphics Controller Register=idx */
RGfx(volatile unsigned char * regs,short idx)1403 inline unsigned char RGfx (volatile unsigned char *regs, short idx)
1404 {
1405 	wb_64 (regs, GCT_ADDRESS, idx);
1406 	mb();
1407 	return (rb_64(regs, GCT_ADDRESS_R));
1408 }
1409 
1410 /*
1411  * Special wakeup/passthrough registers on graphics boards
1412  */
1413 
cv64_write_port(unsigned short bits,volatile unsigned char * base)1414 inline void cv64_write_port (unsigned short bits,
1415 			     volatile unsigned char *base)
1416 {
1417 	volatile unsigned char *addr;
1418 	static unsigned char cvportbits = 0; /* Mirror port bits here */
1419 	DPRINTK("ENTER\n");
1420 
1421 	addr = base + 0x40001;
1422 	if (bits & 0x8000) {
1423 		cvportbits |= bits & 0xff; /* Set bits */
1424 		DPRINTK("Set bits: %04x\n", bits);
1425 	} else {
1426 		bits = bits & 0xff;
1427 		bits = (~bits) & 0xff;
1428 		cvportbits &= bits; /* Clear bits */
1429 		DPRINTK("Clear bits: %04x\n", bits);
1430 	}
1431 
1432 	*addr = cvportbits;
1433 	DPRINTK("EXIT\n");
1434 }
1435 
1436 /*
1437  * Monitor switch on CyberVision board
1438  *
1439  *  toggle:
1440  *    0 = CyberVision Signal
1441  *    1 = Amiga Signal
1442  *  board = board addr
1443  *
1444  */
cvscreen(int toggle,volatile unsigned char * board)1445 inline void cvscreen (int toggle, volatile unsigned char *board)
1446 {
1447 	DPRINTK("ENTER\n");
1448 	if (toggle == 1) {
1449 		DPRINTK("Show Amiga video\n");
1450 		cv64_write_port (0x10, board);
1451 	} else {
1452 		DPRINTK("Show CyberVision video\n");
1453 		cv64_write_port (0x8010, board);
1454 	}
1455 	DPRINTK("EXIT\n");
1456 }
1457 
1458 /* Control screen display */
1459 /* toggle: 0 = on, 1 = off */
1460 /* board = registerbase */
gfx_on_off(int toggle,volatile unsigned char * regs)1461 inline void gfx_on_off(int toggle, volatile unsigned char *regs)
1462 {
1463 	int r;
1464 	DPRINTK("ENTER\n");
1465 
1466 	toggle &= 0x1;
1467 	toggle = toggle << 5;
1468 	DPRINTK("Turn display %s\n", (toggle ? "off" : "on"));
1469 
1470 	r = (int) RSeq(regs, SEQ_ID_CLOCKING_MODE);
1471 	r &= 0xdf;	/* Set bit 5 to 0 */
1472 
1473 	WSeq (regs, SEQ_ID_CLOCKING_MODE, r | toggle);
1474 	DPRINTK("EXIT\n");
1475 }
1476 
1477 /*
1478  * Computes M, N, and R values from
1479  * given input frequency. It uses a table of
1480  * precomputed values, to keep CPU time low.
1481  *
1482  * The return value consist of:
1483  * lower byte:  Bits 4-0: N Divider Value
1484  *	        Bits 5-6: R Value          for e.g. SR10 or SR12
1485  * higher byte: Bits 0-6: M divider value  for e.g. SR11 or SR13
1486  */
cv64_compute_clock(unsigned long freq)1487 static unsigned short cv64_compute_clock(unsigned long freq)
1488 {
1489 	static unsigned char *mnr, *save;	/* M, N + R vals */
1490 	unsigned long work_freq, r;
1491 	unsigned short erg;
1492 	long diff, d2;
1493 
1494 	DPRINTK("ENTER\n");
1495 	if (freq < 12500000 || freq > MAXPIXELCLOCK) {
1496 		printk("CV64 driver: Illegal clock frequency %ld, using 25MHz\n",
1497 		       freq);
1498 		freq = 25000000;
1499 	}
1500 	DPRINTK("Freq = %ld\n", freq);
1501 	mnr = clocks;	/* there the vals are stored */
1502 	d2 = 0x7fffffff;
1503 
1504 	while (*mnr) {	/* mnr vals are 0-terminated */
1505 		work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2);
1506 
1507 		r = (mnr[1] >> 5) & 0x03;
1508 		if (r != 0) {
1509 			work_freq = work_freq >> r;	/* r is the freq divider */
1510 		}
1511 
1512 		work_freq *= 0x3E8;	/* 2nd part of OSC */
1513 
1514 		diff = abs(freq - work_freq);
1515 
1516 		if (d2 >= diff) {
1517 			d2 = diff;
1518 			/* In save are the vals for minimal diff */
1519 			save = mnr;
1520 		}
1521 		mnr += 2;
1522 	}
1523 	erg = *((unsigned short *)save);
1524 
1525 	DPRINTK("EXIT\n");
1526 	return (erg);
1527 }
1528 
cv_has_4mb(volatile unsigned char * fb)1529 static int cv_has_4mb (volatile unsigned char *fb)
1530 {
1531 	volatile unsigned long *tr, *tw;
1532 	DPRINTK("ENTER\n");
1533 
1534 	/* write patterns in memory and test if they can be read */
1535 	tw = (volatile unsigned long *) fb;
1536 	tr = (volatile unsigned long *) (fb + 0x02000000);
1537 
1538 	*tw = 0x87654321;
1539 
1540 	if (*tr != 0x87654321) {
1541 		DPRINTK("EXIT - <4MB\n");
1542 		return (0);
1543 	}
1544 
1545 	/* upper memory region */
1546 	tw = (volatile unsigned long *) (fb + 0x00200000);
1547 	tr = (volatile unsigned long *) (fb + 0x02200000);
1548 
1549 	*tw = 0x87654321;
1550 
1551 	if (*tr != 0x87654321) {
1552 		DPRINTK("EXIT - <4MB\n");
1553 		return (0);
1554 	}
1555 
1556 	*tw = 0xAAAAAAAA;
1557 
1558 	if (*tr != 0xAAAAAAAA) {
1559 		DPRINTK("EXIT - <4MB\n");
1560 		return (0);
1561 	}
1562 
1563 	*tw = 0x55555555;
1564 
1565 	if (*tr != 0x55555555) {
1566 		DPRINTK("EXIT - <4MB\n");
1567 		return (0);
1568 	}
1569 
1570 	DPRINTK("EXIT\n");
1571 	return (1);
1572 }
1573 
cv64_board_init(void)1574 static void cv64_board_init (void)
1575 {
1576 	volatile unsigned char *regs = CyberRegs;
1577 	int i;
1578 	unsigned int clockpar;
1579 	unsigned char test;
1580 
1581 	DPRINTK("ENTER\n");
1582 
1583 	/*
1584 	 * Special CyberVision 64 board operations
1585 	 */
1586 	/* Reset board */
1587 	for (i = 0; i < 6; i++) {
1588 		cv64_write_port (0xff, CyberBase);
1589 	}
1590 	/* Return to operational mode */
1591 	cv64_write_port (0x8004, CyberBase);
1592 
1593 	/*
1594 	 * Generic (?) S3 chip wakeup
1595 	 */
1596 	/* Disable I/O & memory decoders, video in setup mode */
1597 	wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x10);
1598 	/* Video responds to cmds, addrs & data */
1599 	wb_64 (regs, SREG_OPTION_SELECT, 0x1);
1600 	/* Enable I/O & memory decoders, video in operational mode */
1601 	wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x8);
1602 	/* VGA color emulation, enable cpu access to display mem */
1603 	wb_64 (regs, GREG_MISC_OUTPUT_W, 0x03);
1604 	/* Unlock S3 VGA regs */
1605 	WCrt (regs, CRT_ID_REGISTER_LOCK_1, 0x48);
1606 	/* Unlock system control & extension registers */
1607 	WCrt (regs, CRT_ID_REGISTER_LOCK_2, 0xA5);
1608 /* GRF - Enable interrupts */
1609 	/* Enable enhanced regs access, Ready cntl 0 wait states */
1610 	test = RCrt (regs, CRT_ID_SYSTEM_CONFIG);
1611 	test = test | 0x01;		/* enable enhanced register access */
1612 	test = test & 0xEF;		/* clear bit 4, 0 wait state */
1613 	WCrt (regs, CRT_ID_SYSTEM_CONFIG, test);
1614 	/*
1615 	 * bit 0=1: Enable enhaced mode functions
1616 	 * bit 2=0: Enhanced mode 8+ bits/pixel
1617 	 * bit 4=1: Enable linear addressing
1618 	 * bit 5=1: Enable MMIO
1619 	 */
1620 	wb_64 (regs, ECR_ADV_FUNC_CNTL, 0x31);
1621 	/*
1622 	 * bit 0=1: Color emulation
1623 	 * bit 1=1: Enable CPU access to display memory
1624 	 * bit 5=1: Select high 64K memory page
1625 	 */
1626 /* GRF - 0xE3 */
1627 	wb_64 (regs, GREG_MISC_OUTPUT_W, 0x23);
1628 
1629 	/* Cpu base addr */
1630 	WCrt (regs, CRT_ID_EXT_SYS_CNTL_4, 0x0);
1631 
1632 	/* Reset. This does nothing on Trio, but standard VGA practice */
1633 	/* WSeq (CyberRegs, SEQ_ID_RESET, 0x03); */
1634 	/* Character clocks 8 dots wide */
1635 	WSeq (regs, SEQ_ID_CLOCKING_MODE, 0x01);
1636 	/* Enable cpu write to all color planes */
1637 	WSeq (regs, SEQ_ID_MAP_MASK, 0x0F);
1638 	/* Font table in 1st 8k of plane 2, font A=B disables swtich */
1639 	WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x0);
1640 	/* Allow mem access to 256kb */
1641 	WSeq (regs, SEQ_ID_MEMORY_MODE, 0x2);
1642 	/* Unlock S3 extensions to VGA Sequencer regs */
1643 	WSeq (regs, SEQ_ID_UNLOCK_EXT, 0x6);
1644 
1645 	/* Enable 4MB fast page mode */
1646 	test = RSeq (regs, SEQ_ID_BUS_REQ_CNTL);
1647 	test = test | 1 << 6;
1648 	WSeq (regs, SEQ_ID_BUS_REQ_CNTL, test);
1649 
1650 	/* Faster LUT write: 1 DCLK LUT write cycle, RAMDAC clk doubled */
1651 	WSeq (regs, SEQ_ID_RAMDAC_CNTL, 0xC0);
1652 
1653 	/* Clear immediate clock load bit */
1654 	test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
1655 	test = test & 0xDF;
1656 	/* If > 55MHz, enable 2 cycle memory write */
1657 	if (cv64_memclk >= 55000000) {
1658 		test |= 0x80;
1659 	}
1660 	WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
1661 
1662 	/* Set MCLK value */
1663 	clockpar = cv64_compute_clock (cv64_memclk);
1664 	test = (clockpar & 0xFF00) >> 8;
1665 	WSeq (regs, SEQ_ID_MCLK_HI, test);
1666 	test = clockpar & 0xFF;
1667 	WSeq (regs, SEQ_ID_MCLK_LO, test);
1668 
1669 	/* Chip rev specific: Not in my Trio manual!!! */
1670 	if (RCrt (regs, CRT_ID_REVISION) == 0x10)
1671 		WSeq (regs, SEQ_ID_MORE_MAGIC, test);
1672 
1673 	/* We now load an 25 MHz, 31kHz, 640x480 standard VGA Mode. */
1674 
1675 	/* Set DCLK value */
1676 	WSeq (regs, SEQ_ID_DCLK_HI, 0x13);
1677 	WSeq (regs, SEQ_ID_DCLK_LO, 0x41);
1678 
1679 	/* Load DCLK (and MCLK?) immediately */
1680 	test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
1681 	test = test | 0x22;
1682 	WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
1683 
1684 	/* Enable loading of DCLK */
1685 	test = rb_64(regs, GREG_MISC_OUTPUT_R);
1686 	test = test | 0x0C;
1687 	wb_64 (regs, GREG_MISC_OUTPUT_W, test);
1688 
1689 	/* Turn off immediate xCLK load */
1690 	WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, 0x2);
1691 
1692 	/* Horizontal character clock counts */
1693 	/* 8 LSB of 9 bits = total line - 5 */
1694 	WCrt (regs, CRT_ID_HOR_TOTAL, 0x5F);
1695 	/* Active display line */
1696 	WCrt (regs, CRT_ID_HOR_DISP_ENA_END, 0x4F);
1697 	/* Blank assertion start */
1698 	WCrt (regs, CRT_ID_START_HOR_BLANK, 0x50);
1699 	/* Blank assertion end */
1700 	WCrt (regs, CRT_ID_END_HOR_BLANK, 0x82);
1701 	/* HSYNC assertion start */
1702 	WCrt (regs, CRT_ID_START_HOR_RETR, 0x54);
1703 	/* HSYNC assertion end */
1704 	WCrt (regs, CRT_ID_END_HOR_RETR, 0x80);
1705 	WCrt (regs, CRT_ID_VER_TOTAL, 0xBF);
1706 	WCrt (regs, CRT_ID_OVERFLOW, 0x1F);
1707 	WCrt (regs, CRT_ID_PRESET_ROW_SCAN, 0x0);
1708 	WCrt (regs, CRT_ID_MAX_SCAN_LINE, 0x40);
1709 	WCrt (regs, CRT_ID_CURSOR_START, 0x00);
1710 	WCrt (regs, CRT_ID_CURSOR_END, 0x00);
1711 	WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00);
1712 	WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00);
1713 	WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1714 	WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
1715 	WCrt (regs, CRT_ID_START_VER_RETR, 0x9C);
1716 	WCrt (regs, CRT_ID_END_VER_RETR, 0x0E);
1717 	WCrt (regs, CRT_ID_VER_DISP_ENA_END, 0x8F);
1718 	WCrt (regs, CRT_ID_SCREEN_OFFSET, 0x50);
1719 	WCrt (regs, CRT_ID_UNDERLINE_LOC, 0x00);
1720 	WCrt (regs, CRT_ID_START_VER_BLANK, 0x96);
1721 	WCrt (regs, CRT_ID_END_VER_BLANK, 0xB9);
1722 	WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3);
1723 	WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF);
1724 	WCrt (regs, CRT_ID_BACKWAD_COMP_3, 0x10);	/* FIFO enabled */
1725 	WCrt (regs, CRT_ID_MISC_1, 0x35);
1726 	WCrt (regs, CRT_ID_DISPLAY_FIFO, 0x5A);
1727 	WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, 0x70);
1728 	WCrt (regs, CRT_ID_LAW_POS_LO, 0x40);
1729 	WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, 0xFF);
1730 
1731 	WGfx (regs, GCT_ID_SET_RESET, 0x0);
1732 	WGfx (regs, GCT_ID_ENABLE_SET_RESET, 0x0);
1733 	WGfx (regs, GCT_ID_COLOR_COMPARE, 0x0);
1734 	WGfx (regs, GCT_ID_DATA_ROTATE, 0x0);
1735 	WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x0);
1736 	WGfx (regs, GCT_ID_GRAPHICS_MODE, 0x40);
1737 	WGfx (regs, GCT_ID_MISC, 0x01);
1738 	WGfx (regs, GCT_ID_COLOR_XCARE, 0x0F);
1739 	WGfx (regs, GCT_ID_BITMASK, 0xFF);
1740 
1741 	/* Colors for text mode */
1742 	for (i = 0; i < 0xf; i++)
1743 		WAttr (regs, i, i);
1744 
1745 	WAttr (regs, ACT_ID_ATTR_MODE_CNTL, 0x41);
1746 	WAttr (regs, ACT_ID_OVERSCAN_COLOR, 0x01);
1747 	WAttr (regs, ACT_ID_COLOR_PLANE_ENA, 0x0F);
1748 	WAttr (regs, ACT_ID_HOR_PEL_PANNING, 0x0);
1749 	WAttr (regs, ACT_ID_COLOR_SELECT, 0x0);
1750 
1751 	wb_64 (regs, VDAC_MASK, 0xFF);
1752 
1753 	*((unsigned long *) (regs + ECR_FRGD_COLOR)) = 0xFF;
1754 	*((unsigned long *) (regs + ECR_BKGD_COLOR)) = 0;
1755 
1756 	/* Colors initially set to grayscale */
1757 
1758 	wb_64 (regs, VDAC_ADDRESS_W, 0);
1759 	for (i = 255; i >= 0; i--) {
1760 		wb_64(regs, VDAC_DATA, i);
1761 		wb_64(regs, VDAC_DATA, i);
1762 		wb_64(regs, VDAC_DATA, i);
1763 	}
1764 
1765 	/* GFx hardware cursor off */
1766 	WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
1767 
1768 	/* Set first to 4MB, so test will work */
1769 	WCrt (regs, CRT_ID_LAW_CNTL, 0x13);
1770 	/* Find "correct" size of fbmem of Z3 board */
1771 	if (cv_has_4mb (CyberMem)) {
1772 		CyberSize = 1024 * 1024 * 4;
1773 		WCrt (regs, CRT_ID_LAW_CNTL, 0x13);
1774 		DPRINTK("4MB board\n");
1775 	} else {
1776 		CyberSize = 1024 * 1024 * 2;
1777 		WCrt (regs, CRT_ID_LAW_CNTL, 0x12);
1778 		DPRINTK("2MB board\n");
1779 	}
1780 
1781 	/* Initialize graphics engine */
1782 	Cyber_WaitBlit();
1783 	vgaw16 (regs, ECR_FRGD_MIX, 0x27);
1784 	vgaw16 (regs, ECR_BKGD_MIX, 0x07);
1785 	vgaw16 (regs, ECR_READ_REG_DATA, 0x1000);
1786 	udelay(200);
1787 	vgaw16 (regs, ECR_READ_REG_DATA, 0x2000);
1788 	Cyber_WaitBlit();
1789 	vgaw16 (regs, ECR_READ_REG_DATA, 0x3FFF);
1790 	Cyber_WaitBlit();
1791 	udelay(200);
1792 	vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF);
1793 	Cyber_WaitBlit();
1794 	vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, ~0);
1795 	Cyber_WaitBlit();
1796 	vgaw16 (regs, ECR_READ_REG_DATA, 0xE000);
1797 	vgaw16 (regs, ECR_CURRENT_Y_POS2, 0x00);
1798 	vgaw16 (regs, ECR_CURRENT_X_POS2, 0x00);
1799 	vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
1800 	vgaw16 (regs, ECR_DEST_Y__AX_STEP, 0x00);
1801 	vgaw16 (regs, ECR_DEST_Y2__AX_STEP2, 0x00);
1802 	vgaw16 (regs, ECR_DEST_X__DIA_STEP, 0x00);
1803 	vgaw16 (regs, ECR_DEST_X2__DIA_STEP2, 0x00);
1804 	vgaw16 (regs, ECR_SHORT_STROKE, 0x00);
1805 	vgaw16 (regs, ECR_DRAW_CMD, 0x01);
1806 
1807 	Cyber_WaitBlit();
1808 
1809 	vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF);
1810 	vgaw16 (regs, ECR_BKGD_COLOR, 0x01);
1811 	vgaw16 (regs, ECR_FRGD_COLOR, 0x00);
1812 
1813 
1814 	/* Enable video display (set bit 5) */
1815 /* ARB - Would also seem to write to AR13.
1816  *       May want to use parts of WAttr to set JUST bit 5
1817  */
1818 	WAttr (regs, 0x33, 0);
1819 
1820 /* GRF - function code ended here */
1821 
1822 	/* Turn gfx on again */
1823 	gfx_on_off (0, regs);
1824 
1825 	/* Pass-through */
1826 	cvscreen (0, CyberBase);
1827 
1828 	DPRINTK("EXIT\n");
1829 }
1830 
cv64_load_video_mode(struct fb_var_screeninfo * video_mode)1831 static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
1832 {
1833   volatile unsigned char *regs = CyberRegs;
1834   int fx, fy;
1835   unsigned short mnr;
1836   unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, VSE, VT;
1837   char LACE, DBLSCAN, TEXT, CONSOLE;
1838   int cr50, sr15, sr18, clock_mode, test;
1839   int m, n;
1840   int tfillm, temptym;
1841   int hmul;
1842 
1843   /* ---------------- */
1844   int xres, hfront, hsync, hback;
1845   int yres, vfront, vsync, vback;
1846   int bpp;
1847 #if 0
1848   float freq_f;
1849 #endif
1850   long freq;
1851   /* ---------------- */
1852 
1853   DPRINTK("ENTER\n");
1854   TEXT = 0;	/* if depth == 4 */
1855   CONSOLE = 0;	/* mode num == 255 (console) */
1856   fx = fy = 8;	/* force 8x8 font */
1857 
1858 /* GRF - Disable interrupts */
1859 
1860   gfx_on_off (1, regs);
1861 
1862   switch (video_mode->bits_per_pixel) {
1863   case 15:
1864   case 16:
1865     hmul = 2;
1866     break;
1867 
1868   default:
1869     hmul = 1;
1870     break;
1871   }
1872 
1873   bpp = video_mode->bits_per_pixel;
1874   xres = video_mode->xres;
1875   hfront = video_mode->right_margin;
1876   hsync = video_mode->hsync_len;
1877   hback = video_mode->left_margin;
1878 
1879   LACE = 0;
1880   DBLSCAN = 0;
1881 
1882   if (video_mode->vmode & FB_VMODE_DOUBLE) {
1883     yres = video_mode->yres * 2;
1884     vfront = video_mode->lower_margin * 2;
1885     vsync = video_mode->vsync_len * 2;
1886     vback = video_mode->upper_margin * 2;
1887     DBLSCAN = 1;
1888   } else if (video_mode->vmode & FB_VMODE_INTERLACED) {
1889     yres = (video_mode->yres + 1) / 2;
1890     vfront = (video_mode->lower_margin + 1) / 2;
1891     vsync = (video_mode->vsync_len + 1) / 2;
1892     vback = (video_mode->upper_margin + 1) / 2;
1893     LACE = 1;
1894   } else {
1895     yres = video_mode->yres;
1896     vfront = video_mode->lower_margin;
1897     vsync = video_mode->vsync_len;
1898     vback = video_mode->upper_margin;
1899   }
1900 
1901   /* ARB Dropping custom setup method from cvision.c */
1902 #if 0
1903   if (cvision_custom_mode) {
1904     HBS = hbs / 8 * hmul;
1905     HBE = hbe / 8 * hmul;
1906     HSS = hss / 8 * hmul;
1907     HSE = hse / 8 * hmul;
1908     HT  = ht / 8 * hmul - 5;
1909 
1910     VBS = vbs - 1;
1911     VSS = vss;
1912     VSE = vse;
1913     VBE = vbe;
1914     VT  = vt - 2;
1915   } else {
1916 #else
1917     {
1918 #endif
1919     HBS = hmul * (xres / 8);
1920     HBE = hmul * ((xres/8) + (hfront/8) + (hsync/8) + (hback/8) - 2);
1921     HSS = hmul * ((xres/8) + (hfront/8) + 2);
1922     HSE = hmul * ((xres/8) + (hfront/8) + (hsync/8) + 1);
1923     HT  = hmul * ((xres/8) + (hfront/8) + (hsync/8) + (hback/8));
1924 
1925     VBS = yres;
1926     VBE = yres + vfront + vsync + vback - 2;
1927     VSS = yres + vfront - 1;
1928     VSE = yres + vfront + vsync - 1;
1929     VT  = yres + vfront + vsync + vback - 2;
1930   }
1931 
1932   wb_64 (regs, ECR_ADV_FUNC_CNTL, (TEXT ? 0x00 : 0x31));
1933 
1934   if (TEXT)
1935     HDE = ((video_mode->xres + fx - 1) / fx) - 1;
1936   else
1937     HDE = (video_mode->xres + 3) * hmul / 8 - 1;
1938 
1939   VDE = video_mode->yres - 1;
1940 
1941   WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
1942   WCrt (regs, CRT_ID_EXT_DAC_CNTL, 0x00);
1943 
1944   WSeq (regs, SEQ_ID_MEMORY_MODE,
1945 	(TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x0e);
1946   WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x00);
1947   WSeq (regs, SEQ_ID_MAP_MASK,
1948 	(video_mode->bits_per_pixel == 1) ? 0x01 : 0xFF);
1949   WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1950 
1951   /* cv64_compute_clock accepts arguments in Hz */
1952   /* pixclock is in ps ... convert to Hz */
1953 
1954 #if 0
1955   freq_f = (1.0 / (float) video_mode->pixclock) * 1000000000;
1956   freq = ((long) freq_f) * 1000;
1957 #else
1958 /* freq = (long) ((long long)1000000000000 / (long long) video_mode->pixclock);
1959  */
1960   freq = (1000000000 / video_mode->pixclock) * 1000;
1961 #endif
1962 
1963   mnr = cv64_compute_clock (freq);
1964   WSeq (regs, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8));
1965   WSeq (regs, SEQ_ID_DCLK_LO, (mnr & 0xFF));
1966 
1967   /* Load display parameters into board */
1968   WCrt (regs, CRT_ID_EXT_HOR_OVF,
1969 	((HT & 0x100) ? 0x01 : 0x00) |
1970 	((HDE & 0x100) ? 0x02 : 0x00) |
1971 	((HBS & 0x100) ? 0x04 : 0x00) |
1972 	/* ((HBE & 0x40) ? 0x08 : 0x00) | */
1973 	((HSS & 0x100) ? 0x10 : 0x00) |
1974 	/* ((HSE & 0x20) ? 0x20 : 0x00) | */
1975 	(((HT-5) & 0x100) ? 0x40 : 0x00)
1976 	);
1977 
1978   WCrt (regs, CRT_ID_EXT_VER_OVF,
1979 	0x40 |
1980 	((VT & 0x400) ? 0x01 : 0x00) |
1981 	((VDE & 0x400) ? 0x02 : 0x00) |
1982 	((VBS & 0x400) ? 0x04 : 0x00) |
1983 	((VSS & 0x400) ? 0x10 : 0x00)
1984 	);
1985 
1986   WCrt (regs, CRT_ID_HOR_TOTAL, HT);
1987   WCrt (regs, CRT_ID_DISPLAY_FIFO, HT - 5);
1988   WCrt (regs, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE));
1989   WCrt (regs, CRT_ID_START_HOR_BLANK, HBS);
1990   WCrt (regs, CRT_ID_END_HOR_BLANK, ((HBE & 0x1F) | 0x80));
1991   WCrt (regs, CRT_ID_START_HOR_RETR, HSS);
1992   WCrt (regs, CRT_ID_END_HOR_RETR,
1993 	(HSE & 0x1F) |
1994 	((HBE & 0x20) ? 0x80 : 0x00)
1995 	);
1996   WCrt (regs, CRT_ID_VER_TOTAL, VT);
1997   WCrt (regs, CRT_ID_OVERFLOW,
1998 	0x10 |
1999 	((VT & 0x100) ? 0x01 : 0x00) |
2000 	((VDE & 0x100) ? 0x02 : 0x00) |
2001 	((VSS & 0x100) ? 0x04 : 0x00) |
2002 	((VBS & 0x100) ? 0x08 : 0x00) |
2003 	((VT & 0x200) ? 0x20 : 0x00) |
2004 	((VDE & 0x200) ? 0x40 : 0x00) |
2005 	((VSS & 0x200) ? 0x80 : 0x00)
2006 	);
2007   WCrt (regs, CRT_ID_MAX_SCAN_LINE,
2008 	0x40 |
2009 	(DBLSCAN ? 0x80 : 0x00) |
2010 	((VBS & 0x200) ? 0x20 : 0x00) |
2011 	(TEXT ? ((fy - 1) & 0x1F) : 0x00)
2012 	);
2013 
2014   WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3);
2015 
2016   /* Text cursor */
2017 
2018   if (TEXT) {
2019 #if 1
2020     WCrt (regs, CRT_ID_CURSOR_START, (fy & 0x1f) - 2);
2021     WCrt (regs, CRT_ID_CURSOR_END, (fy & 0x1F) - 1);
2022 #else
2023     WCrt (regs, CRT_ID_CURSOR_START, 0x00);
2024     WCrt (regs, CRT_ID_CURSOR_END, fy & 0x1F);
2025 #endif
2026     WCrt (regs, CRT_ID_UNDERLINE_LOC, (fy - 1) & 0x1F);
2027     WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
2028     WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
2029   }
2030 
2031   WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00);
2032   WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00);
2033   WCrt (regs, CRT_ID_START_VER_RETR, VSS);
2034   WCrt (regs, CRT_ID_END_VER_RETR, (VSE & 0x0F));
2035   WCrt (regs, CRT_ID_VER_DISP_ENA_END, VDE);
2036   WCrt (regs, CRT_ID_START_VER_BLANK, VBS);
2037   WCrt (regs, CRT_ID_END_VER_BLANK, VBE);
2038   WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF);
2039   WCrt (regs, CRT_ID_LACE_RETR_START, HT / 2);
2040   WCrt (regs, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00));
2041   WGfx (regs, GCT_ID_GRAPHICS_MODE,
2042 	((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x00 : 0x40));
2043   WGfx (regs, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
2044   WSeq (regs, SEQ_ID_MEMORY_MODE,
2045 	((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x02));
2046 
2047   wb_64 (regs, VDAC_MASK, 0xFF);
2048 
2049   /* Blank border */
2050   test = RCrt (regs, CRT_ID_BACKWAD_COMP_2);
2051   WCrt (regs, CRT_ID_BACKWAD_COMP_2, (test | 0x20));
2052 
2053   sr15 = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
2054   sr15 &= 0xEF;
2055   sr18 = RSeq (regs, SEQ_ID_RAMDAC_CNTL);
2056   sr18 &= 0x7F;
2057   clock_mode = 0x00;
2058   cr50 = 0x00;
2059 
2060   test = RCrt (regs, CRT_ID_EXT_MISC_CNTL_2);
2061   test &= 0xD;
2062 
2063   /* Clear roxxler byte-swapping... */
2064   cv64_write_port (0x0040, CyberBase);
2065   cv64_write_port (0x0020, CyberBase);
2066 
2067   switch (video_mode->bits_per_pixel) {
2068   case 1:
2069   case 4:	/* text */
2070     HDE = video_mode->xres / 16;
2071     break;
2072 
2073   case 8:
2074     if (freq > 80000000) {
2075       clock_mode = 0x10 | 0x02;
2076       sr15 |= 0x10;
2077       sr18 |= 0x80;
2078     }
2079     HDE = video_mode->xres / 8;
2080     cr50 |= 0x00;
2081     break;
2082 
2083   case 15:
2084     cv64_write_port (0x8020, CyberBase);
2085     clock_mode = 0x30;
2086     HDE = video_mode->xres / 4;
2087     cr50 |= 0x10;
2088     break;
2089 
2090   case 16:
2091     cv64_write_port (0x8020, CyberBase);
2092     clock_mode = 0x50;
2093     HDE = video_mode->xres / 4;
2094     cr50 |= 0x10;
2095     break;
2096 
2097   case 24:
2098   case 32:
2099     cv64_write_port (0x8040, CyberBase);
2100     clock_mode = 0xD0;
2101     HDE = video_mode->xres / 2;
2102     cr50 |= 0x30;
2103     break;
2104   }
2105 
2106   WCrt (regs, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test);
2107   WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, sr15);
2108   WSeq (regs, SEQ_ID_RAMDAC_CNTL, sr18);
2109   WCrt (regs, CRT_ID_SCREEN_OFFSET, HDE);
2110 
2111   WCrt (regs, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35));
2112 
2113   test = RCrt (regs, CRT_ID_EXT_SYS_CNTL_2);
2114   test &= ~0x30;
2115   test |= (HDE >> 4) & 0x30;
2116   WCrt (regs, CRT_ID_EXT_SYS_CNTL_2, test);
2117 
2118   /* Set up graphics engine */
2119   switch (video_mode->xres) {
2120   case 1024:
2121     cr50 |= 0x00;
2122     break;
2123 
2124   case 640:
2125     cr50 |= 0x40;
2126     break;
2127 
2128   case 800:
2129     cr50 |= 0x80;
2130     break;
2131 
2132   case 1280:
2133     cr50 |= 0xC0;
2134     break;
2135 
2136   case 1152:
2137     cr50 |= 0x01;
2138     break;
2139 
2140   case 1600:
2141     cr50 |= 0x81;
2142     break;
2143 
2144   default:	/* XXX */
2145     break;
2146   }
2147 
2148   WCrt (regs, CRT_ID_EXT_SYS_CNTL_1, cr50);
2149 
2150   udelay(100);
2151   WAttr (regs, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41));
2152   udelay(100);
2153   WAttr (regs, ACT_ID_COLOR_PLANE_ENA,
2154 	 (video_mode->bits_per_pixel == 1) ? 0x01 : 0x0F);
2155   udelay(100);
2156 
2157   tfillm = (96 * (cv64_memclk / 1000)) / 240000;
2158 
2159   switch (video_mode->bits_per_pixel) {
2160   case 32:
2161   case 24:
2162     temptym = (24 * (cv64_memclk / 1000)) / (freq / 1000);
2163     break;
2164   case 15:
2165   case 16:
2166     temptym = (48 * (cv64_memclk / 1000)) / (freq / 1000);
2167     break;
2168   case 4:
2169     temptym = (192 * (cv64_memclk / 1000)) / (freq / 1000);
2170     break;
2171   default:
2172     temptym = (96 * (cv64_memclk / 1000)) / (freq / 1000);
2173     break;
2174   }
2175 
2176   m = (temptym - tfillm - 9) / 2;
2177   if (m < 0)
2178     m = 0;
2179   m = (m & 0x1F) << 3;
2180   if (m < 0x18)
2181     m = 0x18;
2182   n = 0xFF;
2183 
2184   WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, m);
2185   WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, n);
2186   udelay(10);
2187 
2188   /* Text initialization */
2189 
2190   if (TEXT) {
2191     /* Do text initialization here ! */
2192   }
2193 
2194   if (CONSOLE) {
2195     int i;
2196     wb_64 (regs, VDAC_ADDRESS_W, 0);
2197     for (i = 0; i < 4; i++) {
2198       wb_64 (regs, VDAC_DATA, cvconscolors [i][0]);
2199       wb_64 (regs, VDAC_DATA, cvconscolors [i][1]);
2200       wb_64 (regs, VDAC_DATA, cvconscolors [i][2]);
2201     }
2202   }
2203 
2204   WAttr (regs, 0x33, 0);
2205 
2206   /* Turn gfx on again */
2207   gfx_on_off (0, (volatile unsigned char *) regs);
2208 
2209   /* Pass-through */
2210   cvscreen (0, CyberBase);
2211 
2212 DPRINTK("EXIT\n");
2213 }
2214 
2215 void cvision_bitblt (u_short sx, u_short sy, u_short dx, u_short dy,
2216 		     u_short w, u_short h)
2217 {
2218 	volatile unsigned char *regs = CyberRegs;
2219 	unsigned short drawdir = 0;
2220 
2221 	DPRINTK("ENTER\n");
2222 	if (sx > dx) {
2223 		drawdir |= 1 << 5;
2224 	} else {
2225 		sx += w - 1;
2226 		dx += w - 1;
2227 	}
2228 
2229 	if (sy > dy) {
2230 		drawdir |= 1 << 7;
2231 	} else {
2232 		sy += h - 1;
2233 		dy += h - 1;
2234 	}
2235 
2236 	Cyber_WaitBlit();
2237 	vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
2238 	vgaw16 (regs, ECR_BKGD_MIX, 0x7);
2239 	vgaw16 (regs, ECR_FRGD_MIX, 0x67);
2240 	vgaw16 (regs, ECR_BKGD_COLOR, 0x0);
2241 	vgaw16 (regs, ECR_FRGD_COLOR, 0x1);
2242 	vgaw16 (regs, ECR_BITPLANE_READ_MASK, 0x1);
2243 	vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, 0xFFF);
2244 	vgaw16 (regs, ECR_CURRENT_Y_POS, sy);
2245 	vgaw16 (regs, ECR_CURRENT_X_POS, sx);
2246 	vgaw16 (regs, ECR_DEST_Y__AX_STEP, dy);
2247 	vgaw16 (regs, ECR_DEST_X__DIA_STEP, dx);
2248 	vgaw16 (regs, ECR_READ_REG_DATA, h - 1);
2249 	vgaw16 (regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
2250 	vgaw16 (regs, ECR_DRAW_CMD, 0xC051 | drawdir);
2251 	DPRINTK("EXIT\n");
2252 }
2253 
2254 void cvision_clear (u_short dx, u_short dy, u_short w, u_short h, u_short bg)
2255 {
2256 	volatile unsigned char *regs = CyberRegs;
2257 	DPRINTK("ENTER\n");
2258 	Cyber_WaitBlit();
2259 	vgaw16 (regs, ECR_FRGD_MIX, 0x0027);
2260 	vgaw16 (regs, ECR_FRGD_COLOR, bg);
2261 	vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
2262 	vgaw16 (regs, ECR_CURRENT_Y_POS, dy);
2263 	vgaw16 (regs, ECR_CURRENT_X_POS, dx);
2264 	vgaw16 (regs, ECR_READ_REG_DATA, h - 1);
2265 	vgaw16 (regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
2266 	vgaw16 (regs, ECR_DRAW_CMD, 0x40B1);
2267 	DPRINTK("EXIT\n");
2268 }
2269 
2270 #ifdef CYBERFBDEBUG
2271 /*
2272  * Dump internal settings of CyberVision board
2273  */
2274 static void cv64_dump (void)
2275 {
2276 	volatile unsigned char *regs = CyberRegs;
2277 	DPRINTK("ENTER\n");
2278         /* Dump the VGA setup values */
2279 	*(regs + S3_CRTC_ADR) = 0x00;
2280 	DPRINTK("CR00 = %x\n", *(regs + S3_CRTC_DATA));
2281 	*(regs + S3_CRTC_ADR) = 0x01;
2282 	DPRINTK("CR01 = %x\n", *(regs + S3_CRTC_DATA));
2283 	*(regs + S3_CRTC_ADR) = 0x02;
2284 	DPRINTK("CR02 = %x\n", *(regs + S3_CRTC_DATA));
2285 	*(regs + S3_CRTC_ADR) = 0x03;
2286 	DPRINTK("CR03 = %x\n", *(regs + S3_CRTC_DATA));
2287 	*(regs + S3_CRTC_ADR) = 0x04;
2288 	DPRINTK("CR04 = %x\n", *(regs + S3_CRTC_DATA));
2289 	*(regs + S3_CRTC_ADR) = 0x05;
2290 	DPRINTK("CR05 = %x\n", *(regs + S3_CRTC_DATA));
2291 	*(regs + S3_CRTC_ADR) = 0x06;
2292 	DPRINTK("CR06 = %x\n", *(regs + S3_CRTC_DATA));
2293 	*(regs + S3_CRTC_ADR) = 0x07;
2294 	DPRINTK("CR07 = %x\n", *(regs + S3_CRTC_DATA));
2295 	*(regs + S3_CRTC_ADR) = 0x08;
2296 	DPRINTK("CR08 = %x\n", *(regs + S3_CRTC_DATA));
2297 	*(regs + S3_CRTC_ADR) = 0x09;
2298 	DPRINTK("CR09 = %x\n", *(regs + S3_CRTC_DATA));
2299 	*(regs + S3_CRTC_ADR) = 0x10;
2300 	DPRINTK("CR10 = %x\n", *(regs + S3_CRTC_DATA));
2301 	*(regs + S3_CRTC_ADR) = 0x11;
2302 	DPRINTK("CR11 = %x\n", *(regs + S3_CRTC_DATA));
2303 	*(regs + S3_CRTC_ADR) = 0x12;
2304 	DPRINTK("CR12 = %x\n", *(regs + S3_CRTC_DATA));
2305 	*(regs + S3_CRTC_ADR) = 0x13;
2306 	DPRINTK("CR13 = %x\n", *(regs + S3_CRTC_DATA));
2307 	*(regs + S3_CRTC_ADR) = 0x15;
2308 	DPRINTK("CR15 = %x\n", *(regs + S3_CRTC_DATA));
2309 	*(regs + S3_CRTC_ADR) = 0x16;
2310 	DPRINTK("CR16 = %x\n", *(regs + S3_CRTC_DATA));
2311 	*(regs + S3_CRTC_ADR) = 0x36;
2312 	DPRINTK("CR36 = %x\n", *(regs + S3_CRTC_DATA));
2313 	*(regs + S3_CRTC_ADR) = 0x37;
2314 	DPRINTK("CR37 = %x\n", *(regs + S3_CRTC_DATA));
2315 	*(regs + S3_CRTC_ADR) = 0x42;
2316 	DPRINTK("CR42 = %x\n", *(regs + S3_CRTC_DATA));
2317 	*(regs + S3_CRTC_ADR) = 0x43;
2318 	DPRINTK("CR43 = %x\n", *(regs + S3_CRTC_DATA));
2319 	*(regs + S3_CRTC_ADR) = 0x50;
2320 	DPRINTK("CR50 = %x\n", *(regs + S3_CRTC_DATA));
2321 	*(regs + S3_CRTC_ADR) = 0x51;
2322 	DPRINTK("CR51 = %x\n", *(regs + S3_CRTC_DATA));
2323 	*(regs + S3_CRTC_ADR) = 0x53;
2324 	DPRINTK("CR53 = %x\n", *(regs + S3_CRTC_DATA));
2325 	*(regs + S3_CRTC_ADR) = 0x58;
2326 	DPRINTK("CR58 = %x\n", *(regs + S3_CRTC_DATA));
2327 	*(regs + S3_CRTC_ADR) = 0x59;
2328 	DPRINTK("CR59 = %x\n", *(regs + S3_CRTC_DATA));
2329 	*(regs + S3_CRTC_ADR) = 0x5A;
2330 	DPRINTK("CR5A = %x\n", *(regs + S3_CRTC_DATA));
2331 	*(regs + S3_CRTC_ADR) = 0x5D;
2332 	DPRINTK("CR5D = %x\n", *(regs + S3_CRTC_DATA));
2333 	*(regs + S3_CRTC_ADR) = 0x5E;
2334 	DPRINTK("CR5E = %x\n", *(regs + S3_CRTC_DATA));
2335 	DPRINTK("MISC = %x\n", *(regs + GREG_MISC_OUTPUT_R));
2336 	*(regs + SEQ_ADDRESS) = 0x01;
2337 	DPRINTK("SR01 = %x\n", *(regs + SEQ_ADDRESS_R));
2338 	*(regs + SEQ_ADDRESS) = 0x02;
2339 	DPRINTK("SR02 = %x\n", *(regs + SEQ_ADDRESS_R));
2340 	*(regs + SEQ_ADDRESS) = 0x03;
2341 	DPRINTK("SR03 = %x\n", *(regs + SEQ_ADDRESS_R));
2342 	*(regs + SEQ_ADDRESS) = 0x09;
2343 	DPRINTK("SR09 = %x\n", *(regs + SEQ_ADDRESS_R));
2344 	*(regs + SEQ_ADDRESS) = 0x10;
2345 	DPRINTK("SR10 = %x\n", *(regs + SEQ_ADDRESS_R));
2346 	*(regs + SEQ_ADDRESS) = 0x11;
2347 	DPRINTK("SR11 = %x\n", *(regs + SEQ_ADDRESS_R));
2348 	*(regs + SEQ_ADDRESS) = 0x12;
2349 	DPRINTK("SR12 = %x\n", *(regs + SEQ_ADDRESS_R));
2350 	*(regs + SEQ_ADDRESS) = 0x13;
2351 	DPRINTK("SR13 = %x\n", *(regs + SEQ_ADDRESS_R));
2352 	*(regs + SEQ_ADDRESS) = 0x15;
2353 	DPRINTK("SR15 = %x\n", *(regs + SEQ_ADDRESS_R));
2354 
2355 	return;
2356 }
2357 #endif
2358