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