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