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