[PATCH] kthread: airo.c
[linux-2.6.22.y-op.git] / drivers / video / cirrusfb.c
blobdaf43f535a0b971540ed274706cd747a0e30d81e
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/module.h>
40 #include <linux/kernel.h>
41 #include <linux/errno.h>
42 #include <linux/string.h>
43 #include <linux/mm.h>
44 #include <linux/slab.h>
45 #include <linux/delay.h>
46 #include <linux/fb.h>
47 #include <linux/init.h>
48 #include <linux/selection.h>
49 #include <asm/pgtable.h>
51 #ifdef CONFIG_ZORRO
52 #include <linux/zorro.h>
53 #endif
54 #ifdef CONFIG_PCI
55 #include <linux/pci.h>
56 #endif
57 #ifdef CONFIG_AMIGA
58 #include <asm/amigahw.h>
59 #endif
60 #ifdef CONFIG_PPC_PREP
61 #include <asm/machdep.h>
62 #define isPReP (machine_is(prep))
63 #else
64 #define isPReP 0
65 #endif
67 #include "video/vga.h"
68 #include "video/cirrus.h"
71 /*****************************************************************
73 * debugging and utility macros
77 /* enable debug output? */
78 /* #define CIRRUSFB_DEBUG 1 */
80 /* disable runtime assertions? */
81 /* #define CIRRUSFB_NDEBUG */
83 /* debug output */
84 #ifdef CIRRUSFB_DEBUG
85 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
86 #else
87 #define DPRINTK(fmt, args...)
88 #endif
90 /* debugging assertions */
91 #ifndef CIRRUSFB_NDEBUG
92 #define assert(expr) \
93 if(!(expr)) { \
94 printk( "Assertion failed! %s,%s,%s,line=%d\n",\
95 #expr,__FILE__,__FUNCTION__,__LINE__); \
97 #else
98 #define assert(expr)
99 #endif
101 #ifdef TRUE
102 #undef TRUE
103 #endif
104 #ifdef FALSE
105 #undef FALSE
106 #endif
107 #define TRUE 1
108 #define FALSE 0
110 #define MB_ (1024*1024)
111 #define KB_ (1024)
113 #define MAX_NUM_BOARDS 7
116 /*****************************************************************
118 * chipset information
122 /* board types */
123 typedef enum {
124 BT_NONE = 0,
125 BT_SD64,
126 BT_PICCOLO,
127 BT_PICASSO,
128 BT_SPECTRUM,
129 BT_PICASSO4, /* GD5446 */
130 BT_ALPINE, /* GD543x/4x */
131 BT_GD5480,
132 BT_LAGUNA, /* GD546x */
133 } cirrusfb_board_t;
137 * per-board-type information, used for enumerating and abstracting
138 * chip-specific information
139 * NOTE: MUST be in the same order as cirrusfb_board_t in order to
140 * use direct indexing on this array
141 * NOTE: '__initdata' cannot be used as some of this info
142 * is required at runtime. Maybe separate into an init-only and
143 * a run-time table?
145 static const struct cirrusfb_board_info_rec {
146 char *name; /* ASCII name of chipset */
147 long maxclock[5]; /* maximum video clock */
148 /* for 1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */
149 unsigned init_sr07 : 1; /* init SR07 during init_vgachip() */
150 unsigned init_sr1f : 1; /* write SR1F during init_vgachip() */
151 unsigned scrn_start_bit19 : 1; /* construct bit 19 of screen start address */
153 /* initial SR07 value, then for each mode */
154 unsigned char sr07;
155 unsigned char sr07_1bpp;
156 unsigned char sr07_1bpp_mux;
157 unsigned char sr07_8bpp;
158 unsigned char sr07_8bpp_mux;
160 unsigned char sr1f; /* SR1F VGA initial register value */
161 } cirrusfb_board_info[] = {
162 [BT_SD64] = {
163 .name = "CL SD64",
164 .maxclock = {
165 /* guess */
166 /* the SD64/P4 have a higher max. videoclock */
167 140000, 140000, 140000, 140000, 140000,
169 .init_sr07 = TRUE,
170 .init_sr1f = TRUE,
171 .scrn_start_bit19 = TRUE,
172 .sr07 = 0xF0,
173 .sr07_1bpp = 0xF0,
174 .sr07_8bpp = 0xF1,
175 .sr1f = 0x20
177 [BT_PICCOLO] = {
178 .name = "CL Piccolo",
179 .maxclock = {
180 /* guess */
181 90000, 90000, 90000, 90000, 90000
183 .init_sr07 = TRUE,
184 .init_sr1f = TRUE,
185 .scrn_start_bit19 = FALSE,
186 .sr07 = 0x80,
187 .sr07_1bpp = 0x80,
188 .sr07_8bpp = 0x81,
189 .sr1f = 0x22
191 [BT_PICASSO] = {
192 .name = "CL Picasso",
193 .maxclock = {
194 /* guess */
195 90000, 90000, 90000, 90000, 90000
197 .init_sr07 = TRUE,
198 .init_sr1f = TRUE,
199 .scrn_start_bit19 = FALSE,
200 .sr07 = 0x20,
201 .sr07_1bpp = 0x20,
202 .sr07_8bpp = 0x21,
203 .sr1f = 0x22
205 [BT_SPECTRUM] = {
206 .name = "CL Spectrum",
207 .maxclock = {
208 /* guess */
209 90000, 90000, 90000, 90000, 90000
211 .init_sr07 = TRUE,
212 .init_sr1f = TRUE,
213 .scrn_start_bit19 = FALSE,
214 .sr07 = 0x80,
215 .sr07_1bpp = 0x80,
216 .sr07_8bpp = 0x81,
217 .sr1f = 0x22
219 [BT_PICASSO4] = {
220 .name = "CL Picasso4",
221 .maxclock = {
222 135100, 135100, 85500, 85500, 0
224 .init_sr07 = TRUE,
225 .init_sr1f = FALSE,
226 .scrn_start_bit19 = TRUE,
227 .sr07 = 0x20,
228 .sr07_1bpp = 0x20,
229 .sr07_8bpp = 0x21,
230 .sr1f = 0
232 [BT_ALPINE] = {
233 .name = "CL Alpine",
234 .maxclock = {
235 /* for the GD5430. GD5446 can do more... */
236 85500, 85500, 50000, 28500, 0
238 .init_sr07 = TRUE,
239 .init_sr1f = TRUE,
240 .scrn_start_bit19 = TRUE,
241 .sr07 = 0xA0,
242 .sr07_1bpp = 0xA1,
243 .sr07_1bpp_mux = 0xA7,
244 .sr07_8bpp = 0xA1,
245 .sr07_8bpp_mux = 0xA7,
246 .sr1f = 0x1C
248 [BT_GD5480] = {
249 .name = "CL GD5480",
250 .maxclock = {
251 135100, 200000, 200000, 135100, 135100
253 .init_sr07 = TRUE,
254 .init_sr1f = TRUE,
255 .scrn_start_bit19 = TRUE,
256 .sr07 = 0x10,
257 .sr07_1bpp = 0x11,
258 .sr07_8bpp = 0x11,
259 .sr1f = 0x1C
261 [BT_LAGUNA] = {
262 .name = "CL Laguna",
263 .maxclock = {
264 /* guess */
265 135100, 135100, 135100, 135100, 135100,
267 .init_sr07 = FALSE,
268 .init_sr1f = FALSE,
269 .scrn_start_bit19 = TRUE,
274 #ifdef CONFIG_PCI
275 #define CHIP(id, btype) \
276 { PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
278 static struct pci_device_id cirrusfb_pci_table[] = {
279 CHIP( PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE ),
280 CHIP( PCI_DEVICE_ID_CIRRUS_5434_8, BT_ALPINE ),
281 CHIP( PCI_DEVICE_ID_CIRRUS_5434_4, BT_ALPINE ),
282 CHIP( PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE ), /* GD-5440 is same id */
283 CHIP( PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE ),
284 CHIP( PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE ),
285 CHIP( PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480 ), /* MacPicasso likely */
286 CHIP( PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4 ), /* Picasso 4 is 5446 */
287 CHIP( PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA ), /* CL Laguna */
288 CHIP( PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA ), /* CL Laguna 3D */
289 CHIP( PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNA ), /* CL Laguna 3DA*/
290 { 0, }
292 MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
293 #undef CHIP
294 #endif /* CONFIG_PCI */
297 #ifdef CONFIG_ZORRO
298 static const struct zorro_device_id cirrusfb_zorro_table[] = {
300 .id = ZORRO_PROD_HELFRICH_SD64_RAM,
301 .driver_data = BT_SD64,
302 }, {
303 .id = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
304 .driver_data = BT_PICCOLO,
305 }, {
306 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
307 .driver_data = BT_PICASSO,
308 }, {
309 .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
310 .driver_data = BT_SPECTRUM,
311 }, {
312 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
313 .driver_data = BT_PICASSO4,
315 { 0 }
318 static const struct {
319 zorro_id id2;
320 unsigned long size;
321 } cirrusfb_zorro_table2[] = {
322 [BT_SD64] = {
323 .id2 = ZORRO_PROD_HELFRICH_SD64_REG,
324 .size = 0x400000
326 [BT_PICCOLO] = {
327 .id2 = ZORRO_PROD_HELFRICH_PICCOLO_REG,
328 .size = 0x200000
330 [BT_PICASSO] = {
331 .id2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
332 .size = 0x200000
334 [BT_SPECTRUM] = {
335 .id2 = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
336 .size = 0x200000
338 [BT_PICASSO4] = {
339 .id2 = 0,
340 .size = 0x400000
343 #endif /* CONFIG_ZORRO */
346 struct cirrusfb_regs {
347 __u32 line_length; /* in BYTES! */
348 __u32 visual;
349 __u32 type;
351 long freq;
352 long nom;
353 long den;
354 long div;
355 long multiplexing;
356 long mclk;
357 long divMCLK;
359 long HorizRes; /* The x resolution in pixel */
360 long HorizTotal;
361 long HorizDispEnd;
362 long HorizBlankStart;
363 long HorizBlankEnd;
364 long HorizSyncStart;
365 long HorizSyncEnd;
367 long VertRes; /* the physical y resolution in scanlines */
368 long VertTotal;
369 long VertDispEnd;
370 long VertSyncStart;
371 long VertSyncEnd;
372 long VertBlankStart;
373 long VertBlankEnd;
378 #ifdef CIRRUSFB_DEBUG
379 typedef enum {
380 CRT,
382 } cirrusfb_dbg_reg_class_t;
383 #endif /* CIRRUSFB_DEBUG */
388 /* info about board */
389 struct cirrusfb_info {
390 struct fb_info *info;
392 u8 __iomem *fbmem;
393 u8 __iomem *regbase;
394 u8 __iomem *mem;
395 unsigned long size;
396 cirrusfb_board_t btype;
397 unsigned char SFR; /* Shadow of special function register */
399 unsigned long fbmem_phys;
400 unsigned long fbregs_phys;
402 struct cirrusfb_regs currentmode;
403 int blank_mode;
405 u32 pseudo_palette[16];
406 struct { u8 red, green, blue, pad; } palette[256];
408 #ifdef CONFIG_ZORRO
409 struct zorro_dev *zdev;
410 #endif
411 #ifdef CONFIG_PCI
412 struct pci_dev *pdev;
413 #endif
414 void (*unmap)(struct cirrusfb_info *cinfo);
418 static unsigned cirrusfb_def_mode = 1;
419 static int noaccel = 0;
422 * Predefined Video Modes
425 static const struct {
426 const char *name;
427 struct fb_var_screeninfo var;
428 } cirrusfb_predefined[] = {
430 /* autodetect mode */
431 .name = "Autodetect",
432 }, {
433 /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
434 .name = "640x480",
435 .var = {
436 .xres = 640,
437 .yres = 480,
438 .xres_virtual = 640,
439 .yres_virtual = 480,
440 .bits_per_pixel = 8,
441 .red = { .length = 8 },
442 .green = { .length = 8 },
443 .blue = { .length = 8 },
444 .width = -1,
445 .height = -1,
446 .pixclock = 40000,
447 .left_margin = 48,
448 .right_margin = 16,
449 .upper_margin = 32,
450 .lower_margin = 8,
451 .hsync_len = 96,
452 .vsync_len = 4,
453 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
454 .vmode = FB_VMODE_NONINTERLACED
456 }, {
457 /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */
458 .name = "800x600",
459 .var = {
460 .xres = 800,
461 .yres = 600,
462 .xres_virtual = 800,
463 .yres_virtual = 600,
464 .bits_per_pixel = 8,
465 .red = { .length = 8 },
466 .green = { .length = 8 },
467 .blue = { .length = 8 },
468 .width = -1,
469 .height = -1,
470 .pixclock = 20000,
471 .left_margin = 128,
472 .right_margin = 16,
473 .upper_margin = 24,
474 .lower_margin = 2,
475 .hsync_len = 96,
476 .vsync_len = 6,
477 .vmode = FB_VMODE_NONINTERLACED
479 }, {
481 * Modeline from XF86Config:
482 * Mode "1024x768" 80 1024 1136 1340 1432 768 770 774 805
484 /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
485 .name = "1024x768",
486 .var = {
487 .xres = 1024,
488 .yres = 768,
489 .xres_virtual = 1024,
490 .yres_virtual = 768,
491 .bits_per_pixel = 8,
492 .red = { .length = 8 },
493 .green = { .length = 8 },
494 .blue = { .length = 8 },
495 .width = -1,
496 .height = -1,
497 .pixclock = 12500,
498 .left_margin = 144,
499 .right_margin = 32,
500 .upper_margin = 30,
501 .lower_margin = 2,
502 .hsync_len = 192,
503 .vsync_len = 6,
504 .vmode = FB_VMODE_NONINTERLACED
509 #define NUM_TOTAL_MODES ARRAY_SIZE(cirrusfb_predefined)
511 /****************************************************************************/
512 /**** BEGIN PROTOTYPES ******************************************************/
515 /*--- Interface used by the world ------------------------------------------*/
516 static int cirrusfb_init (void);
517 #ifndef MODULE
518 static int cirrusfb_setup (char *options);
519 #endif
521 static int cirrusfb_open (struct fb_info *info, int user);
522 static int cirrusfb_release (struct fb_info *info, int user);
523 static int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
524 unsigned blue, unsigned transp,
525 struct fb_info *info);
526 static int cirrusfb_check_var (struct fb_var_screeninfo *var,
527 struct fb_info *info);
528 static int cirrusfb_set_par (struct fb_info *info);
529 static int cirrusfb_pan_display (struct fb_var_screeninfo *var,
530 struct fb_info *info);
531 static int cirrusfb_blank (int blank_mode, struct fb_info *info);
532 static void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *region);
533 static void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
534 static void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image);
536 /* function table of the above functions */
537 static struct fb_ops cirrusfb_ops = {
538 .owner = THIS_MODULE,
539 .fb_open = cirrusfb_open,
540 .fb_release = cirrusfb_release,
541 .fb_setcolreg = cirrusfb_setcolreg,
542 .fb_check_var = cirrusfb_check_var,
543 .fb_set_par = cirrusfb_set_par,
544 .fb_pan_display = cirrusfb_pan_display,
545 .fb_blank = cirrusfb_blank,
546 .fb_fillrect = cirrusfb_fillrect,
547 .fb_copyarea = cirrusfb_copyarea,
548 .fb_imageblit = cirrusfb_imageblit,
551 /*--- Hardware Specific Routines -------------------------------------------*/
552 static int cirrusfb_decode_var (const struct fb_var_screeninfo *var,
553 struct cirrusfb_regs *regs,
554 const struct fb_info *info);
555 /*--- Internal routines ----------------------------------------------------*/
556 static void init_vgachip (struct cirrusfb_info *cinfo);
557 static void switch_monitor (struct cirrusfb_info *cinfo, int on);
558 static void WGen (const struct cirrusfb_info *cinfo,
559 int regnum, unsigned char val);
560 static unsigned char RGen (const struct cirrusfb_info *cinfo, int regnum);
561 static void AttrOn (const struct cirrusfb_info *cinfo);
562 static void WHDR (const struct cirrusfb_info *cinfo, unsigned char val);
563 static void WSFR (struct cirrusfb_info *cinfo, unsigned char val);
564 static void WSFR2 (struct cirrusfb_info *cinfo, unsigned char val);
565 static void WClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
566 unsigned char green,
567 unsigned char blue);
568 #if 0
569 static void RClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
570 unsigned char *green,
571 unsigned char *blue);
572 #endif
573 static void cirrusfb_WaitBLT (u8 __iomem *regbase);
574 static void cirrusfb_BitBLT (u8 __iomem *regbase, int bits_per_pixel,
575 u_short curx, u_short cury,
576 u_short destx, u_short desty,
577 u_short width, u_short height,
578 u_short line_length);
579 static void cirrusfb_RectFill (u8 __iomem *regbase, int bits_per_pixel,
580 u_short x, u_short y,
581 u_short width, u_short height,
582 u_char color, u_short line_length);
584 static void bestclock (long freq, long *best,
585 long *nom, long *den,
586 long *div, long maxfreq);
588 #ifdef CIRRUSFB_DEBUG
589 static void cirrusfb_dump (void);
590 static void cirrusfb_dbg_reg_dump (caddr_t regbase);
591 static void cirrusfb_dbg_print_regs (caddr_t regbase, cirrusfb_dbg_reg_class_t reg_class,...);
592 static void cirrusfb_dbg_print_byte (const char *name, unsigned char val);
593 #endif /* CIRRUSFB_DEBUG */
595 /*** END PROTOTYPES ********************************************************/
596 /*****************************************************************************/
597 /*** BEGIN Interface Used by the World ***************************************/
599 static int opencount = 0;
601 /*--- Open /dev/fbx ---------------------------------------------------------*/
602 static int cirrusfb_open (struct fb_info *info, int user)
604 if (opencount++ == 0)
605 switch_monitor (info->par, 1);
606 return 0;
609 /*--- Close /dev/fbx --------------------------------------------------------*/
610 static int cirrusfb_release (struct fb_info *info, int user)
612 if (--opencount == 0)
613 switch_monitor (info->par, 0);
614 return 0;
617 /**** END Interface used by the World *************************************/
618 /****************************************************************************/
619 /**** BEGIN Hardware specific Routines **************************************/
621 /* Get a good MCLK value */
622 static long cirrusfb_get_mclk (long freq, int bpp, long *div)
624 long mclk;
626 assert (div != NULL);
628 /* Calculate MCLK, in case VCLK is high enough to require > 50MHz.
629 * Assume a 64-bit data path for now. The formula is:
630 * ((B * PCLK * 2)/W) * 1.2
631 * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */
632 mclk = ((bpp / 8) * freq * 2) / 4;
633 mclk = (mclk * 12) / 10;
634 if (mclk < 50000)
635 mclk = 50000;
636 DPRINTK ("Use MCLK of %ld kHz\n", mclk);
638 /* Calculate value for SR1F. Multiply by 2 so we can round up. */
639 mclk = ((mclk * 16) / 14318);
640 mclk = (mclk + 1) / 2;
641 DPRINTK ("Set SR1F[5:0] to 0x%lx\n", mclk);
643 /* Determine if we should use MCLK instead of VCLK, and if so, what we
644 * should divide it by to get VCLK */
645 switch (freq) {
646 case 24751 ... 25249:
647 *div = 2;
648 DPRINTK ("Using VCLK = MCLK/2\n");
649 break;
650 case 49501 ... 50499:
651 *div = 1;
652 DPRINTK ("Using VCLK = MCLK\n");
653 break;
654 default:
655 *div = 0;
656 break;
659 return mclk;
662 static int cirrusfb_check_var(struct fb_var_screeninfo *var,
663 struct fb_info *info)
665 struct cirrusfb_info *cinfo = info->par;
666 int nom, den; /* translyting from pixels->bytes */
667 int yres, i;
668 static struct { int xres, yres; } modes[] =
669 { { 1600, 1280 },
670 { 1280, 1024 },
671 { 1024, 768 },
672 { 800, 600 },
673 { 640, 480 },
674 { -1, -1 } };
676 switch (var->bits_per_pixel) {
677 case 0 ... 1:
678 var->bits_per_pixel = 1;
679 nom = 4;
680 den = 8;
681 break; /* 8 pixel per byte, only 1/4th of mem usable */
682 case 2 ... 8:
683 var->bits_per_pixel = 8;
684 nom = 1;
685 den = 1;
686 break; /* 1 pixel == 1 byte */
687 case 9 ... 16:
688 var->bits_per_pixel = 16;
689 nom = 2;
690 den = 1;
691 break; /* 2 bytes per pixel */
692 case 17 ... 24:
693 var->bits_per_pixel = 24;
694 nom = 3;
695 den = 1;
696 break; /* 3 bytes per pixel */
697 case 25 ... 32:
698 var->bits_per_pixel = 32;
699 nom = 4;
700 den = 1;
701 break; /* 4 bytes per pixel */
702 default:
703 printk ("cirrusfb: mode %dx%dx%d rejected...color depth not supported.\n",
704 var->xres, var->yres, var->bits_per_pixel);
705 DPRINTK ("EXIT - EINVAL error\n");
706 return -EINVAL;
709 if (var->xres * nom / den * var->yres > cinfo->size) {
710 printk ("cirrusfb: mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
711 var->xres, var->yres, var->bits_per_pixel);
712 DPRINTK ("EXIT - EINVAL error\n");
713 return -EINVAL;
716 /* use highest possible virtual resolution */
717 if (var->xres_virtual == -1 &&
718 var->yres_virtual == -1) {
719 printk ("cirrusfb: using maximum available virtual resolution\n");
720 for (i = 0; modes[i].xres != -1; i++) {
721 if (modes[i].xres * nom / den * modes[i].yres < cinfo->size / 2)
722 break;
724 if (modes[i].xres == -1) {
725 printk ("cirrusfb: could not find a virtual resolution that fits into video memory!!\n");
726 DPRINTK ("EXIT - EINVAL error\n");
727 return -EINVAL;
729 var->xres_virtual = modes[i].xres;
730 var->yres_virtual = modes[i].yres;
732 printk ("cirrusfb: virtual resolution set to maximum of %dx%d\n",
733 var->xres_virtual, var->yres_virtual);
736 if (var->xres_virtual < var->xres)
737 var->xres_virtual = var->xres;
738 if (var->yres_virtual < var->yres)
739 var->yres_virtual = var->yres;
741 if (var->xoffset < 0)
742 var->xoffset = 0;
743 if (var->yoffset < 0)
744 var->yoffset = 0;
746 /* truncate xoffset and yoffset to maximum if too high */
747 if (var->xoffset > var->xres_virtual - var->xres)
748 var->xoffset = var->xres_virtual - var->xres - 1;
749 if (var->yoffset > var->yres_virtual - var->yres)
750 var->yoffset = var->yres_virtual - var->yres - 1;
752 switch (var->bits_per_pixel) {
753 case 1:
754 var->red.offset = 0;
755 var->red.length = 1;
756 var->green.offset = 0;
757 var->green.length = 1;
758 var->blue.offset = 0;
759 var->blue.length = 1;
760 break;
762 case 8:
763 var->red.offset = 0;
764 var->red.length = 6;
765 var->green.offset = 0;
766 var->green.length = 6;
767 var->blue.offset = 0;
768 var->blue.length = 6;
769 break;
771 case 16:
772 if(isPReP) {
773 var->red.offset = 2;
774 var->green.offset = -3;
775 var->blue.offset = 8;
776 } else {
777 var->red.offset = 10;
778 var->green.offset = 5;
779 var->blue.offset = 0;
781 var->red.length = 5;
782 var->green.length = 5;
783 var->blue.length = 5;
784 break;
786 case 24:
787 if(isPReP) {
788 var->red.offset = 8;
789 var->green.offset = 16;
790 var->blue.offset = 24;
791 } else {
792 var->red.offset = 16;
793 var->green.offset = 8;
794 var->blue.offset = 0;
796 var->red.length = 8;
797 var->green.length = 8;
798 var->blue.length = 8;
799 break;
801 case 32:
802 if(isPReP) {
803 var->red.offset = 8;
804 var->green.offset = 16;
805 var->blue.offset = 24;
806 } else {
807 var->red.offset = 16;
808 var->green.offset = 8;
809 var->blue.offset = 0;
811 var->red.length = 8;
812 var->green.length = 8;
813 var->blue.length = 8;
814 break;
816 default:
817 DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);
818 assert (FALSE);
819 /* should never occur */
820 break;
823 var->red.msb_right =
824 var->green.msb_right =
825 var->blue.msb_right =
826 var->transp.offset =
827 var->transp.length =
828 var->transp.msb_right = 0;
830 yres = var->yres;
831 if (var->vmode & FB_VMODE_DOUBLE)
832 yres *= 2;
833 else if (var->vmode & FB_VMODE_INTERLACED)
834 yres = (yres + 1) / 2;
836 if (yres >= 1280) {
837 printk (KERN_WARNING "cirrusfb: ERROR: VerticalTotal >= 1280; special treatment required! (TODO)\n");
838 DPRINTK ("EXIT - EINVAL error\n");
839 return -EINVAL;
842 return 0;
845 static int cirrusfb_decode_var (const struct fb_var_screeninfo *var,
846 struct cirrusfb_regs *regs,
847 const struct fb_info *info)
849 long freq;
850 long maxclock;
851 int maxclockidx = 0;
852 struct cirrusfb_info *cinfo = info->par;
853 int xres, hfront, hsync, hback;
854 int yres, vfront, vsync, vback;
856 switch(var->bits_per_pixel) {
857 case 1:
858 regs->line_length = var->xres_virtual / 8;
859 regs->visual = FB_VISUAL_MONO10;
860 maxclockidx = 0;
861 break;
863 case 8:
864 regs->line_length = var->xres_virtual;
865 regs->visual = FB_VISUAL_PSEUDOCOLOR;
866 maxclockidx = 1;
867 break;
869 case 16:
870 regs->line_length = var->xres_virtual * 2;
871 regs->visual = FB_VISUAL_DIRECTCOLOR;
872 maxclockidx = 2;
873 break;
875 case 24:
876 regs->line_length = var->xres_virtual * 3;
877 regs->visual = FB_VISUAL_DIRECTCOLOR;
878 maxclockidx = 3;
879 break;
881 case 32:
882 regs->line_length = var->xres_virtual * 4;
883 regs->visual = FB_VISUAL_DIRECTCOLOR;
884 maxclockidx = 4;
885 break;
887 default:
888 DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);
889 assert (FALSE);
890 /* should never occur */
891 break;
894 regs->type = FB_TYPE_PACKED_PIXELS;
896 /* convert from ps to kHz */
897 freq = 1000000000 / var->pixclock;
899 DPRINTK ("desired pixclock: %ld kHz\n", freq);
901 maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
902 regs->multiplexing = 0;
904 /* If the frequency is greater than we can support, we might be able
905 * to use multiplexing for the video mode */
906 if (freq > maxclock) {
907 switch (cinfo->btype) {
908 case BT_ALPINE:
909 case BT_GD5480:
910 regs->multiplexing = 1;
911 break;
913 default:
914 printk (KERN_WARNING "cirrusfb: ERROR: Frequency greater than maxclock (%ld kHz)\n", maxclock);
915 DPRINTK ("EXIT - return -EINVAL\n");
916 return -EINVAL;
919 #if 0
920 /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
921 * the VCLK is double the pixel clock. */
922 switch (var->bits_per_pixel) {
923 case 16:
924 case 32:
925 if (regs->HorizRes <= 800)
926 freq /= 2; /* Xbh has this type of clock for 32-bit */
927 break;
929 #endif
931 bestclock (freq, &regs->freq, &regs->nom, &regs->den, &regs->div,
932 maxclock);
933 regs->mclk = cirrusfb_get_mclk (freq, var->bits_per_pixel, &regs->divMCLK);
935 xres = var->xres;
936 hfront = var->right_margin;
937 hsync = var->hsync_len;
938 hback = var->left_margin;
940 yres = var->yres;
941 vfront = var->lower_margin;
942 vsync = var->vsync_len;
943 vback = var->upper_margin;
945 if (var->vmode & FB_VMODE_DOUBLE) {
946 yres *= 2;
947 vfront *= 2;
948 vsync *= 2;
949 vback *= 2;
950 } else if (var->vmode & FB_VMODE_INTERLACED) {
951 yres = (yres + 1) / 2;
952 vfront = (vfront + 1) / 2;
953 vsync = (vsync + 1) / 2;
954 vback = (vback + 1) / 2;
956 regs->HorizRes = xres;
957 regs->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5;
958 regs->HorizDispEnd = xres / 8 - 1;
959 regs->HorizBlankStart = xres / 8;
960 regs->HorizBlankEnd = regs->HorizTotal + 5; /* does not count with "-5" */
961 regs->HorizSyncStart = (xres + hfront) / 8 + 1;
962 regs->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1;
964 regs->VertRes = yres;
965 regs->VertTotal = yres + vfront + vsync + vback - 2;
966 regs->VertDispEnd = yres - 1;
967 regs->VertBlankStart = yres;
968 regs->VertBlankEnd = regs->VertTotal;
969 regs->VertSyncStart = yres + vfront - 1;
970 regs->VertSyncEnd = yres + vfront + vsync - 1;
972 if (regs->VertRes >= 1024) {
973 regs->VertTotal /= 2;
974 regs->VertSyncStart /= 2;
975 regs->VertSyncEnd /= 2;
976 regs->VertDispEnd /= 2;
978 if (regs->multiplexing) {
979 regs->HorizTotal /= 2;
980 regs->HorizSyncStart /= 2;
981 regs->HorizSyncEnd /= 2;
982 regs->HorizDispEnd /= 2;
985 return 0;
989 static void cirrusfb_set_mclk (const struct cirrusfb_info *cinfo, int val, int div)
991 assert (cinfo != NULL);
993 if (div == 2) {
994 /* VCLK = MCLK/2 */
995 unsigned char old = vga_rseq (cinfo->regbase, CL_SEQR1E);
996 vga_wseq (cinfo->regbase, CL_SEQR1E, old | 0x1);
997 vga_wseq (cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
998 } else if (div == 1) {
999 /* VCLK = MCLK */
1000 unsigned char old = vga_rseq (cinfo->regbase, CL_SEQR1E);
1001 vga_wseq (cinfo->regbase, CL_SEQR1E, old & ~0x1);
1002 vga_wseq (cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
1003 } else {
1004 vga_wseq (cinfo->regbase, CL_SEQR1F, val & 0x3f);
1008 /*************************************************************************
1009 cirrusfb_set_par_foo()
1011 actually writes the values for a new video mode into the hardware,
1012 **************************************************************************/
1013 static int cirrusfb_set_par_foo (struct fb_info *info)
1015 struct cirrusfb_info *cinfo = info->par;
1016 struct fb_var_screeninfo *var = &info->var;
1017 struct cirrusfb_regs regs;
1018 u8 __iomem *regbase = cinfo->regbase;
1019 unsigned char tmp;
1020 int offset = 0, err;
1021 const struct cirrusfb_board_info_rec *bi;
1023 DPRINTK ("ENTER\n");
1024 DPRINTK ("Requested mode: %dx%dx%d\n",
1025 var->xres, var->yres, var->bits_per_pixel);
1026 DPRINTK ("pixclock: %d\n", var->pixclock);
1028 init_vgachip (cinfo);
1030 err = cirrusfb_decode_var(var, &regs, info);
1031 if(err) {
1032 /* should never happen */
1033 DPRINTK("mode change aborted. invalid var.\n");
1034 return -EINVAL;
1037 bi = &cirrusfb_board_info[cinfo->btype];
1040 /* unlock register VGA_CRTC_H_TOTAL..CRT7 */
1041 vga_wcrt (regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */
1043 /* if debugging is enabled, all parameters get output before writing */
1044 DPRINTK ("CRT0: %ld\n", regs.HorizTotal);
1045 vga_wcrt (regbase, VGA_CRTC_H_TOTAL, regs.HorizTotal);
1047 DPRINTK ("CRT1: %ld\n", regs.HorizDispEnd);
1048 vga_wcrt (regbase, VGA_CRTC_H_DISP, regs.HorizDispEnd);
1050 DPRINTK ("CRT2: %ld\n", regs.HorizBlankStart);
1051 vga_wcrt (regbase, VGA_CRTC_H_BLANK_START, regs.HorizBlankStart);
1053 DPRINTK ("CRT3: 128+%ld\n", regs.HorizBlankEnd % 32); /* + 128: Compatible read */
1054 vga_wcrt (regbase, VGA_CRTC_H_BLANK_END, 128 + (regs.HorizBlankEnd % 32));
1056 DPRINTK ("CRT4: %ld\n", regs.HorizSyncStart);
1057 vga_wcrt (regbase, VGA_CRTC_H_SYNC_START, regs.HorizSyncStart);
1059 tmp = regs.HorizSyncEnd % 32;
1060 if (regs.HorizBlankEnd & 32)
1061 tmp += 128;
1062 DPRINTK ("CRT5: %d\n", tmp);
1063 vga_wcrt (regbase, VGA_CRTC_H_SYNC_END, tmp);
1065 DPRINTK ("CRT6: %ld\n", regs.VertTotal & 0xff);
1066 vga_wcrt (regbase, VGA_CRTC_V_TOTAL, (regs.VertTotal & 0xff));
1068 tmp = 16; /* LineCompare bit #9 */
1069 if (regs.VertTotal & 256)
1070 tmp |= 1;
1071 if (regs.VertDispEnd & 256)
1072 tmp |= 2;
1073 if (regs.VertSyncStart & 256)
1074 tmp |= 4;
1075 if (regs.VertBlankStart & 256)
1076 tmp |= 8;
1077 if (regs.VertTotal & 512)
1078 tmp |= 32;
1079 if (regs.VertDispEnd & 512)
1080 tmp |= 64;
1081 if (regs.VertSyncStart & 512)
1082 tmp |= 128;
1083 DPRINTK ("CRT7: %d\n", tmp);
1084 vga_wcrt (regbase, VGA_CRTC_OVERFLOW, tmp);
1086 tmp = 0x40; /* LineCompare bit #8 */
1087 if (regs.VertBlankStart & 512)
1088 tmp |= 0x20;
1089 if (var->vmode & FB_VMODE_DOUBLE)
1090 tmp |= 0x80;
1091 DPRINTK ("CRT9: %d\n", tmp);
1092 vga_wcrt (regbase, VGA_CRTC_MAX_SCAN, tmp);
1094 DPRINTK ("CRT10: %ld\n", regs.VertSyncStart & 0xff);
1095 vga_wcrt (regbase, VGA_CRTC_V_SYNC_START, (regs.VertSyncStart & 0xff));
1097 DPRINTK ("CRT11: 64+32+%ld\n", regs.VertSyncEnd % 16);
1098 vga_wcrt (regbase, VGA_CRTC_V_SYNC_END, (regs.VertSyncEnd % 16 + 64 + 32));
1100 DPRINTK ("CRT12: %ld\n", regs.VertDispEnd & 0xff);
1101 vga_wcrt (regbase, VGA_CRTC_V_DISP_END, (regs.VertDispEnd & 0xff));
1103 DPRINTK ("CRT15: %ld\n", regs.VertBlankStart & 0xff);
1104 vga_wcrt (regbase, VGA_CRTC_V_BLANK_START, (regs.VertBlankStart & 0xff));
1106 DPRINTK ("CRT16: %ld\n", regs.VertBlankEnd & 0xff);
1107 vga_wcrt (regbase, VGA_CRTC_V_BLANK_END, (regs.VertBlankEnd & 0xff));
1109 DPRINTK ("CRT18: 0xff\n");
1110 vga_wcrt (regbase, VGA_CRTC_LINE_COMPARE, 0xff);
1112 tmp = 0;
1113 if (var->vmode & FB_VMODE_INTERLACED)
1114 tmp |= 1;
1115 if (regs.HorizBlankEnd & 64)
1116 tmp |= 16;
1117 if (regs.HorizBlankEnd & 128)
1118 tmp |= 32;
1119 if (regs.VertBlankEnd & 256)
1120 tmp |= 64;
1121 if (regs.VertBlankEnd & 512)
1122 tmp |= 128;
1124 DPRINTK ("CRT1a: %d\n", tmp);
1125 vga_wcrt (regbase, CL_CRT1A, tmp);
1127 /* set VCLK0 */
1128 /* hardware RefClock: 14.31818 MHz */
1129 /* formula: VClk = (OSC * N) / (D * (1+P)) */
1130 /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
1132 vga_wseq (regbase, CL_SEQRB, regs.nom);
1133 tmp = regs.den << 1;
1134 if (regs.div != 0)
1135 tmp |= 1;
1137 if ((cinfo->btype == BT_SD64) ||
1138 (cinfo->btype == BT_ALPINE) ||
1139 (cinfo->btype == BT_GD5480))
1140 tmp |= 0x80; /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
1142 DPRINTK ("CL_SEQR1B: %ld\n", (long) tmp);
1143 vga_wseq (regbase, CL_SEQR1B, tmp);
1145 if (regs.VertRes >= 1024)
1146 /* 1280x1024 */
1147 vga_wcrt (regbase, VGA_CRTC_MODE, 0xc7);
1148 else
1149 /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
1150 * address wrap, no compat. */
1151 vga_wcrt (regbase, VGA_CRTC_MODE, 0xc3);
1153 /* HAEH? vga_wcrt (regbase, VGA_CRTC_V_SYNC_END, 0x20); * previously: 0x00 unlock VGA_CRTC_H_TOTAL..CRT7 */
1155 /* don't know if it would hurt to also program this if no interlaced */
1156 /* mode is used, but I feel better this way.. :-) */
1157 if (var->vmode & FB_VMODE_INTERLACED)
1158 vga_wcrt (regbase, VGA_CRTC_REGS, regs.HorizTotal / 2);
1159 else
1160 vga_wcrt (regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
1162 vga_wseq (regbase, VGA_SEQ_CHARACTER_MAP, 0);
1164 /* adjust horizontal/vertical sync type (low/high) */
1165 tmp = 0x03; /* enable display memory & CRTC I/O address for color mode */
1166 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1167 tmp |= 0x40;
1168 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1169 tmp |= 0x80;
1170 WGen (cinfo, VGA_MIS_W, tmp);
1172 vga_wcrt (regbase, VGA_CRTC_PRESET_ROW, 0); /* Screen A Preset Row-Scan register */
1173 vga_wcrt (regbase, VGA_CRTC_CURSOR_START, 0); /* text cursor on and start line */
1174 vga_wcrt (regbase, VGA_CRTC_CURSOR_END, 31); /* text cursor end line */
1176 /******************************************************
1178 * 1 bpp
1182 /* programming for different color depths */
1183 if (var->bits_per_pixel == 1) {
1184 DPRINTK ("cirrusfb: preparing for 1 bit deep display\n");
1185 vga_wgfx (regbase, VGA_GFX_MODE, 0); /* mode register */
1187 /* SR07 */
1188 switch (cinfo->btype) {
1189 case BT_SD64:
1190 case BT_PICCOLO:
1191 case BT_PICASSO:
1192 case BT_SPECTRUM:
1193 case BT_PICASSO4:
1194 case BT_ALPINE:
1195 case BT_GD5480:
1196 DPRINTK (" (for GD54xx)\n");
1197 vga_wseq (regbase, CL_SEQR7,
1198 regs.multiplexing ?
1199 bi->sr07_1bpp_mux : bi->sr07_1bpp);
1200 break;
1202 case BT_LAGUNA:
1203 DPRINTK (" (for GD546x)\n");
1204 vga_wseq (regbase, CL_SEQR7,
1205 vga_rseq (regbase, CL_SEQR7) & ~0x01);
1206 break;
1208 default:
1209 printk (KERN_WARNING "cirrusfb: unknown Board\n");
1210 break;
1213 /* Extended Sequencer Mode */
1214 switch (cinfo->btype) {
1215 case BT_SD64:
1216 /* setting the SEQRF on SD64 is not necessary (only during init) */
1217 DPRINTK ("(for SD64)\n");
1218 vga_wseq (regbase, CL_SEQR1F, 0x1a); /* MCLK select */
1219 break;
1221 case BT_PICCOLO:
1222 DPRINTK ("(for Piccolo)\n");
1223 /* ### ueberall 0x22? */
1224 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ##vorher 1c MCLK select */
1225 vga_wseq (regbase, CL_SEQRF, 0xb0); /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
1226 break;
1228 case BT_PICASSO:
1229 DPRINTK ("(for Picasso)\n");
1230 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ##vorher 22 MCLK select */
1231 vga_wseq (regbase, CL_SEQRF, 0xd0); /* ## vorher d0 avoid FIFO underruns..? */
1232 break;
1234 case BT_SPECTRUM:
1235 DPRINTK ("(for Spectrum)\n");
1236 /* ### ueberall 0x22? */
1237 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ##vorher 1c MCLK select */
1238 vga_wseq (regbase, CL_SEQRF, 0xb0); /* evtl d0? avoid FIFO underruns..? */
1239 break;
1241 case BT_PICASSO4:
1242 case BT_ALPINE:
1243 case BT_GD5480:
1244 case BT_LAGUNA:
1245 DPRINTK (" (for GD54xx)\n");
1246 /* do nothing */
1247 break;
1249 default:
1250 printk (KERN_WARNING "cirrusfb: unknown Board\n");
1251 break;
1254 WGen (cinfo, VGA_PEL_MSK, 0x01); /* pixel mask: pass-through for first plane */
1255 if (regs.multiplexing)
1256 WHDR (cinfo, 0x4a); /* hidden dac reg: 1280x1024 */
1257 else
1258 WHDR (cinfo, 0); /* hidden dac: nothing */
1259 vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x06); /* memory mode: odd/even, ext. memory */
1260 vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0x01); /* plane mask: only write to first plane */
1261 offset = var->xres_virtual / 16;
1264 /******************************************************
1266 * 8 bpp
1270 else if (var->bits_per_pixel == 8) {
1271 DPRINTK ("cirrusfb: preparing for 8 bit deep display\n");
1272 switch (cinfo->btype) {
1273 case BT_SD64:
1274 case BT_PICCOLO:
1275 case BT_PICASSO:
1276 case BT_SPECTRUM:
1277 case BT_PICASSO4:
1278 case BT_ALPINE:
1279 case BT_GD5480:
1280 DPRINTK (" (for GD54xx)\n");
1281 vga_wseq (regbase, CL_SEQR7,
1282 regs.multiplexing ?
1283 bi->sr07_8bpp_mux : bi->sr07_8bpp);
1284 break;
1286 case BT_LAGUNA:
1287 DPRINTK (" (for GD546x)\n");
1288 vga_wseq (regbase, CL_SEQR7,
1289 vga_rseq (regbase, CL_SEQR7) | 0x01);
1290 break;
1292 default:
1293 printk (KERN_WARNING "cirrusfb: unknown Board\n");
1294 break;
1297 switch (cinfo->btype) {
1298 case BT_SD64:
1299 vga_wseq (regbase, CL_SEQR1F, 0x1d); /* MCLK select */
1300 break;
1302 case BT_PICCOLO:
1303 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */
1304 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1305 break;
1307 case BT_PICASSO:
1308 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */
1309 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1310 break;
1312 case BT_SPECTRUM:
1313 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */
1314 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1315 break;
1317 case BT_PICASSO4:
1318 #ifdef CONFIG_ZORRO
1319 vga_wseq (regbase, CL_SEQRF, 0xb8); /* ### INCOMPLETE!! */
1320 #endif
1321 /* vga_wseq (regbase, CL_SEQR1F, 0x1c); */
1322 break;
1324 case BT_ALPINE:
1325 DPRINTK (" (for GD543x)\n");
1326 cirrusfb_set_mclk (cinfo, regs.mclk, regs.divMCLK);
1327 /* We already set SRF and SR1F */
1328 break;
1330 case BT_GD5480:
1331 case BT_LAGUNA:
1332 DPRINTK (" (for GD54xx)\n");
1333 /* do nothing */
1334 break;
1336 default:
1337 printk (KERN_WARNING "cirrusfb: unknown Board\n");
1338 break;
1341 vga_wgfx (regbase, VGA_GFX_MODE, 64); /* mode register: 256 color mode */
1342 WGen (cinfo, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */
1343 if (regs.multiplexing)
1344 WHDR (cinfo, 0x4a); /* hidden dac reg: 1280x1024 */
1345 else
1346 WHDR (cinfo, 0); /* hidden dac: nothing */
1347 vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */
1348 vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */
1349 offset = var->xres_virtual / 8;
1352 /******************************************************
1354 * 16 bpp
1358 else if (var->bits_per_pixel == 16) {
1359 DPRINTK ("cirrusfb: preparing for 16 bit deep display\n");
1360 switch (cinfo->btype) {
1361 case BT_SD64:
1362 vga_wseq (regbase, CL_SEQR7, 0xf7); /* Extended Sequencer Mode: 256c col. mode */
1363 vga_wseq (regbase, CL_SEQR1F, 0x1e); /* MCLK select */
1364 break;
1366 case BT_PICCOLO:
1367 vga_wseq (regbase, CL_SEQR7, 0x87);
1368 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1369 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
1370 break;
1372 case BT_PICASSO:
1373 vga_wseq (regbase, CL_SEQR7, 0x27);
1374 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1375 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
1376 break;
1378 case BT_SPECTRUM:
1379 vga_wseq (regbase, CL_SEQR7, 0x87);
1380 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1381 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
1382 break;
1384 case BT_PICASSO4:
1385 vga_wseq (regbase, CL_SEQR7, 0x27);
1386 /* vga_wseq (regbase, CL_SEQR1F, 0x1c); */
1387 break;
1389 case BT_ALPINE:
1390 DPRINTK (" (for GD543x)\n");
1391 if (regs.HorizRes >= 1024)
1392 vga_wseq (regbase, CL_SEQR7, 0xa7);
1393 else
1394 vga_wseq (regbase, CL_SEQR7, 0xa3);
1395 cirrusfb_set_mclk (cinfo, regs.mclk, regs.divMCLK);
1396 break;
1398 case BT_GD5480:
1399 DPRINTK (" (for GD5480)\n");
1400 vga_wseq (regbase, CL_SEQR7, 0x17);
1401 /* We already set SRF and SR1F */
1402 break;
1404 case BT_LAGUNA:
1405 DPRINTK (" (for GD546x)\n");
1406 vga_wseq (regbase, CL_SEQR7,
1407 vga_rseq (regbase, CL_SEQR7) & ~0x01);
1408 break;
1410 default:
1411 printk (KERN_WARNING "CIRRUSFB: unknown Board\n");
1412 break;
1415 vga_wgfx (regbase, VGA_GFX_MODE, 64); /* mode register: 256 color mode */
1416 WGen (cinfo, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */
1417 #ifdef CONFIG_PCI
1418 WHDR (cinfo, 0xc0); /* Copy Xbh */
1419 #elif defined(CONFIG_ZORRO)
1420 /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
1421 WHDR (cinfo, 0xa0); /* hidden dac reg: nothing special */
1422 #endif
1423 vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */
1424 vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */
1425 offset = var->xres_virtual / 4;
1428 /******************************************************
1430 * 32 bpp
1434 else if (var->bits_per_pixel == 32) {
1435 DPRINTK ("cirrusfb: preparing for 24/32 bit deep display\n");
1436 switch (cinfo->btype) {
1437 case BT_SD64:
1438 vga_wseq (regbase, CL_SEQR7, 0xf9); /* Extended Sequencer Mode: 256c col. mode */
1439 vga_wseq (regbase, CL_SEQR1F, 0x1e); /* MCLK select */
1440 break;
1442 case BT_PICCOLO:
1443 vga_wseq (regbase, CL_SEQR7, 0x85);
1444 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1445 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
1446 break;
1448 case BT_PICASSO:
1449 vga_wseq (regbase, CL_SEQR7, 0x25);
1450 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1451 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
1452 break;
1454 case BT_SPECTRUM:
1455 vga_wseq (regbase, CL_SEQR7, 0x85);
1456 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1457 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
1458 break;
1460 case BT_PICASSO4:
1461 vga_wseq (regbase, CL_SEQR7, 0x25);
1462 /* vga_wseq (regbase, CL_SEQR1F, 0x1c); */
1463 break;
1465 case BT_ALPINE:
1466 DPRINTK (" (for GD543x)\n");
1467 vga_wseq (regbase, CL_SEQR7, 0xa9);
1468 cirrusfb_set_mclk (cinfo, regs.mclk, regs.divMCLK);
1469 break;
1471 case BT_GD5480:
1472 DPRINTK (" (for GD5480)\n");
1473 vga_wseq (regbase, CL_SEQR7, 0x19);
1474 /* We already set SRF and SR1F */
1475 break;
1477 case BT_LAGUNA:
1478 DPRINTK (" (for GD546x)\n");
1479 vga_wseq (regbase, CL_SEQR7,
1480 vga_rseq (regbase, CL_SEQR7) & ~0x01);
1481 break;
1483 default:
1484 printk (KERN_WARNING "cirrusfb: unknown Board\n");
1485 break;
1488 vga_wgfx (regbase, VGA_GFX_MODE, 64); /* mode register: 256 color mode */
1489 WGen (cinfo, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */
1490 WHDR (cinfo, 0xc5); /* hidden dac reg: 8-8-8 mode (24 or 32) */
1491 vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */
1492 vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */
1493 offset = var->xres_virtual / 4;
1496 /******************************************************
1498 * unknown/unsupported bpp
1502 else {
1503 printk (KERN_ERR "cirrusfb: What's this?? requested color depth == %d.\n",
1504 var->bits_per_pixel);
1507 vga_wcrt (regbase, VGA_CRTC_OFFSET, offset & 0xff);
1508 tmp = 0x22;
1509 if (offset & 0x100)
1510 tmp |= 0x10; /* offset overflow bit */
1512 vga_wcrt (regbase, CL_CRT1B, tmp); /* screen start addr #16-18, fastpagemode cycles */
1514 if (cinfo->btype == BT_SD64 ||
1515 cinfo->btype == BT_PICASSO4 ||
1516 cinfo->btype == BT_ALPINE ||
1517 cinfo->btype == BT_GD5480)
1518 vga_wcrt (regbase, CL_CRT1D, 0x00); /* screen start address bit 19 */
1520 vga_wcrt (regbase, VGA_CRTC_CURSOR_HI, 0); /* text cursor location high */
1521 vga_wcrt (regbase, VGA_CRTC_CURSOR_LO, 0); /* text cursor location low */
1522 vga_wcrt (regbase, VGA_CRTC_UNDERLINE, 0); /* underline row scanline = at very bottom */
1524 vga_wattr (regbase, VGA_ATC_MODE, 1); /* controller mode */
1525 vga_wattr (regbase, VGA_ATC_OVERSCAN, 0); /* overscan (border) color */
1526 vga_wattr (regbase, VGA_ATC_PLANE_ENABLE, 15); /* color plane enable */
1527 vga_wattr (regbase, CL_AR33, 0); /* pixel panning */
1528 vga_wattr (regbase, VGA_ATC_COLOR_PAGE, 0); /* color select */
1530 /* [ EGS: SetOffset(); ] */
1531 /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
1532 AttrOn (cinfo);
1534 vga_wgfx (regbase, VGA_GFX_SR_VALUE, 0); /* set/reset register */
1535 vga_wgfx (regbase, VGA_GFX_SR_ENABLE, 0); /* set/reset enable */
1536 vga_wgfx (regbase, VGA_GFX_COMPARE_VALUE, 0); /* color compare */
1537 vga_wgfx (regbase, VGA_GFX_DATA_ROTATE, 0); /* data rotate */
1538 vga_wgfx (regbase, VGA_GFX_PLANE_READ, 0); /* read map select */
1539 vga_wgfx (regbase, VGA_GFX_MISC, 1); /* miscellaneous register */
1540 vga_wgfx (regbase, VGA_GFX_COMPARE_MASK, 15); /* color don't care */
1541 vga_wgfx (regbase, VGA_GFX_BIT_MASK, 255); /* bit mask */
1543 vga_wseq (regbase, CL_SEQR12, 0x0); /* graphics cursor attributes: nothing special */
1545 /* finally, turn on everything - turn off "FullBandwidth" bit */
1546 /* also, set "DotClock%2" bit where requested */
1547 tmp = 0x01;
1549 /*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
1550 if (var->vmode & FB_VMODE_CLOCK_HALVE)
1551 tmp |= 0x08;
1554 vga_wseq (regbase, VGA_SEQ_CLOCK_MODE, tmp);
1555 DPRINTK ("CL_SEQR1: %d\n", tmp);
1557 cinfo->currentmode = regs;
1558 info->fix.type = regs.type;
1559 info->fix.visual = regs.visual;
1560 info->fix.line_length = regs.line_length;
1562 /* pan to requested offset */
1563 cirrusfb_pan_display (var, info);
1565 #ifdef CIRRUSFB_DEBUG
1566 cirrusfb_dump ();
1567 #endif
1569 DPRINTK ("EXIT\n");
1570 return 0;
1573 /* for some reason incomprehensible to me, cirrusfb requires that you write
1574 * the registers twice for the settings to take..grr. -dte */
1575 static int cirrusfb_set_par (struct fb_info *info)
1577 cirrusfb_set_par_foo (info);
1578 return cirrusfb_set_par_foo (info);
1581 static int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
1582 unsigned blue, unsigned transp,
1583 struct fb_info *info)
1585 struct cirrusfb_info *cinfo = info->par;
1587 if (regno > 255)
1588 return -EINVAL;
1590 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
1591 u32 v;
1592 red >>= (16 - info->var.red.length);
1593 green >>= (16 - info->var.green.length);
1594 blue >>= (16 - info->var.blue.length);
1596 if (regno>=16)
1597 return 1;
1598 v = (red << info->var.red.offset) |
1599 (green << info->var.green.offset) |
1600 (blue << info->var.blue.offset);
1602 switch (info->var.bits_per_pixel) {
1603 case 8:
1604 cinfo->pseudo_palette[regno] = v;
1605 break;
1606 case 16:
1607 cinfo->pseudo_palette[regno] = v;
1608 break;
1609 case 24:
1610 case 32:
1611 cinfo->pseudo_palette[regno] = v;
1612 break;
1614 return 0;
1617 cinfo->palette[regno].red = red;
1618 cinfo->palette[regno].green = green;
1619 cinfo->palette[regno].blue = blue;
1621 if (info->var.bits_per_pixel == 8) {
1622 WClut (cinfo, regno, red >> 10, green >> 10, blue >> 10);
1625 return 0;
1629 /*************************************************************************
1630 cirrusfb_pan_display()
1632 performs display panning - provided hardware permits this
1633 **************************************************************************/
1634 static int cirrusfb_pan_display (struct fb_var_screeninfo *var,
1635 struct fb_info *info)
1637 int xoffset = 0;
1638 int yoffset = 0;
1639 unsigned long base;
1640 unsigned char tmp = 0, tmp2 = 0, xpix;
1641 struct cirrusfb_info *cinfo = info->par;
1643 DPRINTK ("ENTER\n");
1644 DPRINTK ("virtual offset: (%d,%d)\n", var->xoffset, var->yoffset);
1646 /* no range checks for xoffset and yoffset, */
1647 /* as fb_pan_display has already done this */
1648 if (var->vmode & FB_VMODE_YWRAP)
1649 return -EINVAL;
1651 info->var.xoffset = var->xoffset;
1652 info->var.yoffset = var->yoffset;
1654 xoffset = var->xoffset * info->var.bits_per_pixel / 8;
1655 yoffset = var->yoffset;
1657 base = yoffset * cinfo->currentmode.line_length + xoffset;
1659 if (info->var.bits_per_pixel == 1) {
1660 /* base is already correct */
1661 xpix = (unsigned char) (var->xoffset % 8);
1662 } else {
1663 base /= 4;
1664 xpix = (unsigned char) ((xoffset % 4) * 2);
1667 cirrusfb_WaitBLT(cinfo->regbase); /* make sure all the BLT's are done */
1669 /* lower 8 + 8 bits of screen start address */
1670 vga_wcrt (cinfo->regbase, VGA_CRTC_START_LO, (unsigned char) (base & 0xff));
1671 vga_wcrt (cinfo->regbase, VGA_CRTC_START_HI, (unsigned char) (base >> 8));
1673 /* construct bits 16, 17 and 18 of screen start address */
1674 if (base & 0x10000)
1675 tmp |= 0x01;
1676 if (base & 0x20000)
1677 tmp |= 0x04;
1678 if (base & 0x40000)
1679 tmp |= 0x08;
1681 tmp2 = (vga_rcrt (cinfo->regbase, CL_CRT1B) & 0xf2) | tmp; /* 0xf2 is %11110010, exclude tmp bits */
1682 vga_wcrt (cinfo->regbase, CL_CRT1B, tmp2);
1684 /* construct bit 19 of screen start address */
1685 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) {
1686 tmp2 = 0;
1687 if (base & 0x80000)
1688 tmp2 = 0x80;
1689 vga_wcrt (cinfo->regbase, CL_CRT1D, tmp2);
1692 /* write pixel panning value to AR33; this does not quite work in 8bpp */
1693 /* ### Piccolo..? Will this work? */
1694 if (info->var.bits_per_pixel == 1)
1695 vga_wattr (cinfo->regbase, CL_AR33, xpix);
1697 cirrusfb_WaitBLT (cinfo->regbase);
1699 DPRINTK ("EXIT\n");
1700 return (0);
1704 static int cirrusfb_blank (int blank_mode, struct fb_info *info)
1707 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
1708 * then the caller blanks by setting the CLUT (Color Look Up Table) to all
1709 * black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
1710 * to e.g. a video mode which doesn't support it. Implements VESA suspend
1711 * and powerdown modes on hardware that supports disabling hsync/vsync:
1712 * blank_mode == 2: suspend vsync
1713 * blank_mode == 3: suspend hsync
1714 * blank_mode == 4: powerdown
1716 unsigned char val;
1717 struct cirrusfb_info *cinfo = info->par;
1718 int current_mode = cinfo->blank_mode;
1720 DPRINTK ("ENTER, blank mode = %d\n", blank_mode);
1722 if (info->state != FBINFO_STATE_RUNNING ||
1723 current_mode == blank_mode) {
1724 DPRINTK ("EXIT, returning 0\n");
1725 return 0;
1728 /* Undo current */
1729 if (current_mode == FB_BLANK_NORMAL ||
1730 current_mode == FB_BLANK_UNBLANK) {
1731 /* unblank the screen */
1732 val = vga_rseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1733 vga_wseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE, val & 0xdf); /* clear "FullBandwidth" bit */
1734 /* and undo VESA suspend trickery */
1735 vga_wgfx (cinfo->regbase, CL_GRE, 0x00);
1738 /* set new */
1739 if(blank_mode > FB_BLANK_NORMAL) {
1740 /* blank the screen */
1741 val = vga_rseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1742 vga_wseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE, val | 0x20); /* set "FullBandwidth" bit */
1745 switch (blank_mode) {
1746 case FB_BLANK_UNBLANK:
1747 case FB_BLANK_NORMAL:
1748 break;
1749 case FB_BLANK_VSYNC_SUSPEND:
1750 vga_wgfx (cinfo->regbase, CL_GRE, 0x04);
1751 break;
1752 case FB_BLANK_HSYNC_SUSPEND:
1753 vga_wgfx (cinfo->regbase, CL_GRE, 0x02);
1754 break;
1755 case FB_BLANK_POWERDOWN:
1756 vga_wgfx (cinfo->regbase, CL_GRE, 0x06);
1757 break;
1758 default:
1759 DPRINTK ("EXIT, returning 1\n");
1760 return 1;
1763 cinfo->blank_mode = blank_mode;
1764 DPRINTK ("EXIT, returning 0\n");
1766 /* Let fbcon do a soft blank for us */
1767 return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
1769 /**** END Hardware specific Routines **************************************/
1770 /****************************************************************************/
1771 /**** BEGIN Internal Routines ***********************************************/
1773 static void init_vgachip (struct cirrusfb_info *cinfo)
1775 const struct cirrusfb_board_info_rec *bi;
1777 DPRINTK ("ENTER\n");
1779 assert (cinfo != NULL);
1781 bi = &cirrusfb_board_info[cinfo->btype];
1783 /* reset board globally */
1784 switch (cinfo->btype) {
1785 case BT_PICCOLO:
1786 WSFR (cinfo, 0x01);
1787 udelay (500);
1788 WSFR (cinfo, 0x51);
1789 udelay (500);
1790 break;
1791 case BT_PICASSO:
1792 WSFR2 (cinfo, 0xff);
1793 udelay (500);
1794 break;
1795 case BT_SD64:
1796 case BT_SPECTRUM:
1797 WSFR (cinfo, 0x1f);
1798 udelay (500);
1799 WSFR (cinfo, 0x4f);
1800 udelay (500);
1801 break;
1802 case BT_PICASSO4:
1803 vga_wcrt (cinfo->regbase, CL_CRT51, 0x00); /* disable flickerfixer */
1804 mdelay (100);
1805 vga_wgfx (cinfo->regbase, CL_GR2F, 0x00); /* from Klaus' NetBSD driver: */
1806 vga_wgfx (cinfo->regbase, CL_GR33, 0x00); /* put blitter into 542x compat */
1807 vga_wgfx (cinfo->regbase, CL_GR31, 0x00); /* mode */
1808 break;
1810 case BT_GD5480:
1811 vga_wgfx (cinfo->regbase, CL_GR2F, 0x00); /* from Klaus' NetBSD driver: */
1812 break;
1814 case BT_ALPINE:
1815 /* Nothing to do to reset the board. */
1816 break;
1818 default:
1819 printk (KERN_ERR "cirrusfb: Warning: Unknown board type\n");
1820 break;
1823 assert (cinfo->size > 0); /* make sure RAM size set by this point */
1825 /* the P4 is not fully initialized here; I rely on it having been */
1826 /* inited under AmigaOS already, which seems to work just fine */
1827 /* (Klaus advised to do it this way) */
1829 if (cinfo->btype != BT_PICASSO4) {
1830 WGen (cinfo, CL_VSSM, 0x10); /* EGS: 0x16 */
1831 WGen (cinfo, CL_POS102, 0x01);
1832 WGen (cinfo, CL_VSSM, 0x08); /* EGS: 0x0e */
1834 if (cinfo->btype != BT_SD64)
1835 WGen (cinfo, CL_VSSM2, 0x01);
1837 vga_wseq (cinfo->regbase, CL_SEQR0, 0x03); /* reset sequencer logic */
1839 vga_wseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21); /* FullBandwidth (video off) and 8/9 dot clock */
1840 WGen (cinfo, VGA_MIS_W, 0xc1); /* polarity (-/-), disable access to display memory, VGA_CRTC_START_HI base address: color */
1842 /* vga_wgfx (cinfo->regbase, CL_GRA, 0xce); "magic cookie" - doesn't make any sense to me.. */
1843 vga_wseq (cinfo->regbase, CL_SEQR6, 0x12); /* unlock all extension registers */
1845 vga_wgfx (cinfo->regbase, CL_GR31, 0x04); /* reset blitter */
1847 switch (cinfo->btype) {
1848 case BT_GD5480:
1849 vga_wseq (cinfo->regbase, CL_SEQRF, 0x98);
1850 break;
1851 case BT_ALPINE:
1852 break;
1853 case BT_SD64:
1854 vga_wseq (cinfo->regbase, CL_SEQRF, 0xb8);
1855 break;
1856 default:
1857 vga_wseq (cinfo->regbase, CL_SEQR16, 0x0f);
1858 vga_wseq (cinfo->regbase, CL_SEQRF, 0xb0);
1859 break;
1862 vga_wseq (cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: nothing */
1863 vga_wseq (cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00); /* character map select: doesn't even matter in gx mode */
1864 vga_wseq (cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0e); /* memory mode: chain-4, no odd/even, ext. memory */
1866 /* controller-internal base address of video memory */
1867 if (bi->init_sr07)
1868 vga_wseq (cinfo->regbase, CL_SEQR7, bi->sr07);
1870 /* vga_wseq (cinfo->regbase, CL_SEQR8, 0x00); *//* EEPROM control: shouldn't be necessary to write to this at all.. */
1872 vga_wseq (cinfo->regbase, CL_SEQR10, 0x00); /* graphics cursor X position (incomplete; position gives rem. 3 bits */
1873 vga_wseq (cinfo->regbase, CL_SEQR11, 0x00); /* graphics cursor Y position (..."... ) */
1874 vga_wseq (cinfo->regbase, CL_SEQR12, 0x00); /* graphics cursor attributes */
1875 vga_wseq (cinfo->regbase, CL_SEQR13, 0x00); /* graphics cursor pattern address */
1877 /* writing these on a P4 might give problems.. */
1878 if (cinfo->btype != BT_PICASSO4) {
1879 vga_wseq (cinfo->regbase, CL_SEQR17, 0x00); /* configuration readback and ext. color */
1880 vga_wseq (cinfo->regbase, CL_SEQR18, 0x02); /* signature generator */
1883 /* MCLK select etc. */
1884 if (bi->init_sr1f)
1885 vga_wseq (cinfo->regbase, CL_SEQR1F, bi->sr1f);
1887 vga_wcrt (cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00); /* Screen A preset row scan: none */
1888 vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20); /* Text cursor start: disable text cursor */
1889 vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00); /* Text cursor end: - */
1890 vga_wcrt (cinfo->regbase, VGA_CRTC_START_HI, 0x00); /* Screen start address high: 0 */
1891 vga_wcrt (cinfo->regbase, VGA_CRTC_START_LO, 0x00); /* Screen start address low: 0 */
1892 vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00); /* text cursor location high: 0 */
1893 vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00); /* text cursor location low: 0 */
1895 vga_wcrt (cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00); /* Underline Row scanline: - */
1896 vga_wcrt (cinfo->regbase, VGA_CRTC_MODE, 0xc3); /* mode control: timing enable, byte mode, no compat modes */
1897 vga_wcrt (cinfo->regbase, VGA_CRTC_LINE_COMPARE, 0x00); /* Line Compare: not needed */
1898 /* ### add 0x40 for text modes with > 30 MHz pixclock */
1899 vga_wcrt (cinfo->regbase, CL_CRT1B, 0x02); /* ext. display controls: ext.adr. wrap */
1901 vga_wgfx (cinfo->regbase, VGA_GFX_SR_VALUE, 0x00); /* Set/Reset registes: - */
1902 vga_wgfx (cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00); /* Set/Reset enable: - */
1903 vga_wgfx (cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00); /* Color Compare: - */
1904 vga_wgfx (cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00); /* Data Rotate: - */
1905 vga_wgfx (cinfo->regbase, VGA_GFX_PLANE_READ, 0x00); /* Read Map Select: - */
1906 vga_wgfx (cinfo->regbase, VGA_GFX_MODE, 0x00); /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
1907 vga_wgfx (cinfo->regbase, VGA_GFX_MISC, 0x01); /* Miscellaneous: memory map base address, graphics mode */
1908 vga_wgfx (cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f); /* Color Don't care: involve all planes */
1909 vga_wgfx (cinfo->regbase, VGA_GFX_BIT_MASK, 0xff); /* Bit Mask: no mask at all */
1910 if (cinfo->btype == BT_ALPINE)
1911 vga_wgfx (cinfo->regbase, CL_GRB, 0x20); /* (5434 can't have bit 3 set for bitblt) */
1912 else
1913 vga_wgfx (cinfo->regbase, CL_GRB, 0x28); /* Graphics controller mode extensions: finer granularity, 8byte data latches */
1915 vga_wgfx (cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */
1916 vga_wgfx (cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */
1917 vga_wgfx (cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */
1918 /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); *//* Background color byte 1: - */
1919 /* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
1921 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE0, 0x00); /* Attribute Controller palette registers: "identity mapping" */
1922 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
1923 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
1924 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
1925 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
1926 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
1927 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
1928 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
1929 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
1930 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
1931 vga_wattr (cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
1932 vga_wattr (cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
1933 vga_wattr (cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
1934 vga_wattr (cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
1935 vga_wattr (cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
1936 vga_wattr (cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
1938 vga_wattr (cinfo->regbase, VGA_ATC_MODE, 0x01); /* Attribute Controller mode: graphics mode */
1939 vga_wattr (cinfo->regbase, VGA_ATC_OVERSCAN, 0x00); /* Overscan color reg.: reg. 0 */
1940 vga_wattr (cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f); /* Color Plane enable: Enable all 4 planes */
1941 /* ### vga_wattr (cinfo->regbase, CL_AR33, 0x00); * Pixel Panning: - */
1942 vga_wattr (cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00); /* Color Select: - */
1944 WGen (cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
1946 if (cinfo->btype != BT_ALPINE && cinfo->btype != BT_GD5480)
1947 WGen (cinfo, VGA_MIS_W, 0xc3); /* polarity (-/-), enable display mem, VGA_CRTC_START_HI i/o base = color */
1949 vga_wgfx (cinfo->regbase, CL_GR31, 0x04); /* BLT Start/status: Blitter reset */
1950 vga_wgfx (cinfo->regbase, CL_GR31, 0x00); /* - " - : "end-of-reset" */
1952 /* misc... */
1953 WHDR (cinfo, 0); /* Hidden DAC register: - */
1955 printk (KERN_DEBUG "cirrusfb: This board has %ld bytes of DRAM memory\n", cinfo->size);
1956 DPRINTK ("EXIT\n");
1957 return;
1960 static void switch_monitor (struct cirrusfb_info *cinfo, int on)
1962 #ifdef CONFIG_ZORRO /* only works on Zorro boards */
1963 static int IsOn = 0; /* XXX not ok for multiple boards */
1965 DPRINTK ("ENTER\n");
1967 if (cinfo->btype == BT_PICASSO4)
1968 return; /* nothing to switch */
1969 if (cinfo->btype == BT_ALPINE)
1970 return; /* nothing to switch */
1971 if (cinfo->btype == BT_GD5480)
1972 return; /* nothing to switch */
1973 if (cinfo->btype == BT_PICASSO) {
1974 if ((on && !IsOn) || (!on && IsOn))
1975 WSFR (cinfo, 0xff);
1977 DPRINTK ("EXIT\n");
1978 return;
1980 if (on) {
1981 switch (cinfo->btype) {
1982 case BT_SD64:
1983 WSFR (cinfo, cinfo->SFR | 0x21);
1984 break;
1985 case BT_PICCOLO:
1986 WSFR (cinfo, cinfo->SFR | 0x28);
1987 break;
1988 case BT_SPECTRUM:
1989 WSFR (cinfo, 0x6f);
1990 break;
1991 default: /* do nothing */ break;
1993 } else {
1994 switch (cinfo->btype) {
1995 case BT_SD64:
1996 WSFR (cinfo, cinfo->SFR & 0xde);
1997 break;
1998 case BT_PICCOLO:
1999 WSFR (cinfo, cinfo->SFR & 0xd7);
2000 break;
2001 case BT_SPECTRUM:
2002 WSFR (cinfo, 0x4f);
2003 break;
2004 default: /* do nothing */ break;
2008 DPRINTK ("EXIT\n");
2009 #endif /* CONFIG_ZORRO */
2013 /******************************************/
2014 /* Linux 2.6-style accelerated functions */
2015 /******************************************/
2017 static void cirrusfb_prim_fillrect(struct cirrusfb_info *cinfo,
2018 const struct fb_fillrect *region)
2020 int m; /* bytes per pixel */
2021 u32 color = (cinfo->info->fix.visual == FB_VISUAL_TRUECOLOR) ?
2022 cinfo->pseudo_palette[region->color] : region->color;
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 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 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);
2229 #endif /* CONFIG_PCI */
2232 #ifdef CONFIG_ZORRO
2233 static void __devexit cirrusfb_zorro_unmap (struct cirrusfb_info *cinfo)
2235 zorro_release_device(cinfo->zdev);
2237 if (cinfo->btype == BT_PICASSO4) {
2238 cinfo->regbase -= 0x600000;
2239 iounmap ((void *)cinfo->regbase);
2240 iounmap ((void *)cinfo->fbmem);
2241 } else {
2242 if (zorro_resource_start(cinfo->zdev) > 0x01000000)
2243 iounmap ((void *)cinfo->fbmem);
2245 framebuffer_release(cinfo->info);
2247 #endif /* CONFIG_ZORRO */
2249 static int cirrusfb_set_fbinfo(struct cirrusfb_info *cinfo)
2251 struct fb_info *info = cinfo->info;
2252 struct fb_var_screeninfo *var = &info->var;
2254 info->par = cinfo;
2255 info->pseudo_palette = cinfo->pseudo_palette;
2256 info->flags = FBINFO_DEFAULT
2257 | FBINFO_HWACCEL_XPAN
2258 | FBINFO_HWACCEL_YPAN
2259 | FBINFO_HWACCEL_FILLRECT
2260 | FBINFO_HWACCEL_COPYAREA;
2261 if (noaccel)
2262 info->flags |= FBINFO_HWACCEL_DISABLED;
2263 info->fbops = &cirrusfb_ops;
2264 info->screen_base = cinfo->fbmem;
2265 if (cinfo->btype == BT_GD5480) {
2266 if (var->bits_per_pixel == 16)
2267 info->screen_base += 1 * MB_;
2268 if (var->bits_per_pixel == 24 || var->bits_per_pixel == 32)
2269 info->screen_base += 2 * MB_;
2272 /* Fill fix common fields */
2273 strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
2274 sizeof(info->fix.id));
2276 /* monochrome: only 1 memory plane */
2277 /* 8 bit and above: Use whole memory area */
2278 info->fix.smem_start = cinfo->fbmem_phys;
2279 info->fix.smem_len = (var->bits_per_pixel == 1) ? cinfo->size / 4 : cinfo->size;
2280 info->fix.type = cinfo->currentmode.type;
2281 info->fix.type_aux = 0;
2282 info->fix.visual = cinfo->currentmode.visual;
2283 info->fix.xpanstep = 1;
2284 info->fix.ypanstep = 1;
2285 info->fix.ywrapstep = 0;
2286 info->fix.line_length = cinfo->currentmode.line_length;
2288 /* FIXME: map region at 0xB8000 if available, fill in here */
2289 info->fix.mmio_start = cinfo->fbregs_phys;
2290 info->fix.mmio_len = 0;
2291 info->fix.accel = FB_ACCEL_NONE;
2293 fb_alloc_cmap(&info->cmap, 256, 0);
2295 return 0;
2298 static int cirrusfb_register(struct cirrusfb_info *cinfo)
2300 struct fb_info *info;
2301 int err;
2302 cirrusfb_board_t btype;
2304 DPRINTK ("ENTER\n");
2306 printk (KERN_INFO "cirrusfb: Driver for Cirrus Logic based graphic boards, v" CIRRUSFB_VERSION "\n");
2308 info = cinfo->info;
2309 btype = cinfo->btype;
2311 /* sanity checks */
2312 assert (btype != BT_NONE);
2314 DPRINTK ("cirrusfb: (RAM start set to: 0x%p)\n", cinfo->fbmem);
2316 /* Make pretend we've set the var so our structures are in a "good" */
2317 /* state, even though we haven't written the mode to the hw yet... */
2318 info->var = cirrusfb_predefined[cirrusfb_def_mode].var;
2319 info->var.activate = FB_ACTIVATE_NOW;
2321 err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
2322 if (err < 0) {
2323 /* should never happen */
2324 DPRINTK("choking on default var... umm, no good.\n");
2325 goto err_unmap_cirrusfb;
2328 /* set all the vital stuff */
2329 cirrusfb_set_fbinfo(cinfo);
2331 err = register_framebuffer(info);
2332 if (err < 0) {
2333 printk (KERN_ERR "cirrusfb: could not register fb device; err = %d!\n", err);
2334 goto err_dealloc_cmap;
2337 DPRINTK ("EXIT, returning 0\n");
2338 return 0;
2340 err_dealloc_cmap:
2341 fb_dealloc_cmap(&info->cmap);
2342 err_unmap_cirrusfb:
2343 cinfo->unmap(cinfo);
2344 return err;
2347 static void __devexit cirrusfb_cleanup (struct fb_info *info)
2349 struct cirrusfb_info *cinfo = info->par;
2350 DPRINTK ("ENTER\n");
2352 switch_monitor (cinfo, 0);
2354 unregister_framebuffer (info);
2355 fb_dealloc_cmap (&info->cmap);
2356 printk ("Framebuffer unregistered\n");
2357 cinfo->unmap(cinfo);
2359 DPRINTK ("EXIT\n");
2363 #ifdef CONFIG_PCI
2364 static int cirrusfb_pci_register (struct pci_dev *pdev,
2365 const struct pci_device_id *ent)
2367 struct cirrusfb_info *cinfo;
2368 struct fb_info *info;
2369 cirrusfb_board_t btype;
2370 unsigned long board_addr, board_size;
2371 int ret;
2373 ret = pci_enable_device(pdev);
2374 if (ret < 0) {
2375 printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
2376 goto err_out;
2379 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev);
2380 if (!info) {
2381 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2382 ret = -ENOMEM;
2383 goto err_disable;
2386 cinfo = info->par;
2387 cinfo->info = info;
2388 cinfo->pdev = pdev;
2389 cinfo->btype = btype = (cirrusfb_board_t) ent->driver_data;
2391 DPRINTK (" Found PCI device, base address 0 is 0x%lx, btype set to %d\n",
2392 pdev->resource[0].start, btype);
2393 DPRINTK (" base address 1 is 0x%lx\n", pdev->resource[1].start);
2395 if(isPReP) {
2396 pci_write_config_dword (pdev, PCI_BASE_ADDRESS_0, 0x00000000);
2397 #ifdef CONFIG_PPC_PREP
2398 get_prep_addrs (&board_addr, &cinfo->fbregs_phys);
2399 #endif
2400 /* PReP dies if we ioremap the IO registers, but it works w/out... */
2401 cinfo->regbase = (char __iomem *) cinfo->fbregs_phys;
2402 } else {
2403 DPRINTK ("Attempt to get PCI info for Cirrus Graphics Card\n");
2404 get_pci_addrs (pdev, &board_addr, &cinfo->fbregs_phys);
2405 cinfo->regbase = NULL; /* FIXME: this forces VGA. alternatives? */
2408 DPRINTK ("Board address: 0x%lx, register address: 0x%lx\n", board_addr, cinfo->fbregs_phys);
2410 board_size = (btype == BT_GD5480) ?
2411 32 * MB_ : cirrusfb_get_memsize (cinfo->regbase);
2413 ret = pci_request_regions(pdev, "cirrusfb");
2414 if (ret <0) {
2415 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n",
2416 board_addr);
2417 goto err_release_fb;
2419 #if 0 /* if the system didn't claim this region, we would... */
2420 if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
2421 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n"
2423 0xA0000L);
2424 ret = -EBUSY;
2425 goto err_release_regions;
2427 #endif
2428 if (request_region(0x3C0, 32, "cirrusfb"))
2429 release_io_ports = 1;
2431 cinfo->fbmem = ioremap(board_addr, board_size);
2432 if (!cinfo->fbmem) {
2433 ret = -EIO;
2434 goto err_release_legacy;
2437 cinfo->fbmem_phys = board_addr;
2438 cinfo->size = board_size;
2439 cinfo->unmap = cirrusfb_pci_unmap;
2441 printk (" RAM (%lu kB) at 0xx%lx, ", cinfo->size / KB_, board_addr);
2442 printk ("Cirrus Logic chipset on PCI bus\n");
2443 pci_set_drvdata(pdev, info);
2445 return cirrusfb_register(cinfo);
2447 err_release_legacy:
2448 if (release_io_ports)
2449 release_region(0x3C0, 32);
2450 #if 0
2451 release_mem_region(0xA0000, 65535);
2452 err_release_regions:
2453 #endif
2454 pci_release_regions(pdev);
2455 err_release_fb:
2456 framebuffer_release(info);
2457 err_disable:
2458 err_out:
2459 return ret;
2462 static void __devexit cirrusfb_pci_unregister (struct pci_dev *pdev)
2464 struct fb_info *info = pci_get_drvdata(pdev);
2465 DPRINTK ("ENTER\n");
2467 cirrusfb_cleanup (info);
2469 DPRINTK ("EXIT\n");
2472 static struct pci_driver cirrusfb_pci_driver = {
2473 .name = "cirrusfb",
2474 .id_table = cirrusfb_pci_table,
2475 .probe = cirrusfb_pci_register,
2476 .remove = __devexit_p(cirrusfb_pci_unregister),
2477 #ifdef CONFIG_PM
2478 #if 0
2479 .suspend = cirrusfb_pci_suspend,
2480 .resume = cirrusfb_pci_resume,
2481 #endif
2482 #endif
2484 #endif /* CONFIG_PCI */
2487 #ifdef CONFIG_ZORRO
2488 static int cirrusfb_zorro_register(struct zorro_dev *z,
2489 const struct zorro_device_id *ent)
2491 struct cirrusfb_info *cinfo;
2492 struct fb_info *info;
2493 cirrusfb_board_t btype;
2494 struct zorro_dev *z2 = NULL;
2495 unsigned long board_addr, board_size, size;
2496 int ret;
2498 btype = ent->driver_data;
2499 if (cirrusfb_zorro_table2[btype].id2)
2500 z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
2501 size = cirrusfb_zorro_table2[btype].size;
2502 printk(KERN_INFO "cirrusfb: %s board detected; ",
2503 cirrusfb_board_info[btype].name);
2505 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
2506 if (!info) {
2507 printk (KERN_ERR "cirrusfb: could not allocate memory\n");
2508 ret = -ENOMEM;
2509 goto err_out;
2512 cinfo = info->par;
2513 cinfo->info = info;
2514 cinfo->btype = btype;
2516 assert (z > 0);
2517 assert (z2 >= 0);
2518 assert (btype != BT_NONE);
2520 cinfo->zdev = z;
2521 board_addr = zorro_resource_start(z);
2522 board_size = zorro_resource_len(z);
2523 cinfo->size = size;
2525 if (!zorro_request_device(z, "cirrusfb")) {
2526 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n",
2527 board_addr);
2528 ret = -EBUSY;
2529 goto err_release_fb;
2532 printk (" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr);
2534 ret = -EIO;
2536 if (btype == BT_PICASSO4) {
2537 printk (" REG at $%lx\n", board_addr + 0x600000);
2539 /* To be precise, for the P4 this is not the */
2540 /* begin of the board, but the begin of RAM. */
2541 /* for P4, map in its address space in 2 chunks (### TEST! ) */
2542 /* (note the ugly hardcoded 16M number) */
2543 cinfo->regbase = ioremap (board_addr, 16777216);
2544 if (!cinfo->regbase)
2545 goto err_release_region;
2547 DPRINTK ("cirrusfb: Virtual address for board set to: $%p\n", cinfo->regbase);
2548 cinfo->regbase += 0x600000;
2549 cinfo->fbregs_phys = board_addr + 0x600000;
2551 cinfo->fbmem_phys = board_addr + 16777216;
2552 cinfo->fbmem = ioremap (cinfo->fbmem_phys, 16777216);
2553 if (!cinfo->fbmem)
2554 goto err_unmap_regbase;
2555 } else {
2556 printk (" REG at $%lx\n", (unsigned long) z2->resource.start);
2558 cinfo->fbmem_phys = board_addr;
2559 if (board_addr > 0x01000000)
2560 cinfo->fbmem = ioremap (board_addr, board_size);
2561 else
2562 cinfo->fbmem = (caddr_t) ZTWO_VADDR (board_addr);
2563 if (!cinfo->fbmem)
2564 goto err_release_region;
2566 /* set address for REG area of board */
2567 cinfo->regbase = (caddr_t) ZTWO_VADDR (z2->resource.start);
2568 cinfo->fbregs_phys = z2->resource.start;
2570 DPRINTK ("cirrusfb: Virtual address for board set to: $%p\n", cinfo->regbase);
2572 cinfo->unmap = cirrusfb_zorro_unmap;
2574 printk (KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
2575 zorro_set_drvdata(z, info);
2577 return cirrusfb_register(cinfo);
2579 err_unmap_regbase:
2580 /* Parental advisory: explicit hack */
2581 iounmap(cinfo->regbase - 0x600000);
2582 err_release_region:
2583 release_region(board_addr, board_size);
2584 err_release_fb:
2585 framebuffer_release(info);
2586 err_out:
2587 return ret;
2590 void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
2592 struct fb_info *info = zorro_get_drvdata(z);
2593 DPRINTK ("ENTER\n");
2595 cirrusfb_cleanup (info);
2597 DPRINTK ("EXIT\n");
2600 static struct zorro_driver cirrusfb_zorro_driver = {
2601 .name = "cirrusfb",
2602 .id_table = cirrusfb_zorro_table,
2603 .probe = cirrusfb_zorro_register,
2604 .remove = __devexit_p(cirrusfb_zorro_unregister),
2606 #endif /* CONFIG_ZORRO */
2608 static int __init cirrusfb_init(void)
2610 int error = 0;
2612 #ifndef MODULE
2613 char *option = NULL;
2615 if (fb_get_options("cirrusfb", &option))
2616 return -ENODEV;
2617 cirrusfb_setup(option);
2618 #endif
2620 #ifdef CONFIG_ZORRO
2621 error |= zorro_register_driver(&cirrusfb_zorro_driver);
2622 #endif
2623 #ifdef CONFIG_PCI
2624 error |= pci_register_driver(&cirrusfb_pci_driver);
2625 #endif
2626 return error;
2631 #ifndef MODULE
2632 static int __init cirrusfb_setup(char *options) {
2633 char *this_opt, s[32];
2634 int i;
2636 DPRINTK ("ENTER\n");
2638 if (!options || !*options)
2639 return 0;
2641 while ((this_opt = strsep (&options, ",")) != NULL) {
2642 if (!*this_opt) continue;
2644 DPRINTK("cirrusfb_setup: option '%s'\n", this_opt);
2646 for (i = 0; i < NUM_TOTAL_MODES; i++) {
2647 sprintf (s, "mode:%s", cirrusfb_predefined[i].name);
2648 if (strcmp (this_opt, s) == 0)
2649 cirrusfb_def_mode = i;
2651 if (!strcmp(this_opt, "noaccel"))
2652 noaccel = 1;
2654 return 0;
2656 #endif
2660 * Modularization
2663 MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
2664 MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
2665 MODULE_LICENSE("GPL");
2667 static void __exit cirrusfb_exit (void)
2669 #ifdef CONFIG_PCI
2670 pci_unregister_driver(&cirrusfb_pci_driver);
2671 #endif
2672 #ifdef CONFIG_ZORRO
2673 zorro_unregister_driver(&cirrusfb_zorro_driver);
2674 #endif
2677 module_init(cirrusfb_init);
2679 #ifdef MODULE
2680 module_exit(cirrusfb_exit);
2681 #endif
2684 /**********************************************************************/
2685 /* about the following functions - I have used the same names for the */
2686 /* functions as Markus Wild did in his Retina driver for NetBSD as */
2687 /* they just made sense for this purpose. Apart from that, I wrote */
2688 /* these functions myself. */
2689 /**********************************************************************/
2691 /*** WGen() - write into one of the external/general registers ***/
2692 static void WGen (const struct cirrusfb_info *cinfo,
2693 int regnum, unsigned char val)
2695 unsigned long regofs = 0;
2697 if (cinfo->btype == BT_PICASSO) {
2698 /* Picasso II specific hack */
2699 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */
2700 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2701 regofs = 0xfff;
2704 vga_w (cinfo->regbase, regofs + regnum, val);
2707 /*** RGen() - read out one of the external/general registers ***/
2708 static unsigned char RGen (const struct cirrusfb_info *cinfo, int regnum)
2710 unsigned long regofs = 0;
2712 if (cinfo->btype == BT_PICASSO) {
2713 /* Picasso II specific hack */
2714 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */
2715 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2716 regofs = 0xfff;
2719 return vga_r (cinfo->regbase, regofs + regnum);
2722 /*** AttrOn() - turn on VideoEnable for Attribute controller ***/
2723 static void AttrOn (const struct cirrusfb_info *cinfo)
2725 assert (cinfo != NULL);
2727 DPRINTK ("ENTER\n");
2729 if (vga_rcrt (cinfo->regbase, CL_CRT24) & 0x80) {
2730 /* if we're just in "write value" mode, write back the */
2731 /* same value as before to not modify anything */
2732 vga_w (cinfo->regbase, VGA_ATT_IW,
2733 vga_r (cinfo->regbase, VGA_ATT_R));
2735 /* turn on video bit */
2736 /* vga_w (cinfo->regbase, VGA_ATT_IW, 0x20); */
2737 vga_w (cinfo->regbase, VGA_ATT_IW, 0x33);
2739 /* dummy write on Reg0 to be on "write index" mode next time */
2740 vga_w (cinfo->regbase, VGA_ATT_IW, 0x00);
2742 DPRINTK ("EXIT\n");
2745 /*** WHDR() - write into the Hidden DAC register ***/
2746 /* as the HDR is the only extension register that requires special treatment
2747 * (the other extension registers are accessible just like the "ordinary"
2748 * registers of their functional group) here is a specialized routine for
2749 * accessing the HDR
2751 static void WHDR (const struct cirrusfb_info *cinfo, unsigned char val)
2753 unsigned char dummy;
2755 if (cinfo->btype == BT_PICASSO) {
2756 /* Klaus' hint for correct access to HDR on some boards */
2757 /* first write 0 to pixel mask (3c6) */
2758 WGen (cinfo, VGA_PEL_MSK, 0x00);
2759 udelay (200);
2760 /* next read dummy from pixel address (3c8) */
2761 dummy = RGen (cinfo, VGA_PEL_IW);
2762 udelay (200);
2764 /* now do the usual stuff to access the HDR */
2766 dummy = RGen (cinfo, VGA_PEL_MSK);
2767 udelay (200);
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);
2775 WGen (cinfo, VGA_PEL_MSK, val);
2776 udelay (200);
2778 if (cinfo->btype == BT_PICASSO) {
2779 /* now first reset HDR access counter */
2780 dummy = RGen (cinfo, VGA_PEL_IW);
2781 udelay (200);
2783 /* and at the end, restore the mask value */
2784 /* ## is this mask always 0xff? */
2785 WGen (cinfo, VGA_PEL_MSK, 0xff);
2786 udelay (200);
2791 /*** WSFR() - write to the "special function register" (SFR) ***/
2792 static void WSFR (struct cirrusfb_info *cinfo, unsigned char val)
2794 #ifdef CONFIG_ZORRO
2795 assert (cinfo->regbase != NULL);
2796 cinfo->SFR = val;
2797 z_writeb (val, cinfo->regbase + 0x8000);
2798 #endif
2801 /* The Picasso has a second register for switching the monitor bit */
2802 static void WSFR2 (struct cirrusfb_info *cinfo, unsigned char val)
2804 #ifdef CONFIG_ZORRO
2805 /* writing an arbitrary value to this one causes the monitor switcher */
2806 /* to flip to Amiga display */
2807 assert (cinfo->regbase != NULL);
2808 cinfo->SFR = val;
2809 z_writeb (val, cinfo->regbase + 0x9000);
2810 #endif
2814 /*** WClut - set CLUT entry (range: 0..63) ***/
2815 static void WClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
2816 unsigned char green, unsigned char blue)
2818 unsigned int data = VGA_PEL_D;
2820 /* address write mode register is not translated.. */
2821 vga_w (cinfo->regbase, VGA_PEL_IW, regnum);
2823 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2824 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2825 /* but DAC data register IS, at least for Picasso II */
2826 if (cinfo->btype == BT_PICASSO)
2827 data += 0xfff;
2828 vga_w (cinfo->regbase, data, red);
2829 vga_w (cinfo->regbase, data, green);
2830 vga_w (cinfo->regbase, data, blue);
2831 } else {
2832 vga_w (cinfo->regbase, data, blue);
2833 vga_w (cinfo->regbase, data, green);
2834 vga_w (cinfo->regbase, data, red);
2839 #if 0
2840 /*** RClut - read CLUT entry (range 0..63) ***/
2841 static void RClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
2842 unsigned char *green, unsigned char *blue)
2844 unsigned int data = VGA_PEL_D;
2846 vga_w (cinfo->regbase, VGA_PEL_IR, regnum);
2848 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2849 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2850 if (cinfo->btype == BT_PICASSO)
2851 data += 0xfff;
2852 *red = vga_r (cinfo->regbase, data);
2853 *green = vga_r (cinfo->regbase, data);
2854 *blue = vga_r (cinfo->regbase, data);
2855 } else {
2856 *blue = vga_r (cinfo->regbase, data);
2857 *green = vga_r (cinfo->regbase, data);
2858 *red = vga_r (cinfo->regbase, data);
2861 #endif
2864 /*******************************************************************
2865 cirrusfb_WaitBLT()
2867 Wait for the BitBLT engine to complete a possible earlier job
2868 *********************************************************************/
2870 /* FIXME: use interrupts instead */
2871 static void cirrusfb_WaitBLT (u8 __iomem *regbase)
2873 /* now busy-wait until we're done */
2874 while (vga_rgfx (regbase, CL_GR31) & 0x08)
2875 /* do nothing */ ;
2878 /*******************************************************************
2879 cirrusfb_BitBLT()
2881 perform accelerated "scrolling"
2882 ********************************************************************/
2884 static void cirrusfb_BitBLT (u8 __iomem *regbase, int bits_per_pixel,
2885 u_short curx, u_short cury, u_short destx, u_short desty,
2886 u_short width, u_short height, u_short line_length)
2888 u_short nwidth, nheight;
2889 u_long nsrc, ndest;
2890 u_char bltmode;
2892 DPRINTK ("ENTER\n");
2894 nwidth = width - 1;
2895 nheight = height - 1;
2897 bltmode = 0x00;
2898 /* if source adr < dest addr, do the Blt backwards */
2899 if (cury <= desty) {
2900 if (cury == desty) {
2901 /* if src and dest are on the same line, check x */
2902 if (curx < destx)
2903 bltmode |= 0x01;
2904 } else
2905 bltmode |= 0x01;
2907 if (!bltmode) {
2908 /* standard case: forward blitting */
2909 nsrc = (cury * line_length) + curx;
2910 ndest = (desty * line_length) + destx;
2911 } else {
2912 /* this means start addresses are at the end, counting backwards */
2913 nsrc = cury * line_length + curx + nheight * line_length + nwidth;
2914 ndest = desty * line_length + destx + nheight * line_length + nwidth;
2918 run-down of registers to be programmed:
2919 destination pitch
2920 source pitch
2921 BLT width/height
2922 source start
2923 destination start
2924 BLT mode
2925 BLT ROP
2926 VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color"
2927 start/stop
2930 cirrusfb_WaitBLT(regbase);
2932 /* pitch: set to line_length */
2933 vga_wgfx (regbase, CL_GR24, line_length & 0xff); /* dest pitch low */
2934 vga_wgfx (regbase, CL_GR25, (line_length >> 8)); /* dest pitch hi */
2935 vga_wgfx (regbase, CL_GR26, line_length & 0xff); /* source pitch low */
2936 vga_wgfx (regbase, CL_GR27, (line_length >> 8)); /* source pitch hi */
2938 /* BLT width: actual number of pixels - 1 */
2939 vga_wgfx (regbase, CL_GR20, nwidth & 0xff); /* BLT width low */
2940 vga_wgfx (regbase, CL_GR21, (nwidth >> 8)); /* BLT width hi */
2942 /* BLT height: actual number of lines -1 */
2943 vga_wgfx (regbase, CL_GR22, nheight & 0xff); /* BLT height low */
2944 vga_wgfx (regbase, CL_GR23, (nheight >> 8)); /* BLT width hi */
2946 /* BLT destination */
2947 vga_wgfx (regbase, CL_GR28, (u_char) (ndest & 0xff)); /* BLT dest low */
2948 vga_wgfx (regbase, CL_GR29, (u_char) (ndest >> 8)); /* BLT dest mid */
2949 vga_wgfx (regbase, CL_GR2A, (u_char) (ndest >> 16)); /* BLT dest hi */
2951 /* BLT source */
2952 vga_wgfx (regbase, CL_GR2C, (u_char) (nsrc & 0xff)); /* BLT src low */
2953 vga_wgfx (regbase, CL_GR2D, (u_char) (nsrc >> 8)); /* BLT src mid */
2954 vga_wgfx (regbase, CL_GR2E, (u_char) (nsrc >> 16)); /* BLT src hi */
2956 /* BLT mode */
2957 vga_wgfx (regbase, CL_GR30, bltmode); /* BLT mode */
2959 /* BLT ROP: SrcCopy */
2960 vga_wgfx (regbase, CL_GR32, 0x0d); /* BLT ROP */
2962 /* and finally: GO! */
2963 vga_wgfx (regbase, CL_GR31, 0x02); /* BLT Start/status */
2965 DPRINTK ("EXIT\n");
2969 /*******************************************************************
2970 cirrusfb_RectFill()
2972 perform accelerated rectangle fill
2973 ********************************************************************/
2975 static void cirrusfb_RectFill (u8 __iomem *regbase, int bits_per_pixel,
2976 u_short x, u_short y, u_short width, u_short height,
2977 u_char color, u_short line_length)
2979 u_short nwidth, nheight;
2980 u_long ndest;
2981 u_char op;
2983 DPRINTK ("ENTER\n");
2985 nwidth = width - 1;
2986 nheight = height - 1;
2988 ndest = (y * line_length) + x;
2990 cirrusfb_WaitBLT(regbase);
2992 /* pitch: set to line_length */
2993 vga_wgfx (regbase, CL_GR24, line_length & 0xff); /* dest pitch low */
2994 vga_wgfx (regbase, CL_GR25, (line_length >> 8)); /* dest pitch hi */
2995 vga_wgfx (regbase, CL_GR26, line_length & 0xff); /* source pitch low */
2996 vga_wgfx (regbase, CL_GR27, (line_length >> 8)); /* source pitch hi */
2998 /* BLT width: actual number of pixels - 1 */
2999 vga_wgfx (regbase, CL_GR20, nwidth & 0xff); /* BLT width low */
3000 vga_wgfx (regbase, CL_GR21, (nwidth >> 8)); /* BLT width hi */
3002 /* BLT height: actual number of lines -1 */
3003 vga_wgfx (regbase, CL_GR22, nheight & 0xff); /* BLT height low */
3004 vga_wgfx (regbase, CL_GR23, (nheight >> 8)); /* BLT width hi */
3006 /* BLT destination */
3007 vga_wgfx (regbase, CL_GR28, (u_char) (ndest & 0xff)); /* BLT dest low */
3008 vga_wgfx (regbase, CL_GR29, (u_char) (ndest >> 8)); /* BLT dest mid */
3009 vga_wgfx (regbase, CL_GR2A, (u_char) (ndest >> 16)); /* BLT dest hi */
3011 /* BLT source: set to 0 (is a dummy here anyway) */
3012 vga_wgfx (regbase, CL_GR2C, 0x00); /* BLT src low */
3013 vga_wgfx (regbase, CL_GR2D, 0x00); /* BLT src mid */
3014 vga_wgfx (regbase, CL_GR2E, 0x00); /* BLT src hi */
3016 /* This is a ColorExpand Blt, using the */
3017 /* same color for foreground and background */
3018 vga_wgfx (regbase, VGA_GFX_SR_VALUE, color); /* foreground color */
3019 vga_wgfx (regbase, VGA_GFX_SR_ENABLE, color); /* background color */
3021 op = 0xc0;
3022 if (bits_per_pixel == 16) {
3023 vga_wgfx (regbase, CL_GR10, color); /* foreground color */
3024 vga_wgfx (regbase, CL_GR11, color); /* background color */
3025 op = 0x50;
3026 op = 0xd0;
3027 } else if (bits_per_pixel == 32) {
3028 vga_wgfx (regbase, CL_GR10, color); /* foreground color */
3029 vga_wgfx (regbase, CL_GR11, color); /* background color */
3030 vga_wgfx (regbase, CL_GR12, color); /* foreground color */
3031 vga_wgfx (regbase, CL_GR13, color); /* background color */
3032 vga_wgfx (regbase, CL_GR14, 0); /* foreground color */
3033 vga_wgfx (regbase, CL_GR15, 0); /* background color */
3034 op = 0x50;
3035 op = 0xf0;
3037 /* BLT mode: color expand, Enable 8x8 copy (faster?) */
3038 vga_wgfx (regbase, CL_GR30, op); /* BLT mode */
3040 /* BLT ROP: SrcCopy */
3041 vga_wgfx (regbase, CL_GR32, 0x0d); /* BLT ROP */
3043 /* and finally: GO! */
3044 vga_wgfx (regbase, CL_GR31, 0x02); /* BLT Start/status */
3046 DPRINTK ("EXIT\n");
3050 /**************************************************************************
3051 * bestclock() - determine closest possible clock lower(?) than the
3052 * desired pixel clock
3053 **************************************************************************/
3054 static void bestclock (long freq, long *best, long *nom,
3055 long *den, long *div, long maxfreq)
3057 long n, h, d, f;
3059 assert (best != NULL);
3060 assert (nom != NULL);
3061 assert (den != NULL);
3062 assert (div != NULL);
3063 assert (maxfreq > 0);
3065 *nom = 0;
3066 *den = 0;
3067 *div = 0;
3069 DPRINTK ("ENTER\n");
3071 if (freq < 8000)
3072 freq = 8000;
3074 if (freq > maxfreq)
3075 freq = maxfreq;
3077 *best = 0;
3078 f = freq * 10;
3080 for (n = 32; n < 128; n++) {
3081 d = (143181 * n) / f;
3082 if ((d >= 7) && (d <= 63)) {
3083 if (d > 31)
3084 d = (d / 2) * 2;
3085 h = (14318 * n) / d;
3086 if (abs (h - freq) < abs (*best - freq)) {
3087 *best = h;
3088 *nom = n;
3089 if (d < 32) {
3090 *den = d;
3091 *div = 0;
3092 } else {
3093 *den = d / 2;
3094 *div = 1;
3098 d = ((143181 * n) + f - 1) / f;
3099 if ((d >= 7) && (d <= 63)) {
3100 if (d > 31)
3101 d = (d / 2) * 2;
3102 h = (14318 * n) / d;
3103 if (abs (h - freq) < abs (*best - freq)) {
3104 *best = h;
3105 *nom = n;
3106 if (d < 32) {
3107 *den = d;
3108 *div = 0;
3109 } else {
3110 *den = d / 2;
3111 *div = 1;
3117 DPRINTK ("Best possible values for given frequency:\n");
3118 DPRINTK (" best: %ld kHz nom: %ld den: %ld div: %ld\n",
3119 freq, *nom, *den, *div);
3121 DPRINTK ("EXIT\n");
3125 /* -------------------------------------------------------------------------
3127 * debugging functions
3129 * -------------------------------------------------------------------------
3132 #ifdef CIRRUSFB_DEBUG
3135 * cirrusfb_dbg_print_byte
3136 * @name: name associated with byte value to be displayed
3137 * @val: byte value to be displayed
3139 * DESCRIPTION:
3140 * Display an indented string, along with a hexidecimal byte value, and
3141 * its decoded bits. Bits 7 through 0 are listed in left-to-right
3142 * order.
3145 static
3146 void cirrusfb_dbg_print_byte (const char *name, unsigned char val)
3148 DPRINTK ("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n",
3149 name, val,
3150 val & 0x80 ? '1' : '0',
3151 val & 0x40 ? '1' : '0',
3152 val & 0x20 ? '1' : '0',
3153 val & 0x10 ? '1' : '0',
3154 val & 0x08 ? '1' : '0',
3155 val & 0x04 ? '1' : '0',
3156 val & 0x02 ? '1' : '0',
3157 val & 0x01 ? '1' : '0');
3162 * cirrusfb_dbg_print_regs
3163 * @base: If using newmmio, the newmmio base address, otherwise %NULL
3164 * @reg_class: type of registers to read: %CRT, or %SEQ
3166 * DESCRIPTION:
3167 * Dumps the given list of VGA CRTC registers. If @base is %NULL,
3168 * old-style I/O ports are queried for information, otherwise MMIO is
3169 * used at the given @base address to query the information.
3172 static
3173 void cirrusfb_dbg_print_regs (caddr_t regbase, cirrusfb_dbg_reg_class_t reg_class,...)
3175 va_list list;
3176 unsigned char val = 0;
3177 unsigned reg;
3178 char *name;
3180 va_start (list, reg_class);
3182 name = va_arg (list, char *);
3183 while (name != NULL) {
3184 reg = va_arg (list, int);
3186 switch (reg_class) {
3187 case CRT:
3188 val = vga_rcrt (regbase, (unsigned char) reg);
3189 break;
3190 case SEQ:
3191 val = vga_rseq (regbase, (unsigned char) reg);
3192 break;
3193 default:
3194 /* should never occur */
3195 assert (FALSE);
3196 break;
3199 cirrusfb_dbg_print_byte (name, val);
3201 name = va_arg (list, char *);
3204 va_end (list);
3209 * cirrusfb_dump
3210 * @cirrusfbinfo:
3212 * DESCRIPTION:
3215 static
3216 void cirrusfb_dump (void)
3218 cirrusfb_dbg_reg_dump (NULL);
3223 * cirrusfb_dbg_reg_dump
3224 * @base: If using newmmio, the newmmio base address, otherwise %NULL
3226 * DESCRIPTION:
3227 * Dumps a list of interesting VGA and CIRRUSFB registers. If @base is %NULL,
3228 * old-style I/O ports are queried for information, otherwise MMIO is
3229 * used at the given @base address to query the information.
3232 static
3233 void cirrusfb_dbg_reg_dump (caddr_t regbase)
3235 DPRINTK ("CIRRUSFB VGA CRTC register dump:\n");
3237 cirrusfb_dbg_print_regs (regbase, CRT,
3238 "CR00", 0x00,
3239 "CR01", 0x01,
3240 "CR02", 0x02,
3241 "CR03", 0x03,
3242 "CR04", 0x04,
3243 "CR05", 0x05,
3244 "CR06", 0x06,
3245 "CR07", 0x07,
3246 "CR08", 0x08,
3247 "CR09", 0x09,
3248 "CR0A", 0x0A,
3249 "CR0B", 0x0B,
3250 "CR0C", 0x0C,
3251 "CR0D", 0x0D,
3252 "CR0E", 0x0E,
3253 "CR0F", 0x0F,
3254 "CR10", 0x10,
3255 "CR11", 0x11,
3256 "CR12", 0x12,
3257 "CR13", 0x13,
3258 "CR14", 0x14,
3259 "CR15", 0x15,
3260 "CR16", 0x16,
3261 "CR17", 0x17,
3262 "CR18", 0x18,
3263 "CR22", 0x22,
3264 "CR24", 0x24,
3265 "CR26", 0x26,
3266 "CR2D", 0x2D,
3267 "CR2E", 0x2E,
3268 "CR2F", 0x2F,
3269 "CR30", 0x30,
3270 "CR31", 0x31,
3271 "CR32", 0x32,
3272 "CR33", 0x33,
3273 "CR34", 0x34,
3274 "CR35", 0x35,
3275 "CR36", 0x36,
3276 "CR37", 0x37,
3277 "CR38", 0x38,
3278 "CR39", 0x39,
3279 "CR3A", 0x3A,
3280 "CR3B", 0x3B,
3281 "CR3C", 0x3C,
3282 "CR3D", 0x3D,
3283 "CR3E", 0x3E,
3284 "CR3F", 0x3F,
3285 NULL);
3287 DPRINTK ("\n");
3289 DPRINTK ("CIRRUSFB VGA SEQ register dump:\n");
3291 cirrusfb_dbg_print_regs (regbase, SEQ,
3292 "SR00", 0x00,
3293 "SR01", 0x01,
3294 "SR02", 0x02,
3295 "SR03", 0x03,
3296 "SR04", 0x04,
3297 "SR08", 0x08,
3298 "SR09", 0x09,
3299 "SR0A", 0x0A,
3300 "SR0B", 0x0B,
3301 "SR0D", 0x0D,
3302 "SR10", 0x10,
3303 "SR11", 0x11,
3304 "SR12", 0x12,
3305 "SR13", 0x13,
3306 "SR14", 0x14,
3307 "SR15", 0x15,
3308 "SR16", 0x16,
3309 "SR17", 0x17,
3310 "SR18", 0x18,
3311 "SR19", 0x19,
3312 "SR1A", 0x1A,
3313 "SR1B", 0x1B,
3314 "SR1C", 0x1C,
3315 "SR1D", 0x1D,
3316 "SR1E", 0x1E,
3317 "SR1F", 0x1F,
3318 NULL);
3320 DPRINTK ("\n");
3323 #endif /* CIRRUSFB_DEBUG */