cirrusfb: add imageblit function
[linux-2.6/cjktty.git] / drivers / video / cirrusfb.c
bloba2a09b39c59a14597d7d79ff65a98ee731dc9bb4
1 /*
2 * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
4 * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
6 * Contributors (thanks, all!)
8 * David Eger:
9 * Overhaul for Linux 2.6
11 * Jeff Rugen:
12 * Major contributions; Motorola PowerStack (PPC and PCI) support,
13 * GD54xx, 1280x1024 mode support, change MCLK based on VCLK.
15 * Geert Uytterhoeven:
16 * Excellent code review.
18 * Lars Hecking:
19 * Amiga updates and testing.
21 * Original cirrusfb author: Frank Neumann
23 * Based on retz3fb.c and cirrusfb.c:
24 * Copyright (C) 1997 Jes Sorensen
25 * Copyright (C) 1996 Frank Neumann
27 ***************************************************************
29 * Format this code with GNU indent '-kr -i8 -pcs' options.
31 * This file is subject to the terms and conditions of the GNU General Public
32 * License. See the file COPYING in the main directory of this archive
33 * for more details.
37 #include <linux/module.h>
38 #include <linux/kernel.h>
39 #include <linux/errno.h>
40 #include <linux/string.h>
41 #include <linux/mm.h>
42 #include <linux/slab.h>
43 #include <linux/delay.h>
44 #include <linux/fb.h>
45 #include <linux/init.h>
46 #include <asm/pgtable.h>
48 #ifdef CONFIG_ZORRO
49 #include <linux/zorro.h>
50 #endif
51 #ifdef CONFIG_PCI
52 #include <linux/pci.h>
53 #endif
54 #ifdef CONFIG_AMIGA
55 #include <asm/amigahw.h>
56 #endif
57 #ifdef CONFIG_PPC_PREP
58 #include <asm/machdep.h>
59 #define isPReP machine_is(prep)
60 #else
61 #define isPReP 0
62 #endif
64 #include <video/vga.h>
65 #include <video/cirrus.h>
67 /*****************************************************************
69 * debugging and utility macros
73 /* disable runtime assertions? */
74 /* #define CIRRUSFB_NDEBUG */
76 /* debugging assertions */
77 #ifndef CIRRUSFB_NDEBUG
78 #define assert(expr) \
79 if (!(expr)) { \
80 printk("Assertion failed! %s,%s,%s,line=%d\n", \
81 #expr, __FILE__, __func__, __LINE__); \
83 #else
84 #define assert(expr)
85 #endif
87 #define MB_ (1024 * 1024)
89 /*****************************************************************
91 * chipset information
95 /* board types */
96 enum cirrus_board {
97 BT_NONE = 0,
98 BT_SD64,
99 BT_PICCOLO,
100 BT_PICASSO,
101 BT_SPECTRUM,
102 BT_PICASSO4, /* GD5446 */
103 BT_ALPINE, /* GD543x/4x */
104 BT_GD5480,
105 BT_LAGUNA, /* 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 = 0x20,
202 .sr07_1bpp = 0x20,
203 .sr07_8bpp = 0x21,
204 .sr1f = 0
206 [BT_ALPINE] = {
207 .name = "CL Alpine",
208 .maxclock = {
209 /* for the GD5430. GD5446 can do more... */
210 85500, 85500, 50000, 28500, 0
212 .init_sr07 = true,
213 .init_sr1f = true,
214 .scrn_start_bit19 = true,
215 .sr07 = 0xA0,
216 .sr07_1bpp = 0xA1,
217 .sr07_1bpp_mux = 0xA7,
218 .sr07_8bpp = 0xA1,
219 .sr07_8bpp_mux = 0xA7,
220 .sr1f = 0x1C
222 [BT_GD5480] = {
223 .name = "CL GD5480",
224 .maxclock = {
225 135100, 200000, 200000, 135100, 135100
227 .init_sr07 = true,
228 .init_sr1f = true,
229 .scrn_start_bit19 = true,
230 .sr07 = 0x10,
231 .sr07_1bpp = 0x11,
232 .sr07_8bpp = 0x11,
233 .sr1f = 0x1C
235 [BT_LAGUNA] = {
236 .name = "CL Laguna",
237 .maxclock = {
238 /* taken from X11 code */
239 170000, 170000, 170000, 170000, 135100,
241 .init_sr07 = false,
242 .init_sr1f = false,
243 .scrn_start_bit19 = true,
245 [BT_LAGUNAB] = {
246 .name = "CL Laguna AGP",
247 .maxclock = {
248 /* taken from X11 code */
249 170000, 250000, 170000, 170000, 135100,
251 .init_sr07 = false,
252 .init_sr1f = false,
253 .scrn_start_bit19 = true,
257 #ifdef CONFIG_PCI
258 #define CHIP(id, btype) \
259 { PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
261 static struct pci_device_id cirrusfb_pci_table[] = {
262 CHIP(PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE),
263 CHIP(PCI_DEVICE_ID_CIRRUS_5434_8, BT_ALPINE),
264 CHIP(PCI_DEVICE_ID_CIRRUS_5434_4, BT_ALPINE),
265 CHIP(PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE), /* GD-5440 is same id */
266 CHIP(PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE),
267 CHIP(PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE),
268 CHIP(PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480), /* MacPicasso likely */
269 CHIP(PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4), /* Picasso 4 is 5446 */
270 CHIP(PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA), /* CL Laguna */
271 CHIP(PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA), /* CL Laguna 3D */
272 CHIP(PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNAB), /* CL Laguna 3DA*/
273 { 0, }
275 MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
276 #undef CHIP
277 #endif /* CONFIG_PCI */
279 #ifdef CONFIG_ZORRO
280 static const struct zorro_device_id cirrusfb_zorro_table[] = {
282 .id = ZORRO_PROD_HELFRICH_SD64_RAM,
283 .driver_data = BT_SD64,
284 }, {
285 .id = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
286 .driver_data = BT_PICCOLO,
287 }, {
288 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
289 .driver_data = BT_PICASSO,
290 }, {
291 .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
292 .driver_data = BT_SPECTRUM,
293 }, {
294 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
295 .driver_data = BT_PICASSO4,
297 { 0 }
300 static const struct {
301 zorro_id id2;
302 unsigned long size;
303 } cirrusfb_zorro_table2[] = {
304 [BT_SD64] = {
305 .id2 = ZORRO_PROD_HELFRICH_SD64_REG,
306 .size = 0x400000
308 [BT_PICCOLO] = {
309 .id2 = ZORRO_PROD_HELFRICH_PICCOLO_REG,
310 .size = 0x200000
312 [BT_PICASSO] = {
313 .id2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
314 .size = 0x200000
316 [BT_SPECTRUM] = {
317 .id2 = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
318 .size = 0x200000
320 [BT_PICASSO4] = {
321 .id2 = 0,
322 .size = 0x400000
325 #endif /* CONFIG_ZORRO */
327 #ifdef CIRRUSFB_DEBUG
328 enum cirrusfb_dbg_reg_class {
329 CRT,
332 #endif /* CIRRUSFB_DEBUG */
334 /* info about board */
335 struct cirrusfb_info {
336 u8 __iomem *regbase;
337 u8 __iomem *laguna_mmio;
338 enum cirrus_board btype;
339 unsigned char SFR; /* Shadow of special function register */
341 int multiplexing;
342 int blank_mode;
343 u32 pseudo_palette[16];
345 void (*unmap)(struct fb_info *info);
348 static int noaccel __devinitdata;
349 static char *mode_option __devinitdata = "640x480@60";
351 /****************************************************************************/
352 /**** BEGIN PROTOTYPES ******************************************************/
354 /*--- Interface used by the world ------------------------------------------*/
355 static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
356 struct fb_info *info);
358 /*--- Internal routines ----------------------------------------------------*/
359 static void init_vgachip(struct fb_info *info);
360 static void switch_monitor(struct cirrusfb_info *cinfo, int on);
361 static void WGen(const struct cirrusfb_info *cinfo,
362 int regnum, unsigned char val);
363 static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum);
364 static void AttrOn(const struct cirrusfb_info *cinfo);
365 static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val);
366 static void WSFR(struct cirrusfb_info *cinfo, unsigned char val);
367 static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val);
368 static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum,
369 unsigned char red, unsigned char green, unsigned char blue);
370 #if 0
371 static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum,
372 unsigned char *red, unsigned char *green,
373 unsigned char *blue);
374 #endif
375 static void cirrusfb_WaitBLT(u8 __iomem *regbase);
376 static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
377 u_short curx, u_short cury,
378 u_short destx, u_short desty,
379 u_short width, u_short height,
380 u_short line_length);
381 static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
382 u_short x, u_short y,
383 u_short width, u_short height,
384 u32 fg_color, u32 bg_color,
385 u_short line_length, u_char blitmode);
387 static void bestclock(long freq, int *nom, int *den, int *div);
389 #ifdef CIRRUSFB_DEBUG
390 static void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase);
391 static void cirrusfb_dbg_print_regs(struct fb_info *info,
392 caddr_t regbase,
393 enum cirrusfb_dbg_reg_class reg_class, ...);
394 #endif /* CIRRUSFB_DEBUG */
396 /*** END PROTOTYPES ********************************************************/
397 /*****************************************************************************/
398 /*** BEGIN Interface Used by the World ***************************************/
400 static inline int is_laguna(const struct cirrusfb_info *cinfo)
402 return cinfo->btype == BT_LAGUNA || cinfo->btype == BT_LAGUNAB;
405 static int opencount;
407 /*--- Open /dev/fbx ---------------------------------------------------------*/
408 static int cirrusfb_open(struct fb_info *info, int user)
410 if (opencount++ == 0)
411 switch_monitor(info->par, 1);
412 return 0;
415 /*--- Close /dev/fbx --------------------------------------------------------*/
416 static int cirrusfb_release(struct fb_info *info, int user)
418 if (--opencount == 0)
419 switch_monitor(info->par, 0);
420 return 0;
423 /**** END Interface used by the World *************************************/
424 /****************************************************************************/
425 /**** BEGIN Hardware specific Routines **************************************/
427 /* Check if the MCLK is not a better clock source */
428 static int cirrusfb_check_mclk(struct fb_info *info, long freq)
430 struct cirrusfb_info *cinfo = info->par;
431 long mclk = vga_rseq(cinfo->regbase, CL_SEQR1F) & 0x3f;
433 /* Read MCLK value */
434 mclk = (14318 * mclk) >> 3;
435 dev_dbg(info->device, "Read MCLK of %ld kHz\n", mclk);
437 /* Determine if we should use MCLK instead of VCLK, and if so, what we
438 * should divide it by to get VCLK
441 if (abs(freq - mclk) < 250) {
442 dev_dbg(info->device, "Using VCLK = MCLK\n");
443 return 1;
444 } else if (abs(freq - (mclk / 2)) < 250) {
445 dev_dbg(info->device, "Using VCLK = MCLK/2\n");
446 return 2;
449 return 0;
452 static int cirrusfb_check_pixclock(const struct fb_var_screeninfo *var,
453 struct fb_info *info)
455 long freq;
456 long maxclock;
457 struct cirrusfb_info *cinfo = info->par;
458 unsigned maxclockidx = var->bits_per_pixel >> 3;
460 /* convert from ps to kHz */
461 freq = PICOS2KHZ(var->pixclock);
463 dev_dbg(info->device, "desired pixclock: %ld kHz\n", freq);
465 maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
466 cinfo->multiplexing = 0;
468 /* If the frequency is greater than we can support, we might be able
469 * to use multiplexing for the video mode */
470 if (freq > maxclock) {
471 switch (cinfo->btype) {
472 case BT_ALPINE:
473 case BT_GD5480:
474 cinfo->multiplexing = 1;
475 break;
477 default:
478 dev_err(info->device,
479 "Frequency greater than maxclock (%ld kHz)\n",
480 maxclock);
481 return -EINVAL;
484 #if 0
485 /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
486 * the VCLK is double the pixel clock. */
487 switch (var->bits_per_pixel) {
488 case 16:
489 case 32:
490 if (var->xres <= 800)
491 /* Xbh has this type of clock for 32-bit */
492 freq /= 2;
493 break;
495 #endif
496 return 0;
499 static int cirrusfb_check_var(struct fb_var_screeninfo *var,
500 struct fb_info *info)
502 int yres;
503 /* memory size in pixels */
504 unsigned pixels = info->screen_size * 8 / var->bits_per_pixel;
506 switch (var->bits_per_pixel) {
507 case 1:
508 var->red.offset = 0;
509 var->red.length = 1;
510 var->green = var->red;
511 var->blue = var->red;
512 break;
514 case 8:
515 var->red.offset = 0;
516 var->red.length = 8;
517 var->green = var->red;
518 var->blue = var->red;
519 break;
521 case 16:
522 if (isPReP) {
523 var->red.offset = 2;
524 var->green.offset = -3;
525 var->blue.offset = 8;
526 } else {
527 var->red.offset = 11;
528 var->green.offset = 5;
529 var->blue.offset = 0;
531 var->red.length = 5;
532 var->green.length = 6;
533 var->blue.length = 5;
534 break;
536 case 32:
537 if (isPReP) {
538 var->red.offset = 8;
539 var->green.offset = 16;
540 var->blue.offset = 24;
541 } else {
542 var->red.offset = 16;
543 var->green.offset = 8;
544 var->blue.offset = 0;
546 var->red.length = 8;
547 var->green.length = 8;
548 var->blue.length = 8;
549 break;
551 default:
552 dev_dbg(info->device,
553 "Unsupported bpp size: %d\n", var->bits_per_pixel);
554 assert(false);
555 /* should never occur */
556 break;
559 if (var->xres_virtual < var->xres)
560 var->xres_virtual = var->xres;
561 /* use highest possible virtual resolution */
562 if (var->yres_virtual == -1) {
563 var->yres_virtual = pixels / var->xres_virtual;
565 dev_info(info->device,
566 "virtual resolution set to maximum of %dx%d\n",
567 var->xres_virtual, var->yres_virtual);
569 if (var->yres_virtual < var->yres)
570 var->yres_virtual = var->yres;
572 if (var->xres_virtual * var->yres_virtual > pixels) {
573 dev_err(info->device, "mode %dx%dx%d rejected... "
574 "virtual resolution too high to fit into video memory!\n",
575 var->xres_virtual, var->yres_virtual,
576 var->bits_per_pixel);
577 return -EINVAL;
580 if (var->xoffset < 0)
581 var->xoffset = 0;
582 if (var->yoffset < 0)
583 var->yoffset = 0;
585 /* truncate xoffset and yoffset to maximum if too high */
586 if (var->xoffset > var->xres_virtual - var->xres)
587 var->xoffset = var->xres_virtual - var->xres - 1;
588 if (var->yoffset > var->yres_virtual - var->yres)
589 var->yoffset = var->yres_virtual - var->yres - 1;
591 var->red.msb_right =
592 var->green.msb_right =
593 var->blue.msb_right =
594 var->transp.offset =
595 var->transp.length =
596 var->transp.msb_right = 0;
598 yres = var->yres;
599 if (var->vmode & FB_VMODE_DOUBLE)
600 yres *= 2;
601 else if (var->vmode & FB_VMODE_INTERLACED)
602 yres = (yres + 1) / 2;
604 if (yres >= 1280) {
605 dev_err(info->device, "ERROR: VerticalTotal >= 1280; "
606 "special treatment required! (TODO)\n");
607 return -EINVAL;
610 if (cirrusfb_check_pixclock(var, info))
611 return -EINVAL;
613 return 0;
616 static void cirrusfb_set_mclk_as_source(const struct fb_info *info, int div)
618 struct cirrusfb_info *cinfo = info->par;
619 unsigned char old1f, old1e;
621 assert(cinfo != NULL);
622 old1f = vga_rseq(cinfo->regbase, CL_SEQR1F) & ~0x40;
624 if (div) {
625 dev_dbg(info->device, "Set %s as pixclock source.\n",
626 (div == 2) ? "MCLK/2" : "MCLK");
627 old1f |= 0x40;
628 old1e = vga_rseq(cinfo->regbase, CL_SEQR1E) & ~0x1;
629 if (div == 2)
630 old1e |= 1;
632 vga_wseq(cinfo->regbase, CL_SEQR1E, old1e);
634 vga_wseq(cinfo->regbase, CL_SEQR1F, old1f);
637 /*************************************************************************
638 cirrusfb_set_par_foo()
640 actually writes the values for a new video mode into the hardware,
641 **************************************************************************/
642 static int cirrusfb_set_par_foo(struct fb_info *info)
644 struct cirrusfb_info *cinfo = info->par;
645 struct fb_var_screeninfo *var = &info->var;
646 u8 __iomem *regbase = cinfo->regbase;
647 unsigned char tmp;
648 int pitch;
649 const struct cirrusfb_board_info_rec *bi;
650 int hdispend, hsyncstart, hsyncend, htotal;
651 int yres, vdispend, vsyncstart, vsyncend, vtotal;
652 long freq;
653 int nom, den, div;
654 unsigned int control = 0, format = 0, threshold = 0;
656 dev_dbg(info->device, "Requested mode: %dx%dx%d\n",
657 var->xres, var->yres, var->bits_per_pixel);
659 switch (var->bits_per_pixel) {
660 case 1:
661 info->fix.line_length = var->xres_virtual / 8;
662 info->fix.visual = FB_VISUAL_MONO10;
663 break;
665 case 8:
666 info->fix.line_length = var->xres_virtual;
667 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
668 break;
670 case 16:
671 case 32:
672 info->fix.line_length = var->xres_virtual *
673 var->bits_per_pixel >> 3;
674 info->fix.visual = FB_VISUAL_TRUECOLOR;
675 break;
677 info->fix.type = FB_TYPE_PACKED_PIXELS;
679 init_vgachip(info);
681 bi = &cirrusfb_board_info[cinfo->btype];
683 hsyncstart = var->xres + var->right_margin;
684 hsyncend = hsyncstart + var->hsync_len;
685 htotal = (hsyncend + var->left_margin) / 8 - 5;
686 hdispend = var->xres / 8 - 1;
687 hsyncstart = hsyncstart / 8 + 1;
688 hsyncend = hsyncend / 8 + 1;
690 yres = var->yres;
691 vsyncstart = yres + var->lower_margin;
692 vsyncend = vsyncstart + var->vsync_len;
693 vtotal = vsyncend + var->upper_margin;
694 vdispend = yres - 1;
696 if (var->vmode & FB_VMODE_DOUBLE) {
697 yres *= 2;
698 vsyncstart *= 2;
699 vsyncend *= 2;
700 vtotal *= 2;
701 } else if (var->vmode & FB_VMODE_INTERLACED) {
702 yres = (yres + 1) / 2;
703 vsyncstart = (vsyncstart + 1) / 2;
704 vsyncend = (vsyncend + 1) / 2;
705 vtotal = (vtotal + 1) / 2;
708 vtotal -= 2;
709 vsyncstart -= 1;
710 vsyncend -= 1;
712 if (yres >= 1024) {
713 vtotal /= 2;
714 vsyncstart /= 2;
715 vsyncend /= 2;
716 vdispend /= 2;
718 if (cinfo->multiplexing) {
719 htotal /= 2;
720 hsyncstart /= 2;
721 hsyncend /= 2;
722 hdispend /= 2;
724 /* unlock register VGA_CRTC_H_TOTAL..CRT7 */
725 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */
727 /* if debugging is enabled, all parameters get output before writing */
728 dev_dbg(info->device, "CRT0: %d\n", htotal);
729 vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal);
731 dev_dbg(info->device, "CRT1: %d\n", hdispend);
732 vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend);
734 dev_dbg(info->device, "CRT2: %d\n", var->xres / 8);
735 vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8);
737 /* + 128: Compatible read */
738 dev_dbg(info->device, "CRT3: 128+%d\n", (htotal + 5) % 32);
739 vga_wcrt(regbase, VGA_CRTC_H_BLANK_END,
740 128 + ((htotal + 5) % 32));
742 dev_dbg(info->device, "CRT4: %d\n", hsyncstart);
743 vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart);
745 tmp = hsyncend % 32;
746 if ((htotal + 5) & 32)
747 tmp += 128;
748 dev_dbg(info->device, "CRT5: %d\n", tmp);
749 vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp);
751 dev_dbg(info->device, "CRT6: %d\n", vtotal & 0xff);
752 vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff);
754 tmp = 16; /* LineCompare bit #9 */
755 if (vtotal & 256)
756 tmp |= 1;
757 if (vdispend & 256)
758 tmp |= 2;
759 if (vsyncstart & 256)
760 tmp |= 4;
761 if ((vdispend + 1) & 256)
762 tmp |= 8;
763 if (vtotal & 512)
764 tmp |= 32;
765 if (vdispend & 512)
766 tmp |= 64;
767 if (vsyncstart & 512)
768 tmp |= 128;
769 dev_dbg(info->device, "CRT7: %d\n", tmp);
770 vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp);
772 tmp = 0x40; /* LineCompare bit #8 */
773 if ((vdispend + 1) & 512)
774 tmp |= 0x20;
775 if (var->vmode & FB_VMODE_DOUBLE)
776 tmp |= 0x80;
777 dev_dbg(info->device, "CRT9: %d\n", tmp);
778 vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp);
780 dev_dbg(info->device, "CRT10: %d\n", vsyncstart & 0xff);
781 vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff);
783 dev_dbg(info->device, "CRT11: 64+32+%d\n", vsyncend % 16);
784 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32);
786 dev_dbg(info->device, "CRT12: %d\n", vdispend & 0xff);
787 vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff);
789 dev_dbg(info->device, "CRT15: %d\n", (vdispend + 1) & 0xff);
790 vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff);
792 dev_dbg(info->device, "CRT16: %d\n", vtotal & 0xff);
793 vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff);
795 dev_dbg(info->device, "CRT18: 0xff\n");
796 vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff);
798 tmp = 0;
799 if (var->vmode & FB_VMODE_INTERLACED)
800 tmp |= 1;
801 if ((htotal + 5) & 64)
802 tmp |= 16;
803 if ((htotal + 5) & 128)
804 tmp |= 32;
805 if (vtotal & 256)
806 tmp |= 64;
807 if (vtotal & 512)
808 tmp |= 128;
810 dev_dbg(info->device, "CRT1a: %d\n", tmp);
811 vga_wcrt(regbase, CL_CRT1A, tmp);
813 freq = PICOS2KHZ(var->pixclock);
814 bestclock(freq, &nom, &den, &div);
816 dev_dbg(info->device, "VCLK freq: %ld kHz nom: %d den: %d div: %d\n",
817 freq, nom, den, div);
819 /* set VCLK0 */
820 /* hardware RefClock: 14.31818 MHz */
821 /* formula: VClk = (OSC * N) / (D * (1+P)) */
822 /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
824 if (cinfo->btype == BT_ALPINE) {
825 /* if freq is close to mclk or mclk/2 select mclk
826 * as clock source
828 int divMCLK = cirrusfb_check_mclk(info, freq);
829 if (divMCLK) {
830 nom = 0;
831 cirrusfb_set_mclk_as_source(info, divMCLK);
834 if (is_laguna(cinfo)) {
835 long pcifc = fb_readl(cinfo->laguna_mmio + 0x3fc);
836 unsigned char tile = fb_readb(cinfo->laguna_mmio + 0x407);
837 unsigned short tile_control;
839 if (cinfo->btype == BT_LAGUNAB) {
840 tile_control = fb_readw(cinfo->laguna_mmio + 0x2c4);
841 tile_control &= ~0x80;
842 fb_writew(tile_control, cinfo->laguna_mmio + 0x2c4);
845 fb_writel(pcifc | 0x10000000l, cinfo->laguna_mmio + 0x3fc);
846 fb_writeb(tile & 0x3f, cinfo->laguna_mmio + 0x407);
847 control = fb_readw(cinfo->laguna_mmio + 0x402);
848 threshold = fb_readw(cinfo->laguna_mmio + 0xea);
849 control &= ~0x6800;
850 format = 0;
851 threshold &= 0xffe0 & 0x3fbf;
853 if (nom) {
854 tmp = den << 1;
855 if (div != 0)
856 tmp |= 1;
857 /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
858 if ((cinfo->btype == BT_SD64) ||
859 (cinfo->btype == BT_ALPINE) ||
860 (cinfo->btype == BT_GD5480))
861 tmp |= 0x80;
863 dev_dbg(info->device, "CL_SEQR1B: %d\n", (int) tmp);
864 /* Laguna chipset has reversed clock registers */
865 if (is_laguna(cinfo)) {
866 vga_wseq(regbase, CL_SEQRE, tmp);
867 vga_wseq(regbase, CL_SEQR1E, nom);
868 } else {
869 vga_wseq(regbase, CL_SEQRB, nom);
870 vga_wseq(regbase, CL_SEQR1B, tmp);
874 if (yres >= 1024)
875 /* 1280x1024 */
876 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7);
877 else
878 /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
879 * address wrap, no compat. */
880 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3);
882 /* don't know if it would hurt to also program this if no interlaced */
883 /* mode is used, but I feel better this way.. :-) */
884 if (var->vmode & FB_VMODE_INTERLACED)
885 vga_wcrt(regbase, VGA_CRTC_REGS, htotal / 2);
886 else
887 vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
889 /* adjust horizontal/vertical sync type (low/high) */
890 /* enable display memory & CRTC I/O address for color mode */
891 tmp = 0x03;
892 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
893 tmp |= 0x40;
894 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
895 tmp |= 0x80;
896 if (is_laguna(cinfo))
897 tmp |= 0xc;
898 WGen(cinfo, VGA_MIS_W, tmp);
900 /* text cursor on and start line */
901 vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0);
902 /* text cursor end line */
903 vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 31);
905 /******************************************************
907 * 1 bpp
911 /* programming for different color depths */
912 if (var->bits_per_pixel == 1) {
913 dev_dbg(info->device, "preparing for 1 bit deep display\n");
914 vga_wgfx(regbase, VGA_GFX_MODE, 0); /* mode register */
916 /* SR07 */
917 switch (cinfo->btype) {
918 case BT_SD64:
919 case BT_PICCOLO:
920 case BT_PICASSO:
921 case BT_SPECTRUM:
922 case BT_PICASSO4:
923 case BT_ALPINE:
924 case BT_GD5480:
925 vga_wseq(regbase, CL_SEQR7,
926 cinfo->multiplexing ?
927 bi->sr07_1bpp_mux : bi->sr07_1bpp);
928 break;
930 case BT_LAGUNA:
931 case BT_LAGUNAB:
932 vga_wseq(regbase, CL_SEQR7,
933 vga_rseq(regbase, CL_SEQR7) & ~0x01);
934 break;
936 default:
937 dev_warn(info->device, "unknown Board\n");
938 break;
941 /* Extended Sequencer Mode */
942 switch (cinfo->btype) {
943 case BT_SD64:
944 /* setting the SEQRF on SD64 is not necessary
945 * (only during init)
947 /* MCLK select */
948 vga_wseq(regbase, CL_SEQR1F, 0x1a);
949 break;
951 case BT_PICCOLO:
952 case BT_SPECTRUM:
953 /* ### ueberall 0x22? */
954 /* ##vorher 1c MCLK select */
955 vga_wseq(regbase, CL_SEQR1F, 0x22);
956 /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
957 vga_wseq(regbase, CL_SEQRF, 0xb0);
958 break;
960 case BT_PICASSO:
961 /* ##vorher 22 MCLK select */
962 vga_wseq(regbase, CL_SEQR1F, 0x22);
963 /* ## vorher d0 avoid FIFO underruns..? */
964 vga_wseq(regbase, CL_SEQRF, 0xd0);
965 break;
967 case BT_PICASSO4:
968 case BT_ALPINE:
969 case BT_GD5480:
970 case BT_LAGUNA:
971 case BT_LAGUNAB:
972 /* do nothing */
973 break;
975 default:
976 dev_warn(info->device, "unknown Board\n");
977 break;
980 /* pixel mask: pass-through for first plane */
981 WGen(cinfo, VGA_PEL_MSK, 0x01);
982 if (cinfo->multiplexing)
983 /* hidden dac reg: 1280x1024 */
984 WHDR(cinfo, 0x4a);
985 else
986 /* hidden dac: nothing */
987 WHDR(cinfo, 0);
988 /* memory mode: odd/even, ext. memory */
989 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06);
990 /* plane mask: only write to first plane */
991 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01);
994 /******************************************************
996 * 8 bpp
1000 else if (var->bits_per_pixel == 8) {
1001 dev_dbg(info->device, "preparing for 8 bit deep display\n");
1002 switch (cinfo->btype) {
1003 case BT_SD64:
1004 case BT_PICCOLO:
1005 case BT_PICASSO:
1006 case BT_SPECTRUM:
1007 case BT_PICASSO4:
1008 case BT_ALPINE:
1009 case BT_GD5480:
1010 vga_wseq(regbase, CL_SEQR7,
1011 cinfo->multiplexing ?
1012 bi->sr07_8bpp_mux : bi->sr07_8bpp);
1013 break;
1015 case BT_LAGUNA:
1016 case BT_LAGUNAB:
1017 vga_wseq(regbase, CL_SEQR7,
1018 vga_rseq(regbase, CL_SEQR7) | 0x01);
1019 threshold |= 0x10;
1020 break;
1022 default:
1023 dev_warn(info->device, "unknown Board\n");
1024 break;
1027 switch (cinfo->btype) {
1028 case BT_SD64:
1029 /* MCLK select */
1030 vga_wseq(regbase, CL_SEQR1F, 0x1d);
1031 break;
1033 case BT_PICCOLO:
1034 case BT_PICASSO:
1035 case BT_SPECTRUM:
1036 /* ### vorher 1c MCLK select */
1037 vga_wseq(regbase, CL_SEQR1F, 0x22);
1038 /* Fast Page-Mode writes */
1039 vga_wseq(regbase, CL_SEQRF, 0xb0);
1040 break;
1042 case BT_PICASSO4:
1043 #ifdef CONFIG_ZORRO
1044 /* ### INCOMPLETE!! */
1045 vga_wseq(regbase, CL_SEQRF, 0xb8);
1046 #endif
1047 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1048 break;
1050 case BT_ALPINE:
1051 /* We already set SRF and SR1F */
1052 break;
1054 case BT_GD5480:
1055 case BT_LAGUNA:
1056 case BT_LAGUNAB:
1057 /* do nothing */
1058 break;
1060 default:
1061 dev_warn(info->device, "unknown board\n");
1062 break;
1065 /* mode register: 256 color mode */
1066 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1067 if (cinfo->multiplexing)
1068 /* hidden dac reg: 1280x1024 */
1069 WHDR(cinfo, 0x4a);
1070 else
1071 /* hidden dac: nothing */
1072 WHDR(cinfo, 0);
1075 /******************************************************
1077 * 16 bpp
1081 else if (var->bits_per_pixel == 16) {
1082 dev_dbg(info->device, "preparing for 16 bit deep display\n");
1083 switch (cinfo->btype) {
1084 case BT_SD64:
1085 /* Extended Sequencer Mode: 256c col. mode */
1086 vga_wseq(regbase, CL_SEQR7, 0xf7);
1087 /* MCLK select */
1088 vga_wseq(regbase, CL_SEQR1F, 0x1e);
1089 break;
1091 case BT_PICCOLO:
1092 case BT_SPECTRUM:
1093 vga_wseq(regbase, CL_SEQR7, 0x87);
1094 /* Fast Page-Mode writes */
1095 vga_wseq(regbase, CL_SEQRF, 0xb0);
1096 /* MCLK select */
1097 vga_wseq(regbase, CL_SEQR1F, 0x22);
1098 break;
1100 case BT_PICASSO:
1101 vga_wseq(regbase, CL_SEQR7, 0x27);
1102 /* Fast Page-Mode writes */
1103 vga_wseq(regbase, CL_SEQRF, 0xb0);
1104 /* MCLK select */
1105 vga_wseq(regbase, CL_SEQR1F, 0x22);
1106 break;
1108 case BT_PICASSO4:
1109 vga_wseq(regbase, CL_SEQR7, 0x27);
1110 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1111 break;
1113 case BT_ALPINE:
1114 vga_wseq(regbase, CL_SEQR7, 0xa7);
1115 break;
1117 case BT_GD5480:
1118 vga_wseq(regbase, CL_SEQR7, 0x17);
1119 /* We already set SRF and SR1F */
1120 break;
1122 case BT_LAGUNA:
1123 case BT_LAGUNAB:
1124 vga_wseq(regbase, CL_SEQR7,
1125 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1126 control |= 0x2000;
1127 format |= 0x1400;
1128 threshold |= 0x10;
1129 break;
1131 default:
1132 dev_warn(info->device, "unknown Board\n");
1133 break;
1136 /* mode register: 256 color mode */
1137 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1138 #ifdef CONFIG_PCI
1139 WHDR(cinfo, 0xc1); /* Copy Xbh */
1140 #elif defined(CONFIG_ZORRO)
1141 /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
1142 WHDR(cinfo, 0xa0); /* hidden dac reg: nothing special */
1143 #endif
1146 /******************************************************
1148 * 32 bpp
1152 else if (var->bits_per_pixel == 32) {
1153 dev_dbg(info->device, "preparing for 32 bit deep display\n");
1154 switch (cinfo->btype) {
1155 case BT_SD64:
1156 /* Extended Sequencer Mode: 256c col. mode */
1157 vga_wseq(regbase, CL_SEQR7, 0xf9);
1158 /* MCLK select */
1159 vga_wseq(regbase, CL_SEQR1F, 0x1e);
1160 break;
1162 case BT_PICCOLO:
1163 case BT_SPECTRUM:
1164 vga_wseq(regbase, CL_SEQR7, 0x85);
1165 /* Fast Page-Mode writes */
1166 vga_wseq(regbase, CL_SEQRF, 0xb0);
1167 /* MCLK select */
1168 vga_wseq(regbase, CL_SEQR1F, 0x22);
1169 break;
1171 case BT_PICASSO:
1172 vga_wseq(regbase, CL_SEQR7, 0x25);
1173 /* Fast Page-Mode writes */
1174 vga_wseq(regbase, CL_SEQRF, 0xb0);
1175 /* MCLK select */
1176 vga_wseq(regbase, CL_SEQR1F, 0x22);
1177 break;
1179 case BT_PICASSO4:
1180 vga_wseq(regbase, CL_SEQR7, 0x25);
1181 /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1182 break;
1184 case BT_ALPINE:
1185 vga_wseq(regbase, CL_SEQR7, 0xa9);
1186 break;
1188 case BT_GD5480:
1189 vga_wseq(regbase, CL_SEQR7, 0x19);
1190 /* We already set SRF and SR1F */
1191 break;
1193 case BT_LAGUNA:
1194 case BT_LAGUNAB:
1195 vga_wseq(regbase, CL_SEQR7,
1196 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1197 control |= 0x6000;
1198 format |= 0x3400;
1199 threshold |= 0x20;
1200 break;
1202 default:
1203 dev_warn(info->device, "unknown Board\n");
1204 break;
1207 /* mode register: 256 color mode */
1208 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1209 /* hidden dac reg: 8-8-8 mode (24 or 32) */
1210 WHDR(cinfo, 0xc5);
1213 /******************************************************
1215 * unknown/unsupported bpp
1219 else
1220 dev_err(info->device,
1221 "What's this? requested color depth == %d.\n",
1222 var->bits_per_pixel);
1224 pitch = info->fix.line_length >> 3;
1225 vga_wcrt(regbase, VGA_CRTC_OFFSET, pitch & 0xff);
1226 tmp = 0x22;
1227 if (pitch & 0x100)
1228 tmp |= 0x10; /* offset overflow bit */
1230 /* screen start addr #16-18, fastpagemode cycles */
1231 vga_wcrt(regbase, CL_CRT1B, tmp);
1233 /* screen start address bit 19 */
1234 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19)
1235 vga_wcrt(regbase, CL_CRT1D, (pitch >> 9) & 1);
1237 if (is_laguna(cinfo)) {
1238 tmp = 0;
1239 if ((htotal + 5) & 256)
1240 tmp |= 128;
1241 if (hdispend & 256)
1242 tmp |= 64;
1243 if (hsyncstart & 256)
1244 tmp |= 48;
1245 if (vtotal & 1024)
1246 tmp |= 8;
1247 if (vdispend & 1024)
1248 tmp |= 4;
1249 if (vsyncstart & 1024)
1250 tmp |= 3;
1252 vga_wcrt(regbase, CL_CRT1E, tmp);
1253 dev_dbg(info->device, "CRT1e: %d\n", tmp);
1256 /* pixel panning */
1257 vga_wattr(regbase, CL_AR33, 0);
1259 /* [ EGS: SetOffset(); ] */
1260 /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
1261 AttrOn(cinfo);
1263 if (is_laguna(cinfo)) {
1264 /* no tiles */
1265 fb_writew(control | 0x1000, cinfo->laguna_mmio + 0x402);
1266 fb_writew(format, cinfo->laguna_mmio + 0xc0);
1267 fb_writew(threshold, cinfo->laguna_mmio + 0xea);
1269 /* finally, turn on everything - turn off "FullBandwidth" bit */
1270 /* also, set "DotClock%2" bit where requested */
1271 tmp = 0x01;
1273 /*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
1274 if (var->vmode & FB_VMODE_CLOCK_HALVE)
1275 tmp |= 0x08;
1278 vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp);
1279 dev_dbg(info->device, "CL_SEQR1: %d\n", tmp);
1281 #ifdef CIRRUSFB_DEBUG
1282 cirrusfb_dbg_reg_dump(info, NULL);
1283 #endif
1285 return 0;
1288 /* for some reason incomprehensible to me, cirrusfb requires that you write
1289 * the registers twice for the settings to take..grr. -dte */
1290 static int cirrusfb_set_par(struct fb_info *info)
1292 cirrusfb_set_par_foo(info);
1293 return cirrusfb_set_par_foo(info);
1296 static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1297 unsigned blue, unsigned transp,
1298 struct fb_info *info)
1300 struct cirrusfb_info *cinfo = info->par;
1302 if (regno > 255)
1303 return -EINVAL;
1305 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
1306 u32 v;
1307 red >>= (16 - info->var.red.length);
1308 green >>= (16 - info->var.green.length);
1309 blue >>= (16 - info->var.blue.length);
1311 if (regno >= 16)
1312 return 1;
1313 v = (red << info->var.red.offset) |
1314 (green << info->var.green.offset) |
1315 (blue << info->var.blue.offset);
1317 cinfo->pseudo_palette[regno] = v;
1318 return 0;
1321 if (info->var.bits_per_pixel == 8)
1322 WClut(cinfo, regno, red >> 10, green >> 10, blue >> 10);
1324 return 0;
1328 /*************************************************************************
1329 cirrusfb_pan_display()
1331 performs display panning - provided hardware permits this
1332 **************************************************************************/
1333 static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
1334 struct fb_info *info)
1336 int xoffset;
1337 unsigned long base;
1338 unsigned char tmp, xpix;
1339 struct cirrusfb_info *cinfo = info->par;
1341 dev_dbg(info->device,
1342 "virtual offset: (%d,%d)\n", var->xoffset, var->yoffset);
1344 /* no range checks for xoffset and yoffset, */
1345 /* as fb_pan_display has already done this */
1346 if (var->vmode & FB_VMODE_YWRAP)
1347 return -EINVAL;
1349 xoffset = var->xoffset * info->var.bits_per_pixel / 8;
1351 base = var->yoffset * info->fix.line_length + xoffset;
1353 if (info->var.bits_per_pixel == 1) {
1354 /* base is already correct */
1355 xpix = (unsigned char) (var->xoffset % 8);
1356 } else {
1357 base /= 4;
1358 xpix = (unsigned char) ((xoffset % 4) * 2);
1361 if (!is_laguna(cinfo))
1362 cirrusfb_WaitBLT(cinfo->regbase);
1364 /* lower 8 + 8 bits of screen start address */
1365 vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, base & 0xff);
1366 vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, (base >> 8) & 0xff);
1368 /* 0xf2 is %11110010, exclude tmp bits */
1369 tmp = vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2;
1370 /* construct bits 16, 17 and 18 of screen start address */
1371 if (base & 0x10000)
1372 tmp |= 0x01;
1373 if (base & 0x20000)
1374 tmp |= 0x04;
1375 if (base & 0x40000)
1376 tmp |= 0x08;
1378 vga_wcrt(cinfo->regbase, CL_CRT1B, tmp);
1380 /* construct bit 19 of screen start address */
1381 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) {
1382 tmp = vga_rcrt(cinfo->regbase, CL_CRT1D);
1383 if (is_laguna(cinfo))
1384 tmp = (tmp & ~0x18) | ((base >> 16) & 0x18);
1385 else
1386 tmp = (tmp & ~0x80) | ((base >> 12) & 0x80);
1387 vga_wcrt(cinfo->regbase, CL_CRT1D, tmp);
1390 /* write pixel panning value to AR33; this does not quite work in 8bpp
1392 * ### Piccolo..? Will this work?
1394 if (info->var.bits_per_pixel == 1)
1395 vga_wattr(cinfo->regbase, CL_AR33, xpix);
1397 if (!is_laguna(cinfo))
1398 cirrusfb_WaitBLT(cinfo->regbase);
1400 return 0;
1403 static int cirrusfb_blank(int blank_mode, struct fb_info *info)
1406 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
1407 * then the caller blanks by setting the CLUT (Color Look Up Table)
1408 * to all black. Return 0 if blanking succeeded, != 0 if un-/blanking
1409 * failed due to e.g. a video mode which doesn't support it.
1410 * Implements VESA suspend and powerdown modes on hardware that
1411 * supports disabling hsync/vsync:
1412 * blank_mode == 2: suspend vsync
1413 * blank_mode == 3: suspend hsync
1414 * blank_mode == 4: powerdown
1416 unsigned char val;
1417 struct cirrusfb_info *cinfo = info->par;
1418 int current_mode = cinfo->blank_mode;
1420 dev_dbg(info->device, "ENTER, blank mode = %d\n", blank_mode);
1422 if (info->state != FBINFO_STATE_RUNNING ||
1423 current_mode == blank_mode) {
1424 dev_dbg(info->device, "EXIT, returning 0\n");
1425 return 0;
1428 /* Undo current */
1429 if (current_mode == FB_BLANK_NORMAL ||
1430 current_mode == FB_BLANK_UNBLANK)
1431 /* clear "FullBandwidth" bit */
1432 val = 0;
1433 else
1434 /* set "FullBandwidth" bit */
1435 val = 0x20;
1437 val |= vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE) & 0xdf;
1438 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val);
1440 switch (blank_mode) {
1441 case FB_BLANK_UNBLANK:
1442 case FB_BLANK_NORMAL:
1443 val = 0x00;
1444 break;
1445 case FB_BLANK_VSYNC_SUSPEND:
1446 val = 0x04;
1447 break;
1448 case FB_BLANK_HSYNC_SUSPEND:
1449 val = 0x02;
1450 break;
1451 case FB_BLANK_POWERDOWN:
1452 val = 0x06;
1453 break;
1454 default:
1455 dev_dbg(info->device, "EXIT, returning 1\n");
1456 return 1;
1459 vga_wgfx(cinfo->regbase, CL_GRE, val);
1461 cinfo->blank_mode = blank_mode;
1462 dev_dbg(info->device, "EXIT, returning 0\n");
1464 /* Let fbcon do a soft blank for us */
1465 return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
1468 /**** END Hardware specific Routines **************************************/
1469 /****************************************************************************/
1470 /**** BEGIN Internal Routines ***********************************************/
1472 static void init_vgachip(struct fb_info *info)
1474 struct cirrusfb_info *cinfo = info->par;
1475 const struct cirrusfb_board_info_rec *bi;
1477 assert(cinfo != NULL);
1479 bi = &cirrusfb_board_info[cinfo->btype];
1481 /* reset board globally */
1482 switch (cinfo->btype) {
1483 case BT_PICCOLO:
1484 WSFR(cinfo, 0x01);
1485 udelay(500);
1486 WSFR(cinfo, 0x51);
1487 udelay(500);
1488 break;
1489 case BT_PICASSO:
1490 WSFR2(cinfo, 0xff);
1491 udelay(500);
1492 break;
1493 case BT_SD64:
1494 case BT_SPECTRUM:
1495 WSFR(cinfo, 0x1f);
1496 udelay(500);
1497 WSFR(cinfo, 0x4f);
1498 udelay(500);
1499 break;
1500 case BT_PICASSO4:
1501 /* disable flickerfixer */
1502 vga_wcrt(cinfo->regbase, CL_CRT51, 0x00);
1503 mdelay(100);
1504 /* from Klaus' NetBSD driver: */
1505 vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
1506 /* put blitter into 542x compat */
1507 vga_wgfx(cinfo->regbase, CL_GR33, 0x00);
1508 /* mode */
1509 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1510 break;
1512 case BT_GD5480:
1513 /* from Klaus' NetBSD driver: */
1514 vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
1515 break;
1517 case BT_LAGUNA:
1518 case BT_LAGUNAB:
1519 case BT_ALPINE:
1520 /* Nothing to do to reset the board. */
1521 break;
1523 default:
1524 dev_err(info->device, "Warning: Unknown board type\n");
1525 break;
1528 /* make sure RAM size set by this point */
1529 assert(info->screen_size > 0);
1531 /* the P4 is not fully initialized here; I rely on it having been */
1532 /* inited under AmigaOS already, which seems to work just fine */
1533 /* (Klaus advised to do it this way) */
1535 if (cinfo->btype != BT_PICASSO4) {
1536 WGen(cinfo, CL_VSSM, 0x10); /* EGS: 0x16 */
1537 WGen(cinfo, CL_POS102, 0x01);
1538 WGen(cinfo, CL_VSSM, 0x08); /* EGS: 0x0e */
1540 if (cinfo->btype != BT_SD64)
1541 WGen(cinfo, CL_VSSM2, 0x01);
1543 /* reset sequencer logic */
1544 vga_wseq(cinfo->regbase, VGA_SEQ_RESET, 0x03);
1546 /* FullBandwidth (video off) and 8/9 dot clock */
1547 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21);
1549 /* "magic cookie" - doesn't make any sense to me.. */
1550 /* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */
1551 /* unlock all extension registers */
1552 vga_wseq(cinfo->regbase, CL_SEQR6, 0x12);
1554 switch (cinfo->btype) {
1555 case BT_GD5480:
1556 vga_wseq(cinfo->regbase, CL_SEQRF, 0x98);
1557 break;
1558 case BT_ALPINE:
1559 case BT_LAGUNA:
1560 case BT_LAGUNAB:
1561 break;
1562 case BT_SD64:
1563 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8);
1564 break;
1565 default:
1566 vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f);
1567 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb0);
1568 break;
1571 /* plane mask: nothing */
1572 vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1573 /* character map select: doesn't even matter in gx mode */
1574 vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00);
1575 /* memory mode: chain4, ext. memory */
1576 vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1578 /* controller-internal base address of video memory */
1579 if (bi->init_sr07)
1580 vga_wseq(cinfo->regbase, CL_SEQR7, bi->sr07);
1582 /* vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */
1583 /* EEPROM control: shouldn't be necessary to write to this at all.. */
1585 /* graphics cursor X position (incomplete; position gives rem. 3 bits */
1586 vga_wseq(cinfo->regbase, CL_SEQR10, 0x00);
1587 /* graphics cursor Y position (..."... ) */
1588 vga_wseq(cinfo->regbase, CL_SEQR11, 0x00);
1589 /* graphics cursor attributes */
1590 vga_wseq(cinfo->regbase, CL_SEQR12, 0x00);
1591 /* graphics cursor pattern address */
1592 vga_wseq(cinfo->regbase, CL_SEQR13, 0x00);
1594 /* writing these on a P4 might give problems.. */
1595 if (cinfo->btype != BT_PICASSO4) {
1596 /* configuration readback and ext. color */
1597 vga_wseq(cinfo->regbase, CL_SEQR17, 0x00);
1598 /* signature generator */
1599 vga_wseq(cinfo->regbase, CL_SEQR18, 0x02);
1602 /* MCLK select etc. */
1603 if (bi->init_sr1f)
1604 vga_wseq(cinfo->regbase, CL_SEQR1F, bi->sr1f);
1606 /* Screen A preset row scan: none */
1607 vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00);
1608 /* Text cursor start: disable text cursor */
1609 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20);
1610 /* Text cursor end: - */
1611 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00);
1612 /* text cursor location high: 0 */
1613 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00);
1614 /* text cursor location low: 0 */
1615 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00);
1617 /* Underline Row scanline: - */
1618 vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00);
1619 /* ### add 0x40 for text modes with > 30 MHz pixclock */
1620 /* ext. display controls: ext.adr. wrap */
1621 vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02);
1623 /* Set/Reset registes: - */
1624 vga_wgfx(cinfo->regbase, VGA_GFX_SR_VALUE, 0x00);
1625 /* Set/Reset enable: - */
1626 vga_wgfx(cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00);
1627 /* Color Compare: - */
1628 vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00);
1629 /* Data Rotate: - */
1630 vga_wgfx(cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00);
1631 /* Read Map Select: - */
1632 vga_wgfx(cinfo->regbase, VGA_GFX_PLANE_READ, 0x00);
1633 /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
1634 vga_wgfx(cinfo->regbase, VGA_GFX_MODE, 0x00);
1635 /* Miscellaneous: memory map base address, graphics mode */
1636 vga_wgfx(cinfo->regbase, VGA_GFX_MISC, 0x01);
1637 /* Color Don't care: involve all planes */
1638 vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f);
1639 /* Bit Mask: no mask at all */
1640 vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff);
1642 if (cinfo->btype == BT_ALPINE || is_laguna(cinfo))
1643 /* (5434 can't have bit 3 set for bitblt) */
1644 vga_wgfx(cinfo->regbase, CL_GRB, 0x20);
1645 else
1646 /* Graphics controller mode extensions: finer granularity,
1647 * 8byte data latches
1649 vga_wgfx(cinfo->regbase, CL_GRB, 0x28);
1651 vga_wgfx(cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */
1652 vga_wgfx(cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */
1653 vga_wgfx(cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */
1654 /* Background color byte 1: - */
1655 /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); */
1656 /* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
1658 /* Attribute Controller palette registers: "identity mapping" */
1659 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE0, 0x00);
1660 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
1661 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
1662 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
1663 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
1664 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
1665 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
1666 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
1667 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
1668 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
1669 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
1670 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
1671 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
1672 vga_wattr(cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
1673 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
1674 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
1676 /* Attribute Controller mode: graphics mode */
1677 vga_wattr(cinfo->regbase, VGA_ATC_MODE, 0x01);
1678 /* Overscan color reg.: reg. 0 */
1679 vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00);
1680 /* Color Plane enable: Enable all 4 planes */
1681 vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f);
1682 /* Color Select: - */
1683 vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00);
1685 WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
1687 /* BLT Start/status: Blitter reset */
1688 vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
1689 /* - " - : "end-of-reset" */
1690 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1692 /* misc... */
1693 WHDR(cinfo, 0); /* Hidden DAC register: - */
1694 return;
1697 static void switch_monitor(struct cirrusfb_info *cinfo, int on)
1699 #ifdef CONFIG_ZORRO /* only works on Zorro boards */
1700 static int IsOn = 0; /* XXX not ok for multiple boards */
1702 if (cinfo->btype == BT_PICASSO4)
1703 return; /* nothing to switch */
1704 if (cinfo->btype == BT_ALPINE)
1705 return; /* nothing to switch */
1706 if (cinfo->btype == BT_GD5480)
1707 return; /* nothing to switch */
1708 if (cinfo->btype == BT_PICASSO) {
1709 if ((on && !IsOn) || (!on && IsOn))
1710 WSFR(cinfo, 0xff);
1711 return;
1713 if (on) {
1714 switch (cinfo->btype) {
1715 case BT_SD64:
1716 WSFR(cinfo, cinfo->SFR | 0x21);
1717 break;
1718 case BT_PICCOLO:
1719 WSFR(cinfo, cinfo->SFR | 0x28);
1720 break;
1721 case BT_SPECTRUM:
1722 WSFR(cinfo, 0x6f);
1723 break;
1724 default: /* do nothing */ break;
1726 } else {
1727 switch (cinfo->btype) {
1728 case BT_SD64:
1729 WSFR(cinfo, cinfo->SFR & 0xde);
1730 break;
1731 case BT_PICCOLO:
1732 WSFR(cinfo, cinfo->SFR & 0xd7);
1733 break;
1734 case BT_SPECTRUM:
1735 WSFR(cinfo, 0x4f);
1736 break;
1737 default: /* do nothing */
1738 break;
1741 #endif /* CONFIG_ZORRO */
1744 /******************************************/
1745 /* Linux 2.6-style accelerated functions */
1746 /******************************************/
1748 static int cirrusfb_sync(struct fb_info *info)
1750 struct cirrusfb_info *cinfo = info->par;
1752 if (!is_laguna(cinfo)) {
1753 while (vga_rgfx(cinfo->regbase, CL_GR31) & 0x03)
1754 cpu_relax();
1756 return 0;
1759 static void cirrusfb_fillrect(struct fb_info *info,
1760 const struct fb_fillrect *region)
1762 struct fb_fillrect modded;
1763 int vxres, vyres;
1764 struct cirrusfb_info *cinfo = info->par;
1765 int m = info->var.bits_per_pixel;
1766 u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
1767 cinfo->pseudo_palette[region->color] : region->color;
1769 if (info->state != FBINFO_STATE_RUNNING)
1770 return;
1771 if (info->flags & FBINFO_HWACCEL_DISABLED) {
1772 cfb_fillrect(info, region);
1773 return;
1776 vxres = info->var.xres_virtual;
1777 vyres = info->var.yres_virtual;
1779 memcpy(&modded, region, sizeof(struct fb_fillrect));
1781 if (!modded.width || !modded.height ||
1782 modded.dx >= vxres || modded.dy >= vyres)
1783 return;
1785 if (modded.dx + modded.width > vxres)
1786 modded.width = vxres - modded.dx;
1787 if (modded.dy + modded.height > vyres)
1788 modded.height = vyres - modded.dy;
1790 cirrusfb_RectFill(cinfo->regbase,
1791 info->var.bits_per_pixel,
1792 (region->dx * m) / 8, region->dy,
1793 (region->width * m) / 8, region->height,
1794 color, color,
1795 info->fix.line_length, 0x40);
1798 static void cirrusfb_copyarea(struct fb_info *info,
1799 const struct fb_copyarea *area)
1801 struct fb_copyarea modded;
1802 u32 vxres, vyres;
1803 struct cirrusfb_info *cinfo = info->par;
1804 int m = info->var.bits_per_pixel;
1806 if (info->state != FBINFO_STATE_RUNNING)
1807 return;
1808 if (info->flags & FBINFO_HWACCEL_DISABLED) {
1809 cfb_copyarea(info, area);
1810 return;
1813 vxres = info->var.xres_virtual;
1814 vyres = info->var.yres_virtual;
1815 memcpy(&modded, area, sizeof(struct fb_copyarea));
1817 if (!modded.width || !modded.height ||
1818 modded.sx >= vxres || modded.sy >= vyres ||
1819 modded.dx >= vxres || modded.dy >= vyres)
1820 return;
1822 if (modded.sx + modded.width > vxres)
1823 modded.width = vxres - modded.sx;
1824 if (modded.dx + modded.width > vxres)
1825 modded.width = vxres - modded.dx;
1826 if (modded.sy + modded.height > vyres)
1827 modded.height = vyres - modded.sy;
1828 if (modded.dy + modded.height > vyres)
1829 modded.height = vyres - modded.dy;
1831 cirrusfb_BitBLT(cinfo->regbase, info->var.bits_per_pixel,
1832 (area->sx * m) / 8, area->sy,
1833 (area->dx * m) / 8, area->dy,
1834 (area->width * m) / 8, area->height,
1835 info->fix.line_length);
1839 static void cirrusfb_imageblit(struct fb_info *info,
1840 const struct fb_image *image)
1842 struct cirrusfb_info *cinfo = info->par;
1844 if (info->state != FBINFO_STATE_RUNNING)
1845 return;
1846 if (info->flags & FBINFO_HWACCEL_DISABLED)
1847 cfb_imageblit(info, image);
1848 else {
1849 unsigned size = ((image->width + 7) >> 3) * image->height;
1850 int m = info->var.bits_per_pixel;
1851 u32 fg, bg;
1853 if (info->var.bits_per_pixel == 8) {
1854 fg = image->fg_color;
1855 bg = image->bg_color;
1856 } else {
1857 fg = ((u32 *)(info->pseudo_palette))[image->fg_color];
1858 bg = ((u32 *)(info->pseudo_palette))[image->bg_color];
1860 cirrusfb_WaitBLT(cinfo->regbase);
1861 /* byte rounded scanlines */
1862 vga_wgfx(cinfo->regbase, CL_GR33, 0x00);
1863 cirrusfb_RectFill(cinfo->regbase,
1864 info->var.bits_per_pixel,
1865 (image->dx * m) / 8, image->dy,
1866 (image->width * m) / 8, image->height,
1867 fg, bg,
1868 info->fix.line_length, 0x04);
1869 memcpy(info->screen_base, image->data, size);
1873 #ifdef CONFIG_PPC_PREP
1874 #define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
1875 #define PREP_IO_BASE ((volatile unsigned char *) 0x80000000)
1876 static void get_prep_addrs(unsigned long *display, unsigned long *registers)
1878 *display = PREP_VIDEO_BASE;
1879 *registers = (unsigned long) PREP_IO_BASE;
1882 #endif /* CONFIG_PPC_PREP */
1884 #ifdef CONFIG_PCI
1885 static int release_io_ports;
1887 /* Pulled the logic from XFree86 Cirrus driver to get the memory size,
1888 * based on the DRAM bandwidth bit and DRAM bank switching bit. This
1889 * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
1890 * seem to have. */
1891 static unsigned int __devinit cirrusfb_get_memsize(struct fb_info *info,
1892 u8 __iomem *regbase)
1894 unsigned long mem;
1895 struct cirrusfb_info *cinfo = info->par;
1897 if (is_laguna(cinfo)) {
1898 unsigned char SR14 = vga_rseq(regbase, CL_SEQR14);
1900 mem = ((SR14 & 7) + 1) << 20;
1901 } else {
1902 unsigned char SRF = vga_rseq(regbase, CL_SEQRF);
1903 switch ((SRF & 0x18)) {
1904 case 0x08:
1905 mem = 512 * 1024;
1906 break;
1907 case 0x10:
1908 mem = 1024 * 1024;
1909 break;
1910 /* 64-bit DRAM data bus width; assume 2MB.
1911 * Also indicates 2MB memory on the 5430.
1913 case 0x18:
1914 mem = 2048 * 1024;
1915 break;
1916 default:
1917 dev_warn(info->device, "Unknown memory size!\n");
1918 mem = 1024 * 1024;
1920 /* If DRAM bank switching is enabled, there must be
1921 * twice as much memory installed. (4MB on the 5434)
1923 if (SRF & 0x80)
1924 mem *= 2;
1927 /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
1928 return mem;
1931 static void get_pci_addrs(const struct pci_dev *pdev,
1932 unsigned long *display, unsigned long *registers)
1934 assert(pdev != NULL);
1935 assert(display != NULL);
1936 assert(registers != NULL);
1938 *display = 0;
1939 *registers = 0;
1941 /* This is a best-guess for now */
1943 if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
1944 *display = pci_resource_start(pdev, 1);
1945 *registers = pci_resource_start(pdev, 0);
1946 } else {
1947 *display = pci_resource_start(pdev, 0);
1948 *registers = pci_resource_start(pdev, 1);
1951 assert(*display != 0);
1954 static void cirrusfb_pci_unmap(struct fb_info *info)
1956 struct pci_dev *pdev = to_pci_dev(info->device);
1957 struct cirrusfb_info *cinfo = info->par;
1959 if (cinfo->laguna_mmio == NULL)
1960 iounmap(cinfo->laguna_mmio);
1961 iounmap(info->screen_base);
1962 #if 0 /* if system didn't claim this region, we would... */
1963 release_mem_region(0xA0000, 65535);
1964 #endif
1965 if (release_io_ports)
1966 release_region(0x3C0, 32);
1967 pci_release_regions(pdev);
1969 #endif /* CONFIG_PCI */
1971 #ifdef CONFIG_ZORRO
1972 static void cirrusfb_zorro_unmap(struct fb_info *info)
1974 struct cirrusfb_info *cinfo = info->par;
1975 struct zorro_dev *zdev = to_zorro_dev(info->device);
1977 zorro_release_device(zdev);
1979 if (cinfo->btype == BT_PICASSO4) {
1980 cinfo->regbase -= 0x600000;
1981 iounmap((void *)cinfo->regbase);
1982 iounmap(info->screen_base);
1983 } else {
1984 if (zorro_resource_start(zdev) > 0x01000000)
1985 iounmap(info->screen_base);
1988 #endif /* CONFIG_ZORRO */
1990 /* function table of the above functions */
1991 static struct fb_ops cirrusfb_ops = {
1992 .owner = THIS_MODULE,
1993 .fb_open = cirrusfb_open,
1994 .fb_release = cirrusfb_release,
1995 .fb_setcolreg = cirrusfb_setcolreg,
1996 .fb_check_var = cirrusfb_check_var,
1997 .fb_set_par = cirrusfb_set_par,
1998 .fb_pan_display = cirrusfb_pan_display,
1999 .fb_blank = cirrusfb_blank,
2000 .fb_fillrect = cirrusfb_fillrect,
2001 .fb_copyarea = cirrusfb_copyarea,
2002 .fb_sync = cirrusfb_sync,
2003 .fb_imageblit = cirrusfb_imageblit,
2006 static int __devinit cirrusfb_set_fbinfo(struct fb_info *info)
2008 struct cirrusfb_info *cinfo = info->par;
2009 struct fb_var_screeninfo *var = &info->var;
2011 info->pseudo_palette = cinfo->pseudo_palette;
2012 info->flags = FBINFO_DEFAULT
2013 | FBINFO_HWACCEL_XPAN
2014 | FBINFO_HWACCEL_YPAN
2015 | FBINFO_HWACCEL_FILLRECT
2016 | FBINFO_HWACCEL_IMAGEBLIT
2017 | FBINFO_HWACCEL_COPYAREA;
2018 if (noaccel || is_laguna(cinfo))
2019 info->flags |= FBINFO_HWACCEL_DISABLED;
2020 info->fbops = &cirrusfb_ops;
2022 if (cinfo->btype == BT_GD5480) {
2023 if (var->bits_per_pixel == 16)
2024 info->screen_base += 1 * MB_;
2025 if (var->bits_per_pixel == 32)
2026 info->screen_base += 2 * MB_;
2029 /* Fill fix common fields */
2030 strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
2031 sizeof(info->fix.id));
2033 /* monochrome: only 1 memory plane */
2034 /* 8 bit and above: Use whole memory area */
2035 info->fix.smem_len = info->screen_size;
2036 if (var->bits_per_pixel == 1)
2037 info->fix.smem_len /= 4;
2038 info->fix.type_aux = 0;
2039 info->fix.xpanstep = 1;
2040 info->fix.ypanstep = 1;
2041 info->fix.ywrapstep = 0;
2043 /* FIXME: map region at 0xB8000 if available, fill in here */
2044 info->fix.mmio_len = 0;
2045 info->fix.accel = FB_ACCEL_NONE;
2047 fb_alloc_cmap(&info->cmap, 256, 0);
2049 return 0;
2052 static int __devinit cirrusfb_register(struct fb_info *info)
2054 struct cirrusfb_info *cinfo = info->par;
2055 int err;
2057 /* sanity checks */
2058 assert(cinfo->btype != BT_NONE);
2060 /* set all the vital stuff */
2061 cirrusfb_set_fbinfo(info);
2063 dev_dbg(info->device, "(RAM start set to: 0x%p)\n", info->screen_base);
2065 err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
2066 if (!err) {
2067 dev_dbg(info->device, "wrong initial video mode\n");
2068 err = -EINVAL;
2069 goto err_dealloc_cmap;
2072 info->var.activate = FB_ACTIVATE_NOW;
2074 err = cirrusfb_check_var(&info->var, info);
2075 if (err < 0) {
2076 /* should never happen */
2077 dev_dbg(info->device,
2078 "choking on default var... umm, no good.\n");
2079 goto err_dealloc_cmap;
2082 err = register_framebuffer(info);
2083 if (err < 0) {
2084 dev_err(info->device,
2085 "could not register fb device; err = %d!\n", err);
2086 goto err_dealloc_cmap;
2089 return 0;
2091 err_dealloc_cmap:
2092 fb_dealloc_cmap(&info->cmap);
2093 cinfo->unmap(info);
2094 framebuffer_release(info);
2095 return err;
2098 static void __devexit cirrusfb_cleanup(struct fb_info *info)
2100 struct cirrusfb_info *cinfo = info->par;
2102 switch_monitor(cinfo, 0);
2103 unregister_framebuffer(info);
2104 fb_dealloc_cmap(&info->cmap);
2105 dev_dbg(info->device, "Framebuffer unregistered\n");
2106 cinfo->unmap(info);
2107 framebuffer_release(info);
2110 #ifdef CONFIG_PCI
2111 static int __devinit cirrusfb_pci_register(struct pci_dev *pdev,
2112 const struct pci_device_id *ent)
2114 struct cirrusfb_info *cinfo;
2115 struct fb_info *info;
2116 unsigned long board_addr, board_size;
2117 int ret;
2119 ret = pci_enable_device(pdev);
2120 if (ret < 0) {
2121 printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
2122 goto err_out;
2125 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev);
2126 if (!info) {
2127 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2128 ret = -ENOMEM;
2129 goto err_out;
2132 cinfo = info->par;
2133 cinfo->btype = (enum cirrus_board) ent->driver_data;
2135 dev_dbg(info->device,
2136 " Found PCI device, base address 0 is 0x%Lx, btype set to %d\n",
2137 (unsigned long long)pdev->resource[0].start, cinfo->btype);
2138 dev_dbg(info->device, " base address 1 is 0x%Lx\n",
2139 (unsigned long long)pdev->resource[1].start);
2141 if (isPReP) {
2142 pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, 0x00000000);
2143 #ifdef CONFIG_PPC_PREP
2144 get_prep_addrs(&board_addr, &info->fix.mmio_start);
2145 #endif
2146 /* PReP dies if we ioremap the IO registers, but it works w/out... */
2147 cinfo->regbase = (char __iomem *) info->fix.mmio_start;
2148 } else {
2149 dev_dbg(info->device,
2150 "Attempt to get PCI info for Cirrus Graphics Card\n");
2151 get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start);
2152 /* FIXME: this forces VGA. alternatives? */
2153 cinfo->regbase = NULL;
2154 cinfo->laguna_mmio = ioremap(info->fix.mmio_start, 0x1000);
2157 dev_dbg(info->device, "Board address: 0x%lx, register address: 0x%lx\n",
2158 board_addr, info->fix.mmio_start);
2160 board_size = (cinfo->btype == BT_GD5480) ?
2161 32 * MB_ : cirrusfb_get_memsize(info, cinfo->regbase);
2163 ret = pci_request_regions(pdev, "cirrusfb");
2164 if (ret < 0) {
2165 dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
2166 board_addr);
2167 goto err_release_fb;
2169 #if 0 /* if the system didn't claim this region, we would... */
2170 if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
2171 dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
2172 0xA0000L);
2173 ret = -EBUSY;
2174 goto err_release_regions;
2176 #endif
2177 if (request_region(0x3C0, 32, "cirrusfb"))
2178 release_io_ports = 1;
2180 info->screen_base = ioremap(board_addr, board_size);
2181 if (!info->screen_base) {
2182 ret = -EIO;
2183 goto err_release_legacy;
2186 info->fix.smem_start = board_addr;
2187 info->screen_size = board_size;
2188 cinfo->unmap = cirrusfb_pci_unmap;
2190 dev_info(info->device,
2191 "Cirrus Logic chipset on PCI bus, RAM (%lu kB) at 0x%lx\n",
2192 info->screen_size >> 10, board_addr);
2193 pci_set_drvdata(pdev, info);
2195 ret = cirrusfb_register(info);
2196 if (!ret)
2197 return 0;
2199 pci_set_drvdata(pdev, NULL);
2200 iounmap(info->screen_base);
2201 err_release_legacy:
2202 if (release_io_ports)
2203 release_region(0x3C0, 32);
2204 #if 0
2205 release_mem_region(0xA0000, 65535);
2206 err_release_regions:
2207 #endif
2208 pci_release_regions(pdev);
2209 err_release_fb:
2210 if (cinfo->laguna_mmio != NULL)
2211 iounmap(cinfo->laguna_mmio);
2212 framebuffer_release(info);
2213 err_out:
2214 return ret;
2217 static void __devexit cirrusfb_pci_unregister(struct pci_dev *pdev)
2219 struct fb_info *info = pci_get_drvdata(pdev);
2221 cirrusfb_cleanup(info);
2224 static struct pci_driver cirrusfb_pci_driver = {
2225 .name = "cirrusfb",
2226 .id_table = cirrusfb_pci_table,
2227 .probe = cirrusfb_pci_register,
2228 .remove = __devexit_p(cirrusfb_pci_unregister),
2229 #ifdef CONFIG_PM
2230 #if 0
2231 .suspend = cirrusfb_pci_suspend,
2232 .resume = cirrusfb_pci_resume,
2233 #endif
2234 #endif
2236 #endif /* CONFIG_PCI */
2238 #ifdef CONFIG_ZORRO
2239 static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
2240 const struct zorro_device_id *ent)
2242 struct cirrusfb_info *cinfo;
2243 struct fb_info *info;
2244 enum cirrus_board btype;
2245 struct zorro_dev *z2 = NULL;
2246 unsigned long board_addr, board_size, size;
2247 int ret;
2249 btype = ent->driver_data;
2250 if (cirrusfb_zorro_table2[btype].id2)
2251 z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
2252 size = cirrusfb_zorro_table2[btype].size;
2254 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
2255 if (!info) {
2256 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2257 ret = -ENOMEM;
2258 goto err_out;
2261 dev_info(info->device, "%s board detected\n",
2262 cirrusfb_board_info[btype].name);
2264 cinfo = info->par;
2265 cinfo->btype = btype;
2267 assert(z);
2268 assert(btype != BT_NONE);
2270 board_addr = zorro_resource_start(z);
2271 board_size = zorro_resource_len(z);
2272 info->screen_size = size;
2274 if (!zorro_request_device(z, "cirrusfb")) {
2275 dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
2276 board_addr);
2277 ret = -EBUSY;
2278 goto err_release_fb;
2281 ret = -EIO;
2283 if (btype == BT_PICASSO4) {
2284 dev_info(info->device, " REG at $%lx\n", board_addr + 0x600000);
2286 /* To be precise, for the P4 this is not the */
2287 /* begin of the board, but the begin of RAM. */
2288 /* for P4, map in its address space in 2 chunks (### TEST! ) */
2289 /* (note the ugly hardcoded 16M number) */
2290 cinfo->regbase = ioremap(board_addr, 16777216);
2291 if (!cinfo->regbase)
2292 goto err_release_region;
2294 dev_dbg(info->device, "Virtual address for board set to: $%p\n",
2295 cinfo->regbase);
2296 cinfo->regbase += 0x600000;
2297 info->fix.mmio_start = board_addr + 0x600000;
2299 info->fix.smem_start = board_addr + 16777216;
2300 info->screen_base = ioremap(info->fix.smem_start, 16777216);
2301 if (!info->screen_base)
2302 goto err_unmap_regbase;
2303 } else {
2304 dev_info(info->device, " REG at $%lx\n",
2305 (unsigned long) z2->resource.start);
2307 info->fix.smem_start = board_addr;
2308 if (board_addr > 0x01000000)
2309 info->screen_base = ioremap(board_addr, board_size);
2310 else
2311 info->screen_base = (caddr_t) ZTWO_VADDR(board_addr);
2312 if (!info->screen_base)
2313 goto err_release_region;
2315 /* set address for REG area of board */
2316 cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start);
2317 info->fix.mmio_start = z2->resource.start;
2319 dev_dbg(info->device, "Virtual address for board set to: $%p\n",
2320 cinfo->regbase);
2322 cinfo->unmap = cirrusfb_zorro_unmap;
2324 dev_info(info->device,
2325 "Cirrus Logic chipset on Zorro bus, RAM (%lu MB) at $%lx\n",
2326 board_size / MB_, board_addr);
2328 zorro_set_drvdata(z, info);
2330 ret = cirrusfb_register(info);
2331 if (ret) {
2332 if (btype == BT_PICASSO4) {
2333 iounmap(info->screen_base);
2334 iounmap(cinfo->regbase - 0x600000);
2335 } else if (board_addr > 0x01000000)
2336 iounmap(info->screen_base);
2338 return ret;
2340 err_unmap_regbase:
2341 /* Parental advisory: explicit hack */
2342 iounmap(cinfo->regbase - 0x600000);
2343 err_release_region:
2344 release_region(board_addr, board_size);
2345 err_release_fb:
2346 framebuffer_release(info);
2347 err_out:
2348 return ret;
2351 void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
2353 struct fb_info *info = zorro_get_drvdata(z);
2355 cirrusfb_cleanup(info);
2358 static struct zorro_driver cirrusfb_zorro_driver = {
2359 .name = "cirrusfb",
2360 .id_table = cirrusfb_zorro_table,
2361 .probe = cirrusfb_zorro_register,
2362 .remove = __devexit_p(cirrusfb_zorro_unregister),
2364 #endif /* CONFIG_ZORRO */
2366 #ifndef MODULE
2367 static int __init cirrusfb_setup(char *options)
2369 char *this_opt;
2371 if (!options || !*options)
2372 return 0;
2374 while ((this_opt = strsep(&options, ",")) != NULL) {
2375 if (!*this_opt)
2376 continue;
2378 if (!strcmp(this_opt, "noaccel"))
2379 noaccel = 1;
2380 else if (!strncmp(this_opt, "mode:", 5))
2381 mode_option = this_opt + 5;
2382 else
2383 mode_option = this_opt;
2385 return 0;
2387 #endif
2390 * Modularization
2393 MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
2394 MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
2395 MODULE_LICENSE("GPL");
2397 static int __init cirrusfb_init(void)
2399 int error = 0;
2401 #ifndef MODULE
2402 char *option = NULL;
2404 if (fb_get_options("cirrusfb", &option))
2405 return -ENODEV;
2406 cirrusfb_setup(option);
2407 #endif
2409 #ifdef CONFIG_ZORRO
2410 error |= zorro_register_driver(&cirrusfb_zorro_driver);
2411 #endif
2412 #ifdef CONFIG_PCI
2413 error |= pci_register_driver(&cirrusfb_pci_driver);
2414 #endif
2415 return error;
2418 static void __exit cirrusfb_exit(void)
2420 #ifdef CONFIG_PCI
2421 pci_unregister_driver(&cirrusfb_pci_driver);
2422 #endif
2423 #ifdef CONFIG_ZORRO
2424 zorro_unregister_driver(&cirrusfb_zorro_driver);
2425 #endif
2428 module_init(cirrusfb_init);
2430 module_param(mode_option, charp, 0);
2431 MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
2432 module_param(noaccel, bool, 0);
2433 MODULE_PARM_DESC(noaccel, "Disable acceleration");
2435 #ifdef MODULE
2436 module_exit(cirrusfb_exit);
2437 #endif
2439 /**********************************************************************/
2440 /* about the following functions - I have used the same names for the */
2441 /* functions as Markus Wild did in his Retina driver for NetBSD as */
2442 /* they just made sense for this purpose. Apart from that, I wrote */
2443 /* these functions myself. */
2444 /**********************************************************************/
2446 /*** WGen() - write into one of the external/general registers ***/
2447 static void WGen(const struct cirrusfb_info *cinfo,
2448 int regnum, unsigned char val)
2450 unsigned long regofs = 0;
2452 if (cinfo->btype == BT_PICASSO) {
2453 /* Picasso II specific hack */
2454 /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2455 regnum == CL_VSSM2) */
2456 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2457 regofs = 0xfff;
2460 vga_w(cinfo->regbase, regofs + regnum, val);
2463 /*** RGen() - read out one of the external/general registers ***/
2464 static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum)
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 return vga_r(cinfo->regbase, regofs + regnum);
2479 /*** AttrOn() - turn on VideoEnable for Attribute controller ***/
2480 static void AttrOn(const struct cirrusfb_info *cinfo)
2482 assert(cinfo != NULL);
2484 if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) {
2485 /* if we're just in "write value" mode, write back the */
2486 /* same value as before to not modify anything */
2487 vga_w(cinfo->regbase, VGA_ATT_IW,
2488 vga_r(cinfo->regbase, VGA_ATT_R));
2490 /* turn on video bit */
2491 /* vga_w(cinfo->regbase, VGA_ATT_IW, 0x20); */
2492 vga_w(cinfo->regbase, VGA_ATT_IW, 0x33);
2494 /* dummy write on Reg0 to be on "write index" mode next time */
2495 vga_w(cinfo->regbase, VGA_ATT_IW, 0x00);
2498 /*** WHDR() - write into the Hidden DAC register ***/
2499 /* as the HDR is the only extension register that requires special treatment
2500 * (the other extension registers are accessible just like the "ordinary"
2501 * registers of their functional group) here is a specialized routine for
2502 * accessing the HDR
2504 static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val)
2506 unsigned char dummy;
2508 if (is_laguna(cinfo))
2509 return;
2510 if (cinfo->btype == BT_PICASSO) {
2511 /* Klaus' hint for correct access to HDR on some boards */
2512 /* first write 0 to pixel mask (3c6) */
2513 WGen(cinfo, VGA_PEL_MSK, 0x00);
2514 udelay(200);
2515 /* next read dummy from pixel address (3c8) */
2516 dummy = RGen(cinfo, VGA_PEL_IW);
2517 udelay(200);
2519 /* now do the usual stuff to access the HDR */
2521 dummy = RGen(cinfo, VGA_PEL_MSK);
2522 udelay(200);
2523 dummy = RGen(cinfo, VGA_PEL_MSK);
2524 udelay(200);
2525 dummy = RGen(cinfo, VGA_PEL_MSK);
2526 udelay(200);
2527 dummy = RGen(cinfo, VGA_PEL_MSK);
2528 udelay(200);
2530 WGen(cinfo, VGA_PEL_MSK, val);
2531 udelay(200);
2533 if (cinfo->btype == BT_PICASSO) {
2534 /* now first reset HDR access counter */
2535 dummy = RGen(cinfo, VGA_PEL_IW);
2536 udelay(200);
2538 /* and at the end, restore the mask value */
2539 /* ## is this mask always 0xff? */
2540 WGen(cinfo, VGA_PEL_MSK, 0xff);
2541 udelay(200);
2545 /*** WSFR() - write to the "special function register" (SFR) ***/
2546 static void WSFR(struct cirrusfb_info *cinfo, unsigned char val)
2548 #ifdef CONFIG_ZORRO
2549 assert(cinfo->regbase != NULL);
2550 cinfo->SFR = val;
2551 z_writeb(val, cinfo->regbase + 0x8000);
2552 #endif
2555 /* The Picasso has a second register for switching the monitor bit */
2556 static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val)
2558 #ifdef CONFIG_ZORRO
2559 /* writing an arbitrary value to this one causes the monitor switcher */
2560 /* to flip to Amiga display */
2561 assert(cinfo->regbase != NULL);
2562 cinfo->SFR = val;
2563 z_writeb(val, cinfo->regbase + 0x9000);
2564 #endif
2567 /*** WClut - set CLUT entry (range: 0..63) ***/
2568 static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
2569 unsigned char green, unsigned char blue)
2571 unsigned int data = VGA_PEL_D;
2573 /* address write mode register is not translated.. */
2574 vga_w(cinfo->regbase, VGA_PEL_IW, regnum);
2576 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2577 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480 ||
2578 is_laguna(cinfo)) {
2579 /* but DAC data register IS, at least for Picasso II */
2580 if (cinfo->btype == BT_PICASSO)
2581 data += 0xfff;
2582 vga_w(cinfo->regbase, data, red);
2583 vga_w(cinfo->regbase, data, green);
2584 vga_w(cinfo->regbase, data, blue);
2585 } else {
2586 vga_w(cinfo->regbase, data, blue);
2587 vga_w(cinfo->regbase, data, green);
2588 vga_w(cinfo->regbase, data, red);
2592 #if 0
2593 /*** RClut - read CLUT entry (range 0..63) ***/
2594 static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
2595 unsigned char *green, unsigned char *blue)
2597 unsigned int data = VGA_PEL_D;
2599 vga_w(cinfo->regbase, VGA_PEL_IR, regnum);
2601 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2602 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2603 if (cinfo->btype == BT_PICASSO)
2604 data += 0xfff;
2605 *red = vga_r(cinfo->regbase, data);
2606 *green = vga_r(cinfo->regbase, data);
2607 *blue = vga_r(cinfo->regbase, data);
2608 } else {
2609 *blue = vga_r(cinfo->regbase, data);
2610 *green = vga_r(cinfo->regbase, data);
2611 *red = vga_r(cinfo->regbase, data);
2614 #endif
2616 /*******************************************************************
2617 cirrusfb_WaitBLT()
2619 Wait for the BitBLT engine to complete a possible earlier job
2620 *********************************************************************/
2622 /* FIXME: use interrupts instead */
2623 static void cirrusfb_WaitBLT(u8 __iomem *regbase)
2625 while (vga_rgfx(regbase, CL_GR31) & 0x08)
2626 cpu_relax();
2629 /*******************************************************************
2630 cirrusfb_BitBLT()
2632 perform accelerated "scrolling"
2633 ********************************************************************/
2635 static void cirrusfb_set_blitter(u8 __iomem *regbase,
2636 u_short nwidth, u_short nheight,
2637 u_long nsrc, u_long ndest,
2638 u_short bltmode, u_short line_length)
2641 /* pitch: set to line_length */
2642 /* dest pitch low */
2643 vga_wgfx(regbase, CL_GR24, line_length & 0xff);
2644 /* dest pitch hi */
2645 vga_wgfx(regbase, CL_GR25, line_length >> 8);
2646 /* source pitch low */
2647 vga_wgfx(regbase, CL_GR26, line_length & 0xff);
2648 /* source pitch hi */
2649 vga_wgfx(regbase, CL_GR27, line_length >> 8);
2651 /* BLT width: actual number of pixels - 1 */
2652 /* BLT width low */
2653 vga_wgfx(regbase, CL_GR20, nwidth & 0xff);
2654 /* BLT width hi */
2655 vga_wgfx(regbase, CL_GR21, nwidth >> 8);
2657 /* BLT height: actual number of lines -1 */
2658 /* BLT height low */
2659 vga_wgfx(regbase, CL_GR22, nheight & 0xff);
2660 /* BLT width hi */
2661 vga_wgfx(regbase, CL_GR23, nheight >> 8);
2663 /* BLT destination */
2664 /* BLT dest low */
2665 vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
2666 /* BLT dest mid */
2667 vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
2668 /* BLT dest hi */
2669 vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
2671 /* BLT source */
2672 /* BLT src low */
2673 vga_wgfx(regbase, CL_GR2C, (u_char) (nsrc & 0xff));
2674 /* BLT src mid */
2675 vga_wgfx(regbase, CL_GR2D, (u_char) (nsrc >> 8));
2676 /* BLT src hi */
2677 vga_wgfx(regbase, CL_GR2E, (u_char) (nsrc >> 16));
2679 /* BLT mode */
2680 vga_wgfx(regbase, CL_GR30, bltmode); /* BLT mode */
2682 /* BLT ROP: SrcCopy */
2683 vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */
2685 /* and finally: GO! */
2686 vga_wgfx(regbase, CL_GR31, 0x82); /* BLT Start/status */
2689 /*******************************************************************
2690 cirrusfb_BitBLT()
2692 perform accelerated "scrolling"
2693 ********************************************************************/
2695 static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
2696 u_short curx, u_short cury,
2697 u_short destx, u_short desty,
2698 u_short width, u_short height,
2699 u_short line_length)
2701 u_short nwidth = width - 1;
2702 u_short nheight = height - 1;
2703 u_long nsrc, ndest;
2704 u_char bltmode;
2706 bltmode = 0x00;
2707 /* if source adr < dest addr, do the Blt backwards */
2708 if (cury <= desty) {
2709 if (cury == desty) {
2710 /* if src and dest are on the same line, check x */
2711 if (curx < destx)
2712 bltmode |= 0x01;
2713 } else
2714 bltmode |= 0x01;
2716 /* standard case: forward blitting */
2717 nsrc = (cury * line_length) + curx;
2718 ndest = (desty * line_length) + destx;
2719 if (bltmode) {
2720 /* this means start addresses are at the end,
2721 * counting backwards
2723 nsrc += nheight * line_length + nwidth;
2724 ndest += nheight * line_length + nwidth;
2727 cirrusfb_WaitBLT(regbase);
2729 cirrusfb_set_blitter(regbase, nwidth, nheight,
2730 nsrc, ndest, bltmode, line_length);
2733 /*******************************************************************
2734 cirrusfb_RectFill()
2736 perform accelerated rectangle fill
2737 ********************************************************************/
2739 static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
2740 u_short x, u_short y, u_short width, u_short height,
2741 u32 fg_color, u32 bg_color, u_short line_length,
2742 u_char blitmode)
2744 u_long ndest = (y * line_length) + x;
2745 u_char op;
2747 cirrusfb_WaitBLT(regbase);
2749 /* This is a ColorExpand Blt, using the */
2750 /* same color for foreground and background */
2751 vga_wgfx(regbase, VGA_GFX_SR_VALUE, bg_color);
2752 vga_wgfx(regbase, VGA_GFX_SR_ENABLE, fg_color);
2754 op = 0x80;
2755 if (bits_per_pixel >= 16) {
2756 vga_wgfx(regbase, CL_GR10, bg_color >> 8);
2757 vga_wgfx(regbase, CL_GR11, fg_color >> 8);
2758 op = 0x90;
2760 if (bits_per_pixel == 32) {
2761 vga_wgfx(regbase, CL_GR12, bg_color >> 16);
2762 vga_wgfx(regbase, CL_GR13, fg_color >> 16);
2763 vga_wgfx(regbase, CL_GR14, bg_color >> 24);
2764 vga_wgfx(regbase, CL_GR15, fg_color >> 24);
2765 op = 0xb0;
2767 cirrusfb_set_blitter(regbase, width - 1, height - 1,
2768 0, ndest, op | blitmode, line_length);
2771 /**************************************************************************
2772 * bestclock() - determine closest possible clock lower(?) than the
2773 * desired pixel clock
2774 **************************************************************************/
2775 static void bestclock(long freq, int *nom, int *den, int *div)
2777 int n, d;
2778 long h, diff;
2780 assert(nom != NULL);
2781 assert(den != NULL);
2782 assert(div != NULL);
2784 *nom = 0;
2785 *den = 0;
2786 *div = 0;
2788 if (freq < 8000)
2789 freq = 8000;
2791 diff = freq;
2793 for (n = 32; n < 128; n++) {
2794 int s = 0;
2796 d = (14318 * n) / freq;
2797 if ((d >= 7) && (d <= 63)) {
2798 int temp = d;
2800 if (temp > 31) {
2801 s = 1;
2802 temp >>= 1;
2804 h = ((14318 * n) / temp) >> s;
2805 h = h > freq ? h - freq : freq - h;
2806 if (h < diff) {
2807 diff = h;
2808 *nom = n;
2809 *den = temp;
2810 *div = s;
2813 d++;
2814 if ((d >= 7) && (d <= 63)) {
2815 if (d > 31) {
2816 s = 1;
2817 d >>= 1;
2819 h = ((14318 * n) / d) >> s;
2820 h = h > freq ? h - freq : freq - h;
2821 if (h < diff) {
2822 diff = h;
2823 *nom = n;
2824 *den = d;
2825 *div = s;
2831 /* -------------------------------------------------------------------------
2833 * debugging functions
2835 * -------------------------------------------------------------------------
2838 #ifdef CIRRUSFB_DEBUG
2841 * cirrusfb_dbg_print_regs
2842 * @base: If using newmmio, the newmmio base address, otherwise %NULL
2843 * @reg_class: type of registers to read: %CRT, or %SEQ
2845 * DESCRIPTION:
2846 * Dumps the given list of VGA CRTC registers. If @base is %NULL,
2847 * old-style I/O ports are queried for information, otherwise MMIO is
2848 * used at the given @base address to query the information.
2851 static void cirrusfb_dbg_print_regs(struct fb_info *info,
2852 caddr_t regbase,
2853 enum cirrusfb_dbg_reg_class reg_class, ...)
2855 va_list list;
2856 unsigned char val = 0;
2857 unsigned reg;
2858 char *name;
2860 va_start(list, reg_class);
2862 name = va_arg(list, char *);
2863 while (name != NULL) {
2864 reg = va_arg(list, int);
2866 switch (reg_class) {
2867 case CRT:
2868 val = vga_rcrt(regbase, (unsigned char) reg);
2869 break;
2870 case SEQ:
2871 val = vga_rseq(regbase, (unsigned char) reg);
2872 break;
2873 default:
2874 /* should never occur */
2875 assert(false);
2876 break;
2879 dev_dbg(info->device, "%8s = 0x%02X\n", name, val);
2881 name = va_arg(list, char *);
2884 va_end(list);
2888 * cirrusfb_dbg_reg_dump
2889 * @base: If using newmmio, the newmmio base address, otherwise %NULL
2891 * DESCRIPTION:
2892 * Dumps a list of interesting VGA and CIRRUSFB registers. If @base is %NULL,
2893 * old-style I/O ports are queried for information, otherwise MMIO is
2894 * used at the given @base address to query the information.
2897 static void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase)
2899 dev_dbg(info->device, "VGA CRTC register dump:\n");
2901 cirrusfb_dbg_print_regs(info, regbase, CRT,
2902 "CR00", 0x00,
2903 "CR01", 0x01,
2904 "CR02", 0x02,
2905 "CR03", 0x03,
2906 "CR04", 0x04,
2907 "CR05", 0x05,
2908 "CR06", 0x06,
2909 "CR07", 0x07,
2910 "CR08", 0x08,
2911 "CR09", 0x09,
2912 "CR0A", 0x0A,
2913 "CR0B", 0x0B,
2914 "CR0C", 0x0C,
2915 "CR0D", 0x0D,
2916 "CR0E", 0x0E,
2917 "CR0F", 0x0F,
2918 "CR10", 0x10,
2919 "CR11", 0x11,
2920 "CR12", 0x12,
2921 "CR13", 0x13,
2922 "CR14", 0x14,
2923 "CR15", 0x15,
2924 "CR16", 0x16,
2925 "CR17", 0x17,
2926 "CR18", 0x18,
2927 "CR22", 0x22,
2928 "CR24", 0x24,
2929 "CR26", 0x26,
2930 "CR2D", 0x2D,
2931 "CR2E", 0x2E,
2932 "CR2F", 0x2F,
2933 "CR30", 0x30,
2934 "CR31", 0x31,
2935 "CR32", 0x32,
2936 "CR33", 0x33,
2937 "CR34", 0x34,
2938 "CR35", 0x35,
2939 "CR36", 0x36,
2940 "CR37", 0x37,
2941 "CR38", 0x38,
2942 "CR39", 0x39,
2943 "CR3A", 0x3A,
2944 "CR3B", 0x3B,
2945 "CR3C", 0x3C,
2946 "CR3D", 0x3D,
2947 "CR3E", 0x3E,
2948 "CR3F", 0x3F,
2949 NULL);
2951 dev_dbg(info->device, "\n");
2953 dev_dbg(info->device, "VGA SEQ register dump:\n");
2955 cirrusfb_dbg_print_regs(info, regbase, SEQ,
2956 "SR00", 0x00,
2957 "SR01", 0x01,
2958 "SR02", 0x02,
2959 "SR03", 0x03,
2960 "SR04", 0x04,
2961 "SR08", 0x08,
2962 "SR09", 0x09,
2963 "SR0A", 0x0A,
2964 "SR0B", 0x0B,
2965 "SR0D", 0x0D,
2966 "SR10", 0x10,
2967 "SR11", 0x11,
2968 "SR12", 0x12,
2969 "SR13", 0x13,
2970 "SR14", 0x14,
2971 "SR15", 0x15,
2972 "SR16", 0x16,
2973 "SR17", 0x17,
2974 "SR18", 0x18,
2975 "SR19", 0x19,
2976 "SR1A", 0x1A,
2977 "SR1B", 0x1B,
2978 "SR1C", 0x1C,
2979 "SR1D", 0x1D,
2980 "SR1E", 0x1E,
2981 "SR1F", 0x1F,
2982 NULL);
2984 dev_dbg(info->device, "\n");
2987 #endif /* CIRRUSFB_DEBUG */