1 /* $Id: leofb.c,v 1.11 2000/07/26 23:02:52 davem Exp $
2 * leofb.c: Leo (ZX) 24/8bit frame buffer driver
4 * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
5 * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz)
8 #include <linux/module.h>
9 #include <linux/sched.h>
10 #include <linux/kernel.h>
11 #include <linux/errno.h>
12 #include <linux/string.h>
14 #include <linux/tty.h>
15 #include <linux/malloc.h>
16 #include <linux/vmalloc.h>
17 #include <linux/delay.h>
18 #include <linux/interrupt.h>
20 #include <linux/init.h>
21 #include <linux/selection.h>
23 #include <video/sbusfb.h>
26 #define LEO_OFF_LC_SS0_KRN 0x00200000UL
27 #define LEO_OFF_LC_SS0_USR 0x00201000UL
28 #define LEO_OFF_LC_SS1_KRN 0x01200000UL
29 #define LEO_OFF_LC_SS1_USR 0x01201000UL
30 #define LEO_OFF_LD_SS0 0x00400000UL
31 #define LEO_OFF_LD_SS1 0x01400000UL
32 #define LEO_OFF_LD_GBL 0x00401000UL
33 #define LEO_OFF_LX_KRN 0x00600000UL
34 #define LEO_OFF_LX_CURSOR 0x00601000UL
35 #define LEO_OFF_SS0 0x00800000UL
36 #define LEO_OFF_SS1 0x01800000UL
37 #define LEO_OFF_UNK 0x00602000UL
38 #define LEO_OFF_UNK2 0x00000000UL
40 #define LEO_CUR_ENABLE 0x00000080
41 #define LEO_CUR_UPDATE 0x00000030
42 #define LEO_CUR_PROGRESS 0x00000006
43 #define LEO_CUR_UPDATECMAP 0x00000003
45 #define LEO_CUR_TYPE_MASK 0x00000000
46 #define LEO_CUR_TYPE_IMAGE 0x00000020
47 #define LEO_CUR_TYPE_CMAP 0x00000050
51 volatile u32 cur_type
;
52 volatile u32 cur_misc
;
53 volatile u32 cur_cursxy
;
54 volatile u32 cur_data
;
57 #define LEO_KRN_TYPE_CLUT0 0x00001000
58 #define LEO_KRN_TYPE_CLUT1 0x00001001
59 #define LEO_KRN_TYPE_CLUT2 0x00001002
60 #define LEO_KRN_TYPE_WID 0x00001003
61 #define LEO_KRN_TYPE_UNK 0x00001006
62 #define LEO_KRN_TYPE_VIDEO 0x00002003
63 #define LEO_KRN_TYPE_CLUTDATA 0x00004000
64 #define LEO_KRN_CSR_ENABLE 0x00000008
65 #define LEO_KRN_CSR_PROGRESS 0x00000004
66 #define LEO_KRN_CSR_UNK 0x00000002
67 #define LEO_KRN_CSR_UNK2 0x00000001
70 volatile u32 krn_type
;
72 volatile u32 krn_value
;
75 struct leo_lc_ss0_krn
{
81 struct leo_lc_ss0_usr
{
83 volatile u32 addrspace
;
93 struct leo_lc_ss1_krn
{
97 struct leo_lc_ss1_usr
{
106 volatile u32 widclip
;
107 volatile u32 vclipmin
;
108 volatile u32 vclipmax
;
109 volatile u32 pickmin
; /* SS1 only */
110 volatile u32 pickmax
; /* SS1 only */
113 volatile u32 src
; /* Copy/Scroll (SS0 only) */
114 volatile u32 dst
; /* Copy/Scroll/Fill (SS0 only) */
115 volatile u32 extent
; /* Copy/Scroll/Fill size (SS0 only) */
117 volatile u32 setsem
; /* SS1 only */
118 volatile u32 clrsem
; /* SS1 only */
119 volatile u32 clrpick
; /* SS1 only */
120 volatile u32 clrdat
; /* SS1 only */
121 volatile u32 alpha
; /* SS1 only */
124 volatile u32 planemask
;
127 volatile u32 dczf
; /* SS1 only */
128 volatile u32 dczb
; /* SS1 only */
129 volatile u32 dcs
; /* SS1 only */
130 volatile u32 dczs
; /* SS1 only */
131 volatile u32 pickfb
; /* SS1 only */
132 volatile u32 pickbb
; /* SS1 only */
133 volatile u32 dcfc
; /* SS1 only */
134 volatile u32 forcecol
; /* SS1 only */
135 volatile u32 door
[8]; /* SS1 only */
136 volatile u32 pick
[5]; /* SS1 only */
139 #define LEO_SS1_MISC_ENABLE 0x00000001
140 #define LEO_SS1_MISC_STEREO 0x00000002
143 volatile u32 ss1_misc
;
150 static struct sbus_mmap_map leo_mmap_map
[] = {
151 { LEO_SS0_MAP
, LEO_OFF_SS0
, 0x800000 },
152 { LEO_LC_SS0_USR_MAP
, LEO_OFF_LC_SS0_USR
, 0x1000 },
153 { LEO_LD_SS0_MAP
, LEO_OFF_LD_SS0
, 0x1000 },
154 { LEO_LX_CURSOR_MAP
, LEO_OFF_LX_CURSOR
, 0x1000 },
155 { LEO_SS1_MAP
, LEO_OFF_SS1
, 0x800000 },
156 { LEO_LC_SS1_USR_MAP
, LEO_OFF_LC_SS1_USR
, 0x1000 },
157 { LEO_LD_SS1_MAP
, LEO_OFF_LD_SS1
, 0x1000 },
158 { LEO_UNK_MAP
, LEO_OFF_UNK
, 0x1000 },
159 { LEO_LX_KRN_MAP
, LEO_OFF_LX_KRN
, 0x1000 },
160 { LEO_LC_SS0_KRN_MAP
, LEO_OFF_LC_SS0_KRN
, 0x1000 },
161 { LEO_LC_SS1_KRN_MAP
, LEO_OFF_LC_SS1_KRN
, 0x1000 },
162 { LEO_LD_GBL_MAP
, LEO_OFF_LD_GBL
, 0x1000 },
163 { LEO_UNK2_MAP
, LEO_OFF_UNK2
, 0x100000 },
167 static void leo_setup(struct display
*p
)
173 static void leo_clear(struct vc_data
*conp
, struct display
*p
, int sy
, int sx
,
174 int height
, int width
)
176 struct fb_info_sbusfb
*fb
= (struct fb_info_sbusfb
*)p
->fb_info
;
177 register struct leo_lc_ss0_usr
*us
= fb
->s
.leo
.lc_ss0_usr
;
178 register struct leo_ld
*ss
= (struct leo_ld
*) fb
->s
.leo
.ld_ss0
;
183 spin_lock_irqsave(&fb
->lock
, flags
);
185 i
= sbus_readl(&us
->csr
);
186 } while (i
& 0x20000000);
187 sbus_writel((attr_bgcol_ec(p
,conp
)<<24), &ss
->fg
);
188 if (fontheightlog(p
)) {
189 y
= sy
<< fontheightlog(p
); h
= height
<< fontheightlog(p
);
191 y
= sy
* fontheight(p
); h
= height
* fontheight(p
);
193 if (fontwidthlog(p
)) {
194 x
= sx
<< fontwidthlog(p
); w
= width
<< fontwidthlog(p
);
196 x
= sx
* fontwidth(p
); w
= width
* fontwidth(p
);
198 sbus_writel((w
- 1) | ((h
- 1) << 11), &us
->extent
);
199 sbus_writel((x
+ fb
->x_margin
) | ((y
+ fb
->y_margin
) << 11) | 0x80000000,
201 spin_unlock_irqrestore(&fb
->lock
, flags
);
204 static void leo_fill(struct fb_info_sbusfb
*fb
, struct display
*p
, int s
,
205 int count
, unsigned short *boxes
)
208 register struct leo_lc_ss0_usr
*us
= fb
->s
.leo
.lc_ss0_usr
;
209 register struct leo_ld
*ss
= (struct leo_ld
*) fb
->s
.leo
.ld_ss0
;
212 spin_lock_irqsave(&fb
->lock
, flags
);
213 sbus_writel((attr_bgcol(p
,s
)<<24), &ss
->fg
);
214 while (count
-- > 0) {
216 i
= sbus_readl(&us
->csr
);
217 } while (i
& 0x20000000);
218 sbus_writel((boxes
[2] - boxes
[0] - 1) |
219 ((boxes
[3] - boxes
[1] - 1) << 11),
221 sbus_writel(boxes
[0] | (boxes
[1] << 11) | 0x80000000,
225 spin_unlock_irqrestore(&fb
->lock
, flags
);
228 static void leo_putc(struct vc_data
*conp
, struct display
*p
, int c
, int yy
, int xx
)
230 struct fb_info_sbusfb
*fb
= (struct fb_info_sbusfb
*)p
->fb_info
;
231 register struct leo_lc_ss0_usr
*us
= fb
->s
.leo
.lc_ss0_usr
;
232 register struct leo_ld
*ss
= (struct leo_ld
*) fb
->s
.leo
.ld_ss0
;
238 spin_lock_irqsave(&fb
->lock
, flags
);
239 if (fontheightlog(p
)) {
240 y
= yy
<< (fontheightlog(p
) + 11);
241 i
= (c
& p
->charmask
) << fontheightlog(p
);
243 y
= (yy
* fontheight(p
)) << 11;
244 i
= (c
& p
->charmask
) * fontheight(p
);
246 if (fontwidth(p
) <= 8)
247 fd
= p
->fontdata
+ i
;
249 fd
= p
->fontdata
+ (i
<< 1);
251 x
= xx
<< fontwidthlog(p
);
253 x
= xx
* fontwidth(p
);
255 i
= sbus_readl(&us
->csr
);
256 } while (i
& 0x20000000);
257 sbus_writel(attr_fgcol(p
,c
) << 24, &ss
->fg
);
258 sbus_writel(attr_bgcol(p
,c
) << 24, &ss
->bg
);
259 sbus_writel(0xFFFFFFFF<<(32-fontwidth(p
)),
261 u
= ((u32
*)p
->screen_base
) + y
+ x
;
262 if (fontwidth(p
) <= 8) {
263 for (i
= 0; i
< fontheight(p
); i
++, u
+= 2048) {
264 u32 val
= *fd
++ << 24;
269 for (i
= 0; i
< fontheight(p
); i
++, u
+= 2048) {
270 u32 val
= *(u16
*)fd
<< 16;
276 spin_unlock_irqrestore(&fb
->lock
, flags
);
279 static void leo_putcs(struct vc_data
*conp
, struct display
*p
, const unsigned short *s
,
280 int count
, int yy
, int xx
)
282 struct fb_info_sbusfb
*fb
= (struct fb_info_sbusfb
*)p
->fb_info
;
283 register struct leo_lc_ss0_usr
*us
= fb
->s
.leo
.lc_ss0_usr
;
284 register struct leo_ld
*ss
= (struct leo_ld
*) fb
->s
.leo
.ld_ss0
;
287 u8
*fd1
, *fd2
, *fd3
, *fd4
;
290 spin_lock_irqsave(&fb
->lock
, flags
);
292 i
= sbus_readl(&us
->csr
);
293 } while (i
& 0x20000000);
294 sbus_writel(attr_fgcol(p
,scr_readw(s
)) << 24, &ss
->fg
);
295 sbus_writel(attr_bgcol(p
,scr_readw(s
)) << 24, &ss
->bg
);
296 sbus_writel(0xFFFFFFFF<<(32-fontwidth(p
)), &us
->fontmsk
);
298 x
= (xx
<< fontwidthlog(p
));
300 x
= xx
* fontwidth(p
);
301 if (fontheightlog(p
))
302 y
= yy
<< (fontheightlog(p
) + 11);
304 y
= (yy
* fontheight(p
)) << 11;
305 u
= ((u32
*)p
->screen_base
) + y
+ x
;
306 if (fontwidth(p
) <= 8) {
307 sbus_writel(0xFFFFFFFF<<(32-4*fontwidth(p
)), &us
->fontmsk
);
308 x
= 4*fontwidth(p
) - fontheight(p
)*2048;
311 if (fontheightlog(p
)) {
312 fd1
= p
->fontdata
+ ((scr_readw(s
++) & p
->charmask
) << fontheightlog(p
));
313 fd2
= p
->fontdata
+ ((scr_readw(s
++) & p
->charmask
) << fontheightlog(p
));
314 fd3
= p
->fontdata
+ ((scr_readw(s
++) & p
->charmask
) << fontheightlog(p
));
315 fd4
= p
->fontdata
+ ((scr_readw(s
++) & p
->charmask
) << fontheightlog(p
));
317 fd1
= p
->fontdata
+ ((scr_readw(s
++) & p
->charmask
) * fontheight(p
));
318 fd2
= p
->fontdata
+ ((scr_readw(s
++) & p
->charmask
) * fontheight(p
));
319 fd3
= p
->fontdata
+ ((scr_readw(s
++) & p
->charmask
) * fontheight(p
));
320 fd4
= p
->fontdata
+ ((scr_readw(s
++) & p
->charmask
) * fontheight(p
));
322 if (fontwidth(p
) == 8) {
323 for (i
= 0; i
< fontheight(p
); i
++, u
+= 2048) {
326 val
= ((u32
)*fd4
++) | ((((u32
)*fd3
++) | ((((u32
)*fd2
++) | (((u32
)*fd1
++)
332 for (i
= 0; i
< fontheight(p
); i
++, u
+= 2048) {
335 val
= (((u32
)*fd4
++) | ((((u32
)*fd3
++) | ((((u32
)*fd2
++) | (((u32
)*fd1
++)
336 << fontwidth(p
))) << fontwidth(p
))) << fontwidth(p
))) << (24 - 3 * fontwidth(p
));
343 sbus_writel(0xFFFFFFFF<<(32-2*fontwidth(p
)), &us
->fontmsk
);
344 x
= 2*fontwidth(p
) - fontheight(p
)*2048;
347 if (fontheightlog(p
)) {
348 fd1
= p
->fontdata
+ ((scr_readw(s
++) & p
->charmask
) << (fontheightlog(p
) + 1));
349 fd2
= p
->fontdata
+ ((scr_readw(s
++) & p
->charmask
) << (fontheightlog(p
) + 1));
351 fd1
= p
->fontdata
+ (((scr_readw(s
++) & p
->charmask
) * fontheight(p
)) << 1);
352 fd2
= p
->fontdata
+ (((scr_readw(s
++) & p
->charmask
) * fontheight(p
)) << 1);
354 for (i
= 0; i
< fontheight(p
); i
++, u
+= 2048) {
357 val
= ((((u32
)*(u16
*)fd1
) << fontwidth(p
)) | ((u32
)*(u16
*)fd2
)) << (16 - fontwidth(p
));
364 sbus_writel(0xFFFFFFFF<<(32-fontwidth(p
)), &us
->fontmsk
);
365 x
= fontwidth(p
) - fontheight(p
)*2048;
368 if (fontheightlog(p
))
369 i
= ((scr_readw(s
++) & p
->charmask
) << fontheightlog(p
));
371 i
= ((scr_readw(s
++) & p
->charmask
) * fontheight(p
));
372 if (fontwidth(p
) <= 8) {
373 fd1
= p
->fontdata
+ i
;
374 for (i
= 0; i
< fontheight(p
); i
++, u
+= 2048) {
375 u32 val
= *fd1
++ << 24;
380 fd1
= p
->fontdata
+ (i
<< 1);
381 for (i
= 0; i
< fontheight(p
); i
++, u
+= 2048) {
382 u32 val
= *(u16
*)fd1
<< 16;
390 spin_unlock_irqrestore(&fb
->lock
, flags
);
393 static void leo_revc(struct display
*p
, int xx
, int yy
)
395 /* Not used if hw cursor */
398 static int leo_wait (struct leo_lx_krn
*lx_krn
)
402 for (i
= 0; (sbus_readl(&lx_krn
->krn_csr
) & LEO_KRN_CSR_PROGRESS
) && i
< 300000; i
++)
403 udelay (1); /* Busy wait at most 0.3 sec */
405 return -EFAULT
; /* Timed out - should we print some message? */
409 static void leo_loadcmap (struct fb_info_sbusfb
*fb
, struct display
*p
, int index
, int count
)
411 struct leo_lx_krn
*lx_krn
= fb
->s
.leo
.lx_krn
;
416 spin_lock_irqsave(&fb
->lock
, flags
);
417 sbus_writel(LEO_KRN_TYPE_CLUT0
, &lx_krn
->krn_type
);
418 i
= leo_wait (lx_krn
);
421 sbus_writel(LEO_KRN_TYPE_CLUTDATA
, &lx_krn
->krn_type
);
422 for (i
= 0; i
< 256; i
++) {
425 val
= fb
->color_map
CM(i
,0) |
426 (fb
->color_map
CM(i
,1) << 8) |
427 (fb
->color_map
CM(i
,2) << 16);
429 sbus_writel(val
, &lx_krn
->krn_value
); /* Throw colors there :)) */
431 sbus_writel(LEO_KRN_TYPE_CLUT0
, &lx_krn
->krn_type
);
432 tmp
= sbus_readl(&lx_krn
->krn_csr
);
433 tmp
|= (LEO_KRN_CSR_UNK
|LEO_KRN_CSR_UNK2
);
434 sbus_writel(tmp
, &lx_krn
->krn_csr
);
436 spin_unlock_irqrestore(&fb
->lock
, flags
);
439 static void leo_restore_palette (struct fb_info_sbusfb
*fb
)
444 spin_lock_irqsave(&fb
->lock
, flags
);
445 tmp
= sbus_readl(&fb
->s
.leo
.ld_ss1
->ss1_misc
);
446 tmp
&= ~(LEO_SS1_MISC_ENABLE
);
447 sbus_writel(tmp
, &fb
->s
.leo
.ld_ss1
->ss1_misc
);
448 spin_unlock_irqrestore(&fb
->lock
, flags
);
451 static struct display_switch leo_dispsw __initdata
= {
453 bmove
: fbcon_redraw_bmove
,
458 fontwidthmask
: FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */
461 static void leo_setcursormap (struct fb_info_sbusfb
*fb
, u8
*red
, u8
*green
, u8
*blue
)
463 struct leo_cursor
*l
= fb
->s
.leo
.cursor
;
467 spin_lock_irqsave(&fb
->lock
, flags
);
468 for (i
= 0; (sbus_readl(&l
->cur_misc
) & LEO_CUR_PROGRESS
) && i
< 300000; i
++)
469 udelay (1); /* Busy wait at most 0.3 sec */
471 goto out
; /* Timed out - should we print some message? */
472 sbus_writel(LEO_CUR_TYPE_CMAP
, &l
->cur_type
);
473 sbus_writel((red
[0] | (green
[0]<<8) | (blue
[0]<<16)), &l
->cur_data
);
474 sbus_writel((red
[1] | (green
[1]<<8) | (blue
[1]<<16)), &l
->cur_data
);
475 sbus_writel(LEO_CUR_UPDATECMAP
, &l
->cur_misc
);
477 spin_unlock_irqrestore(&fb
->lock
, flags
);
480 /* Set cursor shape */
481 static void leo_setcurshape (struct fb_info_sbusfb
*fb
)
485 struct leo_cursor
*l
= fb
->s
.leo
.cursor
;
489 spin_lock_irqsave(&fb
->lock
, flags
);
490 tmp
= sbus_readl(&l
->cur_misc
);
491 tmp
&= ~LEO_CUR_ENABLE
;
492 sbus_writel(tmp
, &l
->cur_misc
);
493 for (k
= 0; k
< 2; k
++) {
494 sbus_writel((k
* LEO_CUR_TYPE_IMAGE
), &l
->cur_type
);
495 for (i
= 0; i
< 32; i
++) {
497 m
= fb
->cursor
.bits
[k
][i
];
498 /* mask = m with reversed bit order */
499 for (j
= 0, n
= 1; j
< 32; j
++, n
<<= 1)
501 mask
|= (0x80000000 >> j
);
502 sbus_writel(mask
, &l
->cur_data
);
505 tmp
= sbus_readl(&l
->cur_misc
);
506 tmp
|= LEO_CUR_ENABLE
;
507 sbus_writel(tmp
, &l
->cur_misc
);
508 spin_unlock_irqrestore(&fb
->lock
, flags
);
511 /* Load cursor information */
512 static void leo_setcursor (struct fb_info_sbusfb
*fb
)
514 struct cg_cursor
*c
= &fb
->cursor
;
515 struct leo_cursor
*l
= fb
->s
.leo
.cursor
;
519 spin_lock_irqsave(&fb
->lock
, flags
);
520 tmp
= sbus_readl(&l
->cur_misc
);
521 tmp
&= ~LEO_CUR_ENABLE
;
522 sbus_writel(tmp
, &l
->cur_misc
);
524 sbus_writel(((c
->cpos
.fbx
- c
->chot
.fbx
) & 0x7ff) |
525 (((c
->cpos
.fby
- c
->chot
.fby
) & 0x7ff) << 11),
528 tmp
= sbus_readl(&l
->cur_misc
);
529 tmp
|= LEO_CUR_UPDATE
;
531 tmp
|= LEO_CUR_ENABLE
;
532 sbus_writel(tmp
, &l
->cur_misc
);
533 spin_unlock_irqrestore(&fb
->lock
, flags
);
536 static void leo_blank (struct fb_info_sbusfb
*fb
)
541 spin_lock_irqsave(&fb
->lock
, flags
);
542 sbus_writel(LEO_KRN_TYPE_VIDEO
, &fb
->s
.leo
.lx_krn
->krn_type
);
544 tmp
= sbus_readl(&fb
->s
.leo
.lx_krn
->krn_csr
);
545 tmp
&= ~LEO_KRN_CSR_ENABLE
;
546 sbus_writel(tmp
, &fb
->s
.leo
.lx_krn
->krn_csr
);
547 spin_unlock_irqrestore(&fb
->lock
, flags
);
550 static void leo_unblank (struct fb_info_sbusfb
*fb
)
555 spin_lock_irqsave(&fb
->lock
, flags
);
556 sbus_writel(LEO_KRN_TYPE_VIDEO
, &fb
->s
.leo
.lx_krn
->krn_type
);
558 tmp
= sbus_readl(&fb
->s
.leo
.lx_krn
->krn_csr
);
559 if (!(tmp
& LEO_KRN_CSR_ENABLE
)) {
560 tmp
|= LEO_KRN_CSR_ENABLE
;
561 sbus_writel(tmp
, &fb
->s
.leo
.lx_krn
->krn_csr
);
563 spin_unlock_irqrestore(&fb
->lock
, flags
);
567 leo_wid_put (struct fb_info_sbusfb
*fb
, struct fb_wid_list
*wl
)
569 struct leo_lx_krn
*lx_krn
= fb
->s
.leo
.lx_krn
;
570 struct fb_wid_item
*wi
;
573 sbus_writel(LEO_KRN_TYPE_WID
, &lx_krn
->krn_type
);
574 i
= leo_wait (lx_krn
);
577 for (i
= 0, wi
= wl
->wl_list
; i
< wl
->wl_count
; i
++, wi
++) {
578 switch (wi
->wi_type
) {
579 case FB_WID_DBL_8
: j
= (wi
->wi_index
& 0xf) + 0x40; break;
580 case FB_WID_DBL_24
: j
= wi
->wi_index
& 0x3f; break;
581 default: return -EINVAL
;
583 sbus_writel(0x5800 + j
, &lx_krn
->krn_type
);
584 sbus_writel(wi
->wi_values
[0], &lx_krn
->krn_value
);
586 sbus_writel(LEO_KRN_TYPE_WID
, &lx_krn
->krn_type
);
587 sbus_writel(3, &lx_krn
->krn_csr
);
591 static void leo_margins (struct fb_info_sbusfb
*fb
, struct display
*p
, int x_margin
, int y_margin
)
593 p
->screen_base
+= 8192 * (y_margin
- fb
->y_margin
) + 4 * (x_margin
- fb
->x_margin
);
596 static void leo_switch_from_graph (struct fb_info_sbusfb
*fb
)
598 register struct leo_lc_ss0_usr
*us
= fb
->s
.leo
.lc_ss0_usr
;
599 register struct leo_ld
*ss
= (struct leo_ld
*) fb
->s
.leo
.ld_ss0
;
602 spin_lock_irqsave(&fb
->lock
, flags
);
603 sbus_writel(0xffffffff, &ss
->wid
);
604 sbus_writel(0xffff, &ss
->wmask
);
605 sbus_writel(0, &ss
->vclipmin
);
606 sbus_writel(fb
->s
.leo
.extent
, &ss
->vclipmax
);
607 sbus_writel(0xff000000, &ss
->planemask
);
608 sbus_writel(0x310850, &ss
->rop
);
609 sbus_writel(0, &ss
->widclip
);
610 sbus_writel(4, &us
->addrspace
);
611 sbus_writel(0, &us
->fontt
);
612 spin_unlock_irqrestore(&fb
->lock
, flags
);
615 static int __init
leo_rasterimg (struct fb_info
*info
, int start
)
617 struct fb_info_sbusfb
*fb
= sbusfbinfo(info
);
618 register struct leo_lc_ss0_usr
*us
= fb
->s
.leo
.lc_ss0_usr
;
619 register struct leo_ld
*ss
= (struct leo_ld
*) fb
->s
.leo
.ld_ss0
;
622 sbus_writel(1, &ss
->wid
);
623 sbus_writel(0xffffff, &ss
->planemask
);
624 sbus_writel(0x310b90, &ss
->rop
);
625 sbus_writel(0, &us
->addrspace
);
627 sbus_writel(0xffffffff, &ss
->wid
);
628 sbus_writel(0xff000000, &ss
->planemask
);
629 sbus_writel(0x310850, &ss
->rop
);
630 sbus_writel(4, &us
->addrspace
);
635 static char idstring
[40] __initdata
= { 0 };
637 char * __init
leofb_init(struct fb_info_sbusfb
*fb
)
639 struct fb_fix_screeninfo
*fix
= &fb
->fix
;
640 struct fb_var_screeninfo
*var
= &fb
->var
;
641 struct display
*disp
= &fb
->disp
;
642 struct fbtype
*type
= &fb
->type
;
643 struct sbus_dev
*sdev
= fb
->sbdp
;
644 unsigned long phys
= sdev
->reg_addrs
[0].phys_addr
;
645 struct fb_wid_item wi
;
646 struct fb_wid_list wl
;
648 register struct leo_lc_ss0_usr
*us
;
649 register struct leo_ld
*ss
;
650 struct fb_ops
*fbops
;
653 strcpy(fb
->info
.modename
, "Leo");
655 strcpy(fix
->id
, "Leo");
656 fix
->visual
= FB_VISUAL_TRUECOLOR
;
657 fix
->line_length
= 8192;
658 fix
->accel
= FB_ACCEL_SUN_LEO
;
660 var
->bits_per_pixel
= 32;
661 var
->green
.offset
= 8;
662 var
->blue
.offset
= 16;
663 var
->accel_flags
= FB_ACCELF_TEXT
;
665 fbops
= kmalloc(sizeof(*fbops
), GFP_KERNEL
);
669 *fbops
= *fb
->info
.fbops
;
670 fbops
->fb_rasterimg
= leo_rasterimg
;
671 fb
->info
.fbops
= fbops
;
673 disp
->scrollmode
= SCROLL_YREDRAW
;
674 if (!disp
->screen_base
) {
675 disp
->screen_base
= (char *)
676 sbus_ioremap(&sdev
->resource
[0], LEO_OFF_SS0
,
677 0x800000, "leo ram");
679 disp
->screen_base
+= 8192 * fb
->y_margin
+ 4 * fb
->x_margin
;
680 us
= fb
->s
.leo
.lc_ss0_usr
= (struct leo_lc_ss0_usr
*)
681 sbus_ioremap(&sdev
->resource
[0], LEO_OFF_LC_SS0_USR
,
682 0x1000, "leolc ss0usr");
683 fb
->s
.leo
.ld_ss0
= (struct leo_ld_ss0
*)
684 sbus_ioremap(&sdev
->resource
[0], LEO_OFF_LD_SS0
,
685 0x1000, "leold ss0");
686 ss
= (struct leo_ld
*) fb
->s
.leo
.ld_ss0
;
687 fb
->s
.leo
.ld_ss1
= (struct leo_ld_ss1
*)
688 sbus_ioremap(&sdev
->resource
[0], LEO_OFF_LD_SS1
,
689 0x1000, "leold ss1");
690 fb
->s
.leo
.lx_krn
= (struct leo_lx_krn
*)
691 sbus_ioremap(&sdev
->resource
[0], LEO_OFF_LX_KRN
,
692 0x1000, "leolx krn");
693 fb
->s
.leo
.cursor
= (struct leo_cursor
*)
694 sbus_ioremap(&sdev
->resource
[0], LEO_OFF_LX_CURSOR
,
695 sizeof(struct leo_cursor
), "leolx cursor");
696 fb
->dispsw
= leo_dispsw
;
698 fb
->s
.leo
.extent
= (type
->fb_width
-1) | ((type
->fb_height
-1) << 16);
702 wi
.wi_type
= FB_WID_DBL_8
;
704 wi
.wi_values
[0] = 0x2c0;
705 leo_wid_put (fb
, &wl
);
707 wi
.wi_values
[0] = 0x30;
708 leo_wid_put (fb
, &wl
);
710 wi
.wi_values
[0] = 0x20;
711 leo_wid_put (fb
, &wl
);
712 wi
.wi_type
= FB_WID_DBL_24
;
714 wi
.wi_values
[0] = 0x30;
715 leo_wid_put (fb
, &wl
);
717 tmp
= sbus_readl(&fb
->s
.leo
.ld_ss1
->ss1_misc
);
718 tmp
|= LEO_SS1_MISC_ENABLE
;
719 sbus_writel(tmp
, &fb
->s
.leo
.ld_ss1
->ss1_misc
);
721 sbus_writel(0xffffffff, &ss
->wid
);
722 sbus_writel(0xffff, &ss
->wmask
);
723 sbus_writel(0, &ss
->vclipmin
);
724 sbus_writel(fb
->s
.leo
.extent
, &ss
->vclipmax
);
725 sbus_writel(0, &ss
->fg
);
726 sbus_writel(0xff000000, &ss
->planemask
);
727 sbus_writel(0x310850, &ss
->rop
);
728 sbus_writel(0, &ss
->widclip
);
729 sbus_writel((type
->fb_width
-1) | ((type
->fb_height
-1) << 11), &us
->extent
);
730 sbus_writel(4, &us
->addrspace
);
731 sbus_writel(0x80000000, &us
->fill
);
732 sbus_writel(0, &us
->fontt
);
734 i
= sbus_readl(&us
->csr
);
735 } while (i
& 0x20000000);
737 fb
->margins
= leo_margins
;
738 fb
->loadcmap
= leo_loadcmap
;
739 fb
->setcursor
= leo_setcursor
;
740 fb
->setcursormap
= leo_setcursormap
;
741 fb
->setcurshape
= leo_setcurshape
;
742 fb
->restore_palette
= leo_restore_palette
;
743 fb
->switch_from_graph
= leo_switch_from_graph
;
745 fb
->blank
= leo_blank
;
746 fb
->unblank
= leo_unblank
;
749 fb
->mmap_map
= leo_mmap_map
;
752 sprintf(idstring
, "leo at %016lx", phys
);
754 sprintf(idstring
, "leo at %x.%08lx", fb
->iospace
, phys
);