xref: /openbmc/linux/drivers/video/fbdev/gbefb.c (revision 2a598d0b)
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 
33 static struct sgi_gbe *gbe;
34 
35 struct 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 
65 static unsigned int gbe_mem_size = CONFIG_FB_GBE_MEM * 1024*1024;
66 static void *gbe_mem;
67 static dma_addr_t gbe_dma_addr;
68 static unsigned long gbe_mem_phys;
69 
70 static struct {
71 	uint16_t *cpu;
72 	dma_addr_t dma;
73 } gbe_tiles;
74 
75 static int gbe_revision;
76 
77 static int ypan, ywrap;
78 
79 static uint32_t pseudo_palette[16];
80 static uint32_t gbe_cmap[256];
81 static int gbe_turned_on; /* 0 turned off, 1 turned on */
82 
83 static char *mode_option = NULL;
84 
85 /* default CRT mode */
86 static 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 */
117 static 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) */
149 static 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 */
164 static 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 
178 static struct fb_videomode *default_mode = &default_mode_CRT;
179 static struct fb_var_screeninfo *default_var = &default_var_CRT;
180 
181 static int flat_panel_enabled = 0;
182 
183 static 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 
198 static 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 
308 static 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 
370 static 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  */
387 static 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  */
410 static 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 
443 struct gbe_pll_info {
444 	int clock_rate;
445 	int fvco_min;
446 	int fvco_max;
447 };
448 
449 static struct gbe_pll_info gbe_pll_table[2] = {
450 	{ 20, 80, 220 },
451 	{ 27, 80, 220 },
452 };
453 
454 static 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 
530 static 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 
639 static 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 
816 static 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 
848 static 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  */
899 static 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 
994 static 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 
1045 static 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 
1061 static ssize_t gbefb_show_memsize(struct device *dev, struct device_attribute *attr, char *buf)
1062 {
1063 	return sysfs_emit(buf, "%u\n", gbe_mem_size);
1064 }
1065 
1066 static DEVICE_ATTR(size, S_IRUGO, gbefb_show_memsize, NULL);
1067 
1068 static ssize_t gbefb_show_rev(struct device *device, struct device_attribute *attr, char *buf)
1069 {
1070 	return sysfs_emit(buf, "%d\n", gbe_revision);
1071 }
1072 
1073 static DEVICE_ATTR(revision, S_IRUGO, gbefb_show_rev, NULL);
1074 
1075 static struct attribute *gbefb_attrs[] = {
1076 	&dev_attr_size.attr,
1077 	&dev_attr_revision.attr,
1078 	NULL,
1079 };
1080 ATTRIBUTE_GROUPS(gbefb);
1081 
1082 /*
1083  * Initialization
1084  */
1085 
1086 static int gbefb_setup(char *options)
1087 {
1088 	char *this_opt;
1089 
1090 	if (!options || !*options)
1091 		return 0;
1092 
1093 	while ((this_opt = strsep(&options, ",")) != NULL) {
1094 		if (!strncmp(this_opt, "monitor:", 8)) {
1095 			if (!strncmp(this_opt + 8, "crt", 3)) {
1096 				flat_panel_enabled = 0;
1097 				default_var = &default_var_CRT;
1098 				default_mode = &default_mode_CRT;
1099 			} else if (!strncmp(this_opt + 8, "1600sw", 6) ||
1100 				   !strncmp(this_opt + 8, "lcd", 3)) {
1101 				flat_panel_enabled = 1;
1102 				default_var = &default_var_LCD;
1103 				default_mode = &default_mode_LCD;
1104 			}
1105 		} else if (!strncmp(this_opt, "mem:", 4)) {
1106 			gbe_mem_size = memparse(this_opt + 4, &this_opt);
1107 			if (gbe_mem_size > CONFIG_FB_GBE_MEM * 1024 * 1024)
1108 				gbe_mem_size = CONFIG_FB_GBE_MEM * 1024 * 1024;
1109 			if (gbe_mem_size < TILE_SIZE)
1110 				gbe_mem_size = TILE_SIZE;
1111 		} else
1112 			mode_option = this_opt;
1113 	}
1114 	return 0;
1115 }
1116 
1117 static int gbefb_probe(struct platform_device *p_dev)
1118 {
1119 	int i, ret = 0;
1120 	struct fb_info *info;
1121 	struct gbefb_par *par;
1122 #ifndef MODULE
1123 	char *options = NULL;
1124 #endif
1125 
1126 	info = framebuffer_alloc(sizeof(struct gbefb_par), &p_dev->dev);
1127 	if (!info)
1128 		return -ENOMEM;
1129 
1130 #ifndef MODULE
1131 	if (fb_get_options("gbefb", &options)) {
1132 		ret = -ENODEV;
1133 		goto out_release_framebuffer;
1134 	}
1135 	gbefb_setup(options);
1136 #endif
1137 
1138 	if (!request_mem_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) {
1139 		printk(KERN_ERR "gbefb: couldn't reserve mmio region\n");
1140 		ret = -EBUSY;
1141 		goto out_release_framebuffer;
1142 	}
1143 
1144 	gbe = (struct sgi_gbe *) devm_ioremap(&p_dev->dev, GBE_BASE,
1145 					      sizeof(struct sgi_gbe));
1146 	if (!gbe) {
1147 		printk(KERN_ERR "gbefb: couldn't map mmio region\n");
1148 		ret = -ENXIO;
1149 		goto out_release_mem_region;
1150 	}
1151 	gbe_revision = gbe->ctrlstat & 15;
1152 
1153 	gbe_tiles.cpu = dmam_alloc_coherent(&p_dev->dev,
1154 				GBE_TLB_SIZE * sizeof(uint16_t),
1155 				&gbe_tiles.dma, GFP_KERNEL);
1156 	if (!gbe_tiles.cpu) {
1157 		printk(KERN_ERR "gbefb: couldn't allocate tiles table\n");
1158 		ret = -ENOMEM;
1159 		goto out_release_mem_region;
1160 	}
1161 
1162 	if (gbe_mem_phys) {
1163 		/* memory was allocated at boot time */
1164 		gbe_mem = devm_ioremap_wc(&p_dev->dev, gbe_mem_phys,
1165 					  gbe_mem_size);
1166 		if (!gbe_mem) {
1167 			printk(KERN_ERR "gbefb: couldn't map framebuffer\n");
1168 			ret = -ENOMEM;
1169 			goto out_release_mem_region;
1170 		}
1171 
1172 		gbe_dma_addr = 0;
1173 	} else {
1174 		/* try to allocate memory with the classical allocator
1175 		 * this has high chance to fail on low memory machines */
1176 		gbe_mem = dmam_alloc_attrs(&p_dev->dev, gbe_mem_size,
1177 				&gbe_dma_addr, GFP_KERNEL,
1178 				DMA_ATTR_WRITE_COMBINE);
1179 		if (!gbe_mem) {
1180 			printk(KERN_ERR "gbefb: couldn't allocate framebuffer memory\n");
1181 			ret = -ENOMEM;
1182 			goto out_release_mem_region;
1183 		}
1184 
1185 		gbe_mem_phys = (unsigned long) gbe_dma_addr;
1186 	}
1187 
1188 	par = info->par;
1189 	par->wc_cookie = arch_phys_wc_add(gbe_mem_phys, gbe_mem_size);
1190 
1191 	/* map framebuffer memory into tiles table */
1192 	for (i = 0; i < (gbe_mem_size >> TILE_SHIFT); i++)
1193 		gbe_tiles.cpu[i] = (gbe_mem_phys >> TILE_SHIFT) + i;
1194 
1195 	info->fbops = &gbefb_ops;
1196 	info->pseudo_palette = pseudo_palette;
1197 	info->flags = FBINFO_DEFAULT;
1198 	info->screen_base = gbe_mem;
1199 	fb_alloc_cmap(&info->cmap, 256, 0);
1200 
1201 	/* reset GBE */
1202 	gbe_reset();
1203 
1204 	/* turn on default video mode */
1205 	if (fb_find_mode(&par->var, info, mode_option, NULL, 0,
1206 			 default_mode, 8) == 0)
1207 		par->var = *default_var;
1208 	info->var = par->var;
1209 	gbefb_check_var(&par->var, info);
1210 	gbefb_encode_fix(&info->fix, &info->var);
1211 
1212 	if (register_framebuffer(info) < 0) {
1213 		printk(KERN_ERR "gbefb: couldn't register framebuffer\n");
1214 		ret = -ENXIO;
1215 		goto out_gbe_unmap;
1216 	}
1217 
1218 	platform_set_drvdata(p_dev, info);
1219 
1220 	fb_info(info, "%s rev %d @ 0x%08x using %dkB memory\n",
1221 		info->fix.id, gbe_revision, (unsigned)GBE_BASE,
1222 		gbe_mem_size >> 10);
1223 
1224 	return 0;
1225 
1226 out_gbe_unmap:
1227 	arch_phys_wc_del(par->wc_cookie);
1228 out_release_mem_region:
1229 	release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
1230 out_release_framebuffer:
1231 	framebuffer_release(info);
1232 
1233 	return ret;
1234 }
1235 
1236 static void gbefb_remove(struct platform_device* p_dev)
1237 {
1238 	struct fb_info *info = platform_get_drvdata(p_dev);
1239 	struct gbefb_par *par = info->par;
1240 
1241 	unregister_framebuffer(info);
1242 	gbe_turn_off();
1243 	arch_phys_wc_del(par->wc_cookie);
1244 	release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
1245 	framebuffer_release(info);
1246 }
1247 
1248 static struct platform_driver gbefb_driver = {
1249 	.probe = gbefb_probe,
1250 	.remove_new = gbefb_remove,
1251 	.driver	= {
1252 		.name = "gbefb",
1253 		.dev_groups	= gbefb_groups,
1254 	},
1255 };
1256 
1257 static struct platform_device *gbefb_device;
1258 
1259 static int __init gbefb_init(void)
1260 {
1261 	int ret = platform_driver_register(&gbefb_driver);
1262 	if (IS_ENABLED(CONFIG_SGI_IP32) && !ret) {
1263 		gbefb_device = platform_device_alloc("gbefb", 0);
1264 		if (gbefb_device) {
1265 			ret = platform_device_add(gbefb_device);
1266 		} else {
1267 			ret = -ENOMEM;
1268 		}
1269 		if (ret) {
1270 			platform_device_put(gbefb_device);
1271 			platform_driver_unregister(&gbefb_driver);
1272 		}
1273 	}
1274 	return ret;
1275 }
1276 
1277 static void __exit gbefb_exit(void)
1278 {
1279 	platform_device_unregister(gbefb_device);
1280 	platform_driver_unregister(&gbefb_driver);
1281 }
1282 
1283 module_init(gbefb_init);
1284 module_exit(gbefb_exit);
1285 
1286 MODULE_LICENSE("GPL");
1287