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