1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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
103#ifdef CYBERFBDEBUG
104#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
105static void cv64_dump(void);
106#else
107#define DPRINTK(fmt, args...)
108#endif
109
110#define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat)
111#define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg))
112
113#define ww_64(regs,reg,dat) (*((volatile unsigned short *)(regs + reg) = dat)
114
115struct cyberfb_par {
116 struct fb_var_screeninfo var;
117 __u32 type;
118 __u32 type_aux;
119 __u32 visual;
120 __u32 line_length;
121};
122
123static struct cyberfb_par current_par;
124
125static int current_par_valid = 0;
126static int currcon = 0;
127
128static struct display disp;
129static struct fb_info fb_info;
130
131
132
133
134
135
136static char cyberfb_name[16] = "Cybervision";
137
138
139
140
141
142
143static unsigned char Cyber_colour_table [256][3];
144static unsigned long CyberSize;
145static volatile unsigned char *CyberBase;
146static volatile unsigned char *CyberMem;
147static volatile unsigned char *CyberRegs;
148static unsigned long CyberMem_phys;
149static unsigned long CyberRegs_phys;
150
151
152
153
154
155static struct {
156 const char *name;
157 struct fb_var_screeninfo var;
158} cyberfb_predefined[] __initdata = {
159 { "640x480-8", {
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", {
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", {
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", {
181
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
189
190
191
192 { "800x600-8", {
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", {
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", {
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", {
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
224static int Cyberfb_inverse = 0;
225
226
227
228
229
230#define CYBER8_DEFMODE (0)
231#define CYBER16_DEFMODE (1)
232
233static struct fb_var_screeninfo cyberfb_default;
234static int cyberfb_usermode __initdata = 0;
235
236
237
238
239
240int cyberfb_setup(char *options);
241
242static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
243 struct fb_info *info);
244static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
245 struct fb_info *info);
246static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
247 struct fb_info *info);
248static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
249 struct fb_info *info);
250static int cyberfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
251 struct fb_info *info);
252
253
254
255
256
257int cyberfb_init(void);
258static int Cyberfb_switch(int con, struct fb_info *info);
259static int Cyberfb_updatevar(int con, struct fb_info *info);
260static void Cyberfb_blank(int blank, struct fb_info *info);
261
262
263
264
265
266#ifdef FBCON_HAS_CFB8
267static struct display_switch fbcon_cyber8;
268#endif
269
270
271
272
273
274static void Cyber_WaitQueue(u_short fifo);
275static void Cyber_WaitBlit(void);
276static 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);
279static 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
282static void Cyber_MoveCursor(u_short x, u_short y);
283#endif
284
285
286
287
288
289static int Cyber_init(void);
290static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
291 struct cyberfb_par *par);
292static int Cyber_decode_var(struct fb_var_screeninfo *var,
293 struct cyberfb_par *par);
294static int Cyber_encode_var(struct fb_var_screeninfo *var,
295 struct cyberfb_par *par);
296static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
297 u_int *transp, struct fb_info *info);
298static 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
303
304
305static void cyberfb_get_par(struct cyberfb_par *par);
306static void cyberfb_set_par(struct cyberfb_par *par);
307static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
308static void do_install_cmap(int con, struct fb_info *info);
309static void cyberfb_set_disp(int con, struct fb_info *info);
310static int get_video_mode(const char *name);
311
312
313static unsigned short cv64_compute_clock(unsigned long);
314static int cv_has_4mb (volatile unsigned char *);
315static void cv64_board_init (void);
316static void cv64_load_video_mode (struct fb_var_screeninfo *);
317
318
319
320
321
322
323
324
325
326
327
328
329static 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
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
344 cv64_board_init();
345#ifdef CYBERFBDEBUG
346 DPRINTK("Register state after initing board\n");
347 cv64_dump();
348#endif
349
350 DPRINTK("Clear framebuffer memory\n");
351 memset ((char *)CyberMem, 0, CyberSize);
352
353
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
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 );
383 Cyber_setcolreg (254, 0, 0, 0, 0, NULL );
384
385 DPRINTK("EXIT\n");
386 return 0;
387}
388
389
390
391
392
393
394
395static 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
428
429
430
431static 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
471
472
473
474static 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
518
519
520static 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
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
546 return (0);
547}
548
549
550
551
552
553
554
555static 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
561 if (regno > 255) {
562 DPRINTK("EXIT - Register # > 255\n");
563 return (1);
564 }
565
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
574 return (0);
575}
576
577
578
579
580
581
582
583
584void 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
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
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
617
618static 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
631
632static 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
645
646static 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
655
656 if (curx > destx) {
657 blitcmd |= 0x0020;
658 } else {
659 curx += (width - 1);
660 destx += (width - 1);
661 }
662
663 if (cury > desty) {
664 blitcmd |= 0x0080;
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
690
691static 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
720
721static 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
743
744
745
746
747
748
749static 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
761static 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
770static void cyber_set_video(struct fb_var_screeninfo *var)
771{
772
773
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
782static 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
804static 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
824
825
826static 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
845
846
847static 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;
858 } else {
859 *var = fb_display[con].var;
860 }
861
862 DPRINTK("EXIT\n");
863 return(error);
864}
865
866
867static 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;
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
914
915
916static 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
953
954
955static 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) {
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) {
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
977
978
979static 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) {
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) {
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
1004static 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
1013int __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
1052
1053
1054int __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
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
1120 MOD_INC_USE_COUNT;
1121 DPRINTK("EXIT\n");
1122 return 0;
1123 }
1124 return -ENXIO;
1125}
1126
1127
1128static int Cyberfb_switch(int con, struct fb_info *info)
1129{
1130 DPRINTK("ENTER\n");
1131
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
1140 do_install_cmap(con, info);
1141 DPRINTK("EXIT\n");
1142 return(0);
1143}
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153static int Cyberfb_updatevar(int con, struct fb_info *info)
1154{
1155 DPRINTK("Enter - Exit\n");
1156 return(0);
1157}
1158
1159
1160
1161
1162
1163
1164static 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
1183
1184
1185#ifdef FBCON_HAS_CFB8
1186static 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
1197static 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
1214static 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
1223static 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
1233static 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
1241static 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
1255MODULE_LICENSE("GPL");
1256
1257int init_module(void)
1258{
1259 return cyberfb_init();
1260}
1261
1262void cleanup_module(void)
1263{
1264
1265
1266 unregister_framebuffer(&fb_info);
1267
1268}
1269#endif
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279#define MAXPIXELCLOCK 135000000
1280
1281#ifdef CV_AGGRESSIVE_TIMING
1282long cv64_memclk = 55000000;
1283#else
1284long cv64_memclk = 50000000;
1285#endif
1286
1287
1288
1289static 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
1355unsigned char cvconscolors[16][3] = {
1356
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
1376
1377
1378inline 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
1387inline 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
1395inline 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
1403inline 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
1412
1413
1414inline void cv64_write_port (unsigned short bits,
1415 volatile unsigned char *base)
1416{
1417 volatile unsigned char *addr;
1418 static unsigned char cvportbits = 0;
1419 DPRINTK("ENTER\n");
1420
1421 addr = base + 0x40001;
1422 if (bits & 0x8000) {
1423 cvportbits |= bits & 0xff;
1424 DPRINTK("Set bits: %04x\n", bits);
1425 } else {
1426 bits = bits & 0xff;
1427 bits = (~bits) & 0xff;
1428 cvportbits &= bits;
1429 DPRINTK("Clear bits: %04x\n", bits);
1430 }
1431
1432 *addr = cvportbits;
1433 DPRINTK("EXIT\n");
1434}
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445inline 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
1459
1460
1461inline 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;
1472
1473 WSeq (regs, SEQ_ID_CLOCKING_MODE, r | toggle);
1474 DPRINTK("EXIT\n");
1475}
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487static unsigned short cv64_compute_clock(unsigned long freq)
1488{
1489 static unsigned char *mnr, *save;
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;
1502 d2 = 0x7fffffff;
1503
1504 while (*mnr) {
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;
1510 }
1511
1512 work_freq *= 0x3E8;
1513
1514 diff = abs(freq - work_freq);
1515
1516 if (d2 >= diff) {
1517 d2 = diff;
1518
1519 save = mnr;
1520 }
1521 mnr += 2;
1522 }
1523 erg = *((unsigned short *)save);
1524
1525 DPRINTK("EXIT\n");
1526 return (erg);
1527}
1528
1529static int cv_has_4mb (volatile unsigned char *fb)
1530{
1531 volatile unsigned long *tr, *tw;
1532 DPRINTK("ENTER\n");
1533
1534
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
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
1574static 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
1585
1586
1587 for (i = 0; i < 6; i++) {
1588 cv64_write_port (0xff, CyberBase);
1589 }
1590
1591 cv64_write_port (0x8004, CyberBase);
1592
1593
1594
1595
1596
1597 wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x10);
1598
1599 wb_64 (regs, SREG_OPTION_SELECT, 0x1);
1600
1601 wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x8);
1602
1603 wb_64 (regs, GREG_MISC_OUTPUT_W, 0x03);
1604
1605 WCrt (regs, CRT_ID_REGISTER_LOCK_1, 0x48);
1606
1607 WCrt (regs, CRT_ID_REGISTER_LOCK_2, 0xA5);
1608
1609
1610 test = RCrt (regs, CRT_ID_SYSTEM_CONFIG);
1611 test = test | 0x01;
1612 test = test & 0xEF;
1613 WCrt (regs, CRT_ID_SYSTEM_CONFIG, test);
1614
1615
1616
1617
1618
1619
1620 wb_64 (regs, ECR_ADV_FUNC_CNTL, 0x31);
1621
1622
1623
1624
1625
1626
1627 wb_64 (regs, GREG_MISC_OUTPUT_W, 0x23);
1628
1629
1630 WCrt (regs, CRT_ID_EXT_SYS_CNTL_4, 0x0);
1631
1632
1633
1634
1635 WSeq (regs, SEQ_ID_CLOCKING_MODE, 0x01);
1636
1637 WSeq (regs, SEQ_ID_MAP_MASK, 0x0F);
1638
1639 WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x0);
1640
1641 WSeq (regs, SEQ_ID_MEMORY_MODE, 0x2);
1642
1643 WSeq (regs, SEQ_ID_UNLOCK_EXT, 0x6);
1644
1645
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
1651 WSeq (regs, SEQ_ID_RAMDAC_CNTL, 0xC0);
1652
1653
1654 test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
1655 test = test & 0xDF;
1656
1657 if (cv64_memclk >= 55000000) {
1658 test |= 0x80;
1659 }
1660 WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
1661
1662
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
1670 if (RCrt (regs, CRT_ID_REVISION) == 0x10)
1671 WSeq (regs, SEQ_ID_MORE_MAGIC, test);
1672
1673
1674
1675
1676 WSeq (regs, SEQ_ID_DCLK_HI, 0x13);
1677 WSeq (regs, SEQ_ID_DCLK_LO, 0x41);
1678
1679
1680 test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
1681 test = test | 0x22;
1682 WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
1683
1684
1685 test = rb_64(regs, GREG_MISC_OUTPUT_R);
1686 test = test | 0x0C;
1687 wb_64 (regs, GREG_MISC_OUTPUT_W, test);
1688
1689
1690 WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, 0x2);
1691
1692
1693
1694 WCrt (regs, CRT_ID_HOR_TOTAL, 0x5F);
1695
1696 WCrt (regs, CRT_ID_HOR_DISP_ENA_END, 0x4F);
1697
1698 WCrt (regs, CRT_ID_START_HOR_BLANK, 0x50);
1699
1700 WCrt (regs, CRT_ID_END_HOR_BLANK, 0x82);
1701
1702 WCrt (regs, CRT_ID_START_HOR_RETR, 0x54);
1703
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);
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
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
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
1766 WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
1767
1768
1769 WCrt (regs, CRT_ID_LAW_CNTL, 0x13);
1770
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
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
1815
1816
1817
1818 WAttr (regs, 0x33, 0);
1819
1820
1821
1822
1823 gfx_on_off (0, regs);
1824
1825
1826 cvscreen (0, CyberBase);
1827
1828 DPRINTK("EXIT\n");
1829}
1830
1831static 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;
1855 CONSOLE = 0;
1856 fx = fy = 8;
1857
1858
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
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
1952
1953
1954#if 0
1955 freq_f = (1.0 / (float) video_mode->pixclock) * 1000000000;
1956 freq = ((long) freq_f) * 1000;
1957#else
1958
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
1968 WCrt (regs, CRT_ID_EXT_HOR_OVF,
1969 ((HT & 0x100) ? 0x01 : 0x00) |
1970 ((HDE & 0x100) ? 0x02 : 0x00) |
1971 ((HBS & 0x100) ? 0x04 : 0x00) |
1972
1973 ((HSS & 0x100) ? 0x10 : 0x00) |
1974
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
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
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
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:
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
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:
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
2189
2190 if (TEXT) {
2191
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
2207 gfx_on_off (0, (volatile unsigned char *) regs);
2208
2209
2210 cvscreen (0, CyberBase);
2211
2212DPRINTK("EXIT\n");
2213}
2214
2215void 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
2254void 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
2273
2274static void cv64_dump (void)
2275{
2276 volatile unsigned char *regs = CyberRegs;
2277 DPRINTK("ENTER\n");
2278
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