[go: nahoru, domu]

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/delay.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fb.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h>
186cd5a86b56ec8fc8651c043bdb05ea0c662fb704Robert Reif#include <linux/of_device.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/upa.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 ffb_setcolreg(unsigned, unsigned, unsigned, unsigned,
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 unsigned, struct fb_info *);
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ffb_blank(int, struct fb_info *);
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ffb_imageblit(struct fb_info *, const struct fb_image *);
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ffb_fillrect(struct fb_info *, const struct fb_fillrect *);
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ffb_copyarea(struct fb_info *, const struct fb_copyarea *);
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ffb_sync(struct fb_info *);
38216d526c89d144928f095f2800bc6c67e968d628Christoph Hellwigstatic int ffb_mmap(struct fb_info *, struct vm_area_struct *);
3967a6680d64e18c7a1901f31ef747ea53b6cd986dChristoph Hellwigstatic int ffb_ioctl(struct fb_info *, unsigned int, unsigned long);
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ffb_pan_display(struct fb_var_screeninfo *, struct fb_info *);
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Frame buffer operations
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct fb_ops ffb_ops = {
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner			= THIS_MODULE,
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_setcolreg		= ffb_setcolreg,
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_blank		= ffb_blank,
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_pan_display		= ffb_pan_display,
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_fillrect		= ffb_fillrect,
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_copyarea		= ffb_copyarea,
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_imageblit		= ffb_imageblit,
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_sync		= ffb_sync,
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_mmap		= ffb_mmap,
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fb_ioctl		= ffb_ioctl,
579ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig#ifdef CONFIG_COMPAT
589ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	.fb_compat_ioctl	= sbusfb_compat_ioctl,
599ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig#endif
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Register layout and definitions */
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB8R_VOFF		0x00000000
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB8G_VOFF		0x00400000
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB8B_VOFF		0x00800000
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB8X_VOFF		0x00c00000
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB32_VOFF		0x01000000
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB64_VOFF		0x02000000
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_FBC_REGS_VOFF	0x04000000
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_BM_FBC_REGS_VOFF	0x04002000
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB8R_VOFF		0x04004000
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB8G_VOFF		0x04404000
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB8B_VOFF		0x04804000
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB8X_VOFF		0x04c04000
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB24_VOFF		0x05004000
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB32_VOFF		0x06004000
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB422A_VOFF	0x07004000	/* DFB 422 mode write to A */
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB422AD_VOFF	0x07804000	/* DFB 422 mode with line doubling */
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB24B_VOFF		0x08004000	/* DFB 24bit mode write to B */
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB422B_VOFF	0x09004000	/* DFB 422 mode write to B */
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB422BD_VOFF	0x09804000	/* DFB 422 mode with line doubling */
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB16Z_VOFF		0x0a004000	/* 16bit mode Z planes */
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB8Z_VOFF		0x0a404000	/* 8bit mode Z planes */
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB422_VOFF		0x0ac04000	/* SFB 422 mode write to A/B */
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB422D_VOFF	0x0b404000	/* SFB 422 mode with line doubling */
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_FBC_KREGS_VOFF	0x0bc04000
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DAC_VOFF		0x0bc06000
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_PROM_VOFF		0x0bc08000
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_EXP_VOFF		0x0bc18000
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB8R_POFF		0x04000000UL
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB8G_POFF		0x04400000UL
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB8B_POFF		0x04800000UL
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB8X_POFF		0x04c00000UL
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB32_POFF		0x05000000UL
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_SFB64_POFF		0x06000000UL
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_FBC_REGS_POFF	0x00600000UL
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_BM_FBC_REGS_POFF	0x00600000UL
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB8R_POFF		0x01000000UL
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB8G_POFF		0x01400000UL
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB8B_POFF		0x01800000UL
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB8X_POFF		0x01c00000UL
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB24_POFF		0x02000000UL
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DFB32_POFF		0x03000000UL
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_FBC_KREGS_POFF	0x00610000UL
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_DAC_POFF		0x00400000UL
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_PROM_POFF		0x00000000UL
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FFB_EXP_POFF		0x00200000UL
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DFB422A_POFF	0x09000000UL
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DFB422AD_POFF	0x09800000UL
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DFB24B_POFF		0x0a000000UL
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DFB422B_POFF	0x0b000000UL
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DFB422BD_POFF	0x0b800000UL
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_SFB16Z_POFF		0x0c800000UL
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_SFB8Z_POFF		0x0c000000UL
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_SFB422_POFF		0x0d000000UL
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_SFB422D_POFF	0x0d800000UL
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Draw operations */
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_DOT		0x00
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_AADOT	0x01
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_BRLINECAP	0x02
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_BRLINEOPEN	0x03
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_DDLINE	0x04
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_AALINE	0x05
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_TRIANGLE	0x06
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_POLYGON	0x07
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_RECTANGLE	0x08
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_FASTFILL	0x09
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_BCOPY	0x0a
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_DRAWOP_VSCROLL	0x0b
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Pixel processor control */
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Force WID */
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_FW_DISABLE	0x800000
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_FW_ENABLE	0xc00000
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Auxiliary clip */
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_ACE_DISABLE	0x040000
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_ACE_AUX_SUB	0x080000
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_ACE_AUX_ADD	0x0c0000
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Depth cue */
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_DCE_DISABLE	0x020000
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_DCE_ENABLE	0x030000
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Alpha blend */
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_ABE_DISABLE	0x008000
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_ABE_ENABLE	0x00c000
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* View clip */
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_VCE_DISABLE	0x001000
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_VCE_2D		0x002000
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_VCE_3D		0x003000
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Area pattern */
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_APE_DISABLE	0x000800
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_APE_ENABLE	0x000c00
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Transparent background */
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_TBE_OPAQUE	0x000200
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_TBE_TRANSPARENT	0x000300
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Z source */
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_ZS_VAR		0x000080
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_ZS_CONST	0x0000c0
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Y source */
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_YS_VAR		0x000020
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_YS_CONST	0x000030
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* X source */
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_XS_WID		0x000004
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_XS_VAR		0x000008
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_XS_CONST	0x00000c
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Color (BGR) source */
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_CS_VAR		0x000002
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FFB_PPC_CS_CONST	0x000003
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
171f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_ROP_NEW		0x83
172f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_ROP_OLD		0x85
173f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_ROP_NEW_XOR_OLD	0x86
174f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
175f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_UCSR_FIFO_MASK	0x00000fff
176f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_UCSR_FB_BUSY	0x01000000
177f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_UCSR_RP_BUSY	0x02000000
178f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_UCSR_ALL_BUSY	(FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY)
179f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_UCSR_READ_ERR	0x40000000
180f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_UCSR_FIFO_OVFL	0x80000000
181f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_UCSR_ALL_ERRORS	(FFB_UCSR_READ_ERR|FFB_UCSR_FIFO_OVFL)
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct ffb_fbc {
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Next vertex registers */
18550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx1[3];
18650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	alpha;
18750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	red;
18850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	green;
18950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	blue;
19050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	depth;
19150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	y;
19250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	x;
19350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx2[2];
19450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	ryf;
19550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rxf;
19650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx3[2];
197f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
19850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dmyf;
19950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dmxf;
20050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx4[2];
20150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	ebyi;
20250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	ebxi;
20350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx5[2];
20450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	by;
20550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	bx;
20650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dy;
20750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dx;
20850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	bh;
20950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	bw;
21050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx6[2];
211f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
21250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx7[32];
213f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Setup unit vertex state register */
21550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	suvtx;
21650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx8[63];
217f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Control registers */
21950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	ppc;
22050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	wid;
22150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fg;
22250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	bg;
22350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	consty;
22450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	constz;
22550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xclip;
22650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcss;
22750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	vclipmin;
22850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	vclipmax;
22950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	vclipzmin;
23050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	vclipzmax;
23150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcsf;
23250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcsb;
23350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dczf;
23450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dczb;
235f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
23650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx9;
23750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	blendc;
23850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	blendc1;
23950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	blendc2;
24050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fbramitc;
24150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fbc;
24250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rop;
24350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	cmp;
24450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	matchab;
24550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	matchc;
24650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	magnab;
24750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	magnc;
24850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fbcfg0;
24950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fbcfg1;
25050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fbcfg2;
25150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fbcfg3;
252f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
25350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	ppcfg;
25450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	pick;
25550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fillmode;
25650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fbramwac;
25750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	pmask;
25850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xpmask;
25950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	ypmask;
26050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	zpmask;
26150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	clip0min;
26250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	clip0max;
26350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	clip1min;
26450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	clip1max;
26550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	clip2min;
26650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	clip2max;
26750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	clip3min;
26850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	clip3max;
269f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* New 3dRAM III support regs */
27150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawblend2;
27250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawpreblend;
27350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawstencil;
27450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawstencilctl;
27550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	threedram1;
27650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	threedram2;
27750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	passin;
27850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawclrdepth;
27950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawpmask;
28050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawcsrc;
28150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawmatch;
28250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawmagn;
28350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawropblend;
28450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawcmp;
28550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	rawwac;
28650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fbramid;
287f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
28850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	drawop;
28950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx10[2];
29050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fontlpat;
29150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx11;
29250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fontxy;
29350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fontw;
29450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	fontinc;
29550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	font;
29650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx12[3];
29750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	blend2;
29850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	preblend;
29950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	stencil;
30050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	stencilctl;
30150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
302f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	u32	xxx13[4];
30350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcss1;
30450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcss2;
30550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcss3;
30650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	widpmask;
30750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcs2;
30850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcs3;
30950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcs4;
31050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx14;
31150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcd2;
31250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcd3;
31350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	dcd4;
31450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx15;
315f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
31650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	pattern[32];
317f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
31850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx16[256];
319f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
32050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	devid;
32150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx17[63];
322f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
32350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	ucsr;
32450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	xxx18[31];
325f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt
32650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	mer;
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct ffb_dac {
33050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	type;
33150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	value;
33250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	type2;
33350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	u32	value2;
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
336f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_UCTRL		0x1001 /* User Control */
337f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_UCTRL_MANREV	0x00000f00 /* 4-bit Manufacturing Revision */
338f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_UCTRL_MANREV_SHIFT 8
339f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_TGEN		0x6000 /* Timing Generator */
340f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_TGEN_VIDE	0x00000001 /* Video Enable */
341f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_DID		0x8000 /* Device Identification */
342f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_DID_PNUM	0x0ffff000 /* Device Part Number */
343f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_DID_PNUM_SHIFT	12
344f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_DID_REV		0xf0000000 /* Device Revision */
345f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_DID_REV_SHIFT	28
34637db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller
34737db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller#define FFB_DAC_CUR_CTRL	0x100
348f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_CUR_CTRL_P0	0x00000001
349f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt#define FFB_DAC_CUR_CTRL_P1	0x00000002
35037db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct ffb_par {
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spinlock_t		lock;
35350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_fbc __iomem	*fbc;
35450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_dac __iomem	*dac;
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32			flags;
35737db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller#define FFB_FLAG_AFB		0x00000001 /* AFB m3 or m6 */
35837db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller#define FFB_FLAG_BLANKED	0x00000002 /* screen is blanked */
35937db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller#define FFB_FLAG_INVCURSOR	0x00000004 /* DAC has inverted cursor logic */
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32			fg_cache __attribute__((aligned (8)));
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32			bg_cache;
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32			rop_cache;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			fifo_cache;
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		physbase;
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		fbsize;
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			board_type;
371c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
372c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	u32			pseudo_palette[16];
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void FFBFifo(struct ffb_par *par, int n)
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
37750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_fbc __iomem *fbc;
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int cache = par->fifo_cache;
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cache - n < 0) {
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fbc = par->fbc;
382f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt		do {
383f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt			cache = (upa_readl(&fbc->ucsr) & FFB_UCSR_FIFO_MASK);
384f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt			cache -= 8;
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} while (cache - n < 0);
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	par->fifo_cache = cache - n;
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void FFBWait(struct ffb_par *par)
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
39250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_fbc __iomem *fbc;
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int limit = 10000;
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fbc = par->fbc;
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_BUSY) == 0)
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) {
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(10);
403f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	} while (--limit > 0);
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ffb_sync(struct fb_info *p)
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
408f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	struct ffb_par *par = (struct ffb_par *)p->par;
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FFBWait(par);
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic __inline__ void ffb_rop(struct ffb_par *par, u32 rop)
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (par->rop_cache != rop) {
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FFBFifo(par, 1);
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		upa_writel(rop, &par->fbc->rop);
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		par->rop_cache = rop;
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ffb_switch_from_graph(struct ffb_par *par)
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
42550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_fbc __iomem *fbc = par->fbc;
42650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_dac __iomem *dac = par->dac;
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&par->lock, flags);
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FFBWait(par);
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	par->fifo_cache = 0;
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FFBFifo(par, 7);
433f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	upa_writel(FFB_PPC_VCE_DISABLE | FFB_PPC_TBE_OPAQUE |
434f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt		   FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   &fbc->ppc);
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(0x2000707f, &fbc->fbc);
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(par->rop_cache, &fbc->rop);
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(0xffffffff, &fbc->pmask);
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel((1 << 16) | (0 << 0), &fbc->fontinc);
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(par->fg_cache, &fbc->fg);
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(par->bg_cache, &fbc->bg);
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FFBWait(par);
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Disable cursor.  */
44537db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	upa_writel(FFB_DAC_CUR_CTRL, &dac->type2);
44637db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	if (par->flags & FFB_FLAG_INVCURSOR)
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		upa_writel(0, &dac->value2);
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
44937db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller		upa_writel((FFB_DAC_CUR_CTRL_P0 |
45037db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller			    FFB_DAC_CUR_CTRL_P1), &dac->value2);
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&par->lock, flags);
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ffb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
457f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	struct ffb_par *par = (struct ffb_par *)info->par;
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We just use this to catch switches out of
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * graphics mode.
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ffb_switch_from_graph(par);
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (var->xoffset || var->yoffset || var->vmode)
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
470f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	ffb_fillrect - Draws a rectangle on the screen.
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
472f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@info: frame buffer structure that represents a single frame buffer
473f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@rect: structure defining the rectagle and operation.
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ffb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
477f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	struct ffb_par *par = (struct ffb_par *)info->par;
47850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_fbc __iomem *fbc = par->fbc;
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 fg;
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
482232443e2c90cc2930624dec89df327615b002c55Eric Sesterhenn	BUG_ON(rect->rop != ROP_COPY && rect->rop != ROP_XOR);
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fg = ((u32 *)info->pseudo_palette)[rect->color];
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&par->lock, flags);
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fg != par->fg_cache) {
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FFBFifo(par, 1);
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		upa_writel(fg, &fbc->fg);
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		par->fg_cache = fg;
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
494f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	ffb_rop(par, rect->rop == ROP_COPY ?
495f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt		     FFB_ROP_NEW :
496f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt		     FFB_ROP_NEW_XOR_OLD);
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FFBFifo(par, 5);
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(FFB_DRAWOP_RECTANGLE, &fbc->drawop);
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(rect->dy, &fbc->by);
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(rect->dx, &fbc->bx);
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(rect->height, &fbc->bh);
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(rect->width, &fbc->bw);
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&par->lock, flags);
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
509f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	ffb_copyarea - Copies on area of the screen to another area.
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
511f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@info: frame buffer structure that represents a single frame buffer
512f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@area: structure defining the source and destination.
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
515f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Heltstatic void ffb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
517f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	struct ffb_par *par = (struct ffb_par *)info->par;
51850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_fbc __iomem *fbc = par->fbc;
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (area->dx != area->sx ||
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    area->dy == area->sy) {
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cfb_copyarea(info, area);
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&par->lock, flags);
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ffb_rop(par, FFB_ROP_OLD);
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FFBFifo(par, 7);
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(FFB_DRAWOP_VSCROLL, &fbc->drawop);
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(area->sy, &fbc->by);
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(area->sx, &fbc->bx);
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(area->dy, &fbc->dy);
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(area->dx, &fbc->dx);
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(area->height, &fbc->bh);
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	upa_writel(area->width, &fbc->bw);
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&par->lock, flags);
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
544f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	ffb_imageblit - Copies a image from system memory to the screen.
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
546f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@info: frame buffer structure that represents a single frame buffer
547f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@image: structure defining the image.
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ffb_imageblit(struct fb_info *info, const struct fb_image *image)
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
551f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	struct ffb_par *par = (struct ffb_par *)info->par;
55250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_fbc __iomem *fbc = par->fbc;
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u8 *data = image->data;
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 fg, bg, xy;
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u64 fgbg;
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, width, stride;
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (image->depth > 1) {
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cfb_imageblit(info, image);
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fg = ((u32 *)info->pseudo_palette)[image->fg_color];
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bg = ((u32 *)info->pseudo_palette)[image->bg_color];
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fgbg = ((u64) fg << 32) | (u64) bg;
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	xy = (image->dy << 16) | image->dx;
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	width = image->width;
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stride = ((width + 7) >> 3);
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&par->lock, flags);
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fgbg != *(u64 *)&par->fg_cache) {
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FFBFifo(par, 2);
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		upa_writeq(fgbg, &fbc->fg);
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*(u64 *)&par->fg_cache = fgbg;
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (width >= 32) {
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FFBFifo(par, 1);
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		upa_writel(32, &fbc->fontw);
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (width >= 32) {
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		const u8 *next_data = data + 4;
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FFBFifo(par, 1);
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		upa_writel(xy, &fbc->fontxy);
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		xy += (32 << 0);
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < image->height; i++) {
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u32 val = (((u32)data[0] << 24) |
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   ((u32)data[1] << 16) |
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   ((u32)data[2] <<  8) |
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   ((u32)data[3] <<  0));
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			FFBFifo(par, 1);
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			upa_writel(val, &fbc->font);
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data += stride;
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data = next_data;
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		width -= 32;
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (width) {
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FFBFifo(par, 2);
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		upa_writel(width, &fbc->fontw);
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		upa_writel(xy, &fbc->fontxy);
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < image->height; i++) {
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u32 val = (((u32)data[0] << 24) |
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   ((u32)data[1] << 16) |
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   ((u32)data[2] <<  8) |
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   ((u32)data[3] <<  0));
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			FFBFifo(par, 1);
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			upa_writel(val, &fbc->font);
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data += stride;
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&par->lock, flags);
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ffb_fixup_var_rgb(struct fb_var_screeninfo *var)
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->red.offset = 0;
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->red.length = 8;
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->green.offset = 8;
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->green.length = 8;
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->blue.offset = 16;
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->blue.length = 8;
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->transp.offset = 0;
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->transp.length = 0;
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
639f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	ffb_setcolreg - Sets a color register.
640f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *
641f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@regno: boolean, 0 copy local, 1 get_user() function
642f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@red: frame buffer colormap structure
643f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@green: The green value which can be up to 16 bits wide
644f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@blue:  The blue value which can be up to 16 bits wide.
645f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@transp: If supported the alpha value which can be up to 16 bits wide.
646f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@info: frame buffer info structure
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ffb_setcolreg(unsigned regno,
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 unsigned red, unsigned green, unsigned blue,
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 unsigned transp, struct fb_info *info)
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 value;
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
654d2fa9e05e3876198d8ab31624fe84512a0a44b45Antonino Daplas	if (regno >= 16)
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1;
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	red >>= 8;
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	green >>= 8;
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	blue >>= 8;
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	value = (blue << 16) | (green << 8) | red;
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	((u32 *)info->pseudo_palette)[regno] = value;
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
668f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	ffb_blank - Optional function.  Blanks the display.
669f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@blank_mode: the blank mode we want.
670f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt *	@info: frame buffer structure that represents a single frame buffer
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
672f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Heltstatic int ffb_blank(int blank, struct fb_info *info)
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
674f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	struct ffb_par *par = (struct ffb_par *)info->par;
67550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_dac __iomem *dac = par->dac;
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
67737db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	u32 val;
67837db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	int i;
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&par->lock, flags);
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FFBWait(par);
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
68437db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	upa_writel(FFB_DAC_TGEN, &dac->type);
68537db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	val = upa_readl(&dac->value);
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (blank) {
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FB_BLANK_UNBLANK: /* Unblanking */
68837db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller		val |= FFB_DAC_TGEN_VIDE;
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		par->flags &= ~FFB_FLAG_BLANKED;
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FB_BLANK_NORMAL: /* Normal blanking */
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FB_BLANK_POWERDOWN: /* Poweroff */
69637db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller		val &= ~FFB_DAC_TGEN_VIDE;
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		par->flags |= FFB_FLAG_BLANKED;
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
70037db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	upa_writel(FFB_DAC_TGEN, &dac->type);
70137db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	upa_writel(val, &dac->value);
70237db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	for (i = 0; i < 10; i++) {
70337db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller		upa_writel(FFB_DAC_TGEN, &dac->type);
70437db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller		upa_readl(&dac->value);
70537db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	}
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&par->lock, flags);
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sbus_mmap_map ffb_mmap_map[] = {
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_SFB8R_VOFF,
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_SFB8R_POFF,
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0400000
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_SFB8G_VOFF,
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_SFB8G_POFF,
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0400000
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_SFB8B_VOFF,
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_SFB8B_POFF,
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0400000
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_SFB8X_VOFF,
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_SFB8X_POFF,
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0400000
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_SFB32_VOFF,
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_SFB32_POFF,
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000000
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_SFB64_VOFF,
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_SFB64_POFF,
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x2000000
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_FBC_REGS_VOFF,
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_FBC_REGS_POFF,
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0002000
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_BM_FBC_REGS_VOFF,
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_BM_FBC_REGS_POFF,
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0002000
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB8R_VOFF,
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB8R_POFF,
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0400000
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB8G_VOFF,
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB8G_POFF,
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0400000
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB8B_VOFF,
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB8B_POFF,
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0400000
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB8X_VOFF,
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB8X_POFF,
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0400000
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB24_VOFF,
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB24_POFF,
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000000
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB32_VOFF,
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB32_POFF,
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000000
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_FBC_KREGS_VOFF,
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_FBC_KREGS_POFF,
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0002000
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DAC_VOFF,
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DAC_POFF,
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0002000
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_PROM_VOFF,
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_PROM_POFF,
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0010000
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_EXP_VOFF,
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_EXP_POFF,
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0002000
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB422A_VOFF,
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB422A_POFF,
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0800000
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB422AD_VOFF,
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB422AD_POFF,
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0800000
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB24B_VOFF,
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB24B_POFF,
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x1000000
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB422B_VOFF,
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB422B_POFF,
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0800000
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_DFB422BD_VOFF,
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_DFB422BD_POFF,
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0800000
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_SFB16Z_VOFF,
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_SFB16Z_POFF,
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0800000
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_SFB8Z_VOFF,
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_SFB8Z_POFF,
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0800000
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_SFB422_VOFF,
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_SFB422_POFF,
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0800000
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.voff	= FFB_SFB422D_VOFF,
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.poff	= FFB_SFB422D_POFF,
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.size	= 0x0800000
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ .size = 0 }
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
851216d526c89d144928f095f2800bc6c67e968d628Christoph Hellwigstatic int ffb_mmap(struct fb_info *info, struct vm_area_struct *vma)
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ffb_par *par = (struct ffb_par *)info->par;
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sbusfb_mmap_helper(ffb_mmap_map,
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  par->physbase, par->fbsize,
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  0, vma);
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
86067a6680d64e18c7a1901f31ef747ea53b6cd986dChristoph Hellwigstatic int ffb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
862f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Helt	struct ffb_par *par = (struct ffb_par *)info->par;
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sbusfb_ioctl_helper(cmd, arg, info,
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   FBTYPE_CREATOR, 24, par->fbsize);
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Initialisation
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
872f9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bbKrzysztof Heltstatic void ffb_init_fix(struct fb_info *info)
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ffb_par *par = (struct ffb_par *)info->par;
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *ffb_type_name;
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(par->flags & FFB_FLAG_AFB)) {
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((par->board_type & 0x7) == 0x3)
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ffb_type_name = "Creator 3D";
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ffb_type_name = "Creator";
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ffb_type_name = "Elite 3D";
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	strlcpy(info->fix.id, ffb_type_name, sizeof(info->fix.id));
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->fix.type = FB_TYPE_PACKED_PIXELS;
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->fix.visual = FB_VISUAL_TRUECOLOR;
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Framebuffer length is the same regardless of resolution. */
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->fix.line_length = 8192;
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->fix.accel = FB_ACCEL_SUN_CREATOR;
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
89648c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic int ffb_probe(struct platform_device *op)
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
89861c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	struct device_node *dp = op->dev.of_node;
89950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_fbc __iomem *fbc;
90050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	struct ffb_dac __iomem *dac;
901c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	struct fb_info *info;
902c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	struct ffb_par *par;
90337db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	u32 dac_pnum, dac_rev, dac_mrev;
904c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	int err;
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
906c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info = framebuffer_alloc(sizeof(struct ffb_par), &op->dev);
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
908c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	err = -ENOMEM;
909c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (!info)
910c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		goto out_err;
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
912c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par = info->par;
913c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
914c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	spin_lock_init(&par->lock);
915c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->fbc = of_ioremap(&op->resource[2], 0,
916c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller			      sizeof(struct ffb_fbc), "ffb fbc");
917c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (!par->fbc)
918c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		goto out_release_fb;
919c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
920c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->dac = of_ioremap(&op->resource[1], 0,
921c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller			      sizeof(struct ffb_dac), "ffb dac");
922c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (!par->dac)
923c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		goto out_unmap_fbc;
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
925c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->rop_cache = FFB_ROP_NEW;
926c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->physbase = op->resource[0].start;
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Don't mention copyarea, so SCROLL_REDRAW is always
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * used.  It is the fastest on this chip.
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
931c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info->flags = (FBINFO_DEFAULT |
932c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		       /* FBINFO_HWACCEL_COPYAREA | */
933c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		       FBINFO_HWACCEL_FILLRECT |
934c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		       FBINFO_HWACCEL_IMAGEBLIT);
935c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
936c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info->fbops = &ffb_ops;
937c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
938c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info->screen_base = (char *) par->physbase + FFB_DFB24_POFF;
939c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info->pseudo_palette = par->pseudo_palette;
940c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
9416cd5a86b56ec8fc8651c043bdb05ea0c662fb704Robert Reif	sbusfb_fill_var(&info->var, dp, 32);
942c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->fbsize = PAGE_ALIGN(info->var.xres * info->var.yres * 4);
943c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	ffb_fixup_var_rgb(&info->var);
944c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
945c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	info->var.accel_flags = FB_ACCELF_TEXT;
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
94750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	if (!strcmp(dp->name, "SUNW,afb"))
948c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		par->flags |= FFB_FLAG_AFB;
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
950c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	par->board_type = of_getintprop_default(dp, "board_type", 0);
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
952c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	fbc = par->fbc;
95350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
956c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	dac = par->dac;
95737db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	upa_writel(FFB_DAC_DID, &dac->type);
95837db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	dac_pnum = upa_readl(&dac->value);
95937db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	dac_rev = (dac_pnum & FFB_DAC_DID_REV) >> FFB_DAC_DID_REV_SHIFT;
96037db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	dac_pnum = (dac_pnum & FFB_DAC_DID_PNUM) >> FFB_DAC_DID_PNUM_SHIFT;
96137db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller
96237db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	upa_writel(FFB_DAC_UCTRL, &dac->type);
96337db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	dac_mrev = upa_readl(&dac->value);
96437db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	dac_mrev = (dac_mrev & FFB_DAC_UCTRL_MANREV) >>
96537db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller		FFB_DAC_UCTRL_MANREV_SHIFT;
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Elite3D has different DAC revision numbering, and no DAC revisions
96837db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	 * have the reversed meaning of cursor enable.  Otherwise, Pacifica 1
96937db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	 * ramdacs with manufacturing revision less than 3 have inverted
97037db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	 * cursor logic.  We identify Pacifica 1 as not Pacifica 2, the
97137db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	 * latter having a part number value of 0x236e.
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
973c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if ((par->flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) {
974c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		par->flags &= ~FFB_FLAG_INVCURSOR;
97537db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	} else {
97637db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller		if (dac_mrev < 3)
977c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller			par->flags |= FFB_FLAG_INVCURSOR;
97837db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	}
97937db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller
980c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	ffb_switch_from_graph(par);
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Unblank it just to be sure.  When there are multiple
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * FFB/AFB cards in the system, or it is not the OBP
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * chosen console, it will have video outputs off in
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the DAC.
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
98759f7137a1369c25308672def38f3b126d0c7575aRobert Reif	ffb_blank(FB_BLANK_UNBLANK, info);
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
989c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (fb_alloc_cmap(&info->cmap, 256, 0))
990c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		goto out_unmap_dac;
991c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
992c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	ffb_init_fix(info);
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
994c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	err = register_framebuffer(info);
995c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	if (err < 0)
996c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller		goto out_dealloc_cmap;
997c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
998c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	dev_set_drvdata(&op->dev, info);
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1000194f1a68b93e959ede6ec363db4714e630bdbb6aRobert Reif	printk(KERN_INFO "%s: %s at %016lx, type %d, "
100137db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	       "DAC pnum[%x] rev[%d] manuf_rev[%d]\n",
100250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	       dp->full_name,
1003c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	       ((par->flags & FFB_FLAG_AFB) ? "AFB" : "FFB"),
1004c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	       par->physbase, par->board_type,
100537db9a348ad4250bd6009cec1bb108a653d1d220David S. Miller	       dac_pnum, dac_rev, dac_mrev);
100650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
100750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	return 0;
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1009c7f439b99efbea74c70a5531f92566db5a6731f2David S. Millerout_dealloc_cmap:
1010c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	fb_dealloc_cmap(&info->cmap);
1011c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
1012c7f439b99efbea74c70a5531f92566db5a6731f2David S. Millerout_unmap_dac:
10137b0e278519eba8050f2b37d7c408958745f30ecdAxel Lin	of_iounmap(&op->resource[1], par->dac, sizeof(struct ffb_dac));
1014c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
1015c7f439b99efbea74c70a5531f92566db5a6731f2David S. Millerout_unmap_fbc:
1016c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));
1017c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller
1018c7f439b99efbea74c70a5531f92566db5a6731f2David S. Millerout_release_fb:
1019c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	framebuffer_release(info);
102050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
1021c7f439b99efbea74c70a5531f92566db5a6731f2David S. Millerout_err:
1022c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	return err;
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
102548c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic int ffb_remove(struct platform_device *op)
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1027c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	struct fb_info *info = dev_get_drvdata(&op->dev);
1028c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	struct ffb_par *par = info->par;
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1030c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	unregister_framebuffer(info);
1031c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	fb_dealloc_cmap(&info->cmap);
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1033c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));
1034c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	of_iounmap(&op->resource[1], par->dac, sizeof(struct ffb_dac));
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1036c7f439b99efbea74c70a5531f92566db5a6731f2David S. Miller	framebuffer_release(info);
103750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1041fd098316ef533e8441576f020ead4beab93154ceDavid S. Millerstatic const struct of_device_id ffb_match[] = {
104250312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	{
104350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller		.name = "SUNW,ffb",
104450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	},
104550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	{
104650312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller		.name = "SUNW,afb",
104750312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	},
104850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	{},
104950312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller};
105050312ce9dd794eef3df9e64194ba95ca730d82c8David S. MillerMODULE_DEVICE_TABLE(of, ffb_match);
105150312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller
105228541d0f1894cd0c8f4a90c6e006c88d38ad3ac0Grant Likelystatic struct platform_driver ffb_driver = {
10534018294b53d1dae026880e45f174c1cc63b5d435Grant Likely	.driver = {
10544018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.name = "ffb",
10554018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.owner = THIS_MODULE,
10564018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.of_match_table = ffb_match,
10574018294b53d1dae026880e45f174c1cc63b5d435Grant Likely	},
105850312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	.probe		= ffb_probe,
105948c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartman	.remove		= ffb_remove,
106050312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller};
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1062a2fb0ce7aeae9c38146df9c2d9b763e5981a0683Robert Reifstatic int __init ffb_init(void)
106350312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller{
106450312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller	if (fb_get_options("ffb", NULL))
106550312ce9dd794eef3df9e64194ba95ca730d82c8David S. Miller		return -ENODEV;
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
106728541d0f1894cd0c8f4a90c6e006c88d38ad3ac0Grant Likely	return platform_driver_register(&ffb_driver);
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1070a2fb0ce7aeae9c38146df9c2d9b763e5981a0683Robert Reifstatic void __exit ffb_exit(void)
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
107228541d0f1894cd0c8f4a90c6e006c88d38ad3ac0Grant Likely	platform_driver_unregister(&ffb_driver);
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(ffb_init);
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(ffb_exit);
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("framebuffer driver for Creator/Elite3D chipsets");
107950312ce9dd794eef3df9e64194ba95ca730d82c8David S. MillerMODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
108050312ce9dd794eef3df9e64194ba95ca730d82c8David S. MillerMODULE_VERSION("2.0");
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
1082