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