11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* cg14.c: CGFOURTEEN frame buffer driver
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
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>
18631a9dca60ddd7d84a08171a14828e9cfb667d48Robert Reif#include <linux/uaccess.h>
196cd5a86b56ec8fc8651c043bdb05ea0c662fb704Robert Reif#include <linux/of_device.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/fbio.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sbuslib.h"
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Local functions.
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned,
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 unsigned, struct fb_info *);
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33216d526c89d144928f095f2800bc6c67e968d628Christoph Hellwigstatic int cg14_mmap(struct fb_info *, struct vm_area_struct *);
3467a6680d64e18c7a1901f31ef747ea53b6cd986dChristoph Hellwigstatic int cg14_ioctl(struct fb_info *, unsigned int, unsigned long);
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cg14_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 cg14_ops = {
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner			= THIS_MODULE,
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_setcolreg		= cg14_setcolreg,
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_pan_display		= cg14_pan_display,
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_fillrect		= cfb_fillrect,
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_copyarea		= cfb_copyarea,
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_imageblit		= cfb_imageblit,
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_mmap		= cg14_mmap,
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_ioctl		= cg14_ioctl,
509ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig#ifdef CONFIG_COMPAT
519ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	.fb_compat_ioctl	= sbusfb_compat_ioctl,
529ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig#endif
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_MCR_INTENABLE_SHIFT	7
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_MCR_INTENABLE_MASK		0x80
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_MCR_VIDENABLE_SHIFT	6
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_MCR_VIDENABLE_MASK		0x40
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_MCR_PIXMODE_SHIFT		4
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_MCR_PIXMODE_MASK		0x30
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_MCR_TMR_SHIFT		2
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_MCR_TMR_MASK		0x0c
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_MCR_TMENABLE_SHIFT		1
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_MCR_TMENABLE_MASK		0x02
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_MCR_RESET_SHIFT		0
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_MCR_RESET_MASK		0x01
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_REV_REVISION_SHIFT		4
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_REV_REVISION_MASK		0xf0
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_REV_IMPL_SHIFT		0
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_REV_IMPL_MASK		0x0f
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VBR_FRAMEBASE_SHIFT	12
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VBR_FRAMEBASE_MASK		0x00fff000
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VMCR1_SETUP_SHIFT		0
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VMCR1_SETUP_MASK		0x000001ff
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VMCR1_VCONFIG_SHIFT	9
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VMCR1_VCONFIG_MASK		0x00000e00
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VMCR2_REFRESH_SHIFT	0
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VMCR2_REFRESH_MASK		0x00000001
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VMCR2_TESTROWCNT_SHIFT	1
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VMCR2_TESTROWCNT_MASK	0x00000002
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VMCR2_FBCONFIG_SHIFT	2
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VMCR2_FBCONFIG_MASK	0x0000000c
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VCR_REFRESHREQ_SHIFT	0
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VCR_REFRESHREQ_MASK	0x000003ff
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VCR1_REFRESHENA_SHIFT	10
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VCR1_REFRESHENA_MASK	0x00000400
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VCA_CAD_SHIFT		0
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VCA_CAD_MASK		0x000003ff
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VCA_VERS_SHIFT		10
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VCA_VERS_MASK		0x00000c00
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VCA_RAMSPEED_SHIFT		12
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VCA_RAMSPEED_MASK		0x00001000
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VCA_8MB_SHIFT		13
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_VCA_8MB_MASK		0x00002000
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_MCR_PIXMODE_8		0
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_MCR_PIXMODE_16		2
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_MCR_PIXMODE_32		3
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct cg14_regs{
10150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u8 mcr;	/* Master Control Reg */
10250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u8 ppr;	/* Packed Pixel Reg */
10350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u8 tms[2];	/* Test Mode Status Regs */
10450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u8 msr;	/* Master Status Reg */
10550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u8 fsr;	/* Fault Status Reg */
10650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u8 rev;	/* Revision & Impl */
10750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u8 ccr;	/* Clock Control Reg */
10850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32 tmr;	/* Test Mode Read Back */
10950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u8 mod;	/* Monitor Operation Data Reg */
11050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u8 acr;	/* Aux Control */
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 xxx0[6];
11250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u16 hct;	/* Hor Counter */
11350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u16 vct;	/* Vert Counter */
11450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u16 hbs;	/* Hor Blank Start */
11550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u16 hbc;	/* Hor Blank Clear */
11650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u16 hss;	/* Hor Sync Start */
11750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u16 hsc;	/* Hor Sync Clear */
11850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u16 csc;	/* Composite Sync Clear */
11950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u16 vbs;	/* Vert Blank Start */
12050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u16 vbc;	/* Vert Blank Clear */
12150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u16 vss;	/* Vert Sync Start */
12250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u16 vsc;	/* Vert Sync Clear */
12350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u16 xcs;
12450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u16 xcc;
12550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u16 fsa;	/* Fault Status Address */
12650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u16 adr;	/* Address Registers */
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 xxx1[0xce];
12850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u8 pcg[0x100]; /* Pixel Clock Generator */
12950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32 vbr;	/* Frame Base Row */
13050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32 vmcr;	/* VBC Master Control */
13150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32 vcr;	/* VBC refresh */
13250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32 vca;	/* VBC Config */
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_CCR_ENABLE	0x04
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_CCR_SELECT 0x02	/* HW/Full screen */
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct cg14_cursor {
13950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32 cpl0[32];	/* Enable plane 0 */
14050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32 cpl1[32];  /* Color selection plane */
14150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u8 ccr;	/* Cursor Control Reg */
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 xxx0[3];
14350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u16 cursx;	/* Cursor x,y position */
14450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u16 cursy;	/* Cursor x,y position */
14550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32 color0;
14650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32 color1;
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 xxx1[0x1bc];
14850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32 cpl0i[32];	/* Enable plane 0 autoinc */
14950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32 cpl1i[32]; /* Color selection autoinc */
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct cg14_dac {
15350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u8 addr;	/* Address Register */
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 xxx0[255];
15550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u8 glut;	/* Gamma table */
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 xxx1[255];
15750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u8 select;	/* Register Select */
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 xxx2[255];
15950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u8 mode;	/* Mode Register */
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct cg14_xlut{
16350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u8 x_xlut [256];
16450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u8 x_xlutd [256];
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 xxx0[0x600];
16650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u8 x_xlut_inc [256];
16750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u8 x_xlutd_inc [256];
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Color look up table (clut) */
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Each one of these arrays hold the color lookup table (for 256
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * colors) for each MDI page (I assume then there should be 4 MDI
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pages, I still wonder what they are.  I have seen NeXTStep split
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the screen in four parts, while operating in 24 bits mode.  Each
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * integer holds 4 values: alpha value (transparency channel, thanks
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * go to John Stone (johns@umr.edu) from OpenBSD), red, green and blue
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * I currently use the clut instead of the Xlut
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct cg14_clut {
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 c_clut [256];
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 c_clutd [256];    /* i wonder what the 'd' is for */
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 c_clut_inc [256];
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 c_clutd_inc [256];
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_MMAP_ENTRIES	16
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct cg14_par {
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spinlock_t		lock;
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct cg14_regs	__iomem *regs;
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct cg14_clut	__iomem *clut;
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct cg14_cursor	__iomem *cursor;
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32			flags;
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CG14_FLAG_BLANKED	0x00000001
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		iospace;
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sbus_mmap_map	mmap_map[CG14_MMAP_ENTRIES];
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			mode;
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			ramsize;
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __cg14_reset(struct cg14_par *par)
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct cg14_regs __iomem *regs = par->regs;
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 val;
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = sbus_readb(&regs->mcr);
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val &= ~(CG14_MCR_PIXMODE_MASK);
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sbus_writeb(val, &regs->mcr);
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cg14_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct cg14_par *par = (struct cg14_par *) info->par;
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We just use this to catch switches out of
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * graphics mode.
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&par->lock, flags);
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__cg14_reset(par);
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&par->lock, flags);
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (var->xoffset || var->yoffset || var->vmode)
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      cg14_setcolreg - Optional function. Sets a color register.
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      @regno: boolean, 0 copy local, 1 get_user() function
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      @red: frame buffer colormap structure
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      @green: The green value which can be up to 16 bits wide
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      @blue:  The blue value which can be up to 16 bits wide.
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      @transp: If supported the alpha value which can be up to 16 bits wide.
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      @info: frame buffer info structure
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cg14_setcolreg(unsigned regno,
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  unsigned red, unsigned green, unsigned blue,
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  unsigned transp, struct fb_info *info)
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct cg14_par *par = (struct cg14_par *) info->par;
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct cg14_clut __iomem *clut = par->clut;
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val;
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (regno >= 256)
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1;
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	red >>= 8;
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	green >>= 8;
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	blue >>= 8;
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = (red | (green << 8) | (blue << 16));
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&par->lock, flags);
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sbus_writel(val, &clut->c_clut[regno]);
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&par->lock, flags);
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
266216d526c89d144928f095f2800bc6c67e968d628Christoph Hellwigstatic int cg14_mmap(struct fb_info *info, struct vm_area_struct *vma)
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct cg14_par *par = (struct cg14_par *) info->par;
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sbusfb_mmap_helper(par->mmap_map,
271de4dc48ee26ccc9dbc6a86b0710f7fd408149056Krzysztof Helt				  info->fix.smem_start, info->fix.smem_len,
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  par->iospace, vma);
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27567a6680d64e18c7a1901f31ef747ea53b6cd986dChristoph Hellwigstatic int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct cg14_par *par = (struct cg14_par *) info->par;
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct cg14_regs __iomem *regs = par->regs;
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mdi_cfginfo kmdi, __user *mdii;
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int cur_mode, mode, ret = 0;
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MDI_RESET:
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_lock_irqsave(&par->lock, flags);
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__cg14_reset(par);
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(&par->lock, flags);
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MDI_GET_CFGINFO:
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memset(&kmdi, 0, sizeof(kmdi));
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_lock_irqsave(&par->lock, flags);
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kmdi.mdi_type = FBTYPE_MDICOLOR;
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kmdi.mdi_height = info->var.yres;
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kmdi.mdi_width = info->var.xres;
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kmdi.mdi_mode = par->mode;
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kmdi.mdi_pixfreq = 72; /* FIXME */
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kmdi.mdi_size = par->ramsize;
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(&par->lock, flags);
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mdii = (struct mdi_cfginfo __user *) arg;
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (copy_to_user(mdii, &kmdi, sizeof(kmdi)))
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = -EFAULT;
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MDI_SET_PIXELMODE:
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (get_user(mode, (int __user *) arg)) {
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = -EFAULT;
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_lock_irqsave(&par->lock, flags);
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cur_mode = sbus_readb(&regs->mcr);
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cur_mode &= ~CG14_MCR_PIXMODE_MASK;
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch(mode) {
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MDI_32_PIX:
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cur_mode |= (CG14_MCR_PIXMODE_32 <<
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     CG14_MCR_PIXMODE_SHIFT);
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MDI_16_PIX:
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cur_mode |= (CG14_MCR_PIXMODE_16 <<
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     CG14_MCR_PIXMODE_SHIFT);
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MDI_8_PIX:
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = -ENOSYS;
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		};
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!ret) {
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			sbus_writeb(cur_mode, &regs->mcr);
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			par->mode = mode;
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(&par->lock, flags);
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = sbusfb_ioctl_helper(cmd, arg, info,
343de4dc48ee26ccc9dbc6a86b0710f7fd408149056Krzysztof Helt					  FBTYPE_MDICOLOR, 8,
344de4dc48ee26ccc9dbc6a86b0710f7fd408149056Krzysztof Helt					  info->fix.smem_len);
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Initialisation
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3558fdab4763a04f503301b14810b39c536f2277120Robert Reifstatic void __devinit cg14_init_fix(struct fb_info *info, int linebytes,
3568fdab4763a04f503301b14810b39c536f2277120Robert Reif				    struct device_node *dp)
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
35850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	const char *name = dp->name;
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	strlcpy(info->fix.id, name, sizeof(info->fix.id));
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->fix.type = FB_TYPE_PACKED_PIXELS;
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->fix.line_length = linebytes;
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->fix.accel = FB_ACCEL_SUN_CG14;
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3708fdab4763a04f503301b14810b39c536f2277120Robert Reifstatic struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __devinitdata = {
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= CG14_REGS,
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= 0x80000000,
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= CG14_XLUT,
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= 0x80003000,
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= CG14_CLUT1,
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= 0x80004000,
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= CG14_CLUT2,
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= 0x80005000,
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= CG14_CLUT3,
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= 0x80006000,
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= CG3_MMAP_OFFSET - 0x7000,
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= 0x80000000,
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x7000
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= CG3_MMAP_OFFSET,
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= 0x00000000,
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= SBUS_MMAP_FBSIZE(1)
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= MDI_CURSOR_MAP,
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= 0x80001000,
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= MDI_CHUNKY_BGR_MAP,
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= 0x01000000,
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x400000
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= MDI_PLANAR_X16_MAP,
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= 0x02000000,
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x200000
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= MDI_PLANAR_C16_MAP,
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= 0x02800000,
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x200000
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= MDI_PLANAR_X32_MAP,
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= 0x03000000,
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x100000
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= MDI_PLANAR_B32_MAP,
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= 0x03400000,
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x100000
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= MDI_PLANAR_G32_MAP,
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= 0x03800000,
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x100000
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= MDI_PLANAR_R32_MAP,
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= 0x03c00000,
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x100000
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ .size = 0 }
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4492dc11581376829303b98eadb2de253bee065a56aGrant Likelystatic void cg14_unmap_regs(struct platform_device *op, struct fb_info *info,
450c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller			    struct cg14_par *par)
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
452c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (par->regs)
453e3a411a3dfc1d633504aa63efab32b7e00318454David S. Miller		of_iounmap(&op->resource[0],
454c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller			   par->regs, sizeof(struct cg14_regs));
455c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (par->clut)
456e3a411a3dfc1d633504aa63efab32b7e00318454David S. Miller		of_iounmap(&op->resource[0],
457c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller			   par->clut, sizeof(struct cg14_clut));
458c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (par->cursor)
459e3a411a3dfc1d633504aa63efab32b7e00318454David S. Miller		of_iounmap(&op->resource[0],
460c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller			   par->cursor, sizeof(struct cg14_cursor));
461c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (info->screen_base)
462e3a411a3dfc1d633504aa63efab32b7e00318454David S. Miller		of_iounmap(&op->resource[1],
463de4dc48ee26ccc9dbc6a86b0710f7fd408149056Krzysztof Helt			   info->screen_base, info->fix.smem_len);
46450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller}
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46628541d0f1894cd0c8f4a90c6e006c88d38ad3ac0Grant Likelystatic int __devinit cg14_probe(struct platform_device *op)
46750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller{
468d4b8b2c2c0b980fa756267e43e39e5ac3c894857Anatolij Gustschin	struct device_node *dp = op->dev.of_node;
469c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	struct fb_info *info;
470c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	struct cg14_par *par;
47150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	int is_8mb, linebytes, i, err;
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
473c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info = framebuffer_alloc(sizeof(struct cg14_par), &op->dev);
474c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
475c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	err = -ENOMEM;
476c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (!info)
477c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		goto out_err;
478c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par = info->par;
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
480c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	spin_lock_init(&par->lock);
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4826cd5a86b56ec8fc8651c043bdb05ea0c662fb704Robert Reif	sbusfb_fill_var(&info->var, dp, 8);
483c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info->var.red.length = 8;
484c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info->var.green.length = 8;
485c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info->var.blue.length = 8;
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	linebytes = of_getintprop_default(dp, "linebytes",
488c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller					  info->var.xres);
489de4dc48ee26ccc9dbc6a86b0710f7fd408149056Krzysztof Helt	info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	if (!strcmp(dp->parent->name, "sbus") ||
49250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	    !strcmp(dp->parent->name, "sbi")) {
493de4dc48ee26ccc9dbc6a86b0710f7fd408149056Krzysztof Helt		info->fix.smem_start = op->resource[0].start;
494c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		par->iospace = op->resource[0].flags & IORESOURCE_BITS;
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
496de4dc48ee26ccc9dbc6a86b0710f7fd408149056Krzysztof Helt		info->fix.smem_start = op->resource[1].start;
497c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		par->iospace = op->resource[0].flags & IORESOURCE_BITS;
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
500c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->regs = of_ioremap(&op->resource[0], 0,
501c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller			       sizeof(struct cg14_regs), "cg14 regs");
502c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->clut = of_ioremap(&op->resource[0], CG14_CLUT1,
503c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller			       sizeof(struct cg14_clut), "cg14 clut");
504c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->cursor = of_ioremap(&op->resource[0], CG14_CURSORREGS,
505c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller				 sizeof(struct cg14_cursor), "cg14 cursor");
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
507c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info->screen_base = of_ioremap(&op->resource[1], 0,
508de4dc48ee26ccc9dbc6a86b0710f7fd408149056Krzysztof Helt				       info->fix.smem_len, "cg14 ram");
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
510c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (!par->regs || !par->clut || !par->cursor || !info->screen_base)
511c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		goto out_unmap_regs;
51250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
51350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	is_8mb = (((op->resource[1].end - op->resource[1].start) + 1) ==
51450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller		  (8 * 1024 * 1024));
51550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
516c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	BUILD_BUG_ON(sizeof(par->mmap_map) != sizeof(__cg14_mmap_map));
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
518c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	memcpy(&par->mmap_map, &__cg14_mmap_map, sizeof(par->mmap_map));
51950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < CG14_MMAP_ENTRIES; i++) {
521c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		struct sbus_mmap_map *map = &par->mmap_map[i];
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!map->size)
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (map->poff & 0x80000000)
52650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller			map->poff = (map->poff & 0x7fffffff) +
52750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller				(op->resource[0].start -
52850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller				 op->resource[1].start);
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (is_8mb &&
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    map->size >= 0x100000 &&
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    map->size <= 0x400000)
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			map->size *= 2;
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
535c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->mode = MDI_8_PIX;
536c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->ramsize = (is_8mb ? 0x800000 : 0x400000);
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
538c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
539c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info->fbops = &cg14_ops;
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
541c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	__cg14_reset(par);
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
543c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (fb_alloc_cmap(&info->cmap, 256, 0))
544c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		goto out_unmap_regs;
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
546c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	fb_set_cmap(&info->cmap, info);
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
548c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	cg14_init_fix(info, linebytes, dp);
549c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
550c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	err = register_framebuffer(info);
551c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (err < 0)
552c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		goto out_dealloc_cmap;
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
554c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	dev_set_drvdata(&op->dev, info);
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
556194f1a68b93e959ede6ec363db4714e630bdbb6aRobert Reif	printk(KERN_INFO "%s: cgfourteen at %lx:%lx, %dMB\n",
55750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	       dp->full_name,
558de4dc48ee26ccc9dbc6a86b0710f7fd408149056Krzysztof Helt	       par->iospace, info->fix.smem_start,
559c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	       par->ramsize >> 20);
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	return 0;
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
563c7f439b99efbea74c70a5531f92566db5a6731f2David S. Millerout_dealloc_cmap:
564c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	fb_dealloc_cmap(&info->cmap);
565c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
566c7f439b99efbea74c70a5531f92566db5a6731f2David S. Millerout_unmap_regs:
567c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	cg14_unmap_regs(op, info, par);
5686359691d7efc639bf0f996aa9a694b2653fc6ae6Axel Lin	framebuffer_release(info);
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
570c7f439b99efbea74c70a5531f92566db5a6731f2David S. Millerout_err:
571c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	return err;
57250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller}
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5742dc11581376829303b98eadb2de253bee065a56aGrant Likelystatic int __devexit cg14_remove(struct platform_device *op)
57550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller{
576c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	struct fb_info *info = dev_get_drvdata(&op->dev);
577c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	struct cg14_par *par = info->par;
57850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
579c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	unregister_framebuffer(info);
580c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	fb_dealloc_cmap(&info->cmap);
58150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
582c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	cg14_unmap_regs(op, info, par);
58350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
584c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	framebuffer_release(info);
58550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
586e3a411a3dfc1d633504aa63efab32b7e00318454David S. Miller	dev_set_drvdata(&op->dev, NULL);
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
591fd098316ef533e8441576f020ead4beab93154ceDavid S. Millerstatic const struct of_device_id cg14_match[] = {
59250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	{
59350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller		.name = "cgfourteen",
59450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	},
59550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	{},
59650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller};
59750312ce9dd794eef3df9e64194ba95ca730d82c8David S. MillerMODULE_DEVICE_TABLE(of, cg14_match);
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
59928541d0f1894cd0c8f4a90c6e006c88d38ad3ac0Grant Likelystatic struct platform_driver cg14_driver = {
6004018294b53d1dae026880e45f174c1cc63b5d435Grant Likely	.driver = {
6014018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.name = "cg14",
6024018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.owner = THIS_MODULE,
6034018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.of_match_table = cg14_match,
6044018294b53d1dae026880e45f174c1cc63b5d435Grant Likely	},
60550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	.probe		= cg14_probe,
60650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	.remove		= __devexit_p(cg14_remove),
60750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller};
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
609544330009bc5b879129593236aab29e458ec9fe4Robert Reifstatic int __init cg14_init(void)
61050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller{
61150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	if (fb_get_options("cg14fb", NULL))
61250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller		return -ENODEV;
61350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
61428541d0f1894cd0c8f4a90c6e006c88d38ad3ac0Grant Likely	return platform_driver_register(&cg14_driver);
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
617544330009bc5b879129593236aab29e458ec9fe4Robert Reifstatic void __exit cg14_exit(void)
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
61928541d0f1894cd0c8f4a90c6e006c88d38ad3ac0Grant Likely	platform_driver_unregister(&cg14_driver);
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(cg14_init);
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(cg14_exit);
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("framebuffer driver for CGfourteen chipsets");
62650312ce9dd794eef3df9e64194ba95ca730d82c8David S. MillerMODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
62750312ce9dd794eef3df9e64194ba95ca730d82c8David S. MillerMODULE_VERSION("2.0");
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
629