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