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