cirrusfb: use 5-6-5 RGB for 16bpp mode
[linux-2.6/linux-loongson.git] / drivers / video / cirrusfb.c
blobd844c41e20103d188b628ebf42494d064a045451
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 #include <linux/module.h>
38 #include <linux/kernel.h>
39 #include <linux/errno.h>
40 #include <linux/string.h>
41 #include <linux/mm.h>
42 #include <linux/slab.h>
43 #include <linux/delay.h>
44 #include <linux/fb.h>
45 #include <linux/init.h>
46 #include <asm/pgtable.h>
48 #ifdef CONFIG_ZORRO
49 #include <linux/zorro.h>
50 #endif
51 #ifdef CONFIG_PCI
52 #include <linux/pci.h>
53 #endif
54 #ifdef CONFIG_AMIGA
55 #include <asm/amigahw.h>
56 #endif
57 #ifdef CONFIG_PPC_PREP
58 #include <asm/machdep.h>
59 #define isPReP machine_is(prep)
60 #else
61 #define isPReP 0
62 #endif
64 #include <video/vga.h>
65 #include <video/cirrus.h>
67 /*****************************************************************
69 * debugging and utility macros
73 /* disable runtime assertions? */
74 /* #define CIRRUSFB_NDEBUG */
76 /* debugging assertions */
77 #ifndef CIRRUSFB_NDEBUG
78 #define assert(expr) \
79 if (!(expr)) { \
80 printk("Assertion failed! %s,%s,%s,line=%d\n", \
81 #expr, __FILE__, __func__, __LINE__); \
83 #else
84 #define assert(expr)
85 #endif
87 #define MB_ (1024 * 1024)
89 /*****************************************************************
91 * chipset information
95 /* board types */
96 enum cirrus_board {
97 BT_NONE = 0,
98 BT_SD64,
99 BT_PICCOLO,
100 BT_PICASSO,
101 BT_SPECTRUM,
102 BT_PICASSO4, /* GD5446 */
103 BT_ALPINE, /* GD543x/4x */
104 BT_GD5480,
105 BT_LAGUNA, /* GD546x */
109 * per-board-type information, used for enumerating and abstracting
110 * chip-specific information
111 * NOTE: MUST be in the same order as enum cirrus_board in order to
112 * use direct indexing on this array
113 * NOTE: '__initdata' cannot be used as some of this info
114 * is required at runtime. Maybe separate into an init-only and
115 * a run-time table?
117 static const struct cirrusfb_board_info_rec {
118 char *name; /* ASCII name of chipset */
119 long maxclock[5]; /* maximum video clock */
120 /* for 1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */
121 bool init_sr07 : 1; /* init SR07 during init_vgachip() */
122 bool init_sr1f : 1; /* write SR1F during init_vgachip() */
123 /* construct bit 19 of screen start address */
124 bool scrn_start_bit19 : 1;
126 /* initial SR07 value, then for each mode */
127 unsigned char sr07;
128 unsigned char sr07_1bpp;
129 unsigned char sr07_1bpp_mux;
130 unsigned char sr07_8bpp;
131 unsigned char sr07_8bpp_mux;
133 unsigned char sr1f; /* SR1F VGA initial register value */
134 } cirrusfb_board_info[] = {
135 [BT_SD64] = {
136 .name = "CL SD64",
137 .maxclock = {
138 /* guess */
139 /* the SD64/P4 have a higher max. videoclock */
140 135100, 135100, 85500, 85500, 0
142 .init_sr07 = true,
143 .init_sr1f = true,
144 .scrn_start_bit19 = true,
145 .sr07 = 0xF0,
146 .sr07_1bpp = 0xF0,
147 .sr07_8bpp = 0xF1,
148 .sr1f = 0x20
150 [BT_PICCOLO] = {
151 .name = "CL Piccolo",
152 .maxclock = {
153 /* guess */
154 90000, 90000, 90000, 90000, 90000
156 .init_sr07 = true,
157 .init_sr1f = true,
158 .scrn_start_bit19 = false,
159 .sr07 = 0x80,
160 .sr07_1bpp = 0x80,
161 .sr07_8bpp = 0x81,
162 .sr1f = 0x22
164 [BT_PICASSO] = {
165 .name = "CL Picasso",
166 .maxclock = {
167 /* guess */
168 90000, 90000, 90000, 90000, 90000
170 .init_sr07 = true,
171 .init_sr1f = true,
172 .scrn_start_bit19 = false,
173 .sr07 = 0x20,
174 .sr07_1bpp = 0x20,
175 .sr07_8bpp = 0x21,
176 .sr1f = 0x22
178 [BT_SPECTRUM] = {
179 .name = "CL Spectrum",
180 .maxclock = {
181 /* guess */
182 90000, 90000, 90000, 90000, 90000
184 .init_sr07 = true,
185 .init_sr1f = true,
186 .scrn_start_bit19 = false,
187 .sr07 = 0x80,
188 .sr07_1bpp = 0x80,
189 .sr07_8bpp = 0x81,
190 .sr1f = 0x22
192 [BT_PICASSO4] = {
193 .name = "CL Picasso4",
194 .maxclock = {
195 135100, 135100, 85500, 85500, 0
197 .init_sr07 = true,
198 .init_sr1f = false,
199 .scrn_start_bit19 = true,
200 .sr07 = 0x20,
201 .sr07_1bpp = 0x20,
202 .sr07_8bpp = 0x21,
203 .sr1f = 0
205 [BT_ALPINE] = {
206 .name = "CL Alpine",
207 .maxclock = {
208 /* for the GD5430. GD5446 can do more... */
209 85500, 85500, 50000, 28500, 0
211 .init_sr07 = true,
212 .init_sr1f = true,
213 .scrn_start_bit19 = true,
214 .sr07 = 0xA0,
215 .sr07_1bpp = 0xA1,
216 .sr07_1bpp_mux = 0xA7,
217 .sr07_8bpp = 0xA1,
218 .sr07_8bpp_mux = 0xA7,
219 .sr1f = 0x1C
221 [BT_GD5480] = {
222 .name = "CL GD5480",
223 .maxclock = {
224 135100, 200000, 200000, 135100, 135100
226 .init_sr07 = true,
227 .init_sr1f = true,
228 .scrn_start_bit19 = true,
229 .sr07 = 0x10,
230 .sr07_1bpp = 0x11,
231 .sr07_8bpp = 0x11,
232 .sr1f = 0x1C
234 [BT_LAGUNA] = {
235 .name = "CL Laguna",
236 .maxclock = {
237 /* guess */
238 135100, 135100, 135100, 135100, 135100,
240 .init_sr07 = false,
241 .init_sr1f = false,
242 .scrn_start_bit19 = true,
246 #ifdef CONFIG_PCI
247 #define CHIP(id, btype) \
248 { PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
250 static struct pci_device_id cirrusfb_pci_table[] = {
251 CHIP(PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE),
252 CHIP(PCI_DEVICE_ID_CIRRUS_5434_8, BT_ALPINE),
253 CHIP(PCI_DEVICE_ID_CIRRUS_5434_4, BT_ALPINE),
254 CHIP(PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE), /* GD-5440 is same id */
255 CHIP(PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE),
256 CHIP(PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE),
257 CHIP(PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480), /* MacPicasso likely */
258 CHIP(PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4), /* Picasso 4 is 5446 */
259 CHIP(PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA), /* CL Laguna */
260 CHIP(PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA), /* CL Laguna 3D */
261 CHIP(PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNA), /* CL Laguna 3DA*/
262 { 0, }
264 MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
265 #undef CHIP
266 #endif /* CONFIG_PCI */
268 #ifdef CONFIG_ZORRO
269 static const struct zorro_device_id cirrusfb_zorro_table[] = {
271 .id = ZORRO_PROD_HELFRICH_SD64_RAM,
272 .driver_data = BT_SD64,
273 }, {
274 .id = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
275 .driver_data = BT_PICCOLO,
276 }, {
277 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
278 .driver_data = BT_PICASSO,
279 }, {
280 .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
281 .driver_data = BT_SPECTRUM,
282 }, {
283 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
284 .driver_data = BT_PICASSO4,
286 { 0 }
289 static const struct {
290 zorro_id id2;
291 unsigned long size;
292 } cirrusfb_zorro_table2[] = {
293 [BT_SD64] = {
294 .id2 = ZORRO_PROD_HELFRICH_SD64_REG,
295 .size = 0x400000
297 [BT_PICCOLO] = {
298 .id2 = ZORRO_PROD_HELFRICH_PICCOLO_REG,
299 .size = 0x200000
301 [BT_PICASSO] = {
302 .id2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
303 .size = 0x200000
305 [BT_SPECTRUM] = {
306 .id2 = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
307 .size = 0x200000
309 [BT_PICASSO4] = {
310 .id2 = 0,
311 .size = 0x400000
314 #endif /* CONFIG_ZORRO */
316 struct cirrusfb_regs {
317 int multiplexing;
320 #ifdef CIRRUSFB_DEBUG
321 enum cirrusfb_dbg_reg_class {
322 CRT,
325 #endif /* CIRRUSFB_DEBUG */
327 /* info about board */
328 struct cirrusfb_info {
329 u8 __iomem *regbase;
330 u8 __iomem *laguna_mmio;
331 enum cirrus_board btype;
332 unsigned char SFR; /* Shadow of special function register */
334 struct cirrusfb_regs currentmode;
335 int blank_mode;
336 u32 pseudo_palette[16];
338 void (*unmap)(struct fb_info *info);
341 static int noaccel __devinitdata;
342 static char *mode_option __devinitdata = "640x480@60";
344 /****************************************************************************/
345 /**** BEGIN PROTOTYPES ******************************************************/
347 /*--- Interface used by the world ------------------------------------------*/
348 static int cirrusfb_init(void);
349 #ifndef MODULE
350 static int cirrusfb_setup(char *options);
351 #endif
353 static int cirrusfb_open(struct fb_info *info, int user);
354 static int cirrusfb_release(struct fb_info *info, int user);
355 static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
356 unsigned blue, unsigned transp,
357 struct fb_info *info);
358 static int cirrusfb_check_var(struct fb_var_screeninfo *var,
359 struct fb_info *info);
360 static int cirrusfb_set_par(struct fb_info *info);
361 static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
362 struct fb_info *info);
363 static int cirrusfb_blank(int blank_mode, struct fb_info *info);
364 static void cirrusfb_fillrect(struct fb_info *info,
365 const struct fb_fillrect *region);
366 static void cirrusfb_copyarea(struct fb_info *info,
367 const struct fb_copyarea *area);
368 static void cirrusfb_imageblit(struct fb_info *info,
369 const struct fb_image *image);
371 /* function table of the above functions */
372 static struct fb_ops cirrusfb_ops = {
373 .owner = THIS_MODULE,
374 .fb_open = cirrusfb_open,
375 .fb_release = cirrusfb_release,
376 .fb_setcolreg = cirrusfb_setcolreg,
377 .fb_check_var = cirrusfb_check_var,
378 .fb_set_par = cirrusfb_set_par,
379 .fb_pan_display = cirrusfb_pan_display,
380 .fb_blank = cirrusfb_blank,
381 .fb_fillrect = cirrusfb_fillrect,
382 .fb_copyarea = cirrusfb_copyarea,
383 .fb_imageblit = cirrusfb_imageblit,
386 /*--- Internal routines ----------------------------------------------------*/
387 static void init_vgachip(struct fb_info *info);
388 static void switch_monitor(struct cirrusfb_info *cinfo, int on);
389 static void WGen(const struct cirrusfb_info *cinfo,
390 int regnum, unsigned char val);
391 static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum);
392 static void AttrOn(const struct cirrusfb_info *cinfo);
393 static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val);
394 static void WSFR(struct cirrusfb_info *cinfo, unsigned char val);
395 static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val);
396 static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum,
397 unsigned char red, unsigned char green, unsigned char blue);
398 #if 0
399 static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum,
400 unsigned char *red, unsigned char *green,
401 unsigned char *blue);
402 #endif
403 static void cirrusfb_WaitBLT(u8 __iomem *regbase);
404 static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
405 u_short curx, u_short cury,
406 u_short destx, u_short desty,
407 u_short width, u_short height,
408 u_short line_length);
409 static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
410 u_short x, u_short y,
411 u_short width, u_short height,
412 u_char color, u_short line_length);
414 static void bestclock(long freq, int *nom, int *den, int *div);
416 #ifdef CIRRUSFB_DEBUG
417 static void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase);
418 static void cirrusfb_dbg_print_regs(struct fb_info *info,
419 caddr_t regbase,
420 enum cirrusfb_dbg_reg_class reg_class, ...);
421 #endif /* CIRRUSFB_DEBUG */
423 /*** END PROTOTYPES ********************************************************/
424 /*****************************************************************************/
425 /*** BEGIN Interface Used by the World ***************************************/
427 static int opencount;
429 /*--- Open /dev/fbx ---------------------------------------------------------*/
430 static int cirrusfb_open(struct fb_info *info, int user)
432 if (opencount++ == 0)
433 switch_monitor(info->par, 1);
434 return 0;
437 /*--- Close /dev/fbx --------------------------------------------------------*/
438 static int cirrusfb_release(struct fb_info *info, int user)
440 if (--opencount == 0)
441 switch_monitor(info->par, 0);
442 return 0;
445 /**** END Interface used by the World *************************************/
446 /****************************************************************************/
447 /**** BEGIN Hardware specific Routines **************************************/
449 /* Check if the MCLK is not a better clock source */
450 static int cirrusfb_check_mclk(struct fb_info *info, long freq)
452 struct cirrusfb_info *cinfo = info->par;
453 long mclk = vga_rseq(cinfo->regbase, CL_SEQR1F) & 0x3f;
455 /* Read MCLK value */
456 mclk = (14318 * mclk) >> 3;
457 dev_dbg(info->device, "Read MCLK of %ld kHz\n", mclk);
459 /* Determine if we should use MCLK instead of VCLK, and if so, what we
460 * should divide it by to get VCLK
463 if (abs(freq - mclk) < 250) {
464 dev_dbg(info->device, "Using VCLK = MCLK\n");
465 return 1;
466 } else if (abs(freq - (mclk / 2)) < 250) {
467 dev_dbg(info->device, "Using VCLK = MCLK/2\n");
468 return 2;
471 return 0;
474 static int cirrusfb_check_var(struct fb_var_screeninfo *var,
475 struct fb_info *info)
477 int yres;
478 /* memory size in pixels */
479 unsigned pixels = info->screen_size * 8 / var->bits_per_pixel;
481 switch (var->bits_per_pixel) {
482 case 1:
483 var->red.offset = 0;
484 var->red.length = 1;
485 var->green = var->red;
486 var->blue = var->red;
487 break;
489 case 8:
490 var->red.offset = 0;
491 var->red.length = 6;
492 var->green = var->red;
493 var->blue = var->red;
494 break;
496 case 16:
497 if (isPReP) {
498 var->red.offset = 2;
499 var->green.offset = -3;
500 var->blue.offset = 8;
501 } else {
502 var->red.offset = 11;
503 var->green.offset = 5;
504 var->blue.offset = 0;
506 var->red.length = 5;
507 var->green.length = 6;
508 var->blue.length = 5;
509 break;
511 case 32:
512 if (isPReP) {
513 var->red.offset = 8;
514 var->green.offset = 16;
515 var->blue.offset = 24;
516 } else {
517 var->red.offset = 16;
518 var->green.offset = 8;
519 var->blue.offset = 0;
521 var->red.length = 8;
522 var->green.length = 8;
523 var->blue.length = 8;
524 break;
526 default:
527 dev_dbg(info->device,
528 "Unsupported bpp size: %d\n", var->bits_per_pixel);
529 assert(false);
530 /* should never occur */
531 break;
534 if (var->xres_virtual < var->xres)
535 var->xres_virtual = var->xres;
536 /* use highest possible virtual resolution */
537 if (var->yres_virtual == -1) {
538 var->yres_virtual = pixels / var->xres_virtual;
540 dev_info(info->device,
541 "virtual resolution set to maximum of %dx%d\n",
542 var->xres_virtual, var->yres_virtual);
544 if (var->yres_virtual < var->yres)
545 var->yres_virtual = var->yres;
547 if (var->xres_virtual * var->yres_virtual > pixels) {
548 dev_err(info->device, "mode %dx%dx%d rejected... "
549 "virtual resolution too high to fit into video memory!\n",
550 var->xres_virtual, var->yres_virtual,
551 var->bits_per_pixel);
552 return -EINVAL;
556 if (var->xoffset < 0)
557 var->xoffset = 0;
558 if (var->yoffset < 0)
559 var->yoffset = 0;
561 /* truncate xoffset and yoffset to maximum if too high */
562 if (var->xoffset > var->xres_virtual - var->xres)
563 var->xoffset = var->xres_virtual - var->xres - 1;
564 if (var->yoffset > var->yres_virtual - var->yres)
565 var->yoffset = var->yres_virtual - var->yres - 1;
567 var->red.msb_right =
568 var->green.msb_right =
569 var->blue.msb_right =
570 var->transp.offset =
571 var->transp.length =
572 var->transp.msb_right = 0;
574 yres = var->yres;
575 if (var->vmode & FB_VMODE_DOUBLE)
576 yres *= 2;
577 else if (var->vmode & FB_VMODE_INTERLACED)
578 yres = (yres + 1) / 2;
580 if (yres >= 1280) {
581 dev_err(info->device, "ERROR: VerticalTotal >= 1280; "
582 "special treatment required! (TODO)\n");
583 return -EINVAL;
586 return 0;
589 static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
590 struct cirrusfb_regs *regs,
591 struct fb_info *info)
593 long freq;
594 long maxclock;
595 int maxclockidx = var->bits_per_pixel >> 3;
596 struct cirrusfb_info *cinfo = info->par;
598 switch (var->bits_per_pixel) {
599 case 1:
600 info->fix.line_length = var->xres_virtual / 8;
601 info->fix.visual = FB_VISUAL_MONO10;
602 break;
604 case 8:
605 info->fix.line_length = var->xres_virtual;
606 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
607 break;
609 case 16:
610 case 32:
611 info->fix.line_length = var->xres_virtual * maxclockidx;
612 info->fix.visual = FB_VISUAL_TRUECOLOR;
613 break;
615 default:
616 dev_dbg(info->device,
617 "Unsupported bpp size: %d\n", var->bits_per_pixel);
618 assert(false);
619 /* should never occur */
620 break;
623 info->fix.type = FB_TYPE_PACKED_PIXELS;
625 /* convert from ps to kHz */
626 freq = PICOS2KHZ(var->pixclock);
628 dev_dbg(info->device, "desired pixclock: %ld kHz\n", freq);
630 maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
631 regs->multiplexing = 0;
633 /* If the frequency is greater than we can support, we might be able
634 * to use multiplexing for the video mode */
635 if (freq > maxclock) {
636 switch (cinfo->btype) {
637 case BT_ALPINE:
638 case BT_GD5480:
639 regs->multiplexing = 1;
640 break;
642 default:
643 dev_err(info->device,
644 "Frequency greater than maxclock (%ld kHz)\n",
645 maxclock);
646 return -EINVAL;
649 #if 0
650 /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
651 * the VCLK is double the pixel clock. */
652 switch (var->bits_per_pixel) {
653 case 16:
654 case 32:
655 if (var->xres <= 800)
656 /* Xbh has this type of clock for 32-bit */
657 freq /= 2;
658 break;
660 #endif
661 return 0;
664 static void cirrusfb_set_mclk_as_source(const struct fb_info *info, int div)
666 struct cirrusfb_info *cinfo = info->par;
667 unsigned char old1f, old1e;
669 assert(cinfo != NULL);
670 old1f = vga_rseq(cinfo->regbase, CL_SEQR1F) & ~0x40;
672 if (div) {
673 dev_dbg(info->device, "Set %s as pixclock source.\n",
674 (div == 2) ? "MCLK/2" : "MCLK");
675 old1f |= 0x40;
676 old1e = vga_rseq(cinfo->regbase, CL_SEQR1E) & ~0x1;
677 if (div == 2)
678 old1e |= 1;
680 vga_wseq(cinfo->regbase, CL_SEQR1E, old1e);
682 vga_wseq(cinfo->regbase, CL_SEQR1F, old1f);
685 /*************************************************************************
686 cirrusfb_set_par_foo()
688 actually writes the values for a new video mode into the hardware,
689 **************************************************************************/
690 static int cirrusfb_set_par_foo(struct fb_info *info)
692 struct cirrusfb_info *cinfo = info->par;
693 struct fb_var_screeninfo *var = &info->var;
694 struct cirrusfb_regs regs;
695 u8 __iomem *regbase = cinfo->regbase;
696 unsigned char tmp;
697 int err;
698 int pitch;
699 const struct cirrusfb_board_info_rec *bi;
700 int hdispend, hsyncstart, hsyncend, htotal;
701 int yres, vdispend, vsyncstart, vsyncend, vtotal;
702 long freq;
703 int nom, den, div;
704 unsigned int control, format, threshold;
706 dev_dbg(info->device, "Requested mode: %dx%dx%d\n",
707 var->xres, var->yres, var->bits_per_pixel);
708 dev_dbg(info->device, "pixclock: %d\n", var->pixclock);
710 init_vgachip(info);
712 err = cirrusfb_decode_var(var, &regs, info);
713 if (err) {
714 /* should never happen */
715 dev_dbg(info->device, "mode change aborted. invalid var.\n");
716 return -EINVAL;
719 bi = &cirrusfb_board_info[cinfo->btype];
721 hsyncstart = var->xres + var->right_margin;
722 hsyncend = hsyncstart + var->hsync_len;
723 htotal = (hsyncend + var->left_margin) / 8 - 5;
724 hdispend = var->xres / 8 - 1;
725 hsyncstart = hsyncstart / 8 + 1;
726 hsyncend = hsyncend / 8 + 1;
728 yres = var->yres;
729 vsyncstart = yres + var->lower_margin;
730 vsyncend = vsyncstart + var->vsync_len;
731 vtotal = vsyncend + var->upper_margin;
732 vdispend = yres - 1;
734 if (var->vmode & FB_VMODE_DOUBLE) {
735 yres *= 2;
736 vsyncstart *= 2;
737 vsyncend *= 2;
738 vtotal *= 2;
739 } else if (var->vmode & FB_VMODE_INTERLACED) {
740 yres = (yres + 1) / 2;
741 vsyncstart = (vsyncstart + 1) / 2;
742 vsyncend = (vsyncend + 1) / 2;
743 vtotal = (vtotal + 1) / 2;
746 vtotal -= 2;
747 vsyncstart -= 1;
748 vsyncend -= 1;
750 if (yres >= 1024) {
751 vtotal /= 2;
752 vsyncstart /= 2;
753 vsyncend /= 2;
754 vdispend /= 2;
756 if (regs.multiplexing) {
757 htotal /= 2;
758 hsyncstart /= 2;
759 hsyncend /= 2;
760 hdispend /= 2;
762 /* unlock register VGA_CRTC_H_TOTAL..CRT7 */
763 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */
765 /* if debugging is enabled, all parameters get output before writing */
766 dev_dbg(info->device, "CRT0: %d\n", htotal);
767 vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal);
769 dev_dbg(info->device, "CRT1: %d\n", hdispend);
770 vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend);
772 dev_dbg(info->device, "CRT2: %d\n", var->xres / 8);
773 vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8);
775 /* + 128: Compatible read */
776 dev_dbg(info->device, "CRT3: 128+%d\n", (htotal + 5) % 32);
777 vga_wcrt(regbase, VGA_CRTC_H_BLANK_END,
778 128 + ((htotal + 5) % 32));
780 dev_dbg(info->device, "CRT4: %d\n", hsyncstart);
781 vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart);
783 tmp = hsyncend % 32;
784 if ((htotal + 5) & 32)
785 tmp += 128;
786 dev_dbg(info->device, "CRT5: %d\n", tmp);
787 vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp);
789 dev_dbg(info->device, "CRT6: %d\n", vtotal & 0xff);
790 vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff);
792 tmp = 16; /* LineCompare bit #9 */
793 if (vtotal & 256)
794 tmp |= 1;
795 if (vdispend & 256)
796 tmp |= 2;
797 if (vsyncstart & 256)
798 tmp |= 4;
799 if ((vdispend + 1) & 256)
800 tmp |= 8;
801 if (vtotal & 512)
802 tmp |= 32;
803 if (vdispend & 512)
804 tmp |= 64;
805 if (vsyncstart & 512)
806 tmp |= 128;
807 dev_dbg(info->device, "CRT7: %d\n", tmp);
808 vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp);
810 tmp = 0x40; /* LineCompare bit #8 */
811 if ((vdispend + 1) & 512)
812 tmp |= 0x20;
813 if (var->vmode & FB_VMODE_DOUBLE)
814 tmp |= 0x80;
815 dev_dbg(info->device, "CRT9: %d\n", tmp);
816 vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp);
818 dev_dbg(info->device, "CRT10: %d\n", vsyncstart & 0xff);
819 vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff);
821 dev_dbg(info->device, "CRT11: 64+32+%d\n", vsyncend % 16);
822 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32);
824 dev_dbg(info->device, "CRT12: %d\n", vdispend & 0xff);
825 vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff);
827 dev_dbg(info->device, "CRT15: %d\n", (vdispend + 1) & 0xff);
828 vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff);
830 dev_dbg(info->device, "CRT16: %d\n", vtotal & 0xff);
831 vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff);
833 dev_dbg(info->device, "CRT18: 0xff\n");
834 vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff);
836 tmp = 0;
837 if (var->vmode & FB_VMODE_INTERLACED)
838 tmp |= 1;
839 if ((htotal + 5) & 64)
840 tmp |= 16;
841 if ((htotal + 5) & 128)
842 tmp |= 32;
843 if (vtotal & 256)
844 tmp |= 64;
845 if (vtotal & 512)
846 tmp |= 128;
848 dev_dbg(info->device, "CRT1a: %d\n", tmp);
849 vga_wcrt(regbase, CL_CRT1A, tmp);
851 freq = PICOS2KHZ(var->pixclock);
852 bestclock(freq, &nom, &den, &div);
854 dev_dbg(info->device, "VCLK freq: %ld kHz nom: %d den: %d div: %d\n",
855 freq, nom, den, div);
857 /* set VCLK0 */
858 /* hardware RefClock: 14.31818 MHz */
859 /* formula: VClk = (OSC * N) / (D * (1+P)) */
860 /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
862 if (cinfo->btype == BT_ALPINE) {
863 /* if freq is close to mclk or mclk/2 select mclk
864 * as clock source
866 int divMCLK = cirrusfb_check_mclk(info, freq);
867 if (divMCLK) {
868 nom = 0;
869 cirrusfb_set_mclk_as_source(info, divMCLK);
872 if (cinfo->btype == BT_LAGUNA) {
873 long pcifc = fb_readl(cinfo->laguna_mmio + 0x3fc);
874 unsigned char tile = fb_readb(cinfo->laguna_mmio + 0x407);
875 unsigned short tile_control;
877 tile_control = fb_readw(cinfo->laguna_mmio + 0x2c4);
878 fb_writew(tile_control & ~0x80, cinfo->laguna_mmio + 0x2c4);
880 fb_writel(pcifc | 0x10000000l, cinfo->laguna_mmio + 0x3fc);
881 fb_writeb(tile & 0x3f, cinfo->laguna_mmio + 0x407);
882 control = fb_readw(cinfo->laguna_mmio + 0x402);
883 threshold = fb_readw(cinfo->laguna_mmio + 0xea);
884 control &= ~0x6800;
885 format = 0;
886 threshold &= 0xffe0;
887 threshold &= 0x3fbf;
889 if (nom) {
890 tmp = den << 1;
891 if (div != 0)
892 tmp |= 1;
893 /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
894 if ((cinfo->btype == BT_SD64) ||
895 (cinfo->btype == BT_ALPINE) ||
896 (cinfo->btype == BT_GD5480))
897 tmp |= 0x80;
899 dev_dbg(info->device, "CL_SEQR1B: %d\n", (int) tmp);
900 /* Laguna chipset has reversed clock registers */
901 if (cinfo->btype == BT_LAGUNA) {
902 vga_wseq(regbase, CL_SEQRE, tmp);
903 vga_wseq(regbase, CL_SEQR1E, nom);
904 } else {
905 vga_wseq(regbase, CL_SEQRB, nom);
906 vga_wseq(regbase, CL_SEQR1B, tmp);
910 if (yres >= 1024)
911 /* 1280x1024 */
912 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7);
913 else
914 /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
915 * address wrap, no compat. */
916 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3);
918 /* HAEH? vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20);
919 * previously: 0x00 unlock VGA_CRTC_H_TOTAL..CRT7 */
921 /* don't know if it would hurt to also program this if no interlaced */
922 /* mode is used, but I feel better this way.. :-) */
923 if (var->vmode & FB_VMODE_INTERLACED)
924 vga_wcrt(regbase, VGA_CRTC_REGS, htotal / 2);
925 else
926 vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
928 vga_wseq(regbase, VGA_SEQ_CHARACTER_MAP, 0);
930 /* adjust horizontal/vertical sync type (low/high) */
931 /* enable display memory & CRTC I/O address for color mode */
932 tmp = 0x03;
933 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
934 tmp |= 0x40;
935 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
936 tmp |= 0x80;
937 WGen(cinfo, VGA_MIS_W, tmp);
939 /* Screen A Preset Row-Scan register */
940 vga_wcrt(regbase, VGA_CRTC_PRESET_ROW, 0);
941 /* text cursor on and start line */
942 vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0);
943 /* text cursor end line */
944 vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 31);
946 /******************************************************
948 * 1 bpp
952 /* programming for different color depths */
953 if (var->bits_per_pixel == 1) {
954 dev_dbg(info->device, "preparing for 1 bit deep display\n");
955 vga_wgfx(regbase, VGA_GFX_MODE, 0); /* mode register */
957 /* SR07 */
958 switch (cinfo->btype) {
959 case BT_SD64:
960 case BT_PICCOLO:
961 case BT_PICASSO:
962 case BT_SPECTRUM:
963 case BT_PICASSO4:
964 case BT_ALPINE:
965 case BT_GD5480:
966 vga_wseq(regbase, CL_SEQR7,
967 regs.multiplexing ?
968 bi->sr07_1bpp_mux : bi->sr07_1bpp);
969 break;
971 case BT_LAGUNA:
972 vga_wseq(regbase, CL_SEQR7,
973 vga_rseq(regbase, CL_SEQR7) & ~0x01);
974 break;
976 default:
977 dev_warn(info->device, "unknown Board\n");
978 break;
981 /* Extended Sequencer Mode */
982 switch (cinfo->btype) {
983 case BT_SD64:
984 /* setting the SEQRF on SD64 is not necessary
985 * (only during init)
987 /* MCLK select */
988 vga_wseq(regbase, CL_SEQR1F, 0x1a);
989 break;
991 case BT_PICCOLO:
992 case BT_SPECTRUM:
993 /* ### ueberall 0x22? */
994 /* ##vorher 1c MCLK select */
995 vga_wseq(regbase, CL_SEQR1F, 0x22);
996 /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
997 vga_wseq(regbase, CL_SEQRF, 0xb0);
998 break;
1000 case BT_PICASSO:
1001 /* ##vorher 22 MCLK select */
1002 vga_wseq(regbase, CL_SEQR1F, 0x22);
1003 /* ## vorher d0 avoid FIFO underruns..? */
1004 vga_wseq(regbase, CL_SEQRF, 0xd0);
1005 break;
1007 case BT_PICASSO4:
1008 case BT_ALPINE:
1009 case BT_GD5480:
1010 case BT_LAGUNA:
1011 /* do nothing */
1012 break;
1014 default:
1015 dev_warn(info->device, "unknown Board\n");
1016 break;
1019 /* pixel mask: pass-through for first plane */
1020 WGen(cinfo, VGA_PEL_MSK, 0x01);
1021 if (regs.multiplexing)
1022 /* hidden dac reg: 1280x1024 */
1023 WHDR(cinfo, 0x4a);
1024 else
1025 /* hidden dac: nothing */
1026 WHDR(cinfo, 0);
1027 /* memory mode: odd/even, ext. memory */
1028 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06);
1029 /* plane mask: only write to first plane */
1030 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01);
1033 /******************************************************
1035 * 8 bpp
1039 else if (var->bits_per_pixel == 8) {
1040 dev_dbg(info->device, "preparing for 8 bit deep display\n");
1041 switch (cinfo->btype) {
1042 case BT_SD64:
1043 case BT_PICCOLO:
1044 case BT_PICASSO:
1045 case BT_SPECTRUM:
1046 case BT_PICASSO4:
1047 case BT_ALPINE:
1048 case BT_GD5480:
1049 vga_wseq(regbase, CL_SEQR7,
1050 regs.multiplexing ?
1051 bi->sr07_8bpp_mux : bi->sr07_8bpp);
1052 break;
1054 case BT_LAGUNA:
1055 vga_wseq(regbase, CL_SEQR7,
1056 vga_rseq(regbase, CL_SEQR7) | 0x01);
1057 threshold |= 0x10;
1058 break;
1060 default:
1061 dev_warn(info->device, "unknown Board\n");
1062 break;
1065 switch (cinfo->btype) {
1066 case BT_SD64:
1067 /* MCLK select */
1068 vga_wseq(regbase, CL_SEQR1F, 0x1d);
1069 break;
1071 case BT_PICCOLO:
1072 case BT_PICASSO:
1073 case BT_SPECTRUM:
1074 /* ### vorher 1c MCLK select */
1075 vga_wseq(regbase, CL_SEQR1F, 0x22);
1076 /* Fast Page-Mode writes */
1077 vga_wseq(regbase, CL_SEQRF, 0xb0);
1078 break;
1080 case BT_PICASSO4:
1081 #ifdef CONFIG_ZORRO
1082 /* ### INCOMPLETE!! */
1083 vga_wseq(regbase, CL_SEQRF, 0xb8);
1084 #endif
1085 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1086 break;
1088 case BT_ALPINE:
1089 /* We already set SRF and SR1F */
1090 break;
1092 case BT_GD5480:
1093 case BT_LAGUNA:
1094 /* do nothing */
1095 break;
1097 default:
1098 dev_warn(info->device, "unknown board\n");
1099 break;
1102 /* mode register: 256 color mode */
1103 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1104 /* pixel mask: pass-through all planes */
1105 WGen(cinfo, VGA_PEL_MSK, 0xff);
1106 if (regs.multiplexing)
1107 /* hidden dac reg: 1280x1024 */
1108 WHDR(cinfo, 0x4a);
1109 else
1110 /* hidden dac: nothing */
1111 WHDR(cinfo, 0);
1112 /* memory mode: chain4, ext. memory */
1113 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1114 /* plane mask: enable writing to all 4 planes */
1115 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1118 /******************************************************
1120 * 16 bpp
1124 else if (var->bits_per_pixel == 16) {
1125 dev_dbg(info->device, "preparing for 16 bit deep display\n");
1126 switch (cinfo->btype) {
1127 case BT_SD64:
1128 /* Extended Sequencer Mode: 256c col. mode */
1129 vga_wseq(regbase, CL_SEQR7, 0xf7);
1130 /* MCLK select */
1131 vga_wseq(regbase, CL_SEQR1F, 0x1e);
1132 break;
1134 case BT_PICCOLO:
1135 case BT_SPECTRUM:
1136 vga_wseq(regbase, CL_SEQR7, 0x87);
1137 /* Fast Page-Mode writes */
1138 vga_wseq(regbase, CL_SEQRF, 0xb0);
1139 /* MCLK select */
1140 vga_wseq(regbase, CL_SEQR1F, 0x22);
1141 break;
1143 case BT_PICASSO:
1144 vga_wseq(regbase, CL_SEQR7, 0x27);
1145 /* Fast Page-Mode writes */
1146 vga_wseq(regbase, CL_SEQRF, 0xb0);
1147 /* MCLK select */
1148 vga_wseq(regbase, CL_SEQR1F, 0x22);
1149 break;
1151 case BT_PICASSO4:
1152 vga_wseq(regbase, CL_SEQR7, 0x27);
1153 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1154 break;
1156 case BT_ALPINE:
1157 vga_wseq(regbase, CL_SEQR7, 0xa7);
1158 break;
1160 case BT_GD5480:
1161 vga_wseq(regbase, CL_SEQR7, 0x17);
1162 /* We already set SRF and SR1F */
1163 break;
1165 case BT_LAGUNA:
1166 vga_wseq(regbase, CL_SEQR7,
1167 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1168 control |= 0x2000;
1169 format |= 0x1400;
1170 threshold |= 0x10;
1171 break;
1173 default:
1174 dev_warn(info->device, "unknown Board\n");
1175 break;
1178 /* mode register: 256 color mode */
1179 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1180 /* pixel mask: pass-through all planes */
1181 WGen(cinfo, VGA_PEL_MSK, 0xff);
1182 #ifdef CONFIG_PCI
1183 WHDR(cinfo, 0xc1); /* Copy Xbh */
1184 #elif defined(CONFIG_ZORRO)
1185 /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
1186 WHDR(cinfo, 0xa0); /* hidden dac reg: nothing special */
1187 #endif
1188 /* memory mode: chain4, ext. memory */
1189 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1190 /* plane mask: enable writing to all 4 planes */
1191 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1194 /******************************************************
1196 * 32 bpp
1200 else if (var->bits_per_pixel == 32) {
1201 dev_dbg(info->device, "preparing for 32 bit deep display\n");
1202 switch (cinfo->btype) {
1203 case BT_SD64:
1204 /* Extended Sequencer Mode: 256c col. mode */
1205 vga_wseq(regbase, CL_SEQR7, 0xf9);
1206 /* MCLK select */
1207 vga_wseq(regbase, CL_SEQR1F, 0x1e);
1208 break;
1210 case BT_PICCOLO:
1211 case BT_SPECTRUM:
1212 vga_wseq(regbase, CL_SEQR7, 0x85);
1213 /* Fast Page-Mode writes */
1214 vga_wseq(regbase, CL_SEQRF, 0xb0);
1215 /* MCLK select */
1216 vga_wseq(regbase, CL_SEQR1F, 0x22);
1217 break;
1219 case BT_PICASSO:
1220 vga_wseq(regbase, CL_SEQR7, 0x25);
1221 /* Fast Page-Mode writes */
1222 vga_wseq(regbase, CL_SEQRF, 0xb0);
1223 /* MCLK select */
1224 vga_wseq(regbase, CL_SEQR1F, 0x22);
1225 break;
1227 case BT_PICASSO4:
1228 vga_wseq(regbase, CL_SEQR7, 0x25);
1229 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1230 break;
1232 case BT_ALPINE:
1233 vga_wseq(regbase, CL_SEQR7, 0xa9);
1234 break;
1236 case BT_GD5480:
1237 vga_wseq(regbase, CL_SEQR7, 0x19);
1238 /* We already set SRF and SR1F */
1239 break;
1241 case BT_LAGUNA:
1242 vga_wseq(regbase, CL_SEQR7,
1243 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1244 control |= 0x6000;
1245 format |= 0x3400;
1246 threshold |= 0x20;
1247 break;
1249 default:
1250 dev_warn(info->device, "unknown Board\n");
1251 break;
1254 /* mode register: 256 color mode */
1255 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1256 /* pixel mask: pass-through all planes */
1257 WGen(cinfo, VGA_PEL_MSK, 0xff);
1258 /* hidden dac reg: 8-8-8 mode (24 or 32) */
1259 WHDR(cinfo, 0xc5);
1260 /* memory mode: chain4, ext. memory */
1261 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1262 /* plane mask: enable writing to all 4 planes */
1263 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1266 /******************************************************
1268 * unknown/unsupported bpp
1272 else
1273 dev_err(info->device,
1274 "What's this? requested color depth == %d.\n",
1275 var->bits_per_pixel);
1277 pitch = info->fix.line_length >> 3;
1278 vga_wcrt(regbase, VGA_CRTC_OFFSET, pitch & 0xff);
1279 tmp = 0x22;
1280 if (pitch & 0x100)
1281 tmp |= 0x10; /* offset overflow bit */
1283 /* screen start addr #16-18, fastpagemode cycles */
1284 vga_wcrt(regbase, CL_CRT1B, tmp);
1286 /* screen start address bit 19 */
1287 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19)
1288 vga_wcrt(regbase, CL_CRT1D, (pitch >> 9) & 1);
1290 if (cinfo->btype == BT_LAGUNA ||
1291 cinfo->btype == BT_GD5480) {
1293 tmp = 0;
1294 if ((htotal + 5) & 256)
1295 tmp |= 128;
1296 if (hdispend & 256)
1297 tmp |= 64;
1298 if (hsyncstart & 256)
1299 tmp |= 48;
1300 if (vtotal & 1024)
1301 tmp |= 8;
1302 if (vdispend & 1024)
1303 tmp |= 4;
1304 if (vsyncstart & 1024)
1305 tmp |= 3;
1307 vga_wcrt(regbase, CL_CRT1E, tmp);
1308 dev_dbg(info->device, "CRT1e: %d\n", tmp);
1312 /* text cursor location high */
1313 vga_wcrt(regbase, VGA_CRTC_CURSOR_HI, 0);
1314 /* text cursor location low */
1315 vga_wcrt(regbase, VGA_CRTC_CURSOR_LO, 0);
1316 /* underline row scanline = at very bottom */
1317 vga_wcrt(regbase, VGA_CRTC_UNDERLINE, 0);
1319 /* controller mode */
1320 vga_wattr(regbase, VGA_ATC_MODE, 1);
1321 /* overscan (border) color */
1322 vga_wattr(regbase, VGA_ATC_OVERSCAN, 0);
1323 /* color plane enable */
1324 vga_wattr(regbase, VGA_ATC_PLANE_ENABLE, 15);
1325 /* pixel panning */
1326 vga_wattr(regbase, CL_AR33, 0);
1327 /* color select */
1328 vga_wattr(regbase, VGA_ATC_COLOR_PAGE, 0);
1330 /* [ EGS: SetOffset(); ] */
1331 /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
1332 AttrOn(cinfo);
1334 /* set/reset register */
1335 vga_wgfx(regbase, VGA_GFX_SR_VALUE, 0);
1336 /* set/reset enable */
1337 vga_wgfx(regbase, VGA_GFX_SR_ENABLE, 0);
1338 /* color compare */
1339 vga_wgfx(regbase, VGA_GFX_COMPARE_VALUE, 0);
1340 /* data rotate */
1341 vga_wgfx(regbase, VGA_GFX_DATA_ROTATE, 0);
1342 /* read map select */
1343 vga_wgfx(regbase, VGA_GFX_PLANE_READ, 0);
1344 /* miscellaneous register */
1345 vga_wgfx(regbase, VGA_GFX_MISC, 1);
1346 /* color don't care */
1347 vga_wgfx(regbase, VGA_GFX_COMPARE_MASK, 15);
1348 /* bit mask */
1349 vga_wgfx(regbase, VGA_GFX_BIT_MASK, 255);
1351 /* graphics cursor attributes: nothing special */
1352 vga_wseq(regbase, CL_SEQR12, 0x0);
1354 if (cinfo->btype == BT_LAGUNA) {
1355 /* no tiles */
1356 fb_writew(control | 0x1000, cinfo->laguna_mmio + 0x402);
1357 fb_writew(format, cinfo->laguna_mmio + 0xc0);
1358 fb_writew(threshold, cinfo->laguna_mmio + 0xea);
1360 /* finally, turn on everything - turn off "FullBandwidth" bit */
1361 /* also, set "DotClock%2" bit where requested */
1362 tmp = 0x01;
1364 /*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
1365 if (var->vmode & FB_VMODE_CLOCK_HALVE)
1366 tmp |= 0x08;
1369 vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp);
1370 dev_dbg(info->device, "CL_SEQR1: %d\n", tmp);
1372 cinfo->currentmode = regs;
1374 /* pan to requested offset */
1375 cirrusfb_pan_display(var, info);
1377 #ifdef CIRRUSFB_DEBUG
1378 cirrusfb_dbg_reg_dump(info, NULL);
1379 #endif
1381 return 0;
1384 /* for some reason incomprehensible to me, cirrusfb requires that you write
1385 * the registers twice for the settings to take..grr. -dte */
1386 static int cirrusfb_set_par(struct fb_info *info)
1388 cirrusfb_set_par_foo(info);
1389 return cirrusfb_set_par_foo(info);
1392 static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1393 unsigned blue, unsigned transp,
1394 struct fb_info *info)
1396 struct cirrusfb_info *cinfo = info->par;
1398 if (regno > 255)
1399 return -EINVAL;
1401 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
1402 u32 v;
1403 red >>= (16 - info->var.red.length);
1404 green >>= (16 - info->var.green.length);
1405 blue >>= (16 - info->var.blue.length);
1407 if (regno >= 16)
1408 return 1;
1409 v = (red << info->var.red.offset) |
1410 (green << info->var.green.offset) |
1411 (blue << info->var.blue.offset);
1413 cinfo->pseudo_palette[regno] = v;
1414 return 0;
1417 if (info->var.bits_per_pixel == 8)
1418 WClut(cinfo, regno, red >> 10, green >> 10, blue >> 10);
1420 return 0;
1424 /*************************************************************************
1425 cirrusfb_pan_display()
1427 performs display panning - provided hardware permits this
1428 **************************************************************************/
1429 static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
1430 struct fb_info *info)
1432 int xoffset = 0;
1433 int yoffset = 0;
1434 unsigned long base;
1435 unsigned char tmp, xpix;
1436 struct cirrusfb_info *cinfo = info->par;
1438 dev_dbg(info->device,
1439 "virtual offset: (%d,%d)\n", var->xoffset, var->yoffset);
1441 /* no range checks for xoffset and yoffset, */
1442 /* as fb_pan_display has already done this */
1443 if (var->vmode & FB_VMODE_YWRAP)
1444 return -EINVAL;
1446 info->var.xoffset = var->xoffset;
1447 info->var.yoffset = var->yoffset;
1449 xoffset = var->xoffset * info->var.bits_per_pixel / 8;
1450 yoffset = var->yoffset;
1452 base = yoffset * info->fix.line_length + xoffset;
1454 if (info->var.bits_per_pixel == 1) {
1455 /* base is already correct */
1456 xpix = (unsigned char) (var->xoffset % 8);
1457 } else {
1458 base /= 4;
1459 xpix = (unsigned char) ((xoffset % 4) * 2);
1462 cirrusfb_WaitBLT(cinfo->regbase); /* make sure all the BLT's are done */
1464 /* lower 8 + 8 bits of screen start address */
1465 vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO,
1466 (unsigned char) (base & 0xff));
1467 vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI,
1468 (unsigned char) (base >> 8));
1470 /* 0xf2 is %11110010, exclude tmp bits */
1471 tmp = vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2;
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 vga_wcrt(cinfo->regbase, CL_CRT1B, tmp);
1482 /* construct bit 19 of screen start address */
1483 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19)
1484 vga_wcrt(cinfo->regbase, CL_CRT1D, (base >> 12) & 0x80);
1486 /* write pixel panning value to AR33; this does not quite work in 8bpp
1488 * ### Piccolo..? Will this work?
1490 if (info->var.bits_per_pixel == 1)
1491 vga_wattr(cinfo->regbase, CL_AR33, xpix);
1493 cirrusfb_WaitBLT(cinfo->regbase);
1495 return 0;
1498 static int cirrusfb_blank(int blank_mode, struct fb_info *info)
1501 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
1502 * then the caller blanks by setting the CLUT (Color Look Up Table)
1503 * to all black. Return 0 if blanking succeeded, != 0 if un-/blanking
1504 * failed due to e.g. a video mode which doesn't support it.
1505 * Implements VESA suspend and powerdown modes on hardware that
1506 * supports disabling hsync/vsync:
1507 * blank_mode == 2: suspend vsync
1508 * blank_mode == 3: suspend hsync
1509 * blank_mode == 4: powerdown
1511 unsigned char val;
1512 struct cirrusfb_info *cinfo = info->par;
1513 int current_mode = cinfo->blank_mode;
1515 dev_dbg(info->device, "ENTER, blank mode = %d\n", blank_mode);
1517 if (info->state != FBINFO_STATE_RUNNING ||
1518 current_mode == blank_mode) {
1519 dev_dbg(info->device, "EXIT, returning 0\n");
1520 return 0;
1523 /* Undo current */
1524 if (current_mode == FB_BLANK_NORMAL ||
1525 current_mode == FB_BLANK_UNBLANK)
1526 /* clear "FullBandwidth" bit */
1527 val = 0;
1528 else
1529 /* set "FullBandwidth" bit */
1530 val = 0x20;
1532 val |= vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE) & 0xdf;
1533 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val);
1535 switch (blank_mode) {
1536 case FB_BLANK_UNBLANK:
1537 case FB_BLANK_NORMAL:
1538 val = 0x00;
1539 break;
1540 case FB_BLANK_VSYNC_SUSPEND:
1541 val = 0x04;
1542 break;
1543 case FB_BLANK_HSYNC_SUSPEND:
1544 val = 0x02;
1545 break;
1546 case FB_BLANK_POWERDOWN:
1547 val = 0x06;
1548 break;
1549 default:
1550 dev_dbg(info->device, "EXIT, returning 1\n");
1551 return 1;
1554 vga_wgfx(cinfo->regbase, CL_GRE, val);
1556 cinfo->blank_mode = blank_mode;
1557 dev_dbg(info->device, "EXIT, returning 0\n");
1559 /* Let fbcon do a soft blank for us */
1560 return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
1563 /**** END Hardware specific Routines **************************************/
1564 /****************************************************************************/
1565 /**** BEGIN Internal Routines ***********************************************/
1567 static void init_vgachip(struct fb_info *info)
1569 struct cirrusfb_info *cinfo = info->par;
1570 const struct cirrusfb_board_info_rec *bi;
1572 assert(cinfo != NULL);
1574 bi = &cirrusfb_board_info[cinfo->btype];
1576 /* reset board globally */
1577 switch (cinfo->btype) {
1578 case BT_PICCOLO:
1579 WSFR(cinfo, 0x01);
1580 udelay(500);
1581 WSFR(cinfo, 0x51);
1582 udelay(500);
1583 break;
1584 case BT_PICASSO:
1585 WSFR2(cinfo, 0xff);
1586 udelay(500);
1587 break;
1588 case BT_SD64:
1589 case BT_SPECTRUM:
1590 WSFR(cinfo, 0x1f);
1591 udelay(500);
1592 WSFR(cinfo, 0x4f);
1593 udelay(500);
1594 break;
1595 case BT_PICASSO4:
1596 /* disable flickerfixer */
1597 vga_wcrt(cinfo->regbase, CL_CRT51, 0x00);
1598 mdelay(100);
1599 /* from Klaus' NetBSD driver: */
1600 vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
1601 /* put blitter into 542x compat */
1602 vga_wgfx(cinfo->regbase, CL_GR33, 0x00);
1603 /* mode */
1604 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1605 break;
1607 case BT_GD5480:
1608 /* from Klaus' NetBSD driver: */
1609 vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
1610 break;
1612 case BT_ALPINE:
1613 /* Nothing to do to reset the board. */
1614 break;
1616 default:
1617 dev_err(info->device, "Warning: Unknown board type\n");
1618 break;
1621 /* make sure RAM size set by this point */
1622 assert(info->screen_size > 0);
1624 /* the P4 is not fully initialized here; I rely on it having been */
1625 /* inited under AmigaOS already, which seems to work just fine */
1626 /* (Klaus advised to do it this way) */
1628 if (cinfo->btype != BT_PICASSO4) {
1629 WGen(cinfo, CL_VSSM, 0x10); /* EGS: 0x16 */
1630 WGen(cinfo, CL_POS102, 0x01);
1631 WGen(cinfo, CL_VSSM, 0x08); /* EGS: 0x0e */
1633 if (cinfo->btype != BT_SD64)
1634 WGen(cinfo, CL_VSSM2, 0x01);
1636 /* reset sequencer logic */
1637 vga_wseq(cinfo->regbase, CL_SEQR0, 0x03);
1639 /* FullBandwidth (video off) and 8/9 dot clock */
1640 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21);
1641 /* polarity (-/-), disable access to display memory,
1642 * VGA_CRTC_START_HI base address: color
1644 WGen(cinfo, VGA_MIS_W, 0xc1);
1646 /* "magic cookie" - doesn't make any sense to me.. */
1647 /* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */
1648 /* unlock all extension registers */
1649 vga_wseq(cinfo->regbase, CL_SEQR6, 0x12);
1651 /* reset blitter */
1652 vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
1654 switch (cinfo->btype) {
1655 case BT_GD5480:
1656 vga_wseq(cinfo->regbase, CL_SEQRF, 0x98);
1657 break;
1658 case BT_ALPINE:
1659 break;
1660 case BT_SD64:
1661 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8);
1662 break;
1663 default:
1664 vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f);
1665 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb0);
1666 break;
1669 /* plane mask: nothing */
1670 vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1671 /* character map select: doesn't even matter in gx mode */
1672 vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00);
1673 /* memory mode: chain-4, no odd/even, ext. memory */
1674 vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0e);
1676 /* controller-internal base address of video memory */
1677 if (bi->init_sr07)
1678 vga_wseq(cinfo->regbase, CL_SEQR7, bi->sr07);
1680 /* vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */
1681 /* EEPROM control: shouldn't be necessary to write to this at all.. */
1683 /* graphics cursor X position (incomplete; position gives rem. 3 bits */
1684 vga_wseq(cinfo->regbase, CL_SEQR10, 0x00);
1685 /* graphics cursor Y position (..."... ) */
1686 vga_wseq(cinfo->regbase, CL_SEQR11, 0x00);
1687 /* graphics cursor attributes */
1688 vga_wseq(cinfo->regbase, CL_SEQR12, 0x00);
1689 /* graphics cursor pattern address */
1690 vga_wseq(cinfo->regbase, CL_SEQR13, 0x00);
1692 /* writing these on a P4 might give problems.. */
1693 if (cinfo->btype != BT_PICASSO4) {
1694 /* configuration readback and ext. color */
1695 vga_wseq(cinfo->regbase, CL_SEQR17, 0x00);
1696 /* signature generator */
1697 vga_wseq(cinfo->regbase, CL_SEQR18, 0x02);
1700 /* MCLK select etc. */
1701 if (bi->init_sr1f)
1702 vga_wseq(cinfo->regbase, CL_SEQR1F, bi->sr1f);
1704 /* Screen A preset row scan: none */
1705 vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00);
1706 /* Text cursor start: disable text cursor */
1707 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20);
1708 /* Text cursor end: - */
1709 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00);
1710 /* Screen start address high: 0 */
1711 vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, 0x00);
1712 /* Screen start address low: 0 */
1713 vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, 0x00);
1714 /* text cursor location high: 0 */
1715 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00);
1716 /* text cursor location low: 0 */
1717 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00);
1719 /* Underline Row scanline: - */
1720 vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00);
1721 /* mode control: timing enable, byte mode, no compat modes */
1722 vga_wcrt(cinfo->regbase, VGA_CRTC_MODE, 0xc3);
1723 /* Line Compare: not needed */
1724 vga_wcrt(cinfo->regbase, VGA_CRTC_LINE_COMPARE, 0x00);
1725 /* ### add 0x40 for text modes with > 30 MHz pixclock */
1726 /* ext. display controls: ext.adr. wrap */
1727 vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02);
1729 /* Set/Reset registes: - */
1730 vga_wgfx(cinfo->regbase, VGA_GFX_SR_VALUE, 0x00);
1731 /* Set/Reset enable: - */
1732 vga_wgfx(cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00);
1733 /* Color Compare: - */
1734 vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00);
1735 /* Data Rotate: - */
1736 vga_wgfx(cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00);
1737 /* Read Map Select: - */
1738 vga_wgfx(cinfo->regbase, VGA_GFX_PLANE_READ, 0x00);
1739 /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
1740 vga_wgfx(cinfo->regbase, VGA_GFX_MODE, 0x00);
1741 /* Miscellaneous: memory map base address, graphics mode */
1742 vga_wgfx(cinfo->regbase, VGA_GFX_MISC, 0x01);
1743 /* Color Don't care: involve all planes */
1744 vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f);
1745 /* Bit Mask: no mask at all */
1746 vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff);
1747 if (cinfo->btype == BT_ALPINE)
1748 /* (5434 can't have bit 3 set for bitblt) */
1749 vga_wgfx(cinfo->regbase, CL_GRB, 0x20);
1750 else
1751 /* Graphics controller mode extensions: finer granularity,
1752 * 8byte data latches
1754 vga_wgfx(cinfo->regbase, CL_GRB, 0x28);
1756 vga_wgfx(cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */
1757 vga_wgfx(cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */
1758 vga_wgfx(cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */
1759 /* Background color byte 1: - */
1760 /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); */
1761 /* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
1763 /* Attribute Controller palette registers: "identity mapping" */
1764 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE0, 0x00);
1765 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
1766 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
1767 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
1768 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
1769 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
1770 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
1771 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
1772 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
1773 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
1774 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
1775 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
1776 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
1777 vga_wattr(cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
1778 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
1779 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
1781 /* Attribute Controller mode: graphics mode */
1782 vga_wattr(cinfo->regbase, VGA_ATC_MODE, 0x01);
1783 /* Overscan color reg.: reg. 0 */
1784 vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00);
1785 /* Color Plane enable: Enable all 4 planes */
1786 vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f);
1787 /* ### vga_wattr(cinfo->regbase, CL_AR33, 0x00); * Pixel Panning: - */
1788 /* Color Select: - */
1789 vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00);
1791 WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
1793 if (cinfo->btype != BT_ALPINE && cinfo->btype != BT_GD5480)
1794 /* polarity (-/-), enable display mem,
1795 * VGA_CRTC_START_HI i/o base = color
1797 WGen(cinfo, VGA_MIS_W, 0xc3);
1799 /* BLT Start/status: Blitter reset */
1800 vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
1801 /* - " - : "end-of-reset" */
1802 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1804 /* misc... */
1805 WHDR(cinfo, 0); /* Hidden DAC register: - */
1806 return;
1809 static void switch_monitor(struct cirrusfb_info *cinfo, int on)
1811 #ifdef CONFIG_ZORRO /* only works on Zorro boards */
1812 static int IsOn = 0; /* XXX not ok for multiple boards */
1814 if (cinfo->btype == BT_PICASSO4)
1815 return; /* nothing to switch */
1816 if (cinfo->btype == BT_ALPINE)
1817 return; /* nothing to switch */
1818 if (cinfo->btype == BT_GD5480)
1819 return; /* nothing to switch */
1820 if (cinfo->btype == BT_PICASSO) {
1821 if ((on && !IsOn) || (!on && IsOn))
1822 WSFR(cinfo, 0xff);
1823 return;
1825 if (on) {
1826 switch (cinfo->btype) {
1827 case BT_SD64:
1828 WSFR(cinfo, cinfo->SFR | 0x21);
1829 break;
1830 case BT_PICCOLO:
1831 WSFR(cinfo, cinfo->SFR | 0x28);
1832 break;
1833 case BT_SPECTRUM:
1834 WSFR(cinfo, 0x6f);
1835 break;
1836 default: /* do nothing */ break;
1838 } else {
1839 switch (cinfo->btype) {
1840 case BT_SD64:
1841 WSFR(cinfo, cinfo->SFR & 0xde);
1842 break;
1843 case BT_PICCOLO:
1844 WSFR(cinfo, cinfo->SFR & 0xd7);
1845 break;
1846 case BT_SPECTRUM:
1847 WSFR(cinfo, 0x4f);
1848 break;
1849 default: /* do nothing */
1850 break;
1853 #endif /* CONFIG_ZORRO */
1856 /******************************************/
1857 /* Linux 2.6-style accelerated functions */
1858 /******************************************/
1860 static void cirrusfb_fillrect(struct fb_info *info,
1861 const struct fb_fillrect *region)
1863 struct fb_fillrect modded;
1864 int vxres, vyres;
1865 struct cirrusfb_info *cinfo = info->par;
1866 int m = info->var.bits_per_pixel;
1867 u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
1868 cinfo->pseudo_palette[region->color] : region->color;
1870 if (info->state != FBINFO_STATE_RUNNING)
1871 return;
1872 if (info->flags & FBINFO_HWACCEL_DISABLED) {
1873 cfb_fillrect(info, region);
1874 return;
1877 vxres = info->var.xres_virtual;
1878 vyres = info->var.yres_virtual;
1880 memcpy(&modded, region, sizeof(struct fb_fillrect));
1882 if (!modded.width || !modded.height ||
1883 modded.dx >= vxres || modded.dy >= vyres)
1884 return;
1886 if (modded.dx + modded.width > vxres)
1887 modded.width = vxres - modded.dx;
1888 if (modded.dy + modded.height > vyres)
1889 modded.height = vyres - modded.dy;
1891 cirrusfb_RectFill(cinfo->regbase,
1892 info->var.bits_per_pixel,
1893 (region->dx * m) / 8, region->dy,
1894 (region->width * m) / 8, region->height,
1895 color,
1896 info->fix.line_length);
1899 static void cirrusfb_copyarea(struct fb_info *info,
1900 const struct fb_copyarea *area)
1902 struct fb_copyarea modded;
1903 u32 vxres, vyres;
1904 struct cirrusfb_info *cinfo = info->par;
1905 int m = info->var.bits_per_pixel;
1907 if (info->state != FBINFO_STATE_RUNNING)
1908 return;
1909 if (info->flags & FBINFO_HWACCEL_DISABLED) {
1910 cfb_copyarea(info, area);
1911 return;
1914 vxres = info->var.xres_virtual;
1915 vyres = info->var.yres_virtual;
1916 memcpy(&modded, area, sizeof(struct fb_copyarea));
1918 if (!modded.width || !modded.height ||
1919 modded.sx >= vxres || modded.sy >= vyres ||
1920 modded.dx >= vxres || modded.dy >= vyres)
1921 return;
1923 if (modded.sx + modded.width > vxres)
1924 modded.width = vxres - modded.sx;
1925 if (modded.dx + modded.width > vxres)
1926 modded.width = vxres - modded.dx;
1927 if (modded.sy + modded.height > vyres)
1928 modded.height = vyres - modded.sy;
1929 if (modded.dy + modded.height > vyres)
1930 modded.height = vyres - modded.dy;
1932 cirrusfb_BitBLT(cinfo->regbase, info->var.bits_per_pixel,
1933 (area->sx * m) / 8, area->sy,
1934 (area->dx * m) / 8, area->dy,
1935 (area->width * m) / 8, area->height,
1936 info->fix.line_length);
1940 static void cirrusfb_imageblit(struct fb_info *info,
1941 const struct fb_image *image)
1943 struct cirrusfb_info *cinfo = info->par;
1945 cirrusfb_WaitBLT(cinfo->regbase);
1946 cfb_imageblit(info, image);
1949 #ifdef CONFIG_PPC_PREP
1950 #define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
1951 #define PREP_IO_BASE ((volatile unsigned char *) 0x80000000)
1952 static void get_prep_addrs(unsigned long *display, unsigned long *registers)
1954 *display = PREP_VIDEO_BASE;
1955 *registers = (unsigned long) PREP_IO_BASE;
1958 #endif /* CONFIG_PPC_PREP */
1960 #ifdef CONFIG_PCI
1961 static int release_io_ports;
1963 /* Pulled the logic from XFree86 Cirrus driver to get the memory size,
1964 * based on the DRAM bandwidth bit and DRAM bank switching bit. This
1965 * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
1966 * seem to have. */
1967 static unsigned int __devinit cirrusfb_get_memsize(struct fb_info *info,
1968 u8 __iomem *regbase)
1970 unsigned long mem;
1971 struct cirrusfb_info *cinfo = info->par;
1973 if (cinfo->btype == BT_LAGUNA) {
1974 unsigned char SR14 = vga_rseq(regbase, CL_SEQR14);
1976 mem = ((SR14 & 7) + 1) << 20;
1977 } else {
1978 unsigned char SRF = vga_rseq(regbase, CL_SEQRF);
1979 switch ((SRF & 0x18)) {
1980 case 0x08:
1981 mem = 512 * 1024;
1982 break;
1983 case 0x10:
1984 mem = 1024 * 1024;
1985 break;
1986 /* 64-bit DRAM data bus width; assume 2MB.
1987 * Also indicates 2MB memory on the 5430.
1989 case 0x18:
1990 mem = 2048 * 1024;
1991 break;
1992 default:
1993 dev_warn(info->device, "Unknown memory size!\n");
1994 mem = 1024 * 1024;
1996 /* If DRAM bank switching is enabled, there must be
1997 * twice as much memory installed. (4MB on the 5434)
1999 if (SRF & 0x80)
2000 mem *= 2;
2003 /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
2004 return mem;
2007 static void get_pci_addrs(const struct pci_dev *pdev,
2008 unsigned long *display, unsigned long *registers)
2010 assert(pdev != NULL);
2011 assert(display != NULL);
2012 assert(registers != NULL);
2014 *display = 0;
2015 *registers = 0;
2017 /* This is a best-guess for now */
2019 if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
2020 *display = pci_resource_start(pdev, 1);
2021 *registers = pci_resource_start(pdev, 0);
2022 } else {
2023 *display = pci_resource_start(pdev, 0);
2024 *registers = pci_resource_start(pdev, 1);
2027 assert(*display != 0);
2030 static void cirrusfb_pci_unmap(struct fb_info *info)
2032 struct pci_dev *pdev = to_pci_dev(info->device);
2033 struct cirrusfb_info *cinfo = info->par;
2035 if (cinfo->laguna_mmio == NULL)
2036 iounmap(cinfo->laguna_mmio);
2037 iounmap(info->screen_base);
2038 #if 0 /* if system didn't claim this region, we would... */
2039 release_mem_region(0xA0000, 65535);
2040 #endif
2041 if (release_io_ports)
2042 release_region(0x3C0, 32);
2043 pci_release_regions(pdev);
2045 #endif /* CONFIG_PCI */
2047 #ifdef CONFIG_ZORRO
2048 static void cirrusfb_zorro_unmap(struct fb_info *info)
2050 struct cirrusfb_info *cinfo = info->par;
2051 struct zorro_dev *zdev = to_zorro_dev(info->device);
2053 zorro_release_device(zdev);
2055 if (cinfo->btype == BT_PICASSO4) {
2056 cinfo->regbase -= 0x600000;
2057 iounmap((void *)cinfo->regbase);
2058 iounmap(info->screen_base);
2059 } else {
2060 if (zorro_resource_start(zdev) > 0x01000000)
2061 iounmap(info->screen_base);
2064 #endif /* CONFIG_ZORRO */
2066 static int __devinit cirrusfb_set_fbinfo(struct fb_info *info)
2068 struct cirrusfb_info *cinfo = info->par;
2069 struct fb_var_screeninfo *var = &info->var;
2071 info->pseudo_palette = cinfo->pseudo_palette;
2072 info->flags = FBINFO_DEFAULT
2073 | FBINFO_HWACCEL_XPAN
2074 | FBINFO_HWACCEL_YPAN
2075 | FBINFO_HWACCEL_FILLRECT
2076 | FBINFO_HWACCEL_COPYAREA;
2077 if (noaccel)
2078 info->flags |= FBINFO_HWACCEL_DISABLED;
2079 info->fbops = &cirrusfb_ops;
2080 if (cinfo->btype == BT_GD5480) {
2081 if (var->bits_per_pixel == 16)
2082 info->screen_base += 1 * MB_;
2083 if (var->bits_per_pixel == 32)
2084 info->screen_base += 2 * MB_;
2087 /* Fill fix common fields */
2088 strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
2089 sizeof(info->fix.id));
2091 /* monochrome: only 1 memory plane */
2092 /* 8 bit and above: Use whole memory area */
2093 info->fix.smem_len = info->screen_size;
2094 if (var->bits_per_pixel == 1)
2095 info->fix.smem_len /= 4;
2096 info->fix.type_aux = 0;
2097 info->fix.xpanstep = 1;
2098 info->fix.ypanstep = 1;
2099 info->fix.ywrapstep = 0;
2101 /* FIXME: map region at 0xB8000 if available, fill in here */
2102 info->fix.mmio_len = 0;
2103 info->fix.accel = FB_ACCEL_NONE;
2105 fb_alloc_cmap(&info->cmap, 256, 0);
2107 return 0;
2110 static int __devinit cirrusfb_register(struct fb_info *info)
2112 struct cirrusfb_info *cinfo = info->par;
2113 int err;
2114 enum cirrus_board btype;
2116 btype = cinfo->btype;
2118 /* sanity checks */
2119 assert(btype != BT_NONE);
2121 /* set all the vital stuff */
2122 cirrusfb_set_fbinfo(info);
2124 dev_dbg(info->device, "(RAM start set to: 0x%p)\n", info->screen_base);
2126 err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
2127 if (!err) {
2128 dev_dbg(info->device, "wrong initial video mode\n");
2129 err = -EINVAL;
2130 goto err_dealloc_cmap;
2133 info->var.activate = FB_ACTIVATE_NOW;
2135 err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
2136 if (err < 0) {
2137 /* should never happen */
2138 dev_dbg(info->device,
2139 "choking on default var... umm, no good.\n");
2140 goto err_dealloc_cmap;
2143 err = register_framebuffer(info);
2144 if (err < 0) {
2145 dev_err(info->device,
2146 "could not register fb device; err = %d!\n", err);
2147 goto err_dealloc_cmap;
2150 return 0;
2152 err_dealloc_cmap:
2153 fb_dealloc_cmap(&info->cmap);
2154 cinfo->unmap(info);
2155 framebuffer_release(info);
2156 return err;
2159 static void __devexit cirrusfb_cleanup(struct fb_info *info)
2161 struct cirrusfb_info *cinfo = info->par;
2163 switch_monitor(cinfo, 0);
2164 unregister_framebuffer(info);
2165 fb_dealloc_cmap(&info->cmap);
2166 dev_dbg(info->device, "Framebuffer unregistered\n");
2167 cinfo->unmap(info);
2168 framebuffer_release(info);
2171 #ifdef CONFIG_PCI
2172 static int __devinit cirrusfb_pci_register(struct pci_dev *pdev,
2173 const struct pci_device_id *ent)
2175 struct cirrusfb_info *cinfo;
2176 struct fb_info *info;
2177 enum cirrus_board btype;
2178 unsigned long board_addr, board_size;
2179 int ret;
2181 ret = pci_enable_device(pdev);
2182 if (ret < 0) {
2183 printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
2184 goto err_out;
2187 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev);
2188 if (!info) {
2189 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2190 ret = -ENOMEM;
2191 goto err_disable;
2194 cinfo = info->par;
2195 cinfo->btype = btype = (enum cirrus_board) ent->driver_data;
2197 dev_dbg(info->device,
2198 " Found PCI device, base address 0 is 0x%Lx, btype set to %d\n",
2199 (unsigned long long)pdev->resource[0].start, btype);
2200 dev_dbg(info->device, " base address 1 is 0x%Lx\n",
2201 (unsigned long long)pdev->resource[1].start);
2203 if (isPReP) {
2204 pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, 0x00000000);
2205 #ifdef CONFIG_PPC_PREP
2206 get_prep_addrs(&board_addr, &info->fix.mmio_start);
2207 #endif
2208 /* PReP dies if we ioremap the IO registers, but it works w/out... */
2209 cinfo->regbase = (char __iomem *) info->fix.mmio_start;
2210 } else {
2211 dev_dbg(info->device,
2212 "Attempt to get PCI info for Cirrus Graphics Card\n");
2213 get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start);
2214 /* FIXME: this forces VGA. alternatives? */
2215 cinfo->regbase = NULL;
2216 cinfo->laguna_mmio = ioremap(info->fix.mmio_start, 0x1000);
2219 dev_dbg(info->device, "Board address: 0x%lx, register address: 0x%lx\n",
2220 board_addr, info->fix.mmio_start);
2222 board_size = (btype == BT_GD5480) ?
2223 32 * MB_ : cirrusfb_get_memsize(info, cinfo->regbase);
2225 ret = pci_request_regions(pdev, "cirrusfb");
2226 if (ret < 0) {
2227 dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
2228 board_addr);
2229 goto err_release_fb;
2231 #if 0 /* if the system didn't claim this region, we would... */
2232 if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
2233 dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
2234 0xA0000L);
2235 ret = -EBUSY;
2236 goto err_release_regions;
2238 #endif
2239 if (request_region(0x3C0, 32, "cirrusfb"))
2240 release_io_ports = 1;
2242 info->screen_base = ioremap(board_addr, board_size);
2243 if (!info->screen_base) {
2244 ret = -EIO;
2245 goto err_release_legacy;
2248 info->fix.smem_start = board_addr;
2249 info->screen_size = board_size;
2250 cinfo->unmap = cirrusfb_pci_unmap;
2252 dev_info(info->device,
2253 "Cirrus Logic chipset on PCI bus, RAM (%lu kB) at 0x%lx\n",
2254 info->screen_size >> 10, board_addr);
2255 pci_set_drvdata(pdev, info);
2257 ret = cirrusfb_register(info);
2258 if (ret)
2259 iounmap(info->screen_base);
2260 return ret;
2262 err_release_legacy:
2263 if (release_io_ports)
2264 release_region(0x3C0, 32);
2265 #if 0
2266 release_mem_region(0xA0000, 65535);
2267 err_release_regions:
2268 #endif
2269 pci_release_regions(pdev);
2270 err_release_fb:
2271 if (cinfo->laguna_mmio == NULL)
2272 iounmap(cinfo->laguna_mmio);
2273 framebuffer_release(info);
2274 err_disable:
2275 err_out:
2276 return ret;
2279 static void __devexit cirrusfb_pci_unregister(struct pci_dev *pdev)
2281 struct fb_info *info = pci_get_drvdata(pdev);
2283 cirrusfb_cleanup(info);
2286 static struct pci_driver cirrusfb_pci_driver = {
2287 .name = "cirrusfb",
2288 .id_table = cirrusfb_pci_table,
2289 .probe = cirrusfb_pci_register,
2290 .remove = __devexit_p(cirrusfb_pci_unregister),
2291 #ifdef CONFIG_PM
2292 #if 0
2293 .suspend = cirrusfb_pci_suspend,
2294 .resume = cirrusfb_pci_resume,
2295 #endif
2296 #endif
2298 #endif /* CONFIG_PCI */
2300 #ifdef CONFIG_ZORRO
2301 static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
2302 const struct zorro_device_id *ent)
2304 struct cirrusfb_info *cinfo;
2305 struct fb_info *info;
2306 enum cirrus_board btype;
2307 struct zorro_dev *z2 = NULL;
2308 unsigned long board_addr, board_size, size;
2309 int ret;
2311 btype = ent->driver_data;
2312 if (cirrusfb_zorro_table2[btype].id2)
2313 z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
2314 size = cirrusfb_zorro_table2[btype].size;
2316 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
2317 if (!info) {
2318 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2319 ret = -ENOMEM;
2320 goto err_out;
2323 dev_info(info->device, "%s board detected\n",
2324 cirrusfb_board_info[btype].name);
2326 cinfo = info->par;
2327 cinfo->btype = btype;
2329 assert(z);
2330 assert(btype != BT_NONE);
2332 board_addr = zorro_resource_start(z);
2333 board_size = zorro_resource_len(z);
2334 info->screen_size = size;
2336 if (!zorro_request_device(z, "cirrusfb")) {
2337 dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
2338 board_addr);
2339 ret = -EBUSY;
2340 goto err_release_fb;
2343 ret = -EIO;
2345 if (btype == BT_PICASSO4) {
2346 dev_info(info->device, " REG at $%lx\n", board_addr + 0x600000);
2348 /* To be precise, for the P4 this is not the */
2349 /* begin of the board, but the begin of RAM. */
2350 /* for P4, map in its address space in 2 chunks (### TEST! ) */
2351 /* (note the ugly hardcoded 16M number) */
2352 cinfo->regbase = ioremap(board_addr, 16777216);
2353 if (!cinfo->regbase)
2354 goto err_release_region;
2356 dev_dbg(info->device, "Virtual address for board set to: $%p\n",
2357 cinfo->regbase);
2358 cinfo->regbase += 0x600000;
2359 info->fix.mmio_start = board_addr + 0x600000;
2361 info->fix.smem_start = board_addr + 16777216;
2362 info->screen_base = ioremap(info->fix.smem_start, 16777216);
2363 if (!info->screen_base)
2364 goto err_unmap_regbase;
2365 } else {
2366 dev_info(info->device, " REG at $%lx\n",
2367 (unsigned long) z2->resource.start);
2369 info->fix.smem_start = board_addr;
2370 if (board_addr > 0x01000000)
2371 info->screen_base = ioremap(board_addr, board_size);
2372 else
2373 info->screen_base = (caddr_t) ZTWO_VADDR(board_addr);
2374 if (!info->screen_base)
2375 goto err_release_region;
2377 /* set address for REG area of board */
2378 cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start);
2379 info->fix.mmio_start = z2->resource.start;
2381 dev_dbg(info->device, "Virtual address for board set to: $%p\n",
2382 cinfo->regbase);
2384 cinfo->unmap = cirrusfb_zorro_unmap;
2386 dev_info(info->device,
2387 "Cirrus Logic chipset on Zorro bus, RAM (%lu MB) at $%lx\n",
2388 board_size / MB_, board_addr);
2390 zorro_set_drvdata(z, info);
2392 ret = cirrusfb_register(info);
2393 if (ret) {
2394 if (btype == BT_PICASSO4) {
2395 iounmap(info->screen_base);
2396 iounmap(cinfo->regbase - 0x600000);
2397 } else if (board_addr > 0x01000000)
2398 iounmap(info->screen_base);
2400 return ret;
2402 err_unmap_regbase:
2403 /* Parental advisory: explicit hack */
2404 iounmap(cinfo->regbase - 0x600000);
2405 err_release_region:
2406 release_region(board_addr, board_size);
2407 err_release_fb:
2408 framebuffer_release(info);
2409 err_out:
2410 return ret;
2413 void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
2415 struct fb_info *info = zorro_get_drvdata(z);
2417 cirrusfb_cleanup(info);
2420 static struct zorro_driver cirrusfb_zorro_driver = {
2421 .name = "cirrusfb",
2422 .id_table = cirrusfb_zorro_table,
2423 .probe = cirrusfb_zorro_register,
2424 .remove = __devexit_p(cirrusfb_zorro_unregister),
2426 #endif /* CONFIG_ZORRO */
2428 static int __init cirrusfb_init(void)
2430 int error = 0;
2432 #ifndef MODULE
2433 char *option = NULL;
2435 if (fb_get_options("cirrusfb", &option))
2436 return -ENODEV;
2437 cirrusfb_setup(option);
2438 #endif
2440 #ifdef CONFIG_ZORRO
2441 error |= zorro_register_driver(&cirrusfb_zorro_driver);
2442 #endif
2443 #ifdef CONFIG_PCI
2444 error |= pci_register_driver(&cirrusfb_pci_driver);
2445 #endif
2446 return error;
2449 #ifndef MODULE
2450 static int __init cirrusfb_setup(char *options)
2452 char *this_opt;
2454 if (!options || !*options)
2455 return 0;
2457 while ((this_opt = strsep(&options, ",")) != NULL) {
2458 if (!*this_opt)
2459 continue;
2461 if (!strcmp(this_opt, "noaccel"))
2462 noaccel = 1;
2463 else if (!strncmp(this_opt, "mode:", 5))
2464 mode_option = this_opt + 5;
2465 else
2466 mode_option = this_opt;
2468 return 0;
2470 #endif
2473 * Modularization
2476 MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
2477 MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
2478 MODULE_LICENSE("GPL");
2480 static void __exit cirrusfb_exit(void)
2482 #ifdef CONFIG_PCI
2483 pci_unregister_driver(&cirrusfb_pci_driver);
2484 #endif
2485 #ifdef CONFIG_ZORRO
2486 zorro_unregister_driver(&cirrusfb_zorro_driver);
2487 #endif
2490 module_init(cirrusfb_init);
2492 module_param(mode_option, charp, 0);
2493 MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
2494 module_param(noaccel, bool, 0);
2495 MODULE_PARM_DESC(noaccel, "Disable acceleration");
2497 #ifdef MODULE
2498 module_exit(cirrusfb_exit);
2499 #endif
2501 /**********************************************************************/
2502 /* about the following functions - I have used the same names for the */
2503 /* functions as Markus Wild did in his Retina driver for NetBSD as */
2504 /* they just made sense for this purpose. Apart from that, I wrote */
2505 /* these functions myself. */
2506 /**********************************************************************/
2508 /*** WGen() - write into one of the external/general registers ***/
2509 static void WGen(const struct cirrusfb_info *cinfo,
2510 int regnum, unsigned char val)
2512 unsigned long regofs = 0;
2514 if (cinfo->btype == BT_PICASSO) {
2515 /* Picasso II specific hack */
2516 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2517 regnum == CL_VSSM2) */
2518 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2519 regofs = 0xfff;
2522 vga_w(cinfo->regbase, regofs + regnum, val);
2525 /*** RGen() - read out one of the external/general registers ***/
2526 static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum)
2528 unsigned long regofs = 0;
2530 if (cinfo->btype == BT_PICASSO) {
2531 /* Picasso II specific hack */
2532 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2533 regnum == CL_VSSM2) */
2534 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2535 regofs = 0xfff;
2538 return vga_r(cinfo->regbase, regofs + regnum);
2541 /*** AttrOn() - turn on VideoEnable for Attribute controller ***/
2542 static void AttrOn(const struct cirrusfb_info *cinfo)
2544 assert(cinfo != NULL);
2546 if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) {
2547 /* if we're just in "write value" mode, write back the */
2548 /* same value as before to not modify anything */
2549 vga_w(cinfo->regbase, VGA_ATT_IW,
2550 vga_r(cinfo->regbase, VGA_ATT_R));
2552 /* turn on video bit */
2553 /* vga_w(cinfo->regbase, VGA_ATT_IW, 0x20); */
2554 vga_w(cinfo->regbase, VGA_ATT_IW, 0x33);
2556 /* dummy write on Reg0 to be on "write index" mode next time */
2557 vga_w(cinfo->regbase, VGA_ATT_IW, 0x00);
2560 /*** WHDR() - write into the Hidden DAC register ***/
2561 /* as the HDR is the only extension register that requires special treatment
2562 * (the other extension registers are accessible just like the "ordinary"
2563 * registers of their functional group) here is a specialized routine for
2564 * accessing the HDR
2566 static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val)
2568 unsigned char dummy;
2570 if (cinfo->btype == BT_PICASSO) {
2571 /* Klaus' hint for correct access to HDR on some boards */
2572 /* first write 0 to pixel mask (3c6) */
2573 WGen(cinfo, VGA_PEL_MSK, 0x00);
2574 udelay(200);
2575 /* next read dummy from pixel address (3c8) */
2576 dummy = RGen(cinfo, VGA_PEL_IW);
2577 udelay(200);
2579 /* now do the usual stuff to access the HDR */
2581 dummy = RGen(cinfo, VGA_PEL_MSK);
2582 udelay(200);
2583 dummy = RGen(cinfo, VGA_PEL_MSK);
2584 udelay(200);
2585 dummy = RGen(cinfo, VGA_PEL_MSK);
2586 udelay(200);
2587 dummy = RGen(cinfo, VGA_PEL_MSK);
2588 udelay(200);
2590 WGen(cinfo, VGA_PEL_MSK, val);
2591 udelay(200);
2593 if (cinfo->btype == BT_PICASSO) {
2594 /* now first reset HDR access counter */
2595 dummy = RGen(cinfo, VGA_PEL_IW);
2596 udelay(200);
2598 /* and at the end, restore the mask value */
2599 /* ## is this mask always 0xff? */
2600 WGen(cinfo, VGA_PEL_MSK, 0xff);
2601 udelay(200);
2605 /*** WSFR() - write to the "special function register" (SFR) ***/
2606 static void WSFR(struct cirrusfb_info *cinfo, unsigned char val)
2608 #ifdef CONFIG_ZORRO
2609 assert(cinfo->regbase != NULL);
2610 cinfo->SFR = val;
2611 z_writeb(val, cinfo->regbase + 0x8000);
2612 #endif
2615 /* The Picasso has a second register for switching the monitor bit */
2616 static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val)
2618 #ifdef CONFIG_ZORRO
2619 /* writing an arbitrary value to this one causes the monitor switcher */
2620 /* to flip to Amiga display */
2621 assert(cinfo->regbase != NULL);
2622 cinfo->SFR = val;
2623 z_writeb(val, cinfo->regbase + 0x9000);
2624 #endif
2627 /*** WClut - set CLUT entry (range: 0..63) ***/
2628 static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
2629 unsigned char green, unsigned char blue)
2631 unsigned int data = VGA_PEL_D;
2633 /* address write mode register is not translated.. */
2634 vga_w(cinfo->regbase, VGA_PEL_IW, regnum);
2636 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2637 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2638 /* but DAC data register IS, at least for Picasso II */
2639 if (cinfo->btype == BT_PICASSO)
2640 data += 0xfff;
2641 vga_w(cinfo->regbase, data, red);
2642 vga_w(cinfo->regbase, data, green);
2643 vga_w(cinfo->regbase, data, blue);
2644 } else {
2645 vga_w(cinfo->regbase, data, blue);
2646 vga_w(cinfo->regbase, data, green);
2647 vga_w(cinfo->regbase, data, red);
2651 #if 0
2652 /*** RClut - read CLUT entry (range 0..63) ***/
2653 static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
2654 unsigned char *green, unsigned char *blue)
2656 unsigned int data = VGA_PEL_D;
2658 vga_w(cinfo->regbase, VGA_PEL_IR, regnum);
2660 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2661 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2662 if (cinfo->btype == BT_PICASSO)
2663 data += 0xfff;
2664 *red = vga_r(cinfo->regbase, data);
2665 *green = vga_r(cinfo->regbase, data);
2666 *blue = vga_r(cinfo->regbase, data);
2667 } else {
2668 *blue = vga_r(cinfo->regbase, data);
2669 *green = vga_r(cinfo->regbase, data);
2670 *red = vga_r(cinfo->regbase, data);
2673 #endif
2675 /*******************************************************************
2676 cirrusfb_WaitBLT()
2678 Wait for the BitBLT engine to complete a possible earlier job
2679 *********************************************************************/
2681 /* FIXME: use interrupts instead */
2682 static void cirrusfb_WaitBLT(u8 __iomem *regbase)
2684 /* now busy-wait until we're done */
2685 while (vga_rgfx(regbase, CL_GR31) & 0x08)
2686 /* do nothing */ ;
2689 /*******************************************************************
2690 cirrusfb_BitBLT()
2692 perform accelerated "scrolling"
2693 ********************************************************************/
2695 static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
2696 u_short curx, u_short cury,
2697 u_short destx, u_short desty,
2698 u_short width, u_short height,
2699 u_short line_length)
2701 u_short nwidth, nheight;
2702 u_long nsrc, ndest;
2703 u_char bltmode;
2705 nwidth = width - 1;
2706 nheight = height - 1;
2708 bltmode = 0x00;
2709 /* if source adr < dest addr, do the Blt backwards */
2710 if (cury <= desty) {
2711 if (cury == desty) {
2712 /* if src and dest are on the same line, check x */
2713 if (curx < destx)
2714 bltmode |= 0x01;
2715 } else
2716 bltmode |= 0x01;
2718 if (!bltmode) {
2719 /* standard case: forward blitting */
2720 nsrc = (cury * line_length) + curx;
2721 ndest = (desty * line_length) + destx;
2722 } else {
2723 /* this means start addresses are at the end,
2724 * counting backwards
2726 nsrc = cury * line_length + curx +
2727 nheight * line_length + nwidth;
2728 ndest = desty * line_length + destx +
2729 nheight * line_length + nwidth;
2733 run-down of registers to be programmed:
2734 destination pitch
2735 source pitch
2736 BLT width/height
2737 source start
2738 destination start
2739 BLT mode
2740 BLT ROP
2741 VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color"
2742 start/stop
2745 cirrusfb_WaitBLT(regbase);
2747 /* pitch: set to line_length */
2748 /* dest pitch low */
2749 vga_wgfx(regbase, CL_GR24, line_length & 0xff);
2750 /* dest pitch hi */
2751 vga_wgfx(regbase, CL_GR25, line_length >> 8);
2752 /* source pitch low */
2753 vga_wgfx(regbase, CL_GR26, line_length & 0xff);
2754 /* source pitch hi */
2755 vga_wgfx(regbase, CL_GR27, line_length >> 8);
2757 /* BLT width: actual number of pixels - 1 */
2758 /* BLT width low */
2759 vga_wgfx(regbase, CL_GR20, nwidth & 0xff);
2760 /* BLT width hi */
2761 vga_wgfx(regbase, CL_GR21, nwidth >> 8);
2763 /* BLT height: actual number of lines -1 */
2764 /* BLT height low */
2765 vga_wgfx(regbase, CL_GR22, nheight & 0xff);
2766 /* BLT width hi */
2767 vga_wgfx(regbase, CL_GR23, nheight >> 8);
2769 /* BLT destination */
2770 /* BLT dest low */
2771 vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
2772 /* BLT dest mid */
2773 vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
2774 /* BLT dest hi */
2775 vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
2777 /* BLT source */
2778 /* BLT src low */
2779 vga_wgfx(regbase, CL_GR2C, (u_char) (nsrc & 0xff));
2780 /* BLT src mid */
2781 vga_wgfx(regbase, CL_GR2D, (u_char) (nsrc >> 8));
2782 /* BLT src hi */
2783 vga_wgfx(regbase, CL_GR2E, (u_char) (nsrc >> 16));
2785 /* BLT mode */
2786 vga_wgfx(regbase, CL_GR30, bltmode); /* BLT mode */
2788 /* BLT ROP: SrcCopy */
2789 vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */
2791 /* and finally: GO! */
2792 vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */
2795 /*******************************************************************
2796 cirrusfb_RectFill()
2798 perform accelerated rectangle fill
2799 ********************************************************************/
2801 static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
2802 u_short x, u_short y, u_short width, u_short height,
2803 u_char color, u_short line_length)
2805 u_short nwidth, nheight;
2806 u_long ndest;
2807 u_char op;
2809 nwidth = width - 1;
2810 nheight = height - 1;
2812 ndest = (y * line_length) + x;
2814 cirrusfb_WaitBLT(regbase);
2816 /* pitch: set to line_length */
2817 vga_wgfx(regbase, CL_GR24, line_length & 0xff); /* dest pitch low */
2818 vga_wgfx(regbase, CL_GR25, line_length >> 8); /* dest pitch hi */
2819 vga_wgfx(regbase, CL_GR26, line_length & 0xff); /* source pitch low */
2820 vga_wgfx(regbase, CL_GR27, line_length >> 8); /* source pitch hi */
2822 /* BLT width: actual number of pixels - 1 */
2823 vga_wgfx(regbase, CL_GR20, nwidth & 0xff); /* BLT width low */
2824 vga_wgfx(regbase, CL_GR21, nwidth >> 8); /* BLT width hi */
2826 /* BLT height: actual number of lines -1 */
2827 vga_wgfx(regbase, CL_GR22, nheight & 0xff); /* BLT height low */
2828 vga_wgfx(regbase, CL_GR23, nheight >> 8); /* BLT width hi */
2830 /* BLT destination */
2831 /* BLT dest low */
2832 vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
2833 /* BLT dest mid */
2834 vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
2835 /* BLT dest hi */
2836 vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
2838 /* BLT source: set to 0 (is a dummy here anyway) */
2839 vga_wgfx(regbase, CL_GR2C, 0x00); /* BLT src low */
2840 vga_wgfx(regbase, CL_GR2D, 0x00); /* BLT src mid */
2841 vga_wgfx(regbase, CL_GR2E, 0x00); /* BLT src hi */
2843 /* This is a ColorExpand Blt, using the */
2844 /* same color for foreground and background */
2845 vga_wgfx(regbase, VGA_GFX_SR_VALUE, color); /* foreground color */
2846 vga_wgfx(regbase, VGA_GFX_SR_ENABLE, color); /* background color */
2848 op = 0xc0;
2849 if (bits_per_pixel == 16) {
2850 vga_wgfx(regbase, CL_GR10, color); /* foreground color */
2851 vga_wgfx(regbase, CL_GR11, color); /* background color */
2852 op = 0x50;
2853 op = 0xd0;
2854 } else if (bits_per_pixel == 32) {
2855 vga_wgfx(regbase, CL_GR10, color); /* foreground color */
2856 vga_wgfx(regbase, CL_GR11, color); /* background color */
2857 vga_wgfx(regbase, CL_GR12, color); /* foreground color */
2858 vga_wgfx(regbase, CL_GR13, color); /* background color */
2859 vga_wgfx(regbase, CL_GR14, 0); /* foreground color */
2860 vga_wgfx(regbase, CL_GR15, 0); /* background color */
2861 op = 0x50;
2862 op = 0xf0;
2864 /* BLT mode: color expand, Enable 8x8 copy (faster?) */
2865 vga_wgfx(regbase, CL_GR30, op); /* BLT mode */
2867 /* BLT ROP: SrcCopy */
2868 vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */
2870 /* and finally: GO! */
2871 vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */
2874 /**************************************************************************
2875 * bestclock() - determine closest possible clock lower(?) than the
2876 * desired pixel clock
2877 **************************************************************************/
2878 static void bestclock(long freq, int *nom, int *den, int *div)
2880 int n, d;
2881 long h, diff;
2883 assert(nom != NULL);
2884 assert(den != NULL);
2885 assert(div != NULL);
2887 *nom = 0;
2888 *den = 0;
2889 *div = 0;
2891 if (freq < 8000)
2892 freq = 8000;
2894 diff = freq;
2896 for (n = 32; n < 128; n++) {
2897 int s = 0;
2899 d = (14318 * n) / freq;
2900 if ((d >= 7) && (d <= 63)) {
2901 int temp = d;
2903 if (temp > 31) {
2904 s = 1;
2905 temp >>= 1;
2907 h = ((14318 * n) / temp) >> s;
2908 h = h > freq ? h - freq : freq - h;
2909 if (h < diff) {
2910 diff = h;
2911 *nom = n;
2912 *den = temp;
2913 *div = s;
2916 d++;
2917 if ((d >= 7) && (d <= 63)) {
2918 if (d > 31) {
2919 s = 1;
2920 d >>= 1;
2922 h = ((14318 * n) / d) >> s;
2923 h = h > freq ? h - freq : freq - h;
2924 if (h < diff) {
2925 diff = h;
2926 *nom = n;
2927 *den = d;
2928 *div = s;
2934 /* -------------------------------------------------------------------------
2936 * debugging functions
2938 * -------------------------------------------------------------------------
2941 #ifdef CIRRUSFB_DEBUG
2944 * cirrusfb_dbg_print_regs
2945 * @base: If using newmmio, the newmmio base address, otherwise %NULL
2946 * @reg_class: type of registers to read: %CRT, or %SEQ
2948 * DESCRIPTION:
2949 * Dumps the given list of VGA CRTC registers. If @base is %NULL,
2950 * old-style I/O ports are queried for information, otherwise MMIO is
2951 * used at the given @base address to query the information.
2954 static void cirrusfb_dbg_print_regs(struct fb_info *info,
2955 caddr_t regbase,
2956 enum cirrusfb_dbg_reg_class reg_class, ...)
2958 va_list list;
2959 unsigned char val = 0;
2960 unsigned reg;
2961 char *name;
2963 va_start(list, reg_class);
2965 name = va_arg(list, char *);
2966 while (name != NULL) {
2967 reg = va_arg(list, int);
2969 switch (reg_class) {
2970 case CRT:
2971 val = vga_rcrt(regbase, (unsigned char) reg);
2972 break;
2973 case SEQ:
2974 val = vga_rseq(regbase, (unsigned char) reg);
2975 break;
2976 default:
2977 /* should never occur */
2978 assert(false);
2979 break;
2982 dev_dbg(info->device, "%8s = 0x%02X\n", name, val);
2984 name = va_arg(list, char *);
2987 va_end(list);
2991 * cirrusfb_dbg_reg_dump
2992 * @base: If using newmmio, the newmmio base address, otherwise %NULL
2994 * DESCRIPTION:
2995 * Dumps a list of interesting VGA and CIRRUSFB registers. If @base is %NULL,
2996 * old-style I/O ports are queried for information, otherwise MMIO is
2997 * used at the given @base address to query the information.
3000 static void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase)
3002 dev_dbg(info->device, "VGA CRTC register dump:\n");
3004 cirrusfb_dbg_print_regs(info, regbase, CRT,
3005 "CR00", 0x00,
3006 "CR01", 0x01,
3007 "CR02", 0x02,
3008 "CR03", 0x03,
3009 "CR04", 0x04,
3010 "CR05", 0x05,
3011 "CR06", 0x06,
3012 "CR07", 0x07,
3013 "CR08", 0x08,
3014 "CR09", 0x09,
3015 "CR0A", 0x0A,
3016 "CR0B", 0x0B,
3017 "CR0C", 0x0C,
3018 "CR0D", 0x0D,
3019 "CR0E", 0x0E,
3020 "CR0F", 0x0F,
3021 "CR10", 0x10,
3022 "CR11", 0x11,
3023 "CR12", 0x12,
3024 "CR13", 0x13,
3025 "CR14", 0x14,
3026 "CR15", 0x15,
3027 "CR16", 0x16,
3028 "CR17", 0x17,
3029 "CR18", 0x18,
3030 "CR22", 0x22,
3031 "CR24", 0x24,
3032 "CR26", 0x26,
3033 "CR2D", 0x2D,
3034 "CR2E", 0x2E,
3035 "CR2F", 0x2F,
3036 "CR30", 0x30,
3037 "CR31", 0x31,
3038 "CR32", 0x32,
3039 "CR33", 0x33,
3040 "CR34", 0x34,
3041 "CR35", 0x35,
3042 "CR36", 0x36,
3043 "CR37", 0x37,
3044 "CR38", 0x38,
3045 "CR39", 0x39,
3046 "CR3A", 0x3A,
3047 "CR3B", 0x3B,
3048 "CR3C", 0x3C,
3049 "CR3D", 0x3D,
3050 "CR3E", 0x3E,
3051 "CR3F", 0x3F,
3052 NULL);
3054 dev_dbg(info->device, "\n");
3056 dev_dbg(info->device, "VGA SEQ register dump:\n");
3058 cirrusfb_dbg_print_regs(info, regbase, SEQ,
3059 "SR00", 0x00,
3060 "SR01", 0x01,
3061 "SR02", 0x02,
3062 "SR03", 0x03,
3063 "SR04", 0x04,
3064 "SR08", 0x08,
3065 "SR09", 0x09,
3066 "SR0A", 0x0A,
3067 "SR0B", 0x0B,
3068 "SR0D", 0x0D,
3069 "SR10", 0x10,
3070 "SR11", 0x11,
3071 "SR12", 0x12,
3072 "SR13", 0x13,
3073 "SR14", 0x14,
3074 "SR15", 0x15,
3075 "SR16", 0x16,
3076 "SR17", 0x17,
3077 "SR18", 0x18,
3078 "SR19", 0x19,
3079 "SR1A", 0x1A,
3080 "SR1B", 0x1B,
3081 "SR1C", 0x1C,
3082 "SR1D", 0x1D,
3083 "SR1E", 0x1E,
3084 "SR1F", 0x1F,
3085 NULL);
3087 dev_dbg(info->device, "\n");
3090 #endif /* CIRRUSFB_DEBUG */