1 /*
2 * drivers/video/clgenfb.c - driver for Cirrus Logic chipsets
3 *
4 * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
5 *
6 * Contributors (thanks, all!)
7 *
8 * Jeff Rugen:
9 * Major contributions; Motorola PowerStack (PPC and PCI) support,
10 * GD54xx, 1280x1024 mode support, change MCLK based on VCLK.
11 *
12 * Geert Uytterhoeven:
13 * Excellent code review.
14 *
15 * Lars Hecking:
16 * Amiga updates and testing.
17 *
18 * Cliff Matthews <ctm@ardi.com>:
19 * 16bpp fix for CL-GD7548 (uses info from XFree86 4.2.0 source)
20 *
21 * Original clgenfb author: Frank Neumann
22 *
23 * Based on retz3fb.c and clgen.c:
24 * Copyright (C) 1997 Jes Sorensen
25 * Copyright (C) 1996 Frank Neumann
26 *
27 ***************************************************************
28 *
29 * Format this code with GNU indent '-kr -i8 -pcs' options.
30 *
31 * This file is subject to the terms and conditions of the GNU General Public
32 * License. See the file COPYING in the main directory of this archive
33 * for more details.
34 *
35 */
36
37 #define CLGEN_VERSION "1.9.9.1"
38
39 #include <linux/config.h>
40 #include <linux/module.h>
41 #include <linux/kernel.h>
42 #include <linux/errno.h>
43 #include <linux/string.h>
44 #include <linux/mm.h>
45 #include <linux/tty.h>
46 #include <linux/slab.h>
47 #include <linux/delay.h>
48 #include <linux/fb.h>
49 #include <linux/init.h>
50 #include <linux/selection.h>
51 #include <asm/pgtable.h>
52
53 #ifdef CONFIG_ZORRO
54 #include <linux/zorro.h>
55 #endif
56 #ifdef CONFIG_PCI
57 #include <linux/pci.h>
58 #endif
59 #ifdef CONFIG_AMIGA
60 #include <asm/amigahw.h>
61 #endif
62 #ifdef CONFIG_ALL_PPC
63 #include <asm/processor.h>
64 #define isPReP (_machine == _MACH_prep)
65 #else
66 #define isPReP 0
67 #endif
68
69 #include <video/fbcon.h>
70 #include <video/fbcon-mfb.h>
71 #include <video/fbcon-cfb8.h>
72 #include <video/fbcon-cfb16.h>
73 #include <video/fbcon-cfb24.h>
74 #include <video/fbcon-cfb32.h>
75
76 #include "clgenfb.h"
77 #include "vga.h"
78
79
80 /*****************************************************************
81 *
82 * debugging and utility macros
83 *
84 */
85
86 /* enable debug output? */
87 /* #define CLGEN_DEBUG 1 */
88
89 /* disable runtime assertions? */
90 /* #define CLGEN_NDEBUG */
91
92 /* debug output */
93 #ifdef CLGEN_DEBUG
94 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
95 #else
96 #define DPRINTK(fmt, args...)
97 #endif
98
99 /* debugging assertions */
100 #ifndef CLGEN_NDEBUG
101 #define assert(expr) \
102 if(!(expr)) { \
103 printk( "Assertion failed! %s,%s,%s,line=%d\n",\
104 #expr,__FILE__,__FUNCTION__,__LINE__); \
105 }
106 #else
107 #define assert(expr)
108 #endif
109
110 #ifdef TRUE
111 #undef TRUE
112 #endif
113 #ifdef FALSE
114 #undef FALSE
115 #endif
116 #define TRUE 1
117 #define FALSE 0
118
119 #define MB_ (1024*1024)
120 #define KB_ (1024)
121
122 #define MAX_NUM_BOARDS 7
123
124
125 /*****************************************************************
126 *
127 * chipset information
128 *
129 */
130
131 /* board types */
132 typedef enum {
133 BT_NONE = 0,
134 BT_SD64,
135 BT_PICCOLO,
136 BT_PICASSO,
137 BT_SPECTRUM,
138 BT_PICASSO4, /* GD5446 */
139 BT_ALPINE, /* GD543x/4x */
140 BT_GD5480,
141 BT_LAGUNA, /* GD546x */
142 } clgen_board_t;
143
144
145 /*
146 * per-board-type information, used for enumerating and abstracting
147 * chip-specific information
148 * NOTE: MUST be in the same order as clgen_board_t in order to
149 * use direct indexing on this array
150 * NOTE: '__initdata' cannot be used as some of this info
151 * is required at runtime. Maybe separate into an init-only and
152 * a run-time table?
153 */
154 static const struct clgen_board_info_rec {
155 clgen_board_t btype; /* chipset enum, not strictly necessary, as
156 * clgen_board_info[] is directly indexed
157 * by this value */
158 char *name; /* ASCII name of chipset */
159 long maxclock; /* maximum video clock */
160 unsigned init_sr07 : 1; /* init SR07 during init_vgachip() */
161 unsigned init_sr1f : 1; /* write SR1F during init_vgachip() */
162 unsigned scrn_start_bit19 : 1; /* construct bit 19 of screen start address */
163
164 /* initial SR07 value, then for each mode */
165 unsigned char sr07;
166 unsigned char sr07_1bpp;
167 unsigned char sr07_1bpp_mux;
168 unsigned char sr07_8bpp;
169 unsigned char sr07_8bpp_mux;
170
171 unsigned char sr1f; /* SR1F VGA initial register value */
172 } clgen_board_info[] = {
173 { BT_NONE, }, /* dummy record */
174 { BT_SD64,
175 "CL SD64",
176 140000, /* the SD64/P4 have a higher max. videoclock */
177 TRUE,
178 TRUE,
179 TRUE,
180 0xF0,
181 0xF0,
182 0, /* unused, does not multiplex */
183 0xF1,
184 0, /* unused, does not multiplex */
185 0x20 },
186 { BT_PICCOLO,
187 "CL Piccolo",
188 90000,
189 TRUE,
190 TRUE,
191 FALSE,
192 0x80,
193 0x80,
194 0, /* unused, does not multiplex */
195 0x81,
196 0, /* unused, does not multiplex */
197 0x22 },
198 { BT_PICASSO,
199 "CL Picasso",
200 90000,
201 TRUE,
202 TRUE,
203 FALSE,
204 0x20,
205 0x20,
206 0, /* unused, does not multiplex */
207 0x21,
208 0, /* unused, does not multiplex */
209 0x22 },
210 { BT_SPECTRUM,
211 "CL Spectrum",
212 90000,
213 TRUE,
214 TRUE,
215 FALSE,
216 0x80,
217 0x80,
218 0, /* unused, does not multiplex */
219 0x81,
220 0, /* unused, does not multiplex */
221 0x22 },
222 { BT_PICASSO4,
223 "CL Picasso4",
224 140000, /* the SD64/P4 have a higher max. videoclock */
225 TRUE,
226 FALSE,
227 TRUE,
228 0x20,
229 0x20,
230 0, /* unused, does not multiplex */
231 0x21,
232 0, /* unused, does not multiplex */
233 0 },
234 { BT_ALPINE,
235 "CL Alpine",
236 110000, /* 135100 for some, 85500 for others */
237 TRUE,
238 TRUE,
239 TRUE,
240 0xA0,
241 0xA1,
242 0xA7,
243 0xA1,
244 0xA7,
245 0x1C },
246 { BT_GD5480,
247 "CL GD5480",
248 90000,
249 TRUE,
250 TRUE,
251 TRUE,
252 0x10,
253 0x11,
254 0, /* unused, does not multiplex */
255 0x11,
256 0, /* unused, does not multiplex */
257 0x1C },
258 { BT_LAGUNA,
259 "CL Laguna",
260 135100,
261 FALSE,
262 FALSE,
263 TRUE,
264 0, /* unused */
265 0, /* unused */
266 0, /* unused */
267 0, /* unused */
268 0, /* unused */
269 0 }, /* unused */
270 };
271
272
273 #ifdef CONFIG_PCI
274 /* the list of PCI devices for which we probe, and the
275 * order in which we do it */
276 static const struct {
277 clgen_board_t btype;
278 const char *nameOverride; /* XXX unused... for now */
279 unsigned short device;
280 } clgen_pci_probe_list[] __initdata = {
281 { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5436 },
282 { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5434_8 },
283 { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5434_4 },
284 { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5430 }, /* GD-5440 has identical id */
285 { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_7543 },
286 { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_7548 },
287 { BT_GD5480, NULL, PCI_DEVICE_ID_CIRRUS_5480 }, /* MacPicasso probably */
288 { BT_PICASSO4, NULL, PCI_DEVICE_ID_CIRRUS_5446 }, /* Picasso 4 is a GD5446 */
289 { BT_LAGUNA, "CL Laguna", PCI_DEVICE_ID_CIRRUS_5462 },
290 { BT_LAGUNA, "CL Laguna 3D", PCI_DEVICE_ID_CIRRUS_5464 },
291 { BT_LAGUNA, "CL Laguna 3DA", PCI_DEVICE_ID_CIRRUS_5465 },
292 };
293 #endif /* CONFIG_PCI */
294
295
296 #ifdef CONFIG_ZORRO
297 static const struct {
298 clgen_board_t btype;
299 zorro_id id, id2;
300 unsigned long size;
301 } clgen_zorro_probe_list[] __initdata = {
302 { BT_SD64,
303 ZORRO_PROD_HELFRICH_SD64_RAM,
304 ZORRO_PROD_HELFRICH_SD64_REG,
305 0x400000 },
306 { BT_PICCOLO,
307 ZORRO_PROD_HELFRICH_PICCOLO_RAM,
308 ZORRO_PROD_HELFRICH_PICCOLO_REG,
309 0x200000 },
310 { BT_PICASSO,
311 ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
312 ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
313 0x200000 },
314 { BT_SPECTRUM,
315 ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
316 ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
317 0x200000 },
318 { BT_PICASSO4,
319 ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
320 0,
321 0x400000 },
322 };
323 #endif /* CONFIG_ZORRO */
324
325
326
327 struct clgenfb_par {
328 struct fb_var_screeninfo var;
329
330 __u32 line_length; /* in BYTES! */
331 __u32 visual;
332 __u32 type;
333
334 long freq;
335 long nom;
336 long den;
337 long div;
338 long multiplexing;
339 long mclk;
340 long divMCLK;
341
342 long HorizRes; /* The x resolution in pixel */
343 long HorizTotal;
344 long HorizDispEnd;
345 long HorizBlankStart;
346 long HorizBlankEnd;
347 long HorizSyncStart;
348 long HorizSyncEnd;
349
350 long VertRes; /* the physical y resolution in scanlines */
351 long VertTotal;
352 long VertDispEnd;
353 long VertSyncStart;
354 long VertSyncEnd;
355 long VertBlankStart;
356 long VertBlankEnd;
357 };
358
359
360
361 #ifdef CLGEN_DEBUG
362 typedef enum {
363 CRT,
364 SEQ
365 } clgen_dbg_reg_class_t;
366 #endif /* CLGEN_DEBUG */
367
368
369
370
371 /* info about board */
372 struct clgenfb_info {
373 struct fb_info_gen gen;
374
375 caddr_t fbmem;
376 caddr_t regs;
377 caddr_t mem;
378 unsigned long size;
379 clgen_board_t btype;
380 int smallboard;
381 unsigned char SFR; /* Shadow of special function register */
382
383 unsigned long fbmem_phys;
384 unsigned long fbregs_phys;
385
386 struct clgenfb_par currentmode;
387
388 struct { u8 red, green, blue, pad; } palette[256];
389
390 union {
391 #ifdef FBCON_HAS_CFB16
392 u16 cfb16[16];
393 #endif
394 #ifdef FBCON_HAS_CFB24
395 u32 cfb24[16];
396 #endif
397 #ifdef FBCON_HAS_CFB32
398 u32 cfb32[16];
399 #endif
400 } fbcon_cmap;
401
402 #ifdef CONFIG_ZORRO
403 unsigned long board_addr,
404 board_size;
405 #endif
406
407 #ifdef CONFIG_PCI
408 struct pci_dev *pdev;
409 #define IS_7548(x) ((x)->pdev->device == PCI_DEVICE_ID_CIRRUS_7548)
410 #else
411 #define IS_7548(x) (FALSE)
412 #endif
413 };
414
415
416
417
418 static struct display disp;
419
420 static struct clgenfb_info boards[MAX_NUM_BOARDS]; /* the boards */
421
422 static unsigned clgen_def_mode = 1;
423 static int noaccel = 0;
424
425
426
427 /*
428 * Predefined Video Modes
429 */
430
431 static const struct {
432 const char *name;
433 struct fb_var_screeninfo var;
434 } clgenfb_predefined[] __initdata =
435
436 {
437 {"Autodetect", /* autodetect mode */
438 {0}
439 },
440
441 {"640x480", /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
442 {
443 640, 480, 640, 480, 0, 0, 8, 0,
444 {0, 8, 0},
445 {0, 8, 0},
446 {0, 8, 0},
447 {0, 0, 0},
448 0, 0, -1, -1, FB_ACCEL_NONE, 40000, 48, 16, 32, 8, 96, 4,
449 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
450 }
451 },
452
453 {"800x600", /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */
454 {
455 800, 600, 800, 600, 0, 0, 8, 0,
456 {0, 8, 0},
457 {0, 8, 0},
458 {0, 8, 0},
459 {0, 0, 0},
460 0, 0, -1, -1, FB_ACCEL_NONE, 20000, 128, 16, 24, 2, 96, 6,
461 0, FB_VMODE_NONINTERLACED
462 }
463 },
464
465 /*
466 Modeline from XF86Config:
467 Mode "1024x768" 80 1024 1136 1340 1432 768 770 774 805
468 */
469 {"1024x768", /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
470 {
471 1024, 768, 1024, 768, 0, 0, 8, 0,
472 {0, 8, 0},
473 {0, 8, 0},
474 {0, 8, 0},
475 {0, 0, 0},
476 0, 0, -1, -1, FB_ACCEL_NONE, 12500, 144, 32, 30, 2, 192, 6,
477 0, FB_VMODE_NONINTERLACED
478 }
479 }
480 };
481
482 #define NUM_TOTAL_MODES ARRAY_SIZE(clgenfb_predefined)
483 static struct fb_var_screeninfo clgenfb_default;
484
485 /*
486 * Frame Buffer Name
487 */
488
489 static const char *clgenfb_name = "CLgen";
490
491 /****************************************************************************/
492 /**** BEGIN PROTOTYPES ******************************************************/
493
494
495 /*--- Interface used by the world ------------------------------------------*/
496 int clgenfb_init (void);
497 int clgenfb_setup (char *options);
498
499 static int clgenfb_open (struct fb_info *info, int user);
500 static int clgenfb_release (struct fb_info *info, int user);
501
502 /* function table of the above functions */
503 static struct fb_ops clgenfb_ops = {
504 owner: THIS_MODULE,
505 fb_open: clgenfb_open,
506 fb_release: clgenfb_release,
507 fb_get_fix: fbgen_get_fix,
508 fb_get_var: fbgen_get_var,
509 fb_set_var: fbgen_set_var,
510 fb_get_cmap: fbgen_get_cmap,
511 fb_set_cmap: fbgen_set_cmap,
512 fb_pan_display: fbgen_pan_display,
513 };
514
515 /*--- Hardware Specific Routines -------------------------------------------*/
516 static void clgen_detect (void);
517 static int clgen_encode_fix (struct fb_fix_screeninfo *fix, const void *par,
518 struct fb_info_gen *info);
519 static int clgen_decode_var (const struct fb_var_screeninfo *var, void *par,
520 struct fb_info_gen *info);
521 static int clgen_encode_var (struct fb_var_screeninfo *var, const void *par,
522 struct fb_info_gen *info);
523 static void clgen_get_par (void *par, struct fb_info_gen *info);
524 static void clgen_set_par (const void *par, struct fb_info_gen *info);
525 static int clgen_getcolreg (unsigned regno, unsigned *red, unsigned *green,
526 unsigned *blue, unsigned *transp,
527 struct fb_info *info);
528 static int clgen_setcolreg (unsigned regno, unsigned red, unsigned green,
529 unsigned blue, unsigned transp,
530 struct fb_info *info);
531 static int clgen_pan_display (const struct fb_var_screeninfo *var,
532 struct fb_info_gen *info);
533 static int clgen_blank (int blank_mode, struct fb_info_gen *info);
534
535 static void clgen_set_disp (const void *par, struct display *disp,
536 struct fb_info_gen *info);
537
538 /* function table of the above functions */
539 static struct fbgen_hwswitch clgen_hwswitch =
540 {
541 clgen_detect,
542 clgen_encode_fix,
543 clgen_decode_var,
544 clgen_encode_var,
545 clgen_get_par,
546 clgen_set_par,
547 clgen_getcolreg,
548 clgen_setcolreg,
549 clgen_pan_display,
550 clgen_blank,
551 clgen_set_disp
552 };
553
554 /* Text console acceleration */
555
556 #ifdef FBCON_HAS_CFB8
557 static void fbcon_clgen8_bmove (struct display *p, int sy, int sx,
558 int dy, int dx, int height, int width);
559 static void fbcon_clgen8_clear (struct vc_data *conp, struct display *p,
560 int sy, int sx, int height, int width);
561
562 static struct display_switch fbcon_clgen_8 = {
563 setup: fbcon_cfb8_setup,
564 bmove: fbcon_clgen8_bmove,
565 clear: fbcon_clgen8_clear,
566 putc: fbcon_cfb8_putc,
567 putcs: fbcon_cfb8_putcs,
568 revc: fbcon_cfb8_revc,
569 clear_margins: fbcon_cfb8_clear_margins,
570 fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
571 };
572 #endif
573 #ifdef FBCON_HAS_CFB16
574 static void fbcon_clgen16_bmove (struct display *p, int sy, int sx,
575 int dy, int dx, int height, int width);
576 static void fbcon_clgen16_clear (struct vc_data *conp, struct display *p,
577 int sy, int sx, int height, int width);
578 static struct display_switch fbcon_clgen_16 = {
579 setup: fbcon_cfb16_setup,
580 bmove: fbcon_clgen16_bmove,
581 clear: fbcon_clgen16_clear,
582 putc: fbcon_cfb16_putc,
583 putcs: fbcon_cfb16_putcs,
584 revc: fbcon_cfb16_revc,
585 clear_margins: fbcon_cfb16_clear_margins,
586 fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
587 };
588 #endif
589 #ifdef FBCON_HAS_CFB32
590 static void fbcon_clgen32_bmove (struct display *p, int sy, int sx,
591 int dy, int dx, int height, int width);
592 static void fbcon_clgen32_clear (struct vc_data *conp, struct display *p,
593 int sy, int sx, int height, int width);
594 static struct display_switch fbcon_clgen_32 = {
595 setup: fbcon_cfb32_setup,
596 bmove: fbcon_clgen32_bmove,
597 clear: fbcon_clgen32_clear,
598 putc: fbcon_cfb32_putc,
599 putcs: fbcon_cfb32_putcs,
600 revc: fbcon_cfb32_revc,
601 clear_margins: fbcon_cfb32_clear_margins,
602 fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
603 };
604 #endif
605
606
607
608 /*--- Internal routines ----------------------------------------------------*/
609 static void init_vgachip (struct clgenfb_info *fb_info);
610 static void switch_monitor (struct clgenfb_info *fb_info, int on);
611 static void WGen (const struct clgenfb_info *fb_info,
612 int regnum, unsigned char val);
613 static unsigned char RGen (const struct clgenfb_info *fb_info, int regnum);
614 static void AttrOn (const struct clgenfb_info *fb_info);
615 static void WHDR (const struct clgenfb_info *fb_info, unsigned char val);
616 static void WSFR (struct clgenfb_info *fb_info, unsigned char val);
617 static void WSFR2 (struct clgenfb_info *fb_info, unsigned char val);
618 static void WClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char red,
619 unsigned char green,
620 unsigned char blue);
621 #if 0
622 static void RClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char *red,
623 unsigned char *green,
624 unsigned char *blue);
625 #endif
626 static void clgen_WaitBLT (caddr_t regbase);
627 static void clgen_BitBLT (caddr_t regbase, u_short curx, u_short cury,
628 u_short destx, u_short desty,
629 u_short width, u_short height,
630 u_short line_length);
631 static void clgen_RectFill (struct clgenfb_info *fb_info, u_short x, u_short y,
632 u_short width, u_short height,
633 u_char color, u_short line_length);
634
635 static void bestclock (long freq, long *best,
636 long *nom, long *den,
637 long *div, long maxfreq);
638
639 #ifdef CLGEN_DEBUG
640 static void clgen_dump (void);
641 static void clgen_dbg_reg_dump (caddr_t regbase);
642 static void clgen_dbg_print_regs (caddr_t regbase, clgen_dbg_reg_class_t reg_class,...);
643 static void clgen_dbg_print_byte (const char *name, unsigned char val);
644 #endif /* CLGEN_DEBUG */
645
646 /*** END PROTOTYPES ********************************************************/
647 /*****************************************************************************/
648 /*** BEGIN Interface Used by the World ***************************************/
649
650 static int opencount = 0;
651
652 /*--- Open /dev/fbx ---------------------------------------------------------*/
clgenfb_open(struct fb_info * info,int user)653 static int clgenfb_open (struct fb_info *info, int user)
654 {
655 if (opencount++ == 0)
656 switch_monitor ((struct clgenfb_info *) info, 1);
657 return 0;
658 }
659
660 /*--- Close /dev/fbx --------------------------------------------------------*/
clgenfb_release(struct fb_info * info,int user)661 static int clgenfb_release (struct fb_info *info, int user)
662 {
663 if (--opencount == 0)
664 switch_monitor ((struct clgenfb_info *) info, 0);
665 return 0;
666 }
667
668 /**** END Interface used by the World *************************************/
669 /****************************************************************************/
670 /**** BEGIN Hardware specific Routines **************************************/
671
clgen_detect(void)672 static void clgen_detect (void)
673 {
674 DPRINTK ("ENTER\n");
675 DPRINTK ("EXIT\n");
676 }
677
clgen_encode_fix(struct fb_fix_screeninfo * fix,const void * par,struct fb_info_gen * info)678 static int clgen_encode_fix (struct fb_fix_screeninfo *fix, const void *par,
679 struct fb_info_gen *info)
680 {
681 struct clgenfb_par *_par = (struct clgenfb_par *) par;
682 struct clgenfb_info *_info = (struct clgenfb_info *) info;
683
684 DPRINTK ("ENTER\n");
685
686 memset (fix, 0, sizeof (struct fb_fix_screeninfo));
687 strcpy (fix->id, clgenfb_name);
688
689 if (_info->btype == BT_GD5480) {
690 /* Select proper byte-swapping aperture */
691 switch (_par->var.bits_per_pixel) {
692 case 1:
693 case 8:
694 fix->smem_start = _info->fbmem_phys;
695 break;
696 case 16:
697 fix->smem_start = _info->fbmem_phys + 1 * MB_;
698 break;
699 case 24:
700 case 32:
701 fix->smem_start = _info->fbmem_phys + 2 * MB_;
702 break;
703 }
704 } else {
705 fix->smem_start = _info->fbmem_phys;
706 }
707
708 /* monochrome: only 1 memory plane */
709 /* 8 bit and above: Use whole memory area */
710 fix->smem_len = _par->var.bits_per_pixel == 1 ? _info->size / 4
711 : _info->size;
712 fix->type = _par->type;
713 fix->type_aux = 0;
714 fix->visual = _par->visual;
715 fix->xpanstep = 1;
716 fix->ypanstep = 1;
717 fix->ywrapstep = 0;
718 fix->line_length = _par->line_length;
719
720 /* FIXME: map region at 0xB8000 if available, fill in here */
721 fix->mmio_start = 0;
722 fix->mmio_len = 0;
723 fix->accel = FB_ACCEL_NONE;
724
725 DPRINTK ("EXIT\n");
726 return 0;
727 }
728
729
730
731 /* Get a good MCLK value */
clgen_get_mclk(long freq,int bpp,long * div)732 static long clgen_get_mclk (long freq, int bpp, long *div)
733 {
734 long mclk;
735
736 assert (div != NULL);
737
738 /* Calculate MCLK, in case VCLK is high enough to require > 50MHz.
739 * Assume a 64-bit data path for now. The formula is:
740 * ((B * PCLK * 2)/W) * 1.2
741 * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */
742 mclk = ((bpp / 8) * freq * 2) / 4;
743 mclk = (mclk * 12) / 10;
744 if (mclk < 50000)
745 mclk = 50000;
746 DPRINTK ("Use MCLK of %ld kHz\n", mclk);
747
748 /* Calculate value for SR1F. Multiply by 2 so we can round up. */
749 mclk = ((mclk * 16) / 14318);
750 mclk = (mclk + 1) / 2;
751 DPRINTK ("Set SR1F[5:0] to 0x%lx\n", mclk);
752
753 /* Determine if we should use MCLK instead of VCLK, and if so, what we
754 * should divide it by to get VCLK */
755 switch (freq) {
756 case 24751 ... 25249:
757 *div = 2;
758 DPRINTK ("Using VCLK = MCLK/2\n");
759 break;
760 case 49501 ... 50499:
761 *div = 1;
762 DPRINTK ("Using VCLK = MCLK\n");
763 break;
764 default:
765 *div = 0;
766 break;
767 }
768
769 return mclk;
770 }
771
clgen_decode_var(const struct fb_var_screeninfo * var,void * par,struct fb_info_gen * info)772 static int clgen_decode_var (const struct fb_var_screeninfo *var, void *par,
773 struct fb_info_gen *info)
774 {
775 long freq;
776 long maxclock;
777 int xres, hfront, hsync, hback;
778 int yres, vfront, vsync, vback;
779 int nom, den; /* translyting from pixels->bytes */
780 int i;
781 static struct {
782 int xres, yres;
783 } modes[] = { {
784 1600, 1280
785 }, {
786 1280, 1024
787 }, {
788 1024, 768
789 },
790 {
791 800, 600
792 }, {
793 640, 480
794 }, {
795 -1, -1
796 }
797 };
798
799 struct clgenfb_par *_par = (struct clgenfb_par *) par;
800 struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
801
802 assert (var != NULL);
803 assert (par != NULL);
804 assert (info != NULL);
805
806 DPRINTK ("ENTER\n");
807
808 DPRINTK ("Requested: %dx%dx%d\n", var->xres, var->yres, var->bits_per_pixel);
809 DPRINTK (" virtual: %dx%d\n", var->xres_virtual, var->yres_virtual);
810 DPRINTK (" offset: (%d,%d)\n", var->xoffset, var->yoffset);
811 DPRINTK ("grayscale: %d\n", var->grayscale);
812
813 memset (par, 0, sizeof (struct clgenfb_par));
814
815 _par->var = *var;
816
817 switch (var->bits_per_pixel) {
818 case 1:
819 nom = 4;
820 den = 8;
821 break; /* 8 pixel per byte, only 1/4th of mem usable */
822 case 2 ... 8:
823 _par->var.bits_per_pixel = 8;
824 nom = 1;
825 den = 1;
826 break; /* 1 pixel == 1 byte */
827 case 9 ... 16:
828 _par->var.bits_per_pixel = 16;
829 nom = 2;
830 den = 1;
831 break; /* 2 bytes per pixel */
832 case 17 ... 24:
833 _par->var.bits_per_pixel = 24;
834 nom = 3;
835 den = 1;
836 break; /* 3 bytes per pixel */
837 case 25 ... 32:
838 _par->var.bits_per_pixel = 32;
839 nom = 4;
840 den = 1;
841 break; /* 4 bytes per pixel */
842 default:
843 printk ("clgen: mode %dx%dx%d rejected...color depth not supported.\n",
844 var->xres, var->yres, var->bits_per_pixel);
845 DPRINTK ("EXIT - EINVAL error\n");
846 return -EINVAL;
847 }
848
849 if (_par->var.xres * nom / den * _par->var.yres > fb_info->size) {
850 printk ("clgen: mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
851 var->xres, var->yres, var->bits_per_pixel);
852 DPRINTK ("EXIT - EINVAL error\n");
853 return -EINVAL;
854 }
855 /* use highest possible virtual resolution */
856 if (_par->var.xres_virtual == -1 &&
857 _par->var.yres_virtual == -1) {
858 printk ("clgen: using maximum available virtual resolution\n");
859 for (i = 0; modes[i].xres != -1; i++) {
860 if (modes[i].xres * nom / den * modes[i].yres < fb_info->size / 2)
861 break;
862 }
863 if (modes[i].xres == -1) {
864 printk ("clgen: could not find a virtual resolution that fits into video memory!!\n");
865 DPRINTK ("EXIT - EINVAL error\n");
866 return -EINVAL;
867 }
868 _par->var.xres_virtual = modes[i].xres;
869 _par->var.yres_virtual = modes[i].yres;
870
871 printk ("clgen: virtual resolution set to maximum of %dx%d\n",
872 _par->var.xres_virtual, _par->var.yres_virtual);
873 } else if (_par->var.xres_virtual == -1) {
874 /* FIXME: maximize X virtual resolution only */
875 } else if (_par->var.yres_virtual == -1) {
876 /* FIXME: maximize Y virtual resolution only */
877 }
878 if (_par->var.xoffset < 0)
879 _par->var.xoffset = 0;
880 if (_par->var.yoffset < 0)
881 _par->var.yoffset = 0;
882
883 /* truncate xoffset and yoffset to maximum if too high */
884 if (_par->var.xoffset > _par->var.xres_virtual - _par->var.xres)
885 _par->var.xoffset = _par->var.xres_virtual - _par->var.xres - 1;
886
887 if (_par->var.yoffset > _par->var.yres_virtual - _par->var.yres)
888 _par->var.yoffset = _par->var.yres_virtual - _par->var.yres - 1;
889
890 switch (_par->var.bits_per_pixel) {
891 case 1:
892 _par->line_length = _par->var.xres_virtual / 8;
893 _par->visual = FB_VISUAL_MONO10;
894 break;
895
896 case 8:
897 _par->line_length = _par->var.xres_virtual;
898 _par->visual = FB_VISUAL_PSEUDOCOLOR;
899 _par->var.red.offset = 0;
900 _par->var.red.length = 6;
901 _par->var.green.offset = 0;
902 _par->var.green.length = 6;
903 _par->var.blue.offset = 0;
904 _par->var.blue.length = 6;
905 break;
906
907 case 16:
908 _par->line_length = _par->var.xres_virtual * 2;
909 _par->visual = FB_VISUAL_DIRECTCOLOR;
910 if(isPReP) {
911 _par->var.red.offset = 2;
912 _par->var.green.offset = -3;
913 _par->var.blue.offset = 8;
914 } else {
915 _par->var.red.offset = 10;
916 _par->var.green.offset = 5;
917 _par->var.blue.offset = 0;
918 }
919 _par->var.red.length = 5;
920 _par->var.green.length = 5;
921 _par->var.blue.length = 5;
922 break;
923
924 case 24:
925 _par->line_length = _par->var.xres_virtual * 3;
926 _par->visual = FB_VISUAL_DIRECTCOLOR;
927 if(isPReP) {
928 _par->var.red.offset = 8;
929 _par->var.green.offset = 16;
930 _par->var.blue.offset = 24;
931 } else {
932 _par->var.red.offset = 16;
933 _par->var.green.offset = 8;
934 _par->var.blue.offset = 0;
935 }
936 _par->var.red.length = 8;
937 _par->var.green.length = 8;
938 _par->var.blue.length = 8;
939 break;
940
941 case 32:
942 _par->line_length = _par->var.xres_virtual * 4;
943 _par->visual = FB_VISUAL_DIRECTCOLOR;
944 if(isPReP) {
945 _par->var.red.offset = 8;
946 _par->var.green.offset = 16;
947 _par->var.blue.offset = 24;
948 } else {
949 _par->var.red.offset = 16;
950 _par->var.green.offset = 8;
951 _par->var.blue.offset = 0;
952 }
953 _par->var.red.length = 8;
954 _par->var.green.length = 8;
955 _par->var.blue.length = 8;
956 break;
957
958 default:
959 DPRINTK("Unsupported bpp size: %d\n", _par->var.bits_per_pixel);
960 assert (FALSE);
961 /* should never occur */
962 break;
963 }
964
965 _par->var.red.msb_right =
966 _par->var.green.msb_right =
967 _par->var.blue.msb_right =
968 _par->var.transp.offset =
969 _par->var.transp.length =
970 _par->var.transp.msb_right = 0;
971
972 _par->type = FB_TYPE_PACKED_PIXELS;
973
974 /* convert from ps to kHz */
975 freq = 1000000000 / var->pixclock;
976
977 DPRINTK ("desired pixclock: %ld kHz\n", freq);
978
979 if (IS_7548(fb_info))
980 maxclock = 80100;
981 else
982 maxclock = clgen_board_info[fb_info->btype].maxclock;
983 _par->multiplexing = 0;
984
985 /* If the frequency is greater than we can support, we might be able
986 * to use multiplexing for the video mode */
987 if (freq > maxclock) {
988 switch (fb_info->btype) {
989 case BT_ALPINE:
990 case BT_GD5480:
991 _par->multiplexing = 1;
992 break;
993
994 default:
995 printk (KERN_WARNING "clgen: ERROR: Frequency greater than maxclock (%ld kHz)\n", maxclock);
996 DPRINTK ("EXIT - return -EINVAL\n");
997 return -EINVAL;
998 }
999 }
1000 #if 0
1001 /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
1002 * the VCLK is double the pixel clock. */
1003 switch (var->bits_per_pixel) {
1004 case 16:
1005 case 32:
1006 if (_par->HorizRes <= 800)
1007 freq /= 2; /* Xbh has this type of clock for 32-bit */
1008 break;
1009 }
1010 #endif
1011
1012 bestclock (freq, &_par->freq, &_par->nom, &_par->den, &_par->div,
1013 maxclock);
1014 _par->mclk = clgen_get_mclk (freq, _par->var.bits_per_pixel, &_par->divMCLK);
1015
1016 xres = _par->var.xres;
1017 hfront = _par->var.right_margin;
1018 hsync = _par->var.hsync_len;
1019 hback = _par->var.left_margin;
1020
1021 yres = _par->var.yres;
1022 vfront = _par->var.lower_margin;
1023 vsync = _par->var.vsync_len;
1024 vback = _par->var.upper_margin;
1025
1026 if (_par->var.vmode & FB_VMODE_DOUBLE) {
1027 yres *= 2;
1028 vfront *= 2;
1029 vsync *= 2;
1030 vback *= 2;
1031 } else if (_par->var.vmode & FB_VMODE_INTERLACED) {
1032 yres = (yres + 1) / 2;
1033 vfront = (vfront + 1) / 2;
1034 vsync = (vsync + 1) / 2;
1035 vback = (vback + 1) / 2;
1036 }
1037 _par->HorizRes = xres;
1038 _par->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5;
1039 _par->HorizDispEnd = xres / 8 - 1;
1040 _par->HorizBlankStart = xres / 8;
1041 _par->HorizBlankEnd = _par->HorizTotal + 5; /* does not count with "-5" */
1042 _par->HorizSyncStart = (xres + hfront) / 8 + 1;
1043 _par->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1;
1044
1045 _par->VertRes = yres;
1046 _par->VertTotal = yres + vfront + vsync + vback - 2;
1047 _par->VertDispEnd = yres - 1;
1048 _par->VertBlankStart = yres;
1049 _par->VertBlankEnd = _par->VertTotal;
1050 _par->VertSyncStart = yres + vfront - 1;
1051 _par->VertSyncEnd = yres + vfront + vsync - 1;
1052
1053 if (_par->VertRes >= 1024) {
1054 _par->VertTotal /= 2;
1055 _par->VertSyncStart /= 2;
1056 _par->VertSyncEnd /= 2;
1057 _par->VertDispEnd /= 2;
1058 }
1059 if (_par->multiplexing) {
1060 _par->HorizTotal /= 2;
1061 _par->HorizSyncStart /= 2;
1062 _par->HorizSyncEnd /= 2;
1063 _par->HorizDispEnd /= 2;
1064 }
1065 if (_par->VertRes >= 1280) {
1066 printk (KERN_WARNING "clgen: ERROR: VerticalTotal >= 1280; special treatment required! (TODO)\n");
1067 DPRINTK ("EXIT - EINVAL error\n");
1068 return -EINVAL;
1069 }
1070 DPRINTK ("EXIT\n");
1071 return 0;
1072 }
1073
1074
clgen_encode_var(struct fb_var_screeninfo * var,const void * par,struct fb_info_gen * info)1075 static int clgen_encode_var (struct fb_var_screeninfo *var, const void *par,
1076 struct fb_info_gen *info)
1077 {
1078 DPRINTK ("ENTER\n");
1079
1080 *var = ((struct clgenfb_par *) par)->var;
1081
1082 DPRINTK ("EXIT\n");
1083 return 0;
1084 }
1085
1086 /* get current video mode */
clgen_get_par(void * par,struct fb_info_gen * info)1087 static void clgen_get_par (void *par, struct fb_info_gen *info)
1088 {
1089 struct clgenfb_par *_par = (struct clgenfb_par *) par;
1090 struct clgenfb_info *_info = (struct clgenfb_info *) info;
1091
1092 DPRINTK ("ENTER\n");
1093
1094 *_par = _info->currentmode;
1095
1096 DPRINTK ("EXIT\n");
1097 }
1098
clgen_set_mclk(const struct clgenfb_info * fb_info,int val,int div)1099 static void clgen_set_mclk (const struct clgenfb_info *fb_info, int val, int div)
1100 {
1101 assert (fb_info != NULL);
1102
1103 if (div == 2) {
1104 /* VCLK = MCLK/2 */
1105 unsigned char old = vga_rseq (fb_info->regs, CL_SEQR1E);
1106 vga_wseq (fb_info->regs, CL_SEQR1E, old | 0x1);
1107 vga_wseq (fb_info->regs, CL_SEQR1F, 0x40 | (val & 0x3f));
1108 } else if (div == 1) {
1109 /* VCLK = MCLK */
1110 unsigned char old = vga_rseq (fb_info->regs, CL_SEQR1E);
1111 vga_wseq (fb_info->regs, CL_SEQR1E, old & ~0x1);
1112 vga_wseq (fb_info->regs, CL_SEQR1F, 0x40 | (val & 0x3f));
1113 } else {
1114 vga_wseq (fb_info->regs, CL_SEQR1F, val & 0x3f);
1115 }
1116 }
1117
1118 /*************************************************************************
1119 clgen_set_par()
1120
1121 actually writes the values for a new video mode into the hardware,
1122 **************************************************************************/
clgen_set_par(const void * par,struct fb_info_gen * info)1123 static void clgen_set_par (const void *par, struct fb_info_gen *info)
1124 {
1125 unsigned char tmp;
1126 int offset = 0;
1127 struct clgenfb_par *_par = (struct clgenfb_par *) par;
1128 struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
1129 const struct clgen_board_info_rec *bi;
1130
1131 DPRINTK ("ENTER\n");
1132 DPRINTK ("Requested mode: %dx%dx%d\n",
1133 _par->var.xres, _par->var.yres, _par->var.bits_per_pixel);
1134 DPRINTK ("pixclock: %d\n", _par->var.pixclock);
1135
1136 bi = &clgen_board_info[fb_info->btype];
1137
1138
1139 /* unlock register VGA_CRTC_H_TOTAL..CRT7 */
1140 vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */
1141
1142 /* if debugging is enabled, all parameters get output before writing */
1143 DPRINTK ("CRT0: %ld\n", _par->HorizTotal);
1144 vga_wcrt (fb_info->regs, VGA_CRTC_H_TOTAL, _par->HorizTotal);
1145
1146 DPRINTK ("CRT1: %ld\n", _par->HorizDispEnd);
1147 vga_wcrt (fb_info->regs, VGA_CRTC_H_DISP, _par->HorizDispEnd);
1148
1149 DPRINTK ("CRT2: %ld\n", _par->HorizBlankStart);
1150 vga_wcrt (fb_info->regs, VGA_CRTC_H_BLANK_START, _par->HorizBlankStart);
1151
1152 DPRINTK ("CRT3: 128+%ld\n", _par->HorizBlankEnd % 32); /* + 128: Compatible read */
1153 vga_wcrt (fb_info->regs, VGA_CRTC_H_BLANK_END, 128 + (_par->HorizBlankEnd % 32));
1154
1155 DPRINTK ("CRT4: %ld\n", _par->HorizSyncStart);
1156 vga_wcrt (fb_info->regs, VGA_CRTC_H_SYNC_START, _par->HorizSyncStart);
1157
1158 tmp = _par->HorizSyncEnd % 32;
1159 if (_par->HorizBlankEnd & 32)
1160 tmp += 128;
1161 DPRINTK ("CRT5: %d\n", tmp);
1162 vga_wcrt (fb_info->regs, VGA_CRTC_H_SYNC_END, tmp);
1163
1164 DPRINTK ("CRT6: %ld\n", _par->VertTotal & 0xff);
1165 vga_wcrt (fb_info->regs, VGA_CRTC_V_TOTAL, (_par->VertTotal & 0xff));
1166
1167 tmp = 16; /* LineCompare bit #9 */
1168 if (_par->VertTotal & 256)
1169 tmp |= 1;
1170 if (_par->VertDispEnd & 256)
1171 tmp |= 2;
1172 if (_par->VertSyncStart & 256)
1173 tmp |= 4;
1174 if (_par->VertBlankStart & 256)
1175 tmp |= 8;
1176 if (_par->VertTotal & 512)
1177 tmp |= 32;
1178 if (_par->VertDispEnd & 512)
1179 tmp |= 64;
1180 if (_par->VertSyncStart & 512)
1181 tmp |= 128;
1182 DPRINTK ("CRT7: %d\n", tmp);
1183 vga_wcrt (fb_info->regs, VGA_CRTC_OVERFLOW, tmp);
1184
1185 tmp = 0x40; /* LineCompare bit #8 */
1186 if (_par->VertBlankStart & 512)
1187 tmp |= 0x20;
1188 if (_par->var.vmode & FB_VMODE_DOUBLE)
1189 tmp |= 0x80;
1190 DPRINTK ("CRT9: %d\n", tmp);
1191 vga_wcrt (fb_info->regs, VGA_CRTC_MAX_SCAN, tmp);
1192
1193 DPRINTK ("CRT10: %ld\n", _par->VertSyncStart & 0xff);
1194 vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_START, (_par->VertSyncStart & 0xff));
1195
1196 DPRINTK ("CRT11: 64+32+%ld\n", _par->VertSyncEnd % 16);
1197 vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, (_par->VertSyncEnd % 16 + 64 + 32));
1198
1199 DPRINTK ("CRT12: %ld\n", _par->VertDispEnd & 0xff);
1200 vga_wcrt (fb_info->regs, VGA_CRTC_V_DISP_END, (_par->VertDispEnd & 0xff));
1201
1202 DPRINTK ("CRT15: %ld\n", _par->VertBlankStart & 0xff);
1203 vga_wcrt (fb_info->regs, VGA_CRTC_V_BLANK_START, (_par->VertBlankStart & 0xff));
1204
1205 DPRINTK ("CRT16: %ld\n", _par->VertBlankEnd & 0xff);
1206 vga_wcrt (fb_info->regs, VGA_CRTC_V_BLANK_END, (_par->VertBlankEnd & 0xff));
1207
1208 DPRINTK ("CRT18: 0xff\n");
1209 vga_wcrt (fb_info->regs, VGA_CRTC_LINE_COMPARE, 0xff);
1210
1211 tmp = 0;
1212 if (_par->var.vmode & FB_VMODE_INTERLACED)
1213 tmp |= 1;
1214 if (_par->HorizBlankEnd & 64)
1215 tmp |= 16;
1216 if (_par->HorizBlankEnd & 128)
1217 tmp |= 32;
1218 if (_par->VertBlankEnd & 256)
1219 tmp |= 64;
1220 if (_par->VertBlankEnd & 512)
1221 tmp |= 128;
1222
1223 DPRINTK ("CRT1a: %d\n", tmp);
1224 vga_wcrt (fb_info->regs, CL_CRT1A, tmp);
1225
1226 /* set VCLK0 */
1227 /* hardware RefClock: 14.31818 MHz */
1228 /* formula: VClk = (OSC * N) / (D * (1+P)) */
1229 /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
1230
1231 vga_wseq (fb_info->regs, CL_SEQRB, _par->nom);
1232 tmp = _par->den << 1;
1233 if (_par->div != 0)
1234 tmp |= 1;
1235
1236 if ((fb_info->btype == BT_SD64) ||
1237 (fb_info->btype == BT_ALPINE) ||
1238 (fb_info->btype == BT_GD5480))
1239 tmp |= 0x80; /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
1240
1241 DPRINTK ("CL_SEQR1B: %ld\n", (long) tmp);
1242 vga_wseq (fb_info->regs, CL_SEQR1B, tmp);
1243
1244 if (_par->VertRes >= 1024)
1245 /* 1280x1024 */
1246 vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc7);
1247 else
1248 /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
1249 * address wrap, no compat. */
1250 vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc3);
1251
1252 /* HAEH? vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, 0x20); * previously: 0x00 unlock VGA_CRTC_H_TOTAL..CRT7 */
1253
1254 /* don't know if it would hurt to also program this if no interlaced */
1255 /* mode is used, but I feel better this way.. :-) */
1256 if (_par->var.vmode & FB_VMODE_INTERLACED)
1257 vga_wcrt (fb_info->regs, VGA_CRTC_REGS, _par->HorizTotal / 2);
1258 else
1259 vga_wcrt (fb_info->regs, VGA_CRTC_REGS, 0x00); /* interlace control */
1260
1261 vga_wseq (fb_info->regs, VGA_SEQ_CHARACTER_MAP, 0);
1262
1263 /* adjust horizontal/vertical sync type (low/high) */
1264 tmp = 0x03; /* enable display memory & CRTC I/O address for color mode */
1265 if (_par->var.sync & FB_SYNC_HOR_HIGH_ACT)
1266 tmp |= 0x40;
1267 if (_par->var.sync & FB_SYNC_VERT_HIGH_ACT)
1268 tmp |= 0x80;
1269 WGen (fb_info, VGA_MIS_W, tmp);
1270
1271 vga_wcrt (fb_info->regs, VGA_CRTC_PRESET_ROW, 0); /* Screen A Preset Row-Scan register */
1272 vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_START, 0); /* text cursor on and start line */
1273 vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_END, 31); /* text cursor end line */
1274
1275 /******************************************************
1276 *
1277 * 1 bpp
1278 *
1279 */
1280
1281 /* programming for different color depths */
1282 if (_par->var.bits_per_pixel == 1) {
1283 DPRINTK ("clgen: preparing for 1 bit deep display\n");
1284 vga_wgfx (fb_info->regs, VGA_GFX_MODE, 0); /* mode register */
1285
1286 /* SR07 */
1287 switch (fb_info->btype) {
1288 case BT_SD64:
1289 case BT_PICCOLO:
1290 case BT_PICASSO:
1291 case BT_SPECTRUM:
1292 case BT_PICASSO4:
1293 case BT_ALPINE:
1294 case BT_GD5480:
1295 DPRINTK (" (for GD54xx)\n");
1296 vga_wseq (fb_info->regs, CL_SEQR7,
1297 _par->multiplexing ?
1298 bi->sr07_1bpp_mux : bi->sr07_1bpp);
1299 break;
1300
1301 case BT_LAGUNA:
1302 DPRINTK (" (for GD546x)\n");
1303 vga_wseq (fb_info->regs, CL_SEQR7,
1304 vga_rseq (fb_info->regs, CL_SEQR7) & ~0x01);
1305 break;
1306
1307 default:
1308 printk (KERN_WARNING "clgen: unknown Board\n");
1309 break;
1310 }
1311
1312 /* Extended Sequencer Mode */
1313 switch (fb_info->btype) {
1314 case BT_SD64:
1315 /* setting the SEQRF on SD64 is not necessary (only during init) */
1316 DPRINTK ("(for SD64)\n");
1317 vga_wseq (fb_info->regs, CL_SEQR1F, 0x1a); /* MCLK select */
1318 break;
1319
1320 case BT_PICCOLO:
1321 DPRINTK ("(for Piccolo)\n");
1322 /* ### ueberall 0x22? */
1323 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ##vorher 1c MCLK select */
1324 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
1325 break;
1326
1327 case BT_PICASSO:
1328 DPRINTK ("(for Picasso)\n");
1329 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ##vorher 22 MCLK select */
1330 vga_wseq (fb_info->regs, CL_SEQRF, 0xd0); /* ## vorher d0 avoid FIFO underruns..? */
1331 break;
1332
1333 case BT_SPECTRUM:
1334 DPRINTK ("(for Spectrum)\n");
1335 /* ### ueberall 0x22? */
1336 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ##vorher 1c MCLK select */
1337 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* evtl d0? avoid FIFO underruns..? */
1338 break;
1339
1340 case BT_PICASSO4:
1341 case BT_ALPINE:
1342 case BT_GD5480:
1343 case BT_LAGUNA:
1344 DPRINTK (" (for GD54xx)\n");
1345 /* do nothing */
1346 break;
1347
1348 default:
1349 printk (KERN_WARNING "clgen: unknown Board\n");
1350 break;
1351 }
1352
1353 WGen (fb_info, VGA_PEL_MSK, 0x01); /* pixel mask: pass-through for first plane */
1354 if (_par->multiplexing)
1355 WHDR (fb_info, 0x4a); /* hidden dac reg: 1280x1024 */
1356 else
1357 WHDR (fb_info, 0); /* hidden dac: nothing */
1358 vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x06); /* memory mode: odd/even, ext. memory */
1359 vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0x01); /* plane mask: only write to first plane */
1360 offset = _par->var.xres_virtual / 16;
1361 }
1362
1363 /******************************************************
1364 *
1365 * 8 bpp
1366 *
1367 */
1368
1369 else if (_par->var.bits_per_pixel == 8) {
1370 DPRINTK ("clgen: preparing for 8 bit deep display\n");
1371 switch (fb_info->btype) {
1372 case BT_SD64:
1373 case BT_PICCOLO:
1374 case BT_PICASSO:
1375 case BT_SPECTRUM:
1376 case BT_PICASSO4:
1377 case BT_ALPINE:
1378 case BT_GD5480:
1379 DPRINTK (" (for GD54xx)\n");
1380 vga_wseq (fb_info->regs, CL_SEQR7,
1381 _par->multiplexing ?
1382 bi->sr07_8bpp_mux : bi->sr07_8bpp);
1383 break;
1384
1385 case BT_LAGUNA:
1386 DPRINTK (" (for GD546x)\n");
1387 vga_wseq (fb_info->regs, CL_SEQR7,
1388 vga_rseq (fb_info->regs, CL_SEQR7) | 0x01);
1389 break;
1390
1391 default:
1392 printk (KERN_WARNING "clgen: unknown Board\n");
1393 break;
1394 }
1395
1396 switch (fb_info->btype) {
1397 case BT_SD64:
1398 vga_wseq (fb_info->regs, CL_SEQR1F, 0x1d); /* MCLK select */
1399 break;
1400
1401 case BT_PICCOLO:
1402 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */
1403 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1404 break;
1405
1406 case BT_PICASSO:
1407 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */
1408 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1409 break;
1410
1411 case BT_SPECTRUM:
1412 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */
1413 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1414 break;
1415
1416 case BT_PICASSO4:
1417 #ifdef CONFIG_ZORRO
1418 vga_wseq (fb_info->regs, CL_SEQRF, 0xb8); /* ### INCOMPLETE!! */
1419 #endif
1420 /* vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c); */
1421 break;
1422
1423 case BT_ALPINE:
1424 DPRINTK (" (for GD543x)\n");
1425 clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK);
1426 /* We already set SRF and SR1F */
1427 break;
1428
1429 case BT_GD5480:
1430 case BT_LAGUNA:
1431 DPRINTK (" (for GD54xx)\n");
1432 /* do nothing */
1433 break;
1434
1435 default:
1436 printk (KERN_WARNING "clgen: unknown Board\n");
1437 break;
1438 }
1439
1440 vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64); /* mode register: 256 color mode */
1441 WGen (fb_info, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */
1442 if (_par->multiplexing)
1443 WHDR (fb_info, 0x4a); /* hidden dac reg: 1280x1024 */
1444 else
1445 WHDR (fb_info, 0); /* hidden dac: nothing */
1446 vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */
1447 vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */
1448 offset = _par->var.xres_virtual / 8;
1449 }
1450
1451 /******************************************************
1452 *
1453 * 16 bpp
1454 *
1455 */
1456
1457 else if (_par->var.bits_per_pixel == 16) {
1458 DPRINTK ("clgen: preparing for 16 bit deep display\n");
1459 switch (fb_info->btype) {
1460 case BT_SD64:
1461 vga_wseq (fb_info->regs, CL_SEQR7, 0xf7); /* Extended Sequencer Mode: 256c col. mode */
1462 vga_wseq (fb_info->regs, CL_SEQR1F, 0x1e); /* MCLK select */
1463 break;
1464
1465 case BT_PICCOLO:
1466 vga_wseq (fb_info->regs, CL_SEQR7, 0x87);
1467 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1468 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */
1469 break;
1470
1471 case BT_PICASSO:
1472 vga_wseq (fb_info->regs, CL_SEQR7, 0x27);
1473 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1474 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */
1475 break;
1476
1477 case BT_SPECTRUM:
1478 vga_wseq (fb_info->regs, CL_SEQR7, 0x87);
1479 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1480 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */
1481 break;
1482
1483 case BT_PICASSO4:
1484 vga_wseq (fb_info->regs, CL_SEQR7, 0x27);
1485 /* vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c); */
1486 break;
1487
1488 case BT_ALPINE:
1489 DPRINTK (" (for GD543x)\n");
1490 if (IS_7548(fb_info)) {
1491 vga_wseq (fb_info->regs, CL_SEQR7,
1492 (vga_rseq (fb_info->regs, CL_SEQR7) & 0xE0)
1493 | 0x17);
1494 WHDR (fb_info, 0xC1);
1495 } else {
1496 if (_par->HorizRes >= 1024)
1497 vga_wseq (fb_info->regs, CL_SEQR7, 0xa7);
1498 else
1499 vga_wseq (fb_info->regs, CL_SEQR7, 0xa3);
1500 }
1501 clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK);
1502 break;
1503
1504 case BT_GD5480:
1505 DPRINTK (" (for GD5480)\n");
1506 vga_wseq (fb_info->regs, CL_SEQR7, 0x17);
1507 /* We already set SRF and SR1F */
1508 break;
1509
1510 case BT_LAGUNA:
1511 DPRINTK (" (for GD546x)\n");
1512 vga_wseq (fb_info->regs, CL_SEQR7,
1513 vga_rseq (fb_info->regs, CL_SEQR7) & ~0x01);
1514 break;
1515
1516 default:
1517 printk (KERN_WARNING "CLGEN: unknown Board\n");
1518 break;
1519 }
1520
1521 vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64); /* mode register: 256 color mode */
1522 WGen (fb_info, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */
1523 #ifdef CONFIG_PCI
1524 WHDR (fb_info, 0xc0); /* Copy Xbh */
1525 #elif defined(CONFIG_ZORRO)
1526 /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
1527 WHDR (fb_info, 0xa0); /* hidden dac reg: nothing special */
1528 #endif
1529 vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */
1530 vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */
1531 offset = _par->var.xres_virtual / 4;
1532 }
1533
1534 /******************************************************
1535 *
1536 * 32 bpp
1537 *
1538 */
1539
1540 else if (_par->var.bits_per_pixel == 32) {
1541 DPRINTK ("clgen: preparing for 24/32 bit deep display\n");
1542 switch (fb_info->btype) {
1543 case BT_SD64:
1544 vga_wseq (fb_info->regs, CL_SEQR7, 0xf9); /* Extended Sequencer Mode: 256c col. mode */
1545 vga_wseq (fb_info->regs, CL_SEQR1F, 0x1e); /* MCLK select */
1546 break;
1547
1548 case BT_PICCOLO:
1549 vga_wseq (fb_info->regs, CL_SEQR7, 0x85);
1550 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1551 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */
1552 break;
1553
1554 case BT_PICASSO:
1555 vga_wseq (fb_info->regs, CL_SEQR7, 0x25);
1556 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1557 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */
1558 break;
1559
1560 case BT_SPECTRUM:
1561 vga_wseq (fb_info->regs, CL_SEQR7, 0x85);
1562 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1563 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */
1564 break;
1565
1566 case BT_PICASSO4:
1567 vga_wseq (fb_info->regs, CL_SEQR7, 0x25);
1568 /* vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c); */
1569 break;
1570
1571 case BT_ALPINE:
1572 DPRINTK (" (for GD543x)\n");
1573 vga_wseq (fb_info->regs, CL_SEQR7, 0xa9);
1574 clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK);
1575 break;
1576
1577 case BT_GD5480:
1578 DPRINTK (" (for GD5480)\n");
1579 vga_wseq (fb_info->regs, CL_SEQR7, 0x19);
1580 /* We already set SRF and SR1F */
1581 break;
1582
1583 case BT_LAGUNA:
1584 DPRINTK (" (for GD546x)\n");
1585 vga_wseq (fb_info->regs, CL_SEQR7,
1586 vga_rseq (fb_info->regs, CL_SEQR7) & ~0x01);
1587 break;
1588
1589 default:
1590 printk (KERN_WARNING "clgen: unknown Board\n");
1591 break;
1592 }
1593
1594 vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64); /* mode register: 256 color mode */
1595 WGen (fb_info, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */
1596 WHDR (fb_info, 0xc5); /* hidden dac reg: 8-8-8 mode (24 or 32) */
1597 vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */
1598 vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */
1599 offset = _par->var.xres_virtual / 4;
1600 }
1601
1602 /******************************************************
1603 *
1604 * unknown/unsupported bpp
1605 *
1606 */
1607
1608 else {
1609 printk (KERN_ERR "clgen: What's this?? requested color depth == %d.\n",
1610 _par->var.bits_per_pixel);
1611 }
1612
1613 if (IS_7548(fb_info)) {
1614 vga_wseq (fb_info->regs, CL_SEQR2D,
1615 vga_rseq (fb_info->regs, CL_SEQR2D) | 0xC0);
1616 }
1617
1618 vga_wcrt (fb_info->regs, VGA_CRTC_OFFSET, offset & 0xff);
1619 tmp = 0x22;
1620 if (offset & 0x100)
1621 tmp |= 0x10; /* offset overflow bit */
1622
1623 vga_wcrt (fb_info->regs, CL_CRT1B, tmp); /* screen start addr #16-18, fastpagemode cycles */
1624
1625 if (fb_info->btype == BT_SD64 ||
1626 fb_info->btype == BT_PICASSO4 ||
1627 fb_info->btype == BT_ALPINE ||
1628 fb_info->btype == BT_GD5480)
1629 vga_wcrt (fb_info->regs, CL_CRT1D, 0x00); /* screen start address bit 19 */
1630
1631 vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_HI, 0); /* text cursor location high */
1632 vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_LO, 0); /* text cursor location low */
1633 vga_wcrt (fb_info->regs, VGA_CRTC_UNDERLINE, 0); /* underline row scanline = at very bottom */
1634
1635 vga_wattr (fb_info->regs, VGA_ATC_MODE, 1); /* controller mode */
1636 vga_wattr (fb_info->regs, VGA_ATC_OVERSCAN, 0); /* overscan (border) color */
1637 vga_wattr (fb_info->regs, VGA_ATC_PLANE_ENABLE, 15); /* color plane enable */
1638 vga_wattr (fb_info->regs, CL_AR33, 0); /* pixel panning */
1639 vga_wattr (fb_info->regs, VGA_ATC_COLOR_PAGE, 0); /* color select */
1640
1641 /* [ EGS: SetOffset(); ] */
1642 /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
1643 AttrOn (fb_info);
1644
1645 vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, 0); /* set/reset register */
1646 vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, 0); /* set/reset enable */
1647 vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_VALUE, 0); /* color compare */
1648 vga_wgfx (fb_info->regs, VGA_GFX_DATA_ROTATE, 0); /* data rotate */
1649 vga_wgfx (fb_info->regs, VGA_GFX_PLANE_READ, 0); /* read map select */
1650 vga_wgfx (fb_info->regs, VGA_GFX_MISC, 1); /* miscellaneous register */
1651 vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_MASK, 15); /* color don't care */
1652 vga_wgfx (fb_info->regs, VGA_GFX_BIT_MASK, 255); /* bit mask */
1653
1654 vga_wseq (fb_info->regs, CL_SEQR12, 0x0); /* graphics cursor attributes: nothing special */
1655
1656 /* finally, turn on everything - turn off "FullBandwidth" bit */
1657 /* also, set "DotClock%2" bit where requested */
1658 tmp = 0x01;
1659
1660 /*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
1661 if (var->vmode & FB_VMODE_CLOCK_HALVE)
1662 tmp |= 0x08;
1663 */
1664
1665 vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, tmp);
1666 DPRINTK ("CL_SEQR1: %d\n", tmp);
1667
1668 fb_info->currentmode = *_par;
1669
1670 DPRINTK ("virtual offset: (%d,%d)\n", _par->var.xoffset, _par->var.yoffset);
1671 /* pan to requested offset */
1672 clgen_pan_display (&fb_info->currentmode.var, (struct fb_info_gen *) fb_info);
1673
1674 #ifdef CLGEN_DEBUG
1675 clgen_dump ();
1676 #endif
1677
1678 DPRINTK ("EXIT\n");
1679 return;
1680 }
1681
1682
clgen_getcolreg(unsigned regno,unsigned * red,unsigned * green,unsigned * blue,unsigned * transp,struct fb_info * info)1683 static int clgen_getcolreg (unsigned regno, unsigned *red, unsigned *green,
1684 unsigned *blue, unsigned *transp,
1685 struct fb_info *info)
1686 {
1687 struct clgenfb_info *fb_info = (struct clgenfb_info *)info;
1688
1689 if (regno > 255)
1690 return 1;
1691 *red = fb_info->palette[regno].red;
1692 *green = fb_info->palette[regno].green;
1693 *blue = fb_info->palette[regno].blue;
1694 *transp = 0;
1695 return 0;
1696 }
1697
1698
clgen_setcolreg(unsigned regno,unsigned red,unsigned green,unsigned blue,unsigned transp,struct fb_info * info)1699 static int clgen_setcolreg (unsigned regno, unsigned red, unsigned green,
1700 unsigned blue, unsigned transp,
1701 struct fb_info *info)
1702 {
1703 struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
1704
1705 if (regno > 255)
1706 return -EINVAL;
1707
1708 #ifdef FBCON_HAS_CFB8
1709 switch (fb_info->currentmode.var.bits_per_pixel) {
1710 case 8:
1711 /* "transparent" stuff is completely ignored. */
1712 WClut (fb_info, regno, red >> 10, green >> 10, blue >> 10);
1713 break;
1714 default:
1715 /* do nothing */
1716 break;
1717 }
1718 #endif /* FBCON_HAS_CFB8 */
1719
1720 fb_info->palette[regno].red = red;
1721 fb_info->palette[regno].green = green;
1722 fb_info->palette[regno].blue = blue;
1723
1724 if (regno >= 16)
1725 return 0;
1726
1727 switch (fb_info->currentmode.var.bits_per_pixel) {
1728
1729 #ifdef FBCON_HAS_CFB16
1730 case 16:
1731 assert (regno < 16);
1732 if(isPReP) {
1733 fb_info->fbcon_cmap.cfb16[regno] =
1734 ((red & 0xf800) >> 9) |
1735 ((green & 0xf800) >> 14) |
1736 ((green & 0xf800) << 2) |
1737 ((blue & 0xf800) >> 3);
1738 } else {
1739 fb_info->fbcon_cmap.cfb16[regno] =
1740 ((red & 0xf800) >> 1) |
1741 ((green & 0xf800) >> 6) |
1742 ((blue & 0xf800) >> 11);
1743 }
1744 #endif /* FBCON_HAS_CFB16 */
1745
1746 #ifdef FBCON_HAS_CFB24
1747 case 24:
1748 assert (regno < 16);
1749 fb_info->fbcon_cmap.cfb24[regno] =
1750 (red << fb_info->currentmode.var.red.offset) |
1751 (green << fb_info->currentmode.var.green.offset) |
1752 (blue << fb_info->currentmode.var.blue.offset);
1753 break;
1754 #endif /* FBCON_HAS_CFB24 */
1755
1756 #ifdef FBCON_HAS_CFB32
1757 case 32:
1758 assert (regno < 16);
1759 if(isPReP) {
1760 fb_info->fbcon_cmap.cfb32[regno] =
1761 ((red & 0xff00)) |
1762 ((green & 0xff00) << 8) |
1763 ((blue & 0xff00) << 16);
1764 } else {
1765 fb_info->fbcon_cmap.cfb32[regno] =
1766 ((red & 0xff00) << 8) |
1767 ((green & 0xff00)) |
1768 ((blue & 0xff00) >> 8);
1769 }
1770 break;
1771 #endif /* FBCON_HAS_CFB32 */
1772 default:
1773 /* do nothing */
1774 break;
1775 }
1776
1777 return 0;
1778 }
1779
1780 /*************************************************************************
1781 clgen_pan_display()
1782
1783 performs display panning - provided hardware permits this
1784 **************************************************************************/
clgen_pan_display(const struct fb_var_screeninfo * var,struct fb_info_gen * info)1785 static int clgen_pan_display (const struct fb_var_screeninfo *var,
1786 struct fb_info_gen *info)
1787 {
1788 int xoffset = 0;
1789 int yoffset = 0;
1790 unsigned long base;
1791 unsigned char tmp = 0, tmp2 = 0, xpix;
1792 struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
1793
1794 DPRINTK ("ENTER\n");
1795
1796 /* no range checks for xoffset and yoffset, */
1797 /* as fbgen_pan_display has already done this */
1798
1799 fb_info->currentmode.var.xoffset = var->xoffset;
1800 fb_info->currentmode.var.yoffset = var->yoffset;
1801
1802 xoffset = var->xoffset * fb_info->currentmode.var.bits_per_pixel / 8;
1803 yoffset = var->yoffset;
1804
1805 base = yoffset * fb_info->currentmode.line_length + xoffset;
1806
1807 if (fb_info->currentmode.var.bits_per_pixel == 1) {
1808 /* base is already correct */
1809 xpix = (unsigned char) (var->xoffset % 8);
1810 } else {
1811 base /= 4;
1812 xpix = (unsigned char) ((xoffset % 4) * 2);
1813 }
1814
1815 /* lower 8 + 8 bits of screen start address */
1816 vga_wcrt (fb_info->regs, VGA_CRTC_START_LO, (unsigned char) (base & 0xff));
1817 vga_wcrt (fb_info->regs, VGA_CRTC_START_HI, (unsigned char) (base >> 8));
1818
1819 /* construct bits 16, 17 and 18 of screen start address */
1820 if (base & 0x10000)
1821 tmp |= 0x01;
1822 if (base & 0x20000)
1823 tmp |= 0x04;
1824 if (base & 0x40000)
1825 tmp |= 0x08;
1826
1827 tmp2 = (vga_rcrt (fb_info->regs, CL_CRT1B) & 0xf2) | tmp; /* 0xf2 is %11110010, exclude tmp bits */
1828 vga_wcrt (fb_info->regs, CL_CRT1B, tmp2);
1829
1830 /* construct bit 19 of screen start address */
1831 if (clgen_board_info[fb_info->btype].scrn_start_bit19) {
1832 tmp2 = 0;
1833 if (base & 0x80000)
1834 tmp2 = 0x80;
1835 vga_wcrt (fb_info->regs, CL_CRT1D, tmp2);
1836 }
1837
1838 /* write pixel panning value to AR33; this does not quite work in 8bpp */
1839 /* ### Piccolo..? Will this work? */
1840 if (fb_info->currentmode.var.bits_per_pixel == 1)
1841 vga_wattr (fb_info->regs, CL_AR33, xpix);
1842
1843
1844 DPRINTK ("EXIT\n");
1845 return (0);
1846 }
1847
1848
clgen_blank(int blank_mode,struct fb_info_gen * info)1849 static int clgen_blank (int blank_mode, struct fb_info_gen *info)
1850 {
1851 /*
1852 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
1853 * then the caller blanks by setting the CLUT (Color Look Up Table) to all
1854 * black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
1855 * to e.g. a video mode which doesn't support it. Implements VESA suspend
1856 * and powerdown modes on hardware that supports disabling hsync/vsync:
1857 * blank_mode == 2: suspend vsync
1858 * blank_mode == 3: suspend hsync
1859 * blank_mode == 4: powerdown
1860 */
1861 unsigned char val;
1862 static int current_mode = 0;
1863 struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
1864
1865 DPRINTK ("ENTER, blank mode = %d\n", blank_mode);
1866
1867 if (current_mode == blank_mode) {
1868 DPRINTK ("EXIT, returning 0\n");
1869 return 0;
1870 }
1871
1872 /* Undo current */
1873 switch (current_mode) {
1874 case 0: /* Screen is normal */
1875 break;
1876 case 1: /* Screen is blanked */
1877 val = vga_rseq (fb_info->regs, VGA_SEQ_CLOCK_MODE);
1878 vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, val & 0xdf); /* clear "FullBandwidth" bit */
1879 break;
1880 case 2: /* vsync suspended */
1881 case 3: /* hsync suspended */
1882 case 4: /* sceen is powered down */
1883 vga_wgfx (fb_info->regs, CL_GRE, 0x00);
1884 break;
1885 default:
1886 DPRINTK ("EXIT, returning 1\n");
1887 return 1;
1888 }
1889
1890 /* set new */
1891 switch (blank_mode) {
1892 case 0: /* Unblank screen */
1893 break;
1894 case 1: /* Blank screen */
1895 val = vga_rseq (fb_info->regs, VGA_SEQ_CLOCK_MODE);
1896 vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, val | 0x20); /* set "FullBandwidth" bit */
1897 break;
1898 case 2: /* suspend vsync */
1899 vga_wgfx (fb_info->regs, CL_GRE, 0x04);
1900 break;
1901 case 3: /* suspend hsync */
1902 vga_wgfx (fb_info->regs, CL_GRE, 0x02);
1903 break;
1904 case 4: /* powerdown */
1905 vga_wgfx (fb_info->regs, CL_GRE, 0x06);
1906 break;
1907 default:
1908 DPRINTK ("EXIT, returning 1\n");
1909 return 1;
1910 }
1911
1912 current_mode = blank_mode;
1913 DPRINTK ("EXIT, returning 0\n");
1914 return 0;
1915 }
1916 /**** END Hardware specific Routines **************************************/
1917 /****************************************************************************/
1918 /**** BEGIN Internal Routines ***********************************************/
1919
init_vgachip(struct clgenfb_info * fb_info)1920 static void __init init_vgachip (struct clgenfb_info *fb_info)
1921 {
1922 const struct clgen_board_info_rec *bi;
1923
1924 DPRINTK ("ENTER\n");
1925
1926 assert (fb_info != NULL);
1927
1928 bi = &clgen_board_info[fb_info->btype];
1929
1930 /* reset board globally */
1931 switch (fb_info->btype) {
1932 case BT_PICCOLO:
1933 WSFR (fb_info, 0x01);
1934 udelay (500);
1935 WSFR (fb_info, 0x51);
1936 udelay (500);
1937 break;
1938 case BT_PICASSO:
1939 WSFR2 (fb_info, 0xff);
1940 udelay (500);
1941 break;
1942 case BT_SD64:
1943 case BT_SPECTRUM:
1944 WSFR (fb_info, 0x1f);
1945 udelay (500);
1946 WSFR (fb_info, 0x4f);
1947 udelay (500);
1948 break;
1949 case BT_PICASSO4:
1950 vga_wcrt (fb_info->regs, CL_CRT51, 0x00); /* disable flickerfixer */
1951 mdelay (100);
1952 vga_wgfx (fb_info->regs, CL_GR2F, 0x00); /* from Klaus' NetBSD driver: */
1953 vga_wgfx (fb_info->regs, CL_GR33, 0x00); /* put blitter into 542x compat */
1954 vga_wgfx (fb_info->regs, CL_GR31, 0x00); /* mode */
1955 break;
1956
1957 case BT_GD5480:
1958 vga_wgfx (fb_info->regs, CL_GR2F, 0x00); /* from Klaus' NetBSD driver: */
1959 break;
1960
1961 case BT_ALPINE:
1962 /* Nothing to do to reset the board. */
1963 break;
1964
1965 default:
1966 printk (KERN_ERR "clgen: Warning: Unknown board type\n");
1967 break;
1968 }
1969
1970 assert (fb_info->size > 0); /* make sure RAM size set by this point */
1971
1972 /* assume it's a "large memory" board (2/4 MB) */
1973 fb_info->smallboard = FALSE;
1974
1975 /* the P4 is not fully initialized here; I rely on it having been */
1976 /* inited under AmigaOS already, which seems to work just fine */
1977 /* (Klaus advised to do it this way) */
1978
1979 if (fb_info->btype != BT_PICASSO4) {
1980 WGen (fb_info, CL_VSSM, 0x10); /* EGS: 0x16 */
1981 WGen (fb_info, CL_POS102, 0x01);
1982 WGen (fb_info, CL_VSSM, 0x08); /* EGS: 0x0e */
1983
1984 if (fb_info->btype != BT_SD64)
1985 WGen (fb_info, CL_VSSM2, 0x01);
1986
1987 vga_wseq (fb_info->regs, CL_SEQR0, 0x03); /* reset sequencer logic */
1988
1989 vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, 0x21); /* FullBandwidth (video off) and 8/9 dot clock */
1990 WGen (fb_info, VGA_MIS_W, 0xc1); /* polarity (-/-), disable access to display memory, VGA_CRTC_START_HI base address: color */
1991
1992 /* vga_wgfx (fb_info->regs, CL_GRA, 0xce); "magic cookie" - doesn't make any sense to me.. */
1993 vga_wseq (fb_info->regs, CL_SEQR6, 0x12); /* unlock all extension registers */
1994
1995 vga_wgfx (fb_info->regs, CL_GR31, 0x04); /* reset blitter */
1996
1997 switch (fb_info->btype) {
1998 case BT_GD5480:
1999 vga_wseq (fb_info->regs, CL_SEQRF, 0x98);
2000 break;
2001 case BT_ALPINE:
2002 break;
2003 case BT_SD64:
2004 vga_wseq (fb_info->regs, CL_SEQRF, 0xb8);
2005 break;
2006 default:
2007 vga_wseq (fb_info->regs, CL_SEQR16, 0x0f);
2008 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);
2009 break;
2010 }
2011 }
2012 vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: nothing */
2013 vga_wseq (fb_info->regs, VGA_SEQ_CHARACTER_MAP, 0x00); /* character map select: doesn't even matter in gx mode */
2014 vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0e); /* memory mode: chain-4, no odd/even, ext. memory */
2015
2016 /* controller-internal base address of video memory */
2017 if (bi->init_sr07)
2018 vga_wseq (fb_info->regs, CL_SEQR7, bi->sr07);
2019
2020 /* vga_wseq (fb_info->regs, CL_SEQR8, 0x00); *//* EEPROM control: shouldn't be necessary to write to this at all.. */
2021
2022 vga_wseq (fb_info->regs, CL_SEQR10, 0x00); /* graphics cursor X position (incomplete; position gives rem. 3 bits */
2023 vga_wseq (fb_info->regs, CL_SEQR11, 0x00); /* graphics cursor Y position (..."... ) */
2024 vga_wseq (fb_info->regs, CL_SEQR12, 0x00); /* graphics cursor attributes */
2025 vga_wseq (fb_info->regs, CL_SEQR13, 0x00); /* graphics cursor pattern address */
2026
2027 /* writing these on a P4 might give problems.. */
2028 if (fb_info->btype != BT_PICASSO4) {
2029 vga_wseq (fb_info->regs, CL_SEQR17, 0x00); /* configuration readback and ext. color */
2030 vga_wseq (fb_info->regs, CL_SEQR18, 0x02); /* signature generator */
2031 }
2032
2033 /* MCLK select etc. */
2034 if (bi->init_sr1f)
2035 vga_wseq (fb_info->regs, CL_SEQR1F, bi->sr1f);
2036
2037 vga_wcrt (fb_info->regs, VGA_CRTC_PRESET_ROW, 0x00); /* Screen A preset row scan: none */
2038 vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_START, 0x20); /* Text cursor start: disable text cursor */
2039 vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_END, 0x00); /* Text cursor end: - */
2040 vga_wcrt (fb_info->regs, VGA_CRTC_START_HI, 0x00); /* Screen start address high: 0 */
2041 vga_wcrt (fb_info->regs, VGA_CRTC_START_LO, 0x00); /* Screen start address low: 0 */
2042 vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_HI, 0x00); /* text cursor location high: 0 */
2043 vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_LO, 0x00); /* text cursor location low: 0 */
2044
2045 vga_wcrt (fb_info->regs, VGA_CRTC_UNDERLINE, 0x00); /* Underline Row scanline: - */
2046 vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc3); /* mode control: timing enable, byte mode, no compat modes */
2047 vga_wcrt (fb_info->regs, VGA_CRTC_LINE_COMPARE, 0x00); /* Line Compare: not needed */
2048 /* ### add 0x40 for text modes with > 30 MHz pixclock */
2049 vga_wcrt (fb_info->regs, CL_CRT1B, 0x02); /* ext. display controls: ext.adr. wrap */
2050
2051 vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, 0x00); /* Set/Reset registes: - */
2052 vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, 0x00); /* Set/Reset enable: - */
2053 vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_VALUE, 0x00); /* Color Compare: - */
2054 vga_wgfx (fb_info->regs, VGA_GFX_DATA_ROTATE, 0x00); /* Data Rotate: - */
2055 vga_wgfx (fb_info->regs, VGA_GFX_PLANE_READ, 0x00); /* Read Map Select: - */
2056 vga_wgfx (fb_info->regs, VGA_GFX_MODE, 0x00); /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
2057 vga_wgfx (fb_info->regs, VGA_GFX_MISC, 0x01); /* Miscellaneous: memory map base address, graphics mode */
2058 vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_MASK, 0x0f); /* Color Don't care: involve all planes */
2059 vga_wgfx (fb_info->regs, VGA_GFX_BIT_MASK, 0xff); /* Bit Mask: no mask at all */
2060 if (fb_info->btype == BT_ALPINE)
2061 vga_wgfx (fb_info->regs, CL_GRB, 0x20); /* (5434 can't have bit 3 set for bitblt) */
2062 else
2063 vga_wgfx (fb_info->regs, CL_GRB, 0x28); /* Graphics controller mode extensions: finer granularity, 8byte data latches */
2064
2065 vga_wgfx (fb_info->regs, CL_GRC, 0xff); /* Color Key compare: - */
2066 vga_wgfx (fb_info->regs, CL_GRD, 0x00); /* Color Key compare mask: - */
2067 vga_wgfx (fb_info->regs, CL_GRE, 0x00); /* Miscellaneous control: - */
2068 /* vga_wgfx (fb_info->regs, CL_GR10, 0x00); *//* Background color byte 1: - */
2069 /* vga_wgfx (fb_info->regs, CL_GR11, 0x00); */
2070
2071 vga_wattr (fb_info->regs, VGA_ATC_PALETTE0, 0x00); /* Attribute Controller palette registers: "identity mapping" */
2072 vga_wattr (fb_info->regs, VGA_ATC_PALETTE1, 0x01);
2073 vga_wattr (fb_info->regs, VGA_ATC_PALETTE2, 0x02);
2074 vga_wattr (fb_info->regs, VGA_ATC_PALETTE3, 0x03);
2075 vga_wattr (fb_info->regs, VGA_ATC_PALETTE4, 0x04);
2076 vga_wattr (fb_info->regs, VGA_ATC_PALETTE5, 0x05);
2077 vga_wattr (fb_info->regs, VGA_ATC_PALETTE6, 0x06);
2078 vga_wattr (fb_info->regs, VGA_ATC_PALETTE7, 0x07);
2079 vga_wattr (fb_info->regs, VGA_ATC_PALETTE8, 0x08);
2080 vga_wattr (fb_info->regs, VGA_ATC_PALETTE9, 0x09);
2081 vga_wattr (fb_info->regs, VGA_ATC_PALETTEA, 0x0a);
2082 vga_wattr (fb_info->regs, VGA_ATC_PALETTEB, 0x0b);
2083 vga_wattr (fb_info->regs, VGA_ATC_PALETTEC, 0x0c);
2084 vga_wattr (fb_info->regs, VGA_ATC_PALETTED, 0x0d);
2085 vga_wattr (fb_info->regs, VGA_ATC_PALETTEE, 0x0e);
2086 vga_wattr (fb_info->regs, VGA_ATC_PALETTEF, 0x0f);
2087
2088 vga_wattr (fb_info->regs, VGA_ATC_MODE, 0x01); /* Attribute Controller mode: graphics mode */
2089 vga_wattr (fb_info->regs, VGA_ATC_OVERSCAN, 0x00); /* Overscan color reg.: reg. 0 */
2090 vga_wattr (fb_info->regs, VGA_ATC_PLANE_ENABLE, 0x0f); /* Color Plane enable: Enable all 4 planes */
2091 /* ### vga_wattr (fb_info->regs, CL_AR33, 0x00); * Pixel Panning: - */
2092 vga_wattr (fb_info->regs, VGA_ATC_COLOR_PAGE, 0x00); /* Color Select: - */
2093
2094 WGen (fb_info, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
2095
2096 if (fb_info->btype != BT_ALPINE && fb_info->btype != BT_GD5480)
2097 WGen (fb_info, VGA_MIS_W, 0xc3); /* polarity (-/-), enable display mem, VGA_CRTC_START_HI i/o base = color */
2098
2099 vga_wgfx (fb_info->regs, CL_GR31, 0x04); /* BLT Start/status: Blitter reset */
2100 vga_wgfx (fb_info->regs, CL_GR31, 0x00); /* - " - : "end-of-reset" */
2101
2102 /* CLUT setup */
2103 WClut (fb_info, 0, 0x00, 0x00, 0x00); /* background: black */
2104 WClut (fb_info, 1, 0x3f, 0x3f, 0x3f); /* foreground: white */
2105 WClut (fb_info, 2, 0x00, 0x20, 0x00);
2106 WClut (fb_info, 3, 0x00, 0x20, 0x20);
2107 WClut (fb_info, 4, 0x20, 0x00, 0x00);
2108 WClut (fb_info, 5, 0x20, 0x00, 0x20);
2109 WClut (fb_info, 6, 0x20, 0x10, 0x00);
2110 WClut (fb_info, 7, 0x20, 0x20, 0x20);
2111 WClut (fb_info, 8, 0x10, 0x10, 0x10);
2112 WClut (fb_info, 9, 0x10, 0x10, 0x30);
2113 WClut (fb_info, 10, 0x10, 0x30, 0x10);
2114 WClut (fb_info, 11, 0x10, 0x30, 0x30);
2115 WClut (fb_info, 12, 0x30, 0x10, 0x10);
2116 WClut (fb_info, 13, 0x30, 0x10, 0x30);
2117 WClut (fb_info, 14, 0x30, 0x30, 0x10);
2118 WClut (fb_info, 15, 0x30, 0x30, 0x30);
2119
2120 /* the rest a grey ramp */
2121 {
2122 int i;
2123
2124 for (i = 16; i < 256; i++)
2125 WClut (fb_info, i, i >> 2, i >> 2, i >> 2);
2126 }
2127
2128
2129 /* misc... */
2130 WHDR (fb_info, 0); /* Hidden DAC register: - */
2131
2132 printk (KERN_INFO "clgen: This board has %ld bytes of DRAM memory\n", fb_info->size);
2133 DPRINTK ("EXIT\n");
2134 return;
2135 }
2136
switch_monitor(struct clgenfb_info * fb_info,int on)2137 static void switch_monitor (struct clgenfb_info *fb_info, int on)
2138 {
2139 #ifdef CONFIG_ZORRO /* only works on Zorro boards */
2140 static int IsOn = 0; /* XXX not ok for multiple boards */
2141
2142 DPRINTK ("ENTER\n");
2143
2144 if (fb_info->btype == BT_PICASSO4)
2145 return; /* nothing to switch */
2146 if (fb_info->btype == BT_ALPINE)
2147 return; /* nothing to switch */
2148 if (fb_info->btype == BT_GD5480)
2149 return; /* nothing to switch */
2150 if (fb_info->btype == BT_PICASSO) {
2151 if ((on && !IsOn) || (!on && IsOn))
2152 WSFR (fb_info, 0xff);
2153
2154 DPRINTK ("EXIT\n");
2155 return;
2156 }
2157 if (on) {
2158 switch (fb_info->btype) {
2159 case BT_SD64:
2160 WSFR (fb_info, fb_info->SFR | 0x21);
2161 break;
2162 case BT_PICCOLO:
2163 WSFR (fb_info, fb_info->SFR | 0x28);
2164 break;
2165 case BT_SPECTRUM:
2166 WSFR (fb_info, 0x6f);
2167 break;
2168 default: /* do nothing */ break;
2169 }
2170 } else {
2171 switch (fb_info->btype) {
2172 case BT_SD64:
2173 WSFR (fb_info, fb_info->SFR & 0xde);
2174 break;
2175 case BT_PICCOLO:
2176 WSFR (fb_info, fb_info->SFR & 0xd7);
2177 break;
2178 case BT_SPECTRUM:
2179 WSFR (fb_info, 0x4f);
2180 break;
2181 default: /* do nothing */ break;
2182 }
2183 }
2184
2185 DPRINTK ("EXIT\n");
2186 #endif /* CONFIG_ZORRO */
2187 }
2188
clgen_set_disp(const void * par,struct display * disp,struct fb_info_gen * info)2189 static void clgen_set_disp (const void *par, struct display *disp,
2190 struct fb_info_gen *info)
2191 {
2192 struct clgenfb_par *_par = (struct clgenfb_par *) par;
2193 struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
2194 int accel_text;
2195
2196 DPRINTK ("ENTER\n");
2197
2198 assert (_par != NULL);
2199 assert (fb_info != NULL);
2200
2201 accel_text = _par->var.accel_flags & FB_ACCELF_TEXT;
2202
2203 printk ("Cirrus Logic video mode: ");
2204 disp->screen_base = (char *) fb_info->fbmem;
2205 switch (_par->var.bits_per_pixel) {
2206 #ifdef FBCON_HAS_MFB
2207 case 1:
2208 printk ("monochrome\n");
2209 if (fb_info->btype == BT_GD5480)
2210 disp->screen_base = (char *) fb_info->fbmem;
2211 disp->dispsw = &fbcon_mfb;
2212 break;
2213 #endif
2214 #ifdef FBCON_HAS_CFB8
2215 case 8:
2216 printk ("8 bit color depth\n");
2217 if (fb_info->btype == BT_GD5480)
2218 disp->screen_base = (char *) fb_info->fbmem;
2219 if (accel_text)
2220 disp->dispsw = &fbcon_clgen_8;
2221 else
2222 disp->dispsw = &fbcon_cfb8;
2223 break;
2224 #endif
2225 #ifdef FBCON_HAS_CFB16
2226 case 16:
2227 printk ("16 bit color depth\n");
2228 if (accel_text)
2229 disp->dispsw = &fbcon_clgen_16;
2230 else
2231 disp->dispsw = &fbcon_cfb16;
2232 if (fb_info->btype == BT_GD5480)
2233 disp->screen_base = (char *) fb_info->fbmem + 1 * MB_;
2234 disp->dispsw_data = fb_info->fbcon_cmap.cfb16;
2235 break;
2236 #endif
2237 #ifdef FBCON_HAS_CFB24
2238 case 24:
2239 printk ("24 bit color depth\n");
2240 disp->dispsw = &fbcon_cfb24;
2241 if (fb_info->btype == BT_GD5480)
2242 disp->screen_base = (char *) fb_info->fbmem + 2 * MB_;
2243 disp->dispsw_data = fb_info->fbcon_cmap.cfb24;
2244 break;
2245 #endif
2246 #ifdef FBCON_HAS_CFB32
2247 case 32:
2248 printk ("32 bit color depth\n");
2249 if (accel_text)
2250 disp->dispsw = &fbcon_clgen_32;
2251 else
2252 disp->dispsw = &fbcon_cfb32;
2253 if (fb_info->btype == BT_GD5480)
2254 disp->screen_base = (char *) fb_info->fbmem + 2 * MB_;
2255 disp->dispsw_data = fb_info->fbcon_cmap.cfb32;
2256 break;
2257 #endif
2258
2259 default:
2260 printk ("unsupported color depth\n");
2261 disp->dispsw = &fbcon_dummy;
2262 disp->dispsw_data = NULL;
2263 break;
2264 }
2265
2266 DPRINTK ("EXIT\n");
2267 }
2268
2269 #ifdef FBCON_HAS_CFB8
fbcon_clgen8_bmove(struct display * p,int sy,int sx,int dy,int dx,int height,int width)2270 static void fbcon_clgen8_bmove (struct display *p, int sy, int sx,
2271 int dy, int dx, int height, int width)
2272 {
2273 struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
2274
2275 DPRINTK ("ENTER\n");
2276
2277 sx *= fontwidth (p);
2278 sy *= fontheight (p);
2279 dx *= fontwidth (p);
2280 dy *= fontheight (p);
2281 width *= fontwidth (p);
2282 height *= fontheight (p);
2283
2284 clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy,
2285 (unsigned short) dx, (unsigned short) dy,
2286 (unsigned short) width, (unsigned short) height,
2287 fb_info->currentmode.line_length);
2288
2289 DPRINTK ("EXIT\n");
2290 }
2291
fbcon_clgen8_clear(struct vc_data * conp,struct display * p,int sy,int sx,int height,int width)2292 static void fbcon_clgen8_clear (struct vc_data *conp, struct display *p,
2293 int sy, int sx, int height, int width)
2294 {
2295 struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
2296 unsigned short col;
2297
2298 DPRINTK ("ENTER\n");
2299
2300 sx *= fontwidth (p);
2301 sy *= fontheight (p);
2302 width *= fontwidth (p);
2303 height *= fontheight (p);
2304
2305 col = attr_bgcol_ec (p, conp);
2306 col &= 0xff;
2307
2308 clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy,
2309 (unsigned short) width, (unsigned short) height,
2310 col, fb_info->currentmode.line_length);
2311
2312 DPRINTK ("EXIT\n");
2313 }
2314
2315 #endif
2316
2317 #ifdef FBCON_HAS_CFB16
fbcon_clgen16_bmove(struct display * p,int sy,int sx,int dy,int dx,int height,int width)2318 static void fbcon_clgen16_bmove (struct display *p, int sy, int sx,
2319 int dy, int dx, int height, int width)
2320 {
2321 struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
2322
2323 DPRINTK ("ENTER\n");
2324
2325 sx *= fontwidth (p) * 2; /* 2 bytes/pixel */
2326 sy *= fontheight (p);
2327 dx *= fontwidth (p) * 2; /* 2 bytes/pixel */
2328 dy *= fontheight (p);
2329 width *= fontwidth (p) * 2; /* 2 bytes/pixel */
2330 height *= fontheight (p);
2331
2332 clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy,
2333 (unsigned short) dx, (unsigned short) dy,
2334 (unsigned short) width, (unsigned short) height,
2335 fb_info->currentmode.line_length);
2336
2337 DPRINTK ("EXIT\n");
2338 }
2339
fbcon_clgen16_clear(struct vc_data * conp,struct display * p,int sy,int sx,int height,int width)2340 static void fbcon_clgen16_clear (struct vc_data *conp, struct display *p,
2341 int sy, int sx, int height, int width)
2342 {
2343 struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
2344 unsigned short col;
2345
2346 DPRINTK ("ENTER\n");
2347
2348 sx *= fontwidth (p) * 2; /* 2 bytes/pixel */
2349 sy *= fontheight (p);
2350 width *= fontwidth (p) * 2; /* 2 bytes/pixel? */
2351 height *= fontheight (p);
2352
2353 col = attr_bgcol_ec (p, conp);
2354 col &= 0xff;
2355
2356 clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy,
2357 (unsigned short) width, (unsigned short) height,
2358 col, fb_info->currentmode.line_length);
2359
2360 DPRINTK ("EXIT\n");
2361 }
2362
2363 #endif
2364
2365 #ifdef FBCON_HAS_CFB32
fbcon_clgen32_bmove(struct display * p,int sy,int sx,int dy,int dx,int height,int width)2366 static void fbcon_clgen32_bmove (struct display *p, int sy, int sx,
2367 int dy, int dx, int height, int width)
2368 {
2369 struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
2370
2371 DPRINTK ("ENTER\n");
2372
2373 sx *= fontwidth (p) * 4; /* 4 bytes/pixel */
2374 sy *= fontheight (p);
2375 dx *= fontwidth (p) * 4; /* 4 bytes/pixel */
2376 dy *= fontheight (p);
2377 width *= fontwidth (p) * 4; /* 4 bytes/pixel */
2378 height *= fontheight (p);
2379
2380 clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy,
2381 (unsigned short) dx, (unsigned short) dy,
2382 (unsigned short) width, (unsigned short) height,
2383 fb_info->currentmode.line_length);
2384
2385 DPRINTK ("EXIT\n");
2386 }
2387
fbcon_clgen32_clear(struct vc_data * conp,struct display * p,int sy,int sx,int height,int width)2388 static void fbcon_clgen32_clear (struct vc_data *conp, struct display *p,
2389 int sy, int sx, int height, int width)
2390 {
2391 struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
2392
2393 unsigned short col;
2394
2395 DPRINTK ("ENTER\n");
2396
2397 sx *= fontwidth (p) * 4; /* 4 bytes/pixel */
2398 sy *= fontheight (p);
2399 width *= fontwidth (p) * 4; /* 4 bytes/pixel? */
2400 height *= fontheight (p);
2401
2402 col = attr_bgcol_ec (p, conp);
2403 col &= 0xff;
2404
2405 clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy,
2406 (unsigned short) width, (unsigned short) height,
2407 col, fb_info->currentmode.line_length);
2408
2409 DPRINTK ("EXIT\n");
2410 }
2411
2412 #endif /* FBCON_HAS_CFB32 */
2413
2414
2415
2416
2417 #ifdef CONFIG_ALL_PPC
2418 #define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
2419 #define PREP_IO_BASE ((volatile unsigned char *) 0x80000000)
get_prep_addrs(unsigned long * display,unsigned long * registers)2420 static void __init get_prep_addrs (unsigned long *display, unsigned long *registers)
2421 {
2422 DPRINTK ("ENTER\n");
2423
2424 *display = PREP_VIDEO_BASE;
2425 *registers = (unsigned long) PREP_IO_BASE;
2426
2427 DPRINTK ("EXIT\n");
2428 }
2429
2430 #endif /* CONFIG_ALL_PPC */
2431
2432
2433
2434
2435 #ifdef CONFIG_PCI
2436 static int release_io_ports = 0;
2437
2438 /* Pulled the logic from XFree86 Cirrus driver to get the memory size,
2439 * based on the DRAM bandwidth bit and DRAM bank switching bit. This
2440 * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
2441 * seem to have. */
clgen_get_memsize(caddr_t regbase)2442 static unsigned int __init clgen_get_memsize (caddr_t regbase)
2443 {
2444 unsigned long mem;
2445 unsigned char SRF;
2446
2447 DPRINTK ("ENTER\n");
2448
2449 SRF = vga_rseq (regbase, CL_SEQRF);
2450 switch ((SRF & 0x18)) {
2451 case 0x08: mem = 512 * 1024; break;
2452 case 0x10: mem = 1024 * 1024; break;
2453 /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory
2454 * on the 5430. */
2455 case 0x18: mem = 2048 * 1024; break;
2456 default: printk ("CLgenfb: Unknown memory size!\n");
2457 mem = 1024 * 1024;
2458 }
2459 if (SRF & 0x80) {
2460 /* If DRAM bank switching is enabled, there must be twice as much
2461 * memory installed. (4MB on the 5434) */
2462 mem *= 2;
2463 }
2464 /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
2465 return mem;
2466
2467 DPRINTK ("EXIT\n");
2468 }
2469
2470
2471
clgen_pci_dev_get(clgen_board_t * btype)2472 static struct pci_dev * __init clgen_pci_dev_get (clgen_board_t *btype)
2473 {
2474 struct pci_dev *pdev;
2475 int i;
2476
2477 DPRINTK ("ENTER\n");
2478
2479 for (i = 0; i < ARRAY_SIZE(clgen_pci_probe_list); i++) {
2480 pdev = NULL;
2481 while ((pdev = pci_find_device (PCI_VENDOR_ID_CIRRUS,
2482 clgen_pci_probe_list[i].device, pdev)) != NULL) {
2483 if (pci_enable_device(pdev) == 0) {
2484 *btype = clgen_pci_probe_list[i].btype;
2485 DPRINTK ("EXIT, returning pdev=%p\n", pdev);
2486 return pdev;
2487 }
2488 }
2489 }
2490
2491 DPRINTK ("EXIT, returning NULL\n");
2492 return NULL;
2493 }
2494
2495
2496
2497
get_pci_addrs(const struct pci_dev * pdev,unsigned long * display,unsigned long * registers)2498 static void __init get_pci_addrs (const struct pci_dev *pdev,
2499 unsigned long *display, unsigned long *registers)
2500 {
2501 assert (pdev != NULL);
2502 assert (display != NULL);
2503 assert (registers != NULL);
2504
2505 DPRINTK ("ENTER\n");
2506
2507 *display = 0;
2508 *registers = 0;
2509
2510 /* This is a best-guess for now */
2511
2512 if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
2513 *display = pci_resource_start(pdev, 1);
2514 *registers = pci_resource_start(pdev, 0);
2515 } else {
2516 *display = pci_resource_start(pdev, 0);
2517 *registers = pci_resource_start(pdev, 1);
2518 }
2519
2520 assert (*display != 0);
2521
2522 DPRINTK ("EXIT\n");
2523 }
2524
2525
clgen_pci_unmap(struct clgenfb_info * info)2526 static void __exit clgen_pci_unmap (struct clgenfb_info *info)
2527 {
2528 iounmap (info->fbmem);
2529 release_mem_region(info->fbmem_phys, info->size);
2530
2531 #if 0 /* if system didn't claim this region, we would... */
2532 release_mem_region(0xA0000, 65535);
2533 #endif
2534
2535 if (release_io_ports)
2536 release_region(0x3C0, 32);
2537 }
2538
2539
clgen_pci_setup(struct clgenfb_info * info,clgen_board_t * btype)2540 static int __init clgen_pci_setup (struct clgenfb_info *info,
2541 clgen_board_t *btype)
2542 {
2543 struct pci_dev *pdev;
2544 unsigned long board_addr, board_size;
2545
2546 DPRINTK ("ENTER\n");
2547
2548 pdev = clgen_pci_dev_get (btype);
2549 if (!pdev) {
2550 printk (KERN_INFO "clgenfb: couldn't find Cirrus Logic PCI device\n");
2551 DPRINTK ("EXIT, returning 1\n");
2552 return 1;
2553 }
2554 DPRINTK (" Found PCI device, base address 0 is 0x%lx, btype set to %d\n",
2555 pdev->resource[0].start, *btype);
2556 DPRINTK (" base address 1 is 0x%lx\n", pdev->resource[1].start);
2557
2558 info->pdev = pdev;
2559
2560 if(isPReP) {
2561 /* Xbh does this, though 0 seems to be the init value */
2562 pcibios_write_config_dword (0, pdev->devfn, PCI_BASE_ADDRESS_0,
2563 0x00000000);
2564
2565 #ifdef CONFIG_ALL_PPC
2566 get_prep_addrs (&board_addr, &info->fbregs_phys);
2567 #endif
2568 } else {
2569 DPRINTK ("Attempt to get PCI info for Cirrus Graphics Card\n");
2570 get_pci_addrs (pdev, &board_addr, &info->fbregs_phys);
2571 }
2572
2573 DPRINTK ("Board address: 0x%lx, register address: 0x%lx\n", board_addr, info->fbregs_phys);
2574
2575 if(isPReP) {
2576 /* PReP dies if we ioremap the IO registers, but it works w/out... */
2577 info->regs = (char *) info->fbregs_phys;
2578 } else
2579 info->regs = 0; /* FIXME: this forces VGA. alternatives? */
2580
2581 if (*btype == BT_GD5480) {
2582 board_size = 32 * MB_;
2583 } else {
2584 board_size = clgen_get_memsize (info->regs);
2585 }
2586
2587 if (!request_mem_region(board_addr, board_size, "clgenfb")) {
2588 printk(KERN_ERR "clgen: cannot reserve region 0x%lx, abort\n",
2589 board_addr);
2590 return -1;
2591 }
2592 #if 0 /* if the system didn't claim this region, we would... */
2593 if (!request_mem_region(0xA0000, 65535, "clgenfb")) {
2594 printk(KERN_ERR "clgen: cannot reserve region 0x%lx, abort\n",
2595 0xA0000L);
2596 release_mem_region(board_addr, board_size);
2597 return -1;
2598 }
2599 #endif
2600 if (request_region(0x3C0, 32, "clgenfb"))
2601 release_io_ports = 1;
2602
2603 info->fbmem = ioremap (board_addr, board_size);
2604 info->fbmem_phys = board_addr;
2605 info->size = board_size;
2606
2607 printk (" RAM (%lu kB) at 0x%lx, ", info->size / KB_, board_addr);
2608
2609 printk ("Cirrus Logic chipset on PCI bus\n");
2610
2611 DPRINTK ("EXIT, returning 0\n");
2612 return 0;
2613 }
2614 #endif /* CONFIG_PCI */
2615
2616
2617
2618
2619 #ifdef CONFIG_ZORRO
clgen_zorro_find(struct zorro_dev ** z_o,struct zorro_dev ** z2_o,clgen_board_t * btype,unsigned long * size)2620 static int __init clgen_zorro_find (struct zorro_dev **z_o,
2621 struct zorro_dev **z2_o,
2622 clgen_board_t *btype, unsigned long *size)
2623 {
2624 struct zorro_dev *z = NULL;
2625 int i;
2626
2627 assert (z_o != NULL);
2628 assert (btype != NULL);
2629
2630 for (i = 0; i < ARRAY_SIZE(clgen_zorro_probe_list); i++)
2631 if ((z = zorro_find_device(clgen_zorro_probe_list[i].id, NULL)))
2632 break;
2633
2634 if (z) {
2635 *z_o = z;
2636 if (clgen_zorro_probe_list[i].id2)
2637 *z2_o = zorro_find_device(clgen_zorro_probe_list[i].id2, NULL);
2638 else
2639 *z2_o = NULL;
2640
2641 *btype = clgen_zorro_probe_list[i].btype;
2642 *size = clgen_zorro_probe_list[i].size;
2643
2644 printk (KERN_INFO "clgen: %s board detected; ",
2645 clgen_board_info[*btype].name);
2646
2647 return 0;
2648 }
2649
2650 printk (KERN_NOTICE "clgen: no supported board found.\n");
2651 return -1;
2652 }
2653
2654
clgen_zorro_unmap(struct clgenfb_info * info)2655 static void __exit clgen_zorro_unmap (struct clgenfb_info *info)
2656 {
2657 release_mem_region(info->board_addr, info->board_size);
2658
2659 if (info->btype == BT_PICASSO4) {
2660 iounmap ((void *)info->board_addr);
2661 iounmap ((void *)info->fbmem_phys);
2662 } else {
2663 if (info->board_addr > 0x01000000)
2664 iounmap ((void *)info->board_addr);
2665 }
2666 }
2667
2668
clgen_zorro_setup(struct clgenfb_info * info,clgen_board_t * btype)2669 static int __init clgen_zorro_setup (struct clgenfb_info *info,
2670 clgen_board_t *btype)
2671 {
2672 struct zorro_dev *z = NULL, *z2 = NULL;
2673 unsigned long board_addr, board_size, size;
2674
2675 assert (info != NULL);
2676 assert (btype != NULL);
2677
2678 if (clgen_zorro_find (&z, &z2, btype, &size))
2679 return -1;
2680
2681 assert (z > 0);
2682 assert (z2 >= 0);
2683 assert (*btype != BT_NONE);
2684
2685 info->board_addr = board_addr = z->resource.start;
2686 info->board_size = board_size = z->resource.end-z->resource.start+1;
2687 info->size = size;
2688
2689 if (!request_mem_region(board_addr, board_size, "clgenfb")) {
2690 printk(KERN_ERR "clgen: cannot reserve region 0x%lx, abort\n",
2691 board_addr);
2692 return -1;
2693 }
2694
2695 printk (" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr);
2696
2697 if (*btype == BT_PICASSO4) {
2698 printk (" REG at $%lx\n", board_addr + 0x600000);
2699
2700 /* To be precise, for the P4 this is not the */
2701 /* begin of the board, but the begin of RAM. */
2702 /* for P4, map in its address space in 2 chunks (### TEST! ) */
2703 /* (note the ugly hardcoded 16M number) */
2704 info->regs = ioremap (board_addr, 16777216);
2705 DPRINTK ("clgen: Virtual address for board set to: $%p\n", info->regs);
2706 info->regs += 0x600000;
2707 info->fbregs_phys = board_addr + 0x600000;
2708
2709 info->fbmem_phys = board_addr + 16777216;
2710 info->fbmem = ioremap (info->fbmem_phys, 16777216);
2711 } else {
2712 printk (" REG at $%lx\n", (unsigned long) z2->resource.start);
2713
2714 info->fbmem_phys = board_addr;
2715 if (board_addr > 0x01000000)
2716 info->fbmem = ioremap (board_addr, board_size);
2717 else
2718 info->fbmem = (caddr_t) ZTWO_VADDR (board_addr);
2719
2720 /* set address for REG area of board */
2721 info->regs = (caddr_t) ZTWO_VADDR (z2->resource.start);
2722 info->fbregs_phys = z2->resource.start;
2723
2724 DPRINTK ("clgen: Virtual address for board set to: $%p\n", info->regs);
2725 }
2726
2727 printk (KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
2728
2729 return 0;
2730 }
2731 #endif /* CONFIG_ZORRO */
2732
2733
2734
2735 /********************************************************************/
2736 /* clgenfb_init() - master initialization function */
2737 /********************************************************************/
clgenfb_init(void)2738 int __init clgenfb_init(void)
2739 {
2740 int err, j, k;
2741
2742 clgen_board_t btype = BT_NONE;
2743 struct clgenfb_info *fb_info = NULL;
2744
2745 DPRINTK ("ENTER\n");
2746
2747 printk (KERN_INFO "clgen: Driver for Cirrus Logic based graphic boards, v" CLGEN_VERSION "\n");
2748
2749 fb_info = &boards[0]; /* FIXME support multiple boards ... */
2750
2751 #ifdef CONFIG_PCI
2752 if (clgen_pci_setup (fb_info, &btype)) { /* Also does OF setup */
2753 DPRINTK ("EXIT, returning -ENXIO\n");
2754 return -ENXIO;
2755 }
2756
2757 #elif defined(CONFIG_ZORRO)
2758 /* FIXME: CONFIG_PCI and CONFIG_ZORRO may both be defined */
2759 if (clgen_zorro_setup (fb_info, &btype)) {
2760 DPRINTK ("EXIT, returning -ENXIO\n");
2761 return -ENXIO;
2762 }
2763
2764 #else
2765 #error This driver requires Zorro or PCI bus.
2766 #endif /* !CONFIG_PCI, !CONFIG_ZORRO */
2767
2768 /* sanity checks */
2769 assert (btype != BT_NONE);
2770 assert (btype == clgen_board_info[btype].btype);
2771
2772 fb_info->btype = btype;
2773
2774 DPRINTK ("clgen: (RAM start set to: 0x%p)\n", fb_info->fbmem);
2775
2776 if (noaccel)
2777 {
2778 printk("clgen: disabling text acceleration support\n");
2779 #ifdef FBCON_HAS_CFB8
2780 fbcon_clgen_8.bmove = fbcon_cfb8_bmove;
2781 fbcon_clgen_8.clear = fbcon_cfb8_clear;
2782 #endif
2783 #ifdef FBCON_HAS_CFB16
2784 fbcon_clgen_16.bmove = fbcon_cfb16_bmove;
2785 fbcon_clgen_16.clear = fbcon_cfb16_clear;
2786 #endif
2787 #ifdef FBCON_HAS_CFB32
2788 fbcon_clgen_32.bmove = fbcon_cfb32_bmove;
2789 fbcon_clgen_32.clear = fbcon_cfb32_clear;
2790 #endif
2791 }
2792
2793 init_vgachip (fb_info);
2794
2795 /* set up a few more things, register framebuffer driver etc */
2796 fb_info->gen.parsize = sizeof (struct clgenfb_par);
2797 fb_info->gen.fbhw = &clgen_hwswitch;
2798
2799 strncpy (fb_info->gen.info.modename, clgen_board_info[btype].name,
2800 sizeof (fb_info->gen.info.modename));
2801 fb_info->gen.info.modename [sizeof (fb_info->gen.info.modename) - 1] = 0;
2802
2803 fb_info->gen.info.node = -1;
2804 fb_info->gen.info.fbops = &clgenfb_ops;
2805 fb_info->gen.info.disp = &disp;
2806 fb_info->gen.info.changevar = NULL;
2807 fb_info->gen.info.switch_con = &fbgen_switch;
2808 fb_info->gen.info.updatevar = &fbgen_update_var;
2809 fb_info->gen.info.blank = &fbgen_blank;
2810 fb_info->gen.info.flags = FBINFO_FLAG_DEFAULT;
2811
2812 for (j = 0; j < 256; j++) {
2813 if (j < 16) {
2814 k = color_table[j];
2815 fb_info->palette[j].red = default_red[k];
2816 fb_info->palette[j].green = default_grn[k];
2817 fb_info->palette[j].blue = default_blu[k];
2818 } else {
2819 fb_info->palette[j].red =
2820 fb_info->palette[j].green =
2821 fb_info->palette[j].blue = j;
2822 }
2823 }
2824
2825 /* now that we know the board has been registered n' stuff, we */
2826 /* can finally initialize it to a default mode */
2827 clgenfb_default = clgenfb_predefined[clgen_def_mode].var;
2828 clgenfb_default.activate = FB_ACTIVATE_NOW;
2829 clgenfb_default.yres_virtual = 480 * 3; /* for fast scrolling (YPAN-Mode) */
2830 err = fbgen_do_set_var (&clgenfb_default, 1, &fb_info->gen);
2831
2832 if (err) {
2833 DPRINTK ("EXIT, returning -EINVAL\n");
2834 return -EINVAL;
2835 }
2836
2837 disp.var = clgenfb_default;
2838 fbgen_set_disp (-1, &fb_info->gen);
2839 fbgen_install_cmap (0, &fb_info->gen);
2840
2841 err = register_framebuffer (&fb_info->gen.info);
2842 if (err) {
2843 printk (KERN_ERR "clgen: ERROR - could not register fb device; err = %d!\n", err);
2844 DPRINTK ("EXIT, returning -EINVAL\n");
2845 return -EINVAL;
2846 }
2847 DPRINTK ("EXIT, returning 0\n");
2848 return 0;
2849 }
2850
2851
2852
2853 /*
2854 * Cleanup (only needed for module)
2855 */
clgenfb_cleanup(struct clgenfb_info * info)2856 static void __exit clgenfb_cleanup (struct clgenfb_info *info)
2857 {
2858 DPRINTK ("ENTER\n");
2859
2860 #ifdef CONFIG_ZORRO
2861 switch_monitor (info, 0);
2862
2863 clgen_zorro_unmap (info);
2864 #else
2865 clgen_pci_unmap (info);
2866 #endif /* CONFIG_ZORRO */
2867
2868 unregister_framebuffer ((struct fb_info *) info);
2869 printk ("Framebuffer unregistered\n");
2870
2871 DPRINTK ("EXIT\n");
2872 }
2873
2874
2875 #ifndef MODULE
clgenfb_setup(char * options)2876 int __init clgenfb_setup(char *options) {
2877 char *this_opt, s[32];
2878 int i;
2879
2880 DPRINTK ("ENTER\n");
2881
2882 if (!options || !*options)
2883 return 0;
2884
2885 for (this_opt = strtok (options, ","); this_opt != NULL;
2886 this_opt = strtok (NULL, ",")) {
2887 if (!*this_opt) continue;
2888
2889 DPRINTK("clgenfb_setup: option '%s'\n", this_opt);
2890
2891 for (i = 0; i < NUM_TOTAL_MODES; i++) {
2892 sprintf (s, "mode:%s", clgenfb_predefined[i].name);
2893 if (strcmp (this_opt, s) == 0)
2894 clgen_def_mode = i;
2895 }
2896 if (!strcmp(this_opt, "noaccel"))
2897 noaccel = 1;
2898 }
2899 return 0;
2900 }
2901 #endif
2902
2903
2904 /*
2905 * Modularization
2906 */
2907
2908 MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
2909 MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
2910 MODULE_LICENSE("GPL");
2911
clgenfb_exit(void)2912 static void __exit clgenfb_exit (void)
2913 {
2914 DPRINTK ("ENTER\n");
2915
2916 clgenfb_cleanup (&boards[0]); /* FIXME: support multiple boards */
2917
2918 DPRINTK ("EXIT\n");
2919 }
2920
2921 #ifdef MODULE
2922 module_init(clgenfb_init);
2923 #endif
2924 module_exit(clgenfb_exit);
2925
2926
2927 /**********************************************************************/
2928 /* about the following functions - I have used the same names for the */
2929 /* functions as Markus Wild did in his Retina driver for NetBSD as */
2930 /* they just made sense for this purpose. Apart from that, I wrote */
2931 /* these functions myself. */
2932 /**********************************************************************/
2933
2934 /*** WGen() - write into one of the external/general registers ***/
WGen(const struct clgenfb_info * fb_info,int regnum,unsigned char val)2935 static void WGen (const struct clgenfb_info *fb_info,
2936 int regnum, unsigned char val)
2937 {
2938 unsigned long regofs = 0;
2939
2940 if (fb_info->btype == BT_PICASSO) {
2941 /* Picasso II specific hack */
2942 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */
2943 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2944 regofs = 0xfff;
2945 }
2946
2947 vga_w (fb_info->regs, regofs + regnum, val);
2948 }
2949
2950 /*** RGen() - read out one of the external/general registers ***/
RGen(const struct clgenfb_info * fb_info,int regnum)2951 static unsigned char RGen (const struct clgenfb_info *fb_info, int regnum)
2952 {
2953 unsigned long regofs = 0;
2954
2955 if (fb_info->btype == BT_PICASSO) {
2956 /* Picasso II specific hack */
2957 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */
2958 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2959 regofs = 0xfff;
2960 }
2961
2962 return vga_r (fb_info->regs, regofs + regnum);
2963 }
2964
2965 /*** AttrOn() - turn on VideoEnable for Attribute controller ***/
AttrOn(const struct clgenfb_info * fb_info)2966 static void AttrOn (const struct clgenfb_info *fb_info)
2967 {
2968 assert (fb_info != NULL);
2969
2970 DPRINTK ("ENTER\n");
2971
2972 if (vga_rcrt (fb_info->regs, CL_CRT24) & 0x80) {
2973 /* if we're just in "write value" mode, write back the */
2974 /* same value as before to not modify anything */
2975 vga_w (fb_info->regs, VGA_ATT_IW,
2976 vga_r (fb_info->regs, VGA_ATT_R));
2977 }
2978 /* turn on video bit */
2979 /* vga_w (fb_info->regs, VGA_ATT_IW, 0x20); */
2980 vga_w (fb_info->regs, VGA_ATT_IW, 0x33);
2981
2982 /* dummy write on Reg0 to be on "write index" mode next time */
2983 vga_w (fb_info->regs, VGA_ATT_IW, 0x00);
2984
2985 DPRINTK ("EXIT\n");
2986 }
2987
2988 /*** WHDR() - write into the Hidden DAC register ***/
2989 /* as the HDR is the only extension register that requires special treatment
2990 * (the other extension registers are accessible just like the "ordinary"
2991 * registers of their functional group) here is a specialized routine for
2992 * accessing the HDR
2993 */
WHDR(const struct clgenfb_info * fb_info,unsigned char val)2994 static void WHDR (const struct clgenfb_info *fb_info, unsigned char val)
2995 {
2996 unsigned char dummy;
2997
2998 if (fb_info->btype == BT_PICASSO) {
2999 /* Klaus' hint for correct access to HDR on some boards */
3000 /* first write 0 to pixel mask (3c6) */
3001 WGen (fb_info, VGA_PEL_MSK, 0x00);
3002 udelay (200);
3003 /* next read dummy from pixel address (3c8) */
3004 dummy = RGen (fb_info, VGA_PEL_IW);
3005 udelay (200);
3006 }
3007 /* now do the usual stuff to access the HDR */
3008
3009 dummy = RGen (fb_info, VGA_PEL_MSK);
3010 udelay (200);
3011 dummy = RGen (fb_info, VGA_PEL_MSK);
3012 udelay (200);
3013 dummy = RGen (fb_info, VGA_PEL_MSK);
3014 udelay (200);
3015 dummy = RGen (fb_info, VGA_PEL_MSK);
3016 udelay (200);
3017
3018 WGen (fb_info, VGA_PEL_MSK, val);
3019 udelay (200);
3020
3021 if (fb_info->btype == BT_PICASSO) {
3022 /* now first reset HDR access counter */
3023 dummy = RGen (fb_info, VGA_PEL_IW);
3024 udelay (200);
3025
3026 /* and at the end, restore the mask value */
3027 /* ## is this mask always 0xff? */
3028 WGen (fb_info, VGA_PEL_MSK, 0xff);
3029 udelay (200);
3030 }
3031 }
3032
3033
3034 /*** WSFR() - write to the "special function register" (SFR) ***/
WSFR(struct clgenfb_info * fb_info,unsigned char val)3035 static void WSFR (struct clgenfb_info *fb_info, unsigned char val)
3036 {
3037 #ifdef CONFIG_ZORRO
3038 assert (fb_info->regs != NULL);
3039 fb_info->SFR = val;
3040 z_writeb (val, fb_info->regs + 0x8000);
3041 #endif
3042 }
3043
3044 /* The Picasso has a second register for switching the monitor bit */
WSFR2(struct clgenfb_info * fb_info,unsigned char val)3045 static void WSFR2 (struct clgenfb_info *fb_info, unsigned char val)
3046 {
3047 #ifdef CONFIG_ZORRO
3048 /* writing an arbitrary value to this one causes the monitor switcher */
3049 /* to flip to Amiga display */
3050 assert (fb_info->regs != NULL);
3051 fb_info->SFR = val;
3052 z_writeb (val, fb_info->regs + 0x9000);
3053 #endif
3054 }
3055
3056
3057 /*** WClut - set CLUT entry (range: 0..63) ***/
WClut(struct clgenfb_info * fb_info,unsigned char regnum,unsigned char red,unsigned char green,unsigned char blue)3058 static void WClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char red,
3059 unsigned char green, unsigned char blue)
3060 {
3061 unsigned int data = VGA_PEL_D;
3062
3063 /* address write mode register is not translated.. */
3064 vga_w (fb_info->regs, VGA_PEL_IW, regnum);
3065
3066 if (fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4 ||
3067 fb_info->btype == BT_ALPINE || fb_info->btype == BT_GD5480) {
3068 /* but DAC data register IS, at least for Picasso II */
3069 if (fb_info->btype == BT_PICASSO)
3070 data += 0xfff;
3071 vga_w (fb_info->regs, data, red);
3072 vga_w (fb_info->regs, data, green);
3073 vga_w (fb_info->regs, data, blue);
3074 } else {
3075 vga_w (fb_info->regs, data, blue);
3076 vga_w (fb_info->regs, data, green);
3077 vga_w (fb_info->regs, data, red);
3078 }
3079 }
3080
3081
3082 #if 0
3083 /*** RClut - read CLUT entry (range 0..63) ***/
3084 static void RClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char *red,
3085 unsigned char *green, unsigned char *blue)
3086 {
3087 unsigned int data = VGA_PEL_D;
3088
3089 vga_w (fb_info->regs, VGA_PEL_IR, regnum);
3090
3091 if (fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4 ||
3092 fb_info->btype == BT_ALPINE || fb_info->btype == BT_GD5480) {
3093 if (fb_info->btype == BT_PICASSO)
3094 data += 0xfff;
3095 *red = vga_r (fb_info->regs, data);
3096 *green = vga_r (fb_info->regs, data);
3097 *blue = vga_r (fb_info->regs, data);
3098 } else {
3099 *blue = vga_r (fb_info->regs, data);
3100 *green = vga_r (fb_info->regs, data);
3101 *red = vga_r (fb_info->regs, data);
3102 }
3103 }
3104 #endif
3105
3106
3107 /*******************************************************************
3108 clgen_WaitBLT()
3109
3110 Wait for the BitBLT engine to complete a possible earlier job
3111 *********************************************************************/
3112
3113 /* FIXME: use interrupts instead */
clgen_WaitBLT(caddr_t regbase)3114 static inline void clgen_WaitBLT (caddr_t regbase)
3115 {
3116 /* now busy-wait until we're done */
3117 while (vga_rgfx (regbase, CL_GR31) & 0x08)
3118 /* do nothing */ ;
3119 }
3120
3121 /*******************************************************************
3122 clgen_BitBLT()
3123
3124 perform accelerated "scrolling"
3125 ********************************************************************/
3126
clgen_BitBLT(caddr_t regbase,u_short curx,u_short cury,u_short destx,u_short desty,u_short width,u_short height,u_short line_length)3127 static void clgen_BitBLT (caddr_t regbase, u_short curx, u_short cury, u_short destx, u_short desty,
3128 u_short width, u_short height, u_short line_length)
3129 {
3130 u_short nwidth, nheight;
3131 u_long nsrc, ndest;
3132 u_char bltmode;
3133
3134 DPRINTK ("ENTER\n");
3135
3136 nwidth = width - 1;
3137 nheight = height - 1;
3138
3139 bltmode = 0x00;
3140 /* if source adr < dest addr, do the Blt backwards */
3141 if (cury <= desty) {
3142 if (cury == desty) {
3143 /* if src and dest are on the same line, check x */
3144 if (curx < destx)
3145 bltmode |= 0x01;
3146 } else
3147 bltmode |= 0x01;
3148 }
3149 if (!bltmode) {
3150 /* standard case: forward blitting */
3151 nsrc = (cury * line_length) + curx;
3152 ndest = (desty * line_length) + destx;
3153 } else {
3154 /* this means start addresses are at the end, counting backwards */
3155 nsrc = cury * line_length + curx + nheight * line_length + nwidth;
3156 ndest = desty * line_length + destx + nheight * line_length + nwidth;
3157 }
3158
3159 clgen_WaitBLT(regbase);
3160
3161 /*
3162 run-down of registers to be programmed:
3163 destination pitch
3164 source pitch
3165 BLT width/height
3166 source start
3167 destination start
3168 BLT mode
3169 BLT ROP
3170 VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color"
3171 start/stop
3172 */
3173
3174 /* pitch: set to line_length */
3175 vga_wgfx (regbase, CL_GR24, line_length & 0xff); /* dest pitch low */
3176 vga_wgfx (regbase, CL_GR25, (line_length >> 8)); /* dest pitch hi */
3177 vga_wgfx (regbase, CL_GR26, line_length & 0xff); /* source pitch low */
3178 vga_wgfx (regbase, CL_GR27, (line_length >> 8)); /* source pitch hi */
3179
3180 /* BLT width: actual number of pixels - 1 */
3181 vga_wgfx (regbase, CL_GR20, nwidth & 0xff); /* BLT width low */
3182 vga_wgfx (regbase, CL_GR21, (nwidth >> 8)); /* BLT width hi */
3183
3184 /* BLT height: actual number of lines -1 */
3185 vga_wgfx (regbase, CL_GR22, nheight & 0xff); /* BLT height low */
3186 vga_wgfx (regbase, CL_GR23, (nheight >> 8)); /* BLT width hi */
3187
3188 /* BLT destination */
3189 vga_wgfx (regbase, CL_GR28, (u_char) (ndest & 0xff)); /* BLT dest low */
3190 vga_wgfx (regbase, CL_GR29, (u_char) (ndest >> 8)); /* BLT dest mid */
3191 vga_wgfx (regbase, CL_GR2A, (u_char) (ndest >> 16)); /* BLT dest hi */
3192
3193 /* BLT source */
3194 vga_wgfx (regbase, CL_GR2C, (u_char) (nsrc & 0xff)); /* BLT src low */
3195 vga_wgfx (regbase, CL_GR2D, (u_char) (nsrc >> 8)); /* BLT src mid */
3196 vga_wgfx (regbase, CL_GR2E, (u_char) (nsrc >> 16)); /* BLT src hi */
3197
3198 /* BLT mode */
3199 vga_wgfx (regbase, CL_GR30, bltmode); /* BLT mode */
3200
3201 /* BLT ROP: SrcCopy */
3202 vga_wgfx (regbase, CL_GR32, 0x0d); /* BLT ROP */
3203
3204 /* and finally: GO! */
3205 vga_wgfx (regbase, CL_GR31, 0x02); /* BLT Start/status */
3206
3207 DPRINTK ("EXIT\n");
3208 }
3209
3210
3211 /*******************************************************************
3212 clgen_RectFill()
3213
3214 perform accelerated rectangle fill
3215 ********************************************************************/
3216
clgen_RectFill(struct clgenfb_info * fb_info,u_short x,u_short y,u_short width,u_short height,u_char color,u_short line_length)3217 static void clgen_RectFill (struct clgenfb_info *fb_info,
3218 u_short x, u_short y, u_short width, u_short height,
3219 u_char color, u_short line_length)
3220 {
3221 u_short nwidth, nheight;
3222 u_long ndest;
3223 u_char op;
3224
3225 DPRINTK ("ENTER\n");
3226
3227 nwidth = width - 1;
3228 nheight = height - 1;
3229
3230 ndest = (y * line_length) + x;
3231
3232 clgen_WaitBLT(fb_info->regs);
3233
3234 /* pitch: set to line_length */
3235 vga_wgfx (fb_info->regs, CL_GR24, line_length & 0xff); /* dest pitch low */
3236 vga_wgfx (fb_info->regs, CL_GR25, (line_length >> 8)); /* dest pitch hi */
3237 vga_wgfx (fb_info->regs, CL_GR26, line_length & 0xff); /* source pitch low */
3238 vga_wgfx (fb_info->regs, CL_GR27, (line_length >> 8)); /* source pitch hi */
3239
3240 /* BLT width: actual number of pixels - 1 */
3241 vga_wgfx (fb_info->regs, CL_GR20, nwidth & 0xff); /* BLT width low */
3242 vga_wgfx (fb_info->regs, CL_GR21, (nwidth >> 8)); /* BLT width hi */
3243
3244 /* BLT height: actual number of lines -1 */
3245 vga_wgfx (fb_info->regs, CL_GR22, nheight & 0xff); /* BLT height low */
3246 vga_wgfx (fb_info->regs, CL_GR23, (nheight >> 8)); /* BLT width hi */
3247
3248 /* BLT destination */
3249 vga_wgfx (fb_info->regs, CL_GR28, (u_char) (ndest & 0xff)); /* BLT dest low */
3250 vga_wgfx (fb_info->regs, CL_GR29, (u_char) (ndest >> 8)); /* BLT dest mid */
3251 vga_wgfx (fb_info->regs, CL_GR2A, (u_char) (ndest >> 16)); /* BLT dest hi */
3252
3253 /* BLT source: set to 0 (is a dummy here anyway) */
3254 vga_wgfx (fb_info->regs, CL_GR2C, 0x00); /* BLT src low */
3255 vga_wgfx (fb_info->regs, CL_GR2D, 0x00); /* BLT src mid */
3256 vga_wgfx (fb_info->regs, CL_GR2E, 0x00); /* BLT src hi */
3257
3258 /* This is a ColorExpand Blt, using the */
3259 /* same color for foreground and background */
3260 vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, color); /* foreground color */
3261 vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, color); /* background color */
3262
3263 op = 0xc0;
3264 if (fb_info->currentmode.var.bits_per_pixel == 16) {
3265 vga_wgfx (fb_info->regs, CL_GR10, color); /* foreground color */
3266 vga_wgfx (fb_info->regs, CL_GR11, color); /* background color */
3267 op = 0x50;
3268 op = 0xd0;
3269 } else if (fb_info->currentmode.var.bits_per_pixel == 32) {
3270 vga_wgfx (fb_info->regs, CL_GR10, color); /* foreground color */
3271 vga_wgfx (fb_info->regs, CL_GR11, color); /* background color */
3272 vga_wgfx (fb_info->regs, CL_GR12, color); /* foreground color */
3273 vga_wgfx (fb_info->regs, CL_GR13, color); /* background color */
3274 vga_wgfx (fb_info->regs, CL_GR14, 0); /* foreground color */
3275 vga_wgfx (fb_info->regs, CL_GR15, 0); /* background color */
3276 op = 0x50;
3277 op = 0xf0;
3278 }
3279 /* BLT mode: color expand, Enable 8x8 copy (faster?) */
3280 vga_wgfx (fb_info->regs, CL_GR30, op); /* BLT mode */
3281
3282 /* BLT ROP: SrcCopy */
3283 vga_wgfx (fb_info->regs, CL_GR32, 0x0d); /* BLT ROP */
3284
3285 /* and finally: GO! */
3286 vga_wgfx (fb_info->regs, CL_GR31, 0x02); /* BLT Start/status */
3287
3288 DPRINTK ("EXIT\n");
3289 }
3290
3291
3292 /**************************************************************************
3293 * bestclock() - determine closest possible clock lower(?) than the
3294 * desired pixel clock
3295 **************************************************************************/
bestclock(long freq,long * best,long * nom,long * den,long * div,long maxfreq)3296 static void bestclock (long freq, long *best, long *nom,
3297 long *den, long *div, long maxfreq)
3298 {
3299 long n, h, d, f;
3300
3301 assert (best != NULL);
3302 assert (nom != NULL);
3303 assert (den != NULL);
3304 assert (div != NULL);
3305 assert (maxfreq > 0);
3306
3307 *nom = 0;
3308 *den = 0;
3309 *div = 0;
3310
3311 DPRINTK ("ENTER\n");
3312
3313 if (freq < 8000)
3314 freq = 8000;
3315
3316 if (freq > maxfreq)
3317 freq = maxfreq;
3318
3319 *best = 0;
3320 f = freq * 10;
3321
3322 for (n = 32; n < 128; n++) {
3323 d = (143181 * n) / f;
3324 if ((d >= 7) && (d <= 63)) {
3325 if (d > 31)
3326 d = (d / 2) * 2;
3327 h = (14318 * n) / d;
3328 if (abs (h - freq) < abs (*best - freq)) {
3329 *best = h;
3330 *nom = n;
3331 if (d < 32) {
3332 *den = d;
3333 *div = 0;
3334 } else {
3335 *den = d / 2;
3336 *div = 1;
3337 }
3338 }
3339 }
3340 d = ((143181 * n) + f - 1) / f;
3341 if ((d >= 7) && (d <= 63)) {
3342 if (d > 31)
3343 d = (d / 2) * 2;
3344 h = (14318 * n) / d;
3345 if (abs (h - freq) < abs (*best - freq)) {
3346 *best = h;
3347 *nom = n;
3348 if (d < 32) {
3349 *den = d;
3350 *div = 0;
3351 } else {
3352 *den = d / 2;
3353 *div = 1;
3354 }
3355 }
3356 }
3357 }
3358
3359 DPRINTK ("Best possible values for given frequency:\n");
3360 DPRINTK (" best: %ld kHz nom: %ld den: %ld div: %ld\n",
3361 freq, *nom, *den, *div);
3362
3363 DPRINTK ("EXIT\n");
3364 }
3365
3366
3367 /* -------------------------------------------------------------------------
3368 *
3369 * debugging functions
3370 *
3371 * -------------------------------------------------------------------------
3372 */
3373
3374 #ifdef CLGEN_DEBUG
3375
3376 /**
3377 * clgen_dbg_print_byte
3378 * @name: name associated with byte value to be displayed
3379 * @val: byte value to be displayed
3380 *
3381 * DESCRIPTION:
3382 * Display an indented string, along with a hexidecimal byte value, and
3383 * its decoded bits. Bits 7 through 0 are listed in left-to-right
3384 * order.
3385 */
3386
3387 static
clgen_dbg_print_byte(const char * name,unsigned char val)3388 void clgen_dbg_print_byte (const char *name, unsigned char val)
3389 {
3390 DPRINTK ("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n",
3391 name, val,
3392 val & 0x80 ? '1' : '0',
3393 val & 0x40 ? '1' : '0',
3394 val & 0x20 ? '1' : '0',
3395 val & 0x10 ? '1' : '0',
3396 val & 0x08 ? '1' : '0',
3397 val & 0x04 ? '1' : '0',
3398 val & 0x02 ? '1' : '0',
3399 val & 0x01 ? '1' : '0');
3400 }
3401
3402
3403 /**
3404 * clgen_dbg_print_regs
3405 * @base: If using newmmio, the newmmio base address, otherwise %NULL
3406 * @reg_class: type of registers to read: %CRT, or %SEQ
3407 *
3408 * DESCRIPTION:
3409 * Dumps the given list of VGA CRTC registers. If @base is %NULL,
3410 * old-style I/O ports are queried for information, otherwise MMIO is
3411 * used at the given @base address to query the information.
3412 */
3413
3414 static
clgen_dbg_print_regs(caddr_t regbase,clgen_dbg_reg_class_t reg_class,...)3415 void clgen_dbg_print_regs (caddr_t regbase, clgen_dbg_reg_class_t reg_class,...)
3416 {
3417 va_list list;
3418 unsigned char val = 0;
3419 unsigned reg;
3420 char *name;
3421
3422 va_start (list, reg_class);
3423
3424 name = va_arg (list, char *);
3425 while (name != NULL) {
3426 reg = va_arg (list, int);
3427
3428 switch (reg_class) {
3429 case CRT:
3430 val = vga_rcrt (regbase, (unsigned char) reg);
3431 break;
3432 case SEQ:
3433 val = vga_rseq (regbase, (unsigned char) reg);
3434 break;
3435 default:
3436 /* should never occur */
3437 assert (FALSE);
3438 break;
3439 }
3440
3441 clgen_dbg_print_byte (name, val);
3442
3443 name = va_arg (list, char *);
3444 }
3445
3446 va_end (list);
3447 }
3448
3449
3450 /**
3451 * clgen_dump
3452 * @clgeninfo:
3453 *
3454 * DESCRIPTION:
3455 */
3456
3457 static
clgen_dump(void)3458 void clgen_dump (void)
3459 {
3460 clgen_dbg_reg_dump (NULL);
3461 }
3462
3463
3464 /**
3465 * clgen_dbg_reg_dump
3466 * @base: If using newmmio, the newmmio base address, otherwise %NULL
3467 *
3468 * DESCRIPTION:
3469 * Dumps a list of interesting VGA and CLGEN registers. If @base is %NULL,
3470 * old-style I/O ports are queried for information, otherwise MMIO is
3471 * used at the given @base address to query the information.
3472 */
3473
3474 static
clgen_dbg_reg_dump(caddr_t regbase)3475 void clgen_dbg_reg_dump (caddr_t regbase)
3476 {
3477 DPRINTK ("CLGEN VGA CRTC register dump:\n");
3478
3479 clgen_dbg_print_regs (regbase, CRT,
3480 "CR00", 0x00,
3481 "CR01", 0x01,
3482 "CR02", 0x02,
3483 "CR03", 0x03,
3484 "CR04", 0x04,
3485 "CR05", 0x05,
3486 "CR06", 0x06,
3487 "CR07", 0x07,
3488 "CR08", 0x08,
3489 "CR09", 0x09,
3490 "CR0A", 0x0A,
3491 "CR0B", 0x0B,
3492 "CR0C", 0x0C,
3493 "CR0D", 0x0D,
3494 "CR0E", 0x0E,
3495 "CR0F", 0x0F,
3496 "CR10", 0x10,
3497 "CR11", 0x11,
3498 "CR12", 0x12,
3499 "CR13", 0x13,
3500 "CR14", 0x14,
3501 "CR15", 0x15,
3502 "CR16", 0x16,
3503 "CR17", 0x17,
3504 "CR18", 0x18,
3505 "CR22", 0x22,
3506 "CR24", 0x24,
3507 "CR26", 0x26,
3508 "CR2D", 0x2D,
3509 "CR2E", 0x2E,
3510 "CR2F", 0x2F,
3511 "CR30", 0x30,
3512 "CR31", 0x31,
3513 "CR32", 0x32,
3514 "CR33", 0x33,
3515 "CR34", 0x34,
3516 "CR35", 0x35,
3517 "CR36", 0x36,
3518 "CR37", 0x37,
3519 "CR38", 0x38,
3520 "CR39", 0x39,
3521 "CR3A", 0x3A,
3522 "CR3B", 0x3B,
3523 "CR3C", 0x3C,
3524 "CR3D", 0x3D,
3525 "CR3E", 0x3E,
3526 "CR3F", 0x3F,
3527 NULL);
3528
3529 DPRINTK ("\n");
3530
3531 DPRINTK ("CLGEN VGA SEQ register dump:\n");
3532
3533 clgen_dbg_print_regs (regbase, SEQ,
3534 "SR00", 0x00,
3535 "SR01", 0x01,
3536 "SR02", 0x02,
3537 "SR03", 0x03,
3538 "SR04", 0x04,
3539 "SR08", 0x08,
3540 "SR09", 0x09,
3541 "SR0A", 0x0A,
3542 "SR0B", 0x0B,
3543 "SR0D", 0x0D,
3544 "SR10", 0x10,
3545 "SR11", 0x11,
3546 "SR12", 0x12,
3547 "SR13", 0x13,
3548 "SR14", 0x14,
3549 "SR15", 0x15,
3550 "SR16", 0x16,
3551 "SR17", 0x17,
3552 "SR18", 0x18,
3553 "SR19", 0x19,
3554 "SR1A", 0x1A,
3555 "SR1B", 0x1B,
3556 "SR1C", 0x1C,
3557 "SR1D", 0x1D,
3558 "SR1E", 0x1E,
3559 "SR1F", 0x1F,
3560 NULL);
3561
3562 DPRINTK ("\n");
3563 }
3564
3565 #endif /* CLGEN_DEBUG */
3566
3567