cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ffb.c (24672B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/* ffb.c: Creator/Elite3D frame buffer driver
      3 *
      4 * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
      5 * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
      6 *
      7 * Driver layout based loosely on tgafb.c, see that file for credits.
      8 */
      9
     10#include <linux/module.h>
     11#include <linux/kernel.h>
     12#include <linux/errno.h>
     13#include <linux/string.h>
     14#include <linux/delay.h>
     15#include <linux/init.h>
     16#include <linux/fb.h>
     17#include <linux/mm.h>
     18#include <linux/timer.h>
     19#include <linux/of_device.h>
     20
     21#include <asm/io.h>
     22#include <asm/upa.h>
     23#include <asm/fbio.h>
     24
     25#include "sbuslib.h"
     26
     27/*
     28 * Local functions.
     29 */
     30
     31static int ffb_setcolreg(unsigned, unsigned, unsigned, unsigned,
     32			 unsigned, struct fb_info *);
     33static int ffb_blank(int, struct fb_info *);
     34
     35static void ffb_imageblit(struct fb_info *, const struct fb_image *);
     36static void ffb_fillrect(struct fb_info *, const struct fb_fillrect *);
     37static void ffb_copyarea(struct fb_info *, const struct fb_copyarea *);
     38static int ffb_sync(struct fb_info *);
     39static int ffb_mmap(struct fb_info *, struct vm_area_struct *);
     40static int ffb_ioctl(struct fb_info *, unsigned int, unsigned long);
     41static int ffb_pan_display(struct fb_var_screeninfo *, struct fb_info *);
     42
     43/*
     44 *  Frame buffer operations
     45 */
     46
     47static const struct fb_ops ffb_ops = {
     48	.owner			= THIS_MODULE,
     49	.fb_setcolreg		= ffb_setcolreg,
     50	.fb_blank		= ffb_blank,
     51	.fb_pan_display		= ffb_pan_display,
     52	.fb_fillrect		= ffb_fillrect,
     53	.fb_copyarea		= ffb_copyarea,
     54	.fb_imageblit		= ffb_imageblit,
     55	.fb_sync		= ffb_sync,
     56	.fb_mmap		= ffb_mmap,
     57	.fb_ioctl		= ffb_ioctl,
     58#ifdef CONFIG_COMPAT
     59	.fb_compat_ioctl	= sbusfb_compat_ioctl,
     60#endif
     61};
     62
     63/* Register layout and definitions */
     64#define	FFB_SFB8R_VOFF		0x00000000
     65#define	FFB_SFB8G_VOFF		0x00400000
     66#define	FFB_SFB8B_VOFF		0x00800000
     67#define	FFB_SFB8X_VOFF		0x00c00000
     68#define	FFB_SFB32_VOFF		0x01000000
     69#define	FFB_SFB64_VOFF		0x02000000
     70#define	FFB_FBC_REGS_VOFF	0x04000000
     71#define	FFB_BM_FBC_REGS_VOFF	0x04002000
     72#define	FFB_DFB8R_VOFF		0x04004000
     73#define	FFB_DFB8G_VOFF		0x04404000
     74#define	FFB_DFB8B_VOFF		0x04804000
     75#define	FFB_DFB8X_VOFF		0x04c04000
     76#define	FFB_DFB24_VOFF		0x05004000
     77#define	FFB_DFB32_VOFF		0x06004000
     78#define	FFB_DFB422A_VOFF	0x07004000	/* DFB 422 mode write to A */
     79#define	FFB_DFB422AD_VOFF	0x07804000	/* DFB 422 mode with line doubling */
     80#define	FFB_DFB24B_VOFF		0x08004000	/* DFB 24bit mode write to B */
     81#define	FFB_DFB422B_VOFF	0x09004000	/* DFB 422 mode write to B */
     82#define	FFB_DFB422BD_VOFF	0x09804000	/* DFB 422 mode with line doubling */
     83#define	FFB_SFB16Z_VOFF		0x0a004000	/* 16bit mode Z planes */
     84#define	FFB_SFB8Z_VOFF		0x0a404000	/* 8bit mode Z planes */
     85#define	FFB_SFB422_VOFF		0x0ac04000	/* SFB 422 mode write to A/B */
     86#define	FFB_SFB422D_VOFF	0x0b404000	/* SFB 422 mode with line doubling */
     87#define	FFB_FBC_KREGS_VOFF	0x0bc04000
     88#define	FFB_DAC_VOFF		0x0bc06000
     89#define	FFB_PROM_VOFF		0x0bc08000
     90#define	FFB_EXP_VOFF		0x0bc18000
     91
     92#define	FFB_SFB8R_POFF		0x04000000UL
     93#define	FFB_SFB8G_POFF		0x04400000UL
     94#define	FFB_SFB8B_POFF		0x04800000UL
     95#define	FFB_SFB8X_POFF		0x04c00000UL
     96#define	FFB_SFB32_POFF		0x05000000UL
     97#define	FFB_SFB64_POFF		0x06000000UL
     98#define	FFB_FBC_REGS_POFF	0x00600000UL
     99#define	FFB_BM_FBC_REGS_POFF	0x00600000UL
    100#define	FFB_DFB8R_POFF		0x01000000UL
    101#define	FFB_DFB8G_POFF		0x01400000UL
    102#define	FFB_DFB8B_POFF		0x01800000UL
    103#define	FFB_DFB8X_POFF		0x01c00000UL
    104#define	FFB_DFB24_POFF		0x02000000UL
    105#define	FFB_DFB32_POFF		0x03000000UL
    106#define	FFB_FBC_KREGS_POFF	0x00610000UL
    107#define	FFB_DAC_POFF		0x00400000UL
    108#define	FFB_PROM_POFF		0x00000000UL
    109#define	FFB_EXP_POFF		0x00200000UL
    110#define FFB_DFB422A_POFF	0x09000000UL
    111#define FFB_DFB422AD_POFF	0x09800000UL
    112#define FFB_DFB24B_POFF		0x0a000000UL
    113#define FFB_DFB422B_POFF	0x0b000000UL
    114#define FFB_DFB422BD_POFF	0x0b800000UL
    115#define FFB_SFB16Z_POFF		0x0c800000UL
    116#define FFB_SFB8Z_POFF		0x0c000000UL
    117#define FFB_SFB422_POFF		0x0d000000UL
    118#define FFB_SFB422D_POFF	0x0d800000UL
    119
    120/* Draw operations */
    121#define FFB_DRAWOP_DOT		0x00
    122#define FFB_DRAWOP_AADOT	0x01
    123#define FFB_DRAWOP_BRLINECAP	0x02
    124#define FFB_DRAWOP_BRLINEOPEN	0x03
    125#define FFB_DRAWOP_DDLINE	0x04
    126#define FFB_DRAWOP_AALINE	0x05
    127#define FFB_DRAWOP_TRIANGLE	0x06
    128#define FFB_DRAWOP_POLYGON	0x07
    129#define FFB_DRAWOP_RECTANGLE	0x08
    130#define FFB_DRAWOP_FASTFILL	0x09
    131#define FFB_DRAWOP_BCOPY	0x0a
    132#define FFB_DRAWOP_VSCROLL	0x0b
    133
    134/* Pixel processor control */
    135/* Force WID */
    136#define FFB_PPC_FW_DISABLE	0x800000
    137#define FFB_PPC_FW_ENABLE	0xc00000
    138/* Auxiliary clip */
    139#define FFB_PPC_ACE_DISABLE	0x040000
    140#define FFB_PPC_ACE_AUX_SUB	0x080000
    141#define FFB_PPC_ACE_AUX_ADD	0x0c0000
    142/* Depth cue */
    143#define FFB_PPC_DCE_DISABLE	0x020000
    144#define FFB_PPC_DCE_ENABLE	0x030000
    145/* Alpha blend */
    146#define FFB_PPC_ABE_DISABLE	0x008000
    147#define FFB_PPC_ABE_ENABLE	0x00c000
    148/* View clip */
    149#define FFB_PPC_VCE_DISABLE	0x001000
    150#define FFB_PPC_VCE_2D		0x002000
    151#define FFB_PPC_VCE_3D		0x003000
    152/* Area pattern */
    153#define FFB_PPC_APE_DISABLE	0x000800
    154#define FFB_PPC_APE_ENABLE	0x000c00
    155/* Transparent background */
    156#define FFB_PPC_TBE_OPAQUE	0x000200
    157#define FFB_PPC_TBE_TRANSPARENT	0x000300
    158/* Z source */
    159#define FFB_PPC_ZS_VAR		0x000080
    160#define FFB_PPC_ZS_CONST	0x0000c0
    161/* Y source */
    162#define FFB_PPC_YS_VAR		0x000020
    163#define FFB_PPC_YS_CONST	0x000030
    164/* X source */
    165#define FFB_PPC_XS_WID		0x000004
    166#define FFB_PPC_XS_VAR		0x000008
    167#define FFB_PPC_XS_CONST	0x00000c
    168/* Color (BGR) source */
    169#define FFB_PPC_CS_VAR		0x000002
    170#define FFB_PPC_CS_CONST	0x000003
    171
    172#define FFB_ROP_NEW		0x83
    173#define FFB_ROP_OLD		0x85
    174#define FFB_ROP_NEW_XOR_OLD	0x86
    175
    176#define FFB_UCSR_FIFO_MASK	0x00000fff
    177#define FFB_UCSR_FB_BUSY	0x01000000
    178#define FFB_UCSR_RP_BUSY	0x02000000
    179#define FFB_UCSR_ALL_BUSY	(FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY)
    180#define FFB_UCSR_READ_ERR	0x40000000
    181#define FFB_UCSR_FIFO_OVFL	0x80000000
    182#define FFB_UCSR_ALL_ERRORS	(FFB_UCSR_READ_ERR|FFB_UCSR_FIFO_OVFL)
    183
    184struct ffb_fbc {
    185	/* Next vertex registers */
    186	u32	xxx1[3];
    187	u32	alpha;
    188	u32	red;
    189	u32	green;
    190	u32	blue;
    191	u32	depth;
    192	u32	y;
    193	u32	x;
    194	u32	xxx2[2];
    195	u32	ryf;
    196	u32	rxf;
    197	u32	xxx3[2];
    198
    199	u32	dmyf;
    200	u32	dmxf;
    201	u32	xxx4[2];
    202	u32	ebyi;
    203	u32	ebxi;
    204	u32	xxx5[2];
    205	u32	by;
    206	u32	bx;
    207	u32	dy;
    208	u32	dx;
    209	u32	bh;
    210	u32	bw;
    211	u32	xxx6[2];
    212
    213	u32	xxx7[32];
    214
    215	/* Setup unit vertex state register */
    216	u32	suvtx;
    217	u32	xxx8[63];
    218
    219	/* Control registers */
    220	u32	ppc;
    221	u32	wid;
    222	u32	fg;
    223	u32	bg;
    224	u32	consty;
    225	u32	constz;
    226	u32	xclip;
    227	u32	dcss;
    228	u32	vclipmin;
    229	u32	vclipmax;
    230	u32	vclipzmin;
    231	u32	vclipzmax;
    232	u32	dcsf;
    233	u32	dcsb;
    234	u32	dczf;
    235	u32	dczb;
    236
    237	u32	xxx9;
    238	u32	blendc;
    239	u32	blendc1;
    240	u32	blendc2;
    241	u32	fbramitc;
    242	u32	fbc;
    243	u32	rop;
    244	u32	cmp;
    245	u32	matchab;
    246	u32	matchc;
    247	u32	magnab;
    248	u32	magnc;
    249	u32	fbcfg0;
    250	u32	fbcfg1;
    251	u32	fbcfg2;
    252	u32	fbcfg3;
    253
    254	u32	ppcfg;
    255	u32	pick;
    256	u32	fillmode;
    257	u32	fbramwac;
    258	u32	pmask;
    259	u32	xpmask;
    260	u32	ypmask;
    261	u32	zpmask;
    262	u32	clip0min;
    263	u32	clip0max;
    264	u32	clip1min;
    265	u32	clip1max;
    266	u32	clip2min;
    267	u32	clip2max;
    268	u32	clip3min;
    269	u32	clip3max;
    270
    271	/* New 3dRAM III support regs */
    272	u32	rawblend2;
    273	u32	rawpreblend;
    274	u32	rawstencil;
    275	u32	rawstencilctl;
    276	u32	threedram1;
    277	u32	threedram2;
    278	u32	passin;
    279	u32	rawclrdepth;
    280	u32	rawpmask;
    281	u32	rawcsrc;
    282	u32	rawmatch;
    283	u32	rawmagn;
    284	u32	rawropblend;
    285	u32	rawcmp;
    286	u32	rawwac;
    287	u32	fbramid;
    288
    289	u32	drawop;
    290	u32	xxx10[2];
    291	u32	fontlpat;
    292	u32	xxx11;
    293	u32	fontxy;
    294	u32	fontw;
    295	u32	fontinc;
    296	u32	font;
    297	u32	xxx12[3];
    298	u32	blend2;
    299	u32	preblend;
    300	u32	stencil;
    301	u32	stencilctl;
    302
    303	u32	xxx13[4];
    304	u32	dcss1;
    305	u32	dcss2;
    306	u32	dcss3;
    307	u32	widpmask;
    308	u32	dcs2;
    309	u32	dcs3;
    310	u32	dcs4;
    311	u32	xxx14;
    312	u32	dcd2;
    313	u32	dcd3;
    314	u32	dcd4;
    315	u32	xxx15;
    316
    317	u32	pattern[32];
    318
    319	u32	xxx16[256];
    320
    321	u32	devid;
    322	u32	xxx17[63];
    323
    324	u32	ucsr;
    325	u32	xxx18[31];
    326
    327	u32	mer;
    328};
    329
    330struct ffb_dac {
    331	u32	type;
    332	u32	value;
    333	u32	type2;
    334	u32	value2;
    335};
    336
    337#define FFB_DAC_UCTRL		0x1001 /* User Control */
    338#define FFB_DAC_UCTRL_MANREV	0x00000f00 /* 4-bit Manufacturing Revision */
    339#define FFB_DAC_UCTRL_MANREV_SHIFT 8
    340#define FFB_DAC_TGEN		0x6000 /* Timing Generator */
    341#define FFB_DAC_TGEN_VIDE	0x00000001 /* Video Enable */
    342#define FFB_DAC_DID		0x8000 /* Device Identification */
    343#define FFB_DAC_DID_PNUM	0x0ffff000 /* Device Part Number */
    344#define FFB_DAC_DID_PNUM_SHIFT	12
    345#define FFB_DAC_DID_REV		0xf0000000 /* Device Revision */
    346#define FFB_DAC_DID_REV_SHIFT	28
    347
    348#define FFB_DAC_CUR_CTRL	0x100
    349#define FFB_DAC_CUR_CTRL_P0	0x00000001
    350#define FFB_DAC_CUR_CTRL_P1	0x00000002
    351
    352struct ffb_par {
    353	spinlock_t		lock;
    354	struct ffb_fbc __iomem	*fbc;
    355	struct ffb_dac __iomem	*dac;
    356
    357	u32			flags;
    358#define FFB_FLAG_AFB		0x00000001 /* AFB m3 or m6 */
    359#define FFB_FLAG_BLANKED	0x00000002 /* screen is blanked */
    360#define FFB_FLAG_INVCURSOR	0x00000004 /* DAC has inverted cursor logic */
    361
    362	u32			fg_cache __attribute__((aligned (8)));
    363	u32			bg_cache;
    364	u32			rop_cache;
    365
    366	int			fifo_cache;
    367
    368	unsigned long		physbase;
    369	unsigned long		fbsize;
    370
    371	int			board_type;
    372
    373	u32			pseudo_palette[16];
    374};
    375
    376static void FFBFifo(struct ffb_par *par, int n)
    377{
    378	struct ffb_fbc __iomem *fbc;
    379	int cache = par->fifo_cache;
    380
    381	if (cache - n < 0) {
    382		fbc = par->fbc;
    383		do {
    384			cache = (upa_readl(&fbc->ucsr) & FFB_UCSR_FIFO_MASK);
    385			cache -= 8;
    386		} while (cache - n < 0);
    387	}
    388	par->fifo_cache = cache - n;
    389}
    390
    391static void FFBWait(struct ffb_par *par)
    392{
    393	struct ffb_fbc __iomem *fbc;
    394	int limit = 10000;
    395
    396	fbc = par->fbc;
    397	do {
    398		if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_BUSY) == 0)
    399			break;
    400		if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) {
    401			upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
    402		}
    403		udelay(10);
    404	} while (--limit > 0);
    405}
    406
    407static int ffb_sync(struct fb_info *p)
    408{
    409	struct ffb_par *par = (struct ffb_par *)p->par;
    410
    411	FFBWait(par);
    412	return 0;
    413}
    414
    415static __inline__ void ffb_rop(struct ffb_par *par, u32 rop)
    416{
    417	if (par->rop_cache != rop) {
    418		FFBFifo(par, 1);
    419		upa_writel(rop, &par->fbc->rop);
    420		par->rop_cache = rop;
    421	}
    422}
    423
    424static void ffb_switch_from_graph(struct ffb_par *par)
    425{
    426	struct ffb_fbc __iomem *fbc = par->fbc;
    427	struct ffb_dac __iomem *dac = par->dac;
    428	unsigned long flags;
    429
    430	spin_lock_irqsave(&par->lock, flags);
    431	FFBWait(par);
    432	par->fifo_cache = 0;
    433	FFBFifo(par, 7);
    434	upa_writel(FFB_PPC_VCE_DISABLE | FFB_PPC_TBE_OPAQUE |
    435		   FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
    436		   &fbc->ppc);
    437	upa_writel(0x2000707f, &fbc->fbc);
    438	upa_writel(par->rop_cache, &fbc->rop);
    439	upa_writel(0xffffffff, &fbc->pmask);
    440	upa_writel((1 << 16) | (0 << 0), &fbc->fontinc);
    441	upa_writel(par->fg_cache, &fbc->fg);
    442	upa_writel(par->bg_cache, &fbc->bg);
    443	FFBWait(par);
    444
    445	/* Disable cursor.  */
    446	upa_writel(FFB_DAC_CUR_CTRL, &dac->type2);
    447	if (par->flags & FFB_FLAG_INVCURSOR)
    448		upa_writel(0, &dac->value2);
    449	else
    450		upa_writel((FFB_DAC_CUR_CTRL_P0 |
    451			    FFB_DAC_CUR_CTRL_P1), &dac->value2);
    452
    453	spin_unlock_irqrestore(&par->lock, flags);
    454}
    455
    456static int ffb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
    457{
    458	struct ffb_par *par = (struct ffb_par *)info->par;
    459
    460	/* We just use this to catch switches out of
    461	 * graphics mode.
    462	 */
    463	ffb_switch_from_graph(par);
    464
    465	if (var->xoffset || var->yoffset || var->vmode)
    466		return -EINVAL;
    467	return 0;
    468}
    469
    470/**
    471 *	ffb_fillrect - Draws a rectangle on the screen.
    472 *
    473 *	@info: frame buffer structure that represents a single frame buffer
    474 *	@rect: structure defining the rectagle and operation.
    475 */
    476static void ffb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
    477{
    478	struct ffb_par *par = (struct ffb_par *)info->par;
    479	struct ffb_fbc __iomem *fbc = par->fbc;
    480	unsigned long flags;
    481	u32 fg;
    482
    483	BUG_ON(rect->rop != ROP_COPY && rect->rop != ROP_XOR);
    484
    485	fg = ((u32 *)info->pseudo_palette)[rect->color];
    486
    487	spin_lock_irqsave(&par->lock, flags);
    488
    489	if (fg != par->fg_cache) {
    490		FFBFifo(par, 1);
    491		upa_writel(fg, &fbc->fg);
    492		par->fg_cache = fg;
    493	}
    494
    495	ffb_rop(par, rect->rop == ROP_COPY ?
    496		     FFB_ROP_NEW :
    497		     FFB_ROP_NEW_XOR_OLD);
    498
    499	FFBFifo(par, 5);
    500	upa_writel(FFB_DRAWOP_RECTANGLE, &fbc->drawop);
    501	upa_writel(rect->dy, &fbc->by);
    502	upa_writel(rect->dx, &fbc->bx);
    503	upa_writel(rect->height, &fbc->bh);
    504	upa_writel(rect->width, &fbc->bw);
    505
    506	spin_unlock_irqrestore(&par->lock, flags);
    507}
    508
    509/**
    510 *	ffb_copyarea - Copies on area of the screen to another area.
    511 *
    512 *	@info: frame buffer structure that represents a single frame buffer
    513 *	@area: structure defining the source and destination.
    514 */
    515
    516static void ffb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
    517{
    518	struct ffb_par *par = (struct ffb_par *)info->par;
    519	struct ffb_fbc __iomem *fbc = par->fbc;
    520	unsigned long flags;
    521
    522	if (area->dx != area->sx ||
    523	    area->dy == area->sy) {
    524		cfb_copyarea(info, area);
    525		return;
    526	}
    527
    528	spin_lock_irqsave(&par->lock, flags);
    529
    530	ffb_rop(par, FFB_ROP_OLD);
    531
    532	FFBFifo(par, 7);
    533	upa_writel(FFB_DRAWOP_VSCROLL, &fbc->drawop);
    534	upa_writel(area->sy, &fbc->by);
    535	upa_writel(area->sx, &fbc->bx);
    536	upa_writel(area->dy, &fbc->dy);
    537	upa_writel(area->dx, &fbc->dx);
    538	upa_writel(area->height, &fbc->bh);
    539	upa_writel(area->width, &fbc->bw);
    540
    541	spin_unlock_irqrestore(&par->lock, flags);
    542}
    543
    544/**
    545 *	ffb_imageblit - Copies a image from system memory to the screen.
    546 *
    547 *	@info: frame buffer structure that represents a single frame buffer
    548 *	@image: structure defining the image.
    549 */
    550static void ffb_imageblit(struct fb_info *info, const struct fb_image *image)
    551{
    552	struct ffb_par *par = (struct ffb_par *)info->par;
    553	struct ffb_fbc __iomem *fbc = par->fbc;
    554	const u8 *data = image->data;
    555	unsigned long flags;
    556	u32 fg, bg, xy;
    557	u64 fgbg;
    558	int i, width, stride;
    559
    560	if (image->depth > 1) {
    561		cfb_imageblit(info, image);
    562		return;
    563	}
    564
    565	fg = ((u32 *)info->pseudo_palette)[image->fg_color];
    566	bg = ((u32 *)info->pseudo_palette)[image->bg_color];
    567	fgbg = ((u64) fg << 32) | (u64) bg;
    568	xy = (image->dy << 16) | image->dx;
    569	width = image->width;
    570	stride = ((width + 7) >> 3);
    571
    572	spin_lock_irqsave(&par->lock, flags);
    573
    574	if (fgbg != *(u64 *)&par->fg_cache) {
    575		FFBFifo(par, 2);
    576		upa_writeq(fgbg, &fbc->fg);
    577		*(u64 *)&par->fg_cache = fgbg;
    578	}
    579
    580	if (width >= 32) {
    581		FFBFifo(par, 1);
    582		upa_writel(32, &fbc->fontw);
    583	}
    584
    585	while (width >= 32) {
    586		const u8 *next_data = data + 4;
    587
    588		FFBFifo(par, 1);
    589		upa_writel(xy, &fbc->fontxy);
    590		xy += (32 << 0);
    591
    592		for (i = 0; i < image->height; i++) {
    593			u32 val = (((u32)data[0] << 24) |
    594				   ((u32)data[1] << 16) |
    595				   ((u32)data[2] <<  8) |
    596				   ((u32)data[3] <<  0));
    597			FFBFifo(par, 1);
    598			upa_writel(val, &fbc->font);
    599
    600			data += stride;
    601		}
    602
    603		data = next_data;
    604		width -= 32;
    605	}
    606
    607	if (width) {
    608		FFBFifo(par, 2);
    609		upa_writel(width, &fbc->fontw);
    610		upa_writel(xy, &fbc->fontxy);
    611
    612		for (i = 0; i < image->height; i++) {
    613			u32 val = (((u32)data[0] << 24) |
    614				   ((u32)data[1] << 16) |
    615				   ((u32)data[2] <<  8) |
    616				   ((u32)data[3] <<  0));
    617			FFBFifo(par, 1);
    618			upa_writel(val, &fbc->font);
    619
    620			data += stride;
    621		}
    622	}
    623
    624	spin_unlock_irqrestore(&par->lock, flags);
    625}
    626
    627static void ffb_fixup_var_rgb(struct fb_var_screeninfo *var)
    628{
    629	var->red.offset = 0;
    630	var->red.length = 8;
    631	var->green.offset = 8;
    632	var->green.length = 8;
    633	var->blue.offset = 16;
    634	var->blue.length = 8;
    635	var->transp.offset = 0;
    636	var->transp.length = 0;
    637}
    638
    639/**
    640 *	ffb_setcolreg - Sets a color register.
    641 *
    642 *	@regno: boolean, 0 copy local, 1 get_user() function
    643 *	@red: frame buffer colormap structure
    644 *	@green: The green value which can be up to 16 bits wide
    645 *	@blue:  The blue value which can be up to 16 bits wide.
    646 *	@transp: If supported the alpha value which can be up to 16 bits wide.
    647 *	@info: frame buffer info structure
    648 */
    649static int ffb_setcolreg(unsigned regno,
    650			 unsigned red, unsigned green, unsigned blue,
    651			 unsigned transp, struct fb_info *info)
    652{
    653	u32 value;
    654
    655	if (regno >= 16)
    656		return 1;
    657
    658	red >>= 8;
    659	green >>= 8;
    660	blue >>= 8;
    661
    662	value = (blue << 16) | (green << 8) | red;
    663	((u32 *)info->pseudo_palette)[regno] = value;
    664
    665	return 0;
    666}
    667
    668/**
    669 *	ffb_blank - Optional function.  Blanks the display.
    670 *	@blank: the blank mode we want.
    671 *	@info: frame buffer structure that represents a single frame buffer
    672 */
    673static int ffb_blank(int blank, struct fb_info *info)
    674{
    675	struct ffb_par *par = (struct ffb_par *)info->par;
    676	struct ffb_dac __iomem *dac = par->dac;
    677	unsigned long flags;
    678	u32 val;
    679	int i;
    680
    681	spin_lock_irqsave(&par->lock, flags);
    682
    683	FFBWait(par);
    684
    685	upa_writel(FFB_DAC_TGEN, &dac->type);
    686	val = upa_readl(&dac->value);
    687	switch (blank) {
    688	case FB_BLANK_UNBLANK: /* Unblanking */
    689		val |= FFB_DAC_TGEN_VIDE;
    690		par->flags &= ~FFB_FLAG_BLANKED;
    691		break;
    692
    693	case FB_BLANK_NORMAL: /* Normal blanking */
    694	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
    695	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
    696	case FB_BLANK_POWERDOWN: /* Poweroff */
    697		val &= ~FFB_DAC_TGEN_VIDE;
    698		par->flags |= FFB_FLAG_BLANKED;
    699		break;
    700	}
    701	upa_writel(FFB_DAC_TGEN, &dac->type);
    702	upa_writel(val, &dac->value);
    703	for (i = 0; i < 10; i++) {
    704		upa_writel(FFB_DAC_TGEN, &dac->type);
    705		upa_readl(&dac->value);
    706	}
    707
    708	spin_unlock_irqrestore(&par->lock, flags);
    709
    710	return 0;
    711}
    712
    713static struct sbus_mmap_map ffb_mmap_map[] = {
    714	{
    715		.voff	= FFB_SFB8R_VOFF,
    716		.poff	= FFB_SFB8R_POFF,
    717		.size	= 0x0400000
    718	},
    719	{
    720		.voff	= FFB_SFB8G_VOFF,
    721		.poff	= FFB_SFB8G_POFF,
    722		.size	= 0x0400000
    723	},
    724	{
    725		.voff	= FFB_SFB8B_VOFF,
    726		.poff	= FFB_SFB8B_POFF,
    727		.size	= 0x0400000
    728	},
    729	{
    730		.voff	= FFB_SFB8X_VOFF,
    731		.poff	= FFB_SFB8X_POFF,
    732		.size	= 0x0400000
    733	},
    734	{
    735		.voff	= FFB_SFB32_VOFF,
    736		.poff	= FFB_SFB32_POFF,
    737		.size	= 0x1000000
    738	},
    739	{
    740		.voff	= FFB_SFB64_VOFF,
    741		.poff	= FFB_SFB64_POFF,
    742		.size	= 0x2000000
    743	},
    744	{
    745		.voff	= FFB_FBC_REGS_VOFF,
    746		.poff	= FFB_FBC_REGS_POFF,
    747		.size	= 0x0002000
    748	},
    749	{
    750		.voff	= FFB_BM_FBC_REGS_VOFF,
    751		.poff	= FFB_BM_FBC_REGS_POFF,
    752		.size	= 0x0002000
    753	},
    754	{
    755		.voff	= FFB_DFB8R_VOFF,
    756		.poff	= FFB_DFB8R_POFF,
    757		.size	= 0x0400000
    758	},
    759	{
    760		.voff	= FFB_DFB8G_VOFF,
    761		.poff	= FFB_DFB8G_POFF,
    762		.size	= 0x0400000
    763	},
    764	{
    765		.voff	= FFB_DFB8B_VOFF,
    766		.poff	= FFB_DFB8B_POFF,
    767		.size	= 0x0400000
    768	},
    769	{
    770		.voff	= FFB_DFB8X_VOFF,
    771		.poff	= FFB_DFB8X_POFF,
    772		.size	= 0x0400000
    773	},
    774	{
    775		.voff	= FFB_DFB24_VOFF,
    776		.poff	= FFB_DFB24_POFF,
    777		.size	= 0x1000000
    778	},
    779	{
    780		.voff	= FFB_DFB32_VOFF,
    781		.poff	= FFB_DFB32_POFF,
    782		.size	= 0x1000000
    783	},
    784	{
    785		.voff	= FFB_FBC_KREGS_VOFF,
    786		.poff	= FFB_FBC_KREGS_POFF,
    787		.size	= 0x0002000
    788	},
    789	{
    790		.voff	= FFB_DAC_VOFF,
    791		.poff	= FFB_DAC_POFF,
    792		.size	= 0x0002000
    793	},
    794	{
    795		.voff	= FFB_PROM_VOFF,
    796		.poff	= FFB_PROM_POFF,
    797		.size	= 0x0010000
    798	},
    799	{
    800		.voff	= FFB_EXP_VOFF,
    801		.poff	= FFB_EXP_POFF,
    802		.size	= 0x0002000
    803	},
    804	{
    805		.voff	= FFB_DFB422A_VOFF,
    806		.poff	= FFB_DFB422A_POFF,
    807		.size	= 0x0800000
    808	},
    809	{
    810		.voff	= FFB_DFB422AD_VOFF,
    811		.poff	= FFB_DFB422AD_POFF,
    812		.size	= 0x0800000
    813	},
    814	{
    815		.voff	= FFB_DFB24B_VOFF,
    816		.poff	= FFB_DFB24B_POFF,
    817		.size	= 0x1000000
    818	},
    819	{
    820		.voff	= FFB_DFB422B_VOFF,
    821		.poff	= FFB_DFB422B_POFF,
    822		.size	= 0x0800000
    823	},
    824	{
    825		.voff	= FFB_DFB422BD_VOFF,
    826		.poff	= FFB_DFB422BD_POFF,
    827		.size	= 0x0800000
    828	},
    829	{
    830		.voff	= FFB_SFB16Z_VOFF,
    831		.poff	= FFB_SFB16Z_POFF,
    832		.size	= 0x0800000
    833	},
    834	{
    835		.voff	= FFB_SFB8Z_VOFF,
    836		.poff	= FFB_SFB8Z_POFF,
    837		.size	= 0x0800000
    838	},
    839	{
    840		.voff	= FFB_SFB422_VOFF,
    841		.poff	= FFB_SFB422_POFF,
    842		.size	= 0x0800000
    843	},
    844	{
    845		.voff	= FFB_SFB422D_VOFF,
    846		.poff	= FFB_SFB422D_POFF,
    847		.size	= 0x0800000
    848	},
    849	{ .size = 0 }
    850};
    851
    852static int ffb_mmap(struct fb_info *info, struct vm_area_struct *vma)
    853{
    854	struct ffb_par *par = (struct ffb_par *)info->par;
    855
    856	return sbusfb_mmap_helper(ffb_mmap_map,
    857				  par->physbase, par->fbsize,
    858				  0, vma);
    859}
    860
    861static int ffb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
    862{
    863	struct ffb_par *par = (struct ffb_par *)info->par;
    864
    865	return sbusfb_ioctl_helper(cmd, arg, info,
    866				   FBTYPE_CREATOR, 24, par->fbsize);
    867}
    868
    869/*
    870 *  Initialisation
    871 */
    872
    873static void ffb_init_fix(struct fb_info *info)
    874{
    875	struct ffb_par *par = (struct ffb_par *)info->par;
    876	const char *ffb_type_name;
    877
    878	if (!(par->flags & FFB_FLAG_AFB)) {
    879		if ((par->board_type & 0x7) == 0x3)
    880			ffb_type_name = "Creator 3D";
    881		else
    882			ffb_type_name = "Creator";
    883	} else
    884		ffb_type_name = "Elite 3D";
    885
    886	strlcpy(info->fix.id, ffb_type_name, sizeof(info->fix.id));
    887
    888	info->fix.type = FB_TYPE_PACKED_PIXELS;
    889	info->fix.visual = FB_VISUAL_TRUECOLOR;
    890
    891	/* Framebuffer length is the same regardless of resolution. */
    892	info->fix.line_length = 8192;
    893
    894	info->fix.accel = FB_ACCEL_SUN_CREATOR;
    895}
    896
    897static int ffb_probe(struct platform_device *op)
    898{
    899	struct device_node *dp = op->dev.of_node;
    900	struct ffb_fbc __iomem *fbc;
    901	struct ffb_dac __iomem *dac;
    902	struct fb_info *info;
    903	struct ffb_par *par;
    904	u32 dac_pnum, dac_rev, dac_mrev;
    905	int err;
    906
    907	info = framebuffer_alloc(sizeof(struct ffb_par), &op->dev);
    908
    909	err = -ENOMEM;
    910	if (!info)
    911		goto out_err;
    912
    913	par = info->par;
    914
    915	spin_lock_init(&par->lock);
    916	par->fbc = of_ioremap(&op->resource[2], 0,
    917			      sizeof(struct ffb_fbc), "ffb fbc");
    918	if (!par->fbc)
    919		goto out_release_fb;
    920
    921	par->dac = of_ioremap(&op->resource[1], 0,
    922			      sizeof(struct ffb_dac), "ffb dac");
    923	if (!par->dac)
    924		goto out_unmap_fbc;
    925
    926	par->rop_cache = FFB_ROP_NEW;
    927	par->physbase = op->resource[0].start;
    928
    929	/* Don't mention copyarea, so SCROLL_REDRAW is always
    930	 * used.  It is the fastest on this chip.
    931	 */
    932	info->flags = (FBINFO_DEFAULT |
    933		       /* FBINFO_HWACCEL_COPYAREA | */
    934		       FBINFO_HWACCEL_FILLRECT |
    935		       FBINFO_HWACCEL_IMAGEBLIT);
    936
    937	info->fbops = &ffb_ops;
    938
    939	info->screen_base = (char *) par->physbase + FFB_DFB24_POFF;
    940	info->pseudo_palette = par->pseudo_palette;
    941
    942	sbusfb_fill_var(&info->var, dp, 32);
    943	par->fbsize = PAGE_ALIGN(info->var.xres * info->var.yres * 4);
    944	ffb_fixup_var_rgb(&info->var);
    945
    946	info->var.accel_flags = FB_ACCELF_TEXT;
    947
    948	if (of_node_name_eq(dp, "SUNW,afb"))
    949		par->flags |= FFB_FLAG_AFB;
    950
    951	par->board_type = of_getintprop_default(dp, "board_type", 0);
    952
    953	fbc = par->fbc;
    954	if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)
    955		upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
    956
    957	dac = par->dac;
    958	upa_writel(FFB_DAC_DID, &dac->type);
    959	dac_pnum = upa_readl(&dac->value);
    960	dac_rev = (dac_pnum & FFB_DAC_DID_REV) >> FFB_DAC_DID_REV_SHIFT;
    961	dac_pnum = (dac_pnum & FFB_DAC_DID_PNUM) >> FFB_DAC_DID_PNUM_SHIFT;
    962
    963	upa_writel(FFB_DAC_UCTRL, &dac->type);
    964	dac_mrev = upa_readl(&dac->value);
    965	dac_mrev = (dac_mrev & FFB_DAC_UCTRL_MANREV) >>
    966		FFB_DAC_UCTRL_MANREV_SHIFT;
    967
    968	/* Elite3D has different DAC revision numbering, and no DAC revisions
    969	 * have the reversed meaning of cursor enable.  Otherwise, Pacifica 1
    970	 * ramdacs with manufacturing revision less than 3 have inverted
    971	 * cursor logic.  We identify Pacifica 1 as not Pacifica 2, the
    972	 * latter having a part number value of 0x236e.
    973	 */
    974	if ((par->flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) {
    975		par->flags &= ~FFB_FLAG_INVCURSOR;
    976	} else {
    977		if (dac_mrev < 3)
    978			par->flags |= FFB_FLAG_INVCURSOR;
    979	}
    980
    981	ffb_switch_from_graph(par);
    982
    983	/* Unblank it just to be sure.  When there are multiple
    984	 * FFB/AFB cards in the system, or it is not the OBP
    985	 * chosen console, it will have video outputs off in
    986	 * the DAC.
    987	 */
    988	ffb_blank(FB_BLANK_UNBLANK, info);
    989
    990	if (fb_alloc_cmap(&info->cmap, 256, 0))
    991		goto out_unmap_dac;
    992
    993	ffb_init_fix(info);
    994
    995	err = register_framebuffer(info);
    996	if (err < 0)
    997		goto out_dealloc_cmap;
    998
    999	dev_set_drvdata(&op->dev, info);
   1000
   1001	printk(KERN_INFO "%pOF: %s at %016lx, type %d, "
   1002	       "DAC pnum[%x] rev[%d] manuf_rev[%d]\n",
   1003	       dp,
   1004	       ((par->flags & FFB_FLAG_AFB) ? "AFB" : "FFB"),
   1005	       par->physbase, par->board_type,
   1006	       dac_pnum, dac_rev, dac_mrev);
   1007
   1008	return 0;
   1009
   1010out_dealloc_cmap:
   1011	fb_dealloc_cmap(&info->cmap);
   1012
   1013out_unmap_dac:
   1014	of_iounmap(&op->resource[1], par->dac, sizeof(struct ffb_dac));
   1015
   1016out_unmap_fbc:
   1017	of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));
   1018
   1019out_release_fb:
   1020	framebuffer_release(info);
   1021
   1022out_err:
   1023	return err;
   1024}
   1025
   1026static int ffb_remove(struct platform_device *op)
   1027{
   1028	struct fb_info *info = dev_get_drvdata(&op->dev);
   1029	struct ffb_par *par = info->par;
   1030
   1031	unregister_framebuffer(info);
   1032	fb_dealloc_cmap(&info->cmap);
   1033
   1034	of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));
   1035	of_iounmap(&op->resource[1], par->dac, sizeof(struct ffb_dac));
   1036
   1037	framebuffer_release(info);
   1038
   1039	return 0;
   1040}
   1041
   1042static const struct of_device_id ffb_match[] = {
   1043	{
   1044		.name = "SUNW,ffb",
   1045	},
   1046	{
   1047		.name = "SUNW,afb",
   1048	},
   1049	{},
   1050};
   1051MODULE_DEVICE_TABLE(of, ffb_match);
   1052
   1053static struct platform_driver ffb_driver = {
   1054	.driver = {
   1055		.name = "ffb",
   1056		.of_match_table = ffb_match,
   1057	},
   1058	.probe		= ffb_probe,
   1059	.remove		= ffb_remove,
   1060};
   1061
   1062static int __init ffb_init(void)
   1063{
   1064	if (fb_get_options("ffb", NULL))
   1065		return -ENODEV;
   1066
   1067	return platform_driver_register(&ffb_driver);
   1068}
   1069
   1070static void __exit ffb_exit(void)
   1071{
   1072	platform_driver_unregister(&ffb_driver);
   1073}
   1074
   1075module_init(ffb_init);
   1076module_exit(ffb_exit);
   1077
   1078MODULE_DESCRIPTION("framebuffer driver for Creator/Elite3D chipsets");
   1079MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
   1080MODULE_VERSION("2.0");
   1081MODULE_LICENSE("GPL");