11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* leo.c: LEO frame buffer driver
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz)
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Driver layout based loosely on tgafb.c, see that file for credits.
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fb.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h>
186cd5a86b56ec8fc8651c043bdb05ea0c662fb704Robert Reif#include <linux/of_device.h>
19738eca74d1bd3e51180de179b7b74d4e34c4e5a3Robert Reif#include <linux/io.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/fbio.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sbuslib.h"
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Local functions.
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int leo_setcolreg(unsigned, unsigned, unsigned, unsigned,
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 unsigned, struct fb_info *);
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int leo_blank(int, struct fb_info *);
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33216d526c89d144928f095f2800bc6c67e968d628Christoph Hellwigstatic int leo_mmap(struct fb_info *, struct vm_area_struct *);
3467a6680d64e18c7a1901f31ef747ea53b6cd986dChristoph Hellwigstatic int leo_ioctl(struct fb_info *, unsigned int, unsigned long);
354dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reifstatic int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *);
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Frame buffer operations
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct fb_ops leo_ops = {
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner			= THIS_MODULE,
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_setcolreg		= leo_setcolreg,
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_blank		= leo_blank,
454dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	.fb_pan_display		= leo_pan_display,
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_fillrect		= cfb_fillrect,
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_copyarea		= cfb_copyarea,
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_imageblit		= cfb_imageblit,
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_mmap		= leo_mmap,
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_ioctl		= leo_ioctl,
519ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig#ifdef CONFIG_COMPAT
529ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	.fb_compat_ioctl	= sbusfb_compat_ioctl,
539ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig#endif
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_OFF_LC_SS0_KRN	0x00200000UL
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_OFF_LC_SS0_USR	0x00201000UL
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_OFF_LC_SS1_KRN	0x01200000UL
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_OFF_LC_SS1_USR	0x01201000UL
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_OFF_LD_SS0		0x00400000UL
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_OFF_LD_SS1		0x01400000UL
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_OFF_LD_GBL		0x00401000UL
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_OFF_LX_KRN		0x00600000UL
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_OFF_LX_CURSOR	0x00601000UL
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_OFF_SS0		0x00800000UL
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_OFF_SS1		0x01800000UL
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_OFF_UNK		0x00602000UL
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_OFF_UNK2		0x00000000UL
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_CUR_ENABLE		0x00000080
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_CUR_UPDATE		0x00000030
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_CUR_PROGRESS	0x00000006
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_CUR_UPDATECMAP	0x00000003
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_CUR_TYPE_MASK	0x00000000
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_CUR_TYPE_IMAGE	0x00000020
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_CUR_TYPE_CMAP	0x00000050
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct leo_cursor {
80738eca74d1bd3e51180de179b7b74d4e34c4e5a3Robert Reif	u8	xxx0[16];
8150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	cur_type;
8250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	cur_misc;
8350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	cur_cursxy;
8450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	cur_data;
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_KRN_TYPE_CLUT0	0x00001000
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_KRN_TYPE_CLUT1	0x00001001
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_KRN_TYPE_CLUT2	0x00001002
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_KRN_TYPE_WID	0x00001003
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_KRN_TYPE_UNK	0x00001006
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_KRN_TYPE_VIDEO	0x00002003
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_KRN_TYPE_CLUTDATA	0x00004000
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_KRN_CSR_ENABLE	0x00000008
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_KRN_CSR_PROGRESS	0x00000004
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_KRN_CSR_UNK		0x00000002
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_KRN_CSR_UNK2	0x00000001
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct leo_lx_krn {
10050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	krn_type;
10150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	krn_csr;
10250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	krn_value;
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct leo_lc_ss0_krn {
10650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32 	misc;
107738eca74d1bd3e51180de179b7b74d4e34c4e5a3Robert Reif	u8	xxx0[0x800-4];
10850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rev;
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct leo_lc_ss0_usr {
11250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	csr;
11350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	addrspace;
11450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32 	fontmsk;
11550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fontt;
11650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	extent;
11750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	src;
118738eca74d1bd3e51180de179b7b74d4e34c4e5a3Robert Reif	u32	dst;
11950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	copy;
12050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fill;
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct leo_lc_ss1_krn {
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8	unknown;
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct leo_lc_ss1_usr {
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8	unknown;
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131738eca74d1bd3e51180de179b7b74d4e34c4e5a3Robert Reifstruct leo_ld_ss0 {
132738eca74d1bd3e51180de179b7b74d4e34c4e5a3Robert Reif	u8	xxx0[0xe00];
13350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	csr;
13450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	wid;
13550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	wmask;
13650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	widclip;
13750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	vclipmin;
13850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	vclipmax;
13950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	pickmin;	/* SS1 only */
14050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	pickmax;	/* SS1 only */
14150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fg;
14250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	bg;
14350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	src;		/* Copy/Scroll (SS0 only) */
14450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dst;		/* Copy/Scroll/Fill (SS0 only) */
14550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	extent;		/* Copy/Scroll/Fill size (SS0 only) */
146738eca74d1bd3e51180de179b7b74d4e34c4e5a3Robert Reif	u32	xxx1[3];
14750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	setsem;		/* SS1 only */
14850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	clrsem;		/* SS1 only */
14950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	clrpick;	/* SS1 only */
15050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	clrdat;		/* SS1 only */
15150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	alpha;		/* SS1 only */
152738eca74d1bd3e51180de179b7b74d4e34c4e5a3Robert Reif	u8	xxx2[0x2c];
15350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	winbg;
15450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	planemask;
15550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rop;
15650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	z;
15750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dczf;		/* SS1 only */
15850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dczb;		/* SS1 only */
15950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcs;		/* SS1 only */
16050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dczs;		/* SS1 only */
16150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	pickfb;		/* SS1 only */
16250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	pickbb;		/* SS1 only */
16350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcfc;		/* SS1 only */
16450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	forcecol;	/* SS1 only */
16550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	door[8];	/* SS1 only */
16650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	pick[5];	/* SS1 only */
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_SS1_MISC_ENABLE	0x00000001
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_SS1_MISC_STEREO	0x00000002
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct leo_ld_ss1 {
17250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u8	xxx0[0xef4];
17350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	ss1_misc;
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct leo_ld_gbl {
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8	unknown;
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct leo_par {
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spinlock_t		lock;
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct leo_lx_krn	__iomem *lx_krn;
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct leo_lc_ss0_usr	__iomem *lc_ss0_usr;
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct leo_ld_ss0	__iomem *ld_ss0;
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct leo_ld_ss1	__iomem *ld_ss1;
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct leo_cursor	__iomem *cursor;
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32			extent;
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32			clut_data[256];
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32			flags;
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LEO_FLAG_BLANKED	0x00000001
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	unsigned long		which_io;
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void leo_wait(struct leo_lx_krn __iomem *lx_krn)
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
199738eca74d1bd3e51180de179b7b74d4e34c4e5a3Robert Reif
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0;
201738eca74d1bd3e51180de179b7b74d4e34c4e5a3Robert Reif	     (sbus_readl(&lx_krn->krn_csr) & LEO_KRN_CSR_PROGRESS) &&
202738eca74d1bd3e51180de179b7b74d4e34c4e5a3Robert Reif	     i < 300000;
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     i++)
204738eca74d1bd3e51180de179b7b74d4e34c4e5a3Robert Reif		udelay(1); /* Busy wait at most 0.3 sec */
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2084dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reifstatic void leo_switch_from_graph(struct fb_info *info)
2094dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif{
2104dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	struct leo_par *par = (struct leo_par *) info->par;
2114dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	struct leo_ld_ss0 __iomem *ss = par->ld_ss0;
2124dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	struct leo_cursor __iomem *cursor = par->cursor;
2134dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	unsigned long flags;
2144dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	u32 val;
2154dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif
2164dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	spin_lock_irqsave(&par->lock, flags);
2174dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif
2184dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	par->extent = ((info->var.xres - 1) |
2194dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif		       ((info->var.yres - 1) << 16));
2204dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif
2214dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	sbus_writel(0xffffffff, &ss->wid);
2224dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	sbus_writel(0xffff, &ss->wmask);
2234dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	sbus_writel(0, &ss->vclipmin);
2244dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	sbus_writel(par->extent, &ss->vclipmax);
2254dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	sbus_writel(0, &ss->fg);
2264dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	sbus_writel(0xff000000, &ss->planemask);
2274dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	sbus_writel(0x310850, &ss->rop);
2284dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	sbus_writel(0, &ss->widclip);
2294dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11),
2304dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif		    &par->lc_ss0_usr->extent);
2314dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	sbus_writel(4, &par->lc_ss0_usr->addrspace);
2324dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	sbus_writel(0x80000000, &par->lc_ss0_usr->fill);
2334dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	sbus_writel(0, &par->lc_ss0_usr->fontt);
2344dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	do {
2354dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif		val = sbus_readl(&par->lc_ss0_usr->csr);
2364dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	} while (val & 0x20000000);
2374dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif
2384dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	/* setup screen buffer for cfb_* functions */
2394dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	sbus_writel(1, &ss->wid);
2404dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	sbus_writel(0x00ffffff, &ss->planemask);
2414dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	sbus_writel(0x310b90, &ss->rop);
2424dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	sbus_writel(0, &par->lc_ss0_usr->addrspace);
2434dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif
2444dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	/* hide cursor */
2454dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	sbus_writel(sbus_readl(&cursor->cur_misc) & ~LEO_CUR_ENABLE, &cursor->cur_misc);
2464dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif
2474dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	spin_unlock_irqrestore(&par->lock, flags);
2484dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif}
2494dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif
2504dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reifstatic int leo_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
2514dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif{
2524dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	/* We just use this to catch switches out of
2534dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	 * graphics mode.
2544dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	 */
2554dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	leo_switch_from_graph(info);
2564dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif
2574dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	if (var->xoffset || var->yoffset || var->vmode)
2584dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif		return -EINVAL;
2594dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif	return 0;
2604dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif}
2614dd95b63ae25c5cad6986829b5e8788e9faa0330Robert Reif
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      leo_setcolreg - Optional function. Sets a color register.
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      @regno: boolean, 0 copy local, 1 get_user() function
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      @red: frame buffer colormap structure
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      @green: The green value which can be up to 16 bits wide
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      @blue:  The blue value which can be up to 16 bits wide.
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      @transp: If supported the alpha value which can be up to 16 bits wide.
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      @info: frame buffer info structure
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int leo_setcolreg(unsigned regno,
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 unsigned red, unsigned green, unsigned blue,
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 unsigned transp, struct fb_info *info)
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct leo_par *par = (struct leo_par *) info->par;
276738eca74d1bd3e51180de179b7b74d4e34c4e5a3Robert Reif	struct leo_lx_krn __iomem *lx_krn = par->lx_krn;
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val;
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (regno >= 256)
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1;
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	red >>= 8;
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	green >>= 8;
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	blue >>= 8;
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	par->clut_data[regno] = red | (green << 8) | (blue << 16);
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&par->lock, flags);
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	leo_wait(lx_krn);
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sbus_writel(LEO_KRN_TYPE_CLUTDATA, &lx_krn->krn_type);
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 256; i++)
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sbus_writel(par->clut_data[i], &lx_krn->krn_value);
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type);
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = sbus_readl(&lx_krn->krn_csr);
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val |= (LEO_KRN_CSR_UNK | LEO_KRN_CSR_UNK2);
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sbus_writel(val, &lx_krn->krn_csr);
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&par->lock, flags);
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      leo_blank - Optional function.  Blanks the display.
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      @blank_mode: the blank mode we want.
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      @info: frame buffer structure that represents a single frame buffer
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int leo_blank(int blank, struct fb_info *info)
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct leo_par *par = (struct leo_par *) info->par;
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct leo_lx_krn __iomem *lx_krn = par->lx_krn;
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val;
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&par->lock, flags);
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (blank) {
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FB_BLANK_UNBLANK: /* Unblanking */
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val = sbus_readl(&lx_krn->krn_csr);
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val |= LEO_KRN_CSR_ENABLE;
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sbus_writel(val, &lx_krn->krn_csr);
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		par->flags &= ~LEO_FLAG_BLANKED;
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FB_BLANK_NORMAL: /* Normal blanking */
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FB_BLANK_POWERDOWN: /* Poweroff */
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val = sbus_readl(&lx_krn->krn_csr);
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val &= ~LEO_KRN_CSR_ENABLE;
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sbus_writel(val, &lx_krn->krn_csr);
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		par->flags |= LEO_FLAG_BLANKED;
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&par->lock, flags);
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sbus_mmap_map leo_mmap_map[] = {
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= LEO_SS0_MAP,
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= LEO_OFF_SS0,
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x800000
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= LEO_LC_SS0_USR_MAP,
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= LEO_OFF_LC_SS0_USR,
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= LEO_LD_SS0_MAP,
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= LEO_OFF_LD_SS0,
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= LEO_LX_CURSOR_MAP,
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= LEO_OFF_LX_CURSOR,
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= LEO_SS1_MAP,
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= LEO_OFF_SS1,
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x800000
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= LEO_LC_SS1_USR_MAP,
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= LEO_OFF_LC_SS1_USR,
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= LEO_LD_SS1_MAP,
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= LEO_OFF_LD_SS1,
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= LEO_UNK_MAP,
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= LEO_OFF_UNK,
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= LEO_LX_KRN_MAP,
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= LEO_OFF_LX_KRN,
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= LEO_LC_SS0_KRN_MAP,
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= LEO_OFF_LC_SS0_KRN,
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= LEO_LC_SS1_KRN_MAP,
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= LEO_OFF_LC_SS1_KRN,
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= LEO_LD_GBL_MAP,
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= LEO_OFF_LD_GBL,
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= LEO_UNK2_MAP,
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= LEO_OFF_UNK2,
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x100000
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ .size = 0 }
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
415216d526c89d144928f095f2800bc6c67e968d628Christoph Hellwigstatic int leo_mmap(struct fb_info *info, struct vm_area_struct *vma)
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct leo_par *par = (struct leo_par *)info->par;
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sbusfb_mmap_helper(leo_mmap_map,
4208803f7afe6370af8cd97991bde0c3b53eca4e8daKrzysztof Helt				  info->fix.smem_start, info->fix.smem_len,
42150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller				  par->which_io, vma);
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42467a6680d64e18c7a1901f31ef747ea53b6cd986dChristoph Hellwigstatic int leo_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sbusfb_ioctl_helper(cmd, arg, info,
4278803f7afe6370af8cd97991bde0c3b53eca4e8daKrzysztof Helt				   FBTYPE_SUNLEO, 32, info->fix.smem_len);
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Initialisation
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
43550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Millerleo_init_fix(struct fb_info *info, struct device_node *dp)
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
43750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->fix.type = FB_TYPE_PACKED_PIXELS;
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->fix.visual = FB_VISUAL_TRUECOLOR;
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->fix.line_length = 8192;
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->fix.accel = FB_ACCEL_SUN_LEO;
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void leo_wid_put(struct fb_info *info, struct fb_wid_list *wl)
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct leo_par *par = (struct leo_par *) info->par;
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct leo_lx_krn __iomem *lx_krn = par->lx_krn;
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct fb_wid_item *wi;
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val;
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, j;
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&par->lock, flags);
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	leo_wait(lx_krn);
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) {
461738eca74d1bd3e51180de179b7b74d4e34c4e5a3Robert Reif		switch (wi->wi_type) {
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FB_WID_DBL_8:
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			j = (wi->wi_index & 0xf) + 0x40;
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FB_WID_DBL_24:
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			j = wi->wi_index & 0x3f;
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		};
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sbus_writel(0x5800 + j, &lx_krn->krn_type);
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sbus_writel(wi->wi_values[0], &lx_krn->krn_value);
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = sbus_readl(&lx_krn->krn_csr);
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val |= (LEO_KRN_CSR_UNK | LEO_KRN_CSR_UNK2);
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sbus_writel(val, &lx_krn->krn_csr);
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&par->lock, flags);
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void leo_init_wids(struct fb_info *info)
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct fb_wid_item wi;
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct fb_wid_list wl;
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wl.wl_count = 1;
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wl.wl_list = &wi;
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wi.wi_type = FB_WID_DBL_8;
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wi.wi_index = 0;
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wi.wi_values [0] = 0x2c0;
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	leo_wid_put(info, &wl);
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wi.wi_index = 1;
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wi.wi_values [0] = 0x30;
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	leo_wid_put(info, &wl);
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wi.wi_index = 2;
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wi.wi_values [0] = 0x20;
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	leo_wid_put(info, &wl);
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wi.wi_type = FB_WID_DBL_24;
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wi.wi_index = 1;
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wi.wi_values [0] = 0x30;
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	leo_wid_put(info, &wl);
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void leo_init_hw(struct fb_info *info)
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct leo_par *par = (struct leo_par *) info->par;
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val;
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = sbus_readl(&par->ld_ss1->ss1_misc);
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val |= LEO_SS1_MISC_ENABLE;
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sbus_writel(val, &par->ld_ss1->ss1_misc);
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	leo_switch_from_graph(info);
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void leo_fixup_var_rgb(struct fb_var_screeninfo *var)
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->red.offset = 0;
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->red.length = 8;
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->green.offset = 8;
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->green.length = 8;
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->blue.offset = 16;
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->blue.length = 8;
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->transp.offset = 0;
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->transp.length = 0;
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5322dc11581376829303b98eadb2de253bee065a56aGrant Likelystatic void leo_unmap_regs(struct platform_device *op, struct fb_info *info,
533c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller			   struct leo_par *par)
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
535c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (par->lc_ss0_usr)
536c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		of_iounmap(&op->resource[0], par->lc_ss0_usr, 0x1000);
537c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (par->ld_ss0)
538c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		of_iounmap(&op->resource[0], par->ld_ss0, 0x1000);
539c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (par->ld_ss1)
540c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		of_iounmap(&op->resource[0], par->ld_ss1, 0x1000);
541c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (par->lx_krn)
542c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		of_iounmap(&op->resource[0], par->lx_krn, 0x1000);
543c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (par->cursor)
544e3a411a3dfc1d633504aa63efab32b7e00318454David S. Miller		of_iounmap(&op->resource[0],
545c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller			   par->cursor, sizeof(struct leo_cursor));
546c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (info->screen_base)
547c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		of_iounmap(&op->resource[0], info->screen_base, 0x800000);
54850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller}
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55028541d0f1894cd0c8f4a90c6e006c88d38ad3ac0Grant Likelystatic int __devinit leo_probe(struct platform_device *op)
55150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller{
552d4b8b2c2c0b980fa756267e43e39e5ac3c894857Anatolij Gustschin	struct device_node *dp = op->dev.of_node;
553c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	struct fb_info *info;
554c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	struct leo_par *par;
55550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	int linebytes, err;
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
557c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info = framebuffer_alloc(sizeof(struct leo_par), &op->dev);
558c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
559c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	err = -ENOMEM;
560c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (!info)
561c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		goto out_err;
562c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par = info->par;
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
564c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	spin_lock_init(&par->lock);
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5668803f7afe6370af8cd97991bde0c3b53eca4e8daKrzysztof Helt	info->fix.smem_start = op->resource[0].start;
567c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->which_io = op->resource[0].flags & IORESOURCE_BITS;
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5696cd5a86b56ec8fc8651c043bdb05ea0c662fb704Robert Reif	sbusfb_fill_var(&info->var, dp, 32);
570c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	leo_fixup_var_rgb(&info->var);
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
57250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	linebytes = of_getintprop_default(dp, "linebytes",
573c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller					  info->var.xres);
5748803f7afe6370af8cd97991bde0c3b53eca4e8daKrzysztof Helt	info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
576c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->lc_ss0_usr =
57750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller		of_ioremap(&op->resource[0], LEO_OFF_LC_SS0_USR,
57850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller			   0x1000, "leolc ss0usr");
579c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->ld_ss0 =
58050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller		of_ioremap(&op->resource[0], LEO_OFF_LD_SS0,
58150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller			   0x1000, "leold ss0");
582c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->ld_ss1 =
58350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller		of_ioremap(&op->resource[0], LEO_OFF_LD_SS1,
58450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller			   0x1000, "leold ss1");
585c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->lx_krn =
58650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller		of_ioremap(&op->resource[0], LEO_OFF_LX_KRN,
58750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller			   0x1000, "leolx krn");
588c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->cursor =
58950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller		of_ioremap(&op->resource[0], LEO_OFF_LX_CURSOR,
59050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller			   sizeof(struct leo_cursor), "leolx cursor");
591c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info->screen_base =
59250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller		of_ioremap(&op->resource[0], LEO_OFF_SS0,
59350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller			   0x800000, "leo ram");
594c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (!par->lc_ss0_usr ||
595c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	    !par->ld_ss0 ||
596c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	    !par->ld_ss1 ||
597c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	    !par->lx_krn ||
598c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	    !par->cursor ||
599c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	    !info->screen_base)
600c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		goto out_unmap_regs;
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
602738eca74d1bd3e51180de179b7b74d4e34c4e5a3Robert Reif	info->flags = FBINFO_DEFAULT;
603c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info->fbops = &leo_ops;
604738eca74d1bd3e51180de179b7b74d4e34c4e5a3Robert Reif	info->pseudo_palette = par->clut_data;
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
606c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	leo_init_wids(info);
607c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	leo_init_hw(info);
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
60959f7137a1369c25308672def38f3b126d0c7575aRobert Reif	leo_blank(FB_BLANK_UNBLANK, info);
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
611c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (fb_alloc_cmap(&info->cmap, 256, 0))
612c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		goto out_unmap_regs;
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
614c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	leo_init_fix(info, dp);
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
616c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	err = register_framebuffer(info);
617c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (err < 0)
618c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		goto out_dealloc_cmap;
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
620c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	dev_set_drvdata(&op->dev, info);
62150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
622194f1a68b93e959ede6ec363db4714e630bdbb6aRobert Reif	printk(KERN_INFO "%s: leo at %lx:%lx\n",
62350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	       dp->full_name,
6248803f7afe6370af8cd97991bde0c3b53eca4e8daKrzysztof Helt	       par->which_io, info->fix.smem_start);
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
62650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	return 0;
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
628c7f439b99efbea74c70a5531f92566db5a6731f2David S. Millerout_dealloc_cmap:
629c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	fb_dealloc_cmap(&info->cmap);
630c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
631c7f439b99efbea74c70a5531f92566db5a6731f2David S. Millerout_unmap_regs:
632c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	leo_unmap_regs(op, info, par);
633c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	framebuffer_release(info);
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
635c7f439b99efbea74c70a5531f92566db5a6731f2David S. Millerout_err:
636c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	return err;
63750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller}
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6392dc11581376829303b98eadb2de253bee065a56aGrant Likelystatic int __devexit leo_remove(struct platform_device *op)
64050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller{
641c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	struct fb_info *info = dev_get_drvdata(&op->dev);
642c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	struct leo_par *par = info->par;
64350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
644c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	unregister_framebuffer(info);
645c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	fb_dealloc_cmap(&info->cmap);
64650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
647c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	leo_unmap_regs(op, info, par);
64850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
649c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	framebuffer_release(info);
65050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
651e3a411a3dfc1d633504aa63efab32b7e00318454David S. Miller	dev_set_drvdata(&op->dev, NULL);
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
656fd098316ef533e8441576f020ead4beab93154ceDavid S. Millerstatic const struct of_device_id leo_match[] = {
65750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	{
658738eca74d1bd3e51180de179b7b74d4e34c4e5a3Robert Reif		.name = "SUNW,leo",
65950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	},
66050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	{},
66150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller};
66250312ce9dd794eef3df9e64194ba95ca730d82c8David S. MillerMODULE_DEVICE_TABLE(of, leo_match);
66350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
66428541d0f1894cd0c8f4a90c6e006c88d38ad3ac0Grant Likelystatic struct platform_driver leo_driver = {
6654018294b53d1dae026880e45f174c1cc63b5d435Grant Likely	.driver = {
6664018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.name = "leo",
6674018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.owner = THIS_MODULE,
6684018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.of_match_table = leo_match,
6694018294b53d1dae026880e45f174c1cc63b5d435Grant Likely	},
67050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	.probe		= leo_probe,
67150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	.remove		= __devexit_p(leo_remove),
67250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller};
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
67450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Millerstatic int __init leo_init(void)
67550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller{
67650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	if (fb_get_options("leofb", NULL))
67750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller		return -ENODEV;
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
67928541d0f1894cd0c8f4a90c6e006c88d38ad3ac0Grant Likely	return platform_driver_register(&leo_driver);
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
68250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Millerstatic void __exit leo_exit(void)
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
68428541d0f1894cd0c8f4a90c6e006c88d38ad3ac0Grant Likely	platform_driver_unregister(&leo_driver);
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(leo_init);
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(leo_exit);
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("framebuffer driver for LEO chipsets");
69150312ce9dd794eef3df9e64194ba95ca730d82c8David S. MillerMODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
69250312ce9dd794eef3df9e64194ba95ca730d82c8David S. MillerMODULE_VERSION("2.0");
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
694