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