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