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