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