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