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