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