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