[go: nahoru, domu]

ffb.c revision f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bb
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ffb.c: Creator/Elite3D frame buffer driver
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Driver layout based loosely on tgafb.c, see that file for credits.
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.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>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/upa.h>
2250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller#include <asm/prom.h>
2350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller#include <asm/of_device.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/fbio.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sbuslib.h"
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Local functions.
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ffb_setcolreg(unsigned, unsigned, unsigned, unsigned,
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 unsigned, struct fb_info *);
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ffb_blank(int, struct fb_info *);
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ffb_init_fix(struct fb_info *);
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ffb_imageblit(struct fb_info *, const struct fb_image *);
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ffb_fillrect(struct fb_info *, const struct fb_fillrect *);
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ffb_copyarea(struct fb_info *, const struct fb_copyarea *);
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ffb_sync(struct fb_info *);
41216d526c89d144928f095f2800bc6c67e968d628Christoph Hellwigstatic int ffb_mmap(struct fb_info *, struct vm_area_struct *);
4267a6680d64e18c7a1901f31ef747ea53b6cd986dChristoph Hellwigstatic int ffb_ioctl(struct fb_info *, unsigned int, unsigned long);
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ffb_pan_display(struct fb_var_screeninfo *, struct fb_info *);
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Frame buffer operations
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct fb_ops ffb_ops = {
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner			= THIS_MODULE,
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_setcolreg		= ffb_setcolreg,
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_blank		= ffb_blank,
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_pan_display		= ffb_pan_display,
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_fillrect		= ffb_fillrect,
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_copyarea		= ffb_copyarea,
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_imageblit		= ffb_imageblit,
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_sync		= ffb_sync,
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_mmap		= ffb_mmap,
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_ioctl		= ffb_ioctl,
609ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig#ifdef CONFIG_COMPAT
619ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	.fb_compat_ioctl	= sbusfb_compat_ioctl,
629ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig#endif
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Register layout and definitions */
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB8R_VOFF		0x00000000
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB8G_VOFF		0x00400000
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB8B_VOFF		0x00800000
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB8X_VOFF		0x00c00000
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB32_VOFF		0x01000000
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB64_VOFF		0x02000000
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_FBC_REGS_VOFF	0x04000000
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_BM_FBC_REGS_VOFF	0x04002000
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB8R_VOFF		0x04004000
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB8G_VOFF		0x04404000
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB8B_VOFF		0x04804000
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB8X_VOFF		0x04c04000
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB24_VOFF		0x05004000
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB32_VOFF		0x06004000
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB422A_VOFF	0x07004000	/* DFB 422 mode write to A */
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB422AD_VOFF	0x07804000	/* DFB 422 mode with line doubling */
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB24B_VOFF		0x08004000	/* DFB 24bit mode write to B */
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB422B_VOFF	0x09004000	/* DFB 422 mode write to B */
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB422BD_VOFF	0x09804000	/* DFB 422 mode with line doubling */
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB16Z_VOFF		0x0a004000	/* 16bit mode Z planes */
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB8Z_VOFF		0x0a404000	/* 8bit mode Z planes */
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB422_VOFF		0x0ac04000	/* SFB 422 mode write to A/B */
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB422D_VOFF	0x0b404000	/* SFB 422 mode with line doubling */
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_FBC_KREGS_VOFF	0x0bc04000
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DAC_VOFF		0x0bc06000
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_PROM_VOFF		0x0bc08000
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_EXP_VOFF		0x0bc18000
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB8R_POFF		0x04000000UL
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB8G_POFF		0x04400000UL
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB8B_POFF		0x04800000UL
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB8X_POFF		0x04c00000UL
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB32_POFF		0x05000000UL
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB64_POFF		0x06000000UL
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_FBC_REGS_POFF	0x00600000UL
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_BM_FBC_REGS_POFF	0x00600000UL
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB8R_POFF		0x01000000UL
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB8G_POFF		0x01400000UL
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB8B_POFF		0x01800000UL
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB8X_POFF		0x01c00000UL
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB24_POFF		0x02000000UL
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB32_POFF		0x03000000UL
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_FBC_KREGS_POFF	0x00610000UL
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DAC_POFF		0x00400000UL
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_PROM_POFF		0x00000000UL
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_EXP_POFF		0x00200000UL
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DFB422A_POFF	0x09000000UL
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DFB422AD_POFF	0x09800000UL
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DFB24B_POFF		0x0a000000UL
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DFB422B_POFF	0x0b000000UL
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DFB422BD_POFF	0x0b800000UL
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_SFB16Z_POFF		0x0c800000UL
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_SFB8Z_POFF		0x0c000000UL
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_SFB422_POFF		0x0d000000UL
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_SFB422D_POFF	0x0d800000UL
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Draw operations */
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_DOT		0x00
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_AADOT	0x01
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_BRLINECAP	0x02
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_BRLINEOPEN	0x03
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_DDLINE	0x04
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_AALINE	0x05
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_TRIANGLE	0x06
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_POLYGON	0x07
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_RECTANGLE	0x08
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_FASTFILL	0x09
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_BCOPY	0x0a
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_VSCROLL	0x0b
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Pixel processor control */
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Force WID */
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_FW_DISABLE	0x800000
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_FW_ENABLE	0xc00000
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Auxiliary clip */
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_ACE_DISABLE	0x040000
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_ACE_AUX_SUB	0x080000
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_ACE_AUX_ADD	0x0c0000
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Depth cue */
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_DCE_DISABLE	0x020000
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_DCE_ENABLE	0x030000
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Alpha blend */
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_ABE_DISABLE	0x008000
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_ABE_ENABLE	0x00c000
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* View clip */
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_VCE_DISABLE	0x001000
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_VCE_2D		0x002000
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_VCE_3D		0x003000
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Area pattern */
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_APE_DISABLE	0x000800
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_APE_ENABLE	0x000c00
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Transparent background */
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_TBE_OPAQUE	0x000200
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_TBE_TRANSPARENT	0x000300
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Z source */
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_ZS_VAR		0x000080
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_ZS_CONST	0x0000c0
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Y source */
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_YS_VAR		0x000020
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_YS_CONST	0x000030
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* X source */
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_XS_WID		0x000004
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_XS_VAR		0x000008
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_XS_CONST	0x00000c
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Color (BGR) source */
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_CS_VAR		0x000002
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_CS_CONST	0x000003
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
174f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_ROP_NEW		0x83
175f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_ROP_OLD		0x85
176f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_ROP_NEW_XOR_OLD	0x86
177f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
178f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_UCSR_FIFO_MASK	0x00000fff
179f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_UCSR_FB_BUSY	0x01000000
180f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_UCSR_RP_BUSY	0x02000000
181f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_UCSR_ALL_BUSY	(FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY)
182f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_UCSR_READ_ERR	0x40000000
183f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_UCSR_FIFO_OVFL	0x80000000
184f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_UCSR_ALL_ERRORS	(FFB_UCSR_READ_ERR|FFB_UCSR_FIFO_OVFL)
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct ffb_fbc {
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Next vertex registers */
18850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx1[3];
18950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	alpha;
19050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	red;
19150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	green;
19250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	blue;
19350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	depth;
19450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	y;
19550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	x;
19650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx2[2];
19750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	ryf;
19850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rxf;
19950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx3[2];
200f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
20150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dmyf;
20250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dmxf;
20350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx4[2];
20450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	ebyi;
20550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	ebxi;
20650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx5[2];
20750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	by;
20850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	bx;
20950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dy;
21050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dx;
21150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	bh;
21250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	bw;
21350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx6[2];
214f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
21550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx7[32];
216f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Setup unit vertex state register */
21850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	suvtx;
21950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx8[63];
220f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Control registers */
22250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	ppc;
22350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	wid;
22450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fg;
22550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	bg;
22650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	consty;
22750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	constz;
22850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xclip;
22950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcss;
23050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	vclipmin;
23150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	vclipmax;
23250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	vclipzmin;
23350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	vclipzmax;
23450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcsf;
23550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcsb;
23650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dczf;
23750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dczb;
238f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
23950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx9;
24050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	blendc;
24150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	blendc1;
24250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	blendc2;
24350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fbramitc;
24450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fbc;
24550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rop;
24650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	cmp;
24750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	matchab;
24850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	matchc;
24950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	magnab;
25050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	magnc;
25150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fbcfg0;
25250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fbcfg1;
25350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fbcfg2;
25450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fbcfg3;
255f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
25650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	ppcfg;
25750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	pick;
25850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fillmode;
25950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fbramwac;
26050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	pmask;
26150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xpmask;
26250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	ypmask;
26350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	zpmask;
26450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	clip0min;
26550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	clip0max;
26650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	clip1min;
26750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	clip1max;
26850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	clip2min;
26950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	clip2max;
27050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	clip3min;
27150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	clip3max;
272f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* New 3dRAM III support regs */
27450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawblend2;
27550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawpreblend;
27650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawstencil;
27750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawstencilctl;
27850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	threedram1;
27950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	threedram2;
28050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	passin;
28150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawclrdepth;
28250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawpmask;
28350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawcsrc;
28450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawmatch;
28550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawmagn;
28650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawropblend;
28750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawcmp;
28850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawwac;
28950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fbramid;
290f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
29150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	drawop;
29250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx10[2];
29350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fontlpat;
29450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx11;
29550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fontxy;
29650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fontw;
29750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fontinc;
29850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	font;
29950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx12[3];
30050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	blend2;
30150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	preblend;
30250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	stencil;
30350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	stencilctl;
30450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
305f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	u32	xxx13[4];
30650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcss1;
30750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcss2;
30850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcss3;
30950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	widpmask;
31050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcs2;
31150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcs3;
31250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcs4;
31350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx14;
31450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcd2;
31550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcd3;
31650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcd4;
31750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx15;
318f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
31950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	pattern[32];
320f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
32150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx16[256];
322f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
32350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	devid;
32450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx17[63];
325f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
32650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	ucsr;
32750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx18[31];
328f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
32950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	mer;
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct ffb_dac {
33350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	type;
33450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	value;
33550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	type2;
33650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	value2;
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
339f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_UCTRL		0x1001 /* User Control */
340f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_UCTRL_MANREV	0x00000f00 /* 4-bit Manufacturing Revision */
341f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_UCTRL_MANREV_SHIFT 8
342f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_TGEN		0x6000 /* Timing Generator */
343f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_TGEN_VIDE	0x00000001 /* Video Enable */
344f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_DID		0x8000 /* Device Identification */
345f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_DID_PNUM	0x0ffff000 /* Device Part Number */
346f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_DID_PNUM_SHIFT	12
347f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_DID_REV		0xf0000000 /* Device Revision */
348f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_DID_REV_SHIFT	28
34937db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller
35037db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller#define FFB_DAC_CUR_CTRL	0x100
351f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_CUR_CTRL_P0	0x00000001
352f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_CUR_CTRL_P1	0x00000002
35337db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct ffb_par {
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spinlock_t		lock;
35650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_fbc __iomem	*fbc;
35750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_dac __iomem	*dac;
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32			flags;
36037db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller#define FFB_FLAG_AFB		0x00000001 /* AFB m3 or m6 */
36137db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller#define FFB_FLAG_BLANKED	0x00000002 /* screen is blanked */
36237db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller#define FFB_FLAG_INVCURSOR	0x00000004 /* DAC has inverted cursor logic */
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32			fg_cache __attribute__((aligned (8)));
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32			bg_cache;
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32			rop_cache;
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			fifo_cache;
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		physbase;
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		fbsize;
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			board_type;
374c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
375c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	u32			pseudo_palette[16];
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void FFBFifo(struct ffb_par *par, int n)
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
38050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_fbc __iomem *fbc;
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int cache = par->fifo_cache;
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cache - n < 0) {
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fbc = par->fbc;
385f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt		do {
386f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt			cache = (upa_readl(&fbc->ucsr) & FFB_UCSR_FIFO_MASK);
387f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt			cache -= 8;
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} while (cache - n < 0);
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	par->fifo_cache = cache - n;
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void FFBWait(struct ffb_par *par)
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
39550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_fbc __iomem *fbc;
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int limit = 10000;
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fbc = par->fbc;
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_BUSY) == 0)
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) {
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(10);
406f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	} while (--limit > 0);
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ffb_sync(struct fb_info *p)
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
411f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	struct ffb_par *par = (struct ffb_par *)p->par;
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FFBWait(par);
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic __inline__ void ffb_rop(struct ffb_par *par, u32 rop)
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (par->rop_cache != rop) {
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FFBFifo(par, 1);
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		upa_writel(rop, &par->fbc->rop);
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		par->rop_cache = rop;
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ffb_switch_from_graph(struct ffb_par *par)
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
42850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_fbc __iomem *fbc = par->fbc;
42950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_dac __iomem *dac = par->dac;
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&par->lock, flags);
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FFBWait(par);
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	par->fifo_cache = 0;
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FFBFifo(par, 7);
436f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	upa_writel(FFB_PPC_VCE_DISABLE | FFB_PPC_TBE_OPAQUE |
437f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt		   FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   &fbc->ppc);
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(0x2000707f, &fbc->fbc);
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(par->rop_cache, &fbc->rop);
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(0xffffffff, &fbc->pmask);
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel((1 << 16) | (0 << 0), &fbc->fontinc);
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(par->fg_cache, &fbc->fg);
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(par->bg_cache, &fbc->bg);
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FFBWait(par);
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Disable cursor.  */
44837db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	upa_writel(FFB_DAC_CUR_CTRL, &dac->type2);
44937db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	if (par->flags & FFB_FLAG_INVCURSOR)
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		upa_writel(0, &dac->value2);
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
45237db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller		upa_writel((FFB_DAC_CUR_CTRL_P0 |
45337db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller			    FFB_DAC_CUR_CTRL_P1), &dac->value2);
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&par->lock, flags);
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ffb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
460f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	struct ffb_par *par = (struct ffb_par *)info->par;
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We just use this to catch switches out of
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * graphics mode.
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ffb_switch_from_graph(par);
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (var->xoffset || var->yoffset || var->vmode)
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
473f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	ffb_fillrect - Draws a rectangle on the screen.
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
475f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@info: frame buffer structure that represents a single frame buffer
476f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@rect: structure defining the rectagle and operation.
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ffb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
480f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	struct ffb_par *par = (struct ffb_par *)info->par;
48150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_fbc __iomem *fbc = par->fbc;
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 fg;
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
485232443e2c90cc2930624dec89df327615b002c55Eric Sesterhenn	BUG_ON(rect->rop != ROP_COPY && rect->rop != ROP_XOR);
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fg = ((u32 *)info->pseudo_palette)[rect->color];
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&par->lock, flags);
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fg != par->fg_cache) {
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FFBFifo(par, 1);
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		upa_writel(fg, &fbc->fg);
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		par->fg_cache = fg;
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
497f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	ffb_rop(par, rect->rop == ROP_COPY ?
498f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt		     FFB_ROP_NEW :
499f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt		     FFB_ROP_NEW_XOR_OLD);
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FFBFifo(par, 5);
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(FFB_DRAWOP_RECTANGLE, &fbc->drawop);
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(rect->dy, &fbc->by);
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(rect->dx, &fbc->bx);
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(rect->height, &fbc->bh);
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(rect->width, &fbc->bw);
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&par->lock, flags);
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
512f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	ffb_copyarea - Copies on area of the screen to another area.
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
514f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@info: frame buffer structure that represents a single frame buffer
515f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@area: structure defining the source and destination.
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
518f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Heltstatic void ffb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
520f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	struct ffb_par *par = (struct ffb_par *)info->par;
52150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_fbc __iomem *fbc = par->fbc;
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (area->dx != area->sx ||
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    area->dy == area->sy) {
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cfb_copyarea(info, area);
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&par->lock, flags);
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ffb_rop(par, FFB_ROP_OLD);
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FFBFifo(par, 7);
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(FFB_DRAWOP_VSCROLL, &fbc->drawop);
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(area->sy, &fbc->by);
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(area->sx, &fbc->bx);
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(area->dy, &fbc->dy);
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(area->dx, &fbc->dx);
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(area->height, &fbc->bh);
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(area->width, &fbc->bw);
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&par->lock, flags);
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
547f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	ffb_imageblit - Copies a image from system memory to the screen.
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
549f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@info: frame buffer structure that represents a single frame buffer
550f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@image: structure defining the image.
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ffb_imageblit(struct fb_info *info, const struct fb_image *image)
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
554f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	struct ffb_par *par = (struct ffb_par *)info->par;
55550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_fbc __iomem *fbc = par->fbc;
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u8 *data = image->data;
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 fg, bg, xy;
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u64 fgbg;
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, width, stride;
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (image->depth > 1) {
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cfb_imageblit(info, image);
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fg = ((u32 *)info->pseudo_palette)[image->fg_color];
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bg = ((u32 *)info->pseudo_palette)[image->bg_color];
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fgbg = ((u64) fg << 32) | (u64) bg;
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	xy = (image->dy << 16) | image->dx;
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	width = image->width;
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stride = ((width + 7) >> 3);
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&par->lock, flags);
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fgbg != *(u64 *)&par->fg_cache) {
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FFBFifo(par, 2);
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		upa_writeq(fgbg, &fbc->fg);
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*(u64 *)&par->fg_cache = fgbg;
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (width >= 32) {
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FFBFifo(par, 1);
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		upa_writel(32, &fbc->fontw);
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (width >= 32) {
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		const u8 *next_data = data + 4;
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FFBFifo(par, 1);
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		upa_writel(xy, &fbc->fontxy);
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		xy += (32 << 0);
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < image->height; i++) {
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u32 val = (((u32)data[0] << 24) |
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   ((u32)data[1] << 16) |
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   ((u32)data[2] <<  8) |
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   ((u32)data[3] <<  0));
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			FFBFifo(par, 1);
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			upa_writel(val, &fbc->font);
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data += stride;
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data = next_data;
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		width -= 32;
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (width) {
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FFBFifo(par, 2);
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		upa_writel(width, &fbc->fontw);
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		upa_writel(xy, &fbc->fontxy);
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < image->height; i++) {
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u32 val = (((u32)data[0] << 24) |
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   ((u32)data[1] << 16) |
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   ((u32)data[2] <<  8) |
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   ((u32)data[3] <<  0));
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			FFBFifo(par, 1);
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			upa_writel(val, &fbc->font);
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data += stride;
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&par->lock, flags);
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ffb_fixup_var_rgb(struct fb_var_screeninfo *var)
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->red.offset = 0;
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->red.length = 8;
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->green.offset = 8;
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->green.length = 8;
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->blue.offset = 16;
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->blue.length = 8;
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->transp.offset = 0;
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->transp.length = 0;
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
642f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	ffb_setcolreg - Sets a color register.
643f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *
644f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@regno: boolean, 0 copy local, 1 get_user() function
645f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@red: frame buffer colormap structure
646f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@green: The green value which can be up to 16 bits wide
647f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@blue:  The blue value which can be up to 16 bits wide.
648f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@transp: If supported the alpha value which can be up to 16 bits wide.
649f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@info: frame buffer info structure
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ffb_setcolreg(unsigned regno,
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 unsigned red, unsigned green, unsigned blue,
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 unsigned transp, struct fb_info *info)
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 value;
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
657d2fa9e05e3876198d8ab31624fe84512a0a44b45Antonino Daplas	if (regno >= 16)
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1;
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	red >>= 8;
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	green >>= 8;
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	blue >>= 8;
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	value = (blue << 16) | (green << 8) | red;
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	((u32 *)info->pseudo_palette)[regno] = value;
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
671f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	ffb_blank - Optional function.  Blanks the display.
672f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@blank_mode: the blank mode we want.
673f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@info: frame buffer structure that represents a single frame buffer
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
675f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Heltstatic int ffb_blank(int blank, struct fb_info *info)
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
677f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	struct ffb_par *par = (struct ffb_par *)info->par;
67850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_dac __iomem *dac = par->dac;
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
68037db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	u32 val;
68137db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	int i;
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&par->lock, flags);
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FFBWait(par);
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
68737db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	upa_writel(FFB_DAC_TGEN, &dac->type);
68837db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	val = upa_readl(&dac->value);
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (blank) {
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FB_BLANK_UNBLANK: /* Unblanking */
69137db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller		val |= FFB_DAC_TGEN_VIDE;
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		par->flags &= ~FFB_FLAG_BLANKED;
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FB_BLANK_NORMAL: /* Normal blanking */
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FB_BLANK_POWERDOWN: /* Poweroff */
69937db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller		val &= ~FFB_DAC_TGEN_VIDE;
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		par->flags |= FFB_FLAG_BLANKED;
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
70337db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	upa_writel(FFB_DAC_TGEN, &dac->type);
70437db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	upa_writel(val, &dac->value);
70537db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	for (i = 0; i < 10; i++) {
70637db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller		upa_writel(FFB_DAC_TGEN, &dac->type);
70737db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller		upa_readl(&dac->value);
70837db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	}
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&par->lock, flags);
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sbus_mmap_map ffb_mmap_map[] = {
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_SFB8R_VOFF,
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_SFB8R_POFF,
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0400000
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_SFB8G_VOFF,
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_SFB8G_POFF,
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0400000
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_SFB8B_VOFF,
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_SFB8B_POFF,
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0400000
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_SFB8X_VOFF,
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_SFB8X_POFF,
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0400000
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_SFB32_VOFF,
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_SFB32_POFF,
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000000
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_SFB64_VOFF,
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_SFB64_POFF,
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x2000000
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_FBC_REGS_VOFF,
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_FBC_REGS_POFF,
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0002000
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_BM_FBC_REGS_VOFF,
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_BM_FBC_REGS_POFF,
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0002000
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB8R_VOFF,
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB8R_POFF,
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0400000
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB8G_VOFF,
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB8G_POFF,
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0400000
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB8B_VOFF,
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB8B_POFF,
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0400000
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB8X_VOFF,
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB8X_POFF,
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0400000
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB24_VOFF,
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB24_POFF,
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000000
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB32_VOFF,
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB32_POFF,
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000000
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_FBC_KREGS_VOFF,
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_FBC_KREGS_POFF,
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0002000
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DAC_VOFF,
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DAC_POFF,
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0002000
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_PROM_VOFF,
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_PROM_POFF,
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0010000
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_EXP_VOFF,
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_EXP_POFF,
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0002000
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB422A_VOFF,
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB422A_POFF,
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0800000
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB422AD_VOFF,
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB422AD_POFF,
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0800000
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB24B_VOFF,
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB24B_POFF,
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000000
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB422B_VOFF,
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB422B_POFF,
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0800000
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB422BD_VOFF,
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB422BD_POFF,
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0800000
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_SFB16Z_VOFF,
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_SFB16Z_POFF,
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0800000
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_SFB8Z_VOFF,
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_SFB8Z_POFF,
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0800000
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_SFB422_VOFF,
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_SFB422_POFF,
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0800000
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_SFB422D_VOFF,
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_SFB422D_POFF,
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0800000
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ .size = 0 }
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
854216d526c89d144928f095f2800bc6c67e968d628Christoph Hellwigstatic int ffb_mmap(struct fb_info *info, struct vm_area_struct *vma)
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ffb_par *par = (struct ffb_par *)info->par;
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sbusfb_mmap_helper(ffb_mmap_map,
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  par->physbase, par->fbsize,
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  0, vma);
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
86367a6680d64e18c7a1901f31ef747ea53b6cd986dChristoph Hellwigstatic int ffb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
865f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	struct ffb_par *par = (struct ffb_par *)info->par;
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sbusfb_ioctl_helper(cmd, arg, info,
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   FBTYPE_CREATOR, 24, par->fbsize);
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Initialisation
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
875f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Heltstatic void ffb_init_fix(struct fb_info *info)
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ffb_par *par = (struct ffb_par *)info->par;
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *ffb_type_name;
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(par->flags & FFB_FLAG_AFB)) {
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((par->board_type & 0x7) == 0x3)
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ffb_type_name = "Creator 3D";
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ffb_type_name = "Creator";
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ffb_type_name = "Elite 3D";
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	strlcpy(info->fix.id, ffb_type_name, sizeof(info->fix.id));
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->fix.type = FB_TYPE_PACKED_PIXELS;
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->fix.visual = FB_VISUAL_TRUECOLOR;
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Framebuffer length is the same regardless of resolution. */
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->fix.line_length = 8192;
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->fix.accel = FB_ACCEL_SUN_CREATOR;
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
899f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Heltstatic int __devinit ffb_probe(struct of_device *op,
900f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt			       const struct of_device_id *match)
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
90250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct device_node *dp = op->node;
90350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_fbc __iomem *fbc;
90450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_dac __iomem *dac;
905c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	struct fb_info *info;
906c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	struct ffb_par *par;
90737db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	u32 dac_pnum, dac_rev, dac_mrev;
908c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	int err;
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
910c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info = framebuffer_alloc(sizeof(struct ffb_par), &op->dev);
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
912c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	err = -ENOMEM;
913c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (!info)
914c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		goto out_err;
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
916c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par = info->par;
917c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
918c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	spin_lock_init(&par->lock);
919c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->fbc = of_ioremap(&op->resource[2], 0,
920c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller			      sizeof(struct ffb_fbc), "ffb fbc");
921c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (!par->fbc)
922c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		goto out_release_fb;
923c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
924c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->dac = of_ioremap(&op->resource[1], 0,
925c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller			      sizeof(struct ffb_dac), "ffb dac");
926c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (!par->dac)
927c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		goto out_unmap_fbc;
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
929c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->rop_cache = FFB_ROP_NEW;
930c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->physbase = op->resource[0].start;
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Don't mention copyarea, so SCROLL_REDRAW is always
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * used.  It is the fastest on this chip.
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
935c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info->flags = (FBINFO_DEFAULT |
936c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		       /* FBINFO_HWACCEL_COPYAREA | */
937c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		       FBINFO_HWACCEL_FILLRECT |
938c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		       FBINFO_HWACCEL_IMAGEBLIT);
939c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
940c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info->fbops = &ffb_ops;
941c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
942c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info->screen_base = (char *) par->physbase + FFB_DFB24_POFF;
943c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info->pseudo_palette = par->pseudo_palette;
944c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
945c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	sbusfb_fill_var(&info->var, dp->node, 32);
946c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->fbsize = PAGE_ALIGN(info->var.xres * info->var.yres * 4);
947c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	ffb_fixup_var_rgb(&info->var);
948c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
949c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info->var.accel_flags = FB_ACCELF_TEXT;
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
95150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	if (!strcmp(dp->name, "SUNW,afb"))
952c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		par->flags |= FFB_FLAG_AFB;
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
954c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->board_type = of_getintprop_default(dp, "board_type", 0);
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
956c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	fbc = par->fbc;
95750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
960c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	dac = par->dac;
96137db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	upa_writel(FFB_DAC_DID, &dac->type);
96237db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	dac_pnum = upa_readl(&dac->value);
96337db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	dac_rev = (dac_pnum & FFB_DAC_DID_REV) >> FFB_DAC_DID_REV_SHIFT;
96437db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	dac_pnum = (dac_pnum & FFB_DAC_DID_PNUM) >> FFB_DAC_DID_PNUM_SHIFT;
96537db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller
96637db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	upa_writel(FFB_DAC_UCTRL, &dac->type);
96737db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	dac_mrev = upa_readl(&dac->value);
96837db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	dac_mrev = (dac_mrev & FFB_DAC_UCTRL_MANREV) >>
96937db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller		FFB_DAC_UCTRL_MANREV_SHIFT;
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Elite3D has different DAC revision numbering, and no DAC revisions
97237db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	 * have the reversed meaning of cursor enable.  Otherwise, Pacifica 1
97337db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	 * ramdacs with manufacturing revision less than 3 have inverted
97437db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	 * cursor logic.  We identify Pacifica 1 as not Pacifica 2, the
97537db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	 * latter having a part number value of 0x236e.
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
977c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if ((par->flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) {
978c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		par->flags &= ~FFB_FLAG_INVCURSOR;
97937db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	} else {
98037db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller		if (dac_mrev < 3)
981c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller			par->flags |= FFB_FLAG_INVCURSOR;
98237db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	}
98337db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller
984c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	ffb_switch_from_graph(par);
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Unblank it just to be sure.  When there are multiple
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * FFB/AFB cards in the system, or it is not the OBP
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * chosen console, it will have video outputs off in
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the DAC.
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
991c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	ffb_blank(0, info);
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
993c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (fb_alloc_cmap(&info->cmap, 256, 0))
994c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		goto out_unmap_dac;
995c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
996c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	ffb_init_fix(info);
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
998c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	err = register_framebuffer(info);
999c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (err < 0)
1000c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		goto out_dealloc_cmap;
1001c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
1002c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	dev_set_drvdata(&op->dev, info);
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
100437db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	printk("%s: %s at %016lx, type %d, "
100537db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	       "DAC pnum[%x] rev[%d] manuf_rev[%d]\n",
100650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	       dp->full_name,
1007c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	       ((par->flags & FFB_FLAG_AFB) ? "AFB" : "FFB"),
1008c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	       par->physbase, par->board_type,
100937db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	       dac_pnum, dac_rev, dac_mrev);
101050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
101150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	return 0;
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1013c7f439b99efbea74c70a5531f92566db5a6731f2David S. Millerout_dealloc_cmap:
1014c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	fb_dealloc_cmap(&info->cmap);
1015c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
1016c7f439b99efbea74c70a5531f92566db5a6731f2David S. Millerout_unmap_dac:
1017c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));
1018c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
1019c7f439b99efbea74c70a5531f92566db5a6731f2David S. Millerout_unmap_fbc:
1020c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));
1021c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
1022c7f439b99efbea74c70a5531f92566db5a6731f2David S. Millerout_release_fb:
1023c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	framebuffer_release(info);
102450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
1025c7f439b99efbea74c70a5531f92566db5a6731f2David S. Millerout_err:
1026c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	return err;
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1029e3a411a3dfc1d633504aa63efab32b7e00318454David S. Millerstatic int __devexit ffb_remove(struct of_device *op)
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1031c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	struct fb_info *info = dev_get_drvdata(&op->dev);
1032c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	struct ffb_par *par = info->par;
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1034c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	unregister_framebuffer(info);
1035c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	fb_dealloc_cmap(&info->cmap);
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1037c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));
1038c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	of_iounmap(&op->resource[1], par->dac, sizeof(struct ffb_dac));
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1040c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	framebuffer_release(info);
104150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
1042e3a411a3dfc1d633504aa63efab32b7e00318454David S. Miller	dev_set_drvdata(&op->dev, NULL);
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
104750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Millerstatic struct of_device_id ffb_match[] = {
104850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	{
104950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller		.name = "SUNW,ffb",
105050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	},
105150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	{
105250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller		.name = "SUNW,afb",
105350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	},
105450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	{},
105550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller};
105650312ce9dd794eef3df9e64194ba95ca730d82c8David S. MillerMODULE_DEVICE_TABLE(of, ffb_match);
105750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
105850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Millerstatic struct of_platform_driver ffb_driver = {
105950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	.name		= "ffb",
106050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	.match_table	= ffb_match,
106150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	.probe		= ffb_probe,
106250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	.remove		= __devexit_p(ffb_remove),
106350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller};
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
106550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Millerint __init ffb_init(void)
106650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller{
106750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	if (fb_get_options("ffb", NULL))
106850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller		return -ENODEV;
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
107050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	return of_register_driver(&ffb_driver, &of_bus_type);
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
107350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Millervoid __exit ffb_exit(void)
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
107550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	of_unregister_driver(&ffb_driver);
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(ffb_init);
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(ffb_exit);
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("framebuffer driver for Creator/Elite3D chipsets");
108250312ce9dd794eef3df9e64194ba95ca730d82c8David S. MillerMODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
108350312ce9dd794eef3df9e64194ba95ca730d82c8David S. MillerMODULE_VERSION("2.0");
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
1085