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