2.2.0-final
[davej-history.git] / drivers / video / creatorfb.c
blob69242992df1d76812de0e601669e5990c7817583
1 /* $Id: creatorfb.c,v 1.17 1998/12/28 11:23:37 jj Exp $
2 * creatorfb.c: Creator/Creator3D frame buffer driver
4 * Copyright (C) 1997,1998 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];
136 volatile u32 alpha;
137 volatile u32 red;
138 volatile u32 green;
139 volatile u32 blue;
140 volatile u32 depth;
141 volatile u32 y;
142 volatile u32 x;
143 u32 xxx2[2];
144 volatile u32 ryf;
145 volatile u32 rxf;
146 u32 xxx3[2];
148 volatile u32 dmyf;
149 volatile u32 dmxf;
150 u32 xxx4[2];
151 volatile u32 ebyi;
152 volatile u32 ebxi;
153 u32 xxx5[2];
154 volatile u32 by;
155 volatile u32 bx;
156 u32 dy;
157 u32 dx;
158 volatile u32 bh;
159 volatile u32 bw;
160 u32 xxx6[2];
162 u32 xxx7[32];
164 /* Setup unit vertex state register */
165 volatile u32 suvtx;
166 u32 xxx8[63];
168 /* Control registers */
169 volatile u32 ppc;
170 volatile u32 wid;
171 volatile u32 fg;
172 volatile u32 bg;
173 volatile u32 consty;
174 volatile u32 constz;
175 volatile u32 xclip;
176 volatile u32 dcss;
177 volatile u32 vclipmin;
178 volatile u32 vclipmax;
179 volatile u32 vclipzmin;
180 volatile u32 vclipzmax;
181 volatile u32 dcsf;
182 volatile u32 dcsb;
183 volatile u32 dczf;
184 volatile u32 dczb;
186 u32 xxx9;
187 volatile u32 blendc;
188 volatile u32 blendc1;
189 volatile u32 blendc2;
190 volatile u32 fbramitc;
191 volatile u32 fbc;
192 volatile u32 rop;
193 volatile u32 cmp;
194 volatile u32 matchab;
195 volatile u32 matchc;
196 volatile u32 magnab;
197 volatile u32 magnc;
198 volatile u32 fbcfg0;
199 volatile u32 fbcfg1;
200 volatile u32 fbcfg2;
201 volatile u32 fbcfg3;
203 u32 ppcfg;
204 volatile u32 pick;
205 volatile u32 fillmode;
206 volatile u32 fbramwac;
207 volatile u32 pmask;
208 volatile u32 xpmask;
209 volatile u32 ypmask;
210 volatile u32 zpmask;
211 volatile u32 clip0min;
212 volatile u32 clip0max;
213 volatile u32 clip1min;
214 volatile u32 clip1max;
215 volatile u32 clip2min;
216 volatile u32 clip2max;
217 volatile u32 clip3min;
218 volatile u32 clip3max;
220 /* New 3dRAM III support regs */
221 volatile u32 rawblend2;
222 volatile u32 rawpreblend;
223 volatile u32 rawstencil;
224 volatile u32 rawstencilctl;
225 volatile u32 threedram1;
226 volatile u32 threedram2;
227 volatile u32 passin;
228 volatile u32 rawclrdepth;
229 volatile u32 rawpmask;
230 volatile u32 rawcsrc;
231 volatile u32 rawmatch;
232 volatile u32 rawmagn;
233 volatile u32 rawropblend;
234 volatile u32 rawcmp;
235 volatile u32 rawwac;
236 volatile u32 fbramid;
238 volatile u32 drawop;
239 u32 xxx10[2];
240 volatile u32 fontlpat;
241 u32 xxx11;
242 volatile u32 fontxy;
243 volatile u32 fontw;
244 volatile u32 fontinc;
245 volatile u32 font;
246 u32 xxx12[3];
247 volatile u32 blend2;
248 volatile u32 preblend;
249 volatile u32 stencil;
250 volatile u32 stencilctl;
252 u32 xxx13[4];
253 volatile u32 dcss1;
254 volatile u32 dcss2;
255 volatile u32 dcss3;
256 volatile u32 widpmask;
257 volatile u32 dcs2;
258 volatile u32 dcs3;
259 volatile u32 dcs4;
260 u32 xxx14;
261 volatile u32 dcd2;
262 volatile u32 dcd3;
263 volatile u32 dcd4;
264 u32 xxx15;
266 volatile u32 pattern[32];
268 u32 xxx16[256];
270 volatile u32 devid;
271 u32 xxx17[63];
273 volatile u32 ucsr;
274 u32 xxx18[31];
276 volatile u32 mer;
279 static __inline__ void FFBFifo(struct ffb_fbc *ffb, int n)
281 int limit = 10000;
283 do {
284 if((ffb->ucsr & FFB_UCSR_FIFO_MASK) >= (n + 4))
285 break;
286 if((ffb->ucsr & FFB_UCSR_ALL_ERRORS) != 0)
287 ffb->ucsr = FFB_UCSR_ALL_ERRORS;
288 } while(--limit > 0);
291 static __inline__ void FFBWait(struct ffb_fbc *ffb)
293 int limit = 10000;
295 do {
296 if((ffb->ucsr & FFB_UCSR_ALL_BUSY) == 0)
297 break;
298 if((ffb->ucsr & FFB_UCSR_ALL_ERRORS) != 0)
299 ffb->ucsr = FFB_UCSR_ALL_ERRORS;
300 } while(--limit > 0);
303 struct ffb_dac {
304 volatile u32 type;
305 volatile u32 value;
306 volatile u32 type2;
307 volatile u32 value2;
310 static struct sbus_mmap_map ffb_mmap_map[] = {
311 { FFB_SFB8R_VOFF, FFB_SFB8R_POFF, 0x0400000 },
312 { FFB_SFB8G_VOFF, FFB_SFB8G_POFF, 0x0400000 },
313 { FFB_SFB8B_VOFF, FFB_SFB8B_POFF, 0x0400000 },
314 { FFB_SFB8X_VOFF, FFB_SFB8X_POFF, 0x0400000 },
315 { FFB_SFB32_VOFF, FFB_SFB32_POFF, 0x1000000 },
316 { FFB_SFB64_VOFF, FFB_SFB64_POFF, 0x2000000 },
317 { FFB_FBC_REGS_VOFF, FFB_FBC_REGS_POFF, 0x0002000 },
318 { FFB_BM_FBC_REGS_VOFF, FFB_BM_FBC_REGS_POFF, 0x0002000 },
319 { FFB_DFB8R_VOFF, FFB_DFB8R_POFF, 0x0400000 },
320 { FFB_DFB8G_VOFF, FFB_DFB8G_POFF, 0x0400000 },
321 { FFB_DFB8B_VOFF, FFB_DFB8B_POFF, 0x0400000 },
322 { FFB_DFB8X_VOFF, FFB_DFB8X_POFF, 0x0400000 },
323 { FFB_DFB24_VOFF, FFB_DFB24_POFF, 0x1000000 },
324 { FFB_DFB32_VOFF, FFB_DFB32_POFF, 0x1000000 },
325 { FFB_FBC_KREGS_VOFF, FFB_FBC_KREGS_POFF, 0x0002000 },
326 { FFB_DAC_VOFF, FFB_DAC_POFF, 0x0002000 },
327 { FFB_PROM_VOFF, FFB_PROM_POFF, 0x0010000 },
328 { FFB_EXP_VOFF, FFB_EXP_POFF, 0x0002000 },
329 { 0, 0, 0 }
332 static void ffb_setup(struct display *p)
334 p->next_line = 8192;
335 p->next_plane = 0;
338 static void ffb_clear(struct vc_data *conp, struct display *p, int sy, int sx,
339 int height, int width)
341 struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
342 register struct ffb_fbc *fbc = fb->s.ffb.fbc;
343 int x, y, w, h;
345 FFBWait(fbc);
346 FFBFifo(fbc, 6);
347 fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)];
348 fbc->drawop = FFB_DRAWOP_RECTANGLE;
350 if (fontheightlog(p)) {
351 y = sy << fontheightlog(p); h = height << fontheightlog(p);
352 } else {
353 y = sy * fontheight(p); h = height * fontheight(p);
355 if (fontwidthlog(p)) {
356 x = sx << fontwidthlog(p); w = width << fontwidthlog(p);
357 } else {
358 x = sx * fontwidth(p); w = width * fontwidth(p);
360 fbc->by = y + fb->y_margin;
361 fbc->bx = x + fb->x_margin;
362 fbc->bh = h;
363 fbc->bw = w;
366 static void ffb_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
367 int count, unsigned short *boxes)
369 register struct ffb_fbc *fbc = fb->s.ffb.fbc;
371 FFBWait(fbc);
372 FFBFifo(fbc, 2);
373 fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)];
374 fbc->drawop = FFB_DRAWOP_RECTANGLE;
375 while (count-- > 0) {
376 FFBFifo(fbc, 4);
377 fbc->by = boxes[1];
378 fbc->bx = boxes[0];
379 fbc->bh = boxes[3] - boxes[1];
380 fbc->bw = boxes[2] - boxes[0];
381 boxes += 4;
385 static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
387 struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
388 register struct ffb_fbc *fbc = fb->s.ffb.fbc;
389 int i, xy;
390 u8 *fd;
392 if (fontheightlog(p)) {
393 xy = (yy << (16 + fontheightlog(p)));
394 i = ((c & p->charmask) << fontheightlog(p));
395 } else {
396 xy = ((yy * fontheight(p)) << 16);
397 i = (c & p->charmask) * fontheight(p);
399 if (fontwidth(p) <= 8)
400 fd = p->fontdata + i;
401 else
402 fd = p->fontdata + (i << 1);
403 if (fontwidthlog(p))
404 xy += (xx << fontwidthlog(p)) + fb->s.ffb.xy_margin;
405 else
406 xy += (xx * fontwidth(p)) + fb->s.ffb.xy_margin;
407 FFBWait(fbc);
408 FFBFifo(fbc, 5);
409 fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,c)];
410 fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
411 fbc->fontw = fontwidth(p);
412 fbc->fontinc = 0x10000;
413 fbc->fontxy = xy;
414 FFBFifo(fbc, fontheight(p));
415 if (fontwidth(p) <= 8) {
416 for (i = 0; i < fontheight(p); i++)
417 fbc->font = *fd++ << 24;
418 } else {
419 for (i = 0; i < fontheight(p); i++) {
420 fbc->font = *(u16 *)fd << 16;
421 fd += 2;
426 static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
427 int count, int yy, int xx)
429 struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
430 register struct ffb_fbc *fbc = fb->s.ffb.fbc;
431 int i, xy;
432 u8 *fd1, *fd2, *fd3, *fd4;
434 FFBWait(fbc);
435 FFBFifo(fbc, 2);
436 fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,*s)];
437 fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,*s)];
438 xy = fb->s.ffb.xy_margin;
439 if (fontwidthlog(p))
440 xy += (xx << fontwidthlog(p));
441 else
442 xy += xx * fontwidth(p);
443 if (fontheightlog(p))
444 xy += (yy << (16 + fontheightlog(p)));
445 else
446 xy += ((yy * fontheight(p)) << 16);
447 if (fontwidth(p) <= 8) {
448 while (count >= 4) {
449 count -= 4;
450 FFBFifo(fbc, 3);
451 fbc->fontw = 4 * fontwidth(p);
452 fbc->fontinc = 0x10000;
453 fbc->fontxy = xy;
454 if (fontheightlog(p)) {
455 fd1 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
456 fd2 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
457 fd3 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
458 fd4 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
459 } else {
460 fd1 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
461 fd2 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
462 fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
463 fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
465 FFBFifo(fbc, fontheight(p));
466 if (fontwidth(p) == 8) {
467 for (i = 0; i < fontheight(p); i++)
468 fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++)
469 << 8)) << 8)) << 8);
470 xy += 32;
471 } else {
472 for (i = 0; i < fontheight(p); i++)
473 fbc->font = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++)
474 << fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
475 xy += 4 * fontwidth(p);
478 } else {
479 while (count >= 2) {
480 count -= 2;
481 FFBFifo(fbc, 3);
482 fbc->fontw = 2 * fontwidth(p);
483 fbc->fontinc = 0x10000;
484 fbc->fontxy = xy;
485 if (fontheightlog(p)) {
486 fd1 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
487 fd2 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
488 } else {
489 fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
490 fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
492 FFBFifo(fbc, fontheight(p));
493 for (i = 0; i < fontheight(p); i++) {
494 fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
495 fd1 += 2; fd2 += 2;
497 xy += 2 * fontwidth(p);
500 while (count) {
501 count--;
502 FFBFifo(fbc, 3);
503 fbc->fontw = fontwidth(p);
504 fbc->fontinc = 0x10000;
505 fbc->fontxy = xy;
506 if (fontheightlog(p))
507 i = ((*s++ & p->charmask) << fontheightlog(p));
508 else
509 i = ((*s++ & p->charmask) * fontheight(p));
510 FFBFifo(fbc, fontheight(p));
511 if (fontwidth(p) <= 8) {
512 fd1 = p->fontdata + i;
513 for (i = 0; i < fontheight(p); i++)
514 fbc->font = *fd1++ << 24;
515 } else {
516 fd1 = p->fontdata + (i << 1);
517 for (i = 0; i < fontheight(p); i++) {
518 fbc->font = *(u16 *)fd1 << 16;
519 fd1 += 2;
522 xy += fontwidth(p);
526 static void ffb_revc(struct display *p, int xx, int yy)
528 /* Not used if hw cursor */
531 static void ffb_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
533 struct ffb_dac *dac = fb->s.ffb.dac;
534 int i, j = count;
536 dac->type = 0x2000 | index;
537 for (i = index; j--; i++)
538 /* Feed the colors in :)) */
539 dac->value = ((fb->color_map CM(i,0))) |
540 ((fb->color_map CM(i,1)) << 8) |
541 ((fb->color_map CM(i,2)) << 16);
542 if (!p)
543 return;
544 for (i = index, j = count; i < 16 && j--; i++)
545 ((u32 *)p->dispsw_data)[i] = ((fb->color_map CM(i,0))) |
546 ((fb->color_map CM(i,1)) << 8) |
547 ((fb->color_map CM(i,2)) << 16);
550 static struct display_switch ffb_dispsw __initdata = {
551 ffb_setup, fbcon_redraw_bmove, ffb_clear, ffb_putc, ffb_putcs, ffb_revc,
552 NULL, NULL, NULL, FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */
555 static void ffb_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
557 fb->s.ffb.xy_margin = (y_margin << 16) + x_margin;
558 p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin);
561 static inline void ffb_curs_enable (struct fb_info_sbusfb *fb, int enable)
563 struct ffb_dac *dac = fb->s.ffb.dac;
565 dac->type2 = 0x100;
566 if (fb->s.ffb.dac_rev <= 2)
567 dac->value2 = enable ? 3 : 0;
568 else
569 dac->value2 = enable ? 0 : 3;
572 static void ffb_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
574 struct ffb_dac *dac = fb->s.ffb.dac;
576 ffb_curs_enable (fb, 0);
577 dac->type2 = 0x102;
578 dac->value2 = (red[0] | (green[0]<<8) | (blue[0]<<16));
579 dac->value2 = (red[1] | (green[1]<<8) | (blue[1]<<16));
582 /* Set cursor shape */
583 static void ffb_setcurshape (struct fb_info_sbusfb *fb)
585 struct ffb_dac *dac = fb->s.ffb.dac;
586 int i, j;
588 ffb_curs_enable (fb, 0);
589 for (j = 0; j < 2; j++) {
590 dac->type2 = j ? 0 : 0x80;
591 for (i = 0; i < 0x40; i++) {
592 if (fb->cursor.size.fbx <= 32) {
593 dac->value2 = fb->cursor.bits [j][i];
594 dac->value2 = 0;
595 } else {
596 dac->value2 = fb->cursor.bits [j][2*i];
597 dac->value2 = fb->cursor.bits [j][2*i+1];
603 /* Load cursor information */
604 static void ffb_setcursor (struct fb_info_sbusfb *fb)
606 struct ffb_dac *dac = fb->s.ffb.dac;
607 struct cg_cursor *c = &fb->cursor;
609 dac->type2 = 0x104;
610 /* Should this be just 0x7ff??
611 Should I do some margin handling and setcurshape in that case? */
612 dac->value2 = (((c->cpos.fby - c->chot.fby) & 0xffff) << 16)
613 |((c->cpos.fbx - c->chot.fbx) & 0xffff);
614 ffb_curs_enable (fb, fb->cursor.enable);
617 static void ffb_switch_from_graph (struct fb_info_sbusfb *fb)
619 register struct ffb_fbc *fbc = fb->s.ffb.fbc;
621 FFBWait(fbc);
622 FFBFifo(fbc, 4);
623 fbc->ppc = FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST;
624 fbc->fbc = 0x2000707f;
625 fbc->rop = FFB_ROP_NEW;
626 fbc->pmask = 0xffffffff;
627 FFBWait(fbc);
630 static char idstring[60] __initdata = { 0 };
632 __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb))
634 struct fb_fix_screeninfo *fix = &fb->fix;
635 struct fb_var_screeninfo *var = &fb->var;
636 struct display *disp = &fb->disp;
637 struct fbtype *type = &fb->type;
638 struct linux_prom64_registers regs[2*PROMREG_MAX];
639 int i, afb = 0;
640 unsigned int btype;
641 char name[64];
643 if (prom_getproperty(fb->prom_node, "reg", (void *) regs, sizeof(regs)) <= 0)
644 return NULL;
646 disp->dispsw_data = (void *)kmalloc(16 * sizeof(u32), GFP_KERNEL);
647 if (!disp->dispsw_data)
648 return NULL;
649 memset(disp->dispsw_data, 0, 16 * sizeof(u32));
651 prom_getstring(fb->prom_node, "name", name, sizeof(name));
652 if (!strcmp(name, "SUNW,afb"))
653 afb = 1;
655 btype = prom_getintdefault(fb->prom_node, "board_type", 0);
657 strcpy(fb->info.modename, "Creator");
658 if (!afb) {
659 if ((btype & 7) == 3)
660 strcpy(fix->id, "Creator 3D");
661 else
662 strcpy(fix->id, "Creator");
663 } else
664 strcpy(fix->id, "Elite 3D");
666 fix->visual = FB_VISUAL_TRUECOLOR;
667 fix->line_length = 8192;
668 fix->accel = FB_ACCEL_SUN_CREATOR;
670 var->bits_per_pixel = 32;
671 var->green.offset = 8;
672 var->blue.offset = 16;
673 var->accel_flags = FB_ACCELF_TEXT;
675 disp->scrollmode = SCROLL_YREDRAW;
676 disp->screen_base = (char *)__va(regs[0].phys_addr) + FFB_DFB24_POFF + 8192 * fb->y_margin + 4 * fb->x_margin;
677 fb->s.ffb.xy_margin = (fb->y_margin << 16) + fb->x_margin;
678 fb->s.ffb.fbc = (struct ffb_fbc *)((char *)__va(regs[0].phys_addr) + FFB_FBC_REGS_POFF);
679 fb->s.ffb.dac = (struct ffb_dac *)((char *)__va(regs[0].phys_addr) + FFB_DAC_POFF);
680 fb->dispsw = ffb_dispsw;
682 fb->margins = ffb_margins;
683 fb->loadcmap = ffb_loadcmap;
684 fb->setcursor = ffb_setcursor;
685 fb->setcursormap = ffb_setcursormap;
686 fb->setcurshape = ffb_setcurshape;
687 fb->switch_from_graph = ffb_switch_from_graph;
688 fb->fill = ffb_fill;
690 /* If there are any read errors or fifo overflow conditions,
691 * clear them now.
693 if((fb->s.ffb.fbc->ucsr & FFB_UCSR_ALL_ERRORS) != 0)
694 fb->s.ffb.fbc->ucsr = FFB_UCSR_ALL_ERRORS;
696 ffb_switch_from_graph(fb);
698 fb->physbase = regs[0].phys_addr;
699 fb->mmap_map = ffb_mmap_map;
701 fb->cursor.hwsize.fbx = 64;
702 fb->cursor.hwsize.fby = 64;
704 type->fb_depth = 24;
706 fb->s.ffb.dac->type = 0x8000;
707 fb->s.ffb.dac_rev = (fb->s.ffb.dac->value >> 0x1c);
709 i = prom_getintdefault (fb->prom_node, "board_type", 8);
711 sprintf(idstring, "%s at %016lx type %d DAC %d", fix->id, regs[0].phys_addr, i, fb->s.ffb.dac_rev);
713 return idstring;