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