cirrusfb: convert printks to dev_foo
[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) {
870 vga_wseq(regbase, CL_SEQRB, nom);
871 tmp = den << 1;
872 if (div != 0)
873 tmp |= 1;
874
875 /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
876 if ((cinfo->btype == BT_SD64) ||
877 (cinfo->btype == BT_ALPINE) ||
878 (cinfo->btype == BT_GD5480))
879 tmp |= 0x80;
880
75ed3a17 881 dev_dbg(info->device, "CL_SEQR1B: %ld\n", (long) tmp);
486ff387
KH
882 vga_wseq(regbase, CL_SEQR1B, tmp);
883 }
1da177e4 884
9a85cf51 885 if (yres >= 1024)
1da177e4 886 /* 1280x1024 */
8503df65 887 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7);
1da177e4
LT
888 else
889 /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
890 * address wrap, no compat. */
8503df65 891 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3);
1da177e4 892
8503df65
KH
893/* HAEH? vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20);
894 * previously: 0x00 unlock VGA_CRTC_H_TOTAL..CRT7 */
1da177e4
LT
895
896 /* don't know if it would hurt to also program this if no interlaced */
897 /* mode is used, but I feel better this way.. :-) */
898 if (var->vmode & FB_VMODE_INTERLACED)
9a85cf51 899 vga_wcrt(regbase, VGA_CRTC_REGS, htotal / 2);
1da177e4 900 else
8503df65 901 vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
1da177e4 902
8503df65 903 vga_wseq(regbase, VGA_SEQ_CHARACTER_MAP, 0);
1da177e4
LT
904
905 /* adjust horizontal/vertical sync type (low/high) */
8503df65
KH
906 /* enable display memory & CRTC I/O address for color mode */
907 tmp = 0x03;
1da177e4
LT
908 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
909 tmp |= 0x40;
910 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
911 tmp |= 0x80;
8503df65 912 WGen(cinfo, VGA_MIS_W, tmp);
1da177e4 913
8503df65
KH
914 /* Screen A Preset Row-Scan register */
915 vga_wcrt(regbase, VGA_CRTC_PRESET_ROW, 0);
916 /* text cursor on and start line */
917 vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0);
918 /* text cursor end line */
919 vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 31);
1da177e4
LT
920
921 /******************************************************
922 *
923 * 1 bpp
924 *
925 */
926
927 /* programming for different color depths */
928 if (var->bits_per_pixel == 1) {
75ed3a17 929 dev_dbg(info->device, "preparing for 1 bit deep display\n");
8503df65 930 vga_wgfx(regbase, VGA_GFX_MODE, 0); /* mode register */
1da177e4
LT
931
932 /* SR07 */
933 switch (cinfo->btype) {
934 case BT_SD64:
935 case BT_PICCOLO:
936 case BT_PICASSO:
937 case BT_SPECTRUM:
938 case BT_PICASSO4:
939 case BT_ALPINE:
940 case BT_GD5480:
8503df65 941 vga_wseq(regbase, CL_SEQR7,
75ed3a17 942 regs.multiplexing ?
1da177e4
LT
943 bi->sr07_1bpp_mux : bi->sr07_1bpp);
944 break;
945
946 case BT_LAGUNA:
8503df65
KH
947 vga_wseq(regbase, CL_SEQR7,
948 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1da177e4
LT
949 break;
950
951 default:
75ed3a17 952 dev_warn(info->device, "unknown Board\n");
1da177e4
LT
953 break;
954 }
955
956 /* Extended Sequencer Mode */
957 switch (cinfo->btype) {
958 case BT_SD64:
8503df65
KH
959 /* setting the SEQRF on SD64 is not necessary
960 * (only during init)
961 */
8503df65
KH
962 /* MCLK select */
963 vga_wseq(regbase, CL_SEQR1F, 0x1a);
1da177e4
LT
964 break;
965
966 case BT_PICCOLO:
060b6002 967 case BT_SPECTRUM:
8503df65
KH
968 /* ### ueberall 0x22? */
969 /* ##vorher 1c MCLK select */
970 vga_wseq(regbase, CL_SEQR1F, 0x22);
971 /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
972 vga_wseq(regbase, CL_SEQRF, 0xb0);
1da177e4
LT
973 break;
974
975 case BT_PICASSO:
8503df65
KH
976 /* ##vorher 22 MCLK select */
977 vga_wseq(regbase, CL_SEQR1F, 0x22);
978 /* ## vorher d0 avoid FIFO underruns..? */
979 vga_wseq(regbase, CL_SEQRF, 0xd0);
1da177e4
LT
980 break;
981
1da177e4
LT
982 case BT_PICASSO4:
983 case BT_ALPINE:
984 case BT_GD5480:
985 case BT_LAGUNA:
1da177e4
LT
986 /* do nothing */
987 break;
988
989 default:
75ed3a17 990 dev_warn(info->device, "unknown Board\n");
1da177e4
LT
991 break;
992 }
993
8503df65
KH
994 /* pixel mask: pass-through for first plane */
995 WGen(cinfo, VGA_PEL_MSK, 0x01);
1da177e4 996 if (regs.multiplexing)
8503df65
KH
997 /* hidden dac reg: 1280x1024 */
998 WHDR(cinfo, 0x4a);
1da177e4 999 else
8503df65
KH
1000 /* hidden dac: nothing */
1001 WHDR(cinfo, 0);
1002 /* memory mode: odd/even, ext. memory */
1003 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06);
1004 /* plane mask: only write to first plane */
1005 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01);
1da177e4
LT
1006 offset = var->xres_virtual / 16;
1007 }
1008
1009 /******************************************************
1010 *
1011 * 8 bpp
1012 *
1013 */
1014
1015 else if (var->bits_per_pixel == 8) {
75ed3a17 1016 dev_dbg(info->device, "preparing for 8 bit deep display\n");
1da177e4
LT
1017 switch (cinfo->btype) {
1018 case BT_SD64:
1019 case BT_PICCOLO:
1020 case BT_PICASSO:
1021 case BT_SPECTRUM:
1022 case BT_PICASSO4:
1023 case BT_ALPINE:
1024 case BT_GD5480:
8503df65 1025 vga_wseq(regbase, CL_SEQR7,
1da177e4
LT
1026 regs.multiplexing ?
1027 bi->sr07_8bpp_mux : bi->sr07_8bpp);
1028 break;
1029
1030 case BT_LAGUNA:
8503df65
KH
1031 vga_wseq(regbase, CL_SEQR7,
1032 vga_rseq(regbase, CL_SEQR7) | 0x01);
1da177e4
LT
1033 break;
1034
1035 default:
75ed3a17 1036 dev_warn(info->device, "unknown Board\n");
1da177e4
LT
1037 break;
1038 }
1039
1040 switch (cinfo->btype) {
1041 case BT_SD64:
8503df65
KH
1042 /* MCLK select */
1043 vga_wseq(regbase, CL_SEQR1F, 0x1d);
1da177e4
LT
1044 break;
1045
1046 case BT_PICCOLO:
1da177e4 1047 case BT_PICASSO:
1da177e4 1048 case BT_SPECTRUM:
8503df65
KH
1049 /* ### vorher 1c MCLK select */
1050 vga_wseq(regbase, CL_SEQR1F, 0x22);
1051 /* Fast Page-Mode writes */
1052 vga_wseq(regbase, CL_SEQRF, 0xb0);
1da177e4
LT
1053 break;
1054
1055 case BT_PICASSO4:
1056#ifdef CONFIG_ZORRO
8503df65
KH
1057 /* ### INCOMPLETE!! */
1058 vga_wseq(regbase, CL_SEQRF, 0xb8);
1da177e4 1059#endif
8503df65 1060/* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1da177e4
LT
1061 break;
1062
1063 case BT_ALPINE:
1da177e4
LT
1064 /* We already set SRF and SR1F */
1065 break;
1066
1067 case BT_GD5480:
1068 case BT_LAGUNA:
1da177e4
LT
1069 /* do nothing */
1070 break;
1071
1072 default:
75ed3a17 1073 dev_warn(info->device, "unknown board\n");
1da177e4
LT
1074 break;
1075 }
1076
8503df65
KH
1077 /* mode register: 256 color mode */
1078 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1079 /* pixel mask: pass-through all planes */
1080 WGen(cinfo, VGA_PEL_MSK, 0xff);
1da177e4 1081 if (regs.multiplexing)
8503df65
KH
1082 /* hidden dac reg: 1280x1024 */
1083 WHDR(cinfo, 0x4a);
1da177e4 1084 else
8503df65
KH
1085 /* hidden dac: nothing */
1086 WHDR(cinfo, 0);
1087 /* memory mode: chain4, ext. memory */
1088 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1089 /* plane mask: enable writing to all 4 planes */
1090 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1da177e4
LT
1091 offset = var->xres_virtual / 8;
1092 }
1093
1094 /******************************************************
1095 *
1096 * 16 bpp
1097 *
1098 */
1099
1100 else if (var->bits_per_pixel == 16) {
75ed3a17 1101 dev_dbg(info->device, "preparing for 16 bit deep display\n");
1da177e4
LT
1102 switch (cinfo->btype) {
1103 case BT_SD64:
8503df65
KH
1104 /* Extended Sequencer Mode: 256c col. mode */
1105 vga_wseq(regbase, CL_SEQR7, 0xf7);
1106 /* MCLK select */
1107 vga_wseq(regbase, CL_SEQR1F, 0x1e);
1da177e4
LT
1108 break;
1109
1110 case BT_PICCOLO:
060b6002 1111 case BT_SPECTRUM:
8503df65
KH
1112 vga_wseq(regbase, CL_SEQR7, 0x87);
1113 /* Fast Page-Mode writes */
1114 vga_wseq(regbase, CL_SEQRF, 0xb0);
1115 /* MCLK select */
1116 vga_wseq(regbase, CL_SEQR1F, 0x22);
1da177e4
LT
1117 break;
1118
1119 case BT_PICASSO:
8503df65
KH
1120 vga_wseq(regbase, CL_SEQR7, 0x27);
1121 /* Fast Page-Mode writes */
1122 vga_wseq(regbase, CL_SEQRF, 0xb0);
1123 /* MCLK select */
1124 vga_wseq(regbase, CL_SEQR1F, 0x22);
1da177e4
LT
1125 break;
1126
1da177e4 1127 case BT_PICASSO4:
8503df65
KH
1128 vga_wseq(regbase, CL_SEQR7, 0x27);
1129/* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1da177e4
LT
1130 break;
1131
1132 case BT_ALPINE:
3b921832 1133 vga_wseq(regbase, CL_SEQR7, 0xa7);
1da177e4
LT
1134 break;
1135
1136 case BT_GD5480:
8503df65 1137 vga_wseq(regbase, CL_SEQR7, 0x17);
1da177e4
LT
1138 /* We already set SRF and SR1F */
1139 break;
1140
1141 case BT_LAGUNA:
8503df65
KH
1142 vga_wseq(regbase, CL_SEQR7,
1143 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1da177e4
LT
1144 break;
1145
1146 default:
75ed3a17 1147 dev_warn(info->device, "unknown Board\n");
1da177e4
LT
1148 break;
1149 }
1150
8503df65
KH
1151 /* mode register: 256 color mode */
1152 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1153 /* pixel mask: pass-through all planes */
1154 WGen(cinfo, VGA_PEL_MSK, 0xff);
1da177e4 1155#ifdef CONFIG_PCI
8503df65 1156 WHDR(cinfo, 0xc0); /* Copy Xbh */
1da177e4
LT
1157#elif defined(CONFIG_ZORRO)
1158 /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
8503df65 1159 WHDR(cinfo, 0xa0); /* hidden dac reg: nothing special */
1da177e4 1160#endif
8503df65
KH
1161 /* memory mode: chain4, ext. memory */
1162 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1163 /* plane mask: enable writing to all 4 planes */
1164 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1da177e4
LT
1165 offset = var->xres_virtual / 4;
1166 }
1167
1168 /******************************************************
1169 *
1170 * 32 bpp
1171 *
1172 */
1173
1174 else if (var->bits_per_pixel == 32) {
75ed3a17 1175 dev_dbg(info->device, "preparing for 32 bit deep display\n");
1da177e4
LT
1176 switch (cinfo->btype) {
1177 case BT_SD64:
8503df65
KH
1178 /* Extended Sequencer Mode: 256c col. mode */
1179 vga_wseq(regbase, CL_SEQR7, 0xf9);
1180 /* MCLK select */
1181 vga_wseq(regbase, CL_SEQR1F, 0x1e);
1da177e4
LT
1182 break;
1183
1184 case BT_PICCOLO:
060b6002 1185 case BT_SPECTRUM:
8503df65
KH
1186 vga_wseq(regbase, CL_SEQR7, 0x85);
1187 /* Fast Page-Mode writes */
1188 vga_wseq(regbase, CL_SEQRF, 0xb0);
1189 /* MCLK select */
1190 vga_wseq(regbase, CL_SEQR1F, 0x22);
1da177e4
LT
1191 break;
1192
1193 case BT_PICASSO:
8503df65
KH
1194 vga_wseq(regbase, CL_SEQR7, 0x25);
1195 /* Fast Page-Mode writes */
1196 vga_wseq(regbase, CL_SEQRF, 0xb0);
1197 /* MCLK select */
1198 vga_wseq(regbase, CL_SEQR1F, 0x22);
1da177e4
LT
1199 break;
1200
1da177e4 1201 case BT_PICASSO4:
8503df65
KH
1202 vga_wseq(regbase, CL_SEQR7, 0x25);
1203/* vga_wseq(regbase, CL_SEQR1F, 0x1c); */
1da177e4
LT
1204 break;
1205
1206 case BT_ALPINE:
8503df65 1207 vga_wseq(regbase, CL_SEQR7, 0xa9);
1da177e4
LT
1208 break;
1209
1210 case BT_GD5480:
8503df65 1211 vga_wseq(regbase, CL_SEQR7, 0x19);
1da177e4
LT
1212 /* We already set SRF and SR1F */
1213 break;
1214
1215 case BT_LAGUNA:
8503df65
KH
1216 vga_wseq(regbase, CL_SEQR7,
1217 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1da177e4
LT
1218 break;
1219
1220 default:
75ed3a17 1221 dev_warn(info->device, "unknown Board\n");
1da177e4
LT
1222 break;
1223 }
1224
8503df65
KH
1225 /* mode register: 256 color mode */
1226 vga_wgfx(regbase, VGA_GFX_MODE, 64);
1227 /* pixel mask: pass-through all planes */
1228 WGen(cinfo, VGA_PEL_MSK, 0xff);
1229 /* hidden dac reg: 8-8-8 mode (24 or 32) */
1230 WHDR(cinfo, 0xc5);
1231 /* memory mode: chain4, ext. memory */
1232 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
1233 /* plane mask: enable writing to all 4 planes */
1234 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1da177e4
LT
1235 offset = var->xres_virtual / 4;
1236 }
1237
1238 /******************************************************
1239 *
1240 * unknown/unsupported bpp
1241 *
1242 */
1243
8503df65 1244 else
75ed3a17
KH
1245 dev_err(info->device,
1246 "What's this? requested color depth == %d.\n",
1da177e4 1247 var->bits_per_pixel);
1da177e4 1248
8503df65 1249 vga_wcrt(regbase, VGA_CRTC_OFFSET, offset & 0xff);
1da177e4
LT
1250 tmp = 0x22;
1251 if (offset & 0x100)
1252 tmp |= 0x10; /* offset overflow bit */
1253
8503df65
KH
1254 /* screen start addr #16-18, fastpagemode cycles */
1255 vga_wcrt(regbase, CL_CRT1B, tmp);
1da177e4
LT
1256
1257 if (cinfo->btype == BT_SD64 ||
1258 cinfo->btype == BT_PICASSO4 ||
1259 cinfo->btype == BT_ALPINE ||
1260 cinfo->btype == BT_GD5480)
8503df65
KH
1261 /* screen start address bit 19 */
1262 vga_wcrt(regbase, CL_CRT1D, 0x00);
1263
1264 /* text cursor location high */
1265 vga_wcrt(regbase, VGA_CRTC_CURSOR_HI, 0);
1266 /* text cursor location low */
1267 vga_wcrt(regbase, VGA_CRTC_CURSOR_LO, 0);
1268 /* underline row scanline = at very bottom */
1269 vga_wcrt(regbase, VGA_CRTC_UNDERLINE, 0);
1270
1271 /* controller mode */
1272 vga_wattr(regbase, VGA_ATC_MODE, 1);
1273 /* overscan (border) color */
1274 vga_wattr(regbase, VGA_ATC_OVERSCAN, 0);
1275 /* color plane enable */
1276 vga_wattr(regbase, VGA_ATC_PLANE_ENABLE, 15);
1277 /* pixel panning */
1278 vga_wattr(regbase, CL_AR33, 0);
1279 /* color select */
1280 vga_wattr(regbase, VGA_ATC_COLOR_PAGE, 0);
1da177e4
LT
1281
1282 /* [ EGS: SetOffset(); ] */
1283 /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
8503df65
KH
1284 AttrOn(cinfo);
1285
1286 /* set/reset register */
1287 vga_wgfx(regbase, VGA_GFX_SR_VALUE, 0);
1288 /* set/reset enable */
1289 vga_wgfx(regbase, VGA_GFX_SR_ENABLE, 0);
1290 /* color compare */
1291 vga_wgfx(regbase, VGA_GFX_COMPARE_VALUE, 0);
1292 /* data rotate */
1293 vga_wgfx(regbase, VGA_GFX_DATA_ROTATE, 0);
1294 /* read map select */
1295 vga_wgfx(regbase, VGA_GFX_PLANE_READ, 0);
1296 /* miscellaneous register */
1297 vga_wgfx(regbase, VGA_GFX_MISC, 1);
1298 /* color don't care */
1299 vga_wgfx(regbase, VGA_GFX_COMPARE_MASK, 15);
1300 /* bit mask */
1301 vga_wgfx(regbase, VGA_GFX_BIT_MASK, 255);
1302
1303 /* graphics cursor attributes: nothing special */
1304 vga_wseq(regbase, CL_SEQR12, 0x0);
1da177e4
LT
1305
1306 /* finally, turn on everything - turn off "FullBandwidth" bit */
1307 /* also, set "DotClock%2" bit where requested */
1308 tmp = 0x01;
1309
1310/*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
1311 if (var->vmode & FB_VMODE_CLOCK_HALVE)
1312 tmp |= 0x08;
1313*/
1314
8503df65 1315 vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp);
75ed3a17 1316 dev_dbg(info->device, "CL_SEQR1: %d\n", tmp);
1da177e4
LT
1317
1318 cinfo->currentmode = regs;
1da177e4
LT
1319
1320 /* pan to requested offset */
8503df65 1321 cirrusfb_pan_display(var, info);
1da177e4
LT
1322
1323#ifdef CIRRUSFB_DEBUG
75ed3a17 1324 cirrusfb_dbg_reg_dump(info, NULL);
1da177e4
LT
1325#endif
1326
1da177e4
LT
1327 return 0;
1328}
1329
1330/* for some reason incomprehensible to me, cirrusfb requires that you write
1331 * the registers twice for the settings to take..grr. -dte */
8503df65 1332static int cirrusfb_set_par(struct fb_info *info)
1da177e4 1333{
8503df65
KH
1334 cirrusfb_set_par_foo(info);
1335 return cirrusfb_set_par_foo(info);
1da177e4
LT
1336}
1337
8503df65
KH
1338static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1339 unsigned blue, unsigned transp,
1340 struct fb_info *info)
1da177e4
LT
1341{
1342 struct cirrusfb_info *cinfo = info->par;
1343
1344 if (regno > 255)
1345 return -EINVAL;
1346
1347 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
1348 u32 v;
1349 red >>= (16 - info->var.red.length);
1350 green >>= (16 - info->var.green.length);
1351 blue >>= (16 - info->var.blue.length);
1352
8503df65 1353 if (regno >= 16)
1da177e4
LT
1354 return 1;
1355 v = (red << info->var.red.offset) |
1356 (green << info->var.green.offset) |
1357 (blue << info->var.blue.offset);
1358
060b6002 1359 cinfo->pseudo_palette[regno] = v;
1da177e4
LT
1360 return 0;
1361 }
1362
8503df65
KH
1363 if (info->var.bits_per_pixel == 8)
1364 WClut(cinfo, regno, red >> 10, green >> 10, blue >> 10);
1da177e4
LT
1365
1366 return 0;
1367
1368}
1369
1370/*************************************************************************
1371 cirrusfb_pan_display()
1372
1373 performs display panning - provided hardware permits this
1374**************************************************************************/
8503df65
KH
1375static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
1376 struct fb_info *info)
1da177e4
LT
1377{
1378 int xoffset = 0;
1379 int yoffset = 0;
1380 unsigned long base;
1381 unsigned char tmp = 0, tmp2 = 0, xpix;
1382 struct cirrusfb_info *cinfo = info->par;
1383
75ed3a17
KH
1384 dev_dbg(info->device,
1385 "virtual offset: (%d,%d)\n", var->xoffset, var->yoffset);
1da177e4
LT
1386
1387 /* no range checks for xoffset and yoffset, */
1388 /* as fb_pan_display has already done this */
1389 if (var->vmode & FB_VMODE_YWRAP)
1390 return -EINVAL;
1391
1392 info->var.xoffset = var->xoffset;
1393 info->var.yoffset = var->yoffset;
1394
1395 xoffset = var->xoffset * info->var.bits_per_pixel / 8;
1396 yoffset = var->yoffset;
1397
0ff1edee 1398 base = yoffset * info->fix.line_length + xoffset;
1da177e4
LT
1399
1400 if (info->var.bits_per_pixel == 1) {
1401 /* base is already correct */
1402 xpix = (unsigned char) (var->xoffset % 8);
1403 } else {
1404 base /= 4;
1405 xpix = (unsigned char) ((xoffset % 4) * 2);
1406 }
1407
8503df65 1408 cirrusfb_WaitBLT(cinfo->regbase); /* make sure all the BLT's are done */
1da177e4
LT
1409
1410 /* lower 8 + 8 bits of screen start address */
8503df65
KH
1411 vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO,
1412 (unsigned char) (base & 0xff));
1413 vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI,
1414 (unsigned char) (base >> 8));
1da177e4
LT
1415
1416 /* construct bits 16, 17 and 18 of screen start address */
1417 if (base & 0x10000)
1418 tmp |= 0x01;
1419 if (base & 0x20000)
1420 tmp |= 0x04;
1421 if (base & 0x40000)
1422 tmp |= 0x08;
1423
8503df65
KH
1424 /* 0xf2 is %11110010, exclude tmp bits */
1425 tmp2 = (vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2) | tmp;
1426 vga_wcrt(cinfo->regbase, CL_CRT1B, tmp2);
1da177e4
LT
1427
1428 /* construct bit 19 of screen start address */
060b6002
KH
1429 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19)
1430 vga_wcrt(cinfo->regbase, CL_CRT1D, (base >> 12) & 0x80);
1da177e4 1431
8503df65
KH
1432 /* write pixel panning value to AR33; this does not quite work in 8bpp
1433 *
1434 * ### Piccolo..? Will this work?
1435 */
1da177e4 1436 if (info->var.bits_per_pixel == 1)
8503df65 1437 vga_wattr(cinfo->regbase, CL_AR33, xpix);
1da177e4 1438
8503df65 1439 cirrusfb_WaitBLT(cinfo->regbase);
1da177e4 1440
8503df65 1441 return 0;
1da177e4
LT
1442}
1443
8503df65 1444static int cirrusfb_blank(int blank_mode, struct fb_info *info)
1da177e4
LT
1445{
1446 /*
8503df65
KH
1447 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
1448 * then the caller blanks by setting the CLUT (Color Look Up Table)
1449 * to all black. Return 0 if blanking succeeded, != 0 if un-/blanking
1450 * failed due to e.g. a video mode which doesn't support it.
1451 * Implements VESA suspend and powerdown modes on hardware that
1452 * supports disabling hsync/vsync:
1453 * blank_mode == 2: suspend vsync
1454 * blank_mode == 3: suspend hsync
1455 * blank_mode == 4: powerdown
1da177e4
LT
1456 */
1457 unsigned char val;
1458 struct cirrusfb_info *cinfo = info->par;
1459 int current_mode = cinfo->blank_mode;
1460
75ed3a17 1461 dev_dbg(info->device, "ENTER, blank mode = %d\n", blank_mode);
1da177e4
LT
1462
1463 if (info->state != FBINFO_STATE_RUNNING ||
1464 current_mode == blank_mode) {
75ed3a17 1465 dev_dbg(info->device, "EXIT, returning 0\n");
1da177e4
LT
1466 return 0;
1467 }
1468
1469 /* Undo current */
1470 if (current_mode == FB_BLANK_NORMAL ||
1471 current_mode == FB_BLANK_UNBLANK) {
1472 /* unblank the screen */
8503df65
KH
1473 val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1474 /* clear "FullBandwidth" bit */
1475 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val & 0xdf);
1da177e4 1476 /* and undo VESA suspend trickery */
8503df65 1477 vga_wgfx(cinfo->regbase, CL_GRE, 0x00);
1da177e4
LT
1478 }
1479
1480 /* set new */
8503df65 1481 if (blank_mode > FB_BLANK_NORMAL) {
1da177e4 1482 /* blank the screen */
8503df65
KH
1483 val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1484 /* set "FullBandwidth" bit */
1485 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val | 0x20);
1da177e4
LT
1486 }
1487
1488 switch (blank_mode) {
1489 case FB_BLANK_UNBLANK:
1490 case FB_BLANK_NORMAL:
1491 break;
1492 case FB_BLANK_VSYNC_SUSPEND:
8503df65 1493 vga_wgfx(cinfo->regbase, CL_GRE, 0x04);
1da177e4
LT
1494 break;
1495 case FB_BLANK_HSYNC_SUSPEND:
8503df65 1496 vga_wgfx(cinfo->regbase, CL_GRE, 0x02);
1da177e4
LT
1497 break;
1498 case FB_BLANK_POWERDOWN:
8503df65 1499 vga_wgfx(cinfo->regbase, CL_GRE, 0x06);
1da177e4
LT
1500 break;
1501 default:
75ed3a17 1502 dev_dbg(info->device, "EXIT, returning 1\n");
1da177e4
LT
1503 return 1;
1504 }
1505
1506 cinfo->blank_mode = blank_mode;
75ed3a17 1507 dev_dbg(info->device, "EXIT, returning 0\n");
1da177e4
LT
1508
1509 /* Let fbcon do a soft blank for us */
1510 return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
1511}
1512/**** END Hardware specific Routines **************************************/
1513/****************************************************************************/
1514/**** BEGIN Internal Routines ***********************************************/
1515
9199ec5c 1516static void init_vgachip(struct fb_info *info)
1da177e4 1517{
9199ec5c 1518 struct cirrusfb_info *cinfo = info->par;
1da177e4
LT
1519 const struct cirrusfb_board_info_rec *bi;
1520
8503df65 1521 assert(cinfo != NULL);
1da177e4
LT
1522
1523 bi = &cirrusfb_board_info[cinfo->btype];
1524
1525 /* reset board globally */
1526 switch (cinfo->btype) {
1527 case BT_PICCOLO:
8503df65
KH
1528 WSFR(cinfo, 0x01);
1529 udelay(500);
1530 WSFR(cinfo, 0x51);
1531 udelay(500);
1da177e4
LT
1532 break;
1533 case BT_PICASSO:
8503df65
KH
1534 WSFR2(cinfo, 0xff);
1535 udelay(500);
1da177e4
LT
1536 break;
1537 case BT_SD64:
1538 case BT_SPECTRUM:
8503df65
KH
1539 WSFR(cinfo, 0x1f);
1540 udelay(500);
1541 WSFR(cinfo, 0x4f);
1542 udelay(500);
1da177e4
LT
1543 break;
1544 case BT_PICASSO4:
8503df65
KH
1545 /* disable flickerfixer */
1546 vga_wcrt(cinfo->regbase, CL_CRT51, 0x00);
1547 mdelay(100);
1548 /* from Klaus' NetBSD driver: */
1549 vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
1550 /* put blitter into 542x compat */
1551 vga_wgfx(cinfo->regbase, CL_GR33, 0x00);
1552 /* mode */
1553 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1da177e4
LT
1554 break;
1555
1556 case BT_GD5480:
8503df65
KH
1557 /* from Klaus' NetBSD driver: */
1558 vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
1da177e4
LT
1559 break;
1560
1561 case BT_ALPINE:
1562 /* Nothing to do to reset the board. */
1563 break;
1564
1565 default:
75ed3a17 1566 dev_err(info->device, "Warning: Unknown board type\n");
1da177e4
LT
1567 break;
1568 }
1569
9199ec5c
KH
1570 /* make sure RAM size set by this point */
1571 assert(info->screen_size > 0);
1da177e4
LT
1572
1573 /* the P4 is not fully initialized here; I rely on it having been */
1574 /* inited under AmigaOS already, which seems to work just fine */
8503df65 1575 /* (Klaus advised to do it this way) */
1da177e4
LT
1576
1577 if (cinfo->btype != BT_PICASSO4) {
8503df65
KH
1578 WGen(cinfo, CL_VSSM, 0x10); /* EGS: 0x16 */
1579 WGen(cinfo, CL_POS102, 0x01);
1580 WGen(cinfo, CL_VSSM, 0x08); /* EGS: 0x0e */
1da177e4
LT
1581
1582 if (cinfo->btype != BT_SD64)
8503df65 1583 WGen(cinfo, CL_VSSM2, 0x01);
1da177e4 1584
8503df65
KH
1585 /* reset sequencer logic */
1586 vga_wseq(cinfo->regbase, CL_SEQR0, 0x03);
1da177e4 1587
8503df65
KH
1588 /* FullBandwidth (video off) and 8/9 dot clock */
1589 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21);
1590 /* polarity (-/-), disable access to display memory,
1591 * VGA_CRTC_START_HI base address: color
1592 */
1593 WGen(cinfo, VGA_MIS_W, 0xc1);
1da177e4 1594
8503df65
KH
1595 /* "magic cookie" - doesn't make any sense to me.. */
1596/* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */
1597 /* unlock all extension registers */
1598 vga_wseq(cinfo->regbase, CL_SEQR6, 0x12);
1da177e4 1599
8503df65
KH
1600 /* reset blitter */
1601 vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
1da177e4
LT
1602
1603 switch (cinfo->btype) {
1604 case BT_GD5480:
8503df65 1605 vga_wseq(cinfo->regbase, CL_SEQRF, 0x98);
1da177e4
LT
1606 break;
1607 case BT_ALPINE:
1608 break;
1609 case BT_SD64:
8503df65 1610 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8);
1da177e4
LT
1611 break;
1612 default:
8503df65
KH
1613 vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f);
1614 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb0);
1da177e4
LT
1615 break;
1616 }
1617 }
8503df65
KH
1618 /* plane mask: nothing */
1619 vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff);
1620 /* character map select: doesn't even matter in gx mode */
1621 vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00);
1622 /* memory mode: chain-4, no odd/even, ext. memory */
1623 vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0e);
1da177e4
LT
1624
1625 /* controller-internal base address of video memory */
1626 if (bi->init_sr07)
8503df65 1627 vga_wseq(cinfo->regbase, CL_SEQR7, bi->sr07);
1da177e4 1628
8503df65
KH
1629 /* vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */
1630 /* EEPROM control: shouldn't be necessary to write to this at all.. */
1da177e4 1631
8503df65
KH
1632 /* graphics cursor X position (incomplete; position gives rem. 3 bits */
1633 vga_wseq(cinfo->regbase, CL_SEQR10, 0x00);
1634 /* graphics cursor Y position (..."... ) */
1635 vga_wseq(cinfo->regbase, CL_SEQR11, 0x00);
1636 /* graphics cursor attributes */
1637 vga_wseq(cinfo->regbase, CL_SEQR12, 0x00);
1638 /* graphics cursor pattern address */
1639 vga_wseq(cinfo->regbase, CL_SEQR13, 0x00);
1da177e4
LT
1640
1641 /* writing these on a P4 might give problems.. */
1642 if (cinfo->btype != BT_PICASSO4) {
8503df65
KH
1643 /* configuration readback and ext. color */
1644 vga_wseq(cinfo->regbase, CL_SEQR17, 0x00);
1645 /* signature generator */
1646 vga_wseq(cinfo->regbase, CL_SEQR18, 0x02);
1da177e4
LT
1647 }
1648
1649 /* MCLK select etc. */
1650 if (bi->init_sr1f)
8503df65
KH
1651 vga_wseq(cinfo->regbase, CL_SEQR1F, bi->sr1f);
1652
1653 /* Screen A preset row scan: none */
1654 vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00);
1655 /* Text cursor start: disable text cursor */
1656 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20);
1657 /* Text cursor end: - */
1658 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00);
1659 /* Screen start address high: 0 */
1660 vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, 0x00);
1661 /* Screen start address low: 0 */
1662 vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, 0x00);
1663 /* text cursor location high: 0 */
1664 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00);
1665 /* text cursor location low: 0 */
1666 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00);
1667
1668 /* Underline Row scanline: - */
1669 vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00);
1670 /* mode control: timing enable, byte mode, no compat modes */
1671 vga_wcrt(cinfo->regbase, VGA_CRTC_MODE, 0xc3);
1672 /* Line Compare: not needed */
1673 vga_wcrt(cinfo->regbase, VGA_CRTC_LINE_COMPARE, 0x00);
1da177e4 1674 /* ### add 0x40 for text modes with > 30 MHz pixclock */
8503df65
KH
1675 /* ext. display controls: ext.adr. wrap */
1676 vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02);
1677
1678 /* Set/Reset registes: - */
1679 vga_wgfx(cinfo->regbase, VGA_GFX_SR_VALUE, 0x00);
1680 /* Set/Reset enable: - */
1681 vga_wgfx(cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00);
1682 /* Color Compare: - */
1683 vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00);
1684 /* Data Rotate: - */
1685 vga_wgfx(cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00);
1686 /* Read Map Select: - */
1687 vga_wgfx(cinfo->regbase, VGA_GFX_PLANE_READ, 0x00);
1688 /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
1689 vga_wgfx(cinfo->regbase, VGA_GFX_MODE, 0x00);
1690 /* Miscellaneous: memory map base address, graphics mode */
1691 vga_wgfx(cinfo->regbase, VGA_GFX_MISC, 0x01);
1692 /* Color Don't care: involve all planes */
1693 vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f);
1694 /* Bit Mask: no mask at all */
1695 vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff);
1da177e4 1696 if (cinfo->btype == BT_ALPINE)
8503df65
KH
1697 /* (5434 can't have bit 3 set for bitblt) */
1698 vga_wgfx(cinfo->regbase, CL_GRB, 0x20);
1da177e4 1699 else
8503df65
KH
1700 /* Graphics controller mode extensions: finer granularity,
1701 * 8byte data latches
1702 */
1703 vga_wgfx(cinfo->regbase, CL_GRB, 0x28);
1704
1705 vga_wgfx(cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */
1706 vga_wgfx(cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */
1707 vga_wgfx(cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */
1708 /* Background color byte 1: - */
1709 /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); */
1710 /* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
1711
1712 /* Attribute Controller palette registers: "identity mapping" */
1713 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE0, 0x00);
1714 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
1715 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
1716 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
1717 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
1718 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
1719 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
1720 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
1721 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
1722 vga_wattr(cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
1723 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
1724 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
1725 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
1726 vga_wattr(cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
1727 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
1728 vga_wattr(cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
1729
1730 /* Attribute Controller mode: graphics mode */
1731 vga_wattr(cinfo->regbase, VGA_ATC_MODE, 0x01);
1732 /* Overscan color reg.: reg. 0 */
1733 vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00);
1734 /* Color Plane enable: Enable all 4 planes */
1735 vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f);
1736/* ### vga_wattr(cinfo->regbase, CL_AR33, 0x00); * Pixel Panning: - */
1737 /* Color Select: - */
1738 vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00);
1739
1740 WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
1da177e4
LT
1741
1742 if (cinfo->btype != BT_ALPINE && cinfo->btype != BT_GD5480)
8503df65
KH
1743 /* polarity (-/-), enable display mem,
1744 * VGA_CRTC_START_HI i/o base = color
1745 */
1746 WGen(cinfo, VGA_MIS_W, 0xc3);
1da177e4 1747
8503df65
KH
1748 /* BLT Start/status: Blitter reset */
1749 vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
1750 /* - " - : "end-of-reset" */
1751 vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
1da177e4
LT
1752
1753 /* misc... */
8503df65 1754 WHDR(cinfo, 0); /* Hidden DAC register: - */
1da177e4
LT
1755 return;
1756}
1757
8503df65 1758static void switch_monitor(struct cirrusfb_info *cinfo, int on)
1da177e4
LT
1759{
1760#ifdef CONFIG_ZORRO /* only works on Zorro boards */
1761 static int IsOn = 0; /* XXX not ok for multiple boards */
1762
1da177e4
LT
1763 if (cinfo->btype == BT_PICASSO4)
1764 return; /* nothing to switch */
1765 if (cinfo->btype == BT_ALPINE)
1766 return; /* nothing to switch */
1767 if (cinfo->btype == BT_GD5480)
1768 return; /* nothing to switch */
1769 if (cinfo->btype == BT_PICASSO) {
1770 if ((on && !IsOn) || (!on && IsOn))
8503df65 1771 WSFR(cinfo, 0xff);
1da177e4
LT
1772 return;
1773 }
1774 if (on) {
1775 switch (cinfo->btype) {
1776 case BT_SD64:
8503df65 1777 WSFR(cinfo, cinfo->SFR | 0x21);
1da177e4
LT
1778 break;
1779 case BT_PICCOLO:
8503df65 1780 WSFR(cinfo, cinfo->SFR | 0x28);
1da177e4
LT
1781 break;
1782 case BT_SPECTRUM:
8503df65 1783 WSFR(cinfo, 0x6f);
1da177e4
LT
1784 break;
1785 default: /* do nothing */ break;
1786 }
1787 } else {
1788 switch (cinfo->btype) {
1789 case BT_SD64:
8503df65 1790 WSFR(cinfo, cinfo->SFR & 0xde);
1da177e4
LT
1791 break;
1792 case BT_PICCOLO:
8503df65 1793 WSFR(cinfo, cinfo->SFR & 0xd7);
1da177e4
LT
1794 break;
1795 case BT_SPECTRUM:
8503df65 1796 WSFR(cinfo, 0x4f);
1da177e4 1797 break;
75ed3a17
KH
1798 default: /* do nothing */
1799 break;
1da177e4
LT
1800 }
1801 }
1da177e4
LT
1802#endif /* CONFIG_ZORRO */
1803}
1804
1da177e4
LT
1805/******************************************/
1806/* Linux 2.6-style accelerated functions */
1807/******************************************/
1808
8503df65
KH
1809static void cirrusfb_fillrect(struct fb_info *info,
1810 const struct fb_fillrect *region)
1da177e4 1811{
1da177e4
LT
1812 struct fb_fillrect modded;
1813 int vxres, vyres;
060b6002
KH
1814 struct cirrusfb_info *cinfo = info->par;
1815 int m = info->var.bits_per_pixel;
1816 u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
1817 cinfo->pseudo_palette[region->color] : region->color;
1da177e4
LT
1818
1819 if (info->state != FBINFO_STATE_RUNNING)
1820 return;
1821 if (info->flags & FBINFO_HWACCEL_DISABLED) {
1822 cfb_fillrect(info, region);
1823 return;
1824 }
1825
1826 vxres = info->var.xres_virtual;
1827 vyres = info->var.yres_virtual;
1828
1829 memcpy(&modded, region, sizeof(struct fb_fillrect));
1830
8503df65 1831 if (!modded.width || !modded.height ||
1da177e4
LT
1832 modded.dx >= vxres || modded.dy >= vyres)
1833 return;
1834
8503df65
KH
1835 if (modded.dx + modded.width > vxres)
1836 modded.width = vxres - modded.dx;
1837 if (modded.dy + modded.height > vyres)
1838 modded.height = vyres - modded.dy;
1da177e4 1839
060b6002
KH
1840 cirrusfb_RectFill(cinfo->regbase,
1841 info->var.bits_per_pixel,
1842 (region->dx * m) / 8, region->dy,
1843 (region->width * m) / 8, region->height,
1844 color,
0ff1edee 1845 info->fix.line_length);
1da177e4
LT
1846}
1847
8503df65
KH
1848static void cirrusfb_copyarea(struct fb_info *info,
1849 const struct fb_copyarea *area)
1da177e4 1850{
1da177e4
LT
1851 struct fb_copyarea modded;
1852 u32 vxres, vyres;
060b6002
KH
1853 struct cirrusfb_info *cinfo = info->par;
1854 int m = info->var.bits_per_pixel;
1da177e4
LT
1855
1856 if (info->state != FBINFO_STATE_RUNNING)
1857 return;
1858 if (info->flags & FBINFO_HWACCEL_DISABLED) {
1859 cfb_copyarea(info, area);
1860 return;
1861 }
1862
1863 vxres = info->var.xres_virtual;
1864 vyres = info->var.yres_virtual;
060b6002 1865 memcpy(&modded, area, sizeof(struct fb_copyarea));
1da177e4 1866
8503df65 1867 if (!modded.width || !modded.height ||
1da177e4
LT
1868 modded.sx >= vxres || modded.sy >= vyres ||
1869 modded.dx >= vxres || modded.dy >= vyres)
1870 return;
1871
8503df65
KH
1872 if (modded.sx + modded.width > vxres)
1873 modded.width = vxres - modded.sx;
1874 if (modded.dx + modded.width > vxres)
1875 modded.width = vxres - modded.dx;
1876 if (modded.sy + modded.height > vyres)
1877 modded.height = vyres - modded.sy;
1878 if (modded.dy + modded.height > vyres)
1879 modded.height = vyres - modded.dy;
1da177e4 1880
060b6002
KH
1881 cirrusfb_BitBLT(cinfo->regbase, info->var.bits_per_pixel,
1882 (area->sx * m) / 8, area->sy,
1883 (area->dx * m) / 8, area->dy,
1884 (area->width * m) / 8, area->height,
0ff1edee 1885 info->fix.line_length);
060b6002 1886
1da177e4
LT
1887}
1888
8503df65
KH
1889static void cirrusfb_imageblit(struct fb_info *info,
1890 const struct fb_image *image)
1da177e4
LT
1891{
1892 struct cirrusfb_info *cinfo = info->par;
1893
8503df65 1894 cirrusfb_WaitBLT(cinfo->regbase);
1da177e4
LT
1895 cfb_imageblit(info, image);
1896}
1897
1da177e4
LT
1898#ifdef CONFIG_PPC_PREP
1899#define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
1900#define PREP_IO_BASE ((volatile unsigned char *) 0x80000000)
8503df65 1901static void get_prep_addrs(unsigned long *display, unsigned long *registers)
1da177e4 1902{
1da177e4
LT
1903 *display = PREP_VIDEO_BASE;
1904 *registers = (unsigned long) PREP_IO_BASE;
1da177e4
LT
1905}
1906
1907#endif /* CONFIG_PPC_PREP */
1908
1da177e4 1909#ifdef CONFIG_PCI
8503df65 1910static int release_io_ports;
1da177e4
LT
1911
1912/* Pulled the logic from XFree86 Cirrus driver to get the memory size,
1913 * based on the DRAM bandwidth bit and DRAM bank switching bit. This
1914 * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
1915 * seem to have. */
75ed3a17
KH
1916static unsigned int __devinit cirrusfb_get_memsize(struct fb_info *info,
1917 u8 __iomem *regbase)
1da177e4
LT
1918{
1919 unsigned long mem;
1920 unsigned char SRF;
1921
8503df65 1922 SRF = vga_rseq(regbase, CL_SEQRF);
1da177e4 1923 switch ((SRF & 0x18)) {
8503df65
KH
1924 case 0x08:
1925 mem = 512 * 1024;
1926 break;
1927 case 0x10:
1928 mem = 1024 * 1024;
1929 break;
1930 /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory
1931 * on the 5430.
1932 */
1933 case 0x18:
1934 mem = 2048 * 1024;
1935 break;
1936 default:
75ed3a17 1937 dev_warn(info->device, "CLgenfb: Unknown memory size!\n");
1da177e4
LT
1938 mem = 1024 * 1024;
1939 }
8503df65
KH
1940 if (SRF & 0x80)
1941 /* If DRAM bank switching is enabled, there must be twice as much
1942 * memory installed. (4MB on the 5434)
1943 */
1da177e4 1944 mem *= 2;
8503df65 1945
1da177e4 1946 /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
1da177e4
LT
1947 return mem;
1948}
1949
8503df65
KH
1950static void get_pci_addrs(const struct pci_dev *pdev,
1951 unsigned long *display, unsigned long *registers)
1da177e4 1952{
8503df65
KH
1953 assert(pdev != NULL);
1954 assert(display != NULL);
1955 assert(registers != NULL);
1da177e4 1956
1da177e4
LT
1957 *display = 0;
1958 *registers = 0;
1959
1960 /* This is a best-guess for now */
1961
1962 if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
1963 *display = pci_resource_start(pdev, 1);
1964 *registers = pci_resource_start(pdev, 0);
1965 } else {
1966 *display = pci_resource_start(pdev, 0);
1967 *registers = pci_resource_start(pdev, 1);
1968 }
1969
8503df65 1970 assert(*display != 0);
1da177e4
LT
1971}
1972
9199ec5c 1973static void cirrusfb_pci_unmap(struct fb_info *info)
1da177e4 1974{
64beab14 1975 struct pci_dev *pdev = to_pci_dev(info->device);
1da177e4 1976
9199ec5c 1977 iounmap(info->screen_base);
1da177e4
LT
1978#if 0 /* if system didn't claim this region, we would... */
1979 release_mem_region(0xA0000, 65535);
1980#endif
1981 if (release_io_ports)
1982 release_region(0x3C0, 32);
1983 pci_release_regions(pdev);
1da177e4
LT
1984}
1985#endif /* CONFIG_PCI */
1986
1da177e4 1987#ifdef CONFIG_ZORRO
f5ee051e 1988static void cirrusfb_zorro_unmap(struct fb_info *info)
1da177e4 1989{
d91f5bb6 1990 struct cirrusfb_info *cinfo = info->par;
64beab14
KH
1991 struct zorro_dev *zdev = to_zorro_dev(info->device);
1992
1993 zorro_release_device(zdev);
1da177e4
LT
1994
1995 if (cinfo->btype == BT_PICASSO4) {
1996 cinfo->regbase -= 0x600000;
8503df65 1997 iounmap((void *)cinfo->regbase);
9199ec5c 1998 iounmap(info->screen_base);
1da177e4 1999 } else {
64beab14 2000 if (zorro_resource_start(zdev) > 0x01000000)
9199ec5c 2001 iounmap(info->screen_base);
1da177e4 2002 }
1da177e4
LT
2003}
2004#endif /* CONFIG_ZORRO */
2005
c395d3e8 2006static int __devinit cirrusfb_set_fbinfo(struct fb_info *info)
1da177e4 2007{
9199ec5c 2008 struct cirrusfb_info *cinfo = info->par;
1da177e4
LT
2009 struct fb_var_screeninfo *var = &info->var;
2010
1da177e4
LT
2011 info->pseudo_palette = cinfo->pseudo_palette;
2012 info->flags = FBINFO_DEFAULT
2013 | FBINFO_HWACCEL_XPAN
2014 | FBINFO_HWACCEL_YPAN
2015 | FBINFO_HWACCEL_FILLRECT
2016 | FBINFO_HWACCEL_COPYAREA;
2017 if (noaccel)
2018 info->flags |= FBINFO_HWACCEL_DISABLED;
2019 info->fbops = &cirrusfb_ops;
1da177e4
LT
2020 if (cinfo->btype == BT_GD5480) {
2021 if (var->bits_per_pixel == 16)
2022 info->screen_base += 1 * MB_;
1cea9a9a 2023 if (var->bits_per_pixel == 32)
1da177e4
LT
2024 info->screen_base += 2 * MB_;
2025 }
2026
2027 /* Fill fix common fields */
2028 strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
2029 sizeof(info->fix.id));
2030
2031 /* monochrome: only 1 memory plane */
2032 /* 8 bit and above: Use whole memory area */
9199ec5c
KH
2033 info->fix.smem_len = info->screen_size;
2034 if (var->bits_per_pixel == 1)
2035 info->fix.smem_len /= 4;
1da177e4 2036 info->fix.type_aux = 0;
1da177e4
LT
2037 info->fix.xpanstep = 1;
2038 info->fix.ypanstep = 1;
2039 info->fix.ywrapstep = 0;
1da177e4
LT
2040
2041 /* FIXME: map region at 0xB8000 if available, fill in here */
1da177e4
LT
2042 info->fix.mmio_len = 0;
2043 info->fix.accel = FB_ACCEL_NONE;
2044
2045 fb_alloc_cmap(&info->cmap, 256, 0);
2046
2047 return 0;
2048}
2049
c395d3e8 2050static int __devinit cirrusfb_register(struct fb_info *info)
1da177e4 2051{
9199ec5c 2052 struct cirrusfb_info *cinfo = info->par;
1da177e4 2053 int err;
7345de32 2054 enum cirrus_board btype;
1da177e4 2055
1da177e4
LT
2056 btype = cinfo->btype;
2057
2058 /* sanity checks */
8503df65 2059 assert(btype != BT_NONE);
1da177e4 2060
a1d35a7a
KH
2061 /* set all the vital stuff */
2062 cirrusfb_set_fbinfo(info);
2063
75ed3a17 2064 dev_dbg(info->device, "(RAM start set to: 0x%p)\n", info->screen_base);
1da177e4 2065
a1d35a7a
KH
2066 err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
2067 if (!err) {
75ed3a17 2068 dev_dbg(info->device, "wrong initial video mode\n");
a1d35a7a
KH
2069 err = -EINVAL;
2070 goto err_dealloc_cmap;
2071 }
2072
1da177e4
LT
2073 info->var.activate = FB_ACTIVATE_NOW;
2074
2075 err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
2076 if (err < 0) {
2077 /* should never happen */
75ed3a17
KH
2078 dev_dbg(info->device,
2079 "choking on default var... umm, no good.\n");
a1d35a7a 2080 goto err_dealloc_cmap;
1da177e4
LT
2081 }
2082
1da177e4
LT
2083 err = register_framebuffer(info);
2084 if (err < 0) {
75ed3a17
KH
2085 dev_err(info->device,
2086 "could not register fb device; err = %d!\n", err);
1da177e4
LT
2087 goto err_dealloc_cmap;
2088 }
2089
1da177e4
LT
2090 return 0;
2091
2092err_dealloc_cmap:
2093 fb_dealloc_cmap(&info->cmap);
9199ec5c 2094 cinfo->unmap(info);
060b6002 2095 framebuffer_release(info);
1da177e4
LT
2096 return err;
2097}
2098
8503df65 2099static void __devexit cirrusfb_cleanup(struct fb_info *info)
1da177e4
LT
2100{
2101 struct cirrusfb_info *cinfo = info->par;
1da177e4 2102
8503df65 2103 switch_monitor(cinfo, 0);
8503df65
KH
2104 unregister_framebuffer(info);
2105 fb_dealloc_cmap(&info->cmap);
75ed3a17 2106 dev_dbg(info->device, "Framebuffer unregistered\n");
9199ec5c 2107 cinfo->unmap(info);
060b6002 2108 framebuffer_release(info);
1da177e4
LT
2109}
2110
1da177e4 2111#ifdef CONFIG_PCI
c395d3e8
KH
2112static int __devinit cirrusfb_pci_register(struct pci_dev *pdev,
2113 const struct pci_device_id *ent)
1da177e4
LT
2114{
2115 struct cirrusfb_info *cinfo;
2116 struct fb_info *info;
7345de32 2117 enum cirrus_board btype;
1da177e4
LT
2118 unsigned long board_addr, board_size;
2119 int ret;
2120
2121 ret = pci_enable_device(pdev);
2122 if (ret < 0) {
2123 printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
2124 goto err_out;
2125 }
2126
2127 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev);
2128 if (!info) {
2129 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2130 ret = -ENOMEM;
2131 goto err_disable;
2132 }
2133
2134 cinfo = info->par;
7345de32 2135 cinfo->btype = btype = (enum cirrus_board) ent->driver_data;
1da177e4 2136
75ed3a17
KH
2137 dev_dbg(info->device,
2138 " Found PCI device, base address 0 is 0x%Lx, btype set to %d\n",
2139 (unsigned long long)pdev->resource[0].start, btype);
2140 dev_dbg(info->device, " base address 1 is 0x%Lx\n",
2141 (unsigned long long)pdev->resource[1].start);
1da177e4 2142
8503df65
KH
2143 if (isPReP) {
2144 pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, 0x00000000);
1da177e4 2145#ifdef CONFIG_PPC_PREP
9199ec5c 2146 get_prep_addrs(&board_addr, &info->fix.mmio_start);
1da177e4 2147#endif
8503df65 2148 /* PReP dies if we ioremap the IO registers, but it works w/out... */
9199ec5c 2149 cinfo->regbase = (char __iomem *) info->fix.mmio_start;
1da177e4 2150 } else {
75ed3a17
KH
2151 dev_dbg(info->device,
2152 "Attempt to get PCI info for Cirrus Graphics Card\n");
9199ec5c 2153 get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start);
8503df65
KH
2154 /* FIXME: this forces VGA. alternatives? */
2155 cinfo->regbase = NULL;
1da177e4
LT
2156 }
2157
75ed3a17 2158 dev_dbg(info->device, "Board address: 0x%lx, register address: 0x%lx\n",
9199ec5c 2159 board_addr, info->fix.mmio_start);
1da177e4
LT
2160
2161 board_size = (btype == BT_GD5480) ?
75ed3a17 2162 32 * MB_ : cirrusfb_get_memsize(info, cinfo->regbase);
1da177e4
LT
2163
2164 ret = pci_request_regions(pdev, "cirrusfb");
8503df65 2165 if (ret < 0) {
75ed3a17
KH
2166 dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
2167 board_addr);
1da177e4
LT
2168 goto err_release_fb;
2169 }
2170#if 0 /* if the system didn't claim this region, we would... */
2171 if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
75ed3a17
KH
2172 dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
2173 0xA0000L);
1da177e4
LT
2174 ret = -EBUSY;
2175 goto err_release_regions;
2176 }
2177#endif
2178 if (request_region(0x3C0, 32, "cirrusfb"))
2179 release_io_ports = 1;
2180
9199ec5c
KH
2181 info->screen_base = ioremap(board_addr, board_size);
2182 if (!info->screen_base) {
1da177e4
LT
2183 ret = -EIO;
2184 goto err_release_legacy;
2185 }
2186
9199ec5c
KH
2187 info->fix.smem_start = board_addr;
2188 info->screen_size = board_size;
1da177e4
LT
2189 cinfo->unmap = cirrusfb_pci_unmap;
2190
75ed3a17
KH
2191 dev_info(info->device,
2192 "Cirrus Logic chipset on PCI bus, RAM (%lu kB) at 0x%lx\n",
2193 info->screen_size >> 10, board_addr);
1da177e4
LT
2194 pci_set_drvdata(pdev, info);
2195
9199ec5c 2196 ret = cirrusfb_register(info);
d8b8c0a6 2197 if (ret)
9199ec5c 2198 iounmap(info->screen_base);
d8b8c0a6 2199 return ret;
1da177e4
LT
2200
2201err_release_legacy:
2202 if (release_io_ports)
2203 release_region(0x3C0, 32);
2204#if 0
2205 release_mem_region(0xA0000, 65535);
2206err_release_regions:
2207#endif
2208 pci_release_regions(pdev);
2209err_release_fb:
2210 framebuffer_release(info);
2211err_disable:
1da177e4
LT
2212err_out:
2213 return ret;
2214}
2215
8503df65 2216static void __devexit cirrusfb_pci_unregister(struct pci_dev *pdev)
1da177e4
LT
2217{
2218 struct fb_info *info = pci_get_drvdata(pdev);
1da177e4 2219
8503df65 2220 cirrusfb_cleanup(info);
1da177e4
LT
2221}
2222
2223static struct pci_driver cirrusfb_pci_driver = {
2224 .name = "cirrusfb",
2225 .id_table = cirrusfb_pci_table,
2226 .probe = cirrusfb_pci_register,
2227 .remove = __devexit_p(cirrusfb_pci_unregister),
2228#ifdef CONFIG_PM
2229#if 0
2230 .suspend = cirrusfb_pci_suspend,
2231 .resume = cirrusfb_pci_resume,
2232#endif
2233#endif
2234};
2235#endif /* CONFIG_PCI */
2236
1da177e4 2237#ifdef CONFIG_ZORRO
c395d3e8
KH
2238static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
2239 const struct zorro_device_id *ent)
1da177e4
LT
2240{
2241 struct cirrusfb_info *cinfo;
2242 struct fb_info *info;
7345de32 2243 enum cirrus_board btype;
1da177e4
LT
2244 struct zorro_dev *z2 = NULL;
2245 unsigned long board_addr, board_size, size;
2246 int ret;
2247
2248 btype = ent->driver_data;
2249 if (cirrusfb_zorro_table2[btype].id2)
2250 z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
2251 size = cirrusfb_zorro_table2[btype].size;
1da177e4
LT
2252
2253 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
2254 if (!info) {
8503df65 2255 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
1da177e4
LT
2256 ret = -ENOMEM;
2257 goto err_out;
2258 }
2259
75ed3a17
KH
2260 dev_info(info->device, "%s board detected\n",
2261 cirrusfb_board_info[btype].name);
2262
1da177e4 2263 cinfo = info->par;
1da177e4
LT
2264 cinfo->btype = btype;
2265
36ea96a4 2266 assert(z);
8503df65 2267 assert(btype != BT_NONE);
1da177e4 2268
1da177e4
LT
2269 board_addr = zorro_resource_start(z);
2270 board_size = zorro_resource_len(z);
9199ec5c 2271 info->screen_size = size;
1da177e4
LT
2272
2273 if (!zorro_request_device(z, "cirrusfb")) {
75ed3a17
KH
2274 dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
2275 board_addr);
1da177e4
LT
2276 ret = -EBUSY;
2277 goto err_release_fb;
2278 }
2279
1da177e4
LT
2280 ret = -EIO;
2281
2282 if (btype == BT_PICASSO4) {
75ed3a17 2283 dev_info(info->device, " REG at $%lx\n", board_addr + 0x600000);
1da177e4
LT
2284
2285 /* To be precise, for the P4 this is not the */
2286 /* begin of the board, but the begin of RAM. */
2287 /* for P4, map in its address space in 2 chunks (### TEST! ) */
2288 /* (note the ugly hardcoded 16M number) */
8503df65 2289 cinfo->regbase = ioremap(board_addr, 16777216);
1da177e4
LT
2290 if (!cinfo->regbase)
2291 goto err_release_region;
2292
75ed3a17 2293 dev_dbg(info->device, "Virtual address for board set to: $%p\n",
8503df65 2294 cinfo->regbase);
1da177e4 2295 cinfo->regbase += 0x600000;
9199ec5c 2296 info->fix.mmio_start = board_addr + 0x600000;
1da177e4 2297
9199ec5c
KH
2298 info->fix.smem_start = board_addr + 16777216;
2299 info->screen_base = ioremap(info->fix.smem_start, 16777216);
2300 if (!info->screen_base)
1da177e4
LT
2301 goto err_unmap_regbase;
2302 } else {
75ed3a17
KH
2303 dev_info(info->device, " REG at $%lx\n",
2304 (unsigned long) z2->resource.start);
1da177e4 2305
9199ec5c 2306 info->fix.smem_start = board_addr;
1da177e4 2307 if (board_addr > 0x01000000)
9199ec5c 2308 info->screen_base = ioremap(board_addr, board_size);
1da177e4 2309 else
9199ec5c
KH
2310 info->screen_base = (caddr_t) ZTWO_VADDR(board_addr);
2311 if (!info->screen_base)
1da177e4
LT
2312 goto err_release_region;
2313
2314 /* set address for REG area of board */
8503df65 2315 cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start);
9199ec5c 2316 info->fix.mmio_start = z2->resource.start;
1da177e4 2317
75ed3a17 2318 dev_dbg(info->device, "Virtual address for board set to: $%p\n",
8503df65 2319 cinfo->regbase);
1da177e4
LT
2320 }
2321 cinfo->unmap = cirrusfb_zorro_unmap;
2322
75ed3a17
KH
2323 dev_info(info->device,
2324 "Cirrus Logic chipset on Zorro bus, RAM (%lu MB) at $%lx\n",
2325 board_size / MB_, board_addr);
2326
1da177e4
LT
2327 zorro_set_drvdata(z, info);
2328
d91f5bb6 2329 ret = cirrusfb_register(info);
d8b8c0a6
AL
2330 if (ret) {
2331 if (btype == BT_PICASSO4) {
9199ec5c 2332 iounmap(info->screen_base);
d8b8c0a6
AL
2333 iounmap(cinfo->regbase - 0x600000);
2334 } else if (board_addr > 0x01000000)
9199ec5c 2335 iounmap(info->screen_base);
d8b8c0a6
AL
2336 }
2337 return ret;
1da177e4
LT
2338
2339err_unmap_regbase:
2340 /* Parental advisory: explicit hack */
2341 iounmap(cinfo->regbase - 0x600000);
2342err_release_region:
2343 release_region(board_addr, board_size);
2344err_release_fb:
2345 framebuffer_release(info);
2346err_out:
2347 return ret;
2348}
2349
2350void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
2351{
2352 struct fb_info *info = zorro_get_drvdata(z);
1da177e4 2353
8503df65 2354 cirrusfb_cleanup(info);
1da177e4
LT
2355}
2356
2357static struct zorro_driver cirrusfb_zorro_driver = {
2358 .name = "cirrusfb",
2359 .id_table = cirrusfb_zorro_table,
2360 .probe = cirrusfb_zorro_register,
2361 .remove = __devexit_p(cirrusfb_zorro_unregister),
2362};
2363#endif /* CONFIG_ZORRO */
2364
2365static int __init cirrusfb_init(void)
2366{
2367 int error = 0;
2368
2369#ifndef MODULE
2370 char *option = NULL;
2371
2372 if (fb_get_options("cirrusfb", &option))
2373 return -ENODEV;
2374 cirrusfb_setup(option);
2375#endif
2376
2377#ifdef CONFIG_ZORRO
33d8675e 2378 error |= zorro_register_driver(&cirrusfb_zorro_driver);
1da177e4
LT
2379#endif
2380#ifdef CONFIG_PCI
2381 error |= pci_register_driver(&cirrusfb_pci_driver);
2382#endif
2383 return error;
2384}
2385
1da177e4 2386#ifndef MODULE
75ed3a17
KH
2387static int __init cirrusfb_setup(char *options)
2388{
ee11940f 2389 char *this_opt;
1da177e4 2390
1da177e4
LT
2391 if (!options || !*options)
2392 return 0;
2393
8503df65 2394 while ((this_opt = strsep(&options, ",")) != NULL) {
a1d35a7a
KH
2395 if (!*this_opt)
2396 continue;
1da177e4 2397
1da177e4
LT
2398 if (!strcmp(this_opt, "noaccel"))
2399 noaccel = 1;
a1d35a7a
KH
2400 else if (!strncmp(this_opt, "mode:", 5))
2401 mode_option = this_opt + 5;
2402 else
2403 mode_option = this_opt;
1da177e4
LT
2404 }
2405 return 0;
2406}
2407#endif
2408
1da177e4
LT
2409 /*
2410 * Modularization
2411 */
2412
2413MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
2414MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
2415MODULE_LICENSE("GPL");
2416
8503df65 2417static void __exit cirrusfb_exit(void)
1da177e4
LT
2418{
2419#ifdef CONFIG_PCI
2420 pci_unregister_driver(&cirrusfb_pci_driver);
2421#endif
2422#ifdef CONFIG_ZORRO
2423 zorro_unregister_driver(&cirrusfb_zorro_driver);
2424#endif
2425}
2426
2427module_init(cirrusfb_init);
2428
a1d35a7a
KH
2429module_param(mode_option, charp, 0);
2430MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
55a0dd83
KH
2431module_param(noaccel, bool, 0);
2432MODULE_PARM_DESC(noaccel, "Disable acceleration");
a1d35a7a 2433
1da177e4
LT
2434#ifdef MODULE
2435module_exit(cirrusfb_exit);
2436#endif
2437
1da177e4
LT
2438/**********************************************************************/
2439/* about the following functions - I have used the same names for the */
2440/* functions as Markus Wild did in his Retina driver for NetBSD as */
2441/* they just made sense for this purpose. Apart from that, I wrote */
8503df65 2442/* these functions myself. */
1da177e4
LT
2443/**********************************************************************/
2444
2445/*** WGen() - write into one of the external/general registers ***/
8503df65 2446static void WGen(const struct cirrusfb_info *cinfo,
1da177e4
LT
2447 int regnum, unsigned char val)
2448{
2449 unsigned long regofs = 0;
2450
2451 if (cinfo->btype == BT_PICASSO) {
2452 /* Picasso II specific hack */
8503df65
KH
2453/* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2454 regnum == CL_VSSM2) */
1da177e4
LT
2455 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2456 regofs = 0xfff;
2457 }
2458
8503df65 2459 vga_w(cinfo->regbase, regofs + regnum, val);
1da177e4
LT
2460}
2461
2462/*** RGen() - read out one of the external/general registers ***/
8503df65 2463static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum)
1da177e4
LT
2464{
2465 unsigned long regofs = 0;
2466
2467 if (cinfo->btype == BT_PICASSO) {
2468 /* Picasso II specific hack */
8503df65
KH
2469/* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
2470 regnum == CL_VSSM2) */
1da177e4
LT
2471 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2472 regofs = 0xfff;
2473 }
2474
8503df65 2475 return vga_r(cinfo->regbase, regofs + regnum);
1da177e4
LT
2476}
2477
2478/*** AttrOn() - turn on VideoEnable for Attribute controller ***/
8503df65 2479static void AttrOn(const struct cirrusfb_info *cinfo)
1da177e4 2480{
8503df65 2481 assert(cinfo != NULL);
1da177e4 2482
8503df65 2483 if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) {
1da177e4
LT
2484 /* if we're just in "write value" mode, write back the */
2485 /* same value as before to not modify anything */
8503df65
KH
2486 vga_w(cinfo->regbase, VGA_ATT_IW,
2487 vga_r(cinfo->regbase, VGA_ATT_R));
1da177e4
LT
2488 }
2489 /* turn on video bit */
8503df65
KH
2490/* vga_w(cinfo->regbase, VGA_ATT_IW, 0x20); */
2491 vga_w(cinfo->regbase, VGA_ATT_IW, 0x33);
1da177e4
LT
2492
2493 /* dummy write on Reg0 to be on "write index" mode next time */
8503df65 2494 vga_w(cinfo->regbase, VGA_ATT_IW, 0x00);
1da177e4
LT
2495}
2496
2497/*** WHDR() - write into the Hidden DAC register ***/
2498/* as the HDR is the only extension register that requires special treatment
2499 * (the other extension registers are accessible just like the "ordinary"
2500 * registers of their functional group) here is a specialized routine for
2501 * accessing the HDR
2502 */
8503df65 2503static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val)
1da177e4
LT
2504{
2505 unsigned char dummy;
2506
2507 if (cinfo->btype == BT_PICASSO) {
2508 /* Klaus' hint for correct access to HDR on some boards */
2509 /* first write 0 to pixel mask (3c6) */
8503df65
KH
2510 WGen(cinfo, VGA_PEL_MSK, 0x00);
2511 udelay(200);
1da177e4 2512 /* next read dummy from pixel address (3c8) */
8503df65
KH
2513 dummy = RGen(cinfo, VGA_PEL_IW);
2514 udelay(200);
1da177e4
LT
2515 }
2516 /* now do the usual stuff to access the HDR */
2517
8503df65
KH
2518 dummy = RGen(cinfo, VGA_PEL_MSK);
2519 udelay(200);
2520 dummy = RGen(cinfo, VGA_PEL_MSK);
2521 udelay(200);
2522 dummy = RGen(cinfo, VGA_PEL_MSK);
2523 udelay(200);
2524 dummy = RGen(cinfo, VGA_PEL_MSK);
2525 udelay(200);
1da177e4 2526
8503df65
KH
2527 WGen(cinfo, VGA_PEL_MSK, val);
2528 udelay(200);
1da177e4
LT
2529
2530 if (cinfo->btype == BT_PICASSO) {
2531 /* now first reset HDR access counter */
8503df65
KH
2532 dummy = RGen(cinfo, VGA_PEL_IW);
2533 udelay(200);
1da177e4
LT
2534
2535 /* and at the end, restore the mask value */
2536 /* ## is this mask always 0xff? */
8503df65
KH
2537 WGen(cinfo, VGA_PEL_MSK, 0xff);
2538 udelay(200);
1da177e4
LT
2539 }
2540}
2541
1da177e4 2542/*** WSFR() - write to the "special function register" (SFR) ***/
8503df65 2543static void WSFR(struct cirrusfb_info *cinfo, unsigned char val)
1da177e4
LT
2544{
2545#ifdef CONFIG_ZORRO
8503df65 2546 assert(cinfo->regbase != NULL);
1da177e4 2547 cinfo->SFR = val;
8503df65 2548 z_writeb(val, cinfo->regbase + 0x8000);
1da177e4
LT
2549#endif
2550}
2551
2552/* The Picasso has a second register for switching the monitor bit */
8503df65 2553static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val)
1da177e4
LT
2554{
2555#ifdef CONFIG_ZORRO
2556 /* writing an arbitrary value to this one causes the monitor switcher */
2557 /* to flip to Amiga display */
8503df65 2558 assert(cinfo->regbase != NULL);
1da177e4 2559 cinfo->SFR = val;
8503df65 2560 z_writeb(val, cinfo->regbase + 0x9000);
1da177e4
LT
2561#endif
2562}
2563
1da177e4 2564/*** WClut - set CLUT entry (range: 0..63) ***/
8503df65 2565static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
1da177e4
LT
2566 unsigned char green, unsigned char blue)
2567{
2568 unsigned int data = VGA_PEL_D;
2569
2570 /* address write mode register is not translated.. */
8503df65 2571 vga_w(cinfo->regbase, VGA_PEL_IW, regnum);
1da177e4
LT
2572
2573 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2574 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2575 /* but DAC data register IS, at least for Picasso II */
2576 if (cinfo->btype == BT_PICASSO)
2577 data += 0xfff;
8503df65
KH
2578 vga_w(cinfo->regbase, data, red);
2579 vga_w(cinfo->regbase, data, green);
2580 vga_w(cinfo->regbase, data, blue);
1da177e4 2581 } else {
8503df65
KH
2582 vga_w(cinfo->regbase, data, blue);
2583 vga_w(cinfo->regbase, data, green);
2584 vga_w(cinfo->regbase, data, red);
1da177e4
LT
2585 }
2586}
2587
1da177e4
LT
2588#if 0
2589/*** RClut - read CLUT entry (range 0..63) ***/
8503df65 2590static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
1da177e4
LT
2591 unsigned char *green, unsigned char *blue)
2592{
2593 unsigned int data = VGA_PEL_D;
2594
8503df65 2595 vga_w(cinfo->regbase, VGA_PEL_IR, regnum);
1da177e4
LT
2596
2597 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2598 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2599 if (cinfo->btype == BT_PICASSO)
2600 data += 0xfff;
8503df65
KH
2601 *red = vga_r(cinfo->regbase, data);
2602 *green = vga_r(cinfo->regbase, data);
2603 *blue = vga_r(cinfo->regbase, data);
1da177e4 2604 } else {
8503df65
KH
2605 *blue = vga_r(cinfo->regbase, data);
2606 *green = vga_r(cinfo->regbase, data);
2607 *red = vga_r(cinfo->regbase, data);
1da177e4
LT
2608 }
2609}
2610#endif
2611
1da177e4
LT
2612/*******************************************************************
2613 cirrusfb_WaitBLT()
2614
2615 Wait for the BitBLT engine to complete a possible earlier job
2616*********************************************************************/
2617
2618/* FIXME: use interrupts instead */
8503df65 2619static void cirrusfb_WaitBLT(u8 __iomem *regbase)
1da177e4
LT
2620{
2621 /* now busy-wait until we're done */
8503df65 2622 while (vga_rgfx(regbase, CL_GR31) & 0x08)
1da177e4
LT
2623 /* do nothing */ ;
2624}
2625
2626/*******************************************************************
2627 cirrusfb_BitBLT()
2628
2629 perform accelerated "scrolling"
2630********************************************************************/
2631
8503df65
KH
2632static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
2633 u_short curx, u_short cury,
2634 u_short destx, u_short desty,
2635 u_short width, u_short height,
2636 u_short line_length)
1da177e4
LT
2637{
2638 u_short nwidth, nheight;
2639 u_long nsrc, ndest;
2640 u_char bltmode;
2641
1da177e4
LT
2642 nwidth = width - 1;
2643 nheight = height - 1;
2644
2645 bltmode = 0x00;
2646 /* if source adr < dest addr, do the Blt backwards */
2647 if (cury <= desty) {
2648 if (cury == desty) {
2649 /* if src and dest are on the same line, check x */
2650 if (curx < destx)
2651 bltmode |= 0x01;
2652 } else
2653 bltmode |= 0x01;
2654 }
2655 if (!bltmode) {
2656 /* standard case: forward blitting */
2657 nsrc = (cury * line_length) + curx;
2658 ndest = (desty * line_length) + destx;
2659 } else {
8503df65
KH
2660 /* this means start addresses are at the end,
2661 * counting backwards
2662 */
2663 nsrc = cury * line_length + curx +
2664 nheight * line_length + nwidth;
2665 ndest = desty * line_length + destx +
2666 nheight * line_length + nwidth;
1da177e4
LT
2667 }
2668
2669 /*
2670 run-down of registers to be programmed:
2671 destination pitch
2672 source pitch
2673 BLT width/height
2674 source start
2675 destination start
2676 BLT mode
2677 BLT ROP
2678 VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color"
2679 start/stop
2680 */
2681
8503df65 2682 cirrusfb_WaitBLT(regbase);
1da177e4
LT
2683
2684 /* pitch: set to line_length */
8503df65
KH
2685 /* dest pitch low */
2686 vga_wgfx(regbase, CL_GR24, line_length & 0xff);
2687 /* dest pitch hi */
2688 vga_wgfx(regbase, CL_GR25, line_length >> 8);
2689 /* source pitch low */
2690 vga_wgfx(regbase, CL_GR26, line_length & 0xff);
2691 /* source pitch hi */
2692 vga_wgfx(regbase, CL_GR27, line_length >> 8);
1da177e4
LT
2693
2694 /* BLT width: actual number of pixels - 1 */
8503df65
KH
2695 /* BLT width low */
2696 vga_wgfx(regbase, CL_GR20, nwidth & 0xff);
2697 /* BLT width hi */
2698 vga_wgfx(regbase, CL_GR21, nwidth >> 8);
1da177e4
LT
2699
2700 /* BLT height: actual number of lines -1 */
8503df65
KH
2701 /* BLT height low */
2702 vga_wgfx(regbase, CL_GR22, nheight & 0xff);
2703 /* BLT width hi */
2704 vga_wgfx(regbase, CL_GR23, nheight >> 8);
1da177e4
LT
2705
2706 /* BLT destination */
8503df65
KH
2707 /* BLT dest low */
2708 vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
2709 /* BLT dest mid */
2710 vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
2711 /* BLT dest hi */
2712 vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
1da177e4
LT
2713
2714 /* BLT source */
8503df65
KH
2715 /* BLT src low */
2716 vga_wgfx(regbase, CL_GR2C, (u_char) (nsrc & 0xff));
2717 /* BLT src mid */
2718 vga_wgfx(regbase, CL_GR2D, (u_char) (nsrc >> 8));
2719 /* BLT src hi */
2720 vga_wgfx(regbase, CL_GR2E, (u_char) (nsrc >> 16));
1da177e4
LT
2721
2722 /* BLT mode */
8503df65 2723 vga_wgfx(regbase, CL_GR30, bltmode); /* BLT mode */
1da177e4
LT
2724
2725 /* BLT ROP: SrcCopy */
8503df65 2726 vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */
1da177e4
LT
2727
2728 /* and finally: GO! */
8503df65 2729 vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */
1da177e4
LT
2730}
2731
1da177e4
LT
2732/*******************************************************************
2733 cirrusfb_RectFill()
2734
2735 perform accelerated rectangle fill
2736********************************************************************/
2737
8503df65 2738static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
1da177e4
LT
2739 u_short x, u_short y, u_short width, u_short height,
2740 u_char color, u_short line_length)
2741{
2742 u_short nwidth, nheight;
2743 u_long ndest;
2744 u_char op;
2745
1da177e4
LT
2746 nwidth = width - 1;
2747 nheight = height - 1;
2748
2749 ndest = (y * line_length) + x;
2750
8503df65 2751 cirrusfb_WaitBLT(regbase);
1da177e4
LT
2752
2753 /* pitch: set to line_length */
8503df65
KH
2754 vga_wgfx(regbase, CL_GR24, line_length & 0xff); /* dest pitch low */
2755 vga_wgfx(regbase, CL_GR25, line_length >> 8); /* dest pitch hi */
2756 vga_wgfx(regbase, CL_GR26, line_length & 0xff); /* source pitch low */
2757 vga_wgfx(regbase, CL_GR27, line_length >> 8); /* source pitch hi */
1da177e4
LT
2758
2759 /* BLT width: actual number of pixels - 1 */
8503df65
KH
2760 vga_wgfx(regbase, CL_GR20, nwidth & 0xff); /* BLT width low */
2761 vga_wgfx(regbase, CL_GR21, nwidth >> 8); /* BLT width hi */
1da177e4
LT
2762
2763 /* BLT height: actual number of lines -1 */
8503df65
KH
2764 vga_wgfx(regbase, CL_GR22, nheight & 0xff); /* BLT height low */
2765 vga_wgfx(regbase, CL_GR23, nheight >> 8); /* BLT width hi */
1da177e4
LT
2766
2767 /* BLT destination */
8503df65
KH
2768 /* BLT dest low */
2769 vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
2770 /* BLT dest mid */
2771 vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
2772 /* BLT dest hi */
2773 vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
1da177e4
LT
2774
2775 /* BLT source: set to 0 (is a dummy here anyway) */
8503df65
KH
2776 vga_wgfx(regbase, CL_GR2C, 0x00); /* BLT src low */
2777 vga_wgfx(regbase, CL_GR2D, 0x00); /* BLT src mid */
2778 vga_wgfx(regbase, CL_GR2E, 0x00); /* BLT src hi */
1da177e4
LT
2779
2780 /* This is a ColorExpand Blt, using the */
2781 /* same color for foreground and background */
8503df65
KH
2782 vga_wgfx(regbase, VGA_GFX_SR_VALUE, color); /* foreground color */
2783 vga_wgfx(regbase, VGA_GFX_SR_ENABLE, color); /* background color */
1da177e4
LT
2784
2785 op = 0xc0;
2786 if (bits_per_pixel == 16) {
8503df65
KH
2787 vga_wgfx(regbase, CL_GR10, color); /* foreground color */
2788 vga_wgfx(regbase, CL_GR11, color); /* background color */
1da177e4
LT
2789 op = 0x50;
2790 op = 0xd0;
2791 } else if (bits_per_pixel == 32) {
8503df65
KH
2792 vga_wgfx(regbase, CL_GR10, color); /* foreground color */
2793 vga_wgfx(regbase, CL_GR11, color); /* background color */
2794 vga_wgfx(regbase, CL_GR12, color); /* foreground color */
2795 vga_wgfx(regbase, CL_GR13, color); /* background color */
2796 vga_wgfx(regbase, CL_GR14, 0); /* foreground color */
2797 vga_wgfx(regbase, CL_GR15, 0); /* background color */
1da177e4
LT
2798 op = 0x50;
2799 op = 0xf0;
2800 }
2801 /* BLT mode: color expand, Enable 8x8 copy (faster?) */
8503df65 2802 vga_wgfx(regbase, CL_GR30, op); /* BLT mode */
1da177e4
LT
2803
2804 /* BLT ROP: SrcCopy */
8503df65 2805 vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */
1da177e4
LT
2806
2807 /* and finally: GO! */
8503df65 2808 vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */
1da177e4
LT
2809}
2810
1da177e4
LT
2811/**************************************************************************
2812 * bestclock() - determine closest possible clock lower(?) than the
2813 * desired pixel clock
2814 **************************************************************************/
dafa32c5 2815static void bestclock(long freq, int *nom, int *den, int *div)
1da177e4 2816{
dafa32c5
KH
2817 int n, d;
2818 long h, diff;
1da177e4 2819
8503df65
KH
2820 assert(nom != NULL);
2821 assert(den != NULL);
2822 assert(div != NULL);
1da177e4
LT
2823
2824 *nom = 0;
2825 *den = 0;
2826 *div = 0;
2827
1da177e4
LT
2828 if (freq < 8000)
2829 freq = 8000;
2830
dafa32c5 2831 diff = freq;
1da177e4
LT
2832
2833 for (n = 32; n < 128; n++) {
7528f543
KH
2834 int s = 0;
2835
dafa32c5 2836 d = (14318 * n) / freq;
1da177e4 2837 if ((d >= 7) && (d <= 63)) {
7528f543
KH
2838 int temp = d;
2839
2840 if (temp > 31) {
2841 s = 1;
2842 temp >>= 1;
2843 }
2844 h = ((14318 * n) / temp) >> s;
dafa32c5
KH
2845 h = h > freq ? h - freq : freq - h;
2846 if (h < diff) {
2847 diff = h;
1da177e4 2848 *nom = n;
7528f543
KH
2849 *den = temp;
2850 *div = s;
1da177e4
LT
2851 }
2852 }
7528f543 2853 d++;
1da177e4 2854 if ((d >= 7) && (d <= 63)) {
7528f543
KH
2855 if (d > 31) {
2856 s = 1;
2857 d >>= 1;
2858 }
2859 h = ((14318 * n) / d) >> s;
dafa32c5
KH
2860 h = h > freq ? h - freq : freq - h;
2861 if (h < diff) {
2862 diff = h;
1da177e4 2863 *nom = n;
7528f543
KH
2864 *den = d;
2865 *div = s;
1da177e4
LT
2866 }
2867 }
2868 }
1da177e4
LT
2869}
2870
1da177e4
LT
2871/* -------------------------------------------------------------------------
2872 *
2873 * debugging functions
2874 *
2875 * -------------------------------------------------------------------------
2876 */
2877
2878#ifdef CIRRUSFB_DEBUG
2879
1da177e4
LT
2880/**
2881 * cirrusfb_dbg_print_regs
2882 * @base: If using newmmio, the newmmio base address, otherwise %NULL
2883 * @reg_class: type of registers to read: %CRT, or %SEQ
2884 *
2885 * DESCRIPTION:
2886 * Dumps the given list of VGA CRTC registers. If @base is %NULL,
2887 * old-style I/O ports are queried for information, otherwise MMIO is
2888 * used at the given @base address to query the information.
2889 */
2890
75ed3a17
KH
2891static void cirrusfb_dbg_print_regs(struct fb_info *info,
2892 caddr_t regbase,
2893 enum cirrusfb_dbg_reg_class reg_class, ...)
1da177e4
LT
2894{
2895 va_list list;
2896 unsigned char val = 0;
2897 unsigned reg;
2898 char *name;
2899
8503df65 2900 va_start(list, reg_class);
1da177e4 2901
8503df65 2902 name = va_arg(list, char *);
1da177e4 2903 while (name != NULL) {
8503df65 2904 reg = va_arg(list, int);
1da177e4
LT
2905
2906 switch (reg_class) {
2907 case CRT:
8503df65 2908 val = vga_rcrt(regbase, (unsigned char) reg);
1da177e4
LT
2909 break;
2910 case SEQ:
8503df65 2911 val = vga_rseq(regbase, (unsigned char) reg);
1da177e4
LT
2912 break;
2913 default:
2914 /* should never occur */
c930faae 2915 assert(false);
1da177e4
LT
2916 break;
2917 }
2918
75ed3a17 2919 dev_dbg(info->device, "%8s = 0x%02X\n", name, val);
1da177e4 2920
8503df65 2921 name = va_arg(list, char *);
1da177e4
LT
2922 }
2923
8503df65 2924 va_end(list);
1da177e4
LT
2925}
2926
1da177e4
LT
2927/**
2928 * cirrusfb_dbg_reg_dump
2929 * @base: If using newmmio, the newmmio base address, otherwise %NULL
2930 *
2931 * DESCRIPTION:
2932 * Dumps a list of interesting VGA and CIRRUSFB registers. If @base is %NULL,
2933 * old-style I/O ports are queried for information, otherwise MMIO is
2934 * used at the given @base address to query the information.
2935 */
2936
75ed3a17 2937static void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase)
1da177e4 2938{
75ed3a17 2939 dev_dbg(info->device, "VGA CRTC register dump:\n");
1da177e4 2940
75ed3a17 2941 cirrusfb_dbg_print_regs(info, regbase, CRT,
1da177e4
LT
2942 "CR00", 0x00,
2943 "CR01", 0x01,
2944 "CR02", 0x02,
2945 "CR03", 0x03,
2946 "CR04", 0x04,
2947 "CR05", 0x05,
2948 "CR06", 0x06,
2949 "CR07", 0x07,
2950 "CR08", 0x08,
2951 "CR09", 0x09,
2952 "CR0A", 0x0A,
2953 "CR0B", 0x0B,
2954 "CR0C", 0x0C,
2955 "CR0D", 0x0D,
2956 "CR0E", 0x0E,
2957 "CR0F", 0x0F,
2958 "CR10", 0x10,
2959 "CR11", 0x11,
2960 "CR12", 0x12,
2961 "CR13", 0x13,
2962 "CR14", 0x14,
2963 "CR15", 0x15,
2964 "CR16", 0x16,
2965 "CR17", 0x17,
2966 "CR18", 0x18,
2967 "CR22", 0x22,
2968 "CR24", 0x24,
2969 "CR26", 0x26,
2970 "CR2D", 0x2D,
2971 "CR2E", 0x2E,
2972 "CR2F", 0x2F,
2973 "CR30", 0x30,
2974 "CR31", 0x31,
2975 "CR32", 0x32,
2976 "CR33", 0x33,
2977 "CR34", 0x34,
2978 "CR35", 0x35,
2979 "CR36", 0x36,
2980 "CR37", 0x37,
2981 "CR38", 0x38,
2982 "CR39", 0x39,
2983 "CR3A", 0x3A,
2984 "CR3B", 0x3B,
2985 "CR3C", 0x3C,
2986 "CR3D", 0x3D,
2987 "CR3E", 0x3E,
2988 "CR3F", 0x3F,
2989 NULL);
2990
75ed3a17 2991 dev_dbg(info->device, "\n");
1da177e4 2992
75ed3a17 2993 dev_dbg(info->device, "VGA SEQ register dump:\n");
1da177e4 2994
75ed3a17 2995 cirrusfb_dbg_print_regs(info, regbase, SEQ,
1da177e4
LT
2996 "SR00", 0x00,
2997 "SR01", 0x01,
2998 "SR02", 0x02,
2999 "SR03", 0x03,
3000 "SR04", 0x04,
3001 "SR08", 0x08,
3002 "SR09", 0x09,
3003 "SR0A", 0x0A,
3004 "SR0B", 0x0B,
3005 "SR0D", 0x0D,
3006 "SR10", 0x10,
3007 "SR11", 0x11,
3008 "SR12", 0x12,
3009 "SR13", 0x13,
3010 "SR14", 0x14,
3011 "SR15", 0x15,
3012 "SR16", 0x16,
3013 "SR17", 0x17,
3014 "SR18", 0x18,
3015 "SR19", 0x19,
3016 "SR1A", 0x1A,
3017 "SR1B", 0x1B,
3018 "SR1C", 0x1C,
3019 "SR1D", 0x1D,
3020 "SR1E", 0x1E,
3021 "SR1F", 0x1F,
3022 NULL);
3023
75ed3a17 3024 dev_dbg(info->device, "\n");
1da177e4
LT
3025}
3026
3027#endif /* CIRRUSFB_DEBUG */
3028
This page took 0.631785 seconds and 5 git commands to generate.