File: /usr/src/linux/drivers/video/leofb.c

1     /* $Id: leofb.c,v 1.13 2001/09/19 00:04:33 davem Exp $
2      * leofb.c: Leo (ZX) 24/8bit frame buffer driver
3      *
4      * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
5      * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz)
6      */
7     
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>
13     #include <linux/mm.h>
14     #include <linux/tty.h>
15     #include <linux/slab.h>
16     #include <linux/vmalloc.h>
17     #include <linux/delay.h>
18     #include <linux/interrupt.h>
19     #include <linux/fb.h>
20     #include <linux/init.h>
21     #include <linux/selection.h>
22     
23     #include <video/sbusfb.h>
24     #include <asm/io.h>
25     
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
39     
40     #define LEO_CUR_ENABLE		0x00000080
41     #define LEO_CUR_UPDATE		0x00000030
42     #define LEO_CUR_PROGRESS	0x00000006
43     #define LEO_CUR_UPDATECMAP	0x00000003
44     
45     #define LEO_CUR_TYPE_MASK	0x00000000
46     #define LEO_CUR_TYPE_IMAGE	0x00000020
47     #define LEO_CUR_TYPE_CMAP	0x00000050
48     
49     struct leo_cursor {
50     	u8		xxx0[16];
51     	volatile u32	cur_type;
52     	volatile u32	cur_misc;
53     	volatile u32	cur_cursxy;
54     	volatile u32	cur_data;
55     };
56     
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
68     
69     struct leo_lx_krn {
70     	volatile u32	krn_type;
71     	volatile u32	krn_csr;
72     	volatile u32	krn_value;
73     };
74     
75     struct leo_lc_ss0_krn {
76     	volatile u32 	misc;
77     	u8		xxx0[0x800-4];
78     	volatile u32	rev;
79     };
80     
81     struct leo_lc_ss0_usr {
82     	volatile u32	csr;
83     	volatile u32	addrspace;
84     	volatile u32 	fontmsk;
85     	volatile u32	fontt;
86     	volatile u32	extent;
87     	volatile u32	src;
88     	u32		dst;
89     	volatile u32	copy;
90     	volatile u32	fill;
91     };
92     
93     struct leo_lc_ss1_krn {
94     	u8	unknown;
95     };
96     
97     struct leo_lc_ss1_usr {
98     	u8	unknown;
99     };
100     
101     struct leo_ld {
102     	u8		xxx0[0xe00];
103     	volatile u32	csr;
104     	volatile u32	wid;
105     	volatile u32	wmask;
106     	volatile u32	widclip;
107     	volatile u32	vclipmin;
108     	volatile u32	vclipmax;
109     	volatile u32	pickmin;	/* SS1 only */
110     	volatile u32	pickmax;	/* SS1 only */
111     	volatile u32	fg;
112     	volatile u32	bg;
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) */
116     	u32		xxx1[3];
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 */
122     	u8		xxx2[0x2c];
123     	volatile u32	winbg;
124     	volatile u32	planemask;
125     	volatile u32	rop;
126     	volatile u32	z;
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 */
137     };
138     
139     #define LEO_SS1_MISC_ENABLE	0x00000001
140     #define LEO_SS1_MISC_STEREO	0x00000002
141     struct leo_ld_ss1 {
142     	u8		xxx0[0xef4];
143     	volatile u32	ss1_misc;
144     };
145     
146     struct leo_ld_gbl {
147     	u8	unknown;
148     };
149     
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	},
164     	{ 0,			0,			0	  	}
165     };
166     
167     static void leo_setup(struct display *p)
168     {
169     	p->next_line = 8192;
170     	p->next_plane = 0;
171     }
172     
173     static void leo_clear(struct vc_data *conp, struct display *p, int sy, int sx,
174     		      int height, int width)
175     {
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;
179     	unsigned long flags;
180     	int x, y, w, h;
181     	int i;
182     
183     	spin_lock_irqsave(&fb->lock, flags);
184     	do {
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);
190     	} else {
191     		y = sy * fontheight(p); h = height * fontheight(p);
192     	}
193     	if (fontwidthlog(p)) {
194     		x = sx << fontwidthlog(p); w = width << fontwidthlog(p);
195     	} else {
196     		x = sx * fontwidth(p); w = width * fontwidth(p);
197     	}
198     	sbus_writel((w - 1) | ((h - 1) << 11), &us->extent);
199     	sbus_writel((x + fb->x_margin) | ((y + fb->y_margin) << 11) | 0x80000000,
200     		    &us->fill);
201     	spin_unlock_irqrestore(&fb->lock, flags);
202     }
203     
204     static void leo_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
205     		     int count, unsigned short *boxes)
206     {
207     	int i;
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;
210     	unsigned long flags;
211     	
212     	spin_lock_irqsave(&fb->lock, flags);
213     	sbus_writel((attr_bgcol(p,s)<<24), &ss->fg);
214     	while (count-- > 0) {
215     		do {
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),
220     			    &us->extent);
221     		sbus_writel(boxes[0] | (boxes[1] << 11) | 0x80000000,
222     			    &us->fill);
223     		boxes += 4;
224     	}
225     	spin_unlock_irqrestore(&fb->lock, flags);
226     }
227     
228     static void leo_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
229     {
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;
233     	unsigned long flags;
234     	int i, x, y;
235     	u8 *fd;
236     	u32 *u;
237     
238     	spin_lock_irqsave(&fb->lock, flags);
239     	if (fontheightlog(p)) {
240     		y = yy << (fontheightlog(p) + 11);
241     		i = (c & p->charmask) << fontheightlog(p);
242     	} else {
243     		y = (yy * fontheight(p)) << 11;
244     		i = (c & p->charmask) * fontheight(p);
245     	}
246     	if (fontwidth(p) <= 8)
247     		fd = p->fontdata + i;
248     	else
249     		fd = p->fontdata + (i << 1);
250     	if (fontwidthlog(p))
251     		x = xx << fontwidthlog(p);
252     	else
253     		x = xx * fontwidth(p);
254     	do {
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)),
260     		    &us->fontmsk);
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;
265     
266     			sbus_writel(val, u);
267     		}
268     	} else {
269     		for (i = 0; i < fontheight(p); i++, u += 2048) {
270     			u32 val = *(u16 *)fd << 16;
271     
272     			sbus_writel(val, u);
273     			fd += 2;
274     		}
275     	}
276     	spin_unlock_irqrestore(&fb->lock, flags);
277     }
278     
279     static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
280     		      int count, int yy, int xx)
281     {
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;
285     	unsigned long flags;
286     	int i, x, y;
287     	u8 *fd1, *fd2, *fd3, *fd4;
288     	u32 *u;
289     
290     	spin_lock_irqsave(&fb->lock, flags);
291     	do {
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);
297     	if (fontwidthlog(p))
298     		x = (xx << fontwidthlog(p));
299     	else
300     		x = xx * fontwidth(p);
301     	if (fontheightlog(p))
302     		y = yy << (fontheightlog(p) + 11);
303     	else
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;
309     		while (count >= 4) {
310     			count -= 4;
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));
316     			} else {
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));
321     			}
322     			if (fontwidth(p) == 8) {
323     				for (i = 0; i < fontheight(p); i++, u += 2048) {
324     					u32 val;
325     
326     					val = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
327     						<< 8)) << 8)) << 8);
328     					sbus_writel(val, u);
329     				}
330     				u += x;
331     			} else {
332     				for (i = 0; i < fontheight(p); i++, u += 2048) {
333     					u32 val;
334     
335     					val = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
336     						<< fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
337     					sbus_writel(val, u);
338     				}
339     				u += x;
340     			}
341     		}
342     	} else {
343     		sbus_writel(0xFFFFFFFF<<(32-2*fontwidth(p)), &us->fontmsk);
344     		x = 2*fontwidth(p) - fontheight(p)*2048;
345     		while (count >= 2) {
346     			count -= 2;
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));
350     			} else {
351     				fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
352     				fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
353     			}
354     			for (i = 0; i < fontheight(p); i++, u += 2048) {
355     				u32 val;
356     
357     				val = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
358     				sbus_writel(val, u);
359     				fd1 += 2; fd2 += 2;
360     			}
361     			u += x;
362     		}
363     	}
364     	sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), &us->fontmsk);
365     	x = fontwidth(p) - fontheight(p)*2048;
366     	while (count) {
367     		count--;
368     		if (fontheightlog(p))
369     			i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
370     		else
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;
376     
377     				sbus_writel(val, u);
378     			}
379     		} else {
380     			fd1 = p->fontdata + (i << 1);
381     			for (i = 0; i < fontheight(p); i++, u += 2048) {
382     				u32 val = *(u16 *)fd1 << 16;
383     
384     				sbus_writel(val, u);
385     				fd1 += 2;
386     			}
387     		}
388     		u += x;
389     	}
390     	spin_unlock_irqrestore(&fb->lock, flags);
391     }
392     
393     static void leo_revc(struct display *p, int xx, int yy)
394     {
395     	/* Not used if hw cursor */
396     }
397     
398     static int leo_wait (struct leo_lx_krn *lx_krn)
399     {
400     	int i;
401     	
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 */
404     	if (i == 300000)
405     		return -EFAULT; /* Timed out - should we print some message? */
406     	return 0;
407     }
408     
409     static void leo_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
410     {
411             struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn;
412     	unsigned long flags;
413     	u32 tmp;
414     	int i;
415     	
416     	spin_lock_irqsave(&fb->lock, flags);
417     	sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type);
418     	i = leo_wait (lx_krn);
419     	if (i)
420     		goto out;
421     	sbus_writel(LEO_KRN_TYPE_CLUTDATA, &lx_krn->krn_type);
422     	for (i = 0; i < 256; i++) {
423     		u32 val;
424     
425     		val = fb->color_map CM(i,0) |
426     			(fb->color_map CM(i,1) << 8) |
427     			(fb->color_map CM(i,2) << 16);
428     
429     		sbus_writel(val, &lx_krn->krn_value); /* Throw colors there :)) */
430     	}
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);
435     out:
436     	spin_unlock_irqrestore(&fb->lock, flags);
437     }
438     
439     static void leo_restore_palette (struct fb_info_sbusfb *fb)
440     {
441     	u32 tmp;
442     	unsigned long flags;
443     
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);
449     }
450     
451     static struct display_switch leo_dispsw __initdata = {
452     	setup:		leo_setup,
453     	bmove:		fbcon_redraw_bmove,
454     	clear:		leo_clear,
455     	putc:		leo_putc,
456     	putcs:		leo_putcs,
457     	revc:		leo_revc, 
458     	fontwidthmask:	FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */
459     };
460     
461     static void leo_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
462     {
463             struct leo_cursor *l = fb->s.leo.cursor;
464     	unsigned long flags;
465     	int i;
466     
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 */
470     	if (i == 300000)
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);
476     out:
477     	spin_unlock_irqrestore(&fb->lock, flags);
478     }
479     
480     /* Set cursor shape */
481     static void leo_setcurshape (struct fb_info_sbusfb *fb)
482     {
483     	int i, j, k;
484     	u32 m, n, mask;
485     	struct leo_cursor *l = fb->s.leo.cursor;
486     	u32 tmp;
487     	unsigned long flags;
488     
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++) {
496     			mask = 0;
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)
500     				if (m & n)
501     					mask |= (0x80000000 >> j);
502     			sbus_writel(mask, &l->cur_data);
503     		}
504     	}
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);
509     }
510     
511     /* Load cursor information */
512     static void leo_setcursor (struct fb_info_sbusfb *fb)
513     {
514     	struct cg_cursor *c = &fb->cursor;
515     	struct leo_cursor *l = fb->s.leo.cursor;
516     	unsigned long flags;
517     	u32 tmp;
518     
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);
523     
524     	sbus_writel(((c->cpos.fbx - c->chot.fbx) & 0x7ff) |
525     		    (((c->cpos.fby - c->chot.fby) & 0x7ff) << 11),
526     		    &l->cur_cursxy);
527     
528     	tmp = sbus_readl(&l->cur_misc);
529     	tmp |= LEO_CUR_UPDATE;
530     	if (c->enable)
531     		tmp |= LEO_CUR_ENABLE;
532     	sbus_writel(tmp, &l->cur_misc);
533     	spin_unlock_irqrestore(&fb->lock, flags);
534     }
535     
536     static void leo_blank (struct fb_info_sbusfb *fb)
537     {
538     	unsigned long flags;
539     	u32 tmp;
540     
541     	spin_lock_irqsave(&fb->lock, flags);
542     	sbus_writel(LEO_KRN_TYPE_VIDEO, &fb->s.leo.lx_krn->krn_type);
543     
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);
548     }
549     
550     static void leo_unblank (struct fb_info_sbusfb *fb)
551     {
552     	unsigned long flags;
553     	u32 tmp;
554     
555     	spin_lock_irqsave(&fb->lock, flags);
556     	sbus_writel(LEO_KRN_TYPE_VIDEO, &fb->s.leo.lx_krn->krn_type);
557     
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);
562     	}
563     	spin_unlock_irqrestore(&fb->lock, flags);
564     }
565     
566     static int __init
567     leo_wid_put (struct fb_info_sbusfb *fb, struct fb_wid_list *wl)
568     {
569     	struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn;
570     	struct fb_wid_item *wi;
571     	int i, j;
572     
573     	sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
574     	i = leo_wait (lx_krn);
575     	if (i)
576     		return i;
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;
582     		}
583     		sbus_writel(0x5800 + j, &lx_krn->krn_type);
584     		sbus_writel(wi->wi_values[0], &lx_krn->krn_value);
585     	}
586     	sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
587     	sbus_writel(3, &lx_krn->krn_csr);
588     	return 0;
589     }
590     
591     static void leo_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
592     {
593     	p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin);
594     }
595     
596     static void leo_switch_from_graph (struct fb_info_sbusfb *fb)
597     {
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;
600     	unsigned long flags;
601     
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);
613     }
614     
615     static int __init leo_rasterimg (struct fb_info *info, int start)
616     {
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;
620     
621     	if (start) {
622     		sbus_writel(1, &ss->wid);
623     		sbus_writel(0xffffff, &ss->planemask); 
624     		sbus_writel(0x310b90, &ss->rop);
625     		sbus_writel(0, &us->addrspace);
626     	} else {
627     		sbus_writel(0xffffffff, &ss->wid);
628     		sbus_writel(0xff000000, &ss->planemask);
629     		sbus_writel(0x310850, &ss->rop);
630     		sbus_writel(4, &us->addrspace);
631     	}
632     	return 0;
633     }
634     
635     static char idstring[40] __initdata = { 0 };
636     
637     char * __init leofb_init(struct fb_info_sbusfb *fb)
638     {
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;
647     	int i;
648     	register struct leo_lc_ss0_usr *us;
649     	register struct leo_ld *ss;
650     	struct fb_ops *fbops;
651     	u32 tmp;
652     
653     	strcpy(fb->info.modename, "Leo");
654     		
655     	strcpy(fix->id, "Leo");
656     	fix->visual = FB_VISUAL_TRUECOLOR;
657     	fix->line_length = 8192;
658     	fix->accel = FB_ACCEL_SUN_LEO;
659     	
660     	var->bits_per_pixel = 32;
661     	var->green.offset = 8;
662     	var->blue.offset = 16;
663     	var->accel_flags = FB_ACCELF_TEXT;
664     	
665     	fbops = kmalloc(sizeof(*fbops), GFP_KERNEL);
666     	if (fbops == NULL)
667     		return NULL;
668     	
669     	*fbops = *fb->info.fbops;
670     	fbops->fb_rasterimg = leo_rasterimg;
671     	fb->info.fbops = fbops;
672     	
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");
678     	}
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;
697     	
698     	fb->s.leo.extent = (type->fb_width-1) | ((type->fb_height-1) << 16);
699     
700     	wl.wl_count = 1;
701     	wl.wl_list = &wi;
702     	wi.wi_type = FB_WID_DBL_8;
703     	wi.wi_index = 0;
704     	wi.wi_values [0] = 0x2c0;
705     	leo_wid_put (fb, &wl);
706     	wi.wi_index = 1;
707     	wi.wi_values [0] = 0x30;
708     	leo_wid_put (fb, &wl);
709     	wi.wi_index = 2;
710     	wi.wi_values [0] = 0x20;
711     	leo_wid_put (fb, &wl);
712     	wi.wi_type = FB_WID_DBL_24;
713     	wi.wi_index = 1;
714     	wi.wi_values [0] = 0x30;
715     	leo_wid_put (fb, &wl);
716     
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);
720     
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);
733     	do {
734     		i = sbus_readl(&us->csr);
735     	} while (i & 0x20000000);
736     
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;
744     	fb->fill = leo_fill;
745     	fb->blank = leo_blank;
746     	fb->unblank = leo_unblank;
747     	
748     	fb->physbase = phys;
749     	fb->mmap_map = leo_mmap_map;
750     	
751     #ifdef __sparc_v9__
752     	sprintf(idstring, "leo at %016lx", phys);
753     #else	
754     	sprintf(idstring, "leo at %x.%08lx", fb->iospace, phys);
755     #endif
756     		    
757     	return idstring;
758     }
759     
760     MODULE_LICENSE("GPL");
761