cirrusfb: add accelerator constant
[linux-2.6/linux-loongson.git] / drivers / video / cirrusfb.c
blobe9a2661669eb556c77b578ef586f28b32a005979
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, /* GD5434 */
99 BT_PICCOLO, /* GD5426 */
100 BT_PICASSO, /* GD5426 or GD5428 */
101 BT_SPECTRUM, /* GD5426 or GD5428 */
102 BT_PICASSO4, /* GD5446 */
103 BT_ALPINE, /* GD543x/4x */
104 BT_GD5480,
105 BT_LAGUNA, /* GD5462/64 */
106 BT_LAGUNAB, /* GD5465 */
110 * per-board-type information, used for enumerating and abstracting
111 * chip-specific information
112 * NOTE: MUST be in the same order as enum cirrus_board in order to
113 * use direct indexing on this array
114 * NOTE: '__initdata' cannot be used as some of this info
115 * is required at runtime. Maybe separate into an init-only and
116 * a run-time table?
118 static const struct cirrusfb_board_info_rec {
119 char *name; /* ASCII name of chipset */
120 long maxclock[5]; /* maximum video clock */
121 /* for 1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */
122 bool init_sr07 : 1; /* init SR07 during init_vgachip() */
123 bool init_sr1f : 1; /* write SR1F during init_vgachip() */
124 /* construct bit 19 of screen start address */
125 bool scrn_start_bit19 : 1;
127 /* initial SR07 value, then for each mode */
128 unsigned char sr07;
129 unsigned char sr07_1bpp;
130 unsigned char sr07_1bpp_mux;
131 unsigned char sr07_8bpp;
132 unsigned char sr07_8bpp_mux;
134 unsigned char sr1f; /* SR1F VGA initial register value */
135 } cirrusfb_board_info[] = {
136 [BT_SD64] = {
137 .name = "CL SD64",
138 .maxclock = {
139 /* guess */
140 /* the SD64/P4 have a higher max. videoclock */
141 135100, 135100, 85500, 85500, 0
143 .init_sr07 = true,
144 .init_sr1f = true,
145 .scrn_start_bit19 = true,
146 .sr07 = 0xF0,
147 .sr07_1bpp = 0xF0,
148 .sr07_8bpp = 0xF1,
149 .sr1f = 0x20
151 [BT_PICCOLO] = {
152 .name = "CL Piccolo",
153 .maxclock = {
154 /* guess */
155 90000, 90000, 90000, 90000, 90000
157 .init_sr07 = true,
158 .init_sr1f = true,
159 .scrn_start_bit19 = false,
160 .sr07 = 0x80,
161 .sr07_1bpp = 0x80,
162 .sr07_8bpp = 0x81,
163 .sr1f = 0x22
165 [BT_PICASSO] = {
166 .name = "CL Picasso",
167 .maxclock = {
168 /* guess */
169 90000, 90000, 90000, 90000, 90000
171 .init_sr07 = true,
172 .init_sr1f = true,
173 .scrn_start_bit19 = false,
174 .sr07 = 0x20,
175 .sr07_1bpp = 0x20,
176 .sr07_8bpp = 0x21,
177 .sr1f = 0x22
179 [BT_SPECTRUM] = {
180 .name = "CL Spectrum",
181 .maxclock = {
182 /* guess */
183 90000, 90000, 90000, 90000, 90000
185 .init_sr07 = true,
186 .init_sr1f = true,
187 .scrn_start_bit19 = false,
188 .sr07 = 0x80,
189 .sr07_1bpp = 0x80,
190 .sr07_8bpp = 0x81,
191 .sr1f = 0x22
193 [BT_PICASSO4] = {
194 .name = "CL Picasso4",
195 .maxclock = {
196 135100, 135100, 85500, 85500, 0
198 .init_sr07 = true,
199 .init_sr1f = false,
200 .scrn_start_bit19 = true,
201 .sr07 = 0xA0,
202 .sr07_1bpp = 0xA0,
203 .sr07_1bpp_mux = 0xA6,
204 .sr07_8bpp = 0xA1,
205 .sr07_8bpp_mux = 0xA7,
206 .sr1f = 0
208 [BT_ALPINE] = {
209 .name = "CL Alpine",
210 .maxclock = {
211 /* for the GD5430. GD5446 can do more... */
212 85500, 85500, 50000, 28500, 0
214 .init_sr07 = true,
215 .init_sr1f = true,
216 .scrn_start_bit19 = true,
217 .sr07 = 0xA0,
218 .sr07_1bpp = 0xA0,
219 .sr07_1bpp_mux = 0xA6,
220 .sr07_8bpp = 0xA1,
221 .sr07_8bpp_mux = 0xA7,
222 .sr1f = 0x1C
224 [BT_GD5480] = {
225 .name = "CL GD5480",
226 .maxclock = {
227 135100, 200000, 200000, 135100, 135100
229 .init_sr07 = true,
230 .init_sr1f = true,
231 .scrn_start_bit19 = true,
232 .sr07 = 0x10,
233 .sr07_1bpp = 0x11,
234 .sr07_8bpp = 0x11,
235 .sr1f = 0x1C
237 [BT_LAGUNA] = {
238 .name = "CL Laguna",
239 .maxclock = {
240 /* taken from X11 code */
241 170000, 170000, 170000, 170000, 135100,
243 .init_sr07 = false,
244 .init_sr1f = false,
245 .scrn_start_bit19 = true,
247 [BT_LAGUNAB] = {
248 .name = "CL Laguna AGP",
249 .maxclock = {
250 /* taken from X11 code */
251 170000, 250000, 170000, 170000, 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_LAGUNAB), /* 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 #ifdef CIRRUSFB_DEBUG
330 enum cirrusfb_dbg_reg_class {
331 CRT,
334 #endif /* CIRRUSFB_DEBUG */
336 /* info about board */
337 struct cirrusfb_info {
338 u8 __iomem *regbase;
339 u8 __iomem *laguna_mmio;
340 enum cirrus_board btype;
341 unsigned char SFR; /* Shadow of special function register */
343 int multiplexing;
344 int blank_mode;
345 u32 pseudo_palette[16];
347 void (*unmap)(struct fb_info *info);
350 static int noaccel __devinitdata;
351 static char *mode_option __devinitdata = "640x480@60";
353 /****************************************************************************/
354 /**** BEGIN PROTOTYPES ******************************************************/
356 /*--- Interface used by the world ------------------------------------------*/
357 static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
358 struct fb_info *info);
360 /*--- Internal routines ----------------------------------------------------*/
361 static void init_vgachip(struct fb_info *info);
362 static void switch_monitor(struct cirrusfb_info *cinfo, int on);
363 static void WGen(const struct cirrusfb_info *cinfo,
364 int regnum, unsigned char val);
365 static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum);
366 static void AttrOn(const struct cirrusfb_info *cinfo);
367 static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val);
368 static void WSFR(struct cirrusfb_info *cinfo, unsigned char val);
369 static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val);
370 static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum,
371 unsigned char red, unsigned char green, unsigned char blue);
372 #if 0
373 static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum,
374 unsigned char *red, unsigned char *green,
375 unsigned char *blue);
376 #endif
377 static void cirrusfb_WaitBLT(u8 __iomem *regbase);
378 static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
379 u_short curx, u_short cury,
380 u_short destx, u_short desty,
381 u_short width, u_short height,
382 u_short line_length);
383 static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
384 u_short x, u_short y,
385 u_short width, u_short height,
386 u32 fg_color, u32 bg_color,
387 u_short line_length, u_char blitmode);
389 static void bestclock(long freq, int *nom, int *den, int *div);
391 #ifdef CIRRUSFB_DEBUG
392 static void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase);
393 static void cirrusfb_dbg_print_regs(struct fb_info *info,
394 caddr_t regbase,
395 enum cirrusfb_dbg_reg_class reg_class, ...);
396 #endif /* CIRRUSFB_DEBUG */
398 /*** END PROTOTYPES ********************************************************/
399 /*****************************************************************************/
400 /*** BEGIN Interface Used by the World ***************************************/
402 static inline int is_laguna(const struct cirrusfb_info *cinfo)
404 return cinfo->btype == BT_LAGUNA || cinfo->btype == BT_LAGUNAB;
407 static int opencount;
409 /*--- Open /dev/fbx ---------------------------------------------------------*/
410 static int cirrusfb_open(struct fb_info *info, int user)
412 if (opencount++ == 0)
413 switch_monitor(info->par, 1);
414 return 0;
417 /*--- Close /dev/fbx --------------------------------------------------------*/
418 static int cirrusfb_release(struct fb_info *info, int user)
420 if (--opencount == 0)
421 switch_monitor(info->par, 0);
422 return 0;
425 /**** END Interface used by the World *************************************/
426 /****************************************************************************/
427 /**** BEGIN Hardware specific Routines **************************************/
429 /* Check if the MCLK is not a better clock source */
430 static int cirrusfb_check_mclk(struct fb_info *info, long freq)
432 struct cirrusfb_info *cinfo = info->par;
433 long mclk = vga_rseq(cinfo->regbase, CL_SEQR1F) & 0x3f;
435 /* Read MCLK value */
436 mclk = (14318 * mclk) >> 3;
437 dev_dbg(info->device, "Read MCLK of %ld kHz\n", mclk);
439 /* Determine if we should use MCLK instead of VCLK, and if so, what we
440 * should divide it by to get VCLK
443 if (abs(freq - mclk) < 250) {
444 dev_dbg(info->device, "Using VCLK = MCLK\n");
445 return 1;
446 } else if (abs(freq - (mclk / 2)) < 250) {
447 dev_dbg(info->device, "Using VCLK = MCLK/2\n");
448 return 2;
451 return 0;
454 static int cirrusfb_check_pixclock(const struct fb_var_screeninfo *var,
455 struct fb_info *info)
457 long freq;
458 long maxclock;
459 struct cirrusfb_info *cinfo = info->par;
460 unsigned maxclockidx = var->bits_per_pixel >> 3;
462 /* convert from ps to kHz */
463 freq = PICOS2KHZ(var->pixclock);
465 dev_dbg(info->device, "desired pixclock: %ld kHz\n", freq);
467 maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
468 cinfo->multiplexing = 0;
470 /* If the frequency is greater than we can support, we might be able
471 * to use multiplexing for the video mode */
472 if (freq > maxclock) {
473 dev_err(info->device,
474 "Frequency greater than maxclock (%ld kHz)\n",
475 maxclock);
476 return -EINVAL;
479 * Additional constraint: 8bpp uses DAC clock doubling to allow maximum
480 * pixel clock
482 if (var->bits_per_pixel == 8) {
483 switch (cinfo->btype) {
484 case BT_ALPINE:
485 case BT_PICASSO4:
486 if (freq > 85500)
487 cinfo->multiplexing = 1;
488 break;
489 case BT_GD5480:
490 if (freq > 135100)
491 cinfo->multiplexing = 1;
492 break;
494 default:
495 dev_err(info->device,
496 "Frequency greater than maxclock (%ld kHz)\n",
497 maxclock);
498 return -EINVAL;
501 #if 0
502 /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
503 * the VCLK is double the pixel clock. */
504 switch (var->bits_per_pixel) {
505 case 16:
506 case 24:
507 if (var->xres <= 800)
508 /* Xbh has this type of clock for 32-bit */
509 freq /= 2;
510 break;
512 #endif
513 return 0;
516 static int cirrusfb_check_var(struct fb_var_screeninfo *var,
517 struct fb_info *info)
519 int yres;
520 /* memory size in pixels */
521 unsigned pixels = info->screen_size * 8 / var->bits_per_pixel;
522 struct cirrusfb_info *cinfo = info->par;
524 switch (var->bits_per_pixel) {
525 case 1:
526 var->red.offset = 0;
527 var->red.length = 1;
528 var->green = var->red;
529 var->blue = var->red;
530 break;
532 case 8:
533 var->red.offset = 0;
534 var->red.length = 8;
535 var->green = var->red;
536 var->blue = var->red;
537 break;
539 case 16:
540 if (isPReP) {
541 var->red.offset = 2;
542 var->green.offset = -3;
543 var->blue.offset = 8;
544 } else {
545 var->red.offset = 11;
546 var->green.offset = 5;
547 var->blue.offset = 0;
549 var->red.length = 5;
550 var->green.length = 6;
551 var->blue.length = 5;
552 break;
554 case 24:
555 if (isPReP) {
556 var->red.offset = 0;
557 var->green.offset = 8;
558 var->blue.offset = 16;
559 } else {
560 var->red.offset = 16;
561 var->green.offset = 8;
562 var->blue.offset = 0;
564 var->red.length = 8;
565 var->green.length = 8;
566 var->blue.length = 8;
567 break;
569 default:
570 dev_dbg(info->device,
571 "Unsupported bpp size: %d\n", var->bits_per_pixel);
572 assert(false);
573 /* should never occur */
574 break;
577 if (var->xres_virtual < var->xres)
578 var->xres_virtual = var->xres;
579 /* use highest possible virtual resolution */
580 if (var->yres_virtual == -1) {
581 var->yres_virtual = pixels / var->xres_virtual;
583 dev_info(info->device,
584 "virtual resolution set to maximum of %dx%d\n",
585 var->xres_virtual, var->yres_virtual);
587 if (var->yres_virtual < var->yres)
588 var->yres_virtual = var->yres;
590 if (var->xres_virtual * var->yres_virtual > pixels) {
591 dev_err(info->device, "mode %dx%dx%d rejected... "
592 "virtual resolution too high to fit into video memory!\n",
593 var->xres_virtual, var->yres_virtual,
594 var->bits_per_pixel);
595 return -EINVAL;
598 if (var->xoffset < 0)
599 var->xoffset = 0;
600 if (var->yoffset < 0)
601 var->yoffset = 0;
603 /* truncate xoffset and yoffset to maximum if too high */
604 if (var->xoffset > var->xres_virtual - var->xres)
605 var->xoffset = var->xres_virtual - var->xres - 1;
606 if (var->yoffset > var->yres_virtual - var->yres)
607 var->yoffset = var->yres_virtual - var->yres - 1;
609 var->red.msb_right =
610 var->green.msb_right =
611 var->blue.msb_right =
612 var->transp.offset =
613 var->transp.length =
614 var->transp.msb_right = 0;
616 yres = var->yres;
617 if (var->vmode & FB_VMODE_DOUBLE)
618 yres *= 2;
619 else if (var->vmode & FB_VMODE_INTERLACED)
620 yres = (yres + 1) / 2;
622 if (yres >= 1280) {
623 dev_err(info->device, "ERROR: VerticalTotal >= 1280; "
624 "special treatment required! (TODO)\n");
625 return -EINVAL;
628 if (cirrusfb_check_pixclock(var, info))
629 return -EINVAL;
631 if (!is_laguna(cinfo))
632 var->accel_flags = FB_ACCELF_TEXT;
634 return 0;
637 static void cirrusfb_set_mclk_as_source(const struct fb_info *info, int div)
639 struct cirrusfb_info *cinfo = info->par;
640 unsigned char old1f, old1e;
642 assert(cinfo != NULL);
643 old1f = vga_rseq(cinfo->regbase, CL_SEQR1F) & ~0x40;
645 if (div) {
646 dev_dbg(info->device, "Set %s as pixclock source.\n",
647 (div == 2) ? "MCLK/2" : "MCLK");
648 old1f |= 0x40;
649 old1e = vga_rseq(cinfo->regbase, CL_SEQR1E) & ~0x1;
650 if (div == 2)
651 old1e |= 1;
653 vga_wseq(cinfo->regbase, CL_SEQR1E, old1e);
655 vga_wseq(cinfo->regbase, CL_SEQR1F, old1f);
658 /*************************************************************************
659 cirrusfb_set_par_foo()
661 actually writes the values for a new video mode into the hardware,
662 **************************************************************************/
663 static int cirrusfb_set_par_foo(struct fb_info *info)
665 struct cirrusfb_info *cinfo = info->par;
666 struct fb_var_screeninfo *var = &info->var;
667 u8 __iomem *regbase = cinfo->regbase;
668 unsigned char tmp;
669 int pitch;
670 const struct cirrusfb_board_info_rec *bi;
671 int hdispend, hsyncstart, hsyncend, htotal;
672 int yres, vdispend, vsyncstart, vsyncend, vtotal;
673 long freq;
674 int nom, den, div;
675 unsigned int control = 0, format = 0, threshold = 0;
677 dev_dbg(info->device, "Requested mode: %dx%dx%d\n",
678 var->xres, var->yres, var->bits_per_pixel);
680 switch (var->bits_per_pixel) {
681 case 1:
682 info->fix.line_length = var->xres_virtual / 8;
683 info->fix.visual = FB_VISUAL_MONO10;
684 break;
686 case 8:
687 info->fix.line_length = var->xres_virtual;
688 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
689 break;
691 case 16:
692 case 24:
693 info->fix.line_length = var->xres_virtual *
694 var->bits_per_pixel >> 3;
695 info->fix.visual = FB_VISUAL_TRUECOLOR;
696 break;
698 info->fix.type = FB_TYPE_PACKED_PIXELS;
700 init_vgachip(info);
702 bi = &cirrusfb_board_info[cinfo->btype];
704 hsyncstart = var->xres + var->right_margin;
705 hsyncend = hsyncstart + var->hsync_len;
706 htotal = (hsyncend + var->left_margin) / 8 - 5;
707 hdispend = var->xres / 8 - 1;
708 hsyncstart = hsyncstart / 8 + 1;
709 hsyncend = hsyncend / 8 + 1;
711 yres = var->yres;
712 vsyncstart = yres + var->lower_margin;
713 vsyncend = vsyncstart + var->vsync_len;
714 vtotal = vsyncend + var->upper_margin;
715 vdispend = yres - 1;
717 if (var->vmode & FB_VMODE_DOUBLE) {
718 yres *= 2;
719 vsyncstart *= 2;
720 vsyncend *= 2;
721 vtotal *= 2;
722 } else if (var->vmode & FB_VMODE_INTERLACED) {
723 yres = (yres + 1) / 2;
724 vsyncstart = (vsyncstart + 1) / 2;
725 vsyncend = (vsyncend + 1) / 2;
726 vtotal = (vtotal + 1) / 2;
729 vtotal -= 2;
730 vsyncstart -= 1;
731 vsyncend -= 1;
733 if (yres >= 1024) {
734 vtotal /= 2;
735 vsyncstart /= 2;
736 vsyncend /= 2;
737 vdispend /= 2;
739 if (cinfo->multiplexing) {
740 htotal /= 2;
741 hsyncstart /= 2;
742 hsyncend /= 2;
743 hdispend /= 2;
745 /* unlock register VGA_CRTC_H_TOTAL..CRT7 */
746 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */
748 /* if debugging is enabled, all parameters get output before writing */
749 dev_dbg(info->device, "CRT0: %d\n", htotal);
750 vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal);
752 dev_dbg(info->device, "CRT1: %d\n", hdispend);
753 vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend);
755 dev_dbg(info->device, "CRT2: %d\n", var->xres / 8);
756 vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8);
758 /* + 128: Compatible read */
759 dev_dbg(info->device, "CRT3: 128+%d\n", (htotal + 5) % 32);
760 vga_wcrt(regbase, VGA_CRTC_H_BLANK_END,
761 128 + ((htotal + 5) % 32));
763 dev_dbg(info->device, "CRT4: %d\n", hsyncstart);
764 vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart);
766 tmp = hsyncend % 32;
767 if ((htotal + 5) & 32)
768 tmp += 128;
769 dev_dbg(info->device, "CRT5: %d\n", tmp);
770 vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp);
772 dev_dbg(info->device, "CRT6: %d\n", vtotal & 0xff);
773 vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff);
775 tmp = 16; /* LineCompare bit #9 */
776 if (vtotal & 256)
777 tmp |= 1;
778 if (vdispend & 256)
779 tmp |= 2;
780 if (vsyncstart & 256)
781 tmp |= 4;
782 if ((vdispend + 1) & 256)
783 tmp |= 8;
784 if (vtotal & 512)
785 tmp |= 32;
786 if (vdispend & 512)
787 tmp |= 64;
788 if (vsyncstart & 512)
789 tmp |= 128;
790 dev_dbg(info->device, "CRT7: %d\n", tmp);
791 vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp);
793 tmp = 0x40; /* LineCompare bit #8 */
794 if ((vdispend + 1) & 512)
795 tmp |= 0x20;
796 if (var->vmode & FB_VMODE_DOUBLE)
797 tmp |= 0x80;
798 dev_dbg(info->device, "CRT9: %d\n", tmp);
799 vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp);
801 dev_dbg(info->device, "CRT10: %d\n", vsyncstart & 0xff);
802 vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff);
804 dev_dbg(info->device, "CRT11: 64+32+%d\n", vsyncend % 16);
805 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32);
807 dev_dbg(info->device, "CRT12: %d\n", vdispend & 0xff);
808 vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff);
810 dev_dbg(info->device, "CRT15: %d\n", (vdispend + 1) & 0xff);
811 vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff);
813 dev_dbg(info->device, "CRT16: %d\n", vtotal & 0xff);
814 vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff);
816 dev_dbg(info->device, "CRT18: 0xff\n");
817 vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff);
819 tmp = 0;
820 if (var->vmode & FB_VMODE_INTERLACED)
821 tmp |= 1;
822 if ((htotal + 5) & 64)
823 tmp |= 16;
824 if ((htotal + 5) & 128)
825 tmp |= 32;
826 if (vtotal & 256)
827 tmp |= 64;
828 if (vtotal & 512)
829 tmp |= 128;
831 dev_dbg(info->device, "CRT1a: %d\n", tmp);
832 vga_wcrt(regbase, CL_CRT1A, tmp);
834 freq = PICOS2KHZ(var->pixclock);
835 if (cinfo->btype == BT_ALPINE && var->bits_per_pixel == 24)
836 freq *= 3;
837 if (cinfo->multiplexing)
838 freq /= 2;
840 bestclock(freq, &nom, &den, &div);
842 dev_dbg(info->device, "VCLK freq: %ld kHz nom: %d den: %d div: %d\n",
843 freq, nom, den, div);
845 /* set VCLK0 */
846 /* hardware RefClock: 14.31818 MHz */
847 /* formula: VClk = (OSC * N) / (D * (1+P)) */
848 /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
850 if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_PICASSO4) {
851 /* if freq is close to mclk or mclk/2 select mclk
852 * as clock source
854 int divMCLK = cirrusfb_check_mclk(info, freq);
855 if (divMCLK) {
856 nom = 0;
857 cirrusfb_set_mclk_as_source(info, divMCLK);
860 if (is_laguna(cinfo)) {
861 long pcifc = fb_readl(cinfo->laguna_mmio + 0x3fc);
862 unsigned char tile = fb_readb(cinfo->laguna_mmio + 0x407);
863 unsigned short tile_control;
865 if (cinfo->btype == BT_LAGUNAB) {
866 tile_control = fb_readw(cinfo->laguna_mmio + 0x2c4);
867 tile_control &= ~0x80;
868 fb_writew(tile_control, cinfo->laguna_mmio + 0x2c4);
871 fb_writel(pcifc | 0x10000000l, cinfo->laguna_mmio + 0x3fc);
872 fb_writeb(tile & 0x3f, cinfo->laguna_mmio + 0x407);
873 control = fb_readw(cinfo->laguna_mmio + 0x402);
874 threshold = fb_readw(cinfo->laguna_mmio + 0xea);
875 control &= ~0x6800;
876 format = 0;
877 threshold &= 0xffe0 & 0x3fbf;
879 if (nom) {
880 tmp = den << 1;
881 if (div != 0)
882 tmp |= 1;
883 /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
884 if ((cinfo->btype == BT_SD64) ||
885 (cinfo->btype == BT_ALPINE) ||
886 (cinfo->btype == BT_GD5480))
887 tmp |= 0x80;
889 dev_dbg(info->device, "CL_SEQR1B: %d\n", (int) tmp);
890 /* Laguna chipset has reversed clock registers */
891 if (is_laguna(cinfo)) {
892 vga_wseq(regbase, CL_SEQRE, tmp);
893 vga_wseq(regbase, CL_SEQR1E, nom);
894 } else {
895 vga_wseq(regbase, CL_SEQRB, nom);
896 vga_wseq(regbase, CL_SEQR1B, tmp);
900 if (yres >= 1024)
901 /* 1280x1024 */
902 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7);
903 else
904 /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
905 * address wrap, no compat. */
906 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3);
908 /* don't know if it would hurt to also program this if no interlaced */
909 /* mode is used, but I feel better this way.. :-) */
910 if (var->vmode & FB_VMODE_INTERLACED)
911 vga_wcrt(regbase, VGA_CRTC_REGS, htotal / 2);
912 else
913 vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
915 /* adjust horizontal/vertical sync type (low/high) */
916 /* enable display memory & CRTC I/O address for color mode */
917 tmp = 0x03;
918 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
919 tmp |= 0x40;
920 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
921 tmp |= 0x80;
922 if (is_laguna(cinfo))
923 tmp |= 0xc;
924 WGen(cinfo, VGA_MIS_W, tmp);
926 /* text cursor on and start line */
927 vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0);
928 /* text cursor end line */
929 vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 31);
931 /******************************************************
933 * 1 bpp
937 /* programming for different color depths */
938 if (var->bits_per_pixel == 1) {
939 dev_dbg(info->device, "preparing for 1 bit deep display\n");
940 vga_wgfx(regbase, VGA_GFX_MODE, 0); /* mode register */
942 /* SR07 */
943 switch (cinfo->btype) {
944 case BT_SD64:
945 case BT_PICCOLO:
946 case BT_PICASSO:
947 case BT_SPECTRUM:
948 case BT_PICASSO4:
949 case BT_ALPINE:
950 case BT_GD5480:
951 vga_wseq(regbase, CL_SEQR7,
952 cinfo->multiplexing ?
953 bi->sr07_1bpp_mux : bi->sr07_1bpp);
954 break;
956 case BT_LAGUNA:
957 case BT_LAGUNAB:
958 vga_wseq(regbase, CL_SEQR7,
959 vga_rseq(regbase, CL_SEQR7) & ~0x01);
960 break;
962 default:
963 dev_warn(info->device, "unknown Board\n");
964 break;
967 /* Extended Sequencer Mode */
968 switch (cinfo->btype) {
969 case BT_SD64:
970 /* setting the SEQRF on SD64 is not necessary
971 * (only during init)
973 /* MCLK select */
974 vga_wseq(regbase, CL_SEQR1F, 0x1a);
975 break;
977 case BT_PICCOLO:
978 case BT_SPECTRUM:
979 /* ### ueberall 0x22? */
980 /* ##vorher 1c MCLK select */
981 vga_wseq(regbase, CL_SEQR1F, 0x22);
982 /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
983 vga_wseq(regbase, CL_SEQRF, 0xb0);
984 break;
986 case BT_PICASSO:
987 /* ##vorher 22 MCLK select */
988 vga_wseq(regbase, CL_SEQR1F, 0x22);
989 /* ## vorher d0 avoid FIFO underruns..? */
990 vga_wseq(regbase, CL_SEQRF, 0xd0);
991 break;
993 case BT_PICASSO4:
994 case BT_ALPINE:
995 case BT_GD5480:
996 case BT_LAGUNA:
997 case BT_LAGUNAB:
998 /* do nothing */
999 break;
1001 default:
1002 dev_warn(info->device, "unknown Board\n");
1003 break;
1006 /* pixel mask: pass-through for first plane */
1007 WGen(cinfo, VGA_PEL_MSK, 0x01);
1008 if (cinfo->multiplexing)
1009 /* hidden dac reg: 1280x1024 */
1010 WHDR(cinfo, 0x4a);
1011 else
1012 /* hidden dac: nothing */
1013 WHDR(cinfo, 0);
1014 /* memory mode: odd/even, ext. memory */
1015 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06);
1016 /* plane mask: only write to first plane */
1017 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01);
1020 /******************************************************
1022 * 8 bpp
1026 else if (var->bits_per_pixel == 8) {
1027 dev_dbg(info->device, "preparing for 8 bit deep display\n");
1028 switch (cinfo->btype) {
1029 case BT_SD64:
1030 case BT_PICCOLO:
1031 case BT_PICASSO:
1032 case BT_SPECTRUM:
1033 case BT_PICASSO4:
1034 case BT_ALPINE:
1035 case BT_GD5480:
1036 vga_wseq(regbase, CL_SEQR7,
1037 cinfo->multiplexing ?
1038 bi->sr07_8bpp_mux : bi->sr07_8bpp);
1039 break;
1041 case BT_LAGUNA:
1042 case BT_LAGUNAB:
1043 vga_wseq(regbase, CL_SEQR7,
1044 vga_rseq(regbase, CL_SEQR7) | 0x01);
1045 threshold |= 0x10;
1046 break;
1048 default:
1049 dev_warn(info->device, "unknown Board\n");
1050 break;
1053 switch (cinfo->btype) {
1054 case BT_SD64:
1055 /* MCLK select */
1056 vga_wseq(regbase, CL_SEQR1F, 0x1d);
1057 break;
1059 case BT_PICCOLO:
1060 case BT_PICASSO:
1061 case BT_SPECTRUM:
1062 /* ### vorher 1c MCLK select */
1063 vga_wseq(regbase, CL_SEQR1F, 0x22);
1064 /* Fast Page-Mode writes */
1065 vga_wseq(regbase, CL_SEQRF, 0xb0);
1066 break;
1068 case BT_PICASSO4:
1069 #ifdef CONFIG_ZORRO
1070 /* ### INCOMPLETE!! */
1071 vga_wseq(regbase, CL_SEQRF, 0xb8);
1072 #endif
1073 case BT_ALPINE:
1074 /* We already set SRF and SR1F */
1075 break;
1077 case BT_GD5480:
1078 case BT_LAGUNA:
1079 case BT_LAGUNAB:
1080 /* do nothing */
1081 break;
1083 default:
1084 dev_warn(info->device, "unknown board\n");
1085 break;
1088 /* mode register: 256 color mode */
1089 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1090 if (cinfo->multiplexing)
1091 /* hidden dac reg: 1280x1024 */
1092 WHDR(cinfo, 0x4a);
1093 else
1094 /* hidden dac: nothing */
1095 WHDR(cinfo, 0);
1098 /******************************************************
1100 * 16 bpp
1104 else if (var->bits_per_pixel == 16) {
1105 dev_dbg(info->device, "preparing for 16 bit deep display\n");
1106 switch (cinfo->btype) {
1107 case BT_SD64:
1108 /* Extended Sequencer Mode: 256c col. mode */
1109 vga_wseq(regbase, CL_SEQR7, 0xf7);
1110 /* MCLK select */
1111 vga_wseq(regbase, CL_SEQR1F, 0x1e);
1112 break;
1114 case BT_PICCOLO:
1115 case BT_SPECTRUM:
1116 vga_wseq(regbase, CL_SEQR7, 0x87);
1117 /* Fast Page-Mode writes */
1118 vga_wseq(regbase, CL_SEQRF, 0xb0);
1119 /* MCLK select */
1120 vga_wseq(regbase, CL_SEQR1F, 0x22);
1121 break;
1123 case BT_PICASSO:
1124 vga_wseq(regbase, CL_SEQR7, 0x27);
1125 /* Fast Page-Mode writes */
1126 vga_wseq(regbase, CL_SEQRF, 0xb0);
1127 /* MCLK select */
1128 vga_wseq(regbase, CL_SEQR1F, 0x22);
1129 break;
1131 case BT_PICASSO4:
1132 case BT_ALPINE:
1133 vga_wseq(regbase, CL_SEQR7, 0xa7);
1134 break;
1136 case BT_GD5480:
1137 vga_wseq(regbase, CL_SEQR7, 0x17);
1138 /* We already set SRF and SR1F */
1139 break;
1141 case BT_LAGUNA:
1142 case BT_LAGUNAB:
1143 vga_wseq(regbase, CL_SEQR7,
1144 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1145 control |= 0x2000;
1146 format |= 0x1400;
1147 threshold |= 0x10;
1148 break;
1150 default:
1151 dev_warn(info->device, "unknown Board\n");
1152 break;
1155 /* mode register: 256 color mode */
1156 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1157 #ifdef CONFIG_PCI
1158 WHDR(cinfo, 0xc1); /* Copy Xbh */
1159 #elif defined(CONFIG_ZORRO)
1160 /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
1161 WHDR(cinfo, 0xa0); /* hidden dac reg: nothing special */
1162 #endif
1165 /******************************************************
1167 * 24 bpp
1171 else if (var->bits_per_pixel == 24) {
1172 dev_dbg(info->device, "preparing for 24 bit deep display\n");
1173 switch (cinfo->btype) {
1174 case BT_SD64:
1175 /* Extended Sequencer Mode: 256c col. mode */
1176 vga_wseq(regbase, CL_SEQR7, 0xf5);
1177 /* MCLK select */
1178 vga_wseq(regbase, CL_SEQR1F, 0x1e);
1179 break;
1181 case BT_PICCOLO:
1182 case BT_SPECTRUM:
1183 vga_wseq(regbase, CL_SEQR7, 0x85);
1184 /* Fast Page-Mode writes */
1185 vga_wseq(regbase, CL_SEQRF, 0xb0);
1186 /* MCLK select */
1187 vga_wseq(regbase, CL_SEQR1F, 0x22);
1188 break;
1190 case BT_PICASSO:
1191 vga_wseq(regbase, CL_SEQR7, 0x25);
1192 /* Fast Page-Mode writes */
1193 vga_wseq(regbase, CL_SEQRF, 0xb0);
1194 /* MCLK select */
1195 vga_wseq(regbase, CL_SEQR1F, 0x22);
1196 break;
1198 case BT_PICASSO4:
1199 case BT_ALPINE:
1200 vga_wseq(regbase, CL_SEQR7, 0xa5);
1201 break;
1203 case BT_GD5480:
1204 vga_wseq(regbase, CL_SEQR7, 0x15);
1205 /* We already set SRF and SR1F */
1206 break;
1208 case BT_LAGUNA:
1209 case BT_LAGUNAB:
1210 vga_wseq(regbase, CL_SEQR7,
1211 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1212 control |= 0x4000;
1213 format |= 0x2400;
1214 threshold |= 0x20;
1215 break;
1217 default:
1218 dev_warn(info->device, "unknown Board\n");
1219 break;
1222 /* mode register: 256 color mode */
1223 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1224 /* hidden dac reg: 8-8-8 mode (24 or 32) */
1225 WHDR(cinfo, 0xc5);
1228 /******************************************************
1230 * unknown/unsupported bpp
1234 else
1235 dev_err(info->device,
1236 "What's this? requested color depth == %d.\n",
1237 var->bits_per_pixel);
1239 pitch = info->fix.line_length >> 3;
1240 vga_wcrt(regbase, VGA_CRTC_OFFSET, pitch & 0xff);
1241 tmp = 0x22;
1242 if (pitch & 0x100)
1243 tmp |= 0x10; /* offset overflow bit */
1245 /* screen start addr #16-18, fastpagemode cycles */
1246 vga_wcrt(regbase, CL_CRT1B, tmp);
1248 /* screen start address bit 19 */
1249 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19)
1250 vga_wcrt(regbase, CL_CRT1D, (pitch >> 9) & 1);
1252 if (is_laguna(cinfo)) {
1253 tmp = 0;
1254 if ((htotal + 5) & 256)
1255 tmp |= 128;
1256 if (hdispend & 256)
1257 tmp |= 64;
1258 if (hsyncstart & 256)
1259 tmp |= 48;
1260 if (vtotal & 1024)
1261 tmp |= 8;
1262 if (vdispend & 1024)
1263 tmp |= 4;
1264 if (vsyncstart & 1024)
1265 tmp |= 3;
1267 vga_wcrt(regbase, CL_CRT1E, tmp);
1268 dev_dbg(info->device, "CRT1e: %d\n", tmp);
1271 /* pixel panning */
1272 vga_wattr(regbase, CL_AR33, 0);
1274 /* [ EGS: SetOffset(); ] */
1275 /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
1276 AttrOn(cinfo);
1278 if (is_laguna(cinfo)) {
1279 /* no tiles */
1280 fb_writew(control | 0x1000, cinfo->laguna_mmio + 0x402);
1281 fb_writew(format, cinfo->laguna_mmio + 0xc0);
1282 fb_writew(threshold, cinfo->laguna_mmio + 0xea);
1284 /* finally, turn on everything - turn off "FullBandwidth" bit */
1285 /* also, set "DotClock%2" bit where requested */
1286 tmp = 0x01;
1288 /*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
1289 if (var->vmode & FB_VMODE_CLOCK_HALVE)
1290 tmp |= 0x08;
1293 vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp);
1294 dev_dbg(info->device, "CL_SEQR1: %d\n", tmp);
1296 #ifdef CIRRUSFB_DEBUG
1297 cirrusfb_dbg_reg_dump(info, NULL);
1298 #endif
1300 return 0;
1303 /* for some reason incomprehensible to me, cirrusfb requires that you write
1304 * the registers twice for the settings to take..grr. -dte */
1305 static int cirrusfb_set_par(struct fb_info *info)
1307 cirrusfb_set_par_foo(info);
1308 return cirrusfb_set_par_foo(info);
1311 static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1312 unsigned blue, unsigned transp,
1313 struct fb_info *info)
1315 struct cirrusfb_info *cinfo = info->par;
1317 if (regno > 255)
1318 return -EINVAL;
1320 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
1321 u32 v;
1322 red >>= (16 - info->var.red.length);
1323 green >>= (16 - info->var.green.length);
1324 blue >>= (16 - info->var.blue.length);
1326 if (regno >= 16)
1327 return 1;
1328 v = (red << info->var.red.offset) |
1329 (green << info->var.green.offset) |
1330 (blue << info->var.blue.offset);
1332 cinfo->pseudo_palette[regno] = v;
1333 return 0;
1336 if (info->var.bits_per_pixel == 8)
1337 WClut(cinfo, regno, red >> 10, green >> 10, blue >> 10);
1339 return 0;
1343 /*************************************************************************
1344 cirrusfb_pan_display()
1346 performs display panning - provided hardware permits this
1347 **************************************************************************/
1348 static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
1349 struct fb_info *info)
1351 int xoffset;
1352 unsigned long base;
1353 unsigned char tmp, xpix;
1354 struct cirrusfb_info *cinfo = info->par;
1356 dev_dbg(info->device,
1357 "virtual offset: (%d,%d)\n", var->xoffset, var->yoffset);
1359 /* no range checks for xoffset and yoffset, */
1360 /* as fb_pan_display has already done this */
1361 if (var->vmode & FB_VMODE_YWRAP)
1362 return -EINVAL;
1364 xoffset = var->xoffset * info->var.bits_per_pixel / 8;
1366 base = var->yoffset * info->fix.line_length + xoffset;
1368 if (info->var.bits_per_pixel == 1) {
1369 /* base is already correct */
1370 xpix = (unsigned char) (var->xoffset % 8);
1371 } else {
1372 base /= 4;
1373 xpix = (unsigned char) ((xoffset % 4) * 2);
1376 if (!is_laguna(cinfo))
1377 cirrusfb_WaitBLT(cinfo->regbase);
1379 /* lower 8 + 8 bits of screen start address */
1380 vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, base & 0xff);
1381 vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, (base >> 8) & 0xff);
1383 /* 0xf2 is %11110010, exclude tmp bits */
1384 tmp = vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2;
1385 /* construct bits 16, 17 and 18 of screen start address */
1386 if (base & 0x10000)
1387 tmp |= 0x01;
1388 if (base & 0x20000)
1389 tmp |= 0x04;
1390 if (base & 0x40000)
1391 tmp |= 0x08;
1393 vga_wcrt(cinfo->regbase, CL_CRT1B, tmp);
1395 /* construct bit 19 of screen start address */
1396 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) {
1397 tmp = vga_rcrt(cinfo->regbase, CL_CRT1D);
1398 if (is_laguna(cinfo))
1399 tmp = (tmp & ~0x18) | ((base >> 16) & 0x18);
1400 else
1401 tmp = (tmp & ~0x80) | ((base >> 12) & 0x80);
1402 vga_wcrt(cinfo->regbase, CL_CRT1D, tmp);
1405 /* write pixel panning value to AR33; this does not quite work in 8bpp
1407 * ### Piccolo..? Will this work?
1409 if (info->var.bits_per_pixel == 1)
1410 vga_wattr(cinfo->regbase, CL_AR33, xpix);
1412 return 0;
1415 static int cirrusfb_blank(int blank_mode, struct fb_info *info)
1418 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
1419 * then the caller blanks by setting the CLUT (Color Look Up Table)
1420 * to all black. Return 0 if blanking succeeded, != 0 if un-/blanking
1421 * failed due to e.g. a video mode which doesn't support it.
1422 * Implements VESA suspend and powerdown modes on hardware that
1423 * supports disabling hsync/vsync:
1424 * blank_mode == 2: suspend vsync
1425 * blank_mode == 3: suspend hsync
1426 * blank_mode == 4: powerdown
1428 unsigned char val;
1429 struct cirrusfb_info *cinfo = info->par;
1430 int current_mode = cinfo->blank_mode;
1432 dev_dbg(info->device, "ENTER, blank mode = %d\n", blank_mode);
1434 if (info->state != FBINFO_STATE_RUNNING ||
1435 current_mode == blank_mode) {
1436 dev_dbg(info->device, "EXIT, returning 0\n");
1437 return 0;
1440 /* Undo current */
1441 if (current_mode == FB_BLANK_NORMAL ||
1442 current_mode == FB_BLANK_UNBLANK)
1443 /* clear "FullBandwidth" bit */
1444 val = 0;
1445 else
1446 /* set "FullBandwidth" bit */
1447 val = 0x20;
1449 val |= vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE) & 0xdf;
1450 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val);
1452 switch (blank_mode) {
1453 case FB_BLANK_UNBLANK:
1454 case FB_BLANK_NORMAL:
1455 val = 0x00;
1456 break;
1457 case FB_BLANK_VSYNC_SUSPEND:
1458 val = 0x04;
1459 break;
1460 case FB_BLANK_HSYNC_SUSPEND:
1461 val = 0x02;
1462 break;
1463 case FB_BLANK_POWERDOWN:
1464 val = 0x06;
1465 break;
1466 default:
1467 dev_dbg(info->device, "EXIT, returning 1\n");
1468 return 1;
1471 vga_wgfx(cinfo->regbase, CL_GRE, val);
1473 cinfo->blank_mode = blank_mode;
1474 dev_dbg(info->device, "EXIT, returning 0\n");
1476 /* Let fbcon do a soft blank for us */
1477 return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
1480 /**** END Hardware specific Routines **************************************/
1481 /****************************************************************************/
1482 /**** BEGIN Internal Routines ***********************************************/
1484 static void init_vgachip(struct fb_info *info)
1486 struct cirrusfb_info *cinfo = info->par;
1487 const struct cirrusfb_board_info_rec *bi;
1489 assert(cinfo != NULL);
1491 bi = &cirrusfb_board_info[cinfo->btype];
1493 /* reset board globally */
1494 switch (cinfo->btype) {
1495 case BT_PICCOLO:
1496 WSFR(cinfo, 0x01);
1497 udelay(500);
1498 WSFR(cinfo, 0x51);
1499 udelay(500);
1500 break;
1501 case BT_PICASSO:
1502 WSFR2(cinfo, 0xff);
1503 udelay(500);
1504 break;
1505 case BT_SD64:
1506 case BT_SPECTRUM:
1507 WSFR(cinfo, 0x1f);
1508 udelay(500);
1509 WSFR(cinfo, 0x4f);
1510 udelay(500);
1511 break;
1512 case BT_PICASSO4:
1513 /* disable flickerfixer */
1514 vga_wcrt(cinfo->regbase, CL_CRT51, 0x00);
1515 mdelay(100);
1516 /* mode */
1517 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1518 case BT_GD5480: /* fall through */
1519 /* from Klaus' NetBSD driver: */
1520 vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
1521 case BT_ALPINE: /* fall through */
1522 /* put blitter into 542x compat */
1523 vga_wgfx(cinfo->regbase, CL_GR33, 0x00);
1524 break;
1526 case BT_LAGUNA:
1527 case BT_LAGUNAB:
1528 /* Nothing to do to reset the board. */
1529 break;
1531 default:
1532 dev_err(info->device, "Warning: Unknown board type\n");
1533 break;
1536 /* make sure RAM size set by this point */
1537 assert(info->screen_size > 0);
1539 /* the P4 is not fully initialized here; I rely on it having been */
1540 /* inited under AmigaOS already, which seems to work just fine */
1541 /* (Klaus advised to do it this way) */
1543 if (cinfo->btype != BT_PICASSO4) {
1544 WGen(cinfo, CL_VSSM, 0x10); /* EGS: 0x16 */
1545 WGen(cinfo, CL_POS102, 0x01);
1546 WGen(cinfo, CL_VSSM, 0x08); /* EGS: 0x0e */
1548 if (cinfo->btype != BT_SD64)
1549 WGen(cinfo, CL_VSSM2, 0x01);
1551 /* reset sequencer logic */
1552 vga_wseq(cinfo->regbase, VGA_SEQ_RESET, 0x03);
1554 /* FullBandwidth (video off) and 8/9 dot clock */
1555 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21);
1557 /* "magic cookie" - doesn't make any sense to me.. */
1558 /* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */
1559 /* unlock all extension registers */
1560 vga_wseq(cinfo->regbase, CL_SEQR6, 0x12);
1562 switch (cinfo->btype) {
1563 case BT_GD5480:
1564 vga_wseq(cinfo->regbase, CL_SEQRF, 0x98);
1565 break;
1566 case BT_ALPINE:
1567 case BT_LAGUNA:
1568 case BT_LAGUNAB:
1569 break;
1570 case BT_SD64:
1571 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8);
1572 break;
1573 default:
1574 vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f);
1575 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb0);
1576 break;
1579 /* plane mask: nothing */
1580 vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1581 /* character map select: doesn't even matter in gx mode */
1582 vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00);
1583 /* memory mode: chain4, ext. memory */
1584 vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1586 /* controller-internal base address of video memory */
1587 if (bi->init_sr07)
1588 vga_wseq(cinfo->regbase, CL_SEQR7, bi->sr07);
1590 /* vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */
1591 /* EEPROM control: shouldn't be necessary to write to this at all.. */
1593 /* graphics cursor X position (incomplete; position gives rem. 3 bits */
1594 vga_wseq(cinfo->regbase, CL_SEQR10, 0x00);
1595 /* graphics cursor Y position (..."... ) */
1596 vga_wseq(cinfo->regbase, CL_SEQR11, 0x00);
1597 /* graphics cursor attributes */
1598 vga_wseq(cinfo->regbase, CL_SEQR12, 0x00);
1599 /* graphics cursor pattern address */
1600 vga_wseq(cinfo->regbase, CL_SEQR13, 0x00);
1602 /* writing these on a P4 might give problems.. */
1603 if (cinfo->btype != BT_PICASSO4) {
1604 /* configuration readback and ext. color */
1605 vga_wseq(cinfo->regbase, CL_SEQR17, 0x00);
1606 /* signature generator */
1607 vga_wseq(cinfo->regbase, CL_SEQR18, 0x02);
1610 /* MCLK select etc. */
1611 if (bi->init_sr1f)
1612 vga_wseq(cinfo->regbase, CL_SEQR1F, bi->sr1f);
1614 /* Screen A preset row scan: none */
1615 vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00);
1616 /* Text cursor start: disable text cursor */
1617 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20);
1618 /* Text cursor end: - */
1619 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00);
1620 /* text cursor location high: 0 */
1621 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00);
1622 /* text cursor location low: 0 */
1623 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00);
1625 /* Underline Row scanline: - */
1626 vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00);
1627 /* ### add 0x40 for text modes with > 30 MHz pixclock */
1628 /* ext. display controls: ext.adr. wrap */
1629 vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02);
1631 /* Set/Reset registes: - */
1632 vga_wgfx(cinfo->regbase, VGA_GFX_SR_VALUE, 0x00);
1633 /* Set/Reset enable: - */
1634 vga_wgfx(cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00);
1635 /* Color Compare: - */
1636 vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00);
1637 /* Data Rotate: - */
1638 vga_wgfx(cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00);
1639 /* Read Map Select: - */
1640 vga_wgfx(cinfo->regbase, VGA_GFX_PLANE_READ, 0x00);
1641 /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
1642 vga_wgfx(cinfo->regbase, VGA_GFX_MODE, 0x00);
1643 /* Miscellaneous: memory map base address, graphics mode */
1644 vga_wgfx(cinfo->regbase, VGA_GFX_MISC, 0x01);
1645 /* Color Don't care: involve all planes */
1646 vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f);
1647 /* Bit Mask: no mask at all */
1648 vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff);
1650 if (cinfo->btype == BT_ALPINE || is_laguna(cinfo))
1651 /* (5434 can't have bit 3 set for bitblt) */
1652 vga_wgfx(cinfo->regbase, CL_GRB, 0x20);
1653 else
1654 /* Graphics controller mode extensions: finer granularity,
1655 * 8byte data latches
1657 vga_wgfx(cinfo->regbase, CL_GRB, 0x28);
1659 vga_wgfx(cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */
1660 vga_wgfx(cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */
1661 vga_wgfx(cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */
1662 /* Background color byte 1: - */
1663 /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); */
1664 /* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
1666 /* Attribute Controller palette registers: "identity mapping" */
1667 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE0, 0x00);
1668 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
1669 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
1670 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
1671 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
1672 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
1673 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
1674 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
1675 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
1676 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
1677 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
1678 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
1679 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
1680 vga_wattr(cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
1681 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
1682 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
1684 /* Attribute Controller mode: graphics mode */
1685 vga_wattr(cinfo->regbase, VGA_ATC_MODE, 0x01);
1686 /* Overscan color reg.: reg. 0 */
1687 vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00);
1688 /* Color Plane enable: Enable all 4 planes */
1689 vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f);
1690 /* Color Select: - */
1691 vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00);
1693 WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
1695 /* BLT Start/status: Blitter reset */
1696 vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
1697 /* - " - : "end-of-reset" */
1698 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1700 /* misc... */
1701 WHDR(cinfo, 0); /* Hidden DAC register: - */
1702 return;
1705 static void switch_monitor(struct cirrusfb_info *cinfo, int on)
1707 #ifdef CONFIG_ZORRO /* only works on Zorro boards */
1708 static int IsOn = 0; /* XXX not ok for multiple boards */
1710 if (cinfo->btype == BT_PICASSO4)
1711 return; /* nothing to switch */
1712 if (cinfo->btype == BT_ALPINE)
1713 return; /* nothing to switch */
1714 if (cinfo->btype == BT_GD5480)
1715 return; /* nothing to switch */
1716 if (cinfo->btype == BT_PICASSO) {
1717 if ((on && !IsOn) || (!on && IsOn))
1718 WSFR(cinfo, 0xff);
1719 return;
1721 if (on) {
1722 switch (cinfo->btype) {
1723 case BT_SD64:
1724 WSFR(cinfo, cinfo->SFR | 0x21);
1725 break;
1726 case BT_PICCOLO:
1727 WSFR(cinfo, cinfo->SFR | 0x28);
1728 break;
1729 case BT_SPECTRUM:
1730 WSFR(cinfo, 0x6f);
1731 break;
1732 default: /* do nothing */ break;
1734 } else {
1735 switch (cinfo->btype) {
1736 case BT_SD64:
1737 WSFR(cinfo, cinfo->SFR & 0xde);
1738 break;
1739 case BT_PICCOLO:
1740 WSFR(cinfo, cinfo->SFR & 0xd7);
1741 break;
1742 case BT_SPECTRUM:
1743 WSFR(cinfo, 0x4f);
1744 break;
1745 default: /* do nothing */
1746 break;
1749 #endif /* CONFIG_ZORRO */
1752 /******************************************/
1753 /* Linux 2.6-style accelerated functions */
1754 /******************************************/
1756 static int cirrusfb_sync(struct fb_info *info)
1758 struct cirrusfb_info *cinfo = info->par;
1760 if (!is_laguna(cinfo)) {
1761 while (vga_rgfx(cinfo->regbase, CL_GR31) & 0x03)
1762 cpu_relax();
1764 return 0;
1767 static void cirrusfb_fillrect(struct fb_info *info,
1768 const struct fb_fillrect *region)
1770 struct fb_fillrect modded;
1771 int vxres, vyres;
1772 struct cirrusfb_info *cinfo = info->par;
1773 int m = info->var.bits_per_pixel;
1774 u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
1775 cinfo->pseudo_palette[region->color] : region->color;
1777 if (info->state != FBINFO_STATE_RUNNING)
1778 return;
1779 if (info->flags & FBINFO_HWACCEL_DISABLED) {
1780 cfb_fillrect(info, region);
1781 return;
1784 vxres = info->var.xres_virtual;
1785 vyres = info->var.yres_virtual;
1787 memcpy(&modded, region, sizeof(struct fb_fillrect));
1789 if (!modded.width || !modded.height ||
1790 modded.dx >= vxres || modded.dy >= vyres)
1791 return;
1793 if (modded.dx + modded.width > vxres)
1794 modded.width = vxres - modded.dx;
1795 if (modded.dy + modded.height > vyres)
1796 modded.height = vyres - modded.dy;
1798 cirrusfb_RectFill(cinfo->regbase,
1799 info->var.bits_per_pixel,
1800 (region->dx * m) / 8, region->dy,
1801 (region->width * m) / 8, region->height,
1802 color, color,
1803 info->fix.line_length, 0x40);
1806 static void cirrusfb_copyarea(struct fb_info *info,
1807 const struct fb_copyarea *area)
1809 struct fb_copyarea modded;
1810 u32 vxres, vyres;
1811 struct cirrusfb_info *cinfo = info->par;
1812 int m = info->var.bits_per_pixel;
1814 if (info->state != FBINFO_STATE_RUNNING)
1815 return;
1816 if (info->flags & FBINFO_HWACCEL_DISABLED) {
1817 cfb_copyarea(info, area);
1818 return;
1821 vxres = info->var.xres_virtual;
1822 vyres = info->var.yres_virtual;
1823 memcpy(&modded, area, sizeof(struct fb_copyarea));
1825 if (!modded.width || !modded.height ||
1826 modded.sx >= vxres || modded.sy >= vyres ||
1827 modded.dx >= vxres || modded.dy >= vyres)
1828 return;
1830 if (modded.sx + modded.width > vxres)
1831 modded.width = vxres - modded.sx;
1832 if (modded.dx + modded.width > vxres)
1833 modded.width = vxres - modded.dx;
1834 if (modded.sy + modded.height > vyres)
1835 modded.height = vyres - modded.sy;
1836 if (modded.dy + modded.height > vyres)
1837 modded.height = vyres - modded.dy;
1839 cirrusfb_BitBLT(cinfo->regbase, info->var.bits_per_pixel,
1840 (area->sx * m) / 8, area->sy,
1841 (area->dx * m) / 8, area->dy,
1842 (area->width * m) / 8, area->height,
1843 info->fix.line_length);
1847 static void cirrusfb_imageblit(struct fb_info *info,
1848 const struct fb_image *image)
1850 struct cirrusfb_info *cinfo = info->par;
1851 unsigned char op = (info->var.bits_per_pixel == 24) ? 0xc : 0x4;
1853 if (info->state != FBINFO_STATE_RUNNING)
1854 return;
1855 /* Alpine acceleration does not work at 24bpp ?!? */
1856 if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1 ||
1857 (cinfo->btype == BT_ALPINE && op == 0xc))
1858 cfb_imageblit(info, image);
1859 else {
1860 unsigned size = ((image->width + 7) >> 3) * image->height;
1861 int m = info->var.bits_per_pixel;
1862 u32 fg, bg;
1864 if (info->var.bits_per_pixel == 8) {
1865 fg = image->fg_color;
1866 bg = image->bg_color;
1867 } else {
1868 fg = ((u32 *)(info->pseudo_palette))[image->fg_color];
1869 bg = ((u32 *)(info->pseudo_palette))[image->bg_color];
1871 if (info->var.bits_per_pixel == 24) {
1872 /* clear background first */
1873 cirrusfb_RectFill(cinfo->regbase,
1874 info->var.bits_per_pixel,
1875 (image->dx * m) / 8, image->dy,
1876 (image->width * m) / 8,
1877 image->height,
1878 bg, bg,
1879 info->fix.line_length, 0x40);
1881 cirrusfb_RectFill(cinfo->regbase,
1882 info->var.bits_per_pixel,
1883 (image->dx * m) / 8, image->dy,
1884 (image->width * m) / 8, image->height,
1885 fg, bg,
1886 info->fix.line_length, op);
1887 memcpy(info->screen_base, image->data, size);
1891 #ifdef CONFIG_PPC_PREP
1892 #define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
1893 #define PREP_IO_BASE ((volatile unsigned char *) 0x80000000)
1894 static void get_prep_addrs(unsigned long *display, unsigned long *registers)
1896 *display = PREP_VIDEO_BASE;
1897 *registers = (unsigned long) PREP_IO_BASE;
1900 #endif /* CONFIG_PPC_PREP */
1902 #ifdef CONFIG_PCI
1903 static int release_io_ports;
1905 /* Pulled the logic from XFree86 Cirrus driver to get the memory size,
1906 * based on the DRAM bandwidth bit and DRAM bank switching bit. This
1907 * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
1908 * seem to have. */
1909 static unsigned int __devinit cirrusfb_get_memsize(struct fb_info *info,
1910 u8 __iomem *regbase)
1912 unsigned long mem;
1913 struct cirrusfb_info *cinfo = info->par;
1915 if (is_laguna(cinfo)) {
1916 unsigned char SR14 = vga_rseq(regbase, CL_SEQR14);
1918 mem = ((SR14 & 7) + 1) << 20;
1919 } else {
1920 unsigned char SRF = vga_rseq(regbase, CL_SEQRF);
1921 switch ((SRF & 0x18)) {
1922 case 0x08:
1923 mem = 512 * 1024;
1924 break;
1925 case 0x10:
1926 mem = 1024 * 1024;
1927 break;
1928 /* 64-bit DRAM data bus width; assume 2MB.
1929 * Also indicates 2MB memory on the 5430.
1931 case 0x18:
1932 mem = 2048 * 1024;
1933 break;
1934 default:
1935 dev_warn(info->device, "Unknown memory size!\n");
1936 mem = 1024 * 1024;
1938 /* If DRAM bank switching is enabled, there must be
1939 * twice as much memory installed. (4MB on the 5434)
1941 if (SRF & 0x80)
1942 mem *= 2;
1945 /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
1946 return mem;
1949 static void get_pci_addrs(const struct pci_dev *pdev,
1950 unsigned long *display, unsigned long *registers)
1952 assert(pdev != NULL);
1953 assert(display != NULL);
1954 assert(registers != NULL);
1956 *display = 0;
1957 *registers = 0;
1959 /* This is a best-guess for now */
1961 if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
1962 *display = pci_resource_start(pdev, 1);
1963 *registers = pci_resource_start(pdev, 0);
1964 } else {
1965 *display = pci_resource_start(pdev, 0);
1966 *registers = pci_resource_start(pdev, 1);
1969 assert(*display != 0);
1972 static void cirrusfb_pci_unmap(struct fb_info *info)
1974 struct pci_dev *pdev = to_pci_dev(info->device);
1975 struct cirrusfb_info *cinfo = info->par;
1977 if (cinfo->laguna_mmio == NULL)
1978 iounmap(cinfo->laguna_mmio);
1979 iounmap(info->screen_base);
1980 #if 0 /* if system didn't claim this region, we would... */
1981 release_mem_region(0xA0000, 65535);
1982 #endif
1983 if (release_io_ports)
1984 release_region(0x3C0, 32);
1985 pci_release_regions(pdev);
1987 #endif /* CONFIG_PCI */
1989 #ifdef CONFIG_ZORRO
1990 static void cirrusfb_zorro_unmap(struct fb_info *info)
1992 struct cirrusfb_info *cinfo = info->par;
1993 struct zorro_dev *zdev = to_zorro_dev(info->device);
1995 zorro_release_device(zdev);
1997 if (cinfo->btype == BT_PICASSO4) {
1998 cinfo->regbase -= 0x600000;
1999 iounmap((void *)cinfo->regbase);
2000 iounmap(info->screen_base);
2001 } else {
2002 if (zorro_resource_start(zdev) > 0x01000000)
2003 iounmap(info->screen_base);
2006 #endif /* CONFIG_ZORRO */
2008 /* function table of the above functions */
2009 static struct fb_ops cirrusfb_ops = {
2010 .owner = THIS_MODULE,
2011 .fb_open = cirrusfb_open,
2012 .fb_release = cirrusfb_release,
2013 .fb_setcolreg = cirrusfb_setcolreg,
2014 .fb_check_var = cirrusfb_check_var,
2015 .fb_set_par = cirrusfb_set_par,
2016 .fb_pan_display = cirrusfb_pan_display,
2017 .fb_blank = cirrusfb_blank,
2018 .fb_fillrect = cirrusfb_fillrect,
2019 .fb_copyarea = cirrusfb_copyarea,
2020 .fb_sync = cirrusfb_sync,
2021 .fb_imageblit = cirrusfb_imageblit,
2024 static int __devinit cirrusfb_set_fbinfo(struct fb_info *info)
2026 struct cirrusfb_info *cinfo = info->par;
2027 struct fb_var_screeninfo *var = &info->var;
2029 info->pseudo_palette = cinfo->pseudo_palette;
2030 info->flags = FBINFO_DEFAULT
2031 | FBINFO_HWACCEL_XPAN
2032 | FBINFO_HWACCEL_YPAN
2033 | FBINFO_HWACCEL_FILLRECT
2034 | FBINFO_HWACCEL_IMAGEBLIT
2035 | FBINFO_HWACCEL_COPYAREA;
2036 if (noaccel || is_laguna(cinfo)) {
2037 info->flags |= FBINFO_HWACCEL_DISABLED;
2038 info->fix.accel = FB_ACCEL_NONE;
2039 } else
2040 info->fix.accel = FB_ACCEL_CIRRUS_ALPINE;
2042 info->fbops = &cirrusfb_ops;
2044 if (cinfo->btype == BT_GD5480) {
2045 if (var->bits_per_pixel == 16)
2046 info->screen_base += 1 * MB_;
2047 if (var->bits_per_pixel == 32)
2048 info->screen_base += 2 * MB_;
2051 /* Fill fix common fields */
2052 strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
2053 sizeof(info->fix.id));
2055 /* monochrome: only 1 memory plane */
2056 /* 8 bit and above: Use whole memory area */
2057 info->fix.smem_len = info->screen_size;
2058 if (var->bits_per_pixel == 1)
2059 info->fix.smem_len /= 4;
2060 info->fix.type_aux = 0;
2061 info->fix.xpanstep = 1;
2062 info->fix.ypanstep = 1;
2063 info->fix.ywrapstep = 0;
2065 /* FIXME: map region at 0xB8000 if available, fill in here */
2066 info->fix.mmio_len = 0;
2068 fb_alloc_cmap(&info->cmap, 256, 0);
2070 return 0;
2073 static int __devinit cirrusfb_register(struct fb_info *info)
2075 struct cirrusfb_info *cinfo = info->par;
2076 int err;
2078 /* sanity checks */
2079 assert(cinfo->btype != BT_NONE);
2081 /* set all the vital stuff */
2082 cirrusfb_set_fbinfo(info);
2084 dev_dbg(info->device, "(RAM start set to: 0x%p)\n", info->screen_base);
2086 err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
2087 if (!err) {
2088 dev_dbg(info->device, "wrong initial video mode\n");
2089 err = -EINVAL;
2090 goto err_dealloc_cmap;
2093 info->var.activate = FB_ACTIVATE_NOW;
2095 err = cirrusfb_check_var(&info->var, info);
2096 if (err < 0) {
2097 /* should never happen */
2098 dev_dbg(info->device,
2099 "choking on default var... umm, no good.\n");
2100 goto err_dealloc_cmap;
2103 err = register_framebuffer(info);
2104 if (err < 0) {
2105 dev_err(info->device,
2106 "could not register fb device; err = %d!\n", err);
2107 goto err_dealloc_cmap;
2110 return 0;
2112 err_dealloc_cmap:
2113 fb_dealloc_cmap(&info->cmap);
2114 return err;
2117 static void __devexit cirrusfb_cleanup(struct fb_info *info)
2119 struct cirrusfb_info *cinfo = info->par;
2121 switch_monitor(cinfo, 0);
2122 unregister_framebuffer(info);
2123 fb_dealloc_cmap(&info->cmap);
2124 dev_dbg(info->device, "Framebuffer unregistered\n");
2125 cinfo->unmap(info);
2126 framebuffer_release(info);
2129 #ifdef CONFIG_PCI
2130 static int __devinit cirrusfb_pci_register(struct pci_dev *pdev,
2131 const struct pci_device_id *ent)
2133 struct cirrusfb_info *cinfo;
2134 struct fb_info *info;
2135 unsigned long board_addr, board_size;
2136 int ret;
2138 ret = pci_enable_device(pdev);
2139 if (ret < 0) {
2140 printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
2141 goto err_out;
2144 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev);
2145 if (!info) {
2146 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2147 ret = -ENOMEM;
2148 goto err_out;
2151 cinfo = info->par;
2152 cinfo->btype = (enum cirrus_board) ent->driver_data;
2154 dev_dbg(info->device,
2155 " Found PCI device, base address 0 is 0x%Lx, btype set to %d\n",
2156 (unsigned long long)pdev->resource[0].start, cinfo->btype);
2157 dev_dbg(info->device, " base address 1 is 0x%Lx\n",
2158 (unsigned long long)pdev->resource[1].start);
2160 if (isPReP) {
2161 pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, 0x00000000);
2162 #ifdef CONFIG_PPC_PREP
2163 get_prep_addrs(&board_addr, &info->fix.mmio_start);
2164 #endif
2165 /* PReP dies if we ioremap the IO registers, but it works w/out... */
2166 cinfo->regbase = (char __iomem *) info->fix.mmio_start;
2167 } else {
2168 dev_dbg(info->device,
2169 "Attempt to get PCI info for Cirrus Graphics Card\n");
2170 get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start);
2171 /* FIXME: this forces VGA. alternatives? */
2172 cinfo->regbase = NULL;
2173 cinfo->laguna_mmio = ioremap(info->fix.mmio_start, 0x1000);
2176 dev_dbg(info->device, "Board address: 0x%lx, register address: 0x%lx\n",
2177 board_addr, info->fix.mmio_start);
2179 board_size = (cinfo->btype == BT_GD5480) ?
2180 32 * MB_ : cirrusfb_get_memsize(info, cinfo->regbase);
2182 ret = pci_request_regions(pdev, "cirrusfb");
2183 if (ret < 0) {
2184 dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
2185 board_addr);
2186 goto err_release_fb;
2188 #if 0 /* if the system didn't claim this region, we would... */
2189 if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
2190 dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
2191 0xA0000L);
2192 ret = -EBUSY;
2193 goto err_release_regions;
2195 #endif
2196 if (request_region(0x3C0, 32, "cirrusfb"))
2197 release_io_ports = 1;
2199 info->screen_base = ioremap(board_addr, board_size);
2200 if (!info->screen_base) {
2201 ret = -EIO;
2202 goto err_release_legacy;
2205 info->fix.smem_start = board_addr;
2206 info->screen_size = board_size;
2207 cinfo->unmap = cirrusfb_pci_unmap;
2209 dev_info(info->device,
2210 "Cirrus Logic chipset on PCI bus, RAM (%lu kB) at 0x%lx\n",
2211 info->screen_size >> 10, board_addr);
2212 pci_set_drvdata(pdev, info);
2214 ret = cirrusfb_register(info);
2215 if (!ret)
2216 return 0;
2218 pci_set_drvdata(pdev, NULL);
2219 iounmap(info->screen_base);
2220 err_release_legacy:
2221 if (release_io_ports)
2222 release_region(0x3C0, 32);
2223 #if 0
2224 release_mem_region(0xA0000, 65535);
2225 err_release_regions:
2226 #endif
2227 pci_release_regions(pdev);
2228 err_release_fb:
2229 if (cinfo->laguna_mmio != NULL)
2230 iounmap(cinfo->laguna_mmio);
2231 framebuffer_release(info);
2232 err_out:
2233 return ret;
2236 static void __devexit cirrusfb_pci_unregister(struct pci_dev *pdev)
2238 struct fb_info *info = pci_get_drvdata(pdev);
2240 cirrusfb_cleanup(info);
2243 static struct pci_driver cirrusfb_pci_driver = {
2244 .name = "cirrusfb",
2245 .id_table = cirrusfb_pci_table,
2246 .probe = cirrusfb_pci_register,
2247 .remove = __devexit_p(cirrusfb_pci_unregister),
2248 #ifdef CONFIG_PM
2249 #if 0
2250 .suspend = cirrusfb_pci_suspend,
2251 .resume = cirrusfb_pci_resume,
2252 #endif
2253 #endif
2255 #endif /* CONFIG_PCI */
2257 #ifdef CONFIG_ZORRO
2258 static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
2259 const struct zorro_device_id *ent)
2261 struct cirrusfb_info *cinfo;
2262 struct fb_info *info;
2263 enum cirrus_board btype;
2264 struct zorro_dev *z2 = NULL;
2265 unsigned long board_addr, board_size, size;
2266 int ret;
2268 btype = ent->driver_data;
2269 if (cirrusfb_zorro_table2[btype].id2)
2270 z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
2271 size = cirrusfb_zorro_table2[btype].size;
2273 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
2274 if (!info) {
2275 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2276 ret = -ENOMEM;
2277 goto err_out;
2280 dev_info(info->device, "%s board detected\n",
2281 cirrusfb_board_info[btype].name);
2283 cinfo = info->par;
2284 cinfo->btype = btype;
2286 assert(z);
2287 assert(btype != BT_NONE);
2289 board_addr = zorro_resource_start(z);
2290 board_size = zorro_resource_len(z);
2291 info->screen_size = size;
2293 if (!zorro_request_device(z, "cirrusfb")) {
2294 dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
2295 board_addr);
2296 ret = -EBUSY;
2297 goto err_release_fb;
2300 ret = -EIO;
2302 if (btype == BT_PICASSO4) {
2303 dev_info(info->device, " REG at $%lx\n", board_addr + 0x600000);
2305 /* To be precise, for the P4 this is not the */
2306 /* begin of the board, but the begin of RAM. */
2307 /* for P4, map in its address space in 2 chunks (### TEST! ) */
2308 /* (note the ugly hardcoded 16M number) */
2309 cinfo->regbase = ioremap(board_addr, 16777216);
2310 if (!cinfo->regbase)
2311 goto err_release_region;
2313 dev_dbg(info->device, "Virtual address for board set to: $%p\n",
2314 cinfo->regbase);
2315 cinfo->regbase += 0x600000;
2316 info->fix.mmio_start = board_addr + 0x600000;
2318 info->fix.smem_start = board_addr + 16777216;
2319 info->screen_base = ioremap(info->fix.smem_start, 16777216);
2320 if (!info->screen_base)
2321 goto err_unmap_regbase;
2322 } else {
2323 dev_info(info->device, " REG at $%lx\n",
2324 (unsigned long) z2->resource.start);
2326 info->fix.smem_start = board_addr;
2327 if (board_addr > 0x01000000)
2328 info->screen_base = ioremap(board_addr, board_size);
2329 else
2330 info->screen_base = (caddr_t) ZTWO_VADDR(board_addr);
2331 if (!info->screen_base)
2332 goto err_release_region;
2334 /* set address for REG area of board */
2335 cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start);
2336 info->fix.mmio_start = z2->resource.start;
2338 dev_dbg(info->device, "Virtual address for board set to: $%p\n",
2339 cinfo->regbase);
2341 cinfo->unmap = cirrusfb_zorro_unmap;
2343 dev_info(info->device,
2344 "Cirrus Logic chipset on Zorro bus, RAM (%lu MB) at $%lx\n",
2345 board_size / MB_, board_addr);
2347 zorro_set_drvdata(z, info);
2349 ret = cirrusfb_register(info);
2350 if (!ret)
2351 return 0;
2353 if (btype == BT_PICASSO4 || board_addr > 0x01000000)
2354 iounmap(info->screen_base);
2356 err_unmap_regbase:
2357 if (btype == BT_PICASSO4)
2358 iounmap(cinfo->regbase - 0x600000);
2359 err_release_region:
2360 release_region(board_addr, board_size);
2361 err_release_fb:
2362 framebuffer_release(info);
2363 err_out:
2364 return ret;
2367 void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
2369 struct fb_info *info = zorro_get_drvdata(z);
2371 cirrusfb_cleanup(info);
2374 static struct zorro_driver cirrusfb_zorro_driver = {
2375 .name = "cirrusfb",
2376 .id_table = cirrusfb_zorro_table,
2377 .probe = cirrusfb_zorro_register,
2378 .remove = __devexit_p(cirrusfb_zorro_unregister),
2380 #endif /* CONFIG_ZORRO */
2382 #ifndef MODULE
2383 static int __init cirrusfb_setup(char *options)
2385 char *this_opt;
2387 if (!options || !*options)
2388 return 0;
2390 while ((this_opt = strsep(&options, ",")) != NULL) {
2391 if (!*this_opt)
2392 continue;
2394 if (!strcmp(this_opt, "noaccel"))
2395 noaccel = 1;
2396 else if (!strncmp(this_opt, "mode:", 5))
2397 mode_option = this_opt + 5;
2398 else
2399 mode_option = this_opt;
2401 return 0;
2403 #endif
2406 * Modularization
2409 MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
2410 MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
2411 MODULE_LICENSE("GPL");
2413 static int __init cirrusfb_init(void)
2415 int error = 0;
2417 #ifndef MODULE
2418 char *option = NULL;
2420 if (fb_get_options("cirrusfb", &option))
2421 return -ENODEV;
2422 cirrusfb_setup(option);
2423 #endif
2425 #ifdef CONFIG_ZORRO
2426 error |= zorro_register_driver(&cirrusfb_zorro_driver);
2427 #endif
2428 #ifdef CONFIG_PCI
2429 error |= pci_register_driver(&cirrusfb_pci_driver);
2430 #endif
2431 return error;
2434 static void __exit cirrusfb_exit(void)
2436 #ifdef CONFIG_PCI
2437 pci_unregister_driver(&cirrusfb_pci_driver);
2438 #endif
2439 #ifdef CONFIG_ZORRO
2440 zorro_unregister_driver(&cirrusfb_zorro_driver);
2441 #endif
2444 module_init(cirrusfb_init);
2446 module_param(mode_option, charp, 0);
2447 MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
2448 module_param(noaccel, bool, 0);
2449 MODULE_PARM_DESC(noaccel, "Disable acceleration");
2451 #ifdef MODULE
2452 module_exit(cirrusfb_exit);
2453 #endif
2455 /**********************************************************************/
2456 /* about the following functions - I have used the same names for the */
2457 /* functions as Markus Wild did in his Retina driver for NetBSD as */
2458 /* they just made sense for this purpose. Apart from that, I wrote */
2459 /* these functions myself. */
2460 /**********************************************************************/
2462 /*** WGen() - write into one of the external/general registers ***/
2463 static void WGen(const struct cirrusfb_info *cinfo,
2464 int regnum, unsigned char val)
2466 unsigned long regofs = 0;
2468 if (cinfo->btype == BT_PICASSO) {
2469 /* Picasso II specific hack */
2470 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2471 regnum == CL_VSSM2) */
2472 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2473 regofs = 0xfff;
2476 vga_w(cinfo->regbase, regofs + regnum, val);
2479 /*** RGen() - read out one of the external/general registers ***/
2480 static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum)
2482 unsigned long regofs = 0;
2484 if (cinfo->btype == BT_PICASSO) {
2485 /* Picasso II specific hack */
2486 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2487 regnum == CL_VSSM2) */
2488 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2489 regofs = 0xfff;
2492 return vga_r(cinfo->regbase, regofs + regnum);
2495 /*** AttrOn() - turn on VideoEnable for Attribute controller ***/
2496 static void AttrOn(const struct cirrusfb_info *cinfo)
2498 assert(cinfo != NULL);
2500 if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) {
2501 /* if we're just in "write value" mode, write back the */
2502 /* same value as before to not modify anything */
2503 vga_w(cinfo->regbase, VGA_ATT_IW,
2504 vga_r(cinfo->regbase, VGA_ATT_R));
2506 /* turn on video bit */
2507 /* vga_w(cinfo->regbase, VGA_ATT_IW, 0x20); */
2508 vga_w(cinfo->regbase, VGA_ATT_IW, 0x33);
2510 /* dummy write on Reg0 to be on "write index" mode next time */
2511 vga_w(cinfo->regbase, VGA_ATT_IW, 0x00);
2514 /*** WHDR() - write into the Hidden DAC register ***/
2515 /* as the HDR is the only extension register that requires special treatment
2516 * (the other extension registers are accessible just like the "ordinary"
2517 * registers of their functional group) here is a specialized routine for
2518 * accessing the HDR
2520 static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val)
2522 unsigned char dummy;
2524 if (is_laguna(cinfo))
2525 return;
2526 if (cinfo->btype == BT_PICASSO) {
2527 /* Klaus' hint for correct access to HDR on some boards */
2528 /* first write 0 to pixel mask (3c6) */
2529 WGen(cinfo, VGA_PEL_MSK, 0x00);
2530 udelay(200);
2531 /* next read dummy from pixel address (3c8) */
2532 dummy = RGen(cinfo, VGA_PEL_IW);
2533 udelay(200);
2535 /* now do the usual stuff to access the HDR */
2537 dummy = RGen(cinfo, VGA_PEL_MSK);
2538 udelay(200);
2539 dummy = RGen(cinfo, VGA_PEL_MSK);
2540 udelay(200);
2541 dummy = RGen(cinfo, VGA_PEL_MSK);
2542 udelay(200);
2543 dummy = RGen(cinfo, VGA_PEL_MSK);
2544 udelay(200);
2546 WGen(cinfo, VGA_PEL_MSK, val);
2547 udelay(200);
2549 if (cinfo->btype == BT_PICASSO) {
2550 /* now first reset HDR access counter */
2551 dummy = RGen(cinfo, VGA_PEL_IW);
2552 udelay(200);
2554 /* and at the end, restore the mask value */
2555 /* ## is this mask always 0xff? */
2556 WGen(cinfo, VGA_PEL_MSK, 0xff);
2557 udelay(200);
2561 /*** WSFR() - write to the "special function register" (SFR) ***/
2562 static void WSFR(struct cirrusfb_info *cinfo, unsigned char val)
2564 #ifdef CONFIG_ZORRO
2565 assert(cinfo->regbase != NULL);
2566 cinfo->SFR = val;
2567 z_writeb(val, cinfo->regbase + 0x8000);
2568 #endif
2571 /* The Picasso has a second register for switching the monitor bit */
2572 static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val)
2574 #ifdef CONFIG_ZORRO
2575 /* writing an arbitrary value to this one causes the monitor switcher */
2576 /* to flip to Amiga display */
2577 assert(cinfo->regbase != NULL);
2578 cinfo->SFR = val;
2579 z_writeb(val, cinfo->regbase + 0x9000);
2580 #endif
2583 /*** WClut - set CLUT entry (range: 0..63) ***/
2584 static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
2585 unsigned char green, unsigned char blue)
2587 unsigned int data = VGA_PEL_D;
2589 /* address write mode register is not translated.. */
2590 vga_w(cinfo->regbase, VGA_PEL_IW, regnum);
2592 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2593 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480 ||
2594 is_laguna(cinfo)) {
2595 /* but DAC data register IS, at least for Picasso II */
2596 if (cinfo->btype == BT_PICASSO)
2597 data += 0xfff;
2598 vga_w(cinfo->regbase, data, red);
2599 vga_w(cinfo->regbase, data, green);
2600 vga_w(cinfo->regbase, data, blue);
2601 } else {
2602 vga_w(cinfo->regbase, data, blue);
2603 vga_w(cinfo->regbase, data, green);
2604 vga_w(cinfo->regbase, data, red);
2608 #if 0
2609 /*** RClut - read CLUT entry (range 0..63) ***/
2610 static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
2611 unsigned char *green, unsigned char *blue)
2613 unsigned int data = VGA_PEL_D;
2615 vga_w(cinfo->regbase, VGA_PEL_IR, regnum);
2617 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2618 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2619 if (cinfo->btype == BT_PICASSO)
2620 data += 0xfff;
2621 *red = vga_r(cinfo->regbase, data);
2622 *green = vga_r(cinfo->regbase, data);
2623 *blue = vga_r(cinfo->regbase, data);
2624 } else {
2625 *blue = vga_r(cinfo->regbase, data);
2626 *green = vga_r(cinfo->regbase, data);
2627 *red = vga_r(cinfo->regbase, data);
2630 #endif
2632 /*******************************************************************
2633 cirrusfb_WaitBLT()
2635 Wait for the BitBLT engine to complete a possible earlier job
2636 *********************************************************************/
2638 /* FIXME: use interrupts instead */
2639 static void cirrusfb_WaitBLT(u8 __iomem *regbase)
2641 while (vga_rgfx(regbase, CL_GR31) & 0x08)
2642 cpu_relax();
2645 /*******************************************************************
2646 cirrusfb_BitBLT()
2648 perform accelerated "scrolling"
2649 ********************************************************************/
2651 static void cirrusfb_set_blitter(u8 __iomem *regbase,
2652 u_short nwidth, u_short nheight,
2653 u_long nsrc, u_long ndest,
2654 u_short bltmode, u_short line_length)
2657 /* pitch: set to line_length */
2658 /* dest pitch low */
2659 vga_wgfx(regbase, CL_GR24, line_length & 0xff);
2660 /* dest pitch hi */
2661 vga_wgfx(regbase, CL_GR25, line_length >> 8);
2662 /* source pitch low */
2663 vga_wgfx(regbase, CL_GR26, line_length & 0xff);
2664 /* source pitch hi */
2665 vga_wgfx(regbase, CL_GR27, line_length >> 8);
2667 /* BLT width: actual number of pixels - 1 */
2668 /* BLT width low */
2669 vga_wgfx(regbase, CL_GR20, nwidth & 0xff);
2670 /* BLT width hi */
2671 vga_wgfx(regbase, CL_GR21, nwidth >> 8);
2673 /* BLT height: actual number of lines -1 */
2674 /* BLT height low */
2675 vga_wgfx(regbase, CL_GR22, nheight & 0xff);
2676 /* BLT width hi */
2677 vga_wgfx(regbase, CL_GR23, nheight >> 8);
2679 /* BLT destination */
2680 /* BLT dest low */
2681 vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
2682 /* BLT dest mid */
2683 vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
2684 /* BLT dest hi */
2685 vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
2687 /* BLT source */
2688 /* BLT src low */
2689 vga_wgfx(regbase, CL_GR2C, (u_char) (nsrc & 0xff));
2690 /* BLT src mid */
2691 vga_wgfx(regbase, CL_GR2D, (u_char) (nsrc >> 8));
2692 /* BLT src hi */
2693 vga_wgfx(regbase, CL_GR2E, (u_char) (nsrc >> 16));
2695 /* BLT mode */
2696 vga_wgfx(regbase, CL_GR30, bltmode); /* BLT mode */
2698 /* BLT ROP: SrcCopy */
2699 vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */
2701 /* and finally: GO! */
2702 vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */
2705 /*******************************************************************
2706 cirrusfb_BitBLT()
2708 perform accelerated "scrolling"
2709 ********************************************************************/
2711 static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
2712 u_short curx, u_short cury,
2713 u_short destx, u_short desty,
2714 u_short width, u_short height,
2715 u_short line_length)
2717 u_short nwidth = width - 1;
2718 u_short nheight = height - 1;
2719 u_long nsrc, ndest;
2720 u_char bltmode;
2722 bltmode = 0x00;
2723 /* if source adr < dest addr, do the Blt backwards */
2724 if (cury <= desty) {
2725 if (cury == desty) {
2726 /* if src and dest are on the same line, check x */
2727 if (curx < destx)
2728 bltmode |= 0x01;
2729 } else
2730 bltmode |= 0x01;
2732 /* standard case: forward blitting */
2733 nsrc = (cury * line_length) + curx;
2734 ndest = (desty * line_length) + destx;
2735 if (bltmode) {
2736 /* this means start addresses are at the end,
2737 * counting backwards
2739 nsrc += nheight * line_length + nwidth;
2740 ndest += nheight * line_length + nwidth;
2743 cirrusfb_WaitBLT(regbase);
2745 cirrusfb_set_blitter(regbase, nwidth, nheight,
2746 nsrc, ndest, bltmode, line_length);
2749 /*******************************************************************
2750 cirrusfb_RectFill()
2752 perform accelerated rectangle fill
2753 ********************************************************************/
2755 static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
2756 u_short x, u_short y, u_short width, u_short height,
2757 u32 fg_color, u32 bg_color, u_short line_length,
2758 u_char blitmode)
2760 u_long ndest = (y * line_length) + x;
2761 u_char op;
2763 cirrusfb_WaitBLT(regbase);
2765 /* This is a ColorExpand Blt, using the */
2766 /* same color for foreground and background */
2767 vga_wgfx(regbase, VGA_GFX_SR_VALUE, bg_color);
2768 vga_wgfx(regbase, VGA_GFX_SR_ENABLE, fg_color);
2770 op = 0x80;
2771 if (bits_per_pixel >= 16) {
2772 vga_wgfx(regbase, CL_GR10, bg_color >> 8);
2773 vga_wgfx(regbase, CL_GR11, fg_color >> 8);
2774 op = 0x90;
2776 if (bits_per_pixel >= 24) {
2777 vga_wgfx(regbase, CL_GR12, bg_color >> 16);
2778 vga_wgfx(regbase, CL_GR13, fg_color >> 16);
2779 op = 0xa0;
2781 if (bits_per_pixel == 32) {
2782 vga_wgfx(regbase, CL_GR14, bg_color >> 24);
2783 vga_wgfx(regbase, CL_GR15, fg_color >> 24);
2784 op = 0xb0;
2786 cirrusfb_set_blitter(regbase, width - 1, height - 1,
2787 0, ndest, op | blitmode, line_length);
2790 /**************************************************************************
2791 * bestclock() - determine closest possible clock lower(?) than the
2792 * desired pixel clock
2793 **************************************************************************/
2794 static void bestclock(long freq, int *nom, int *den, int *div)
2796 int n, d;
2797 long h, diff;
2799 assert(nom != NULL);
2800 assert(den != NULL);
2801 assert(div != NULL);
2803 *nom = 0;
2804 *den = 0;
2805 *div = 0;
2807 if (freq < 8000)
2808 freq = 8000;
2810 diff = freq;
2812 for (n = 32; n < 128; n++) {
2813 int s = 0;
2815 d = (14318 * n) / freq;
2816 if ((d >= 7) && (d <= 63)) {
2817 int temp = d;
2819 if (temp > 31) {
2820 s = 1;
2821 temp >>= 1;
2823 h = ((14318 * n) / temp) >> s;
2824 h = h > freq ? h - freq : freq - h;
2825 if (h < diff) {
2826 diff = h;
2827 *nom = n;
2828 *den = temp;
2829 *div = s;
2832 d++;
2833 if ((d >= 7) && (d <= 63)) {
2834 if (d > 31) {
2835 s = 1;
2836 d >>= 1;
2838 h = ((14318 * n) / d) >> s;
2839 h = h > freq ? h - freq : freq - h;
2840 if (h < diff) {
2841 diff = h;
2842 *nom = n;
2843 *den = d;
2844 *div = s;
2850 /* -------------------------------------------------------------------------
2852 * debugging functions
2854 * -------------------------------------------------------------------------
2857 #ifdef CIRRUSFB_DEBUG
2860 * cirrusfb_dbg_print_regs
2861 * @base: If using newmmio, the newmmio base address, otherwise %NULL
2862 * @reg_class: type of registers to read: %CRT, or %SEQ
2864 * DESCRIPTION:
2865 * Dumps the given list of VGA CRTC registers. If @base is %NULL,
2866 * old-style I/O ports are queried for information, otherwise MMIO is
2867 * used at the given @base address to query the information.
2870 static void cirrusfb_dbg_print_regs(struct fb_info *info,
2871 caddr_t regbase,
2872 enum cirrusfb_dbg_reg_class reg_class, ...)
2874 va_list list;
2875 unsigned char val = 0;
2876 unsigned reg;
2877 char *name;
2879 va_start(list, reg_class);
2881 name = va_arg(list, char *);
2882 while (name != NULL) {
2883 reg = va_arg(list, int);
2885 switch (reg_class) {
2886 case CRT:
2887 val = vga_rcrt(regbase, (unsigned char) reg);
2888 break;
2889 case SEQ:
2890 val = vga_rseq(regbase, (unsigned char) reg);
2891 break;
2892 default:
2893 /* should never occur */
2894 assert(false);
2895 break;
2898 dev_dbg(info->device, "%8s = 0x%02X\n", name, val);
2900 name = va_arg(list, char *);
2903 va_end(list);
2907 * cirrusfb_dbg_reg_dump
2908 * @base: If using newmmio, the newmmio base address, otherwise %NULL
2910 * DESCRIPTION:
2911 * Dumps a list of interesting VGA and CIRRUSFB registers. If @base is %NULL,
2912 * old-style I/O ports are queried for information, otherwise MMIO is
2913 * used at the given @base address to query the information.
2916 static void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase)
2918 dev_dbg(info->device, "VGA CRTC register dump:\n");
2920 cirrusfb_dbg_print_regs(info, regbase, CRT,
2921 "CR00", 0x00,
2922 "CR01", 0x01,
2923 "CR02", 0x02,
2924 "CR03", 0x03,
2925 "CR04", 0x04,
2926 "CR05", 0x05,
2927 "CR06", 0x06,
2928 "CR07", 0x07,
2929 "CR08", 0x08,
2930 "CR09", 0x09,
2931 "CR0A", 0x0A,
2932 "CR0B", 0x0B,
2933 "CR0C", 0x0C,
2934 "CR0D", 0x0D,
2935 "CR0E", 0x0E,
2936 "CR0F", 0x0F,
2937 "CR10", 0x10,
2938 "CR11", 0x11,
2939 "CR12", 0x12,
2940 "CR13", 0x13,
2941 "CR14", 0x14,
2942 "CR15", 0x15,
2943 "CR16", 0x16,
2944 "CR17", 0x17,
2945 "CR18", 0x18,
2946 "CR22", 0x22,
2947 "CR24", 0x24,
2948 "CR26", 0x26,
2949 "CR2D", 0x2D,
2950 "CR2E", 0x2E,
2951 "CR2F", 0x2F,
2952 "CR30", 0x30,
2953 "CR31", 0x31,
2954 "CR32", 0x32,
2955 "CR33", 0x33,
2956 "CR34", 0x34,
2957 "CR35", 0x35,
2958 "CR36", 0x36,
2959 "CR37", 0x37,
2960 "CR38", 0x38,
2961 "CR39", 0x39,
2962 "CR3A", 0x3A,
2963 "CR3B", 0x3B,
2964 "CR3C", 0x3C,
2965 "CR3D", 0x3D,
2966 "CR3E", 0x3E,
2967 "CR3F", 0x3F,
2968 NULL);
2970 dev_dbg(info->device, "\n");
2972 dev_dbg(info->device, "VGA SEQ register dump:\n");
2974 cirrusfb_dbg_print_regs(info, regbase, SEQ,
2975 "SR00", 0x00,
2976 "SR01", 0x01,
2977 "SR02", 0x02,
2978 "SR03", 0x03,
2979 "SR04", 0x04,
2980 "SR08", 0x08,
2981 "SR09", 0x09,
2982 "SR0A", 0x0A,
2983 "SR0B", 0x0B,
2984 "SR0D", 0x0D,
2985 "SR10", 0x10,
2986 "SR11", 0x11,
2987 "SR12", 0x12,
2988 "SR13", 0x13,
2989 "SR14", 0x14,
2990 "SR15", 0x15,
2991 "SR16", 0x16,
2992 "SR17", 0x17,
2993 "SR18", 0x18,
2994 "SR19", 0x19,
2995 "SR1A", 0x1A,
2996 "SR1B", 0x1B,
2997 "SR1C", 0x1C,
2998 "SR1D", 0x1D,
2999 "SR1E", 0x1E,
3000 "SR1F", 0x1F,
3001 NULL);
3003 dev_dbg(info->device, "\n");
3006 #endif /* CIRRUSFB_DEBUG */