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