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