cirrusfb: fix 16bpp modes
[linux-2.6/mini2440.git] / drivers / video / cirrusfb.c
blob9e0a1c58fde4425b6c8650b66d1b8ed1c0c846c0
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 <asm/pgtable.h>
50 #ifdef CONFIG_ZORRO
51 #include <linux/zorro.h>
52 #endif
53 #ifdef CONFIG_PCI
54 #include <linux/pci.h>
55 #endif
56 #ifdef CONFIG_AMIGA
57 #include <asm/amigahw.h>
58 #endif
59 #ifdef CONFIG_PPC_PREP
60 #include <asm/machdep.h>
61 #define isPReP machine_is(prep)
62 #else
63 #define isPReP 0
64 #endif
66 #include <video/vga.h>
67 #include <video/cirrus.h>
69 /*****************************************************************
71 * debugging and utility macros
75 /* enable debug output? */
76 /* #define CIRRUSFB_DEBUG 1 */
78 /* disable runtime assertions? */
79 /* #define CIRRUSFB_NDEBUG */
81 /* debug output */
82 #ifdef CIRRUSFB_DEBUG
83 #define DPRINTK(fmt, args...) \
84 printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
85 #else
86 #define DPRINTK(fmt, args...)
87 #endif
89 /* debugging assertions */
90 #ifndef CIRRUSFB_NDEBUG
91 #define assert(expr) \
92 if (!(expr)) { \
93 printk("Assertion failed! %s,%s,%s,line=%d\n", \
94 #expr, __FILE__, __func__, __LINE__); \
96 #else
97 #define assert(expr)
98 #endif
100 #define MB_ (1024 * 1024)
102 /*****************************************************************
104 * chipset information
108 /* board types */
109 enum cirrus_board {
110 BT_NONE = 0,
111 BT_SD64,
112 BT_PICCOLO,
113 BT_PICASSO,
114 BT_SPECTRUM,
115 BT_PICASSO4, /* GD5446 */
116 BT_ALPINE, /* GD543x/4x */
117 BT_GD5480,
118 BT_LAGUNA, /* GD546x */
122 * per-board-type information, used for enumerating and abstracting
123 * chip-specific information
124 * NOTE: MUST be in the same order as enum cirrus_board in order to
125 * use direct indexing on this array
126 * NOTE: '__initdata' cannot be used as some of this info
127 * is required at runtime. Maybe separate into an init-only and
128 * a run-time table?
130 static const struct cirrusfb_board_info_rec {
131 char *name; /* ASCII name of chipset */
132 long maxclock[5]; /* maximum video clock */
133 /* for 1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */
134 bool init_sr07 : 1; /* init SR07 during init_vgachip() */
135 bool init_sr1f : 1; /* write SR1F during init_vgachip() */
136 /* construct bit 19 of screen start address */
137 bool scrn_start_bit19 : 1;
139 /* initial SR07 value, then for each mode */
140 unsigned char sr07;
141 unsigned char sr07_1bpp;
142 unsigned char sr07_1bpp_mux;
143 unsigned char sr07_8bpp;
144 unsigned char sr07_8bpp_mux;
146 unsigned char sr1f; /* SR1F VGA initial register value */
147 } cirrusfb_board_info[] = {
148 [BT_SD64] = {
149 .name = "CL SD64",
150 .maxclock = {
151 /* guess */
152 /* the SD64/P4 have a higher max. videoclock */
153 140000, 140000, 140000, 140000, 140000,
155 .init_sr07 = true,
156 .init_sr1f = true,
157 .scrn_start_bit19 = true,
158 .sr07 = 0xF0,
159 .sr07_1bpp = 0xF0,
160 .sr07_8bpp = 0xF1,
161 .sr1f = 0x20
163 [BT_PICCOLO] = {
164 .name = "CL Piccolo",
165 .maxclock = {
166 /* guess */
167 90000, 90000, 90000, 90000, 90000
169 .init_sr07 = true,
170 .init_sr1f = true,
171 .scrn_start_bit19 = false,
172 .sr07 = 0x80,
173 .sr07_1bpp = 0x80,
174 .sr07_8bpp = 0x81,
175 .sr1f = 0x22
177 [BT_PICASSO] = {
178 .name = "CL Picasso",
179 .maxclock = {
180 /* guess */
181 90000, 90000, 90000, 90000, 90000
183 .init_sr07 = true,
184 .init_sr1f = true,
185 .scrn_start_bit19 = false,
186 .sr07 = 0x20,
187 .sr07_1bpp = 0x20,
188 .sr07_8bpp = 0x21,
189 .sr1f = 0x22
191 [BT_SPECTRUM] = {
192 .name = "CL Spectrum",
193 .maxclock = {
194 /* guess */
195 90000, 90000, 90000, 90000, 90000
197 .init_sr07 = true,
198 .init_sr1f = true,
199 .scrn_start_bit19 = false,
200 .sr07 = 0x80,
201 .sr07_1bpp = 0x80,
202 .sr07_8bpp = 0x81,
203 .sr1f = 0x22
205 [BT_PICASSO4] = {
206 .name = "CL Picasso4",
207 .maxclock = {
208 135100, 135100, 85500, 85500, 0
210 .init_sr07 = true,
211 .init_sr1f = false,
212 .scrn_start_bit19 = true,
213 .sr07 = 0x20,
214 .sr07_1bpp = 0x20,
215 .sr07_8bpp = 0x21,
216 .sr1f = 0
218 [BT_ALPINE] = {
219 .name = "CL Alpine",
220 .maxclock = {
221 /* for the GD5430. GD5446 can do more... */
222 85500, 85500, 50000, 28500, 0
224 .init_sr07 = true,
225 .init_sr1f = true,
226 .scrn_start_bit19 = true,
227 .sr07 = 0xA0,
228 .sr07_1bpp = 0xA1,
229 .sr07_1bpp_mux = 0xA7,
230 .sr07_8bpp = 0xA1,
231 .sr07_8bpp_mux = 0xA7,
232 .sr1f = 0x1C
234 [BT_GD5480] = {
235 .name = "CL GD5480",
236 .maxclock = {
237 135100, 200000, 200000, 135100, 135100
239 .init_sr07 = true,
240 .init_sr1f = true,
241 .scrn_start_bit19 = true,
242 .sr07 = 0x10,
243 .sr07_1bpp = 0x11,
244 .sr07_8bpp = 0x11,
245 .sr1f = 0x1C
247 [BT_LAGUNA] = {
248 .name = "CL Laguna",
249 .maxclock = {
250 /* guess */
251 135100, 135100, 135100, 135100, 135100,
253 .init_sr07 = false,
254 .init_sr1f = false,
255 .scrn_start_bit19 = true,
259 #ifdef CONFIG_PCI
260 #define CHIP(id, btype) \
261 { PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
263 static struct pci_device_id cirrusfb_pci_table[] = {
264 CHIP(PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE),
265 CHIP(PCI_DEVICE_ID_CIRRUS_5434_8, BT_ALPINE),
266 CHIP(PCI_DEVICE_ID_CIRRUS_5434_4, BT_ALPINE),
267 CHIP(PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE), /* GD-5440 is same id */
268 CHIP(PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE),
269 CHIP(PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE),
270 CHIP(PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480), /* MacPicasso likely */
271 CHIP(PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4), /* Picasso 4 is 5446 */
272 CHIP(PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA), /* CL Laguna */
273 CHIP(PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA), /* CL Laguna 3D */
274 CHIP(PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNA), /* CL Laguna 3DA*/
275 { 0, }
277 MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
278 #undef CHIP
279 #endif /* CONFIG_PCI */
281 #ifdef CONFIG_ZORRO
282 static const struct zorro_device_id cirrusfb_zorro_table[] = {
284 .id = ZORRO_PROD_HELFRICH_SD64_RAM,
285 .driver_data = BT_SD64,
286 }, {
287 .id = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
288 .driver_data = BT_PICCOLO,
289 }, {
290 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
291 .driver_data = BT_PICASSO,
292 }, {
293 .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
294 .driver_data = BT_SPECTRUM,
295 }, {
296 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
297 .driver_data = BT_PICASSO4,
299 { 0 }
302 static const struct {
303 zorro_id id2;
304 unsigned long size;
305 } cirrusfb_zorro_table2[] = {
306 [BT_SD64] = {
307 .id2 = ZORRO_PROD_HELFRICH_SD64_REG,
308 .size = 0x400000
310 [BT_PICCOLO] = {
311 .id2 = ZORRO_PROD_HELFRICH_PICCOLO_REG,
312 .size = 0x200000
314 [BT_PICASSO] = {
315 .id2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
316 .size = 0x200000
318 [BT_SPECTRUM] = {
319 .id2 = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
320 .size = 0x200000
322 [BT_PICASSO4] = {
323 .id2 = 0,
324 .size = 0x400000
327 #endif /* CONFIG_ZORRO */
329 struct cirrusfb_regs {
330 long multiplexing;
331 long mclk;
332 long divMCLK;
335 #ifdef CIRRUSFB_DEBUG
336 enum cirrusfb_dbg_reg_class {
337 CRT,
340 #endif /* CIRRUSFB_DEBUG */
342 /* info about board */
343 struct cirrusfb_info {
344 u8 __iomem *regbase;
345 enum cirrus_board btype;
346 unsigned char SFR; /* Shadow of special function register */
348 struct cirrusfb_regs currentmode;
349 int blank_mode;
350 u32 pseudo_palette[16];
352 void (*unmap)(struct fb_info *info);
355 static int noaccel __devinitdata;
356 static char *mode_option __devinitdata = "640x480@60";
358 /****************************************************************************/
359 /**** BEGIN PROTOTYPES ******************************************************/
361 /*--- Interface used by the world ------------------------------------------*/
362 static int cirrusfb_init(void);
363 #ifndef MODULE
364 static int cirrusfb_setup(char *options);
365 #endif
367 static int cirrusfb_open(struct fb_info *info, int user);
368 static int cirrusfb_release(struct fb_info *info, int user);
369 static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
370 unsigned blue, unsigned transp,
371 struct fb_info *info);
372 static int cirrusfb_check_var(struct fb_var_screeninfo *var,
373 struct fb_info *info);
374 static int cirrusfb_set_par(struct fb_info *info);
375 static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
376 struct fb_info *info);
377 static int cirrusfb_blank(int blank_mode, struct fb_info *info);
378 static void cirrusfb_fillrect(struct fb_info *info,
379 const struct fb_fillrect *region);
380 static void cirrusfb_copyarea(struct fb_info *info,
381 const struct fb_copyarea *area);
382 static void cirrusfb_imageblit(struct fb_info *info,
383 const struct fb_image *image);
385 /* function table of the above functions */
386 static struct fb_ops cirrusfb_ops = {
387 .owner = THIS_MODULE,
388 .fb_open = cirrusfb_open,
389 .fb_release = cirrusfb_release,
390 .fb_setcolreg = cirrusfb_setcolreg,
391 .fb_check_var = cirrusfb_check_var,
392 .fb_set_par = cirrusfb_set_par,
393 .fb_pan_display = cirrusfb_pan_display,
394 .fb_blank = cirrusfb_blank,
395 .fb_fillrect = cirrusfb_fillrect,
396 .fb_copyarea = cirrusfb_copyarea,
397 .fb_imageblit = cirrusfb_imageblit,
400 /*--- Internal routines ----------------------------------------------------*/
401 static void init_vgachip(struct fb_info *info);
402 static void switch_monitor(struct cirrusfb_info *cinfo, int on);
403 static void WGen(const struct cirrusfb_info *cinfo,
404 int regnum, unsigned char val);
405 static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum);
406 static void AttrOn(const struct cirrusfb_info *cinfo);
407 static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val);
408 static void WSFR(struct cirrusfb_info *cinfo, unsigned char val);
409 static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val);
410 static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum,
411 unsigned char red, unsigned char green, unsigned char blue);
412 #if 0
413 static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum,
414 unsigned char *red, unsigned char *green,
415 unsigned char *blue);
416 #endif
417 static void cirrusfb_WaitBLT(u8 __iomem *regbase);
418 static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
419 u_short curx, u_short cury,
420 u_short destx, u_short desty,
421 u_short width, u_short height,
422 u_short line_length);
423 static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
424 u_short x, u_short y,
425 u_short width, u_short height,
426 u_char color, u_short line_length);
428 static void bestclock(long freq, int *nom, int *den, int *div);
430 #ifdef CIRRUSFB_DEBUG
431 static void cirrusfb_dump(void);
432 static void cirrusfb_dbg_reg_dump(caddr_t regbase);
433 static void cirrusfb_dbg_print_regs(caddr_t regbase,
434 enum cirrusfb_dbg_reg_class reg_class, ...);
435 static void cirrusfb_dbg_print_byte(const char *name, unsigned char val);
436 #endif /* CIRRUSFB_DEBUG */
438 /*** END PROTOTYPES ********************************************************/
439 /*****************************************************************************/
440 /*** BEGIN Interface Used by the World ***************************************/
442 static int opencount;
444 /*--- Open /dev/fbx ---------------------------------------------------------*/
445 static int cirrusfb_open(struct fb_info *info, int user)
447 if (opencount++ == 0)
448 switch_monitor(info->par, 1);
449 return 0;
452 /*--- Close /dev/fbx --------------------------------------------------------*/
453 static int cirrusfb_release(struct fb_info *info, int user)
455 if (--opencount == 0)
456 switch_monitor(info->par, 0);
457 return 0;
460 /**** END Interface used by the World *************************************/
461 /****************************************************************************/
462 /**** BEGIN Hardware specific Routines **************************************/
464 /* Get a good MCLK value */
465 static long cirrusfb_get_mclk(long freq, int bpp, long *div)
467 long mclk;
469 assert(div != NULL);
471 /* Calculate MCLK, in case VCLK is high enough to require > 50MHz.
472 * Assume a 64-bit data path for now. The formula is:
473 * ((B * PCLK * 2)/W) * 1.2
474 * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */
475 mclk = ((bpp / 8) * freq * 2) / 4;
476 mclk = (mclk * 12) / 10;
477 if (mclk < 50000)
478 mclk = 50000;
479 DPRINTK("Use MCLK of %ld kHz\n", mclk);
481 /* Calculate value for SR1F. Multiply by 2 so we can round up. */
482 mclk = ((mclk * 16) / 14318);
483 mclk = (mclk + 1) / 2;
484 DPRINTK("Set SR1F[5:0] to 0x%lx\n", mclk);
486 /* Determine if we should use MCLK instead of VCLK, and if so, what we
487 * should divide it by to get VCLK */
488 switch (freq) {
489 case 24751 ... 25249:
490 *div = 2;
491 DPRINTK("Using VCLK = MCLK/2\n");
492 break;
493 case 49501 ... 50499:
494 *div = 1;
495 DPRINTK("Using VCLK = MCLK\n");
496 break;
497 default:
498 *div = 0;
499 break;
502 return mclk;
505 static int cirrusfb_check_var(struct fb_var_screeninfo *var,
506 struct fb_info *info)
508 int yres;
509 /* memory size in pixels */
510 unsigned pixels = info->screen_size * 8 / var->bits_per_pixel;
512 switch (var->bits_per_pixel) {
513 case 1:
514 pixels /= 4;
515 break; /* 8 pixel per byte, only 1/4th of mem usable */
516 case 8:
517 case 16:
518 case 32:
519 break; /* 1 pixel == 1 byte */
520 default:
521 printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..."
522 "color depth not supported.\n",
523 var->xres, var->yres, var->bits_per_pixel);
524 DPRINTK("EXIT - EINVAL error\n");
525 return -EINVAL;
528 if (var->xres_virtual < var->xres)
529 var->xres_virtual = var->xres;
530 /* use highest possible virtual resolution */
531 if (var->yres_virtual == -1) {
532 var->yres_virtual = pixels / var->xres_virtual;
534 printk(KERN_INFO "cirrusfb: virtual resolution set to "
535 "maximum of %dx%d\n", var->xres_virtual,
536 var->yres_virtual);
538 if (var->yres_virtual < var->yres)
539 var->yres_virtual = var->yres;
541 if (var->xres_virtual * var->yres_virtual > pixels) {
542 printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected... "
543 "virtual resolution too high to fit into video memory!\n",
544 var->xres_virtual, var->yres_virtual,
545 var->bits_per_pixel);
546 DPRINTK("EXIT - EINVAL error\n");
547 return -EINVAL;
551 if (var->xoffset < 0)
552 var->xoffset = 0;
553 if (var->yoffset < 0)
554 var->yoffset = 0;
556 /* truncate xoffset and yoffset to maximum if too high */
557 if (var->xoffset > var->xres_virtual - var->xres)
558 var->xoffset = var->xres_virtual - var->xres - 1;
559 if (var->yoffset > var->yres_virtual - var->yres)
560 var->yoffset = var->yres_virtual - var->yres - 1;
562 switch (var->bits_per_pixel) {
563 case 1:
564 var->red.offset = 0;
565 var->red.length = 1;
566 var->green = var->red;
567 var->blue = var->red;
568 break;
570 case 8:
571 var->red.offset = 0;
572 var->red.length = 6;
573 var->green = var->red;
574 var->blue = var->red;
575 break;
577 case 16:
578 if (isPReP) {
579 var->red.offset = 2;
580 var->green.offset = -3;
581 var->blue.offset = 8;
582 } else {
583 var->red.offset = 10;
584 var->green.offset = 5;
585 var->blue.offset = 0;
587 var->red.length = 5;
588 var->green.length = 5;
589 var->blue.length = 5;
590 break;
592 case 32:
593 if (isPReP) {
594 var->red.offset = 8;
595 var->green.offset = 16;
596 var->blue.offset = 24;
597 } else {
598 var->red.offset = 16;
599 var->green.offset = 8;
600 var->blue.offset = 0;
602 var->red.length = 8;
603 var->green.length = 8;
604 var->blue.length = 8;
605 break;
607 default:
608 DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);
609 assert(false);
610 /* should never occur */
611 break;
614 var->red.msb_right =
615 var->green.msb_right =
616 var->blue.msb_right =
617 var->transp.offset =
618 var->transp.length =
619 var->transp.msb_right = 0;
621 yres = var->yres;
622 if (var->vmode & FB_VMODE_DOUBLE)
623 yres *= 2;
624 else if (var->vmode & FB_VMODE_INTERLACED)
625 yres = (yres + 1) / 2;
627 if (yres >= 1280) {
628 printk(KERN_ERR "cirrusfb: ERROR: VerticalTotal >= 1280; "
629 "special treatment required! (TODO)\n");
630 DPRINTK("EXIT - EINVAL error\n");
631 return -EINVAL;
634 return 0;
637 static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
638 struct cirrusfb_regs *regs,
639 struct fb_info *info)
641 long freq;
642 long maxclock;
643 int maxclockidx = var->bits_per_pixel >> 3;
644 struct cirrusfb_info *cinfo = info->par;
646 switch (var->bits_per_pixel) {
647 case 1:
648 info->fix.line_length = var->xres_virtual / 8;
649 info->fix.visual = FB_VISUAL_MONO10;
650 break;
652 case 8:
653 info->fix.line_length = var->xres_virtual;
654 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
655 break;
657 case 16:
658 case 32:
659 info->fix.line_length = var->xres_virtual * maxclockidx;
660 info->fix.visual = FB_VISUAL_TRUECOLOR;
661 break;
663 default:
664 DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);
665 assert(false);
666 /* should never occur */
667 break;
670 info->fix.type = FB_TYPE_PACKED_PIXELS;
672 /* convert from ps to kHz */
673 freq = PICOS2KHZ(var->pixclock);
675 DPRINTK("desired pixclock: %ld kHz\n", freq);
677 maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
678 regs->multiplexing = 0;
680 /* If the frequency is greater than we can support, we might be able
681 * to use multiplexing for the video mode */
682 if (freq > maxclock) {
683 switch (cinfo->btype) {
684 case BT_ALPINE:
685 case BT_GD5480:
686 regs->multiplexing = 1;
687 break;
689 default:
690 printk(KERN_ERR "cirrusfb: Frequency greater "
691 "than maxclock (%ld kHz)\n", maxclock);
692 DPRINTK("EXIT - return -EINVAL\n");
693 return -EINVAL;
696 #if 0
697 /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
698 * the VCLK is double the pixel clock. */
699 switch (var->bits_per_pixel) {
700 case 16:
701 case 32:
702 if (var->xres <= 800)
703 /* Xbh has this type of clock for 32-bit */
704 freq /= 2;
705 break;
707 #endif
708 regs->mclk = cirrusfb_get_mclk(freq, var->bits_per_pixel,
709 &regs->divMCLK);
711 return 0;
714 static void cirrusfb_set_mclk(const struct cirrusfb_info *cinfo, int val,
715 int div)
717 assert(cinfo != NULL);
719 if (div == 2) {
720 /* VCLK = MCLK/2 */
721 unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E);
722 vga_wseq(cinfo->regbase, CL_SEQR1E, old | 0x1);
723 vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
724 } else if (div == 1) {
725 /* VCLK = MCLK */
726 unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E);
727 vga_wseq(cinfo->regbase, CL_SEQR1E, old & ~0x1);
728 vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
729 } else {
730 vga_wseq(cinfo->regbase, CL_SEQR1F, val & 0x3f);
734 /*************************************************************************
735 cirrusfb_set_par_foo()
737 actually writes the values for a new video mode into the hardware,
738 **************************************************************************/
739 static int cirrusfb_set_par_foo(struct fb_info *info)
741 struct cirrusfb_info *cinfo = info->par;
742 struct fb_var_screeninfo *var = &info->var;
743 struct cirrusfb_regs regs;
744 u8 __iomem *regbase = cinfo->regbase;
745 unsigned char tmp;
746 int offset = 0, err;
747 const struct cirrusfb_board_info_rec *bi;
748 int hdispend, hsyncstart, hsyncend, htotal;
749 int yres, vdispend, vsyncstart, vsyncend, vtotal;
750 long freq;
751 int nom, den, div;
753 DPRINTK("ENTER\n");
754 DPRINTK("Requested mode: %dx%dx%d\n",
755 var->xres, var->yres, var->bits_per_pixel);
756 DPRINTK("pixclock: %d\n", var->pixclock);
758 init_vgachip(info);
760 err = cirrusfb_decode_var(var, &regs, info);
761 if (err) {
762 /* should never happen */
763 DPRINTK("mode change aborted. invalid var.\n");
764 return -EINVAL;
767 bi = &cirrusfb_board_info[cinfo->btype];
769 hsyncstart = var->xres + var->right_margin;
770 hsyncend = hsyncstart + var->hsync_len;
771 htotal = (hsyncend + var->left_margin) / 8 - 5;
772 hdispend = var->xres / 8 - 1;
773 hsyncstart = hsyncstart / 8 + 1;
774 hsyncend = hsyncend / 8 + 1;
776 yres = var->yres;
777 vsyncstart = yres + var->lower_margin;
778 vsyncend = vsyncstart + var->vsync_len;
779 vtotal = vsyncend + var->upper_margin;
780 vdispend = yres - 1;
782 if (var->vmode & FB_VMODE_DOUBLE) {
783 yres *= 2;
784 vsyncstart *= 2;
785 vsyncend *= 2;
786 vtotal *= 2;
787 } else if (var->vmode & FB_VMODE_INTERLACED) {
788 yres = (yres + 1) / 2;
789 vsyncstart = (vsyncstart + 1) / 2;
790 vsyncend = (vsyncend + 1) / 2;
791 vtotal = (vtotal + 1) / 2;
794 vtotal -= 2;
795 vsyncstart -= 1;
796 vsyncend -= 1;
798 if (yres >= 1024) {
799 vtotal /= 2;
800 vsyncstart /= 2;
801 vsyncend /= 2;
802 vdispend /= 2;
804 if (regs.multiplexing) {
805 htotal /= 2;
806 hsyncstart /= 2;
807 hsyncend /= 2;
808 hdispend /= 2;
810 /* unlock register VGA_CRTC_H_TOTAL..CRT7 */
811 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */
813 /* if debugging is enabled, all parameters get output before writing */
814 DPRINTK("CRT0: %d\n", htotal);
815 vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal);
817 DPRINTK("CRT1: %d\n", hdispend);
818 vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend);
820 DPRINTK("CRT2: %d\n", var->xres / 8);
821 vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8);
823 /* + 128: Compatible read */
824 DPRINTK("CRT3: 128+%d\n", (htotal + 5) % 32);
825 vga_wcrt(regbase, VGA_CRTC_H_BLANK_END,
826 128 + ((htotal + 5) % 32));
828 DPRINTK("CRT4: %d\n", hsyncstart);
829 vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart);
831 tmp = hsyncend % 32;
832 if ((htotal + 5) & 32)
833 tmp += 128;
834 DPRINTK("CRT5: %d\n", tmp);
835 vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp);
837 DPRINTK("CRT6: %d\n", vtotal & 0xff);
838 vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff);
840 tmp = 16; /* LineCompare bit #9 */
841 if (vtotal & 256)
842 tmp |= 1;
843 if (vdispend & 256)
844 tmp |= 2;
845 if (vsyncstart & 256)
846 tmp |= 4;
847 if ((vdispend + 1) & 256)
848 tmp |= 8;
849 if (vtotal & 512)
850 tmp |= 32;
851 if (vdispend & 512)
852 tmp |= 64;
853 if (vsyncstart & 512)
854 tmp |= 128;
855 DPRINTK("CRT7: %d\n", tmp);
856 vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp);
858 tmp = 0x40; /* LineCompare bit #8 */
859 if ((vdispend + 1) & 512)
860 tmp |= 0x20;
861 if (var->vmode & FB_VMODE_DOUBLE)
862 tmp |= 0x80;
863 DPRINTK("CRT9: %d\n", tmp);
864 vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp);
866 DPRINTK("CRT10: %d\n", vsyncstart & 0xff);
867 vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff);
869 DPRINTK("CRT11: 64+32+%d\n", vsyncend % 16);
870 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32);
872 DPRINTK("CRT12: %d\n", vdispend & 0xff);
873 vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff);
875 DPRINTK("CRT15: %d\n", (vdispend + 1) & 0xff);
876 vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff);
878 DPRINTK("CRT16: %d\n", vtotal & 0xff);
879 vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff);
881 DPRINTK("CRT18: 0xff\n");
882 vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff);
884 tmp = 0;
885 if (var->vmode & FB_VMODE_INTERLACED)
886 tmp |= 1;
887 if ((htotal + 5) & 64)
888 tmp |= 16;
889 if ((htotal + 5) & 128)
890 tmp |= 32;
891 if (vtotal & 256)
892 tmp |= 64;
893 if (vtotal & 512)
894 tmp |= 128;
896 DPRINTK("CRT1a: %d\n", tmp);
897 vga_wcrt(regbase, CL_CRT1A, tmp);
899 freq = PICOS2KHZ(var->pixclock);
900 bestclock(freq, &nom, &den, &div);
902 /* set VCLK0 */
903 /* hardware RefClock: 14.31818 MHz */
904 /* formula: VClk = (OSC * N) / (D * (1+P)) */
905 /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
907 vga_wseq(regbase, CL_SEQRB, nom);
908 tmp = den << 1;
909 if (div != 0)
910 tmp |= 1;
912 /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
913 if ((cinfo->btype == BT_SD64) ||
914 (cinfo->btype == BT_ALPINE) ||
915 (cinfo->btype == BT_GD5480))
916 tmp |= 0x80;
918 DPRINTK("CL_SEQR1B: %ld\n", (long) tmp);
919 vga_wseq(regbase, CL_SEQR1B, tmp);
921 if (yres >= 1024)
922 /* 1280x1024 */
923 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7);
924 else
925 /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
926 * address wrap, no compat. */
927 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3);
929 /* HAEH? vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20);
930 * previously: 0x00 unlock VGA_CRTC_H_TOTAL..CRT7 */
932 /* don't know if it would hurt to also program this if no interlaced */
933 /* mode is used, but I feel better this way.. :-) */
934 if (var->vmode & FB_VMODE_INTERLACED)
935 vga_wcrt(regbase, VGA_CRTC_REGS, htotal / 2);
936 else
937 vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
939 vga_wseq(regbase, VGA_SEQ_CHARACTER_MAP, 0);
941 /* adjust horizontal/vertical sync type (low/high) */
942 /* enable display memory & CRTC I/O address for color mode */
943 tmp = 0x03;
944 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
945 tmp |= 0x40;
946 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
947 tmp |= 0x80;
948 WGen(cinfo, VGA_MIS_W, tmp);
950 /* Screen A Preset Row-Scan register */
951 vga_wcrt(regbase, VGA_CRTC_PRESET_ROW, 0);
952 /* text cursor on and start line */
953 vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0);
954 /* text cursor end line */
955 vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 31);
957 /******************************************************
959 * 1 bpp
963 /* programming for different color depths */
964 if (var->bits_per_pixel == 1) {
965 DPRINTK("cirrusfb: preparing for 1 bit deep display\n");
966 vga_wgfx(regbase, VGA_GFX_MODE, 0); /* mode register */
968 /* SR07 */
969 switch (cinfo->btype) {
970 case BT_SD64:
971 case BT_PICCOLO:
972 case BT_PICASSO:
973 case BT_SPECTRUM:
974 case BT_PICASSO4:
975 case BT_ALPINE:
976 case BT_GD5480:
977 DPRINTK(" (for GD54xx)\n");
978 vga_wseq(regbase, CL_SEQR7,
979 regs.multiplexing ?
980 bi->sr07_1bpp_mux : bi->sr07_1bpp);
981 break;
983 case BT_LAGUNA:
984 DPRINTK(" (for GD546x)\n");
985 vga_wseq(regbase, CL_SEQR7,
986 vga_rseq(regbase, CL_SEQR7) & ~0x01);
987 break;
989 default:
990 printk(KERN_WARNING "cirrusfb: unknown Board\n");
991 break;
994 /* Extended Sequencer Mode */
995 switch (cinfo->btype) {
996 case BT_SD64:
997 /* setting the SEQRF on SD64 is not necessary
998 * (only during init)
1000 DPRINTK("(for SD64)\n");
1001 /* MCLK select */
1002 vga_wseq(regbase, CL_SEQR1F, 0x1a);
1003 break;
1005 case BT_PICCOLO:
1006 case BT_SPECTRUM:
1007 DPRINTK("(for Piccolo/Spectrum)\n");
1008 /* ### ueberall 0x22? */
1009 /* ##vorher 1c MCLK select */
1010 vga_wseq(regbase, CL_SEQR1F, 0x22);
1011 /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
1012 vga_wseq(regbase, CL_SEQRF, 0xb0);
1013 break;
1015 case BT_PICASSO:
1016 DPRINTK("(for Picasso)\n");
1017 /* ##vorher 22 MCLK select */
1018 vga_wseq(regbase, CL_SEQR1F, 0x22);
1019 /* ## vorher d0 avoid FIFO underruns..? */
1020 vga_wseq(regbase, CL_SEQRF, 0xd0);
1021 break;
1023 case BT_PICASSO4:
1024 case BT_ALPINE:
1025 case BT_GD5480:
1026 case BT_LAGUNA:
1027 DPRINTK(" (for GD54xx)\n");
1028 /* do nothing */
1029 break;
1031 default:
1032 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1033 break;
1036 /* pixel mask: pass-through for first plane */
1037 WGen(cinfo, VGA_PEL_MSK, 0x01);
1038 if (regs.multiplexing)
1039 /* hidden dac reg: 1280x1024 */
1040 WHDR(cinfo, 0x4a);
1041 else
1042 /* hidden dac: nothing */
1043 WHDR(cinfo, 0);
1044 /* memory mode: odd/even, ext. memory */
1045 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06);
1046 /* plane mask: only write to first plane */
1047 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01);
1048 offset = var->xres_virtual / 16;
1051 /******************************************************
1053 * 8 bpp
1057 else if (var->bits_per_pixel == 8) {
1058 DPRINTK("cirrusfb: preparing for 8 bit deep display\n");
1059 switch (cinfo->btype) {
1060 case BT_SD64:
1061 case BT_PICCOLO:
1062 case BT_PICASSO:
1063 case BT_SPECTRUM:
1064 case BT_PICASSO4:
1065 case BT_ALPINE:
1066 case BT_GD5480:
1067 DPRINTK(" (for GD54xx)\n");
1068 vga_wseq(regbase, CL_SEQR7,
1069 regs.multiplexing ?
1070 bi->sr07_8bpp_mux : bi->sr07_8bpp);
1071 break;
1073 case BT_LAGUNA:
1074 DPRINTK(" (for GD546x)\n");
1075 vga_wseq(regbase, CL_SEQR7,
1076 vga_rseq(regbase, CL_SEQR7) | 0x01);
1077 break;
1079 default:
1080 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1081 break;
1084 switch (cinfo->btype) {
1085 case BT_SD64:
1086 /* MCLK select */
1087 vga_wseq(regbase, CL_SEQR1F, 0x1d);
1088 break;
1090 case BT_PICCOLO:
1091 case BT_PICASSO:
1092 case BT_SPECTRUM:
1093 /* ### vorher 1c MCLK select */
1094 vga_wseq(regbase, CL_SEQR1F, 0x22);
1095 /* Fast Page-Mode writes */
1096 vga_wseq(regbase, CL_SEQRF, 0xb0);
1097 break;
1099 case BT_PICASSO4:
1100 #ifdef CONFIG_ZORRO
1101 /* ### INCOMPLETE!! */
1102 vga_wseq(regbase, CL_SEQRF, 0xb8);
1103 #endif
1104 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1105 break;
1107 case BT_ALPINE:
1108 DPRINTK(" (for GD543x)\n");
1109 cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
1110 /* We already set SRF and SR1F */
1111 break;
1113 case BT_GD5480:
1114 case BT_LAGUNA:
1115 DPRINTK(" (for GD54xx)\n");
1116 /* do nothing */
1117 break;
1119 default:
1120 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1121 break;
1124 /* mode register: 256 color mode */
1125 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1126 /* pixel mask: pass-through all planes */
1127 WGen(cinfo, VGA_PEL_MSK, 0xff);
1128 if (regs.multiplexing)
1129 /* hidden dac reg: 1280x1024 */
1130 WHDR(cinfo, 0x4a);
1131 else
1132 /* hidden dac: nothing */
1133 WHDR(cinfo, 0);
1134 /* memory mode: chain4, ext. memory */
1135 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1136 /* plane mask: enable writing to all 4 planes */
1137 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1138 offset = var->xres_virtual / 8;
1141 /******************************************************
1143 * 16 bpp
1147 else if (var->bits_per_pixel == 16) {
1148 DPRINTK("cirrusfb: preparing for 16 bit deep display\n");
1149 switch (cinfo->btype) {
1150 case BT_SD64:
1151 /* Extended Sequencer Mode: 256c col. mode */
1152 vga_wseq(regbase, CL_SEQR7, 0xf7);
1153 /* MCLK select */
1154 vga_wseq(regbase, CL_SEQR1F, 0x1e);
1155 break;
1157 case BT_PICCOLO:
1158 case BT_SPECTRUM:
1159 vga_wseq(regbase, CL_SEQR7, 0x87);
1160 /* Fast Page-Mode writes */
1161 vga_wseq(regbase, CL_SEQRF, 0xb0);
1162 /* MCLK select */
1163 vga_wseq(regbase, CL_SEQR1F, 0x22);
1164 break;
1166 case BT_PICASSO:
1167 vga_wseq(regbase, CL_SEQR7, 0x27);
1168 /* Fast Page-Mode writes */
1169 vga_wseq(regbase, CL_SEQRF, 0xb0);
1170 /* MCLK select */
1171 vga_wseq(regbase, CL_SEQR1F, 0x22);
1172 break;
1174 case BT_PICASSO4:
1175 vga_wseq(regbase, CL_SEQR7, 0x27);
1176 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1177 break;
1179 case BT_ALPINE:
1180 DPRINTK(" (for GD543x)\n");
1181 vga_wseq(regbase, CL_SEQR7, 0xa7);
1182 cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
1183 break;
1185 case BT_GD5480:
1186 DPRINTK(" (for GD5480)\n");
1187 vga_wseq(regbase, CL_SEQR7, 0x17);
1188 /* We already set SRF and SR1F */
1189 break;
1191 case BT_LAGUNA:
1192 DPRINTK(" (for GD546x)\n");
1193 vga_wseq(regbase, CL_SEQR7,
1194 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1195 break;
1197 default:
1198 printk(KERN_WARNING "CIRRUSFB: unknown Board\n");
1199 break;
1202 /* mode register: 256 color mode */
1203 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1204 /* pixel mask: pass-through all planes */
1205 WGen(cinfo, VGA_PEL_MSK, 0xff);
1206 #ifdef CONFIG_PCI
1207 WHDR(cinfo, 0xc0); /* Copy Xbh */
1208 #elif defined(CONFIG_ZORRO)
1209 /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
1210 WHDR(cinfo, 0xa0); /* hidden dac reg: nothing special */
1211 #endif
1212 /* memory mode: chain4, ext. memory */
1213 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1214 /* plane mask: enable writing to all 4 planes */
1215 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1216 offset = var->xres_virtual / 4;
1219 /******************************************************
1221 * 32 bpp
1225 else if (var->bits_per_pixel == 32) {
1226 DPRINTK("cirrusfb: preparing for 32 bit deep display\n");
1227 switch (cinfo->btype) {
1228 case BT_SD64:
1229 /* Extended Sequencer Mode: 256c col. mode */
1230 vga_wseq(regbase, CL_SEQR7, 0xf9);
1231 /* MCLK select */
1232 vga_wseq(regbase, CL_SEQR1F, 0x1e);
1233 break;
1235 case BT_PICCOLO:
1236 case BT_SPECTRUM:
1237 vga_wseq(regbase, CL_SEQR7, 0x85);
1238 /* Fast Page-Mode writes */
1239 vga_wseq(regbase, CL_SEQRF, 0xb0);
1240 /* MCLK select */
1241 vga_wseq(regbase, CL_SEQR1F, 0x22);
1242 break;
1244 case BT_PICASSO:
1245 vga_wseq(regbase, CL_SEQR7, 0x25);
1246 /* Fast Page-Mode writes */
1247 vga_wseq(regbase, CL_SEQRF, 0xb0);
1248 /* MCLK select */
1249 vga_wseq(regbase, CL_SEQR1F, 0x22);
1250 break;
1252 case BT_PICASSO4:
1253 vga_wseq(regbase, CL_SEQR7, 0x25);
1254 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1255 break;
1257 case BT_ALPINE:
1258 DPRINTK(" (for GD543x)\n");
1259 vga_wseq(regbase, CL_SEQR7, 0xa9);
1260 cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
1261 break;
1263 case BT_GD5480:
1264 DPRINTK(" (for GD5480)\n");
1265 vga_wseq(regbase, CL_SEQR7, 0x19);
1266 /* We already set SRF and SR1F */
1267 break;
1269 case BT_LAGUNA:
1270 DPRINTK(" (for GD546x)\n");
1271 vga_wseq(regbase, CL_SEQR7,
1272 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1273 break;
1275 default:
1276 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1277 break;
1280 /* mode register: 256 color mode */
1281 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1282 /* pixel mask: pass-through all planes */
1283 WGen(cinfo, VGA_PEL_MSK, 0xff);
1284 /* hidden dac reg: 8-8-8 mode (24 or 32) */
1285 WHDR(cinfo, 0xc5);
1286 /* memory mode: chain4, ext. memory */
1287 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1288 /* plane mask: enable writing to all 4 planes */
1289 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1290 offset = var->xres_virtual / 4;
1293 /******************************************************
1295 * unknown/unsupported bpp
1299 else
1300 printk(KERN_ERR "cirrusfb: What's this?? "
1301 " requested color depth == %d.\n",
1302 var->bits_per_pixel);
1304 vga_wcrt(regbase, VGA_CRTC_OFFSET, offset & 0xff);
1305 tmp = 0x22;
1306 if (offset & 0x100)
1307 tmp |= 0x10; /* offset overflow bit */
1309 /* screen start addr #16-18, fastpagemode cycles */
1310 vga_wcrt(regbase, CL_CRT1B, tmp);
1312 if (cinfo->btype == BT_SD64 ||
1313 cinfo->btype == BT_PICASSO4 ||
1314 cinfo->btype == BT_ALPINE ||
1315 cinfo->btype == BT_GD5480)
1316 /* screen start address bit 19 */
1317 vga_wcrt(regbase, CL_CRT1D, 0x00);
1319 /* text cursor location high */
1320 vga_wcrt(regbase, VGA_CRTC_CURSOR_HI, 0);
1321 /* text cursor location low */
1322 vga_wcrt(regbase, VGA_CRTC_CURSOR_LO, 0);
1323 /* underline row scanline = at very bottom */
1324 vga_wcrt(regbase, VGA_CRTC_UNDERLINE, 0);
1326 /* controller mode */
1327 vga_wattr(regbase, VGA_ATC_MODE, 1);
1328 /* overscan (border) color */
1329 vga_wattr(regbase, VGA_ATC_OVERSCAN, 0);
1330 /* color plane enable */
1331 vga_wattr(regbase, VGA_ATC_PLANE_ENABLE, 15);
1332 /* pixel panning */
1333 vga_wattr(regbase, CL_AR33, 0);
1334 /* color select */
1335 vga_wattr(regbase, VGA_ATC_COLOR_PAGE, 0);
1337 /* [ EGS: SetOffset(); ] */
1338 /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
1339 AttrOn(cinfo);
1341 /* set/reset register */
1342 vga_wgfx(regbase, VGA_GFX_SR_VALUE, 0);
1343 /* set/reset enable */
1344 vga_wgfx(regbase, VGA_GFX_SR_ENABLE, 0);
1345 /* color compare */
1346 vga_wgfx(regbase, VGA_GFX_COMPARE_VALUE, 0);
1347 /* data rotate */
1348 vga_wgfx(regbase, VGA_GFX_DATA_ROTATE, 0);
1349 /* read map select */
1350 vga_wgfx(regbase, VGA_GFX_PLANE_READ, 0);
1351 /* miscellaneous register */
1352 vga_wgfx(regbase, VGA_GFX_MISC, 1);
1353 /* color don't care */
1354 vga_wgfx(regbase, VGA_GFX_COMPARE_MASK, 15);
1355 /* bit mask */
1356 vga_wgfx(regbase, VGA_GFX_BIT_MASK, 255);
1358 /* graphics cursor attributes: nothing special */
1359 vga_wseq(regbase, CL_SEQR12, 0x0);
1361 /* finally, turn on everything - turn off "FullBandwidth" bit */
1362 /* also, set "DotClock%2" bit where requested */
1363 tmp = 0x01;
1365 /*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
1366 if (var->vmode & FB_VMODE_CLOCK_HALVE)
1367 tmp |= 0x08;
1370 vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp);
1371 DPRINTK("CL_SEQR1: %d\n", tmp);
1373 cinfo->currentmode = regs;
1375 /* pan to requested offset */
1376 cirrusfb_pan_display(var, info);
1378 #ifdef CIRRUSFB_DEBUG
1379 cirrusfb_dump();
1380 #endif
1382 DPRINTK("EXIT\n");
1383 return 0;
1386 /* for some reason incomprehensible to me, cirrusfb requires that you write
1387 * the registers twice for the settings to take..grr. -dte */
1388 static int cirrusfb_set_par(struct fb_info *info)
1390 cirrusfb_set_par_foo(info);
1391 return cirrusfb_set_par_foo(info);
1394 static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1395 unsigned blue, unsigned transp,
1396 struct fb_info *info)
1398 struct cirrusfb_info *cinfo = info->par;
1400 if (regno > 255)
1401 return -EINVAL;
1403 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
1404 u32 v;
1405 red >>= (16 - info->var.red.length);
1406 green >>= (16 - info->var.green.length);
1407 blue >>= (16 - info->var.blue.length);
1409 if (regno >= 16)
1410 return 1;
1411 v = (red << info->var.red.offset) |
1412 (green << info->var.green.offset) |
1413 (blue << info->var.blue.offset);
1415 cinfo->pseudo_palette[regno] = v;
1416 return 0;
1419 if (info->var.bits_per_pixel == 8)
1420 WClut(cinfo, regno, red >> 10, green >> 10, blue >> 10);
1422 return 0;
1426 /*************************************************************************
1427 cirrusfb_pan_display()
1429 performs display panning - provided hardware permits this
1430 **************************************************************************/
1431 static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
1432 struct fb_info *info)
1434 int xoffset = 0;
1435 int yoffset = 0;
1436 unsigned long base;
1437 unsigned char tmp = 0, tmp2 = 0, xpix;
1438 struct cirrusfb_info *cinfo = info->par;
1440 DPRINTK("ENTER\n");
1441 DPRINTK("virtual offset: (%d,%d)\n", var->xoffset, var->yoffset);
1443 /* no range checks for xoffset and yoffset, */
1444 /* as fb_pan_display has already done this */
1445 if (var->vmode & FB_VMODE_YWRAP)
1446 return -EINVAL;
1448 info->var.xoffset = var->xoffset;
1449 info->var.yoffset = var->yoffset;
1451 xoffset = var->xoffset * info->var.bits_per_pixel / 8;
1452 yoffset = var->yoffset;
1454 base = yoffset * info->fix.line_length + xoffset;
1456 if (info->var.bits_per_pixel == 1) {
1457 /* base is already correct */
1458 xpix = (unsigned char) (var->xoffset % 8);
1459 } else {
1460 base /= 4;
1461 xpix = (unsigned char) ((xoffset % 4) * 2);
1464 cirrusfb_WaitBLT(cinfo->regbase); /* make sure all the BLT's are done */
1466 /* lower 8 + 8 bits of screen start address */
1467 vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO,
1468 (unsigned char) (base & 0xff));
1469 vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI,
1470 (unsigned char) (base >> 8));
1472 /* construct bits 16, 17 and 18 of screen start address */
1473 if (base & 0x10000)
1474 tmp |= 0x01;
1475 if (base & 0x20000)
1476 tmp |= 0x04;
1477 if (base & 0x40000)
1478 tmp |= 0x08;
1480 /* 0xf2 is %11110010, exclude tmp bits */
1481 tmp2 = (vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2) | tmp;
1482 vga_wcrt(cinfo->regbase, CL_CRT1B, tmp2);
1484 /* construct bit 19 of screen start address */
1485 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19)
1486 vga_wcrt(cinfo->regbase, CL_CRT1D, (base >> 12) & 0x80);
1488 /* write pixel panning value to AR33; this does not quite work in 8bpp
1490 * ### Piccolo..? Will this work?
1492 if (info->var.bits_per_pixel == 1)
1493 vga_wattr(cinfo->regbase, CL_AR33, xpix);
1495 cirrusfb_WaitBLT(cinfo->regbase);
1497 DPRINTK("EXIT\n");
1498 return 0;
1501 static int cirrusfb_blank(int blank_mode, struct fb_info *info)
1504 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
1505 * then the caller blanks by setting the CLUT (Color Look Up Table)
1506 * to all black. Return 0 if blanking succeeded, != 0 if un-/blanking
1507 * failed due to e.g. a video mode which doesn't support it.
1508 * Implements VESA suspend and powerdown modes on hardware that
1509 * supports disabling hsync/vsync:
1510 * blank_mode == 2: suspend vsync
1511 * blank_mode == 3: suspend hsync
1512 * blank_mode == 4: powerdown
1514 unsigned char val;
1515 struct cirrusfb_info *cinfo = info->par;
1516 int current_mode = cinfo->blank_mode;
1518 DPRINTK("ENTER, blank mode = %d\n", blank_mode);
1520 if (info->state != FBINFO_STATE_RUNNING ||
1521 current_mode == blank_mode) {
1522 DPRINTK("EXIT, returning 0\n");
1523 return 0;
1526 /* Undo current */
1527 if (current_mode == FB_BLANK_NORMAL ||
1528 current_mode == FB_BLANK_UNBLANK) {
1529 /* unblank the screen */
1530 val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1531 /* clear "FullBandwidth" bit */
1532 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val & 0xdf);
1533 /* and undo VESA suspend trickery */
1534 vga_wgfx(cinfo->regbase, CL_GRE, 0x00);
1537 /* set new */
1538 if (blank_mode > FB_BLANK_NORMAL) {
1539 /* blank the screen */
1540 val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1541 /* set "FullBandwidth" bit */
1542 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val | 0x20);
1545 switch (blank_mode) {
1546 case FB_BLANK_UNBLANK:
1547 case FB_BLANK_NORMAL:
1548 break;
1549 case FB_BLANK_VSYNC_SUSPEND:
1550 vga_wgfx(cinfo->regbase, CL_GRE, 0x04);
1551 break;
1552 case FB_BLANK_HSYNC_SUSPEND:
1553 vga_wgfx(cinfo->regbase, CL_GRE, 0x02);
1554 break;
1555 case FB_BLANK_POWERDOWN:
1556 vga_wgfx(cinfo->regbase, CL_GRE, 0x06);
1557 break;
1558 default:
1559 DPRINTK("EXIT, returning 1\n");
1560 return 1;
1563 cinfo->blank_mode = blank_mode;
1564 DPRINTK("EXIT, returning 0\n");
1566 /* Let fbcon do a soft blank for us */
1567 return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
1569 /**** END Hardware specific Routines **************************************/
1570 /****************************************************************************/
1571 /**** BEGIN Internal Routines ***********************************************/
1573 static void init_vgachip(struct fb_info *info)
1575 struct cirrusfb_info *cinfo = info->par;
1576 const struct cirrusfb_board_info_rec *bi;
1578 DPRINTK("ENTER\n");
1580 assert(cinfo != NULL);
1582 bi = &cirrusfb_board_info[cinfo->btype];
1584 /* reset board globally */
1585 switch (cinfo->btype) {
1586 case BT_PICCOLO:
1587 WSFR(cinfo, 0x01);
1588 udelay(500);
1589 WSFR(cinfo, 0x51);
1590 udelay(500);
1591 break;
1592 case BT_PICASSO:
1593 WSFR2(cinfo, 0xff);
1594 udelay(500);
1595 break;
1596 case BT_SD64:
1597 case BT_SPECTRUM:
1598 WSFR(cinfo, 0x1f);
1599 udelay(500);
1600 WSFR(cinfo, 0x4f);
1601 udelay(500);
1602 break;
1603 case BT_PICASSO4:
1604 /* disable flickerfixer */
1605 vga_wcrt(cinfo->regbase, CL_CRT51, 0x00);
1606 mdelay(100);
1607 /* from Klaus' NetBSD driver: */
1608 vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
1609 /* put blitter into 542x compat */
1610 vga_wgfx(cinfo->regbase, CL_GR33, 0x00);
1611 /* mode */
1612 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1613 break;
1615 case BT_GD5480:
1616 /* from Klaus' NetBSD driver: */
1617 vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
1618 break;
1620 case BT_ALPINE:
1621 /* Nothing to do to reset the board. */
1622 break;
1624 default:
1625 printk(KERN_ERR "cirrusfb: Warning: Unknown board type\n");
1626 break;
1629 /* make sure RAM size set by this point */
1630 assert(info->screen_size > 0);
1632 /* the P4 is not fully initialized here; I rely on it having been */
1633 /* inited under AmigaOS already, which seems to work just fine */
1634 /* (Klaus advised to do it this way) */
1636 if (cinfo->btype != BT_PICASSO4) {
1637 WGen(cinfo, CL_VSSM, 0x10); /* EGS: 0x16 */
1638 WGen(cinfo, CL_POS102, 0x01);
1639 WGen(cinfo, CL_VSSM, 0x08); /* EGS: 0x0e */
1641 if (cinfo->btype != BT_SD64)
1642 WGen(cinfo, CL_VSSM2, 0x01);
1644 /* reset sequencer logic */
1645 vga_wseq(cinfo->regbase, CL_SEQR0, 0x03);
1647 /* FullBandwidth (video off) and 8/9 dot clock */
1648 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21);
1649 /* polarity (-/-), disable access to display memory,
1650 * VGA_CRTC_START_HI base address: color
1652 WGen(cinfo, VGA_MIS_W, 0xc1);
1654 /* "magic cookie" - doesn't make any sense to me.. */
1655 /* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */
1656 /* unlock all extension registers */
1657 vga_wseq(cinfo->regbase, CL_SEQR6, 0x12);
1659 /* reset blitter */
1660 vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
1662 switch (cinfo->btype) {
1663 case BT_GD5480:
1664 vga_wseq(cinfo->regbase, CL_SEQRF, 0x98);
1665 break;
1666 case BT_ALPINE:
1667 break;
1668 case BT_SD64:
1669 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8);
1670 break;
1671 default:
1672 vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f);
1673 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb0);
1674 break;
1677 /* plane mask: nothing */
1678 vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1679 /* character map select: doesn't even matter in gx mode */
1680 vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00);
1681 /* memory mode: chain-4, no odd/even, ext. memory */
1682 vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0e);
1684 /* controller-internal base address of video memory */
1685 if (bi->init_sr07)
1686 vga_wseq(cinfo->regbase, CL_SEQR7, bi->sr07);
1688 /* vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */
1689 /* EEPROM control: shouldn't be necessary to write to this at all.. */
1691 /* graphics cursor X position (incomplete; position gives rem. 3 bits */
1692 vga_wseq(cinfo->regbase, CL_SEQR10, 0x00);
1693 /* graphics cursor Y position (..."... ) */
1694 vga_wseq(cinfo->regbase, CL_SEQR11, 0x00);
1695 /* graphics cursor attributes */
1696 vga_wseq(cinfo->regbase, CL_SEQR12, 0x00);
1697 /* graphics cursor pattern address */
1698 vga_wseq(cinfo->regbase, CL_SEQR13, 0x00);
1700 /* writing these on a P4 might give problems.. */
1701 if (cinfo->btype != BT_PICASSO4) {
1702 /* configuration readback and ext. color */
1703 vga_wseq(cinfo->regbase, CL_SEQR17, 0x00);
1704 /* signature generator */
1705 vga_wseq(cinfo->regbase, CL_SEQR18, 0x02);
1708 /* MCLK select etc. */
1709 if (bi->init_sr1f)
1710 vga_wseq(cinfo->regbase, CL_SEQR1F, bi->sr1f);
1712 /* Screen A preset row scan: none */
1713 vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00);
1714 /* Text cursor start: disable text cursor */
1715 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20);
1716 /* Text cursor end: - */
1717 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00);
1718 /* Screen start address high: 0 */
1719 vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, 0x00);
1720 /* Screen start address low: 0 */
1721 vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, 0x00);
1722 /* text cursor location high: 0 */
1723 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00);
1724 /* text cursor location low: 0 */
1725 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00);
1727 /* Underline Row scanline: - */
1728 vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00);
1729 /* mode control: timing enable, byte mode, no compat modes */
1730 vga_wcrt(cinfo->regbase, VGA_CRTC_MODE, 0xc3);
1731 /* Line Compare: not needed */
1732 vga_wcrt(cinfo->regbase, VGA_CRTC_LINE_COMPARE, 0x00);
1733 /* ### add 0x40 for text modes with > 30 MHz pixclock */
1734 /* ext. display controls: ext.adr. wrap */
1735 vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02);
1737 /* Set/Reset registes: - */
1738 vga_wgfx(cinfo->regbase, VGA_GFX_SR_VALUE, 0x00);
1739 /* Set/Reset enable: - */
1740 vga_wgfx(cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00);
1741 /* Color Compare: - */
1742 vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00);
1743 /* Data Rotate: - */
1744 vga_wgfx(cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00);
1745 /* Read Map Select: - */
1746 vga_wgfx(cinfo->regbase, VGA_GFX_PLANE_READ, 0x00);
1747 /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
1748 vga_wgfx(cinfo->regbase, VGA_GFX_MODE, 0x00);
1749 /* Miscellaneous: memory map base address, graphics mode */
1750 vga_wgfx(cinfo->regbase, VGA_GFX_MISC, 0x01);
1751 /* Color Don't care: involve all planes */
1752 vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f);
1753 /* Bit Mask: no mask at all */
1754 vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff);
1755 if (cinfo->btype == BT_ALPINE)
1756 /* (5434 can't have bit 3 set for bitblt) */
1757 vga_wgfx(cinfo->regbase, CL_GRB, 0x20);
1758 else
1759 /* Graphics controller mode extensions: finer granularity,
1760 * 8byte data latches
1762 vga_wgfx(cinfo->regbase, CL_GRB, 0x28);
1764 vga_wgfx(cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */
1765 vga_wgfx(cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */
1766 vga_wgfx(cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */
1767 /* Background color byte 1: - */
1768 /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); */
1769 /* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
1771 /* Attribute Controller palette registers: "identity mapping" */
1772 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE0, 0x00);
1773 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
1774 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
1775 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
1776 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
1777 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
1778 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
1779 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
1780 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
1781 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
1782 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
1783 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
1784 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
1785 vga_wattr(cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
1786 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
1787 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
1789 /* Attribute Controller mode: graphics mode */
1790 vga_wattr(cinfo->regbase, VGA_ATC_MODE, 0x01);
1791 /* Overscan color reg.: reg. 0 */
1792 vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00);
1793 /* Color Plane enable: Enable all 4 planes */
1794 vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f);
1795 /* ### vga_wattr(cinfo->regbase, CL_AR33, 0x00); * Pixel Panning: - */
1796 /* Color Select: - */
1797 vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00);
1799 WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
1801 if (cinfo->btype != BT_ALPINE && cinfo->btype != BT_GD5480)
1802 /* polarity (-/-), enable display mem,
1803 * VGA_CRTC_START_HI i/o base = color
1805 WGen(cinfo, VGA_MIS_W, 0xc3);
1807 /* BLT Start/status: Blitter reset */
1808 vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
1809 /* - " - : "end-of-reset" */
1810 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1812 /* misc... */
1813 WHDR(cinfo, 0); /* Hidden DAC register: - */
1815 DPRINTK("EXIT\n");
1816 return;
1819 static void switch_monitor(struct cirrusfb_info *cinfo, int on)
1821 #ifdef CONFIG_ZORRO /* only works on Zorro boards */
1822 static int IsOn = 0; /* XXX not ok for multiple boards */
1824 DPRINTK("ENTER\n");
1826 if (cinfo->btype == BT_PICASSO4)
1827 return; /* nothing to switch */
1828 if (cinfo->btype == BT_ALPINE)
1829 return; /* nothing to switch */
1830 if (cinfo->btype == BT_GD5480)
1831 return; /* nothing to switch */
1832 if (cinfo->btype == BT_PICASSO) {
1833 if ((on && !IsOn) || (!on && IsOn))
1834 WSFR(cinfo, 0xff);
1836 DPRINTK("EXIT\n");
1837 return;
1839 if (on) {
1840 switch (cinfo->btype) {
1841 case BT_SD64:
1842 WSFR(cinfo, cinfo->SFR | 0x21);
1843 break;
1844 case BT_PICCOLO:
1845 WSFR(cinfo, cinfo->SFR | 0x28);
1846 break;
1847 case BT_SPECTRUM:
1848 WSFR(cinfo, 0x6f);
1849 break;
1850 default: /* do nothing */ break;
1852 } else {
1853 switch (cinfo->btype) {
1854 case BT_SD64:
1855 WSFR(cinfo, cinfo->SFR & 0xde);
1856 break;
1857 case BT_PICCOLO:
1858 WSFR(cinfo, cinfo->SFR & 0xd7);
1859 break;
1860 case BT_SPECTRUM:
1861 WSFR(cinfo, 0x4f);
1862 break;
1863 default: /* do nothing */ break;
1867 DPRINTK("EXIT\n");
1868 #endif /* CONFIG_ZORRO */
1871 /******************************************/
1872 /* Linux 2.6-style accelerated functions */
1873 /******************************************/
1875 static void cirrusfb_fillrect(struct fb_info *info,
1876 const struct fb_fillrect *region)
1878 struct fb_fillrect modded;
1879 int vxres, vyres;
1880 struct cirrusfb_info *cinfo = info->par;
1881 int m = info->var.bits_per_pixel;
1882 u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
1883 cinfo->pseudo_palette[region->color] : region->color;
1885 if (info->state != FBINFO_STATE_RUNNING)
1886 return;
1887 if (info->flags & FBINFO_HWACCEL_DISABLED) {
1888 cfb_fillrect(info, region);
1889 return;
1892 vxres = info->var.xres_virtual;
1893 vyres = info->var.yres_virtual;
1895 memcpy(&modded, region, sizeof(struct fb_fillrect));
1897 if (!modded.width || !modded.height ||
1898 modded.dx >= vxres || modded.dy >= vyres)
1899 return;
1901 if (modded.dx + modded.width > vxres)
1902 modded.width = vxres - modded.dx;
1903 if (modded.dy + modded.height > vyres)
1904 modded.height = vyres - modded.dy;
1906 cirrusfb_RectFill(cinfo->regbase,
1907 info->var.bits_per_pixel,
1908 (region->dx * m) / 8, region->dy,
1909 (region->width * m) / 8, region->height,
1910 color,
1911 info->fix.line_length);
1914 static void cirrusfb_copyarea(struct fb_info *info,
1915 const struct fb_copyarea *area)
1917 struct fb_copyarea modded;
1918 u32 vxres, vyres;
1919 struct cirrusfb_info *cinfo = info->par;
1920 int m = info->var.bits_per_pixel;
1922 if (info->state != FBINFO_STATE_RUNNING)
1923 return;
1924 if (info->flags & FBINFO_HWACCEL_DISABLED) {
1925 cfb_copyarea(info, area);
1926 return;
1929 vxres = info->var.xres_virtual;
1930 vyres = info->var.yres_virtual;
1931 memcpy(&modded, area, sizeof(struct fb_copyarea));
1933 if (!modded.width || !modded.height ||
1934 modded.sx >= vxres || modded.sy >= vyres ||
1935 modded.dx >= vxres || modded.dy >= vyres)
1936 return;
1938 if (modded.sx + modded.width > vxres)
1939 modded.width = vxres - modded.sx;
1940 if (modded.dx + modded.width > vxres)
1941 modded.width = vxres - modded.dx;
1942 if (modded.sy + modded.height > vyres)
1943 modded.height = vyres - modded.sy;
1944 if (modded.dy + modded.height > vyres)
1945 modded.height = vyres - modded.dy;
1947 cirrusfb_BitBLT(cinfo->regbase, info->var.bits_per_pixel,
1948 (area->sx * m) / 8, area->sy,
1949 (area->dx * m) / 8, area->dy,
1950 (area->width * m) / 8, area->height,
1951 info->fix.line_length);
1955 static void cirrusfb_imageblit(struct fb_info *info,
1956 const struct fb_image *image)
1958 struct cirrusfb_info *cinfo = info->par;
1960 cirrusfb_WaitBLT(cinfo->regbase);
1961 cfb_imageblit(info, image);
1964 #ifdef CONFIG_PPC_PREP
1965 #define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
1966 #define PREP_IO_BASE ((volatile unsigned char *) 0x80000000)
1967 static void get_prep_addrs(unsigned long *display, unsigned long *registers)
1969 DPRINTK("ENTER\n");
1971 *display = PREP_VIDEO_BASE;
1972 *registers = (unsigned long) PREP_IO_BASE;
1974 DPRINTK("EXIT\n");
1977 #endif /* CONFIG_PPC_PREP */
1979 #ifdef CONFIG_PCI
1980 static int release_io_ports;
1982 /* Pulled the logic from XFree86 Cirrus driver to get the memory size,
1983 * based on the DRAM bandwidth bit and DRAM bank switching bit. This
1984 * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
1985 * seem to have. */
1986 static unsigned int __devinit cirrusfb_get_memsize(u8 __iomem *regbase)
1988 unsigned long mem;
1989 unsigned char SRF;
1991 DPRINTK("ENTER\n");
1993 SRF = vga_rseq(regbase, CL_SEQRF);
1994 switch ((SRF & 0x18)) {
1995 case 0x08:
1996 mem = 512 * 1024;
1997 break;
1998 case 0x10:
1999 mem = 1024 * 1024;
2000 break;
2001 /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory
2002 * on the 5430.
2004 case 0x18:
2005 mem = 2048 * 1024;
2006 break;
2007 default:
2008 printk(KERN_WARNING "CLgenfb: Unknown memory size!\n");
2009 mem = 1024 * 1024;
2011 if (SRF & 0x80)
2012 /* If DRAM bank switching is enabled, there must be twice as much
2013 * memory installed. (4MB on the 5434)
2015 mem *= 2;
2017 /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
2019 DPRINTK("EXIT\n");
2020 return mem;
2023 static void get_pci_addrs(const struct pci_dev *pdev,
2024 unsigned long *display, unsigned long *registers)
2026 assert(pdev != NULL);
2027 assert(display != NULL);
2028 assert(registers != NULL);
2030 DPRINTK("ENTER\n");
2032 *display = 0;
2033 *registers = 0;
2035 /* This is a best-guess for now */
2037 if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
2038 *display = pci_resource_start(pdev, 1);
2039 *registers = pci_resource_start(pdev, 0);
2040 } else {
2041 *display = pci_resource_start(pdev, 0);
2042 *registers = pci_resource_start(pdev, 1);
2045 assert(*display != 0);
2047 DPRINTK("EXIT\n");
2050 static void cirrusfb_pci_unmap(struct fb_info *info)
2052 struct pci_dev *pdev = to_pci_dev(info->device);
2054 iounmap(info->screen_base);
2055 #if 0 /* if system didn't claim this region, we would... */
2056 release_mem_region(0xA0000, 65535);
2057 #endif
2058 if (release_io_ports)
2059 release_region(0x3C0, 32);
2060 pci_release_regions(pdev);
2062 #endif /* CONFIG_PCI */
2064 #ifdef CONFIG_ZORRO
2065 static void __devexit cirrusfb_zorro_unmap(struct fb_info *info)
2067 struct cirrusfb_info *cinfo = info->par;
2068 struct zorro_dev *zdev = to_zorro_dev(info->device);
2070 zorro_release_device(zdev);
2072 if (cinfo->btype == BT_PICASSO4) {
2073 cinfo->regbase -= 0x600000;
2074 iounmap((void *)cinfo->regbase);
2075 iounmap(info->screen_base);
2076 } else {
2077 if (zorro_resource_start(zdev) > 0x01000000)
2078 iounmap(info->screen_base);
2081 #endif /* CONFIG_ZORRO */
2083 static int __devinit cirrusfb_set_fbinfo(struct fb_info *info)
2085 struct cirrusfb_info *cinfo = info->par;
2086 struct fb_var_screeninfo *var = &info->var;
2088 info->pseudo_palette = cinfo->pseudo_palette;
2089 info->flags = FBINFO_DEFAULT
2090 | FBINFO_HWACCEL_XPAN
2091 | FBINFO_HWACCEL_YPAN
2092 | FBINFO_HWACCEL_FILLRECT
2093 | FBINFO_HWACCEL_COPYAREA;
2094 if (noaccel)
2095 info->flags |= FBINFO_HWACCEL_DISABLED;
2096 info->fbops = &cirrusfb_ops;
2097 if (cinfo->btype == BT_GD5480) {
2098 if (var->bits_per_pixel == 16)
2099 info->screen_base += 1 * MB_;
2100 if (var->bits_per_pixel == 32)
2101 info->screen_base += 2 * MB_;
2104 /* Fill fix common fields */
2105 strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
2106 sizeof(info->fix.id));
2108 /* monochrome: only 1 memory plane */
2109 /* 8 bit and above: Use whole memory area */
2110 info->fix.smem_len = info->screen_size;
2111 if (var->bits_per_pixel == 1)
2112 info->fix.smem_len /= 4;
2113 info->fix.type_aux = 0;
2114 info->fix.xpanstep = 1;
2115 info->fix.ypanstep = 1;
2116 info->fix.ywrapstep = 0;
2118 /* FIXME: map region at 0xB8000 if available, fill in here */
2119 info->fix.mmio_len = 0;
2120 info->fix.accel = FB_ACCEL_NONE;
2122 fb_alloc_cmap(&info->cmap, 256, 0);
2124 return 0;
2127 static int __devinit cirrusfb_register(struct fb_info *info)
2129 struct cirrusfb_info *cinfo = info->par;
2130 int err;
2131 enum cirrus_board btype;
2133 DPRINTK("ENTER\n");
2135 printk(KERN_INFO "cirrusfb: Driver for Cirrus Logic based "
2136 "graphic boards, v" CIRRUSFB_VERSION "\n");
2138 btype = cinfo->btype;
2140 /* sanity checks */
2141 assert(btype != BT_NONE);
2143 /* set all the vital stuff */
2144 cirrusfb_set_fbinfo(info);
2146 DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base);
2148 err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
2149 if (!err) {
2150 DPRINTK("wrong initial video mode\n");
2151 err = -EINVAL;
2152 goto err_dealloc_cmap;
2155 info->var.activate = FB_ACTIVATE_NOW;
2157 err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
2158 if (err < 0) {
2159 /* should never happen */
2160 DPRINTK("choking on default var... umm, no good.\n");
2161 goto err_dealloc_cmap;
2164 err = register_framebuffer(info);
2165 if (err < 0) {
2166 printk(KERN_ERR "cirrusfb: could not register "
2167 "fb device; err = %d!\n", err);
2168 goto err_dealloc_cmap;
2171 DPRINTK("EXIT, returning 0\n");
2172 return 0;
2174 err_dealloc_cmap:
2175 fb_dealloc_cmap(&info->cmap);
2176 cinfo->unmap(info);
2177 framebuffer_release(info);
2178 return err;
2181 static void __devexit cirrusfb_cleanup(struct fb_info *info)
2183 struct cirrusfb_info *cinfo = info->par;
2184 DPRINTK("ENTER\n");
2186 switch_monitor(cinfo, 0);
2188 unregister_framebuffer(info);
2189 fb_dealloc_cmap(&info->cmap);
2190 printk("Framebuffer unregistered\n");
2191 cinfo->unmap(info);
2192 framebuffer_release(info);
2194 DPRINTK("EXIT\n");
2197 #ifdef CONFIG_PCI
2198 static int __devinit cirrusfb_pci_register(struct pci_dev *pdev,
2199 const struct pci_device_id *ent)
2201 struct cirrusfb_info *cinfo;
2202 struct fb_info *info;
2203 enum cirrus_board btype;
2204 unsigned long board_addr, board_size;
2205 int ret;
2207 ret = pci_enable_device(pdev);
2208 if (ret < 0) {
2209 printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
2210 goto err_out;
2213 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev);
2214 if (!info) {
2215 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2216 ret = -ENOMEM;
2217 goto err_disable;
2220 cinfo = info->par;
2221 cinfo->btype = btype = (enum cirrus_board) ent->driver_data;
2223 DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n",
2224 pdev->resource[0].start, btype);
2225 DPRINTK(" base address 1 is 0x%x\n", pdev->resource[1].start);
2227 if (isPReP) {
2228 pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, 0x00000000);
2229 #ifdef CONFIG_PPC_PREP
2230 get_prep_addrs(&board_addr, &info->fix.mmio_start);
2231 #endif
2232 /* PReP dies if we ioremap the IO registers, but it works w/out... */
2233 cinfo->regbase = (char __iomem *) info->fix.mmio_start;
2234 } else {
2235 DPRINTK("Attempt to get PCI info for Cirrus Graphics Card\n");
2236 get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start);
2237 /* FIXME: this forces VGA. alternatives? */
2238 cinfo->regbase = NULL;
2241 DPRINTK("Board address: 0x%lx, register address: 0x%lx\n",
2242 board_addr, info->fix.mmio_start);
2244 board_size = (btype == BT_GD5480) ?
2245 32 * MB_ : cirrusfb_get_memsize(cinfo->regbase);
2247 ret = pci_request_regions(pdev, "cirrusfb");
2248 if (ret < 0) {
2249 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, "
2250 "abort\n",
2251 board_addr);
2252 goto err_release_fb;
2254 #if 0 /* if the system didn't claim this region, we would... */
2255 if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
2256 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n"
2258 0xA0000L);
2259 ret = -EBUSY;
2260 goto err_release_regions;
2262 #endif
2263 if (request_region(0x3C0, 32, "cirrusfb"))
2264 release_io_ports = 1;
2266 info->screen_base = ioremap(board_addr, board_size);
2267 if (!info->screen_base) {
2268 ret = -EIO;
2269 goto err_release_legacy;
2272 info->fix.smem_start = board_addr;
2273 info->screen_size = board_size;
2274 cinfo->unmap = cirrusfb_pci_unmap;
2276 printk(KERN_INFO "RAM (%lu kB) at 0x%lx, Cirrus "
2277 "Logic chipset on PCI bus\n",
2278 info->screen_size >> 10, board_addr);
2279 pci_set_drvdata(pdev, info);
2281 ret = cirrusfb_register(info);
2282 if (ret)
2283 iounmap(info->screen_base);
2284 return ret;
2286 err_release_legacy:
2287 if (release_io_ports)
2288 release_region(0x3C0, 32);
2289 #if 0
2290 release_mem_region(0xA0000, 65535);
2291 err_release_regions:
2292 #endif
2293 pci_release_regions(pdev);
2294 err_release_fb:
2295 framebuffer_release(info);
2296 err_disable:
2297 err_out:
2298 return ret;
2301 static void __devexit cirrusfb_pci_unregister(struct pci_dev *pdev)
2303 struct fb_info *info = pci_get_drvdata(pdev);
2304 DPRINTK("ENTER\n");
2306 cirrusfb_cleanup(info);
2308 DPRINTK("EXIT\n");
2311 static struct pci_driver cirrusfb_pci_driver = {
2312 .name = "cirrusfb",
2313 .id_table = cirrusfb_pci_table,
2314 .probe = cirrusfb_pci_register,
2315 .remove = __devexit_p(cirrusfb_pci_unregister),
2316 #ifdef CONFIG_PM
2317 #if 0
2318 .suspend = cirrusfb_pci_suspend,
2319 .resume = cirrusfb_pci_resume,
2320 #endif
2321 #endif
2323 #endif /* CONFIG_PCI */
2325 #ifdef CONFIG_ZORRO
2326 static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
2327 const struct zorro_device_id *ent)
2329 struct cirrusfb_info *cinfo;
2330 struct fb_info *info;
2331 enum cirrus_board btype;
2332 struct zorro_dev *z2 = NULL;
2333 unsigned long board_addr, board_size, size;
2334 int ret;
2336 btype = ent->driver_data;
2337 if (cirrusfb_zorro_table2[btype].id2)
2338 z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
2339 size = cirrusfb_zorro_table2[btype].size;
2340 printk(KERN_INFO "cirrusfb: %s board detected; ",
2341 cirrusfb_board_info[btype].name);
2343 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
2344 if (!info) {
2345 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2346 ret = -ENOMEM;
2347 goto err_out;
2350 cinfo = info->par;
2351 cinfo->btype = btype;
2353 assert(z);
2354 assert(btype != BT_NONE);
2356 board_addr = zorro_resource_start(z);
2357 board_size = zorro_resource_len(z);
2358 info->screen_size = size;
2360 if (!zorro_request_device(z, "cirrusfb")) {
2361 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, "
2362 "abort\n",
2363 board_addr);
2364 ret = -EBUSY;
2365 goto err_release_fb;
2368 printk(" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr);
2370 ret = -EIO;
2372 if (btype == BT_PICASSO4) {
2373 printk(KERN_INFO " REG at $%lx\n", board_addr + 0x600000);
2375 /* To be precise, for the P4 this is not the */
2376 /* begin of the board, but the begin of RAM. */
2377 /* for P4, map in its address space in 2 chunks (### TEST! ) */
2378 /* (note the ugly hardcoded 16M number) */
2379 cinfo->regbase = ioremap(board_addr, 16777216);
2380 if (!cinfo->regbase)
2381 goto err_release_region;
2383 DPRINTK("cirrusfb: Virtual address for board set to: $%p\n",
2384 cinfo->regbase);
2385 cinfo->regbase += 0x600000;
2386 info->fix.mmio_start = board_addr + 0x600000;
2388 info->fix.smem_start = board_addr + 16777216;
2389 info->screen_base = ioremap(info->fix.smem_start, 16777216);
2390 if (!info->screen_base)
2391 goto err_unmap_regbase;
2392 } else {
2393 printk(KERN_INFO " REG at $%lx\n",
2394 (unsigned long) z2->resource.start);
2396 info->fix.smem_start = board_addr;
2397 if (board_addr > 0x01000000)
2398 info->screen_base = ioremap(board_addr, board_size);
2399 else
2400 info->screen_base = (caddr_t) ZTWO_VADDR(board_addr);
2401 if (!info->screen_base)
2402 goto err_release_region;
2404 /* set address for REG area of board */
2405 cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start);
2406 info->fix.mmio_start = z2->resource.start;
2408 DPRINTK("cirrusfb: Virtual address for board set to: $%p\n",
2409 cinfo->regbase);
2411 cinfo->unmap = cirrusfb_zorro_unmap;
2413 printk(KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
2414 zorro_set_drvdata(z, info);
2416 ret = cirrusfb_register(info);
2417 if (ret) {
2418 if (btype == BT_PICASSO4) {
2419 iounmap(info->screen_base);
2420 iounmap(cinfo->regbase - 0x600000);
2421 } else if (board_addr > 0x01000000)
2422 iounmap(info->screen_base);
2424 return ret;
2426 err_unmap_regbase:
2427 /* Parental advisory: explicit hack */
2428 iounmap(cinfo->regbase - 0x600000);
2429 err_release_region:
2430 release_region(board_addr, board_size);
2431 err_release_fb:
2432 framebuffer_release(info);
2433 err_out:
2434 return ret;
2437 void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
2439 struct fb_info *info = zorro_get_drvdata(z);
2440 DPRINTK("ENTER\n");
2442 cirrusfb_cleanup(info);
2444 DPRINTK("EXIT\n");
2447 static struct zorro_driver cirrusfb_zorro_driver = {
2448 .name = "cirrusfb",
2449 .id_table = cirrusfb_zorro_table,
2450 .probe = cirrusfb_zorro_register,
2451 .remove = __devexit_p(cirrusfb_zorro_unregister),
2453 #endif /* CONFIG_ZORRO */
2455 static int __init cirrusfb_init(void)
2457 int error = 0;
2459 #ifndef MODULE
2460 char *option = NULL;
2462 if (fb_get_options("cirrusfb", &option))
2463 return -ENODEV;
2464 cirrusfb_setup(option);
2465 #endif
2467 #ifdef CONFIG_ZORRO
2468 error |= zorro_register_driver(&cirrusfb_zorro_driver);
2469 #endif
2470 #ifdef CONFIG_PCI
2471 error |= pci_register_driver(&cirrusfb_pci_driver);
2472 #endif
2473 return error;
2476 #ifndef MODULE
2477 static int __init cirrusfb_setup(char *options) {
2478 char *this_opt, s[32];
2479 int i;
2481 DPRINTK("ENTER\n");
2483 if (!options || !*options)
2484 return 0;
2486 while ((this_opt = strsep(&options, ",")) != NULL) {
2487 if (!*this_opt)
2488 continue;
2490 DPRINTK("cirrusfb_setup: option '%s'\n", this_opt);
2492 if (!strcmp(this_opt, "noaccel"))
2493 noaccel = 1;
2494 else if (!strncmp(this_opt, "mode:", 5))
2495 mode_option = this_opt + 5;
2496 else
2497 mode_option = this_opt;
2499 return 0;
2501 #endif
2504 * Modularization
2507 MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
2508 MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
2509 MODULE_LICENSE("GPL");
2511 static void __exit cirrusfb_exit(void)
2513 #ifdef CONFIG_PCI
2514 pci_unregister_driver(&cirrusfb_pci_driver);
2515 #endif
2516 #ifdef CONFIG_ZORRO
2517 zorro_unregister_driver(&cirrusfb_zorro_driver);
2518 #endif
2521 module_init(cirrusfb_init);
2523 module_param(mode_option, charp, 0);
2524 MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
2525 module_param(noaccel, bool, 0);
2526 MODULE_PARM_DESC(noaccel, "Disable acceleration");
2528 #ifdef MODULE
2529 module_exit(cirrusfb_exit);
2530 #endif
2532 /**********************************************************************/
2533 /* about the following functions - I have used the same names for the */
2534 /* functions as Markus Wild did in his Retina driver for NetBSD as */
2535 /* they just made sense for this purpose. Apart from that, I wrote */
2536 /* these functions myself. */
2537 /**********************************************************************/
2539 /*** WGen() - write into one of the external/general registers ***/
2540 static void WGen(const struct cirrusfb_info *cinfo,
2541 int regnum, unsigned char val)
2543 unsigned long regofs = 0;
2545 if (cinfo->btype == BT_PICASSO) {
2546 /* Picasso II specific hack */
2547 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2548 regnum == CL_VSSM2) */
2549 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2550 regofs = 0xfff;
2553 vga_w(cinfo->regbase, regofs + regnum, val);
2556 /*** RGen() - read out one of the external/general registers ***/
2557 static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum)
2559 unsigned long regofs = 0;
2561 if (cinfo->btype == BT_PICASSO) {
2562 /* Picasso II specific hack */
2563 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2564 regnum == CL_VSSM2) */
2565 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2566 regofs = 0xfff;
2569 return vga_r(cinfo->regbase, regofs + regnum);
2572 /*** AttrOn() - turn on VideoEnable for Attribute controller ***/
2573 static void AttrOn(const struct cirrusfb_info *cinfo)
2575 assert(cinfo != NULL);
2577 DPRINTK("ENTER\n");
2579 if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) {
2580 /* if we're just in "write value" mode, write back the */
2581 /* same value as before to not modify anything */
2582 vga_w(cinfo->regbase, VGA_ATT_IW,
2583 vga_r(cinfo->regbase, VGA_ATT_R));
2585 /* turn on video bit */
2586 /* vga_w(cinfo->regbase, VGA_ATT_IW, 0x20); */
2587 vga_w(cinfo->regbase, VGA_ATT_IW, 0x33);
2589 /* dummy write on Reg0 to be on "write index" mode next time */
2590 vga_w(cinfo->regbase, VGA_ATT_IW, 0x00);
2592 DPRINTK("EXIT\n");
2595 /*** WHDR() - write into the Hidden DAC register ***/
2596 /* as the HDR is the only extension register that requires special treatment
2597 * (the other extension registers are accessible just like the "ordinary"
2598 * registers of their functional group) here is a specialized routine for
2599 * accessing the HDR
2601 static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val)
2603 unsigned char dummy;
2605 if (cinfo->btype == BT_PICASSO) {
2606 /* Klaus' hint for correct access to HDR on some boards */
2607 /* first write 0 to pixel mask (3c6) */
2608 WGen(cinfo, VGA_PEL_MSK, 0x00);
2609 udelay(200);
2610 /* next read dummy from pixel address (3c8) */
2611 dummy = RGen(cinfo, VGA_PEL_IW);
2612 udelay(200);
2614 /* now do the usual stuff to access the HDR */
2616 dummy = RGen(cinfo, VGA_PEL_MSK);
2617 udelay(200);
2618 dummy = RGen(cinfo, VGA_PEL_MSK);
2619 udelay(200);
2620 dummy = RGen(cinfo, VGA_PEL_MSK);
2621 udelay(200);
2622 dummy = RGen(cinfo, VGA_PEL_MSK);
2623 udelay(200);
2625 WGen(cinfo, VGA_PEL_MSK, val);
2626 udelay(200);
2628 if (cinfo->btype == BT_PICASSO) {
2629 /* now first reset HDR access counter */
2630 dummy = RGen(cinfo, VGA_PEL_IW);
2631 udelay(200);
2633 /* and at the end, restore the mask value */
2634 /* ## is this mask always 0xff? */
2635 WGen(cinfo, VGA_PEL_MSK, 0xff);
2636 udelay(200);
2640 /*** WSFR() - write to the "special function register" (SFR) ***/
2641 static void WSFR(struct cirrusfb_info *cinfo, unsigned char val)
2643 #ifdef CONFIG_ZORRO
2644 assert(cinfo->regbase != NULL);
2645 cinfo->SFR = val;
2646 z_writeb(val, cinfo->regbase + 0x8000);
2647 #endif
2650 /* The Picasso has a second register for switching the monitor bit */
2651 static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val)
2653 #ifdef CONFIG_ZORRO
2654 /* writing an arbitrary value to this one causes the monitor switcher */
2655 /* to flip to Amiga display */
2656 assert(cinfo->regbase != NULL);
2657 cinfo->SFR = val;
2658 z_writeb(val, cinfo->regbase + 0x9000);
2659 #endif
2662 /*** WClut - set CLUT entry (range: 0..63) ***/
2663 static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
2664 unsigned char green, unsigned char blue)
2666 unsigned int data = VGA_PEL_D;
2668 /* address write mode register is not translated.. */
2669 vga_w(cinfo->regbase, VGA_PEL_IW, regnum);
2671 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2672 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2673 /* but DAC data register IS, at least for Picasso II */
2674 if (cinfo->btype == BT_PICASSO)
2675 data += 0xfff;
2676 vga_w(cinfo->regbase, data, red);
2677 vga_w(cinfo->regbase, data, green);
2678 vga_w(cinfo->regbase, data, blue);
2679 } else {
2680 vga_w(cinfo->regbase, data, blue);
2681 vga_w(cinfo->regbase, data, green);
2682 vga_w(cinfo->regbase, data, red);
2686 #if 0
2687 /*** RClut - read CLUT entry (range 0..63) ***/
2688 static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
2689 unsigned char *green, unsigned char *blue)
2691 unsigned int data = VGA_PEL_D;
2693 vga_w(cinfo->regbase, VGA_PEL_IR, regnum);
2695 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2696 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2697 if (cinfo->btype == BT_PICASSO)
2698 data += 0xfff;
2699 *red = vga_r(cinfo->regbase, data);
2700 *green = vga_r(cinfo->regbase, data);
2701 *blue = vga_r(cinfo->regbase, data);
2702 } else {
2703 *blue = vga_r(cinfo->regbase, data);
2704 *green = vga_r(cinfo->regbase, data);
2705 *red = vga_r(cinfo->regbase, data);
2708 #endif
2710 /*******************************************************************
2711 cirrusfb_WaitBLT()
2713 Wait for the BitBLT engine to complete a possible earlier job
2714 *********************************************************************/
2716 /* FIXME: use interrupts instead */
2717 static void cirrusfb_WaitBLT(u8 __iomem *regbase)
2719 /* now busy-wait until we're done */
2720 while (vga_rgfx(regbase, CL_GR31) & 0x08)
2721 /* do nothing */ ;
2724 /*******************************************************************
2725 cirrusfb_BitBLT()
2727 perform accelerated "scrolling"
2728 ********************************************************************/
2730 static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
2731 u_short curx, u_short cury,
2732 u_short destx, u_short desty,
2733 u_short width, u_short height,
2734 u_short line_length)
2736 u_short nwidth, nheight;
2737 u_long nsrc, ndest;
2738 u_char bltmode;
2740 DPRINTK("ENTER\n");
2742 nwidth = width - 1;
2743 nheight = height - 1;
2745 bltmode = 0x00;
2746 /* if source adr < dest addr, do the Blt backwards */
2747 if (cury <= desty) {
2748 if (cury == desty) {
2749 /* if src and dest are on the same line, check x */
2750 if (curx < destx)
2751 bltmode |= 0x01;
2752 } else
2753 bltmode |= 0x01;
2755 if (!bltmode) {
2756 /* standard case: forward blitting */
2757 nsrc = (cury * line_length) + curx;
2758 ndest = (desty * line_length) + destx;
2759 } else {
2760 /* this means start addresses are at the end,
2761 * counting backwards
2763 nsrc = cury * line_length + curx +
2764 nheight * line_length + nwidth;
2765 ndest = desty * line_length + destx +
2766 nheight * line_length + nwidth;
2770 run-down of registers to be programmed:
2771 destination pitch
2772 source pitch
2773 BLT width/height
2774 source start
2775 destination start
2776 BLT mode
2777 BLT ROP
2778 VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color"
2779 start/stop
2782 cirrusfb_WaitBLT(regbase);
2784 /* pitch: set to line_length */
2785 /* dest pitch low */
2786 vga_wgfx(regbase, CL_GR24, line_length & 0xff);
2787 /* dest pitch hi */
2788 vga_wgfx(regbase, CL_GR25, line_length >> 8);
2789 /* source pitch low */
2790 vga_wgfx(regbase, CL_GR26, line_length & 0xff);
2791 /* source pitch hi */
2792 vga_wgfx(regbase, CL_GR27, line_length >> 8);
2794 /* BLT width: actual number of pixels - 1 */
2795 /* BLT width low */
2796 vga_wgfx(regbase, CL_GR20, nwidth & 0xff);
2797 /* BLT width hi */
2798 vga_wgfx(regbase, CL_GR21, nwidth >> 8);
2800 /* BLT height: actual number of lines -1 */
2801 /* BLT height low */
2802 vga_wgfx(regbase, CL_GR22, nheight & 0xff);
2803 /* BLT width hi */
2804 vga_wgfx(regbase, CL_GR23, nheight >> 8);
2806 /* BLT destination */
2807 /* BLT dest low */
2808 vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
2809 /* BLT dest mid */
2810 vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
2811 /* BLT dest hi */
2812 vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
2814 /* BLT source */
2815 /* BLT src low */
2816 vga_wgfx(regbase, CL_GR2C, (u_char) (nsrc & 0xff));
2817 /* BLT src mid */
2818 vga_wgfx(regbase, CL_GR2D, (u_char) (nsrc >> 8));
2819 /* BLT src hi */
2820 vga_wgfx(regbase, CL_GR2E, (u_char) (nsrc >> 16));
2822 /* BLT mode */
2823 vga_wgfx(regbase, CL_GR30, bltmode); /* BLT mode */
2825 /* BLT ROP: SrcCopy */
2826 vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */
2828 /* and finally: GO! */
2829 vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */
2831 DPRINTK("EXIT\n");
2834 /*******************************************************************
2835 cirrusfb_RectFill()
2837 perform accelerated rectangle fill
2838 ********************************************************************/
2840 static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
2841 u_short x, u_short y, u_short width, u_short height,
2842 u_char color, u_short line_length)
2844 u_short nwidth, nheight;
2845 u_long ndest;
2846 u_char op;
2848 DPRINTK("ENTER\n");
2850 nwidth = width - 1;
2851 nheight = height - 1;
2853 ndest = (y * line_length) + x;
2855 cirrusfb_WaitBLT(regbase);
2857 /* pitch: set to line_length */
2858 vga_wgfx(regbase, CL_GR24, line_length & 0xff); /* dest pitch low */
2859 vga_wgfx(regbase, CL_GR25, line_length >> 8); /* dest pitch hi */
2860 vga_wgfx(regbase, CL_GR26, line_length & 0xff); /* source pitch low */
2861 vga_wgfx(regbase, CL_GR27, line_length >> 8); /* source pitch hi */
2863 /* BLT width: actual number of pixels - 1 */
2864 vga_wgfx(regbase, CL_GR20, nwidth & 0xff); /* BLT width low */
2865 vga_wgfx(regbase, CL_GR21, nwidth >> 8); /* BLT width hi */
2867 /* BLT height: actual number of lines -1 */
2868 vga_wgfx(regbase, CL_GR22, nheight & 0xff); /* BLT height low */
2869 vga_wgfx(regbase, CL_GR23, nheight >> 8); /* BLT width hi */
2871 /* BLT destination */
2872 /* BLT dest low */
2873 vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
2874 /* BLT dest mid */
2875 vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
2876 /* BLT dest hi */
2877 vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
2879 /* BLT source: set to 0 (is a dummy here anyway) */
2880 vga_wgfx(regbase, CL_GR2C, 0x00); /* BLT src low */
2881 vga_wgfx(regbase, CL_GR2D, 0x00); /* BLT src mid */
2882 vga_wgfx(regbase, CL_GR2E, 0x00); /* BLT src hi */
2884 /* This is a ColorExpand Blt, using the */
2885 /* same color for foreground and background */
2886 vga_wgfx(regbase, VGA_GFX_SR_VALUE, color); /* foreground color */
2887 vga_wgfx(regbase, VGA_GFX_SR_ENABLE, color); /* background color */
2889 op = 0xc0;
2890 if (bits_per_pixel == 16) {
2891 vga_wgfx(regbase, CL_GR10, color); /* foreground color */
2892 vga_wgfx(regbase, CL_GR11, color); /* background color */
2893 op = 0x50;
2894 op = 0xd0;
2895 } else if (bits_per_pixel == 32) {
2896 vga_wgfx(regbase, CL_GR10, color); /* foreground color */
2897 vga_wgfx(regbase, CL_GR11, color); /* background color */
2898 vga_wgfx(regbase, CL_GR12, color); /* foreground color */
2899 vga_wgfx(regbase, CL_GR13, color); /* background color */
2900 vga_wgfx(regbase, CL_GR14, 0); /* foreground color */
2901 vga_wgfx(regbase, CL_GR15, 0); /* background color */
2902 op = 0x50;
2903 op = 0xf0;
2905 /* BLT mode: color expand, Enable 8x8 copy (faster?) */
2906 vga_wgfx(regbase, CL_GR30, op); /* BLT mode */
2908 /* BLT ROP: SrcCopy */
2909 vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */
2911 /* and finally: GO! */
2912 vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */
2914 DPRINTK("EXIT\n");
2917 /**************************************************************************
2918 * bestclock() - determine closest possible clock lower(?) than the
2919 * desired pixel clock
2920 **************************************************************************/
2921 static void bestclock(long freq, int *nom, int *den, int *div)
2923 int n, d;
2924 long h, diff;
2926 assert(nom != NULL);
2927 assert(den != NULL);
2928 assert(div != NULL);
2930 *nom = 0;
2931 *den = 0;
2932 *div = 0;
2934 DPRINTK("ENTER\n");
2936 if (freq < 8000)
2937 freq = 8000;
2939 diff = freq;
2941 for (n = 32; n < 128; n++) {
2942 int s = 0;
2944 d = (14318 * n) / freq;
2945 if ((d >= 7) && (d <= 63)) {
2946 int temp = d;
2948 if (temp > 31) {
2949 s = 1;
2950 temp >>= 1;
2952 h = ((14318 * n) / temp) >> s;
2953 h = h > freq ? h - freq : freq - h;
2954 if (h < diff) {
2955 diff = h;
2956 *nom = n;
2957 *den = temp;
2958 *div = s;
2961 d++;
2962 if ((d >= 7) && (d <= 63)) {
2963 if (d > 31) {
2964 s = 1;
2965 d >>= 1;
2967 h = ((14318 * n) / d) >> s;
2968 h = h > freq ? h - freq : freq - h;
2969 if (h < diff) {
2970 diff = h;
2971 *nom = n;
2972 *den = d;
2973 *div = s;
2978 DPRINTK("Best possible values for given frequency:\n");
2979 DPRINTK(" freq: %ld kHz nom: %d den: %d div: %d\n",
2980 freq, *nom, *den, *div);
2982 DPRINTK("EXIT\n");
2985 /* -------------------------------------------------------------------------
2987 * debugging functions
2989 * -------------------------------------------------------------------------
2992 #ifdef CIRRUSFB_DEBUG
2995 * cirrusfb_dbg_print_byte
2996 * @name: name associated with byte value to be displayed
2997 * @val: byte value to be displayed
2999 * DESCRIPTION:
3000 * Display an indented string, along with a hexidecimal byte value, and
3001 * its decoded bits. Bits 7 through 0 are listed in left-to-right
3002 * order.
3005 static
3006 void cirrusfb_dbg_print_byte(const char *name, unsigned char val)
3008 DPRINTK("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n",
3009 name, val,
3010 val & 0x80 ? '1' : '0',
3011 val & 0x40 ? '1' : '0',
3012 val & 0x20 ? '1' : '0',
3013 val & 0x10 ? '1' : '0',
3014 val & 0x08 ? '1' : '0',
3015 val & 0x04 ? '1' : '0',
3016 val & 0x02 ? '1' : '0',
3017 val & 0x01 ? '1' : '0');
3021 * cirrusfb_dbg_print_regs
3022 * @base: If using newmmio, the newmmio base address, otherwise %NULL
3023 * @reg_class: type of registers to read: %CRT, or %SEQ
3025 * DESCRIPTION:
3026 * Dumps the given list of VGA CRTC registers. If @base is %NULL,
3027 * old-style I/O ports are queried for information, otherwise MMIO is
3028 * used at the given @base address to query the information.
3031 static
3032 void cirrusfb_dbg_print_regs(caddr_t regbase,
3033 enum cirrusfb_dbg_reg_class reg_class, ...)
3035 va_list list;
3036 unsigned char val = 0;
3037 unsigned reg;
3038 char *name;
3040 va_start(list, reg_class);
3042 name = va_arg(list, char *);
3043 while (name != NULL) {
3044 reg = va_arg(list, int);
3046 switch (reg_class) {
3047 case CRT:
3048 val = vga_rcrt(regbase, (unsigned char) reg);
3049 break;
3050 case SEQ:
3051 val = vga_rseq(regbase, (unsigned char) reg);
3052 break;
3053 default:
3054 /* should never occur */
3055 assert(false);
3056 break;
3059 cirrusfb_dbg_print_byte(name, val);
3061 name = va_arg(list, char *);
3064 va_end(list);
3068 * cirrusfb_dump
3069 * @cirrusfbinfo:
3071 * DESCRIPTION:
3074 static void cirrusfb_dump(void)
3076 cirrusfb_dbg_reg_dump(NULL);
3080 * cirrusfb_dbg_reg_dump
3081 * @base: If using newmmio, the newmmio base address, otherwise %NULL
3083 * DESCRIPTION:
3084 * Dumps a list of interesting VGA and CIRRUSFB registers. If @base is %NULL,
3085 * old-style I/O ports are queried for information, otherwise MMIO is
3086 * used at the given @base address to query the information.
3089 static
3090 void cirrusfb_dbg_reg_dump(caddr_t regbase)
3092 DPRINTK("CIRRUSFB VGA CRTC register dump:\n");
3094 cirrusfb_dbg_print_regs(regbase, CRT,
3095 "CR00", 0x00,
3096 "CR01", 0x01,
3097 "CR02", 0x02,
3098 "CR03", 0x03,
3099 "CR04", 0x04,
3100 "CR05", 0x05,
3101 "CR06", 0x06,
3102 "CR07", 0x07,
3103 "CR08", 0x08,
3104 "CR09", 0x09,
3105 "CR0A", 0x0A,
3106 "CR0B", 0x0B,
3107 "CR0C", 0x0C,
3108 "CR0D", 0x0D,
3109 "CR0E", 0x0E,
3110 "CR0F", 0x0F,
3111 "CR10", 0x10,
3112 "CR11", 0x11,
3113 "CR12", 0x12,
3114 "CR13", 0x13,
3115 "CR14", 0x14,
3116 "CR15", 0x15,
3117 "CR16", 0x16,
3118 "CR17", 0x17,
3119 "CR18", 0x18,
3120 "CR22", 0x22,
3121 "CR24", 0x24,
3122 "CR26", 0x26,
3123 "CR2D", 0x2D,
3124 "CR2E", 0x2E,
3125 "CR2F", 0x2F,
3126 "CR30", 0x30,
3127 "CR31", 0x31,
3128 "CR32", 0x32,
3129 "CR33", 0x33,
3130 "CR34", 0x34,
3131 "CR35", 0x35,
3132 "CR36", 0x36,
3133 "CR37", 0x37,
3134 "CR38", 0x38,
3135 "CR39", 0x39,
3136 "CR3A", 0x3A,
3137 "CR3B", 0x3B,
3138 "CR3C", 0x3C,
3139 "CR3D", 0x3D,
3140 "CR3E", 0x3E,
3141 "CR3F", 0x3F,
3142 NULL);
3144 DPRINTK("\n");
3146 DPRINTK("CIRRUSFB VGA SEQ register dump:\n");
3148 cirrusfb_dbg_print_regs(regbase, SEQ,
3149 "SR00", 0x00,
3150 "SR01", 0x01,
3151 "SR02", 0x02,
3152 "SR03", 0x03,
3153 "SR04", 0x04,
3154 "SR08", 0x08,
3155 "SR09", 0x09,
3156 "SR0A", 0x0A,
3157 "SR0B", 0x0B,
3158 "SR0D", 0x0D,
3159 "SR10", 0x10,
3160 "SR11", 0x11,
3161 "SR12", 0x12,
3162 "SR13", 0x13,
3163 "SR14", 0x14,
3164 "SR15", 0x15,
3165 "SR16", 0x16,
3166 "SR17", 0x17,
3167 "SR18", 0x18,
3168 "SR19", 0x19,
3169 "SR1A", 0x1A,
3170 "SR1B", 0x1B,
3171 "SR1C", 0x1C,
3172 "SR1D", 0x1D,
3173 "SR1E", 0x1E,
3174 "SR1F", 0x1F,
3175 NULL);
3177 DPRINTK("\n");
3180 #endif /* CIRRUSFB_DEBUG */