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