blob: 8269d704ab2a2c27731490b3eeb39b203c9f80f3 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
3 *
4 * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
5 *
6 * Contributors (thanks, all!)
7 *
8 * David Eger:
9 * Overhaul for Linux 2.6
10 *
11 * Jeff Rugen:
12 * Major contributions; Motorola PowerStack (PPC and PCI) support,
13 * GD54xx, 1280x1024 mode support, change MCLK based on VCLK.
14 *
15 * Geert Uytterhoeven:
16 * Excellent code review.
17 *
18 * Lars Hecking:
19 * Amiga updates and testing.
20 *
21 * Original cirrusfb author: Frank Neumann
22 *
23 * Based on retz3fb.c and cirrusfb.c:
24 * Copyright (C) 1997 Jes Sorensen
25 * Copyright (C) 1996 Frank Neumann
26 *
27 ***************************************************************
28 *
29 * Format this code with GNU indent '-kr -i8 -pcs' options.
30 *
31 * This file is subject to the terms and conditions of the GNU General Public
32 * License. See the file COPYING in the main directory of this archive
33 * for more details.
34 *
35 */
36
37#define CIRRUSFB_VERSION "2.0-pre2"
38
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <linux/module.h>
40#include <linux/kernel.h>
41#include <linux/errno.h>
42#include <linux/string.h>
43#include <linux/mm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <linux/slab.h>
45#include <linux/delay.h>
46#include <linux/fb.h>
47#include <linux/init.h>
48#include <linux/selection.h>
49#include <asm/pgtable.h>
50
51#ifdef CONFIG_ZORRO
52#include <linux/zorro.h>
53#endif
54#ifdef CONFIG_PCI
55#include <linux/pci.h>
56#endif
57#ifdef CONFIG_AMIGA
58#include <asm/amigahw.h>
59#endif
60#ifdef CONFIG_PPC_PREP
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +110061#include <asm/machdep.h>
62#define isPReP (machine_is(prep))
Linus Torvalds1da177e2005-04-16 15:20:36 -070063#else
64#define isPReP 0
65#endif
66
67#include "video/vga.h"
68#include "video/cirrus.h"
69
70
71/*****************************************************************
72 *
73 * debugging and utility macros
74 *
75 */
76
77/* enable debug output? */
78/* #define CIRRUSFB_DEBUG 1 */
79
80/* disable runtime assertions? */
81/* #define CIRRUSFB_NDEBUG */
82
83/* debug output */
84#ifdef CIRRUSFB_DEBUG
85#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
86#else
87#define DPRINTK(fmt, args...)
88#endif
89
90/* debugging assertions */
91#ifndef CIRRUSFB_NDEBUG
92#define assert(expr) \
93 if(!(expr)) { \
94 printk( "Assertion failed! %s,%s,%s,line=%d\n",\
95 #expr,__FILE__,__FUNCTION__,__LINE__); \
96 }
97#else
98#define assert(expr)
99#endif
100
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101#define MB_ (1024*1024)
102#define KB_ (1024)
103
104#define MAX_NUM_BOARDS 7
105
106
107/*****************************************************************
108 *
109 * chipset information
110 *
111 */
112
113/* board types */
114typedef enum {
115 BT_NONE = 0,
116 BT_SD64,
117 BT_PICCOLO,
118 BT_PICASSO,
119 BT_SPECTRUM,
120 BT_PICASSO4, /* GD5446 */
121 BT_ALPINE, /* GD543x/4x */
122 BT_GD5480,
123 BT_LAGUNA, /* GD546x */
124} cirrusfb_board_t;
125
126
127/*
128 * per-board-type information, used for enumerating and abstracting
129 * chip-specific information
130 * NOTE: MUST be in the same order as cirrusfb_board_t in order to
131 * use direct indexing on this array
132 * NOTE: '__initdata' cannot be used as some of this info
133 * is required at runtime. Maybe separate into an init-only and
134 * a run-time table?
135 */
136static const struct cirrusfb_board_info_rec {
137 char *name; /* ASCII name of chipset */
138 long maxclock[5]; /* maximum video clock */
139 /* for 1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */
Richard Knutssonc930faa2007-05-08 00:38:29 -0700140 bool init_sr07 : 1; /* init SR07 during init_vgachip() */
141 bool init_sr1f : 1; /* write SR1F during init_vgachip() */
142 bool scrn_start_bit19 : 1; /* construct bit 19 of screen start address */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143
144 /* initial SR07 value, then for each mode */
145 unsigned char sr07;
146 unsigned char sr07_1bpp;
147 unsigned char sr07_1bpp_mux;
148 unsigned char sr07_8bpp;
149 unsigned char sr07_8bpp_mux;
150
151 unsigned char sr1f; /* SR1F VGA initial register value */
152} cirrusfb_board_info[] = {
153 [BT_SD64] = {
154 .name = "CL SD64",
155 .maxclock = {
156 /* guess */
157 /* the SD64/P4 have a higher max. videoclock */
158 140000, 140000, 140000, 140000, 140000,
159 },
Richard Knutssonc930faa2007-05-08 00:38:29 -0700160 .init_sr07 = true,
161 .init_sr1f = true,
162 .scrn_start_bit19 = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163 .sr07 = 0xF0,
164 .sr07_1bpp = 0xF0,
165 .sr07_8bpp = 0xF1,
166 .sr1f = 0x20
167 },
168 [BT_PICCOLO] = {
169 .name = "CL Piccolo",
170 .maxclock = {
171 /* guess */
172 90000, 90000, 90000, 90000, 90000
173 },
Richard Knutssonc930faa2007-05-08 00:38:29 -0700174 .init_sr07 = true,
175 .init_sr1f = true,
176 .scrn_start_bit19 = false,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 .sr07 = 0x80,
178 .sr07_1bpp = 0x80,
179 .sr07_8bpp = 0x81,
180 .sr1f = 0x22
181 },
182 [BT_PICASSO] = {
183 .name = "CL Picasso",
184 .maxclock = {
185 /* guess */
186 90000, 90000, 90000, 90000, 90000
187 },
Richard Knutssonc930faa2007-05-08 00:38:29 -0700188 .init_sr07 = true,
189 .init_sr1f = true,
190 .scrn_start_bit19 = false,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 .sr07 = 0x20,
192 .sr07_1bpp = 0x20,
193 .sr07_8bpp = 0x21,
194 .sr1f = 0x22
195 },
196 [BT_SPECTRUM] = {
197 .name = "CL Spectrum",
198 .maxclock = {
199 /* guess */
200 90000, 90000, 90000, 90000, 90000
201 },
Richard Knutssonc930faa2007-05-08 00:38:29 -0700202 .init_sr07 = true,
203 .init_sr1f = true,
204 .scrn_start_bit19 = false,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 .sr07 = 0x80,
206 .sr07_1bpp = 0x80,
207 .sr07_8bpp = 0x81,
208 .sr1f = 0x22
209 },
210 [BT_PICASSO4] = {
211 .name = "CL Picasso4",
212 .maxclock = {
213 135100, 135100, 85500, 85500, 0
214 },
Richard Knutssonc930faa2007-05-08 00:38:29 -0700215 .init_sr07 = true,
216 .init_sr1f = false,
217 .scrn_start_bit19 = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 .sr07 = 0x20,
219 .sr07_1bpp = 0x20,
220 .sr07_8bpp = 0x21,
221 .sr1f = 0
222 },
223 [BT_ALPINE] = {
224 .name = "CL Alpine",
225 .maxclock = {
226 /* for the GD5430. GD5446 can do more... */
227 85500, 85500, 50000, 28500, 0
228 },
Richard Knutssonc930faa2007-05-08 00:38:29 -0700229 .init_sr07 = true,
230 .init_sr1f = true,
231 .scrn_start_bit19 = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 .sr07 = 0xA0,
233 .sr07_1bpp = 0xA1,
234 .sr07_1bpp_mux = 0xA7,
235 .sr07_8bpp = 0xA1,
236 .sr07_8bpp_mux = 0xA7,
237 .sr1f = 0x1C
238 },
239 [BT_GD5480] = {
240 .name = "CL GD5480",
241 .maxclock = {
242 135100, 200000, 200000, 135100, 135100
243 },
Richard Knutssonc930faa2007-05-08 00:38:29 -0700244 .init_sr07 = true,
245 .init_sr1f = true,
246 .scrn_start_bit19 = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 .sr07 = 0x10,
248 .sr07_1bpp = 0x11,
249 .sr07_8bpp = 0x11,
250 .sr1f = 0x1C
251 },
252 [BT_LAGUNA] = {
253 .name = "CL Laguna",
254 .maxclock = {
255 /* guess */
256 135100, 135100, 135100, 135100, 135100,
257 },
Richard Knutssonc930faa2007-05-08 00:38:29 -0700258 .init_sr07 = false,
259 .init_sr1f = false,
260 .scrn_start_bit19 = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 }
262};
263
264
265#ifdef CONFIG_PCI
266#define CHIP(id, btype) \
Grant Coady41538122005-09-29 10:40:52 +1000267 { PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268
269static struct pci_device_id cirrusfb_pci_table[] = {
Grant Coady41538122005-09-29 10:40:52 +1000270 CHIP( PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE ),
271 CHIP( PCI_DEVICE_ID_CIRRUS_5434_8, BT_ALPINE ),
272 CHIP( PCI_DEVICE_ID_CIRRUS_5434_4, BT_ALPINE ),
273 CHIP( PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE ), /* GD-5440 is same id */
274 CHIP( PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE ),
275 CHIP( PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE ),
276 CHIP( PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480 ), /* MacPicasso likely */
277 CHIP( PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4 ), /* Picasso 4 is 5446 */
278 CHIP( PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA ), /* CL Laguna */
279 CHIP( PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA ), /* CL Laguna 3D */
280 CHIP( PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNA ), /* CL Laguna 3DA*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 { 0, }
282};
283MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
284#undef CHIP
285#endif /* CONFIG_PCI */
286
287
288#ifdef CONFIG_ZORRO
289static const struct zorro_device_id cirrusfb_zorro_table[] = {
290 {
291 .id = ZORRO_PROD_HELFRICH_SD64_RAM,
292 .driver_data = BT_SD64,
293 }, {
294 .id = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
295 .driver_data = BT_PICCOLO,
296 }, {
297 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
298 .driver_data = BT_PICASSO,
299 }, {
300 .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
301 .driver_data = BT_SPECTRUM,
302 }, {
303 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
304 .driver_data = BT_PICASSO4,
305 },
306 { 0 }
307};
308
309static const struct {
310 zorro_id id2;
311 unsigned long size;
312} cirrusfb_zorro_table2[] = {
313 [BT_SD64] = {
314 .id2 = ZORRO_PROD_HELFRICH_SD64_REG,
315 .size = 0x400000
316 },
317 [BT_PICCOLO] = {
318 .id2 = ZORRO_PROD_HELFRICH_PICCOLO_REG,
319 .size = 0x200000
320 },
321 [BT_PICASSO] = {
322 .id2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
323 .size = 0x200000
324 },
325 [BT_SPECTRUM] = {
326 .id2 = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
327 .size = 0x200000
328 },
329 [BT_PICASSO4] = {
330 .id2 = 0,
331 .size = 0x400000
332 }
333};
334#endif /* CONFIG_ZORRO */
335
336
337struct cirrusfb_regs {
338 __u32 line_length; /* in BYTES! */
339 __u32 visual;
340 __u32 type;
341
342 long freq;
343 long nom;
344 long den;
345 long div;
346 long multiplexing;
347 long mclk;
348 long divMCLK;
349
350 long HorizRes; /* The x resolution in pixel */
351 long HorizTotal;
352 long HorizDispEnd;
353 long HorizBlankStart;
354 long HorizBlankEnd;
355 long HorizSyncStart;
356 long HorizSyncEnd;
357
358 long VertRes; /* the physical y resolution in scanlines */
359 long VertTotal;
360 long VertDispEnd;
361 long VertSyncStart;
362 long VertSyncEnd;
363 long VertBlankStart;
364 long VertBlankEnd;
365};
366
367
368
369#ifdef CIRRUSFB_DEBUG
370typedef enum {
371 CRT,
372 SEQ
373} cirrusfb_dbg_reg_class_t;
374#endif /* CIRRUSFB_DEBUG */
375
376
377
378
379/* info about board */
380struct cirrusfb_info {
381 struct fb_info *info;
382
383 u8 __iomem *fbmem;
384 u8 __iomem *regbase;
385 u8 __iomem *mem;
386 unsigned long size;
387 cirrusfb_board_t btype;
388 unsigned char SFR; /* Shadow of special function register */
389
390 unsigned long fbmem_phys;
391 unsigned long fbregs_phys;
392
393 struct cirrusfb_regs currentmode;
394 int blank_mode;
395
Antonino A. Daplas49d5c7b2005-11-29 19:34:43 -0800396 u32 pseudo_palette[16];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 struct { u8 red, green, blue, pad; } palette[256];
398
399#ifdef CONFIG_ZORRO
400 struct zorro_dev *zdev;
401#endif
402#ifdef CONFIG_PCI
403 struct pci_dev *pdev;
404#endif
405 void (*unmap)(struct cirrusfb_info *cinfo);
406};
407
408
409static unsigned cirrusfb_def_mode = 1;
410static int noaccel = 0;
411
412/*
413 * Predefined Video Modes
414 */
415
416static const struct {
417 const char *name;
418 struct fb_var_screeninfo var;
419} cirrusfb_predefined[] = {
420 {
421 /* autodetect mode */
422 .name = "Autodetect",
423 }, {
424 /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
425 .name = "640x480",
426 .var = {
427 .xres = 640,
428 .yres = 480,
429 .xres_virtual = 640,
430 .yres_virtual = 480,
431 .bits_per_pixel = 8,
432 .red = { .length = 8 },
433 .green = { .length = 8 },
434 .blue = { .length = 8 },
435 .width = -1,
436 .height = -1,
437 .pixclock = 40000,
438 .left_margin = 48,
439 .right_margin = 16,
440 .upper_margin = 32,
441 .lower_margin = 8,
442 .hsync_len = 96,
443 .vsync_len = 4,
444 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
445 .vmode = FB_VMODE_NONINTERLACED
446 }
447 }, {
448 /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */
449 .name = "800x600",
450 .var = {
451 .xres = 800,
452 .yres = 600,
453 .xres_virtual = 800,
454 .yres_virtual = 600,
455 .bits_per_pixel = 8,
456 .red = { .length = 8 },
457 .green = { .length = 8 },
458 .blue = { .length = 8 },
459 .width = -1,
460 .height = -1,
461 .pixclock = 20000,
462 .left_margin = 128,
463 .right_margin = 16,
464 .upper_margin = 24,
465 .lower_margin = 2,
466 .hsync_len = 96,
467 .vsync_len = 6,
468 .vmode = FB_VMODE_NONINTERLACED
469 }
470 }, {
471 /*
472 * Modeline from XF86Config:
473 * Mode "1024x768" 80 1024 1136 1340 1432 768 770 774 805
474 */
475 /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
476 .name = "1024x768",
477 .var = {
478 .xres = 1024,
479 .yres = 768,
480 .xres_virtual = 1024,
481 .yres_virtual = 768,
482 .bits_per_pixel = 8,
483 .red = { .length = 8 },
484 .green = { .length = 8 },
485 .blue = { .length = 8 },
486 .width = -1,
487 .height = -1,
488 .pixclock = 12500,
489 .left_margin = 144,
490 .right_margin = 32,
491 .upper_margin = 30,
492 .lower_margin = 2,
493 .hsync_len = 192,
494 .vsync_len = 6,
495 .vmode = FB_VMODE_NONINTERLACED
496 }
497 }
498};
499
500#define NUM_TOTAL_MODES ARRAY_SIZE(cirrusfb_predefined)
501
502/****************************************************************************/
503/**** BEGIN PROTOTYPES ******************************************************/
504
505
506/*--- Interface used by the world ------------------------------------------*/
507static int cirrusfb_init (void);
508#ifndef MODULE
509static int cirrusfb_setup (char *options);
510#endif
511
512static int cirrusfb_open (struct fb_info *info, int user);
513static int cirrusfb_release (struct fb_info *info, int user);
514static int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
515 unsigned blue, unsigned transp,
516 struct fb_info *info);
517static int cirrusfb_check_var (struct fb_var_screeninfo *var,
518 struct fb_info *info);
519static int cirrusfb_set_par (struct fb_info *info);
520static int cirrusfb_pan_display (struct fb_var_screeninfo *var,
521 struct fb_info *info);
522static int cirrusfb_blank (int blank_mode, struct fb_info *info);
523static void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *region);
524static void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
525static void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image);
526
527/* function table of the above functions */
528static struct fb_ops cirrusfb_ops = {
529 .owner = THIS_MODULE,
530 .fb_open = cirrusfb_open,
531 .fb_release = cirrusfb_release,
532 .fb_setcolreg = cirrusfb_setcolreg,
533 .fb_check_var = cirrusfb_check_var,
534 .fb_set_par = cirrusfb_set_par,
535 .fb_pan_display = cirrusfb_pan_display,
536 .fb_blank = cirrusfb_blank,
537 .fb_fillrect = cirrusfb_fillrect,
538 .fb_copyarea = cirrusfb_copyarea,
539 .fb_imageblit = cirrusfb_imageblit,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540};
541
542/*--- Hardware Specific Routines -------------------------------------------*/
543static int cirrusfb_decode_var (const struct fb_var_screeninfo *var,
544 struct cirrusfb_regs *regs,
545 const struct fb_info *info);
546/*--- Internal routines ----------------------------------------------------*/
547static void init_vgachip (struct cirrusfb_info *cinfo);
548static void switch_monitor (struct cirrusfb_info *cinfo, int on);
549static void WGen (const struct cirrusfb_info *cinfo,
550 int regnum, unsigned char val);
551static unsigned char RGen (const struct cirrusfb_info *cinfo, int regnum);
552static void AttrOn (const struct cirrusfb_info *cinfo);
553static void WHDR (const struct cirrusfb_info *cinfo, unsigned char val);
554static void WSFR (struct cirrusfb_info *cinfo, unsigned char val);
555static void WSFR2 (struct cirrusfb_info *cinfo, unsigned char val);
556static void WClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
557 unsigned char green,
558 unsigned char blue);
559#if 0
560static void RClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
561 unsigned char *green,
562 unsigned char *blue);
563#endif
564static void cirrusfb_WaitBLT (u8 __iomem *regbase);
565static void cirrusfb_BitBLT (u8 __iomem *regbase, int bits_per_pixel,
566 u_short curx, u_short cury,
567 u_short destx, u_short desty,
568 u_short width, u_short height,
569 u_short line_length);
570static void cirrusfb_RectFill (u8 __iomem *regbase, int bits_per_pixel,
571 u_short x, u_short y,
572 u_short width, u_short height,
573 u_char color, u_short line_length);
574
575static void bestclock (long freq, long *best,
576 long *nom, long *den,
577 long *div, long maxfreq);
578
579#ifdef CIRRUSFB_DEBUG
580static void cirrusfb_dump (void);
581static void cirrusfb_dbg_reg_dump (caddr_t regbase);
582static void cirrusfb_dbg_print_regs (caddr_t regbase, cirrusfb_dbg_reg_class_t reg_class,...);
583static void cirrusfb_dbg_print_byte (const char *name, unsigned char val);
584#endif /* CIRRUSFB_DEBUG */
585
586/*** END PROTOTYPES ********************************************************/
587/*****************************************************************************/
588/*** BEGIN Interface Used by the World ***************************************/
589
590static int opencount = 0;
591
592/*--- Open /dev/fbx ---------------------------------------------------------*/
593static int cirrusfb_open (struct fb_info *info, int user)
594{
595 if (opencount++ == 0)
596 switch_monitor (info->par, 1);
597 return 0;
598}
599
600/*--- Close /dev/fbx --------------------------------------------------------*/
601static int cirrusfb_release (struct fb_info *info, int user)
602{
603 if (--opencount == 0)
604 switch_monitor (info->par, 0);
605 return 0;
606}
607
608/**** END Interface used by the World *************************************/
609/****************************************************************************/
610/**** BEGIN Hardware specific Routines **************************************/
611
612/* Get a good MCLK value */
613static long cirrusfb_get_mclk (long freq, int bpp, long *div)
614{
615 long mclk;
616
617 assert (div != NULL);
618
619 /* Calculate MCLK, in case VCLK is high enough to require > 50MHz.
620 * Assume a 64-bit data path for now. The formula is:
621 * ((B * PCLK * 2)/W) * 1.2
622 * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */
623 mclk = ((bpp / 8) * freq * 2) / 4;
624 mclk = (mclk * 12) / 10;
625 if (mclk < 50000)
626 mclk = 50000;
627 DPRINTK ("Use MCLK of %ld kHz\n", mclk);
628
629 /* Calculate value for SR1F. Multiply by 2 so we can round up. */
630 mclk = ((mclk * 16) / 14318);
631 mclk = (mclk + 1) / 2;
632 DPRINTK ("Set SR1F[5:0] to 0x%lx\n", mclk);
633
634 /* Determine if we should use MCLK instead of VCLK, and if so, what we
635 * should divide it by to get VCLK */
636 switch (freq) {
637 case 24751 ... 25249:
638 *div = 2;
639 DPRINTK ("Using VCLK = MCLK/2\n");
640 break;
641 case 49501 ... 50499:
642 *div = 1;
643 DPRINTK ("Using VCLK = MCLK\n");
644 break;
645 default:
646 *div = 0;
647 break;
648 }
649
650 return mclk;
651}
652
653static int cirrusfb_check_var(struct fb_var_screeninfo *var,
654 struct fb_info *info)
655{
656 struct cirrusfb_info *cinfo = info->par;
657 int nom, den; /* translyting from pixels->bytes */
658 int yres, i;
659 static struct { int xres, yres; } modes[] =
660 { { 1600, 1280 },
661 { 1280, 1024 },
662 { 1024, 768 },
663 { 800, 600 },
664 { 640, 480 },
665 { -1, -1 } };
666
667 switch (var->bits_per_pixel) {
668 case 0 ... 1:
669 var->bits_per_pixel = 1;
670 nom = 4;
671 den = 8;
672 break; /* 8 pixel per byte, only 1/4th of mem usable */
673 case 2 ... 8:
674 var->bits_per_pixel = 8;
675 nom = 1;
676 den = 1;
677 break; /* 1 pixel == 1 byte */
678 case 9 ... 16:
679 var->bits_per_pixel = 16;
680 nom = 2;
681 den = 1;
682 break; /* 2 bytes per pixel */
683 case 17 ... 24:
684 var->bits_per_pixel = 24;
685 nom = 3;
686 den = 1;
687 break; /* 3 bytes per pixel */
688 case 25 ... 32:
689 var->bits_per_pixel = 32;
690 nom = 4;
691 den = 1;
692 break; /* 4 bytes per pixel */
693 default:
694 printk ("cirrusfb: mode %dx%dx%d rejected...color depth not supported.\n",
695 var->xres, var->yres, var->bits_per_pixel);
696 DPRINTK ("EXIT - EINVAL error\n");
697 return -EINVAL;
698 }
699
700 if (var->xres * nom / den * var->yres > cinfo->size) {
701 printk ("cirrusfb: mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
702 var->xres, var->yres, var->bits_per_pixel);
703 DPRINTK ("EXIT - EINVAL error\n");
704 return -EINVAL;
705 }
706
707 /* use highest possible virtual resolution */
708 if (var->xres_virtual == -1 &&
709 var->yres_virtual == -1) {
710 printk ("cirrusfb: using maximum available virtual resolution\n");
711 for (i = 0; modes[i].xres != -1; i++) {
712 if (modes[i].xres * nom / den * modes[i].yres < cinfo->size / 2)
713 break;
714 }
715 if (modes[i].xres == -1) {
716 printk ("cirrusfb: could not find a virtual resolution that fits into video memory!!\n");
717 DPRINTK ("EXIT - EINVAL error\n");
718 return -EINVAL;
719 }
720 var->xres_virtual = modes[i].xres;
721 var->yres_virtual = modes[i].yres;
722
723 printk ("cirrusfb: virtual resolution set to maximum of %dx%d\n",
724 var->xres_virtual, var->yres_virtual);
725 }
726
727 if (var->xres_virtual < var->xres)
728 var->xres_virtual = var->xres;
729 if (var->yres_virtual < var->yres)
730 var->yres_virtual = var->yres;
731
732 if (var->xoffset < 0)
733 var->xoffset = 0;
734 if (var->yoffset < 0)
735 var->yoffset = 0;
736
737 /* truncate xoffset and yoffset to maximum if too high */
738 if (var->xoffset > var->xres_virtual - var->xres)
739 var->xoffset = var->xres_virtual - var->xres - 1;
740 if (var->yoffset > var->yres_virtual - var->yres)
741 var->yoffset = var->yres_virtual - var->yres - 1;
742
743 switch (var->bits_per_pixel) {
744 case 1:
745 var->red.offset = 0;
746 var->red.length = 1;
747 var->green.offset = 0;
748 var->green.length = 1;
749 var->blue.offset = 0;
750 var->blue.length = 1;
751 break;
752
753 case 8:
754 var->red.offset = 0;
755 var->red.length = 6;
756 var->green.offset = 0;
757 var->green.length = 6;
758 var->blue.offset = 0;
759 var->blue.length = 6;
760 break;
761
762 case 16:
763 if(isPReP) {
764 var->red.offset = 2;
765 var->green.offset = -3;
766 var->blue.offset = 8;
767 } else {
768 var->red.offset = 10;
769 var->green.offset = 5;
770 var->blue.offset = 0;
771 }
772 var->red.length = 5;
773 var->green.length = 5;
774 var->blue.length = 5;
775 break;
776
777 case 24:
778 if(isPReP) {
779 var->red.offset = 8;
780 var->green.offset = 16;
781 var->blue.offset = 24;
782 } else {
783 var->red.offset = 16;
784 var->green.offset = 8;
785 var->blue.offset = 0;
786 }
787 var->red.length = 8;
788 var->green.length = 8;
789 var->blue.length = 8;
790 break;
791
792 case 32:
793 if(isPReP) {
794 var->red.offset = 8;
795 var->green.offset = 16;
796 var->blue.offset = 24;
797 } else {
798 var->red.offset = 16;
799 var->green.offset = 8;
800 var->blue.offset = 0;
801 }
802 var->red.length = 8;
803 var->green.length = 8;
804 var->blue.length = 8;
805 break;
806
807 default:
808 DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);
Richard Knutssonc930faa2007-05-08 00:38:29 -0700809 assert(false);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 /* should never occur */
811 break;
812 }
813
814 var->red.msb_right =
815 var->green.msb_right =
816 var->blue.msb_right =
817 var->transp.offset =
818 var->transp.length =
819 var->transp.msb_right = 0;
820
821 yres = var->yres;
822 if (var->vmode & FB_VMODE_DOUBLE)
823 yres *= 2;
824 else if (var->vmode & FB_VMODE_INTERLACED)
825 yres = (yres + 1) / 2;
826
827 if (yres >= 1280) {
828 printk (KERN_WARNING "cirrusfb: ERROR: VerticalTotal >= 1280; special treatment required! (TODO)\n");
829 DPRINTK ("EXIT - EINVAL error\n");
830 return -EINVAL;
831 }
832
833 return 0;
834}
835
836static int cirrusfb_decode_var (const struct fb_var_screeninfo *var,
837 struct cirrusfb_regs *regs,
838 const struct fb_info *info)
839{
840 long freq;
841 long maxclock;
842 int maxclockidx = 0;
843 struct cirrusfb_info *cinfo = info->par;
844 int xres, hfront, hsync, hback;
845 int yres, vfront, vsync, vback;
846
847 switch(var->bits_per_pixel) {
848 case 1:
849 regs->line_length = var->xres_virtual / 8;
850 regs->visual = FB_VISUAL_MONO10;
851 maxclockidx = 0;
852 break;
853
854 case 8:
855 regs->line_length = var->xres_virtual;
856 regs->visual = FB_VISUAL_PSEUDOCOLOR;
857 maxclockidx = 1;
858 break;
859
860 case 16:
861 regs->line_length = var->xres_virtual * 2;
862 regs->visual = FB_VISUAL_DIRECTCOLOR;
863 maxclockidx = 2;
864 break;
865
866 case 24:
867 regs->line_length = var->xres_virtual * 3;
868 regs->visual = FB_VISUAL_DIRECTCOLOR;
869 maxclockidx = 3;
870 break;
871
872 case 32:
873 regs->line_length = var->xres_virtual * 4;
874 regs->visual = FB_VISUAL_DIRECTCOLOR;
875 maxclockidx = 4;
876 break;
877
878 default:
879 DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);
Richard Knutssonc930faa2007-05-08 00:38:29 -0700880 assert(false);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 /* should never occur */
882 break;
883 }
884
885 regs->type = FB_TYPE_PACKED_PIXELS;
886
887 /* convert from ps to kHz */
888 freq = 1000000000 / var->pixclock;
889
890 DPRINTK ("desired pixclock: %ld kHz\n", freq);
891
892 maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
893 regs->multiplexing = 0;
894
895 /* If the frequency is greater than we can support, we might be able
896 * to use multiplexing for the video mode */
897 if (freq > maxclock) {
898 switch (cinfo->btype) {
899 case BT_ALPINE:
900 case BT_GD5480:
901 regs->multiplexing = 1;
902 break;
903
904 default:
905 printk (KERN_WARNING "cirrusfb: ERROR: Frequency greater than maxclock (%ld kHz)\n", maxclock);
906 DPRINTK ("EXIT - return -EINVAL\n");
907 return -EINVAL;
908 }
909 }
910#if 0
911 /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
912 * the VCLK is double the pixel clock. */
913 switch (var->bits_per_pixel) {
914 case 16:
915 case 32:
916 if (regs->HorizRes <= 800)
917 freq /= 2; /* Xbh has this type of clock for 32-bit */
918 break;
919 }
920#endif
921
922 bestclock (freq, &regs->freq, &regs->nom, &regs->den, &regs->div,
923 maxclock);
924 regs->mclk = cirrusfb_get_mclk (freq, var->bits_per_pixel, &regs->divMCLK);
925
926 xres = var->xres;
927 hfront = var->right_margin;
928 hsync = var->hsync_len;
929 hback = var->left_margin;
930
931 yres = var->yres;
932 vfront = var->lower_margin;
933 vsync = var->vsync_len;
934 vback = var->upper_margin;
935
936 if (var->vmode & FB_VMODE_DOUBLE) {
937 yres *= 2;
938 vfront *= 2;
939 vsync *= 2;
940 vback *= 2;
941 } else if (var->vmode & FB_VMODE_INTERLACED) {
942 yres = (yres + 1) / 2;
943 vfront = (vfront + 1) / 2;
944 vsync = (vsync + 1) / 2;
945 vback = (vback + 1) / 2;
946 }
947 regs->HorizRes = xres;
948 regs->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5;
949 regs->HorizDispEnd = xres / 8 - 1;
950 regs->HorizBlankStart = xres / 8;
951 regs->HorizBlankEnd = regs->HorizTotal + 5; /* does not count with "-5" */
952 regs->HorizSyncStart = (xres + hfront) / 8 + 1;
953 regs->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1;
954
955 regs->VertRes = yres;
956 regs->VertTotal = yres + vfront + vsync + vback - 2;
957 regs->VertDispEnd = yres - 1;
958 regs->VertBlankStart = yres;
959 regs->VertBlankEnd = regs->VertTotal;
960 regs->VertSyncStart = yres + vfront - 1;
961 regs->VertSyncEnd = yres + vfront + vsync - 1;
962
963 if (regs->VertRes >= 1024) {
964 regs->VertTotal /= 2;
965 regs->VertSyncStart /= 2;
966 regs->VertSyncEnd /= 2;
967 regs->VertDispEnd /= 2;
968 }
969 if (regs->multiplexing) {
970 regs->HorizTotal /= 2;
971 regs->HorizSyncStart /= 2;
972 regs->HorizSyncEnd /= 2;
973 regs->HorizDispEnd /= 2;
974 }
975
976 return 0;
977}
978
979
980static void cirrusfb_set_mclk (const struct cirrusfb_info *cinfo, int val, int div)
981{
982 assert (cinfo != NULL);
983
984 if (div == 2) {
985 /* VCLK = MCLK/2 */
986 unsigned char old = vga_rseq (cinfo->regbase, CL_SEQR1E);
987 vga_wseq (cinfo->regbase, CL_SEQR1E, old | 0x1);
988 vga_wseq (cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
989 } else if (div == 1) {
990 /* VCLK = MCLK */
991 unsigned char old = vga_rseq (cinfo->regbase, CL_SEQR1E);
992 vga_wseq (cinfo->regbase, CL_SEQR1E, old & ~0x1);
993 vga_wseq (cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
994 } else {
995 vga_wseq (cinfo->regbase, CL_SEQR1F, val & 0x3f);
996 }
997}
998
999/*************************************************************************
1000 cirrusfb_set_par_foo()
1001
1002 actually writes the values for a new video mode into the hardware,
1003**************************************************************************/
1004static int cirrusfb_set_par_foo (struct fb_info *info)
1005{
1006 struct cirrusfb_info *cinfo = info->par;
1007 struct fb_var_screeninfo *var = &info->var;
1008 struct cirrusfb_regs regs;
1009 u8 __iomem *regbase = cinfo->regbase;
1010 unsigned char tmp;
1011 int offset = 0, err;
1012 const struct cirrusfb_board_info_rec *bi;
1013
1014 DPRINTK ("ENTER\n");
1015 DPRINTK ("Requested mode: %dx%dx%d\n",
1016 var->xres, var->yres, var->bits_per_pixel);
1017 DPRINTK ("pixclock: %d\n", var->pixclock);
1018
1019 init_vgachip (cinfo);
1020
1021 err = cirrusfb_decode_var(var, &regs, info);
1022 if(err) {
1023 /* should never happen */
1024 DPRINTK("mode change aborted. invalid var.\n");
1025 return -EINVAL;
1026 }
1027
1028 bi = &cirrusfb_board_info[cinfo->btype];
1029
1030
1031 /* unlock register VGA_CRTC_H_TOTAL..CRT7 */
1032 vga_wcrt (regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */
1033
1034 /* if debugging is enabled, all parameters get output before writing */
1035 DPRINTK ("CRT0: %ld\n", regs.HorizTotal);
1036 vga_wcrt (regbase, VGA_CRTC_H_TOTAL, regs.HorizTotal);
1037
1038 DPRINTK ("CRT1: %ld\n", regs.HorizDispEnd);
1039 vga_wcrt (regbase, VGA_CRTC_H_DISP, regs.HorizDispEnd);
1040
1041 DPRINTK ("CRT2: %ld\n", regs.HorizBlankStart);
1042 vga_wcrt (regbase, VGA_CRTC_H_BLANK_START, regs.HorizBlankStart);
1043
1044 DPRINTK ("CRT3: 128+%ld\n", regs.HorizBlankEnd % 32); /* + 128: Compatible read */
1045 vga_wcrt (regbase, VGA_CRTC_H_BLANK_END, 128 + (regs.HorizBlankEnd % 32));
1046
1047 DPRINTK ("CRT4: %ld\n", regs.HorizSyncStart);
1048 vga_wcrt (regbase, VGA_CRTC_H_SYNC_START, regs.HorizSyncStart);
1049
1050 tmp = regs.HorizSyncEnd % 32;
1051 if (regs.HorizBlankEnd & 32)
1052 tmp += 128;
1053 DPRINTK ("CRT5: %d\n", tmp);
1054 vga_wcrt (regbase, VGA_CRTC_H_SYNC_END, tmp);
1055
1056 DPRINTK ("CRT6: %ld\n", regs.VertTotal & 0xff);
1057 vga_wcrt (regbase, VGA_CRTC_V_TOTAL, (regs.VertTotal & 0xff));
1058
1059 tmp = 16; /* LineCompare bit #9 */
1060 if (regs.VertTotal & 256)
1061 tmp |= 1;
1062 if (regs.VertDispEnd & 256)
1063 tmp |= 2;
1064 if (regs.VertSyncStart & 256)
1065 tmp |= 4;
1066 if (regs.VertBlankStart & 256)
1067 tmp |= 8;
1068 if (regs.VertTotal & 512)
1069 tmp |= 32;
1070 if (regs.VertDispEnd & 512)
1071 tmp |= 64;
1072 if (regs.VertSyncStart & 512)
1073 tmp |= 128;
1074 DPRINTK ("CRT7: %d\n", tmp);
1075 vga_wcrt (regbase, VGA_CRTC_OVERFLOW, tmp);
1076
1077 tmp = 0x40; /* LineCompare bit #8 */
1078 if (regs.VertBlankStart & 512)
1079 tmp |= 0x20;
1080 if (var->vmode & FB_VMODE_DOUBLE)
1081 tmp |= 0x80;
1082 DPRINTK ("CRT9: %d\n", tmp);
1083 vga_wcrt (regbase, VGA_CRTC_MAX_SCAN, tmp);
1084
1085 DPRINTK ("CRT10: %ld\n", regs.VertSyncStart & 0xff);
1086 vga_wcrt (regbase, VGA_CRTC_V_SYNC_START, (regs.VertSyncStart & 0xff));
1087
1088 DPRINTK ("CRT11: 64+32+%ld\n", regs.VertSyncEnd % 16);
1089 vga_wcrt (regbase, VGA_CRTC_V_SYNC_END, (regs.VertSyncEnd % 16 + 64 + 32));
1090
1091 DPRINTK ("CRT12: %ld\n", regs.VertDispEnd & 0xff);
1092 vga_wcrt (regbase, VGA_CRTC_V_DISP_END, (regs.VertDispEnd & 0xff));
1093
1094 DPRINTK ("CRT15: %ld\n", regs.VertBlankStart & 0xff);
1095 vga_wcrt (regbase, VGA_CRTC_V_BLANK_START, (regs.VertBlankStart & 0xff));
1096
1097 DPRINTK ("CRT16: %ld\n", regs.VertBlankEnd & 0xff);
1098 vga_wcrt (regbase, VGA_CRTC_V_BLANK_END, (regs.VertBlankEnd & 0xff));
1099
1100 DPRINTK ("CRT18: 0xff\n");
1101 vga_wcrt (regbase, VGA_CRTC_LINE_COMPARE, 0xff);
1102
1103 tmp = 0;
1104 if (var->vmode & FB_VMODE_INTERLACED)
1105 tmp |= 1;
1106 if (regs.HorizBlankEnd & 64)
1107 tmp |= 16;
1108 if (regs.HorizBlankEnd & 128)
1109 tmp |= 32;
1110 if (regs.VertBlankEnd & 256)
1111 tmp |= 64;
1112 if (regs.VertBlankEnd & 512)
1113 tmp |= 128;
1114
1115 DPRINTK ("CRT1a: %d\n", tmp);
1116 vga_wcrt (regbase, CL_CRT1A, tmp);
1117
1118 /* set VCLK0 */
1119 /* hardware RefClock: 14.31818 MHz */
1120 /* formula: VClk = (OSC * N) / (D * (1+P)) */
1121 /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
1122
1123 vga_wseq (regbase, CL_SEQRB, regs.nom);
1124 tmp = regs.den << 1;
1125 if (regs.div != 0)
1126 tmp |= 1;
1127
1128 if ((cinfo->btype == BT_SD64) ||
1129 (cinfo->btype == BT_ALPINE) ||
1130 (cinfo->btype == BT_GD5480))
1131 tmp |= 0x80; /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
1132
1133 DPRINTK ("CL_SEQR1B: %ld\n", (long) tmp);
1134 vga_wseq (regbase, CL_SEQR1B, tmp);
1135
1136 if (regs.VertRes >= 1024)
1137 /* 1280x1024 */
1138 vga_wcrt (regbase, VGA_CRTC_MODE, 0xc7);
1139 else
1140 /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
1141 * address wrap, no compat. */
1142 vga_wcrt (regbase, VGA_CRTC_MODE, 0xc3);
1143
1144/* HAEH? vga_wcrt (regbase, VGA_CRTC_V_SYNC_END, 0x20); * previously: 0x00 unlock VGA_CRTC_H_TOTAL..CRT7 */
1145
1146 /* don't know if it would hurt to also program this if no interlaced */
1147 /* mode is used, but I feel better this way.. :-) */
1148 if (var->vmode & FB_VMODE_INTERLACED)
1149 vga_wcrt (regbase, VGA_CRTC_REGS, regs.HorizTotal / 2);
1150 else
1151 vga_wcrt (regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
1152
1153 vga_wseq (regbase, VGA_SEQ_CHARACTER_MAP, 0);
1154
1155 /* adjust horizontal/vertical sync type (low/high) */
1156 tmp = 0x03; /* enable display memory & CRTC I/O address for color mode */
1157 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1158 tmp |= 0x40;
1159 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1160 tmp |= 0x80;
1161 WGen (cinfo, VGA_MIS_W, tmp);
1162
1163 vga_wcrt (regbase, VGA_CRTC_PRESET_ROW, 0); /* Screen A Preset Row-Scan register */
1164 vga_wcrt (regbase, VGA_CRTC_CURSOR_START, 0); /* text cursor on and start line */
1165 vga_wcrt (regbase, VGA_CRTC_CURSOR_END, 31); /* text cursor end line */
1166
1167 /******************************************************
1168 *
1169 * 1 bpp
1170 *
1171 */
1172
1173 /* programming for different color depths */
1174 if (var->bits_per_pixel == 1) {
1175 DPRINTK ("cirrusfb: preparing for 1 bit deep display\n");
1176 vga_wgfx (regbase, VGA_GFX_MODE, 0); /* mode register */
1177
1178 /* SR07 */
1179 switch (cinfo->btype) {
1180 case BT_SD64:
1181 case BT_PICCOLO:
1182 case BT_PICASSO:
1183 case BT_SPECTRUM:
1184 case BT_PICASSO4:
1185 case BT_ALPINE:
1186 case BT_GD5480:
1187 DPRINTK (" (for GD54xx)\n");
1188 vga_wseq (regbase, CL_SEQR7,
1189 regs.multiplexing ?
1190 bi->sr07_1bpp_mux : bi->sr07_1bpp);
1191 break;
1192
1193 case BT_LAGUNA:
1194 DPRINTK (" (for GD546x)\n");
1195 vga_wseq (regbase, CL_SEQR7,
1196 vga_rseq (regbase, CL_SEQR7) & ~0x01);
1197 break;
1198
1199 default:
1200 printk (KERN_WARNING "cirrusfb: unknown Board\n");
1201 break;
1202 }
1203
1204 /* Extended Sequencer Mode */
1205 switch (cinfo->btype) {
1206 case BT_SD64:
1207 /* setting the SEQRF on SD64 is not necessary (only during init) */
1208 DPRINTK ("(for SD64)\n");
1209 vga_wseq (regbase, CL_SEQR1F, 0x1a); /* MCLK select */
1210 break;
1211
1212 case BT_PICCOLO:
1213 DPRINTK ("(for Piccolo)\n");
1214/* ### ueberall 0x22? */
1215 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ##vorher 1c MCLK select */
1216 vga_wseq (regbase, CL_SEQRF, 0xb0); /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
1217 break;
1218
1219 case BT_PICASSO:
1220 DPRINTK ("(for Picasso)\n");
1221 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ##vorher 22 MCLK select */
1222 vga_wseq (regbase, CL_SEQRF, 0xd0); /* ## vorher d0 avoid FIFO underruns..? */
1223 break;
1224
1225 case BT_SPECTRUM:
1226 DPRINTK ("(for Spectrum)\n");
1227/* ### ueberall 0x22? */
1228 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ##vorher 1c MCLK select */
1229 vga_wseq (regbase, CL_SEQRF, 0xb0); /* evtl d0? avoid FIFO underruns..? */
1230 break;
1231
1232 case BT_PICASSO4:
1233 case BT_ALPINE:
1234 case BT_GD5480:
1235 case BT_LAGUNA:
1236 DPRINTK (" (for GD54xx)\n");
1237 /* do nothing */
1238 break;
1239
1240 default:
1241 printk (KERN_WARNING "cirrusfb: unknown Board\n");
1242 break;
1243 }
1244
1245 WGen (cinfo, VGA_PEL_MSK, 0x01); /* pixel mask: pass-through for first plane */
1246 if (regs.multiplexing)
1247 WHDR (cinfo, 0x4a); /* hidden dac reg: 1280x1024 */
1248 else
1249 WHDR (cinfo, 0); /* hidden dac: nothing */
1250 vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x06); /* memory mode: odd/even, ext. memory */
1251 vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0x01); /* plane mask: only write to first plane */
1252 offset = var->xres_virtual / 16;
1253 }
1254
1255 /******************************************************
1256 *
1257 * 8 bpp
1258 *
1259 */
1260
1261 else if (var->bits_per_pixel == 8) {
1262 DPRINTK ("cirrusfb: preparing for 8 bit deep display\n");
1263 switch (cinfo->btype) {
1264 case BT_SD64:
1265 case BT_PICCOLO:
1266 case BT_PICASSO:
1267 case BT_SPECTRUM:
1268 case BT_PICASSO4:
1269 case BT_ALPINE:
1270 case BT_GD5480:
1271 DPRINTK (" (for GD54xx)\n");
1272 vga_wseq (regbase, CL_SEQR7,
1273 regs.multiplexing ?
1274 bi->sr07_8bpp_mux : bi->sr07_8bpp);
1275 break;
1276
1277 case BT_LAGUNA:
1278 DPRINTK (" (for GD546x)\n");
1279 vga_wseq (regbase, CL_SEQR7,
1280 vga_rseq (regbase, CL_SEQR7) | 0x01);
1281 break;
1282
1283 default:
1284 printk (KERN_WARNING "cirrusfb: unknown Board\n");
1285 break;
1286 }
1287
1288 switch (cinfo->btype) {
1289 case BT_SD64:
1290 vga_wseq (regbase, CL_SEQR1F, 0x1d); /* MCLK select */
1291 break;
1292
1293 case BT_PICCOLO:
1294 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */
1295 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1296 break;
1297
1298 case BT_PICASSO:
1299 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */
1300 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1301 break;
1302
1303 case BT_SPECTRUM:
1304 vga_wseq (regbase, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */
1305 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1306 break;
1307
1308 case BT_PICASSO4:
1309#ifdef CONFIG_ZORRO
1310 vga_wseq (regbase, CL_SEQRF, 0xb8); /* ### INCOMPLETE!! */
1311#endif
1312/* vga_wseq (regbase, CL_SEQR1F, 0x1c); */
1313 break;
1314
1315 case BT_ALPINE:
1316 DPRINTK (" (for GD543x)\n");
1317 cirrusfb_set_mclk (cinfo, regs.mclk, regs.divMCLK);
1318 /* We already set SRF and SR1F */
1319 break;
1320
1321 case BT_GD5480:
1322 case BT_LAGUNA:
1323 DPRINTK (" (for GD54xx)\n");
1324 /* do nothing */
1325 break;
1326
1327 default:
1328 printk (KERN_WARNING "cirrusfb: unknown Board\n");
1329 break;
1330 }
1331
1332 vga_wgfx (regbase, VGA_GFX_MODE, 64); /* mode register: 256 color mode */
1333 WGen (cinfo, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */
1334 if (regs.multiplexing)
1335 WHDR (cinfo, 0x4a); /* hidden dac reg: 1280x1024 */
1336 else
1337 WHDR (cinfo, 0); /* hidden dac: nothing */
1338 vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */
1339 vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */
1340 offset = var->xres_virtual / 8;
1341 }
1342
1343 /******************************************************
1344 *
1345 * 16 bpp
1346 *
1347 */
1348
1349 else if (var->bits_per_pixel == 16) {
1350 DPRINTK ("cirrusfb: preparing for 16 bit deep display\n");
1351 switch (cinfo->btype) {
1352 case BT_SD64:
1353 vga_wseq (regbase, CL_SEQR7, 0xf7); /* Extended Sequencer Mode: 256c col. mode */
1354 vga_wseq (regbase, CL_SEQR1F, 0x1e); /* MCLK select */
1355 break;
1356
1357 case BT_PICCOLO:
1358 vga_wseq (regbase, CL_SEQR7, 0x87);
1359 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1360 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
1361 break;
1362
1363 case BT_PICASSO:
1364 vga_wseq (regbase, CL_SEQR7, 0x27);
1365 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1366 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
1367 break;
1368
1369 case BT_SPECTRUM:
1370 vga_wseq (regbase, CL_SEQR7, 0x87);
1371 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1372 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
1373 break;
1374
1375 case BT_PICASSO4:
1376 vga_wseq (regbase, CL_SEQR7, 0x27);
1377/* vga_wseq (regbase, CL_SEQR1F, 0x1c); */
1378 break;
1379
1380 case BT_ALPINE:
1381 DPRINTK (" (for GD543x)\n");
1382 if (regs.HorizRes >= 1024)
1383 vga_wseq (regbase, CL_SEQR7, 0xa7);
1384 else
1385 vga_wseq (regbase, CL_SEQR7, 0xa3);
1386 cirrusfb_set_mclk (cinfo, regs.mclk, regs.divMCLK);
1387 break;
1388
1389 case BT_GD5480:
1390 DPRINTK (" (for GD5480)\n");
1391 vga_wseq (regbase, CL_SEQR7, 0x17);
1392 /* We already set SRF and SR1F */
1393 break;
1394
1395 case BT_LAGUNA:
1396 DPRINTK (" (for GD546x)\n");
1397 vga_wseq (regbase, CL_SEQR7,
1398 vga_rseq (regbase, CL_SEQR7) & ~0x01);
1399 break;
1400
1401 default:
1402 printk (KERN_WARNING "CIRRUSFB: unknown Board\n");
1403 break;
1404 }
1405
1406 vga_wgfx (regbase, VGA_GFX_MODE, 64); /* mode register: 256 color mode */
1407 WGen (cinfo, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */
1408#ifdef CONFIG_PCI
1409 WHDR (cinfo, 0xc0); /* Copy Xbh */
1410#elif defined(CONFIG_ZORRO)
1411 /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
1412 WHDR (cinfo, 0xa0); /* hidden dac reg: nothing special */
1413#endif
1414 vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */
1415 vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */
1416 offset = var->xres_virtual / 4;
1417 }
1418
1419 /******************************************************
1420 *
1421 * 32 bpp
1422 *
1423 */
1424
1425 else if (var->bits_per_pixel == 32) {
1426 DPRINTK ("cirrusfb: preparing for 24/32 bit deep display\n");
1427 switch (cinfo->btype) {
1428 case BT_SD64:
1429 vga_wseq (regbase, CL_SEQR7, 0xf9); /* Extended Sequencer Mode: 256c col. mode */
1430 vga_wseq (regbase, CL_SEQR1F, 0x1e); /* MCLK select */
1431 break;
1432
1433 case BT_PICCOLO:
1434 vga_wseq (regbase, CL_SEQR7, 0x85);
1435 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1436 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
1437 break;
1438
1439 case BT_PICASSO:
1440 vga_wseq (regbase, CL_SEQR7, 0x25);
1441 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1442 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
1443 break;
1444
1445 case BT_SPECTRUM:
1446 vga_wseq (regbase, CL_SEQR7, 0x85);
1447 vga_wseq (regbase, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
1448 vga_wseq (regbase, CL_SEQR1F, 0x22); /* MCLK select */
1449 break;
1450
1451 case BT_PICASSO4:
1452 vga_wseq (regbase, CL_SEQR7, 0x25);
1453/* vga_wseq (regbase, CL_SEQR1F, 0x1c); */
1454 break;
1455
1456 case BT_ALPINE:
1457 DPRINTK (" (for GD543x)\n");
1458 vga_wseq (regbase, CL_SEQR7, 0xa9);
1459 cirrusfb_set_mclk (cinfo, regs.mclk, regs.divMCLK);
1460 break;
1461
1462 case BT_GD5480:
1463 DPRINTK (" (for GD5480)\n");
1464 vga_wseq (regbase, CL_SEQR7, 0x19);
1465 /* We already set SRF and SR1F */
1466 break;
1467
1468 case BT_LAGUNA:
1469 DPRINTK (" (for GD546x)\n");
1470 vga_wseq (regbase, CL_SEQR7,
1471 vga_rseq (regbase, CL_SEQR7) & ~0x01);
1472 break;
1473
1474 default:
1475 printk (KERN_WARNING "cirrusfb: unknown Board\n");
1476 break;
1477 }
1478
1479 vga_wgfx (regbase, VGA_GFX_MODE, 64); /* mode register: 256 color mode */
1480 WGen (cinfo, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */
1481 WHDR (cinfo, 0xc5); /* hidden dac reg: 8-8-8 mode (24 or 32) */
1482 vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */
1483 vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */
1484 offset = var->xres_virtual / 4;
1485 }
1486
1487 /******************************************************
1488 *
1489 * unknown/unsupported bpp
1490 *
1491 */
1492
1493 else {
1494 printk (KERN_ERR "cirrusfb: What's this?? requested color depth == %d.\n",
1495 var->bits_per_pixel);
1496 }
1497
1498 vga_wcrt (regbase, VGA_CRTC_OFFSET, offset & 0xff);
1499 tmp = 0x22;
1500 if (offset & 0x100)
1501 tmp |= 0x10; /* offset overflow bit */
1502
1503 vga_wcrt (regbase, CL_CRT1B, tmp); /* screen start addr #16-18, fastpagemode cycles */
1504
1505 if (cinfo->btype == BT_SD64 ||
1506 cinfo->btype == BT_PICASSO4 ||
1507 cinfo->btype == BT_ALPINE ||
1508 cinfo->btype == BT_GD5480)
1509 vga_wcrt (regbase, CL_CRT1D, 0x00); /* screen start address bit 19 */
1510
1511 vga_wcrt (regbase, VGA_CRTC_CURSOR_HI, 0); /* text cursor location high */
1512 vga_wcrt (regbase, VGA_CRTC_CURSOR_LO, 0); /* text cursor location low */
1513 vga_wcrt (regbase, VGA_CRTC_UNDERLINE, 0); /* underline row scanline = at very bottom */
1514
1515 vga_wattr (regbase, VGA_ATC_MODE, 1); /* controller mode */
1516 vga_wattr (regbase, VGA_ATC_OVERSCAN, 0); /* overscan (border) color */
1517 vga_wattr (regbase, VGA_ATC_PLANE_ENABLE, 15); /* color plane enable */
1518 vga_wattr (regbase, CL_AR33, 0); /* pixel panning */
1519 vga_wattr (regbase, VGA_ATC_COLOR_PAGE, 0); /* color select */
1520
1521 /* [ EGS: SetOffset(); ] */
1522 /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
1523 AttrOn (cinfo);
1524
1525 vga_wgfx (regbase, VGA_GFX_SR_VALUE, 0); /* set/reset register */
1526 vga_wgfx (regbase, VGA_GFX_SR_ENABLE, 0); /* set/reset enable */
1527 vga_wgfx (regbase, VGA_GFX_COMPARE_VALUE, 0); /* color compare */
1528 vga_wgfx (regbase, VGA_GFX_DATA_ROTATE, 0); /* data rotate */
1529 vga_wgfx (regbase, VGA_GFX_PLANE_READ, 0); /* read map select */
1530 vga_wgfx (regbase, VGA_GFX_MISC, 1); /* miscellaneous register */
1531 vga_wgfx (regbase, VGA_GFX_COMPARE_MASK, 15); /* color don't care */
1532 vga_wgfx (regbase, VGA_GFX_BIT_MASK, 255); /* bit mask */
1533
1534 vga_wseq (regbase, CL_SEQR12, 0x0); /* graphics cursor attributes: nothing special */
1535
1536 /* finally, turn on everything - turn off "FullBandwidth" bit */
1537 /* also, set "DotClock%2" bit where requested */
1538 tmp = 0x01;
1539
1540/*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
1541 if (var->vmode & FB_VMODE_CLOCK_HALVE)
1542 tmp |= 0x08;
1543*/
1544
1545 vga_wseq (regbase, VGA_SEQ_CLOCK_MODE, tmp);
1546 DPRINTK ("CL_SEQR1: %d\n", tmp);
1547
1548 cinfo->currentmode = regs;
1549 info->fix.type = regs.type;
1550 info->fix.visual = regs.visual;
1551 info->fix.line_length = regs.line_length;
1552
1553 /* pan to requested offset */
1554 cirrusfb_pan_display (var, info);
1555
1556#ifdef CIRRUSFB_DEBUG
1557 cirrusfb_dump ();
1558#endif
1559
1560 DPRINTK ("EXIT\n");
1561 return 0;
1562}
1563
1564/* for some reason incomprehensible to me, cirrusfb requires that you write
1565 * the registers twice for the settings to take..grr. -dte */
1566static int cirrusfb_set_par (struct fb_info *info)
1567{
1568 cirrusfb_set_par_foo (info);
1569 return cirrusfb_set_par_foo (info);
1570}
1571
1572static int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
1573 unsigned blue, unsigned transp,
1574 struct fb_info *info)
1575{
1576 struct cirrusfb_info *cinfo = info->par;
1577
1578 if (regno > 255)
1579 return -EINVAL;
1580
1581 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
1582 u32 v;
1583 red >>= (16 - info->var.red.length);
1584 green >>= (16 - info->var.green.length);
1585 blue >>= (16 - info->var.blue.length);
1586
1587 if (regno>=16)
1588 return 1;
1589 v = (red << info->var.red.offset) |
1590 (green << info->var.green.offset) |
1591 (blue << info->var.blue.offset);
1592
1593 switch (info->var.bits_per_pixel) {
1594 case 8:
Antonino A. Daplas49d5c7b2005-11-29 19:34:43 -08001595 cinfo->pseudo_palette[regno] = v;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 break;
1597 case 16:
Antonino A. Daplas49d5c7b2005-11-29 19:34:43 -08001598 cinfo->pseudo_palette[regno] = v;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 break;
1600 case 24:
1601 case 32:
Antonino A. Daplas49d5c7b2005-11-29 19:34:43 -08001602 cinfo->pseudo_palette[regno] = v;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 break;
1604 }
1605 return 0;
1606 }
1607
1608 cinfo->palette[regno].red = red;
1609 cinfo->palette[regno].green = green;
1610 cinfo->palette[regno].blue = blue;
1611
1612 if (info->var.bits_per_pixel == 8) {
1613 WClut (cinfo, regno, red >> 10, green >> 10, blue >> 10);
1614 }
1615
1616 return 0;
1617
1618}
1619
1620/*************************************************************************
1621 cirrusfb_pan_display()
1622
1623 performs display panning - provided hardware permits this
1624**************************************************************************/
1625static int cirrusfb_pan_display (struct fb_var_screeninfo *var,
1626 struct fb_info *info)
1627{
1628 int xoffset = 0;
1629 int yoffset = 0;
1630 unsigned long base;
1631 unsigned char tmp = 0, tmp2 = 0, xpix;
1632 struct cirrusfb_info *cinfo = info->par;
1633
1634 DPRINTK ("ENTER\n");
1635 DPRINTK ("virtual offset: (%d,%d)\n", var->xoffset, var->yoffset);
1636
1637 /* no range checks for xoffset and yoffset, */
1638 /* as fb_pan_display has already done this */
1639 if (var->vmode & FB_VMODE_YWRAP)
1640 return -EINVAL;
1641
1642 info->var.xoffset = var->xoffset;
1643 info->var.yoffset = var->yoffset;
1644
1645 xoffset = var->xoffset * info->var.bits_per_pixel / 8;
1646 yoffset = var->yoffset;
1647
1648 base = yoffset * cinfo->currentmode.line_length + xoffset;
1649
1650 if (info->var.bits_per_pixel == 1) {
1651 /* base is already correct */
1652 xpix = (unsigned char) (var->xoffset % 8);
1653 } else {
1654 base /= 4;
1655 xpix = (unsigned char) ((xoffset % 4) * 2);
1656 }
1657
1658 cirrusfb_WaitBLT(cinfo->regbase); /* make sure all the BLT's are done */
1659
1660 /* lower 8 + 8 bits of screen start address */
1661 vga_wcrt (cinfo->regbase, VGA_CRTC_START_LO, (unsigned char) (base & 0xff));
1662 vga_wcrt (cinfo->regbase, VGA_CRTC_START_HI, (unsigned char) (base >> 8));
1663
1664 /* construct bits 16, 17 and 18 of screen start address */
1665 if (base & 0x10000)
1666 tmp |= 0x01;
1667 if (base & 0x20000)
1668 tmp |= 0x04;
1669 if (base & 0x40000)
1670 tmp |= 0x08;
1671
1672 tmp2 = (vga_rcrt (cinfo->regbase, CL_CRT1B) & 0xf2) | tmp; /* 0xf2 is %11110010, exclude tmp bits */
1673 vga_wcrt (cinfo->regbase, CL_CRT1B, tmp2);
1674
1675 /* construct bit 19 of screen start address */
1676 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) {
1677 tmp2 = 0;
1678 if (base & 0x80000)
1679 tmp2 = 0x80;
1680 vga_wcrt (cinfo->regbase, CL_CRT1D, tmp2);
1681 }
1682
1683 /* write pixel panning value to AR33; this does not quite work in 8bpp */
1684 /* ### Piccolo..? Will this work? */
1685 if (info->var.bits_per_pixel == 1)
1686 vga_wattr (cinfo->regbase, CL_AR33, xpix);
1687
1688 cirrusfb_WaitBLT (cinfo->regbase);
1689
1690 DPRINTK ("EXIT\n");
1691 return (0);
1692}
1693
1694
1695static int cirrusfb_blank (int blank_mode, struct fb_info *info)
1696{
1697 /*
1698 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
1699 * then the caller blanks by setting the CLUT (Color Look Up Table) to all
1700 * black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
1701 * to e.g. a video mode which doesn't support it. Implements VESA suspend
1702 * and powerdown modes on hardware that supports disabling hsync/vsync:
1703 * blank_mode == 2: suspend vsync
1704 * blank_mode == 3: suspend hsync
1705 * blank_mode == 4: powerdown
1706 */
1707 unsigned char val;
1708 struct cirrusfb_info *cinfo = info->par;
1709 int current_mode = cinfo->blank_mode;
1710
1711 DPRINTK ("ENTER, blank mode = %d\n", blank_mode);
1712
1713 if (info->state != FBINFO_STATE_RUNNING ||
1714 current_mode == blank_mode) {
1715 DPRINTK ("EXIT, returning 0\n");
1716 return 0;
1717 }
1718
1719 /* Undo current */
1720 if (current_mode == FB_BLANK_NORMAL ||
1721 current_mode == FB_BLANK_UNBLANK) {
1722 /* unblank the screen */
1723 val = vga_rseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1724 vga_wseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE, val & 0xdf); /* clear "FullBandwidth" bit */
1725 /* and undo VESA suspend trickery */
1726 vga_wgfx (cinfo->regbase, CL_GRE, 0x00);
1727 }
1728
1729 /* set new */
1730 if(blank_mode > FB_BLANK_NORMAL) {
1731 /* blank the screen */
1732 val = vga_rseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1733 vga_wseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE, val | 0x20); /* set "FullBandwidth" bit */
1734 }
1735
1736 switch (blank_mode) {
1737 case FB_BLANK_UNBLANK:
1738 case FB_BLANK_NORMAL:
1739 break;
1740 case FB_BLANK_VSYNC_SUSPEND:
1741 vga_wgfx (cinfo->regbase, CL_GRE, 0x04);
1742 break;
1743 case FB_BLANK_HSYNC_SUSPEND:
1744 vga_wgfx (cinfo->regbase, CL_GRE, 0x02);
1745 break;
1746 case FB_BLANK_POWERDOWN:
1747 vga_wgfx (cinfo->regbase, CL_GRE, 0x06);
1748 break;
1749 default:
1750 DPRINTK ("EXIT, returning 1\n");
1751 return 1;
1752 }
1753
1754 cinfo->blank_mode = blank_mode;
1755 DPRINTK ("EXIT, returning 0\n");
1756
1757 /* Let fbcon do a soft blank for us */
1758 return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
1759}
1760/**** END Hardware specific Routines **************************************/
1761/****************************************************************************/
1762/**** BEGIN Internal Routines ***********************************************/
1763
1764static void init_vgachip (struct cirrusfb_info *cinfo)
1765{
1766 const struct cirrusfb_board_info_rec *bi;
1767
1768 DPRINTK ("ENTER\n");
1769
1770 assert (cinfo != NULL);
1771
1772 bi = &cirrusfb_board_info[cinfo->btype];
1773
1774 /* reset board globally */
1775 switch (cinfo->btype) {
1776 case BT_PICCOLO:
1777 WSFR (cinfo, 0x01);
1778 udelay (500);
1779 WSFR (cinfo, 0x51);
1780 udelay (500);
1781 break;
1782 case BT_PICASSO:
1783 WSFR2 (cinfo, 0xff);
1784 udelay (500);
1785 break;
1786 case BT_SD64:
1787 case BT_SPECTRUM:
1788 WSFR (cinfo, 0x1f);
1789 udelay (500);
1790 WSFR (cinfo, 0x4f);
1791 udelay (500);
1792 break;
1793 case BT_PICASSO4:
1794 vga_wcrt (cinfo->regbase, CL_CRT51, 0x00); /* disable flickerfixer */
1795 mdelay (100);
1796 vga_wgfx (cinfo->regbase, CL_GR2F, 0x00); /* from Klaus' NetBSD driver: */
1797 vga_wgfx (cinfo->regbase, CL_GR33, 0x00); /* put blitter into 542x compat */
1798 vga_wgfx (cinfo->regbase, CL_GR31, 0x00); /* mode */
1799 break;
1800
1801 case BT_GD5480:
1802 vga_wgfx (cinfo->regbase, CL_GR2F, 0x00); /* from Klaus' NetBSD driver: */
1803 break;
1804
1805 case BT_ALPINE:
1806 /* Nothing to do to reset the board. */
1807 break;
1808
1809 default:
1810 printk (KERN_ERR "cirrusfb: Warning: Unknown board type\n");
1811 break;
1812 }
1813
1814 assert (cinfo->size > 0); /* make sure RAM size set by this point */
1815
1816 /* the P4 is not fully initialized here; I rely on it having been */
1817 /* inited under AmigaOS already, which seems to work just fine */
1818 /* (Klaus advised to do it this way) */
1819
1820 if (cinfo->btype != BT_PICASSO4) {
1821 WGen (cinfo, CL_VSSM, 0x10); /* EGS: 0x16 */
1822 WGen (cinfo, CL_POS102, 0x01);
1823 WGen (cinfo, CL_VSSM, 0x08); /* EGS: 0x0e */
1824
1825 if (cinfo->btype != BT_SD64)
1826 WGen (cinfo, CL_VSSM2, 0x01);
1827
1828 vga_wseq (cinfo->regbase, CL_SEQR0, 0x03); /* reset sequencer logic */
1829
1830 vga_wseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21); /* FullBandwidth (video off) and 8/9 dot clock */
1831 WGen (cinfo, VGA_MIS_W, 0xc1); /* polarity (-/-), disable access to display memory, VGA_CRTC_START_HI base address: color */
1832
1833/* vga_wgfx (cinfo->regbase, CL_GRA, 0xce); "magic cookie" - doesn't make any sense to me.. */
1834 vga_wseq (cinfo->regbase, CL_SEQR6, 0x12); /* unlock all extension registers */
1835
1836 vga_wgfx (cinfo->regbase, CL_GR31, 0x04); /* reset blitter */
1837
1838 switch (cinfo->btype) {
1839 case BT_GD5480:
1840 vga_wseq (cinfo->regbase, CL_SEQRF, 0x98);
1841 break;
1842 case BT_ALPINE:
1843 break;
1844 case BT_SD64:
1845 vga_wseq (cinfo->regbase, CL_SEQRF, 0xb8);
1846 break;
1847 default:
1848 vga_wseq (cinfo->regbase, CL_SEQR16, 0x0f);
1849 vga_wseq (cinfo->regbase, CL_SEQRF, 0xb0);
1850 break;
1851 }
1852 }
1853 vga_wseq (cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: nothing */
1854 vga_wseq (cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00); /* character map select: doesn't even matter in gx mode */
1855 vga_wseq (cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0e); /* memory mode: chain-4, no odd/even, ext. memory */
1856
1857 /* controller-internal base address of video memory */
1858 if (bi->init_sr07)
1859 vga_wseq (cinfo->regbase, CL_SEQR7, bi->sr07);
1860
1861 /* vga_wseq (cinfo->regbase, CL_SEQR8, 0x00); *//* EEPROM control: shouldn't be necessary to write to this at all.. */
1862
1863 vga_wseq (cinfo->regbase, CL_SEQR10, 0x00); /* graphics cursor X position (incomplete; position gives rem. 3 bits */
1864 vga_wseq (cinfo->regbase, CL_SEQR11, 0x00); /* graphics cursor Y position (..."... ) */
1865 vga_wseq (cinfo->regbase, CL_SEQR12, 0x00); /* graphics cursor attributes */
1866 vga_wseq (cinfo->regbase, CL_SEQR13, 0x00); /* graphics cursor pattern address */
1867
1868 /* writing these on a P4 might give problems.. */
1869 if (cinfo->btype != BT_PICASSO4) {
1870 vga_wseq (cinfo->regbase, CL_SEQR17, 0x00); /* configuration readback and ext. color */
1871 vga_wseq (cinfo->regbase, CL_SEQR18, 0x02); /* signature generator */
1872 }
1873
1874 /* MCLK select etc. */
1875 if (bi->init_sr1f)
1876 vga_wseq (cinfo->regbase, CL_SEQR1F, bi->sr1f);
1877
1878 vga_wcrt (cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00); /* Screen A preset row scan: none */
1879 vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20); /* Text cursor start: disable text cursor */
1880 vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00); /* Text cursor end: - */
1881 vga_wcrt (cinfo->regbase, VGA_CRTC_START_HI, 0x00); /* Screen start address high: 0 */
1882 vga_wcrt (cinfo->regbase, VGA_CRTC_START_LO, 0x00); /* Screen start address low: 0 */
1883 vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00); /* text cursor location high: 0 */
1884 vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00); /* text cursor location low: 0 */
1885
1886 vga_wcrt (cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00); /* Underline Row scanline: - */
1887 vga_wcrt (cinfo->regbase, VGA_CRTC_MODE, 0xc3); /* mode control: timing enable, byte mode, no compat modes */
1888 vga_wcrt (cinfo->regbase, VGA_CRTC_LINE_COMPARE, 0x00); /* Line Compare: not needed */
1889 /* ### add 0x40 for text modes with > 30 MHz pixclock */
1890 vga_wcrt (cinfo->regbase, CL_CRT1B, 0x02); /* ext. display controls: ext.adr. wrap */
1891
1892 vga_wgfx (cinfo->regbase, VGA_GFX_SR_VALUE, 0x00); /* Set/Reset registes: - */
1893 vga_wgfx (cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00); /* Set/Reset enable: - */
1894 vga_wgfx (cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00); /* Color Compare: - */
1895 vga_wgfx (cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00); /* Data Rotate: - */
1896 vga_wgfx (cinfo->regbase, VGA_GFX_PLANE_READ, 0x00); /* Read Map Select: - */
1897 vga_wgfx (cinfo->regbase, VGA_GFX_MODE, 0x00); /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
1898 vga_wgfx (cinfo->regbase, VGA_GFX_MISC, 0x01); /* Miscellaneous: memory map base address, graphics mode */
1899 vga_wgfx (cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f); /* Color Don't care: involve all planes */
1900 vga_wgfx (cinfo->regbase, VGA_GFX_BIT_MASK, 0xff); /* Bit Mask: no mask at all */
1901 if (cinfo->btype == BT_ALPINE)
1902 vga_wgfx (cinfo->regbase, CL_GRB, 0x20); /* (5434 can't have bit 3 set for bitblt) */
1903 else
1904 vga_wgfx (cinfo->regbase, CL_GRB, 0x28); /* Graphics controller mode extensions: finer granularity, 8byte data latches */
1905
1906 vga_wgfx (cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */
1907 vga_wgfx (cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */
1908 vga_wgfx (cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */
1909 /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); *//* Background color byte 1: - */
1910/* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
1911
1912 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE0, 0x00); /* Attribute Controller palette registers: "identity mapping" */
1913 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
1914 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
1915 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
1916 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
1917 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
1918 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
1919 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
1920 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
1921 vga_wattr (cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
1922 vga_wattr (cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
1923 vga_wattr (cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
1924 vga_wattr (cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
1925 vga_wattr (cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
1926 vga_wattr (cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
1927 vga_wattr (cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
1928
1929 vga_wattr (cinfo->regbase, VGA_ATC_MODE, 0x01); /* Attribute Controller mode: graphics mode */
1930 vga_wattr (cinfo->regbase, VGA_ATC_OVERSCAN, 0x00); /* Overscan color reg.: reg. 0 */
1931 vga_wattr (cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f); /* Color Plane enable: Enable all 4 planes */
1932/* ### vga_wattr (cinfo->regbase, CL_AR33, 0x00); * Pixel Panning: - */
1933 vga_wattr (cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00); /* Color Select: - */
1934
1935 WGen (cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
1936
1937 if (cinfo->btype != BT_ALPINE && cinfo->btype != BT_GD5480)
1938 WGen (cinfo, VGA_MIS_W, 0xc3); /* polarity (-/-), enable display mem, VGA_CRTC_START_HI i/o base = color */
1939
1940 vga_wgfx (cinfo->regbase, CL_GR31, 0x04); /* BLT Start/status: Blitter reset */
1941 vga_wgfx (cinfo->regbase, CL_GR31, 0x00); /* - " - : "end-of-reset" */
1942
1943 /* misc... */
1944 WHDR (cinfo, 0); /* Hidden DAC register: - */
1945
1946 printk (KERN_DEBUG "cirrusfb: This board has %ld bytes of DRAM memory\n", cinfo->size);
1947 DPRINTK ("EXIT\n");
1948 return;
1949}
1950
1951static void switch_monitor (struct cirrusfb_info *cinfo, int on)
1952{
1953#ifdef CONFIG_ZORRO /* only works on Zorro boards */
1954 static int IsOn = 0; /* XXX not ok for multiple boards */
1955
1956 DPRINTK ("ENTER\n");
1957
1958 if (cinfo->btype == BT_PICASSO4)
1959 return; /* nothing to switch */
1960 if (cinfo->btype == BT_ALPINE)
1961 return; /* nothing to switch */
1962 if (cinfo->btype == BT_GD5480)
1963 return; /* nothing to switch */
1964 if (cinfo->btype == BT_PICASSO) {
1965 if ((on && !IsOn) || (!on && IsOn))
1966 WSFR (cinfo, 0xff);
1967
1968 DPRINTK ("EXIT\n");
1969 return;
1970 }
1971 if (on) {
1972 switch (cinfo->btype) {
1973 case BT_SD64:
1974 WSFR (cinfo, cinfo->SFR | 0x21);
1975 break;
1976 case BT_PICCOLO:
1977 WSFR (cinfo, cinfo->SFR | 0x28);
1978 break;
1979 case BT_SPECTRUM:
1980 WSFR (cinfo, 0x6f);
1981 break;
1982 default: /* do nothing */ break;
1983 }
1984 } else {
1985 switch (cinfo->btype) {
1986 case BT_SD64:
1987 WSFR (cinfo, cinfo->SFR & 0xde);
1988 break;
1989 case BT_PICCOLO:
1990 WSFR (cinfo, cinfo->SFR & 0xd7);
1991 break;
1992 case BT_SPECTRUM:
1993 WSFR (cinfo, 0x4f);
1994 break;
1995 default: /* do nothing */ break;
1996 }
1997 }
1998
1999 DPRINTK ("EXIT\n");
2000#endif /* CONFIG_ZORRO */
2001}
2002
2003
2004/******************************************/
2005/* Linux 2.6-style accelerated functions */
2006/******************************************/
2007
2008static void cirrusfb_prim_fillrect(struct cirrusfb_info *cinfo,
2009 const struct fb_fillrect *region)
2010{
2011 int m; /* bytes per pixel */
Antonino A. Daplas49d5c7b2005-11-29 19:34:43 -08002012 u32 color = (cinfo->info->fix.visual == FB_VISUAL_TRUECOLOR) ?
2013 cinfo->pseudo_palette[region->color] : region->color;
2014
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 if(cinfo->info->var.bits_per_pixel == 1) {
2016 cirrusfb_RectFill(cinfo->regbase, cinfo->info->var.bits_per_pixel,
2017 region->dx / 8, region->dy,
2018 region->width / 8, region->height,
Antonino A. Daplas49d5c7b2005-11-29 19:34:43 -08002019 color,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 cinfo->currentmode.line_length);
2021 } else {
2022 m = ( cinfo->info->var.bits_per_pixel + 7 ) / 8;
2023 cirrusfb_RectFill(cinfo->regbase, cinfo->info->var.bits_per_pixel,
2024 region->dx * m, region->dy,
2025 region->width * m, region->height,
Antonino A. Daplas49d5c7b2005-11-29 19:34:43 -08002026 color,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 cinfo->currentmode.line_length);
2028 }
2029 return;
2030}
2031
2032static void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *region)
2033{
2034 struct cirrusfb_info *cinfo = info->par;
2035 struct fb_fillrect modded;
2036 int vxres, vyres;
2037
2038 if (info->state != FBINFO_STATE_RUNNING)
2039 return;
2040 if (info->flags & FBINFO_HWACCEL_DISABLED) {
2041 cfb_fillrect(info, region);
2042 return;
2043 }
2044
2045 vxres = info->var.xres_virtual;
2046 vyres = info->var.yres_virtual;
2047
2048 memcpy(&modded, region, sizeof(struct fb_fillrect));
2049
2050 if(!modded.width || !modded.height ||
2051 modded.dx >= vxres || modded.dy >= vyres)
2052 return;
2053
2054 if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx;
2055 if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
2056
2057 cirrusfb_prim_fillrect(cinfo, &modded);
2058}
2059
2060static void cirrusfb_prim_copyarea(struct cirrusfb_info *cinfo,
2061 const struct fb_copyarea *area)
2062{
2063 int m; /* bytes per pixel */
2064 if(cinfo->info->var.bits_per_pixel == 1) {
2065 cirrusfb_BitBLT(cinfo->regbase, cinfo->info->var.bits_per_pixel,
2066 area->sx / 8, area->sy,
2067 area->dx / 8, area->dy,
2068 area->width / 8, area->height,
2069 cinfo->currentmode.line_length);
2070 } else {
2071 m = ( cinfo->info->var.bits_per_pixel + 7 ) / 8;
2072 cirrusfb_BitBLT(cinfo->regbase, cinfo->info->var.bits_per_pixel,
2073 area->sx * m, area->sy,
2074 area->dx * m, area->dy,
2075 area->width * m, area->height,
2076 cinfo->currentmode.line_length);
2077 }
2078 return;
2079}
2080
2081
2082static void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
2083{
2084 struct cirrusfb_info *cinfo = info->par;
2085 struct fb_copyarea modded;
2086 u32 vxres, vyres;
2087 modded.sx = area->sx;
2088 modded.sy = area->sy;
2089 modded.dx = area->dx;
2090 modded.dy = area->dy;
2091 modded.width = area->width;
2092 modded.height = area->height;
2093
2094 if (info->state != FBINFO_STATE_RUNNING)
2095 return;
2096 if (info->flags & FBINFO_HWACCEL_DISABLED) {
2097 cfb_copyarea(info, area);
2098 return;
2099 }
2100
2101 vxres = info->var.xres_virtual;
2102 vyres = info->var.yres_virtual;
2103
2104 if(!modded.width || !modded.height ||
2105 modded.sx >= vxres || modded.sy >= vyres ||
2106 modded.dx >= vxres || modded.dy >= vyres)
2107 return;
2108
2109 if(modded.sx + modded.width > vxres) modded.width = vxres - modded.sx;
2110 if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx;
2111 if(modded.sy + modded.height > vyres) modded.height = vyres - modded.sy;
2112 if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
2113
2114 cirrusfb_prim_copyarea(cinfo, &modded);
2115}
2116
2117static void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image)
2118{
2119 struct cirrusfb_info *cinfo = info->par;
2120
2121 cirrusfb_WaitBLT(cinfo->regbase);
2122 cfb_imageblit(info, image);
2123}
2124
2125
2126#ifdef CONFIG_PPC_PREP
2127#define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
2128#define PREP_IO_BASE ((volatile unsigned char *) 0x80000000)
2129static void get_prep_addrs (unsigned long *display, unsigned long *registers)
2130{
2131 DPRINTK ("ENTER\n");
2132
2133 *display = PREP_VIDEO_BASE;
2134 *registers = (unsigned long) PREP_IO_BASE;
2135
2136 DPRINTK ("EXIT\n");
2137}
2138
2139#endif /* CONFIG_PPC_PREP */
2140
2141
2142#ifdef CONFIG_PCI
2143static int release_io_ports = 0;
2144
2145/* Pulled the logic from XFree86 Cirrus driver to get the memory size,
2146 * based on the DRAM bandwidth bit and DRAM bank switching bit. This
2147 * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
2148 * seem to have. */
2149static unsigned int cirrusfb_get_memsize (u8 __iomem *regbase)
2150{
2151 unsigned long mem;
2152 unsigned char SRF;
2153
2154 DPRINTK ("ENTER\n");
2155
2156 SRF = vga_rseq (regbase, CL_SEQRF);
2157 switch ((SRF & 0x18)) {
2158 case 0x08: mem = 512 * 1024; break;
2159 case 0x10: mem = 1024 * 1024; break;
2160 /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory
2161 * on the 5430. */
2162 case 0x18: mem = 2048 * 1024; break;
2163 default: printk ("CLgenfb: Unknown memory size!\n");
2164 mem = 1024 * 1024;
2165 }
2166 if (SRF & 0x80) {
2167 /* If DRAM bank switching is enabled, there must be twice as much
2168 * memory installed. (4MB on the 5434) */
2169 mem *= 2;
2170 }
2171 /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
2172
2173 DPRINTK ("EXIT\n");
2174 return mem;
2175}
2176
2177
2178
2179static void get_pci_addrs (const struct pci_dev *pdev,
2180 unsigned long *display, unsigned long *registers)
2181{
2182 assert (pdev != NULL);
2183 assert (display != NULL);
2184 assert (registers != NULL);
2185
2186 DPRINTK ("ENTER\n");
2187
2188 *display = 0;
2189 *registers = 0;
2190
2191 /* This is a best-guess for now */
2192
2193 if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
2194 *display = pci_resource_start(pdev, 1);
2195 *registers = pci_resource_start(pdev, 0);
2196 } else {
2197 *display = pci_resource_start(pdev, 0);
2198 *registers = pci_resource_start(pdev, 1);
2199 }
2200
2201 assert (*display != 0);
2202
2203 DPRINTK ("EXIT\n");
2204}
2205
2206
2207static void cirrusfb_pci_unmap (struct cirrusfb_info *cinfo)
2208{
2209 struct pci_dev *pdev = cinfo->pdev;
2210
2211 iounmap(cinfo->fbmem);
2212#if 0 /* if system didn't claim this region, we would... */
2213 release_mem_region(0xA0000, 65535);
2214#endif
2215 if (release_io_ports)
2216 release_region(0x3C0, 32);
2217 pci_release_regions(pdev);
2218 framebuffer_release(cinfo->info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219}
2220#endif /* CONFIG_PCI */
2221
2222
2223#ifdef CONFIG_ZORRO
2224static void __devexit cirrusfb_zorro_unmap (struct cirrusfb_info *cinfo)
2225{
2226 zorro_release_device(cinfo->zdev);
2227
2228 if (cinfo->btype == BT_PICASSO4) {
2229 cinfo->regbase -= 0x600000;
2230 iounmap ((void *)cinfo->regbase);
2231 iounmap ((void *)cinfo->fbmem);
2232 } else {
2233 if (zorro_resource_start(cinfo->zdev) > 0x01000000)
2234 iounmap ((void *)cinfo->fbmem);
2235 }
2236 framebuffer_release(cinfo->info);
2237}
2238#endif /* CONFIG_ZORRO */
2239
2240static int cirrusfb_set_fbinfo(struct cirrusfb_info *cinfo)
2241{
2242 struct fb_info *info = cinfo->info;
2243 struct fb_var_screeninfo *var = &info->var;
2244
2245 info->par = cinfo;
2246 info->pseudo_palette = cinfo->pseudo_palette;
2247 info->flags = FBINFO_DEFAULT
2248 | FBINFO_HWACCEL_XPAN
2249 | FBINFO_HWACCEL_YPAN
2250 | FBINFO_HWACCEL_FILLRECT
2251 | FBINFO_HWACCEL_COPYAREA;
2252 if (noaccel)
2253 info->flags |= FBINFO_HWACCEL_DISABLED;
2254 info->fbops = &cirrusfb_ops;
2255 info->screen_base = cinfo->fbmem;
2256 if (cinfo->btype == BT_GD5480) {
2257 if (var->bits_per_pixel == 16)
2258 info->screen_base += 1 * MB_;
2259 if (var->bits_per_pixel == 24 || var->bits_per_pixel == 32)
2260 info->screen_base += 2 * MB_;
2261 }
2262
2263 /* Fill fix common fields */
2264 strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
2265 sizeof(info->fix.id));
2266
2267 /* monochrome: only 1 memory plane */
2268 /* 8 bit and above: Use whole memory area */
2269 info->fix.smem_start = cinfo->fbmem_phys;
2270 info->fix.smem_len = (var->bits_per_pixel == 1) ? cinfo->size / 4 : cinfo->size;
2271 info->fix.type = cinfo->currentmode.type;
2272 info->fix.type_aux = 0;
2273 info->fix.visual = cinfo->currentmode.visual;
2274 info->fix.xpanstep = 1;
2275 info->fix.ypanstep = 1;
2276 info->fix.ywrapstep = 0;
2277 info->fix.line_length = cinfo->currentmode.line_length;
2278
2279 /* FIXME: map region at 0xB8000 if available, fill in here */
2280 info->fix.mmio_start = cinfo->fbregs_phys;
2281 info->fix.mmio_len = 0;
2282 info->fix.accel = FB_ACCEL_NONE;
2283
2284 fb_alloc_cmap(&info->cmap, 256, 0);
2285
2286 return 0;
2287}
2288
2289static int cirrusfb_register(struct cirrusfb_info *cinfo)
2290{
2291 struct fb_info *info;
2292 int err;
2293 cirrusfb_board_t btype;
2294
2295 DPRINTK ("ENTER\n");
2296
2297 printk (KERN_INFO "cirrusfb: Driver for Cirrus Logic based graphic boards, v" CIRRUSFB_VERSION "\n");
2298
2299 info = cinfo->info;
2300 btype = cinfo->btype;
2301
2302 /* sanity checks */
2303 assert (btype != BT_NONE);
2304
2305 DPRINTK ("cirrusfb: (RAM start set to: 0x%p)\n", cinfo->fbmem);
2306
2307 /* Make pretend we've set the var so our structures are in a "good" */
2308 /* state, even though we haven't written the mode to the hw yet... */
2309 info->var = cirrusfb_predefined[cirrusfb_def_mode].var;
2310 info->var.activate = FB_ACTIVATE_NOW;
2311
2312 err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
2313 if (err < 0) {
2314 /* should never happen */
2315 DPRINTK("choking on default var... umm, no good.\n");
2316 goto err_unmap_cirrusfb;
2317 }
2318
2319 /* set all the vital stuff */
2320 cirrusfb_set_fbinfo(cinfo);
2321
2322 err = register_framebuffer(info);
2323 if (err < 0) {
2324 printk (KERN_ERR "cirrusfb: could not register fb device; err = %d!\n", err);
2325 goto err_dealloc_cmap;
2326 }
2327
2328 DPRINTK ("EXIT, returning 0\n");
2329 return 0;
2330
2331err_dealloc_cmap:
2332 fb_dealloc_cmap(&info->cmap);
2333err_unmap_cirrusfb:
2334 cinfo->unmap(cinfo);
2335 return err;
2336}
2337
2338static void __devexit cirrusfb_cleanup (struct fb_info *info)
2339{
2340 struct cirrusfb_info *cinfo = info->par;
2341 DPRINTK ("ENTER\n");
2342
2343 switch_monitor (cinfo, 0);
2344
2345 unregister_framebuffer (info);
2346 fb_dealloc_cmap (&info->cmap);
2347 printk ("Framebuffer unregistered\n");
2348 cinfo->unmap(cinfo);
2349
2350 DPRINTK ("EXIT\n");
2351}
2352
2353
2354#ifdef CONFIG_PCI
2355static int cirrusfb_pci_register (struct pci_dev *pdev,
2356 const struct pci_device_id *ent)
2357{
2358 struct cirrusfb_info *cinfo;
2359 struct fb_info *info;
2360 cirrusfb_board_t btype;
2361 unsigned long board_addr, board_size;
2362 int ret;
2363
2364 ret = pci_enable_device(pdev);
2365 if (ret < 0) {
2366 printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
2367 goto err_out;
2368 }
2369
2370 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev);
2371 if (!info) {
2372 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2373 ret = -ENOMEM;
2374 goto err_disable;
2375 }
2376
2377 cinfo = info->par;
2378 cinfo->info = info;
2379 cinfo->pdev = pdev;
2380 cinfo->btype = btype = (cirrusfb_board_t) ent->driver_data;
2381
2382 DPRINTK (" Found PCI device, base address 0 is 0x%lx, btype set to %d\n",
2383 pdev->resource[0].start, btype);
2384 DPRINTK (" base address 1 is 0x%lx\n", pdev->resource[1].start);
2385
2386 if(isPReP) {
2387 pci_write_config_dword (pdev, PCI_BASE_ADDRESS_0, 0x00000000);
2388#ifdef CONFIG_PPC_PREP
2389 get_prep_addrs (&board_addr, &cinfo->fbregs_phys);
2390#endif
2391 /* PReP dies if we ioremap the IO registers, but it works w/out... */
2392 cinfo->regbase = (char __iomem *) cinfo->fbregs_phys;
2393 } else {
2394 DPRINTK ("Attempt to get PCI info for Cirrus Graphics Card\n");
2395 get_pci_addrs (pdev, &board_addr, &cinfo->fbregs_phys);
2396 cinfo->regbase = NULL; /* FIXME: this forces VGA. alternatives? */
2397 }
2398
2399 DPRINTK ("Board address: 0x%lx, register address: 0x%lx\n", board_addr, cinfo->fbregs_phys);
2400
2401 board_size = (btype == BT_GD5480) ?
2402 32 * MB_ : cirrusfb_get_memsize (cinfo->regbase);
2403
2404 ret = pci_request_regions(pdev, "cirrusfb");
2405 if (ret <0) {
2406 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n",
2407 board_addr);
2408 goto err_release_fb;
2409 }
2410#if 0 /* if the system didn't claim this region, we would... */
2411 if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
2412 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n"
2413,
2414 0xA0000L);
2415 ret = -EBUSY;
2416 goto err_release_regions;
2417 }
2418#endif
2419 if (request_region(0x3C0, 32, "cirrusfb"))
2420 release_io_ports = 1;
2421
2422 cinfo->fbmem = ioremap(board_addr, board_size);
2423 if (!cinfo->fbmem) {
2424 ret = -EIO;
2425 goto err_release_legacy;
2426 }
2427
2428 cinfo->fbmem_phys = board_addr;
2429 cinfo->size = board_size;
2430 cinfo->unmap = cirrusfb_pci_unmap;
2431
2432 printk (" RAM (%lu kB) at 0xx%lx, ", cinfo->size / KB_, board_addr);
2433 printk ("Cirrus Logic chipset on PCI bus\n");
2434 pci_set_drvdata(pdev, info);
2435
Amol Ladd8b8c0a2006-12-08 02:40:13 -08002436 ret = cirrusfb_register(cinfo);
2437 if (ret)
2438 iounmap(cinfo->fbmem);
2439 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440
2441err_release_legacy:
2442 if (release_io_ports)
2443 release_region(0x3C0, 32);
2444#if 0
2445 release_mem_region(0xA0000, 65535);
2446err_release_regions:
2447#endif
2448 pci_release_regions(pdev);
2449err_release_fb:
2450 framebuffer_release(info);
2451err_disable:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452err_out:
2453 return ret;
2454}
2455
2456static void __devexit cirrusfb_pci_unregister (struct pci_dev *pdev)
2457{
2458 struct fb_info *info = pci_get_drvdata(pdev);
2459 DPRINTK ("ENTER\n");
2460
2461 cirrusfb_cleanup (info);
2462
2463 DPRINTK ("EXIT\n");
2464}
2465
2466static struct pci_driver cirrusfb_pci_driver = {
2467 .name = "cirrusfb",
2468 .id_table = cirrusfb_pci_table,
2469 .probe = cirrusfb_pci_register,
2470 .remove = __devexit_p(cirrusfb_pci_unregister),
2471#ifdef CONFIG_PM
2472#if 0
2473 .suspend = cirrusfb_pci_suspend,
2474 .resume = cirrusfb_pci_resume,
2475#endif
2476#endif
2477};
2478#endif /* CONFIG_PCI */
2479
2480
2481#ifdef CONFIG_ZORRO
2482static int cirrusfb_zorro_register(struct zorro_dev *z,
2483 const struct zorro_device_id *ent)
2484{
2485 struct cirrusfb_info *cinfo;
2486 struct fb_info *info;
2487 cirrusfb_board_t btype;
2488 struct zorro_dev *z2 = NULL;
2489 unsigned long board_addr, board_size, size;
2490 int ret;
2491
2492 btype = ent->driver_data;
2493 if (cirrusfb_zorro_table2[btype].id2)
2494 z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
2495 size = cirrusfb_zorro_table2[btype].size;
2496 printk(KERN_INFO "cirrusfb: %s board detected; ",
2497 cirrusfb_board_info[btype].name);
2498
2499 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
2500 if (!info) {
2501 printk (KERN_ERR "cirrusfb: could not allocate memory\n");
2502 ret = -ENOMEM;
2503 goto err_out;
2504 }
2505
2506 cinfo = info->par;
2507 cinfo->info = info;
2508 cinfo->btype = btype;
2509
2510 assert (z > 0);
2511 assert (z2 >= 0);
2512 assert (btype != BT_NONE);
2513
2514 cinfo->zdev = z;
2515 board_addr = zorro_resource_start(z);
2516 board_size = zorro_resource_len(z);
2517 cinfo->size = size;
2518
2519 if (!zorro_request_device(z, "cirrusfb")) {
2520 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n",
2521 board_addr);
2522 ret = -EBUSY;
2523 goto err_release_fb;
2524 }
2525
2526 printk (" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr);
2527
2528 ret = -EIO;
2529
2530 if (btype == BT_PICASSO4) {
2531 printk (" REG at $%lx\n", board_addr + 0x600000);
2532
2533 /* To be precise, for the P4 this is not the */
2534 /* begin of the board, but the begin of RAM. */
2535 /* for P4, map in its address space in 2 chunks (### TEST! ) */
2536 /* (note the ugly hardcoded 16M number) */
2537 cinfo->regbase = ioremap (board_addr, 16777216);
2538 if (!cinfo->regbase)
2539 goto err_release_region;
2540
2541 DPRINTK ("cirrusfb: Virtual address for board set to: $%p\n", cinfo->regbase);
2542 cinfo->regbase += 0x600000;
2543 cinfo->fbregs_phys = board_addr + 0x600000;
2544
2545 cinfo->fbmem_phys = board_addr + 16777216;
2546 cinfo->fbmem = ioremap (cinfo->fbmem_phys, 16777216);
2547 if (!cinfo->fbmem)
2548 goto err_unmap_regbase;
2549 } else {
2550 printk (" REG at $%lx\n", (unsigned long) z2->resource.start);
2551
2552 cinfo->fbmem_phys = board_addr;
2553 if (board_addr > 0x01000000)
2554 cinfo->fbmem = ioremap (board_addr, board_size);
2555 else
2556 cinfo->fbmem = (caddr_t) ZTWO_VADDR (board_addr);
2557 if (!cinfo->fbmem)
2558 goto err_release_region;
2559
2560 /* set address for REG area of board */
2561 cinfo->regbase = (caddr_t) ZTWO_VADDR (z2->resource.start);
2562 cinfo->fbregs_phys = z2->resource.start;
2563
2564 DPRINTK ("cirrusfb: Virtual address for board set to: $%p\n", cinfo->regbase);
2565 }
2566 cinfo->unmap = cirrusfb_zorro_unmap;
2567
2568 printk (KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
2569 zorro_set_drvdata(z, info);
2570
Amol Ladd8b8c0a2006-12-08 02:40:13 -08002571 ret = cirrusfb_register(cinfo);
2572 if (ret) {
2573 if (btype == BT_PICASSO4) {
2574 iounmap(cinfo->fbmem);
2575 iounmap(cinfo->regbase - 0x600000);
2576 } else if (board_addr > 0x01000000)
2577 iounmap(cinfo->fbmem);
2578 }
2579 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580
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 */
Richard Knutssonc930faa2007-05-08 00:38:29 -07003197 assert(false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003198 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