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