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