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