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