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