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