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)
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>
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>
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
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 */
87 #define FFB_PPC_FW_DISABLE 0x800000
88 #define FFB_PPC_FW_ENABLE 0xc00000
90 #define FFB_PPC_ACE_DISABLE 0x040000
91 #define FFB_PPC_ACE_AUX_SUB 0x080000
92 #define FFB_PPC_ACE_AUX_ADD 0x0c0000
94 #define FFB_PPC_DCE_DISABLE 0x020000
95 #define FFB_PPC_DCE_ENABLE 0x030000
97 #define FFB_PPC_ABE_DISABLE 0x008000
98 #define FFB_PPC_ABE_ENABLE 0x00c000
100 #define FFB_PPC_VCE_DISABLE 0x001000
101 #define FFB_PPC_VCE_2D 0x002000
102 #define FFB_PPC_VCE_3D 0x003000
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
110 #define FFB_PPC_ZS_VAR 0x000080
111 #define FFB_PPC_ZS_CONST 0x0000c0
113 #define FFB_PPC_YS_VAR 0x000020
114 #define FFB_PPC_YS_CONST 0x000030
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)
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
156 /* Setup unit vertex state register */
160 /* Control registers */
169 volatile u32 vclipmin
;
170 volatile u32 vclipmax
;
171 volatile u32 vclipzmin
;
172 volatile u32 vclipzmax
;
180 volatile u32 blendc1
;
181 volatile u32 blendc2
;
182 volatile u32 fbramitc
;
186 volatile u32 matchab
;
197 volatile u32 fillmode
;
198 volatile u32 fbramwac
;
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
;
220 volatile u32 rawclrdepth
;
221 volatile u32 rawpmask
;
222 volatile u32 rawcsrc
;
223 volatile u32 rawmatch
;
224 volatile u32 rawmagn
;
225 volatile u32 rawropblend
;
228 volatile u32 fbramid
;
232 volatile u32 fontlpat
;
236 volatile u32 fontinc
;
240 volatile u32 preblend
;
241 volatile u32 stencil
;
242 volatile u32 stencilctl
;
248 volatile u32 widpmask
;
258 volatile u32 pattern
[32];
271 static __inline__
void FFBFifo(struct fb_info_sbusfb
*fb
, int n
)
274 int cache
= fb
->s
.ffb
.fifo_cache
;
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
)
289 if((ffb
->ucsr
& FFB_UCSR_ALL_BUSY
) == 0)
291 if((ffb
->ucsr
& FFB_UCSR_ALL_ERRORS
) != 0)
292 ffb
->ucsr
= FFB_UCSR_ALL_ERRORS
;
293 } while(--limit
> 0);
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 },
325 static void ffb_setup(struct display
*p
)
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
;
339 fg
= ((u32
*)p
->dispsw_data
)[attr_bgcol_ec(p
,conp
)];
340 if (fg
!= fb
->s
.ffb
.fg_cache
) {
343 fb
->s
.ffb
.fg_cache
= fg
;
347 if (fontheightlog(p
)) {
348 yx
= (u64
)sy
<< (fontheightlog(p
) + 32); hw
= (u64
)height
<< (fontheightlog(p
) + 32);
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
);
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
;
367 fg
= ((u32
*)p
->dispsw_data
)[attr_bgcol(p
,s
)];
368 if (fg
!= fb
->s
.ffb
.fg_cache
) {
371 fb
->s
.ffb
.fg_cache
= fg
;
373 while (count
-- > 0) {
377 fbc
->bh
= boxes
[3] - boxes
[1];
378 fbc
->bw
= boxes
[2] - boxes
[0];
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
;
391 if (fontheightlog(p
)) {
392 xy
= (yy
<< (16 + fontheightlog(p
)));
393 i
= ((c
& p
->charmask
) << fontheightlog(p
));
395 xy
= ((yy
* fontheight(p
)) << 16);
396 i
= (c
& p
->charmask
) * fontheight(p
);
398 if (fontwidth(p
) <= 8)
399 fd
= p
->fontdata
+ i
;
401 fd
= p
->fontdata
+ (i
<< 1);
403 xy
+= (xx
<< fontwidthlog(p
)) + fb
->s
.ffb
.xy_margin
;
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
) {
410 *(volatile u64
*)&fbc
->fg
= fgbg
;
411 *(u64
*)&fb
->s
.ffb
.fg_cache
= fgbg
;
413 FFBFifo(fb
, 2 + fontheight(p
));
415 fbc
->fontw
= fontwidth(p
);
416 if (fontwidth(p
) <= 8) {
417 for (i
= 0; i
< fontheight(p
); i
++)
418 fbc
->font
= *fd
++ << 24;
420 for (i
= 0; i
< fontheight(p
); i
++) {
421 fbc
->font
= *(u16
*)fd
<< 16;
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
;
433 u8
*fd1
, *fd2
, *fd3
, *fd4
;
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
) {
440 *(volatile u64
*)&fbc
->fg
= fgbg
;
441 *(u64
*)&fb
->s
.ffb
.fg_cache
= fgbg
;
443 xy
= fb
->s
.ffb
.xy_margin
;
445 xy
+= (xx
<< fontwidthlog(p
));
447 xy
+= xx
* fontwidth(p
);
448 if (fontheightlog(p
))
449 xy
+= (yy
<< (16 + fontheightlog(p
)));
451 xy
+= ((yy
* fontheight(p
)) << 16);
452 if (fontwidth(p
) <= 8) {
455 FFBFifo(fb
, 2 + fontheight(p
));
456 fbc
->fontw
= 4 * fontwidth(p
);
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
));
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
++)
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
);
484 FFBFifo(fb
, 2 + fontheight(p
));
485 fbc
->fontw
= 2 * fontwidth(p
);
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));
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
));
498 xy
+= 2 * fontwidth(p
);
503 FFBFifo(fb
, 2 + fontheight(p
));
504 fbc
->fontw
= fontwidth(p
);
506 if (fontheightlog(p
))
507 i
= ((scr_readw(s
++) & p
->charmask
) << fontheightlog(p
));
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;
515 fd1
= p
->fontdata
+ (i
<< 1);
516 for (i
= 0; i
< fontheight(p
); i
++) {
517 fbc
->font
= *(u16
*)fd1
<< 16;
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
;
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);
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
);
564 static inline void ffb_curs_enable (struct fb_info_sbusfb
*fb
, int enable
)
566 struct ffb_dac
*dac
= fb
->s
.ffb
.dac
;
569 if (fb
->s
.ffb
.dac_rev
<= 2)
570 dac
->value2
= enable
? 3 : 0;
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);
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
;
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
];
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
;
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
;
625 fb
->s
.ffb
.fifo_cache
= 0;
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
;
638 static int __init
ffb_rasterimg (struct fb_info
*info
, int start
)
640 ffb_switch_from_graph (sbusfbinfo(info
));
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
];
656 struct fb_ops
*fbops
;
658 if (prom_getproperty(fb
->prom_node
, "reg", (void *) regs
, sizeof(regs
)) <= 0)
661 disp
->dispsw_data
= (void *)kmalloc(16 * sizeof(u32
), GFP_KERNEL
);
662 if (!disp
->dispsw_data
)
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"))
677 btype
= prom_getintdefault(fb
->prom_node
, "board_type", 0);
679 strcpy(fb
->info
.modename
, "Creator");
681 if ((btype
& 7) == 3)
682 strcpy(fix
->id
, "Creator 3D");
684 strcpy(fix
->id
, "Creator");
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
;
713 /* If there are any read errors or fifo overflow conditions,
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;
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 */
739 fb
->s
.ffb
.dac_rev
= 10;