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