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

gbefb.c (32866B)


      1/*
      2 *  SGI GBE frame buffer driver
      3 *
      4 *  Copyright (C) 1999 Silicon Graphics, Inc. - Jeffrey Newquist
      5 *  Copyright (C) 2002 Vivien Chappelier <vivien.chappelier@linux-mips.org>
      6 *
      7 *  This file is subject to the terms and conditions of the GNU General Public
      8 *  License. See the file COPYING in the main directory of this archive for
      9 *  more details.
     10 */
     11
     12#include <linux/delay.h>
     13#include <linux/platform_device.h>
     14#include <linux/dma-mapping.h>
     15#include <linux/errno.h>
     16#include <linux/gfp.h>
     17#include <linux/fb.h>
     18#include <linux/init.h>
     19#include <linux/interrupt.h>
     20#include <linux/kernel.h>
     21#include <linux/mm.h>
     22#include <linux/module.h>
     23#include <linux/io.h>
     24
     25#ifdef CONFIG_MIPS
     26#include <asm/addrspace.h>
     27#endif
     28#include <asm/byteorder.h>
     29#include <asm/tlbflush.h>
     30
     31#include <video/gbe.h>
     32
     33static struct sgi_gbe *gbe;
     34
     35struct gbefb_par {
     36	struct fb_var_screeninfo var;
     37	struct gbe_timing_info timing;
     38	int wc_cookie;
     39	int valid;
     40};
     41
     42#define GBE_BASE	0x16000000 /* SGI O2 */
     43
     44/* macro for fastest write-though access to the framebuffer */
     45#ifdef CONFIG_MIPS
     46#ifdef CONFIG_CPU_R10000
     47#define pgprot_fb(_prot) (((_prot) & (~_CACHE_MASK)) | _CACHE_UNCACHED_ACCELERATED)
     48#else
     49#define pgprot_fb(_prot) (((_prot) & (~_CACHE_MASK)) | _CACHE_CACHABLE_NO_WA)
     50#endif
     51#endif
     52
     53/*
     54 *  RAM we reserve for the frame buffer. This defines the maximum screen
     55 *  size
     56 */
     57#if CONFIG_FB_GBE_MEM > 8
     58#error GBE Framebuffer cannot use more than 8MB of memory
     59#endif
     60
     61#define TILE_SHIFT 16
     62#define TILE_SIZE (1 << TILE_SHIFT)
     63#define TILE_MASK (TILE_SIZE - 1)
     64
     65static unsigned int gbe_mem_size = CONFIG_FB_GBE_MEM * 1024*1024;
     66static void *gbe_mem;
     67static dma_addr_t gbe_dma_addr;
     68static unsigned long gbe_mem_phys;
     69
     70static struct {
     71	uint16_t *cpu;
     72	dma_addr_t dma;
     73} gbe_tiles;
     74
     75static int gbe_revision;
     76
     77static int ypan, ywrap;
     78
     79static uint32_t pseudo_palette[16];
     80static uint32_t gbe_cmap[256];
     81static int gbe_turned_on; /* 0 turned off, 1 turned on */
     82
     83static char *mode_option = NULL;
     84
     85/* default CRT mode */
     86static struct fb_var_screeninfo default_var_CRT = {
     87	/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
     88	.xres		= 640,
     89	.yres		= 480,
     90	.xres_virtual	= 640,
     91	.yres_virtual	= 480,
     92	.xoffset	= 0,
     93	.yoffset	= 0,
     94	.bits_per_pixel	= 8,
     95	.grayscale	= 0,
     96	.red		= { 0, 8, 0 },
     97	.green		= { 0, 8, 0 },
     98	.blue		= { 0, 8, 0 },
     99	.transp		= { 0, 0, 0 },
    100	.nonstd		= 0,
    101	.activate	= 0,
    102	.height		= -1,
    103	.width		= -1,
    104	.accel_flags	= 0,
    105	.pixclock	= 39722,	/* picoseconds */
    106	.left_margin	= 48,
    107	.right_margin	= 16,
    108	.upper_margin	= 33,
    109	.lower_margin	= 10,
    110	.hsync_len	= 96,
    111	.vsync_len	= 2,
    112	.sync		= 0,
    113	.vmode		= FB_VMODE_NONINTERLACED,
    114};
    115
    116/* default LCD mode */
    117static struct fb_var_screeninfo default_var_LCD = {
    118	/* 1600x1024, 8 bpp */
    119	.xres		= 1600,
    120	.yres		= 1024,
    121	.xres_virtual	= 1600,
    122	.yres_virtual	= 1024,
    123	.xoffset	= 0,
    124	.yoffset	= 0,
    125	.bits_per_pixel	= 8,
    126	.grayscale	= 0,
    127	.red		= { 0, 8, 0 },
    128	.green		= { 0, 8, 0 },
    129	.blue		= { 0, 8, 0 },
    130	.transp		= { 0, 0, 0 },
    131	.nonstd		= 0,
    132	.activate	= 0,
    133	.height		= -1,
    134	.width		= -1,
    135	.accel_flags	= 0,
    136	.pixclock	= 9353,
    137	.left_margin	= 20,
    138	.right_margin	= 30,
    139	.upper_margin	= 37,
    140	.lower_margin	= 3,
    141	.hsync_len	= 20,
    142	.vsync_len	= 3,
    143	.sync		= 0,
    144	.vmode		= FB_VMODE_NONINTERLACED
    145};
    146
    147/* default modedb mode */
    148/* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
    149static struct fb_videomode default_mode_CRT = {
    150	.refresh	= 60,
    151	.xres		= 640,
    152	.yres		= 480,
    153	.pixclock	= 39722,
    154	.left_margin	= 48,
    155	.right_margin	= 16,
    156	.upper_margin	= 33,
    157	.lower_margin	= 10,
    158	.hsync_len	= 96,
    159	.vsync_len	= 2,
    160	.sync		= 0,
    161	.vmode		= FB_VMODE_NONINTERLACED,
    162};
    163/* 1600x1024 SGI flatpanel 1600sw */
    164static struct fb_videomode default_mode_LCD = {
    165	/* 1600x1024, 8 bpp */
    166	.xres		= 1600,
    167	.yres		= 1024,
    168	.pixclock	= 9353,
    169	.left_margin	= 20,
    170	.right_margin	= 30,
    171	.upper_margin	= 37,
    172	.lower_margin	= 3,
    173	.hsync_len	= 20,
    174	.vsync_len	= 3,
    175	.vmode		= FB_VMODE_NONINTERLACED,
    176};
    177
    178static struct fb_videomode *default_mode = &default_mode_CRT;
    179static struct fb_var_screeninfo *default_var = &default_var_CRT;
    180
    181static int flat_panel_enabled = 0;
    182
    183static void gbe_reset(void)
    184{
    185	/* Turn on dotclock PLL */
    186	gbe->ctrlstat = 0x300aa000;
    187}
    188
    189
    190/*
    191 * Function:	gbe_turn_off
    192 * Parameters:	(None)
    193 * Description:	This should turn off the monitor and gbe.  This is used
    194 *              when switching between the serial console and the graphics
    195 *              console.
    196 */
    197
    198static void gbe_turn_off(void)
    199{
    200	int i;
    201	unsigned int val, y, vpixen_off;
    202
    203	gbe_turned_on = 0;
    204
    205	/* check if pixel counter is on */
    206	val = gbe->vt_xy;
    207	if (GET_GBE_FIELD(VT_XY, FREEZE, val) == 1)
    208		return;
    209
    210	/* turn off DMA */
    211	val = gbe->ovr_control;
    212	SET_GBE_FIELD(OVR_CONTROL, OVR_DMA_ENABLE, val, 0);
    213	gbe->ovr_control = val;
    214	udelay(1000);
    215	val = gbe->frm_control;
    216	SET_GBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, val, 0);
    217	gbe->frm_control = val;
    218	udelay(1000);
    219	val = gbe->did_control;
    220	SET_GBE_FIELD(DID_CONTROL, DID_DMA_ENABLE, val, 0);
    221	gbe->did_control = val;
    222	udelay(1000);
    223
    224	/* We have to wait through two vertical retrace periods before
    225	 * the pixel DMA is turned off for sure. */
    226	for (i = 0; i < 10000; i++) {
    227		val = gbe->frm_inhwctrl;
    228		if (GET_GBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, val)) {
    229			udelay(10);
    230		} else {
    231			val = gbe->ovr_inhwctrl;
    232			if (GET_GBE_FIELD(OVR_INHWCTRL, OVR_DMA_ENABLE, val)) {
    233				udelay(10);
    234			} else {
    235				val = gbe->did_inhwctrl;
    236				if (GET_GBE_FIELD(DID_INHWCTRL, DID_DMA_ENABLE, val)) {
    237					udelay(10);
    238				} else
    239					break;
    240			}
    241		}
    242	}
    243	if (i == 10000)
    244		printk(KERN_ERR "gbefb: turn off DMA timed out\n");
    245
    246	/* wait for vpixen_off */
    247	val = gbe->vt_vpixen;
    248	vpixen_off = GET_GBE_FIELD(VT_VPIXEN, VPIXEN_OFF, val);
    249
    250	for (i = 0; i < 100000; i++) {
    251		val = gbe->vt_xy;
    252		y = GET_GBE_FIELD(VT_XY, Y, val);
    253		if (y < vpixen_off)
    254			break;
    255		udelay(1);
    256	}
    257	if (i == 100000)
    258		printk(KERN_ERR
    259		       "gbefb: wait for vpixen_off timed out\n");
    260	for (i = 0; i < 10000; i++) {
    261		val = gbe->vt_xy;
    262		y = GET_GBE_FIELD(VT_XY, Y, val);
    263		if (y > vpixen_off)
    264			break;
    265		udelay(1);
    266	}
    267	if (i == 10000)
    268		printk(KERN_ERR "gbefb: wait for vpixen_off timed out\n");
    269
    270	/* turn off pixel counter */
    271	val = 0;
    272	SET_GBE_FIELD(VT_XY, FREEZE, val, 1);
    273	gbe->vt_xy = val;
    274	mdelay(10);
    275	for (i = 0; i < 10000; i++) {
    276		val = gbe->vt_xy;
    277		if (GET_GBE_FIELD(VT_XY, FREEZE, val) != 1)
    278			udelay(10);
    279		else
    280			break;
    281	}
    282	if (i == 10000)
    283		printk(KERN_ERR "gbefb: turn off pixel clock timed out\n");
    284
    285	/* turn off dot clock */
    286	val = gbe->dotclock;
    287	SET_GBE_FIELD(DOTCLK, RUN, val, 0);
    288	gbe->dotclock = val;
    289	mdelay(10);
    290	for (i = 0; i < 10000; i++) {
    291		val = gbe->dotclock;
    292		if (GET_GBE_FIELD(DOTCLK, RUN, val))
    293			udelay(10);
    294		else
    295			break;
    296	}
    297	if (i == 10000)
    298		printk(KERN_ERR "gbefb: turn off dotclock timed out\n");
    299
    300	/* reset the frame DMA FIFO */
    301	val = gbe->frm_size_tile;
    302	SET_GBE_FIELD(FRM_SIZE_TILE, FRM_FIFO_RESET, val, 1);
    303	gbe->frm_size_tile = val;
    304	SET_GBE_FIELD(FRM_SIZE_TILE, FRM_FIFO_RESET, val, 0);
    305	gbe->frm_size_tile = val;
    306}
    307
    308static void gbe_turn_on(void)
    309{
    310	unsigned int val, i;
    311
    312	/*
    313	 * Check if pixel counter is off, for unknown reason this
    314	 * code hangs Visual Workstations
    315	 */
    316	if (gbe_revision < 2) {
    317		val = gbe->vt_xy;
    318		if (GET_GBE_FIELD(VT_XY, FREEZE, val) == 0)
    319			return;
    320	}
    321
    322	/* turn on dot clock */
    323	val = gbe->dotclock;
    324	SET_GBE_FIELD(DOTCLK, RUN, val, 1);
    325	gbe->dotclock = val;
    326	mdelay(10);
    327	for (i = 0; i < 10000; i++) {
    328		val = gbe->dotclock;
    329		if (GET_GBE_FIELD(DOTCLK, RUN, val) != 1)
    330			udelay(10);
    331		else
    332			break;
    333	}
    334	if (i == 10000)
    335		printk(KERN_ERR "gbefb: turn on dotclock timed out\n");
    336
    337	/* turn on pixel counter */
    338	val = 0;
    339	SET_GBE_FIELD(VT_XY, FREEZE, val, 0);
    340	gbe->vt_xy = val;
    341	mdelay(10);
    342	for (i = 0; i < 10000; i++) {
    343		val = gbe->vt_xy;
    344		if (GET_GBE_FIELD(VT_XY, FREEZE, val))
    345			udelay(10);
    346		else
    347			break;
    348	}
    349	if (i == 10000)
    350		printk(KERN_ERR "gbefb: turn on pixel clock timed out\n");
    351
    352	/* turn on DMA */
    353	val = gbe->frm_control;
    354	SET_GBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, val, 1);
    355	gbe->frm_control = val;
    356	udelay(1000);
    357	for (i = 0; i < 10000; i++) {
    358		val = gbe->frm_inhwctrl;
    359		if (GET_GBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, val) != 1)
    360			udelay(10);
    361		else
    362			break;
    363	}
    364	if (i == 10000)
    365		printk(KERN_ERR "gbefb: turn on DMA timed out\n");
    366
    367	gbe_turned_on = 1;
    368}
    369
    370static void gbe_loadcmap(void)
    371{
    372	int i, j;
    373
    374	for (i = 0; i < 256; i++) {
    375		for (j = 0; j < 1000 && gbe->cm_fifo >= 63; j++)
    376			udelay(10);
    377		if (j == 1000)
    378			printk(KERN_ERR "gbefb: cmap FIFO timeout\n");
    379
    380		gbe->cmap[i] = gbe_cmap[i];
    381	}
    382}
    383
    384/*
    385 *  Blank the display.
    386 */
    387static int gbefb_blank(int blank, struct fb_info *info)
    388{
    389	/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
    390	switch (blank) {
    391	case FB_BLANK_UNBLANK:		/* unblank */
    392		gbe_turn_on();
    393		gbe_loadcmap();
    394		break;
    395
    396	case FB_BLANK_NORMAL:		/* blank */
    397		gbe_turn_off();
    398		break;
    399
    400	default:
    401		/* Nothing */
    402		break;
    403	}
    404	return 0;
    405}
    406
    407/*
    408 *  Setup flatpanel related registers.
    409 */
    410static void gbefb_setup_flatpanel(struct gbe_timing_info *timing)
    411{
    412	int fp_wid, fp_hgt, fp_vbs, fp_vbe;
    413	u32 outputVal = 0;
    414
    415	SET_GBE_FIELD(VT_FLAGS, HDRV_INVERT, outputVal,
    416		(timing->flags & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1);
    417	SET_GBE_FIELD(VT_FLAGS, VDRV_INVERT, outputVal,
    418		(timing->flags & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1);
    419	gbe->vt_flags = outputVal;
    420
    421	/* Turn on the flat panel */
    422	fp_wid = 1600;
    423	fp_hgt = 1024;
    424	fp_vbs = 0;
    425	fp_vbe = 1600;
    426	timing->pll_m = 4;
    427	timing->pll_n = 1;
    428	timing->pll_p = 0;
    429
    430	outputVal = 0;
    431	SET_GBE_FIELD(FP_DE, ON, outputVal, fp_vbs);
    432	SET_GBE_FIELD(FP_DE, OFF, outputVal, fp_vbe);
    433	gbe->fp_de = outputVal;
    434	outputVal = 0;
    435	SET_GBE_FIELD(FP_HDRV, OFF, outputVal, fp_wid);
    436	gbe->fp_hdrv = outputVal;
    437	outputVal = 0;
    438	SET_GBE_FIELD(FP_VDRV, ON, outputVal, 1);
    439	SET_GBE_FIELD(FP_VDRV, OFF, outputVal, fp_hgt + 1);
    440	gbe->fp_vdrv = outputVal;
    441}
    442
    443struct gbe_pll_info {
    444	int clock_rate;
    445	int fvco_min;
    446	int fvco_max;
    447};
    448
    449static struct gbe_pll_info gbe_pll_table[2] = {
    450	{ 20, 80, 220 },
    451	{ 27, 80, 220 },
    452};
    453
    454static int compute_gbe_timing(struct fb_var_screeninfo *var,
    455			      struct gbe_timing_info *timing)
    456{
    457	int pll_m, pll_n, pll_p, error, best_m, best_n, best_p, best_error;
    458	int pixclock;
    459	struct gbe_pll_info *gbe_pll;
    460
    461	if (gbe_revision < 2)
    462		gbe_pll = &gbe_pll_table[0];
    463	else
    464		gbe_pll = &gbe_pll_table[1];
    465
    466	/* Determine valid resolution and timing
    467	 * GBE crystal runs at 20Mhz or 27Mhz
    468	 * pll_m, pll_n, pll_p define the following frequencies
    469	 * fvco = pll_m * 20Mhz / pll_n
    470	 * fout = fvco / (2**pll_p) */
    471	best_error = 1000000000;
    472	best_n = best_m = best_p = 0;
    473	for (pll_p = 0; pll_p < 4; pll_p++)
    474		for (pll_m = 1; pll_m < 256; pll_m++)
    475			for (pll_n = 1; pll_n < 64; pll_n++) {
    476				pixclock = (1000000 / gbe_pll->clock_rate) *
    477						(pll_n << pll_p) / pll_m;
    478
    479				error = var->pixclock - pixclock;
    480
    481				if (error < 0)
    482					error = -error;
    483
    484				if (error < best_error &&
    485				    pll_m / pll_n >
    486				    gbe_pll->fvco_min / gbe_pll->clock_rate &&
    487 				    pll_m / pll_n <
    488				    gbe_pll->fvco_max / gbe_pll->clock_rate) {
    489					best_error = error;
    490					best_m = pll_m;
    491					best_n = pll_n;
    492					best_p = pll_p;
    493				}
    494			}
    495
    496	if (!best_n || !best_m)
    497		return -EINVAL;	/* Resolution to high */
    498
    499	pixclock = (1000000 / gbe_pll->clock_rate) *
    500		(best_n << best_p) / best_m;
    501
    502	/* set video timing information */
    503	if (timing) {
    504		timing->width = var->xres;
    505		timing->height = var->yres;
    506		timing->pll_m = best_m;
    507		timing->pll_n = best_n;
    508		timing->pll_p = best_p;
    509		timing->cfreq = gbe_pll->clock_rate * 1000 * timing->pll_m /
    510			(timing->pll_n << timing->pll_p);
    511		timing->htotal = var->left_margin + var->xres +
    512				var->right_margin + var->hsync_len;
    513		timing->vtotal = var->upper_margin + var->yres +
    514				var->lower_margin + var->vsync_len;
    515		timing->fields_sec = 1000 * timing->cfreq / timing->htotal *
    516				1000 / timing->vtotal;
    517		timing->hblank_start = var->xres;
    518		timing->vblank_start = var->yres;
    519		timing->hblank_end = timing->htotal;
    520		timing->hsync_start = var->xres + var->right_margin + 1;
    521		timing->hsync_end = timing->hsync_start + var->hsync_len;
    522		timing->vblank_end = timing->vtotal;
    523		timing->vsync_start = var->yres + var->lower_margin + 1;
    524		timing->vsync_end = timing->vsync_start + var->vsync_len;
    525	}
    526
    527	return pixclock;
    528}
    529
    530static void gbe_set_timing_info(struct gbe_timing_info *timing)
    531{
    532	int temp;
    533	unsigned int val;
    534
    535	/* setup dot clock PLL */
    536	val = 0;
    537	SET_GBE_FIELD(DOTCLK, M, val, timing->pll_m - 1);
    538	SET_GBE_FIELD(DOTCLK, N, val, timing->pll_n - 1);
    539	SET_GBE_FIELD(DOTCLK, P, val, timing->pll_p);
    540	SET_GBE_FIELD(DOTCLK, RUN, val, 0);	/* do not start yet */
    541	gbe->dotclock = val;
    542	mdelay(10);
    543
    544	/* setup pixel counter */
    545	val = 0;
    546	SET_GBE_FIELD(VT_XYMAX, MAXX, val, timing->htotal);
    547	SET_GBE_FIELD(VT_XYMAX, MAXY, val, timing->vtotal);
    548	gbe->vt_xymax = val;
    549
    550	/* setup video timing signals */
    551	val = 0;
    552	SET_GBE_FIELD(VT_VSYNC, VSYNC_ON, val, timing->vsync_start);
    553	SET_GBE_FIELD(VT_VSYNC, VSYNC_OFF, val, timing->vsync_end);
    554	gbe->vt_vsync = val;
    555	val = 0;
    556	SET_GBE_FIELD(VT_HSYNC, HSYNC_ON, val, timing->hsync_start);
    557	SET_GBE_FIELD(VT_HSYNC, HSYNC_OFF, val, timing->hsync_end);
    558	gbe->vt_hsync = val;
    559	val = 0;
    560	SET_GBE_FIELD(VT_VBLANK, VBLANK_ON, val, timing->vblank_start);
    561	SET_GBE_FIELD(VT_VBLANK, VBLANK_OFF, val, timing->vblank_end);
    562	gbe->vt_vblank = val;
    563	val = 0;
    564	SET_GBE_FIELD(VT_HBLANK, HBLANK_ON, val,
    565		      timing->hblank_start - 5);
    566	SET_GBE_FIELD(VT_HBLANK, HBLANK_OFF, val,
    567		      timing->hblank_end - 3);
    568	gbe->vt_hblank = val;
    569
    570	/* setup internal timing signals */
    571	val = 0;
    572	SET_GBE_FIELD(VT_VCMAP, VCMAP_ON, val, timing->vblank_start);
    573	SET_GBE_FIELD(VT_VCMAP, VCMAP_OFF, val, timing->vblank_end);
    574	gbe->vt_vcmap = val;
    575	val = 0;
    576	SET_GBE_FIELD(VT_HCMAP, HCMAP_ON, val, timing->hblank_start);
    577	SET_GBE_FIELD(VT_HCMAP, HCMAP_OFF, val, timing->hblank_end);
    578	gbe->vt_hcmap = val;
    579
    580	val = 0;
    581	temp = timing->vblank_start - timing->vblank_end - 1;
    582	if (temp > 0)
    583		temp = -temp;
    584
    585	if (flat_panel_enabled)
    586		gbefb_setup_flatpanel(timing);
    587
    588	SET_GBE_FIELD(DID_START_XY, DID_STARTY, val, (u32) temp);
    589	if (timing->hblank_end >= 20)
    590		SET_GBE_FIELD(DID_START_XY, DID_STARTX, val,
    591			      timing->hblank_end - 20);
    592	else
    593		SET_GBE_FIELD(DID_START_XY, DID_STARTX, val,
    594			      timing->htotal - (20 - timing->hblank_end));
    595	gbe->did_start_xy = val;
    596
    597	val = 0;
    598	SET_GBE_FIELD(CRS_START_XY, CRS_STARTY, val, (u32) (temp + 1));
    599	if (timing->hblank_end >= GBE_CRS_MAGIC)
    600		SET_GBE_FIELD(CRS_START_XY, CRS_STARTX, val,
    601			      timing->hblank_end - GBE_CRS_MAGIC);
    602	else
    603		SET_GBE_FIELD(CRS_START_XY, CRS_STARTX, val,
    604			      timing->htotal - (GBE_CRS_MAGIC -
    605						timing->hblank_end));
    606	gbe->crs_start_xy = val;
    607
    608	val = 0;
    609	SET_GBE_FIELD(VC_START_XY, VC_STARTY, val, (u32) temp);
    610	SET_GBE_FIELD(VC_START_XY, VC_STARTX, val, timing->hblank_end - 4);
    611	gbe->vc_start_xy = val;
    612
    613	val = 0;
    614	temp = timing->hblank_end - GBE_PIXEN_MAGIC_ON;
    615	if (temp < 0)
    616		temp += timing->htotal;	/* allow blank to wrap around */
    617
    618	SET_GBE_FIELD(VT_HPIXEN, HPIXEN_ON, val, temp);
    619	SET_GBE_FIELD(VT_HPIXEN, HPIXEN_OFF, val,
    620		      ((temp + timing->width -
    621			GBE_PIXEN_MAGIC_OFF) % timing->htotal));
    622	gbe->vt_hpixen = val;
    623
    624	val = 0;
    625	SET_GBE_FIELD(VT_VPIXEN, VPIXEN_ON, val, timing->vblank_end);
    626	SET_GBE_FIELD(VT_VPIXEN, VPIXEN_OFF, val, timing->vblank_start);
    627	gbe->vt_vpixen = val;
    628
    629	/* turn off sync on green */
    630	val = 0;
    631	SET_GBE_FIELD(VT_FLAGS, SYNC_LOW, val, 1);
    632	gbe->vt_flags = val;
    633}
    634
    635/*
    636 *  Set the hardware according to 'par'.
    637 */
    638
    639static int gbefb_set_par(struct fb_info *info)
    640{
    641	int i;
    642	unsigned int val;
    643	int wholeTilesX, partTilesX, maxPixelsPerTileX;
    644	int height_pix;
    645	int xpmax, ypmax;	/* Monitor resolution */
    646	int bytesPerPixel;	/* Bytes per pixel */
    647	struct gbefb_par *par = (struct gbefb_par *) info->par;
    648
    649	compute_gbe_timing(&info->var, &par->timing);
    650
    651	bytesPerPixel = info->var.bits_per_pixel / 8;
    652	info->fix.line_length = info->var.xres_virtual * bytesPerPixel;
    653	xpmax = par->timing.width;
    654	ypmax = par->timing.height;
    655
    656	/* turn off GBE */
    657	gbe_turn_off();
    658
    659	/* set timing info */
    660	gbe_set_timing_info(&par->timing);
    661
    662	/* initialize DIDs */
    663	val = 0;
    664	switch (bytesPerPixel) {
    665	case 1:
    666		SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_I8);
    667		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
    668		break;
    669	case 2:
    670		SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_ARGB5);
    671		info->fix.visual = FB_VISUAL_TRUECOLOR;
    672		break;
    673	case 4:
    674		SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_RGB8);
    675		info->fix.visual = FB_VISUAL_TRUECOLOR;
    676		break;
    677	}
    678	SET_GBE_FIELD(WID, BUF, val, GBE_BMODE_BOTH);
    679
    680	for (i = 0; i < 32; i++)
    681		gbe->mode_regs[i] = val;
    682
    683	/* Initialize interrupts */
    684	gbe->vt_intr01 = 0xffffffff;
    685	gbe->vt_intr23 = 0xffffffff;
    686
    687	/* HACK:
    688	   The GBE hardware uses a tiled memory to screen mapping. Tiles are
    689	   blocks of 512x128, 256x128 or 128x128 pixels, respectively for 8bit,
    690	   16bit and 32 bit modes (64 kB). They cover the screen with partial
    691	   tiles on the right and/or bottom of the screen if needed.
    692	   For example in 640x480 8 bit mode the mapping is:
    693
    694	   <-------- 640 ----->
    695	   <---- 512 ----><128|384 offscreen>
    696	   ^  ^
    697	   | 128    [tile 0]        [tile 1]
    698	   |  v
    699	   ^
    700	   4 128    [tile 2]        [tile 3]
    701	   8  v
    702	   0  ^
    703	   128    [tile 4]        [tile 5]
    704	   |  v
    705	   |  ^
    706	   v  96    [tile 6]        [tile 7]
    707	   32 offscreen
    708
    709	   Tiles have the advantage that they can be allocated individually in
    710	   memory. However, this mapping is not linear at all, which is not
    711	   really convenient. In order to support linear addressing, the GBE
    712	   DMA hardware is fooled into thinking the screen is only one tile
    713	   large and but has a greater height, so that the DMA transfer covers
    714	   the same region.
    715	   Tiles are still allocated as independent chunks of 64KB of
    716	   continuous physical memory and remapped so that the kernel sees the
    717	   framebuffer as a continuous virtual memory. The GBE tile table is
    718	   set up so that each tile references one of these 64k blocks:
    719
    720	   GBE -> tile list    framebuffer           TLB   <------------ CPU
    721	          [ tile 0 ] -> [ 64KB ]  <- [ 16x 4KB page entries ]     ^
    722	             ...           ...              ...       linear virtual FB
    723	          [ tile n ] -> [ 64KB ]  <- [ 16x 4KB page entries ]     v
    724
    725
    726	   The GBE hardware is then told that the buffer is 512*tweaked_height,
    727	   with tweaked_height = real_width*real_height/pixels_per_tile.
    728	   Thus the GBE hardware will scan the first tile, filing the first 64k
    729	   covered region of the screen, and then will proceed to the next
    730	   tile, until the whole screen is covered.
    731
    732	   Here is what would happen at 640x480 8bit:
    733
    734	   normal tiling               linear
    735	   ^   11111111111111112222    11111111111111111111  ^
    736	   128 11111111111111112222    11111111111111111111 102 lines
    737	       11111111111111112222    11111111111111111111  v
    738	   V   11111111111111112222    11111111222222222222
    739	       33333333333333334444    22222222222222222222
    740	       33333333333333334444    22222222222222222222
    741	       <      512     >        <  256 >               102*640+256 = 64k
    742
    743	   NOTE: The only mode for which this is not working is 800x600 8bit,
    744	   as 800*600/512 = 937.5 which is not integer and thus causes
    745	   flickering.
    746	   I guess this is not so important as one can use 640x480 8bit or
    747	   800x600 16bit anyway.
    748	 */
    749
    750	/* Tell gbe about the tiles table location */
    751	/* tile_ptr -> [ tile 1 ] -> FB mem */
    752	/*             [ tile 2 ] -> FB mem */
    753	/*               ...                */
    754	val = 0;
    755	SET_GBE_FIELD(FRM_CONTROL, FRM_TILE_PTR, val, gbe_tiles.dma >> 9);
    756	SET_GBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, val, 0); /* do not start */
    757	SET_GBE_FIELD(FRM_CONTROL, FRM_LINEAR, val, 0);
    758	gbe->frm_control = val;
    759
    760	maxPixelsPerTileX = 512 / bytesPerPixel;
    761	wholeTilesX = 1;
    762	partTilesX = 0;
    763
    764	/* Initialize the framebuffer */
    765	val = 0;
    766	SET_GBE_FIELD(FRM_SIZE_TILE, FRM_WIDTH_TILE, val, wholeTilesX);
    767	SET_GBE_FIELD(FRM_SIZE_TILE, FRM_RHS, val, partTilesX);
    768
    769	switch (bytesPerPixel) {
    770	case 1:
    771		SET_GBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, val,
    772			      GBE_FRM_DEPTH_8);
    773		break;
    774	case 2:
    775		SET_GBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, val,
    776			      GBE_FRM_DEPTH_16);
    777		break;
    778	case 4:
    779		SET_GBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, val,
    780			      GBE_FRM_DEPTH_32);
    781		break;
    782	}
    783	gbe->frm_size_tile = val;
    784
    785	/* compute tweaked height */
    786	height_pix = xpmax * ypmax / maxPixelsPerTileX;
    787
    788	val = 0;
    789	SET_GBE_FIELD(FRM_SIZE_PIXEL, FB_HEIGHT_PIX, val, height_pix);
    790	gbe->frm_size_pixel = val;
    791
    792	/* turn off DID and overlay DMA */
    793	gbe->did_control = 0;
    794	gbe->ovr_width_tile = 0;
    795
    796	/* Turn off mouse cursor */
    797	gbe->crs_ctl = 0;
    798
    799	/* Turn on GBE */
    800	gbe_turn_on();
    801
    802	/* Initialize the gamma map */
    803	udelay(10);
    804	for (i = 0; i < 256; i++)
    805		gbe->gmap[i] = (i << 24) | (i << 16) | (i << 8);
    806
    807	/* Initialize the color map */
    808	for (i = 0; i < 256; i++)
    809		gbe_cmap[i] = (i << 8) | (i << 16) | (i << 24);
    810
    811	gbe_loadcmap();
    812
    813	return 0;
    814}
    815
    816static void gbefb_encode_fix(struct fb_fix_screeninfo *fix,
    817			     struct fb_var_screeninfo *var)
    818{
    819	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
    820	strcpy(fix->id, "SGI GBE");
    821	fix->smem_start = (unsigned long) gbe_mem;
    822	fix->smem_len = gbe_mem_size;
    823	fix->type = FB_TYPE_PACKED_PIXELS;
    824	fix->type_aux = 0;
    825	fix->accel = FB_ACCEL_NONE;
    826	switch (var->bits_per_pixel) {
    827	case 8:
    828		fix->visual = FB_VISUAL_PSEUDOCOLOR;
    829		break;
    830	default:
    831		fix->visual = FB_VISUAL_TRUECOLOR;
    832		break;
    833	}
    834	fix->ywrapstep = 0;
    835	fix->xpanstep = 0;
    836	fix->ypanstep = 0;
    837	fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
    838	fix->mmio_start = GBE_BASE;
    839	fix->mmio_len = sizeof(struct sgi_gbe);
    840}
    841
    842/*
    843 *  Set a single color register. The values supplied are already
    844 *  rounded down to the hardware's capabilities (according to the
    845 *  entries in the var structure). Return != 0 for invalid regno.
    846 */
    847
    848static int gbefb_setcolreg(unsigned regno, unsigned red, unsigned green,
    849			     unsigned blue, unsigned transp,
    850			     struct fb_info *info)
    851{
    852	int i;
    853
    854	if (regno > 255)
    855		return 1;
    856	red >>= 8;
    857	green >>= 8;
    858	blue >>= 8;
    859
    860	if (info->var.bits_per_pixel <= 8) {
    861		gbe_cmap[regno] = (red << 24) | (green << 16) | (blue << 8);
    862		if (gbe_turned_on) {
    863			/* wait for the color map FIFO to have a free entry */
    864			for (i = 0; i < 1000 && gbe->cm_fifo >= 63; i++)
    865				udelay(10);
    866			if (i == 1000) {
    867				printk(KERN_ERR "gbefb: cmap FIFO timeout\n");
    868				return 1;
    869			}
    870			gbe->cmap[regno] = gbe_cmap[regno];
    871		}
    872	} else if (regno < 16) {
    873		switch (info->var.bits_per_pixel) {
    874		case 15:
    875		case 16:
    876			red >>= 3;
    877			green >>= 3;
    878			blue >>= 3;
    879			pseudo_palette[regno] =
    880				(red << info->var.red.offset) |
    881				(green << info->var.green.offset) |
    882				(blue << info->var.blue.offset);
    883			break;
    884		case 32:
    885			pseudo_palette[regno] =
    886				(red << info->var.red.offset) |
    887				(green << info->var.green.offset) |
    888				(blue << info->var.blue.offset);
    889			break;
    890		}
    891	}
    892
    893	return 0;
    894}
    895
    896/*
    897 *  Check video mode validity, eventually modify var to best match.
    898 */
    899static int gbefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
    900{
    901	unsigned int line_length;
    902	struct gbe_timing_info timing;
    903	int ret;
    904
    905	/* Limit bpp to 8, 16, and 32 */
    906	if (var->bits_per_pixel <= 8)
    907		var->bits_per_pixel = 8;
    908	else if (var->bits_per_pixel <= 16)
    909		var->bits_per_pixel = 16;
    910	else if (var->bits_per_pixel <= 32)
    911		var->bits_per_pixel = 32;
    912	else
    913		return -EINVAL;
    914
    915	/* Check the mode can be mapped linearly with the tile table trick. */
    916	/* This requires width x height x bytes/pixel be a multiple of 512 */
    917	if ((var->xres * var->yres * var->bits_per_pixel) & 4095)
    918		return -EINVAL;
    919
    920	var->grayscale = 0;	/* No grayscale for now */
    921
    922	ret = compute_gbe_timing(var, &timing);
    923	var->pixclock = ret;
    924	if (ret < 0)
    925		return -EINVAL;
    926
    927	/* Adjust virtual resolution, if necessary */
    928	if (var->xres > var->xres_virtual || (!ywrap && !ypan))
    929		var->xres_virtual = var->xres;
    930	if (var->yres > var->yres_virtual || (!ywrap && !ypan))
    931		var->yres_virtual = var->yres;
    932
    933	if (var->vmode & FB_VMODE_CONUPDATE) {
    934		var->vmode |= FB_VMODE_YWRAP;
    935		var->xoffset = info->var.xoffset;
    936		var->yoffset = info->var.yoffset;
    937	}
    938
    939	/* No grayscale for now */
    940	var->grayscale = 0;
    941
    942	/* Memory limit */
    943	line_length = var->xres_virtual * var->bits_per_pixel / 8;
    944	if (line_length * var->yres_virtual > gbe_mem_size)
    945		return -ENOMEM;	/* Virtual resolution too high */
    946
    947	switch (var->bits_per_pixel) {
    948	case 8:
    949		var->red.offset = 0;
    950		var->red.length = 8;
    951		var->green.offset = 0;
    952		var->green.length = 8;
    953		var->blue.offset = 0;
    954		var->blue.length = 8;
    955		var->transp.offset = 0;
    956		var->transp.length = 0;
    957		break;
    958	case 16:		/* RGB 1555 */
    959		var->red.offset = 10;
    960		var->red.length = 5;
    961		var->green.offset = 5;
    962		var->green.length = 5;
    963		var->blue.offset = 0;
    964		var->blue.length = 5;
    965		var->transp.offset = 0;
    966		var->transp.length = 0;
    967		break;
    968	case 32:		/* RGB 8888 */
    969		var->red.offset = 24;
    970		var->red.length = 8;
    971		var->green.offset = 16;
    972		var->green.length = 8;
    973		var->blue.offset = 8;
    974		var->blue.length = 8;
    975		var->transp.offset = 0;
    976		var->transp.length = 8;
    977		break;
    978	}
    979	var->red.msb_right = 0;
    980	var->green.msb_right = 0;
    981	var->blue.msb_right = 0;
    982	var->transp.msb_right = 0;
    983
    984	var->left_margin = timing.htotal - timing.hsync_end;
    985	var->right_margin = timing.hsync_start - timing.width;
    986	var->upper_margin = timing.vtotal - timing.vsync_end;
    987	var->lower_margin = timing.vsync_start - timing.height;
    988	var->hsync_len = timing.hsync_end - timing.hsync_start;
    989	var->vsync_len = timing.vsync_end - timing.vsync_start;
    990
    991	return 0;
    992}
    993
    994static int gbefb_mmap(struct fb_info *info,
    995			struct vm_area_struct *vma)
    996{
    997	unsigned long size = vma->vm_end - vma->vm_start;
    998	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
    999	unsigned long addr;
   1000	unsigned long phys_addr, phys_size;
   1001	u16 *tile;
   1002
   1003	/* check range */
   1004	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
   1005		return -EINVAL;
   1006	if (size > gbe_mem_size)
   1007		return -EINVAL;
   1008	if (offset > gbe_mem_size - size)
   1009		return -EINVAL;
   1010
   1011	/* remap using the fastest write-through mode on architecture */
   1012	/* try not polluting the cache when possible */
   1013#ifdef CONFIG_MIPS
   1014	pgprot_val(vma->vm_page_prot) =
   1015		pgprot_fb(pgprot_val(vma->vm_page_prot));
   1016#endif
   1017	/* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
   1018
   1019	/* look for the starting tile */
   1020	tile = &gbe_tiles.cpu[offset >> TILE_SHIFT];
   1021	addr = vma->vm_start;
   1022	offset &= TILE_MASK;
   1023
   1024	/* remap each tile separately */
   1025	do {
   1026		phys_addr = (((unsigned long) (*tile)) << TILE_SHIFT) + offset;
   1027		if ((offset + size) < TILE_SIZE)
   1028			phys_size = size;
   1029		else
   1030			phys_size = TILE_SIZE - offset;
   1031
   1032		if (remap_pfn_range(vma, addr, phys_addr >> PAGE_SHIFT,
   1033						phys_size, vma->vm_page_prot))
   1034			return -EAGAIN;
   1035
   1036		offset = 0;
   1037		size -= phys_size;
   1038		addr += phys_size;
   1039		tile++;
   1040	} while (size);
   1041
   1042	return 0;
   1043}
   1044
   1045static const struct fb_ops gbefb_ops = {
   1046	.owner		= THIS_MODULE,
   1047	.fb_check_var	= gbefb_check_var,
   1048	.fb_set_par	= gbefb_set_par,
   1049	.fb_setcolreg	= gbefb_setcolreg,
   1050	.fb_mmap	= gbefb_mmap,
   1051	.fb_blank	= gbefb_blank,
   1052	.fb_fillrect	= cfb_fillrect,
   1053	.fb_copyarea	= cfb_copyarea,
   1054	.fb_imageblit	= cfb_imageblit,
   1055};
   1056
   1057/*
   1058 * sysfs
   1059 */
   1060
   1061static ssize_t gbefb_show_memsize(struct device *dev, struct device_attribute *attr, char *buf)
   1062{
   1063	return snprintf(buf, PAGE_SIZE, "%u\n", gbe_mem_size);
   1064}
   1065
   1066static DEVICE_ATTR(size, S_IRUGO, gbefb_show_memsize, NULL);
   1067
   1068static ssize_t gbefb_show_rev(struct device *device, struct device_attribute *attr, char *buf)
   1069{
   1070	return snprintf(buf, PAGE_SIZE, "%d\n", gbe_revision);
   1071}
   1072
   1073static DEVICE_ATTR(revision, S_IRUGO, gbefb_show_rev, NULL);
   1074
   1075static void gbefb_remove_sysfs(struct device *dev)
   1076{
   1077	device_remove_file(dev, &dev_attr_size);
   1078	device_remove_file(dev, &dev_attr_revision);
   1079}
   1080
   1081static void gbefb_create_sysfs(struct device *dev)
   1082{
   1083	device_create_file(dev, &dev_attr_size);
   1084	device_create_file(dev, &dev_attr_revision);
   1085}
   1086
   1087/*
   1088 * Initialization
   1089 */
   1090
   1091static int gbefb_setup(char *options)
   1092{
   1093	char *this_opt;
   1094
   1095	if (!options || !*options)
   1096		return 0;
   1097
   1098	while ((this_opt = strsep(&options, ",")) != NULL) {
   1099		if (!strncmp(this_opt, "monitor:", 8)) {
   1100			if (!strncmp(this_opt + 8, "crt", 3)) {
   1101				flat_panel_enabled = 0;
   1102				default_var = &default_var_CRT;
   1103				default_mode = &default_mode_CRT;
   1104			} else if (!strncmp(this_opt + 8, "1600sw", 6) ||
   1105				   !strncmp(this_opt + 8, "lcd", 3)) {
   1106				flat_panel_enabled = 1;
   1107				default_var = &default_var_LCD;
   1108				default_mode = &default_mode_LCD;
   1109			}
   1110		} else if (!strncmp(this_opt, "mem:", 4)) {
   1111			gbe_mem_size = memparse(this_opt + 4, &this_opt);
   1112			if (gbe_mem_size > CONFIG_FB_GBE_MEM * 1024 * 1024)
   1113				gbe_mem_size = CONFIG_FB_GBE_MEM * 1024 * 1024;
   1114			if (gbe_mem_size < TILE_SIZE)
   1115				gbe_mem_size = TILE_SIZE;
   1116		} else
   1117			mode_option = this_opt;
   1118	}
   1119	return 0;
   1120}
   1121
   1122static int gbefb_probe(struct platform_device *p_dev)
   1123{
   1124	int i, ret = 0;
   1125	struct fb_info *info;
   1126	struct gbefb_par *par;
   1127#ifndef MODULE
   1128	char *options = NULL;
   1129#endif
   1130
   1131	info = framebuffer_alloc(sizeof(struct gbefb_par), &p_dev->dev);
   1132	if (!info)
   1133		return -ENOMEM;
   1134
   1135#ifndef MODULE
   1136	if (fb_get_options("gbefb", &options)) {
   1137		ret = -ENODEV;
   1138		goto out_release_framebuffer;
   1139	}
   1140	gbefb_setup(options);
   1141#endif
   1142
   1143	if (!request_mem_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) {
   1144		printk(KERN_ERR "gbefb: couldn't reserve mmio region\n");
   1145		ret = -EBUSY;
   1146		goto out_release_framebuffer;
   1147	}
   1148
   1149	gbe = (struct sgi_gbe *) devm_ioremap(&p_dev->dev, GBE_BASE,
   1150					      sizeof(struct sgi_gbe));
   1151	if (!gbe) {
   1152		printk(KERN_ERR "gbefb: couldn't map mmio region\n");
   1153		ret = -ENXIO;
   1154		goto out_release_mem_region;
   1155	}
   1156	gbe_revision = gbe->ctrlstat & 15;
   1157
   1158	gbe_tiles.cpu = dmam_alloc_coherent(&p_dev->dev,
   1159				GBE_TLB_SIZE * sizeof(uint16_t),
   1160				&gbe_tiles.dma, GFP_KERNEL);
   1161	if (!gbe_tiles.cpu) {
   1162		printk(KERN_ERR "gbefb: couldn't allocate tiles table\n");
   1163		ret = -ENOMEM;
   1164		goto out_release_mem_region;
   1165	}
   1166
   1167	if (gbe_mem_phys) {
   1168		/* memory was allocated at boot time */
   1169		gbe_mem = devm_ioremap_wc(&p_dev->dev, gbe_mem_phys,
   1170					  gbe_mem_size);
   1171		if (!gbe_mem) {
   1172			printk(KERN_ERR "gbefb: couldn't map framebuffer\n");
   1173			ret = -ENOMEM;
   1174			goto out_release_mem_region;
   1175		}
   1176
   1177		gbe_dma_addr = 0;
   1178	} else {
   1179		/* try to allocate memory with the classical allocator
   1180		 * this has high chance to fail on low memory machines */
   1181		gbe_mem = dmam_alloc_attrs(&p_dev->dev, gbe_mem_size,
   1182				&gbe_dma_addr, GFP_KERNEL,
   1183				DMA_ATTR_WRITE_COMBINE);
   1184		if (!gbe_mem) {
   1185			printk(KERN_ERR "gbefb: couldn't allocate framebuffer memory\n");
   1186			ret = -ENOMEM;
   1187			goto out_release_mem_region;
   1188		}
   1189
   1190		gbe_mem_phys = (unsigned long) gbe_dma_addr;
   1191	}
   1192
   1193	par = info->par;
   1194	par->wc_cookie = arch_phys_wc_add(gbe_mem_phys, gbe_mem_size);
   1195
   1196	/* map framebuffer memory into tiles table */
   1197	for (i = 0; i < (gbe_mem_size >> TILE_SHIFT); i++)
   1198		gbe_tiles.cpu[i] = (gbe_mem_phys >> TILE_SHIFT) + i;
   1199
   1200	info->fbops = &gbefb_ops;
   1201	info->pseudo_palette = pseudo_palette;
   1202	info->flags = FBINFO_DEFAULT;
   1203	info->screen_base = gbe_mem;
   1204	fb_alloc_cmap(&info->cmap, 256, 0);
   1205
   1206	/* reset GBE */
   1207	gbe_reset();
   1208
   1209	/* turn on default video mode */
   1210	if (fb_find_mode(&par->var, info, mode_option, NULL, 0,
   1211			 default_mode, 8) == 0)
   1212		par->var = *default_var;
   1213	info->var = par->var;
   1214	gbefb_check_var(&par->var, info);
   1215	gbefb_encode_fix(&info->fix, &info->var);
   1216
   1217	if (register_framebuffer(info) < 0) {
   1218		printk(KERN_ERR "gbefb: couldn't register framebuffer\n");
   1219		ret = -ENXIO;
   1220		goto out_gbe_unmap;
   1221	}
   1222
   1223	platform_set_drvdata(p_dev, info);
   1224	gbefb_create_sysfs(&p_dev->dev);
   1225
   1226	fb_info(info, "%s rev %d @ 0x%08x using %dkB memory\n",
   1227		info->fix.id, gbe_revision, (unsigned)GBE_BASE,
   1228		gbe_mem_size >> 10);
   1229
   1230	return 0;
   1231
   1232out_gbe_unmap:
   1233	arch_phys_wc_del(par->wc_cookie);
   1234out_release_mem_region:
   1235	release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
   1236out_release_framebuffer:
   1237	framebuffer_release(info);
   1238
   1239	return ret;
   1240}
   1241
   1242static int gbefb_remove(struct platform_device* p_dev)
   1243{
   1244	struct fb_info *info = platform_get_drvdata(p_dev);
   1245	struct gbefb_par *par = info->par;
   1246
   1247	unregister_framebuffer(info);
   1248	gbe_turn_off();
   1249	arch_phys_wc_del(par->wc_cookie);
   1250	release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
   1251	gbefb_remove_sysfs(&p_dev->dev);
   1252	framebuffer_release(info);
   1253
   1254	return 0;
   1255}
   1256
   1257static struct platform_driver gbefb_driver = {
   1258	.probe = gbefb_probe,
   1259	.remove = gbefb_remove,
   1260	.driver	= {
   1261		.name = "gbefb",
   1262	},
   1263};
   1264
   1265static struct platform_device *gbefb_device;
   1266
   1267static int __init gbefb_init(void)
   1268{
   1269	int ret = platform_driver_register(&gbefb_driver);
   1270	if (IS_ENABLED(CONFIG_SGI_IP32) && !ret) {
   1271		gbefb_device = platform_device_alloc("gbefb", 0);
   1272		if (gbefb_device) {
   1273			ret = platform_device_add(gbefb_device);
   1274		} else {
   1275			ret = -ENOMEM;
   1276		}
   1277		if (ret) {
   1278			platform_device_put(gbefb_device);
   1279			platform_driver_unregister(&gbefb_driver);
   1280		}
   1281	}
   1282	return ret;
   1283}
   1284
   1285static void __exit gbefb_exit(void)
   1286{
   1287	platform_device_unregister(gbefb_device);
   1288	platform_driver_unregister(&gbefb_driver);
   1289}
   1290
   1291module_init(gbefb_init);
   1292module_exit(gbefb_exit);
   1293
   1294MODULE_LICENSE("GPL");