cirrusfb: remove fields from cirrusfb_info
[linux-2.6/linux-loongson.git] / drivers / video / cirrusfb.c
blobebb8ddb0095a4ede6a08794a35063b861fc01d7a
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"
70 /*****************************************************************
72 * debugging and utility macros
76 /* enable debug output? */
77 /* #define CIRRUSFB_DEBUG 1 */
79 /* disable runtime assertions? */
80 /* #define CIRRUSFB_NDEBUG */
82 /* debug output */
83 #ifdef CIRRUSFB_DEBUG
84 #define DPRINTK(fmt, args...) \
85 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 #define MB_ (1024 * 1024)
102 #define KB_ (1024)
104 #define MAX_NUM_BOARDS 7
106 /*****************************************************************
108 * chipset information
112 /* board types */
113 enum cirrus_board {
114 BT_NONE = 0,
115 BT_SD64,
116 BT_PICCOLO,
117 BT_PICASSO,
118 BT_SPECTRUM,
119 BT_PICASSO4, /* GD5446 */
120 BT_ALPINE, /* GD543x/4x */
121 BT_GD5480,
122 BT_LAGUNA, /* GD546x */
126 * per-board-type information, used for enumerating and abstracting
127 * chip-specific information
128 * NOTE: MUST be in the same order as enum cirrus_board in order to
129 * use direct indexing on this array
130 * NOTE: '__initdata' cannot be used as some of this info
131 * is required at runtime. Maybe separate into an init-only and
132 * a run-time table?
134 static const struct cirrusfb_board_info_rec {
135 char *name; /* ASCII name of chipset */
136 long maxclock[5]; /* maximum video clock */
137 /* for 1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */
138 bool init_sr07 : 1; /* init SR07 during init_vgachip() */
139 bool init_sr1f : 1; /* write SR1F during init_vgachip() */
140 /* construct bit 19 of screen start address */
141 bool scrn_start_bit19 : 1;
143 /* initial SR07 value, then for each mode */
144 unsigned char sr07;
145 unsigned char sr07_1bpp;
146 unsigned char sr07_1bpp_mux;
147 unsigned char sr07_8bpp;
148 unsigned char sr07_8bpp_mux;
150 unsigned char sr1f; /* SR1F VGA initial register value */
151 } cirrusfb_board_info[] = {
152 [BT_SD64] = {
153 .name = "CL SD64",
154 .maxclock = {
155 /* guess */
156 /* the SD64/P4 have a higher max. videoclock */
157 140000, 140000, 140000, 140000, 140000,
159 .init_sr07 = true,
160 .init_sr1f = true,
161 .scrn_start_bit19 = true,
162 .sr07 = 0xF0,
163 .sr07_1bpp = 0xF0,
164 .sr07_8bpp = 0xF1,
165 .sr1f = 0x20
167 [BT_PICCOLO] = {
168 .name = "CL Piccolo",
169 .maxclock = {
170 /* guess */
171 90000, 90000, 90000, 90000, 90000
173 .init_sr07 = true,
174 .init_sr1f = true,
175 .scrn_start_bit19 = false,
176 .sr07 = 0x80,
177 .sr07_1bpp = 0x80,
178 .sr07_8bpp = 0x81,
179 .sr1f = 0x22
181 [BT_PICASSO] = {
182 .name = "CL Picasso",
183 .maxclock = {
184 /* guess */
185 90000, 90000, 90000, 90000, 90000
187 .init_sr07 = true,
188 .init_sr1f = true,
189 .scrn_start_bit19 = false,
190 .sr07 = 0x20,
191 .sr07_1bpp = 0x20,
192 .sr07_8bpp = 0x21,
193 .sr1f = 0x22
195 [BT_SPECTRUM] = {
196 .name = "CL Spectrum",
197 .maxclock = {
198 /* guess */
199 90000, 90000, 90000, 90000, 90000
201 .init_sr07 = true,
202 .init_sr1f = true,
203 .scrn_start_bit19 = false,
204 .sr07 = 0x80,
205 .sr07_1bpp = 0x80,
206 .sr07_8bpp = 0x81,
207 .sr1f = 0x22
209 [BT_PICASSO4] = {
210 .name = "CL Picasso4",
211 .maxclock = {
212 135100, 135100, 85500, 85500, 0
214 .init_sr07 = true,
215 .init_sr1f = false,
216 .scrn_start_bit19 = true,
217 .sr07 = 0x20,
218 .sr07_1bpp = 0x20,
219 .sr07_8bpp = 0x21,
220 .sr1f = 0
222 [BT_ALPINE] = {
223 .name = "CL Alpine",
224 .maxclock = {
225 /* for the GD5430. GD5446 can do more... */
226 85500, 85500, 50000, 28500, 0
228 .init_sr07 = true,
229 .init_sr1f = true,
230 .scrn_start_bit19 = true,
231 .sr07 = 0xA0,
232 .sr07_1bpp = 0xA1,
233 .sr07_1bpp_mux = 0xA7,
234 .sr07_8bpp = 0xA1,
235 .sr07_8bpp_mux = 0xA7,
236 .sr1f = 0x1C
238 [BT_GD5480] = {
239 .name = "CL GD5480",
240 .maxclock = {
241 135100, 200000, 200000, 135100, 135100
243 .init_sr07 = true,
244 .init_sr1f = true,
245 .scrn_start_bit19 = true,
246 .sr07 = 0x10,
247 .sr07_1bpp = 0x11,
248 .sr07_8bpp = 0x11,
249 .sr1f = 0x1C
251 [BT_LAGUNA] = {
252 .name = "CL Laguna",
253 .maxclock = {
254 /* guess */
255 135100, 135100, 135100, 135100, 135100,
257 .init_sr07 = false,
258 .init_sr1f = false,
259 .scrn_start_bit19 = true,
263 #ifdef CONFIG_PCI
264 #define CHIP(id, btype) \
265 { PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
267 static struct pci_device_id cirrusfb_pci_table[] = {
268 CHIP(PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE),
269 CHIP(PCI_DEVICE_ID_CIRRUS_5434_8, BT_ALPINE),
270 CHIP(PCI_DEVICE_ID_CIRRUS_5434_4, BT_ALPINE),
271 CHIP(PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE), /* GD-5440 is same id */
272 CHIP(PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE),
273 CHIP(PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE),
274 CHIP(PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480), /* MacPicasso likely */
275 CHIP(PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4), /* Picasso 4 is 5446 */
276 CHIP(PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA), /* CL Laguna */
277 CHIP(PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA), /* CL Laguna 3D */
278 CHIP(PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNA), /* CL Laguna 3DA*/
279 { 0, }
281 MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
282 #undef CHIP
283 #endif /* CONFIG_PCI */
285 #ifdef CONFIG_ZORRO
286 static const struct zorro_device_id cirrusfb_zorro_table[] = {
288 .id = ZORRO_PROD_HELFRICH_SD64_RAM,
289 .driver_data = BT_SD64,
290 }, {
291 .id = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
292 .driver_data = BT_PICCOLO,
293 }, {
294 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
295 .driver_data = BT_PICASSO,
296 }, {
297 .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
298 .driver_data = BT_SPECTRUM,
299 }, {
300 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
301 .driver_data = BT_PICASSO4,
303 { 0 }
306 static const struct {
307 zorro_id id2;
308 unsigned long size;
309 } cirrusfb_zorro_table2[] = {
310 [BT_SD64] = {
311 .id2 = ZORRO_PROD_HELFRICH_SD64_REG,
312 .size = 0x400000
314 [BT_PICCOLO] = {
315 .id2 = ZORRO_PROD_HELFRICH_PICCOLO_REG,
316 .size = 0x200000
318 [BT_PICASSO] = {
319 .id2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
320 .size = 0x200000
322 [BT_SPECTRUM] = {
323 .id2 = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
324 .size = 0x200000
326 [BT_PICASSO4] = {
327 .id2 = 0,
328 .size = 0x400000
331 #endif /* CONFIG_ZORRO */
333 struct cirrusfb_regs {
334 __u32 line_length; /* in BYTES! */
335 __u32 visual;
336 __u32 type;
338 long freq;
339 long nom;
340 long den;
341 long div;
342 long multiplexing;
343 long mclk;
344 long divMCLK;
346 long HorizRes; /* The x resolution in pixel */
347 long HorizTotal;
348 long HorizDispEnd;
349 long HorizBlankStart;
350 long HorizBlankEnd;
351 long HorizSyncStart;
352 long HorizSyncEnd;
354 long VertRes; /* the physical y resolution in scanlines */
355 long VertTotal;
356 long VertDispEnd;
357 long VertSyncStart;
358 long VertSyncEnd;
359 long VertBlankStart;
360 long VertBlankEnd;
363 #ifdef CIRRUSFB_DEBUG
364 enum cirrusfb_dbg_reg_class {
365 CRT,
368 #endif /* CIRRUSFB_DEBUG */
370 /* info about board */
371 struct cirrusfb_info {
372 u8 __iomem *regbase;
373 enum cirrus_board btype;
374 unsigned char SFR; /* Shadow of special function register */
376 struct cirrusfb_regs currentmode;
377 int blank_mode;
379 u32 pseudo_palette[16];
381 #ifdef CONFIG_ZORRO
382 struct zorro_dev *zdev;
383 #endif
384 #ifdef CONFIG_PCI
385 struct pci_dev *pdev;
386 #endif
387 void (*unmap)(struct fb_info *info);
390 static unsigned cirrusfb_def_mode = 1;
391 static int noaccel;
394 * Predefined Video Modes
397 static const struct {
398 const char *name;
399 struct fb_var_screeninfo var;
400 } cirrusfb_predefined[] = {
402 /* autodetect mode */
403 .name = "Autodetect",
404 }, {
405 /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
406 .name = "640x480",
407 .var = {
408 .xres = 640,
409 .yres = 480,
410 .xres_virtual = 640,
411 .yres_virtual = 480,
412 .bits_per_pixel = 8,
413 .red = { .length = 8 },
414 .green = { .length = 8 },
415 .blue = { .length = 8 },
416 .width = -1,
417 .height = -1,
418 .pixclock = 40000,
419 .left_margin = 48,
420 .right_margin = 16,
421 .upper_margin = 32,
422 .lower_margin = 8,
423 .hsync_len = 96,
424 .vsync_len = 4,
425 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
426 .vmode = FB_VMODE_NONINTERLACED
428 }, {
429 /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */
430 .name = "800x600",
431 .var = {
432 .xres = 800,
433 .yres = 600,
434 .xres_virtual = 800,
435 .yres_virtual = 600,
436 .bits_per_pixel = 8,
437 .red = { .length = 8 },
438 .green = { .length = 8 },
439 .blue = { .length = 8 },
440 .width = -1,
441 .height = -1,
442 .pixclock = 20000,
443 .left_margin = 128,
444 .right_margin = 16,
445 .upper_margin = 24,
446 .lower_margin = 2,
447 .hsync_len = 96,
448 .vsync_len = 6,
449 .vmode = FB_VMODE_NONINTERLACED
451 }, {
453 * Modeline from XF86Config:
454 * Mode "1024x768" 80 1024 1136 1340 1432 768 770 774 805
456 /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
457 .name = "1024x768",
458 .var = {
459 .xres = 1024,
460 .yres = 768,
461 .xres_virtual = 1024,
462 .yres_virtual = 768,
463 .bits_per_pixel = 8,
464 .red = { .length = 8 },
465 .green = { .length = 8 },
466 .blue = { .length = 8 },
467 .width = -1,
468 .height = -1,
469 .pixclock = 12500,
470 .left_margin = 144,
471 .right_margin = 32,
472 .upper_margin = 30,
473 .lower_margin = 2,
474 .hsync_len = 192,
475 .vsync_len = 6,
476 .vmode = FB_VMODE_NONINTERLACED
481 #define NUM_TOTAL_MODES ARRAY_SIZE(cirrusfb_predefined)
483 /****************************************************************************/
484 /**** BEGIN PROTOTYPES ******************************************************/
486 /*--- Interface used by the world ------------------------------------------*/
487 static int cirrusfb_init(void);
488 #ifndef MODULE
489 static int cirrusfb_setup(char *options);
490 #endif
492 static int cirrusfb_open(struct fb_info *info, int user);
493 static int cirrusfb_release(struct fb_info *info, int user);
494 static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
495 unsigned blue, unsigned transp,
496 struct fb_info *info);
497 static int cirrusfb_check_var(struct fb_var_screeninfo *var,
498 struct fb_info *info);
499 static int cirrusfb_set_par(struct fb_info *info);
500 static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
501 struct fb_info *info);
502 static int cirrusfb_blank(int blank_mode, struct fb_info *info);
503 static void cirrusfb_fillrect(struct fb_info *info,
504 const struct fb_fillrect *region);
505 static void cirrusfb_copyarea(struct fb_info *info,
506 const struct fb_copyarea *area);
507 static void cirrusfb_imageblit(struct fb_info *info,
508 const struct fb_image *image);
510 /* function table of the above functions */
511 static struct fb_ops cirrusfb_ops = {
512 .owner = THIS_MODULE,
513 .fb_open = cirrusfb_open,
514 .fb_release = cirrusfb_release,
515 .fb_setcolreg = cirrusfb_setcolreg,
516 .fb_check_var = cirrusfb_check_var,
517 .fb_set_par = cirrusfb_set_par,
518 .fb_pan_display = cirrusfb_pan_display,
519 .fb_blank = cirrusfb_blank,
520 .fb_fillrect = cirrusfb_fillrect,
521 .fb_copyarea = cirrusfb_copyarea,
522 .fb_imageblit = cirrusfb_imageblit,
525 /*--- Hardware Specific Routines -------------------------------------------*/
526 static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
527 struct cirrusfb_regs *regs,
528 const struct fb_info *info);
529 /*--- Internal routines ----------------------------------------------------*/
530 static void init_vgachip(struct fb_info *info);
531 static void switch_monitor(struct cirrusfb_info *cinfo, int on);
532 static void WGen(const struct cirrusfb_info *cinfo,
533 int regnum, unsigned char val);
534 static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum);
535 static void AttrOn(const struct cirrusfb_info *cinfo);
536 static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val);
537 static void WSFR(struct cirrusfb_info *cinfo, unsigned char val);
538 static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val);
539 static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum,
540 unsigned char red, unsigned char green, unsigned char blue);
541 #if 0
542 static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum,
543 unsigned char *red, unsigned char *green,
544 unsigned char *blue);
545 #endif
546 static void cirrusfb_WaitBLT(u8 __iomem *regbase);
547 static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
548 u_short curx, u_short cury,
549 u_short destx, u_short desty,
550 u_short width, u_short height,
551 u_short line_length);
552 static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
553 u_short x, u_short y,
554 u_short width, u_short height,
555 u_char color, u_short line_length);
557 static void bestclock(long freq, long *best,
558 long *nom, long *den,
559 long *div, long maxfreq);
561 #ifdef CIRRUSFB_DEBUG
562 static void cirrusfb_dump(void);
563 static void cirrusfb_dbg_reg_dump(caddr_t regbase);
564 static void cirrusfb_dbg_print_regs(caddr_t regbase,
565 enum cirrusfb_dbg_reg_class reg_class, ...);
566 static void cirrusfb_dbg_print_byte(const char *name, unsigned char val);
567 #endif /* CIRRUSFB_DEBUG */
569 /*** END PROTOTYPES ********************************************************/
570 /*****************************************************************************/
571 /*** BEGIN Interface Used by the World ***************************************/
573 static int opencount;
575 /*--- Open /dev/fbx ---------------------------------------------------------*/
576 static int cirrusfb_open(struct fb_info *info, int user)
578 if (opencount++ == 0)
579 switch_monitor(info->par, 1);
580 return 0;
583 /*--- Close /dev/fbx --------------------------------------------------------*/
584 static int cirrusfb_release(struct fb_info *info, int user)
586 if (--opencount == 0)
587 switch_monitor(info->par, 0);
588 return 0;
591 /**** END Interface used by the World *************************************/
592 /****************************************************************************/
593 /**** BEGIN Hardware specific Routines **************************************/
595 /* Get a good MCLK value */
596 static long cirrusfb_get_mclk(long freq, int bpp, long *div)
598 long mclk;
600 assert(div != NULL);
602 /* Calculate MCLK, in case VCLK is high enough to require > 50MHz.
603 * Assume a 64-bit data path for now. The formula is:
604 * ((B * PCLK * 2)/W) * 1.2
605 * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */
606 mclk = ((bpp / 8) * freq * 2) / 4;
607 mclk = (mclk * 12) / 10;
608 if (mclk < 50000)
609 mclk = 50000;
610 DPRINTK("Use MCLK of %ld kHz\n", mclk);
612 /* Calculate value for SR1F. Multiply by 2 so we can round up. */
613 mclk = ((mclk * 16) / 14318);
614 mclk = (mclk + 1) / 2;
615 DPRINTK("Set SR1F[5:0] to 0x%lx\n", mclk);
617 /* Determine if we should use MCLK instead of VCLK, and if so, what we
618 * should divide it by to get VCLK */
619 switch (freq) {
620 case 24751 ... 25249:
621 *div = 2;
622 DPRINTK("Using VCLK = MCLK/2\n");
623 break;
624 case 49501 ... 50499:
625 *div = 1;
626 DPRINTK("Using VCLK = MCLK\n");
627 break;
628 default:
629 *div = 0;
630 break;
633 return mclk;
636 static int cirrusfb_check_var(struct fb_var_screeninfo *var,
637 struct fb_info *info)
639 int nom, den; /* translyting from pixels->bytes */
640 int yres, i;
641 static struct { int xres, yres; } modes[] =
642 { { 1600, 1280 },
643 { 1280, 1024 },
644 { 1024, 768 },
645 { 800, 600 },
646 { 640, 480 },
647 { -1, -1 } };
649 switch (var->bits_per_pixel) {
650 case 0 ... 1:
651 var->bits_per_pixel = 1;
652 nom = 4;
653 den = 8;
654 break; /* 8 pixel per byte, only 1/4th of mem usable */
655 case 2 ... 8:
656 var->bits_per_pixel = 8;
657 nom = 1;
658 den = 1;
659 break; /* 1 pixel == 1 byte */
660 case 9 ... 16:
661 var->bits_per_pixel = 16;
662 nom = 2;
663 den = 1;
664 break; /* 2 bytes per pixel */
665 case 17 ... 24:
666 var->bits_per_pixel = 24;
667 nom = 3;
668 den = 1;
669 break; /* 3 bytes per pixel */
670 case 25 ... 32:
671 var->bits_per_pixel = 32;
672 nom = 4;
673 den = 1;
674 break; /* 4 bytes per pixel */
675 default:
676 printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..."
677 "color depth not supported.\n",
678 var->xres, var->yres, var->bits_per_pixel);
679 DPRINTK("EXIT - EINVAL error\n");
680 return -EINVAL;
683 if (var->xres * nom / den * var->yres > info->screen_size) {
684 printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..."
685 "resolution too high to fit into video memory!\n",
686 var->xres, var->yres, var->bits_per_pixel);
687 DPRINTK("EXIT - EINVAL error\n");
688 return -EINVAL;
691 /* use highest possible virtual resolution */
692 if (var->xres_virtual == -1 &&
693 var->yres_virtual == -1) {
694 printk(KERN_INFO
695 "cirrusfb: using maximum available virtual resolution\n");
696 for (i = 0; modes[i].xres != -1; i++) {
697 int size = modes[i].xres * nom / den * modes[i].yres;
698 if (size < info->screen_size / 2)
699 break;
701 if (modes[i].xres == -1) {
702 printk(KERN_ERR "cirrusfb: could not find a virtual "
703 "resolution that fits into video memory!!\n");
704 DPRINTK("EXIT - EINVAL error\n");
705 return -EINVAL;
707 var->xres_virtual = modes[i].xres;
708 var->yres_virtual = modes[i].yres;
710 printk(KERN_INFO "cirrusfb: virtual resolution set to "
711 "maximum of %dx%d\n", var->xres_virtual,
712 var->yres_virtual);
715 if (var->xres_virtual < var->xres)
716 var->xres_virtual = var->xres;
717 if (var->yres_virtual < var->yres)
718 var->yres_virtual = var->yres;
720 if (var->xoffset < 0)
721 var->xoffset = 0;
722 if (var->yoffset < 0)
723 var->yoffset = 0;
725 /* truncate xoffset and yoffset to maximum if too high */
726 if (var->xoffset > var->xres_virtual - var->xres)
727 var->xoffset = var->xres_virtual - var->xres - 1;
728 if (var->yoffset > var->yres_virtual - var->yres)
729 var->yoffset = var->yres_virtual - var->yres - 1;
731 switch (var->bits_per_pixel) {
732 case 1:
733 var->red.offset = 0;
734 var->red.length = 1;
735 var->green.offset = 0;
736 var->green.length = 1;
737 var->blue.offset = 0;
738 var->blue.length = 1;
739 break;
741 case 8:
742 var->red.offset = 0;
743 var->red.length = 6;
744 var->green.offset = 0;
745 var->green.length = 6;
746 var->blue.offset = 0;
747 var->blue.length = 6;
748 break;
750 case 16:
751 if (isPReP) {
752 var->red.offset = 2;
753 var->green.offset = -3;
754 var->blue.offset = 8;
755 } else {
756 var->red.offset = 10;
757 var->green.offset = 5;
758 var->blue.offset = 0;
760 var->red.length = 5;
761 var->green.length = 5;
762 var->blue.length = 5;
763 break;
765 case 24:
766 if (isPReP) {
767 var->red.offset = 8;
768 var->green.offset = 16;
769 var->blue.offset = 24;
770 } else {
771 var->red.offset = 16;
772 var->green.offset = 8;
773 var->blue.offset = 0;
775 var->red.length = 8;
776 var->green.length = 8;
777 var->blue.length = 8;
778 break;
780 case 32:
781 if (isPReP) {
782 var->red.offset = 8;
783 var->green.offset = 16;
784 var->blue.offset = 24;
785 } else {
786 var->red.offset = 16;
787 var->green.offset = 8;
788 var->blue.offset = 0;
790 var->red.length = 8;
791 var->green.length = 8;
792 var->blue.length = 8;
793 break;
795 default:
796 DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);
797 assert(false);
798 /* should never occur */
799 break;
802 var->red.msb_right =
803 var->green.msb_right =
804 var->blue.msb_right =
805 var->transp.offset =
806 var->transp.length =
807 var->transp.msb_right = 0;
809 yres = var->yres;
810 if (var->vmode & FB_VMODE_DOUBLE)
811 yres *= 2;
812 else if (var->vmode & FB_VMODE_INTERLACED)
813 yres = (yres + 1) / 2;
815 if (yres >= 1280) {
816 printk(KERN_ERR "cirrusfb: ERROR: VerticalTotal >= 1280; "
817 "special treatment required! (TODO)\n");
818 DPRINTK("EXIT - EINVAL error\n");
819 return -EINVAL;
822 return 0;
825 static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
826 struct cirrusfb_regs *regs,
827 const struct fb_info *info)
829 long freq;
830 long maxclock;
831 int maxclockidx = 0;
832 struct cirrusfb_info *cinfo = info->par;
833 int xres, hfront, hsync, hback;
834 int yres, vfront, vsync, vback;
836 switch (var->bits_per_pixel) {
837 case 1:
838 regs->line_length = var->xres_virtual / 8;
839 regs->visual = FB_VISUAL_MONO10;
840 maxclockidx = 0;
841 break;
843 case 8:
844 regs->line_length = var->xres_virtual;
845 regs->visual = FB_VISUAL_PSEUDOCOLOR;
846 maxclockidx = 1;
847 break;
849 case 16:
850 regs->line_length = var->xres_virtual * 2;
851 regs->visual = FB_VISUAL_DIRECTCOLOR;
852 maxclockidx = 2;
853 break;
855 case 24:
856 regs->line_length = var->xres_virtual * 3;
857 regs->visual = FB_VISUAL_DIRECTCOLOR;
858 maxclockidx = 3;
859 break;
861 case 32:
862 regs->line_length = var->xres_virtual * 4;
863 regs->visual = FB_VISUAL_DIRECTCOLOR;
864 maxclockidx = 4;
865 break;
867 default:
868 DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);
869 assert(false);
870 /* should never occur */
871 break;
874 regs->type = FB_TYPE_PACKED_PIXELS;
876 /* convert from ps to kHz */
877 freq = 1000000000 / var->pixclock;
879 DPRINTK("desired pixclock: %ld kHz\n", freq);
881 maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
882 regs->multiplexing = 0;
884 /* If the frequency is greater than we can support, we might be able
885 * to use multiplexing for the video mode */
886 if (freq > maxclock) {
887 switch (cinfo->btype) {
888 case BT_ALPINE:
889 case BT_GD5480:
890 regs->multiplexing = 1;
891 break;
893 default:
894 printk(KERN_ERR "cirrusfb: Frequency greater "
895 "than maxclock (%ld kHz)\n", maxclock);
896 DPRINTK("EXIT - return -EINVAL\n");
897 return -EINVAL;
900 #if 0
901 /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
902 * the VCLK is double the pixel clock. */
903 switch (var->bits_per_pixel) {
904 case 16:
905 case 32:
906 if (regs->HorizRes <= 800)
907 /* Xbh has this type of clock for 32-bit */
908 freq /= 2;
909 break;
911 #endif
913 bestclock(freq, &regs->freq, &regs->nom, &regs->den, &regs->div,
914 maxclock);
915 regs->mclk = cirrusfb_get_mclk(freq, var->bits_per_pixel,
916 &regs->divMCLK);
918 xres = var->xres;
919 hfront = var->right_margin;
920 hsync = var->hsync_len;
921 hback = var->left_margin;
923 yres = var->yres;
924 vfront = var->lower_margin;
925 vsync = var->vsync_len;
926 vback = var->upper_margin;
928 if (var->vmode & FB_VMODE_DOUBLE) {
929 yres *= 2;
930 vfront *= 2;
931 vsync *= 2;
932 vback *= 2;
933 } else if (var->vmode & FB_VMODE_INTERLACED) {
934 yres = (yres + 1) / 2;
935 vfront = (vfront + 1) / 2;
936 vsync = (vsync + 1) / 2;
937 vback = (vback + 1) / 2;
939 regs->HorizRes = xres;
940 regs->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5;
941 regs->HorizDispEnd = xres / 8 - 1;
942 regs->HorizBlankStart = xres / 8;
943 /* does not count with "-5" */
944 regs->HorizBlankEnd = regs->HorizTotal + 5;
945 regs->HorizSyncStart = (xres + hfront) / 8 + 1;
946 regs->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1;
948 regs->VertRes = yres;
949 regs->VertTotal = yres + vfront + vsync + vback - 2;
950 regs->VertDispEnd = yres - 1;
951 regs->VertBlankStart = yres;
952 regs->VertBlankEnd = regs->VertTotal;
953 regs->VertSyncStart = yres + vfront - 1;
954 regs->VertSyncEnd = yres + vfront + vsync - 1;
956 if (regs->VertRes >= 1024) {
957 regs->VertTotal /= 2;
958 regs->VertSyncStart /= 2;
959 regs->VertSyncEnd /= 2;
960 regs->VertDispEnd /= 2;
962 if (regs->multiplexing) {
963 regs->HorizTotal /= 2;
964 regs->HorizSyncStart /= 2;
965 regs->HorizSyncEnd /= 2;
966 regs->HorizDispEnd /= 2;
969 return 0;
972 static void cirrusfb_set_mclk(const struct cirrusfb_info *cinfo, int val,
973 int div)
975 assert(cinfo != NULL);
977 if (div == 2) {
978 /* VCLK = MCLK/2 */
979 unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E);
980 vga_wseq(cinfo->regbase, CL_SEQR1E, old | 0x1);
981 vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
982 } else if (div == 1) {
983 /* VCLK = MCLK */
984 unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E);
985 vga_wseq(cinfo->regbase, CL_SEQR1E, old & ~0x1);
986 vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
987 } else {
988 vga_wseq(cinfo->regbase, CL_SEQR1F, val & 0x3f);
992 /*************************************************************************
993 cirrusfb_set_par_foo()
995 actually writes the values for a new video mode into the hardware,
996 **************************************************************************/
997 static int cirrusfb_set_par_foo(struct fb_info *info)
999 struct cirrusfb_info *cinfo = info->par;
1000 struct fb_var_screeninfo *var = &info->var;
1001 struct cirrusfb_regs regs;
1002 u8 __iomem *regbase = cinfo->regbase;
1003 unsigned char tmp;
1004 int offset = 0, err;
1005 const struct cirrusfb_board_info_rec *bi;
1007 DPRINTK("ENTER\n");
1008 DPRINTK("Requested mode: %dx%dx%d\n",
1009 var->xres, var->yres, var->bits_per_pixel);
1010 DPRINTK("pixclock: %d\n", var->pixclock);
1012 init_vgachip(info);
1014 err = cirrusfb_decode_var(var, &regs, info);
1015 if (err) {
1016 /* should never happen */
1017 DPRINTK("mode change aborted. invalid var.\n");
1018 return -EINVAL;
1021 bi = &cirrusfb_board_info[cinfo->btype];
1023 /* unlock register VGA_CRTC_H_TOTAL..CRT7 */
1024 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */
1026 /* if debugging is enabled, all parameters get output before writing */
1027 DPRINTK("CRT0: %ld\n", regs.HorizTotal);
1028 vga_wcrt(regbase, VGA_CRTC_H_TOTAL, regs.HorizTotal);
1030 DPRINTK("CRT1: %ld\n", regs.HorizDispEnd);
1031 vga_wcrt(regbase, VGA_CRTC_H_DISP, regs.HorizDispEnd);
1033 DPRINTK("CRT2: %ld\n", regs.HorizBlankStart);
1034 vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, regs.HorizBlankStart);
1036 /* + 128: Compatible read */
1037 DPRINTK("CRT3: 128+%ld\n", regs.HorizBlankEnd % 32);
1038 vga_wcrt(regbase, VGA_CRTC_H_BLANK_END,
1039 128 + (regs.HorizBlankEnd % 32));
1041 DPRINTK("CRT4: %ld\n", regs.HorizSyncStart);
1042 vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, regs.HorizSyncStart);
1044 tmp = regs.HorizSyncEnd % 32;
1045 if (regs.HorizBlankEnd & 32)
1046 tmp += 128;
1047 DPRINTK("CRT5: %d\n", tmp);
1048 vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp);
1050 DPRINTK("CRT6: %ld\n", regs.VertTotal & 0xff);
1051 vga_wcrt(regbase, VGA_CRTC_V_TOTAL, (regs.VertTotal & 0xff));
1053 tmp = 16; /* LineCompare bit #9 */
1054 if (regs.VertTotal & 256)
1055 tmp |= 1;
1056 if (regs.VertDispEnd & 256)
1057 tmp |= 2;
1058 if (regs.VertSyncStart & 256)
1059 tmp |= 4;
1060 if (regs.VertBlankStart & 256)
1061 tmp |= 8;
1062 if (regs.VertTotal & 512)
1063 tmp |= 32;
1064 if (regs.VertDispEnd & 512)
1065 tmp |= 64;
1066 if (regs.VertSyncStart & 512)
1067 tmp |= 128;
1068 DPRINTK("CRT7: %d\n", tmp);
1069 vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp);
1071 tmp = 0x40; /* LineCompare bit #8 */
1072 if (regs.VertBlankStart & 512)
1073 tmp |= 0x20;
1074 if (var->vmode & FB_VMODE_DOUBLE)
1075 tmp |= 0x80;
1076 DPRINTK("CRT9: %d\n", tmp);
1077 vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp);
1079 DPRINTK("CRT10: %ld\n", regs.VertSyncStart & 0xff);
1080 vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, regs.VertSyncStart & 0xff);
1082 DPRINTK("CRT11: 64+32+%ld\n", regs.VertSyncEnd % 16);
1083 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, regs.VertSyncEnd % 16 + 64 + 32);
1085 DPRINTK("CRT12: %ld\n", regs.VertDispEnd & 0xff);
1086 vga_wcrt(regbase, VGA_CRTC_V_DISP_END, regs.VertDispEnd & 0xff);
1088 DPRINTK("CRT15: %ld\n", regs.VertBlankStart & 0xff);
1089 vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, regs.VertBlankStart & 0xff);
1091 DPRINTK("CRT16: %ld\n", regs.VertBlankEnd & 0xff);
1092 vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, regs.VertBlankEnd & 0xff);
1094 DPRINTK("CRT18: 0xff\n");
1095 vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff);
1097 tmp = 0;
1098 if (var->vmode & FB_VMODE_INTERLACED)
1099 tmp |= 1;
1100 if (regs.HorizBlankEnd & 64)
1101 tmp |= 16;
1102 if (regs.HorizBlankEnd & 128)
1103 tmp |= 32;
1104 if (regs.VertBlankEnd & 256)
1105 tmp |= 64;
1106 if (regs.VertBlankEnd & 512)
1107 tmp |= 128;
1109 DPRINTK("CRT1a: %d\n", tmp);
1110 vga_wcrt(regbase, CL_CRT1A, tmp);
1112 /* set VCLK0 */
1113 /* hardware RefClock: 14.31818 MHz */
1114 /* formula: VClk = (OSC * N) / (D * (1+P)) */
1115 /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
1117 vga_wseq(regbase, CL_SEQRB, regs.nom);
1118 tmp = regs.den << 1;
1119 if (regs.div != 0)
1120 tmp |= 1;
1122 /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
1123 if ((cinfo->btype == BT_SD64) ||
1124 (cinfo->btype == BT_ALPINE) ||
1125 (cinfo->btype == BT_GD5480))
1126 tmp |= 0x80;
1128 DPRINTK("CL_SEQR1B: %ld\n", (long) tmp);
1129 vga_wseq(regbase, CL_SEQR1B, tmp);
1131 if (regs.VertRes >= 1024)
1132 /* 1280x1024 */
1133 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7);
1134 else
1135 /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
1136 * address wrap, no compat. */
1137 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3);
1139 /* HAEH? vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20);
1140 * previously: 0x00 unlock VGA_CRTC_H_TOTAL..CRT7 */
1142 /* don't know if it would hurt to also program this if no interlaced */
1143 /* mode is used, but I feel better this way.. :-) */
1144 if (var->vmode & FB_VMODE_INTERLACED)
1145 vga_wcrt(regbase, VGA_CRTC_REGS, regs.HorizTotal / 2);
1146 else
1147 vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
1149 vga_wseq(regbase, VGA_SEQ_CHARACTER_MAP, 0);
1151 /* adjust horizontal/vertical sync type (low/high) */
1152 /* enable display memory & CRTC I/O address for color mode */
1153 tmp = 0x03;
1154 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1155 tmp |= 0x40;
1156 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1157 tmp |= 0x80;
1158 WGen(cinfo, VGA_MIS_W, tmp);
1160 /* Screen A Preset Row-Scan register */
1161 vga_wcrt(regbase, VGA_CRTC_PRESET_ROW, 0);
1162 /* text cursor on and start line */
1163 vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0);
1164 /* text cursor end line */
1165 vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 31);
1167 /******************************************************
1169 * 1 bpp
1173 /* programming for different color depths */
1174 if (var->bits_per_pixel == 1) {
1175 DPRINTK("cirrusfb: preparing for 1 bit deep display\n");
1176 vga_wgfx(regbase, VGA_GFX_MODE, 0); /* mode register */
1178 /* SR07 */
1179 switch (cinfo->btype) {
1180 case BT_SD64:
1181 case BT_PICCOLO:
1182 case BT_PICASSO:
1183 case BT_SPECTRUM:
1184 case BT_PICASSO4:
1185 case BT_ALPINE:
1186 case BT_GD5480:
1187 DPRINTK(" (for GD54xx)\n");
1188 vga_wseq(regbase, CL_SEQR7,
1189 regs.multiplexing ?
1190 bi->sr07_1bpp_mux : bi->sr07_1bpp);
1191 break;
1193 case BT_LAGUNA:
1194 DPRINTK(" (for GD546x)\n");
1195 vga_wseq(regbase, CL_SEQR7,
1196 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1197 break;
1199 default:
1200 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1201 break;
1204 /* Extended Sequencer Mode */
1205 switch (cinfo->btype) {
1206 case BT_SD64:
1207 /* setting the SEQRF on SD64 is not necessary
1208 * (only during init)
1210 DPRINTK("(for SD64)\n");
1211 /* MCLK select */
1212 vga_wseq(regbase, CL_SEQR1F, 0x1a);
1213 break;
1215 case BT_PICCOLO:
1216 DPRINTK("(for Piccolo)\n");
1217 /* ### ueberall 0x22? */
1218 /* ##vorher 1c MCLK select */
1219 vga_wseq(regbase, CL_SEQR1F, 0x22);
1220 /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
1221 vga_wseq(regbase, CL_SEQRF, 0xb0);
1222 break;
1224 case BT_PICASSO:
1225 DPRINTK("(for Picasso)\n");
1226 /* ##vorher 22 MCLK select */
1227 vga_wseq(regbase, CL_SEQR1F, 0x22);
1228 /* ## vorher d0 avoid FIFO underruns..? */
1229 vga_wseq(regbase, CL_SEQRF, 0xd0);
1230 break;
1232 case BT_SPECTRUM:
1233 DPRINTK("(for Spectrum)\n");
1234 /* ### ueberall 0x22? */
1235 /* ##vorher 1c MCLK select */
1236 vga_wseq(regbase, CL_SEQR1F, 0x22);
1237 /* evtl d0? avoid FIFO underruns..? */
1238 vga_wseq(regbase, CL_SEQRF, 0xb0);
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 /* pixel mask: pass-through for first plane */
1255 WGen(cinfo, VGA_PEL_MSK, 0x01);
1256 if (regs.multiplexing)
1257 /* hidden dac reg: 1280x1024 */
1258 WHDR(cinfo, 0x4a);
1259 else
1260 /* hidden dac: nothing */
1261 WHDR(cinfo, 0);
1262 /* memory mode: odd/even, ext. memory */
1263 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06);
1264 /* plane mask: only write to first plane */
1265 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01);
1266 offset = var->xres_virtual / 16;
1269 /******************************************************
1271 * 8 bpp
1275 else if (var->bits_per_pixel == 8) {
1276 DPRINTK("cirrusfb: preparing for 8 bit deep display\n");
1277 switch (cinfo->btype) {
1278 case BT_SD64:
1279 case BT_PICCOLO:
1280 case BT_PICASSO:
1281 case BT_SPECTRUM:
1282 case BT_PICASSO4:
1283 case BT_ALPINE:
1284 case BT_GD5480:
1285 DPRINTK(" (for GD54xx)\n");
1286 vga_wseq(regbase, CL_SEQR7,
1287 regs.multiplexing ?
1288 bi->sr07_8bpp_mux : bi->sr07_8bpp);
1289 break;
1291 case BT_LAGUNA:
1292 DPRINTK(" (for GD546x)\n");
1293 vga_wseq(regbase, CL_SEQR7,
1294 vga_rseq(regbase, CL_SEQR7) | 0x01);
1295 break;
1297 default:
1298 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1299 break;
1302 switch (cinfo->btype) {
1303 case BT_SD64:
1304 /* MCLK select */
1305 vga_wseq(regbase, CL_SEQR1F, 0x1d);
1306 break;
1308 case BT_PICCOLO:
1309 /* ### vorher 1c MCLK select */
1310 vga_wseq(regbase, CL_SEQR1F, 0x22);
1311 /* Fast Page-Mode writes */
1312 vga_wseq(regbase, CL_SEQRF, 0xb0);
1313 break;
1315 case BT_PICASSO:
1316 /* ### vorher 1c MCLK select */
1317 vga_wseq(regbase, CL_SEQR1F, 0x22);
1318 /* Fast Page-Mode writes */
1319 vga_wseq(regbase, CL_SEQRF, 0xb0);
1320 break;
1322 case BT_SPECTRUM:
1323 /* ### vorher 1c MCLK select */
1324 vga_wseq(regbase, CL_SEQR1F, 0x22);
1325 /* Fast Page-Mode writes */
1326 vga_wseq(regbase, CL_SEQRF, 0xb0);
1327 break;
1329 case BT_PICASSO4:
1330 #ifdef CONFIG_ZORRO
1331 /* ### INCOMPLETE!! */
1332 vga_wseq(regbase, CL_SEQRF, 0xb8);
1333 #endif
1334 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1335 break;
1337 case BT_ALPINE:
1338 DPRINTK(" (for GD543x)\n");
1339 cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
1340 /* We already set SRF and SR1F */
1341 break;
1343 case BT_GD5480:
1344 case BT_LAGUNA:
1345 DPRINTK(" (for GD54xx)\n");
1346 /* do nothing */
1347 break;
1349 default:
1350 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1351 break;
1354 /* mode register: 256 color mode */
1355 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1356 /* pixel mask: pass-through all planes */
1357 WGen(cinfo, VGA_PEL_MSK, 0xff);
1358 if (regs.multiplexing)
1359 /* hidden dac reg: 1280x1024 */
1360 WHDR(cinfo, 0x4a);
1361 else
1362 /* hidden dac: nothing */
1363 WHDR(cinfo, 0);
1364 /* memory mode: chain4, ext. memory */
1365 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1366 /* plane mask: enable writing to all 4 planes */
1367 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1368 offset = var->xres_virtual / 8;
1371 /******************************************************
1373 * 16 bpp
1377 else if (var->bits_per_pixel == 16) {
1378 DPRINTK("cirrusfb: preparing for 16 bit deep display\n");
1379 switch (cinfo->btype) {
1380 case BT_SD64:
1381 /* Extended Sequencer Mode: 256c col. mode */
1382 vga_wseq(regbase, CL_SEQR7, 0xf7);
1383 /* MCLK select */
1384 vga_wseq(regbase, CL_SEQR1F, 0x1e);
1385 break;
1387 case BT_PICCOLO:
1388 vga_wseq(regbase, CL_SEQR7, 0x87);
1389 /* Fast Page-Mode writes */
1390 vga_wseq(regbase, CL_SEQRF, 0xb0);
1391 /* MCLK select */
1392 vga_wseq(regbase, CL_SEQR1F, 0x22);
1393 break;
1395 case BT_PICASSO:
1396 vga_wseq(regbase, CL_SEQR7, 0x27);
1397 /* Fast Page-Mode writes */
1398 vga_wseq(regbase, CL_SEQRF, 0xb0);
1399 /* MCLK select */
1400 vga_wseq(regbase, CL_SEQR1F, 0x22);
1401 break;
1403 case BT_SPECTRUM:
1404 vga_wseq(regbase, CL_SEQR7, 0x87);
1405 /* Fast Page-Mode writes */
1406 vga_wseq(regbase, CL_SEQRF, 0xb0);
1407 /* MCLK select */
1408 vga_wseq(regbase, CL_SEQR1F, 0x22);
1409 break;
1411 case BT_PICASSO4:
1412 vga_wseq(regbase, CL_SEQR7, 0x27);
1413 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1414 break;
1416 case BT_ALPINE:
1417 DPRINTK(" (for GD543x)\n");
1418 if (regs.HorizRes >= 1024)
1419 vga_wseq(regbase, CL_SEQR7, 0xa7);
1420 else
1421 vga_wseq(regbase, CL_SEQR7, 0xa3);
1422 cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
1423 break;
1425 case BT_GD5480:
1426 DPRINTK(" (for GD5480)\n");
1427 vga_wseq(regbase, CL_SEQR7, 0x17);
1428 /* We already set SRF and SR1F */
1429 break;
1431 case BT_LAGUNA:
1432 DPRINTK(" (for GD546x)\n");
1433 vga_wseq(regbase, CL_SEQR7,
1434 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1435 break;
1437 default:
1438 printk(KERN_WARNING "CIRRUSFB: unknown Board\n");
1439 break;
1442 /* mode register: 256 color mode */
1443 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1444 /* pixel mask: pass-through all planes */
1445 WGen(cinfo, VGA_PEL_MSK, 0xff);
1446 #ifdef CONFIG_PCI
1447 WHDR(cinfo, 0xc0); /* Copy Xbh */
1448 #elif defined(CONFIG_ZORRO)
1449 /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
1450 WHDR(cinfo, 0xa0); /* hidden dac reg: nothing special */
1451 #endif
1452 /* memory mode: chain4, ext. memory */
1453 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1454 /* plane mask: enable writing to all 4 planes */
1455 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1456 offset = var->xres_virtual / 4;
1459 /******************************************************
1461 * 32 bpp
1465 else if (var->bits_per_pixel == 32) {
1466 DPRINTK("cirrusfb: preparing for 24/32 bit deep display\n");
1467 switch (cinfo->btype) {
1468 case BT_SD64:
1469 /* Extended Sequencer Mode: 256c col. mode */
1470 vga_wseq(regbase, CL_SEQR7, 0xf9);
1471 /* MCLK select */
1472 vga_wseq(regbase, CL_SEQR1F, 0x1e);
1473 break;
1475 case BT_PICCOLO:
1476 vga_wseq(regbase, CL_SEQR7, 0x85);
1477 /* Fast Page-Mode writes */
1478 vga_wseq(regbase, CL_SEQRF, 0xb0);
1479 /* MCLK select */
1480 vga_wseq(regbase, CL_SEQR1F, 0x22);
1481 break;
1483 case BT_PICASSO:
1484 vga_wseq(regbase, CL_SEQR7, 0x25);
1485 /* Fast Page-Mode writes */
1486 vga_wseq(regbase, CL_SEQRF, 0xb0);
1487 /* MCLK select */
1488 vga_wseq(regbase, CL_SEQR1F, 0x22);
1489 break;
1491 case BT_SPECTRUM:
1492 vga_wseq(regbase, CL_SEQR7, 0x85);
1493 /* Fast Page-Mode writes */
1494 vga_wseq(regbase, CL_SEQRF, 0xb0);
1495 /* MCLK select */
1496 vga_wseq(regbase, CL_SEQR1F, 0x22);
1497 break;
1499 case BT_PICASSO4:
1500 vga_wseq(regbase, CL_SEQR7, 0x25);
1501 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1502 break;
1504 case BT_ALPINE:
1505 DPRINTK(" (for GD543x)\n");
1506 vga_wseq(regbase, CL_SEQR7, 0xa9);
1507 cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
1508 break;
1510 case BT_GD5480:
1511 DPRINTK(" (for GD5480)\n");
1512 vga_wseq(regbase, CL_SEQR7, 0x19);
1513 /* We already set SRF and SR1F */
1514 break;
1516 case BT_LAGUNA:
1517 DPRINTK(" (for GD546x)\n");
1518 vga_wseq(regbase, CL_SEQR7,
1519 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1520 break;
1522 default:
1523 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1524 break;
1527 /* mode register: 256 color mode */
1528 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1529 /* pixel mask: pass-through all planes */
1530 WGen(cinfo, VGA_PEL_MSK, 0xff);
1531 /* hidden dac reg: 8-8-8 mode (24 or 32) */
1532 WHDR(cinfo, 0xc5);
1533 /* memory mode: chain4, ext. memory */
1534 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1535 /* plane mask: enable writing to all 4 planes */
1536 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1537 offset = var->xres_virtual / 4;
1540 /******************************************************
1542 * unknown/unsupported bpp
1546 else
1547 printk(KERN_ERR "cirrusfb: What's this?? "
1548 " requested color depth == %d.\n",
1549 var->bits_per_pixel);
1551 vga_wcrt(regbase, VGA_CRTC_OFFSET, offset & 0xff);
1552 tmp = 0x22;
1553 if (offset & 0x100)
1554 tmp |= 0x10; /* offset overflow bit */
1556 /* screen start addr #16-18, fastpagemode cycles */
1557 vga_wcrt(regbase, CL_CRT1B, tmp);
1559 if (cinfo->btype == BT_SD64 ||
1560 cinfo->btype == BT_PICASSO4 ||
1561 cinfo->btype == BT_ALPINE ||
1562 cinfo->btype == BT_GD5480)
1563 /* screen start address bit 19 */
1564 vga_wcrt(regbase, CL_CRT1D, 0x00);
1566 /* text cursor location high */
1567 vga_wcrt(regbase, VGA_CRTC_CURSOR_HI, 0);
1568 /* text cursor location low */
1569 vga_wcrt(regbase, VGA_CRTC_CURSOR_LO, 0);
1570 /* underline row scanline = at very bottom */
1571 vga_wcrt(regbase, VGA_CRTC_UNDERLINE, 0);
1573 /* controller mode */
1574 vga_wattr(regbase, VGA_ATC_MODE, 1);
1575 /* overscan (border) color */
1576 vga_wattr(regbase, VGA_ATC_OVERSCAN, 0);
1577 /* color plane enable */
1578 vga_wattr(regbase, VGA_ATC_PLANE_ENABLE, 15);
1579 /* pixel panning */
1580 vga_wattr(regbase, CL_AR33, 0);
1581 /* color select */
1582 vga_wattr(regbase, VGA_ATC_COLOR_PAGE, 0);
1584 /* [ EGS: SetOffset(); ] */
1585 /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
1586 AttrOn(cinfo);
1588 /* set/reset register */
1589 vga_wgfx(regbase, VGA_GFX_SR_VALUE, 0);
1590 /* set/reset enable */
1591 vga_wgfx(regbase, VGA_GFX_SR_ENABLE, 0);
1592 /* color compare */
1593 vga_wgfx(regbase, VGA_GFX_COMPARE_VALUE, 0);
1594 /* data rotate */
1595 vga_wgfx(regbase, VGA_GFX_DATA_ROTATE, 0);
1596 /* read map select */
1597 vga_wgfx(regbase, VGA_GFX_PLANE_READ, 0);
1598 /* miscellaneous register */
1599 vga_wgfx(regbase, VGA_GFX_MISC, 1);
1600 /* color don't care */
1601 vga_wgfx(regbase, VGA_GFX_COMPARE_MASK, 15);
1602 /* bit mask */
1603 vga_wgfx(regbase, VGA_GFX_BIT_MASK, 255);
1605 /* graphics cursor attributes: nothing special */
1606 vga_wseq(regbase, CL_SEQR12, 0x0);
1608 /* finally, turn on everything - turn off "FullBandwidth" bit */
1609 /* also, set "DotClock%2" bit where requested */
1610 tmp = 0x01;
1612 /*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
1613 if (var->vmode & FB_VMODE_CLOCK_HALVE)
1614 tmp |= 0x08;
1617 vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp);
1618 DPRINTK("CL_SEQR1: %d\n", tmp);
1620 cinfo->currentmode = regs;
1621 info->fix.type = regs.type;
1622 info->fix.visual = regs.visual;
1623 info->fix.line_length = regs.line_length;
1625 /* pan to requested offset */
1626 cirrusfb_pan_display(var, info);
1628 #ifdef CIRRUSFB_DEBUG
1629 cirrusfb_dump();
1630 #endif
1632 DPRINTK("EXIT\n");
1633 return 0;
1636 /* for some reason incomprehensible to me, cirrusfb requires that you write
1637 * the registers twice for the settings to take..grr. -dte */
1638 static int cirrusfb_set_par(struct fb_info *info)
1640 cirrusfb_set_par_foo(info);
1641 return cirrusfb_set_par_foo(info);
1644 static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1645 unsigned blue, unsigned transp,
1646 struct fb_info *info)
1648 struct cirrusfb_info *cinfo = info->par;
1650 if (regno > 255)
1651 return -EINVAL;
1653 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
1654 u32 v;
1655 red >>= (16 - info->var.red.length);
1656 green >>= (16 - info->var.green.length);
1657 blue >>= (16 - info->var.blue.length);
1659 if (regno >= 16)
1660 return 1;
1661 v = (red << info->var.red.offset) |
1662 (green << info->var.green.offset) |
1663 (blue << info->var.blue.offset);
1665 switch (info->var.bits_per_pixel) {
1666 case 8:
1667 cinfo->pseudo_palette[regno] = v;
1668 break;
1669 case 16:
1670 cinfo->pseudo_palette[regno] = v;
1671 break;
1672 case 24:
1673 case 32:
1674 cinfo->pseudo_palette[regno] = v;
1675 break;
1677 return 0;
1680 if (info->var.bits_per_pixel == 8)
1681 WClut(cinfo, regno, red >> 10, green >> 10, blue >> 10);
1683 return 0;
1687 /*************************************************************************
1688 cirrusfb_pan_display()
1690 performs display panning - provided hardware permits this
1691 **************************************************************************/
1692 static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
1693 struct fb_info *info)
1695 int xoffset = 0;
1696 int yoffset = 0;
1697 unsigned long base;
1698 unsigned char tmp = 0, tmp2 = 0, xpix;
1699 struct cirrusfb_info *cinfo = info->par;
1701 DPRINTK("ENTER\n");
1702 DPRINTK("virtual offset: (%d,%d)\n", var->xoffset, var->yoffset);
1704 /* no range checks for xoffset and yoffset, */
1705 /* as fb_pan_display has already done this */
1706 if (var->vmode & FB_VMODE_YWRAP)
1707 return -EINVAL;
1709 info->var.xoffset = var->xoffset;
1710 info->var.yoffset = var->yoffset;
1712 xoffset = var->xoffset * info->var.bits_per_pixel / 8;
1713 yoffset = var->yoffset;
1715 base = yoffset * cinfo->currentmode.line_length + xoffset;
1717 if (info->var.bits_per_pixel == 1) {
1718 /* base is already correct */
1719 xpix = (unsigned char) (var->xoffset % 8);
1720 } else {
1721 base /= 4;
1722 xpix = (unsigned char) ((xoffset % 4) * 2);
1725 cirrusfb_WaitBLT(cinfo->regbase); /* make sure all the BLT's are done */
1727 /* lower 8 + 8 bits of screen start address */
1728 vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO,
1729 (unsigned char) (base & 0xff));
1730 vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI,
1731 (unsigned char) (base >> 8));
1733 /* construct bits 16, 17 and 18 of screen start address */
1734 if (base & 0x10000)
1735 tmp |= 0x01;
1736 if (base & 0x20000)
1737 tmp |= 0x04;
1738 if (base & 0x40000)
1739 tmp |= 0x08;
1741 /* 0xf2 is %11110010, exclude tmp bits */
1742 tmp2 = (vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2) | tmp;
1743 vga_wcrt(cinfo->regbase, CL_CRT1B, tmp2);
1745 /* construct bit 19 of screen start address */
1746 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) {
1747 tmp2 = 0;
1748 if (base & 0x80000)
1749 tmp2 = 0x80;
1750 vga_wcrt(cinfo->regbase, CL_CRT1D, tmp2);
1753 /* write pixel panning value to AR33; this does not quite work in 8bpp
1755 * ### Piccolo..? Will this work?
1757 if (info->var.bits_per_pixel == 1)
1758 vga_wattr(cinfo->regbase, CL_AR33, xpix);
1760 cirrusfb_WaitBLT(cinfo->regbase);
1762 DPRINTK("EXIT\n");
1763 return 0;
1766 static int cirrusfb_blank(int blank_mode, struct fb_info *info)
1769 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
1770 * then the caller blanks by setting the CLUT (Color Look Up Table)
1771 * to all black. Return 0 if blanking succeeded, != 0 if un-/blanking
1772 * failed due to e.g. a video mode which doesn't support it.
1773 * Implements VESA suspend and powerdown modes on hardware that
1774 * supports disabling hsync/vsync:
1775 * blank_mode == 2: suspend vsync
1776 * blank_mode == 3: suspend hsync
1777 * blank_mode == 4: powerdown
1779 unsigned char val;
1780 struct cirrusfb_info *cinfo = info->par;
1781 int current_mode = cinfo->blank_mode;
1783 DPRINTK("ENTER, blank mode = %d\n", blank_mode);
1785 if (info->state != FBINFO_STATE_RUNNING ||
1786 current_mode == blank_mode) {
1787 DPRINTK("EXIT, returning 0\n");
1788 return 0;
1791 /* Undo current */
1792 if (current_mode == FB_BLANK_NORMAL ||
1793 current_mode == FB_BLANK_UNBLANK) {
1794 /* unblank the screen */
1795 val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1796 /* clear "FullBandwidth" bit */
1797 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val & 0xdf);
1798 /* and undo VESA suspend trickery */
1799 vga_wgfx(cinfo->regbase, CL_GRE, 0x00);
1802 /* set new */
1803 if (blank_mode > FB_BLANK_NORMAL) {
1804 /* blank the screen */
1805 val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1806 /* set "FullBandwidth" bit */
1807 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val | 0x20);
1810 switch (blank_mode) {
1811 case FB_BLANK_UNBLANK:
1812 case FB_BLANK_NORMAL:
1813 break;
1814 case FB_BLANK_VSYNC_SUSPEND:
1815 vga_wgfx(cinfo->regbase, CL_GRE, 0x04);
1816 break;
1817 case FB_BLANK_HSYNC_SUSPEND:
1818 vga_wgfx(cinfo->regbase, CL_GRE, 0x02);
1819 break;
1820 case FB_BLANK_POWERDOWN:
1821 vga_wgfx(cinfo->regbase, CL_GRE, 0x06);
1822 break;
1823 default:
1824 DPRINTK("EXIT, returning 1\n");
1825 return 1;
1828 cinfo->blank_mode = blank_mode;
1829 DPRINTK("EXIT, returning 0\n");
1831 /* Let fbcon do a soft blank for us */
1832 return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
1834 /**** END Hardware specific Routines **************************************/
1835 /****************************************************************************/
1836 /**** BEGIN Internal Routines ***********************************************/
1838 static void init_vgachip(struct fb_info *info)
1840 struct cirrusfb_info *cinfo = info->par;
1841 const struct cirrusfb_board_info_rec *bi;
1843 DPRINTK("ENTER\n");
1845 assert(cinfo != NULL);
1847 bi = &cirrusfb_board_info[cinfo->btype];
1849 /* reset board globally */
1850 switch (cinfo->btype) {
1851 case BT_PICCOLO:
1852 WSFR(cinfo, 0x01);
1853 udelay(500);
1854 WSFR(cinfo, 0x51);
1855 udelay(500);
1856 break;
1857 case BT_PICASSO:
1858 WSFR2(cinfo, 0xff);
1859 udelay(500);
1860 break;
1861 case BT_SD64:
1862 case BT_SPECTRUM:
1863 WSFR(cinfo, 0x1f);
1864 udelay(500);
1865 WSFR(cinfo, 0x4f);
1866 udelay(500);
1867 break;
1868 case BT_PICASSO4:
1869 /* disable flickerfixer */
1870 vga_wcrt(cinfo->regbase, CL_CRT51, 0x00);
1871 mdelay(100);
1872 /* from Klaus' NetBSD driver: */
1873 vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
1874 /* put blitter into 542x compat */
1875 vga_wgfx(cinfo->regbase, CL_GR33, 0x00);
1876 /* mode */
1877 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1878 break;
1880 case BT_GD5480:
1881 /* from Klaus' NetBSD driver: */
1882 vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
1883 break;
1885 case BT_ALPINE:
1886 /* Nothing to do to reset the board. */
1887 break;
1889 default:
1890 printk(KERN_ERR "cirrusfb: Warning: Unknown board type\n");
1891 break;
1894 /* make sure RAM size set by this point */
1895 assert(info->screen_size > 0);
1897 /* the P4 is not fully initialized here; I rely on it having been */
1898 /* inited under AmigaOS already, which seems to work just fine */
1899 /* (Klaus advised to do it this way) */
1901 if (cinfo->btype != BT_PICASSO4) {
1902 WGen(cinfo, CL_VSSM, 0x10); /* EGS: 0x16 */
1903 WGen(cinfo, CL_POS102, 0x01);
1904 WGen(cinfo, CL_VSSM, 0x08); /* EGS: 0x0e */
1906 if (cinfo->btype != BT_SD64)
1907 WGen(cinfo, CL_VSSM2, 0x01);
1909 /* reset sequencer logic */
1910 vga_wseq(cinfo->regbase, CL_SEQR0, 0x03);
1912 /* FullBandwidth (video off) and 8/9 dot clock */
1913 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21);
1914 /* polarity (-/-), disable access to display memory,
1915 * VGA_CRTC_START_HI base address: color
1917 WGen(cinfo, VGA_MIS_W, 0xc1);
1919 /* "magic cookie" - doesn't make any sense to me.. */
1920 /* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */
1921 /* unlock all extension registers */
1922 vga_wseq(cinfo->regbase, CL_SEQR6, 0x12);
1924 /* reset blitter */
1925 vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
1927 switch (cinfo->btype) {
1928 case BT_GD5480:
1929 vga_wseq(cinfo->regbase, CL_SEQRF, 0x98);
1930 break;
1931 case BT_ALPINE:
1932 break;
1933 case BT_SD64:
1934 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8);
1935 break;
1936 default:
1937 vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f);
1938 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb0);
1939 break;
1942 /* plane mask: nothing */
1943 vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1944 /* character map select: doesn't even matter in gx mode */
1945 vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00);
1946 /* memory mode: chain-4, no odd/even, ext. memory */
1947 vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0e);
1949 /* controller-internal base address of video memory */
1950 if (bi->init_sr07)
1951 vga_wseq(cinfo->regbase, CL_SEQR7, bi->sr07);
1953 /* vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */
1954 /* EEPROM control: shouldn't be necessary to write to this at all.. */
1956 /* graphics cursor X position (incomplete; position gives rem. 3 bits */
1957 vga_wseq(cinfo->regbase, CL_SEQR10, 0x00);
1958 /* graphics cursor Y position (..."... ) */
1959 vga_wseq(cinfo->regbase, CL_SEQR11, 0x00);
1960 /* graphics cursor attributes */
1961 vga_wseq(cinfo->regbase, CL_SEQR12, 0x00);
1962 /* graphics cursor pattern address */
1963 vga_wseq(cinfo->regbase, CL_SEQR13, 0x00);
1965 /* writing these on a P4 might give problems.. */
1966 if (cinfo->btype != BT_PICASSO4) {
1967 /* configuration readback and ext. color */
1968 vga_wseq(cinfo->regbase, CL_SEQR17, 0x00);
1969 /* signature generator */
1970 vga_wseq(cinfo->regbase, CL_SEQR18, 0x02);
1973 /* MCLK select etc. */
1974 if (bi->init_sr1f)
1975 vga_wseq(cinfo->regbase, CL_SEQR1F, bi->sr1f);
1977 /* Screen A preset row scan: none */
1978 vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00);
1979 /* Text cursor start: disable text cursor */
1980 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20);
1981 /* Text cursor end: - */
1982 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00);
1983 /* Screen start address high: 0 */
1984 vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, 0x00);
1985 /* Screen start address low: 0 */
1986 vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, 0x00);
1987 /* text cursor location high: 0 */
1988 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00);
1989 /* text cursor location low: 0 */
1990 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00);
1992 /* Underline Row scanline: - */
1993 vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00);
1994 /* mode control: timing enable, byte mode, no compat modes */
1995 vga_wcrt(cinfo->regbase, VGA_CRTC_MODE, 0xc3);
1996 /* Line Compare: not needed */
1997 vga_wcrt(cinfo->regbase, VGA_CRTC_LINE_COMPARE, 0x00);
1998 /* ### add 0x40 for text modes with > 30 MHz pixclock */
1999 /* ext. display controls: ext.adr. wrap */
2000 vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02);
2002 /* Set/Reset registes: - */
2003 vga_wgfx(cinfo->regbase, VGA_GFX_SR_VALUE, 0x00);
2004 /* Set/Reset enable: - */
2005 vga_wgfx(cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00);
2006 /* Color Compare: - */
2007 vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00);
2008 /* Data Rotate: - */
2009 vga_wgfx(cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00);
2010 /* Read Map Select: - */
2011 vga_wgfx(cinfo->regbase, VGA_GFX_PLANE_READ, 0x00);
2012 /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
2013 vga_wgfx(cinfo->regbase, VGA_GFX_MODE, 0x00);
2014 /* Miscellaneous: memory map base address, graphics mode */
2015 vga_wgfx(cinfo->regbase, VGA_GFX_MISC, 0x01);
2016 /* Color Don't care: involve all planes */
2017 vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f);
2018 /* Bit Mask: no mask at all */
2019 vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff);
2020 if (cinfo->btype == BT_ALPINE)
2021 /* (5434 can't have bit 3 set for bitblt) */
2022 vga_wgfx(cinfo->regbase, CL_GRB, 0x20);
2023 else
2024 /* Graphics controller mode extensions: finer granularity,
2025 * 8byte data latches
2027 vga_wgfx(cinfo->regbase, CL_GRB, 0x28);
2029 vga_wgfx(cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */
2030 vga_wgfx(cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */
2031 vga_wgfx(cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */
2032 /* Background color byte 1: - */
2033 /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); */
2034 /* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
2036 /* Attribute Controller palette registers: "identity mapping" */
2037 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE0, 0x00);
2038 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
2039 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
2040 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
2041 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
2042 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
2043 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
2044 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
2045 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
2046 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
2047 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
2048 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
2049 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
2050 vga_wattr(cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
2051 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
2052 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
2054 /* Attribute Controller mode: graphics mode */
2055 vga_wattr(cinfo->regbase, VGA_ATC_MODE, 0x01);
2056 /* Overscan color reg.: reg. 0 */
2057 vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00);
2058 /* Color Plane enable: Enable all 4 planes */
2059 vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f);
2060 /* ### vga_wattr(cinfo->regbase, CL_AR33, 0x00); * Pixel Panning: - */
2061 /* Color Select: - */
2062 vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00);
2064 WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
2066 if (cinfo->btype != BT_ALPINE && cinfo->btype != BT_GD5480)
2067 /* polarity (-/-), enable display mem,
2068 * VGA_CRTC_START_HI i/o base = color
2070 WGen(cinfo, VGA_MIS_W, 0xc3);
2072 /* BLT Start/status: Blitter reset */
2073 vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
2074 /* - " - : "end-of-reset" */
2075 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
2077 /* misc... */
2078 WHDR(cinfo, 0); /* Hidden DAC register: - */
2080 printk(KERN_DEBUG "cirrusfb: This board has %ld bytes of DRAM memory\n",
2081 info->screen_size);
2082 DPRINTK("EXIT\n");
2083 return;
2086 static void switch_monitor(struct cirrusfb_info *cinfo, int on)
2088 #ifdef CONFIG_ZORRO /* only works on Zorro boards */
2089 static int IsOn = 0; /* XXX not ok for multiple boards */
2091 DPRINTK("ENTER\n");
2093 if (cinfo->btype == BT_PICASSO4)
2094 return; /* nothing to switch */
2095 if (cinfo->btype == BT_ALPINE)
2096 return; /* nothing to switch */
2097 if (cinfo->btype == BT_GD5480)
2098 return; /* nothing to switch */
2099 if (cinfo->btype == BT_PICASSO) {
2100 if ((on && !IsOn) || (!on && IsOn))
2101 WSFR(cinfo, 0xff);
2103 DPRINTK("EXIT\n");
2104 return;
2106 if (on) {
2107 switch (cinfo->btype) {
2108 case BT_SD64:
2109 WSFR(cinfo, cinfo->SFR | 0x21);
2110 break;
2111 case BT_PICCOLO:
2112 WSFR(cinfo, cinfo->SFR | 0x28);
2113 break;
2114 case BT_SPECTRUM:
2115 WSFR(cinfo, 0x6f);
2116 break;
2117 default: /* do nothing */ break;
2119 } else {
2120 switch (cinfo->btype) {
2121 case BT_SD64:
2122 WSFR(cinfo, cinfo->SFR & 0xde);
2123 break;
2124 case BT_PICCOLO:
2125 WSFR(cinfo, cinfo->SFR & 0xd7);
2126 break;
2127 case BT_SPECTRUM:
2128 WSFR(cinfo, 0x4f);
2129 break;
2130 default: /* do nothing */ break;
2134 DPRINTK("EXIT\n");
2135 #endif /* CONFIG_ZORRO */
2138 /******************************************/
2139 /* Linux 2.6-style accelerated functions */
2140 /******************************************/
2142 static void cirrusfb_prim_fillrect(struct fb_info *info,
2143 const struct fb_fillrect *region)
2145 struct cirrusfb_info *cinfo = info->par;
2146 int m; /* bytes per pixel */
2147 u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
2148 cinfo->pseudo_palette[region->color] : region->color;
2150 if (info->var.bits_per_pixel == 1) {
2151 cirrusfb_RectFill(cinfo->regbase,
2152 info->var.bits_per_pixel,
2153 region->dx / 8, region->dy,
2154 region->width / 8, region->height,
2155 color,
2156 cinfo->currentmode.line_length);
2157 } else {
2158 m = (info->var.bits_per_pixel + 7) / 8;
2159 cirrusfb_RectFill(cinfo->regbase,
2160 info->var.bits_per_pixel,
2161 region->dx * m, region->dy,
2162 region->width * m, region->height,
2163 color,
2164 cinfo->currentmode.line_length);
2166 return;
2169 static void cirrusfb_fillrect(struct fb_info *info,
2170 const struct fb_fillrect *region)
2172 struct fb_fillrect modded;
2173 int vxres, vyres;
2175 if (info->state != FBINFO_STATE_RUNNING)
2176 return;
2177 if (info->flags & FBINFO_HWACCEL_DISABLED) {
2178 cfb_fillrect(info, region);
2179 return;
2182 vxres = info->var.xres_virtual;
2183 vyres = info->var.yres_virtual;
2185 memcpy(&modded, region, sizeof(struct fb_fillrect));
2187 if (!modded.width || !modded.height ||
2188 modded.dx >= vxres || modded.dy >= vyres)
2189 return;
2191 if (modded.dx + modded.width > vxres)
2192 modded.width = vxres - modded.dx;
2193 if (modded.dy + modded.height > vyres)
2194 modded.height = vyres - modded.dy;
2196 cirrusfb_prim_fillrect(info, &modded);
2199 static void cirrusfb_prim_copyarea(struct fb_info *info,
2200 const struct fb_copyarea *area)
2202 struct cirrusfb_info *cinfo = info->par;
2203 int m; /* bytes per pixel */
2205 if (info->var.bits_per_pixel == 1) {
2206 cirrusfb_BitBLT(cinfo->regbase, info->var.bits_per_pixel,
2207 area->sx / 8, area->sy,
2208 area->dx / 8, area->dy,
2209 area->width / 8, area->height,
2210 cinfo->currentmode.line_length);
2211 } else {
2212 m = (info->var.bits_per_pixel + 7) / 8;
2213 cirrusfb_BitBLT(cinfo->regbase, info->var.bits_per_pixel,
2214 area->sx * m, area->sy,
2215 area->dx * m, area->dy,
2216 area->width * m, area->height,
2217 cinfo->currentmode.line_length);
2219 return;
2222 static void cirrusfb_copyarea(struct fb_info *info,
2223 const struct fb_copyarea *area)
2225 struct fb_copyarea modded;
2226 u32 vxres, vyres;
2228 modded.sx = area->sx;
2229 modded.sy = area->sy;
2230 modded.dx = area->dx;
2231 modded.dy = area->dy;
2232 modded.width = area->width;
2233 modded.height = area->height;
2235 if (info->state != FBINFO_STATE_RUNNING)
2236 return;
2237 if (info->flags & FBINFO_HWACCEL_DISABLED) {
2238 cfb_copyarea(info, area);
2239 return;
2242 vxres = info->var.xres_virtual;
2243 vyres = info->var.yres_virtual;
2245 if (!modded.width || !modded.height ||
2246 modded.sx >= vxres || modded.sy >= vyres ||
2247 modded.dx >= vxres || modded.dy >= vyres)
2248 return;
2250 if (modded.sx + modded.width > vxres)
2251 modded.width = vxres - modded.sx;
2252 if (modded.dx + modded.width > vxres)
2253 modded.width = vxres - modded.dx;
2254 if (modded.sy + modded.height > vyres)
2255 modded.height = vyres - modded.sy;
2256 if (modded.dy + modded.height > vyres)
2257 modded.height = vyres - modded.dy;
2259 cirrusfb_prim_copyarea(info, &modded);
2262 static void cirrusfb_imageblit(struct fb_info *info,
2263 const struct fb_image *image)
2265 struct cirrusfb_info *cinfo = info->par;
2267 cirrusfb_WaitBLT(cinfo->regbase);
2268 cfb_imageblit(info, image);
2271 #ifdef CONFIG_PPC_PREP
2272 #define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
2273 #define PREP_IO_BASE ((volatile unsigned char *) 0x80000000)
2274 static void get_prep_addrs(unsigned long *display, unsigned long *registers)
2276 DPRINTK("ENTER\n");
2278 *display = PREP_VIDEO_BASE;
2279 *registers = (unsigned long) PREP_IO_BASE;
2281 DPRINTK("EXIT\n");
2284 #endif /* CONFIG_PPC_PREP */
2286 #ifdef CONFIG_PCI
2287 static int release_io_ports;
2289 /* Pulled the logic from XFree86 Cirrus driver to get the memory size,
2290 * based on the DRAM bandwidth bit and DRAM bank switching bit. This
2291 * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
2292 * seem to have. */
2293 static unsigned int cirrusfb_get_memsize(u8 __iomem *regbase)
2295 unsigned long mem;
2296 unsigned char SRF;
2298 DPRINTK("ENTER\n");
2300 SRF = vga_rseq(regbase, CL_SEQRF);
2301 switch ((SRF & 0x18)) {
2302 case 0x08:
2303 mem = 512 * 1024;
2304 break;
2305 case 0x10:
2306 mem = 1024 * 1024;
2307 break;
2308 /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory
2309 * on the 5430.
2311 case 0x18:
2312 mem = 2048 * 1024;
2313 break;
2314 default:
2315 printk(KERN_WARNING "CLgenfb: Unknown memory size!\n");
2316 mem = 1024 * 1024;
2318 if (SRF & 0x80)
2319 /* If DRAM bank switching is enabled, there must be twice as much
2320 * memory installed. (4MB on the 5434)
2322 mem *= 2;
2324 /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
2326 DPRINTK("EXIT\n");
2327 return mem;
2330 static void get_pci_addrs(const struct pci_dev *pdev,
2331 unsigned long *display, unsigned long *registers)
2333 assert(pdev != NULL);
2334 assert(display != NULL);
2335 assert(registers != NULL);
2337 DPRINTK("ENTER\n");
2339 *display = 0;
2340 *registers = 0;
2342 /* This is a best-guess for now */
2344 if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
2345 *display = pci_resource_start(pdev, 1);
2346 *registers = pci_resource_start(pdev, 0);
2347 } else {
2348 *display = pci_resource_start(pdev, 0);
2349 *registers = pci_resource_start(pdev, 1);
2352 assert(*display != 0);
2354 DPRINTK("EXIT\n");
2357 static void cirrusfb_pci_unmap(struct fb_info *info)
2359 struct cirrusfb_info *cinfo = info->par;
2360 struct pci_dev *pdev = cinfo->pdev;
2362 iounmap(info->screen_base);
2363 #if 0 /* if system didn't claim this region, we would... */
2364 release_mem_region(0xA0000, 65535);
2365 #endif
2366 if (release_io_ports)
2367 release_region(0x3C0, 32);
2368 pci_release_regions(pdev);
2369 framebuffer_release(info);
2371 #endif /* CONFIG_PCI */
2373 #ifdef CONFIG_ZORRO
2374 static void __devexit cirrusfb_zorro_unmap(struct cirrusfb_info *cinfo)
2376 zorro_release_device(cinfo->zdev);
2378 if (cinfo->btype == BT_PICASSO4) {
2379 cinfo->regbase -= 0x600000;
2380 iounmap((void *)cinfo->regbase);
2381 iounmap(info->screen_base);
2382 } else {
2383 if (zorro_resource_start(cinfo->zdev) > 0x01000000)
2384 iounmap(info->screen_base);
2386 framebuffer_release(cinfo->info);
2388 #endif /* CONFIG_ZORRO */
2390 static int cirrusfb_set_fbinfo(struct fb_info *info)
2392 struct cirrusfb_info *cinfo = info->par;
2393 struct fb_var_screeninfo *var = &info->var;
2395 info->pseudo_palette = cinfo->pseudo_palette;
2396 info->flags = FBINFO_DEFAULT
2397 | FBINFO_HWACCEL_XPAN
2398 | FBINFO_HWACCEL_YPAN
2399 | FBINFO_HWACCEL_FILLRECT
2400 | FBINFO_HWACCEL_COPYAREA;
2401 if (noaccel)
2402 info->flags |= FBINFO_HWACCEL_DISABLED;
2403 info->fbops = &cirrusfb_ops;
2404 if (cinfo->btype == BT_GD5480) {
2405 if (var->bits_per_pixel == 16)
2406 info->screen_base += 1 * MB_;
2407 if (var->bits_per_pixel == 24 || var->bits_per_pixel == 32)
2408 info->screen_base += 2 * MB_;
2411 /* Fill fix common fields */
2412 strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
2413 sizeof(info->fix.id));
2415 /* monochrome: only 1 memory plane */
2416 /* 8 bit and above: Use whole memory area */
2417 info->fix.smem_len = info->screen_size;
2418 if (var->bits_per_pixel == 1)
2419 info->fix.smem_len /= 4;
2420 info->fix.type = cinfo->currentmode.type;
2421 info->fix.type_aux = 0;
2422 info->fix.visual = cinfo->currentmode.visual;
2423 info->fix.xpanstep = 1;
2424 info->fix.ypanstep = 1;
2425 info->fix.ywrapstep = 0;
2426 info->fix.line_length = cinfo->currentmode.line_length;
2428 /* FIXME: map region at 0xB8000 if available, fill in here */
2429 info->fix.mmio_len = 0;
2430 info->fix.accel = FB_ACCEL_NONE;
2432 fb_alloc_cmap(&info->cmap, 256, 0);
2434 return 0;
2437 static int cirrusfb_register(struct fb_info *info)
2439 struct cirrusfb_info *cinfo = info->par;
2440 int err;
2441 enum cirrus_board btype;
2443 DPRINTK("ENTER\n");
2445 printk(KERN_INFO "cirrusfb: Driver for Cirrus Logic based "
2446 "graphic boards, v" CIRRUSFB_VERSION "\n");
2448 btype = cinfo->btype;
2450 /* sanity checks */
2451 assert(btype != BT_NONE);
2453 DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base);
2455 /* Make pretend we've set the var so our structures are in a "good" */
2456 /* state, even though we haven't written the mode to the hw yet... */
2457 info->var = cirrusfb_predefined[cirrusfb_def_mode].var;
2458 info->var.activate = FB_ACTIVATE_NOW;
2460 err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
2461 if (err < 0) {
2462 /* should never happen */
2463 DPRINTK("choking on default var... umm, no good.\n");
2464 goto err_unmap_cirrusfb;
2467 /* set all the vital stuff */
2468 cirrusfb_set_fbinfo(info);
2470 err = register_framebuffer(info);
2471 if (err < 0) {
2472 printk(KERN_ERR "cirrusfb: could not register "
2473 "fb device; err = %d!\n", err);
2474 goto err_dealloc_cmap;
2477 DPRINTK("EXIT, returning 0\n");
2478 return 0;
2480 err_dealloc_cmap:
2481 fb_dealloc_cmap(&info->cmap);
2482 err_unmap_cirrusfb:
2483 cinfo->unmap(info);
2484 return err;
2487 static void __devexit cirrusfb_cleanup(struct fb_info *info)
2489 struct cirrusfb_info *cinfo = info->par;
2490 DPRINTK("ENTER\n");
2492 switch_monitor(cinfo, 0);
2494 unregister_framebuffer(info);
2495 fb_dealloc_cmap(&info->cmap);
2496 printk("Framebuffer unregistered\n");
2497 cinfo->unmap(info);
2499 DPRINTK("EXIT\n");
2502 #ifdef CONFIG_PCI
2503 static int cirrusfb_pci_register(struct pci_dev *pdev,
2504 const struct pci_device_id *ent)
2506 struct cirrusfb_info *cinfo;
2507 struct fb_info *info;
2508 enum cirrus_board btype;
2509 unsigned long board_addr, board_size;
2510 int ret;
2512 ret = pci_enable_device(pdev);
2513 if (ret < 0) {
2514 printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
2515 goto err_out;
2518 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev);
2519 if (!info) {
2520 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2521 ret = -ENOMEM;
2522 goto err_disable;
2525 cinfo = info->par;
2526 cinfo->pdev = pdev;
2527 cinfo->btype = btype = (enum cirrus_board) ent->driver_data;
2529 DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n",
2530 pdev->resource[0].start, btype);
2531 DPRINTK(" base address 1 is 0x%x\n", pdev->resource[1].start);
2533 if (isPReP) {
2534 pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, 0x00000000);
2535 #ifdef CONFIG_PPC_PREP
2536 get_prep_addrs(&board_addr, &info->fix.mmio_start);
2537 #endif
2538 /* PReP dies if we ioremap the IO registers, but it works w/out... */
2539 cinfo->regbase = (char __iomem *) info->fix.mmio_start;
2540 } else {
2541 DPRINTK("Attempt to get PCI info for Cirrus Graphics Card\n");
2542 get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start);
2543 /* FIXME: this forces VGA. alternatives? */
2544 cinfo->regbase = NULL;
2547 DPRINTK("Board address: 0x%lx, register address: 0x%lx\n",
2548 board_addr, info->fix.mmio_start);
2550 board_size = (btype == BT_GD5480) ?
2551 32 * MB_ : cirrusfb_get_memsize(cinfo->regbase);
2553 ret = pci_request_regions(pdev, "cirrusfb");
2554 if (ret < 0) {
2555 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, "
2556 "abort\n",
2557 board_addr);
2558 goto err_release_fb;
2560 #if 0 /* if the system didn't claim this region, we would... */
2561 if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
2562 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n"
2564 0xA0000L);
2565 ret = -EBUSY;
2566 goto err_release_regions;
2568 #endif
2569 if (request_region(0x3C0, 32, "cirrusfb"))
2570 release_io_ports = 1;
2572 info->screen_base = ioremap(board_addr, board_size);
2573 if (!info->screen_base) {
2574 ret = -EIO;
2575 goto err_release_legacy;
2578 info->fix.smem_start = board_addr;
2579 info->screen_size = board_size;
2580 cinfo->unmap = cirrusfb_pci_unmap;
2582 printk(KERN_INFO " RAM (%lu kB) at 0xx%lx, ",
2583 info->screen_size / KB_, board_addr);
2584 printk(KERN_INFO "Cirrus Logic chipset on PCI bus\n");
2585 pci_set_drvdata(pdev, info);
2587 ret = cirrusfb_register(info);
2588 if (ret)
2589 iounmap(info->screen_base);
2590 return ret;
2592 err_release_legacy:
2593 if (release_io_ports)
2594 release_region(0x3C0, 32);
2595 #if 0
2596 release_mem_region(0xA0000, 65535);
2597 err_release_regions:
2598 #endif
2599 pci_release_regions(pdev);
2600 err_release_fb:
2601 framebuffer_release(info);
2602 err_disable:
2603 err_out:
2604 return ret;
2607 static void __devexit cirrusfb_pci_unregister(struct pci_dev *pdev)
2609 struct fb_info *info = pci_get_drvdata(pdev);
2610 DPRINTK("ENTER\n");
2612 cirrusfb_cleanup(info);
2614 DPRINTK("EXIT\n");
2617 static struct pci_driver cirrusfb_pci_driver = {
2618 .name = "cirrusfb",
2619 .id_table = cirrusfb_pci_table,
2620 .probe = cirrusfb_pci_register,
2621 .remove = __devexit_p(cirrusfb_pci_unregister),
2622 #ifdef CONFIG_PM
2623 #if 0
2624 .suspend = cirrusfb_pci_suspend,
2625 .resume = cirrusfb_pci_resume,
2626 #endif
2627 #endif
2629 #endif /* CONFIG_PCI */
2631 #ifdef CONFIG_ZORRO
2632 static int cirrusfb_zorro_register(struct zorro_dev *z,
2633 const struct zorro_device_id *ent)
2635 struct cirrusfb_info *cinfo;
2636 struct fb_info *info;
2637 enum cirrus_board btype;
2638 struct zorro_dev *z2 = NULL;
2639 unsigned long board_addr, board_size, size;
2640 int ret;
2642 btype = ent->driver_data;
2643 if (cirrusfb_zorro_table2[btype].id2)
2644 z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
2645 size = cirrusfb_zorro_table2[btype].size;
2646 printk(KERN_INFO "cirrusfb: %s board detected; ",
2647 cirrusfb_board_info[btype].name);
2649 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
2650 if (!info) {
2651 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2652 ret = -ENOMEM;
2653 goto err_out;
2656 cinfo = info->par;
2657 cinfo->info = info;
2658 cinfo->btype = btype;
2660 assert(z > 0);
2661 assert(z2 >= 0);
2662 assert(btype != BT_NONE);
2664 cinfo->zdev = z;
2665 board_addr = zorro_resource_start(z);
2666 board_size = zorro_resource_len(z);
2667 info->screen_size = size;
2669 if (!zorro_request_device(z, "cirrusfb")) {
2670 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, "
2671 "abort\n",
2672 board_addr);
2673 ret = -EBUSY;
2674 goto err_release_fb;
2677 printk(" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr);
2679 ret = -EIO;
2681 if (btype == BT_PICASSO4) {
2682 printk(KERN_INFO " REG at $%lx\n", board_addr + 0x600000);
2684 /* To be precise, for the P4 this is not the */
2685 /* begin of the board, but the begin of RAM. */
2686 /* for P4, map in its address space in 2 chunks (### TEST! ) */
2687 /* (note the ugly hardcoded 16M number) */
2688 cinfo->regbase = ioremap(board_addr, 16777216);
2689 if (!cinfo->regbase)
2690 goto err_release_region;
2692 DPRINTK("cirrusfb: Virtual address for board set to: $%p\n",
2693 cinfo->regbase);
2694 cinfo->regbase += 0x600000;
2695 info->fix.mmio_start = board_addr + 0x600000;
2697 info->fix.smem_start = board_addr + 16777216;
2698 info->screen_base = ioremap(info->fix.smem_start, 16777216);
2699 if (!info->screen_base)
2700 goto err_unmap_regbase;
2701 } else {
2702 printk(KERN_INFO " REG at $%lx\n",
2703 (unsigned long) z2->resource.start);
2705 info->fix.smem_start = board_addr;
2706 if (board_addr > 0x01000000)
2707 info->screen_base = ioremap(board_addr, board_size);
2708 else
2709 info->screen_base = (caddr_t) ZTWO_VADDR(board_addr);
2710 if (!info->screen_base)
2711 goto err_release_region;
2713 /* set address for REG area of board */
2714 cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start);
2715 info->fix.mmio_start = z2->resource.start;
2717 DPRINTK("cirrusfb: Virtual address for board set to: $%p\n",
2718 cinfo->regbase);
2720 cinfo->unmap = cirrusfb_zorro_unmap;
2722 printk(KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
2723 zorro_set_drvdata(z, info);
2725 ret = cirrusfb_register(cinfo);
2726 if (ret) {
2727 if (btype == BT_PICASSO4) {
2728 iounmap(info->screen_base);
2729 iounmap(cinfo->regbase - 0x600000);
2730 } else if (board_addr > 0x01000000)
2731 iounmap(info->screen_base);
2733 return ret;
2735 err_unmap_regbase:
2736 /* Parental advisory: explicit hack */
2737 iounmap(cinfo->regbase - 0x600000);
2738 err_release_region:
2739 release_region(board_addr, board_size);
2740 err_release_fb:
2741 framebuffer_release(info);
2742 err_out:
2743 return ret;
2746 void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
2748 struct fb_info *info = zorro_get_drvdata(z);
2749 DPRINTK("ENTER\n");
2751 cirrusfb_cleanup(info);
2753 DPRINTK("EXIT\n");
2756 static struct zorro_driver cirrusfb_zorro_driver = {
2757 .name = "cirrusfb",
2758 .id_table = cirrusfb_zorro_table,
2759 .probe = cirrusfb_zorro_register,
2760 .remove = __devexit_p(cirrusfb_zorro_unregister),
2762 #endif /* CONFIG_ZORRO */
2764 static int __init cirrusfb_init(void)
2766 int error = 0;
2768 #ifndef MODULE
2769 char *option = NULL;
2771 if (fb_get_options("cirrusfb", &option))
2772 return -ENODEV;
2773 cirrusfb_setup(option);
2774 #endif
2776 #ifdef CONFIG_ZORRO
2777 error |= zorro_register_driver(&cirrusfb_zorro_driver);
2778 #endif
2779 #ifdef CONFIG_PCI
2780 error |= pci_register_driver(&cirrusfb_pci_driver);
2781 #endif
2782 return error;
2785 #ifndef MODULE
2786 static int __init cirrusfb_setup(char *options) {
2787 char *this_opt, s[32];
2788 int i;
2790 DPRINTK("ENTER\n");
2792 if (!options || !*options)
2793 return 0;
2795 while ((this_opt = strsep(&options, ",")) != NULL) {
2796 if (!*this_opt) continue;
2798 DPRINTK("cirrusfb_setup: option '%s'\n", this_opt);
2800 for (i = 0; i < NUM_TOTAL_MODES; i++) {
2801 sprintf(s, "mode:%s", cirrusfb_predefined[i].name);
2802 if (strcmp(this_opt, s) == 0)
2803 cirrusfb_def_mode = i;
2805 if (!strcmp(this_opt, "noaccel"))
2806 noaccel = 1;
2808 return 0;
2810 #endif
2813 * Modularization
2816 MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
2817 MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
2818 MODULE_LICENSE("GPL");
2820 static void __exit cirrusfb_exit(void)
2822 #ifdef CONFIG_PCI
2823 pci_unregister_driver(&cirrusfb_pci_driver);
2824 #endif
2825 #ifdef CONFIG_ZORRO
2826 zorro_unregister_driver(&cirrusfb_zorro_driver);
2827 #endif
2830 module_init(cirrusfb_init);
2832 #ifdef MODULE
2833 module_exit(cirrusfb_exit);
2834 #endif
2836 /**********************************************************************/
2837 /* about the following functions - I have used the same names for the */
2838 /* functions as Markus Wild did in his Retina driver for NetBSD as */
2839 /* they just made sense for this purpose. Apart from that, I wrote */
2840 /* these functions myself. */
2841 /**********************************************************************/
2843 /*** WGen() - write into one of the external/general registers ***/
2844 static void WGen(const struct cirrusfb_info *cinfo,
2845 int regnum, unsigned char val)
2847 unsigned long regofs = 0;
2849 if (cinfo->btype == BT_PICASSO) {
2850 /* Picasso II specific hack */
2851 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2852 regnum == CL_VSSM2) */
2853 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2854 regofs = 0xfff;
2857 vga_w(cinfo->regbase, regofs + regnum, val);
2860 /*** RGen() - read out one of the external/general registers ***/
2861 static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum)
2863 unsigned long regofs = 0;
2865 if (cinfo->btype == BT_PICASSO) {
2866 /* Picasso II specific hack */
2867 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2868 regnum == CL_VSSM2) */
2869 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2870 regofs = 0xfff;
2873 return vga_r(cinfo->regbase, regofs + regnum);
2876 /*** AttrOn() - turn on VideoEnable for Attribute controller ***/
2877 static void AttrOn(const struct cirrusfb_info *cinfo)
2879 assert(cinfo != NULL);
2881 DPRINTK("ENTER\n");
2883 if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) {
2884 /* if we're just in "write value" mode, write back the */
2885 /* same value as before to not modify anything */
2886 vga_w(cinfo->regbase, VGA_ATT_IW,
2887 vga_r(cinfo->regbase, VGA_ATT_R));
2889 /* turn on video bit */
2890 /* vga_w(cinfo->regbase, VGA_ATT_IW, 0x20); */
2891 vga_w(cinfo->regbase, VGA_ATT_IW, 0x33);
2893 /* dummy write on Reg0 to be on "write index" mode next time */
2894 vga_w(cinfo->regbase, VGA_ATT_IW, 0x00);
2896 DPRINTK("EXIT\n");
2899 /*** WHDR() - write into the Hidden DAC register ***/
2900 /* as the HDR is the only extension register that requires special treatment
2901 * (the other extension registers are accessible just like the "ordinary"
2902 * registers of their functional group) here is a specialized routine for
2903 * accessing the HDR
2905 static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val)
2907 unsigned char dummy;
2909 if (cinfo->btype == BT_PICASSO) {
2910 /* Klaus' hint for correct access to HDR on some boards */
2911 /* first write 0 to pixel mask (3c6) */
2912 WGen(cinfo, VGA_PEL_MSK, 0x00);
2913 udelay(200);
2914 /* next read dummy from pixel address (3c8) */
2915 dummy = RGen(cinfo, VGA_PEL_IW);
2916 udelay(200);
2918 /* now do the usual stuff to access the HDR */
2920 dummy = RGen(cinfo, VGA_PEL_MSK);
2921 udelay(200);
2922 dummy = RGen(cinfo, VGA_PEL_MSK);
2923 udelay(200);
2924 dummy = RGen(cinfo, VGA_PEL_MSK);
2925 udelay(200);
2926 dummy = RGen(cinfo, VGA_PEL_MSK);
2927 udelay(200);
2929 WGen(cinfo, VGA_PEL_MSK, val);
2930 udelay(200);
2932 if (cinfo->btype == BT_PICASSO) {
2933 /* now first reset HDR access counter */
2934 dummy = RGen(cinfo, VGA_PEL_IW);
2935 udelay(200);
2937 /* and at the end, restore the mask value */
2938 /* ## is this mask always 0xff? */
2939 WGen(cinfo, VGA_PEL_MSK, 0xff);
2940 udelay(200);
2944 /*** WSFR() - write to the "special function register" (SFR) ***/
2945 static void WSFR(struct cirrusfb_info *cinfo, unsigned char val)
2947 #ifdef CONFIG_ZORRO
2948 assert(cinfo->regbase != NULL);
2949 cinfo->SFR = val;
2950 z_writeb(val, cinfo->regbase + 0x8000);
2951 #endif
2954 /* The Picasso has a second register for switching the monitor bit */
2955 static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val)
2957 #ifdef CONFIG_ZORRO
2958 /* writing an arbitrary value to this one causes the monitor switcher */
2959 /* to flip to Amiga display */
2960 assert(cinfo->regbase != NULL);
2961 cinfo->SFR = val;
2962 z_writeb(val, cinfo->regbase + 0x9000);
2963 #endif
2966 /*** WClut - set CLUT entry (range: 0..63) ***/
2967 static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
2968 unsigned char green, unsigned char blue)
2970 unsigned int data = VGA_PEL_D;
2972 /* address write mode register is not translated.. */
2973 vga_w(cinfo->regbase, VGA_PEL_IW, regnum);
2975 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2976 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2977 /* but DAC data register IS, at least for Picasso II */
2978 if (cinfo->btype == BT_PICASSO)
2979 data += 0xfff;
2980 vga_w(cinfo->regbase, data, red);
2981 vga_w(cinfo->regbase, data, green);
2982 vga_w(cinfo->regbase, data, blue);
2983 } else {
2984 vga_w(cinfo->regbase, data, blue);
2985 vga_w(cinfo->regbase, data, green);
2986 vga_w(cinfo->regbase, data, red);
2990 #if 0
2991 /*** RClut - read CLUT entry (range 0..63) ***/
2992 static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
2993 unsigned char *green, unsigned char *blue)
2995 unsigned int data = VGA_PEL_D;
2997 vga_w(cinfo->regbase, VGA_PEL_IR, regnum);
2999 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
3000 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
3001 if (cinfo->btype == BT_PICASSO)
3002 data += 0xfff;
3003 *red = vga_r(cinfo->regbase, data);
3004 *green = vga_r(cinfo->regbase, data);
3005 *blue = vga_r(cinfo->regbase, data);
3006 } else {
3007 *blue = vga_r(cinfo->regbase, data);
3008 *green = vga_r(cinfo->regbase, data);
3009 *red = vga_r(cinfo->regbase, data);
3012 #endif
3014 /*******************************************************************
3015 cirrusfb_WaitBLT()
3017 Wait for the BitBLT engine to complete a possible earlier job
3018 *********************************************************************/
3020 /* FIXME: use interrupts instead */
3021 static void cirrusfb_WaitBLT(u8 __iomem *regbase)
3023 /* now busy-wait until we're done */
3024 while (vga_rgfx(regbase, CL_GR31) & 0x08)
3025 /* do nothing */ ;
3028 /*******************************************************************
3029 cirrusfb_BitBLT()
3031 perform accelerated "scrolling"
3032 ********************************************************************/
3034 static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
3035 u_short curx, u_short cury,
3036 u_short destx, u_short desty,
3037 u_short width, u_short height,
3038 u_short line_length)
3040 u_short nwidth, nheight;
3041 u_long nsrc, ndest;
3042 u_char bltmode;
3044 DPRINTK("ENTER\n");
3046 nwidth = width - 1;
3047 nheight = height - 1;
3049 bltmode = 0x00;
3050 /* if source adr < dest addr, do the Blt backwards */
3051 if (cury <= desty) {
3052 if (cury == desty) {
3053 /* if src and dest are on the same line, check x */
3054 if (curx < destx)
3055 bltmode |= 0x01;
3056 } else
3057 bltmode |= 0x01;
3059 if (!bltmode) {
3060 /* standard case: forward blitting */
3061 nsrc = (cury * line_length) + curx;
3062 ndest = (desty * line_length) + destx;
3063 } else {
3064 /* this means start addresses are at the end,
3065 * counting backwards
3067 nsrc = cury * line_length + curx +
3068 nheight * line_length + nwidth;
3069 ndest = desty * line_length + destx +
3070 nheight * line_length + nwidth;
3074 run-down of registers to be programmed:
3075 destination pitch
3076 source pitch
3077 BLT width/height
3078 source start
3079 destination start
3080 BLT mode
3081 BLT ROP
3082 VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color"
3083 start/stop
3086 cirrusfb_WaitBLT(regbase);
3088 /* pitch: set to line_length */
3089 /* dest pitch low */
3090 vga_wgfx(regbase, CL_GR24, line_length & 0xff);
3091 /* dest pitch hi */
3092 vga_wgfx(regbase, CL_GR25, line_length >> 8);
3093 /* source pitch low */
3094 vga_wgfx(regbase, CL_GR26, line_length & 0xff);
3095 /* source pitch hi */
3096 vga_wgfx(regbase, CL_GR27, line_length >> 8);
3098 /* BLT width: actual number of pixels - 1 */
3099 /* BLT width low */
3100 vga_wgfx(regbase, CL_GR20, nwidth & 0xff);
3101 /* BLT width hi */
3102 vga_wgfx(regbase, CL_GR21, nwidth >> 8);
3104 /* BLT height: actual number of lines -1 */
3105 /* BLT height low */
3106 vga_wgfx(regbase, CL_GR22, nheight & 0xff);
3107 /* BLT width hi */
3108 vga_wgfx(regbase, CL_GR23, nheight >> 8);
3110 /* BLT destination */
3111 /* BLT dest low */
3112 vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
3113 /* BLT dest mid */
3114 vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
3115 /* BLT dest hi */
3116 vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
3118 /* BLT source */
3119 /* BLT src low */
3120 vga_wgfx(regbase, CL_GR2C, (u_char) (nsrc & 0xff));
3121 /* BLT src mid */
3122 vga_wgfx(regbase, CL_GR2D, (u_char) (nsrc >> 8));
3123 /* BLT src hi */
3124 vga_wgfx(regbase, CL_GR2E, (u_char) (nsrc >> 16));
3126 /* BLT mode */
3127 vga_wgfx(regbase, CL_GR30, bltmode); /* BLT mode */
3129 /* BLT ROP: SrcCopy */
3130 vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */
3132 /* and finally: GO! */
3133 vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */
3135 DPRINTK("EXIT\n");
3138 /*******************************************************************
3139 cirrusfb_RectFill()
3141 perform accelerated rectangle fill
3142 ********************************************************************/
3144 static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
3145 u_short x, u_short y, u_short width, u_short height,
3146 u_char color, u_short line_length)
3148 u_short nwidth, nheight;
3149 u_long ndest;
3150 u_char op;
3152 DPRINTK("ENTER\n");
3154 nwidth = width - 1;
3155 nheight = height - 1;
3157 ndest = (y * line_length) + x;
3159 cirrusfb_WaitBLT(regbase);
3161 /* pitch: set to line_length */
3162 vga_wgfx(regbase, CL_GR24, line_length & 0xff); /* dest pitch low */
3163 vga_wgfx(regbase, CL_GR25, line_length >> 8); /* dest pitch hi */
3164 vga_wgfx(regbase, CL_GR26, line_length & 0xff); /* source pitch low */
3165 vga_wgfx(regbase, CL_GR27, line_length >> 8); /* source pitch hi */
3167 /* BLT width: actual number of pixels - 1 */
3168 vga_wgfx(regbase, CL_GR20, nwidth & 0xff); /* BLT width low */
3169 vga_wgfx(regbase, CL_GR21, nwidth >> 8); /* BLT width hi */
3171 /* BLT height: actual number of lines -1 */
3172 vga_wgfx(regbase, CL_GR22, nheight & 0xff); /* BLT height low */
3173 vga_wgfx(regbase, CL_GR23, nheight >> 8); /* BLT width hi */
3175 /* BLT destination */
3176 /* BLT dest low */
3177 vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
3178 /* BLT dest mid */
3179 vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
3180 /* BLT dest hi */
3181 vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
3183 /* BLT source: set to 0 (is a dummy here anyway) */
3184 vga_wgfx(regbase, CL_GR2C, 0x00); /* BLT src low */
3185 vga_wgfx(regbase, CL_GR2D, 0x00); /* BLT src mid */
3186 vga_wgfx(regbase, CL_GR2E, 0x00); /* BLT src hi */
3188 /* This is a ColorExpand Blt, using the */
3189 /* same color for foreground and background */
3190 vga_wgfx(regbase, VGA_GFX_SR_VALUE, color); /* foreground color */
3191 vga_wgfx(regbase, VGA_GFX_SR_ENABLE, color); /* background color */
3193 op = 0xc0;
3194 if (bits_per_pixel == 16) {
3195 vga_wgfx(regbase, CL_GR10, color); /* foreground color */
3196 vga_wgfx(regbase, CL_GR11, color); /* background color */
3197 op = 0x50;
3198 op = 0xd0;
3199 } else if (bits_per_pixel == 32) {
3200 vga_wgfx(regbase, CL_GR10, color); /* foreground color */
3201 vga_wgfx(regbase, CL_GR11, color); /* background color */
3202 vga_wgfx(regbase, CL_GR12, color); /* foreground color */
3203 vga_wgfx(regbase, CL_GR13, color); /* background color */
3204 vga_wgfx(regbase, CL_GR14, 0); /* foreground color */
3205 vga_wgfx(regbase, CL_GR15, 0); /* background color */
3206 op = 0x50;
3207 op = 0xf0;
3209 /* BLT mode: color expand, Enable 8x8 copy (faster?) */
3210 vga_wgfx(regbase, CL_GR30, op); /* BLT mode */
3212 /* BLT ROP: SrcCopy */
3213 vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */
3215 /* and finally: GO! */
3216 vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */
3218 DPRINTK("EXIT\n");
3221 /**************************************************************************
3222 * bestclock() - determine closest possible clock lower(?) than the
3223 * desired pixel clock
3224 **************************************************************************/
3225 static void bestclock(long freq, long *best, long *nom,
3226 long *den, long *div, long maxfreq)
3228 long n, h, d, f;
3230 assert(best != NULL);
3231 assert(nom != NULL);
3232 assert(den != NULL);
3233 assert(div != NULL);
3234 assert(maxfreq > 0);
3236 *nom = 0;
3237 *den = 0;
3238 *div = 0;
3240 DPRINTK("ENTER\n");
3242 if (freq < 8000)
3243 freq = 8000;
3245 if (freq > maxfreq)
3246 freq = maxfreq;
3248 *best = 0;
3249 f = freq * 10;
3251 for (n = 32; n < 128; n++) {
3252 d = (143181 * n) / f;
3253 if ((d >= 7) && (d <= 63)) {
3254 if (d > 31)
3255 d = (d / 2) * 2;
3256 h = (14318 * n) / d;
3257 if (abs(h - freq) < abs(*best - freq)) {
3258 *best = h;
3259 *nom = n;
3260 if (d < 32) {
3261 *den = d;
3262 *div = 0;
3263 } else {
3264 *den = d / 2;
3265 *div = 1;
3269 d = ((143181 * n) + f - 1) / f;
3270 if ((d >= 7) && (d <= 63)) {
3271 if (d > 31)
3272 d = (d / 2) * 2;
3273 h = (14318 * n) / d;
3274 if (abs(h - freq) < abs(*best - freq)) {
3275 *best = h;
3276 *nom = n;
3277 if (d < 32) {
3278 *den = d;
3279 *div = 0;
3280 } else {
3281 *den = d / 2;
3282 *div = 1;
3288 DPRINTK("Best possible values for given frequency:\n");
3289 DPRINTK(" best: %ld kHz nom: %ld den: %ld div: %ld\n",
3290 freq, *nom, *den, *div);
3292 DPRINTK("EXIT\n");
3295 /* -------------------------------------------------------------------------
3297 * debugging functions
3299 * -------------------------------------------------------------------------
3302 #ifdef CIRRUSFB_DEBUG
3305 * cirrusfb_dbg_print_byte
3306 * @name: name associated with byte value to be displayed
3307 * @val: byte value to be displayed
3309 * DESCRIPTION:
3310 * Display an indented string, along with a hexidecimal byte value, and
3311 * its decoded bits. Bits 7 through 0 are listed in left-to-right
3312 * order.
3315 static
3316 void cirrusfb_dbg_print_byte(const char *name, unsigned char val)
3318 DPRINTK("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n",
3319 name, val,
3320 val & 0x80 ? '1' : '0',
3321 val & 0x40 ? '1' : '0',
3322 val & 0x20 ? '1' : '0',
3323 val & 0x10 ? '1' : '0',
3324 val & 0x08 ? '1' : '0',
3325 val & 0x04 ? '1' : '0',
3326 val & 0x02 ? '1' : '0',
3327 val & 0x01 ? '1' : '0');
3331 * cirrusfb_dbg_print_regs
3332 * @base: If using newmmio, the newmmio base address, otherwise %NULL
3333 * @reg_class: type of registers to read: %CRT, or %SEQ
3335 * DESCRIPTION:
3336 * Dumps the given list of VGA CRTC registers. If @base is %NULL,
3337 * old-style I/O ports are queried for information, otherwise MMIO is
3338 * used at the given @base address to query the information.
3341 static
3342 void cirrusfb_dbg_print_regs(caddr_t regbase,
3343 enum cirrusfb_dbg_reg_class reg_class, ...)
3345 va_list list;
3346 unsigned char val = 0;
3347 unsigned reg;
3348 char *name;
3350 va_start(list, reg_class);
3352 name = va_arg(list, char *);
3353 while (name != NULL) {
3354 reg = va_arg(list, int);
3356 switch (reg_class) {
3357 case CRT:
3358 val = vga_rcrt(regbase, (unsigned char) reg);
3359 break;
3360 case SEQ:
3361 val = vga_rseq(regbase, (unsigned char) reg);
3362 break;
3363 default:
3364 /* should never occur */
3365 assert(false);
3366 break;
3369 cirrusfb_dbg_print_byte(name, val);
3371 name = va_arg(list, char *);
3374 va_end(list);
3378 * cirrusfb_dump
3379 * @cirrusfbinfo:
3381 * DESCRIPTION:
3384 static void cirrusfb_dump(void)
3386 cirrusfb_dbg_reg_dump(NULL);
3390 * cirrusfb_dbg_reg_dump
3391 * @base: If using newmmio, the newmmio base address, otherwise %NULL
3393 * DESCRIPTION:
3394 * Dumps a list of interesting VGA and CIRRUSFB registers. If @base is %NULL,
3395 * old-style I/O ports are queried for information, otherwise MMIO is
3396 * used at the given @base address to query the information.
3399 static
3400 void cirrusfb_dbg_reg_dump(caddr_t regbase)
3402 DPRINTK("CIRRUSFB VGA CRTC register dump:\n");
3404 cirrusfb_dbg_print_regs(regbase, CRT,
3405 "CR00", 0x00,
3406 "CR01", 0x01,
3407 "CR02", 0x02,
3408 "CR03", 0x03,
3409 "CR04", 0x04,
3410 "CR05", 0x05,
3411 "CR06", 0x06,
3412 "CR07", 0x07,
3413 "CR08", 0x08,
3414 "CR09", 0x09,
3415 "CR0A", 0x0A,
3416 "CR0B", 0x0B,
3417 "CR0C", 0x0C,
3418 "CR0D", 0x0D,
3419 "CR0E", 0x0E,
3420 "CR0F", 0x0F,
3421 "CR10", 0x10,
3422 "CR11", 0x11,
3423 "CR12", 0x12,
3424 "CR13", 0x13,
3425 "CR14", 0x14,
3426 "CR15", 0x15,
3427 "CR16", 0x16,
3428 "CR17", 0x17,
3429 "CR18", 0x18,
3430 "CR22", 0x22,
3431 "CR24", 0x24,
3432 "CR26", 0x26,
3433 "CR2D", 0x2D,
3434 "CR2E", 0x2E,
3435 "CR2F", 0x2F,
3436 "CR30", 0x30,
3437 "CR31", 0x31,
3438 "CR32", 0x32,
3439 "CR33", 0x33,
3440 "CR34", 0x34,
3441 "CR35", 0x35,
3442 "CR36", 0x36,
3443 "CR37", 0x37,
3444 "CR38", 0x38,
3445 "CR39", 0x39,
3446 "CR3A", 0x3A,
3447 "CR3B", 0x3B,
3448 "CR3C", 0x3C,
3449 "CR3D", 0x3D,
3450 "CR3E", 0x3E,
3451 "CR3F", 0x3F,
3452 NULL);
3454 DPRINTK("\n");
3456 DPRINTK("CIRRUSFB VGA SEQ register dump:\n");
3458 cirrusfb_dbg_print_regs(regbase, SEQ,
3459 "SR00", 0x00,
3460 "SR01", 0x01,
3461 "SR02", 0x02,
3462 "SR03", 0x03,
3463 "SR04", 0x04,
3464 "SR08", 0x08,
3465 "SR09", 0x09,
3466 "SR0A", 0x0A,
3467 "SR0B", 0x0B,
3468 "SR0D", 0x0D,
3469 "SR10", 0x10,
3470 "SR11", 0x11,
3471 "SR12", 0x12,
3472 "SR13", 0x13,
3473 "SR14", 0x14,
3474 "SR15", 0x15,
3475 "SR16", 0x16,
3476 "SR17", 0x17,
3477 "SR18", 0x18,
3478 "SR19", 0x19,
3479 "SR1A", 0x1A,
3480 "SR1B", 0x1B,
3481 "SR1C", 0x1C,
3482 "SR1D", 0x1D,
3483 "SR1E", 0x1E,
3484 "SR1F", 0x1F,
3485 NULL);
3487 DPRINTK("\n");
3490 #endif /* CIRRUSFB_DEBUG */