1/* ffb.c: Creator/Elite3D frame buffer driver
2 *
3 * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
4 * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
5 *
6 * Driver layout based loosely on tgafb.c, see that file for credits.
7 */
8
9#include <linux/module.h>
10#include <linux/kernel.h>
11#include <linux/errno.h>
12#include <linux/string.h>
13#include <linux/slab.h>
14#include <linux/delay.h>
15#include <linux/init.h>
16#include <linux/fb.h>
17#include <linux/mm.h>
18#include <linux/timer.h>
19
20#include <asm/io.h>
21#include <asm/upa.h>
22#include <asm/prom.h>
23#include <asm/of_device.h>
24#include <asm/fbio.h>
25
26#include "sbuslib.h"
27
28/*
29 * Local functions.
30 */
31
32static int ffb_setcolreg(unsigned, unsigned, unsigned, unsigned,
33			 unsigned, struct fb_info *);
34static int ffb_blank(int, struct fb_info *);
35static void ffb_init_fix(struct fb_info *);
36
37static void ffb_imageblit(struct fb_info *, const struct fb_image *);
38static void ffb_fillrect(struct fb_info *, const struct fb_fillrect *);
39static void ffb_copyarea(struct fb_info *, const struct fb_copyarea *);
40static int ffb_sync(struct fb_info *);
41static int ffb_mmap(struct fb_info *, struct vm_area_struct *);
42static int ffb_ioctl(struct fb_info *, unsigned int, unsigned long);
43static int ffb_pan_display(struct fb_var_screeninfo *, struct fb_info *);
44
45/*
46 *  Frame buffer operations
47 */
48
49static struct fb_ops ffb_ops = {
50	.owner			= THIS_MODULE,
51	.fb_setcolreg		= ffb_setcolreg,
52	.fb_blank		= ffb_blank,
53	.fb_pan_display		= ffb_pan_display,
54	.fb_fillrect		= ffb_fillrect,
55	.fb_copyarea		= ffb_copyarea,
56	.fb_imageblit		= ffb_imageblit,
57	.fb_sync		= ffb_sync,
58	.fb_mmap		= ffb_mmap,
59	.fb_ioctl		= ffb_ioctl,
60#ifdef CONFIG_COMPAT
61	.fb_compat_ioctl	= sbusfb_compat_ioctl,
62#endif
63};
64
65/* Register layout and definitions */
66#define	FFB_SFB8R_VOFF		0x00000000
67#define	FFB_SFB8G_VOFF		0x00400000
68#define	FFB_SFB8B_VOFF		0x00800000
69#define	FFB_SFB8X_VOFF		0x00c00000
70#define	FFB_SFB32_VOFF		0x01000000
71#define	FFB_SFB64_VOFF		0x02000000
72#define	FFB_FBC_REGS_VOFF	0x04000000
73#define	FFB_BM_FBC_REGS_VOFF	0x04002000
74#define	FFB_DFB8R_VOFF		0x04004000
75#define	FFB_DFB8G_VOFF		0x04404000
76#define	FFB_DFB8B_VOFF		0x04804000
77#define	FFB_DFB8X_VOFF		0x04c04000
78#define	FFB_DFB24_VOFF		0x05004000
79#define	FFB_DFB32_VOFF		0x06004000
80#define	FFB_DFB422A_VOFF	0x07004000	/* DFB 422 mode write to A */
81#define	FFB_DFB422AD_VOFF	0x07804000	/* DFB 422 mode with line doubling */
82#define	FFB_DFB24B_VOFF		0x08004000	/* DFB 24bit mode write to B */
83#define	FFB_DFB422B_VOFF	0x09004000	/* DFB 422 mode write to B */
84#define	FFB_DFB422BD_VOFF	0x09804000	/* DFB 422 mode with line doubling */
85#define	FFB_SFB16Z_VOFF		0x0a004000	/* 16bit mode Z planes */
86#define	FFB_SFB8Z_VOFF		0x0a404000	/* 8bit mode Z planes */
87#define	FFB_SFB422_VOFF		0x0ac04000	/* SFB 422 mode write to A/B */
88#define	FFB_SFB422D_VOFF	0x0b404000	/* SFB 422 mode with line doubling */
89#define	FFB_FBC_KREGS_VOFF	0x0bc04000
90#define	FFB_DAC_VOFF		0x0bc06000
91#define	FFB_PROM_VOFF		0x0bc08000
92#define	FFB_EXP_VOFF		0x0bc18000
93
94#define	FFB_SFB8R_POFF		0x04000000UL
95#define	FFB_SFB8G_POFF		0x04400000UL
96#define	FFB_SFB8B_POFF		0x04800000UL
97#define	FFB_SFB8X_POFF		0x04c00000UL
98#define	FFB_SFB32_POFF		0x05000000UL
99#define	FFB_SFB64_POFF		0x06000000UL
100#define	FFB_FBC_REGS_POFF	0x00600000UL
101#define	FFB_BM_FBC_REGS_POFF	0x00600000UL
102#define	FFB_DFB8R_POFF		0x01000000UL
103#define	FFB_DFB8G_POFF		0x01400000UL
104#define	FFB_DFB8B_POFF		0x01800000UL
105#define	FFB_DFB8X_POFF		0x01c00000UL
106#define	FFB_DFB24_POFF		0x02000000UL
107#define	FFB_DFB32_POFF		0x03000000UL
108#define	FFB_FBC_KREGS_POFF	0x00610000UL
109#define	FFB_DAC_POFF		0x00400000UL
110#define	FFB_PROM_POFF		0x00000000UL
111#define	FFB_EXP_POFF		0x00200000UL
112#define FFB_DFB422A_POFF	0x09000000UL
113#define FFB_DFB422AD_POFF	0x09800000UL
114#define FFB_DFB24B_POFF		0x0a000000UL
115#define FFB_DFB422B_POFF	0x0b000000UL
116#define FFB_DFB422BD_POFF	0x0b800000UL
117#define FFB_SFB16Z_POFF		0x0c800000UL
118#define FFB_SFB8Z_POFF		0x0c000000UL
119#define FFB_SFB422_POFF		0x0d000000UL
120#define FFB_SFB422D_POFF	0x0d800000UL
121
122/* Draw operations */
123#define FFB_DRAWOP_DOT		0x00
124#define FFB_DRAWOP_AADOT	0x01
125#define FFB_DRAWOP_BRLINECAP	0x02
126#define FFB_DRAWOP_BRLINEOPEN	0x03
127#define FFB_DRAWOP_DDLINE	0x04
128#define FFB_DRAWOP_AALINE	0x05
129#define FFB_DRAWOP_TRIANGLE	0x06
130#define FFB_DRAWOP_POLYGON	0x07
131#define FFB_DRAWOP_RECTANGLE	0x08
132#define FFB_DRAWOP_FASTFILL	0x09
133#define FFB_DRAWOP_BCOPY	0x0a
134#define FFB_DRAWOP_VSCROLL	0x0b
135
136/* Pixel processor control */
137/* Force WID */
138#define FFB_PPC_FW_DISABLE	0x800000
139#define FFB_PPC_FW_ENABLE	0xc00000
140/* Auxiliary clip */
141#define FFB_PPC_ACE_DISABLE	0x040000
142#define FFB_PPC_ACE_AUX_SUB	0x080000
143#define FFB_PPC_ACE_AUX_ADD	0x0c0000
144/* Depth cue */
145#define FFB_PPC_DCE_DISABLE	0x020000
146#define FFB_PPC_DCE_ENABLE	0x030000
147/* Alpha blend */
148#define FFB_PPC_ABE_DISABLE	0x008000
149#define FFB_PPC_ABE_ENABLE	0x00c000
150/* View clip */
151#define FFB_PPC_VCE_DISABLE	0x001000
152#define FFB_PPC_VCE_2D		0x002000
153#define FFB_PPC_VCE_3D		0x003000
154/* Area pattern */
155#define FFB_PPC_APE_DISABLE	0x000800
156#define FFB_PPC_APE_ENABLE	0x000c00
157/* Transparent background */
158#define FFB_PPC_TBE_OPAQUE	0x000200
159#define FFB_PPC_TBE_TRANSPARENT	0x000300
160/* Z source */
161#define FFB_PPC_ZS_VAR		0x000080
162#define FFB_PPC_ZS_CONST	0x0000c0
163/* Y source */
164#define FFB_PPC_YS_VAR		0x000020
165#define FFB_PPC_YS_CONST	0x000030
166/* X source */
167#define FFB_PPC_XS_WID		0x000004
168#define FFB_PPC_XS_VAR		0x000008
169#define FFB_PPC_XS_CONST	0x00000c
170/* Color (BGR) source */
171#define FFB_PPC_CS_VAR		0x000002
172#define FFB_PPC_CS_CONST	0x000003
173
174#define FFB_ROP_NEW                  0x83
175#define FFB_ROP_OLD                  0x85
176#define FFB_ROP_NEW_XOR_OLD          0x86
177
178#define FFB_UCSR_FIFO_MASK     0x00000fff
179#define FFB_UCSR_FB_BUSY       0x01000000
180#define FFB_UCSR_RP_BUSY       0x02000000
181#define FFB_UCSR_ALL_BUSY      (FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY)
182#define FFB_UCSR_READ_ERR      0x40000000
183#define FFB_UCSR_FIFO_OVFL     0x80000000
184#define FFB_UCSR_ALL_ERRORS    (FFB_UCSR_READ_ERR|FFB_UCSR_FIFO_OVFL)
185
186struct ffb_fbc {
187	/* Next vertex registers */
188	u32	xxx1[3];
189	u32	alpha;
190	u32	red;
191	u32	green;
192	u32	blue;
193	u32	depth;
194	u32	y;
195	u32	x;
196	u32	xxx2[2];
197	u32	ryf;
198	u32	rxf;
199	u32	xxx3[2];
200
201	u32	dmyf;
202	u32	dmxf;
203	u32	xxx4[2];
204	u32	ebyi;
205	u32	ebxi;
206	u32	xxx5[2];
207	u32	by;
208	u32	bx;
209	u32	dy;
210	u32	dx;
211	u32	bh;
212	u32	bw;
213	u32	xxx6[2];
214
215	u32	xxx7[32];
216
217	/* Setup unit vertex state register */
218	u32	suvtx;
219	u32	xxx8[63];
220
221	/* Control registers */
222	u32	ppc;
223	u32	wid;
224	u32	fg;
225	u32	bg;
226	u32	consty;
227	u32	constz;
228	u32	xclip;
229	u32	dcss;
230	u32	vclipmin;
231	u32	vclipmax;
232	u32	vclipzmin;
233	u32	vclipzmax;
234	u32	dcsf;
235	u32	dcsb;
236	u32	dczf;
237	u32	dczb;
238
239	u32	xxx9;
240	u32	blendc;
241	u32	blendc1;
242	u32	blendc2;
243	u32	fbramitc;
244	u32	fbc;
245	u32	rop;
246	u32	cmp;
247	u32	matchab;
248	u32	matchc;
249	u32	magnab;
250	u32	magnc;
251	u32	fbcfg0;
252	u32	fbcfg1;
253	u32	fbcfg2;
254	u32	fbcfg3;
255
256	u32	ppcfg;
257	u32	pick;
258	u32	fillmode;
259	u32	fbramwac;
260	u32	pmask;
261	u32	xpmask;
262	u32	ypmask;
263	u32	zpmask;
264	u32	clip0min;
265	u32	clip0max;
266	u32	clip1min;
267	u32	clip1max;
268	u32	clip2min;
269	u32	clip2max;
270	u32	clip3min;
271	u32	clip3max;
272
273	/* New 3dRAM III support regs */
274	u32	rawblend2;
275	u32	rawpreblend;
276	u32	rawstencil;
277	u32	rawstencilctl;
278	u32	threedram1;
279	u32	threedram2;
280	u32	passin;
281	u32	rawclrdepth;
282	u32	rawpmask;
283	u32	rawcsrc;
284	u32	rawmatch;
285	u32	rawmagn;
286	u32	rawropblend;
287	u32	rawcmp;
288	u32	rawwac;
289	u32	fbramid;
290
291	u32	drawop;
292	u32	xxx10[2];
293	u32	fontlpat;
294	u32	xxx11;
295	u32	fontxy;
296	u32	fontw;
297	u32	fontinc;
298	u32	font;
299	u32	xxx12[3];
300	u32	blend2;
301	u32	preblend;
302	u32	stencil;
303	u32	stencilctl;
304
305	u32	xxx13[4];
306	u32	dcss1;
307	u32	dcss2;
308	u32	dcss3;
309	u32	widpmask;
310	u32	dcs2;
311	u32	dcs3;
312	u32	dcs4;
313	u32	xxx14;
314	u32	dcd2;
315	u32	dcd3;
316	u32	dcd4;
317	u32	xxx15;
318
319	u32	pattern[32];
320
321	u32	xxx16[256];
322
323	u32	devid;
324	u32	xxx17[63];
325
326	u32	ucsr;
327	u32	xxx18[31];
328
329	u32	mer;
330};
331
332struct ffb_dac {
333	u32	type;
334	u32	value;
335	u32	type2;
336	u32	value2;
337};
338
339#define FFB_DAC_UCTRL	0x1001 /* User Control */
340#define  FFB_DAC_UCTRL_MANREV	0x00000f00 /* 4-bit Manufacturing Revision */
341#define  FFB_DAC_UCTRL_MANREV_SHIFT 8
342#define FFB_DAC_TGEN	0x6000 /* Timing Generator */
343#define  FFB_DAC_TGEN_VIDE	0x00000001 /* Video Enable */
344#define FFB_DAC_DID	0x8000 /* Device Identification */
345#define  FFB_DAC_DID_PNUM	0x0ffff000 /* Device Part Number */
346#define  FFB_DAC_DID_PNUM_SHIFT 12
347#define  FFB_DAC_DID_REV	0xf0000000 /* Device Revision */
348#define  FFB_DAC_DID_REV_SHIFT 28
349
350#define FFB_DAC_CUR_CTRL	0x100
351#define  FFB_DAC_CUR_CTRL_P0	0x00000001
352#define  FFB_DAC_CUR_CTRL_P1	0x00000002
353
354struct ffb_par {
355	spinlock_t		lock;
356	struct ffb_fbc __iomem	*fbc;
357	struct ffb_dac __iomem	*dac;
358
359	u32			flags;
360#define FFB_FLAG_AFB		0x00000001 /* AFB m3 or m6 */
361#define FFB_FLAG_BLANKED	0x00000002 /* screen is blanked */
362#define FFB_FLAG_INVCURSOR	0x00000004 /* DAC has inverted cursor logic */
363
364	u32			fg_cache __attribute__((aligned (8)));
365	u32			bg_cache;
366	u32			rop_cache;
367
368	int			fifo_cache;
369
370	unsigned long		physbase;
371	unsigned long		fbsize;
372
373	int			board_type;
374};
375
376static void FFBFifo(struct ffb_par *par, int n)
377{
378	struct ffb_fbc __iomem *fbc;
379	int cache = par->fifo_cache;
380
381	if (cache - n < 0) {
382		fbc = par->fbc;
383		do {	cache = (upa_readl(&fbc->ucsr) & FFB_UCSR_FIFO_MASK) - 8;
384		} while (cache - n < 0);
385	}
386	par->fifo_cache = cache - n;
387}
388
389static void FFBWait(struct ffb_par *par)
390{
391	struct ffb_fbc __iomem *fbc;
392	int limit = 10000;
393
394	fbc = par->fbc;
395	do {
396		if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_BUSY) == 0)
397			break;
398		if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) {
399			upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
400		}
401		udelay(10);
402	} while(--limit > 0);
403}
404
405static int ffb_sync(struct fb_info *p)
406{
407	struct ffb_par *par = (struct ffb_par *) p->par;
408
409	FFBWait(par);
410	return 0;
411}
412
413static __inline__ void ffb_rop(struct ffb_par *par, u32 rop)
414{
415	if (par->rop_cache != rop) {
416		FFBFifo(par, 1);
417		upa_writel(rop, &par->fbc->rop);
418		par->rop_cache = rop;
419	}
420}
421
422static void ffb_switch_from_graph(struct ffb_par *par)
423{
424	struct ffb_fbc __iomem *fbc = par->fbc;
425	struct ffb_dac __iomem *dac = par->dac;
426	unsigned long flags;
427
428	spin_lock_irqsave(&par->lock, flags);
429	FFBWait(par);
430	par->fifo_cache = 0;
431	FFBFifo(par, 7);
432	upa_writel(FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|
433		   FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST,
434		   &fbc->ppc);
435	upa_writel(0x2000707f, &fbc->fbc);
436	upa_writel(par->rop_cache, &fbc->rop);
437	upa_writel(0xffffffff, &fbc->pmask);
438	upa_writel((1 << 16) | (0 << 0), &fbc->fontinc);
439	upa_writel(par->fg_cache, &fbc->fg);
440	upa_writel(par->bg_cache, &fbc->bg);
441	FFBWait(par);
442
443	/* Disable cursor.  */
444	upa_writel(FFB_DAC_CUR_CTRL, &dac->type2);
445	if (par->flags & FFB_FLAG_INVCURSOR)
446		upa_writel(0, &dac->value2);
447	else
448		upa_writel((FFB_DAC_CUR_CTRL_P0 |
449			    FFB_DAC_CUR_CTRL_P1), &dac->value2);
450
451	spin_unlock_irqrestore(&par->lock, flags);
452}
453
454static int ffb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
455{
456	struct ffb_par *par = (struct ffb_par *) info->par;
457
458	/* We just use this to catch switches out of
459	 * graphics mode.
460	 */
461	ffb_switch_from_graph(par);
462
463	if (var->xoffset || var->yoffset || var->vmode)
464		return -EINVAL;
465	return 0;
466}
467
468/**
469 *      ffb_fillrect - REQUIRED function. Can use generic routines if
470 *                     non acclerated hardware and packed pixel based.
471 *                     Draws a rectangle on the screen.
472 *
473 *      @info: frame buffer structure that represents a single frame buffer
474 *      @rect: structure defining the rectagle and operation.
475 */
476static void ffb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
477{
478	struct ffb_par *par = (struct ffb_par *) info->par;
479	struct ffb_fbc __iomem *fbc = par->fbc;
480	unsigned long flags;
481	u32 fg;
482
483	BUG_ON(rect->rop != ROP_COPY && rect->rop != ROP_XOR);
484
485	fg = ((u32 *)info->pseudo_palette)[rect->color];
486
487	spin_lock_irqsave(&par->lock, flags);
488
489	if (fg != par->fg_cache) {
490		FFBFifo(par, 1);
491		upa_writel(fg, &fbc->fg);
492		par->fg_cache = fg;
493	}
494
495	ffb_rop(par, (rect->rop == ROP_COPY ?
496		      FFB_ROP_NEW :
497		      FFB_ROP_NEW_XOR_OLD));
498
499	FFBFifo(par, 5);
500	upa_writel(FFB_DRAWOP_RECTANGLE, &fbc->drawop);
501	upa_writel(rect->dy, &fbc->by);
502	upa_writel(rect->dx, &fbc->bx);
503	upa_writel(rect->height, &fbc->bh);
504	upa_writel(rect->width, &fbc->bw);
505
506	spin_unlock_irqrestore(&par->lock, flags);
507}
508
509/**
510 *      ffb_copyarea - REQUIRED function. Can use generic routines if
511 *                     non acclerated hardware and packed pixel based.
512 *                     Copies on area of the screen to another area.
513 *
514 *      @info: frame buffer structure that represents a single frame buffer
515 *      @area: structure defining the source and destination.
516 */
517
518static void
519ffb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
520{
521	struct ffb_par *par = (struct ffb_par *) info->par;
522	struct ffb_fbc __iomem *fbc = par->fbc;
523	unsigned long flags;
524
525	if (area->dx != area->sx ||
526	    area->dy == area->sy) {
527		cfb_copyarea(info, area);
528		return;
529	}
530
531	spin_lock_irqsave(&par->lock, flags);
532
533	ffb_rop(par, FFB_ROP_OLD);
534
535	FFBFifo(par, 7);
536	upa_writel(FFB_DRAWOP_VSCROLL, &fbc->drawop);
537	upa_writel(area->sy, &fbc->by);
538	upa_writel(area->sx, &fbc->bx);
539	upa_writel(area->dy, &fbc->dy);
540	upa_writel(area->dx, &fbc->dx);
541	upa_writel(area->height, &fbc->bh);
542	upa_writel(area->width, &fbc->bw);
543
544	spin_unlock_irqrestore(&par->lock, flags);
545}
546
547/**
548 *      ffb_imageblit - REQUIRED function. Can use generic routines if
549 *                      non acclerated hardware and packed pixel based.
550 *                      Copies a image from system memory to the screen.
551 *
552 *      @info: frame buffer structure that represents a single frame buffer
553 *      @image: structure defining the image.
554 */
555static void ffb_imageblit(struct fb_info *info, const struct fb_image *image)
556{
557	struct ffb_par *par = (struct ffb_par *) info->par;
558	struct ffb_fbc __iomem *fbc = par->fbc;
559	const u8 *data = image->data;
560	unsigned long flags;
561	u32 fg, bg, xy;
562	u64 fgbg;
563	int i, width, stride;
564
565	if (image->depth > 1) {
566		cfb_imageblit(info, image);
567		return;
568	}
569
570	fg = ((u32 *)info->pseudo_palette)[image->fg_color];
571	bg = ((u32 *)info->pseudo_palette)[image->bg_color];
572	fgbg = ((u64) fg << 32) | (u64) bg;
573	xy = (image->dy << 16) | image->dx;
574	width = image->width;
575	stride = ((width + 7) >> 3);
576
577	spin_lock_irqsave(&par->lock, flags);
578
579	if (fgbg != *(u64 *)&par->fg_cache) {
580		FFBFifo(par, 2);
581		upa_writeq(fgbg, &fbc->fg);
582		*(u64 *)&par->fg_cache = fgbg;
583	}
584
585	if (width >= 32) {
586		FFBFifo(par, 1);
587		upa_writel(32, &fbc->fontw);
588	}
589
590	while (width >= 32) {
591		const u8 *next_data = data + 4;
592
593		FFBFifo(par, 1);
594		upa_writel(xy, &fbc->fontxy);
595		xy += (32 << 0);
596
597		for (i = 0; i < image->height; i++) {
598			u32 val = (((u32)data[0] << 24) |
599				   ((u32)data[1] << 16) |
600				   ((u32)data[2] <<  8) |
601				   ((u32)data[3] <<  0));
602			FFBFifo(par, 1);
603			upa_writel(val, &fbc->font);
604
605			data += stride;
606		}
607
608		data = next_data;
609		width -= 32;
610	}
611
612	if (width) {
613		FFBFifo(par, 2);
614		upa_writel(width, &fbc->fontw);
615		upa_writel(xy, &fbc->fontxy);
616
617		for (i = 0; i < image->height; i++) {
618			u32 val = (((u32)data[0] << 24) |
619				   ((u32)data[1] << 16) |
620				   ((u32)data[2] <<  8) |
621				   ((u32)data[3] <<  0));
622			FFBFifo(par, 1);
623			upa_writel(val, &fbc->font);
624
625			data += stride;
626		}
627	}
628
629	spin_unlock_irqrestore(&par->lock, flags);
630}
631
632static void ffb_fixup_var_rgb(struct fb_var_screeninfo *var)
633{
634	var->red.offset = 0;
635	var->red.length = 8;
636	var->green.offset = 8;
637	var->green.length = 8;
638	var->blue.offset = 16;
639	var->blue.length = 8;
640	var->transp.offset = 0;
641	var->transp.length = 0;
642}
643
644/**
645 *      ffb_setcolreg - Optional function. Sets a color register.
646 *      @regno: boolean, 0 copy local, 1 get_user() function
647 *      @red: frame buffer colormap structure
648 *      @green: The green value which can be up to 16 bits wide
649 *      @blue:  The blue value which can be up to 16 bits wide.
650 *      @transp: If supported the alpha value which can be up to 16 bits wide.
651 *      @info: frame buffer info structure
652 */
653static int ffb_setcolreg(unsigned regno,
654			 unsigned red, unsigned green, unsigned blue,
655			 unsigned transp, struct fb_info *info)
656{
657	u32 value;
658
659	if (regno >= 16)
660		return 1;
661
662	red >>= 8;
663	green >>= 8;
664	blue >>= 8;
665
666	value = (blue << 16) | (green << 8) | red;
667	((u32 *)info->pseudo_palette)[regno] = value;
668
669	return 0;
670}
671
672/**
673 *      ffb_blank - Optional function.  Blanks the display.
674 *      @blank_mode: the blank mode we want.
675 *      @info: frame buffer structure that represents a single frame buffer
676 */
677static int
678ffb_blank(int blank, struct fb_info *info)
679{
680	struct ffb_par *par = (struct ffb_par *) info->par;
681	struct ffb_dac __iomem *dac = par->dac;
682	unsigned long flags;
683	u32 val;
684	int i;
685
686	spin_lock_irqsave(&par->lock, flags);
687
688	FFBWait(par);
689
690	upa_writel(FFB_DAC_TGEN, &dac->type);
691	val = upa_readl(&dac->value);
692	switch (blank) {
693	case FB_BLANK_UNBLANK: /* Unblanking */
694		val |= FFB_DAC_TGEN_VIDE;
695		par->flags &= ~FFB_FLAG_BLANKED;
696		break;
697
698	case FB_BLANK_NORMAL: /* Normal blanking */
699	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
700	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
701	case FB_BLANK_POWERDOWN: /* Poweroff */
702		val &= ~FFB_DAC_TGEN_VIDE;
703		par->flags |= FFB_FLAG_BLANKED;
704		break;
705	}
706	upa_writel(FFB_DAC_TGEN, &dac->type);
707	upa_writel(val, &dac->value);
708	for (i = 0; i < 10; i++) {
709		upa_writel(FFB_DAC_TGEN, &dac->type);
710		upa_readl(&dac->value);
711	}
712
713	spin_unlock_irqrestore(&par->lock, flags);
714
715	return 0;
716}
717
718static struct sbus_mmap_map ffb_mmap_map[] = {
719	{
720		.voff	= FFB_SFB8R_VOFF,
721		.poff	= FFB_SFB8R_POFF,
722		.size	= 0x0400000
723	},
724	{
725		.voff	= FFB_SFB8G_VOFF,
726		.poff	= FFB_SFB8G_POFF,
727		.size	= 0x0400000
728	},
729	{
730		.voff	= FFB_SFB8B_VOFF,
731		.poff	= FFB_SFB8B_POFF,
732		.size	= 0x0400000
733	},
734	{
735		.voff	= FFB_SFB8X_VOFF,
736		.poff	= FFB_SFB8X_POFF,
737		.size	= 0x0400000
738	},
739	{
740		.voff	= FFB_SFB32_VOFF,
741		.poff	= FFB_SFB32_POFF,
742		.size	= 0x1000000
743	},
744	{
745		.voff	= FFB_SFB64_VOFF,
746		.poff	= FFB_SFB64_POFF,
747		.size	= 0x2000000
748	},
749	{
750		.voff	= FFB_FBC_REGS_VOFF,
751		.poff	= FFB_FBC_REGS_POFF,
752		.size	= 0x0002000
753	},
754	{
755		.voff	= FFB_BM_FBC_REGS_VOFF,
756		.poff	= FFB_BM_FBC_REGS_POFF,
757		.size	= 0x0002000
758	},
759	{
760		.voff	= FFB_DFB8R_VOFF,
761		.poff	= FFB_DFB8R_POFF,
762		.size	= 0x0400000
763	},
764	{
765		.voff	= FFB_DFB8G_VOFF,
766		.poff	= FFB_DFB8G_POFF,
767		.size	= 0x0400000
768	},
769	{
770		.voff	= FFB_DFB8B_VOFF,
771		.poff	= FFB_DFB8B_POFF,
772		.size	= 0x0400000
773	},
774	{
775		.voff	= FFB_DFB8X_VOFF,
776		.poff	= FFB_DFB8X_POFF,
777		.size	= 0x0400000
778	},
779	{
780		.voff	= FFB_DFB24_VOFF,
781		.poff	= FFB_DFB24_POFF,
782		.size	= 0x1000000
783	},
784	{
785		.voff	= FFB_DFB32_VOFF,
786		.poff	= FFB_DFB32_POFF,
787		.size	= 0x1000000
788	},
789	{
790		.voff	= FFB_FBC_KREGS_VOFF,
791		.poff	= FFB_FBC_KREGS_POFF,
792		.size	= 0x0002000
793	},
794	{
795		.voff	= FFB_DAC_VOFF,
796		.poff	= FFB_DAC_POFF,
797		.size	= 0x0002000
798	},
799	{
800		.voff	= FFB_PROM_VOFF,
801		.poff	= FFB_PROM_POFF,
802		.size	= 0x0010000
803	},
804	{
805		.voff	= FFB_EXP_VOFF,
806		.poff	= FFB_EXP_POFF,
807		.size	= 0x0002000
808	},
809	{
810		.voff	= FFB_DFB422A_VOFF,
811		.poff	= FFB_DFB422A_POFF,
812		.size	= 0x0800000
813	},
814	{
815		.voff	= FFB_DFB422AD_VOFF,
816		.poff	= FFB_DFB422AD_POFF,
817		.size	= 0x0800000
818	},
819	{
820		.voff	= FFB_DFB24B_VOFF,
821		.poff	= FFB_DFB24B_POFF,
822		.size	= 0x1000000
823	},
824	{
825		.voff	= FFB_DFB422B_VOFF,
826		.poff	= FFB_DFB422B_POFF,
827		.size	= 0x0800000
828	},
829	{
830		.voff	= FFB_DFB422BD_VOFF,
831		.poff	= FFB_DFB422BD_POFF,
832		.size	= 0x0800000
833	},
834	{
835		.voff	= FFB_SFB16Z_VOFF,
836		.poff	= FFB_SFB16Z_POFF,
837		.size	= 0x0800000
838	},
839	{
840		.voff	= FFB_SFB8Z_VOFF,
841		.poff	= FFB_SFB8Z_POFF,
842		.size	= 0x0800000
843	},
844	{
845		.voff	= FFB_SFB422_VOFF,
846		.poff	= FFB_SFB422_POFF,
847		.size	= 0x0800000
848	},
849	{
850		.voff	= FFB_SFB422D_VOFF,
851		.poff	= FFB_SFB422D_POFF,
852		.size	= 0x0800000
853	},
854	{ .size = 0 }
855};
856
857static int ffb_mmap(struct fb_info *info, struct vm_area_struct *vma)
858{
859	struct ffb_par *par = (struct ffb_par *)info->par;
860
861	return sbusfb_mmap_helper(ffb_mmap_map,
862				  par->physbase, par->fbsize,
863				  0, vma);
864}
865
866static int ffb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
867{
868	struct ffb_par *par = (struct ffb_par *) info->par;
869
870	return sbusfb_ioctl_helper(cmd, arg, info,
871				   FBTYPE_CREATOR, 24, par->fbsize);
872}
873
874/*
875 *  Initialisation
876 */
877
878static void
879ffb_init_fix(struct fb_info *info)
880{
881	struct ffb_par *par = (struct ffb_par *)info->par;
882	const char *ffb_type_name;
883
884	if (!(par->flags & FFB_FLAG_AFB)) {
885		if ((par->board_type & 0x7) == 0x3)
886			ffb_type_name = "Creator 3D";
887		else
888			ffb_type_name = "Creator";
889	} else
890		ffb_type_name = "Elite 3D";
891
892	strlcpy(info->fix.id, ffb_type_name, sizeof(info->fix.id));
893
894	info->fix.type = FB_TYPE_PACKED_PIXELS;
895	info->fix.visual = FB_VISUAL_TRUECOLOR;
896
897	/* Framebuffer length is the same regardless of resolution. */
898	info->fix.line_length = 8192;
899
900	info->fix.accel = FB_ACCEL_SUN_CREATOR;
901}
902
903struct all_info {
904	struct fb_info info;
905	struct ffb_par par;
906	u32 pseudo_palette[16];
907};
908
909static int ffb_init_one(struct of_device *op)
910{
911	struct device_node *dp = op->node;
912	struct ffb_fbc __iomem *fbc;
913	struct ffb_dac __iomem *dac;
914	struct all_info *all;
915	int err;
916	u32 dac_pnum, dac_rev, dac_mrev;
917
918	all = kzalloc(sizeof(*all), GFP_KERNEL);
919	if (!all)
920		return -ENOMEM;
921
922	spin_lock_init(&all->par.lock);
923	all->par.fbc = of_ioremap(&op->resource[2], 0,
924				  sizeof(struct ffb_fbc), "ffb fbc");
925	if (!all->par.fbc) {
926		kfree(all);
927		return -ENOMEM;
928	}
929
930	all->par.dac = of_ioremap(&op->resource[1], 0,
931				  sizeof(struct ffb_dac), "ffb dac");
932	if (!all->par.dac) {
933		of_iounmap(&op->resource[2],
934			   all->par.fbc, sizeof(struct ffb_fbc));
935		kfree(all);
936		return -ENOMEM;
937	}
938
939	all->par.rop_cache = FFB_ROP_NEW;
940	all->par.physbase = op->resource[0].start;
941
942	/* Don't mention copyarea, so SCROLL_REDRAW is always
943	 * used.  It is the fastest on this chip.
944	 */
945	all->info.flags = (FBINFO_DEFAULT |
946			   /* FBINFO_HWACCEL_COPYAREA | */
947			   FBINFO_HWACCEL_FILLRECT |
948			   FBINFO_HWACCEL_IMAGEBLIT);
949	all->info.fbops = &ffb_ops;
950	all->info.screen_base = (char *) all->par.physbase + FFB_DFB24_POFF;
951	all->info.par = &all->par;
952	all->info.pseudo_palette = all->pseudo_palette;
953
954	sbusfb_fill_var(&all->info.var, dp->node, 32);
955	all->par.fbsize = PAGE_ALIGN(all->info.var.xres *
956				     all->info.var.yres *
957				     4);
958	ffb_fixup_var_rgb(&all->info.var);
959
960	all->info.var.accel_flags = FB_ACCELF_TEXT;
961
962	if (!strcmp(dp->name, "SUNW,afb"))
963		all->par.flags |= FFB_FLAG_AFB;
964
965	all->par.board_type = of_getintprop_default(dp, "board_type", 0);
966
967	fbc = all->par.fbc;
968	if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)
969		upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
970
971	dac = all->par.dac;
972	upa_writel(FFB_DAC_DID, &dac->type);
973	dac_pnum = upa_readl(&dac->value);
974	dac_rev = (dac_pnum & FFB_DAC_DID_REV) >> FFB_DAC_DID_REV_SHIFT;
975	dac_pnum = (dac_pnum & FFB_DAC_DID_PNUM) >> FFB_DAC_DID_PNUM_SHIFT;
976
977	upa_writel(FFB_DAC_UCTRL, &dac->type);
978	dac_mrev = upa_readl(&dac->value);
979	dac_mrev = (dac_mrev & FFB_DAC_UCTRL_MANREV) >>
980		FFB_DAC_UCTRL_MANREV_SHIFT;
981
982	/* Elite3D has different DAC revision numbering, and no DAC revisions
983	 * have the reversed meaning of cursor enable.  Otherwise, Pacifica 1
984	 * ramdacs with manufacturing revision less than 3 have inverted
985	 * cursor logic.  We identify Pacifica 1 as not Pacifica 2, the
986	 * latter having a part number value of 0x236e.
987	 */
988	if ((all->par.flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) {
989		all->par.flags &= ~FFB_FLAG_INVCURSOR;
990	} else {
991		if (dac_mrev < 3)
992			all->par.flags |= FFB_FLAG_INVCURSOR;
993	}
994
995	ffb_switch_from_graph(&all->par);
996
997	/* Unblank it just to be sure.  When there are multiple
998	 * FFB/AFB cards in the system, or it is not the OBP
999	 * chosen console, it will have video outputs off in
1000	 * the DAC.
1001	 */
1002	ffb_blank(0, &all->info);
1003
1004	if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
1005		printk(KERN_ERR "ffb: Could not allocate color map.\n");
1006		of_iounmap(&op->resource[2],
1007			   all->par.fbc, sizeof(struct ffb_fbc));
1008		of_iounmap(&op->resource[1],
1009			   all->par.dac, sizeof(struct ffb_dac));
1010		kfree(all);
1011		return -ENOMEM;
1012	}
1013
1014	ffb_init_fix(&all->info);
1015
1016	err = register_framebuffer(&all->info);
1017	if (err < 0) {
1018		printk(KERN_ERR "ffb: Could not register framebuffer.\n");
1019		fb_dealloc_cmap(&all->info.cmap);
1020		of_iounmap(&op->resource[2],
1021			   all->par.fbc, sizeof(struct ffb_fbc));
1022		of_iounmap(&op->resource[1],
1023			   all->par.dac, sizeof(struct ffb_dac));
1024		kfree(all);
1025		return err;
1026	}
1027
1028	dev_set_drvdata(&op->dev, all);
1029
1030	printk("%s: %s at %016lx, type %d, "
1031	       "DAC pnum[%x] rev[%d] manuf_rev[%d]\n",
1032	       dp->full_name,
1033	       ((all->par.flags & FFB_FLAG_AFB) ? "AFB" : "FFB"),
1034	       all->par.physbase, all->par.board_type,
1035	       dac_pnum, dac_rev, dac_mrev);
1036
1037	return 0;
1038}
1039
1040static int __devinit ffb_probe(struct of_device *dev, const struct of_device_id *match)
1041{
1042	struct of_device *op = to_of_device(&dev->dev);
1043
1044	return ffb_init_one(op);
1045}
1046
1047static int __devexit ffb_remove(struct of_device *op)
1048{
1049	struct all_info *all = dev_get_drvdata(&op->dev);
1050
1051	unregister_framebuffer(&all->info);
1052	fb_dealloc_cmap(&all->info.cmap);
1053
1054	of_iounmap(&op->resource[2], all->par.fbc, sizeof(struct ffb_fbc));
1055	of_iounmap(&op->resource[1], all->par.dac, sizeof(struct ffb_dac));
1056
1057	kfree(all);
1058
1059	dev_set_drvdata(&op->dev, NULL);
1060
1061	return 0;
1062}
1063
1064static struct of_device_id ffb_match[] = {
1065	{
1066		.name = "SUNW,ffb",
1067	},
1068	{
1069		.name = "SUNW,afb",
1070	},
1071	{},
1072};
1073MODULE_DEVICE_TABLE(of, ffb_match);
1074
1075static struct of_platform_driver ffb_driver = {
1076	.name		= "ffb",
1077	.match_table	= ffb_match,
1078	.probe		= ffb_probe,
1079	.remove		= __devexit_p(ffb_remove),
1080};
1081
1082int __init ffb_init(void)
1083{
1084	if (fb_get_options("ffb", NULL))
1085		return -ENODEV;
1086
1087	return of_register_driver(&ffb_driver, &of_bus_type);
1088}
1089
1090void __exit ffb_exit(void)
1091{
1092	of_unregister_driver(&ffb_driver);
1093}
1094
1095module_init(ffb_init);
1096module_exit(ffb_exit);
1097
1098MODULE_DESCRIPTION("framebuffer driver for Creator/Elite3D chipsets");
1099MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
1100MODULE_VERSION("2.0");
1101MODULE_LICENSE("GPL");
1102