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