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