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