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