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