1/*
2 * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
3 *
4 * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
5 *
6 * Contributors (thanks, all!)
7 *
8 * David Eger:
9 * Overhaul for Linux 2.6
10 *
11 * Jeff Rugen:
12 * Major contributions; Motorola PowerStack (PPC and PCI) support,
13 * GD54xx, 1280x1024 mode support, change MCLK based on VCLK.
14 *
15 * Geert Uytterhoeven:
16 * Excellent code review.
17 *
18 * Lars Hecking:
19 * Amiga updates and testing.
20 *
21 * Original cirrusfb author: Frank Neumann
22 *
23 * Based on retz3fb.c and cirrusfb.c:
24 * Copyright (C) 1997 Jes Sorensen
25 * Copyright (C) 1996 Frank Neumann
26 *
27 ***************************************************************
28 *
29 * Format this code with GNU indent '-kr -i8 -pcs' options.
30 *
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.
34 *
35 */
36
37#include <linux/aperture.h>
38#include <linux/module.h>
39#include <linux/kernel.h>
40#include <linux/errno.h>
41#include <linux/string.h>
42#include <linux/mm.h>
43#include <linux/delay.h>
44#include <linux/fb.h>
45#include <linux/init.h>
46
47#ifdef CONFIG_ZORRO
48#include <linux/zorro.h>
49#endif
50#ifdef CONFIG_PCI
51#include <linux/pci.h>
52#endif
53#ifdef CONFIG_AMIGA
54#include <asm/amigahw.h>
55#endif
56
57#include <video/vga.h>
58#include <video/cirrus.h>
59
60/*****************************************************************
61 *
62 * debugging and utility macros
63 *
64 */
65
66/* disable runtime assertions? */
67/* #define CIRRUSFB_NDEBUG */
68
69/* debugging assertions */
70#ifndef CIRRUSFB_NDEBUG
71#define assert(expr) \
72 if (!(expr)) { \
73 printk("Assertion failed! %s,%s,%s,line=%d\n", \
74 #expr, __FILE__, __func__, __LINE__); \
75 }
76#else
77#define assert(expr)
78#endif
79
80#define MB_ (1024 * 1024)
81
82/*****************************************************************
83 *
84 * chipset information
85 *
86 */
87
88/* board types */
89enum cirrus_board {
90 BT_NONE = 0,
91 BT_SD64, /* GD5434 */
92 BT_PICCOLO, /* GD5426 */
93 BT_PICASSO, /* GD5426 or GD5428 */
94 BT_SPECTRUM, /* GD5426 or GD5428 */
95 BT_PICASSO4, /* GD5446 */
96 BT_ALPINE, /* GD543x/4x */
97 BT_GD5480,
98 BT_LAGUNA, /* GD5462/64 */
99 BT_LAGUNAB, /* GD5465 */
100};
101
102/*
103 * per-board-type information, used for enumerating and abstracting
104 * chip-specific information
105 * NOTE: MUST be in the same order as enum cirrus_board in order to
106 * use direct indexing on this array
107 * NOTE: '__initdata' cannot be used as some of this info
108 * is required at runtime. Maybe separate into an init-only and
109 * a run-time table?
110 */
111static const struct cirrusfb_board_info_rec {
112 char *name; /* ASCII name of chipset */
113 long maxclock[5]; /* maximum video clock */
114 /* for 1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */
115 bool init_sr07 : 1; /* init SR07 during init_vgachip() */
116 bool init_sr1f : 1; /* write SR1F during init_vgachip() */
117 /* construct bit 19 of screen start address */
118 bool scrn_start_bit19 : 1;
119
120 /* initial SR07 value, then for each mode */
121 unsigned char sr07;
122 unsigned char sr07_1bpp;
123 unsigned char sr07_1bpp_mux;
124 unsigned char sr07_8bpp;
125 unsigned char sr07_8bpp_mux;
126
127 unsigned char sr1f; /* SR1F VGA initial register value */
128} cirrusfb_board_info[] = {
129 [BT_SD64] = {
130 .name = "CL SD64",
131 .maxclock = {
132 /* guess */
133 /* the SD64/P4 have a higher max. videoclock */
134 135100, 135100, 85500, 85500, 0
135 },
136 .init_sr07 = true,
137 .init_sr1f = true,
138 .scrn_start_bit19 = true,
139 .sr07 = 0xF0,
140 .sr07_1bpp = 0xF0,
141 .sr07_1bpp_mux = 0xF6,
142 .sr07_8bpp = 0xF1,
143 .sr07_8bpp_mux = 0xF7,
144 .sr1f = 0x1E
145 },
146 [BT_PICCOLO] = {
147 .name = "CL Piccolo",
148 .maxclock = {
149 /* guess */
150 90000, 90000, 90000, 90000, 90000
151 },
152 .init_sr07 = true,
153 .init_sr1f = true,
154 .scrn_start_bit19 = false,
155 .sr07 = 0x80,
156 .sr07_1bpp = 0x80,
157 .sr07_8bpp = 0x81,
158 .sr1f = 0x22
159 },
160 [BT_PICASSO] = {
161 .name = "CL Picasso",
162 .maxclock = {
163 /* guess */
164 90000, 90000, 90000, 90000, 90000
165 },
166 .init_sr07 = true,
167 .init_sr1f = true,
168 .scrn_start_bit19 = false,
169 .sr07 = 0x20,
170 .sr07_1bpp = 0x20,
171 .sr07_8bpp = 0x21,
172 .sr1f = 0x22
173 },
174 [BT_SPECTRUM] = {
175 .name = "CL Spectrum",
176 .maxclock = {
177 /* guess */
178 90000, 90000, 90000, 90000, 90000
179 },
180 .init_sr07 = true,
181 .init_sr1f = true,
182 .scrn_start_bit19 = false,
183 .sr07 = 0x80,
184 .sr07_1bpp = 0x80,
185 .sr07_8bpp = 0x81,
186 .sr1f = 0x22
187 },
188 [BT_PICASSO4] = {
189 .name = "CL Picasso4",
190 .maxclock = {
191 135100, 135100, 85500, 85500, 0
192 },
193 .init_sr07 = true,
194 .init_sr1f = false,
195 .scrn_start_bit19 = true,
196 .sr07 = 0xA0,
197 .sr07_1bpp = 0xA0,
198 .sr07_1bpp_mux = 0xA6,
199 .sr07_8bpp = 0xA1,
200 .sr07_8bpp_mux = 0xA7,
201 .sr1f = 0
202 },
203 [BT_ALPINE] = {
204 .name = "CL Alpine",
205 .maxclock = {
206 /* for the GD5430. GD5446 can do more... */
207 85500, 85500, 50000, 28500, 0
208 },
209 .init_sr07 = true,
210 .init_sr1f = true,
211 .scrn_start_bit19 = true,
212 .sr07 = 0xA0,
213 .sr07_1bpp = 0xA0,
214 .sr07_1bpp_mux = 0xA6,
215 .sr07_8bpp = 0xA1,
216 .sr07_8bpp_mux = 0xA7,
217 .sr1f = 0x1C
218 },
219 [BT_GD5480] = {
220 .name = "CL GD5480",
221 .maxclock = {
222 135100, 200000, 200000, 135100, 135100
223 },
224 .init_sr07 = true,
225 .init_sr1f = true,
226 .scrn_start_bit19 = true,
227 .sr07 = 0x10,
228 .sr07_1bpp = 0x11,
229 .sr07_8bpp = 0x11,
230 .sr1f = 0x1C
231 },
232 [BT_LAGUNA] = {
233 .name = "CL Laguna",
234 .maxclock = {
235 /* taken from X11 code */
236 170000, 170000, 170000, 170000, 135100,
237 },
238 .init_sr07 = false,
239 .init_sr1f = false,
240 .scrn_start_bit19 = true,
241 },
242 [BT_LAGUNAB] = {
243 .name = "CL Laguna AGP",
244 .maxclock = {
245 /* taken from X11 code */
246 170000, 250000, 170000, 170000, 135100,
247 },
248 .init_sr07 = false,
249 .init_sr1f = false,
250 .scrn_start_bit19 = true,
251 }
252};
253
254#ifdef CONFIG_PCI
255#define CHIP(id, btype) \
256 { PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
257
258static struct pci_device_id cirrusfb_pci_table[] = {
259 CHIP(PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE),
260 CHIP(PCI_DEVICE_ID_CIRRUS_5434_8, BT_SD64),
261 CHIP(PCI_DEVICE_ID_CIRRUS_5434_4, BT_SD64),
262 CHIP(PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE), /* GD-5440 is same id */
263 CHIP(PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE),
264 CHIP(PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE),
265 CHIP(PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480), /* MacPicasso likely */
266 CHIP(PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4), /* Picasso 4 is 5446 */
267 CHIP(PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA), /* CL Laguna */
268 CHIP(PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA), /* CL Laguna 3D */
269 CHIP(PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNAB), /* CL Laguna 3DA*/
270 { 0, }
271};
272MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
273#undef CHIP
274#endif /* CONFIG_PCI */
275
276#ifdef CONFIG_ZORRO
277struct zorrocl {
278 enum cirrus_board type; /* Board type */
279 u32 regoffset; /* Offset of registers in first Zorro device */
280 u32 ramsize; /* Size of video RAM in first Zorro device */
281 /* If zero, use autoprobe on RAM device */
282 u32 ramoffset; /* Offset of video RAM in first Zorro device */
283 zorro_id ramid; /* Zorro ID of RAM device */
284 zorro_id ramid2; /* Zorro ID of optional second RAM device */
285};
286
287static const struct zorrocl zcl_sd64 = {
288 .type = BT_SD64,
289 .ramid = ZORRO_PROD_HELFRICH_SD64_RAM,
290};
291
292static const struct zorrocl zcl_piccolo = {
293 .type = BT_PICCOLO,
294 .ramid = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
295};
296
297static const struct zorrocl zcl_picasso = {
298 .type = BT_PICASSO,
299 .ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
300};
301
302static const struct zorrocl zcl_spectrum = {
303 .type = BT_SPECTRUM,
304 .ramid = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
305};
306
307static const struct zorrocl zcl_picasso4_z3 = {
308 .type = BT_PICASSO4,
309 .regoffset = 0x00600000,
310 .ramsize = 4 * MB_,
311 .ramoffset = 0x01000000, /* 0x02000000 for 64 MiB boards */
312};
313
314static const struct zorrocl zcl_picasso4_z2 = {
315 .type = BT_PICASSO4,
316 .regoffset = 0x10000,
317 .ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM1,
318 .ramid2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM2,
319};
320
321
322static const struct zorro_device_id cirrusfb_zorro_table[] = {
323 {
324 .id = ZORRO_PROD_HELFRICH_SD64_REG,
325 .driver_data = (unsigned long)&zcl_sd64,
326 }, {
327 .id = ZORRO_PROD_HELFRICH_PICCOLO_REG,
328 .driver_data = (unsigned long)&zcl_piccolo,
329 }, {
330 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
331 .driver_data = (unsigned long)&zcl_picasso,
332 }, {
333 .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
334 .driver_data = (unsigned long)&zcl_spectrum,
335 }, {
336 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
337 .driver_data = (unsigned long)&zcl_picasso4_z3,
338 }, {
339 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_REG,
340 .driver_data = (unsigned long)&zcl_picasso4_z2,
341 },
342 { 0 }
343};
344MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table);
345#endif /* CONFIG_ZORRO */
346
347#ifdef CIRRUSFB_DEBUG
348enum cirrusfb_dbg_reg_class {
349 CRT,
350 SEQ
351};
352#endif /* CIRRUSFB_DEBUG */
353
354/* info about board */
355struct cirrusfb_info {
356 u8 __iomem *regbase;
357 u8 __iomem *laguna_mmio;
358 enum cirrus_board btype;
359 unsigned char SFR; /* Shadow of special function register */
360
361 int multiplexing;
362 int doubleVCLK;
363 int blank_mode;
364 u32 pseudo_palette[16];
365
366 void (*unmap)(struct fb_info *info);
367};
368
369static bool noaccel;
370static char *mode_option = "640x480@60";
371
372/****************************************************************************/
373/**** BEGIN PROTOTYPES ******************************************************/
374
375/*--- Interface used by the world ------------------------------------------*/
376static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
377 struct fb_info *info);
378
379/*--- Internal routines ----------------------------------------------------*/
380static void init_vgachip(struct fb_info *info);
381static void switch_monitor(struct cirrusfb_info *cinfo, int on);
382static void WGen(const struct cirrusfb_info *cinfo,
383 int regnum, unsigned char val);
384static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum);
385static void AttrOn(const struct cirrusfb_info *cinfo);
386static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val);
387static void WSFR(struct cirrusfb_info *cinfo, unsigned char val);
388static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val);
389static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum,
390 unsigned char red, unsigned char green, unsigned char blue);
391#if 0
392static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum,
393 unsigned char *red, unsigned char *green,
394 unsigned char *blue);
395#endif
396static void cirrusfb_WaitBLT(u8 __iomem *regbase);
397static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
398 u_short curx, u_short cury,
399 u_short destx, u_short desty,
400 u_short width, u_short height,
401 u_short line_length);
402static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
403 u_short x, u_short y,
404 u_short width, u_short height,
405 u32 fg_color, u32 bg_color,
406 u_short line_length, u_char blitmode);
407
408static void bestclock(long freq, int *nom, int *den, int *div);
409
410#ifdef CIRRUSFB_DEBUG
411static void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase);
412static void cirrusfb_dbg_print_regs(struct fb_info *info,
413 caddr_t regbase,
414 enum cirrusfb_dbg_reg_class reg_class, ...);
415#endif /* CIRRUSFB_DEBUG */
416
417/*** END PROTOTYPES ********************************************************/
418/*****************************************************************************/
419/*** BEGIN Interface Used by the World ***************************************/
420
421static inline int is_laguna(const struct cirrusfb_info *cinfo)
422{
423 return cinfo->btype == BT_LAGUNA || cinfo->btype == BT_LAGUNAB;
424}
425
426static int opencount;
427
428/*--- Open /dev/fbx ---------------------------------------------------------*/
429static int cirrusfb_open(struct fb_info *info, int user)
430{
431 if (opencount++ == 0)
432 switch_monitor(cinfo: info->par, on: 1);
433 return 0;
434}
435
436/*--- Close /dev/fbx --------------------------------------------------------*/
437static int cirrusfb_release(struct fb_info *info, int user)
438{
439 if (--opencount == 0)
440 switch_monitor(cinfo: info->par, on: 0);
441 return 0;
442}
443
444/**** END Interface used by the World *************************************/
445/****************************************************************************/
446/**** BEGIN Hardware specific Routines **************************************/
447
448/* Check if the MCLK is not a better clock source */
449static int cirrusfb_check_mclk(struct fb_info *info, long freq)
450{
451 struct cirrusfb_info *cinfo = info->par;
452 long mclk = vga_rseq(regbase: cinfo->regbase, CL_SEQR1F) & 0x3f;
453
454 /* Read MCLK value */
455 mclk = (14318 * mclk) >> 3;
456 dev_dbg(info->device, "Read MCLK of %ld kHz\n", mclk);
457
458 /* Determine if we should use MCLK instead of VCLK, and if so, what we
459 * should divide it by to get VCLK
460 */
461
462 if (abs(freq - mclk) < 250) {
463 dev_dbg(info->device, "Using VCLK = MCLK\n");
464 return 1;
465 } else if (abs(freq - (mclk / 2)) < 250) {
466 dev_dbg(info->device, "Using VCLK = MCLK/2\n");
467 return 2;
468 }
469
470 return 0;
471}
472
473static int cirrusfb_check_pixclock(struct fb_var_screeninfo *var,
474 struct fb_info *info)
475{
476 long freq;
477 long maxclock;
478 struct cirrusfb_info *cinfo = info->par;
479 unsigned maxclockidx = var->bits_per_pixel >> 3;
480
481 /* convert from ps to kHz */
482 freq = PICOS2KHZ(var->pixclock ? : 1);
483
484 maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
485 cinfo->multiplexing = 0;
486
487 /* If the frequency is greater than we can support, we might be able
488 * to use multiplexing for the video mode */
489 if (freq > maxclock) {
490 var->pixclock = KHZ2PICOS(maxclock);
491
492 while ((freq = PICOS2KHZ(var->pixclock)) > maxclock)
493 var->pixclock++;
494 }
495 dev_dbg(info->device, "desired pixclock: %ld kHz\n", freq);
496
497 /*
498 * Additional constraint: 8bpp uses DAC clock doubling to allow maximum
499 * pixel clock
500 */
501 if (var->bits_per_pixel == 8) {
502 switch (cinfo->btype) {
503 case BT_ALPINE:
504 case BT_SD64:
505 case BT_PICASSO4:
506 if (freq > 85500)
507 cinfo->multiplexing = 1;
508 break;
509 case BT_GD5480:
510 if (freq > 135100)
511 cinfo->multiplexing = 1;
512 break;
513
514 default:
515 break;
516 }
517 }
518
519 /* If we have a 1MB 5434, we need to put ourselves in a mode where
520 * the VCLK is double the pixel clock. */
521 cinfo->doubleVCLK = 0;
522 if (cinfo->btype == BT_SD64 && info->fix.smem_len <= MB_ &&
523 var->bits_per_pixel == 16) {
524 cinfo->doubleVCLK = 1;
525 }
526
527 return 0;
528}
529
530static int cirrusfb_check_var(struct fb_var_screeninfo *var,
531 struct fb_info *info)
532{
533 int yres;
534 /* memory size in pixels */
535 unsigned int pixels;
536 struct cirrusfb_info *cinfo = info->par;
537
538 switch (var->bits_per_pixel) {
539 case 1:
540 var->red.offset = 0;
541 var->red.length = 1;
542 var->green = var->red;
543 var->blue = var->red;
544 break;
545
546 case 8:
547 var->red.offset = 0;
548 var->red.length = 8;
549 var->green = var->red;
550 var->blue = var->red;
551 break;
552
553 case 16:
554 var->red.offset = 11;
555 var->green.offset = 5;
556 var->blue.offset = 0;
557 var->red.length = 5;
558 var->green.length = 6;
559 var->blue.length = 5;
560 break;
561
562 case 24:
563 var->red.offset = 16;
564 var->green.offset = 8;
565 var->blue.offset = 0;
566 var->red.length = 8;
567 var->green.length = 8;
568 var->blue.length = 8;
569 break;
570
571 default:
572 dev_dbg(info->device,
573 "Unsupported bpp size: %d\n", var->bits_per_pixel);
574 return -EINVAL;
575 }
576
577 pixels = info->screen_size * 8 / var->bits_per_pixel;
578 if (var->xres_virtual < var->xres)
579 var->xres_virtual = var->xres;
580 /* use highest possible virtual resolution */
581 if (var->yres_virtual == -1) {
582 var->yres_virtual = pixels / var->xres_virtual;
583
584 dev_info(info->device,
585 "virtual resolution set to maximum of %dx%d\n",
586 var->xres_virtual, var->yres_virtual);
587 }
588 if (var->yres_virtual < var->yres)
589 var->yres_virtual = var->yres;
590
591 if (var->xres_virtual * var->yres_virtual > pixels) {
592 dev_err(info->device, "mode %dx%dx%d rejected... "
593 "virtual resolution too high to fit into video memory!\n",
594 var->xres_virtual, var->yres_virtual,
595 var->bits_per_pixel);
596 return -EINVAL;
597 }
598
599 /* truncate xoffset and yoffset to maximum if too high */
600 if (var->xoffset > var->xres_virtual - var->xres)
601 var->xoffset = var->xres_virtual - var->xres - 1;
602 if (var->yoffset > var->yres_virtual - var->yres)
603 var->yoffset = var->yres_virtual - var->yres - 1;
604
605 var->red.msb_right =
606 var->green.msb_right =
607 var->blue.msb_right =
608 var->transp.offset =
609 var->transp.length =
610 var->transp.msb_right = 0;
611
612 yres = var->yres;
613 if (var->vmode & FB_VMODE_DOUBLE)
614 yres *= 2;
615 else if (var->vmode & FB_VMODE_INTERLACED)
616 yres = (yres + 1) / 2;
617
618 if (yres >= 1280) {
619 dev_err(info->device, "ERROR: VerticalTotal >= 1280; "
620 "special treatment required! (TODO)\n");
621 return -EINVAL;
622 }
623
624 if (cirrusfb_check_pixclock(var, info))
625 return -EINVAL;
626
627 if (!is_laguna(cinfo))
628 var->accel_flags = FB_ACCELF_TEXT;
629
630 return 0;
631}
632
633static void cirrusfb_set_mclk_as_source(const struct fb_info *info, int div)
634{
635 struct cirrusfb_info *cinfo = info->par;
636 unsigned char old1f, old1e;
637
638 assert(cinfo != NULL);
639 old1f = vga_rseq(regbase: cinfo->regbase, CL_SEQR1F) & ~0x40;
640
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(regbase: cinfo->regbase, CL_SEQR1E) & ~0x1;
646 if (div == 2)
647 old1e |= 1;
648
649 vga_wseq(regbase: cinfo->regbase, CL_SEQR1E, val: old1e);
650 }
651 vga_wseq(regbase: cinfo->regbase, CL_SEQR1F, val: old1f);
652}
653
654/*************************************************************************
655 cirrusfb_set_par_foo()
656
657 actually writes the values for a new video mode into the hardware,
658**************************************************************************/
659static int cirrusfb_set_par_foo(struct fb_info *info)
660{
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;
672
673 dev_dbg(info->device, "Requested mode: %dx%dx%d\n",
674 var->xres, var->yres, var->bits_per_pixel);
675
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;
681
682 case 8:
683 info->fix.line_length = var->xres_virtual;
684 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
685 break;
686
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;
693 }
694 info->fix.type = FB_TYPE_PACKED_PIXELS;
695
696 init_vgachip(info);
697
698 bi = &cirrusfb_board_info[cinfo->btype];
699
700 hsyncstart = var->xres + var->right_margin;
701 hsyncend = hsyncstart + var->hsync_len;
702 htotal = (hsyncend + var->left_margin) / 8;
703 hdispend = var->xres / 8;
704 hsyncstart = hsyncstart / 8;
705 hsyncend = hsyncend / 8;
706
707 vdispend = var->yres;
708 vsyncstart = vdispend + var->lower_margin;
709 vsyncend = vsyncstart + var->vsync_len;
710 vtotal = vsyncend + var->upper_margin;
711
712 if (var->vmode & FB_VMODE_DOUBLE) {
713 vdispend *= 2;
714 vsyncstart *= 2;
715 vsyncend *= 2;
716 vtotal *= 2;
717 } else if (var->vmode & FB_VMODE_INTERLACED) {
718 vdispend = (vdispend + 1) / 2;
719 vsyncstart = (vsyncstart + 1) / 2;
720 vsyncend = (vsyncend + 1) / 2;
721 vtotal = (vtotal + 1) / 2;
722 }
723 yres = vdispend;
724 if (yres >= 1024) {
725 vtotal /= 2;
726 vsyncstart /= 2;
727 vsyncend /= 2;
728 vdispend /= 2;
729 }
730
731 vdispend -= 1;
732 vsyncstart -= 1;
733 vsyncend -= 1;
734 vtotal -= 2;
735
736 if (cinfo->multiplexing) {
737 htotal /= 2;
738 hsyncstart /= 2;
739 hsyncend /= 2;
740 hdispend /= 2;
741 }
742
743 htotal -= 5;
744 hdispend -= 1;
745 hsyncstart += 1;
746 hsyncend += 1;
747
748 /* unlock register VGA_CRTC_H_TOTAL..CRT7 */
749 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, val: 0x20); /* previously: 0x00) */
750
751 /* if debugging is enabled, all parameters get output before writing */
752 dev_dbg(info->device, "CRT0: %d\n", htotal);
753 vga_wcrt(regbase, VGA_CRTC_H_TOTAL, val: htotal);
754
755 dev_dbg(info->device, "CRT1: %d\n", hdispend);
756 vga_wcrt(regbase, VGA_CRTC_H_DISP, val: hdispend);
757
758 dev_dbg(info->device, "CRT2: %d\n", var->xres / 8);
759 vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, val: var->xres / 8);
760
761 /* + 128: Compatible read */
762 dev_dbg(info->device, "CRT3: 128+%d\n", (htotal + 5) % 32);
763 vga_wcrt(regbase, VGA_CRTC_H_BLANK_END,
764 val: 128 + ((htotal + 5) % 32));
765
766 dev_dbg(info->device, "CRT4: %d\n", hsyncstart);
767 vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, val: hsyncstart);
768
769 tmp = hsyncend % 32;
770 if ((htotal + 5) & 32)
771 tmp += 128;
772 dev_dbg(info->device, "CRT5: %d\n", tmp);
773 vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, val: tmp);
774
775 dev_dbg(info->device, "CRT6: %d\n", vtotal & 0xff);
776 vga_wcrt(regbase, VGA_CRTC_V_TOTAL, val: vtotal & 0xff);
777
778 tmp = 16; /* LineCompare bit #9 */
779 if (vtotal & 256)
780 tmp |= 1;
781 if (vdispend & 256)
782 tmp |= 2;
783 if (vsyncstart & 256)
784 tmp |= 4;
785 if ((vdispend + 1) & 256)
786 tmp |= 8;
787 if (vtotal & 512)
788 tmp |= 32;
789 if (vdispend & 512)
790 tmp |= 64;
791 if (vsyncstart & 512)
792 tmp |= 128;
793 dev_dbg(info->device, "CRT7: %d\n", tmp);
794 vga_wcrt(regbase, VGA_CRTC_OVERFLOW, val: tmp);
795
796 tmp = 0x40; /* LineCompare bit #8 */
797 if ((vdispend + 1) & 512)
798 tmp |= 0x20;
799 if (var->vmode & FB_VMODE_DOUBLE)
800 tmp |= 0x80;
801 dev_dbg(info->device, "CRT9: %d\n", tmp);
802 vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, val: tmp);
803
804 dev_dbg(info->device, "CRT10: %d\n", vsyncstart & 0xff);
805 vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, val: vsyncstart & 0xff);
806
807 dev_dbg(info->device, "CRT11: 64+32+%d\n", vsyncend % 16);
808 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, val: vsyncend % 16 + 64 + 32);
809
810 dev_dbg(info->device, "CRT12: %d\n", vdispend & 0xff);
811 vga_wcrt(regbase, VGA_CRTC_V_DISP_END, val: vdispend & 0xff);
812
813 dev_dbg(info->device, "CRT15: %d\n", (vdispend + 1) & 0xff);
814 vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, val: (vdispend + 1) & 0xff);
815
816 dev_dbg(info->device, "CRT16: %d\n", vtotal & 0xff);
817 vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, val: vtotal & 0xff);
818
819 dev_dbg(info->device, "CRT18: 0xff\n");
820 vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, val: 0xff);
821
822 tmp = 0;
823 if (var->vmode & FB_VMODE_INTERLACED)
824 tmp |= 1;
825 if ((htotal + 5) & 64)
826 tmp |= 16;
827 if ((htotal + 5) & 128)
828 tmp |= 32;
829 if (vtotal & 256)
830 tmp |= 64;
831 if (vtotal & 512)
832 tmp |= 128;
833
834 dev_dbg(info->device, "CRT1a: %d\n", tmp);
835 vga_wcrt(regbase, CL_CRT1A, val: tmp);
836
837 freq = PICOS2KHZ(var->pixclock);
838 if (var->bits_per_pixel == 24)
839 if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64)
840 freq *= 3;
841 if (cinfo->multiplexing)
842 freq /= 2;
843 if (cinfo->doubleVCLK)
844 freq *= 2;
845
846 bestclock(freq, nom: &nom, den: &den, div: &div);
847
848 dev_dbg(info->device, "VCLK freq: %ld kHz nom: %d den: %d div: %d\n",
849 freq, nom, den, div);
850
851 /* set VCLK0 */
852 /* hardware RefClock: 14.31818 MHz */
853 /* formula: VClk = (OSC * N) / (D * (1+P)) */
854 /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
855
856 if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_PICASSO4 ||
857 cinfo->btype == BT_SD64) {
858 /* if freq is close to mclk or mclk/2 select mclk
859 * as clock source
860 */
861 int divMCLK = cirrusfb_check_mclk(info, freq);
862 if (divMCLK)
863 nom = 0;
864 cirrusfb_set_mclk_as_source(info, div: divMCLK);
865 }
866 if (is_laguna(cinfo)) {
867 long pcifc = fb_readl(addr: cinfo->laguna_mmio + 0x3fc);
868 unsigned char tile = fb_readb(addr: cinfo->laguna_mmio + 0x407);
869 unsigned short tile_control;
870
871 if (cinfo->btype == BT_LAGUNAB) {
872 tile_control = fb_readw(addr: cinfo->laguna_mmio + 0x2c4);
873 tile_control &= ~0x80;
874 fb_writew(b: tile_control, addr: cinfo->laguna_mmio + 0x2c4);
875 }
876
877 fb_writel(b: pcifc | 0x10000000l, addr: cinfo->laguna_mmio + 0x3fc);
878 fb_writeb(b: tile & 0x3f, addr: cinfo->laguna_mmio + 0x407);
879 control = fb_readw(addr: cinfo->laguna_mmio + 0x402);
880 threshold = fb_readw(addr: cinfo->laguna_mmio + 0xea);
881 control &= ~0x6800;
882 format = 0;
883 threshold &= 0xffc0 & 0x3fbf;
884 }
885 if (nom) {
886 tmp = den << 1;
887 if (div != 0)
888 tmp |= 1;
889 /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
890 if ((cinfo->btype == BT_SD64) ||
891 (cinfo->btype == BT_ALPINE) ||
892 (cinfo->btype == BT_GD5480))
893 tmp |= 0x80;
894
895 /* Laguna chipset has reversed clock registers */
896 if (is_laguna(cinfo)) {
897 vga_wseq(regbase, CL_SEQRE, val: tmp);
898 vga_wseq(regbase, CL_SEQR1E, val: nom);
899 } else {
900 vga_wseq(regbase, CL_SEQRE, val: nom);
901 vga_wseq(regbase, CL_SEQR1E, val: tmp);
902 }
903 }
904
905 if (yres >= 1024)
906 /* 1280x1024 */
907 vga_wcrt(regbase, VGA_CRTC_MODE, val: 0xc7);
908 else
909 /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
910 * address wrap, no compat. */
911 vga_wcrt(regbase, VGA_CRTC_MODE, val: 0xc3);
912
913 /* don't know if it would hurt to also program this if no interlaced */
914 /* mode is used, but I feel better this way.. :-) */
915 if (var->vmode & FB_VMODE_INTERLACED)
916 vga_wcrt(regbase, VGA_CRTC_REGS, val: htotal / 2);
917 else
918 vga_wcrt(regbase, VGA_CRTC_REGS, val: 0x00); /* interlace control */
919
920 /* adjust horizontal/vertical sync type (low/high), use VCLK3 */
921 /* enable display memory & CRTC I/O address for color mode */
922 tmp = 0x03 | 0xc;
923 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
924 tmp |= 0x40;
925 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
926 tmp |= 0x80;
927 WGen(cinfo, VGA_MIS_W, val: tmp);
928
929 /* text cursor on and start line */
930 vga_wcrt(regbase, VGA_CRTC_CURSOR_START, val: 0);
931 /* text cursor end line */
932 vga_wcrt(regbase, VGA_CRTC_CURSOR_END, val: 31);
933
934 /******************************************************
935 *
936 * 1 bpp
937 *
938 */
939
940 /* programming for different color depths */
941 if (var->bits_per_pixel == 1) {
942 dev_dbg(info->device, "preparing for 1 bit deep display\n");
943 vga_wgfx(regbase, VGA_GFX_MODE, val: 0); /* mode register */
944
945 /* SR07 */
946 switch (cinfo->btype) {
947 case BT_SD64:
948 case BT_PICCOLO:
949 case BT_PICASSO:
950 case BT_SPECTRUM:
951 case BT_PICASSO4:
952 case BT_ALPINE:
953 case BT_GD5480:
954 vga_wseq(regbase, CL_SEQR7,
955 val: cinfo->multiplexing ?
956 bi->sr07_1bpp_mux : bi->sr07_1bpp);
957 break;
958
959 case BT_LAGUNA:
960 case BT_LAGUNAB:
961 vga_wseq(regbase, CL_SEQR7,
962 val: vga_rseq(regbase, CL_SEQR7) & ~0x01);
963 break;
964
965 default:
966 dev_warn(info->device, "unknown Board\n");
967 break;
968 }
969
970 /* Extended Sequencer Mode */
971 switch (cinfo->btype) {
972
973 case BT_PICCOLO:
974 case BT_SPECTRUM:
975 /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
976 vga_wseq(regbase, CL_SEQRF, val: 0xb0);
977 break;
978
979 case BT_PICASSO:
980 /* ## vorher d0 avoid FIFO underruns..? */
981 vga_wseq(regbase, CL_SEQRF, val: 0xd0);
982 break;
983
984 case BT_SD64:
985 case BT_PICASSO4:
986 case BT_ALPINE:
987 case BT_GD5480:
988 case BT_LAGUNA:
989 case BT_LAGUNAB:
990 /* do nothing */
991 break;
992
993 default:
994 dev_warn(info->device, "unknown Board\n");
995 break;
996 }
997
998 /* pixel mask: pass-through for first plane */
999 WGen(cinfo, VGA_PEL_MSK, val: 0x01);
1000 if (cinfo->multiplexing)
1001 /* hidden dac reg: 1280x1024 */
1002 WHDR(cinfo, val: 0x4a);
1003 else
1004 /* hidden dac: nothing */
1005 WHDR(cinfo, val: 0);
1006 /* memory mode: odd/even, ext. memory */
1007 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, val: 0x06);
1008 /* plane mask: only write to first plane */
1009 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, val: 0x01);
1010 }
1011
1012 /******************************************************
1013 *
1014 * 8 bpp
1015 *
1016 */
1017
1018 else if (var->bits_per_pixel == 8) {
1019 dev_dbg(info->device, "preparing for 8 bit deep display\n");
1020 switch (cinfo->btype) {
1021 case BT_SD64:
1022 case BT_PICCOLO:
1023 case BT_PICASSO:
1024 case BT_SPECTRUM:
1025 case BT_PICASSO4:
1026 case BT_ALPINE:
1027 case BT_GD5480:
1028 vga_wseq(regbase, CL_SEQR7,
1029 val: cinfo->multiplexing ?
1030 bi->sr07_8bpp_mux : bi->sr07_8bpp);
1031 break;
1032
1033 case BT_LAGUNA:
1034 case BT_LAGUNAB:
1035 vga_wseq(regbase, CL_SEQR7,
1036 val: vga_rseq(regbase, CL_SEQR7) | 0x01);
1037 threshold |= 0x10;
1038 break;
1039
1040 default:
1041 dev_warn(info->device, "unknown Board\n");
1042 break;
1043 }
1044
1045 switch (cinfo->btype) {
1046 case BT_PICCOLO:
1047 case BT_PICASSO:
1048 case BT_SPECTRUM:
1049 /* Fast Page-Mode writes */
1050 vga_wseq(regbase, CL_SEQRF, val: 0xb0);
1051 break;
1052
1053 case BT_PICASSO4:
1054#ifdef CONFIG_ZORRO
1055 /* ### INCOMPLETE!! */
1056 vga_wseq(regbase, CL_SEQRF, 0xb8);
1057#endif
1058 case BT_ALPINE:
1059 case BT_SD64:
1060 case BT_GD5480:
1061 case BT_LAGUNA:
1062 case BT_LAGUNAB:
1063 /* do nothing */
1064 break;
1065
1066 default:
1067 dev_warn(info->device, "unknown board\n");
1068 break;
1069 }
1070
1071 /* mode register: 256 color mode */
1072 vga_wgfx(regbase, VGA_GFX_MODE, val: 64);
1073 if (cinfo->multiplexing)
1074 /* hidden dac reg: 1280x1024 */
1075 WHDR(cinfo, val: 0x4a);
1076 else
1077 /* hidden dac: nothing */
1078 WHDR(cinfo, val: 0);
1079 }
1080
1081 /******************************************************
1082 *
1083 * 16 bpp
1084 *
1085 */
1086
1087 else if (var->bits_per_pixel == 16) {
1088 dev_dbg(info->device, "preparing for 16 bit deep display\n");
1089 switch (cinfo->btype) {
1090 case BT_PICCOLO:
1091 case BT_SPECTRUM:
1092 vga_wseq(regbase, CL_SEQR7, val: 0x87);
1093 /* Fast Page-Mode writes */
1094 vga_wseq(regbase, CL_SEQRF, val: 0xb0);
1095 break;
1096
1097 case BT_PICASSO:
1098 vga_wseq(regbase, CL_SEQR7, val: 0x27);
1099 /* Fast Page-Mode writes */
1100 vga_wseq(regbase, CL_SEQRF, val: 0xb0);
1101 break;
1102
1103 case BT_SD64:
1104 case BT_PICASSO4:
1105 case BT_ALPINE:
1106 /* Extended Sequencer Mode: 256c col. mode */
1107 vga_wseq(regbase, CL_SEQR7,
1108 val: cinfo->doubleVCLK ? 0xa3 : 0xa7);
1109 break;
1110
1111 case BT_GD5480:
1112 vga_wseq(regbase, CL_SEQR7, val: 0x17);
1113 /* We already set SRF and SR1F */
1114 break;
1115
1116 case BT_LAGUNA:
1117 case BT_LAGUNAB:
1118 vga_wseq(regbase, CL_SEQR7,
1119 val: vga_rseq(regbase, CL_SEQR7) & ~0x01);
1120 control |= 0x2000;
1121 format |= 0x1400;
1122 threshold |= 0x10;
1123 break;
1124
1125 default:
1126 dev_warn(info->device, "unknown Board\n");
1127 break;
1128 }
1129
1130 /* mode register: 256 color mode */
1131 vga_wgfx(regbase, VGA_GFX_MODE, val: 64);
1132#ifdef CONFIG_PCI
1133 WHDR(cinfo, val: cinfo->doubleVCLK ? 0xe1 : 0xc1);
1134#elif defined(CONFIG_ZORRO)
1135 /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
1136 WHDR(cinfo, 0xa0); /* hidden dac reg: nothing special */
1137#endif
1138 }
1139
1140 /******************************************************
1141 *
1142 * 24 bpp
1143 *
1144 */
1145
1146 else if (var->bits_per_pixel == 24) {
1147 dev_dbg(info->device, "preparing for 24 bit deep display\n");
1148 switch (cinfo->btype) {
1149 case BT_PICCOLO:
1150 case BT_SPECTRUM:
1151 vga_wseq(regbase, CL_SEQR7, val: 0x85);
1152 /* Fast Page-Mode writes */
1153 vga_wseq(regbase, CL_SEQRF, val: 0xb0);
1154 break;
1155
1156 case BT_PICASSO:
1157 vga_wseq(regbase, CL_SEQR7, val: 0x25);
1158 /* Fast Page-Mode writes */
1159 vga_wseq(regbase, CL_SEQRF, val: 0xb0);
1160 break;
1161
1162 case BT_SD64:
1163 case BT_PICASSO4:
1164 case BT_ALPINE:
1165 /* Extended Sequencer Mode: 256c col. mode */
1166 vga_wseq(regbase, CL_SEQR7, val: 0xa5);
1167 break;
1168
1169 case BT_GD5480:
1170 vga_wseq(regbase, CL_SEQR7, val: 0x15);
1171 /* We already set SRF and SR1F */
1172 break;
1173
1174 case BT_LAGUNA:
1175 case BT_LAGUNAB:
1176 vga_wseq(regbase, CL_SEQR7,
1177 val: vga_rseq(regbase, CL_SEQR7) & ~0x01);
1178 control |= 0x4000;
1179 format |= 0x2400;
1180 threshold |= 0x20;
1181 break;
1182
1183 default:
1184 dev_warn(info->device, "unknown Board\n");
1185 break;
1186 }
1187
1188 /* mode register: 256 color mode */
1189 vga_wgfx(regbase, VGA_GFX_MODE, val: 64);
1190 /* hidden dac reg: 8-8-8 mode (24 or 32) */
1191 WHDR(cinfo, val: 0xc5);
1192 }
1193
1194 /******************************************************
1195 *
1196 * unknown/unsupported bpp
1197 *
1198 */
1199
1200 else
1201 dev_err(info->device,
1202 "What's this? requested color depth == %d.\n",
1203 var->bits_per_pixel);
1204
1205 pitch = info->fix.line_length >> 3;
1206 vga_wcrt(regbase, VGA_CRTC_OFFSET, val: pitch & 0xff);
1207 tmp = 0x22;
1208 if (pitch & 0x100)
1209 tmp |= 0x10; /* offset overflow bit */
1210
1211 /* screen start addr #16-18, fastpagemode cycles */
1212 vga_wcrt(regbase, CL_CRT1B, val: tmp);
1213
1214 /* screen start address bit 19 */
1215 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19)
1216 vga_wcrt(regbase, CL_CRT1D, val: (pitch >> 9) & 1);
1217
1218 if (is_laguna(cinfo)) {
1219 tmp = 0;
1220 if ((htotal + 5) & 256)
1221 tmp |= 128;
1222 if (hdispend & 256)
1223 tmp |= 64;
1224 if (hsyncstart & 256)
1225 tmp |= 48;
1226 if (vtotal & 1024)
1227 tmp |= 8;
1228 if (vdispend & 1024)
1229 tmp |= 4;
1230 if (vsyncstart & 1024)
1231 tmp |= 3;
1232
1233 vga_wcrt(regbase, CL_CRT1E, val: tmp);
1234 dev_dbg(info->device, "CRT1e: %d\n", tmp);
1235 }
1236
1237 /* pixel panning */
1238 vga_wattr(regbase, CL_AR33, val: 0);
1239
1240 /* [ EGS: SetOffset(); ] */
1241 /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
1242 AttrOn(cinfo);
1243
1244 if (is_laguna(cinfo)) {
1245 /* no tiles */
1246 fb_writew(b: control | 0x1000, addr: cinfo->laguna_mmio + 0x402);
1247 fb_writew(b: format, addr: cinfo->laguna_mmio + 0xc0);
1248 fb_writew(b: threshold, addr: cinfo->laguna_mmio + 0xea);
1249 }
1250 /* finally, turn on everything - turn off "FullBandwidth" bit */
1251 /* also, set "DotClock%2" bit where requested */
1252 tmp = 0x01;
1253
1254/*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
1255 if (var->vmode & FB_VMODE_CLOCK_HALVE)
1256 tmp |= 0x08;
1257*/
1258
1259 vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, val: tmp);
1260 dev_dbg(info->device, "CL_SEQR1: %d\n", tmp);
1261
1262#ifdef CIRRUSFB_DEBUG
1263 cirrusfb_dbg_reg_dump(info, NULL);
1264#endif
1265
1266 return 0;
1267}
1268
1269/* for some reason incomprehensible to me, cirrusfb requires that you write
1270 * the registers twice for the settings to take..grr. -dte */
1271static int cirrusfb_set_par(struct fb_info *info)
1272{
1273 cirrusfb_set_par_foo(info);
1274 return cirrusfb_set_par_foo(info);
1275}
1276
1277static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1278 unsigned blue, unsigned transp,
1279 struct fb_info *info)
1280{
1281 struct cirrusfb_info *cinfo = info->par;
1282
1283 if (regno > 255)
1284 return -EINVAL;
1285
1286 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
1287 u32 v;
1288 red >>= (16 - info->var.red.length);
1289 green >>= (16 - info->var.green.length);
1290 blue >>= (16 - info->var.blue.length);
1291
1292 if (regno >= 16)
1293 return 1;
1294 v = (red << info->var.red.offset) |
1295 (green << info->var.green.offset) |
1296 (blue << info->var.blue.offset);
1297
1298 cinfo->pseudo_palette[regno] = v;
1299 return 0;
1300 }
1301
1302 if (info->var.bits_per_pixel == 8)
1303 WClut(cinfo, regnum: regno, red: red >> 10, green: green >> 10, blue: blue >> 10);
1304
1305 return 0;
1306
1307}
1308
1309/*************************************************************************
1310 cirrusfb_pan_display()
1311
1312 performs display panning - provided hardware permits this
1313**************************************************************************/
1314static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
1315 struct fb_info *info)
1316{
1317 int xoffset;
1318 unsigned long base;
1319 unsigned char tmp, xpix;
1320 struct cirrusfb_info *cinfo = info->par;
1321
1322 /* no range checks for xoffset and yoffset, */
1323 /* as fb_pan_display has already done this */
1324 if (var->vmode & FB_VMODE_YWRAP)
1325 return -EINVAL;
1326
1327 xoffset = var->xoffset * info->var.bits_per_pixel / 8;
1328
1329 base = var->yoffset * info->fix.line_length + xoffset;
1330
1331 if (info->var.bits_per_pixel == 1) {
1332 /* base is already correct */
1333 xpix = (unsigned char) (var->xoffset % 8);
1334 } else {
1335 base /= 4;
1336 xpix = (unsigned char) ((xoffset % 4) * 2);
1337 }
1338
1339 if (!is_laguna(cinfo))
1340 cirrusfb_WaitBLT(regbase: cinfo->regbase);
1341
1342 /* lower 8 + 8 bits of screen start address */
1343 vga_wcrt(regbase: cinfo->regbase, VGA_CRTC_START_LO, val: base & 0xff);
1344 vga_wcrt(regbase: cinfo->regbase, VGA_CRTC_START_HI, val: (base >> 8) & 0xff);
1345
1346 /* 0xf2 is %11110010, exclude tmp bits */
1347 tmp = vga_rcrt(regbase: cinfo->regbase, CL_CRT1B) & 0xf2;
1348 /* construct bits 16, 17 and 18 of screen start address */
1349 if (base & 0x10000)
1350 tmp |= 0x01;
1351 if (base & 0x20000)
1352 tmp |= 0x04;
1353 if (base & 0x40000)
1354 tmp |= 0x08;
1355
1356 vga_wcrt(regbase: cinfo->regbase, CL_CRT1B, val: tmp);
1357
1358 /* construct bit 19 of screen start address */
1359 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) {
1360 tmp = vga_rcrt(regbase: cinfo->regbase, CL_CRT1D);
1361 if (is_laguna(cinfo))
1362 tmp = (tmp & ~0x18) | ((base >> 16) & 0x18);
1363 else
1364 tmp = (tmp & ~0x80) | ((base >> 12) & 0x80);
1365 vga_wcrt(regbase: cinfo->regbase, CL_CRT1D, val: tmp);
1366 }
1367
1368 /* write pixel panning value to AR33; this does not quite work in 8bpp
1369 *
1370 * ### Piccolo..? Will this work?
1371 */
1372 if (info->var.bits_per_pixel == 1)
1373 vga_wattr(regbase: cinfo->regbase, CL_AR33, val: xpix);
1374
1375 return 0;
1376}
1377
1378static int cirrusfb_blank(int blank_mode, struct fb_info *info)
1379{
1380 /*
1381 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
1382 * then the caller blanks by setting the CLUT (Color Look Up Table)
1383 * to all black. Return 0 if blanking succeeded, != 0 if un-/blanking
1384 * failed due to e.g. a video mode which doesn't support it.
1385 * Implements VESA suspend and powerdown modes on hardware that
1386 * supports disabling hsync/vsync:
1387 * blank_mode == 2: suspend vsync
1388 * blank_mode == 3: suspend hsync
1389 * blank_mode == 4: powerdown
1390 */
1391 unsigned char val;
1392 struct cirrusfb_info *cinfo = info->par;
1393 int current_mode = cinfo->blank_mode;
1394
1395 dev_dbg(info->device, "ENTER, blank mode = %d\n", blank_mode);
1396
1397 if (info->state != FBINFO_STATE_RUNNING ||
1398 current_mode == blank_mode) {
1399 dev_dbg(info->device, "EXIT, returning 0\n");
1400 return 0;
1401 }
1402
1403 /* Undo current */
1404 if (current_mode == FB_BLANK_NORMAL ||
1405 current_mode == FB_BLANK_UNBLANK)
1406 /* clear "FullBandwidth" bit */
1407 val = 0;
1408 else
1409 /* set "FullBandwidth" bit */
1410 val = 0x20;
1411
1412 val |= vga_rseq(regbase: cinfo->regbase, VGA_SEQ_CLOCK_MODE) & 0xdf;
1413 vga_wseq(regbase: cinfo->regbase, VGA_SEQ_CLOCK_MODE, val);
1414
1415 switch (blank_mode) {
1416 case FB_BLANK_UNBLANK:
1417 case FB_BLANK_NORMAL:
1418 val = 0x00;
1419 break;
1420 case FB_BLANK_VSYNC_SUSPEND:
1421 val = 0x04;
1422 break;
1423 case FB_BLANK_HSYNC_SUSPEND:
1424 val = 0x02;
1425 break;
1426 case FB_BLANK_POWERDOWN:
1427 val = 0x06;
1428 break;
1429 default:
1430 dev_dbg(info->device, "EXIT, returning 1\n");
1431 return 1;
1432 }
1433
1434 vga_wgfx(regbase: cinfo->regbase, CL_GRE, val);
1435
1436 cinfo->blank_mode = blank_mode;
1437 dev_dbg(info->device, "EXIT, returning 0\n");
1438
1439 /* Let fbcon do a soft blank for us */
1440 return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
1441}
1442
1443/**** END Hardware specific Routines **************************************/
1444/****************************************************************************/
1445/**** BEGIN Internal Routines ***********************************************/
1446
1447static void init_vgachip(struct fb_info *info)
1448{
1449 struct cirrusfb_info *cinfo = info->par;
1450 const struct cirrusfb_board_info_rec *bi;
1451
1452 assert(cinfo != NULL);
1453
1454 bi = &cirrusfb_board_info[cinfo->btype];
1455
1456 /* reset board globally */
1457 switch (cinfo->btype) {
1458 case BT_PICCOLO:
1459 WSFR(cinfo, val: 0x01);
1460 udelay(500);
1461 WSFR(cinfo, val: 0x51);
1462 udelay(500);
1463 break;
1464 case BT_PICASSO:
1465 WSFR2(cinfo, val: 0xff);
1466 udelay(500);
1467 break;
1468 case BT_SD64:
1469 case BT_SPECTRUM:
1470 WSFR(cinfo, val: 0x1f);
1471 udelay(500);
1472 WSFR(cinfo, val: 0x4f);
1473 udelay(500);
1474 break;
1475 case BT_PICASSO4:
1476 /* disable flickerfixer */
1477 vga_wcrt(regbase: cinfo->regbase, CL_CRT51, val: 0x00);
1478 mdelay(100);
1479 /* mode */
1480 vga_wgfx(regbase: cinfo->regbase, CL_GR31, val: 0x00);
1481 fallthrough;
1482 case BT_GD5480:
1483 /* from Klaus' NetBSD driver: */
1484 vga_wgfx(regbase: cinfo->regbase, CL_GR2F, val: 0x00);
1485 fallthrough;
1486 case BT_ALPINE:
1487 /* put blitter into 542x compat */
1488 vga_wgfx(regbase: cinfo->regbase, CL_GR33, val: 0x00);
1489 break;
1490
1491 case BT_LAGUNA:
1492 case BT_LAGUNAB:
1493 /* Nothing to do to reset the board. */
1494 break;
1495
1496 default:
1497 dev_err(info->device, "Warning: Unknown board type\n");
1498 break;
1499 }
1500
1501 /* make sure RAM size set by this point */
1502 assert(info->screen_size > 0);
1503
1504 /* the P4 is not fully initialized here; I rely on it having been */
1505 /* inited under AmigaOS already, which seems to work just fine */
1506 /* (Klaus advised to do it this way) */
1507
1508 if (cinfo->btype != BT_PICASSO4) {
1509 WGen(cinfo, CL_VSSM, val: 0x10); /* EGS: 0x16 */
1510 WGen(cinfo, CL_POS102, val: 0x01);
1511 WGen(cinfo, CL_VSSM, val: 0x08); /* EGS: 0x0e */
1512
1513 if (cinfo->btype != BT_SD64)
1514 WGen(cinfo, CL_VSSM2, val: 0x01);
1515
1516 /* reset sequencer logic */
1517 vga_wseq(regbase: cinfo->regbase, VGA_SEQ_RESET, val: 0x03);
1518
1519 /* FullBandwidth (video off) and 8/9 dot clock */
1520 vga_wseq(regbase: cinfo->regbase, VGA_SEQ_CLOCK_MODE, val: 0x21);
1521
1522 /* "magic cookie" - doesn't make any sense to me.. */
1523/* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */
1524 /* unlock all extension registers */
1525 vga_wseq(regbase: cinfo->regbase, CL_SEQR6, val: 0x12);
1526
1527 switch (cinfo->btype) {
1528 case BT_GD5480:
1529 vga_wseq(regbase: cinfo->regbase, CL_SEQRF, val: 0x98);
1530 break;
1531 case BT_ALPINE:
1532 case BT_LAGUNA:
1533 case BT_LAGUNAB:
1534 break;
1535 case BT_SD64:
1536#ifdef CONFIG_ZORRO
1537 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8);
1538#endif
1539 break;
1540 default:
1541 vga_wseq(regbase: cinfo->regbase, CL_SEQR16, val: 0x0f);
1542 vga_wseq(regbase: cinfo->regbase, CL_SEQRF, val: 0xb0);
1543 break;
1544 }
1545 }
1546 /* plane mask: nothing */
1547 vga_wseq(regbase: cinfo->regbase, VGA_SEQ_PLANE_WRITE, val: 0xff);
1548 /* character map select: doesn't even matter in gx mode */
1549 vga_wseq(regbase: cinfo->regbase, VGA_SEQ_CHARACTER_MAP, val: 0x00);
1550 /* memory mode: chain4, ext. memory */
1551 vga_wseq(regbase: cinfo->regbase, VGA_SEQ_MEMORY_MODE, val: 0x0a);
1552
1553 /* controller-internal base address of video memory */
1554 if (bi->init_sr07)
1555 vga_wseq(regbase: cinfo->regbase, CL_SEQR7, val: bi->sr07);
1556
1557 /* vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */
1558 /* EEPROM control: shouldn't be necessary to write to this at all.. */
1559
1560 /* graphics cursor X position (incomplete; position gives rem. 3 bits */
1561 vga_wseq(regbase: cinfo->regbase, CL_SEQR10, val: 0x00);
1562 /* graphics cursor Y position (..."... ) */
1563 vga_wseq(regbase: cinfo->regbase, CL_SEQR11, val: 0x00);
1564 /* graphics cursor attributes */
1565 vga_wseq(regbase: cinfo->regbase, CL_SEQR12, val: 0x00);
1566 /* graphics cursor pattern address */
1567 vga_wseq(regbase: cinfo->regbase, CL_SEQR13, val: 0x00);
1568
1569 /* writing these on a P4 might give problems.. */
1570 if (cinfo->btype != BT_PICASSO4) {
1571 /* configuration readback and ext. color */
1572 vga_wseq(regbase: cinfo->regbase, CL_SEQR17, val: 0x00);
1573 /* signature generator */
1574 vga_wseq(regbase: cinfo->regbase, CL_SEQR18, val: 0x02);
1575 }
1576
1577 /* Screen A preset row scan: none */
1578 vga_wcrt(regbase: cinfo->regbase, VGA_CRTC_PRESET_ROW, val: 0x00);
1579 /* Text cursor start: disable text cursor */
1580 vga_wcrt(regbase: cinfo->regbase, VGA_CRTC_CURSOR_START, val: 0x20);
1581 /* Text cursor end: - */
1582 vga_wcrt(regbase: cinfo->regbase, VGA_CRTC_CURSOR_END, val: 0x00);
1583 /* text cursor location high: 0 */
1584 vga_wcrt(regbase: cinfo->regbase, VGA_CRTC_CURSOR_HI, val: 0x00);
1585 /* text cursor location low: 0 */
1586 vga_wcrt(regbase: cinfo->regbase, VGA_CRTC_CURSOR_LO, val: 0x00);
1587
1588 /* Underline Row scanline: - */
1589 vga_wcrt(regbase: cinfo->regbase, VGA_CRTC_UNDERLINE, val: 0x00);
1590 /* ### add 0x40 for text modes with > 30 MHz pixclock */
1591 /* ext. display controls: ext.adr. wrap */
1592 vga_wcrt(regbase: cinfo->regbase, CL_CRT1B, val: 0x02);
1593
1594 /* Set/Reset registers: - */
1595 vga_wgfx(regbase: cinfo->regbase, VGA_GFX_SR_VALUE, val: 0x00);
1596 /* Set/Reset enable: - */
1597 vga_wgfx(regbase: cinfo->regbase, VGA_GFX_SR_ENABLE, val: 0x00);
1598 /* Color Compare: - */
1599 vga_wgfx(regbase: cinfo->regbase, VGA_GFX_COMPARE_VALUE, val: 0x00);
1600 /* Data Rotate: - */
1601 vga_wgfx(regbase: cinfo->regbase, VGA_GFX_DATA_ROTATE, val: 0x00);
1602 /* Read Map Select: - */
1603 vga_wgfx(regbase: cinfo->regbase, VGA_GFX_PLANE_READ, val: 0x00);
1604 /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
1605 vga_wgfx(regbase: cinfo->regbase, VGA_GFX_MODE, val: 0x00);
1606 /* Miscellaneous: memory map base address, graphics mode */
1607 vga_wgfx(regbase: cinfo->regbase, VGA_GFX_MISC, val: 0x01);
1608 /* Color Don't care: involve all planes */
1609 vga_wgfx(regbase: cinfo->regbase, VGA_GFX_COMPARE_MASK, val: 0x0f);
1610 /* Bit Mask: no mask at all */
1611 vga_wgfx(regbase: cinfo->regbase, VGA_GFX_BIT_MASK, val: 0xff);
1612
1613 if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64 ||
1614 is_laguna(cinfo))
1615 /* (5434 can't have bit 3 set for bitblt) */
1616 vga_wgfx(regbase: cinfo->regbase, CL_GRB, val: 0x20);
1617 else
1618 /* Graphics controller mode extensions: finer granularity,
1619 * 8byte data latches
1620 */
1621 vga_wgfx(regbase: cinfo->regbase, CL_GRB, val: 0x28);
1622
1623 vga_wgfx(regbase: cinfo->regbase, CL_GRC, val: 0xff); /* Color Key compare: - */
1624 vga_wgfx(regbase: cinfo->regbase, CL_GRD, val: 0x00); /* Color Key compare mask: - */
1625 vga_wgfx(regbase: cinfo->regbase, CL_GRE, val: 0x00); /* Miscellaneous control: - */
1626 /* Background color byte 1: - */
1627 /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); */
1628 /* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
1629
1630 /* Attribute Controller palette registers: "identity mapping" */
1631 vga_wattr(regbase: cinfo->regbase, VGA_ATC_PALETTE0, val: 0x00);
1632 vga_wattr(regbase: cinfo->regbase, VGA_ATC_PALETTE1, val: 0x01);
1633 vga_wattr(regbase: cinfo->regbase, VGA_ATC_PALETTE2, val: 0x02);
1634 vga_wattr(regbase: cinfo->regbase, VGA_ATC_PALETTE3, val: 0x03);
1635 vga_wattr(regbase: cinfo->regbase, VGA_ATC_PALETTE4, val: 0x04);
1636 vga_wattr(regbase: cinfo->regbase, VGA_ATC_PALETTE5, val: 0x05);
1637 vga_wattr(regbase: cinfo->regbase, VGA_ATC_PALETTE6, val: 0x06);
1638 vga_wattr(regbase: cinfo->regbase, VGA_ATC_PALETTE7, val: 0x07);
1639 vga_wattr(regbase: cinfo->regbase, VGA_ATC_PALETTE8, val: 0x08);
1640 vga_wattr(regbase: cinfo->regbase, VGA_ATC_PALETTE9, val: 0x09);
1641 vga_wattr(regbase: cinfo->regbase, VGA_ATC_PALETTEA, val: 0x0a);
1642 vga_wattr(regbase: cinfo->regbase, VGA_ATC_PALETTEB, val: 0x0b);
1643 vga_wattr(regbase: cinfo->regbase, VGA_ATC_PALETTEC, val: 0x0c);
1644 vga_wattr(regbase: cinfo->regbase, VGA_ATC_PALETTED, val: 0x0d);
1645 vga_wattr(regbase: cinfo->regbase, VGA_ATC_PALETTEE, val: 0x0e);
1646 vga_wattr(regbase: cinfo->regbase, VGA_ATC_PALETTEF, val: 0x0f);
1647
1648 /* Attribute Controller mode: graphics mode */
1649 vga_wattr(regbase: cinfo->regbase, VGA_ATC_MODE, val: 0x01);
1650 /* Overscan color reg.: reg. 0 */
1651 vga_wattr(regbase: cinfo->regbase, VGA_ATC_OVERSCAN, val: 0x00);
1652 /* Color Plane enable: Enable all 4 planes */
1653 vga_wattr(regbase: cinfo->regbase, VGA_ATC_PLANE_ENABLE, val: 0x0f);
1654 /* Color Select: - */
1655 vga_wattr(regbase: cinfo->regbase, VGA_ATC_COLOR_PAGE, val: 0x00);
1656
1657 WGen(cinfo, VGA_PEL_MSK, val: 0xff); /* Pixel mask: no mask */
1658
1659 /* BLT Start/status: Blitter reset */
1660 vga_wgfx(regbase: cinfo->regbase, CL_GR31, val: 0x04);
1661 /* - " - : "end-of-reset" */
1662 vga_wgfx(regbase: cinfo->regbase, CL_GR31, val: 0x00);
1663
1664 /* misc... */
1665 WHDR(cinfo, val: 0); /* Hidden DAC register: - */
1666 return;
1667}
1668
1669static void switch_monitor(struct cirrusfb_info *cinfo, int on)
1670{
1671#ifdef CONFIG_ZORRO /* only works on Zorro boards */
1672 static int IsOn = 0; /* XXX not ok for multiple boards */
1673
1674 if (cinfo->btype == BT_PICASSO4)
1675 return; /* nothing to switch */
1676 if (cinfo->btype == BT_ALPINE)
1677 return; /* nothing to switch */
1678 if (cinfo->btype == BT_GD5480)
1679 return; /* nothing to switch */
1680 if (cinfo->btype == BT_PICASSO) {
1681 if ((on && !IsOn) || (!on && IsOn))
1682 WSFR(cinfo, 0xff);
1683 return;
1684 }
1685 if (on) {
1686 switch (cinfo->btype) {
1687 case BT_SD64:
1688 WSFR(cinfo, cinfo->SFR | 0x21);
1689 break;
1690 case BT_PICCOLO:
1691 WSFR(cinfo, cinfo->SFR | 0x28);
1692 break;
1693 case BT_SPECTRUM:
1694 WSFR(cinfo, 0x6f);
1695 break;
1696 default: /* do nothing */ break;
1697 }
1698 } else {
1699 switch (cinfo->btype) {
1700 case BT_SD64:
1701 WSFR(cinfo, cinfo->SFR & 0xde);
1702 break;
1703 case BT_PICCOLO:
1704 WSFR(cinfo, cinfo->SFR & 0xd7);
1705 break;
1706 case BT_SPECTRUM:
1707 WSFR(cinfo, 0x4f);
1708 break;
1709 default: /* do nothing */
1710 break;
1711 }
1712 }
1713#endif /* CONFIG_ZORRO */
1714}
1715
1716/******************************************/
1717/* Linux 2.6-style accelerated functions */
1718/******************************************/
1719
1720static int cirrusfb_sync(struct fb_info *info)
1721{
1722 struct cirrusfb_info *cinfo = info->par;
1723
1724 if (!is_laguna(cinfo)) {
1725 while (vga_rgfx(regbase: cinfo->regbase, CL_GR31) & 0x03)
1726 cpu_relax();
1727 }
1728 return 0;
1729}
1730
1731static void cirrusfb_fillrect(struct fb_info *info,
1732 const struct fb_fillrect *region)
1733{
1734 struct fb_fillrect modded;
1735 int vxres, vyres;
1736 struct cirrusfb_info *cinfo = info->par;
1737 int m = info->var.bits_per_pixel;
1738 u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
1739 cinfo->pseudo_palette[region->color] : region->color;
1740
1741 if (info->state != FBINFO_STATE_RUNNING)
1742 return;
1743 if (info->flags & FBINFO_HWACCEL_DISABLED) {
1744 cfb_fillrect(info, rect: region);
1745 return;
1746 }
1747
1748 vxres = info->var.xres_virtual;
1749 vyres = info->var.yres_virtual;
1750
1751 memcpy(&modded, region, sizeof(struct fb_fillrect));
1752
1753 if (!modded.width || !modded.height ||
1754 modded.dx >= vxres || modded.dy >= vyres)
1755 return;
1756
1757 if (modded.dx + modded.width > vxres)
1758 modded.width = vxres - modded.dx;
1759 if (modded.dy + modded.height > vyres)
1760 modded.height = vyres - modded.dy;
1761
1762 cirrusfb_RectFill(regbase: cinfo->regbase,
1763 bits_per_pixel: info->var.bits_per_pixel,
1764 x: (region->dx * m) / 8, y: region->dy,
1765 width: (region->width * m) / 8, height: region->height,
1766 fg_color: color, bg_color: color,
1767 line_length: info->fix.line_length, blitmode: 0x40);
1768}
1769
1770static void cirrusfb_copyarea(struct fb_info *info,
1771 const struct fb_copyarea *area)
1772{
1773 struct fb_copyarea modded;
1774 u32 vxres, vyres;
1775 struct cirrusfb_info *cinfo = info->par;
1776 int m = info->var.bits_per_pixel;
1777
1778 if (info->state != FBINFO_STATE_RUNNING)
1779 return;
1780 if (info->flags & FBINFO_HWACCEL_DISABLED) {
1781 cfb_copyarea(info, area);
1782 return;
1783 }
1784
1785 vxres = info->var.xres_virtual;
1786 vyres = info->var.yres_virtual;
1787 memcpy(&modded, area, sizeof(struct fb_copyarea));
1788
1789 if (!modded.width || !modded.height ||
1790 modded.sx >= vxres || modded.sy >= vyres ||
1791 modded.dx >= vxres || modded.dy >= vyres)
1792 return;
1793
1794 if (modded.sx + modded.width > vxres)
1795 modded.width = vxres - modded.sx;
1796 if (modded.dx + modded.width > vxres)
1797 modded.width = vxres - modded.dx;
1798 if (modded.sy + modded.height > vyres)
1799 modded.height = vyres - modded.sy;
1800 if (modded.dy + modded.height > vyres)
1801 modded.height = vyres - modded.dy;
1802
1803 cirrusfb_BitBLT(regbase: cinfo->regbase, bits_per_pixel: info->var.bits_per_pixel,
1804 curx: (area->sx * m) / 8, cury: area->sy,
1805 destx: (area->dx * m) / 8, desty: area->dy,
1806 width: (area->width * m) / 8, height: area->height,
1807 line_length: info->fix.line_length);
1808
1809}
1810
1811static void cirrusfb_imageblit(struct fb_info *info,
1812 const struct fb_image *image)
1813{
1814 struct cirrusfb_info *cinfo = info->par;
1815 unsigned char op = (info->var.bits_per_pixel == 24) ? 0xc : 0x4;
1816
1817 if (info->state != FBINFO_STATE_RUNNING)
1818 return;
1819 /* Alpine/SD64 does not work at 24bpp ??? */
1820 if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1)
1821 cfb_imageblit(info, image);
1822 else if ((cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64) &&
1823 op == 0xc)
1824 cfb_imageblit(info, image);
1825 else {
1826 unsigned size = ((image->width + 7) >> 3) * image->height;
1827 int m = info->var.bits_per_pixel;
1828 u32 fg, bg;
1829
1830 if (info->var.bits_per_pixel == 8) {
1831 fg = image->fg_color;
1832 bg = image->bg_color;
1833 } else {
1834 fg = ((u32 *)(info->pseudo_palette))[image->fg_color];
1835 bg = ((u32 *)(info->pseudo_palette))[image->bg_color];
1836 }
1837 if (info->var.bits_per_pixel == 24) {
1838 /* clear background first */
1839 cirrusfb_RectFill(regbase: cinfo->regbase,
1840 bits_per_pixel: info->var.bits_per_pixel,
1841 x: (image->dx * m) / 8, y: image->dy,
1842 width: (image->width * m) / 8,
1843 height: image->height,
1844 fg_color: bg, bg_color: bg,
1845 line_length: info->fix.line_length, blitmode: 0x40);
1846 }
1847 cirrusfb_RectFill(regbase: cinfo->regbase,
1848 bits_per_pixel: info->var.bits_per_pixel,
1849 x: (image->dx * m) / 8, y: image->dy,
1850 width: (image->width * m) / 8, height: image->height,
1851 fg_color: fg, bg_color: bg,
1852 line_length: info->fix.line_length, blitmode: op);
1853 memcpy(info->screen_base, image->data, size);
1854 }
1855}
1856
1857#ifdef CONFIG_PCI
1858static int release_io_ports;
1859
1860/* Pulled the logic from XFree86 Cirrus driver to get the memory size,
1861 * based on the DRAM bandwidth bit and DRAM bank switching bit. This
1862 * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
1863 * seem to have. */
1864static unsigned int cirrusfb_get_memsize(struct fb_info *info,
1865 u8 __iomem *regbase)
1866{
1867 unsigned long mem;
1868 struct cirrusfb_info *cinfo = info->par;
1869
1870 if (is_laguna(cinfo)) {
1871 unsigned char SR14 = vga_rseq(regbase, CL_SEQR14);
1872
1873 mem = ((SR14 & 7) + 1) << 20;
1874 } else {
1875 unsigned char SRF = vga_rseq(regbase, CL_SEQRF);
1876 switch ((SRF & 0x18)) {
1877 case 0x08:
1878 mem = 512 * 1024;
1879 break;
1880 case 0x10:
1881 mem = 1024 * 1024;
1882 break;
1883 /* 64-bit DRAM data bus width; assume 2MB.
1884 * Also indicates 2MB memory on the 5430.
1885 */
1886 case 0x18:
1887 mem = 2048 * 1024;
1888 break;
1889 default:
1890 dev_warn(info->device, "Unknown memory size!\n");
1891 mem = 1024 * 1024;
1892 }
1893 /* If DRAM bank switching is enabled, there must be
1894 * twice as much memory installed. (4MB on the 5434)
1895 */
1896 if (cinfo->btype != BT_ALPINE && (SRF & 0x80) != 0)
1897 mem *= 2;
1898 }
1899
1900 /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
1901 return mem;
1902}
1903
1904static void get_pci_addrs(const struct pci_dev *pdev,
1905 unsigned long *display, unsigned long *registers)
1906{
1907 assert(pdev != NULL);
1908 assert(display != NULL);
1909 assert(registers != NULL);
1910
1911 *display = 0;
1912 *registers = 0;
1913
1914 /* This is a best-guess for now */
1915
1916 if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
1917 *display = pci_resource_start(pdev, 1);
1918 *registers = pci_resource_start(pdev, 0);
1919 } else {
1920 *display = pci_resource_start(pdev, 0);
1921 *registers = pci_resource_start(pdev, 1);
1922 }
1923
1924 assert(*display != 0);
1925}
1926
1927static void cirrusfb_pci_unmap(struct fb_info *info)
1928{
1929 struct pci_dev *pdev = to_pci_dev(info->device);
1930 struct cirrusfb_info *cinfo = info->par;
1931
1932 if (cinfo->laguna_mmio == NULL)
1933 iounmap(addr: cinfo->laguna_mmio);
1934 iounmap(addr: info->screen_base);
1935#if 0 /* if system didn't claim this region, we would... */
1936 release_mem_region(0xA0000, 65535);
1937#endif
1938 if (release_io_ports)
1939 release_region(0x3C0, 32);
1940 pci_release_regions(pdev);
1941}
1942#endif /* CONFIG_PCI */
1943
1944#ifdef CONFIG_ZORRO
1945static void cirrusfb_zorro_unmap(struct fb_info *info)
1946{
1947 struct cirrusfb_info *cinfo = info->par;
1948 struct zorro_dev *zdev = to_zorro_dev(info->device);
1949
1950 if (info->fix.smem_start > 16 * MB_)
1951 iounmap(info->screen_base);
1952 if (info->fix.mmio_start > 16 * MB_)
1953 iounmap(cinfo->regbase);
1954
1955 zorro_release_device(zdev);
1956}
1957#endif /* CONFIG_ZORRO */
1958
1959/* function table of the above functions */
1960static const struct fb_ops cirrusfb_ops = {
1961 .owner = THIS_MODULE,
1962 .fb_open = cirrusfb_open,
1963 .fb_release = cirrusfb_release,
1964 __FB_DEFAULT_IOMEM_OPS_RDWR,
1965 .fb_setcolreg = cirrusfb_setcolreg,
1966 .fb_check_var = cirrusfb_check_var,
1967 .fb_set_par = cirrusfb_set_par,
1968 .fb_pan_display = cirrusfb_pan_display,
1969 .fb_blank = cirrusfb_blank,
1970 .fb_fillrect = cirrusfb_fillrect,
1971 .fb_copyarea = cirrusfb_copyarea,
1972 .fb_sync = cirrusfb_sync,
1973 .fb_imageblit = cirrusfb_imageblit,
1974 __FB_DEFAULT_IOMEM_OPS_MMAP,
1975};
1976
1977static int cirrusfb_set_fbinfo(struct fb_info *info)
1978{
1979 struct cirrusfb_info *cinfo = info->par;
1980 struct fb_var_screeninfo *var = &info->var;
1981
1982 info->pseudo_palette = cinfo->pseudo_palette;
1983 info->flags = FBINFO_HWACCEL_XPAN
1984 | FBINFO_HWACCEL_YPAN
1985 | FBINFO_HWACCEL_FILLRECT
1986 | FBINFO_HWACCEL_IMAGEBLIT
1987 | FBINFO_HWACCEL_COPYAREA;
1988 if (noaccel || is_laguna(cinfo)) {
1989 info->flags |= FBINFO_HWACCEL_DISABLED;
1990 info->fix.accel = FB_ACCEL_NONE;
1991 } else
1992 info->fix.accel = FB_ACCEL_CIRRUS_ALPINE;
1993
1994 info->fbops = &cirrusfb_ops;
1995
1996 if (cinfo->btype == BT_GD5480) {
1997 if (var->bits_per_pixel == 16)
1998 info->screen_base += 1 * MB_;
1999 if (var->bits_per_pixel == 32)
2000 info->screen_base += 2 * MB_;
2001 }
2002
2003 /* Fill fix common fields */
2004 strscpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
2005 sizeof(info->fix.id));
2006
2007 /* monochrome: only 1 memory plane */
2008 /* 8 bit and above: Use whole memory area */
2009 info->fix.smem_len = info->screen_size;
2010 if (var->bits_per_pixel == 1)
2011 info->fix.smem_len /= 4;
2012 info->fix.type_aux = 0;
2013 info->fix.xpanstep = 1;
2014 info->fix.ypanstep = 1;
2015 info->fix.ywrapstep = 0;
2016
2017 /* FIXME: map region at 0xB8000 if available, fill in here */
2018 info->fix.mmio_len = 0;
2019
2020 fb_alloc_cmap(cmap: &info->cmap, len: 256, transp: 0);
2021
2022 return 0;
2023}
2024
2025static int cirrusfb_register(struct fb_info *info)
2026{
2027 struct cirrusfb_info *cinfo = info->par;
2028 int err;
2029
2030 /* sanity checks */
2031 assert(cinfo->btype != BT_NONE);
2032
2033 /* set all the vital stuff */
2034 cirrusfb_set_fbinfo(info);
2035
2036 dev_dbg(info->device, "(RAM start set to: 0x%p)\n", info->screen_base);
2037
2038 err = fb_find_mode(var: &info->var, info, mode_option, NULL, dbsize: 0, NULL, default_bpp: 8);
2039 if (!err) {
2040 dev_dbg(info->device, "wrong initial video mode\n");
2041 err = -EINVAL;
2042 goto err_dealloc_cmap;
2043 }
2044
2045 info->var.activate = FB_ACTIVATE_NOW;
2046
2047 err = cirrusfb_check_var(var: &info->var, info);
2048 if (err < 0) {
2049 /* should never happen */
2050 dev_dbg(info->device,
2051 "choking on default var... umm, no good.\n");
2052 goto err_dealloc_cmap;
2053 }
2054
2055 err = register_framebuffer(fb_info: info);
2056 if (err < 0) {
2057 dev_err(info->device,
2058 "could not register fb device; err = %d!\n", err);
2059 goto err_dealloc_cmap;
2060 }
2061
2062 return 0;
2063
2064err_dealloc_cmap:
2065 fb_dealloc_cmap(cmap: &info->cmap);
2066 return err;
2067}
2068
2069static void cirrusfb_cleanup(struct fb_info *info)
2070{
2071 struct cirrusfb_info *cinfo = info->par;
2072
2073 switch_monitor(cinfo, on: 0);
2074 unregister_framebuffer(fb_info: info);
2075 fb_dealloc_cmap(cmap: &info->cmap);
2076 dev_dbg(info->device, "Framebuffer unregistered\n");
2077 cinfo->unmap(info);
2078 framebuffer_release(info);
2079}
2080
2081#ifdef CONFIG_PCI
2082static int cirrusfb_pci_register(struct pci_dev *pdev,
2083 const struct pci_device_id *ent)
2084{
2085 struct cirrusfb_info *cinfo;
2086 struct fb_info *info;
2087 unsigned long board_addr, board_size;
2088 int ret;
2089
2090 ret = aperture_remove_conflicting_pci_devices(pdev, name: "cirrusfb");
2091 if (ret)
2092 return ret;
2093
2094 ret = pci_enable_device(dev: pdev);
2095 if (ret < 0) {
2096 printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
2097 goto err_out;
2098 }
2099
2100 info = framebuffer_alloc(size: sizeof(struct cirrusfb_info), dev: &pdev->dev);
2101 if (!info) {
2102 ret = -ENOMEM;
2103 goto err_out;
2104 }
2105
2106 cinfo = info->par;
2107 cinfo->btype = (enum cirrus_board) ent->driver_data;
2108
2109 dev_dbg(info->device,
2110 " Found PCI device, base address 0 is 0x%Lx, btype set to %d\n",
2111 (unsigned long long)pdev->resource[0].start, cinfo->btype);
2112 dev_dbg(info->device, " base address 1 is 0x%Lx\n",
2113 (unsigned long long)pdev->resource[1].start);
2114
2115 dev_dbg(info->device,
2116 "Attempt to get PCI info for Cirrus Graphics Card\n");
2117 get_pci_addrs(pdev, display: &board_addr, registers: &info->fix.mmio_start);
2118 /* FIXME: this forces VGA. alternatives? */
2119 cinfo->regbase = NULL;
2120 cinfo->laguna_mmio = ioremap(offset: info->fix.mmio_start, size: 0x1000);
2121
2122 dev_dbg(info->device, "Board address: 0x%lx, register address: 0x%lx\n",
2123 board_addr, info->fix.mmio_start);
2124
2125 board_size = (cinfo->btype == BT_GD5480) ?
2126 32 * MB_ : cirrusfb_get_memsize(info, regbase: cinfo->regbase);
2127
2128 ret = pci_request_regions(pdev, "cirrusfb");
2129 if (ret < 0) {
2130 dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
2131 board_addr);
2132 goto err_release_fb;
2133 }
2134#if 0 /* if the system didn't claim this region, we would... */
2135 if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
2136 dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
2137 0xA0000L);
2138 ret = -EBUSY;
2139 goto err_release_regions;
2140 }
2141#endif
2142 if (request_region(0x3C0, 32, "cirrusfb"))
2143 release_io_ports = 1;
2144
2145 info->screen_base = ioremap(offset: board_addr, size: board_size);
2146 if (!info->screen_base) {
2147 ret = -EIO;
2148 goto err_release_legacy;
2149 }
2150
2151 info->fix.smem_start = board_addr;
2152 info->screen_size = board_size;
2153 cinfo->unmap = cirrusfb_pci_unmap;
2154
2155 dev_info(info->device,
2156 "Cirrus Logic chipset on PCI bus, RAM (%lu kB) at 0x%lx\n",
2157 info->screen_size >> 10, board_addr);
2158 pci_set_drvdata(pdev, data: info);
2159
2160 ret = cirrusfb_register(info);
2161 if (!ret)
2162 return 0;
2163
2164 iounmap(addr: info->screen_base);
2165err_release_legacy:
2166 if (release_io_ports)
2167 release_region(0x3C0, 32);
2168#if 0
2169 release_mem_region(0xA0000, 65535);
2170err_release_regions:
2171#endif
2172 pci_release_regions(pdev);
2173err_release_fb:
2174 if (cinfo->laguna_mmio != NULL)
2175 iounmap(addr: cinfo->laguna_mmio);
2176 framebuffer_release(info);
2177err_out:
2178 return ret;
2179}
2180
2181static void cirrusfb_pci_unregister(struct pci_dev *pdev)
2182{
2183 struct fb_info *info = pci_get_drvdata(pdev);
2184
2185 cirrusfb_cleanup(info);
2186}
2187
2188static struct pci_driver cirrusfb_pci_driver = {
2189 .name = "cirrusfb",
2190 .id_table = cirrusfb_pci_table,
2191 .probe = cirrusfb_pci_register,
2192 .remove = cirrusfb_pci_unregister,
2193};
2194#endif /* CONFIG_PCI */
2195
2196#ifdef CONFIG_ZORRO
2197static int cirrusfb_zorro_register(struct zorro_dev *z,
2198 const struct zorro_device_id *ent)
2199{
2200 struct fb_info *info;
2201 int error;
2202 const struct zorrocl *zcl;
2203 enum cirrus_board btype;
2204 unsigned long regbase, ramsize, rambase;
2205 struct cirrusfb_info *cinfo;
2206
2207 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
2208 if (!info)
2209 return -ENOMEM;
2210
2211 zcl = (const struct zorrocl *)ent->driver_data;
2212 btype = zcl->type;
2213 regbase = zorro_resource_start(z) + zcl->regoffset;
2214 ramsize = zcl->ramsize;
2215 if (ramsize) {
2216 rambase = zorro_resource_start(z) + zcl->ramoffset;
2217 if (zorro_resource_len(z) == 64 * MB_) {
2218 /* Quirk for 64 MiB Picasso IV */
2219 rambase += zcl->ramoffset;
2220 }
2221 } else {
2222 struct zorro_dev *ram = zorro_find_device(zcl->ramid, NULL);
2223 if (!ram || !zorro_resource_len(ram)) {
2224 dev_err(info->device, "No video RAM found\n");
2225 error = -ENODEV;
2226 goto err_release_fb;
2227 }
2228 rambase = zorro_resource_start(ram);
2229 ramsize = zorro_resource_len(ram);
2230 if (zcl->ramid2 &&
2231 (ram = zorro_find_device(zcl->ramid2, NULL))) {
2232 if (zorro_resource_start(ram) != rambase + ramsize) {
2233 dev_warn(info->device,
2234 "Skipping non-contiguous RAM at %pR\n",
2235 &ram->resource);
2236 } else {
2237 ramsize += zorro_resource_len(ram);
2238 }
2239 }
2240 }
2241
2242 dev_info(info->device,
2243 "%s board detected, REG at 0x%lx, %lu MiB RAM at 0x%lx\n",
2244 cirrusfb_board_info[btype].name, regbase, ramsize / MB_,
2245 rambase);
2246
2247 if (!zorro_request_device(z, "cirrusfb")) {
2248 dev_err(info->device, "Cannot reserve %pR\n", &z->resource);
2249 error = -EBUSY;
2250 goto err_release_fb;
2251 }
2252
2253 cinfo = info->par;
2254 cinfo->btype = btype;
2255
2256 info->fix.mmio_start = regbase;
2257 cinfo->regbase = regbase > 16 * MB_ ? ioremap(regbase, 64 * 1024)
2258 : ZTWO_VADDR(regbase);
2259 if (!cinfo->regbase) {
2260 dev_err(info->device, "Cannot map registers\n");
2261 error = -EIO;
2262 goto err_release_dev;
2263 }
2264
2265 info->fix.smem_start = rambase;
2266 info->screen_size = ramsize;
2267 info->screen_base = rambase > 16 * MB_ ? ioremap(rambase, ramsize)
2268 : ZTWO_VADDR(rambase);
2269 if (!info->screen_base) {
2270 dev_err(info->device, "Cannot map video RAM\n");
2271 error = -EIO;
2272 goto err_unmap_reg;
2273 }
2274
2275 cinfo->unmap = cirrusfb_zorro_unmap;
2276
2277 dev_info(info->device,
2278 "Cirrus Logic chipset on Zorro bus, RAM (%lu MiB) at 0x%lx\n",
2279 ramsize / MB_, rambase);
2280
2281 /* MCLK select etc. */
2282 if (cirrusfb_board_info[btype].init_sr1f)
2283 vga_wseq(cinfo->regbase, CL_SEQR1F,
2284 cirrusfb_board_info[btype].sr1f);
2285
2286 error = cirrusfb_register(info);
2287 if (error) {
2288 dev_err(info->device, "Failed to register device, error %d\n",
2289 error);
2290 goto err_unmap_ram;
2291 }
2292
2293 zorro_set_drvdata(z, info);
2294 return 0;
2295
2296err_unmap_ram:
2297 if (rambase > 16 * MB_)
2298 iounmap(info->screen_base);
2299
2300err_unmap_reg:
2301 if (regbase > 16 * MB_)
2302 iounmap(cinfo->regbase);
2303err_release_dev:
2304 zorro_release_device(z);
2305err_release_fb:
2306 framebuffer_release(info);
2307 return error;
2308}
2309
2310static void cirrusfb_zorro_unregister(struct zorro_dev *z)
2311{
2312 struct fb_info *info = zorro_get_drvdata(z);
2313
2314 cirrusfb_cleanup(info);
2315 zorro_set_drvdata(z, NULL);
2316}
2317
2318static struct zorro_driver cirrusfb_zorro_driver = {
2319 .name = "cirrusfb",
2320 .id_table = cirrusfb_zorro_table,
2321 .probe = cirrusfb_zorro_register,
2322 .remove = cirrusfb_zorro_unregister,
2323};
2324#endif /* CONFIG_ZORRO */
2325
2326#ifndef MODULE
2327static int __init cirrusfb_setup(char *options)
2328{
2329 char *this_opt;
2330
2331 if (!options || !*options)
2332 return 0;
2333
2334 while ((this_opt = strsep(&options, ",")) != NULL) {
2335 if (!*this_opt)
2336 continue;
2337
2338 if (!strcmp(this_opt, "noaccel"))
2339 noaccel = 1;
2340 else if (!strncmp(this_opt, "mode:", 5))
2341 mode_option = this_opt + 5;
2342 else
2343 mode_option = this_opt;
2344 }
2345 return 0;
2346}
2347#endif
2348
2349 /*
2350 * Modularization
2351 */
2352
2353MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
2354MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
2355MODULE_LICENSE("GPL");
2356
2357static int __init cirrusfb_init(void)
2358{
2359 int error = 0;
2360
2361#ifndef MODULE
2362 char *option = NULL;
2363#endif
2364
2365 if (fb_modesetting_disabled(drvname: "cirrusfb"))
2366 return -ENODEV;
2367
2368#ifndef MODULE
2369 if (fb_get_options(name: "cirrusfb", option: &option))
2370 return -ENODEV;
2371 cirrusfb_setup(options: option);
2372#endif
2373
2374#ifdef CONFIG_ZORRO
2375 error |= zorro_register_driver(&cirrusfb_zorro_driver);
2376#endif
2377#ifdef CONFIG_PCI
2378 error |= pci_register_driver(&cirrusfb_pci_driver);
2379#endif
2380 return error;
2381}
2382
2383static void __exit cirrusfb_exit(void)
2384{
2385#ifdef CONFIG_PCI
2386 pci_unregister_driver(dev: &cirrusfb_pci_driver);
2387#endif
2388#ifdef CONFIG_ZORRO
2389 zorro_unregister_driver(&cirrusfb_zorro_driver);
2390#endif
2391}
2392
2393module_init(cirrusfb_init);
2394
2395module_param(mode_option, charp, 0);
2396MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
2397module_param(noaccel, bool, 0);
2398MODULE_PARM_DESC(noaccel, "Disable acceleration");
2399
2400#ifdef MODULE
2401module_exit(cirrusfb_exit);
2402#endif
2403
2404/**********************************************************************/
2405/* about the following functions - I have used the same names for the */
2406/* functions as Markus Wild did in his Retina driver for NetBSD as */
2407/* they just made sense for this purpose. Apart from that, I wrote */
2408/* these functions myself. */
2409/**********************************************************************/
2410
2411/*** WGen() - write into one of the external/general registers ***/
2412static void WGen(const struct cirrusfb_info *cinfo,
2413 int regnum, unsigned char val)
2414{
2415 unsigned long regofs = 0;
2416
2417 if (cinfo->btype == BT_PICASSO) {
2418 /* Picasso II specific hack */
2419/* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2420 regnum == CL_VSSM2) */
2421 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2422 regofs = 0xfff;
2423 }
2424
2425 vga_w(regbase: cinfo->regbase, port: regofs + regnum, val);
2426}
2427
2428/*** RGen() - read out one of the external/general registers ***/
2429static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum)
2430{
2431 unsigned long regofs = 0;
2432
2433 if (cinfo->btype == BT_PICASSO) {
2434 /* Picasso II specific hack */
2435/* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2436 regnum == CL_VSSM2) */
2437 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2438 regofs = 0xfff;
2439 }
2440
2441 return vga_r(regbase: cinfo->regbase, port: regofs + regnum);
2442}
2443
2444/*** AttrOn() - turn on VideoEnable for Attribute controller ***/
2445static void AttrOn(const struct cirrusfb_info *cinfo)
2446{
2447 assert(cinfo != NULL);
2448
2449 if (vga_rcrt(regbase: cinfo->regbase, CL_CRT24) & 0x80) {
2450 /* if we're just in "write value" mode, write back the */
2451 /* same value as before to not modify anything */
2452 vga_w(regbase: cinfo->regbase, VGA_ATT_IW,
2453 val: vga_r(regbase: cinfo->regbase, VGA_ATT_R));
2454 }
2455 /* turn on video bit */
2456/* vga_w(cinfo->regbase, VGA_ATT_IW, 0x20); */
2457 vga_w(regbase: cinfo->regbase, VGA_ATT_IW, val: 0x33);
2458
2459 /* dummy write on Reg0 to be on "write index" mode next time */
2460 vga_w(regbase: cinfo->regbase, VGA_ATT_IW, val: 0x00);
2461}
2462
2463/*** WHDR() - write into the Hidden DAC register ***/
2464/* as the HDR is the only extension register that requires special treatment
2465 * (the other extension registers are accessible just like the "ordinary"
2466 * registers of their functional group) here is a specialized routine for
2467 * accessing the HDR
2468 */
2469static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val)
2470{
2471 if (is_laguna(cinfo))
2472 return;
2473 if (cinfo->btype == BT_PICASSO) {
2474 /* Klaus' hint for correct access to HDR on some boards */
2475 /* first write 0 to pixel mask (3c6) */
2476 WGen(cinfo, VGA_PEL_MSK, val: 0x00);
2477 udelay(200);
2478 /* next read dummy from pixel address (3c8) */
2479 RGen(cinfo, VGA_PEL_IW);
2480 udelay(200);
2481 }
2482 /* now do the usual stuff to access the HDR */
2483
2484 RGen(cinfo, VGA_PEL_MSK);
2485 udelay(200);
2486 RGen(cinfo, VGA_PEL_MSK);
2487 udelay(200);
2488 RGen(cinfo, VGA_PEL_MSK);
2489 udelay(200);
2490 RGen(cinfo, VGA_PEL_MSK);
2491 udelay(200);
2492
2493 WGen(cinfo, VGA_PEL_MSK, val);
2494 udelay(200);
2495
2496 if (cinfo->btype == BT_PICASSO) {
2497 /* now first reset HDR access counter */
2498 RGen(cinfo, VGA_PEL_IW);
2499 udelay(200);
2500
2501 /* and at the end, restore the mask value */
2502 /* ## is this mask always 0xff? */
2503 WGen(cinfo, VGA_PEL_MSK, val: 0xff);
2504 udelay(200);
2505 }
2506}
2507
2508/*** WSFR() - write to the "special function register" (SFR) ***/
2509static void WSFR(struct cirrusfb_info *cinfo, unsigned char val)
2510{
2511#ifdef CONFIG_ZORRO
2512 assert(cinfo->regbase != NULL);
2513 cinfo->SFR = val;
2514 z_writeb(val, cinfo->regbase + 0x8000);
2515#endif
2516}
2517
2518/* The Picasso has a second register for switching the monitor bit */
2519static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val)
2520{
2521#ifdef CONFIG_ZORRO
2522 /* writing an arbitrary value to this one causes the monitor switcher */
2523 /* to flip to Amiga display */
2524 assert(cinfo->regbase != NULL);
2525 cinfo->SFR = val;
2526 z_writeb(val, cinfo->regbase + 0x9000);
2527#endif
2528}
2529
2530/*** WClut - set CLUT entry (range: 0..63) ***/
2531static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
2532 unsigned char green, unsigned char blue)
2533{
2534 unsigned int data = VGA_PEL_D;
2535
2536 /* address write mode register is not translated.. */
2537 vga_w(regbase: cinfo->regbase, VGA_PEL_IW, val: regnum);
2538
2539 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2540 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480 ||
2541 cinfo->btype == BT_SD64 || is_laguna(cinfo)) {
2542 /* but DAC data register IS, at least for Picasso II */
2543 if (cinfo->btype == BT_PICASSO)
2544 data += 0xfff;
2545 vga_w(regbase: cinfo->regbase, port: data, val: red);
2546 vga_w(regbase: cinfo->regbase, port: data, val: green);
2547 vga_w(regbase: cinfo->regbase, port: data, val: blue);
2548 } else {
2549 vga_w(regbase: cinfo->regbase, port: data, val: blue);
2550 vga_w(regbase: cinfo->regbase, port: data, val: green);
2551 vga_w(regbase: cinfo->regbase, port: data, val: red);
2552 }
2553}
2554
2555#if 0
2556/*** RClut - read CLUT entry (range 0..63) ***/
2557static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
2558 unsigned char *green, unsigned char *blue)
2559{
2560 unsigned int data = VGA_PEL_D;
2561
2562 vga_w(cinfo->regbase, VGA_PEL_IR, regnum);
2563
2564 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2565 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2566 if (cinfo->btype == BT_PICASSO)
2567 data += 0xfff;
2568 *red = vga_r(cinfo->regbase, data);
2569 *green = vga_r(cinfo->regbase, data);
2570 *blue = vga_r(cinfo->regbase, data);
2571 } else {
2572 *blue = vga_r(cinfo->regbase, data);
2573 *green = vga_r(cinfo->regbase, data);
2574 *red = vga_r(cinfo->regbase, data);
2575 }
2576}
2577#endif
2578
2579/*******************************************************************
2580 cirrusfb_WaitBLT()
2581
2582 Wait for the BitBLT engine to complete a possible earlier job
2583*********************************************************************/
2584
2585/* FIXME: use interrupts instead */
2586static void cirrusfb_WaitBLT(u8 __iomem *regbase)
2587{
2588 while (vga_rgfx(regbase, CL_GR31) & 0x08)
2589 cpu_relax();
2590}
2591
2592/*******************************************************************
2593 cirrusfb_BitBLT()
2594
2595 perform accelerated "scrolling"
2596********************************************************************/
2597
2598static void cirrusfb_set_blitter(u8 __iomem *regbase,
2599 u_short nwidth, u_short nheight,
2600 u_long nsrc, u_long ndest,
2601 u_short bltmode, u_short line_length)
2602
2603{
2604 /* pitch: set to line_length */
2605 /* dest pitch low */
2606 vga_wgfx(regbase, CL_GR24, val: line_length & 0xff);
2607 /* dest pitch hi */
2608 vga_wgfx(regbase, CL_GR25, val: line_length >> 8);
2609 /* source pitch low */
2610 vga_wgfx(regbase, CL_GR26, val: line_length & 0xff);
2611 /* source pitch hi */
2612 vga_wgfx(regbase, CL_GR27, val: line_length >> 8);
2613
2614 /* BLT width: actual number of pixels - 1 */
2615 /* BLT width low */
2616 vga_wgfx(regbase, CL_GR20, val: nwidth & 0xff);
2617 /* BLT width hi */
2618 vga_wgfx(regbase, CL_GR21, val: nwidth >> 8);
2619
2620 /* BLT height: actual number of lines -1 */
2621 /* BLT height low */
2622 vga_wgfx(regbase, CL_GR22, val: nheight & 0xff);
2623 /* BLT width hi */
2624 vga_wgfx(regbase, CL_GR23, val: nheight >> 8);
2625
2626 /* BLT destination */
2627 /* BLT dest low */
2628 vga_wgfx(regbase, CL_GR28, val: (u_char) (ndest & 0xff));
2629 /* BLT dest mid */
2630 vga_wgfx(regbase, CL_GR29, val: (u_char) (ndest >> 8));
2631 /* BLT dest hi */
2632 vga_wgfx(regbase, CL_GR2A, val: (u_char) (ndest >> 16));
2633
2634 /* BLT source */
2635 /* BLT src low */
2636 vga_wgfx(regbase, CL_GR2C, val: (u_char) (nsrc & 0xff));
2637 /* BLT src mid */
2638 vga_wgfx(regbase, CL_GR2D, val: (u_char) (nsrc >> 8));
2639 /* BLT src hi */
2640 vga_wgfx(regbase, CL_GR2E, val: (u_char) (nsrc >> 16));
2641
2642 /* BLT mode */
2643 vga_wgfx(regbase, CL_GR30, val: bltmode); /* BLT mode */
2644
2645 /* BLT ROP: SrcCopy */
2646 vga_wgfx(regbase, CL_GR32, val: 0x0d); /* BLT ROP */
2647
2648 /* and finally: GO! */
2649 vga_wgfx(regbase, CL_GR31, val: 0x02); /* BLT Start/status */
2650}
2651
2652/*******************************************************************
2653 cirrusfb_BitBLT()
2654
2655 perform accelerated "scrolling"
2656********************************************************************/
2657
2658static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
2659 u_short curx, u_short cury,
2660 u_short destx, u_short desty,
2661 u_short width, u_short height,
2662 u_short line_length)
2663{
2664 u_short nwidth = width - 1;
2665 u_short nheight = height - 1;
2666 u_long nsrc, ndest;
2667 u_char bltmode;
2668
2669 bltmode = 0x00;
2670 /* if source adr < dest addr, do the Blt backwards */
2671 if (cury <= desty) {
2672 if (cury == desty) {
2673 /* if src and dest are on the same line, check x */
2674 if (curx < destx)
2675 bltmode |= 0x01;
2676 } else
2677 bltmode |= 0x01;
2678 }
2679 /* standard case: forward blitting */
2680 nsrc = (cury * line_length) + curx;
2681 ndest = (desty * line_length) + destx;
2682 if (bltmode) {
2683 /* this means start addresses are at the end,
2684 * counting backwards
2685 */
2686 nsrc += nheight * line_length + nwidth;
2687 ndest += nheight * line_length + nwidth;
2688 }
2689
2690 cirrusfb_WaitBLT(regbase);
2691
2692 cirrusfb_set_blitter(regbase, nwidth, nheight,
2693 nsrc, ndest, bltmode, line_length);
2694}
2695
2696/*******************************************************************
2697 cirrusfb_RectFill()
2698
2699 perform accelerated rectangle fill
2700********************************************************************/
2701
2702static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
2703 u_short x, u_short y, u_short width, u_short height,
2704 u32 fg_color, u32 bg_color, u_short line_length,
2705 u_char blitmode)
2706{
2707 u_long ndest = (y * line_length) + x;
2708 u_char op;
2709
2710 cirrusfb_WaitBLT(regbase);
2711
2712 /* This is a ColorExpand Blt, using the */
2713 /* same color for foreground and background */
2714 vga_wgfx(regbase, VGA_GFX_SR_VALUE, val: bg_color);
2715 vga_wgfx(regbase, VGA_GFX_SR_ENABLE, val: fg_color);
2716
2717 op = 0x80;
2718 if (bits_per_pixel >= 16) {
2719 vga_wgfx(regbase, CL_GR10, val: bg_color >> 8);
2720 vga_wgfx(regbase, CL_GR11, val: fg_color >> 8);
2721 op = 0x90;
2722 }
2723 if (bits_per_pixel >= 24) {
2724 vga_wgfx(regbase, CL_GR12, val: bg_color >> 16);
2725 vga_wgfx(regbase, CL_GR13, val: fg_color >> 16);
2726 op = 0xa0;
2727 }
2728 if (bits_per_pixel == 32) {
2729 vga_wgfx(regbase, CL_GR14, val: bg_color >> 24);
2730 vga_wgfx(regbase, CL_GR15, val: fg_color >> 24);
2731 op = 0xb0;
2732 }
2733 cirrusfb_set_blitter(regbase, nwidth: width - 1, nheight: height - 1,
2734 nsrc: 0, ndest, bltmode: op | blitmode, line_length);
2735}
2736
2737/**************************************************************************
2738 * bestclock() - determine closest possible clock lower(?) than the
2739 * desired pixel clock
2740 **************************************************************************/
2741static void bestclock(long freq, int *nom, int *den, int *div)
2742{
2743 int n, d;
2744 long h, diff;
2745
2746 assert(nom != NULL);
2747 assert(den != NULL);
2748 assert(div != NULL);
2749
2750 *nom = 0;
2751 *den = 0;
2752 *div = 0;
2753
2754 if (freq < 8000)
2755 freq = 8000;
2756
2757 diff = freq;
2758
2759 for (n = 32; n < 128; n++) {
2760 int s = 0;
2761
2762 d = (14318 * n) / freq;
2763 if ((d >= 7) && (d <= 63)) {
2764 int temp = d;
2765
2766 if (temp > 31) {
2767 s = 1;
2768 temp >>= 1;
2769 }
2770 h = ((14318 * n) / temp) >> s;
2771 h = h > freq ? h - freq : freq - h;
2772 if (h < diff) {
2773 diff = h;
2774 *nom = n;
2775 *den = temp;
2776 *div = s;
2777 }
2778 }
2779 d++;
2780 if ((d >= 7) && (d <= 63)) {
2781 if (d > 31) {
2782 s = 1;
2783 d >>= 1;
2784 }
2785 h = ((14318 * n) / d) >> s;
2786 h = h > freq ? h - freq : freq - h;
2787 if (h < diff) {
2788 diff = h;
2789 *nom = n;
2790 *den = d;
2791 *div = s;
2792 }
2793 }
2794 }
2795}
2796
2797/* -------------------------------------------------------------------------
2798 *
2799 * debugging functions
2800 *
2801 * -------------------------------------------------------------------------
2802 */
2803
2804#ifdef CIRRUSFB_DEBUG
2805
2806/*
2807 * cirrusfb_dbg_print_regs
2808 * @regbase: If using newmmio, the newmmio base address, otherwise %NULL
2809 * @reg_class: type of registers to read: %CRT, or %SEQ
2810 *
2811 * DESCRIPTION:
2812 * Dumps the given list of VGA CRTC registers. If @base is %NULL,
2813 * old-style I/O ports are queried for information, otherwise MMIO is
2814 * used at the given @base address to query the information.
2815 */
2816
2817static void cirrusfb_dbg_print_regs(struct fb_info *info,
2818 caddr_t regbase,
2819 enum cirrusfb_dbg_reg_class reg_class, ...)
2820{
2821 va_list list;
2822 unsigned char val = 0;
2823 unsigned reg;
2824 char *name;
2825
2826 va_start(list, reg_class);
2827
2828 name = va_arg(list, char *);
2829 while (name != NULL) {
2830 reg = va_arg(list, int);
2831
2832 switch (reg_class) {
2833 case CRT:
2834 val = vga_rcrt(regbase, (unsigned char) reg);
2835 break;
2836 case SEQ:
2837 val = vga_rseq(regbase, (unsigned char) reg);
2838 break;
2839 default:
2840 /* should never occur */
2841 assert(false);
2842 break;
2843 }
2844
2845 dev_dbg(info->device, "%8s = 0x%02X\n", name, val);
2846
2847 name = va_arg(list, char *);
2848 }
2849
2850 va_end(list);
2851}
2852
2853/*
2854 * cirrusfb_dbg_reg_dump
2855 * @base: If using newmmio, the newmmio base address, otherwise %NULL
2856 *
2857 * DESCRIPTION:
2858 * Dumps a list of interesting VGA and CIRRUSFB 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.
2861 */
2862
2863static void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase)
2864{
2865 dev_dbg(info->device, "VGA CRTC register dump:\n");
2866
2867 cirrusfb_dbg_print_regs(info, regbase, CRT,
2868 "CR00", 0x00,
2869 "CR01", 0x01,
2870 "CR02", 0x02,
2871 "CR03", 0x03,
2872 "CR04", 0x04,
2873 "CR05", 0x05,
2874 "CR06", 0x06,
2875 "CR07", 0x07,
2876 "CR08", 0x08,
2877 "CR09", 0x09,
2878 "CR0A", 0x0A,
2879 "CR0B", 0x0B,
2880 "CR0C", 0x0C,
2881 "CR0D", 0x0D,
2882 "CR0E", 0x0E,
2883 "CR0F", 0x0F,
2884 "CR10", 0x10,
2885 "CR11", 0x11,
2886 "CR12", 0x12,
2887 "CR13", 0x13,
2888 "CR14", 0x14,
2889 "CR15", 0x15,
2890 "CR16", 0x16,
2891 "CR17", 0x17,
2892 "CR18", 0x18,
2893 "CR22", 0x22,
2894 "CR24", 0x24,
2895 "CR26", 0x26,
2896 "CR2D", 0x2D,
2897 "CR2E", 0x2E,
2898 "CR2F", 0x2F,
2899 "CR30", 0x30,
2900 "CR31", 0x31,
2901 "CR32", 0x32,
2902 "CR33", 0x33,
2903 "CR34", 0x34,
2904 "CR35", 0x35,
2905 "CR36", 0x36,
2906 "CR37", 0x37,
2907 "CR38", 0x38,
2908 "CR39", 0x39,
2909 "CR3A", 0x3A,
2910 "CR3B", 0x3B,
2911 "CR3C", 0x3C,
2912 "CR3D", 0x3D,
2913 "CR3E", 0x3E,
2914 "CR3F", 0x3F,
2915 NULL);
2916
2917 dev_dbg(info->device, "\n");
2918
2919 dev_dbg(info->device, "VGA SEQ register dump:\n");
2920
2921 cirrusfb_dbg_print_regs(info, regbase, SEQ,
2922 "SR00", 0x00,
2923 "SR01", 0x01,
2924 "SR02", 0x02,
2925 "SR03", 0x03,
2926 "SR04", 0x04,
2927 "SR08", 0x08,
2928 "SR09", 0x09,
2929 "SR0A", 0x0A,
2930 "SR0B", 0x0B,
2931 "SR0D", 0x0D,
2932 "SR10", 0x10,
2933 "SR11", 0x11,
2934 "SR12", 0x12,
2935 "SR13", 0x13,
2936 "SR14", 0x14,
2937 "SR15", 0x15,
2938 "SR16", 0x16,
2939 "SR17", 0x17,
2940 "SR18", 0x18,
2941 "SR19", 0x19,
2942 "SR1A", 0x1A,
2943 "SR1B", 0x1B,
2944 "SR1C", 0x1C,
2945 "SR1D", 0x1D,
2946 "SR1E", 0x1E,
2947 "SR1F", 0x1F,
2948 NULL);
2949
2950 dev_dbg(info->device, "\n");
2951}
2952
2953#endif /* CIRRUSFB_DEBUG */
2954
2955

source code of linux/drivers/video/fbdev/cirrusfb.c