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