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