1/*
2 * Permedia2 framebuffer driver.
3 *
4 * 2.5/2.6 driver:
5 * Copyright (c) 2003 Jim Hague (jim.hague@acm.org)
6 *
7 * based on 2.4 driver:
8 * Copyright (c) 1998-2000 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
9 * Copyright (c) 1999 Jakub Jelinek (jakub@redhat.com)
10 *
11 * and additional input from James Simmon's port of Hannu Mallat's tdfx
12 * driver.
13 *
14 * I have a Creative Graphics Blaster Exxtreme card - pm2fb on x86.  I
15 * have no access to other pm2fb implementations. Sparc (and thus
16 * hopefully other big-endian) devices now work, thanks to a lot of
17 * testing work by Ron Murray. I have no access to CVision hardware,
18 * and therefore for now I am omitting the CVision code.
19 *
20 * Multiple boards support has been on the TODO list for ages.
21 * Don't expect this to change.
22 *
23 * This file is subject to the terms and conditions of the GNU General Public
24 * License. See the file COPYING in the main directory of this archive for
25 * more details.
26 *
27 *
28 */
29
30#include <linux/module.h>
31#include <linux/moduleparam.h>
32#include <linux/kernel.h>
33#include <linux/errno.h>
34#include <linux/string.h>
35#include <linux/mm.h>
36#include <linux/slab.h>
37#include <linux/delay.h>
38#include <linux/fb.h>
39#include <linux/init.h>
40#include <linux/pci.h>
41
42#include <video/permedia2.h>
43#include <video/cvisionppc.h>
44
45#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
46#error	"The endianness of the target host has not been defined."
47#endif
48
49#if !defined(CONFIG_PCI)
50#error "Only generic PCI cards supported."
51#endif
52
53#undef PM2FB_MASTER_DEBUG
54#ifdef PM2FB_MASTER_DEBUG
55#define DPRINTK(a,b...)	printk(KERN_DEBUG "pm2fb: %s: " a, __FUNCTION__ , ## b)
56#else
57#define DPRINTK(a,b...)
58#endif
59
60/*
61 * Driver data
62 */
63static char *mode __devinitdata = NULL;
64
65/*
66 * The XFree GLINT driver will (I think to implement hardware cursor
67 * support on TVP4010 and similar where there is no RAMDAC - see
68 * comment in set_video) always request +ve sync regardless of what
69 * the mode requires. This screws me because I have a Sun
70 * fixed-frequency monitor which absolutely has to have -ve sync. So
71 * these flags allow the user to specify that requests for +ve sync
72 * should be silently turned in -ve sync.
73 */
74static int lowhsync;
75static int lowvsync;
76
77/*
78 * The hardware state of the graphics card that isn't part of the
79 * screeninfo.
80 */
81struct pm2fb_par
82{
83	pm2type_t	type;		/* Board type */
84	unsigned char	__iomem *v_regs;/* virtual address of p_regs */
85	u32 	   	memclock;	/* memclock */
86	u32		video;		/* video flags before blanking */
87	u32		mem_config;	/* MemConfig reg at probe */
88	u32		mem_control;	/* MemControl reg at probe */
89	u32		boot_address;	/* BootAddress reg at probe */
90	u32             palette[16];
91};
92
93/*
94 * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo
95 * if we don't use modedb.
96 */
97static struct fb_fix_screeninfo pm2fb_fix __devinitdata = {
98	.id =		"",
99	.type =		FB_TYPE_PACKED_PIXELS,
100	.visual =	FB_VISUAL_PSEUDOCOLOR,
101	.xpanstep =	1,
102	.ypanstep =	1,
103	.ywrapstep =	0,
104	.accel =	FB_ACCEL_3DLABS_PERMEDIA2,
105};
106
107/*
108 * Default video mode. In case the modedb doesn't work.
109 */
110static struct fb_var_screeninfo pm2fb_var __devinitdata = {
111	/* "640x480, 8 bpp @ 60 Hz */
112	.xres =		640,
113	.yres =		480,
114	.xres_virtual =	640,
115	.yres_virtual =	480,
116	.bits_per_pixel =8,
117	.red =		{0, 8, 0},
118	.blue =		{0, 8, 0},
119	.green =	{0, 8, 0},
120	.activate =	FB_ACTIVATE_NOW,
121	.height =	-1,
122	.width =	-1,
123	.accel_flags =	0,
124	.pixclock =	39721,
125	.left_margin =	40,
126	.right_margin =	24,
127	.upper_margin =	32,
128	.lower_margin =	11,
129	.hsync_len =	96,
130	.vsync_len =	2,
131	.vmode =	FB_VMODE_NONINTERLACED
132};
133
134/*
135 * Utility functions
136 */
137
138static inline u32 RD32(unsigned char __iomem *base, s32 off)
139{
140	return fb_readl(base + off);
141}
142
143static inline void WR32(unsigned char __iomem *base, s32 off, u32 v)
144{
145	fb_writel(v, base + off);
146}
147
148static inline u32 pm2_RD(struct pm2fb_par* p, s32 off)
149{
150	return RD32(p->v_regs, off);
151}
152
153static inline void pm2_WR(struct pm2fb_par* p, s32 off, u32 v)
154{
155	WR32(p->v_regs, off, v);
156}
157
158static inline u32 pm2_RDAC_RD(struct pm2fb_par* p, s32 idx)
159{
160	int index = PM2R_RD_INDEXED_DATA;
161	switch (p->type) {
162	case PM2_TYPE_PERMEDIA2:
163		pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
164		break;
165	case PM2_TYPE_PERMEDIA2V:
166		pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
167		index = PM2VR_RD_INDEXED_DATA;
168		break;
169	}
170	mb();
171	return pm2_RD(p, index);
172}
173
174static inline void pm2_RDAC_WR(struct pm2fb_par* p, s32 idx, u32 v)
175{
176	int index = PM2R_RD_INDEXED_DATA;
177	switch (p->type) {
178	case PM2_TYPE_PERMEDIA2:
179		pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
180		break;
181	case PM2_TYPE_PERMEDIA2V:
182		pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
183		index = PM2VR_RD_INDEXED_DATA;
184		break;
185	}
186	wmb();
187	pm2_WR(p, index, v);
188	wmb();
189}
190
191static inline void pm2v_RDAC_WR(struct pm2fb_par* p, s32 idx, u32 v)
192{
193	pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
194	wmb();
195	pm2_WR(p, PM2VR_RD_INDEXED_DATA, v);
196	wmb();
197}
198
199#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
200#define WAIT_FIFO(p,a)
201#else
202static inline void WAIT_FIFO(struct pm2fb_par* p, u32 a)
203{
204	while( pm2_RD(p, PM2R_IN_FIFO_SPACE) < a );
205	mb();
206}
207#endif
208
209/*
210 * partial products for the supported horizontal resolutions.
211 */
212#define PACKPP(p0,p1,p2)	(((p2) << 6) | ((p1) << 3) | (p0))
213static const struct {
214	u16 width;
215	u16 pp;
216} pp_table[] = {
217	{ 32,	PACKPP(1, 0, 0) }, { 64,	PACKPP(1, 1, 0) },
218	{ 96,	PACKPP(1, 1, 1) }, { 128,	PACKPP(2, 1, 1) },
219	{ 160,	PACKPP(2, 2, 1) }, { 192,	PACKPP(2, 2, 2) },
220	{ 224,	PACKPP(3, 2, 1) }, { 256,	PACKPP(3, 2, 2) },
221	{ 288,	PACKPP(3, 3, 1) }, { 320,	PACKPP(3, 3, 2) },
222	{ 384,	PACKPP(3, 3, 3) }, { 416,	PACKPP(4, 3, 1) },
223	{ 448,	PACKPP(4, 3, 2) }, { 512,	PACKPP(4, 3, 3) },
224	{ 544,	PACKPP(4, 4, 1) }, { 576,	PACKPP(4, 4, 2) },
225	{ 640,	PACKPP(4, 4, 3) }, { 768,	PACKPP(4, 4, 4) },
226	{ 800,	PACKPP(5, 4, 1) }, { 832,	PACKPP(5, 4, 2) },
227	{ 896,	PACKPP(5, 4, 3) }, { 1024,	PACKPP(5, 4, 4) },
228	{ 1056,	PACKPP(5, 5, 1) }, { 1088,	PACKPP(5, 5, 2) },
229	{ 1152,	PACKPP(5, 5, 3) }, { 1280,	PACKPP(5, 5, 4) },
230	{ 1536,	PACKPP(5, 5, 5) }, { 1568,	PACKPP(6, 5, 1) },
231	{ 1600,	PACKPP(6, 5, 2) }, { 1664,	PACKPP(6, 5, 3) },
232	{ 1792,	PACKPP(6, 5, 4) }, { 2048,	PACKPP(6, 5, 5) },
233	{ 0,	0 } };
234
235static u32 partprod(u32 xres)
236{
237	int i;
238
239	for (i = 0; pp_table[i].width && pp_table[i].width != xres; i++)
240		;
241	if ( pp_table[i].width == 0 )
242		DPRINTK("invalid width %u\n", xres);
243	return pp_table[i].pp;
244}
245
246static u32 to3264(u32 timing, int bpp, int is64)
247{
248	switch (bpp) {
249	case 8:
250		timing >>= 2 + is64;
251		break;
252	case 16:
253		timing >>= 1 + is64;
254		break;
255	case 24:
256		timing = (timing * 3) >> (2 + is64);
257		break;
258	case 32:
259		if (is64)
260			timing >>= 1;
261		break;
262	}
263	return timing;
264}
265
266static void pm2_mnp(u32 clk, unsigned char* mm, unsigned char* nn,
267		    unsigned char* pp)
268{
269	unsigned char m;
270	unsigned char n;
271	unsigned char p;
272	u32 f;
273	s32 curr;
274	s32 delta = 100000;
275
276	*mm = *nn = *pp = 0;
277	for (n = 2; n < 15; n++) {
278		for (m = 2; m; m++) {
279			f = PM2_REFERENCE_CLOCK * m / n;
280			if (f >= 150000 && f <= 300000) {
281				for ( p = 0; p < 5; p++, f >>= 1) {
282					curr = ( clk > f ) ? clk - f : f - clk;
283					if ( curr < delta ) {
284						delta=curr;
285						*mm=m;
286						*nn=n;
287						*pp=p;
288					}
289				}
290			}
291		}
292	}
293}
294
295static void pm2v_mnp(u32 clk, unsigned char* mm, unsigned char* nn,
296		     unsigned char* pp)
297{
298	unsigned char m;
299	unsigned char n;
300	unsigned char p;
301	u32 f;
302	s32 delta = 1000;
303
304	*mm = *nn = *pp = 0;
305	for ( m = 1; m < 128; m++) {
306		for (n = 2 * m + 1; n; n++) {
307			for ( p = 0; p < 2; p++) {
308				f = ( PM2_REFERENCE_CLOCK >> ( p + 1 )) * n / m;
309				if ( clk > f - delta && clk < f + delta ) {
310					delta = ( clk > f ) ? clk - f : f - clk;
311					*mm=m;
312					*nn=n;
313					*pp=p;
314				}
315			}
316		}
317	}
318}
319
320static void clear_palette(struct pm2fb_par* p) {
321	int i=256;
322
323	WAIT_FIFO(p, 1);
324	pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, 0);
325	wmb();
326	while (i--) {
327		WAIT_FIFO(p, 3);
328		pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
329		pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
330		pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
331	}
332}
333
334static void reset_card(struct pm2fb_par* p)
335{
336	if (p->type == PM2_TYPE_PERMEDIA2V)
337		pm2_WR(p, PM2VR_RD_INDEX_HIGH, 0);
338	pm2_WR(p, PM2R_RESET_STATUS, 0);
339	mb();
340	while (pm2_RD(p, PM2R_RESET_STATUS) & PM2F_BEING_RESET)
341		;
342	mb();
343#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
344	DPRINTK("FIFO disconnect enabled\n");
345	pm2_WR(p, PM2R_FIFO_DISCON, 1);
346	mb();
347#endif
348
349	/* Restore stashed memory config information from probe */
350	WAIT_FIFO(p, 3);
351	pm2_WR(p, PM2R_MEM_CONTROL, p->mem_control);
352	pm2_WR(p, PM2R_BOOT_ADDRESS, p->boot_address);
353	wmb();
354	pm2_WR(p, PM2R_MEM_CONFIG, p->mem_config);
355}
356
357static void reset_config(struct pm2fb_par* p)
358{
359	WAIT_FIFO(p, 52);
360	pm2_WR(p, PM2R_CHIP_CONFIG, pm2_RD(p, PM2R_CHIP_CONFIG)&
361	       ~(PM2F_VGA_ENABLE|PM2F_VGA_FIXED));
362	pm2_WR(p, PM2R_BYPASS_WRITE_MASK, ~(0L));
363	pm2_WR(p, PM2R_FRAMEBUFFER_WRITE_MASK, ~(0L));
364	pm2_WR(p, PM2R_FIFO_CONTROL, 0);
365	pm2_WR(p, PM2R_APERTURE_ONE, 0);
366	pm2_WR(p, PM2R_APERTURE_TWO, 0);
367	pm2_WR(p, PM2R_RASTERIZER_MODE, 0);
368	pm2_WR(p, PM2R_DELTA_MODE, PM2F_DELTA_ORDER_RGB);
369	pm2_WR(p, PM2R_LB_READ_FORMAT, 0);
370	pm2_WR(p, PM2R_LB_WRITE_FORMAT, 0);
371	pm2_WR(p, PM2R_LB_READ_MODE, 0);
372	pm2_WR(p, PM2R_LB_SOURCE_OFFSET, 0);
373	pm2_WR(p, PM2R_FB_SOURCE_OFFSET, 0);
374	pm2_WR(p, PM2R_FB_PIXEL_OFFSET, 0);
375	pm2_WR(p, PM2R_FB_WINDOW_BASE, 0);
376	pm2_WR(p, PM2R_LB_WINDOW_BASE, 0);
377	pm2_WR(p, PM2R_FB_SOFT_WRITE_MASK, ~(0L));
378	pm2_WR(p, PM2R_FB_HARD_WRITE_MASK, ~(0L));
379	pm2_WR(p, PM2R_FB_READ_PIXEL, 0);
380	pm2_WR(p, PM2R_DITHER_MODE, 0);
381	pm2_WR(p, PM2R_AREA_STIPPLE_MODE, 0);
382	pm2_WR(p, PM2R_DEPTH_MODE, 0);
383	pm2_WR(p, PM2R_STENCIL_MODE, 0);
384	pm2_WR(p, PM2R_TEXTURE_ADDRESS_MODE, 0);
385	pm2_WR(p, PM2R_TEXTURE_READ_MODE, 0);
386	pm2_WR(p, PM2R_TEXEL_LUT_MODE, 0);
387	pm2_WR(p, PM2R_YUV_MODE, 0);
388	pm2_WR(p, PM2R_COLOR_DDA_MODE, 0);
389	pm2_WR(p, PM2R_TEXTURE_COLOR_MODE, 0);
390	pm2_WR(p, PM2R_FOG_MODE, 0);
391	pm2_WR(p, PM2R_ALPHA_BLEND_MODE, 0);
392	pm2_WR(p, PM2R_LOGICAL_OP_MODE, 0);
393	pm2_WR(p, PM2R_STATISTICS_MODE, 0);
394	pm2_WR(p, PM2R_SCISSOR_MODE, 0);
395	pm2_WR(p, PM2R_FILTER_MODE, PM2F_SYNCHRONIZATION);
396	switch (p->type) {
397	case PM2_TYPE_PERMEDIA2:
398		pm2_RDAC_WR(p, PM2I_RD_MODE_CONTROL, 0); /* no overlay */
399		pm2_RDAC_WR(p, PM2I_RD_CURSOR_CONTROL, 0);
400		pm2_RDAC_WR(p, PM2I_RD_MISC_CONTROL, PM2F_RD_PALETTE_WIDTH_8);
401		break;
402	case PM2_TYPE_PERMEDIA2V:
403		pm2v_RDAC_WR(p, PM2VI_RD_MISC_CONTROL, 1); /* 8bit */
404		break;
405	}
406	pm2_RDAC_WR(p, PM2I_RD_COLOR_KEY_CONTROL, 0);
407	pm2_RDAC_WR(p, PM2I_RD_OVERLAY_KEY, 0);
408	pm2_RDAC_WR(p, PM2I_RD_RED_KEY, 0);
409	pm2_RDAC_WR(p, PM2I_RD_GREEN_KEY, 0);
410	pm2_RDAC_WR(p, PM2I_RD_BLUE_KEY, 0);
411}
412
413static void set_aperture(struct pm2fb_par* p, u32 depth)
414{
415	/*
416	 * The hardware is little-endian. When used in big-endian
417	 * hosts, the on-chip aperture settings are used where
418	 * possible to translate from host to card byte order.
419	 */
420	WAIT_FIFO(p, 4);
421#ifdef __LITTLE_ENDIAN
422	pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_STANDARD);
423#else
424	switch (depth) {
425	case 24:	/* RGB->BGR */
426		/*
427		 * We can't use the aperture to translate host to
428		 * card byte order here, so we switch to BGR mode
429		 * in pm2fb_set_par().
430		 */
431	case 8:		/* B->B */
432		pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_STANDARD);
433		break;
434	case 16:	/* HL->LH */
435		pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_HALFWORDSWAP);
436		break;
437	case 32:	/* RGBA->ABGR */
438		pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_BYTESWAP);
439		break;
440	}
441#endif
442
443	// We don't use aperture two, so this may be superflous
444	pm2_WR(p, PM2R_APERTURE_TWO, PM2F_APERTURE_STANDARD);
445}
446
447static void set_color(struct pm2fb_par* p, unsigned char regno,
448		      unsigned char r, unsigned char g, unsigned char b)
449{
450	WAIT_FIFO(p, 4);
451	pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, regno);
452	wmb();
453	pm2_WR(p, PM2R_RD_PALETTE_DATA, r);
454	wmb();
455	pm2_WR(p, PM2R_RD_PALETTE_DATA, g);
456	wmb();
457	pm2_WR(p, PM2R_RD_PALETTE_DATA, b);
458}
459
460static void set_memclock(struct pm2fb_par* par, u32 clk)
461{
462	int i;
463	unsigned char m, n, p;
464
465	switch (par->type) {
466	case PM2_TYPE_PERMEDIA2V:
467		pm2v_mnp(clk/2, &m, &n, &p);
468		WAIT_FIFO(par, 8);
469		pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_MCLK_CONTROL >> 8);
470		pm2v_RDAC_WR(par, PM2VI_RD_MCLK_CONTROL, 0);
471		pm2v_RDAC_WR(par, PM2VI_RD_MCLK_PRESCALE, m);
472		pm2v_RDAC_WR(par, PM2VI_RD_MCLK_FEEDBACK, n);
473		pm2v_RDAC_WR(par, PM2VI_RD_MCLK_POSTSCALE, p);
474		pm2v_RDAC_WR(par, PM2VI_RD_MCLK_CONTROL, 1);
475		rmb();
476		for (i = 256;
477		     i && !(pm2_RDAC_RD(par, PM2VI_RD_MCLK_CONTROL) & 2);
478		     i--)
479			;
480		pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
481		break;
482	case PM2_TYPE_PERMEDIA2:
483		pm2_mnp(clk, &m, &n, &p);
484		WAIT_FIFO(par, 10);
485		pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 6);
486		pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_1, m);
487		pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_2, n);
488		pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 8|p);
489		pm2_RDAC_RD(par, PM2I_RD_MEMORY_CLOCK_STATUS);
490		rmb();
491		for (i = 256;
492		     i && !(pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED);
493		     i--)
494			;
495		break;
496	}
497}
498
499static void set_pixclock(struct pm2fb_par* par, u32 clk)
500{
501	int i;
502	unsigned char m, n, p;
503
504	switch (par->type) {
505	case PM2_TYPE_PERMEDIA2:
506		pm2_mnp(clk, &m, &n, &p);
507		WAIT_FIFO(par, 8);
508		pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A3, 0);
509		pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A1, m);
510		pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A2, n);
511		pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A3, 8|p);
512		pm2_RDAC_RD(par, PM2I_RD_PIXEL_CLOCK_STATUS);
513		rmb();
514		for (i = 256;
515		     i && !(pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED);
516		     i--)
517			;
518		break;
519	case PM2_TYPE_PERMEDIA2V:
520		pm2v_mnp(clk/2, &m, &n, &p);
521		WAIT_FIFO(par, 8);
522		pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CLK0_PRESCALE >> 8);
523		pm2v_RDAC_WR(par, PM2VI_RD_CLK0_PRESCALE, m);
524		pm2v_RDAC_WR(par, PM2VI_RD_CLK0_FEEDBACK, n);
525		pm2v_RDAC_WR(par, PM2VI_RD_CLK0_POSTSCALE, p);
526		pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
527		break;
528	}
529}
530
531static void set_video(struct pm2fb_par* p, u32 video) {
532	u32 tmp;
533	u32 vsync;
534
535	vsync = video;
536
537	DPRINTK("video = 0x%x\n", video);
538
539	/*
540	 * The hardware cursor needs +vsync to recognise vert retrace.
541	 * We may not be using the hardware cursor, but the X Glint
542	 * driver may well. So always set +hsync/+vsync and then set
543	 * the RAMDAC to invert the sync if necessary.
544	 */
545	vsync &= ~(PM2F_HSYNC_MASK|PM2F_VSYNC_MASK);
546	vsync |= PM2F_HSYNC_ACT_HIGH|PM2F_VSYNC_ACT_HIGH;
547
548	WAIT_FIFO(p, 5);
549	pm2_WR(p, PM2R_VIDEO_CONTROL, vsync);
550
551	switch (p->type) {
552	case PM2_TYPE_PERMEDIA2:
553		tmp = PM2F_RD_PALETTE_WIDTH_8;
554		if ((video & PM2F_HSYNC_MASK) == PM2F_HSYNC_ACT_LOW)
555			tmp |= 4; /* invert hsync */
556		if ((video & PM2F_VSYNC_MASK) == PM2F_VSYNC_ACT_LOW)
557			tmp |= 8; /* invert vsync */
558		pm2_RDAC_WR(p, PM2I_RD_MISC_CONTROL, tmp);
559		break;
560	case PM2_TYPE_PERMEDIA2V:
561		tmp = 0;
562		if ((video & PM2F_HSYNC_MASK) == PM2F_HSYNC_ACT_LOW)
563			tmp |= 1; /* invert hsync */
564		if ((video & PM2F_VSYNC_MASK) == PM2F_VSYNC_ACT_LOW)
565			tmp |= 4; /* invert vsync */
566		pm2v_RDAC_WR(p, PM2VI_RD_SYNC_CONTROL, tmp);
567		pm2v_RDAC_WR(p, PM2VI_RD_MISC_CONTROL, 1);
568		break;
569	}
570}
571
572/*
573 *
574 */
575
576/**
577 *      pm2fb_check_var - Optional function. Validates a var passed in.
578 *      @var: frame buffer variable screen structure
579 *      @info: frame buffer structure that represents a single frame buffer
580 *
581 *	Checks to see if the hardware supports the state requested by
582 *	var passed in.
583 *
584 *	Returns negative errno on error, or zero on success.
585 */
586static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
587{
588	u32 lpitch;
589
590	if (var->bits_per_pixel != 8  && var->bits_per_pixel != 16 &&
591	    var->bits_per_pixel != 24 && var->bits_per_pixel != 32) {
592		DPRINTK("depth not supported: %u\n", var->bits_per_pixel);
593		return -EINVAL;
594	}
595
596	if (var->xres != var->xres_virtual) {
597		DPRINTK("virtual x resolution != physical x resolution not supported\n");
598		return -EINVAL;
599	}
600
601	if (var->yres > var->yres_virtual) {
602		DPRINTK("virtual y resolution < physical y resolution not possible\n");
603		return -EINVAL;
604	}
605
606	if (var->xoffset) {
607		DPRINTK("xoffset not supported\n");
608		return -EINVAL;
609	}
610
611	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
612		DPRINTK("interlace not supported\n");
613		return -EINVAL;
614	}
615
616	var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */
617	lpitch = var->xres * ((var->bits_per_pixel + 7)>>3);
618
619	if (var->xres < 320 || var->xres > 1600) {
620		DPRINTK("width not supported: %u\n", var->xres);
621		return -EINVAL;
622	}
623
624	if (var->yres < 200 || var->yres > 1200) {
625		DPRINTK("height not supported: %u\n", var->yres);
626		return -EINVAL;
627	}
628
629	if (lpitch * var->yres_virtual > info->fix.smem_len) {
630		DPRINTK("no memory for screen (%ux%ux%u)\n",
631			var->xres, var->yres_virtual, var->bits_per_pixel);
632		return -EINVAL;
633	}
634
635	if (PICOS2KHZ(var->pixclock) > PM2_MAX_PIXCLOCK) {
636		DPRINTK("pixclock too high (%ldKHz)\n", PICOS2KHZ(var->pixclock));
637		return -EINVAL;
638	}
639
640	var->transp.offset = 0;
641	var->transp.length = 0;
642	switch(var->bits_per_pixel) {
643	case 8:
644		var->red.length = var->green.length = var->blue.length = 8;
645		break;
646	case 16:
647		var->red.offset   = 11;
648		var->red.length   = 5;
649		var->green.offset = 5;
650		var->green.length = 6;
651		var->blue.offset  = 0;
652		var->blue.length  = 5;
653		break;
654	case 32:
655		var->transp.offset = 24;
656		var->transp.length = 8;
657		var->red.offset	  = 16;
658		var->green.offset = 8;
659		var->blue.offset  = 0;
660		var->red.length = var->green.length = var->blue.length = 8;
661		break;
662	case 24:
663#ifdef __BIG_ENDIAN
664		var->red.offset   = 0;
665		var->blue.offset  = 16;
666#else
667		var->red.offset   = 16;
668		var->blue.offset  = 0;
669#endif
670		var->green.offset = 8;
671		var->red.length = var->green.length = var->blue.length = 8;
672		break;
673	}
674	var->height = var->width = -1;
675
676	var->accel_flags = 0;	/* Can't mmap if this is on */
677
678	DPRINTK("Checking graphics mode at %dx%d depth %d\n",
679		var->xres, var->yres, var->bits_per_pixel);
680	return 0;
681}
682
683/**
684 *      pm2fb_set_par - Alters the hardware state.
685 *      @info: frame buffer structure that represents a single frame buffer
686 *
687 *	Using the fb_var_screeninfo in fb_info we set the resolution of the
688 *	this particular framebuffer.
689 */
690static int pm2fb_set_par(struct fb_info *info)
691{
692	struct pm2fb_par *par = info->par;
693	u32 pixclock;
694	u32 width, height, depth;
695	u32 hsstart, hsend, hbend, htotal;
696	u32 vsstart, vsend, vbend, vtotal;
697	u32 stride;
698	u32 base;
699	u32 video = 0;
700	u32 clrmode = PM2F_RD_COLOR_MODE_RGB | PM2F_RD_GUI_ACTIVE;
701	u32 txtmap = 0;
702	u32 pixsize = 0;
703	u32 clrformat = 0;
704	u32 xres;
705	int data64;
706
707	reset_card(par);
708	reset_config(par);
709	clear_palette(par);
710	if ( par->memclock )
711		set_memclock(par, par->memclock);
712
713	width = (info->var.xres_virtual + 7) & ~7;
714	height = info->var.yres_virtual;
715	depth = (info->var.bits_per_pixel + 7) & ~7;
716	depth = (depth > 32) ? 32 : depth;
717	data64 = depth > 8 || par->type == PM2_TYPE_PERMEDIA2V;
718
719	xres = (info->var.xres + 31) & ~31;
720	pixclock = PICOS2KHZ(info->var.pixclock);
721	if (pixclock > PM2_MAX_PIXCLOCK) {
722		DPRINTK("pixclock too high (%uKHz)\n", pixclock);
723		return -EINVAL;
724	}
725
726	hsstart = to3264(info->var.right_margin, depth, data64);
727	hsend = hsstart + to3264(info->var.hsync_len, depth, data64);
728	hbend = hsend + to3264(info->var.left_margin, depth, data64);
729	htotal = to3264(xres, depth, data64) + hbend - 1;
730	vsstart = (info->var.lower_margin)
731		? info->var.lower_margin - 1
732		: 0;
733	vsend = info->var.lower_margin + info->var.vsync_len - 1;
734	vbend = info->var.lower_margin + info->var.vsync_len + info->var.upper_margin;
735	vtotal = info->var.yres + vbend - 1;
736	stride = to3264(width, depth, 1);
737	base = to3264(info->var.yoffset * xres + info->var.xoffset, depth, 1);
738	if (data64)
739		video |= PM2F_DATA_64_ENABLE;
740
741	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) {
742		if (lowhsync) {
743			DPRINTK("ignoring +hsync, using -hsync.\n");
744			video |= PM2F_HSYNC_ACT_LOW;
745		} else
746			video |= PM2F_HSYNC_ACT_HIGH;
747	}
748	else
749		video |= PM2F_HSYNC_ACT_LOW;
750	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) {
751		if (lowvsync) {
752			DPRINTK("ignoring +vsync, using -vsync.\n");
753			video |= PM2F_VSYNC_ACT_LOW;
754		} else
755			video |= PM2F_VSYNC_ACT_HIGH;
756	}
757	else
758		video |= PM2F_VSYNC_ACT_LOW;
759	if ((info->var.vmode & FB_VMODE_MASK)==FB_VMODE_INTERLACED) {
760		DPRINTK("interlaced not supported\n");
761		return -EINVAL;
762	}
763	if ((info->var.vmode & FB_VMODE_MASK)==FB_VMODE_DOUBLE)
764		video |= PM2F_LINE_DOUBLE;
765	if ((info->var.activate & FB_ACTIVATE_MASK)==FB_ACTIVATE_NOW)
766		video |= PM2F_VIDEO_ENABLE;
767	par->video = video;
768
769	info->fix.visual =
770		(depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
771	info->fix.line_length = info->var.xres * depth / 8;
772	info->cmap.len = 256;
773
774	/*
775	 * Settings calculated. Now write them out.
776	 */
777	if (par->type == PM2_TYPE_PERMEDIA2V) {
778		WAIT_FIFO(par, 1);
779		pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
780	}
781
782	set_aperture(par, depth);
783
784	mb();
785	WAIT_FIFO(par, 19);
786	pm2_RDAC_WR(par, PM2I_RD_COLOR_KEY_CONTROL,
787		    ( depth == 8 ) ? 0 : PM2F_COLOR_KEY_TEST_OFF);
788	switch (depth) {
789	case 8:
790		pm2_WR(par, PM2R_FB_READ_PIXEL, 0);
791		clrformat = 0x0e;
792		break;
793	case 16:
794		pm2_WR(par, PM2R_FB_READ_PIXEL, 1);
795		clrmode |= PM2F_RD_TRUECOLOR | PM2F_RD_PIXELFORMAT_RGB565;
796		txtmap = PM2F_TEXTEL_SIZE_16;
797		pixsize = 1;
798		clrformat = 0x70;
799		break;
800	case 32:
801		pm2_WR(par, PM2R_FB_READ_PIXEL, 2);
802		clrmode |= PM2F_RD_TRUECOLOR | PM2F_RD_PIXELFORMAT_RGBA8888;
803		txtmap = PM2F_TEXTEL_SIZE_32;
804		pixsize = 2;
805		clrformat = 0x20;
806		break;
807	case 24:
808		pm2_WR(par, PM2R_FB_READ_PIXEL, 4);
809		clrmode |= PM2F_RD_TRUECOLOR | PM2F_RD_PIXELFORMAT_RGB888;
810		txtmap = PM2F_TEXTEL_SIZE_24;
811		pixsize = 4;
812		clrformat = 0x20;
813		break;
814	}
815	pm2_WR(par, PM2R_FB_WRITE_MODE, PM2F_FB_WRITE_ENABLE);
816	pm2_WR(par, PM2R_FB_READ_MODE, partprod(xres));
817	pm2_WR(par, PM2R_LB_READ_MODE, partprod(xres));
818	pm2_WR(par, PM2R_TEXTURE_MAP_FORMAT, txtmap | partprod(xres));
819	pm2_WR(par, PM2R_H_TOTAL, htotal);
820	pm2_WR(par, PM2R_HS_START, hsstart);
821	pm2_WR(par, PM2R_HS_END, hsend);
822	pm2_WR(par, PM2R_HG_END, hbend);
823	pm2_WR(par, PM2R_HB_END, hbend);
824	pm2_WR(par, PM2R_V_TOTAL, vtotal);
825	pm2_WR(par, PM2R_VS_START, vsstart);
826	pm2_WR(par, PM2R_VS_END, vsend);
827	pm2_WR(par, PM2R_VB_END, vbend);
828	pm2_WR(par, PM2R_SCREEN_STRIDE, stride);
829	wmb();
830	pm2_WR(par, PM2R_WINDOW_ORIGIN, 0);
831	pm2_WR(par, PM2R_SCREEN_SIZE, (height << 16) | width);
832	pm2_WR(par, PM2R_SCISSOR_MODE, PM2F_SCREEN_SCISSOR_ENABLE);
833	wmb();
834	pm2_WR(par, PM2R_SCREEN_BASE, base);
835	wmb();
836	set_video(par, video);
837	WAIT_FIFO(par, 4);
838	switch (par->type) {
839	case PM2_TYPE_PERMEDIA2:
840		pm2_RDAC_WR(par, PM2I_RD_COLOR_MODE, clrmode);
841		break;
842	case PM2_TYPE_PERMEDIA2V:
843		pm2v_RDAC_WR(par, PM2VI_RD_PIXEL_SIZE, pixsize);
844		pm2v_RDAC_WR(par, PM2VI_RD_COLOR_FORMAT, clrformat);
845		break;
846	}
847	set_pixclock(par, pixclock);
848	DPRINTK("Setting graphics mode at %dx%d depth %d\n",
849		info->var.xres, info->var.yres, info->var.bits_per_pixel);
850	return 0;
851}
852
853/**
854 *  	pm2fb_setcolreg - Sets a color register.
855 *      @regno: boolean, 0 copy local, 1 get_user() function
856 *      @red: frame buffer colormap structure
857 *	@green: The green value which can be up to 16 bits wide
858 *	@blue:  The blue value which can be up to 16 bits wide.
859 *	@transp: If supported the alpha value which can be up to 16 bits wide.
860 *      @info: frame buffer info structure
861 *
862 *  	Set a single color register. The values supplied have a 16 bit
863 *  	magnitude which needs to be scaled in this function for the hardware.
864 *	Pretty much a direct lift from tdfxfb.c.
865 *
866 *	Returns negative errno on error, or zero on success.
867 */
868static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
869			   unsigned blue, unsigned transp,
870			   struct fb_info *info)
871{
872	struct pm2fb_par *par = info->par;
873
874	if (regno >= info->cmap.len)  /* no. of hw registers */
875		return 1;
876	/*
877	 * Program hardware... do anything you want with transp
878	 */
879
880	/* grayscale works only partially under directcolor */
881	if (info->var.grayscale) {
882		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
883		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
884	}
885
886	/* Directcolor:
887	 *   var->{color}.offset contains start of bitfield
888	 *   var->{color}.length contains length of bitfield
889	 *   {hardwarespecific} contains width of DAC
890	 *   cmap[X] is programmed to
891	 *   (X << red.offset) | (X << green.offset) | (X << blue.offset)
892	 *   RAMDAC[X] is programmed to (red, green, blue)
893	 *
894	 * Pseudocolor:
895	 *    uses offset = 0 && length = DAC register width.
896	 *    var->{color}.offset is 0
897	 *    var->{color}.length contains widht of DAC
898	 *    cmap is not used
899	 *    DAC[X] is programmed to (red, green, blue)
900	 * Truecolor:
901	 *    does not use RAMDAC (usually has 3 of them).
902	 *    var->{color}.offset contains start of bitfield
903	 *    var->{color}.length contains length of bitfield
904	 *    cmap is programmed to
905	 *    (red << red.offset) | (green << green.offset) |
906	 *    (blue << blue.offset) | (transp << transp.offset)
907	 *    RAMDAC does not exist
908	 */
909#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
910	switch (info->fix.visual) {
911	case FB_VISUAL_TRUECOLOR:
912	case FB_VISUAL_PSEUDOCOLOR:
913		red = CNVT_TOHW(red, info->var.red.length);
914		green = CNVT_TOHW(green, info->var.green.length);
915		blue = CNVT_TOHW(blue, info->var.blue.length);
916		transp = CNVT_TOHW(transp, info->var.transp.length);
917		break;
918	case FB_VISUAL_DIRECTCOLOR:
919		/* example here assumes 8 bit DAC. Might be different
920		 * for your hardware */
921		red = CNVT_TOHW(red, 8);
922		green = CNVT_TOHW(green, 8);
923		blue = CNVT_TOHW(blue, 8);
924		/* hey, there is bug in transp handling... */
925		transp = CNVT_TOHW(transp, 8);
926		break;
927	}
928#undef CNVT_TOHW
929	/* Truecolor has hardware independent palette */
930	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
931		u32 v;
932
933		if (regno >= 16)
934			return 1;
935
936		v = (red << info->var.red.offset) |
937			(green << info->var.green.offset) |
938			(blue << info->var.blue.offset) |
939			(transp << info->var.transp.offset);
940
941		switch (info->var.bits_per_pixel) {
942		case 8:
943			break;
944   		case 16:
945		case 24:
946		case 32:
947           		par->palette[regno] = v;
948			break;
949		}
950		return 0;
951	}
952	else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
953		set_color(par, regno, red, green, blue);
954
955	return 0;
956}
957
958/**
959 *      pm2fb_pan_display - Pans the display.
960 *      @var: frame buffer variable screen structure
961 *      @info: frame buffer structure that represents a single frame buffer
962 *
963 *	Pan (or wrap, depending on the `vmode' field) the display using the
964 *  	`xoffset' and `yoffset' fields of the `var' structure.
965 *  	If the values don't fit, return -EINVAL.
966 *
967 *      Returns negative errno on error, or zero on success.
968 *
969 */
970static int pm2fb_pan_display(struct fb_var_screeninfo *var,
971			     struct fb_info *info)
972{
973	struct pm2fb_par *p = info->par;
974	u32 base;
975	u32 depth;
976	u32 xres;
977
978	xres = (var->xres + 31) & ~31;
979	depth = (var->bits_per_pixel + 7) & ~7;
980	depth = (depth > 32) ? 32 : depth;
981	base = to3264(var->yoffset * xres + var->xoffset, depth, 1);
982	WAIT_FIFO(p, 1);
983	pm2_WR(p, PM2R_SCREEN_BASE, base);
984	return 0;
985}
986
987/**
988 *      pm2fb_blank - Blanks the display.
989 *      @blank_mode: the blank mode we want.
990 *      @info: frame buffer structure that represents a single frame buffer
991 *
992 *      Blank the screen if blank_mode != 0, else unblank. Return 0 if
993 *      blanking succeeded, != 0 if un-/blanking failed due to e.g. a
994 *      video mode which doesn't support it. Implements VESA suspend
995 *      and powerdown modes on hardware that supports disabling hsync/vsync:
996 *      blank_mode == 2: suspend vsync
997 *      blank_mode == 3: suspend hsync
998 *      blank_mode == 4: powerdown
999 *
1000 *      Returns negative errno on error, or zero on success.
1001 *
1002 */
1003static int pm2fb_blank(int blank_mode, struct fb_info *info)
1004{
1005	struct pm2fb_par *par = info->par;
1006	u32 video = par->video;
1007
1008	DPRINTK("blank_mode %d\n", blank_mode);
1009
1010	switch (blank_mode) {
1011	case FB_BLANK_UNBLANK:
1012		/* Screen: On */
1013		video |= PM2F_VIDEO_ENABLE;
1014		break;
1015	case FB_BLANK_NORMAL:
1016		/* Screen: Off */
1017		video &= ~PM2F_VIDEO_ENABLE;
1018		break;
1019	case FB_BLANK_VSYNC_SUSPEND:
1020		/* VSync: Off */
1021		video &= ~(PM2F_VSYNC_MASK | PM2F_BLANK_LOW );
1022		break;
1023	case FB_BLANK_HSYNC_SUSPEND:
1024		/* HSync: Off */
1025		video &= ~(PM2F_HSYNC_MASK | PM2F_BLANK_LOW );
1026		break;
1027	case FB_BLANK_POWERDOWN:
1028		/* HSync: Off, VSync: Off */
1029		video &= ~(PM2F_VSYNC_MASK | PM2F_HSYNC_MASK| PM2F_BLANK_LOW);
1030		break;
1031	}
1032	set_video(par, video);
1033	return 0;
1034}
1035
1036static int pm2fb_sync(struct fb_info *info)
1037{
1038	struct pm2fb_par *par = info->par;
1039
1040	WAIT_FIFO(par, 1);
1041	pm2_WR(par, PM2R_SYNC, 0);
1042	mb();
1043	do {
1044		while (pm2_RD(par, PM2R_OUT_FIFO_WORDS) == 0)
1045			udelay(10);
1046		rmb();
1047	} while (pm2_RD(par, PM2R_OUT_FIFO) != PM2TAG(PM2R_SYNC));
1048
1049	return 0;
1050}
1051
1052/*
1053 * block operation. copy=0: rectangle fill, copy=1: rectangle copy.
1054 */
1055static void pm2fb_block_op(struct fb_info* info, int copy,
1056				s32 xsrc, s32 ysrc,
1057				s32 x, s32 y, s32 w, s32 h,
1058				u32 color) {
1059	struct pm2fb_par *par = info->par;
1060
1061	if (!w || !h)
1062		return;
1063	WAIT_FIFO(par, 5);
1064	pm2_WR(par, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE |
1065		PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
1066	if (copy)
1067		pm2_WR(par, PM2R_FB_SOURCE_DELTA,
1068			((ysrc-y) & 0xfff) << 16 | ((xsrc-x) & 0xfff));
1069	else
1070		pm2_WR(par, PM2R_FB_BLOCK_COLOR, color);
1071	pm2_WR(par, PM2R_RECTANGLE_ORIGIN, (y << 16) | x);
1072	pm2_WR(par, PM2R_RECTANGLE_SIZE, (h << 16) | w);
1073	wmb();
1074	pm2_WR(par, PM2R_RENDER,PM2F_RENDER_RECTANGLE |
1075				(x<xsrc ? PM2F_INCREASE_X : 0) |
1076				(y<ysrc ? PM2F_INCREASE_Y : 0) |
1077				(copy ? 0 : PM2F_RENDER_FASTFILL));
1078}
1079
1080static void pm2fb_fillrect (struct fb_info *info,
1081				const struct fb_fillrect *region)
1082{
1083	struct fb_fillrect modded;
1084	int vxres, vyres;
1085	u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
1086		((u32*)info->pseudo_palette)[region->color] : region->color;
1087
1088	if (info->state != FBINFO_STATE_RUNNING)
1089		return;
1090	if ((info->flags & FBINFO_HWACCEL_DISABLED) ||
1091		region->rop != ROP_COPY ) {
1092		cfb_fillrect(info, region);
1093		return;
1094	}
1095
1096	vxres = info->var.xres_virtual;
1097	vyres = info->var.yres_virtual;
1098
1099	memcpy(&modded, region, sizeof(struct fb_fillrect));
1100
1101	if(!modded.width || !modded.height ||
1102	   modded.dx >= vxres || modded.dy >= vyres)
1103		return;
1104
1105	if(modded.dx + modded.width  > vxres)
1106		modded.width  = vxres - modded.dx;
1107	if(modded.dy + modded.height > vyres)
1108		modded.height = vyres - modded.dy;
1109
1110	if(info->var.bits_per_pixel == 8)
1111		color |= color << 8;
1112	if(info->var.bits_per_pixel <= 16)
1113		color |= color << 16;
1114
1115	if(info->var.bits_per_pixel != 24)
1116		pm2fb_block_op(info, 0, 0, 0,
1117				modded.dx, modded.dy,
1118				modded.width, modded.height, color);
1119	else
1120		cfb_fillrect(info, region);
1121}
1122
1123static void pm2fb_copyarea(struct fb_info *info,
1124				const struct fb_copyarea *area)
1125{
1126	struct fb_copyarea modded;
1127	u32 vxres, vyres;
1128
1129	if (info->state != FBINFO_STATE_RUNNING)
1130		return;
1131	if (info->flags & FBINFO_HWACCEL_DISABLED) {
1132		cfb_copyarea(info, area);
1133		return;
1134	}
1135
1136	memcpy(&modded, area, sizeof(struct fb_copyarea));
1137
1138	vxres = info->var.xres_virtual;
1139	vyres = info->var.yres_virtual;
1140
1141	if(!modded.width || !modded.height ||
1142	   modded.sx >= vxres || modded.sy >= vyres ||
1143	   modded.dx >= vxres || modded.dy >= vyres)
1144		return;
1145
1146	if(modded.sx + modded.width > vxres)
1147		modded.width = vxres - modded.sx;
1148	if(modded.dx + modded.width > vxres)
1149		modded.width = vxres - modded.dx;
1150	if(modded.sy + modded.height > vyres)
1151		modded.height = vyres - modded.sy;
1152	if(modded.dy + modded.height > vyres)
1153		modded.height = vyres - modded.dy;
1154
1155	pm2fb_block_op(info, 1, modded.sx, modded.sy,
1156			modded.dx, modded.dy,
1157			modded.width, modded.height, 0);
1158}
1159
1160/* ------------ Hardware Independent Functions ------------ */
1161
1162/*
1163 *  Frame buffer operations
1164 */
1165
1166static struct fb_ops pm2fb_ops = {
1167	.owner		= THIS_MODULE,
1168	.fb_check_var	= pm2fb_check_var,
1169	.fb_set_par	= pm2fb_set_par,
1170	.fb_setcolreg	= pm2fb_setcolreg,
1171	.fb_blank	= pm2fb_blank,
1172	.fb_pan_display	= pm2fb_pan_display,
1173	.fb_fillrect	= pm2fb_fillrect,
1174	.fb_copyarea	= pm2fb_copyarea,
1175	.fb_imageblit	= cfb_imageblit,
1176	.fb_sync	= pm2fb_sync,
1177};
1178
1179/*
1180 * PCI stuff
1181 */
1182
1183
1184/**
1185 * Device initialisation
1186 *
1187 * Initialise and allocate resource for PCI device.
1188 *
1189 * @param	pdev	PCI device.
1190 * @param	id	PCI device ID.
1191 */
1192static int __devinit pm2fb_probe(struct pci_dev *pdev,
1193				 const struct pci_device_id *id)
1194{
1195	struct pm2fb_par *default_par;
1196	struct fb_info *info;
1197	int err, err_retval = -ENXIO;
1198
1199	err = pci_enable_device(pdev);
1200	if ( err ) {
1201		printk(KERN_WARNING "pm2fb: Can't enable pdev: %d\n", err);
1202		return err;
1203	}
1204
1205	info = framebuffer_alloc(sizeof(struct pm2fb_par), &pdev->dev);
1206	if ( !info )
1207		return -ENOMEM;
1208	default_par = info->par;
1209
1210	switch (pdev->device) {
1211	case  PCI_DEVICE_ID_TI_TVP4020:
1212		strcpy(pm2fb_fix.id, "TVP4020");
1213		default_par->type = PM2_TYPE_PERMEDIA2;
1214		break;
1215	case  PCI_DEVICE_ID_3DLABS_PERMEDIA2:
1216		strcpy(pm2fb_fix.id, "Permedia2");
1217		default_par->type = PM2_TYPE_PERMEDIA2;
1218		break;
1219	case  PCI_DEVICE_ID_3DLABS_PERMEDIA2V:
1220		strcpy(pm2fb_fix.id, "Permedia2v");
1221		default_par->type = PM2_TYPE_PERMEDIA2V;
1222		break;
1223	}
1224
1225	pm2fb_fix.mmio_start = pci_resource_start(pdev, 0);
1226	pm2fb_fix.mmio_len = PM2_REGS_SIZE;
1227
1228#if defined(__BIG_ENDIAN)
1229	/*
1230	 * PM2 has a 64k register file, mapped twice in 128k. Lower
1231	 * map is little-endian, upper map is big-endian.
1232	 */
1233	pm2fb_fix.mmio_start += PM2_REGS_SIZE;
1234	DPRINTK("Adjusting register base for big-endian.\n");
1235#endif
1236	DPRINTK("Register base at 0x%lx\n", pm2fb_fix.mmio_start);
1237
1238	/* Registers - request region and map it. */
1239	if ( !request_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len,
1240				 "pm2fb regbase") ) {
1241		printk(KERN_WARNING "pm2fb: Can't reserve regbase.\n");
1242		goto err_exit_neither;
1243	}
1244	default_par->v_regs =
1245		ioremap_nocache(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
1246	if ( !default_par->v_regs ) {
1247		printk(KERN_WARNING "pm2fb: Can't remap %s register area.\n",
1248		       pm2fb_fix.id);
1249		release_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
1250		goto err_exit_neither;
1251	}
1252
1253	/* Stash away memory register info for use when we reset the board */
1254	default_par->mem_control = pm2_RD(default_par, PM2R_MEM_CONTROL);
1255	default_par->boot_address = pm2_RD(default_par, PM2R_BOOT_ADDRESS);
1256	default_par->mem_config = pm2_RD(default_par, PM2R_MEM_CONFIG);
1257	DPRINTK("MemControl 0x%x BootAddress 0x%x MemConfig 0x%x\n",
1258		default_par->mem_control, default_par->boot_address,
1259		default_par->mem_config);
1260
1261	if(default_par->mem_control == 0 &&
1262		default_par->boot_address == 0x31 &&
1263		default_par->mem_config == 0x259fffff) {
1264		default_par->memclock = CVPPC_MEMCLOCK;
1265		default_par->mem_control=0;
1266		default_par->boot_address=0x20;
1267		default_par->mem_config=0xe6002021;
1268		if (pdev->subsystem_vendor == 0x1048 &&
1269			pdev->subsystem_device == 0x0a31) {
1270			DPRINTK("subsystem_vendor: %04x, subsystem_device: %04x\n",
1271				pdev->subsystem_vendor, pdev->subsystem_device);
1272			DPRINTK("We have not been initialized by VGA BIOS "
1273				"and are running on an Elsa Winner 2000 Office\n");
1274			DPRINTK("Initializing card timings manually...\n");
1275			default_par->memclock=70000;
1276		}
1277		if (pdev->subsystem_vendor == 0x3d3d &&
1278			pdev->subsystem_device == 0x0100) {
1279			DPRINTK("subsystem_vendor: %04x, subsystem_device: %04x\n",
1280				pdev->subsystem_vendor, pdev->subsystem_device);
1281			DPRINTK("We have not been initialized by VGA BIOS "
1282				"and are running on an 3dlabs reference board\n");
1283			DPRINTK("Initializing card timings manually...\n");
1284			default_par->memclock=74894;
1285		}
1286	}
1287
1288	/* Now work out how big lfb is going to be. */
1289	switch(default_par->mem_config & PM2F_MEM_CONFIG_RAM_MASK) {
1290	case PM2F_MEM_BANKS_1:
1291		pm2fb_fix.smem_len=0x200000;
1292		break;
1293	case PM2F_MEM_BANKS_2:
1294		pm2fb_fix.smem_len=0x400000;
1295		break;
1296	case PM2F_MEM_BANKS_3:
1297		pm2fb_fix.smem_len=0x600000;
1298		break;
1299	case PM2F_MEM_BANKS_4:
1300		pm2fb_fix.smem_len=0x800000;
1301		break;
1302	}
1303	pm2fb_fix.smem_start = pci_resource_start(pdev, 1);
1304
1305	/* Linear frame buffer - request region and map it. */
1306	if ( !request_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len,
1307				 "pm2fb smem") ) {
1308		printk(KERN_WARNING "pm2fb: Can't reserve smem.\n");
1309		goto err_exit_mmio;
1310	}
1311	info->screen_base =
1312		ioremap_nocache(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
1313	if ( !info->screen_base ) {
1314		printk(KERN_WARNING "pm2fb: Can't ioremap smem area.\n");
1315		release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
1316		goto err_exit_mmio;
1317	}
1318
1319	info->fbops		= &pm2fb_ops;
1320	info->fix		= pm2fb_fix;
1321	info->pseudo_palette	= default_par->palette;
1322	info->flags		= FBINFO_DEFAULT |
1323                                  FBINFO_HWACCEL_YPAN |
1324	                          FBINFO_HWACCEL_COPYAREA |
1325	                          FBINFO_HWACCEL_FILLRECT;
1326
1327	if (!mode)
1328		mode = "640x480@60";
1329
1330	err = fb_find_mode(&info->var, info, mode, NULL, 0, NULL, 8);
1331	if (!err || err == 4)
1332		info->var = pm2fb_var;
1333
1334	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
1335		goto err_exit_both;
1336
1337	if (register_framebuffer(info) < 0)
1338		goto err_exit_all;
1339
1340	printk(KERN_INFO "fb%d: %s frame buffer device, memory = %dK.\n",
1341	       info->node, info->fix.id, pm2fb_fix.smem_len / 1024);
1342
1343	/*
1344	 * Our driver data
1345	 */
1346	pci_set_drvdata(pdev, info);
1347
1348	return 0;
1349
1350 err_exit_all:
1351	fb_dealloc_cmap(&info->cmap);
1352 err_exit_both:
1353	iounmap(info->screen_base);
1354	release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
1355 err_exit_mmio:
1356	iounmap(default_par->v_regs);
1357	release_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
1358 err_exit_neither:
1359	framebuffer_release(info);
1360	return err_retval;
1361}
1362
1363/**
1364 * Device removal.
1365 *
1366 * Release all device resources.
1367 *
1368 * @param	pdev	PCI device to clean up.
1369 */
1370static void __devexit pm2fb_remove(struct pci_dev *pdev)
1371{
1372	struct fb_info* info = pci_get_drvdata(pdev);
1373	struct fb_fix_screeninfo* fix = &info->fix;
1374	struct pm2fb_par *par = info->par;
1375
1376	unregister_framebuffer(info);
1377
1378	iounmap(info->screen_base);
1379	release_mem_region(fix->smem_start, fix->smem_len);
1380	iounmap(par->v_regs);
1381	release_mem_region(fix->mmio_start, fix->mmio_len);
1382
1383	pci_set_drvdata(pdev, NULL);
1384	kfree(info);
1385}
1386
1387static struct pci_device_id pm2fb_id_table[] = {
1388	{ PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TVP4020,
1389	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
1390	  0xff0000, 0 },
1391	{ PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2,
1392	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
1393	  0xff0000, 0 },
1394	{ PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2V,
1395	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
1396	  0xff0000, 0 },
1397	{ PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2V,
1398	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NOT_DEFINED_VGA << 8,
1399	  0xff00, 0 },
1400	{ 0, }
1401};
1402
1403static struct pci_driver pm2fb_driver = {
1404	.name		= "pm2fb",
1405	.id_table 	= pm2fb_id_table,
1406	.probe 		= pm2fb_probe,
1407	.remove 	= __devexit_p(pm2fb_remove),
1408};
1409
1410MODULE_DEVICE_TABLE(pci, pm2fb_id_table);
1411
1412
1413#ifndef MODULE
1414/**
1415 * Parse user speficied options.
1416 *
1417 * This is, comma-separated options following `video=pm2fb:'.
1418 */
1419static int __init pm2fb_setup(char *options)
1420{
1421	char* this_opt;
1422
1423	if (!options || !*options)
1424		return 0;
1425
1426	while ((this_opt = strsep(&options, ",")) != NULL) {
1427		if (!*this_opt)
1428			continue;
1429		if(!strcmp(this_opt, "lowhsync")) {
1430			lowhsync = 1;
1431		} else if(!strcmp(this_opt, "lowvsync")) {
1432			lowvsync = 1;
1433		} else {
1434			mode = this_opt;
1435		}
1436	}
1437	return 0;
1438}
1439#endif
1440
1441
1442static int __init pm2fb_init(void)
1443{
1444#ifndef MODULE
1445	char *option = NULL;
1446
1447	if (fb_get_options("pm2fb", &option))
1448		return -ENODEV;
1449	pm2fb_setup(option);
1450#endif
1451
1452	return pci_register_driver(&pm2fb_driver);
1453}
1454
1455module_init(pm2fb_init);
1456
1457#ifdef MODULE
1458/*
1459 *  Cleanup
1460 */
1461
1462static void __exit pm2fb_exit(void)
1463{
1464	pci_unregister_driver(&pm2fb_driver);
1465}
1466#endif
1467
1468#ifdef MODULE
1469module_exit(pm2fb_exit);
1470
1471module_param(mode, charp, 0);
1472MODULE_PARM_DESC(mode, "Preferred video mode e.g. '648x480-8@60'");
1473module_param(lowhsync, bool, 0);
1474MODULE_PARM_DESC(lowhsync, "Force horizontal sync low regardless of mode");
1475module_param(lowvsync, bool, 0);
1476MODULE_PARM_DESC(lowvsync, "Force vertical sync low regardless of mode");
1477
1478MODULE_AUTHOR("Jim Hague <jim.hague@acm.org>");
1479MODULE_DESCRIPTION("Permedia2 framebuffer device driver");
1480MODULE_LICENSE("GPL");
1481#endif
1482