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