cirrusfb: fix clock doubling
[linux-2.6/mini2440.git] / drivers / video / cirrusfb.c
blob15e2e6bfcbffb1794d77fdd9ca03dd2474d9ddfb
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;
523 switch (var->bits_per_pixel) {
524 case 1:
525 var->red.offset = 0;
526 var->red.length = 1;
527 var->green = var->red;
528 var->blue = var->red;
529 break;
531 case 8:
532 var->red.offset = 0;
533 var->red.length = 8;
534 var->green = var->red;
535 var->blue = var->red;
536 break;
538 case 16:
539 if (isPReP) {
540 var->red.offset = 2;
541 var->green.offset = -3;
542 var->blue.offset = 8;
543 } else {
544 var->red.offset = 11;
545 var->green.offset = 5;
546 var->blue.offset = 0;
548 var->red.length = 5;
549 var->green.length = 6;
550 var->blue.length = 5;
551 break;
553 case 24:
554 if (isPReP) {
555 var->red.offset = 0;
556 var->green.offset = 8;
557 var->blue.offset = 16;
558 } else {
559 var->red.offset = 16;
560 var->green.offset = 8;
561 var->blue.offset = 0;
563 var->red.length = 8;
564 var->green.length = 8;
565 var->blue.length = 8;
566 break;
568 default:
569 dev_dbg(info->device,
570 "Unsupported bpp size: %d\n", var->bits_per_pixel);
571 assert(false);
572 /* should never occur */
573 break;
576 if (var->xres_virtual < var->xres)
577 var->xres_virtual = var->xres;
578 /* use highest possible virtual resolution */
579 if (var->yres_virtual == -1) {
580 var->yres_virtual = pixels / var->xres_virtual;
582 dev_info(info->device,
583 "virtual resolution set to maximum of %dx%d\n",
584 var->xres_virtual, var->yres_virtual);
586 if (var->yres_virtual < var->yres)
587 var->yres_virtual = var->yres;
589 if (var->xres_virtual * var->yres_virtual > pixels) {
590 dev_err(info->device, "mode %dx%dx%d rejected... "
591 "virtual resolution too high to fit into video memory!\n",
592 var->xres_virtual, var->yres_virtual,
593 var->bits_per_pixel);
594 return -EINVAL;
597 if (var->xoffset < 0)
598 var->xoffset = 0;
599 if (var->yoffset < 0)
600 var->yoffset = 0;
602 /* truncate xoffset and yoffset to maximum if too high */
603 if (var->xoffset > var->xres_virtual - var->xres)
604 var->xoffset = var->xres_virtual - var->xres - 1;
605 if (var->yoffset > var->yres_virtual - var->yres)
606 var->yoffset = var->yres_virtual - var->yres - 1;
608 var->red.msb_right =
609 var->green.msb_right =
610 var->blue.msb_right =
611 var->transp.offset =
612 var->transp.length =
613 var->transp.msb_right = 0;
615 yres = var->yres;
616 if (var->vmode & FB_VMODE_DOUBLE)
617 yres *= 2;
618 else if (var->vmode & FB_VMODE_INTERLACED)
619 yres = (yres + 1) / 2;
621 if (yres >= 1280) {
622 dev_err(info->device, "ERROR: VerticalTotal >= 1280; "
623 "special treatment required! (TODO)\n");
624 return -EINVAL;
627 if (cirrusfb_check_pixclock(var, info))
628 return -EINVAL;
630 return 0;
633 static void cirrusfb_set_mclk_as_source(const struct fb_info *info, int div)
635 struct cirrusfb_info *cinfo = info->par;
636 unsigned char old1f, old1e;
638 assert(cinfo != NULL);
639 old1f = vga_rseq(cinfo->regbase, CL_SEQR1F) & ~0x40;
641 if (div) {
642 dev_dbg(info->device, "Set %s as pixclock source.\n",
643 (div == 2) ? "MCLK/2" : "MCLK");
644 old1f |= 0x40;
645 old1e = vga_rseq(cinfo->regbase, CL_SEQR1E) & ~0x1;
646 if (div == 2)
647 old1e |= 1;
649 vga_wseq(cinfo->regbase, CL_SEQR1E, old1e);
651 vga_wseq(cinfo->regbase, CL_SEQR1F, old1f);
654 /*************************************************************************
655 cirrusfb_set_par_foo()
657 actually writes the values for a new video mode into the hardware,
658 **************************************************************************/
659 static int cirrusfb_set_par_foo(struct fb_info *info)
661 struct cirrusfb_info *cinfo = info->par;
662 struct fb_var_screeninfo *var = &info->var;
663 u8 __iomem *regbase = cinfo->regbase;
664 unsigned char tmp;
665 int pitch;
666 const struct cirrusfb_board_info_rec *bi;
667 int hdispend, hsyncstart, hsyncend, htotal;
668 int yres, vdispend, vsyncstart, vsyncend, vtotal;
669 long freq;
670 int nom, den, div;
671 unsigned int control = 0, format = 0, threshold = 0;
673 dev_dbg(info->device, "Requested mode: %dx%dx%d\n",
674 var->xres, var->yres, var->bits_per_pixel);
676 switch (var->bits_per_pixel) {
677 case 1:
678 info->fix.line_length = var->xres_virtual / 8;
679 info->fix.visual = FB_VISUAL_MONO10;
680 break;
682 case 8:
683 info->fix.line_length = var->xres_virtual;
684 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
685 break;
687 case 16:
688 case 24:
689 info->fix.line_length = var->xres_virtual *
690 var->bits_per_pixel >> 3;
691 info->fix.visual = FB_VISUAL_TRUECOLOR;
692 break;
694 info->fix.type = FB_TYPE_PACKED_PIXELS;
696 init_vgachip(info);
698 bi = &cirrusfb_board_info[cinfo->btype];
700 hsyncstart = var->xres + var->right_margin;
701 hsyncend = hsyncstart + var->hsync_len;
702 htotal = (hsyncend + var->left_margin) / 8 - 5;
703 hdispend = var->xres / 8 - 1;
704 hsyncstart = hsyncstart / 8 + 1;
705 hsyncend = hsyncend / 8 + 1;
707 yres = var->yres;
708 vsyncstart = yres + var->lower_margin;
709 vsyncend = vsyncstart + var->vsync_len;
710 vtotal = vsyncend + var->upper_margin;
711 vdispend = yres - 1;
713 if (var->vmode & FB_VMODE_DOUBLE) {
714 yres *= 2;
715 vsyncstart *= 2;
716 vsyncend *= 2;
717 vtotal *= 2;
718 } else if (var->vmode & FB_VMODE_INTERLACED) {
719 yres = (yres + 1) / 2;
720 vsyncstart = (vsyncstart + 1) / 2;
721 vsyncend = (vsyncend + 1) / 2;
722 vtotal = (vtotal + 1) / 2;
725 vtotal -= 2;
726 vsyncstart -= 1;
727 vsyncend -= 1;
729 if (yres >= 1024) {
730 vtotal /= 2;
731 vsyncstart /= 2;
732 vsyncend /= 2;
733 vdispend /= 2;
735 if (cinfo->multiplexing) {
736 htotal /= 2;
737 hsyncstart /= 2;
738 hsyncend /= 2;
739 hdispend /= 2;
741 /* unlock register VGA_CRTC_H_TOTAL..CRT7 */
742 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */
744 /* if debugging is enabled, all parameters get output before writing */
745 dev_dbg(info->device, "CRT0: %d\n", htotal);
746 vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal);
748 dev_dbg(info->device, "CRT1: %d\n", hdispend);
749 vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend);
751 dev_dbg(info->device, "CRT2: %d\n", var->xres / 8);
752 vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8);
754 /* + 128: Compatible read */
755 dev_dbg(info->device, "CRT3: 128+%d\n", (htotal + 5) % 32);
756 vga_wcrt(regbase, VGA_CRTC_H_BLANK_END,
757 128 + ((htotal + 5) % 32));
759 dev_dbg(info->device, "CRT4: %d\n", hsyncstart);
760 vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart);
762 tmp = hsyncend % 32;
763 if ((htotal + 5) & 32)
764 tmp += 128;
765 dev_dbg(info->device, "CRT5: %d\n", tmp);
766 vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp);
768 dev_dbg(info->device, "CRT6: %d\n", vtotal & 0xff);
769 vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff);
771 tmp = 16; /* LineCompare bit #9 */
772 if (vtotal & 256)
773 tmp |= 1;
774 if (vdispend & 256)
775 tmp |= 2;
776 if (vsyncstart & 256)
777 tmp |= 4;
778 if ((vdispend + 1) & 256)
779 tmp |= 8;
780 if (vtotal & 512)
781 tmp |= 32;
782 if (vdispend & 512)
783 tmp |= 64;
784 if (vsyncstart & 512)
785 tmp |= 128;
786 dev_dbg(info->device, "CRT7: %d\n", tmp);
787 vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp);
789 tmp = 0x40; /* LineCompare bit #8 */
790 if ((vdispend + 1) & 512)
791 tmp |= 0x20;
792 if (var->vmode & FB_VMODE_DOUBLE)
793 tmp |= 0x80;
794 dev_dbg(info->device, "CRT9: %d\n", tmp);
795 vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp);
797 dev_dbg(info->device, "CRT10: %d\n", vsyncstart & 0xff);
798 vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff);
800 dev_dbg(info->device, "CRT11: 64+32+%d\n", vsyncend % 16);
801 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32);
803 dev_dbg(info->device, "CRT12: %d\n", vdispend & 0xff);
804 vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff);
806 dev_dbg(info->device, "CRT15: %d\n", (vdispend + 1) & 0xff);
807 vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff);
809 dev_dbg(info->device, "CRT16: %d\n", vtotal & 0xff);
810 vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff);
812 dev_dbg(info->device, "CRT18: 0xff\n");
813 vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff);
815 tmp = 0;
816 if (var->vmode & FB_VMODE_INTERLACED)
817 tmp |= 1;
818 if ((htotal + 5) & 64)
819 tmp |= 16;
820 if ((htotal + 5) & 128)
821 tmp |= 32;
822 if (vtotal & 256)
823 tmp |= 64;
824 if (vtotal & 512)
825 tmp |= 128;
827 dev_dbg(info->device, "CRT1a: %d\n", tmp);
828 vga_wcrt(regbase, CL_CRT1A, tmp);
830 freq = PICOS2KHZ(var->pixclock);
831 if (cinfo->btype == BT_ALPINE && var->bits_per_pixel == 24)
832 freq *= 3;
833 if (cinfo->multiplexing)
834 freq /= 2;
836 bestclock(freq, &nom, &den, &div);
838 dev_dbg(info->device, "VCLK freq: %ld kHz nom: %d den: %d div: %d\n",
839 freq, nom, den, div);
841 /* set VCLK0 */
842 /* hardware RefClock: 14.31818 MHz */
843 /* formula: VClk = (OSC * N) / (D * (1+P)) */
844 /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
846 if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_PICASSO4) {
847 /* if freq is close to mclk or mclk/2 select mclk
848 * as clock source
850 int divMCLK = cirrusfb_check_mclk(info, freq);
851 if (divMCLK) {
852 nom = 0;
853 cirrusfb_set_mclk_as_source(info, divMCLK);
856 if (is_laguna(cinfo)) {
857 long pcifc = fb_readl(cinfo->laguna_mmio + 0x3fc);
858 unsigned char tile = fb_readb(cinfo->laguna_mmio + 0x407);
859 unsigned short tile_control;
861 if (cinfo->btype == BT_LAGUNAB) {
862 tile_control = fb_readw(cinfo->laguna_mmio + 0x2c4);
863 tile_control &= ~0x80;
864 fb_writew(tile_control, cinfo->laguna_mmio + 0x2c4);
867 fb_writel(pcifc | 0x10000000l, cinfo->laguna_mmio + 0x3fc);
868 fb_writeb(tile & 0x3f, cinfo->laguna_mmio + 0x407);
869 control = fb_readw(cinfo->laguna_mmio + 0x402);
870 threshold = fb_readw(cinfo->laguna_mmio + 0xea);
871 control &= ~0x6800;
872 format = 0;
873 threshold &= 0xffe0 & 0x3fbf;
875 if (nom) {
876 tmp = den << 1;
877 if (div != 0)
878 tmp |= 1;
879 /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
880 if ((cinfo->btype == BT_SD64) ||
881 (cinfo->btype == BT_ALPINE) ||
882 (cinfo->btype == BT_GD5480))
883 tmp |= 0x80;
885 dev_dbg(info->device, "CL_SEQR1B: %d\n", (int) tmp);
886 /* Laguna chipset has reversed clock registers */
887 if (is_laguna(cinfo)) {
888 vga_wseq(regbase, CL_SEQRE, tmp);
889 vga_wseq(regbase, CL_SEQR1E, nom);
890 } else {
891 vga_wseq(regbase, CL_SEQRB, nom);
892 vga_wseq(regbase, CL_SEQR1B, tmp);
896 if (yres >= 1024)
897 /* 1280x1024 */
898 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7);
899 else
900 /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
901 * address wrap, no compat. */
902 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3);
904 /* don't know if it would hurt to also program this if no interlaced */
905 /* mode is used, but I feel better this way.. :-) */
906 if (var->vmode & FB_VMODE_INTERLACED)
907 vga_wcrt(regbase, VGA_CRTC_REGS, htotal / 2);
908 else
909 vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
911 /* adjust horizontal/vertical sync type (low/high) */
912 /* enable display memory & CRTC I/O address for color mode */
913 tmp = 0x03;
914 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
915 tmp |= 0x40;
916 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
917 tmp |= 0x80;
918 if (is_laguna(cinfo))
919 tmp |= 0xc;
920 WGen(cinfo, VGA_MIS_W, tmp);
922 /* text cursor on and start line */
923 vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0);
924 /* text cursor end line */
925 vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 31);
927 /******************************************************
929 * 1 bpp
933 /* programming for different color depths */
934 if (var->bits_per_pixel == 1) {
935 dev_dbg(info->device, "preparing for 1 bit deep display\n");
936 vga_wgfx(regbase, VGA_GFX_MODE, 0); /* mode register */
938 /* SR07 */
939 switch (cinfo->btype) {
940 case BT_SD64:
941 case BT_PICCOLO:
942 case BT_PICASSO:
943 case BT_SPECTRUM:
944 case BT_PICASSO4:
945 case BT_ALPINE:
946 case BT_GD5480:
947 vga_wseq(regbase, CL_SEQR7,
948 cinfo->multiplexing ?
949 bi->sr07_1bpp_mux : bi->sr07_1bpp);
950 break;
952 case BT_LAGUNA:
953 case BT_LAGUNAB:
954 vga_wseq(regbase, CL_SEQR7,
955 vga_rseq(regbase, CL_SEQR7) & ~0x01);
956 break;
958 default:
959 dev_warn(info->device, "unknown Board\n");
960 break;
963 /* Extended Sequencer Mode */
964 switch (cinfo->btype) {
965 case BT_SD64:
966 /* setting the SEQRF on SD64 is not necessary
967 * (only during init)
969 /* MCLK select */
970 vga_wseq(regbase, CL_SEQR1F, 0x1a);
971 break;
973 case BT_PICCOLO:
974 case BT_SPECTRUM:
975 /* ### ueberall 0x22? */
976 /* ##vorher 1c MCLK select */
977 vga_wseq(regbase, CL_SEQR1F, 0x22);
978 /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
979 vga_wseq(regbase, CL_SEQRF, 0xb0);
980 break;
982 case BT_PICASSO:
983 /* ##vorher 22 MCLK select */
984 vga_wseq(regbase, CL_SEQR1F, 0x22);
985 /* ## vorher d0 avoid FIFO underruns..? */
986 vga_wseq(regbase, CL_SEQRF, 0xd0);
987 break;
989 case BT_PICASSO4:
990 case BT_ALPINE:
991 case BT_GD5480:
992 case BT_LAGUNA:
993 case BT_LAGUNAB:
994 /* do nothing */
995 break;
997 default:
998 dev_warn(info->device, "unknown Board\n");
999 break;
1002 /* pixel mask: pass-through for first plane */
1003 WGen(cinfo, VGA_PEL_MSK, 0x01);
1004 if (cinfo->multiplexing)
1005 /* hidden dac reg: 1280x1024 */
1006 WHDR(cinfo, 0x4a);
1007 else
1008 /* hidden dac: nothing */
1009 WHDR(cinfo, 0);
1010 /* memory mode: odd/even, ext. memory */
1011 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06);
1012 /* plane mask: only write to first plane */
1013 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01);
1016 /******************************************************
1018 * 8 bpp
1022 else if (var->bits_per_pixel == 8) {
1023 dev_dbg(info->device, "preparing for 8 bit deep display\n");
1024 switch (cinfo->btype) {
1025 case BT_SD64:
1026 case BT_PICCOLO:
1027 case BT_PICASSO:
1028 case BT_SPECTRUM:
1029 case BT_PICASSO4:
1030 case BT_ALPINE:
1031 case BT_GD5480:
1032 vga_wseq(regbase, CL_SEQR7,
1033 cinfo->multiplexing ?
1034 bi->sr07_8bpp_mux : bi->sr07_8bpp);
1035 break;
1037 case BT_LAGUNA:
1038 case BT_LAGUNAB:
1039 vga_wseq(regbase, CL_SEQR7,
1040 vga_rseq(regbase, CL_SEQR7) | 0x01);
1041 threshold |= 0x10;
1042 break;
1044 default:
1045 dev_warn(info->device, "unknown Board\n");
1046 break;
1049 switch (cinfo->btype) {
1050 case BT_SD64:
1051 /* MCLK select */
1052 vga_wseq(regbase, CL_SEQR1F, 0x1d);
1053 break;
1055 case BT_PICCOLO:
1056 case BT_PICASSO:
1057 case BT_SPECTRUM:
1058 /* ### vorher 1c MCLK select */
1059 vga_wseq(regbase, CL_SEQR1F, 0x22);
1060 /* Fast Page-Mode writes */
1061 vga_wseq(regbase, CL_SEQRF, 0xb0);
1062 break;
1064 case BT_PICASSO4:
1065 #ifdef CONFIG_ZORRO
1066 /* ### INCOMPLETE!! */
1067 vga_wseq(regbase, CL_SEQRF, 0xb8);
1068 #endif
1069 case BT_ALPINE:
1070 /* We already set SRF and SR1F */
1071 break;
1073 case BT_GD5480:
1074 case BT_LAGUNA:
1075 case BT_LAGUNAB:
1076 /* do nothing */
1077 break;
1079 default:
1080 dev_warn(info->device, "unknown board\n");
1081 break;
1084 /* mode register: 256 color mode */
1085 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1086 if (cinfo->multiplexing)
1087 /* hidden dac reg: 1280x1024 */
1088 WHDR(cinfo, 0x4a);
1089 else
1090 /* hidden dac: nothing */
1091 WHDR(cinfo, 0);
1094 /******************************************************
1096 * 16 bpp
1100 else if (var->bits_per_pixel == 16) {
1101 dev_dbg(info->device, "preparing for 16 bit deep display\n");
1102 switch (cinfo->btype) {
1103 case BT_SD64:
1104 /* Extended Sequencer Mode: 256c col. mode */
1105 vga_wseq(regbase, CL_SEQR7, 0xf7);
1106 /* MCLK select */
1107 vga_wseq(regbase, CL_SEQR1F, 0x1e);
1108 break;
1110 case BT_PICCOLO:
1111 case BT_SPECTRUM:
1112 vga_wseq(regbase, CL_SEQR7, 0x87);
1113 /* Fast Page-Mode writes */
1114 vga_wseq(regbase, CL_SEQRF, 0xb0);
1115 /* MCLK select */
1116 vga_wseq(regbase, CL_SEQR1F, 0x22);
1117 break;
1119 case BT_PICASSO:
1120 vga_wseq(regbase, CL_SEQR7, 0x27);
1121 /* Fast Page-Mode writes */
1122 vga_wseq(regbase, CL_SEQRF, 0xb0);
1123 /* MCLK select */
1124 vga_wseq(regbase, CL_SEQR1F, 0x22);
1125 break;
1127 case BT_PICASSO4:
1128 case BT_ALPINE:
1129 vga_wseq(regbase, CL_SEQR7, 0xa7);
1130 break;
1132 case BT_GD5480:
1133 vga_wseq(regbase, CL_SEQR7, 0x17);
1134 /* We already set SRF and SR1F */
1135 break;
1137 case BT_LAGUNA:
1138 case BT_LAGUNAB:
1139 vga_wseq(regbase, CL_SEQR7,
1140 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1141 control |= 0x2000;
1142 format |= 0x1400;
1143 threshold |= 0x10;
1144 break;
1146 default:
1147 dev_warn(info->device, "unknown Board\n");
1148 break;
1151 /* mode register: 256 color mode */
1152 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1153 #ifdef CONFIG_PCI
1154 WHDR(cinfo, 0xc1); /* Copy Xbh */
1155 #elif defined(CONFIG_ZORRO)
1156 /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
1157 WHDR(cinfo, 0xa0); /* hidden dac reg: nothing special */
1158 #endif
1161 /******************************************************
1163 * 24 bpp
1167 else if (var->bits_per_pixel == 24) {
1168 dev_dbg(info->device, "preparing for 24 bit deep display\n");
1169 switch (cinfo->btype) {
1170 case BT_SD64:
1171 /* Extended Sequencer Mode: 256c col. mode */
1172 vga_wseq(regbase, CL_SEQR7, 0xf5);
1173 /* MCLK select */
1174 vga_wseq(regbase, CL_SEQR1F, 0x1e);
1175 break;
1177 case BT_PICCOLO:
1178 case BT_SPECTRUM:
1179 vga_wseq(regbase, CL_SEQR7, 0x85);
1180 /* Fast Page-Mode writes */
1181 vga_wseq(regbase, CL_SEQRF, 0xb0);
1182 /* MCLK select */
1183 vga_wseq(regbase, CL_SEQR1F, 0x22);
1184 break;
1186 case BT_PICASSO:
1187 vga_wseq(regbase, CL_SEQR7, 0x25);
1188 /* Fast Page-Mode writes */
1189 vga_wseq(regbase, CL_SEQRF, 0xb0);
1190 /* MCLK select */
1191 vga_wseq(regbase, CL_SEQR1F, 0x22);
1192 break;
1194 case BT_PICASSO4:
1195 case BT_ALPINE:
1196 vga_wseq(regbase, CL_SEQR7, 0xa5);
1197 break;
1199 case BT_GD5480:
1200 vga_wseq(regbase, CL_SEQR7, 0x15);
1201 /* We already set SRF and SR1F */
1202 break;
1204 case BT_LAGUNA:
1205 case BT_LAGUNAB:
1206 vga_wseq(regbase, CL_SEQR7,
1207 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1208 control |= 0x4000;
1209 format |= 0x2400;
1210 threshold |= 0x20;
1211 break;
1213 default:
1214 dev_warn(info->device, "unknown Board\n");
1215 break;
1218 /* mode register: 256 color mode */
1219 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1220 /* hidden dac reg: 8-8-8 mode (24 or 32) */
1221 WHDR(cinfo, 0xc5);
1224 /******************************************************
1226 * unknown/unsupported bpp
1230 else
1231 dev_err(info->device,
1232 "What's this? requested color depth == %d.\n",
1233 var->bits_per_pixel);
1235 pitch = info->fix.line_length >> 3;
1236 vga_wcrt(regbase, VGA_CRTC_OFFSET, pitch & 0xff);
1237 tmp = 0x22;
1238 if (pitch & 0x100)
1239 tmp |= 0x10; /* offset overflow bit */
1241 /* screen start addr #16-18, fastpagemode cycles */
1242 vga_wcrt(regbase, CL_CRT1B, tmp);
1244 /* screen start address bit 19 */
1245 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19)
1246 vga_wcrt(regbase, CL_CRT1D, (pitch >> 9) & 1);
1248 if (is_laguna(cinfo)) {
1249 tmp = 0;
1250 if ((htotal + 5) & 256)
1251 tmp |= 128;
1252 if (hdispend & 256)
1253 tmp |= 64;
1254 if (hsyncstart & 256)
1255 tmp |= 48;
1256 if (vtotal & 1024)
1257 tmp |= 8;
1258 if (vdispend & 1024)
1259 tmp |= 4;
1260 if (vsyncstart & 1024)
1261 tmp |= 3;
1263 vga_wcrt(regbase, CL_CRT1E, tmp);
1264 dev_dbg(info->device, "CRT1e: %d\n", tmp);
1267 /* pixel panning */
1268 vga_wattr(regbase, CL_AR33, 0);
1270 /* [ EGS: SetOffset(); ] */
1271 /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
1272 AttrOn(cinfo);
1274 if (is_laguna(cinfo)) {
1275 /* no tiles */
1276 fb_writew(control | 0x1000, cinfo->laguna_mmio + 0x402);
1277 fb_writew(format, cinfo->laguna_mmio + 0xc0);
1278 fb_writew(threshold, cinfo->laguna_mmio + 0xea);
1280 /* finally, turn on everything - turn off "FullBandwidth" bit */
1281 /* also, set "DotClock%2" bit where requested */
1282 tmp = 0x01;
1284 /*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
1285 if (var->vmode & FB_VMODE_CLOCK_HALVE)
1286 tmp |= 0x08;
1289 vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp);
1290 dev_dbg(info->device, "CL_SEQR1: %d\n", tmp);
1292 #ifdef CIRRUSFB_DEBUG
1293 cirrusfb_dbg_reg_dump(info, NULL);
1294 #endif
1296 return 0;
1299 /* for some reason incomprehensible to me, cirrusfb requires that you write
1300 * the registers twice for the settings to take..grr. -dte */
1301 static int cirrusfb_set_par(struct fb_info *info)
1303 cirrusfb_set_par_foo(info);
1304 return cirrusfb_set_par_foo(info);
1307 static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1308 unsigned blue, unsigned transp,
1309 struct fb_info *info)
1311 struct cirrusfb_info *cinfo = info->par;
1313 if (regno > 255)
1314 return -EINVAL;
1316 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
1317 u32 v;
1318 red >>= (16 - info->var.red.length);
1319 green >>= (16 - info->var.green.length);
1320 blue >>= (16 - info->var.blue.length);
1322 if (regno >= 16)
1323 return 1;
1324 v = (red << info->var.red.offset) |
1325 (green << info->var.green.offset) |
1326 (blue << info->var.blue.offset);
1328 cinfo->pseudo_palette[regno] = v;
1329 return 0;
1332 if (info->var.bits_per_pixel == 8)
1333 WClut(cinfo, regno, red >> 10, green >> 10, blue >> 10);
1335 return 0;
1339 /*************************************************************************
1340 cirrusfb_pan_display()
1342 performs display panning - provided hardware permits this
1343 **************************************************************************/
1344 static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
1345 struct fb_info *info)
1347 int xoffset;
1348 unsigned long base;
1349 unsigned char tmp, xpix;
1350 struct cirrusfb_info *cinfo = info->par;
1352 dev_dbg(info->device,
1353 "virtual offset: (%d,%d)\n", var->xoffset, var->yoffset);
1355 /* no range checks for xoffset and yoffset, */
1356 /* as fb_pan_display has already done this */
1357 if (var->vmode & FB_VMODE_YWRAP)
1358 return -EINVAL;
1360 xoffset = var->xoffset * info->var.bits_per_pixel / 8;
1362 base = var->yoffset * info->fix.line_length + xoffset;
1364 if (info->var.bits_per_pixel == 1) {
1365 /* base is already correct */
1366 xpix = (unsigned char) (var->xoffset % 8);
1367 } else {
1368 base /= 4;
1369 xpix = (unsigned char) ((xoffset % 4) * 2);
1372 if (!is_laguna(cinfo))
1373 cirrusfb_WaitBLT(cinfo->regbase);
1375 /* lower 8 + 8 bits of screen start address */
1376 vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, base & 0xff);
1377 vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, (base >> 8) & 0xff);
1379 /* 0xf2 is %11110010, exclude tmp bits */
1380 tmp = vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2;
1381 /* construct bits 16, 17 and 18 of screen start address */
1382 if (base & 0x10000)
1383 tmp |= 0x01;
1384 if (base & 0x20000)
1385 tmp |= 0x04;
1386 if (base & 0x40000)
1387 tmp |= 0x08;
1389 vga_wcrt(cinfo->regbase, CL_CRT1B, tmp);
1391 /* construct bit 19 of screen start address */
1392 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) {
1393 tmp = vga_rcrt(cinfo->regbase, CL_CRT1D);
1394 if (is_laguna(cinfo))
1395 tmp = (tmp & ~0x18) | ((base >> 16) & 0x18);
1396 else
1397 tmp = (tmp & ~0x80) | ((base >> 12) & 0x80);
1398 vga_wcrt(cinfo->regbase, CL_CRT1D, tmp);
1401 /* write pixel panning value to AR33; this does not quite work in 8bpp
1403 * ### Piccolo..? Will this work?
1405 if (info->var.bits_per_pixel == 1)
1406 vga_wattr(cinfo->regbase, CL_AR33, xpix);
1408 return 0;
1411 static int cirrusfb_blank(int blank_mode, struct fb_info *info)
1414 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
1415 * then the caller blanks by setting the CLUT (Color Look Up Table)
1416 * to all black. Return 0 if blanking succeeded, != 0 if un-/blanking
1417 * failed due to e.g. a video mode which doesn't support it.
1418 * Implements VESA suspend and powerdown modes on hardware that
1419 * supports disabling hsync/vsync:
1420 * blank_mode == 2: suspend vsync
1421 * blank_mode == 3: suspend hsync
1422 * blank_mode == 4: powerdown
1424 unsigned char val;
1425 struct cirrusfb_info *cinfo = info->par;
1426 int current_mode = cinfo->blank_mode;
1428 dev_dbg(info->device, "ENTER, blank mode = %d\n", blank_mode);
1430 if (info->state != FBINFO_STATE_RUNNING ||
1431 current_mode == blank_mode) {
1432 dev_dbg(info->device, "EXIT, returning 0\n");
1433 return 0;
1436 /* Undo current */
1437 if (current_mode == FB_BLANK_NORMAL ||
1438 current_mode == FB_BLANK_UNBLANK)
1439 /* clear "FullBandwidth" bit */
1440 val = 0;
1441 else
1442 /* set "FullBandwidth" bit */
1443 val = 0x20;
1445 val |= vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE) & 0xdf;
1446 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val);
1448 switch (blank_mode) {
1449 case FB_BLANK_UNBLANK:
1450 case FB_BLANK_NORMAL:
1451 val = 0x00;
1452 break;
1453 case FB_BLANK_VSYNC_SUSPEND:
1454 val = 0x04;
1455 break;
1456 case FB_BLANK_HSYNC_SUSPEND:
1457 val = 0x02;
1458 break;
1459 case FB_BLANK_POWERDOWN:
1460 val = 0x06;
1461 break;
1462 default:
1463 dev_dbg(info->device, "EXIT, returning 1\n");
1464 return 1;
1467 vga_wgfx(cinfo->regbase, CL_GRE, val);
1469 cinfo->blank_mode = blank_mode;
1470 dev_dbg(info->device, "EXIT, returning 0\n");
1472 /* Let fbcon do a soft blank for us */
1473 return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
1476 /**** END Hardware specific Routines **************************************/
1477 /****************************************************************************/
1478 /**** BEGIN Internal Routines ***********************************************/
1480 static void init_vgachip(struct fb_info *info)
1482 struct cirrusfb_info *cinfo = info->par;
1483 const struct cirrusfb_board_info_rec *bi;
1485 assert(cinfo != NULL);
1487 bi = &cirrusfb_board_info[cinfo->btype];
1489 /* reset board globally */
1490 switch (cinfo->btype) {
1491 case BT_PICCOLO:
1492 WSFR(cinfo, 0x01);
1493 udelay(500);
1494 WSFR(cinfo, 0x51);
1495 udelay(500);
1496 break;
1497 case BT_PICASSO:
1498 WSFR2(cinfo, 0xff);
1499 udelay(500);
1500 break;
1501 case BT_SD64:
1502 case BT_SPECTRUM:
1503 WSFR(cinfo, 0x1f);
1504 udelay(500);
1505 WSFR(cinfo, 0x4f);
1506 udelay(500);
1507 break;
1508 case BT_PICASSO4:
1509 /* disable flickerfixer */
1510 vga_wcrt(cinfo->regbase, CL_CRT51, 0x00);
1511 mdelay(100);
1512 /* mode */
1513 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1514 case BT_GD5480: /* fall through */
1515 /* from Klaus' NetBSD driver: */
1516 vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
1517 case BT_ALPINE: /* fall through */
1518 /* put blitter into 542x compat */
1519 vga_wgfx(cinfo->regbase, CL_GR33, 0x00);
1520 break;
1522 case BT_LAGUNA:
1523 case BT_LAGUNAB:
1524 /* Nothing to do to reset the board. */
1525 break;
1527 default:
1528 dev_err(info->device, "Warning: Unknown board type\n");
1529 break;
1532 /* make sure RAM size set by this point */
1533 assert(info->screen_size > 0);
1535 /* the P4 is not fully initialized here; I rely on it having been */
1536 /* inited under AmigaOS already, which seems to work just fine */
1537 /* (Klaus advised to do it this way) */
1539 if (cinfo->btype != BT_PICASSO4) {
1540 WGen(cinfo, CL_VSSM, 0x10); /* EGS: 0x16 */
1541 WGen(cinfo, CL_POS102, 0x01);
1542 WGen(cinfo, CL_VSSM, 0x08); /* EGS: 0x0e */
1544 if (cinfo->btype != BT_SD64)
1545 WGen(cinfo, CL_VSSM2, 0x01);
1547 /* reset sequencer logic */
1548 vga_wseq(cinfo->regbase, VGA_SEQ_RESET, 0x03);
1550 /* FullBandwidth (video off) and 8/9 dot clock */
1551 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21);
1553 /* "magic cookie" - doesn't make any sense to me.. */
1554 /* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */
1555 /* unlock all extension registers */
1556 vga_wseq(cinfo->regbase, CL_SEQR6, 0x12);
1558 switch (cinfo->btype) {
1559 case BT_GD5480:
1560 vga_wseq(cinfo->regbase, CL_SEQRF, 0x98);
1561 break;
1562 case BT_ALPINE:
1563 case BT_LAGUNA:
1564 case BT_LAGUNAB:
1565 break;
1566 case BT_SD64:
1567 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8);
1568 break;
1569 default:
1570 vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f);
1571 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb0);
1572 break;
1575 /* plane mask: nothing */
1576 vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1577 /* character map select: doesn't even matter in gx mode */
1578 vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00);
1579 /* memory mode: chain4, ext. memory */
1580 vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1582 /* controller-internal base address of video memory */
1583 if (bi->init_sr07)
1584 vga_wseq(cinfo->regbase, CL_SEQR7, bi->sr07);
1586 /* vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */
1587 /* EEPROM control: shouldn't be necessary to write to this at all.. */
1589 /* graphics cursor X position (incomplete; position gives rem. 3 bits */
1590 vga_wseq(cinfo->regbase, CL_SEQR10, 0x00);
1591 /* graphics cursor Y position (..."... ) */
1592 vga_wseq(cinfo->regbase, CL_SEQR11, 0x00);
1593 /* graphics cursor attributes */
1594 vga_wseq(cinfo->regbase, CL_SEQR12, 0x00);
1595 /* graphics cursor pattern address */
1596 vga_wseq(cinfo->regbase, CL_SEQR13, 0x00);
1598 /* writing these on a P4 might give problems.. */
1599 if (cinfo->btype != BT_PICASSO4) {
1600 /* configuration readback and ext. color */
1601 vga_wseq(cinfo->regbase, CL_SEQR17, 0x00);
1602 /* signature generator */
1603 vga_wseq(cinfo->regbase, CL_SEQR18, 0x02);
1606 /* MCLK select etc. */
1607 if (bi->init_sr1f)
1608 vga_wseq(cinfo->regbase, CL_SEQR1F, bi->sr1f);
1610 /* Screen A preset row scan: none */
1611 vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00);
1612 /* Text cursor start: disable text cursor */
1613 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20);
1614 /* Text cursor end: - */
1615 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00);
1616 /* text cursor location high: 0 */
1617 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00);
1618 /* text cursor location low: 0 */
1619 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00);
1621 /* Underline Row scanline: - */
1622 vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00);
1623 /* ### add 0x40 for text modes with > 30 MHz pixclock */
1624 /* ext. display controls: ext.adr. wrap */
1625 vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02);
1627 /* Set/Reset registes: - */
1628 vga_wgfx(cinfo->regbase, VGA_GFX_SR_VALUE, 0x00);
1629 /* Set/Reset enable: - */
1630 vga_wgfx(cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00);
1631 /* Color Compare: - */
1632 vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00);
1633 /* Data Rotate: - */
1634 vga_wgfx(cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00);
1635 /* Read Map Select: - */
1636 vga_wgfx(cinfo->regbase, VGA_GFX_PLANE_READ, 0x00);
1637 /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
1638 vga_wgfx(cinfo->regbase, VGA_GFX_MODE, 0x00);
1639 /* Miscellaneous: memory map base address, graphics mode */
1640 vga_wgfx(cinfo->regbase, VGA_GFX_MISC, 0x01);
1641 /* Color Don't care: involve all planes */
1642 vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f);
1643 /* Bit Mask: no mask at all */
1644 vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff);
1646 if (cinfo->btype == BT_ALPINE || is_laguna(cinfo))
1647 /* (5434 can't have bit 3 set for bitblt) */
1648 vga_wgfx(cinfo->regbase, CL_GRB, 0x20);
1649 else
1650 /* Graphics controller mode extensions: finer granularity,
1651 * 8byte data latches
1653 vga_wgfx(cinfo->regbase, CL_GRB, 0x28);
1655 vga_wgfx(cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */
1656 vga_wgfx(cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */
1657 vga_wgfx(cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */
1658 /* Background color byte 1: - */
1659 /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); */
1660 /* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
1662 /* Attribute Controller palette registers: "identity mapping" */
1663 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE0, 0x00);
1664 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
1665 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
1666 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
1667 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
1668 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
1669 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
1670 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
1671 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
1672 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
1673 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
1674 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
1675 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
1676 vga_wattr(cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
1677 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
1678 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
1680 /* Attribute Controller mode: graphics mode */
1681 vga_wattr(cinfo->regbase, VGA_ATC_MODE, 0x01);
1682 /* Overscan color reg.: reg. 0 */
1683 vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00);
1684 /* Color Plane enable: Enable all 4 planes */
1685 vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f);
1686 /* Color Select: - */
1687 vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00);
1689 WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
1691 /* BLT Start/status: Blitter reset */
1692 vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
1693 /* - " - : "end-of-reset" */
1694 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1696 /* misc... */
1697 WHDR(cinfo, 0); /* Hidden DAC register: - */
1698 return;
1701 static void switch_monitor(struct cirrusfb_info *cinfo, int on)
1703 #ifdef CONFIG_ZORRO /* only works on Zorro boards */
1704 static int IsOn = 0; /* XXX not ok for multiple boards */
1706 if (cinfo->btype == BT_PICASSO4)
1707 return; /* nothing to switch */
1708 if (cinfo->btype == BT_ALPINE)
1709 return; /* nothing to switch */
1710 if (cinfo->btype == BT_GD5480)
1711 return; /* nothing to switch */
1712 if (cinfo->btype == BT_PICASSO) {
1713 if ((on && !IsOn) || (!on && IsOn))
1714 WSFR(cinfo, 0xff);
1715 return;
1717 if (on) {
1718 switch (cinfo->btype) {
1719 case BT_SD64:
1720 WSFR(cinfo, cinfo->SFR | 0x21);
1721 break;
1722 case BT_PICCOLO:
1723 WSFR(cinfo, cinfo->SFR | 0x28);
1724 break;
1725 case BT_SPECTRUM:
1726 WSFR(cinfo, 0x6f);
1727 break;
1728 default: /* do nothing */ break;
1730 } else {
1731 switch (cinfo->btype) {
1732 case BT_SD64:
1733 WSFR(cinfo, cinfo->SFR & 0xde);
1734 break;
1735 case BT_PICCOLO:
1736 WSFR(cinfo, cinfo->SFR & 0xd7);
1737 break;
1738 case BT_SPECTRUM:
1739 WSFR(cinfo, 0x4f);
1740 break;
1741 default: /* do nothing */
1742 break;
1745 #endif /* CONFIG_ZORRO */
1748 /******************************************/
1749 /* Linux 2.6-style accelerated functions */
1750 /******************************************/
1752 static int cirrusfb_sync(struct fb_info *info)
1754 struct cirrusfb_info *cinfo = info->par;
1756 if (!is_laguna(cinfo)) {
1757 while (vga_rgfx(cinfo->regbase, CL_GR31) & 0x03)
1758 cpu_relax();
1760 return 0;
1763 static void cirrusfb_fillrect(struct fb_info *info,
1764 const struct fb_fillrect *region)
1766 struct fb_fillrect modded;
1767 int vxres, vyres;
1768 struct cirrusfb_info *cinfo = info->par;
1769 int m = info->var.bits_per_pixel;
1770 u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
1771 cinfo->pseudo_palette[region->color] : region->color;
1773 if (info->state != FBINFO_STATE_RUNNING)
1774 return;
1775 if (info->flags & FBINFO_HWACCEL_DISABLED) {
1776 cfb_fillrect(info, region);
1777 return;
1780 vxres = info->var.xres_virtual;
1781 vyres = info->var.yres_virtual;
1783 memcpy(&modded, region, sizeof(struct fb_fillrect));
1785 if (!modded.width || !modded.height ||
1786 modded.dx >= vxres || modded.dy >= vyres)
1787 return;
1789 if (modded.dx + modded.width > vxres)
1790 modded.width = vxres - modded.dx;
1791 if (modded.dy + modded.height > vyres)
1792 modded.height = vyres - modded.dy;
1794 cirrusfb_RectFill(cinfo->regbase,
1795 info->var.bits_per_pixel,
1796 (region->dx * m) / 8, region->dy,
1797 (region->width * m) / 8, region->height,
1798 color, color,
1799 info->fix.line_length, 0x40);
1802 static void cirrusfb_copyarea(struct fb_info *info,
1803 const struct fb_copyarea *area)
1805 struct fb_copyarea modded;
1806 u32 vxres, vyres;
1807 struct cirrusfb_info *cinfo = info->par;
1808 int m = info->var.bits_per_pixel;
1810 if (info->state != FBINFO_STATE_RUNNING)
1811 return;
1812 if (info->flags & FBINFO_HWACCEL_DISABLED) {
1813 cfb_copyarea(info, area);
1814 return;
1817 vxres = info->var.xres_virtual;
1818 vyres = info->var.yres_virtual;
1819 memcpy(&modded, area, sizeof(struct fb_copyarea));
1821 if (!modded.width || !modded.height ||
1822 modded.sx >= vxres || modded.sy >= vyres ||
1823 modded.dx >= vxres || modded.dy >= vyres)
1824 return;
1826 if (modded.sx + modded.width > vxres)
1827 modded.width = vxres - modded.sx;
1828 if (modded.dx + modded.width > vxres)
1829 modded.width = vxres - modded.dx;
1830 if (modded.sy + modded.height > vyres)
1831 modded.height = vyres - modded.sy;
1832 if (modded.dy + modded.height > vyres)
1833 modded.height = vyres - modded.dy;
1835 cirrusfb_BitBLT(cinfo->regbase, info->var.bits_per_pixel,
1836 (area->sx * m) / 8, area->sy,
1837 (area->dx * m) / 8, area->dy,
1838 (area->width * m) / 8, area->height,
1839 info->fix.line_length);
1843 static void cirrusfb_imageblit(struct fb_info *info,
1844 const struct fb_image *image)
1846 struct cirrusfb_info *cinfo = info->par;
1847 unsigned char op = (info->var.bits_per_pixel == 24) ? 0xc : 0x4;
1849 if (info->state != FBINFO_STATE_RUNNING)
1850 return;
1851 /* Alpine acceleration does not work at 24bpp ?!? */
1852 if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1 ||
1853 (cinfo->btype == BT_ALPINE && op == 0xc))
1854 cfb_imageblit(info, image);
1855 else {
1856 unsigned size = ((image->width + 7) >> 3) * image->height;
1857 int m = info->var.bits_per_pixel;
1858 u32 fg, bg;
1860 if (info->var.bits_per_pixel == 8) {
1861 fg = image->fg_color;
1862 bg = image->bg_color;
1863 } else {
1864 fg = ((u32 *)(info->pseudo_palette))[image->fg_color];
1865 bg = ((u32 *)(info->pseudo_palette))[image->bg_color];
1867 if (info->var.bits_per_pixel == 24) {
1868 /* clear background first */
1869 cirrusfb_RectFill(cinfo->regbase,
1870 info->var.bits_per_pixel,
1871 (image->dx * m) / 8, image->dy,
1872 (image->width * m) / 8,
1873 image->height,
1874 bg, bg,
1875 info->fix.line_length, 0x40);
1877 cirrusfb_RectFill(cinfo->regbase,
1878 info->var.bits_per_pixel,
1879 (image->dx * m) / 8, image->dy,
1880 (image->width * m) / 8, image->height,
1881 fg, bg,
1882 info->fix.line_length, op);
1883 memcpy(info->screen_base, image->data, size);
1887 #ifdef CONFIG_PPC_PREP
1888 #define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
1889 #define PREP_IO_BASE ((volatile unsigned char *) 0x80000000)
1890 static void get_prep_addrs(unsigned long *display, unsigned long *registers)
1892 *display = PREP_VIDEO_BASE;
1893 *registers = (unsigned long) PREP_IO_BASE;
1896 #endif /* CONFIG_PPC_PREP */
1898 #ifdef CONFIG_PCI
1899 static int release_io_ports;
1901 /* Pulled the logic from XFree86 Cirrus driver to get the memory size,
1902 * based on the DRAM bandwidth bit and DRAM bank switching bit. This
1903 * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
1904 * seem to have. */
1905 static unsigned int __devinit cirrusfb_get_memsize(struct fb_info *info,
1906 u8 __iomem *regbase)
1908 unsigned long mem;
1909 struct cirrusfb_info *cinfo = info->par;
1911 if (is_laguna(cinfo)) {
1912 unsigned char SR14 = vga_rseq(regbase, CL_SEQR14);
1914 mem = ((SR14 & 7) + 1) << 20;
1915 } else {
1916 unsigned char SRF = vga_rseq(regbase, CL_SEQRF);
1917 switch ((SRF & 0x18)) {
1918 case 0x08:
1919 mem = 512 * 1024;
1920 break;
1921 case 0x10:
1922 mem = 1024 * 1024;
1923 break;
1924 /* 64-bit DRAM data bus width; assume 2MB.
1925 * Also indicates 2MB memory on the 5430.
1927 case 0x18:
1928 mem = 2048 * 1024;
1929 break;
1930 default:
1931 dev_warn(info->device, "Unknown memory size!\n");
1932 mem = 1024 * 1024;
1934 /* If DRAM bank switching is enabled, there must be
1935 * twice as much memory installed. (4MB on the 5434)
1937 if (SRF & 0x80)
1938 mem *= 2;
1941 /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
1942 return mem;
1945 static void get_pci_addrs(const struct pci_dev *pdev,
1946 unsigned long *display, unsigned long *registers)
1948 assert(pdev != NULL);
1949 assert(display != NULL);
1950 assert(registers != NULL);
1952 *display = 0;
1953 *registers = 0;
1955 /* This is a best-guess for now */
1957 if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
1958 *display = pci_resource_start(pdev, 1);
1959 *registers = pci_resource_start(pdev, 0);
1960 } else {
1961 *display = pci_resource_start(pdev, 0);
1962 *registers = pci_resource_start(pdev, 1);
1965 assert(*display != 0);
1968 static void cirrusfb_pci_unmap(struct fb_info *info)
1970 struct pci_dev *pdev = to_pci_dev(info->device);
1971 struct cirrusfb_info *cinfo = info->par;
1973 if (cinfo->laguna_mmio == NULL)
1974 iounmap(cinfo->laguna_mmio);
1975 iounmap(info->screen_base);
1976 #if 0 /* if system didn't claim this region, we would... */
1977 release_mem_region(0xA0000, 65535);
1978 #endif
1979 if (release_io_ports)
1980 release_region(0x3C0, 32);
1981 pci_release_regions(pdev);
1983 #endif /* CONFIG_PCI */
1985 #ifdef CONFIG_ZORRO
1986 static void cirrusfb_zorro_unmap(struct fb_info *info)
1988 struct cirrusfb_info *cinfo = info->par;
1989 struct zorro_dev *zdev = to_zorro_dev(info->device);
1991 zorro_release_device(zdev);
1993 if (cinfo->btype == BT_PICASSO4) {
1994 cinfo->regbase -= 0x600000;
1995 iounmap((void *)cinfo->regbase);
1996 iounmap(info->screen_base);
1997 } else {
1998 if (zorro_resource_start(zdev) > 0x01000000)
1999 iounmap(info->screen_base);
2002 #endif /* CONFIG_ZORRO */
2004 /* function table of the above functions */
2005 static struct fb_ops cirrusfb_ops = {
2006 .owner = THIS_MODULE,
2007 .fb_open = cirrusfb_open,
2008 .fb_release = cirrusfb_release,
2009 .fb_setcolreg = cirrusfb_setcolreg,
2010 .fb_check_var = cirrusfb_check_var,
2011 .fb_set_par = cirrusfb_set_par,
2012 .fb_pan_display = cirrusfb_pan_display,
2013 .fb_blank = cirrusfb_blank,
2014 .fb_fillrect = cirrusfb_fillrect,
2015 .fb_copyarea = cirrusfb_copyarea,
2016 .fb_sync = cirrusfb_sync,
2017 .fb_imageblit = cirrusfb_imageblit,
2020 static int __devinit cirrusfb_set_fbinfo(struct fb_info *info)
2022 struct cirrusfb_info *cinfo = info->par;
2023 struct fb_var_screeninfo *var = &info->var;
2025 info->pseudo_palette = cinfo->pseudo_palette;
2026 info->flags = FBINFO_DEFAULT
2027 | FBINFO_HWACCEL_XPAN
2028 | FBINFO_HWACCEL_YPAN
2029 | FBINFO_HWACCEL_FILLRECT
2030 | FBINFO_HWACCEL_IMAGEBLIT
2031 | FBINFO_HWACCEL_COPYAREA;
2032 if (noaccel || is_laguna(cinfo))
2033 info->flags |= FBINFO_HWACCEL_DISABLED;
2034 info->fbops = &cirrusfb_ops;
2036 if (cinfo->btype == BT_GD5480) {
2037 if (var->bits_per_pixel == 16)
2038 info->screen_base += 1 * MB_;
2039 if (var->bits_per_pixel == 32)
2040 info->screen_base += 2 * MB_;
2043 /* Fill fix common fields */
2044 strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
2045 sizeof(info->fix.id));
2047 /* monochrome: only 1 memory plane */
2048 /* 8 bit and above: Use whole memory area */
2049 info->fix.smem_len = info->screen_size;
2050 if (var->bits_per_pixel == 1)
2051 info->fix.smem_len /= 4;
2052 info->fix.type_aux = 0;
2053 info->fix.xpanstep = 1;
2054 info->fix.ypanstep = 1;
2055 info->fix.ywrapstep = 0;
2057 /* FIXME: map region at 0xB8000 if available, fill in here */
2058 info->fix.mmio_len = 0;
2059 info->fix.accel = FB_ACCEL_NONE;
2061 fb_alloc_cmap(&info->cmap, 256, 0);
2063 return 0;
2066 static int __devinit cirrusfb_register(struct fb_info *info)
2068 struct cirrusfb_info *cinfo = info->par;
2069 int err;
2071 /* sanity checks */
2072 assert(cinfo->btype != BT_NONE);
2074 /* set all the vital stuff */
2075 cirrusfb_set_fbinfo(info);
2077 dev_dbg(info->device, "(RAM start set to: 0x%p)\n", info->screen_base);
2079 err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
2080 if (!err) {
2081 dev_dbg(info->device, "wrong initial video mode\n");
2082 err = -EINVAL;
2083 goto err_dealloc_cmap;
2086 info->var.activate = FB_ACTIVATE_NOW;
2088 err = cirrusfb_check_var(&info->var, info);
2089 if (err < 0) {
2090 /* should never happen */
2091 dev_dbg(info->device,
2092 "choking on default var... umm, no good.\n");
2093 goto err_dealloc_cmap;
2096 err = register_framebuffer(info);
2097 if (err < 0) {
2098 dev_err(info->device,
2099 "could not register fb device; err = %d!\n", err);
2100 goto err_dealloc_cmap;
2103 return 0;
2105 err_dealloc_cmap:
2106 fb_dealloc_cmap(&info->cmap);
2107 return err;
2110 static void __devexit cirrusfb_cleanup(struct fb_info *info)
2112 struct cirrusfb_info *cinfo = info->par;
2114 switch_monitor(cinfo, 0);
2115 unregister_framebuffer(info);
2116 fb_dealloc_cmap(&info->cmap);
2117 dev_dbg(info->device, "Framebuffer unregistered\n");
2118 cinfo->unmap(info);
2119 framebuffer_release(info);
2122 #ifdef CONFIG_PCI
2123 static int __devinit cirrusfb_pci_register(struct pci_dev *pdev,
2124 const struct pci_device_id *ent)
2126 struct cirrusfb_info *cinfo;
2127 struct fb_info *info;
2128 unsigned long board_addr, board_size;
2129 int ret;
2131 ret = pci_enable_device(pdev);
2132 if (ret < 0) {
2133 printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
2134 goto err_out;
2137 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev);
2138 if (!info) {
2139 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2140 ret = -ENOMEM;
2141 goto err_out;
2144 cinfo = info->par;
2145 cinfo->btype = (enum cirrus_board) ent->driver_data;
2147 dev_dbg(info->device,
2148 " Found PCI device, base address 0 is 0x%Lx, btype set to %d\n",
2149 (unsigned long long)pdev->resource[0].start, cinfo->btype);
2150 dev_dbg(info->device, " base address 1 is 0x%Lx\n",
2151 (unsigned long long)pdev->resource[1].start);
2153 if (isPReP) {
2154 pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, 0x00000000);
2155 #ifdef CONFIG_PPC_PREP
2156 get_prep_addrs(&board_addr, &info->fix.mmio_start);
2157 #endif
2158 /* PReP dies if we ioremap the IO registers, but it works w/out... */
2159 cinfo->regbase = (char __iomem *) info->fix.mmio_start;
2160 } else {
2161 dev_dbg(info->device,
2162 "Attempt to get PCI info for Cirrus Graphics Card\n");
2163 get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start);
2164 /* FIXME: this forces VGA. alternatives? */
2165 cinfo->regbase = NULL;
2166 cinfo->laguna_mmio = ioremap(info->fix.mmio_start, 0x1000);
2169 dev_dbg(info->device, "Board address: 0x%lx, register address: 0x%lx\n",
2170 board_addr, info->fix.mmio_start);
2172 board_size = (cinfo->btype == BT_GD5480) ?
2173 32 * MB_ : cirrusfb_get_memsize(info, cinfo->regbase);
2175 ret = pci_request_regions(pdev, "cirrusfb");
2176 if (ret < 0) {
2177 dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
2178 board_addr);
2179 goto err_release_fb;
2181 #if 0 /* if the system didn't claim this region, we would... */
2182 if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
2183 dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
2184 0xA0000L);
2185 ret = -EBUSY;
2186 goto err_release_regions;
2188 #endif
2189 if (request_region(0x3C0, 32, "cirrusfb"))
2190 release_io_ports = 1;
2192 info->screen_base = ioremap(board_addr, board_size);
2193 if (!info->screen_base) {
2194 ret = -EIO;
2195 goto err_release_legacy;
2198 info->fix.smem_start = board_addr;
2199 info->screen_size = board_size;
2200 cinfo->unmap = cirrusfb_pci_unmap;
2202 dev_info(info->device,
2203 "Cirrus Logic chipset on PCI bus, RAM (%lu kB) at 0x%lx\n",
2204 info->screen_size >> 10, board_addr);
2205 pci_set_drvdata(pdev, info);
2207 ret = cirrusfb_register(info);
2208 if (!ret)
2209 return 0;
2211 pci_set_drvdata(pdev, NULL);
2212 iounmap(info->screen_base);
2213 err_release_legacy:
2214 if (release_io_ports)
2215 release_region(0x3C0, 32);
2216 #if 0
2217 release_mem_region(0xA0000, 65535);
2218 err_release_regions:
2219 #endif
2220 pci_release_regions(pdev);
2221 err_release_fb:
2222 if (cinfo->laguna_mmio != NULL)
2223 iounmap(cinfo->laguna_mmio);
2224 framebuffer_release(info);
2225 err_out:
2226 return ret;
2229 static void __devexit cirrusfb_pci_unregister(struct pci_dev *pdev)
2231 struct fb_info *info = pci_get_drvdata(pdev);
2233 cirrusfb_cleanup(info);
2236 static struct pci_driver cirrusfb_pci_driver = {
2237 .name = "cirrusfb",
2238 .id_table = cirrusfb_pci_table,
2239 .probe = cirrusfb_pci_register,
2240 .remove = __devexit_p(cirrusfb_pci_unregister),
2241 #ifdef CONFIG_PM
2242 #if 0
2243 .suspend = cirrusfb_pci_suspend,
2244 .resume = cirrusfb_pci_resume,
2245 #endif
2246 #endif
2248 #endif /* CONFIG_PCI */
2250 #ifdef CONFIG_ZORRO
2251 static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
2252 const struct zorro_device_id *ent)
2254 struct cirrusfb_info *cinfo;
2255 struct fb_info *info;
2256 enum cirrus_board btype;
2257 struct zorro_dev *z2 = NULL;
2258 unsigned long board_addr, board_size, size;
2259 int ret;
2261 btype = ent->driver_data;
2262 if (cirrusfb_zorro_table2[btype].id2)
2263 z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
2264 size = cirrusfb_zorro_table2[btype].size;
2266 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
2267 if (!info) {
2268 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2269 ret = -ENOMEM;
2270 goto err_out;
2273 dev_info(info->device, "%s board detected\n",
2274 cirrusfb_board_info[btype].name);
2276 cinfo = info->par;
2277 cinfo->btype = btype;
2279 assert(z);
2280 assert(btype != BT_NONE);
2282 board_addr = zorro_resource_start(z);
2283 board_size = zorro_resource_len(z);
2284 info->screen_size = size;
2286 if (!zorro_request_device(z, "cirrusfb")) {
2287 dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
2288 board_addr);
2289 ret = -EBUSY;
2290 goto err_release_fb;
2293 ret = -EIO;
2295 if (btype == BT_PICASSO4) {
2296 dev_info(info->device, " REG at $%lx\n", board_addr + 0x600000);
2298 /* To be precise, for the P4 this is not the */
2299 /* begin of the board, but the begin of RAM. */
2300 /* for P4, map in its address space in 2 chunks (### TEST! ) */
2301 /* (note the ugly hardcoded 16M number) */
2302 cinfo->regbase = ioremap(board_addr, 16777216);
2303 if (!cinfo->regbase)
2304 goto err_release_region;
2306 dev_dbg(info->device, "Virtual address for board set to: $%p\n",
2307 cinfo->regbase);
2308 cinfo->regbase += 0x600000;
2309 info->fix.mmio_start = board_addr + 0x600000;
2311 info->fix.smem_start = board_addr + 16777216;
2312 info->screen_base = ioremap(info->fix.smem_start, 16777216);
2313 if (!info->screen_base)
2314 goto err_unmap_regbase;
2315 } else {
2316 dev_info(info->device, " REG at $%lx\n",
2317 (unsigned long) z2->resource.start);
2319 info->fix.smem_start = board_addr;
2320 if (board_addr > 0x01000000)
2321 info->screen_base = ioremap(board_addr, board_size);
2322 else
2323 info->screen_base = (caddr_t) ZTWO_VADDR(board_addr);
2324 if (!info->screen_base)
2325 goto err_release_region;
2327 /* set address for REG area of board */
2328 cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start);
2329 info->fix.mmio_start = z2->resource.start;
2331 dev_dbg(info->device, "Virtual address for board set to: $%p\n",
2332 cinfo->regbase);
2334 cinfo->unmap = cirrusfb_zorro_unmap;
2336 dev_info(info->device,
2337 "Cirrus Logic chipset on Zorro bus, RAM (%lu MB) at $%lx\n",
2338 board_size / MB_, board_addr);
2340 zorro_set_drvdata(z, info);
2342 ret = cirrusfb_register(info);
2343 if (!ret)
2344 return 0;
2346 if (btype == BT_PICASSO4 || board_addr > 0x01000000)
2347 iounmap(info->screen_base);
2349 err_unmap_regbase:
2350 if (btype == BT_PICASSO4)
2351 iounmap(cinfo->regbase - 0x600000);
2352 err_release_region:
2353 release_region(board_addr, board_size);
2354 err_release_fb:
2355 framebuffer_release(info);
2356 err_out:
2357 return ret;
2360 void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
2362 struct fb_info *info = zorro_get_drvdata(z);
2364 cirrusfb_cleanup(info);
2367 static struct zorro_driver cirrusfb_zorro_driver = {
2368 .name = "cirrusfb",
2369 .id_table = cirrusfb_zorro_table,
2370 .probe = cirrusfb_zorro_register,
2371 .remove = __devexit_p(cirrusfb_zorro_unregister),
2373 #endif /* CONFIG_ZORRO */
2375 #ifndef MODULE
2376 static int __init cirrusfb_setup(char *options)
2378 char *this_opt;
2380 if (!options || !*options)
2381 return 0;
2383 while ((this_opt = strsep(&options, ",")) != NULL) {
2384 if (!*this_opt)
2385 continue;
2387 if (!strcmp(this_opt, "noaccel"))
2388 noaccel = 1;
2389 else if (!strncmp(this_opt, "mode:", 5))
2390 mode_option = this_opt + 5;
2391 else
2392 mode_option = this_opt;
2394 return 0;
2396 #endif
2399 * Modularization
2402 MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
2403 MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
2404 MODULE_LICENSE("GPL");
2406 static int __init cirrusfb_init(void)
2408 int error = 0;
2410 #ifndef MODULE
2411 char *option = NULL;
2413 if (fb_get_options("cirrusfb", &option))
2414 return -ENODEV;
2415 cirrusfb_setup(option);
2416 #endif
2418 #ifdef CONFIG_ZORRO
2419 error |= zorro_register_driver(&cirrusfb_zorro_driver);
2420 #endif
2421 #ifdef CONFIG_PCI
2422 error |= pci_register_driver(&cirrusfb_pci_driver);
2423 #endif
2424 return error;
2427 static void __exit cirrusfb_exit(void)
2429 #ifdef CONFIG_PCI
2430 pci_unregister_driver(&cirrusfb_pci_driver);
2431 #endif
2432 #ifdef CONFIG_ZORRO
2433 zorro_unregister_driver(&cirrusfb_zorro_driver);
2434 #endif
2437 module_init(cirrusfb_init);
2439 module_param(mode_option, charp, 0);
2440 MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
2441 module_param(noaccel, bool, 0);
2442 MODULE_PARM_DESC(noaccel, "Disable acceleration");
2444 #ifdef MODULE
2445 module_exit(cirrusfb_exit);
2446 #endif
2448 /**********************************************************************/
2449 /* about the following functions - I have used the same names for the */
2450 /* functions as Markus Wild did in his Retina driver for NetBSD as */
2451 /* they just made sense for this purpose. Apart from that, I wrote */
2452 /* these functions myself. */
2453 /**********************************************************************/
2455 /*** WGen() - write into one of the external/general registers ***/
2456 static void WGen(const struct cirrusfb_info *cinfo,
2457 int regnum, unsigned char val)
2459 unsigned long regofs = 0;
2461 if (cinfo->btype == BT_PICASSO) {
2462 /* Picasso II specific hack */
2463 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2464 regnum == CL_VSSM2) */
2465 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2466 regofs = 0xfff;
2469 vga_w(cinfo->regbase, regofs + regnum, val);
2472 /*** RGen() - read out one of the external/general registers ***/
2473 static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum)
2475 unsigned long regofs = 0;
2477 if (cinfo->btype == BT_PICASSO) {
2478 /* Picasso II specific hack */
2479 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2480 regnum == CL_VSSM2) */
2481 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2482 regofs = 0xfff;
2485 return vga_r(cinfo->regbase, regofs + regnum);
2488 /*** AttrOn() - turn on VideoEnable for Attribute controller ***/
2489 static void AttrOn(const struct cirrusfb_info *cinfo)
2491 assert(cinfo != NULL);
2493 if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) {
2494 /* if we're just in "write value" mode, write back the */
2495 /* same value as before to not modify anything */
2496 vga_w(cinfo->regbase, VGA_ATT_IW,
2497 vga_r(cinfo->regbase, VGA_ATT_R));
2499 /* turn on video bit */
2500 /* vga_w(cinfo->regbase, VGA_ATT_IW, 0x20); */
2501 vga_w(cinfo->regbase, VGA_ATT_IW, 0x33);
2503 /* dummy write on Reg0 to be on "write index" mode next time */
2504 vga_w(cinfo->regbase, VGA_ATT_IW, 0x00);
2507 /*** WHDR() - write into the Hidden DAC register ***/
2508 /* as the HDR is the only extension register that requires special treatment
2509 * (the other extension registers are accessible just like the "ordinary"
2510 * registers of their functional group) here is a specialized routine for
2511 * accessing the HDR
2513 static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val)
2515 unsigned char dummy;
2517 if (is_laguna(cinfo))
2518 return;
2519 if (cinfo->btype == BT_PICASSO) {
2520 /* Klaus' hint for correct access to HDR on some boards */
2521 /* first write 0 to pixel mask (3c6) */
2522 WGen(cinfo, VGA_PEL_MSK, 0x00);
2523 udelay(200);
2524 /* next read dummy from pixel address (3c8) */
2525 dummy = RGen(cinfo, VGA_PEL_IW);
2526 udelay(200);
2528 /* now do the usual stuff to access the HDR */
2530 dummy = RGen(cinfo, VGA_PEL_MSK);
2531 udelay(200);
2532 dummy = RGen(cinfo, VGA_PEL_MSK);
2533 udelay(200);
2534 dummy = RGen(cinfo, VGA_PEL_MSK);
2535 udelay(200);
2536 dummy = RGen(cinfo, VGA_PEL_MSK);
2537 udelay(200);
2539 WGen(cinfo, VGA_PEL_MSK, val);
2540 udelay(200);
2542 if (cinfo->btype == BT_PICASSO) {
2543 /* now first reset HDR access counter */
2544 dummy = RGen(cinfo, VGA_PEL_IW);
2545 udelay(200);
2547 /* and at the end, restore the mask value */
2548 /* ## is this mask always 0xff? */
2549 WGen(cinfo, VGA_PEL_MSK, 0xff);
2550 udelay(200);
2554 /*** WSFR() - write to the "special function register" (SFR) ***/
2555 static void WSFR(struct cirrusfb_info *cinfo, unsigned char val)
2557 #ifdef CONFIG_ZORRO
2558 assert(cinfo->regbase != NULL);
2559 cinfo->SFR = val;
2560 z_writeb(val, cinfo->regbase + 0x8000);
2561 #endif
2564 /* The Picasso has a second register for switching the monitor bit */
2565 static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val)
2567 #ifdef CONFIG_ZORRO
2568 /* writing an arbitrary value to this one causes the monitor switcher */
2569 /* to flip to Amiga display */
2570 assert(cinfo->regbase != NULL);
2571 cinfo->SFR = val;
2572 z_writeb(val, cinfo->regbase + 0x9000);
2573 #endif
2576 /*** WClut - set CLUT entry (range: 0..63) ***/
2577 static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
2578 unsigned char green, unsigned char blue)
2580 unsigned int data = VGA_PEL_D;
2582 /* address write mode register is not translated.. */
2583 vga_w(cinfo->regbase, VGA_PEL_IW, regnum);
2585 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2586 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480 ||
2587 is_laguna(cinfo)) {
2588 /* but DAC data register IS, at least for Picasso II */
2589 if (cinfo->btype == BT_PICASSO)
2590 data += 0xfff;
2591 vga_w(cinfo->regbase, data, red);
2592 vga_w(cinfo->regbase, data, green);
2593 vga_w(cinfo->regbase, data, blue);
2594 } else {
2595 vga_w(cinfo->regbase, data, blue);
2596 vga_w(cinfo->regbase, data, green);
2597 vga_w(cinfo->regbase, data, red);
2601 #if 0
2602 /*** RClut - read CLUT entry (range 0..63) ***/
2603 static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
2604 unsigned char *green, unsigned char *blue)
2606 unsigned int data = VGA_PEL_D;
2608 vga_w(cinfo->regbase, VGA_PEL_IR, regnum);
2610 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2611 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2612 if (cinfo->btype == BT_PICASSO)
2613 data += 0xfff;
2614 *red = vga_r(cinfo->regbase, data);
2615 *green = vga_r(cinfo->regbase, data);
2616 *blue = vga_r(cinfo->regbase, data);
2617 } else {
2618 *blue = vga_r(cinfo->regbase, data);
2619 *green = vga_r(cinfo->regbase, data);
2620 *red = vga_r(cinfo->regbase, data);
2623 #endif
2625 /*******************************************************************
2626 cirrusfb_WaitBLT()
2628 Wait for the BitBLT engine to complete a possible earlier job
2629 *********************************************************************/
2631 /* FIXME: use interrupts instead */
2632 static void cirrusfb_WaitBLT(u8 __iomem *regbase)
2634 while (vga_rgfx(regbase, CL_GR31) & 0x08)
2635 cpu_relax();
2638 /*******************************************************************
2639 cirrusfb_BitBLT()
2641 perform accelerated "scrolling"
2642 ********************************************************************/
2644 static void cirrusfb_set_blitter(u8 __iomem *regbase,
2645 u_short nwidth, u_short nheight,
2646 u_long nsrc, u_long ndest,
2647 u_short bltmode, u_short line_length)
2650 /* pitch: set to line_length */
2651 /* dest pitch low */
2652 vga_wgfx(regbase, CL_GR24, line_length & 0xff);
2653 /* dest pitch hi */
2654 vga_wgfx(regbase, CL_GR25, line_length >> 8);
2655 /* source pitch low */
2656 vga_wgfx(regbase, CL_GR26, line_length & 0xff);
2657 /* source pitch hi */
2658 vga_wgfx(regbase, CL_GR27, line_length >> 8);
2660 /* BLT width: actual number of pixels - 1 */
2661 /* BLT width low */
2662 vga_wgfx(regbase, CL_GR20, nwidth & 0xff);
2663 /* BLT width hi */
2664 vga_wgfx(regbase, CL_GR21, nwidth >> 8);
2666 /* BLT height: actual number of lines -1 */
2667 /* BLT height low */
2668 vga_wgfx(regbase, CL_GR22, nheight & 0xff);
2669 /* BLT width hi */
2670 vga_wgfx(regbase, CL_GR23, nheight >> 8);
2672 /* BLT destination */
2673 /* BLT dest low */
2674 vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
2675 /* BLT dest mid */
2676 vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
2677 /* BLT dest hi */
2678 vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
2680 /* BLT source */
2681 /* BLT src low */
2682 vga_wgfx(regbase, CL_GR2C, (u_char) (nsrc & 0xff));
2683 /* BLT src mid */
2684 vga_wgfx(regbase, CL_GR2D, (u_char) (nsrc >> 8));
2685 /* BLT src hi */
2686 vga_wgfx(regbase, CL_GR2E, (u_char) (nsrc >> 16));
2688 /* BLT mode */
2689 vga_wgfx(regbase, CL_GR30, bltmode); /* BLT mode */
2691 /* BLT ROP: SrcCopy */
2692 vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */
2694 /* and finally: GO! */
2695 vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */
2698 /*******************************************************************
2699 cirrusfb_BitBLT()
2701 perform accelerated "scrolling"
2702 ********************************************************************/
2704 static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
2705 u_short curx, u_short cury,
2706 u_short destx, u_short desty,
2707 u_short width, u_short height,
2708 u_short line_length)
2710 u_short nwidth = width - 1;
2711 u_short nheight = height - 1;
2712 u_long nsrc, ndest;
2713 u_char bltmode;
2715 bltmode = 0x00;
2716 /* if source adr < dest addr, do the Blt backwards */
2717 if (cury <= desty) {
2718 if (cury == desty) {
2719 /* if src and dest are on the same line, check x */
2720 if (curx < destx)
2721 bltmode |= 0x01;
2722 } else
2723 bltmode |= 0x01;
2725 /* standard case: forward blitting */
2726 nsrc = (cury * line_length) + curx;
2727 ndest = (desty * line_length) + destx;
2728 if (bltmode) {
2729 /* this means start addresses are at the end,
2730 * counting backwards
2732 nsrc += nheight * line_length + nwidth;
2733 ndest += nheight * line_length + nwidth;
2736 cirrusfb_WaitBLT(regbase);
2738 cirrusfb_set_blitter(regbase, nwidth, nheight,
2739 nsrc, ndest, bltmode, line_length);
2742 /*******************************************************************
2743 cirrusfb_RectFill()
2745 perform accelerated rectangle fill
2746 ********************************************************************/
2748 static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
2749 u_short x, u_short y, u_short width, u_short height,
2750 u32 fg_color, u32 bg_color, u_short line_length,
2751 u_char blitmode)
2753 u_long ndest = (y * line_length) + x;
2754 u_char op;
2756 cirrusfb_WaitBLT(regbase);
2758 /* This is a ColorExpand Blt, using the */
2759 /* same color for foreground and background */
2760 vga_wgfx(regbase, VGA_GFX_SR_VALUE, bg_color);
2761 vga_wgfx(regbase, VGA_GFX_SR_ENABLE, fg_color);
2763 op = 0x80;
2764 if (bits_per_pixel >= 16) {
2765 vga_wgfx(regbase, CL_GR10, bg_color >> 8);
2766 vga_wgfx(regbase, CL_GR11, fg_color >> 8);
2767 op = 0x90;
2769 if (bits_per_pixel >= 24) {
2770 vga_wgfx(regbase, CL_GR12, bg_color >> 16);
2771 vga_wgfx(regbase, CL_GR13, fg_color >> 16);
2772 op = 0xa0;
2774 if (bits_per_pixel == 32) {
2775 vga_wgfx(regbase, CL_GR14, bg_color >> 24);
2776 vga_wgfx(regbase, CL_GR15, fg_color >> 24);
2777 op = 0xb0;
2779 cirrusfb_set_blitter(regbase, width - 1, height - 1,
2780 0, ndest, op | blitmode, line_length);
2783 /**************************************************************************
2784 * bestclock() - determine closest possible clock lower(?) than the
2785 * desired pixel clock
2786 **************************************************************************/
2787 static void bestclock(long freq, int *nom, int *den, int *div)
2789 int n, d;
2790 long h, diff;
2792 assert(nom != NULL);
2793 assert(den != NULL);
2794 assert(div != NULL);
2796 *nom = 0;
2797 *den = 0;
2798 *div = 0;
2800 if (freq < 8000)
2801 freq = 8000;
2803 diff = freq;
2805 for (n = 32; n < 128; n++) {
2806 int s = 0;
2808 d = (14318 * n) / freq;
2809 if ((d >= 7) && (d <= 63)) {
2810 int temp = d;
2812 if (temp > 31) {
2813 s = 1;
2814 temp >>= 1;
2816 h = ((14318 * n) / temp) >> s;
2817 h = h > freq ? h - freq : freq - h;
2818 if (h < diff) {
2819 diff = h;
2820 *nom = n;
2821 *den = temp;
2822 *div = s;
2825 d++;
2826 if ((d >= 7) && (d <= 63)) {
2827 if (d > 31) {
2828 s = 1;
2829 d >>= 1;
2831 h = ((14318 * n) / d) >> s;
2832 h = h > freq ? h - freq : freq - h;
2833 if (h < diff) {
2834 diff = h;
2835 *nom = n;
2836 *den = d;
2837 *div = s;
2843 /* -------------------------------------------------------------------------
2845 * debugging functions
2847 * -------------------------------------------------------------------------
2850 #ifdef CIRRUSFB_DEBUG
2853 * cirrusfb_dbg_print_regs
2854 * @base: If using newmmio, the newmmio base address, otherwise %NULL
2855 * @reg_class: type of registers to read: %CRT, or %SEQ
2857 * DESCRIPTION:
2858 * Dumps the given list of VGA CRTC registers. If @base is %NULL,
2859 * old-style I/O ports are queried for information, otherwise MMIO is
2860 * used at the given @base address to query the information.
2863 static void cirrusfb_dbg_print_regs(struct fb_info *info,
2864 caddr_t regbase,
2865 enum cirrusfb_dbg_reg_class reg_class, ...)
2867 va_list list;
2868 unsigned char val = 0;
2869 unsigned reg;
2870 char *name;
2872 va_start(list, reg_class);
2874 name = va_arg(list, char *);
2875 while (name != NULL) {
2876 reg = va_arg(list, int);
2878 switch (reg_class) {
2879 case CRT:
2880 val = vga_rcrt(regbase, (unsigned char) reg);
2881 break;
2882 case SEQ:
2883 val = vga_rseq(regbase, (unsigned char) reg);
2884 break;
2885 default:
2886 /* should never occur */
2887 assert(false);
2888 break;
2891 dev_dbg(info->device, "%8s = 0x%02X\n", name, val);
2893 name = va_arg(list, char *);
2896 va_end(list);
2900 * cirrusfb_dbg_reg_dump
2901 * @base: If using newmmio, the newmmio base address, otherwise %NULL
2903 * DESCRIPTION:
2904 * Dumps a list of interesting VGA and CIRRUSFB registers. If @base is %NULL,
2905 * old-style I/O ports are queried for information, otherwise MMIO is
2906 * used at the given @base address to query the information.
2909 static void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase)
2911 dev_dbg(info->device, "VGA CRTC register dump:\n");
2913 cirrusfb_dbg_print_regs(info, regbase, CRT,
2914 "CR00", 0x00,
2915 "CR01", 0x01,
2916 "CR02", 0x02,
2917 "CR03", 0x03,
2918 "CR04", 0x04,
2919 "CR05", 0x05,
2920 "CR06", 0x06,
2921 "CR07", 0x07,
2922 "CR08", 0x08,
2923 "CR09", 0x09,
2924 "CR0A", 0x0A,
2925 "CR0B", 0x0B,
2926 "CR0C", 0x0C,
2927 "CR0D", 0x0D,
2928 "CR0E", 0x0E,
2929 "CR0F", 0x0F,
2930 "CR10", 0x10,
2931 "CR11", 0x11,
2932 "CR12", 0x12,
2933 "CR13", 0x13,
2934 "CR14", 0x14,
2935 "CR15", 0x15,
2936 "CR16", 0x16,
2937 "CR17", 0x17,
2938 "CR18", 0x18,
2939 "CR22", 0x22,
2940 "CR24", 0x24,
2941 "CR26", 0x26,
2942 "CR2D", 0x2D,
2943 "CR2E", 0x2E,
2944 "CR2F", 0x2F,
2945 "CR30", 0x30,
2946 "CR31", 0x31,
2947 "CR32", 0x32,
2948 "CR33", 0x33,
2949 "CR34", 0x34,
2950 "CR35", 0x35,
2951 "CR36", 0x36,
2952 "CR37", 0x37,
2953 "CR38", 0x38,
2954 "CR39", 0x39,
2955 "CR3A", 0x3A,
2956 "CR3B", 0x3B,
2957 "CR3C", 0x3C,
2958 "CR3D", 0x3D,
2959 "CR3E", 0x3E,
2960 "CR3F", 0x3F,
2961 NULL);
2963 dev_dbg(info->device, "\n");
2965 dev_dbg(info->device, "VGA SEQ register dump:\n");
2967 cirrusfb_dbg_print_regs(info, regbase, SEQ,
2968 "SR00", 0x00,
2969 "SR01", 0x01,
2970 "SR02", 0x02,
2971 "SR03", 0x03,
2972 "SR04", 0x04,
2973 "SR08", 0x08,
2974 "SR09", 0x09,
2975 "SR0A", 0x0A,
2976 "SR0B", 0x0B,
2977 "SR0D", 0x0D,
2978 "SR10", 0x10,
2979 "SR11", 0x11,
2980 "SR12", 0x12,
2981 "SR13", 0x13,
2982 "SR14", 0x14,
2983 "SR15", 0x15,
2984 "SR16", 0x16,
2985 "SR17", 0x17,
2986 "SR18", 0x18,
2987 "SR19", 0x19,
2988 "SR1A", 0x1A,
2989 "SR1B", 0x1B,
2990 "SR1C", 0x1C,
2991 "SR1D", 0x1D,
2992 "SR1E", 0x1E,
2993 "SR1F", 0x1F,
2994 NULL);
2996 dev_dbg(info->device, "\n");
2999 #endif /* CIRRUSFB_DEBUG */