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