Import 2.3.16
[davej-history.git] / drivers / video / creatorfb.c
blobe2fefe0f4990781945e6ea27021e289210a2e28d
1 /* $Id: creatorfb.c,v 1.29 1999/08/10 15:56:07 davem Exp $
2 * creatorfb.c: Creator/Creator3D frame buffer driver
4 * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
5 */
7 #include <linux/module.h>
8 #include <linux/sched.h>
9 #include <linux/kernel.h>
10 #include <linux/errno.h>
11 #include <linux/string.h>
12 #include <linux/mm.h>
13 #include <linux/tty.h>
14 #include <linux/malloc.h>
15 #include <linux/vmalloc.h>
16 #include <linux/delay.h>
17 #include <linux/interrupt.h>
18 #include <linux/fb.h>
19 #include <linux/init.h>
20 #include <linux/selection.h>
22 #include <video/sbusfb.h>
24 #define FFB_SFB8R_VOFF 0x00000000
25 #define FFB_SFB8G_VOFF 0x00400000
26 #define FFB_SFB8B_VOFF 0x00800000
27 #define FFB_SFB8X_VOFF 0x00c00000
28 #define FFB_SFB32_VOFF 0x01000000
29 #define FFB_SFB64_VOFF 0x02000000
30 #define FFB_FBC_REGS_VOFF 0x04000000
31 #define FFB_BM_FBC_REGS_VOFF 0x04002000
32 #define FFB_DFB8R_VOFF 0x04004000
33 #define FFB_DFB8G_VOFF 0x04404000
34 #define FFB_DFB8B_VOFF 0x04804000
35 #define FFB_DFB8X_VOFF 0x04c04000
36 #define FFB_DFB24_VOFF 0x05004000
37 #define FFB_DFB32_VOFF 0x06004000
38 #define FFB_DFB422A_VOFF 0x07004000 /* DFB 422 mode write to A */
39 #define FFB_DFB422AD_VOFF 0x07804000 /* DFB 422 mode with line doubling */
40 #define FFB_DFB24B_VOFF 0x08004000 /* DFB 24bit mode write to B */
41 #define FFB_DFB422B_VOFF 0x09004000 /* DFB 422 mode write to B */
42 #define FFB_DFB422BD_VOFF 0x09804000 /* DFB 422 mode with line doubling */
43 #define FFB_SFB16Z_VOFF 0x0a004000 /* 16bit mode Z planes */
44 #define FFB_SFB8Z_VOFF 0x0a404000 /* 8bit mode Z planes */
45 #define FFB_SFB422_VOFF 0x0ac04000 /* SFB 422 mode write to A/B */
46 #define FFB_SFB422D_VOFF 0x0b404000 /* SFB 422 mode with line doubling */
47 #define FFB_FBC_KREGS_VOFF 0x0bc04000
48 #define FFB_DAC_VOFF 0x0bc06000
49 #define FFB_PROM_VOFF 0x0bc08000
50 #define FFB_EXP_VOFF 0x0bc18000
52 #define FFB_SFB8R_POFF 0x04000000
53 #define FFB_SFB8G_POFF 0x04400000
54 #define FFB_SFB8B_POFF 0x04800000
55 #define FFB_SFB8X_POFF 0x04c00000
56 #define FFB_SFB32_POFF 0x05000000
57 #define FFB_SFB64_POFF 0x06000000
58 #define FFB_FBC_REGS_POFF 0x00600000
59 #define FFB_BM_FBC_REGS_POFF 0x00600000
60 #define FFB_DFB8R_POFF 0x01000000
61 #define FFB_DFB8G_POFF 0x01400000
62 #define FFB_DFB8B_POFF 0x01800000
63 #define FFB_DFB8X_POFF 0x01c00000
64 #define FFB_DFB24_POFF 0x02000000
65 #define FFB_DFB32_POFF 0x03000000
66 #define FFB_FBC_KREGS_POFF 0x00610000
67 #define FFB_DAC_POFF 0x00400000
68 #define FFB_PROM_POFF 0x00000000
69 #define FFB_EXP_POFF 0x00200000
71 /* Draw operations */
72 #define FFB_DRAWOP_DOT 0x00
73 #define FFB_DRAWOP_AADOT 0x01
74 #define FFB_DRAWOP_BRLINECAP 0x02
75 #define FFB_DRAWOP_BRLINEOPEN 0x03
76 #define FFB_DRAWOP_DDLINE 0x04
77 #define FFB_DRAWOP_AALINE 0x05
78 #define FFB_DRAWOP_TRIANGLE 0x06
79 #define FFB_DRAWOP_POLYGON 0x07
80 #define FFB_DRAWOP_RECTANGLE 0x08
81 #define FFB_DRAWOP_FASTFILL 0x09
82 #define FFB_DRAWOP_BCOPY 0x0a
83 #define FFB_DRAWOP_VSCROLL 0x0b
85 /* Pixel processor control */
86 /* Force WID */
87 #define FFB_PPC_FW_DISABLE 0x800000
88 #define FFB_PPC_FW_ENABLE 0xc00000
89 /* Auxiliary clip */
90 #define FFB_PPC_ACE_DISABLE 0x040000
91 #define FFB_PPC_ACE_AUX_SUB 0x080000
92 #define FFB_PPC_ACE_AUX_ADD 0x0c0000
93 /* Depth cue */
94 #define FFB_PPC_DCE_DISABLE 0x020000
95 #define FFB_PPC_DCE_ENABLE 0x030000
96 /* Alpha blend */
97 #define FFB_PPC_ABE_DISABLE 0x008000
98 #define FFB_PPC_ABE_ENABLE 0x00c000
99 /* View clip */
100 #define FFB_PPC_VCE_DISABLE 0x001000
101 #define FFB_PPC_VCE_2D 0x002000
102 #define FFB_PPC_VCE_3D 0x003000
103 /* Area pattern */
104 #define FFB_PPC_APE_DISABLE 0x000800
105 #define FFB_PPC_APE_ENABLE 0x000c00
106 /* Transparent background */
107 #define FFB_PPC_TBE_OPAQUE 0x000200
108 #define FFB_PPC_TBE_TRANSPARENT 0x000300
109 /* Z source */
110 #define FFB_PPC_ZS_VAR 0x000080
111 #define FFB_PPC_ZS_CONST 0x0000c0
112 /* Y source */
113 #define FFB_PPC_YS_VAR 0x000020
114 #define FFB_PPC_YS_CONST 0x000030
115 /* X source */
116 #define FFB_PPC_XS_WID 0x000004
117 #define FFB_PPC_XS_VAR 0x000008
118 #define FFB_PPC_XS_CONST 0x00000c
119 /* Color (BGR) source */
120 #define FFB_PPC_CS_VAR 0x000002
121 #define FFB_PPC_CS_CONST 0x000003
123 #define FFB_ROP_NEW 0x83
125 #define FFB_UCSR_FIFO_MASK 0x00000fff
126 #define FFB_UCSR_FB_BUSY 0x01000000
127 #define FFB_UCSR_RP_BUSY 0x02000000
128 #define FFB_UCSR_ALL_BUSY (FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY)
129 #define FFB_UCSR_READ_ERR 0x40000000
130 #define FFB_UCSR_FIFO_OVFL 0x80000000
131 #define FFB_UCSR_ALL_ERRORS (FFB_UCSR_READ_ERR|FFB_UCSR_FIFO_OVFL)
133 struct ffb_fbc {
134 /* Next vertex registers */
135 u32 xxx1[3]; volatile u32 alpha; volatile u32 red;
136 volatile u32 green; volatile u32 blue; volatile u32 depth; volatile
137 u32 y; volatile u32 x; u32 xxx2[2]; volatile u32 ryf; volatile u32
138 rxf; u32 xxx3[2];
140 volatile u32 dmyf;
141 volatile u32 dmxf;
142 u32 xxx4[2];
143 volatile u32 ebyi;
144 volatile u32 ebxi;
145 u32 xxx5[2];
146 volatile u32 by;
147 volatile u32 bx;
148 u32 dy;
149 u32 dx;
150 volatile u32 bh;
151 volatile u32 bw;
152 u32 xxx6[2];
154 u32 xxx7[32];
156 /* Setup unit vertex state register */
157 volatile u32 suvtx;
158 u32 xxx8[63];
160 /* Control registers */
161 volatile u32 ppc;
162 volatile u32 wid;
163 volatile u32 fg;
164 volatile u32 bg;
165 volatile u32 consty;
166 volatile u32 constz;
167 volatile u32 xclip;
168 volatile u32 dcss;
169 volatile u32 vclipmin;
170 volatile u32 vclipmax;
171 volatile u32 vclipzmin;
172 volatile u32 vclipzmax;
173 volatile u32 dcsf;
174 volatile u32 dcsb;
175 volatile u32 dczf;
176 volatile u32 dczb;
178 u32 xxx9;
179 volatile u32 blendc;
180 volatile u32 blendc1;
181 volatile u32 blendc2;
182 volatile u32 fbramitc;
183 volatile u32 fbc;
184 volatile u32 rop;
185 volatile u32 cmp;
186 volatile u32 matchab;
187 volatile u32 matchc;
188 volatile u32 magnab;
189 volatile u32 magnc;
190 volatile u32 fbcfg0;
191 volatile u32 fbcfg1;
192 volatile u32 fbcfg2;
193 volatile u32 fbcfg3;
195 u32 ppcfg;
196 volatile u32 pick;
197 volatile u32 fillmode;
198 volatile u32 fbramwac;
199 volatile u32 pmask;
200 volatile u32 xpmask;
201 volatile u32 ypmask;
202 volatile u32 zpmask;
203 volatile u32 clip0min;
204 volatile u32 clip0max;
205 volatile u32 clip1min;
206 volatile u32 clip1max;
207 volatile u32 clip2min;
208 volatile u32 clip2max;
209 volatile u32 clip3min;
210 volatile u32 clip3max;
212 /* New 3dRAM III support regs */
213 volatile u32 rawblend2;
214 volatile u32 rawpreblend;
215 volatile u32 rawstencil;
216 volatile u32 rawstencilctl;
217 volatile u32 threedram1;
218 volatile u32 threedram2;
219 volatile u32 passin;
220 volatile u32 rawclrdepth;
221 volatile u32 rawpmask;
222 volatile u32 rawcsrc;
223 volatile u32 rawmatch;
224 volatile u32 rawmagn;
225 volatile u32 rawropblend;
226 volatile u32 rawcmp;
227 volatile u32 rawwac;
228 volatile u32 fbramid;
230 volatile u32 drawop;
231 u32 xxx10[2];
232 volatile u32 fontlpat;
233 u32 xxx11;
234 volatile u32 fontxy;
235 volatile u32 fontw;
236 volatile u32 fontinc;
237 volatile u32 font;
238 u32 xxx12[3];
239 volatile u32 blend2;
240 volatile u32 preblend;
241 volatile u32 stencil;
242 volatile u32 stencilctl;
244 u32 xxx13[4];
245 volatile u32 dcss1;
246 volatile u32 dcss2;
247 volatile u32 dcss3;
248 volatile u32 widpmask;
249 volatile u32 dcs2;
250 volatile u32 dcs3;
251 volatile u32 dcs4;
252 u32 xxx14;
253 volatile u32 dcd2;
254 volatile u32 dcd3;
255 volatile u32 dcd4;
256 u32 xxx15;
258 volatile u32 pattern[32];
260 u32 xxx16[256];
262 volatile u32 devid;
263 u32 xxx17[63];
265 volatile u32 ucsr;
266 u32 xxx18[31];
268 volatile u32 mer;
271 static __inline__ void FFBFifo(struct fb_info_sbusfb *fb, int n)
273 struct ffb_fbc *fbc;
274 int cache = fb->s.ffb.fifo_cache;
276 if (cache - n < 0) {
277 fbc = fb->s.ffb.fbc;
278 do { cache = (fbc->ucsr & FFB_UCSR_FIFO_MASK) - 8;
279 } while (cache - n < 0);
281 fb->s.ffb.fifo_cache = cache - n;
284 static __inline__ void FFBWait(struct ffb_fbc *ffb)
286 int limit = 10000;
288 do {
289 if((ffb->ucsr & FFB_UCSR_ALL_BUSY) == 0)
290 break;
291 if((ffb->ucsr & FFB_UCSR_ALL_ERRORS) != 0)
292 ffb->ucsr = FFB_UCSR_ALL_ERRORS;
293 } while(--limit > 0);
296 struct ffb_dac {
297 volatile u32 type;
298 volatile u32 value;
299 volatile u32 type2;
300 volatile u32 value2;
303 static struct sbus_mmap_map ffb_mmap_map[] = {
304 { FFB_SFB8R_VOFF, FFB_SFB8R_POFF, 0x0400000 },
305 { FFB_SFB8G_VOFF, FFB_SFB8G_POFF, 0x0400000 },
306 { FFB_SFB8B_VOFF, FFB_SFB8B_POFF, 0x0400000 },
307 { FFB_SFB8X_VOFF, FFB_SFB8X_POFF, 0x0400000 },
308 { FFB_SFB32_VOFF, FFB_SFB32_POFF, 0x1000000 },
309 { FFB_SFB64_VOFF, FFB_SFB64_POFF, 0x2000000 },
310 { FFB_FBC_REGS_VOFF, FFB_FBC_REGS_POFF, 0x0002000 },
311 { FFB_BM_FBC_REGS_VOFF, FFB_BM_FBC_REGS_POFF, 0x0002000 },
312 { FFB_DFB8R_VOFF, FFB_DFB8R_POFF, 0x0400000 },
313 { FFB_DFB8G_VOFF, FFB_DFB8G_POFF, 0x0400000 },
314 { FFB_DFB8B_VOFF, FFB_DFB8B_POFF, 0x0400000 },
315 { FFB_DFB8X_VOFF, FFB_DFB8X_POFF, 0x0400000 },
316 { FFB_DFB24_VOFF, FFB_DFB24_POFF, 0x1000000 },
317 { FFB_DFB32_VOFF, FFB_DFB32_POFF, 0x1000000 },
318 { FFB_FBC_KREGS_VOFF, FFB_FBC_KREGS_POFF, 0x0002000 },
319 { FFB_DAC_VOFF, FFB_DAC_POFF, 0x0002000 },
320 { FFB_PROM_VOFF, FFB_PROM_POFF, 0x0010000 },
321 { FFB_EXP_VOFF, FFB_EXP_POFF, 0x0002000 },
322 { 0, 0, 0 }
325 static void ffb_setup(struct display *p)
327 p->next_line = 8192;
328 p->next_plane = 0;
331 static void ffb_clear(struct vc_data *conp, struct display *p, int sy, int sx,
332 int height, int width)
334 struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
335 register struct ffb_fbc *fbc = fb->s.ffb.fbc;
336 u64 yx, hw;
337 int fg;
339 fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)];
340 if (fg != fb->s.ffb.fg_cache) {
341 FFBFifo(fb, 5);
342 fbc->fg = fg;
343 fb->s.ffb.fg_cache = fg;
344 } else
345 FFBFifo(fb, 4);
347 if (fontheightlog(p)) {
348 yx = (u64)sy << (fontheightlog(p) + 32); hw = (u64)height << (fontheightlog(p) + 32);
349 } else {
350 yx = (u64)(sy * fontheight(p)) << 32; hw = (u64)(height * fontheight(p)) << 32;
352 if (fontwidthlog(p)) {
353 yx += sx << fontwidthlog(p); hw += width << fontwidthlog(p);
354 } else {
355 yx += sx * fontwidth(p); hw += width * fontwidth(p);
357 *(volatile u64 *)&fbc->by = yx + fb->s.ffb.yx_margin;
358 *(volatile u64 *)&fbc->bh = hw;
361 static void ffb_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
362 int count, unsigned short *boxes)
364 register struct ffb_fbc *fbc = fb->s.ffb.fbc;
365 int fg;
367 fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)];
368 if (fg != fb->s.ffb.fg_cache) {
369 FFBFifo(fb, 1);
370 fbc->fg = fg;
371 fb->s.ffb.fg_cache = fg;
373 while (count-- > 0) {
374 FFBFifo(fb, 4);
375 fbc->by = boxes[1];
376 fbc->bx = boxes[0];
377 fbc->bh = boxes[3] - boxes[1];
378 fbc->bw = boxes[2] - boxes[0];
379 boxes += 4;
383 static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
385 struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
386 register struct ffb_fbc *fbc = fb->s.ffb.fbc;
387 int i, xy;
388 u8 *fd;
389 u64 fgbg;
391 if (fontheightlog(p)) {
392 xy = (yy << (16 + fontheightlog(p)));
393 i = ((c & p->charmask) << fontheightlog(p));
394 } else {
395 xy = ((yy * fontheight(p)) << 16);
396 i = (c & p->charmask) * fontheight(p);
398 if (fontwidth(p) <= 8)
399 fd = p->fontdata + i;
400 else
401 fd = p->fontdata + (i << 1);
402 if (fontwidthlog(p))
403 xy += (xx << fontwidthlog(p)) + fb->s.ffb.xy_margin;
404 else
405 xy += (xx * fontwidth(p)) + fb->s.ffb.xy_margin;
406 fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p,c)])) << 32) |
407 ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
408 if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) {
409 FFBFifo(fb, 2);
410 *(volatile u64 *)&fbc->fg = fgbg;
411 *(u64 *)&fb->s.ffb.fg_cache = fgbg;
413 FFBFifo(fb, 2 + fontheight(p));
414 fbc->fontxy = xy;
415 fbc->fontw = fontwidth(p);
416 if (fontwidth(p) <= 8) {
417 for (i = 0; i < fontheight(p); i++)
418 fbc->font = *fd++ << 24;
419 } else {
420 for (i = 0; i < fontheight(p); i++) {
421 fbc->font = *(u16 *)fd << 16;
422 fd += 2;
427 static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
428 int count, int yy, int xx)
430 struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
431 register struct ffb_fbc *fbc = fb->s.ffb.fbc;
432 int i, xy;
433 u8 *fd1, *fd2, *fd3, *fd4;
434 u64 fgbg;
436 fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p,scr_readw(s))])) << 32) |
437 ((u32 *)p->dispsw_data)[attr_bgcol(p,scr_readw(s))];
438 if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) {
439 FFBFifo(fb, 2);
440 *(volatile u64 *)&fbc->fg = fgbg;
441 *(u64 *)&fb->s.ffb.fg_cache = fgbg;
443 xy = fb->s.ffb.xy_margin;
444 if (fontwidthlog(p))
445 xy += (xx << fontwidthlog(p));
446 else
447 xy += xx * fontwidth(p);
448 if (fontheightlog(p))
449 xy += (yy << (16 + fontheightlog(p)));
450 else
451 xy += ((yy * fontheight(p)) << 16);
452 if (fontwidth(p) <= 8) {
453 while (count >= 4) {
454 count -= 4;
455 FFBFifo(fb, 2 + fontheight(p));
456 fbc->fontw = 4 * fontwidth(p);
457 fbc->fontxy = xy;
458 if (fontheightlog(p)) {
459 fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
460 fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
461 fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
462 fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
463 } else {
464 fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
465 fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
466 fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
467 fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
469 if (fontwidth(p) == 8) {
470 for (i = 0; i < fontheight(p); i++)
471 fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++)
472 << 8)) << 8)) << 8);
473 xy += 32;
474 } else {
475 for (i = 0; i < fontheight(p); i++)
476 fbc->font = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++)
477 << fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
478 xy += 4 * fontwidth(p);
481 } else {
482 while (count >= 2) {
483 count -= 2;
484 FFBFifo(fb, 2 + fontheight(p));
485 fbc->fontw = 2 * fontwidth(p);
486 fbc->fontxy = xy;
487 if (fontheightlog(p)) {
488 fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
489 fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
490 } else {
491 fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
492 fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
494 for (i = 0; i < fontheight(p); i++) {
495 fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
496 fd1 += 2; fd2 += 2;
498 xy += 2 * fontwidth(p);
501 while (count) {
502 count--;
503 FFBFifo(fb, 2 + fontheight(p));
504 fbc->fontw = fontwidth(p);
505 fbc->fontxy = xy;
506 if (fontheightlog(p))
507 i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
508 else
509 i = ((scr_readw(s++) & p->charmask) * fontheight(p));
510 if (fontwidth(p) <= 8) {
511 fd1 = p->fontdata + i;
512 for (i = 0; i < fontheight(p); i++)
513 fbc->font = *fd1++ << 24;
514 } else {
515 fd1 = p->fontdata + (i << 1);
516 for (i = 0; i < fontheight(p); i++) {
517 fbc->font = *(u16 *)fd1 << 16;
518 fd1 += 2;
521 xy += fontwidth(p);
525 static void ffb_revc(struct display *p, int xx, int yy)
527 /* Not used if hw cursor */
530 static void ffb_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
532 struct ffb_dac *dac = fb->s.ffb.dac;
533 int i, j = count;
535 dac->type = 0x2000 | index;
536 for (i = index; j--; i++)
537 /* Feed the colors in :)) */
538 dac->value = ((fb->color_map CM(i,0))) |
539 ((fb->color_map CM(i,1)) << 8) |
540 ((fb->color_map CM(i,2)) << 16);
541 if (!p)
542 return;
543 for (i = index, j = count; i < 16 && j--; i++)
544 ((u32 *)p->dispsw_data)[i] = ((fb->color_map CM(i,0))) |
545 ((fb->color_map CM(i,1)) << 8) |
546 ((fb->color_map CM(i,2)) << 16);
549 static struct display_switch ffb_dispsw __initdata = {
550 ffb_setup, fbcon_redraw_bmove, ffb_clear, ffb_putc, ffb_putcs, ffb_revc,
551 NULL, NULL, NULL, FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */
554 static void ffb_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
556 register struct ffb_fbc *fbc = fb->s.ffb.fbc;
558 fb->s.ffb.xy_margin = (y_margin << 16) + x_margin;
559 fb->s.ffb.yx_margin = (((u64)y_margin) << 32) + x_margin;
560 p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin);
561 FFBWait(fbc);
564 static inline void ffb_curs_enable (struct fb_info_sbusfb *fb, int enable)
566 struct ffb_dac *dac = fb->s.ffb.dac;
568 dac->type2 = 0x100;
569 if (fb->s.ffb.dac_rev <= 2)
570 dac->value2 = enable ? 3 : 0;
571 else
572 dac->value2 = enable ? 0 : 3;
575 static void ffb_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
577 struct ffb_dac *dac = fb->s.ffb.dac;
579 ffb_curs_enable (fb, 0);
580 dac->type2 = 0x102;
581 dac->value2 = (red[0] | (green[0]<<8) | (blue[0]<<16));
582 dac->value2 = (red[1] | (green[1]<<8) | (blue[1]<<16));
585 /* Set cursor shape */
586 static void ffb_setcurshape (struct fb_info_sbusfb *fb)
588 struct ffb_dac *dac = fb->s.ffb.dac;
589 int i, j;
591 ffb_curs_enable (fb, 0);
592 for (j = 0; j < 2; j++) {
593 dac->type2 = j ? 0 : 0x80;
594 for (i = 0; i < 0x40; i++) {
595 if (fb->cursor.size.fbx <= 32) {
596 dac->value2 = fb->cursor.bits [j][i];
597 dac->value2 = 0;
598 } else {
599 dac->value2 = fb->cursor.bits [j][2*i];
600 dac->value2 = fb->cursor.bits [j][2*i+1];
606 /* Load cursor information */
607 static void ffb_setcursor (struct fb_info_sbusfb *fb)
609 struct ffb_dac *dac = fb->s.ffb.dac;
610 struct cg_cursor *c = &fb->cursor;
612 dac->type2 = 0x104;
613 /* Should this be just 0x7ff??
614 Should I do some margin handling and setcurshape in that case? */
615 dac->value2 = (((c->cpos.fby - c->chot.fby) & 0xffff) << 16)
616 |((c->cpos.fbx - c->chot.fbx) & 0xffff);
617 ffb_curs_enable (fb, fb->cursor.enable);
620 static void ffb_switch_from_graph (struct fb_info_sbusfb *fb)
622 register struct ffb_fbc *fbc = fb->s.ffb.fbc;
624 FFBWait(fbc);
625 fb->s.ffb.fifo_cache = 0;
626 FFBFifo(fb, 8);
627 fbc->ppc = FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST;
628 fbc->fbc = 0x2000707f;
629 fbc->rop = FFB_ROP_NEW;
630 fbc->drawop = FFB_DRAWOP_RECTANGLE;
631 fbc->pmask = 0xffffffff;
632 fbc->fontinc = 0x10000;
633 fbc->fg = fb->s.ffb.fg_cache;
634 fbc->bg = fb->s.ffb.bg_cache;
635 FFBWait(fbc);
638 static int __init ffb_rasterimg (struct fb_info *info, int start)
640 ffb_switch_from_graph (sbusfbinfo(info));
641 return 0;
644 static char idstring[60] __initdata = { 0 };
646 char __init *creatorfb_init(struct fb_info_sbusfb *fb)
648 struct fb_fix_screeninfo *fix = &fb->fix;
649 struct fb_var_screeninfo *var = &fb->var;
650 struct display *disp = &fb->disp;
651 struct fbtype *type = &fb->type;
652 struct linux_prom64_registers regs[2*PROMREG_MAX];
653 int i, afb = 0;
654 unsigned int btype;
655 char name[64];
656 struct fb_ops *fbops;
658 if (prom_getproperty(fb->prom_node, "reg", (void *) regs, sizeof(regs)) <= 0)
659 return NULL;
661 disp->dispsw_data = (void *)kmalloc(16 * sizeof(u32), GFP_KERNEL);
662 if (!disp->dispsw_data)
663 return NULL;
664 memset(disp->dispsw_data, 0, 16 * sizeof(u32));
666 fbops = kmalloc(sizeof(*fbops), GFP_KERNEL);
667 if (!fbops) return NULL;
669 *fbops = *fb->info.fbops;
670 fbops->fb_rasterimg = ffb_rasterimg;
671 fb->info.fbops = fbops;
673 prom_getstring(fb->prom_node, "name", name, sizeof(name));
674 if (!strcmp(name, "SUNW,afb"))
675 afb = 1;
677 btype = prom_getintdefault(fb->prom_node, "board_type", 0);
679 strcpy(fb->info.modename, "Creator");
680 if (!afb) {
681 if ((btype & 7) == 3)
682 strcpy(fix->id, "Creator 3D");
683 else
684 strcpy(fix->id, "Creator");
685 } else
686 strcpy(fix->id, "Elite 3D");
688 fix->visual = FB_VISUAL_TRUECOLOR;
689 fix->line_length = 8192;
690 fix->accel = FB_ACCEL_SUN_CREATOR;
692 var->bits_per_pixel = 32;
693 var->green.offset = 8;
694 var->blue.offset = 16;
695 var->accel_flags = FB_ACCELF_TEXT;
697 disp->scrollmode = SCROLL_YREDRAW;
698 disp->screen_base = (char *)__va(regs[0].phys_addr) + FFB_DFB24_POFF + 8192 * fb->y_margin + 4 * fb->x_margin;
699 fb->s.ffb.xy_margin = (fb->y_margin << 16) + fb->x_margin;
700 fb->s.ffb.yx_margin = (((u64)fb->y_margin) << 32) + fb->x_margin;
701 fb->s.ffb.fbc = (struct ffb_fbc *)((char *)__va(regs[0].phys_addr) + FFB_FBC_REGS_POFF);
702 fb->s.ffb.dac = (struct ffb_dac *)((char *)__va(regs[0].phys_addr) + FFB_DAC_POFF);
703 fb->dispsw = ffb_dispsw;
705 fb->margins = ffb_margins;
706 fb->loadcmap = ffb_loadcmap;
707 fb->setcursor = ffb_setcursor;
708 fb->setcursormap = ffb_setcursormap;
709 fb->setcurshape = ffb_setcurshape;
710 fb->switch_from_graph = ffb_switch_from_graph;
711 fb->fill = ffb_fill;
713 /* If there are any read errors or fifo overflow conditions,
714 * clear them now.
716 if((fb->s.ffb.fbc->ucsr & FFB_UCSR_ALL_ERRORS) != 0)
717 fb->s.ffb.fbc->ucsr = FFB_UCSR_ALL_ERRORS;
719 ffb_switch_from_graph(fb);
721 fb->physbase = regs[0].phys_addr;
722 fb->mmap_map = ffb_mmap_map;
724 fb->cursor.hwsize.fbx = 64;
725 fb->cursor.hwsize.fby = 64;
727 type->fb_depth = 24;
729 fb->s.ffb.dac->type = 0x8000;
730 fb->s.ffb.dac_rev = (fb->s.ffb.dac->value >> 0x1c);
732 i = prom_getintdefault (fb->prom_node, "board_type", 8);
734 sprintf(idstring, "%s at %016lx type %d DAC %d", fix->id, regs[0].phys_addr, i, fb->s.ffb.dac_rev);
736 /* Elite3D has different DAC revision numbering, and no DAC revisions
737 have the reversed meaning of cursor enable */
738 if (afb)
739 fb->s.ffb.dac_rev = 10;
741 return idstring;