[TG3]: Set minimal hw interrupt mitigation.
[linux-2.6/verdex.git] / drivers / video / cirrusfb.c
bloba3040429c27b7e0d62ca52808b028ebdae211ebc
1 /*
2 * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
4 * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
6 * Contributors (thanks, all!)
8 * David Eger:
9 * Overhaul for Linux 2.6
11 * Jeff Rugen:
12 * Major contributions; Motorola PowerStack (PPC and PCI) support,
13 * GD54xx, 1280x1024 mode support, change MCLK based on VCLK.
15 * Geert Uytterhoeven:
16 * Excellent code review.
18 * Lars Hecking:
19 * Amiga updates and testing.
21 * Original cirrusfb author: Frank Neumann
23 * Based on retz3fb.c and cirrusfb.c:
24 * Copyright (C) 1997 Jes Sorensen
25 * Copyright (C) 1996 Frank Neumann
27 ***************************************************************
29 * Format this code with GNU indent '-kr -i8 -pcs' options.
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.
37 #define CIRRUSFB_VERSION "2.0-pre2"
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>
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_PPC_PREP
63 #include <asm/processor.h>
64 #define isPReP (_machine == _MACH_prep)
65 #else
66 #define isPReP 0
67 #endif
69 #include "video/vga.h"
70 #include "video/cirrus.h"
73 /*****************************************************************
75 * debugging and utility macros
79 /* enable debug output? */
80 /* #define CIRRUSFB_DEBUG 1 */
82 /* disable runtime assertions? */
83 /* #define CIRRUSFB_NDEBUG */
85 /* debug output */
86 #ifdef CIRRUSFB_DEBUG
87 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
88 #else
89 #define DPRINTK(fmt, args...)
90 #endif
92 /* debugging assertions */
93 #ifndef CIRRUSFB_NDEBUG
94 #define assert(expr) \
95 if(!(expr)) { \
96 printk( "Assertion failed! %s,%s,%s,line=%d\n",\
97 #expr,__FILE__,__FUNCTION__,__LINE__); \
99 #else
100 #define assert(expr)
101 #endif
103 #ifdef TRUE
104 #undef TRUE
105 #endif
106 #ifdef FALSE
107 #undef FALSE
108 #endif
109 #define TRUE 1
110 #define FALSE 0
112 #define MB_ (1024*1024)
113 #define KB_ (1024)
115 #define MAX_NUM_BOARDS 7
118 /*****************************************************************
120 * chipset information
124 /* board types */
125 typedef enum {
126 BT_NONE = 0,
127 BT_SD64,
128 BT_PICCOLO,
129 BT_PICASSO,
130 BT_SPECTRUM,
131 BT_PICASSO4, /* GD5446 */
132 BT_ALPINE, /* GD543x/4x */
133 BT_GD5480,
134 BT_LAGUNA, /* GD546x */
135 } cirrusfb_board_t;
139 * per-board-type information, used for enumerating and abstracting
140 * chip-specific information
141 * NOTE: MUST be in the same order as cirrusfb_board_t in order to
142 * use direct indexing on this array
143 * NOTE: '__initdata' cannot be used as some of this info
144 * is required at runtime. Maybe separate into an init-only and
145 * a run-time table?
147 static const struct cirrusfb_board_info_rec {
148 char *name; /* ASCII name of chipset */
149 long maxclock[5]; /* maximum video clock */
150 /* for 1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */
151 unsigned init_sr07 : 1; /* init SR07 during init_vgachip() */
152 unsigned init_sr1f : 1; /* write SR1F during init_vgachip() */
153 unsigned scrn_start_bit19 : 1; /* construct bit 19 of screen start address */
155 /* initial SR07 value, then for each mode */
156 unsigned char sr07;
157 unsigned char sr07_1bpp;
158 unsigned char sr07_1bpp_mux;
159 unsigned char sr07_8bpp;
160 unsigned char sr07_8bpp_mux;
162 unsigned char sr1f; /* SR1F VGA initial register value */
163 } cirrusfb_board_info[] = {
164 [BT_SD64] = {
165 .name = "CL SD64",
166 .maxclock = {
167 /* guess */
168 /* the SD64/P4 have a higher max. videoclock */
169 140000, 140000, 140000, 140000, 140000,
171 .init_sr07 = TRUE,
172 .init_sr1f = TRUE,
173 .scrn_start_bit19 = TRUE,
174 .sr07 = 0xF0,
175 .sr07_1bpp = 0xF0,
176 .sr07_8bpp = 0xF1,
177 .sr1f = 0x20
179 [BT_PICCOLO] = {
180 .name = "CL Piccolo",
181 .maxclock = {
182 /* guess */
183 90000, 90000, 90000, 90000, 90000
185 .init_sr07 = TRUE,
186 .init_sr1f = TRUE,
187 .scrn_start_bit19 = FALSE,
188 .sr07 = 0x80,
189 .sr07_1bpp = 0x80,
190 .sr07_8bpp = 0x81,
191 .sr1f = 0x22
193 [BT_PICASSO] = {
194 .name = "CL Picasso",
195 .maxclock = {
196 /* guess */
197 90000, 90000, 90000, 90000, 90000
199 .init_sr07 = TRUE,
200 .init_sr1f = TRUE,
201 .scrn_start_bit19 = FALSE,
202 .sr07 = 0x20,
203 .sr07_1bpp = 0x20,
204 .sr07_8bpp = 0x21,
205 .sr1f = 0x22
207 [BT_SPECTRUM] = {
208 .name = "CL Spectrum",
209 .maxclock = {
210 /* guess */
211 90000, 90000, 90000, 90000, 90000
213 .init_sr07 = TRUE,
214 .init_sr1f = TRUE,
215 .scrn_start_bit19 = FALSE,
216 .sr07 = 0x80,
217 .sr07_1bpp = 0x80,
218 .sr07_8bpp = 0x81,
219 .sr1f = 0x22
221 [BT_PICASSO4] = {
222 .name = "CL Picasso4",
223 .maxclock = {
224 135100, 135100, 85500, 85500, 0
226 .init_sr07 = TRUE,
227 .init_sr1f = FALSE,
228 .scrn_start_bit19 = TRUE,
229 .sr07 = 0x20,
230 .sr07_1bpp = 0x20,
231 .sr07_8bpp = 0x21,
232 .sr1f = 0
234 [BT_ALPINE] = {
235 .name = "CL Alpine",
236 .maxclock = {
237 /* for the GD5430. GD5446 can do more... */
238 85500, 85500, 50000, 28500, 0
240 .init_sr07 = TRUE,
241 .init_sr1f = TRUE,
242 .scrn_start_bit19 = TRUE,
243 .sr07 = 0xA0,
244 .sr07_1bpp = 0xA1,
245 .sr07_1bpp_mux = 0xA7,
246 .sr07_8bpp = 0xA1,
247 .sr07_8bpp_mux = 0xA7,
248 .sr1f = 0x1C
250 [BT_GD5480] = {
251 .name = "CL GD5480",
252 .maxclock = {
253 135100, 200000, 200000, 135100, 135100
255 .init_sr07 = TRUE,
256 .init_sr1f = TRUE,
257 .scrn_start_bit19 = TRUE,
258 .sr07 = 0x10,
259 .sr07_1bpp = 0x11,
260 .sr07_8bpp = 0x11,
261 .sr1f = 0x1C
263 [BT_LAGUNA] = {
264 .name = "CL Laguna",
265 .maxclock = {
266 /* guess */
267 135100, 135100, 135100, 135100, 135100,
269 .init_sr07 = FALSE,
270 .init_sr1f = FALSE,
271 .scrn_start_bit19 = TRUE,
276 #ifdef CONFIG_PCI
277 #define CHIP(id, btype) \
278 { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_##id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
280 static struct pci_device_id cirrusfb_pci_table[] = {
281 CHIP( CIRRUS_5436, BT_ALPINE ),
282 CHIP( CIRRUS_5434_8, BT_ALPINE ),
283 CHIP( CIRRUS_5434_4, BT_ALPINE ),
284 CHIP( CIRRUS_5430, BT_ALPINE ), /* GD-5440 has identical id */
285 CHIP( CIRRUS_7543, BT_ALPINE ),
286 CHIP( CIRRUS_7548, BT_ALPINE ),
287 CHIP( CIRRUS_5480, BT_GD5480 ), /* MacPicasso probably */
288 CHIP( CIRRUS_5446, BT_PICASSO4 ), /* Picasso 4 is a GD5446 */
289 CHIP( CIRRUS_5462, BT_LAGUNA ), /* CL Laguna */
290 CHIP( CIRRUS_5464, BT_LAGUNA ), /* CL Laguna 3D */
291 CHIP( CIRRUS_5465, BT_LAGUNA ), /* CL Laguna 3DA*/
292 { 0, }
294 MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
295 #undef CHIP
296 #endif /* CONFIG_PCI */
299 #ifdef CONFIG_ZORRO
300 static const struct zorro_device_id cirrusfb_zorro_table[] = {
302 .id = ZORRO_PROD_HELFRICH_SD64_RAM,
303 .driver_data = BT_SD64,
304 }, {
305 .id = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
306 .driver_data = BT_PICCOLO,
307 }, {
308 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
309 .driver_data = BT_PICASSO,
310 }, {
311 .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
312 .driver_data = BT_SPECTRUM,
313 }, {
314 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
315 .driver_data = BT_PICASSO4,
317 { 0 }
320 static const struct {
321 zorro_id id2;
322 unsigned long size;
323 } cirrusfb_zorro_table2[] = {
324 [BT_SD64] = {
325 .id2 = ZORRO_PROD_HELFRICH_SD64_REG,
326 .size = 0x400000
328 [BT_PICCOLO] = {
329 .id2 = ZORRO_PROD_HELFRICH_PICCOLO_REG,
330 .size = 0x200000
332 [BT_PICASSO] = {
333 .id2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
334 .size = 0x200000
336 [BT_SPECTRUM] = {
337 .id2 = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
338 .size = 0x200000
340 [BT_PICASSO4] = {
341 .id2 = 0,
342 .size = 0x400000
345 #endif /* CONFIG_ZORRO */
348 struct cirrusfb_regs {
349 __u32 line_length; /* in BYTES! */
350 __u32 visual;
351 __u32 type;
353 long freq;
354 long nom;
355 long den;
356 long div;
357 long multiplexing;
358 long mclk;
359 long divMCLK;
361 long HorizRes; /* The x resolution in pixel */
362 long HorizTotal;
363 long HorizDispEnd;
364 long HorizBlankStart;
365 long HorizBlankEnd;
366 long HorizSyncStart;
367 long HorizSyncEnd;
369 long VertRes; /* the physical y resolution in scanlines */
370 long VertTotal;
371 long VertDispEnd;
372 long VertSyncStart;
373 long VertSyncEnd;
374 long VertBlankStart;
375 long VertBlankEnd;
380 #ifdef CIRRUSFB_DEBUG
381 typedef enum {
382 CRT,
384 } cirrusfb_dbg_reg_class_t;
385 #endif /* CIRRUSFB_DEBUG */
390 /* info about board */
391 struct cirrusfb_info {
392 struct fb_info *info;
394 u8 __iomem *fbmem;
395 u8 __iomem *regbase;
396 u8 __iomem *mem;
397 unsigned long size;
398 cirrusfb_board_t btype;
399 unsigned char SFR; /* Shadow of special function register */
401 unsigned long fbmem_phys;
402 unsigned long fbregs_phys;
404 struct cirrusfb_regs currentmode;
405 int blank_mode;
407 u32 pseudo_palette[17];
408 struct { u8 red, green, blue, pad; } palette[256];
410 #ifdef CONFIG_ZORRO
411 struct zorro_dev *zdev;
412 #endif
413 #ifdef CONFIG_PCI
414 struct pci_dev *pdev;
415 #endif
416 void (*unmap)(struct cirrusfb_info *cinfo);
420 static unsigned cirrusfb_def_mode = 1;
421 static int noaccel = 0;
424 * Predefined Video Modes
427 static const struct {
428 const char *name;
429 struct fb_var_screeninfo var;
430 } cirrusfb_predefined[] = {
432 /* autodetect mode */
433 .name = "Autodetect",
434 }, {
435 /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
436 .name = "640x480",
437 .var = {
438 .xres = 640,
439 .yres = 480,
440 .xres_virtual = 640,
441 .yres_virtual = 480,
442 .bits_per_pixel = 8,
443 .red = { .length = 8 },
444 .green = { .length = 8 },
445 .blue = { .length = 8 },
446 .width = -1,
447 .height = -1,
448 .pixclock = 40000,
449 .left_margin = 48,
450 .right_margin = 16,
451 .upper_margin = 32,
452 .lower_margin = 8,
453 .hsync_len = 96,
454 .vsync_len = 4,
455 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
456 .vmode = FB_VMODE_NONINTERLACED
458 }, {
459 /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */
460 .name = "800x600",
461 .var = {
462 .xres = 800,
463 .yres = 600,
464 .xres_virtual = 800,
465 .yres_virtual = 600,
466 .bits_per_pixel = 8,
467 .red = { .length = 8 },
468 .green = { .length = 8 },
469 .blue = { .length = 8 },
470 .width = -1,
471 .height = -1,
472 .pixclock = 20000,
473 .left_margin = 128,
474 .right_margin = 16,
475 .upper_margin = 24,
476 .lower_margin = 2,
477 .hsync_len = 96,
478 .vsync_len = 6,
479 .vmode = FB_VMODE_NONINTERLACED
481 }, {
483 * Modeline from XF86Config:
484 * Mode "1024x768" 80 1024 1136 1340 1432 768 770 774 805
486 /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
487 .name = "1024x768",
488 .var = {
489 .xres = 1024,
490 .yres = 768,
491 .xres_virtual = 1024,
492 .yres_virtual = 768,
493 .bits_per_pixel = 8,
494 .red = { .length = 8 },
495 .green = { .length = 8 },
496 .blue = { .length = 8 },
497 .width = -1,
498 .height = -1,
499 .pixclock = 12500,
500 .left_margin = 144,
501 .right_margin = 32,
502 .upper_margin = 30,
503 .lower_margin = 2,
504 .hsync_len = 192,
505 .vsync_len = 6,
506 .vmode = FB_VMODE_NONINTERLACED
511 #define NUM_TOTAL_MODES ARRAY_SIZE(cirrusfb_predefined)
513 /****************************************************************************/
514 /**** BEGIN PROTOTYPES ******************************************************/
517 /*--- Interface used by the world ------------------------------------------*/
518 static int cirrusfb_init (void);
519 #ifndef MODULE
520 static int cirrusfb_setup (char *options);
521 #endif
523 static int cirrusfb_open (struct fb_info *info, int user);
524 static int cirrusfb_release (struct fb_info *info, int user);
525 static int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
526 unsigned blue, unsigned transp,
527 struct fb_info *info);
528 static int cirrusfb_check_var (struct fb_var_screeninfo *var,
529 struct fb_info *info);
530 static int cirrusfb_set_par (struct fb_info *info);
531 static int cirrusfb_pan_display (struct fb_var_screeninfo *var,
532 struct fb_info *info);
533 static int cirrusfb_blank (int blank_mode, struct fb_info *info);
534 static void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *region);
535 static void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
536 static void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image);
538 /* function table of the above functions */
539 static struct fb_ops cirrusfb_ops = {
540 .owner = THIS_MODULE,
541 .fb_open = cirrusfb_open,
542 .fb_release = cirrusfb_release,
543 .fb_setcolreg = cirrusfb_setcolreg,
544 .fb_check_var = cirrusfb_check_var,
545 .fb_set_par = cirrusfb_set_par,
546 .fb_pan_display = cirrusfb_pan_display,
547 .fb_blank = cirrusfb_blank,
548 .fb_fillrect = cirrusfb_fillrect,
549 .fb_copyarea = cirrusfb_copyarea,
550 .fb_imageblit = cirrusfb_imageblit,
551 .fb_cursor = soft_cursor,
554 /*--- Hardware Specific Routines -------------------------------------------*/
555 static int cirrusfb_decode_var (const struct fb_var_screeninfo *var,
556 struct cirrusfb_regs *regs,
557 const struct fb_info *info);
558 /*--- Internal routines ----------------------------------------------------*/
559 static void init_vgachip (struct cirrusfb_info *cinfo);
560 static void switch_monitor (struct cirrusfb_info *cinfo, int on);
561 static void WGen (const struct cirrusfb_info *cinfo,
562 int regnum, unsigned char val);
563 static unsigned char RGen (const struct cirrusfb_info *cinfo, int regnum);
564 static void AttrOn (const struct cirrusfb_info *cinfo);
565 static void WHDR (const struct cirrusfb_info *cinfo, unsigned char val);
566 static void WSFR (struct cirrusfb_info *cinfo, unsigned char val);
567 static void WSFR2 (struct cirrusfb_info *cinfo, unsigned char val);
568 static void WClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
569 unsigned char green,
570 unsigned char blue);
571 #if 0
572 static void RClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
573 unsigned char *green,
574 unsigned char *blue);
575 #endif
576 static void cirrusfb_WaitBLT (u8 __iomem *regbase);
577 static void cirrusfb_BitBLT (u8 __iomem *regbase, int bits_per_pixel,
578 u_short curx, u_short cury,
579 u_short destx, u_short desty,
580 u_short width, u_short height,
581 u_short line_length);
582 static void cirrusfb_RectFill (u8 __iomem *regbase, int bits_per_pixel,
583 u_short x, u_short y,
584 u_short width, u_short height,
585 u_char color, u_short line_length);
587 static void bestclock (long freq, long *best,
588 long *nom, long *den,
589 long *div, long maxfreq);
591 #ifdef CIRRUSFB_DEBUG
592 static void cirrusfb_dump (void);
593 static void cirrusfb_dbg_reg_dump (caddr_t regbase);
594 static void cirrusfb_dbg_print_regs (caddr_t regbase, cirrusfb_dbg_reg_class_t reg_class,...);
595 static void cirrusfb_dbg_print_byte (const char *name, unsigned char val);
596 #endif /* CIRRUSFB_DEBUG */
598 /*** END PROTOTYPES ********************************************************/
599 /*****************************************************************************/
600 /*** BEGIN Interface Used by the World ***************************************/
602 static int opencount = 0;
604 /*--- Open /dev/fbx ---------------------------------------------------------*/
605 static int cirrusfb_open (struct fb_info *info, int user)
607 if (opencount++ == 0)
608 switch_monitor (info->par, 1);
609 return 0;
612 /*--- Close /dev/fbx --------------------------------------------------------*/
613 static int cirrusfb_release (struct fb_info *info, int user)
615 if (--opencount == 0)
616 switch_monitor (info->par, 0);
617 return 0;
620 /**** END Interface used by the World *************************************/
621 /****************************************************************************/
622 /**** BEGIN Hardware specific Routines **************************************/
624 /* Get a good MCLK value */
625 static long cirrusfb_get_mclk (long freq, int bpp, long *div)
627 long mclk;
629 assert (div != NULL);
631 /* Calculate MCLK, in case VCLK is high enough to require > 50MHz.
632 * Assume a 64-bit data path for now. The formula is:
633 * ((B * PCLK * 2)/W) * 1.2
634 * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */
635 mclk = ((bpp / 8) * freq * 2) / 4;
636 mclk = (mclk * 12) / 10;
637 if (mclk < 50000)
638 mclk = 50000;
639 DPRINTK ("Use MCLK of %ld kHz\n", mclk);
641 /* Calculate value for SR1F. Multiply by 2 so we can round up. */
642 mclk = ((mclk * 16) / 14318);
643 mclk = (mclk + 1) / 2;
644 DPRINTK ("Set SR1F[5:0] to 0x%lx\n", mclk);
646 /* Determine if we should use MCLK instead of VCLK, and if so, what we
647 * should divide it by to get VCLK */
648 switch (freq) {
649 case 24751 ... 25249:
650 *div = 2;
651 DPRINTK ("Using VCLK = MCLK/2\n");
652 break;
653 case 49501 ... 50499:
654 *div = 1;
655 DPRINTK ("Using VCLK = MCLK\n");
656 break;
657 default:
658 *div = 0;
659 break;
662 return mclk;
665 static int cirrusfb_check_var(struct fb_var_screeninfo *var,
666 struct fb_info *info)
668 struct cirrusfb_info *cinfo = info->par;
669 int nom, den; /* translyting from pixels->bytes */
670 int yres, i;
671 static struct { int xres, yres; } modes[] =
672 { { 1600, 1280 },
673 { 1280, 1024 },
674 { 1024, 768 },
675 { 800, 600 },
676 { 640, 480 },
677 { -1, -1 } };
679 switch (var->bits_per_pixel) {
680 case 0 ... 1:
681 var->bits_per_pixel = 1;
682 nom = 4;
683 den = 8;
684 break; /* 8 pixel per byte, only 1/4th of mem usable */
685 case 2 ... 8:
686 var->bits_per_pixel = 8;
687 nom = 1;
688 den = 1;
689 break; /* 1 pixel == 1 byte */
690 case 9 ... 16:
691 var->bits_per_pixel = 16;
692 nom = 2;
693 den = 1;
694 break; /* 2 bytes per pixel */
695 case 17 ... 24:
696 var->bits_per_pixel = 24;
697 nom = 3;
698 den = 1;
699 break; /* 3 bytes per pixel */
700 case 25 ... 32:
701 var->bits_per_pixel = 32;
702 nom = 4;
703 den = 1;
704 break; /* 4 bytes per pixel */
705 default:
706 printk ("cirrusfb: mode %dx%dx%d rejected...color depth not supported.\n",
707 var->xres, var->yres, var->bits_per_pixel);
708 DPRINTK ("EXIT - EINVAL error\n");
709 return -EINVAL;
712 if (var->xres * nom / den * var->yres > cinfo->size) {
713 printk ("cirrusfb: mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
714 var->xres, var->yres, var->bits_per_pixel);
715 DPRINTK ("EXIT - EINVAL error\n");
716 return -EINVAL;
719 /* use highest possible virtual resolution */
720 if (var->xres_virtual == -1 &&
721 var->yres_virtual == -1) {
722 printk ("cirrusfb: using maximum available virtual resolution\n");
723 for (i = 0; modes[i].xres != -1; i++) {
724 if (modes[i].xres * nom / den * modes[i].yres < cinfo->size / 2)
725 break;
727 if (modes[i].xres == -1) {
728 printk ("cirrusfb: could not find a virtual resolution that fits into video memory!!\n");
729 DPRINTK ("EXIT - EINVAL error\n");
730 return -EINVAL;
732 var->xres_virtual = modes[i].xres;
733 var->yres_virtual = modes[i].yres;
735 printk ("cirrusfb: virtual resolution set to maximum of %dx%d\n",
736 var->xres_virtual, var->yres_virtual);
739 if (var->xres_virtual < var->xres)
740 var->xres_virtual = var->xres;
741 if (var->yres_virtual < var->yres)
742 var->yres_virtual = var->yres;
744 if (var->xoffset < 0)
745 var->xoffset = 0;
746 if (var->yoffset < 0)
747 var->yoffset = 0;
749 /* truncate xoffset and yoffset to maximum if too high */
750 if (var->xoffset > var->xres_virtual - var->xres)
751 var->xoffset = var->xres_virtual - var->xres - 1;
752 if (var->yoffset > var->yres_virtual - var->yres)
753 var->yoffset = var->yres_virtual - var->yres - 1;
755 switch (var->bits_per_pixel) {
756 case 1:
757 var->red.offset = 0;
758 var->red.length = 1;
759 var->green.offset = 0;
760 var->green.length = 1;
761 var->blue.offset = 0;
762 var->blue.length = 1;
763 break;
765 case 8:
766 var->red.offset = 0;
767 var->red.length = 6;
768 var->green.offset = 0;
769 var->green.length = 6;
770 var->blue.offset = 0;
771 var->blue.length = 6;
772 break;
774 case 16:
775 if(isPReP) {
776 var->red.offset = 2;
777 var->green.offset = -3;
778 var->blue.offset = 8;
779 } else {
780 var->red.offset = 10;
781 var->green.offset = 5;
782 var->blue.offset = 0;
784 var->red.length = 5;
785 var->green.length = 5;
786 var->blue.length = 5;
787 break;
789 case 24:
790 if(isPReP) {
791 var->red.offset = 8;
792 var->green.offset = 16;
793 var->blue.offset = 24;
794 } else {
795 var->red.offset = 16;
796 var->green.offset = 8;
797 var->blue.offset = 0;
799 var->red.length = 8;
800 var->green.length = 8;
801 var->blue.length = 8;
802 break;
804 case 32:
805 if(isPReP) {
806 var->red.offset = 8;
807 var->green.offset = 16;
808 var->blue.offset = 24;
809 } else {
810 var->red.offset = 16;
811 var->green.offset = 8;
812 var->blue.offset = 0;
814 var->red.length = 8;
815 var->green.length = 8;
816 var->blue.length = 8;
817 break;
819 default:
820 DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);
821 assert (FALSE);
822 /* should never occur */
823 break;
826 var->red.msb_right =
827 var->green.msb_right =
828 var->blue.msb_right =
829 var->transp.offset =
830 var->transp.length =
831 var->transp.msb_right = 0;
833 yres = var->yres;
834 if (var->vmode & FB_VMODE_DOUBLE)
835 yres *= 2;
836 else if (var->vmode & FB_VMODE_INTERLACED)
837 yres = (yres + 1) / 2;
839 if (yres >= 1280) {
840 printk (KERN_WARNING "cirrusfb: ERROR: VerticalTotal >= 1280; special treatment required! (TODO)\n");
841 DPRINTK ("EXIT - EINVAL error\n");
842 return -EINVAL;
845 return 0;
848 static int cirrusfb_decode_var (const struct fb_var_screeninfo *var,
849 struct cirrusfb_regs *regs,
850 const struct fb_info *info)
852 long freq;
853 long maxclock;
854 int maxclockidx = 0;
855 struct cirrusfb_info *cinfo = info->par;
856 int xres, hfront, hsync, hback;
857 int yres, vfront, vsync, vback;
859 switch(var->bits_per_pixel) {
860 case 1:
861 regs->line_length = var->xres_virtual / 8;
862 regs->visual = FB_VISUAL_MONO10;
863 maxclockidx = 0;
864 break;
866 case 8:
867 regs->line_length = var->xres_virtual;
868 regs->visual = FB_VISUAL_PSEUDOCOLOR;
869 maxclockidx = 1;
870 break;
872 case 16:
873 regs->line_length = var->xres_virtual * 2;
874 regs->visual = FB_VISUAL_DIRECTCOLOR;
875 maxclockidx = 2;
876 break;
878 case 24:
879 regs->line_length = var->xres_virtual * 3;
880 regs->visual = FB_VISUAL_DIRECTCOLOR;
881 maxclockidx = 3;
882 break;
884 case 32:
885 regs->line_length = var->xres_virtual * 4;
886 regs->visual = FB_VISUAL_DIRECTCOLOR;
887 maxclockidx = 4;
888 break;
890 default:
891 DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);
892 assert (FALSE);
893 /* should never occur */
894 break;
897 regs->type = FB_TYPE_PACKED_PIXELS;
899 /* convert from ps to kHz */
900 freq = 1000000000 / var->pixclock;
902 DPRINTK ("desired pixclock: %ld kHz\n", freq);
904 maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
905 regs->multiplexing = 0;
907 /* If the frequency is greater than we can support, we might be able
908 * to use multiplexing for the video mode */
909 if (freq > maxclock) {
910 switch (cinfo->btype) {
911 case BT_ALPINE:
912 case BT_GD5480:
913 regs->multiplexing = 1;
914 break;
916 default:
917 printk (KERN_WARNING "cirrusfb: ERROR: Frequency greater than maxclock (%ld kHz)\n", maxclock);
918 DPRINTK ("EXIT - return -EINVAL\n");
919 return -EINVAL;
922 #if 0
923 /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
924 * the VCLK is double the pixel clock. */
925 switch (var->bits_per_pixel) {
926 case 16:
927 case 32:
928 if (regs->HorizRes <= 800)
929 freq /= 2; /* Xbh has this type of clock for 32-bit */
930 break;
932 #endif
934 bestclock (freq, &regs->freq, &regs->nom, &regs->den, &regs->div,
935 maxclock);
936 regs->mclk = cirrusfb_get_mclk (freq, var->bits_per_pixel, &regs->divMCLK);
938 xres = var->xres;
939 hfront = var->right_margin;
940 hsync = var->hsync_len;
941 hback = var->left_margin;
943 yres = var->yres;
944 vfront = var->lower_margin;
945 vsync = var->vsync_len;
946 vback = var->upper_margin;
948 if (var->vmode & FB_VMODE_DOUBLE) {
949 yres *= 2;
950 vfront *= 2;
951 vsync *= 2;
952 vback *= 2;
953 } else if (var->vmode & FB_VMODE_INTERLACED) {
954 yres = (yres + 1) / 2;
955 vfront = (vfront + 1) / 2;
956 vsync = (vsync + 1) / 2;
957 vback = (vback + 1) / 2;
959 regs->HorizRes = xres;
960 regs->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5;
961 regs->HorizDispEnd = xres / 8 - 1;
962 regs->HorizBlankStart = xres / 8;
963 regs->HorizBlankEnd = regs->HorizTotal + 5; /* does not count with "-5" */
964 regs->HorizSyncStart = (xres + hfront) / 8 + 1;
965 regs->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1;
967 regs->VertRes = yres;
968 regs->VertTotal = yres + vfront + vsync + vback - 2;
969 regs->VertDispEnd = yres - 1;
970 regs->VertBlankStart = yres;
971 regs->VertBlankEnd = regs->VertTotal;
972 regs->VertSyncStart = yres + vfront - 1;
973 regs->VertSyncEnd = yres + vfront + vsync - 1;
975 if (regs->VertRes >= 1024) {
976 regs->VertTotal /= 2;
977 regs->VertSyncStart /= 2;
978 regs->VertSyncEnd /= 2;
979 regs->VertDispEnd /= 2;
981 if (regs->multiplexing) {
982 regs->HorizTotal /= 2;
983 regs->HorizSyncStart /= 2;
984 regs->HorizSyncEnd /= 2;
985 regs->HorizDispEnd /= 2;
988 return 0;
992 static void cirrusfb_set_mclk (const struct cirrusfb_info *cinfo, int val, int div)
994 assert (cinfo != NULL);
996 if (div == 2) {
997 /* VCLK = MCLK/2 */
998 unsigned char old = vga_rseq (cinfo->regbase, CL_SEQR1E);
999 vga_wseq (cinfo->regbase, CL_SEQR1E, old | 0x1);
1000 vga_wseq (cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
1001 } else if (div == 1) {
1002 /* VCLK = MCLK */
1003 unsigned char old = vga_rseq (cinfo->regbase, CL_SEQR1E);
1004 vga_wseq (cinfo->regbase, CL_SEQR1E, old & ~0x1);
1005 vga_wseq (cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
1006 } else {
1007 vga_wseq (cinfo->regbase, CL_SEQR1F, val & 0x3f);
1011 /*************************************************************************
1012 cirrusfb_set_par_foo()
1014 actually writes the values for a new video mode into the hardware,
1015 **************************************************************************/
1016 static int cirrusfb_set_par_foo (struct fb_info *info)
1018 struct cirrusfb_info *cinfo = info->par;
1019 struct fb_var_screeninfo *var = &info->var;
1020 struct cirrusfb_regs regs;
1021 u8 __iomem *regbase = cinfo->regbase;
1022 unsigned char tmp;
1023 int offset = 0, err;
1024 const struct cirrusfb_board_info_rec *bi;
1026 DPRINTK ("ENTER\n");
1027 DPRINTK ("Requested mode: %dx%dx%d\n",
1028 var->xres, var->yres, var->bits_per_pixel);
1029 DPRINTK ("pixclock: %d\n", var->pixclock);
1031 init_vgachip (cinfo);
1033 err = cirrusfb_decode_var(var, &regs, info);
1034 if(err) {
1035 /* should never happen */
1036 DPRINTK("mode change aborted. invalid var.\n");
1037 return -EINVAL;
1040 bi = &cirrusfb_board_info[cinfo->btype];
1043 /* unlock register VGA_CRTC_H_TOTAL..CRT7 */
1044 vga_wcrt (regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */
1046 /* if debugging is enabled, all parameters get output before writing */
1047 DPRINTK ("CRT0: %ld\n", regs.HorizTotal);
1048 vga_wcrt (regbase, VGA_CRTC_H_TOTAL, regs.HorizTotal);
1050 DPRINTK ("CRT1: %ld\n", regs.HorizDispEnd);
1051 vga_wcrt (regbase, VGA_CRTC_H_DISP, regs.HorizDispEnd);
1053 DPRINTK ("CRT2: %ld\n", regs.HorizBlankStart);
1054 vga_wcrt (regbase, VGA_CRTC_H_BLANK_START, regs.HorizBlankStart);
1056 DPRINTK ("CRT3: 128+%ld\n", regs.HorizBlankEnd % 32); /* + 128: Compatible read */
1057 vga_wcrt (regbase, VGA_CRTC_H_BLANK_END, 128 + (regs.HorizBlankEnd % 32));
1059 DPRINTK ("CRT4: %ld\n", regs.HorizSyncStart);
1060 vga_wcrt (regbase, VGA_CRTC_H_SYNC_START, regs.HorizSyncStart);
1062 tmp = regs.HorizSyncEnd % 32;
1063 if (regs.HorizBlankEnd & 32)
1064 tmp += 128;
1065 DPRINTK ("CRT5: %d\n", tmp);
1066 vga_wcrt (regbase, VGA_CRTC_H_SYNC_END, tmp);
1068 DPRINTK ("CRT6: %ld\n", regs.VertTotal & 0xff);
1069 vga_wcrt (regbase, VGA_CRTC_V_TOTAL, (regs.VertTotal & 0xff));
1071 tmp = 16; /* LineCompare bit #9 */
1072 if (regs.VertTotal & 256)
1073 tmp |= 1;
1074 if (regs.VertDispEnd & 256)
1075 tmp |= 2;
1076 if (regs.VertSyncStart & 256)
1077 tmp |= 4;
1078 if (regs.VertBlankStart & 256)
1079 tmp |= 8;
1080 if (regs.VertTotal & 512)
1081 tmp |= 32;
1082 if (regs.VertDispEnd & 512)
1083 tmp |= 64;
1084 if (regs.VertSyncStart & 512)
1085 tmp |= 128;
1086 DPRINTK ("CRT7: %d\n", tmp);
1087 vga_wcrt (regbase, VGA_CRTC_OVERFLOW, tmp);
1089 tmp = 0x40; /* LineCompare bit #8 */
1090 if (regs.VertBlankStart & 512)
1091 tmp |= 0x20;
1092 if (var->vmode & FB_VMODE_DOUBLE)
1093 tmp |= 0x80;
1094 DPRINTK ("CRT9: %d\n", tmp);
1095 vga_wcrt (regbase, VGA_CRTC_MAX_SCAN, tmp);
1097 DPRINTK ("CRT10: %ld\n", regs.VertSyncStart & 0xff);
1098 vga_wcrt (regbase, VGA_CRTC_V_SYNC_START, (regs.VertSyncStart & 0xff));
1100 DPRINTK ("CRT11: 64+32+%ld\n", regs.VertSyncEnd % 16);
1101 vga_wcrt (regbase, VGA_CRTC_V_SYNC_END, (regs.VertSyncEnd % 16 + 64 + 32));
1103 DPRINTK ("CRT12: %ld\n", regs.VertDispEnd & 0xff);
1104 vga_wcrt (regbase, VGA_CRTC_V_DISP_END, (regs.VertDispEnd & 0xff));
1106 DPRINTK ("CRT15: %ld\n", regs.VertBlankStart & 0xff);
1107 vga_wcrt (regbase, VGA_CRTC_V_BLANK_START, (regs.VertBlankStart & 0xff));
1109 DPRINTK ("CRT16: %ld\n", regs.VertBlankEnd & 0xff);
1110 vga_wcrt (regbase, VGA_CRTC_V_BLANK_END, (regs.VertBlankEnd & 0xff));
1112 DPRINTK ("CRT18: 0xff\n");
1113 vga_wcrt (regbase, VGA_CRTC_LINE_COMPARE, 0xff);
1115 tmp = 0;
1116 if (var->vmode & FB_VMODE_INTERLACED)
1117 tmp |= 1;
1118 if (regs.HorizBlankEnd & 64)
1119 tmp |= 16;
1120 if (regs.HorizBlankEnd & 128)
1121 tmp |= 32;
1122 if (regs.VertBlankEnd & 256)
1123 tmp |= 64;
1124 if (regs.VertBlankEnd & 512)
1125 tmp |= 128;
1127 DPRINTK ("CRT1a: %d\n", tmp);
1128 vga_wcrt (regbase, CL_CRT1A, tmp);
1130 /* set VCLK0 */
1131 /* hardware RefClock: 14.31818 MHz */
1132 /* formula: VClk = (OSC * N) / (D * (1+P)) */
1133 /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
1135 vga_wseq (regbase, CL_SEQRB, regs.nom);
1136 tmp = regs.den << 1;
1137 if (regs.div != 0)
1138 tmp |= 1;
1140 if ((cinfo->btype == BT_SD64) ||
1141 (cinfo->btype == BT_ALPINE) ||
1142 (cinfo->btype == BT_GD5480))
1143 tmp |= 0x80; /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
1145 DPRINTK ("CL_SEQR1B: %ld\n", (long) tmp);
1146 vga_wseq (regbase, CL_SEQR1B, tmp);
1148 if (regs.VertRes >= 1024)
1149 /* 1280x1024 */
1150 vga_wcrt (regbase, VGA_CRTC_MODE, 0xc7);
1151 else
1152 /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
1153 * address wrap, no compat. */
1154 vga_wcrt (regbase, VGA_CRTC_MODE, 0xc3);
1156 /* HAEH? vga_wcrt (regbase, VGA_CRTC_V_SYNC_END, 0x20); * previously: 0x00 unlock VGA_CRTC_H_TOTAL..CRT7 */
1158 /* don't know if it would hurt to also program this if no interlaced */
1159 /* mode is used, but I feel better this way.. :-) */
1160 if (var->vmode & FB_VMODE_INTERLACED)
1161 vga_wcrt (regbase, VGA_CRTC_REGS, regs.HorizTotal / 2);
1162 else
1163 vga_wcrt (regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
1165 vga_wseq (regbase, VGA_SEQ_CHARACTER_MAP, 0);
1167 /* adjust horizontal/vertical sync type (low/high) */
1168 tmp = 0x03; /* enable display memory & CRTC I/O address for color mode */
1169 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1170 tmp |= 0x40;
1171 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1172 tmp |= 0x80;
1173 WGen (cinfo, VGA_MIS_W, tmp);
1175 vga_wcrt (regbase, VGA_CRTC_PRESET_ROW, 0); /* Screen A Preset Row-Scan register */
1176 vga_wcrt (regbase, VGA_CRTC_CURSOR_START, 0); /* text cursor on and start line */
1177 vga_wcrt (regbase, VGA_CRTC_CURSOR_END, 31); /* text cursor end line */
1179 /******************************************************
1181 * 1 bpp
1185 /* programming for different color depths */
1186 if (var->bits_per_pixel == 1) {
1187 DPRINTK ("cirrusfb: preparing for 1 bit deep display\n");
1188 vga_wgfx (regbase, VGA_GFX_MODE, 0); /* mode register */
1190 /* SR07 */
1191 switch (cinfo->btype) {
1192 case BT_SD64:
1193 case BT_PICCOLO:
1194 case BT_PICASSO:
1195 case BT_SPECTRUM:
1196 case BT_PICASSO4:
1197 case BT_ALPINE:
1198 case BT_GD5480:
1199 DPRINTK (" (for GD54xx)\n");
1200 vga_wseq (regbase, CL_SEQR7,
1201 regs.multiplexing ?
1202 bi->sr07_1bpp_mux : bi->sr07_1bpp);
1203 break;
1205 case BT_LAGUNA:
1206 DPRINTK (" (for GD546x)\n");
1207 vga_wseq (regbase, CL_SEQR7,
1208 vga_rseq (regbase, CL_SEQR7) & ~0x01);
1209 break;
1211 default:
1212 printk (KERN_WARNING "cirrusfb: unknown Board\n");
1213 break;
1216 /* Extended Sequencer Mode */
1217 switch (cinfo->btype) {
1218 case BT_SD64:
1219 /* setting the SEQRF on SD64 is not necessary (only during init) */
1220 DPRINTK ("(for SD64)\n");
1221 vga_wseq (regbase, CL_SEQR1F, 0x1a); /* MCLK select */
1222 break;
1224 case BT_PICCOLO:
1225 DPRINTK ("(for Piccolo)\n");
1226 /* ### ueberall 0x22? */
1227 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ##vorher 1c MCLK select */
1228 vga_wseq (regbase, CL_SEQRF, 0xb0); /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
1229 break;
1231 case BT_PICASSO:
1232 DPRINTK ("(for Picasso)\n");
1233 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ##vorher 22 MCLK select */
1234 vga_wseq (regbase, CL_SEQRF, 0xd0); /* ## vorher d0 avoid FIFO underruns..? */
1235 break;
1237 case BT_SPECTRUM:
1238 DPRINTK ("(for Spectrum)\n");
1239 /* ### ueberall 0x22? */
1240 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ##vorher 1c MCLK select */
1241 vga_wseq (regbase, CL_SEQRF, 0xb0); /* evtl d0? avoid FIFO underruns..? */
1242 break;
1244 case BT_PICASSO4:
1245 case BT_ALPINE:
1246 case BT_GD5480:
1247 case BT_LAGUNA:
1248 DPRINTK (" (for GD54xx)\n");
1249 /* do nothing */
1250 break;
1252 default:
1253 printk (KERN_WARNING "cirrusfb: unknown Board\n");
1254 break;
1257 WGen (cinfo, VGA_PEL_MSK, 0x01); /* pixel mask: pass-through for first plane */
1258 if (regs.multiplexing)
1259 WHDR (cinfo, 0x4a); /* hidden dac reg: 1280x1024 */
1260 else
1261 WHDR (cinfo, 0); /* hidden dac: nothing */
1262 vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x06); /* memory mode: odd/even, ext. memory */
1263 vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0x01); /* plane mask: only write to first plane */
1264 offset = var->xres_virtual / 16;
1267 /******************************************************
1269 * 8 bpp
1273 else if (var->bits_per_pixel == 8) {
1274 DPRINTK ("cirrusfb: preparing for 8 bit deep display\n");
1275 switch (cinfo->btype) {
1276 case BT_SD64:
1277 case BT_PICCOLO:
1278 case BT_PICASSO:
1279 case BT_SPECTRUM:
1280 case BT_PICASSO4:
1281 case BT_ALPINE:
1282 case BT_GD5480:
1283 DPRINTK (" (for GD54xx)\n");
1284 vga_wseq (regbase, CL_SEQR7,
1285 regs.multiplexing ?
1286 bi->sr07_8bpp_mux : bi->sr07_8bpp);
1287 break;
1289 case BT_LAGUNA:
1290 DPRINTK (" (for GD546x)\n");
1291 vga_wseq (regbase, CL_SEQR7,
1292 vga_rseq (regbase, CL_SEQR7) | 0x01);
1293 break;
1295 default:
1296 printk (KERN_WARNING "cirrusfb: unknown Board\n");
1297 break;
1300 switch (cinfo->btype) {
1301 case BT_SD64:
1302 vga_wseq (regbase, CL_SEQR1F, 0x1d); /* MCLK select */
1303 break;
1305 case BT_PICCOLO:
1306 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */
1307 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1308 break;
1310 case BT_PICASSO:
1311 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */
1312 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1313 break;
1315 case BT_SPECTRUM:
1316 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */
1317 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1318 break;
1320 case BT_PICASSO4:
1321 #ifdef CONFIG_ZORRO
1322 vga_wseq (regbase, CL_SEQRF, 0xb8); /* ### INCOMPLETE!! */
1323 #endif
1324 /* vga_wseq (regbase, CL_SEQR1F, 0x1c); */
1325 break;
1327 case BT_ALPINE:
1328 DPRINTK (" (for GD543x)\n");
1329 cirrusfb_set_mclk (cinfo, regs.mclk, regs.divMCLK);
1330 /* We already set SRF and SR1F */
1331 break;
1333 case BT_GD5480:
1334 case BT_LAGUNA:
1335 DPRINTK (" (for GD54xx)\n");
1336 /* do nothing */
1337 break;
1339 default:
1340 printk (KERN_WARNING "cirrusfb: unknown Board\n");
1341 break;
1344 vga_wgfx (regbase, VGA_GFX_MODE, 64); /* mode register: 256 color mode */
1345 WGen (cinfo, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */
1346 if (regs.multiplexing)
1347 WHDR (cinfo, 0x4a); /* hidden dac reg: 1280x1024 */
1348 else
1349 WHDR (cinfo, 0); /* hidden dac: nothing */
1350 vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */
1351 vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */
1352 offset = var->xres_virtual / 8;
1355 /******************************************************
1357 * 16 bpp
1361 else if (var->bits_per_pixel == 16) {
1362 DPRINTK ("cirrusfb: preparing for 16 bit deep display\n");
1363 switch (cinfo->btype) {
1364 case BT_SD64:
1365 vga_wseq (regbase, CL_SEQR7, 0xf7); /* Extended Sequencer Mode: 256c col. mode */
1366 vga_wseq (regbase, CL_SEQR1F, 0x1e); /* MCLK select */
1367 break;
1369 case BT_PICCOLO:
1370 vga_wseq (regbase, CL_SEQR7, 0x87);
1371 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1372 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
1373 break;
1375 case BT_PICASSO:
1376 vga_wseq (regbase, CL_SEQR7, 0x27);
1377 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1378 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
1379 break;
1381 case BT_SPECTRUM:
1382 vga_wseq (regbase, CL_SEQR7, 0x87);
1383 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1384 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
1385 break;
1387 case BT_PICASSO4:
1388 vga_wseq (regbase, CL_SEQR7, 0x27);
1389 /* vga_wseq (regbase, CL_SEQR1F, 0x1c); */
1390 break;
1392 case BT_ALPINE:
1393 DPRINTK (" (for GD543x)\n");
1394 if (regs.HorizRes >= 1024)
1395 vga_wseq (regbase, CL_SEQR7, 0xa7);
1396 else
1397 vga_wseq (regbase, CL_SEQR7, 0xa3);
1398 cirrusfb_set_mclk (cinfo, regs.mclk, regs.divMCLK);
1399 break;
1401 case BT_GD5480:
1402 DPRINTK (" (for GD5480)\n");
1403 vga_wseq (regbase, CL_SEQR7, 0x17);
1404 /* We already set SRF and SR1F */
1405 break;
1407 case BT_LAGUNA:
1408 DPRINTK (" (for GD546x)\n");
1409 vga_wseq (regbase, CL_SEQR7,
1410 vga_rseq (regbase, CL_SEQR7) & ~0x01);
1411 break;
1413 default:
1414 printk (KERN_WARNING "CIRRUSFB: unknown Board\n");
1415 break;
1418 vga_wgfx (regbase, VGA_GFX_MODE, 64); /* mode register: 256 color mode */
1419 WGen (cinfo, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */
1420 #ifdef CONFIG_PCI
1421 WHDR (cinfo, 0xc0); /* Copy Xbh */
1422 #elif defined(CONFIG_ZORRO)
1423 /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
1424 WHDR (cinfo, 0xa0); /* hidden dac reg: nothing special */
1425 #endif
1426 vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */
1427 vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */
1428 offset = var->xres_virtual / 4;
1431 /******************************************************
1433 * 32 bpp
1437 else if (var->bits_per_pixel == 32) {
1438 DPRINTK ("cirrusfb: preparing for 24/32 bit deep display\n");
1439 switch (cinfo->btype) {
1440 case BT_SD64:
1441 vga_wseq (regbase, CL_SEQR7, 0xf9); /* Extended Sequencer Mode: 256c col. mode */
1442 vga_wseq (regbase, CL_SEQR1F, 0x1e); /* MCLK select */
1443 break;
1445 case BT_PICCOLO:
1446 vga_wseq (regbase, CL_SEQR7, 0x85);
1447 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1448 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
1449 break;
1451 case BT_PICASSO:
1452 vga_wseq (regbase, CL_SEQR7, 0x25);
1453 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1454 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
1455 break;
1457 case BT_SPECTRUM:
1458 vga_wseq (regbase, CL_SEQR7, 0x85);
1459 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1460 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
1461 break;
1463 case BT_PICASSO4:
1464 vga_wseq (regbase, CL_SEQR7, 0x25);
1465 /* vga_wseq (regbase, CL_SEQR1F, 0x1c); */
1466 break;
1468 case BT_ALPINE:
1469 DPRINTK (" (for GD543x)\n");
1470 vga_wseq (regbase, CL_SEQR7, 0xa9);
1471 cirrusfb_set_mclk (cinfo, regs.mclk, regs.divMCLK);
1472 break;
1474 case BT_GD5480:
1475 DPRINTK (" (for GD5480)\n");
1476 vga_wseq (regbase, CL_SEQR7, 0x19);
1477 /* We already set SRF and SR1F */
1478 break;
1480 case BT_LAGUNA:
1481 DPRINTK (" (for GD546x)\n");
1482 vga_wseq (regbase, CL_SEQR7,
1483 vga_rseq (regbase, CL_SEQR7) & ~0x01);
1484 break;
1486 default:
1487 printk (KERN_WARNING "cirrusfb: unknown Board\n");
1488 break;
1491 vga_wgfx (regbase, VGA_GFX_MODE, 64); /* mode register: 256 color mode */
1492 WGen (cinfo, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */
1493 WHDR (cinfo, 0xc5); /* hidden dac reg: 8-8-8 mode (24 or 32) */
1494 vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */
1495 vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */
1496 offset = var->xres_virtual / 4;
1499 /******************************************************
1501 * unknown/unsupported bpp
1505 else {
1506 printk (KERN_ERR "cirrusfb: What's this?? requested color depth == %d.\n",
1507 var->bits_per_pixel);
1510 vga_wcrt (regbase, VGA_CRTC_OFFSET, offset & 0xff);
1511 tmp = 0x22;
1512 if (offset & 0x100)
1513 tmp |= 0x10; /* offset overflow bit */
1515 vga_wcrt (regbase, CL_CRT1B, tmp); /* screen start addr #16-18, fastpagemode cycles */
1517 if (cinfo->btype == BT_SD64 ||
1518 cinfo->btype == BT_PICASSO4 ||
1519 cinfo->btype == BT_ALPINE ||
1520 cinfo->btype == BT_GD5480)
1521 vga_wcrt (regbase, CL_CRT1D, 0x00); /* screen start address bit 19 */
1523 vga_wcrt (regbase, VGA_CRTC_CURSOR_HI, 0); /* text cursor location high */
1524 vga_wcrt (regbase, VGA_CRTC_CURSOR_LO, 0); /* text cursor location low */
1525 vga_wcrt (regbase, VGA_CRTC_UNDERLINE, 0); /* underline row scanline = at very bottom */
1527 vga_wattr (regbase, VGA_ATC_MODE, 1); /* controller mode */
1528 vga_wattr (regbase, VGA_ATC_OVERSCAN, 0); /* overscan (border) color */
1529 vga_wattr (regbase, VGA_ATC_PLANE_ENABLE, 15); /* color plane enable */
1530 vga_wattr (regbase, CL_AR33, 0); /* pixel panning */
1531 vga_wattr (regbase, VGA_ATC_COLOR_PAGE, 0); /* color select */
1533 /* [ EGS: SetOffset(); ] */
1534 /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
1535 AttrOn (cinfo);
1537 vga_wgfx (regbase, VGA_GFX_SR_VALUE, 0); /* set/reset register */
1538 vga_wgfx (regbase, VGA_GFX_SR_ENABLE, 0); /* set/reset enable */
1539 vga_wgfx (regbase, VGA_GFX_COMPARE_VALUE, 0); /* color compare */
1540 vga_wgfx (regbase, VGA_GFX_DATA_ROTATE, 0); /* data rotate */
1541 vga_wgfx (regbase, VGA_GFX_PLANE_READ, 0); /* read map select */
1542 vga_wgfx (regbase, VGA_GFX_MISC, 1); /* miscellaneous register */
1543 vga_wgfx (regbase, VGA_GFX_COMPARE_MASK, 15); /* color don't care */
1544 vga_wgfx (regbase, VGA_GFX_BIT_MASK, 255); /* bit mask */
1546 vga_wseq (regbase, CL_SEQR12, 0x0); /* graphics cursor attributes: nothing special */
1548 /* finally, turn on everything - turn off "FullBandwidth" bit */
1549 /* also, set "DotClock%2" bit where requested */
1550 tmp = 0x01;
1552 /*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
1553 if (var->vmode & FB_VMODE_CLOCK_HALVE)
1554 tmp |= 0x08;
1557 vga_wseq (regbase, VGA_SEQ_CLOCK_MODE, tmp);
1558 DPRINTK ("CL_SEQR1: %d\n", tmp);
1560 cinfo->currentmode = regs;
1561 info->fix.type = regs.type;
1562 info->fix.visual = regs.visual;
1563 info->fix.line_length = regs.line_length;
1565 /* pan to requested offset */
1566 cirrusfb_pan_display (var, info);
1568 #ifdef CIRRUSFB_DEBUG
1569 cirrusfb_dump ();
1570 #endif
1572 DPRINTK ("EXIT\n");
1573 return 0;
1576 /* for some reason incomprehensible to me, cirrusfb requires that you write
1577 * the registers twice for the settings to take..grr. -dte */
1578 static int cirrusfb_set_par (struct fb_info *info)
1580 cirrusfb_set_par_foo (info);
1581 return cirrusfb_set_par_foo (info);
1584 static int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
1585 unsigned blue, unsigned transp,
1586 struct fb_info *info)
1588 struct cirrusfb_info *cinfo = info->par;
1590 if (regno > 255)
1591 return -EINVAL;
1593 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
1594 u32 v;
1595 red >>= (16 - info->var.red.length);
1596 green >>= (16 - info->var.green.length);
1597 blue >>= (16 - info->var.blue.length);
1599 if (regno>=16)
1600 return 1;
1601 v = (red << info->var.red.offset) |
1602 (green << info->var.green.offset) |
1603 (blue << info->var.blue.offset);
1605 switch (info->var.bits_per_pixel) {
1606 case 8:
1607 ((u8*)(info->pseudo_palette))[regno] = v;
1608 break;
1609 case 16:
1610 ((u16*)(info->pseudo_palette))[regno] = v;
1611 break;
1612 case 24:
1613 case 32:
1614 ((u32*)(info->pseudo_palette))[regno] = v;
1615 break;
1617 return 0;
1620 cinfo->palette[regno].red = red;
1621 cinfo->palette[regno].green = green;
1622 cinfo->palette[regno].blue = blue;
1624 if (info->var.bits_per_pixel == 8) {
1625 WClut (cinfo, regno, red >> 10, green >> 10, blue >> 10);
1628 return 0;
1632 /*************************************************************************
1633 cirrusfb_pan_display()
1635 performs display panning - provided hardware permits this
1636 **************************************************************************/
1637 static int cirrusfb_pan_display (struct fb_var_screeninfo *var,
1638 struct fb_info *info)
1640 int xoffset = 0;
1641 int yoffset = 0;
1642 unsigned long base;
1643 unsigned char tmp = 0, tmp2 = 0, xpix;
1644 struct cirrusfb_info *cinfo = info->par;
1646 DPRINTK ("ENTER\n");
1647 DPRINTK ("virtual offset: (%d,%d)\n", var->xoffset, var->yoffset);
1649 /* no range checks for xoffset and yoffset, */
1650 /* as fb_pan_display has already done this */
1651 if (var->vmode & FB_VMODE_YWRAP)
1652 return -EINVAL;
1654 info->var.xoffset = var->xoffset;
1655 info->var.yoffset = var->yoffset;
1657 xoffset = var->xoffset * info->var.bits_per_pixel / 8;
1658 yoffset = var->yoffset;
1660 base = yoffset * cinfo->currentmode.line_length + xoffset;
1662 if (info->var.bits_per_pixel == 1) {
1663 /* base is already correct */
1664 xpix = (unsigned char) (var->xoffset % 8);
1665 } else {
1666 base /= 4;
1667 xpix = (unsigned char) ((xoffset % 4) * 2);
1670 cirrusfb_WaitBLT(cinfo->regbase); /* make sure all the BLT's are done */
1672 /* lower 8 + 8 bits of screen start address */
1673 vga_wcrt (cinfo->regbase, VGA_CRTC_START_LO, (unsigned char) (base & 0xff));
1674 vga_wcrt (cinfo->regbase, VGA_CRTC_START_HI, (unsigned char) (base >> 8));
1676 /* construct bits 16, 17 and 18 of screen start address */
1677 if (base & 0x10000)
1678 tmp |= 0x01;
1679 if (base & 0x20000)
1680 tmp |= 0x04;
1681 if (base & 0x40000)
1682 tmp |= 0x08;
1684 tmp2 = (vga_rcrt (cinfo->regbase, CL_CRT1B) & 0xf2) | tmp; /* 0xf2 is %11110010, exclude tmp bits */
1685 vga_wcrt (cinfo->regbase, CL_CRT1B, tmp2);
1687 /* construct bit 19 of screen start address */
1688 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) {
1689 tmp2 = 0;
1690 if (base & 0x80000)
1691 tmp2 = 0x80;
1692 vga_wcrt (cinfo->regbase, CL_CRT1D, tmp2);
1695 /* write pixel panning value to AR33; this does not quite work in 8bpp */
1696 /* ### Piccolo..? Will this work? */
1697 if (info->var.bits_per_pixel == 1)
1698 vga_wattr (cinfo->regbase, CL_AR33, xpix);
1700 cirrusfb_WaitBLT (cinfo->regbase);
1702 DPRINTK ("EXIT\n");
1703 return (0);
1707 static int cirrusfb_blank (int blank_mode, struct fb_info *info)
1710 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
1711 * then the caller blanks by setting the CLUT (Color Look Up Table) to all
1712 * black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
1713 * to e.g. a video mode which doesn't support it. Implements VESA suspend
1714 * and powerdown modes on hardware that supports disabling hsync/vsync:
1715 * blank_mode == 2: suspend vsync
1716 * blank_mode == 3: suspend hsync
1717 * blank_mode == 4: powerdown
1719 unsigned char val;
1720 struct cirrusfb_info *cinfo = info->par;
1721 int current_mode = cinfo->blank_mode;
1723 DPRINTK ("ENTER, blank mode = %d\n", blank_mode);
1725 if (info->state != FBINFO_STATE_RUNNING ||
1726 current_mode == blank_mode) {
1727 DPRINTK ("EXIT, returning 0\n");
1728 return 0;
1731 /* Undo current */
1732 if (current_mode == FB_BLANK_NORMAL ||
1733 current_mode == FB_BLANK_UNBLANK) {
1734 /* unblank the screen */
1735 val = vga_rseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1736 vga_wseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE, val & 0xdf); /* clear "FullBandwidth" bit */
1737 /* and undo VESA suspend trickery */
1738 vga_wgfx (cinfo->regbase, CL_GRE, 0x00);
1741 /* set new */
1742 if(blank_mode > FB_BLANK_NORMAL) {
1743 /* blank the screen */
1744 val = vga_rseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1745 vga_wseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE, val | 0x20); /* set "FullBandwidth" bit */
1748 switch (blank_mode) {
1749 case FB_BLANK_UNBLANK:
1750 case FB_BLANK_NORMAL:
1751 break;
1752 case FB_BLANK_VSYNC_SUSPEND:
1753 vga_wgfx (cinfo->regbase, CL_GRE, 0x04);
1754 break;
1755 case FB_BLANK_HSYNC_SUSPEND:
1756 vga_wgfx (cinfo->regbase, CL_GRE, 0x02);
1757 break;
1758 case FB_BLANK_POWERDOWN:
1759 vga_wgfx (cinfo->regbase, CL_GRE, 0x06);
1760 break;
1761 default:
1762 DPRINTK ("EXIT, returning 1\n");
1763 return 1;
1766 cinfo->blank_mode = blank_mode;
1767 DPRINTK ("EXIT, returning 0\n");
1769 /* Let fbcon do a soft blank for us */
1770 return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
1772 /**** END Hardware specific Routines **************************************/
1773 /****************************************************************************/
1774 /**** BEGIN Internal Routines ***********************************************/
1776 static void init_vgachip (struct cirrusfb_info *cinfo)
1778 const struct cirrusfb_board_info_rec *bi;
1780 DPRINTK ("ENTER\n");
1782 assert (cinfo != NULL);
1784 bi = &cirrusfb_board_info[cinfo->btype];
1786 /* reset board globally */
1787 switch (cinfo->btype) {
1788 case BT_PICCOLO:
1789 WSFR (cinfo, 0x01);
1790 udelay (500);
1791 WSFR (cinfo, 0x51);
1792 udelay (500);
1793 break;
1794 case BT_PICASSO:
1795 WSFR2 (cinfo, 0xff);
1796 udelay (500);
1797 break;
1798 case BT_SD64:
1799 case BT_SPECTRUM:
1800 WSFR (cinfo, 0x1f);
1801 udelay (500);
1802 WSFR (cinfo, 0x4f);
1803 udelay (500);
1804 break;
1805 case BT_PICASSO4:
1806 vga_wcrt (cinfo->regbase, CL_CRT51, 0x00); /* disable flickerfixer */
1807 mdelay (100);
1808 vga_wgfx (cinfo->regbase, CL_GR2F, 0x00); /* from Klaus' NetBSD driver: */
1809 vga_wgfx (cinfo->regbase, CL_GR33, 0x00); /* put blitter into 542x compat */
1810 vga_wgfx (cinfo->regbase, CL_GR31, 0x00); /* mode */
1811 break;
1813 case BT_GD5480:
1814 vga_wgfx (cinfo->regbase, CL_GR2F, 0x00); /* from Klaus' NetBSD driver: */
1815 break;
1817 case BT_ALPINE:
1818 /* Nothing to do to reset the board. */
1819 break;
1821 default:
1822 printk (KERN_ERR "cirrusfb: Warning: Unknown board type\n");
1823 break;
1826 assert (cinfo->size > 0); /* make sure RAM size set by this point */
1828 /* the P4 is not fully initialized here; I rely on it having been */
1829 /* inited under AmigaOS already, which seems to work just fine */
1830 /* (Klaus advised to do it this way) */
1832 if (cinfo->btype != BT_PICASSO4) {
1833 WGen (cinfo, CL_VSSM, 0x10); /* EGS: 0x16 */
1834 WGen (cinfo, CL_POS102, 0x01);
1835 WGen (cinfo, CL_VSSM, 0x08); /* EGS: 0x0e */
1837 if (cinfo->btype != BT_SD64)
1838 WGen (cinfo, CL_VSSM2, 0x01);
1840 vga_wseq (cinfo->regbase, CL_SEQR0, 0x03); /* reset sequencer logic */
1842 vga_wseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21); /* FullBandwidth (video off) and 8/9 dot clock */
1843 WGen (cinfo, VGA_MIS_W, 0xc1); /* polarity (-/-), disable access to display memory, VGA_CRTC_START_HI base address: color */
1845 /* vga_wgfx (cinfo->regbase, CL_GRA, 0xce); "magic cookie" - doesn't make any sense to me.. */
1846 vga_wseq (cinfo->regbase, CL_SEQR6, 0x12); /* unlock all extension registers */
1848 vga_wgfx (cinfo->regbase, CL_GR31, 0x04); /* reset blitter */
1850 switch (cinfo->btype) {
1851 case BT_GD5480:
1852 vga_wseq (cinfo->regbase, CL_SEQRF, 0x98);
1853 break;
1854 case BT_ALPINE:
1855 break;
1856 case BT_SD64:
1857 vga_wseq (cinfo->regbase, CL_SEQRF, 0xb8);
1858 break;
1859 default:
1860 vga_wseq (cinfo->regbase, CL_SEQR16, 0x0f);
1861 vga_wseq (cinfo->regbase, CL_SEQRF, 0xb0);
1862 break;
1865 vga_wseq (cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: nothing */
1866 vga_wseq (cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00); /* character map select: doesn't even matter in gx mode */
1867 vga_wseq (cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0e); /* memory mode: chain-4, no odd/even, ext. memory */
1869 /* controller-internal base address of video memory */
1870 if (bi->init_sr07)
1871 vga_wseq (cinfo->regbase, CL_SEQR7, bi->sr07);
1873 /* vga_wseq (cinfo->regbase, CL_SEQR8, 0x00); *//* EEPROM control: shouldn't be necessary to write to this at all.. */
1875 vga_wseq (cinfo->regbase, CL_SEQR10, 0x00); /* graphics cursor X position (incomplete; position gives rem. 3 bits */
1876 vga_wseq (cinfo->regbase, CL_SEQR11, 0x00); /* graphics cursor Y position (..."... ) */
1877 vga_wseq (cinfo->regbase, CL_SEQR12, 0x00); /* graphics cursor attributes */
1878 vga_wseq (cinfo->regbase, CL_SEQR13, 0x00); /* graphics cursor pattern address */
1880 /* writing these on a P4 might give problems.. */
1881 if (cinfo->btype != BT_PICASSO4) {
1882 vga_wseq (cinfo->regbase, CL_SEQR17, 0x00); /* configuration readback and ext. color */
1883 vga_wseq (cinfo->regbase, CL_SEQR18, 0x02); /* signature generator */
1886 /* MCLK select etc. */
1887 if (bi->init_sr1f)
1888 vga_wseq (cinfo->regbase, CL_SEQR1F, bi->sr1f);
1890 vga_wcrt (cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00); /* Screen A preset row scan: none */
1891 vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20); /* Text cursor start: disable text cursor */
1892 vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00); /* Text cursor end: - */
1893 vga_wcrt (cinfo->regbase, VGA_CRTC_START_HI, 0x00); /* Screen start address high: 0 */
1894 vga_wcrt (cinfo->regbase, VGA_CRTC_START_LO, 0x00); /* Screen start address low: 0 */
1895 vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00); /* text cursor location high: 0 */
1896 vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00); /* text cursor location low: 0 */
1898 vga_wcrt (cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00); /* Underline Row scanline: - */
1899 vga_wcrt (cinfo->regbase, VGA_CRTC_MODE, 0xc3); /* mode control: timing enable, byte mode, no compat modes */
1900 vga_wcrt (cinfo->regbase, VGA_CRTC_LINE_COMPARE, 0x00); /* Line Compare: not needed */
1901 /* ### add 0x40 for text modes with > 30 MHz pixclock */
1902 vga_wcrt (cinfo->regbase, CL_CRT1B, 0x02); /* ext. display controls: ext.adr. wrap */
1904 vga_wgfx (cinfo->regbase, VGA_GFX_SR_VALUE, 0x00); /* Set/Reset registes: - */
1905 vga_wgfx (cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00); /* Set/Reset enable: - */
1906 vga_wgfx (cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00); /* Color Compare: - */
1907 vga_wgfx (cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00); /* Data Rotate: - */
1908 vga_wgfx (cinfo->regbase, VGA_GFX_PLANE_READ, 0x00); /* Read Map Select: - */
1909 vga_wgfx (cinfo->regbase, VGA_GFX_MODE, 0x00); /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
1910 vga_wgfx (cinfo->regbase, VGA_GFX_MISC, 0x01); /* Miscellaneous: memory map base address, graphics mode */
1911 vga_wgfx (cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f); /* Color Don't care: involve all planes */
1912 vga_wgfx (cinfo->regbase, VGA_GFX_BIT_MASK, 0xff); /* Bit Mask: no mask at all */
1913 if (cinfo->btype == BT_ALPINE)
1914 vga_wgfx (cinfo->regbase, CL_GRB, 0x20); /* (5434 can't have bit 3 set for bitblt) */
1915 else
1916 vga_wgfx (cinfo->regbase, CL_GRB, 0x28); /* Graphics controller mode extensions: finer granularity, 8byte data latches */
1918 vga_wgfx (cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */
1919 vga_wgfx (cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */
1920 vga_wgfx (cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */
1921 /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); *//* Background color byte 1: - */
1922 /* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
1924 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE0, 0x00); /* Attribute Controller palette registers: "identity mapping" */
1925 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
1926 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
1927 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
1928 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
1929 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
1930 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
1931 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
1932 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
1933 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
1934 vga_wattr (cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
1935 vga_wattr (cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
1936 vga_wattr (cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
1937 vga_wattr (cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
1938 vga_wattr (cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
1939 vga_wattr (cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
1941 vga_wattr (cinfo->regbase, VGA_ATC_MODE, 0x01); /* Attribute Controller mode: graphics mode */
1942 vga_wattr (cinfo->regbase, VGA_ATC_OVERSCAN, 0x00); /* Overscan color reg.: reg. 0 */
1943 vga_wattr (cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f); /* Color Plane enable: Enable all 4 planes */
1944 /* ### vga_wattr (cinfo->regbase, CL_AR33, 0x00); * Pixel Panning: - */
1945 vga_wattr (cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00); /* Color Select: - */
1947 WGen (cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
1949 if (cinfo->btype != BT_ALPINE && cinfo->btype != BT_GD5480)
1950 WGen (cinfo, VGA_MIS_W, 0xc3); /* polarity (-/-), enable display mem, VGA_CRTC_START_HI i/o base = color */
1952 vga_wgfx (cinfo->regbase, CL_GR31, 0x04); /* BLT Start/status: Blitter reset */
1953 vga_wgfx (cinfo->regbase, CL_GR31, 0x00); /* - " - : "end-of-reset" */
1955 /* misc... */
1956 WHDR (cinfo, 0); /* Hidden DAC register: - */
1958 printk (KERN_DEBUG "cirrusfb: This board has %ld bytes of DRAM memory\n", cinfo->size);
1959 DPRINTK ("EXIT\n");
1960 return;
1963 static void switch_monitor (struct cirrusfb_info *cinfo, int on)
1965 #ifdef CONFIG_ZORRO /* only works on Zorro boards */
1966 static int IsOn = 0; /* XXX not ok for multiple boards */
1968 DPRINTK ("ENTER\n");
1970 if (cinfo->btype == BT_PICASSO4)
1971 return; /* nothing to switch */
1972 if (cinfo->btype == BT_ALPINE)
1973 return; /* nothing to switch */
1974 if (cinfo->btype == BT_GD5480)
1975 return; /* nothing to switch */
1976 if (cinfo->btype == BT_PICASSO) {
1977 if ((on && !IsOn) || (!on && IsOn))
1978 WSFR (cinfo, 0xff);
1980 DPRINTK ("EXIT\n");
1981 return;
1983 if (on) {
1984 switch (cinfo->btype) {
1985 case BT_SD64:
1986 WSFR (cinfo, cinfo->SFR | 0x21);
1987 break;
1988 case BT_PICCOLO:
1989 WSFR (cinfo, cinfo->SFR | 0x28);
1990 break;
1991 case BT_SPECTRUM:
1992 WSFR (cinfo, 0x6f);
1993 break;
1994 default: /* do nothing */ break;
1996 } else {
1997 switch (cinfo->btype) {
1998 case BT_SD64:
1999 WSFR (cinfo, cinfo->SFR & 0xde);
2000 break;
2001 case BT_PICCOLO:
2002 WSFR (cinfo, cinfo->SFR & 0xd7);
2003 break;
2004 case BT_SPECTRUM:
2005 WSFR (cinfo, 0x4f);
2006 break;
2007 default: /* do nothing */ break;
2011 DPRINTK ("EXIT\n");
2012 #endif /* CONFIG_ZORRO */
2016 /******************************************/
2017 /* Linux 2.6-style accelerated functions */
2018 /******************************************/
2020 static void cirrusfb_prim_fillrect(struct cirrusfb_info *cinfo,
2021 const struct fb_fillrect *region)
2023 int m; /* bytes per pixel */
2024 if(cinfo->info->var.bits_per_pixel == 1) {
2025 cirrusfb_RectFill(cinfo->regbase, cinfo->info->var.bits_per_pixel,
2026 region->dx / 8, region->dy,
2027 region->width / 8, region->height,
2028 region->color,
2029 cinfo->currentmode.line_length);
2030 } else {
2031 m = ( cinfo->info->var.bits_per_pixel + 7 ) / 8;
2032 cirrusfb_RectFill(cinfo->regbase, cinfo->info->var.bits_per_pixel,
2033 region->dx * m, region->dy,
2034 region->width * m, region->height,
2035 region->color,
2036 cinfo->currentmode.line_length);
2038 return;
2041 static void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *region)
2043 struct cirrusfb_info *cinfo = info->par;
2044 struct fb_fillrect modded;
2045 int vxres, vyres;
2047 if (info->state != FBINFO_STATE_RUNNING)
2048 return;
2049 if (info->flags & FBINFO_HWACCEL_DISABLED) {
2050 cfb_fillrect(info, region);
2051 return;
2054 vxres = info->var.xres_virtual;
2055 vyres = info->var.yres_virtual;
2057 memcpy(&modded, region, sizeof(struct fb_fillrect));
2059 if(!modded.width || !modded.height ||
2060 modded.dx >= vxres || modded.dy >= vyres)
2061 return;
2063 if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx;
2064 if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
2066 cirrusfb_prim_fillrect(cinfo, &modded);
2069 static void cirrusfb_prim_copyarea(struct cirrusfb_info *cinfo,
2070 const struct fb_copyarea *area)
2072 int m; /* bytes per pixel */
2073 if(cinfo->info->var.bits_per_pixel == 1) {
2074 cirrusfb_BitBLT(cinfo->regbase, cinfo->info->var.bits_per_pixel,
2075 area->sx / 8, area->sy,
2076 area->dx / 8, area->dy,
2077 area->width / 8, area->height,
2078 cinfo->currentmode.line_length);
2079 } else {
2080 m = ( cinfo->info->var.bits_per_pixel + 7 ) / 8;
2081 cirrusfb_BitBLT(cinfo->regbase, cinfo->info->var.bits_per_pixel,
2082 area->sx * m, area->sy,
2083 area->dx * m, area->dy,
2084 area->width * m, area->height,
2085 cinfo->currentmode.line_length);
2087 return;
2091 static void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
2093 struct cirrusfb_info *cinfo = info->par;
2094 struct fb_copyarea modded;
2095 u32 vxres, vyres;
2096 modded.sx = area->sx;
2097 modded.sy = area->sy;
2098 modded.dx = area->dx;
2099 modded.dy = area->dy;
2100 modded.width = area->width;
2101 modded.height = area->height;
2103 if (info->state != FBINFO_STATE_RUNNING)
2104 return;
2105 if (info->flags & FBINFO_HWACCEL_DISABLED) {
2106 cfb_copyarea(info, area);
2107 return;
2110 vxres = info->var.xres_virtual;
2111 vyres = info->var.yres_virtual;
2113 if(!modded.width || !modded.height ||
2114 modded.sx >= vxres || modded.sy >= vyres ||
2115 modded.dx >= vxres || modded.dy >= vyres)
2116 return;
2118 if(modded.sx + modded.width > vxres) modded.width = vxres - modded.sx;
2119 if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx;
2120 if(modded.sy + modded.height > vyres) modded.height = vyres - modded.sy;
2121 if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
2123 cirrusfb_prim_copyarea(cinfo, &modded);
2126 static void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image)
2128 struct cirrusfb_info *cinfo = info->par;
2130 cirrusfb_WaitBLT(cinfo->regbase);
2131 cfb_imageblit(info, image);
2135 #ifdef CONFIG_PPC_PREP
2136 #define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
2137 #define PREP_IO_BASE ((volatile unsigned char *) 0x80000000)
2138 static void get_prep_addrs (unsigned long *display, unsigned long *registers)
2140 DPRINTK ("ENTER\n");
2142 *display = PREP_VIDEO_BASE;
2143 *registers = (unsigned long) PREP_IO_BASE;
2145 DPRINTK ("EXIT\n");
2148 #endif /* CONFIG_PPC_PREP */
2151 #ifdef CONFIG_PCI
2152 static int release_io_ports = 0;
2154 /* Pulled the logic from XFree86 Cirrus driver to get the memory size,
2155 * based on the DRAM bandwidth bit and DRAM bank switching bit. This
2156 * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
2157 * seem to have. */
2158 static unsigned int cirrusfb_get_memsize (u8 __iomem *regbase)
2160 unsigned long mem;
2161 unsigned char SRF;
2163 DPRINTK ("ENTER\n");
2165 SRF = vga_rseq (regbase, CL_SEQRF);
2166 switch ((SRF & 0x18)) {
2167 case 0x08: mem = 512 * 1024; break;
2168 case 0x10: mem = 1024 * 1024; break;
2169 /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory
2170 * on the 5430. */
2171 case 0x18: mem = 2048 * 1024; break;
2172 default: printk ("CLgenfb: Unknown memory size!\n");
2173 mem = 1024 * 1024;
2175 if (SRF & 0x80) {
2176 /* If DRAM bank switching is enabled, there must be twice as much
2177 * memory installed. (4MB on the 5434) */
2178 mem *= 2;
2180 /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
2182 DPRINTK ("EXIT\n");
2183 return mem;
2188 static void get_pci_addrs (const struct pci_dev *pdev,
2189 unsigned long *display, unsigned long *registers)
2191 assert (pdev != NULL);
2192 assert (display != NULL);
2193 assert (registers != NULL);
2195 DPRINTK ("ENTER\n");
2197 *display = 0;
2198 *registers = 0;
2200 /* This is a best-guess for now */
2202 if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
2203 *display = pci_resource_start(pdev, 1);
2204 *registers = pci_resource_start(pdev, 0);
2205 } else {
2206 *display = pci_resource_start(pdev, 0);
2207 *registers = pci_resource_start(pdev, 1);
2210 assert (*display != 0);
2212 DPRINTK ("EXIT\n");
2216 static void cirrusfb_pci_unmap (struct cirrusfb_info *cinfo)
2218 struct pci_dev *pdev = cinfo->pdev;
2220 iounmap(cinfo->fbmem);
2221 #if 0 /* if system didn't claim this region, we would... */
2222 release_mem_region(0xA0000, 65535);
2223 #endif
2224 if (release_io_ports)
2225 release_region(0x3C0, 32);
2226 pci_release_regions(pdev);
2227 framebuffer_release(cinfo->info);
2228 pci_disable_device(pdev);
2230 #endif /* CONFIG_PCI */
2233 #ifdef CONFIG_ZORRO
2234 static void __devexit cirrusfb_zorro_unmap (struct cirrusfb_info *cinfo)
2236 zorro_release_device(cinfo->zdev);
2238 if (cinfo->btype == BT_PICASSO4) {
2239 cinfo->regbase -= 0x600000;
2240 iounmap ((void *)cinfo->regbase);
2241 iounmap ((void *)cinfo->fbmem);
2242 } else {
2243 if (zorro_resource_start(cinfo->zdev) > 0x01000000)
2244 iounmap ((void *)cinfo->fbmem);
2246 framebuffer_release(cinfo->info);
2248 #endif /* CONFIG_ZORRO */
2250 static int cirrusfb_set_fbinfo(struct cirrusfb_info *cinfo)
2252 struct fb_info *info = cinfo->info;
2253 struct fb_var_screeninfo *var = &info->var;
2255 info->par = cinfo;
2256 info->pseudo_palette = cinfo->pseudo_palette;
2257 info->flags = FBINFO_DEFAULT
2258 | FBINFO_HWACCEL_XPAN
2259 | FBINFO_HWACCEL_YPAN
2260 | FBINFO_HWACCEL_FILLRECT
2261 | FBINFO_HWACCEL_COPYAREA;
2262 if (noaccel)
2263 info->flags |= FBINFO_HWACCEL_DISABLED;
2264 info->fbops = &cirrusfb_ops;
2265 info->screen_base = cinfo->fbmem;
2266 if (cinfo->btype == BT_GD5480) {
2267 if (var->bits_per_pixel == 16)
2268 info->screen_base += 1 * MB_;
2269 if (var->bits_per_pixel == 24 || var->bits_per_pixel == 32)
2270 info->screen_base += 2 * MB_;
2273 /* Fill fix common fields */
2274 strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
2275 sizeof(info->fix.id));
2277 /* monochrome: only 1 memory plane */
2278 /* 8 bit and above: Use whole memory area */
2279 info->fix.smem_start = cinfo->fbmem_phys;
2280 info->fix.smem_len = (var->bits_per_pixel == 1) ? cinfo->size / 4 : cinfo->size;
2281 info->fix.type = cinfo->currentmode.type;
2282 info->fix.type_aux = 0;
2283 info->fix.visual = cinfo->currentmode.visual;
2284 info->fix.xpanstep = 1;
2285 info->fix.ypanstep = 1;
2286 info->fix.ywrapstep = 0;
2287 info->fix.line_length = cinfo->currentmode.line_length;
2289 /* FIXME: map region at 0xB8000 if available, fill in here */
2290 info->fix.mmio_start = cinfo->fbregs_phys;
2291 info->fix.mmio_len = 0;
2292 info->fix.accel = FB_ACCEL_NONE;
2294 fb_alloc_cmap(&info->cmap, 256, 0);
2296 return 0;
2299 static int cirrusfb_register(struct cirrusfb_info *cinfo)
2301 struct fb_info *info;
2302 int err;
2303 cirrusfb_board_t btype;
2305 DPRINTK ("ENTER\n");
2307 printk (KERN_INFO "cirrusfb: Driver for Cirrus Logic based graphic boards, v" CIRRUSFB_VERSION "\n");
2309 info = cinfo->info;
2310 btype = cinfo->btype;
2312 /* sanity checks */
2313 assert (btype != BT_NONE);
2315 DPRINTK ("cirrusfb: (RAM start set to: 0x%p)\n", cinfo->fbmem);
2317 /* Make pretend we've set the var so our structures are in a "good" */
2318 /* state, even though we haven't written the mode to the hw yet... */
2319 info->var = cirrusfb_predefined[cirrusfb_def_mode].var;
2320 info->var.activate = FB_ACTIVATE_NOW;
2322 err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
2323 if (err < 0) {
2324 /* should never happen */
2325 DPRINTK("choking on default var... umm, no good.\n");
2326 goto err_unmap_cirrusfb;
2329 /* set all the vital stuff */
2330 cirrusfb_set_fbinfo(cinfo);
2332 err = register_framebuffer(info);
2333 if (err < 0) {
2334 printk (KERN_ERR "cirrusfb: could not register fb device; err = %d!\n", err);
2335 goto err_dealloc_cmap;
2338 DPRINTK ("EXIT, returning 0\n");
2339 return 0;
2341 err_dealloc_cmap:
2342 fb_dealloc_cmap(&info->cmap);
2343 err_unmap_cirrusfb:
2344 cinfo->unmap(cinfo);
2345 return err;
2348 static void __devexit cirrusfb_cleanup (struct fb_info *info)
2350 struct cirrusfb_info *cinfo = info->par;
2351 DPRINTK ("ENTER\n");
2353 switch_monitor (cinfo, 0);
2355 unregister_framebuffer (info);
2356 fb_dealloc_cmap (&info->cmap);
2357 printk ("Framebuffer unregistered\n");
2358 cinfo->unmap(cinfo);
2360 DPRINTK ("EXIT\n");
2364 #ifdef CONFIG_PCI
2365 static int cirrusfb_pci_register (struct pci_dev *pdev,
2366 const struct pci_device_id *ent)
2368 struct cirrusfb_info *cinfo;
2369 struct fb_info *info;
2370 cirrusfb_board_t btype;
2371 unsigned long board_addr, board_size;
2372 int ret;
2374 ret = pci_enable_device(pdev);
2375 if (ret < 0) {
2376 printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
2377 goto err_out;
2380 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev);
2381 if (!info) {
2382 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2383 ret = -ENOMEM;
2384 goto err_disable;
2387 cinfo = info->par;
2388 cinfo->info = info;
2389 cinfo->pdev = pdev;
2390 cinfo->btype = btype = (cirrusfb_board_t) ent->driver_data;
2392 DPRINTK (" Found PCI device, base address 0 is 0x%lx, btype set to %d\n",
2393 pdev->resource[0].start, btype);
2394 DPRINTK (" base address 1 is 0x%lx\n", pdev->resource[1].start);
2396 if(isPReP) {
2397 pci_write_config_dword (pdev, PCI_BASE_ADDRESS_0, 0x00000000);
2398 #ifdef CONFIG_PPC_PREP
2399 get_prep_addrs (&board_addr, &cinfo->fbregs_phys);
2400 #endif
2401 /* PReP dies if we ioremap the IO registers, but it works w/out... */
2402 cinfo->regbase = (char __iomem *) cinfo->fbregs_phys;
2403 } else {
2404 DPRINTK ("Attempt to get PCI info for Cirrus Graphics Card\n");
2405 get_pci_addrs (pdev, &board_addr, &cinfo->fbregs_phys);
2406 cinfo->regbase = NULL; /* FIXME: this forces VGA. alternatives? */
2409 DPRINTK ("Board address: 0x%lx, register address: 0x%lx\n", board_addr, cinfo->fbregs_phys);
2411 board_size = (btype == BT_GD5480) ?
2412 32 * MB_ : cirrusfb_get_memsize (cinfo->regbase);
2414 ret = pci_request_regions(pdev, "cirrusfb");
2415 if (ret <0) {
2416 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n",
2417 board_addr);
2418 goto err_release_fb;
2420 #if 0 /* if the system didn't claim this region, we would... */
2421 if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
2422 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n"
2424 0xA0000L);
2425 ret = -EBUSY;
2426 goto err_release_regions;
2428 #endif
2429 if (request_region(0x3C0, 32, "cirrusfb"))
2430 release_io_ports = 1;
2432 cinfo->fbmem = ioremap(board_addr, board_size);
2433 if (!cinfo->fbmem) {
2434 ret = -EIO;
2435 goto err_release_legacy;
2438 cinfo->fbmem_phys = board_addr;
2439 cinfo->size = board_size;
2440 cinfo->unmap = cirrusfb_pci_unmap;
2442 printk (" RAM (%lu kB) at 0xx%lx, ", cinfo->size / KB_, board_addr);
2443 printk ("Cirrus Logic chipset on PCI bus\n");
2444 pci_set_drvdata(pdev, info);
2446 return cirrusfb_register(cinfo);
2448 err_release_legacy:
2449 if (release_io_ports)
2450 release_region(0x3C0, 32);
2451 #if 0
2452 release_mem_region(0xA0000, 65535);
2453 err_release_regions:
2454 #endif
2455 pci_release_regions(pdev);
2456 err_release_fb:
2457 framebuffer_release(info);
2458 err_disable:
2459 pci_disable_device(pdev);
2460 err_out:
2461 return ret;
2464 static void __devexit cirrusfb_pci_unregister (struct pci_dev *pdev)
2466 struct fb_info *info = pci_get_drvdata(pdev);
2467 DPRINTK ("ENTER\n");
2469 cirrusfb_cleanup (info);
2471 DPRINTK ("EXIT\n");
2474 static struct pci_driver cirrusfb_pci_driver = {
2475 .name = "cirrusfb",
2476 .id_table = cirrusfb_pci_table,
2477 .probe = cirrusfb_pci_register,
2478 .remove = __devexit_p(cirrusfb_pci_unregister),
2479 #ifdef CONFIG_PM
2480 #if 0
2481 .suspend = cirrusfb_pci_suspend,
2482 .resume = cirrusfb_pci_resume,
2483 #endif
2484 #endif
2486 #endif /* CONFIG_PCI */
2489 #ifdef CONFIG_ZORRO
2490 static int cirrusfb_zorro_register(struct zorro_dev *z,
2491 const struct zorro_device_id *ent)
2493 struct cirrusfb_info *cinfo;
2494 struct fb_info *info;
2495 cirrusfb_board_t btype;
2496 struct zorro_dev *z2 = NULL;
2497 unsigned long board_addr, board_size, size;
2498 int ret;
2500 btype = ent->driver_data;
2501 if (cirrusfb_zorro_table2[btype].id2)
2502 z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
2503 size = cirrusfb_zorro_table2[btype].size;
2504 printk(KERN_INFO "cirrusfb: %s board detected; ",
2505 cirrusfb_board_info[btype].name);
2507 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
2508 if (!info) {
2509 printk (KERN_ERR "cirrusfb: could not allocate memory\n");
2510 ret = -ENOMEM;
2511 goto err_out;
2514 cinfo = info->par;
2515 cinfo->info = info;
2516 cinfo->btype = btype;
2518 assert (z > 0);
2519 assert (z2 >= 0);
2520 assert (btype != BT_NONE);
2522 cinfo->zdev = z;
2523 board_addr = zorro_resource_start(z);
2524 board_size = zorro_resource_len(z);
2525 cinfo->size = size;
2527 if (!zorro_request_device(z, "cirrusfb")) {
2528 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n",
2529 board_addr);
2530 ret = -EBUSY;
2531 goto err_release_fb;
2534 printk (" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr);
2536 ret = -EIO;
2538 if (btype == BT_PICASSO4) {
2539 printk (" REG at $%lx\n", board_addr + 0x600000);
2541 /* To be precise, for the P4 this is not the */
2542 /* begin of the board, but the begin of RAM. */
2543 /* for P4, map in its address space in 2 chunks (### TEST! ) */
2544 /* (note the ugly hardcoded 16M number) */
2545 cinfo->regbase = ioremap (board_addr, 16777216);
2546 if (!cinfo->regbase)
2547 goto err_release_region;
2549 DPRINTK ("cirrusfb: Virtual address for board set to: $%p\n", cinfo->regbase);
2550 cinfo->regbase += 0x600000;
2551 cinfo->fbregs_phys = board_addr + 0x600000;
2553 cinfo->fbmem_phys = board_addr + 16777216;
2554 cinfo->fbmem = ioremap (cinfo->fbmem_phys, 16777216);
2555 if (!cinfo->fbmem)
2556 goto err_unmap_regbase;
2557 } else {
2558 printk (" REG at $%lx\n", (unsigned long) z2->resource.start);
2560 cinfo->fbmem_phys = board_addr;
2561 if (board_addr > 0x01000000)
2562 cinfo->fbmem = ioremap (board_addr, board_size);
2563 else
2564 cinfo->fbmem = (caddr_t) ZTWO_VADDR (board_addr);
2565 if (!cinfo->fbmem)
2566 goto err_release_region;
2568 /* set address for REG area of board */
2569 cinfo->regbase = (caddr_t) ZTWO_VADDR (z2->resource.start);
2570 cinfo->fbregs_phys = z2->resource.start;
2572 DPRINTK ("cirrusfb: Virtual address for board set to: $%p\n", cinfo->regbase);
2574 cinfo->unmap = cirrusfb_zorro_unmap;
2576 printk (KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
2577 zorro_set_drvdata(z, info);
2579 return cirrusfb_register(cinfo);
2581 err_unmap_regbase:
2582 /* Parental advisory: explicit hack */
2583 iounmap(cinfo->regbase - 0x600000);
2584 err_release_region:
2585 release_region(board_addr, board_size);
2586 err_release_fb:
2587 framebuffer_release(info);
2588 err_out:
2589 return ret;
2592 void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
2594 struct fb_info *info = zorro_get_drvdata(z);
2595 DPRINTK ("ENTER\n");
2597 cirrusfb_cleanup (info);
2599 DPRINTK ("EXIT\n");
2602 static struct zorro_driver cirrusfb_zorro_driver = {
2603 .name = "cirrusfb",
2604 .id_table = cirrusfb_zorro_table,
2605 .probe = cirrusfb_zorro_register,
2606 .remove = __devexit_p(cirrusfb_zorro_unregister),
2608 #endif /* CONFIG_ZORRO */
2610 static int __init cirrusfb_init(void)
2612 int error = 0;
2614 #ifndef MODULE
2615 char *option = NULL;
2617 if (fb_get_options("cirrusfb", &option))
2618 return -ENODEV;
2619 cirrusfb_setup(option);
2620 #endif
2622 #ifdef CONFIG_ZORRO
2623 error |= zorro_module_init(&cirrusfb_zorro_driver);
2624 #endif
2625 #ifdef CONFIG_PCI
2626 error |= pci_register_driver(&cirrusfb_pci_driver);
2627 #endif
2628 return error;
2633 #ifndef MODULE
2634 static int __init cirrusfb_setup(char *options) {
2635 char *this_opt, s[32];
2636 int i;
2638 DPRINTK ("ENTER\n");
2640 if (!options || !*options)
2641 return 0;
2643 while ((this_opt = strsep (&options, ",")) != NULL) {
2644 if (!*this_opt) continue;
2646 DPRINTK("cirrusfb_setup: option '%s'\n", this_opt);
2648 for (i = 0; i < NUM_TOTAL_MODES; i++) {
2649 sprintf (s, "mode:%s", cirrusfb_predefined[i].name);
2650 if (strcmp (this_opt, s) == 0)
2651 cirrusfb_def_mode = i;
2653 if (!strcmp(this_opt, "noaccel"))
2654 noaccel = 1;
2656 return 0;
2658 #endif
2662 * Modularization
2665 MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
2666 MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
2667 MODULE_LICENSE("GPL");
2669 static void __exit cirrusfb_exit (void)
2671 #ifdef CONFIG_PCI
2672 pci_unregister_driver(&cirrusfb_pci_driver);
2673 #endif
2674 #ifdef CONFIG_ZORRO
2675 zorro_unregister_driver(&cirrusfb_zorro_driver);
2676 #endif
2679 module_init(cirrusfb_init);
2681 #ifdef MODULE
2682 module_exit(cirrusfb_exit);
2683 #endif
2686 /**********************************************************************/
2687 /* about the following functions - I have used the same names for the */
2688 /* functions as Markus Wild did in his Retina driver for NetBSD as */
2689 /* they just made sense for this purpose. Apart from that, I wrote */
2690 /* these functions myself. */
2691 /**********************************************************************/
2693 /*** WGen() - write into one of the external/general registers ***/
2694 static void WGen (const struct cirrusfb_info *cinfo,
2695 int regnum, unsigned char val)
2697 unsigned long regofs = 0;
2699 if (cinfo->btype == BT_PICASSO) {
2700 /* Picasso II specific hack */
2701 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */
2702 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2703 regofs = 0xfff;
2706 vga_w (cinfo->regbase, regofs + regnum, val);
2709 /*** RGen() - read out one of the external/general registers ***/
2710 static unsigned char RGen (const struct cirrusfb_info *cinfo, int regnum)
2712 unsigned long regofs = 0;
2714 if (cinfo->btype == BT_PICASSO) {
2715 /* Picasso II specific hack */
2716 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */
2717 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2718 regofs = 0xfff;
2721 return vga_r (cinfo->regbase, regofs + regnum);
2724 /*** AttrOn() - turn on VideoEnable for Attribute controller ***/
2725 static void AttrOn (const struct cirrusfb_info *cinfo)
2727 assert (cinfo != NULL);
2729 DPRINTK ("ENTER\n");
2731 if (vga_rcrt (cinfo->regbase, CL_CRT24) & 0x80) {
2732 /* if we're just in "write value" mode, write back the */
2733 /* same value as before to not modify anything */
2734 vga_w (cinfo->regbase, VGA_ATT_IW,
2735 vga_r (cinfo->regbase, VGA_ATT_R));
2737 /* turn on video bit */
2738 /* vga_w (cinfo->regbase, VGA_ATT_IW, 0x20); */
2739 vga_w (cinfo->regbase, VGA_ATT_IW, 0x33);
2741 /* dummy write on Reg0 to be on "write index" mode next time */
2742 vga_w (cinfo->regbase, VGA_ATT_IW, 0x00);
2744 DPRINTK ("EXIT\n");
2747 /*** WHDR() - write into the Hidden DAC register ***/
2748 /* as the HDR is the only extension register that requires special treatment
2749 * (the other extension registers are accessible just like the "ordinary"
2750 * registers of their functional group) here is a specialized routine for
2751 * accessing the HDR
2753 static void WHDR (const struct cirrusfb_info *cinfo, unsigned char val)
2755 unsigned char dummy;
2757 if (cinfo->btype == BT_PICASSO) {
2758 /* Klaus' hint for correct access to HDR on some boards */
2759 /* first write 0 to pixel mask (3c6) */
2760 WGen (cinfo, VGA_PEL_MSK, 0x00);
2761 udelay (200);
2762 /* next read dummy from pixel address (3c8) */
2763 dummy = RGen (cinfo, VGA_PEL_IW);
2764 udelay (200);
2766 /* now do the usual stuff to access the HDR */
2768 dummy = RGen (cinfo, VGA_PEL_MSK);
2769 udelay (200);
2770 dummy = RGen (cinfo, VGA_PEL_MSK);
2771 udelay (200);
2772 dummy = RGen (cinfo, VGA_PEL_MSK);
2773 udelay (200);
2774 dummy = RGen (cinfo, VGA_PEL_MSK);
2775 udelay (200);
2777 WGen (cinfo, VGA_PEL_MSK, val);
2778 udelay (200);
2780 if (cinfo->btype == BT_PICASSO) {
2781 /* now first reset HDR access counter */
2782 dummy = RGen (cinfo, VGA_PEL_IW);
2783 udelay (200);
2785 /* and at the end, restore the mask value */
2786 /* ## is this mask always 0xff? */
2787 WGen (cinfo, VGA_PEL_MSK, 0xff);
2788 udelay (200);
2793 /*** WSFR() - write to the "special function register" (SFR) ***/
2794 static void WSFR (struct cirrusfb_info *cinfo, unsigned char val)
2796 #ifdef CONFIG_ZORRO
2797 assert (cinfo->regbase != NULL);
2798 cinfo->SFR = val;
2799 z_writeb (val, cinfo->regbase + 0x8000);
2800 #endif
2803 /* The Picasso has a second register for switching the monitor bit */
2804 static void WSFR2 (struct cirrusfb_info *cinfo, unsigned char val)
2806 #ifdef CONFIG_ZORRO
2807 /* writing an arbitrary value to this one causes the monitor switcher */
2808 /* to flip to Amiga display */
2809 assert (cinfo->regbase != NULL);
2810 cinfo->SFR = val;
2811 z_writeb (val, cinfo->regbase + 0x9000);
2812 #endif
2816 /*** WClut - set CLUT entry (range: 0..63) ***/
2817 static void WClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
2818 unsigned char green, unsigned char blue)
2820 unsigned int data = VGA_PEL_D;
2822 /* address write mode register is not translated.. */
2823 vga_w (cinfo->regbase, VGA_PEL_IW, regnum);
2825 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2826 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2827 /* but DAC data register IS, at least for Picasso II */
2828 if (cinfo->btype == BT_PICASSO)
2829 data += 0xfff;
2830 vga_w (cinfo->regbase, data, red);
2831 vga_w (cinfo->regbase, data, green);
2832 vga_w (cinfo->regbase, data, blue);
2833 } else {
2834 vga_w (cinfo->regbase, data, blue);
2835 vga_w (cinfo->regbase, data, green);
2836 vga_w (cinfo->regbase, data, red);
2841 #if 0
2842 /*** RClut - read CLUT entry (range 0..63) ***/
2843 static void RClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
2844 unsigned char *green, unsigned char *blue)
2846 unsigned int data = VGA_PEL_D;
2848 vga_w (cinfo->regbase, VGA_PEL_IR, regnum);
2850 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2851 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2852 if (cinfo->btype == BT_PICASSO)
2853 data += 0xfff;
2854 *red = vga_r (cinfo->regbase, data);
2855 *green = vga_r (cinfo->regbase, data);
2856 *blue = vga_r (cinfo->regbase, data);
2857 } else {
2858 *blue = vga_r (cinfo->regbase, data);
2859 *green = vga_r (cinfo->regbase, data);
2860 *red = vga_r (cinfo->regbase, data);
2863 #endif
2866 /*******************************************************************
2867 cirrusfb_WaitBLT()
2869 Wait for the BitBLT engine to complete a possible earlier job
2870 *********************************************************************/
2872 /* FIXME: use interrupts instead */
2873 static void cirrusfb_WaitBLT (u8 __iomem *regbase)
2875 /* now busy-wait until we're done */
2876 while (vga_rgfx (regbase, CL_GR31) & 0x08)
2877 /* do nothing */ ;
2880 /*******************************************************************
2881 cirrusfb_BitBLT()
2883 perform accelerated "scrolling"
2884 ********************************************************************/
2886 static void cirrusfb_BitBLT (u8 __iomem *regbase, int bits_per_pixel,
2887 u_short curx, u_short cury, u_short destx, u_short desty,
2888 u_short width, u_short height, u_short line_length)
2890 u_short nwidth, nheight;
2891 u_long nsrc, ndest;
2892 u_char bltmode;
2894 DPRINTK ("ENTER\n");
2896 nwidth = width - 1;
2897 nheight = height - 1;
2899 bltmode = 0x00;
2900 /* if source adr < dest addr, do the Blt backwards */
2901 if (cury <= desty) {
2902 if (cury == desty) {
2903 /* if src and dest are on the same line, check x */
2904 if (curx < destx)
2905 bltmode |= 0x01;
2906 } else
2907 bltmode |= 0x01;
2909 if (!bltmode) {
2910 /* standard case: forward blitting */
2911 nsrc = (cury * line_length) + curx;
2912 ndest = (desty * line_length) + destx;
2913 } else {
2914 /* this means start addresses are at the end, counting backwards */
2915 nsrc = cury * line_length + curx + nheight * line_length + nwidth;
2916 ndest = desty * line_length + destx + nheight * line_length + nwidth;
2920 run-down of registers to be programmed:
2921 destination pitch
2922 source pitch
2923 BLT width/height
2924 source start
2925 destination start
2926 BLT mode
2927 BLT ROP
2928 VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color"
2929 start/stop
2932 cirrusfb_WaitBLT(regbase);
2934 /* pitch: set to line_length */
2935 vga_wgfx (regbase, CL_GR24, line_length & 0xff); /* dest pitch low */
2936 vga_wgfx (regbase, CL_GR25, (line_length >> 8)); /* dest pitch hi */
2937 vga_wgfx (regbase, CL_GR26, line_length & 0xff); /* source pitch low */
2938 vga_wgfx (regbase, CL_GR27, (line_length >> 8)); /* source pitch hi */
2940 /* BLT width: actual number of pixels - 1 */
2941 vga_wgfx (regbase, CL_GR20, nwidth & 0xff); /* BLT width low */
2942 vga_wgfx (regbase, CL_GR21, (nwidth >> 8)); /* BLT width hi */
2944 /* BLT height: actual number of lines -1 */
2945 vga_wgfx (regbase, CL_GR22, nheight & 0xff); /* BLT height low */
2946 vga_wgfx (regbase, CL_GR23, (nheight >> 8)); /* BLT width hi */
2948 /* BLT destination */
2949 vga_wgfx (regbase, CL_GR28, (u_char) (ndest & 0xff)); /* BLT dest low */
2950 vga_wgfx (regbase, CL_GR29, (u_char) (ndest >> 8)); /* BLT dest mid */
2951 vga_wgfx (regbase, CL_GR2A, (u_char) (ndest >> 16)); /* BLT dest hi */
2953 /* BLT source */
2954 vga_wgfx (regbase, CL_GR2C, (u_char) (nsrc & 0xff)); /* BLT src low */
2955 vga_wgfx (regbase, CL_GR2D, (u_char) (nsrc >> 8)); /* BLT src mid */
2956 vga_wgfx (regbase, CL_GR2E, (u_char) (nsrc >> 16)); /* BLT src hi */
2958 /* BLT mode */
2959 vga_wgfx (regbase, CL_GR30, bltmode); /* BLT mode */
2961 /* BLT ROP: SrcCopy */
2962 vga_wgfx (regbase, CL_GR32, 0x0d); /* BLT ROP */
2964 /* and finally: GO! */
2965 vga_wgfx (regbase, CL_GR31, 0x02); /* BLT Start/status */
2967 DPRINTK ("EXIT\n");
2971 /*******************************************************************
2972 cirrusfb_RectFill()
2974 perform accelerated rectangle fill
2975 ********************************************************************/
2977 static void cirrusfb_RectFill (u8 __iomem *regbase, int bits_per_pixel,
2978 u_short x, u_short y, u_short width, u_short height,
2979 u_char color, u_short line_length)
2981 u_short nwidth, nheight;
2982 u_long ndest;
2983 u_char op;
2985 DPRINTK ("ENTER\n");
2987 nwidth = width - 1;
2988 nheight = height - 1;
2990 ndest = (y * line_length) + x;
2992 cirrusfb_WaitBLT(regbase);
2994 /* pitch: set to line_length */
2995 vga_wgfx (regbase, CL_GR24, line_length & 0xff); /* dest pitch low */
2996 vga_wgfx (regbase, CL_GR25, (line_length >> 8)); /* dest pitch hi */
2997 vga_wgfx (regbase, CL_GR26, line_length & 0xff); /* source pitch low */
2998 vga_wgfx (regbase, CL_GR27, (line_length >> 8)); /* source pitch hi */
3000 /* BLT width: actual number of pixels - 1 */
3001 vga_wgfx (regbase, CL_GR20, nwidth & 0xff); /* BLT width low */
3002 vga_wgfx (regbase, CL_GR21, (nwidth >> 8)); /* BLT width hi */
3004 /* BLT height: actual number of lines -1 */
3005 vga_wgfx (regbase, CL_GR22, nheight & 0xff); /* BLT height low */
3006 vga_wgfx (regbase, CL_GR23, (nheight >> 8)); /* BLT width hi */
3008 /* BLT destination */
3009 vga_wgfx (regbase, CL_GR28, (u_char) (ndest & 0xff)); /* BLT dest low */
3010 vga_wgfx (regbase, CL_GR29, (u_char) (ndest >> 8)); /* BLT dest mid */
3011 vga_wgfx (regbase, CL_GR2A, (u_char) (ndest >> 16)); /* BLT dest hi */
3013 /* BLT source: set to 0 (is a dummy here anyway) */
3014 vga_wgfx (regbase, CL_GR2C, 0x00); /* BLT src low */
3015 vga_wgfx (regbase, CL_GR2D, 0x00); /* BLT src mid */
3016 vga_wgfx (regbase, CL_GR2E, 0x00); /* BLT src hi */
3018 /* This is a ColorExpand Blt, using the */
3019 /* same color for foreground and background */
3020 vga_wgfx (regbase, VGA_GFX_SR_VALUE, color); /* foreground color */
3021 vga_wgfx (regbase, VGA_GFX_SR_ENABLE, color); /* background color */
3023 op = 0xc0;
3024 if (bits_per_pixel == 16) {
3025 vga_wgfx (regbase, CL_GR10, color); /* foreground color */
3026 vga_wgfx (regbase, CL_GR11, color); /* background color */
3027 op = 0x50;
3028 op = 0xd0;
3029 } else if (bits_per_pixel == 32) {
3030 vga_wgfx (regbase, CL_GR10, color); /* foreground color */
3031 vga_wgfx (regbase, CL_GR11, color); /* background color */
3032 vga_wgfx (regbase, CL_GR12, color); /* foreground color */
3033 vga_wgfx (regbase, CL_GR13, color); /* background color */
3034 vga_wgfx (regbase, CL_GR14, 0); /* foreground color */
3035 vga_wgfx (regbase, CL_GR15, 0); /* background color */
3036 op = 0x50;
3037 op = 0xf0;
3039 /* BLT mode: color expand, Enable 8x8 copy (faster?) */
3040 vga_wgfx (regbase, CL_GR30, op); /* BLT mode */
3042 /* BLT ROP: SrcCopy */
3043 vga_wgfx (regbase, CL_GR32, 0x0d); /* BLT ROP */
3045 /* and finally: GO! */
3046 vga_wgfx (regbase, CL_GR31, 0x02); /* BLT Start/status */
3048 DPRINTK ("EXIT\n");
3052 /**************************************************************************
3053 * bestclock() - determine closest possible clock lower(?) than the
3054 * desired pixel clock
3055 **************************************************************************/
3056 static void bestclock (long freq, long *best, long *nom,
3057 long *den, long *div, long maxfreq)
3059 long n, h, d, f;
3061 assert (best != NULL);
3062 assert (nom != NULL);
3063 assert (den != NULL);
3064 assert (div != NULL);
3065 assert (maxfreq > 0);
3067 *nom = 0;
3068 *den = 0;
3069 *div = 0;
3071 DPRINTK ("ENTER\n");
3073 if (freq < 8000)
3074 freq = 8000;
3076 if (freq > maxfreq)
3077 freq = maxfreq;
3079 *best = 0;
3080 f = freq * 10;
3082 for (n = 32; n < 128; n++) {
3083 d = (143181 * n) / f;
3084 if ((d >= 7) && (d <= 63)) {
3085 if (d > 31)
3086 d = (d / 2) * 2;
3087 h = (14318 * n) / d;
3088 if (abs (h - freq) < abs (*best - freq)) {
3089 *best = h;
3090 *nom = n;
3091 if (d < 32) {
3092 *den = d;
3093 *div = 0;
3094 } else {
3095 *den = d / 2;
3096 *div = 1;
3100 d = ((143181 * n) + f - 1) / f;
3101 if ((d >= 7) && (d <= 63)) {
3102 if (d > 31)
3103 d = (d / 2) * 2;
3104 h = (14318 * n) / d;
3105 if (abs (h - freq) < abs (*best - freq)) {
3106 *best = h;
3107 *nom = n;
3108 if (d < 32) {
3109 *den = d;
3110 *div = 0;
3111 } else {
3112 *den = d / 2;
3113 *div = 1;
3119 DPRINTK ("Best possible values for given frequency:\n");
3120 DPRINTK (" best: %ld kHz nom: %ld den: %ld div: %ld\n",
3121 freq, *nom, *den, *div);
3123 DPRINTK ("EXIT\n");
3127 /* -------------------------------------------------------------------------
3129 * debugging functions
3131 * -------------------------------------------------------------------------
3134 #ifdef CIRRUSFB_DEBUG
3137 * cirrusfb_dbg_print_byte
3138 * @name: name associated with byte value to be displayed
3139 * @val: byte value to be displayed
3141 * DESCRIPTION:
3142 * Display an indented string, along with a hexidecimal byte value, and
3143 * its decoded bits. Bits 7 through 0 are listed in left-to-right
3144 * order.
3147 static
3148 void cirrusfb_dbg_print_byte (const char *name, unsigned char val)
3150 DPRINTK ("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n",
3151 name, val,
3152 val & 0x80 ? '1' : '0',
3153 val & 0x40 ? '1' : '0',
3154 val & 0x20 ? '1' : '0',
3155 val & 0x10 ? '1' : '0',
3156 val & 0x08 ? '1' : '0',
3157 val & 0x04 ? '1' : '0',
3158 val & 0x02 ? '1' : '0',
3159 val & 0x01 ? '1' : '0');
3164 * cirrusfb_dbg_print_regs
3165 * @base: If using newmmio, the newmmio base address, otherwise %NULL
3166 * @reg_class: type of registers to read: %CRT, or %SEQ
3168 * DESCRIPTION:
3169 * Dumps the given list of VGA CRTC registers. If @base is %NULL,
3170 * old-style I/O ports are queried for information, otherwise MMIO is
3171 * used at the given @base address to query the information.
3174 static
3175 void cirrusfb_dbg_print_regs (caddr_t regbase, cirrusfb_dbg_reg_class_t reg_class,...)
3177 va_list list;
3178 unsigned char val = 0;
3179 unsigned reg;
3180 char *name;
3182 va_start (list, reg_class);
3184 name = va_arg (list, char *);
3185 while (name != NULL) {
3186 reg = va_arg (list, int);
3188 switch (reg_class) {
3189 case CRT:
3190 val = vga_rcrt (regbase, (unsigned char) reg);
3191 break;
3192 case SEQ:
3193 val = vga_rseq (regbase, (unsigned char) reg);
3194 break;
3195 default:
3196 /* should never occur */
3197 assert (FALSE);
3198 break;
3201 cirrusfb_dbg_print_byte (name, val);
3203 name = va_arg (list, char *);
3206 va_end (list);
3211 * cirrusfb_dump
3212 * @cirrusfbinfo:
3214 * DESCRIPTION:
3217 static
3218 void cirrusfb_dump (void)
3220 cirrusfb_dbg_reg_dump (NULL);
3225 * cirrusfb_dbg_reg_dump
3226 * @base: If using newmmio, the newmmio base address, otherwise %NULL
3228 * DESCRIPTION:
3229 * Dumps a list of interesting VGA and CIRRUSFB registers. If @base is %NULL,
3230 * old-style I/O ports are queried for information, otherwise MMIO is
3231 * used at the given @base address to query the information.
3234 static
3235 void cirrusfb_dbg_reg_dump (caddr_t regbase)
3237 DPRINTK ("CIRRUSFB VGA CRTC register dump:\n");
3239 cirrusfb_dbg_print_regs (regbase, CRT,
3240 "CR00", 0x00,
3241 "CR01", 0x01,
3242 "CR02", 0x02,
3243 "CR03", 0x03,
3244 "CR04", 0x04,
3245 "CR05", 0x05,
3246 "CR06", 0x06,
3247 "CR07", 0x07,
3248 "CR08", 0x08,
3249 "CR09", 0x09,
3250 "CR0A", 0x0A,
3251 "CR0B", 0x0B,
3252 "CR0C", 0x0C,
3253 "CR0D", 0x0D,
3254 "CR0E", 0x0E,
3255 "CR0F", 0x0F,
3256 "CR10", 0x10,
3257 "CR11", 0x11,
3258 "CR12", 0x12,
3259 "CR13", 0x13,
3260 "CR14", 0x14,
3261 "CR15", 0x15,
3262 "CR16", 0x16,
3263 "CR17", 0x17,
3264 "CR18", 0x18,
3265 "CR22", 0x22,
3266 "CR24", 0x24,
3267 "CR26", 0x26,
3268 "CR2D", 0x2D,
3269 "CR2E", 0x2E,
3270 "CR2F", 0x2F,
3271 "CR30", 0x30,
3272 "CR31", 0x31,
3273 "CR32", 0x32,
3274 "CR33", 0x33,
3275 "CR34", 0x34,
3276 "CR35", 0x35,
3277 "CR36", 0x36,
3278 "CR37", 0x37,
3279 "CR38", 0x38,
3280 "CR39", 0x39,
3281 "CR3A", 0x3A,
3282 "CR3B", 0x3B,
3283 "CR3C", 0x3C,
3284 "CR3D", 0x3D,
3285 "CR3E", 0x3E,
3286 "CR3F", 0x3F,
3287 NULL);
3289 DPRINTK ("\n");
3291 DPRINTK ("CIRRUSFB VGA SEQ register dump:\n");
3293 cirrusfb_dbg_print_regs (regbase, SEQ,
3294 "SR00", 0x00,
3295 "SR01", 0x01,
3296 "SR02", 0x02,
3297 "SR03", 0x03,
3298 "SR04", 0x04,
3299 "SR08", 0x08,
3300 "SR09", 0x09,
3301 "SR0A", 0x0A,
3302 "SR0B", 0x0B,
3303 "SR0D", 0x0D,
3304 "SR10", 0x10,
3305 "SR11", 0x11,
3306 "SR12", 0x12,
3307 "SR13", 0x13,
3308 "SR14", 0x14,
3309 "SR15", 0x15,
3310 "SR16", 0x16,
3311 "SR17", 0x17,
3312 "SR18", 0x18,
3313 "SR19", 0x19,
3314 "SR1A", 0x1A,
3315 "SR1B", 0x1B,
3316 "SR1C", 0x1C,
3317 "SR1D", 0x1D,
3318 "SR1E", 0x1E,
3319 "SR1F", 0x1F,
3320 NULL);
3322 DPRINTK ("\n");
3325 #endif /* CIRRUSFB_DEBUG */