added 2.6.29.6 aldebaran kernel
[nao-ulib.git] / kernel / 2.6.29.6-aldebaran-rt / drivers / video / cirrusfb.c
bloba2aa6ddffbe25d6e764a0dc6bdc7dd298e9f1849
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 int multiplexing;
333 #ifdef CIRRUSFB_DEBUG
334 enum cirrusfb_dbg_reg_class {
335 CRT,
338 #endif /* CIRRUSFB_DEBUG */
340 /* info about board */
341 struct cirrusfb_info {
342 u8 __iomem *regbase;
343 enum cirrus_board btype;
344 unsigned char SFR; /* Shadow of special function register */
346 struct cirrusfb_regs currentmode;
347 int blank_mode;
348 u32 pseudo_palette[16];
350 void (*unmap)(struct fb_info *info);
353 static int noaccel __devinitdata;
354 static char *mode_option __devinitdata = "640x480@60";
356 /****************************************************************************/
357 /**** BEGIN PROTOTYPES ******************************************************/
359 /*--- Interface used by the world ------------------------------------------*/
360 static int cirrusfb_init(void);
361 #ifndef MODULE
362 static int cirrusfb_setup(char *options);
363 #endif
365 static int cirrusfb_open(struct fb_info *info, int user);
366 static int cirrusfb_release(struct fb_info *info, int user);
367 static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
368 unsigned blue, unsigned transp,
369 struct fb_info *info);
370 static int cirrusfb_check_var(struct fb_var_screeninfo *var,
371 struct fb_info *info);
372 static int cirrusfb_set_par(struct fb_info *info);
373 static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
374 struct fb_info *info);
375 static int cirrusfb_blank(int blank_mode, struct fb_info *info);
376 static void cirrusfb_fillrect(struct fb_info *info,
377 const struct fb_fillrect *region);
378 static void cirrusfb_copyarea(struct fb_info *info,
379 const struct fb_copyarea *area);
380 static void cirrusfb_imageblit(struct fb_info *info,
381 const struct fb_image *image);
383 /* function table of the above functions */
384 static struct fb_ops cirrusfb_ops = {
385 .owner = THIS_MODULE,
386 .fb_open = cirrusfb_open,
387 .fb_release = cirrusfb_release,
388 .fb_setcolreg = cirrusfb_setcolreg,
389 .fb_check_var = cirrusfb_check_var,
390 .fb_set_par = cirrusfb_set_par,
391 .fb_pan_display = cirrusfb_pan_display,
392 .fb_blank = cirrusfb_blank,
393 .fb_fillrect = cirrusfb_fillrect,
394 .fb_copyarea = cirrusfb_copyarea,
395 .fb_imageblit = cirrusfb_imageblit,
398 /*--- Internal routines ----------------------------------------------------*/
399 static void init_vgachip(struct fb_info *info);
400 static void switch_monitor(struct cirrusfb_info *cinfo, int on);
401 static void WGen(const struct cirrusfb_info *cinfo,
402 int regnum, unsigned char val);
403 static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum);
404 static void AttrOn(const struct cirrusfb_info *cinfo);
405 static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val);
406 static void WSFR(struct cirrusfb_info *cinfo, unsigned char val);
407 static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val);
408 static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum,
409 unsigned char red, unsigned char green, unsigned char blue);
410 #if 0
411 static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum,
412 unsigned char *red, unsigned char *green,
413 unsigned char *blue);
414 #endif
415 static void cirrusfb_WaitBLT(u8 __iomem *regbase);
416 static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
417 u_short curx, u_short cury,
418 u_short destx, u_short desty,
419 u_short width, u_short height,
420 u_short line_length);
421 static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
422 u_short x, u_short y,
423 u_short width, u_short height,
424 u_char color, u_short line_length);
426 static void bestclock(long freq, int *nom, int *den, int *div);
428 #ifdef CIRRUSFB_DEBUG
429 static void cirrusfb_dump(void);
430 static void cirrusfb_dbg_reg_dump(caddr_t regbase);
431 static void cirrusfb_dbg_print_regs(caddr_t regbase,
432 enum cirrusfb_dbg_reg_class reg_class, ...);
433 static void cirrusfb_dbg_print_byte(const char *name, unsigned char val);
434 #endif /* CIRRUSFB_DEBUG */
436 /*** END PROTOTYPES ********************************************************/
437 /*****************************************************************************/
438 /*** BEGIN Interface Used by the World ***************************************/
440 static int opencount;
442 /*--- Open /dev/fbx ---------------------------------------------------------*/
443 static int cirrusfb_open(struct fb_info *info, int user)
445 if (opencount++ == 0)
446 switch_monitor(info->par, 1);
447 return 0;
450 /*--- Close /dev/fbx --------------------------------------------------------*/
451 static int cirrusfb_release(struct fb_info *info, int user)
453 if (--opencount == 0)
454 switch_monitor(info->par, 0);
455 return 0;
458 /**** END Interface used by the World *************************************/
459 /****************************************************************************/
460 /**** BEGIN Hardware specific Routines **************************************/
462 /* Check if the MCLK is not a better clock source */
463 static int cirrusfb_check_mclk(struct cirrusfb_info *cinfo, long freq)
465 long mclk = vga_rseq(cinfo->regbase, CL_SEQR1F) & 0x3f;
467 /* Read MCLK value */
468 mclk = (14318 * mclk) >> 3;
469 DPRINTK("Read MCLK of %ld kHz\n", mclk);
471 /* Determine if we should use MCLK instead of VCLK, and if so, what we
472 * should divide it by to get VCLK
475 if (abs(freq - mclk) < 250) {
476 DPRINTK("Using VCLK = MCLK\n");
477 return 1;
478 } else if (abs(freq - (mclk / 2)) < 250) {
479 DPRINTK("Using VCLK = MCLK/2\n");
480 return 2;
483 return 0;
486 static int cirrusfb_check_var(struct fb_var_screeninfo *var,
487 struct fb_info *info)
489 int yres;
490 /* memory size in pixels */
491 unsigned pixels = info->screen_size * 8 / var->bits_per_pixel;
493 switch (var->bits_per_pixel) {
494 case 1:
495 pixels /= 4;
496 break; /* 8 pixel per byte, only 1/4th of mem usable */
497 case 8:
498 case 16:
499 case 32:
500 break; /* 1 pixel == 1 byte */
501 default:
502 printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..."
503 "color depth not supported.\n",
504 var->xres, var->yres, var->bits_per_pixel);
505 DPRINTK("EXIT - EINVAL error\n");
506 return -EINVAL;
509 if (var->xres_virtual < var->xres)
510 var->xres_virtual = var->xres;
511 /* use highest possible virtual resolution */
512 if (var->yres_virtual == -1) {
513 var->yres_virtual = pixels / var->xres_virtual;
515 printk(KERN_INFO "cirrusfb: virtual resolution set to "
516 "maximum of %dx%d\n", var->xres_virtual,
517 var->yres_virtual);
519 if (var->yres_virtual < var->yres)
520 var->yres_virtual = var->yres;
522 if (var->xres_virtual * var->yres_virtual > pixels) {
523 printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected... "
524 "virtual resolution too high to fit into video memory!\n",
525 var->xres_virtual, var->yres_virtual,
526 var->bits_per_pixel);
527 DPRINTK("EXIT - EINVAL error\n");
528 return -EINVAL;
532 if (var->xoffset < 0)
533 var->xoffset = 0;
534 if (var->yoffset < 0)
535 var->yoffset = 0;
537 /* truncate xoffset and yoffset to maximum if too high */
538 if (var->xoffset > var->xres_virtual - var->xres)
539 var->xoffset = var->xres_virtual - var->xres - 1;
540 if (var->yoffset > var->yres_virtual - var->yres)
541 var->yoffset = var->yres_virtual - var->yres - 1;
543 switch (var->bits_per_pixel) {
544 case 1:
545 var->red.offset = 0;
546 var->red.length = 1;
547 var->green = var->red;
548 var->blue = var->red;
549 break;
551 case 8:
552 var->red.offset = 0;
553 var->red.length = 6;
554 var->green = var->red;
555 var->blue = var->red;
556 break;
558 case 16:
559 if (isPReP) {
560 var->red.offset = 2;
561 var->green.offset = -3;
562 var->blue.offset = 8;
563 } else {
564 var->red.offset = 10;
565 var->green.offset = 5;
566 var->blue.offset = 0;
568 var->red.length = 5;
569 var->green.length = 5;
570 var->blue.length = 5;
571 break;
573 case 32:
574 if (isPReP) {
575 var->red.offset = 8;
576 var->green.offset = 16;
577 var->blue.offset = 24;
578 } else {
579 var->red.offset = 16;
580 var->green.offset = 8;
581 var->blue.offset = 0;
583 var->red.length = 8;
584 var->green.length = 8;
585 var->blue.length = 8;
586 break;
588 default:
589 DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);
590 assert(false);
591 /* should never occur */
592 break;
595 var->red.msb_right =
596 var->green.msb_right =
597 var->blue.msb_right =
598 var->transp.offset =
599 var->transp.length =
600 var->transp.msb_right = 0;
602 yres = var->yres;
603 if (var->vmode & FB_VMODE_DOUBLE)
604 yres *= 2;
605 else if (var->vmode & FB_VMODE_INTERLACED)
606 yres = (yres + 1) / 2;
608 if (yres >= 1280) {
609 printk(KERN_ERR "cirrusfb: ERROR: VerticalTotal >= 1280; "
610 "special treatment required! (TODO)\n");
611 DPRINTK("EXIT - EINVAL error\n");
612 return -EINVAL;
615 return 0;
618 static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
619 struct cirrusfb_regs *regs,
620 struct fb_info *info)
622 long freq;
623 long maxclock;
624 int maxclockidx = var->bits_per_pixel >> 3;
625 struct cirrusfb_info *cinfo = info->par;
627 switch (var->bits_per_pixel) {
628 case 1:
629 info->fix.line_length = var->xres_virtual / 8;
630 info->fix.visual = FB_VISUAL_MONO10;
631 break;
633 case 8:
634 info->fix.line_length = var->xres_virtual;
635 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
636 break;
638 case 16:
639 case 32:
640 info->fix.line_length = var->xres_virtual * maxclockidx;
641 info->fix.visual = FB_VISUAL_TRUECOLOR;
642 break;
644 default:
645 DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);
646 assert(false);
647 /* should never occur */
648 break;
651 info->fix.type = FB_TYPE_PACKED_PIXELS;
653 /* convert from ps to kHz */
654 freq = PICOS2KHZ(var->pixclock);
656 DPRINTK("desired pixclock: %ld kHz\n", freq);
658 maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
659 regs->multiplexing = 0;
661 /* If the frequency is greater than we can support, we might be able
662 * to use multiplexing for the video mode */
663 if (freq > maxclock) {
664 switch (cinfo->btype) {
665 case BT_ALPINE:
666 case BT_GD5480:
667 regs->multiplexing = 1;
668 break;
670 default:
671 printk(KERN_ERR "cirrusfb: Frequency greater "
672 "than maxclock (%ld kHz)\n", maxclock);
673 DPRINTK("EXIT - return -EINVAL\n");
674 return -EINVAL;
677 #if 0
678 /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
679 * the VCLK is double the pixel clock. */
680 switch (var->bits_per_pixel) {
681 case 16:
682 case 32:
683 if (var->xres <= 800)
684 /* Xbh has this type of clock for 32-bit */
685 freq /= 2;
686 break;
688 #endif
689 return 0;
692 static void cirrusfb_set_mclk_as_source(const struct cirrusfb_info *cinfo,
693 int div)
695 unsigned char old1f, old1e;
696 assert(cinfo != NULL);
697 old1f = vga_rseq(cinfo->regbase, CL_SEQR1F) & ~0x40;
699 if (div) {
700 DPRINTK("Set %s as pixclock source.\n",
701 (div == 2) ? "MCLK/2" : "MCLK");
702 old1f |= 0x40;
703 old1e = vga_rseq(cinfo->regbase, CL_SEQR1E) & ~0x1;
704 if (div == 2)
705 old1e |= 1;
707 vga_wseq(cinfo->regbase, CL_SEQR1E, old1e);
709 vga_wseq(cinfo->regbase, CL_SEQR1F, old1f);
712 /*************************************************************************
713 cirrusfb_set_par_foo()
715 actually writes the values for a new video mode into the hardware,
716 **************************************************************************/
717 static int cirrusfb_set_par_foo(struct fb_info *info)
719 struct cirrusfb_info *cinfo = info->par;
720 struct fb_var_screeninfo *var = &info->var;
721 struct cirrusfb_regs regs;
722 u8 __iomem *regbase = cinfo->regbase;
723 unsigned char tmp;
724 int offset = 0, err;
725 const struct cirrusfb_board_info_rec *bi;
726 int hdispend, hsyncstart, hsyncend, htotal;
727 int yres, vdispend, vsyncstart, vsyncend, vtotal;
728 long freq;
729 int nom, den, div;
731 DPRINTK("ENTER\n");
732 DPRINTK("Requested mode: %dx%dx%d\n",
733 var->xres, var->yres, var->bits_per_pixel);
734 DPRINTK("pixclock: %d\n", var->pixclock);
736 init_vgachip(info);
738 err = cirrusfb_decode_var(var, &regs, info);
739 if (err) {
740 /* should never happen */
741 DPRINTK("mode change aborted. invalid var.\n");
742 return -EINVAL;
745 bi = &cirrusfb_board_info[cinfo->btype];
747 hsyncstart = var->xres + var->right_margin;
748 hsyncend = hsyncstart + var->hsync_len;
749 htotal = (hsyncend + var->left_margin) / 8 - 5;
750 hdispend = var->xres / 8 - 1;
751 hsyncstart = hsyncstart / 8 + 1;
752 hsyncend = hsyncend / 8 + 1;
754 yres = var->yres;
755 vsyncstart = yres + var->lower_margin;
756 vsyncend = vsyncstart + var->vsync_len;
757 vtotal = vsyncend + var->upper_margin;
758 vdispend = yres - 1;
760 if (var->vmode & FB_VMODE_DOUBLE) {
761 yres *= 2;
762 vsyncstart *= 2;
763 vsyncend *= 2;
764 vtotal *= 2;
765 } else if (var->vmode & FB_VMODE_INTERLACED) {
766 yres = (yres + 1) / 2;
767 vsyncstart = (vsyncstart + 1) / 2;
768 vsyncend = (vsyncend + 1) / 2;
769 vtotal = (vtotal + 1) / 2;
772 vtotal -= 2;
773 vsyncstart -= 1;
774 vsyncend -= 1;
776 if (yres >= 1024) {
777 vtotal /= 2;
778 vsyncstart /= 2;
779 vsyncend /= 2;
780 vdispend /= 2;
782 if (regs.multiplexing) {
783 htotal /= 2;
784 hsyncstart /= 2;
785 hsyncend /= 2;
786 hdispend /= 2;
788 /* unlock register VGA_CRTC_H_TOTAL..CRT7 */
789 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */
791 /* if debugging is enabled, all parameters get output before writing */
792 DPRINTK("CRT0: %d\n", htotal);
793 vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal);
795 DPRINTK("CRT1: %d\n", hdispend);
796 vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend);
798 DPRINTK("CRT2: %d\n", var->xres / 8);
799 vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8);
801 /* + 128: Compatible read */
802 DPRINTK("CRT3: 128+%d\n", (htotal + 5) % 32);
803 vga_wcrt(regbase, VGA_CRTC_H_BLANK_END,
804 128 + ((htotal + 5) % 32));
806 DPRINTK("CRT4: %d\n", hsyncstart);
807 vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart);
809 tmp = hsyncend % 32;
810 if ((htotal + 5) & 32)
811 tmp += 128;
812 DPRINTK("CRT5: %d\n", tmp);
813 vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp);
815 DPRINTK("CRT6: %d\n", vtotal & 0xff);
816 vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff);
818 tmp = 16; /* LineCompare bit #9 */
819 if (vtotal & 256)
820 tmp |= 1;
821 if (vdispend & 256)
822 tmp |= 2;
823 if (vsyncstart & 256)
824 tmp |= 4;
825 if ((vdispend + 1) & 256)
826 tmp |= 8;
827 if (vtotal & 512)
828 tmp |= 32;
829 if (vdispend & 512)
830 tmp |= 64;
831 if (vsyncstart & 512)
832 tmp |= 128;
833 DPRINTK("CRT7: %d\n", tmp);
834 vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp);
836 tmp = 0x40; /* LineCompare bit #8 */
837 if ((vdispend + 1) & 512)
838 tmp |= 0x20;
839 if (var->vmode & FB_VMODE_DOUBLE)
840 tmp |= 0x80;
841 DPRINTK("CRT9: %d\n", tmp);
842 vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp);
844 DPRINTK("CRT10: %d\n", vsyncstart & 0xff);
845 vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff);
847 DPRINTK("CRT11: 64+32+%d\n", vsyncend % 16);
848 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32);
850 DPRINTK("CRT12: %d\n", vdispend & 0xff);
851 vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff);
853 DPRINTK("CRT15: %d\n", (vdispend + 1) & 0xff);
854 vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff);
856 DPRINTK("CRT16: %d\n", vtotal & 0xff);
857 vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff);
859 DPRINTK("CRT18: 0xff\n");
860 vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff);
862 tmp = 0;
863 if (var->vmode & FB_VMODE_INTERLACED)
864 tmp |= 1;
865 if ((htotal + 5) & 64)
866 tmp |= 16;
867 if ((htotal + 5) & 128)
868 tmp |= 32;
869 if (vtotal & 256)
870 tmp |= 64;
871 if (vtotal & 512)
872 tmp |= 128;
874 DPRINTK("CRT1a: %d\n", tmp);
875 vga_wcrt(regbase, CL_CRT1A, tmp);
877 freq = PICOS2KHZ(var->pixclock);
878 bestclock(freq, &nom, &den, &div);
880 /* set VCLK0 */
881 /* hardware RefClock: 14.31818 MHz */
882 /* formula: VClk = (OSC * N) / (D * (1+P)) */
883 /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
885 if (cinfo->btype == BT_ALPINE) {
886 /* if freq is close to mclk or mclk/2 select mclk
887 * as clock source
889 int divMCLK = cirrusfb_check_mclk(cinfo, freq);
890 if (divMCLK) {
891 nom = 0;
892 cirrusfb_set_mclk_as_source(cinfo, divMCLK);
895 if (nom) {
896 vga_wseq(regbase, CL_SEQRB, nom);
897 tmp = den << 1;
898 if (div != 0)
899 tmp |= 1;
901 /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
902 if ((cinfo->btype == BT_SD64) ||
903 (cinfo->btype == BT_ALPINE) ||
904 (cinfo->btype == BT_GD5480))
905 tmp |= 0x80;
907 DPRINTK("CL_SEQR1B: %ld\n", (long) tmp);
908 vga_wseq(regbase, CL_SEQR1B, tmp);
911 if (yres >= 1024)
912 /* 1280x1024 */
913 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7);
914 else
915 /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
916 * address wrap, no compat. */
917 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3);
919 /* HAEH? vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20);
920 * previously: 0x00 unlock VGA_CRTC_H_TOTAL..CRT7 */
922 /* don't know if it would hurt to also program this if no interlaced */
923 /* mode is used, but I feel better this way.. :-) */
924 if (var->vmode & FB_VMODE_INTERLACED)
925 vga_wcrt(regbase, VGA_CRTC_REGS, htotal / 2);
926 else
927 vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
929 vga_wseq(regbase, VGA_SEQ_CHARACTER_MAP, 0);
931 /* adjust horizontal/vertical sync type (low/high) */
932 /* enable display memory & CRTC I/O address for color mode */
933 tmp = 0x03;
934 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
935 tmp |= 0x40;
936 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
937 tmp |= 0x80;
938 WGen(cinfo, VGA_MIS_W, tmp);
940 /* Screen A Preset Row-Scan register */
941 vga_wcrt(regbase, VGA_CRTC_PRESET_ROW, 0);
942 /* text cursor on and start line */
943 vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0);
944 /* text cursor end line */
945 vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 31);
947 /******************************************************
949 * 1 bpp
953 /* programming for different color depths */
954 if (var->bits_per_pixel == 1) {
955 DPRINTK("cirrusfb: preparing for 1 bit deep display\n");
956 vga_wgfx(regbase, VGA_GFX_MODE, 0); /* mode register */
958 /* SR07 */
959 switch (cinfo->btype) {
960 case BT_SD64:
961 case BT_PICCOLO:
962 case BT_PICASSO:
963 case BT_SPECTRUM:
964 case BT_PICASSO4:
965 case BT_ALPINE:
966 case BT_GD5480:
967 DPRINTK(" (for GD54xx)\n");
968 vga_wseq(regbase, CL_SEQR7,
969 regs.multiplexing ?
970 bi->sr07_1bpp_mux : bi->sr07_1bpp);
971 break;
973 case BT_LAGUNA:
974 DPRINTK(" (for GD546x)\n");
975 vga_wseq(regbase, CL_SEQR7,
976 vga_rseq(regbase, CL_SEQR7) & ~0x01);
977 break;
979 default:
980 printk(KERN_WARNING "cirrusfb: unknown Board\n");
981 break;
984 /* Extended Sequencer Mode */
985 switch (cinfo->btype) {
986 case BT_SD64:
987 /* setting the SEQRF on SD64 is not necessary
988 * (only during init)
990 DPRINTK("(for SD64)\n");
991 /* MCLK select */
992 vga_wseq(regbase, CL_SEQR1F, 0x1a);
993 break;
995 case BT_PICCOLO:
996 case BT_SPECTRUM:
997 DPRINTK("(for Piccolo/Spectrum)\n");
998 /* ### ueberall 0x22? */
999 /* ##vorher 1c MCLK select */
1000 vga_wseq(regbase, CL_SEQR1F, 0x22);
1001 /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
1002 vga_wseq(regbase, CL_SEQRF, 0xb0);
1003 break;
1005 case BT_PICASSO:
1006 DPRINTK("(for Picasso)\n");
1007 /* ##vorher 22 MCLK select */
1008 vga_wseq(regbase, CL_SEQR1F, 0x22);
1009 /* ## vorher d0 avoid FIFO underruns..? */
1010 vga_wseq(regbase, CL_SEQRF, 0xd0);
1011 break;
1013 case BT_PICASSO4:
1014 case BT_ALPINE:
1015 case BT_GD5480:
1016 case BT_LAGUNA:
1017 DPRINTK(" (for GD54xx)\n");
1018 /* do nothing */
1019 break;
1021 default:
1022 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1023 break;
1026 /* pixel mask: pass-through for first plane */
1027 WGen(cinfo, VGA_PEL_MSK, 0x01);
1028 if (regs.multiplexing)
1029 /* hidden dac reg: 1280x1024 */
1030 WHDR(cinfo, 0x4a);
1031 else
1032 /* hidden dac: nothing */
1033 WHDR(cinfo, 0);
1034 /* memory mode: odd/even, ext. memory */
1035 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06);
1036 /* plane mask: only write to first plane */
1037 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01);
1038 offset = var->xres_virtual / 16;
1041 /******************************************************
1043 * 8 bpp
1047 else if (var->bits_per_pixel == 8) {
1048 DPRINTK("cirrusfb: preparing for 8 bit deep display\n");
1049 switch (cinfo->btype) {
1050 case BT_SD64:
1051 case BT_PICCOLO:
1052 case BT_PICASSO:
1053 case BT_SPECTRUM:
1054 case BT_PICASSO4:
1055 case BT_ALPINE:
1056 case BT_GD5480:
1057 DPRINTK(" (for GD54xx)\n");
1058 vga_wseq(regbase, CL_SEQR7,
1059 regs.multiplexing ?
1060 bi->sr07_8bpp_mux : bi->sr07_8bpp);
1061 break;
1063 case BT_LAGUNA:
1064 DPRINTK(" (for GD546x)\n");
1065 vga_wseq(regbase, CL_SEQR7,
1066 vga_rseq(regbase, CL_SEQR7) | 0x01);
1067 break;
1069 default:
1070 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1071 break;
1074 switch (cinfo->btype) {
1075 case BT_SD64:
1076 /* MCLK select */
1077 vga_wseq(regbase, CL_SEQR1F, 0x1d);
1078 break;
1080 case BT_PICCOLO:
1081 case BT_PICASSO:
1082 case BT_SPECTRUM:
1083 /* ### vorher 1c MCLK select */
1084 vga_wseq(regbase, CL_SEQR1F, 0x22);
1085 /* Fast Page-Mode writes */
1086 vga_wseq(regbase, CL_SEQRF, 0xb0);
1087 break;
1089 case BT_PICASSO4:
1090 #ifdef CONFIG_ZORRO
1091 /* ### INCOMPLETE!! */
1092 vga_wseq(regbase, CL_SEQRF, 0xb8);
1093 #endif
1094 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1095 break;
1097 case BT_ALPINE:
1098 DPRINTK(" (for GD543x)\n");
1099 /* We already set SRF and SR1F */
1100 break;
1102 case BT_GD5480:
1103 case BT_LAGUNA:
1104 DPRINTK(" (for GD54xx)\n");
1105 /* do nothing */
1106 break;
1108 default:
1109 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1110 break;
1113 /* mode register: 256 color mode */
1114 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1115 /* pixel mask: pass-through all planes */
1116 WGen(cinfo, VGA_PEL_MSK, 0xff);
1117 if (regs.multiplexing)
1118 /* hidden dac reg: 1280x1024 */
1119 WHDR(cinfo, 0x4a);
1120 else
1121 /* hidden dac: nothing */
1122 WHDR(cinfo, 0);
1123 /* memory mode: chain4, ext. memory */
1124 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1125 /* plane mask: enable writing to all 4 planes */
1126 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1127 offset = var->xres_virtual / 8;
1130 /******************************************************
1132 * 16 bpp
1136 else if (var->bits_per_pixel == 16) {
1137 DPRINTK("cirrusfb: preparing for 16 bit deep display\n");
1138 switch (cinfo->btype) {
1139 case BT_SD64:
1140 /* Extended Sequencer Mode: 256c col. mode */
1141 vga_wseq(regbase, CL_SEQR7, 0xf7);
1142 /* MCLK select */
1143 vga_wseq(regbase, CL_SEQR1F, 0x1e);
1144 break;
1146 case BT_PICCOLO:
1147 case BT_SPECTRUM:
1148 vga_wseq(regbase, CL_SEQR7, 0x87);
1149 /* Fast Page-Mode writes */
1150 vga_wseq(regbase, CL_SEQRF, 0xb0);
1151 /* MCLK select */
1152 vga_wseq(regbase, CL_SEQR1F, 0x22);
1153 break;
1155 case BT_PICASSO:
1156 vga_wseq(regbase, CL_SEQR7, 0x27);
1157 /* Fast Page-Mode writes */
1158 vga_wseq(regbase, CL_SEQRF, 0xb0);
1159 /* MCLK select */
1160 vga_wseq(regbase, CL_SEQR1F, 0x22);
1161 break;
1163 case BT_PICASSO4:
1164 vga_wseq(regbase, CL_SEQR7, 0x27);
1165 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1166 break;
1168 case BT_ALPINE:
1169 DPRINTK(" (for GD543x)\n");
1170 vga_wseq(regbase, CL_SEQR7, 0xa7);
1171 break;
1173 case BT_GD5480:
1174 DPRINTK(" (for GD5480)\n");
1175 vga_wseq(regbase, CL_SEQR7, 0x17);
1176 /* We already set SRF and SR1F */
1177 break;
1179 case BT_LAGUNA:
1180 DPRINTK(" (for GD546x)\n");
1181 vga_wseq(regbase, CL_SEQR7,
1182 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1183 break;
1185 default:
1186 printk(KERN_WARNING "CIRRUSFB: unknown Board\n");
1187 break;
1190 /* mode register: 256 color mode */
1191 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1192 /* pixel mask: pass-through all planes */
1193 WGen(cinfo, VGA_PEL_MSK, 0xff);
1194 #ifdef CONFIG_PCI
1195 WHDR(cinfo, 0xc0); /* Copy Xbh */
1196 #elif defined(CONFIG_ZORRO)
1197 /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
1198 WHDR(cinfo, 0xa0); /* hidden dac reg: nothing special */
1199 #endif
1200 /* memory mode: chain4, ext. memory */
1201 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1202 /* plane mask: enable writing to all 4 planes */
1203 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1204 offset = var->xres_virtual / 4;
1207 /******************************************************
1209 * 32 bpp
1213 else if (var->bits_per_pixel == 32) {
1214 DPRINTK("cirrusfb: preparing for 32 bit deep display\n");
1215 switch (cinfo->btype) {
1216 case BT_SD64:
1217 /* Extended Sequencer Mode: 256c col. mode */
1218 vga_wseq(regbase, CL_SEQR7, 0xf9);
1219 /* MCLK select */
1220 vga_wseq(regbase, CL_SEQR1F, 0x1e);
1221 break;
1223 case BT_PICCOLO:
1224 case BT_SPECTRUM:
1225 vga_wseq(regbase, CL_SEQR7, 0x85);
1226 /* Fast Page-Mode writes */
1227 vga_wseq(regbase, CL_SEQRF, 0xb0);
1228 /* MCLK select */
1229 vga_wseq(regbase, CL_SEQR1F, 0x22);
1230 break;
1232 case BT_PICASSO:
1233 vga_wseq(regbase, CL_SEQR7, 0x25);
1234 /* Fast Page-Mode writes */
1235 vga_wseq(regbase, CL_SEQRF, 0xb0);
1236 /* MCLK select */
1237 vga_wseq(regbase, CL_SEQR1F, 0x22);
1238 break;
1240 case BT_PICASSO4:
1241 vga_wseq(regbase, CL_SEQR7, 0x25);
1242 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1243 break;
1245 case BT_ALPINE:
1246 DPRINTK(" (for GD543x)\n");
1247 vga_wseq(regbase, CL_SEQR7, 0xa9);
1248 break;
1250 case BT_GD5480:
1251 DPRINTK(" (for GD5480)\n");
1252 vga_wseq(regbase, CL_SEQR7, 0x19);
1253 /* We already set SRF and SR1F */
1254 break;
1256 case BT_LAGUNA:
1257 DPRINTK(" (for GD546x)\n");
1258 vga_wseq(regbase, CL_SEQR7,
1259 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1260 break;
1262 default:
1263 printk(KERN_WARNING "cirrusfb: unknown Board\n");
1264 break;
1267 /* mode register: 256 color mode */
1268 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1269 /* pixel mask: pass-through all planes */
1270 WGen(cinfo, VGA_PEL_MSK, 0xff);
1271 /* hidden dac reg: 8-8-8 mode (24 or 32) */
1272 WHDR(cinfo, 0xc5);
1273 /* memory mode: chain4, ext. memory */
1274 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1275 /* plane mask: enable writing to all 4 planes */
1276 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1277 offset = var->xres_virtual / 4;
1280 /******************************************************
1282 * unknown/unsupported bpp
1286 else
1287 printk(KERN_ERR "cirrusfb: What's this?? "
1288 " requested color depth == %d.\n",
1289 var->bits_per_pixel);
1291 vga_wcrt(regbase, VGA_CRTC_OFFSET, offset & 0xff);
1292 tmp = 0x22;
1293 if (offset & 0x100)
1294 tmp |= 0x10; /* offset overflow bit */
1296 /* screen start addr #16-18, fastpagemode cycles */
1297 vga_wcrt(regbase, CL_CRT1B, tmp);
1299 if (cinfo->btype == BT_SD64 ||
1300 cinfo->btype == BT_PICASSO4 ||
1301 cinfo->btype == BT_ALPINE ||
1302 cinfo->btype == BT_GD5480)
1303 /* screen start address bit 19 */
1304 vga_wcrt(regbase, CL_CRT1D, 0x00);
1306 /* text cursor location high */
1307 vga_wcrt(regbase, VGA_CRTC_CURSOR_HI, 0);
1308 /* text cursor location low */
1309 vga_wcrt(regbase, VGA_CRTC_CURSOR_LO, 0);
1310 /* underline row scanline = at very bottom */
1311 vga_wcrt(regbase, VGA_CRTC_UNDERLINE, 0);
1313 /* controller mode */
1314 vga_wattr(regbase, VGA_ATC_MODE, 1);
1315 /* overscan (border) color */
1316 vga_wattr(regbase, VGA_ATC_OVERSCAN, 0);
1317 /* color plane enable */
1318 vga_wattr(regbase, VGA_ATC_PLANE_ENABLE, 15);
1319 /* pixel panning */
1320 vga_wattr(regbase, CL_AR33, 0);
1321 /* color select */
1322 vga_wattr(regbase, VGA_ATC_COLOR_PAGE, 0);
1324 /* [ EGS: SetOffset(); ] */
1325 /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
1326 AttrOn(cinfo);
1328 /* set/reset register */
1329 vga_wgfx(regbase, VGA_GFX_SR_VALUE, 0);
1330 /* set/reset enable */
1331 vga_wgfx(regbase, VGA_GFX_SR_ENABLE, 0);
1332 /* color compare */
1333 vga_wgfx(regbase, VGA_GFX_COMPARE_VALUE, 0);
1334 /* data rotate */
1335 vga_wgfx(regbase, VGA_GFX_DATA_ROTATE, 0);
1336 /* read map select */
1337 vga_wgfx(regbase, VGA_GFX_PLANE_READ, 0);
1338 /* miscellaneous register */
1339 vga_wgfx(regbase, VGA_GFX_MISC, 1);
1340 /* color don't care */
1341 vga_wgfx(regbase, VGA_GFX_COMPARE_MASK, 15);
1342 /* bit mask */
1343 vga_wgfx(regbase, VGA_GFX_BIT_MASK, 255);
1345 /* graphics cursor attributes: nothing special */
1346 vga_wseq(regbase, CL_SEQR12, 0x0);
1348 /* finally, turn on everything - turn off "FullBandwidth" bit */
1349 /* also, set "DotClock%2" bit where requested */
1350 tmp = 0x01;
1352 /*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
1353 if (var->vmode & FB_VMODE_CLOCK_HALVE)
1354 tmp |= 0x08;
1357 vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp);
1358 DPRINTK("CL_SEQR1: %d\n", tmp);
1360 cinfo->currentmode = regs;
1362 /* pan to requested offset */
1363 cirrusfb_pan_display(var, info);
1365 #ifdef CIRRUSFB_DEBUG
1366 cirrusfb_dump();
1367 #endif
1369 DPRINTK("EXIT\n");
1370 return 0;
1373 /* for some reason incomprehensible to me, cirrusfb requires that you write
1374 * the registers twice for the settings to take..grr. -dte */
1375 static int cirrusfb_set_par(struct fb_info *info)
1377 cirrusfb_set_par_foo(info);
1378 return cirrusfb_set_par_foo(info);
1381 static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1382 unsigned blue, unsigned transp,
1383 struct fb_info *info)
1385 struct cirrusfb_info *cinfo = info->par;
1387 if (regno > 255)
1388 return -EINVAL;
1390 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
1391 u32 v;
1392 red >>= (16 - info->var.red.length);
1393 green >>= (16 - info->var.green.length);
1394 blue >>= (16 - info->var.blue.length);
1396 if (regno >= 16)
1397 return 1;
1398 v = (red << info->var.red.offset) |
1399 (green << info->var.green.offset) |
1400 (blue << info->var.blue.offset);
1402 cinfo->pseudo_palette[regno] = v;
1403 return 0;
1406 if (info->var.bits_per_pixel == 8)
1407 WClut(cinfo, regno, red >> 10, green >> 10, blue >> 10);
1409 return 0;
1413 /*************************************************************************
1414 cirrusfb_pan_display()
1416 performs display panning - provided hardware permits this
1417 **************************************************************************/
1418 static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
1419 struct fb_info *info)
1421 int xoffset = 0;
1422 int yoffset = 0;
1423 unsigned long base;
1424 unsigned char tmp = 0, tmp2 = 0, xpix;
1425 struct cirrusfb_info *cinfo = info->par;
1427 DPRINTK("ENTER\n");
1428 DPRINTK("virtual offset: (%d,%d)\n", var->xoffset, var->yoffset);
1430 /* no range checks for xoffset and yoffset, */
1431 /* as fb_pan_display has already done this */
1432 if (var->vmode & FB_VMODE_YWRAP)
1433 return -EINVAL;
1435 info->var.xoffset = var->xoffset;
1436 info->var.yoffset = var->yoffset;
1438 xoffset = var->xoffset * info->var.bits_per_pixel / 8;
1439 yoffset = var->yoffset;
1441 base = yoffset * info->fix.line_length + xoffset;
1443 if (info->var.bits_per_pixel == 1) {
1444 /* base is already correct */
1445 xpix = (unsigned char) (var->xoffset % 8);
1446 } else {
1447 base /= 4;
1448 xpix = (unsigned char) ((xoffset % 4) * 2);
1451 cirrusfb_WaitBLT(cinfo->regbase); /* make sure all the BLT's are done */
1453 /* lower 8 + 8 bits of screen start address */
1454 vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO,
1455 (unsigned char) (base & 0xff));
1456 vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI,
1457 (unsigned char) (base >> 8));
1459 /* construct bits 16, 17 and 18 of screen start address */
1460 if (base & 0x10000)
1461 tmp |= 0x01;
1462 if (base & 0x20000)
1463 tmp |= 0x04;
1464 if (base & 0x40000)
1465 tmp |= 0x08;
1467 /* 0xf2 is %11110010, exclude tmp bits */
1468 tmp2 = (vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2) | tmp;
1469 vga_wcrt(cinfo->regbase, CL_CRT1B, tmp2);
1471 /* construct bit 19 of screen start address */
1472 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19)
1473 vga_wcrt(cinfo->regbase, CL_CRT1D, (base >> 12) & 0x80);
1475 /* write pixel panning value to AR33; this does not quite work in 8bpp
1477 * ### Piccolo..? Will this work?
1479 if (info->var.bits_per_pixel == 1)
1480 vga_wattr(cinfo->regbase, CL_AR33, xpix);
1482 cirrusfb_WaitBLT(cinfo->regbase);
1484 DPRINTK("EXIT\n");
1485 return 0;
1488 static int cirrusfb_blank(int blank_mode, struct fb_info *info)
1491 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
1492 * then the caller blanks by setting the CLUT (Color Look Up Table)
1493 * to all black. Return 0 if blanking succeeded, != 0 if un-/blanking
1494 * failed due to e.g. a video mode which doesn't support it.
1495 * Implements VESA suspend and powerdown modes on hardware that
1496 * supports disabling hsync/vsync:
1497 * blank_mode == 2: suspend vsync
1498 * blank_mode == 3: suspend hsync
1499 * blank_mode == 4: powerdown
1501 unsigned char val;
1502 struct cirrusfb_info *cinfo = info->par;
1503 int current_mode = cinfo->blank_mode;
1505 DPRINTK("ENTER, blank mode = %d\n", blank_mode);
1507 if (info->state != FBINFO_STATE_RUNNING ||
1508 current_mode == blank_mode) {
1509 DPRINTK("EXIT, returning 0\n");
1510 return 0;
1513 /* Undo current */
1514 if (current_mode == FB_BLANK_NORMAL ||
1515 current_mode == FB_BLANK_UNBLANK) {
1516 /* unblank the screen */
1517 val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1518 /* clear "FullBandwidth" bit */
1519 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val & 0xdf);
1520 /* and undo VESA suspend trickery */
1521 vga_wgfx(cinfo->regbase, CL_GRE, 0x00);
1524 /* set new */
1525 if (blank_mode > FB_BLANK_NORMAL) {
1526 /* blank the screen */
1527 val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1528 /* set "FullBandwidth" bit */
1529 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val | 0x20);
1532 switch (blank_mode) {
1533 case FB_BLANK_UNBLANK:
1534 case FB_BLANK_NORMAL:
1535 break;
1536 case FB_BLANK_VSYNC_SUSPEND:
1537 vga_wgfx(cinfo->regbase, CL_GRE, 0x04);
1538 break;
1539 case FB_BLANK_HSYNC_SUSPEND:
1540 vga_wgfx(cinfo->regbase, CL_GRE, 0x02);
1541 break;
1542 case FB_BLANK_POWERDOWN:
1543 vga_wgfx(cinfo->regbase, CL_GRE, 0x06);
1544 break;
1545 default:
1546 DPRINTK("EXIT, returning 1\n");
1547 return 1;
1550 cinfo->blank_mode = blank_mode;
1551 DPRINTK("EXIT, returning 0\n");
1553 /* Let fbcon do a soft blank for us */
1554 return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
1556 /**** END Hardware specific Routines **************************************/
1557 /****************************************************************************/
1558 /**** BEGIN Internal Routines ***********************************************/
1560 static void init_vgachip(struct fb_info *info)
1562 struct cirrusfb_info *cinfo = info->par;
1563 const struct cirrusfb_board_info_rec *bi;
1565 DPRINTK("ENTER\n");
1567 assert(cinfo != NULL);
1569 bi = &cirrusfb_board_info[cinfo->btype];
1571 /* reset board globally */
1572 switch (cinfo->btype) {
1573 case BT_PICCOLO:
1574 WSFR(cinfo, 0x01);
1575 udelay(500);
1576 WSFR(cinfo, 0x51);
1577 udelay(500);
1578 break;
1579 case BT_PICASSO:
1580 WSFR2(cinfo, 0xff);
1581 udelay(500);
1582 break;
1583 case BT_SD64:
1584 case BT_SPECTRUM:
1585 WSFR(cinfo, 0x1f);
1586 udelay(500);
1587 WSFR(cinfo, 0x4f);
1588 udelay(500);
1589 break;
1590 case BT_PICASSO4:
1591 /* disable flickerfixer */
1592 vga_wcrt(cinfo->regbase, CL_CRT51, 0x00);
1593 mdelay(100);
1594 /* from Klaus' NetBSD driver: */
1595 vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
1596 /* put blitter into 542x compat */
1597 vga_wgfx(cinfo->regbase, CL_GR33, 0x00);
1598 /* mode */
1599 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1600 break;
1602 case BT_GD5480:
1603 /* from Klaus' NetBSD driver: */
1604 vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
1605 break;
1607 case BT_ALPINE:
1608 /* Nothing to do to reset the board. */
1609 break;
1611 default:
1612 printk(KERN_ERR "cirrusfb: Warning: Unknown board type\n");
1613 break;
1616 /* make sure RAM size set by this point */
1617 assert(info->screen_size > 0);
1619 /* the P4 is not fully initialized here; I rely on it having been */
1620 /* inited under AmigaOS already, which seems to work just fine */
1621 /* (Klaus advised to do it this way) */
1623 if (cinfo->btype != BT_PICASSO4) {
1624 WGen(cinfo, CL_VSSM, 0x10); /* EGS: 0x16 */
1625 WGen(cinfo, CL_POS102, 0x01);
1626 WGen(cinfo, CL_VSSM, 0x08); /* EGS: 0x0e */
1628 if (cinfo->btype != BT_SD64)
1629 WGen(cinfo, CL_VSSM2, 0x01);
1631 /* reset sequencer logic */
1632 vga_wseq(cinfo->regbase, CL_SEQR0, 0x03);
1634 /* FullBandwidth (video off) and 8/9 dot clock */
1635 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21);
1636 /* polarity (-/-), disable access to display memory,
1637 * VGA_CRTC_START_HI base address: color
1639 WGen(cinfo, VGA_MIS_W, 0xc1);
1641 /* "magic cookie" - doesn't make any sense to me.. */
1642 /* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */
1643 /* unlock all extension registers */
1644 vga_wseq(cinfo->regbase, CL_SEQR6, 0x12);
1646 /* reset blitter */
1647 vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
1649 switch (cinfo->btype) {
1650 case BT_GD5480:
1651 vga_wseq(cinfo->regbase, CL_SEQRF, 0x98);
1652 break;
1653 case BT_ALPINE:
1654 break;
1655 case BT_SD64:
1656 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8);
1657 break;
1658 default:
1659 vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f);
1660 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb0);
1661 break;
1664 /* plane mask: nothing */
1665 vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1666 /* character map select: doesn't even matter in gx mode */
1667 vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00);
1668 /* memory mode: chain-4, no odd/even, ext. memory */
1669 vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0e);
1671 /* controller-internal base address of video memory */
1672 if (bi->init_sr07)
1673 vga_wseq(cinfo->regbase, CL_SEQR7, bi->sr07);
1675 /* vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */
1676 /* EEPROM control: shouldn't be necessary to write to this at all.. */
1678 /* graphics cursor X position (incomplete; position gives rem. 3 bits */
1679 vga_wseq(cinfo->regbase, CL_SEQR10, 0x00);
1680 /* graphics cursor Y position (..."... ) */
1681 vga_wseq(cinfo->regbase, CL_SEQR11, 0x00);
1682 /* graphics cursor attributes */
1683 vga_wseq(cinfo->regbase, CL_SEQR12, 0x00);
1684 /* graphics cursor pattern address */
1685 vga_wseq(cinfo->regbase, CL_SEQR13, 0x00);
1687 /* writing these on a P4 might give problems.. */
1688 if (cinfo->btype != BT_PICASSO4) {
1689 /* configuration readback and ext. color */
1690 vga_wseq(cinfo->regbase, CL_SEQR17, 0x00);
1691 /* signature generator */
1692 vga_wseq(cinfo->regbase, CL_SEQR18, 0x02);
1695 /* MCLK select etc. */
1696 if (bi->init_sr1f)
1697 vga_wseq(cinfo->regbase, CL_SEQR1F, bi->sr1f);
1699 /* Screen A preset row scan: none */
1700 vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00);
1701 /* Text cursor start: disable text cursor */
1702 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20);
1703 /* Text cursor end: - */
1704 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00);
1705 /* Screen start address high: 0 */
1706 vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, 0x00);
1707 /* Screen start address low: 0 */
1708 vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, 0x00);
1709 /* text cursor location high: 0 */
1710 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00);
1711 /* text cursor location low: 0 */
1712 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00);
1714 /* Underline Row scanline: - */
1715 vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00);
1716 /* mode control: timing enable, byte mode, no compat modes */
1717 vga_wcrt(cinfo->regbase, VGA_CRTC_MODE, 0xc3);
1718 /* Line Compare: not needed */
1719 vga_wcrt(cinfo->regbase, VGA_CRTC_LINE_COMPARE, 0x00);
1720 /* ### add 0x40 for text modes with > 30 MHz pixclock */
1721 /* ext. display controls: ext.adr. wrap */
1722 vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02);
1724 /* Set/Reset registes: - */
1725 vga_wgfx(cinfo->regbase, VGA_GFX_SR_VALUE, 0x00);
1726 /* Set/Reset enable: - */
1727 vga_wgfx(cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00);
1728 /* Color Compare: - */
1729 vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00);
1730 /* Data Rotate: - */
1731 vga_wgfx(cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00);
1732 /* Read Map Select: - */
1733 vga_wgfx(cinfo->regbase, VGA_GFX_PLANE_READ, 0x00);
1734 /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
1735 vga_wgfx(cinfo->regbase, VGA_GFX_MODE, 0x00);
1736 /* Miscellaneous: memory map base address, graphics mode */
1737 vga_wgfx(cinfo->regbase, VGA_GFX_MISC, 0x01);
1738 /* Color Don't care: involve all planes */
1739 vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f);
1740 /* Bit Mask: no mask at all */
1741 vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff);
1742 if (cinfo->btype == BT_ALPINE)
1743 /* (5434 can't have bit 3 set for bitblt) */
1744 vga_wgfx(cinfo->regbase, CL_GRB, 0x20);
1745 else
1746 /* Graphics controller mode extensions: finer granularity,
1747 * 8byte data latches
1749 vga_wgfx(cinfo->regbase, CL_GRB, 0x28);
1751 vga_wgfx(cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */
1752 vga_wgfx(cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */
1753 vga_wgfx(cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */
1754 /* Background color byte 1: - */
1755 /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); */
1756 /* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
1758 /* Attribute Controller palette registers: "identity mapping" */
1759 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE0, 0x00);
1760 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
1761 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
1762 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
1763 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
1764 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
1765 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
1766 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
1767 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
1768 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
1769 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
1770 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
1771 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
1772 vga_wattr(cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
1773 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
1774 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
1776 /* Attribute Controller mode: graphics mode */
1777 vga_wattr(cinfo->regbase, VGA_ATC_MODE, 0x01);
1778 /* Overscan color reg.: reg. 0 */
1779 vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00);
1780 /* Color Plane enable: Enable all 4 planes */
1781 vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f);
1782 /* ### vga_wattr(cinfo->regbase, CL_AR33, 0x00); * Pixel Panning: - */
1783 /* Color Select: - */
1784 vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00);
1786 WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
1788 if (cinfo->btype != BT_ALPINE && cinfo->btype != BT_GD5480)
1789 /* polarity (-/-), enable display mem,
1790 * VGA_CRTC_START_HI i/o base = color
1792 WGen(cinfo, VGA_MIS_W, 0xc3);
1794 /* BLT Start/status: Blitter reset */
1795 vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
1796 /* - " - : "end-of-reset" */
1797 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1799 /* misc... */
1800 WHDR(cinfo, 0); /* Hidden DAC register: - */
1802 DPRINTK("EXIT\n");
1803 return;
1806 static void switch_monitor(struct cirrusfb_info *cinfo, int on)
1808 #ifdef CONFIG_ZORRO /* only works on Zorro boards */
1809 static int IsOn = 0; /* XXX not ok for multiple boards */
1811 DPRINTK("ENTER\n");
1813 if (cinfo->btype == BT_PICASSO4)
1814 return; /* nothing to switch */
1815 if (cinfo->btype == BT_ALPINE)
1816 return; /* nothing to switch */
1817 if (cinfo->btype == BT_GD5480)
1818 return; /* nothing to switch */
1819 if (cinfo->btype == BT_PICASSO) {
1820 if ((on && !IsOn) || (!on && IsOn))
1821 WSFR(cinfo, 0xff);
1823 DPRINTK("EXIT\n");
1824 return;
1826 if (on) {
1827 switch (cinfo->btype) {
1828 case BT_SD64:
1829 WSFR(cinfo, cinfo->SFR | 0x21);
1830 break;
1831 case BT_PICCOLO:
1832 WSFR(cinfo, cinfo->SFR | 0x28);
1833 break;
1834 case BT_SPECTRUM:
1835 WSFR(cinfo, 0x6f);
1836 break;
1837 default: /* do nothing */ break;
1839 } else {
1840 switch (cinfo->btype) {
1841 case BT_SD64:
1842 WSFR(cinfo, cinfo->SFR & 0xde);
1843 break;
1844 case BT_PICCOLO:
1845 WSFR(cinfo, cinfo->SFR & 0xd7);
1846 break;
1847 case BT_SPECTRUM:
1848 WSFR(cinfo, 0x4f);
1849 break;
1850 default: /* do nothing */ break;
1854 DPRINTK("EXIT\n");
1855 #endif /* CONFIG_ZORRO */
1858 /******************************************/
1859 /* Linux 2.6-style accelerated functions */
1860 /******************************************/
1862 static void cirrusfb_fillrect(struct fb_info *info,
1863 const struct fb_fillrect *region)
1865 struct fb_fillrect modded;
1866 int vxres, vyres;
1867 struct cirrusfb_info *cinfo = info->par;
1868 int m = info->var.bits_per_pixel;
1869 u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
1870 cinfo->pseudo_palette[region->color] : region->color;
1872 if (info->state != FBINFO_STATE_RUNNING)
1873 return;
1874 if (info->flags & FBINFO_HWACCEL_DISABLED) {
1875 cfb_fillrect(info, region);
1876 return;
1879 vxres = info->var.xres_virtual;
1880 vyres = info->var.yres_virtual;
1882 memcpy(&modded, region, sizeof(struct fb_fillrect));
1884 if (!modded.width || !modded.height ||
1885 modded.dx >= vxres || modded.dy >= vyres)
1886 return;
1888 if (modded.dx + modded.width > vxres)
1889 modded.width = vxres - modded.dx;
1890 if (modded.dy + modded.height > vyres)
1891 modded.height = vyres - modded.dy;
1893 cirrusfb_RectFill(cinfo->regbase,
1894 info->var.bits_per_pixel,
1895 (region->dx * m) / 8, region->dy,
1896 (region->width * m) / 8, region->height,
1897 color,
1898 info->fix.line_length);
1901 static void cirrusfb_copyarea(struct fb_info *info,
1902 const struct fb_copyarea *area)
1904 struct fb_copyarea modded;
1905 u32 vxres, vyres;
1906 struct cirrusfb_info *cinfo = info->par;
1907 int m = info->var.bits_per_pixel;
1909 if (info->state != FBINFO_STATE_RUNNING)
1910 return;
1911 if (info->flags & FBINFO_HWACCEL_DISABLED) {
1912 cfb_copyarea(info, area);
1913 return;
1916 vxres = info->var.xres_virtual;
1917 vyres = info->var.yres_virtual;
1918 memcpy(&modded, area, sizeof(struct fb_copyarea));
1920 if (!modded.width || !modded.height ||
1921 modded.sx >= vxres || modded.sy >= vyres ||
1922 modded.dx >= vxres || modded.dy >= vyres)
1923 return;
1925 if (modded.sx + modded.width > vxres)
1926 modded.width = vxres - modded.sx;
1927 if (modded.dx + modded.width > vxres)
1928 modded.width = vxres - modded.dx;
1929 if (modded.sy + modded.height > vyres)
1930 modded.height = vyres - modded.sy;
1931 if (modded.dy + modded.height > vyres)
1932 modded.height = vyres - modded.dy;
1934 cirrusfb_BitBLT(cinfo->regbase, info->var.bits_per_pixel,
1935 (area->sx * m) / 8, area->sy,
1936 (area->dx * m) / 8, area->dy,
1937 (area->width * m) / 8, area->height,
1938 info->fix.line_length);
1942 static void cirrusfb_imageblit(struct fb_info *info,
1943 const struct fb_image *image)
1945 struct cirrusfb_info *cinfo = info->par;
1947 cirrusfb_WaitBLT(cinfo->regbase);
1948 cfb_imageblit(info, image);
1951 #ifdef CONFIG_PPC_PREP
1952 #define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
1953 #define PREP_IO_BASE ((volatile unsigned char *) 0x80000000)
1954 static void get_prep_addrs(unsigned long *display, unsigned long *registers)
1956 DPRINTK("ENTER\n");
1958 *display = PREP_VIDEO_BASE;
1959 *registers = (unsigned long) PREP_IO_BASE;
1961 DPRINTK("EXIT\n");
1964 #endif /* CONFIG_PPC_PREP */
1966 #ifdef CONFIG_PCI
1967 static int release_io_ports;
1969 /* Pulled the logic from XFree86 Cirrus driver to get the memory size,
1970 * based on the DRAM bandwidth bit and DRAM bank switching bit. This
1971 * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
1972 * seem to have. */
1973 static unsigned int __devinit cirrusfb_get_memsize(u8 __iomem *regbase)
1975 unsigned long mem;
1976 unsigned char SRF;
1978 DPRINTK("ENTER\n");
1980 SRF = vga_rseq(regbase, CL_SEQRF);
1981 switch ((SRF & 0x18)) {
1982 case 0x08:
1983 mem = 512 * 1024;
1984 break;
1985 case 0x10:
1986 mem = 1024 * 1024;
1987 break;
1988 /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory
1989 * on the 5430.
1991 case 0x18:
1992 mem = 2048 * 1024;
1993 break;
1994 default:
1995 printk(KERN_WARNING "CLgenfb: Unknown memory size!\n");
1996 mem = 1024 * 1024;
1998 if (SRF & 0x80)
1999 /* If DRAM bank switching is enabled, there must be twice as much
2000 * memory installed. (4MB on the 5434)
2002 mem *= 2;
2004 /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
2006 DPRINTK("EXIT\n");
2007 return mem;
2010 static void get_pci_addrs(const struct pci_dev *pdev,
2011 unsigned long *display, unsigned long *registers)
2013 assert(pdev != NULL);
2014 assert(display != NULL);
2015 assert(registers != NULL);
2017 DPRINTK("ENTER\n");
2019 *display = 0;
2020 *registers = 0;
2022 /* This is a best-guess for now */
2024 if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
2025 *display = pci_resource_start(pdev, 1);
2026 *registers = pci_resource_start(pdev, 0);
2027 } else {
2028 *display = pci_resource_start(pdev, 0);
2029 *registers = pci_resource_start(pdev, 1);
2032 assert(*display != 0);
2034 DPRINTK("EXIT\n");
2037 static void cirrusfb_pci_unmap(struct fb_info *info)
2039 struct pci_dev *pdev = to_pci_dev(info->device);
2041 iounmap(info->screen_base);
2042 #if 0 /* if system didn't claim this region, we would... */
2043 release_mem_region(0xA0000, 65535);
2044 #endif
2045 if (release_io_ports)
2046 release_region(0x3C0, 32);
2047 pci_release_regions(pdev);
2049 #endif /* CONFIG_PCI */
2051 #ifdef CONFIG_ZORRO
2052 static void cirrusfb_zorro_unmap(struct fb_info *info)
2054 struct cirrusfb_info *cinfo = info->par;
2055 struct zorro_dev *zdev = to_zorro_dev(info->device);
2057 zorro_release_device(zdev);
2059 if (cinfo->btype == BT_PICASSO4) {
2060 cinfo->regbase -= 0x600000;
2061 iounmap((void *)cinfo->regbase);
2062 iounmap(info->screen_base);
2063 } else {
2064 if (zorro_resource_start(zdev) > 0x01000000)
2065 iounmap(info->screen_base);
2068 #endif /* CONFIG_ZORRO */
2070 static int __devinit cirrusfb_set_fbinfo(struct fb_info *info)
2072 struct cirrusfb_info *cinfo = info->par;
2073 struct fb_var_screeninfo *var = &info->var;
2075 info->pseudo_palette = cinfo->pseudo_palette;
2076 info->flags = FBINFO_DEFAULT
2077 | FBINFO_HWACCEL_XPAN
2078 | FBINFO_HWACCEL_YPAN
2079 | FBINFO_HWACCEL_FILLRECT
2080 | FBINFO_HWACCEL_COPYAREA;
2081 if (noaccel)
2082 info->flags |= FBINFO_HWACCEL_DISABLED;
2083 info->fbops = &cirrusfb_ops;
2084 if (cinfo->btype == BT_GD5480) {
2085 if (var->bits_per_pixel == 16)
2086 info->screen_base += 1 * MB_;
2087 if (var->bits_per_pixel == 32)
2088 info->screen_base += 2 * MB_;
2091 /* Fill fix common fields */
2092 strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
2093 sizeof(info->fix.id));
2095 /* monochrome: only 1 memory plane */
2096 /* 8 bit and above: Use whole memory area */
2097 info->fix.smem_len = info->screen_size;
2098 if (var->bits_per_pixel == 1)
2099 info->fix.smem_len /= 4;
2100 info->fix.type_aux = 0;
2101 info->fix.xpanstep = 1;
2102 info->fix.ypanstep = 1;
2103 info->fix.ywrapstep = 0;
2105 /* FIXME: map region at 0xB8000 if available, fill in here */
2106 info->fix.mmio_len = 0;
2107 info->fix.accel = FB_ACCEL_NONE;
2109 fb_alloc_cmap(&info->cmap, 256, 0);
2111 return 0;
2114 static int __devinit cirrusfb_register(struct fb_info *info)
2116 struct cirrusfb_info *cinfo = info->par;
2117 int err;
2118 enum cirrus_board btype;
2120 DPRINTK("ENTER\n");
2122 printk(KERN_INFO "cirrusfb: Driver for Cirrus Logic based "
2123 "graphic boards, v" CIRRUSFB_VERSION "\n");
2125 btype = cinfo->btype;
2127 /* sanity checks */
2128 assert(btype != BT_NONE);
2130 /* set all the vital stuff */
2131 cirrusfb_set_fbinfo(info);
2133 DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base);
2135 err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
2136 if (!err) {
2137 DPRINTK("wrong initial video mode\n");
2138 err = -EINVAL;
2139 goto err_dealloc_cmap;
2142 info->var.activate = FB_ACTIVATE_NOW;
2144 err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
2145 if (err < 0) {
2146 /* should never happen */
2147 DPRINTK("choking on default var... umm, no good.\n");
2148 goto err_dealloc_cmap;
2151 err = register_framebuffer(info);
2152 if (err < 0) {
2153 printk(KERN_ERR "cirrusfb: could not register "
2154 "fb device; err = %d!\n", err);
2155 goto err_dealloc_cmap;
2158 DPRINTK("EXIT, returning 0\n");
2159 return 0;
2161 err_dealloc_cmap:
2162 fb_dealloc_cmap(&info->cmap);
2163 cinfo->unmap(info);
2164 framebuffer_release(info);
2165 return err;
2168 static void __devexit cirrusfb_cleanup(struct fb_info *info)
2170 struct cirrusfb_info *cinfo = info->par;
2171 DPRINTK("ENTER\n");
2173 switch_monitor(cinfo, 0);
2175 unregister_framebuffer(info);
2176 fb_dealloc_cmap(&info->cmap);
2177 printk("Framebuffer unregistered\n");
2178 cinfo->unmap(info);
2179 framebuffer_release(info);
2181 DPRINTK("EXIT\n");
2184 #ifdef CONFIG_PCI
2185 static int __devinit cirrusfb_pci_register(struct pci_dev *pdev,
2186 const struct pci_device_id *ent)
2188 struct cirrusfb_info *cinfo;
2189 struct fb_info *info;
2190 enum cirrus_board btype;
2191 unsigned long board_addr, board_size;
2192 int ret;
2194 ret = pci_enable_device(pdev);
2195 if (ret < 0) {
2196 printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
2197 goto err_out;
2200 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev);
2201 if (!info) {
2202 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2203 ret = -ENOMEM;
2204 goto err_disable;
2207 cinfo = info->par;
2208 cinfo->btype = btype = (enum cirrus_board) ent->driver_data;
2210 DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n",
2211 pdev->resource[0].start, btype);
2212 DPRINTK(" base address 1 is 0x%x\n", pdev->resource[1].start);
2214 if (isPReP) {
2215 pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, 0x00000000);
2216 #ifdef CONFIG_PPC_PREP
2217 get_prep_addrs(&board_addr, &info->fix.mmio_start);
2218 #endif
2219 /* PReP dies if we ioremap the IO registers, but it works w/out... */
2220 cinfo->regbase = (char __iomem *) info->fix.mmio_start;
2221 } else {
2222 DPRINTK("Attempt to get PCI info for Cirrus Graphics Card\n");
2223 get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start);
2224 /* FIXME: this forces VGA. alternatives? */
2225 cinfo->regbase = NULL;
2228 DPRINTK("Board address: 0x%lx, register address: 0x%lx\n",
2229 board_addr, info->fix.mmio_start);
2231 board_size = (btype == BT_GD5480) ?
2232 32 * MB_ : cirrusfb_get_memsize(cinfo->regbase);
2234 ret = pci_request_regions(pdev, "cirrusfb");
2235 if (ret < 0) {
2236 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, "
2237 "abort\n",
2238 board_addr);
2239 goto err_release_fb;
2241 #if 0 /* if the system didn't claim this region, we would... */
2242 if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
2243 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n"
2245 0xA0000L);
2246 ret = -EBUSY;
2247 goto err_release_regions;
2249 #endif
2250 if (request_region(0x3C0, 32, "cirrusfb"))
2251 release_io_ports = 1;
2253 info->screen_base = ioremap(board_addr, board_size);
2254 if (!info->screen_base) {
2255 ret = -EIO;
2256 goto err_release_legacy;
2259 info->fix.smem_start = board_addr;
2260 info->screen_size = board_size;
2261 cinfo->unmap = cirrusfb_pci_unmap;
2263 printk(KERN_INFO "RAM (%lu kB) at 0x%lx, Cirrus "
2264 "Logic chipset on PCI bus\n",
2265 info->screen_size >> 10, board_addr);
2266 pci_set_drvdata(pdev, info);
2268 ret = cirrusfb_register(info);
2269 if (ret)
2270 iounmap(info->screen_base);
2271 return ret;
2273 err_release_legacy:
2274 if (release_io_ports)
2275 release_region(0x3C0, 32);
2276 #if 0
2277 release_mem_region(0xA0000, 65535);
2278 err_release_regions:
2279 #endif
2280 pci_release_regions(pdev);
2281 err_release_fb:
2282 framebuffer_release(info);
2283 err_disable:
2284 err_out:
2285 return ret;
2288 static void __devexit cirrusfb_pci_unregister(struct pci_dev *pdev)
2290 struct fb_info *info = pci_get_drvdata(pdev);
2291 DPRINTK("ENTER\n");
2293 cirrusfb_cleanup(info);
2295 DPRINTK("EXIT\n");
2298 static struct pci_driver cirrusfb_pci_driver = {
2299 .name = "cirrusfb",
2300 .id_table = cirrusfb_pci_table,
2301 .probe = cirrusfb_pci_register,
2302 .remove = __devexit_p(cirrusfb_pci_unregister),
2303 #ifdef CONFIG_PM
2304 #if 0
2305 .suspend = cirrusfb_pci_suspend,
2306 .resume = cirrusfb_pci_resume,
2307 #endif
2308 #endif
2310 #endif /* CONFIG_PCI */
2312 #ifdef CONFIG_ZORRO
2313 static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
2314 const struct zorro_device_id *ent)
2316 struct cirrusfb_info *cinfo;
2317 struct fb_info *info;
2318 enum cirrus_board btype;
2319 struct zorro_dev *z2 = NULL;
2320 unsigned long board_addr, board_size, size;
2321 int ret;
2323 btype = ent->driver_data;
2324 if (cirrusfb_zorro_table2[btype].id2)
2325 z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
2326 size = cirrusfb_zorro_table2[btype].size;
2327 printk(KERN_INFO "cirrusfb: %s board detected; ",
2328 cirrusfb_board_info[btype].name);
2330 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
2331 if (!info) {
2332 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2333 ret = -ENOMEM;
2334 goto err_out;
2337 cinfo = info->par;
2338 cinfo->btype = btype;
2340 assert(z);
2341 assert(btype != BT_NONE);
2343 board_addr = zorro_resource_start(z);
2344 board_size = zorro_resource_len(z);
2345 info->screen_size = size;
2347 if (!zorro_request_device(z, "cirrusfb")) {
2348 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, "
2349 "abort\n",
2350 board_addr);
2351 ret = -EBUSY;
2352 goto err_release_fb;
2355 printk(" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr);
2357 ret = -EIO;
2359 if (btype == BT_PICASSO4) {
2360 printk(KERN_INFO " REG at $%lx\n", board_addr + 0x600000);
2362 /* To be precise, for the P4 this is not the */
2363 /* begin of the board, but the begin of RAM. */
2364 /* for P4, map in its address space in 2 chunks (### TEST! ) */
2365 /* (note the ugly hardcoded 16M number) */
2366 cinfo->regbase = ioremap(board_addr, 16777216);
2367 if (!cinfo->regbase)
2368 goto err_release_region;
2370 DPRINTK("cirrusfb: Virtual address for board set to: $%p\n",
2371 cinfo->regbase);
2372 cinfo->regbase += 0x600000;
2373 info->fix.mmio_start = board_addr + 0x600000;
2375 info->fix.smem_start = board_addr + 16777216;
2376 info->screen_base = ioremap(info->fix.smem_start, 16777216);
2377 if (!info->screen_base)
2378 goto err_unmap_regbase;
2379 } else {
2380 printk(KERN_INFO " REG at $%lx\n",
2381 (unsigned long) z2->resource.start);
2383 info->fix.smem_start = board_addr;
2384 if (board_addr > 0x01000000)
2385 info->screen_base = ioremap(board_addr, board_size);
2386 else
2387 info->screen_base = (caddr_t) ZTWO_VADDR(board_addr);
2388 if (!info->screen_base)
2389 goto err_release_region;
2391 /* set address for REG area of board */
2392 cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start);
2393 info->fix.mmio_start = z2->resource.start;
2395 DPRINTK("cirrusfb: Virtual address for board set to: $%p\n",
2396 cinfo->regbase);
2398 cinfo->unmap = cirrusfb_zorro_unmap;
2400 printk(KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
2401 zorro_set_drvdata(z, info);
2403 ret = cirrusfb_register(info);
2404 if (ret) {
2405 if (btype == BT_PICASSO4) {
2406 iounmap(info->screen_base);
2407 iounmap(cinfo->regbase - 0x600000);
2408 } else if (board_addr > 0x01000000)
2409 iounmap(info->screen_base);
2411 return ret;
2413 err_unmap_regbase:
2414 /* Parental advisory: explicit hack */
2415 iounmap(cinfo->regbase - 0x600000);
2416 err_release_region:
2417 release_region(board_addr, board_size);
2418 err_release_fb:
2419 framebuffer_release(info);
2420 err_out:
2421 return ret;
2424 void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
2426 struct fb_info *info = zorro_get_drvdata(z);
2427 DPRINTK("ENTER\n");
2429 cirrusfb_cleanup(info);
2431 DPRINTK("EXIT\n");
2434 static struct zorro_driver cirrusfb_zorro_driver = {
2435 .name = "cirrusfb",
2436 .id_table = cirrusfb_zorro_table,
2437 .probe = cirrusfb_zorro_register,
2438 .remove = __devexit_p(cirrusfb_zorro_unregister),
2440 #endif /* CONFIG_ZORRO */
2442 static int __init cirrusfb_init(void)
2444 int error = 0;
2446 #ifndef MODULE
2447 char *option = NULL;
2449 if (fb_get_options("cirrusfb", &option))
2450 return -ENODEV;
2451 cirrusfb_setup(option);
2452 #endif
2454 #ifdef CONFIG_ZORRO
2455 error |= zorro_register_driver(&cirrusfb_zorro_driver);
2456 #endif
2457 #ifdef CONFIG_PCI
2458 error |= pci_register_driver(&cirrusfb_pci_driver);
2459 #endif
2460 return error;
2463 #ifndef MODULE
2464 static int __init cirrusfb_setup(char *options) {
2465 char *this_opt;
2467 DPRINTK("ENTER\n");
2469 if (!options || !*options)
2470 return 0;
2472 while ((this_opt = strsep(&options, ",")) != NULL) {
2473 if (!*this_opt)
2474 continue;
2476 DPRINTK("cirrusfb_setup: option '%s'\n", this_opt);
2478 if (!strcmp(this_opt, "noaccel"))
2479 noaccel = 1;
2480 else if (!strncmp(this_opt, "mode:", 5))
2481 mode_option = this_opt + 5;
2482 else
2483 mode_option = this_opt;
2485 return 0;
2487 #endif
2490 * Modularization
2493 MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
2494 MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
2495 MODULE_LICENSE("GPL");
2497 static void __exit cirrusfb_exit(void)
2499 #ifdef CONFIG_PCI
2500 pci_unregister_driver(&cirrusfb_pci_driver);
2501 #endif
2502 #ifdef CONFIG_ZORRO
2503 zorro_unregister_driver(&cirrusfb_zorro_driver);
2504 #endif
2507 module_init(cirrusfb_init);
2509 module_param(mode_option, charp, 0);
2510 MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
2511 module_param(noaccel, bool, 0);
2512 MODULE_PARM_DESC(noaccel, "Disable acceleration");
2514 #ifdef MODULE
2515 module_exit(cirrusfb_exit);
2516 #endif
2518 /**********************************************************************/
2519 /* about the following functions - I have used the same names for the */
2520 /* functions as Markus Wild did in his Retina driver for NetBSD as */
2521 /* they just made sense for this purpose. Apart from that, I wrote */
2522 /* these functions myself. */
2523 /**********************************************************************/
2525 /*** WGen() - write into one of the external/general registers ***/
2526 static void WGen(const struct cirrusfb_info *cinfo,
2527 int regnum, unsigned char val)
2529 unsigned long regofs = 0;
2531 if (cinfo->btype == BT_PICASSO) {
2532 /* Picasso II specific hack */
2533 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2534 regnum == CL_VSSM2) */
2535 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2536 regofs = 0xfff;
2539 vga_w(cinfo->regbase, regofs + regnum, val);
2542 /*** RGen() - read out one of the external/general registers ***/
2543 static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum)
2545 unsigned long regofs = 0;
2547 if (cinfo->btype == BT_PICASSO) {
2548 /* Picasso II specific hack */
2549 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2550 regnum == CL_VSSM2) */
2551 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2552 regofs = 0xfff;
2555 return vga_r(cinfo->regbase, regofs + regnum);
2558 /*** AttrOn() - turn on VideoEnable for Attribute controller ***/
2559 static void AttrOn(const struct cirrusfb_info *cinfo)
2561 assert(cinfo != NULL);
2563 DPRINTK("ENTER\n");
2565 if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) {
2566 /* if we're just in "write value" mode, write back the */
2567 /* same value as before to not modify anything */
2568 vga_w(cinfo->regbase, VGA_ATT_IW,
2569 vga_r(cinfo->regbase, VGA_ATT_R));
2571 /* turn on video bit */
2572 /* vga_w(cinfo->regbase, VGA_ATT_IW, 0x20); */
2573 vga_w(cinfo->regbase, VGA_ATT_IW, 0x33);
2575 /* dummy write on Reg0 to be on "write index" mode next time */
2576 vga_w(cinfo->regbase, VGA_ATT_IW, 0x00);
2578 DPRINTK("EXIT\n");
2581 /*** WHDR() - write into the Hidden DAC register ***/
2582 /* as the HDR is the only extension register that requires special treatment
2583 * (the other extension registers are accessible just like the "ordinary"
2584 * registers of their functional group) here is a specialized routine for
2585 * accessing the HDR
2587 static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val)
2589 unsigned char dummy;
2591 if (cinfo->btype == BT_PICASSO) {
2592 /* Klaus' hint for correct access to HDR on some boards */
2593 /* first write 0 to pixel mask (3c6) */
2594 WGen(cinfo, VGA_PEL_MSK, 0x00);
2595 udelay(200);
2596 /* next read dummy from pixel address (3c8) */
2597 dummy = RGen(cinfo, VGA_PEL_IW);
2598 udelay(200);
2600 /* now do the usual stuff to access the HDR */
2602 dummy = RGen(cinfo, VGA_PEL_MSK);
2603 udelay(200);
2604 dummy = RGen(cinfo, VGA_PEL_MSK);
2605 udelay(200);
2606 dummy = RGen(cinfo, VGA_PEL_MSK);
2607 udelay(200);
2608 dummy = RGen(cinfo, VGA_PEL_MSK);
2609 udelay(200);
2611 WGen(cinfo, VGA_PEL_MSK, val);
2612 udelay(200);
2614 if (cinfo->btype == BT_PICASSO) {
2615 /* now first reset HDR access counter */
2616 dummy = RGen(cinfo, VGA_PEL_IW);
2617 udelay(200);
2619 /* and at the end, restore the mask value */
2620 /* ## is this mask always 0xff? */
2621 WGen(cinfo, VGA_PEL_MSK, 0xff);
2622 udelay(200);
2626 /*** WSFR() - write to the "special function register" (SFR) ***/
2627 static void WSFR(struct cirrusfb_info *cinfo, unsigned char val)
2629 #ifdef CONFIG_ZORRO
2630 assert(cinfo->regbase != NULL);
2631 cinfo->SFR = val;
2632 z_writeb(val, cinfo->regbase + 0x8000);
2633 #endif
2636 /* The Picasso has a second register for switching the monitor bit */
2637 static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val)
2639 #ifdef CONFIG_ZORRO
2640 /* writing an arbitrary value to this one causes the monitor switcher */
2641 /* to flip to Amiga display */
2642 assert(cinfo->regbase != NULL);
2643 cinfo->SFR = val;
2644 z_writeb(val, cinfo->regbase + 0x9000);
2645 #endif
2648 /*** WClut - set CLUT entry (range: 0..63) ***/
2649 static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
2650 unsigned char green, unsigned char blue)
2652 unsigned int data = VGA_PEL_D;
2654 /* address write mode register is not translated.. */
2655 vga_w(cinfo->regbase, VGA_PEL_IW, regnum);
2657 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2658 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2659 /* but DAC data register IS, at least for Picasso II */
2660 if (cinfo->btype == BT_PICASSO)
2661 data += 0xfff;
2662 vga_w(cinfo->regbase, data, red);
2663 vga_w(cinfo->regbase, data, green);
2664 vga_w(cinfo->regbase, data, blue);
2665 } else {
2666 vga_w(cinfo->regbase, data, blue);
2667 vga_w(cinfo->regbase, data, green);
2668 vga_w(cinfo->regbase, data, red);
2672 #if 0
2673 /*** RClut - read CLUT entry (range 0..63) ***/
2674 static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
2675 unsigned char *green, unsigned char *blue)
2677 unsigned int data = VGA_PEL_D;
2679 vga_w(cinfo->regbase, VGA_PEL_IR, regnum);
2681 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2682 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2683 if (cinfo->btype == BT_PICASSO)
2684 data += 0xfff;
2685 *red = vga_r(cinfo->regbase, data);
2686 *green = vga_r(cinfo->regbase, data);
2687 *blue = vga_r(cinfo->regbase, data);
2688 } else {
2689 *blue = vga_r(cinfo->regbase, data);
2690 *green = vga_r(cinfo->regbase, data);
2691 *red = vga_r(cinfo->regbase, data);
2694 #endif
2696 /*******************************************************************
2697 cirrusfb_WaitBLT()
2699 Wait for the BitBLT engine to complete a possible earlier job
2700 *********************************************************************/
2702 /* FIXME: use interrupts instead */
2703 static void cirrusfb_WaitBLT(u8 __iomem *regbase)
2705 /* now busy-wait until we're done */
2706 while (vga_rgfx(regbase, CL_GR31) & 0x08)
2707 /* do nothing */ ;
2710 /*******************************************************************
2711 cirrusfb_BitBLT()
2713 perform accelerated "scrolling"
2714 ********************************************************************/
2716 static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
2717 u_short curx, u_short cury,
2718 u_short destx, u_short desty,
2719 u_short width, u_short height,
2720 u_short line_length)
2722 u_short nwidth, nheight;
2723 u_long nsrc, ndest;
2724 u_char bltmode;
2726 DPRINTK("ENTER\n");
2728 nwidth = width - 1;
2729 nheight = height - 1;
2731 bltmode = 0x00;
2732 /* if source adr < dest addr, do the Blt backwards */
2733 if (cury <= desty) {
2734 if (cury == desty) {
2735 /* if src and dest are on the same line, check x */
2736 if (curx < destx)
2737 bltmode |= 0x01;
2738 } else
2739 bltmode |= 0x01;
2741 if (!bltmode) {
2742 /* standard case: forward blitting */
2743 nsrc = (cury * line_length) + curx;
2744 ndest = (desty * line_length) + destx;
2745 } else {
2746 /* this means start addresses are at the end,
2747 * counting backwards
2749 nsrc = cury * line_length + curx +
2750 nheight * line_length + nwidth;
2751 ndest = desty * line_length + destx +
2752 nheight * line_length + nwidth;
2756 run-down of registers to be programmed:
2757 destination pitch
2758 source pitch
2759 BLT width/height
2760 source start
2761 destination start
2762 BLT mode
2763 BLT ROP
2764 VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color"
2765 start/stop
2768 cirrusfb_WaitBLT(regbase);
2770 /* pitch: set to line_length */
2771 /* dest pitch low */
2772 vga_wgfx(regbase, CL_GR24, line_length & 0xff);
2773 /* dest pitch hi */
2774 vga_wgfx(regbase, CL_GR25, line_length >> 8);
2775 /* source pitch low */
2776 vga_wgfx(regbase, CL_GR26, line_length & 0xff);
2777 /* source pitch hi */
2778 vga_wgfx(regbase, CL_GR27, line_length >> 8);
2780 /* BLT width: actual number of pixels - 1 */
2781 /* BLT width low */
2782 vga_wgfx(regbase, CL_GR20, nwidth & 0xff);
2783 /* BLT width hi */
2784 vga_wgfx(regbase, CL_GR21, nwidth >> 8);
2786 /* BLT height: actual number of lines -1 */
2787 /* BLT height low */
2788 vga_wgfx(regbase, CL_GR22, nheight & 0xff);
2789 /* BLT width hi */
2790 vga_wgfx(regbase, CL_GR23, nheight >> 8);
2792 /* BLT destination */
2793 /* BLT dest low */
2794 vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
2795 /* BLT dest mid */
2796 vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
2797 /* BLT dest hi */
2798 vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
2800 /* BLT source */
2801 /* BLT src low */
2802 vga_wgfx(regbase, CL_GR2C, (u_char) (nsrc & 0xff));
2803 /* BLT src mid */
2804 vga_wgfx(regbase, CL_GR2D, (u_char) (nsrc >> 8));
2805 /* BLT src hi */
2806 vga_wgfx(regbase, CL_GR2E, (u_char) (nsrc >> 16));
2808 /* BLT mode */
2809 vga_wgfx(regbase, CL_GR30, bltmode); /* BLT mode */
2811 /* BLT ROP: SrcCopy */
2812 vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */
2814 /* and finally: GO! */
2815 vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */
2817 DPRINTK("EXIT\n");
2820 /*******************************************************************
2821 cirrusfb_RectFill()
2823 perform accelerated rectangle fill
2824 ********************************************************************/
2826 static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
2827 u_short x, u_short y, u_short width, u_short height,
2828 u_char color, u_short line_length)
2830 u_short nwidth, nheight;
2831 u_long ndest;
2832 u_char op;
2834 DPRINTK("ENTER\n");
2836 nwidth = width - 1;
2837 nheight = height - 1;
2839 ndest = (y * line_length) + x;
2841 cirrusfb_WaitBLT(regbase);
2843 /* pitch: set to line_length */
2844 vga_wgfx(regbase, CL_GR24, line_length & 0xff); /* dest pitch low */
2845 vga_wgfx(regbase, CL_GR25, line_length >> 8); /* dest pitch hi */
2846 vga_wgfx(regbase, CL_GR26, line_length & 0xff); /* source pitch low */
2847 vga_wgfx(regbase, CL_GR27, line_length >> 8); /* source pitch hi */
2849 /* BLT width: actual number of pixels - 1 */
2850 vga_wgfx(regbase, CL_GR20, nwidth & 0xff); /* BLT width low */
2851 vga_wgfx(regbase, CL_GR21, nwidth >> 8); /* BLT width hi */
2853 /* BLT height: actual number of lines -1 */
2854 vga_wgfx(regbase, CL_GR22, nheight & 0xff); /* BLT height low */
2855 vga_wgfx(regbase, CL_GR23, nheight >> 8); /* BLT width hi */
2857 /* BLT destination */
2858 /* BLT dest low */
2859 vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
2860 /* BLT dest mid */
2861 vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
2862 /* BLT dest hi */
2863 vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
2865 /* BLT source: set to 0 (is a dummy here anyway) */
2866 vga_wgfx(regbase, CL_GR2C, 0x00); /* BLT src low */
2867 vga_wgfx(regbase, CL_GR2D, 0x00); /* BLT src mid */
2868 vga_wgfx(regbase, CL_GR2E, 0x00); /* BLT src hi */
2870 /* This is a ColorExpand Blt, using the */
2871 /* same color for foreground and background */
2872 vga_wgfx(regbase, VGA_GFX_SR_VALUE, color); /* foreground color */
2873 vga_wgfx(regbase, VGA_GFX_SR_ENABLE, color); /* background color */
2875 op = 0xc0;
2876 if (bits_per_pixel == 16) {
2877 vga_wgfx(regbase, CL_GR10, color); /* foreground color */
2878 vga_wgfx(regbase, CL_GR11, color); /* background color */
2879 op = 0x50;
2880 op = 0xd0;
2881 } else if (bits_per_pixel == 32) {
2882 vga_wgfx(regbase, CL_GR10, color); /* foreground color */
2883 vga_wgfx(regbase, CL_GR11, color); /* background color */
2884 vga_wgfx(regbase, CL_GR12, color); /* foreground color */
2885 vga_wgfx(regbase, CL_GR13, color); /* background color */
2886 vga_wgfx(regbase, CL_GR14, 0); /* foreground color */
2887 vga_wgfx(regbase, CL_GR15, 0); /* background color */
2888 op = 0x50;
2889 op = 0xf0;
2891 /* BLT mode: color expand, Enable 8x8 copy (faster?) */
2892 vga_wgfx(regbase, CL_GR30, op); /* BLT mode */
2894 /* BLT ROP: SrcCopy */
2895 vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */
2897 /* and finally: GO! */
2898 vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */
2900 DPRINTK("EXIT\n");
2903 /**************************************************************************
2904 * bestclock() - determine closest possible clock lower(?) than the
2905 * desired pixel clock
2906 **************************************************************************/
2907 static void bestclock(long freq, int *nom, int *den, int *div)
2909 int n, d;
2910 long h, diff;
2912 assert(nom != NULL);
2913 assert(den != NULL);
2914 assert(div != NULL);
2916 *nom = 0;
2917 *den = 0;
2918 *div = 0;
2920 DPRINTK("ENTER\n");
2922 if (freq < 8000)
2923 freq = 8000;
2925 diff = freq;
2927 for (n = 32; n < 128; n++) {
2928 int s = 0;
2930 d = (14318 * n) / freq;
2931 if ((d >= 7) && (d <= 63)) {
2932 int temp = d;
2934 if (temp > 31) {
2935 s = 1;
2936 temp >>= 1;
2938 h = ((14318 * n) / temp) >> s;
2939 h = h > freq ? h - freq : freq - h;
2940 if (h < diff) {
2941 diff = h;
2942 *nom = n;
2943 *den = temp;
2944 *div = s;
2947 d++;
2948 if ((d >= 7) && (d <= 63)) {
2949 if (d > 31) {
2950 s = 1;
2951 d >>= 1;
2953 h = ((14318 * n) / d) >> s;
2954 h = h > freq ? h - freq : freq - h;
2955 if (h < diff) {
2956 diff = h;
2957 *nom = n;
2958 *den = d;
2959 *div = s;
2964 DPRINTK("Best possible values for given frequency:\n");
2965 DPRINTK(" freq: %ld kHz nom: %d den: %d div: %d\n",
2966 freq, *nom, *den, *div);
2968 DPRINTK("EXIT\n");
2971 /* -------------------------------------------------------------------------
2973 * debugging functions
2975 * -------------------------------------------------------------------------
2978 #ifdef CIRRUSFB_DEBUG
2981 * cirrusfb_dbg_print_byte
2982 * @name: name associated with byte value to be displayed
2983 * @val: byte value to be displayed
2985 * DESCRIPTION:
2986 * Display an indented string, along with a hexidecimal byte value, and
2987 * its decoded bits. Bits 7 through 0 are listed in left-to-right
2988 * order.
2991 static
2992 void cirrusfb_dbg_print_byte(const char *name, unsigned char val)
2994 DPRINTK("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n",
2995 name, val,
2996 val & 0x80 ? '1' : '0',
2997 val & 0x40 ? '1' : '0',
2998 val & 0x20 ? '1' : '0',
2999 val & 0x10 ? '1' : '0',
3000 val & 0x08 ? '1' : '0',
3001 val & 0x04 ? '1' : '0',
3002 val & 0x02 ? '1' : '0',
3003 val & 0x01 ? '1' : '0');
3007 * cirrusfb_dbg_print_regs
3008 * @base: If using newmmio, the newmmio base address, otherwise %NULL
3009 * @reg_class: type of registers to read: %CRT, or %SEQ
3011 * DESCRIPTION:
3012 * Dumps the given list of VGA CRTC registers. If @base is %NULL,
3013 * old-style I/O ports are queried for information, otherwise MMIO is
3014 * used at the given @base address to query the information.
3017 static
3018 void cirrusfb_dbg_print_regs(caddr_t regbase,
3019 enum cirrusfb_dbg_reg_class reg_class, ...)
3021 va_list list;
3022 unsigned char val = 0;
3023 unsigned reg;
3024 char *name;
3026 va_start(list, reg_class);
3028 name = va_arg(list, char *);
3029 while (name != NULL) {
3030 reg = va_arg(list, int);
3032 switch (reg_class) {
3033 case CRT:
3034 val = vga_rcrt(regbase, (unsigned char) reg);
3035 break;
3036 case SEQ:
3037 val = vga_rseq(regbase, (unsigned char) reg);
3038 break;
3039 default:
3040 /* should never occur */
3041 assert(false);
3042 break;
3045 cirrusfb_dbg_print_byte(name, val);
3047 name = va_arg(list, char *);
3050 va_end(list);
3054 * cirrusfb_dump
3055 * @cirrusfbinfo:
3057 * DESCRIPTION:
3060 static void cirrusfb_dump(void)
3062 cirrusfb_dbg_reg_dump(NULL);
3066 * cirrusfb_dbg_reg_dump
3067 * @base: If using newmmio, the newmmio base address, otherwise %NULL
3069 * DESCRIPTION:
3070 * Dumps a list of interesting VGA and CIRRUSFB registers. If @base is %NULL,
3071 * old-style I/O ports are queried for information, otherwise MMIO is
3072 * used at the given @base address to query the information.
3075 static
3076 void cirrusfb_dbg_reg_dump(caddr_t regbase)
3078 DPRINTK("CIRRUSFB VGA CRTC register dump:\n");
3080 cirrusfb_dbg_print_regs(regbase, CRT,
3081 "CR00", 0x00,
3082 "CR01", 0x01,
3083 "CR02", 0x02,
3084 "CR03", 0x03,
3085 "CR04", 0x04,
3086 "CR05", 0x05,
3087 "CR06", 0x06,
3088 "CR07", 0x07,
3089 "CR08", 0x08,
3090 "CR09", 0x09,
3091 "CR0A", 0x0A,
3092 "CR0B", 0x0B,
3093 "CR0C", 0x0C,
3094 "CR0D", 0x0D,
3095 "CR0E", 0x0E,
3096 "CR0F", 0x0F,
3097 "CR10", 0x10,
3098 "CR11", 0x11,
3099 "CR12", 0x12,
3100 "CR13", 0x13,
3101 "CR14", 0x14,
3102 "CR15", 0x15,
3103 "CR16", 0x16,
3104 "CR17", 0x17,
3105 "CR18", 0x18,
3106 "CR22", 0x22,
3107 "CR24", 0x24,
3108 "CR26", 0x26,
3109 "CR2D", 0x2D,
3110 "CR2E", 0x2E,
3111 "CR2F", 0x2F,
3112 "CR30", 0x30,
3113 "CR31", 0x31,
3114 "CR32", 0x32,
3115 "CR33", 0x33,
3116 "CR34", 0x34,
3117 "CR35", 0x35,
3118 "CR36", 0x36,
3119 "CR37", 0x37,
3120 "CR38", 0x38,
3121 "CR39", 0x39,
3122 "CR3A", 0x3A,
3123 "CR3B", 0x3B,
3124 "CR3C", 0x3C,
3125 "CR3D", 0x3D,
3126 "CR3E", 0x3E,
3127 "CR3F", 0x3F,
3128 NULL);
3130 DPRINTK("\n");
3132 DPRINTK("CIRRUSFB VGA SEQ register dump:\n");
3134 cirrusfb_dbg_print_regs(regbase, SEQ,
3135 "SR00", 0x00,
3136 "SR01", 0x01,
3137 "SR02", 0x02,
3138 "SR03", 0x03,
3139 "SR04", 0x04,
3140 "SR08", 0x08,
3141 "SR09", 0x09,
3142 "SR0A", 0x0A,
3143 "SR0B", 0x0B,
3144 "SR0D", 0x0D,
3145 "SR10", 0x10,
3146 "SR11", 0x11,
3147 "SR12", 0x12,
3148 "SR13", 0x13,
3149 "SR14", 0x14,
3150 "SR15", 0x15,
3151 "SR16", 0x16,
3152 "SR17", 0x17,
3153 "SR18", 0x18,
3154 "SR19", 0x19,
3155 "SR1A", 0x1A,
3156 "SR1B", 0x1B,
3157 "SR1C", 0x1C,
3158 "SR1D", 0x1D,
3159 "SR1E", 0x1E,
3160 "SR1F", 0x1F,
3161 NULL);
3163 DPRINTK("\n");
3166 #endif /* CIRRUSFB_DEBUG */