MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / video / gbefb.c
blob1dfc1d65c59b1f24f78b82d7441b6dcdef5e4306
1 /*
2 * SGI GBE frame buffer driver
4 * Copyright (C) 1999 Silicon Graphics, Inc. - Jeffrey Newquist
5 * Copyright (C) 2002 Vivien Chappelier <vivien.chappelier@linux-mips.org>
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.
12 #include <linux/config.h>
13 #include <linux/delay.h>
14 #include <linux/device.h>
15 #include <linux/dma-mapping.h>
16 #include <linux/errno.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>
24 #ifdef CONFIG_X86
25 #include <asm/mtrr.h>
26 #endif
27 #ifdef CONFIG_MIPS
28 #include <asm/addrspace.h>
29 #endif
30 #include <asm/byteorder.h>
31 #include <asm/io.h>
32 #include <asm/tlbflush.h>
34 #include <video/gbe.h>
36 static struct sgi_gbe *gbe;
38 struct gbefb_par {
39 struct fb_var_screeninfo var;
40 struct gbe_timing_info timing;
41 int valid;
44 #ifdef CONFIG_SGI_IP32
45 #define GBE_BASE 0x16000000 /* SGI O2 */
46 #endif
48 #ifdef CONFIG_X86_VISWS
49 #define GBE_BASE 0xd0000000 /* SGI Visual Workstation */
50 #endif
52 /* macro for fastest write-though access to the framebuffer */
53 #ifdef CONFIG_MIPS
54 #ifdef CONFIG_CPU_R10000
55 #define pgprot_fb(_prot) (((_prot) & (~_CACHE_MASK)) | _CACHE_UNCACHED_ACCELERATED)
56 #else
57 #define pgprot_fb(_prot) (((_prot) & (~_CACHE_MASK)) | _CACHE_CACHABLE_NO_WA)
58 #endif
59 #endif
60 #ifdef CONFIG_X86
61 #define pgprot_fb(_prot) ((_prot) | _PAGE_PCD)
62 #endif
65 * RAM we reserve for the frame buffer. This defines the maximum screen
66 * size
68 #if CONFIG_FB_GBE_MEM > 8
69 #error GBE Framebuffer cannot use more than 8MB of memory
70 #endif
72 #define TILE_SHIFT 16
73 #define TILE_SIZE (1 << TILE_SHIFT)
74 #define TILE_MASK (TILE_SIZE - 1)
76 static unsigned int gbe_mem_size = CONFIG_FB_GBE_MEM * 1024*1024;
77 static void *gbe_mem;
78 static dma_addr_t gbe_dma_addr;
79 unsigned long gbe_mem_phys;
81 static struct {
82 uint16_t *cpu;
83 dma_addr_t dma;
84 } gbe_tiles;
86 static int gbe_revision;
88 static struct fb_info fb_info;
89 static int ypan, ywrap;
91 static uint32_t pseudo_palette[256];
93 static char *mode_option __initdata = NULL;
95 /* default CRT mode */
96 static struct fb_var_screeninfo default_var_CRT __initdata = {
97 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
98 .xres = 640,
99 .yres = 480,
100 .xres_virtual = 640,
101 .yres_virtual = 480,
102 .xoffset = 0,
103 .yoffset = 0,
104 .bits_per_pixel = 8,
105 .grayscale = 0,
106 .red = { 0, 8, 0 },
107 .green = { 0, 8, 0 },
108 .blue = { 0, 8, 0 },
109 .transp = { 0, 0, 0 },
110 .nonstd = 0,
111 .activate = 0,
112 .height = -1,
113 .width = -1,
114 .accel_flags = 0,
115 .pixclock = 39722, /* picoseconds */
116 .left_margin = 48,
117 .right_margin = 16,
118 .upper_margin = 33,
119 .lower_margin = 10,
120 .hsync_len = 96,
121 .vsync_len = 2,
122 .sync = 0,
123 .vmode = FB_VMODE_NONINTERLACED,
126 /* default LCD mode */
127 static struct fb_var_screeninfo default_var_LCD __initdata = {
128 /* 1600x1024, 8 bpp */
129 .xres = 1600,
130 .yres = 1024,
131 .xres_virtual = 1600,
132 .yres_virtual = 1024,
133 .xoffset = 0,
134 .yoffset = 0,
135 .bits_per_pixel = 8,
136 .grayscale = 0,
137 .red = { 0, 8, 0 },
138 .green = { 0, 8, 0 },
139 .blue = { 0, 8, 0 },
140 .transp = { 0, 0, 0 },
141 .nonstd = 0,
142 .activate = 0,
143 .height = -1,
144 .width = -1,
145 .accel_flags = 0,
146 .pixclock = 9353,
147 .left_margin = 20,
148 .right_margin = 30,
149 .upper_margin = 37,
150 .lower_margin = 3,
151 .hsync_len = 20,
152 .vsync_len = 3,
153 .sync = 0,
154 .vmode = FB_VMODE_NONINTERLACED
157 /* default modedb mode */
158 /* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
159 static struct fb_videomode default_mode_CRT __initdata = {
160 .refresh = 60,
161 .xres = 640,
162 .yres = 480,
163 .pixclock = 39722,
164 .left_margin = 48,
165 .right_margin = 16,
166 .upper_margin = 33,
167 .lower_margin = 10,
168 .hsync_len = 96,
169 .vsync_len = 2,
170 .sync = 0,
171 .vmode = FB_VMODE_NONINTERLACED,
173 /* 1600x1024 SGI flatpanel 1600sw */
174 static struct fb_videomode default_mode_LCD __initdata = {
175 /* 1600x1024, 8 bpp */
176 .xres = 1600,
177 .yres = 1024,
178 .pixclock = 9353,
179 .left_margin = 20,
180 .right_margin = 30,
181 .upper_margin = 37,
182 .lower_margin = 3,
183 .hsync_len = 20,
184 .vsync_len = 3,
185 .vmode = FB_VMODE_NONINTERLACED,
188 struct fb_videomode *default_mode = &default_mode_CRT;
189 struct fb_var_screeninfo *default_var = &default_var_CRT;
191 static int flat_panel_enabled = 0;
193 static struct gbefb_par par_current;
195 static void gbe_reset(void)
197 /* Turn on dotclock PLL */
198 gbe->ctrlstat = 0x300aa000;
203 * Function: gbe_turn_off
204 * Parameters: (None)
205 * Description: This should turn off the monitor and gbe. This is used
206 * when switching between the serial console and the graphics
207 * console.
210 void gbe_turn_off(void)
212 int i;
213 unsigned int val, x, y, vpixen_off;
215 /* check if pixel counter is on */
216 val = gbe->vt_xy;
217 if (GET_GBE_FIELD(VT_XY, FREEZE, val) == 1)
218 return;
220 /* turn off DMA */
221 val = gbe->ovr_control;
222 SET_GBE_FIELD(OVR_CONTROL, OVR_DMA_ENABLE, val, 0);
223 gbe->ovr_control = val;
224 udelay(1000);
225 val = gbe->frm_control;
226 SET_GBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, val, 0);
227 gbe->frm_control = val;
228 udelay(1000);
229 val = gbe->did_control;
230 SET_GBE_FIELD(DID_CONTROL, DID_DMA_ENABLE, val, 0);
231 gbe->did_control = val;
232 udelay(1000);
234 /* We have to wait through two vertical retrace periods before
235 * the pixel DMA is turned off for sure. */
236 for (i = 0; i < 10000; i++) {
237 val = gbe->frm_inhwctrl;
238 if (GET_GBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, val)) {
239 udelay(10);
240 } else {
241 val = gbe->ovr_inhwctrl;
242 if (GET_GBE_FIELD(OVR_INHWCTRL, OVR_DMA_ENABLE, val)) {
243 udelay(10);
244 } else {
245 val = gbe->did_inhwctrl;
246 if (GET_GBE_FIELD(DID_INHWCTRL, DID_DMA_ENABLE, val)) {
247 udelay(10);
248 } else
249 break;
253 if (i == 10000)
254 printk(KERN_ERR "gbefb: turn off DMA timed out\n");
256 /* wait for vpixen_off */
257 val = gbe->vt_vpixen;
258 vpixen_off = GET_GBE_FIELD(VT_VPIXEN, VPIXEN_OFF, val);
260 for (i = 0; i < 100000; i++) {
261 val = gbe->vt_xy;
262 x = GET_GBE_FIELD(VT_XY, X, val);
263 y = GET_GBE_FIELD(VT_XY, Y, val);
264 if (y < vpixen_off)
265 break;
266 udelay(1);
268 if (i == 100000)
269 printk(KERN_ERR
270 "gbefb: wait for vpixen_off timed out\n");
271 for (i = 0; i < 10000; i++) {
272 val = gbe->vt_xy;
273 x = GET_GBE_FIELD(VT_XY, X, val);
274 y = GET_GBE_FIELD(VT_XY, Y, val);
275 if (y > vpixen_off)
276 break;
277 udelay(1);
279 if (i == 10000)
280 printk(KERN_ERR "gbefb: wait for vpixen_off timed out\n");
282 /* turn off pixel counter */
283 val = 0;
284 SET_GBE_FIELD(VT_XY, FREEZE, val, 1);
285 gbe->vt_xy = val;
286 udelay(10000);
287 for (i = 0; i < 10000; i++) {
288 val = gbe->vt_xy;
289 if (GET_GBE_FIELD(VT_XY, FREEZE, val) != 1)
290 udelay(10);
291 else
292 break;
294 if (i == 10000)
295 printk(KERN_ERR "gbefb: turn off pixel clock timed out\n");
297 /* turn off dot clock */
298 val = gbe->dotclock;
299 SET_GBE_FIELD(DOTCLK, RUN, val, 0);
300 gbe->dotclock = val;
301 udelay(10000);
302 for (i = 0; i < 10000; i++) {
303 val = gbe->dotclock;
304 if (GET_GBE_FIELD(DOTCLK, RUN, val))
305 udelay(10);
306 else
307 break;
309 if (i == 10000)
310 printk(KERN_ERR "gbefb: turn off dotclock timed out\n");
312 /* reset the frame DMA FIFO */
313 val = gbe->frm_size_tile;
314 SET_GBE_FIELD(FRM_SIZE_TILE, FRM_FIFO_RESET, val, 1);
315 gbe->frm_size_tile = val;
316 SET_GBE_FIELD(FRM_SIZE_TILE, FRM_FIFO_RESET, val, 0);
317 gbe->frm_size_tile = val;
320 static void gbe_turn_on(void)
322 unsigned int val, i;
325 * Check if pixel counter is off, for unknown reason this
326 * code hangs Visual Workstations
328 if (gbe_revision < 2) {
329 val = gbe->vt_xy;
330 if (GET_GBE_FIELD(VT_XY, FREEZE, val) == 0)
331 return;
334 /* turn on dot clock */
335 val = gbe->dotclock;
336 SET_GBE_FIELD(DOTCLK, RUN, val, 1);
337 gbe->dotclock = val;
338 udelay(10000);
339 for (i = 0; i < 10000; i++) {
340 val = gbe->dotclock;
341 if (GET_GBE_FIELD(DOTCLK, RUN, val) != 1)
342 udelay(10);
343 else
344 break;
346 if (i == 10000)
347 printk(KERN_ERR "gbefb: turn on dotclock timed out\n");
349 /* turn on pixel counter */
350 val = 0;
351 SET_GBE_FIELD(VT_XY, FREEZE, val, 0);
352 gbe->vt_xy = val;
353 udelay(10000);
354 for (i = 0; i < 10000; i++) {
355 val = gbe->vt_xy;
356 if (GET_GBE_FIELD(VT_XY, FREEZE, val))
357 udelay(10);
358 else
359 break;
361 if (i == 10000)
362 printk(KERN_ERR "gbefb: turn on pixel clock timed out\n");
364 /* turn on DMA */
365 val = gbe->frm_control;
366 SET_GBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, val, 1);
367 gbe->frm_control = val;
368 udelay(1000);
369 for (i = 0; i < 10000; i++) {
370 val = gbe->frm_inhwctrl;
371 if (GET_GBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, val) != 1)
372 udelay(10);
373 else
374 break;
376 if (i == 10000)
377 printk(KERN_ERR "gbefb: turn on DMA timed out\n");
381 * Blank the display.
383 static int gbefb_blank(int blank, struct fb_info *info)
385 /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
386 switch (blank) {
387 case 0: /* unblank */
388 gbe_turn_on();
389 break;
391 case 1: /* blank */
392 gbe_turn_off();
393 break;
395 default:
396 /* Nothing */
397 break;
399 return 0;
403 * Setup flatpanel related registers.
405 static void gbefb_setup_flatpanel(struct gbe_timing_info *timing)
407 int fp_wid, fp_hgt, fp_vbs, fp_vbe;
408 u32 outputVal = 0;
410 SET_GBE_FIELD(VT_FLAGS, HDRV_INVERT, outputVal,
411 (timing->flags & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1);
412 SET_GBE_FIELD(VT_FLAGS, VDRV_INVERT, outputVal,
413 (timing->flags & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1);
414 gbe->vt_flags = outputVal;
416 /* Turn on the flat panel */
417 fp_wid = 1600;
418 fp_hgt = 1024;
419 fp_vbs = 0;
420 fp_vbe = 1600;
421 timing->pll_m = 4;
422 timing->pll_n = 1;
423 timing->pll_p = 0;
425 outputVal = 0;
426 SET_GBE_FIELD(FP_DE, ON, outputVal, fp_vbs);
427 SET_GBE_FIELD(FP_DE, OFF, outputVal, fp_vbe);
428 gbe->fp_de = outputVal;
429 outputVal = 0;
430 SET_GBE_FIELD(FP_HDRV, OFF, outputVal, fp_wid);
431 gbe->fp_hdrv = outputVal;
432 outputVal = 0;
433 SET_GBE_FIELD(FP_VDRV, ON, outputVal, 1);
434 SET_GBE_FIELD(FP_VDRV, OFF, outputVal, fp_hgt + 1);
435 gbe->fp_vdrv = outputVal;
438 struct gbe_pll_info {
439 int clock_rate;
440 int fvco_min;
441 int fvco_max;
444 static struct gbe_pll_info gbe_pll_table[2] = {
445 { 20, 80, 220 },
446 { 27, 80, 220 },
449 static int compute_gbe_timing(struct fb_var_screeninfo *var,
450 struct gbe_timing_info *timing)
452 int pll_m, pll_n, pll_p, error, best_m, best_n, best_p, best_error;
453 int pixclock;
454 struct gbe_pll_info *gbe_pll;
456 if (gbe_revision < 2)
457 gbe_pll = &gbe_pll_table[0];
458 else
459 gbe_pll = &gbe_pll_table[1];
461 /* Determine valid resolution and timing
462 * GBE crystal runs at 20Mhz or 27Mhz
463 * pll_m, pll_n, pll_p define the following frequencies
464 * fvco = pll_m * 20Mhz / pll_n
465 * fout = fvco / (2**pll_p) */
466 best_error = 1000000000;
467 best_n = best_m = best_p = 0;
468 for (pll_p = 0; pll_p < 4; pll_p++)
469 for (pll_m = 1; pll_m < 256; pll_m++)
470 for (pll_n = 1; pll_n < 64; pll_n++) {
471 pixclock = (1000000 / gbe_pll->clock_rate) *
472 (pll_n << pll_p) / pll_m;
474 error = var->pixclock - pixclock;
476 if (error < 0)
477 error = -error;
479 if (error < best_error &&
480 pll_m / pll_n >
481 gbe_pll->fvco_min / gbe_pll->clock_rate &&
482 pll_m / pll_n <
483 gbe_pll->fvco_max / gbe_pll->clock_rate) {
484 best_error = error;
485 best_m = pll_m;
486 best_n = pll_n;
487 best_p = pll_p;
491 if (!best_n || !best_m)
492 return -EINVAL; /* Resolution to high */
494 pixclock = (1000000 / gbe_pll->clock_rate) *
495 (best_n << best_p) / best_m;
497 /* set video timing information */
498 if (timing) {
499 timing->width = var->xres;
500 timing->height = var->yres;
501 timing->pll_m = best_m;
502 timing->pll_n = best_n;
503 timing->pll_p = best_p;
504 timing->cfreq = gbe_pll->clock_rate * 1000 * timing->pll_m /
505 (timing->pll_n << timing->pll_p);
506 timing->htotal = var->left_margin + var->xres +
507 var->right_margin + var->hsync_len;
508 timing->vtotal = var->upper_margin + var->yres +
509 var->lower_margin + var->vsync_len;
510 timing->fields_sec = 1000 * timing->cfreq / timing->htotal *
511 1000 / timing->vtotal;
512 timing->hblank_start = var->xres;
513 timing->vblank_start = var->yres;
514 timing->hblank_end = timing->htotal;
515 timing->hsync_start = var->xres + var->right_margin + 1;
516 timing->hsync_end = timing->hsync_start + var->hsync_len;
517 timing->vblank_end = timing->vtotal;
518 timing->vsync_start = var->yres + var->lower_margin + 1;
519 timing->vsync_end = timing->vsync_start + var->vsync_len;
522 return pixclock;
525 static void gbe_set_timing_info(struct gbe_timing_info *timing)
527 int temp;
528 unsigned int val;
530 /* setup dot clock PLL */
531 val = 0;
532 SET_GBE_FIELD(DOTCLK, M, val, timing->pll_m - 1);
533 SET_GBE_FIELD(DOTCLK, N, val, timing->pll_n - 1);
534 SET_GBE_FIELD(DOTCLK, P, val, timing->pll_p);
535 SET_GBE_FIELD(DOTCLK, RUN, val, 0); /* do not start yet */
536 gbe->dotclock = val;
537 udelay(10000);
539 /* setup pixel counter */
540 val = 0;
541 SET_GBE_FIELD(VT_XYMAX, MAXX, val, timing->htotal);
542 SET_GBE_FIELD(VT_XYMAX, MAXY, val, timing->vtotal);
543 gbe->vt_xymax = val;
545 /* setup video timing signals */
546 val = 0;
547 SET_GBE_FIELD(VT_VSYNC, VSYNC_ON, val, timing->vsync_start);
548 SET_GBE_FIELD(VT_VSYNC, VSYNC_OFF, val, timing->vsync_end);
549 gbe->vt_vsync = val;
550 val = 0;
551 SET_GBE_FIELD(VT_HSYNC, HSYNC_ON, val, timing->hsync_start);
552 SET_GBE_FIELD(VT_HSYNC, HSYNC_OFF, val, timing->hsync_end);
553 gbe->vt_hsync = val;
554 val = 0;
555 SET_GBE_FIELD(VT_VBLANK, VBLANK_ON, val, timing->vblank_start);
556 SET_GBE_FIELD(VT_VBLANK, VBLANK_OFF, val, timing->vblank_end);
557 gbe->vt_vblank = val;
558 val = 0;
559 SET_GBE_FIELD(VT_HBLANK, HBLANK_ON, val,
560 timing->hblank_start - 5);
561 SET_GBE_FIELD(VT_HBLANK, HBLANK_OFF, val,
562 timing->hblank_end - 3);
563 gbe->vt_hblank = val;
565 /* setup internal timing signals */
566 val = 0;
567 SET_GBE_FIELD(VT_VCMAP, VCMAP_ON, val, timing->vblank_start);
568 SET_GBE_FIELD(VT_VCMAP, VCMAP_OFF, val, timing->vblank_end);
569 gbe->vt_vcmap = val;
570 val = 0;
571 SET_GBE_FIELD(VT_HCMAP, HCMAP_ON, val, timing->hblank_start);
572 SET_GBE_FIELD(VT_HCMAP, HCMAP_OFF, val, timing->hblank_end);
573 gbe->vt_hcmap = val;
575 val = 0;
576 temp = timing->vblank_start - timing->vblank_end - 1;
577 if (temp > 0)
578 temp = -temp;
580 if (flat_panel_enabled)
581 gbefb_setup_flatpanel(timing);
583 SET_GBE_FIELD(DID_START_XY, DID_STARTY, val, (u32) temp);
584 if (timing->hblank_end >= 20)
585 SET_GBE_FIELD(DID_START_XY, DID_STARTX, val,
586 timing->hblank_end - 20);
587 else
588 SET_GBE_FIELD(DID_START_XY, DID_STARTX, val,
589 timing->htotal - (20 - timing->hblank_end));
590 gbe->did_start_xy = val;
592 val = 0;
593 SET_GBE_FIELD(CRS_START_XY, CRS_STARTY, val, (u32) (temp + 1));
594 if (timing->hblank_end >= GBE_CRS_MAGIC)
595 SET_GBE_FIELD(CRS_START_XY, CRS_STARTX, val,
596 timing->hblank_end - GBE_CRS_MAGIC);
597 else
598 SET_GBE_FIELD(CRS_START_XY, CRS_STARTX, val,
599 timing->htotal - (GBE_CRS_MAGIC -
600 timing->hblank_end));
601 gbe->crs_start_xy = val;
603 val = 0;
604 SET_GBE_FIELD(VC_START_XY, VC_STARTY, val, (u32) temp);
605 SET_GBE_FIELD(VC_START_XY, VC_STARTX, val, timing->hblank_end - 4);
606 gbe->vc_start_xy = val;
608 val = 0;
609 temp = timing->hblank_end - GBE_PIXEN_MAGIC_ON;
610 if (temp < 0)
611 temp += timing->htotal; /* allow blank to wrap around */
613 SET_GBE_FIELD(VT_HPIXEN, HPIXEN_ON, val, temp);
614 SET_GBE_FIELD(VT_HPIXEN, HPIXEN_OFF, val,
615 ((temp + timing->width -
616 GBE_PIXEN_MAGIC_OFF) % timing->htotal));
617 gbe->vt_hpixen = val;
619 val = 0;
620 SET_GBE_FIELD(VT_VPIXEN, VPIXEN_ON, val, timing->vblank_end);
621 SET_GBE_FIELD(VT_VPIXEN, VPIXEN_OFF, val, timing->vblank_start);
622 gbe->vt_vpixen = val;
624 /* turn off sync on green */
625 val = 0;
626 SET_GBE_FIELD(VT_FLAGS, SYNC_LOW, val, 1);
627 gbe->vt_flags = val;
631 * Set the hardware according to 'par'.
634 static int gbefb_set_par(struct fb_info *info)
636 int i;
637 unsigned int val;
638 int wholeTilesX, partTilesX, maxPixelsPerTileX;
639 int height_pix;
640 int xpmax, ypmax; /* Monitor resolution */
641 int bytesPerPixel; /* Bytes per pixel */
642 struct gbefb_par *par = (struct gbefb_par *) info->par;
644 compute_gbe_timing(&info->var, &par->timing);
646 bytesPerPixel = info->var.bits_per_pixel / 8;
647 info->fix.line_length = info->var.xres_virtual * bytesPerPixel;
648 xpmax = par->timing.width;
649 ypmax = par->timing.height;
651 /* turn off GBE */
652 gbe_turn_off();
654 /* set timing info */
655 gbe_set_timing_info(&par->timing);
657 /* initialize DIDs */
658 val = 0;
659 switch (bytesPerPixel) {
660 case 1:
661 SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_I8);
662 break;
663 case 2:
664 SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_ARGB5);
665 break;
666 case 4:
667 SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_RGB8);
668 break;
670 SET_GBE_FIELD(WID, BUF, val, GBE_BMODE_BOTH);
672 for (i = 0; i < 32; i++)
673 gbe->mode_regs[i] = val;
675 /* Initialize interrupts */
676 gbe->vt_intr01 = 0xffffffff;
677 gbe->vt_intr23 = 0xffffffff;
679 /* HACK:
680 The GBE hardware uses a tiled memory to screen mapping. Tiles are
681 blocks of 512x128, 256x128 or 128x128 pixels, respectively for 8bit,
682 16bit and 32 bit modes (64 kB). They cover the screen with partial
683 tiles on the right and/or bottom of the screen if needed.
684 For exemple in 640x480 8 bit mode the mapping is:
686 <-------- 640 ----->
687 <---- 512 ----><128|384 offscreen>
689 | 128 [tile 0] [tile 1]
692 4 128 [tile 2] [tile 3]
695 128 [tile 4] [tile 5]
698 v 96 [tile 6] [tile 7]
699 32 offscreen
701 Tiles have the advantage that they can be allocated individually in
702 memory. However, this mapping is not linear at all, which is not
703 really convienient. In order to support linear addressing, the GBE
704 DMA hardware is fooled into thinking the screen is only one tile
705 large and but has a greater height, so that the DMA transfer covers
706 the same region.
707 Tiles are still allocated as independent chunks of 64KB of
708 continuous physical memory and remapped so that the kernel sees the
709 framebuffer as a continuous virtual memory. The GBE tile table is
710 set up so that each tile references one of these 64k blocks:
712 GBE -> tile list framebuffer TLB <------------ CPU
713 [ tile 0 ] -> [ 64KB ] <- [ 16x 4KB page entries ] ^
714 ... ... ... linear virtual FB
715 [ tile n ] -> [ 64KB ] <- [ 16x 4KB page entries ] v
718 The GBE hardware is then told that the buffer is 512*tweaked_height,
719 with tweaked_height = real_width*real_height/pixels_per_tile.
720 Thus the GBE hardware will scan the first tile, filing the first 64k
721 covered region of the screen, and then will proceed to the next
722 tile, until the whole screen is covered.
724 Here is what would happen at 640x480 8bit:
726 normal tiling linear
727 ^ 11111111111111112222 11111111111111111111 ^
728 128 11111111111111112222 11111111111111111111 102 lines
729 11111111111111112222 11111111111111111111 v
730 V 11111111111111112222 11111111222222222222
731 33333333333333334444 22222222222222222222
732 33333333333333334444 22222222222222222222
733 < 512 > < 256 > 102*640+256 = 64k
735 NOTE: The only mode for which this is not working is 800x600 8bit,
736 as 800*600/512 = 937.5 which is not integer and thus causes
737 flickering.
738 I guess this is not so important as one can use 640x480 8bit or
739 800x600 16bit anyway.
742 /* Tell gbe about the tiles table location */
743 /* tile_ptr -> [ tile 1 ] -> FB mem */
744 /* [ tile 2 ] -> FB mem */
745 /* ... */
746 val = 0;
747 SET_GBE_FIELD(FRM_CONTROL, FRM_TILE_PTR, val, gbe_tiles.dma >> 9);
748 SET_GBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, val, 0); /* do not start */
749 SET_GBE_FIELD(FRM_CONTROL, FRM_LINEAR, val, 0);
750 gbe->frm_control = val;
752 maxPixelsPerTileX = 512 / bytesPerPixel;
753 wholeTilesX = 1;
754 partTilesX = 0;
756 /* Initialize the framebuffer */
757 val = 0;
758 SET_GBE_FIELD(FRM_SIZE_TILE, FRM_WIDTH_TILE, val, wholeTilesX);
759 SET_GBE_FIELD(FRM_SIZE_TILE, FRM_RHS, val, partTilesX);
761 switch (bytesPerPixel) {
762 case 1:
763 SET_GBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, val,
764 GBE_FRM_DEPTH_8);
765 break;
766 case 2:
767 SET_GBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, val,
768 GBE_FRM_DEPTH_16);
769 break;
770 case 4:
771 SET_GBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, val,
772 GBE_FRM_DEPTH_32);
773 break;
775 gbe->frm_size_tile = val;
777 /* compute tweaked height */
778 height_pix = xpmax * ypmax / maxPixelsPerTileX;
780 val = 0;
781 SET_GBE_FIELD(FRM_SIZE_PIXEL, FB_HEIGHT_PIX, val, height_pix);
782 gbe->frm_size_pixel = val;
784 /* turn off DID and overlay DMA */
785 gbe->did_control = 0;
786 gbe->ovr_width_tile = 0;
788 /* Turn off mouse cursor */
789 gbe->crs_ctl = 0;
791 /* Turn on GBE */
792 gbe_turn_on();
794 /* Initialize the gamma map */
795 udelay(10);
796 for (i = 0; i < 256; i++)
797 gbe->gmap[i] = (i << 24) | (i << 16) | (i << 8);
799 /* Initialize the color map */
800 for (i = 0; i < 256; i++) {
801 int j;
803 for (j = 0; j < 1000 && gbe->cm_fifo >= 63; j++)
804 udelay(10);
805 if (j == 1000)
806 printk(KERN_ERR "gbefb: cmap FIFO timeout\n");
808 gbe->cmap[i] = (i << 8) | (i << 16) | (i << 24);
811 return 0;
814 static void gbefb_encode_fix(struct fb_fix_screeninfo *fix,
815 struct fb_var_screeninfo *var)
817 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
818 strcpy(fix->id, "SGI GBE");
819 fix->smem_start = (unsigned long) gbe_mem;
820 fix->smem_len = gbe_mem_size;
821 fix->type = FB_TYPE_PACKED_PIXELS;
822 fix->type_aux = 0;
823 fix->accel = FB_ACCEL_NONE;
824 switch (var->bits_per_pixel) {
825 case 8:
826 fix->visual = FB_VISUAL_PSEUDOCOLOR;
827 break;
828 default:
829 fix->visual = FB_VISUAL_TRUECOLOR;
830 break;
832 fix->ywrapstep = 0;
833 fix->xpanstep = 0;
834 fix->ypanstep = 0;
835 fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
836 fix->mmio_start = GBE_BASE;
837 fix->mmio_len = sizeof(struct sgi_gbe);
841 * Set a single color register. The values supplied are already
842 * rounded down to the hardware's capabilities (according to the
843 * entries in the var structure). Return != 0 for invalid regno.
846 static int gbefb_setcolreg(unsigned regno, unsigned red, unsigned green,
847 unsigned blue, unsigned transp,
848 struct fb_info *info)
850 int i;
852 if (regno > 255)
853 return 1;
854 red >>= 8;
855 green >>= 8;
856 blue >>= 8;
858 switch (info->var.bits_per_pixel) {
859 case 8:
860 /* wait for the color map FIFO to have a free entry */
861 for (i = 0; i < 1000 && gbe->cm_fifo >= 63; i++)
862 udelay(10);
863 if (i == 1000) {
864 printk(KERN_ERR "gbefb: cmap FIFO timeout\n");
865 return 1;
867 gbe->cmap[regno] = (red << 24) | (green << 16) | (blue << 8);
868 break;
869 case 15:
870 case 16:
871 red >>= 3;
872 green >>= 3;
873 blue >>= 3;
874 pseudo_palette[regno] =
875 (red << info->var.red.offset) |
876 (green << info->var.green.offset) |
877 (blue << info->var.blue.offset);
878 break;
879 case 32:
880 pseudo_palette[regno] =
881 (red << info->var.red.offset) |
882 (green << info->var.green.offset) |
883 (blue << info->var.blue.offset);
884 break;
887 return 0;
891 * Check video mode validity, eventually modify var to best match.
893 static int gbefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
895 unsigned int line_length;
896 struct gbe_timing_info timing;
898 /* Limit bpp to 8, 16, and 32 */
899 if (var->bits_per_pixel <= 8)
900 var->bits_per_pixel = 8;
901 else if (var->bits_per_pixel <= 16)
902 var->bits_per_pixel = 16;
903 else if (var->bits_per_pixel <= 32)
904 var->bits_per_pixel = 32;
905 else
906 return -EINVAL;
908 /* Check the mode can be mapped linearly with the tile table trick. */
909 /* This requires width x height x bytes/pixel be a multiple of 512 */
910 if ((var->xres * var->yres * var->bits_per_pixel) & 4095)
911 return -EINVAL;
913 var->grayscale = 0; /* No grayscale for now */
915 if ((var->pixclock = compute_gbe_timing(var, &timing)) < 0)
916 return(-EINVAL);
918 /* Adjust virtual resolution, if necessary */
919 if (var->xres > var->xres_virtual || (!ywrap && !ypan))
920 var->xres_virtual = var->xres;
921 if (var->yres > var->yres_virtual || (!ywrap && !ypan))
922 var->yres_virtual = var->yres;
924 if (var->vmode & FB_VMODE_CONUPDATE) {
925 var->vmode |= FB_VMODE_YWRAP;
926 var->xoffset = info->var.xoffset;
927 var->yoffset = info->var.yoffset;
930 /* No grayscale for now */
931 var->grayscale = 0;
933 /* Memory limit */
934 line_length = var->xres_virtual * var->bits_per_pixel / 8;
935 if (line_length * var->yres_virtual > gbe_mem_size)
936 return -ENOMEM; /* Virtual resolution too high */
938 switch (var->bits_per_pixel) {
939 case 8:
940 var->red.offset = 0;
941 var->red.length = 8;
942 var->green.offset = 0;
943 var->green.length = 8;
944 var->blue.offset = 0;
945 var->blue.length = 8;
946 var->transp.offset = 0;
947 var->transp.length = 0;
948 break;
949 case 16: /* RGB 1555 */
950 var->red.offset = 10;
951 var->red.length = 5;
952 var->green.offset = 5;
953 var->green.length = 5;
954 var->blue.offset = 0;
955 var->blue.length = 5;
956 var->transp.offset = 0;
957 var->transp.length = 0;
958 break;
959 case 32: /* RGB 8888 */
960 var->red.offset = 24;
961 var->red.length = 8;
962 var->green.offset = 16;
963 var->green.length = 8;
964 var->blue.offset = 8;
965 var->blue.length = 8;
966 var->transp.offset = 0;
967 var->transp.length = 8;
968 break;
970 var->red.msb_right = 0;
971 var->green.msb_right = 0;
972 var->blue.msb_right = 0;
973 var->transp.msb_right = 0;
975 var->left_margin = timing.htotal - timing.hsync_end;
976 var->right_margin = timing.hsync_start - timing.width;
977 var->upper_margin = timing.vtotal - timing.vsync_end;
978 var->lower_margin = timing.vsync_start - timing.height;
979 var->hsync_len = timing.hsync_end - timing.hsync_start;
980 var->vsync_len = timing.vsync_end - timing.vsync_start;
982 return 0;
985 static int gbefb_mmap(struct fb_info *info, struct file *file,
986 struct vm_area_struct *vma)
988 unsigned long size = vma->vm_end - vma->vm_start;
989 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
990 unsigned long addr;
991 unsigned long phys_addr, phys_size;
992 u16 *tile;
994 /* check range */
995 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
996 return -EINVAL;
997 if (offset + size > gbe_mem_size)
998 return -EINVAL;
1000 /* remap using the fastest write-through mode on architecture */
1001 /* try not polluting the cache when possible */
1002 pgprot_val(vma->vm_page_prot) =
1003 pgprot_fb(pgprot_val(vma->vm_page_prot));
1005 vma->vm_flags |= VM_IO | VM_RESERVED;
1006 vma->vm_file = file;
1008 /* look for the starting tile */
1009 tile = &gbe_tiles.cpu[offset >> TILE_SHIFT];
1010 addr = vma->vm_start;
1011 offset &= TILE_MASK;
1013 /* remap each tile separately */
1014 do {
1015 phys_addr = (((unsigned long) (*tile)) << TILE_SHIFT) + offset;
1016 if ((offset + size) < TILE_SIZE)
1017 phys_size = size;
1018 else
1019 phys_size = TILE_SIZE - offset;
1021 if (remap_page_range
1022 (vma, addr, phys_addr, phys_size, vma->vm_page_prot))
1023 return -EAGAIN;
1025 offset = 0;
1026 size -= phys_size;
1027 addr += phys_size;
1028 tile++;
1029 } while (size);
1031 return 0;
1034 static struct fb_ops gbefb_ops = {
1035 .owner = THIS_MODULE,
1036 .fb_check_var = gbefb_check_var,
1037 .fb_set_par = gbefb_set_par,
1038 .fb_setcolreg = gbefb_setcolreg,
1039 .fb_mmap = gbefb_mmap,
1040 .fb_blank = gbefb_blank,
1041 .fb_fillrect = cfb_fillrect,
1042 .fb_copyarea = cfb_copyarea,
1043 .fb_imageblit = cfb_imageblit,
1044 .fb_cursor = soft_cursor,
1048 * Initialization
1051 int __init gbefb_setup(char *options)
1053 char *this_opt;
1055 if (!options || !*options)
1056 return 0;
1058 while ((this_opt = strsep(&options, ",")) != NULL) {
1059 if (!strncmp(this_opt, "monitor:", 8)) {
1060 if (!strncmp(this_opt + 8, "crt", 3)) {
1061 flat_panel_enabled = 0;
1062 default_var = &default_var_CRT;
1063 default_mode = &default_mode_CRT;
1064 } else if (!strncmp(this_opt + 8, "1600sw", 6) ||
1065 !strncmp(this_opt + 8, "lcd", 3)) {
1066 flat_panel_enabled = 1;
1067 default_var = &default_var_LCD;
1068 default_mode = &default_mode_LCD;
1070 } else if (!strncmp(this_opt, "mem:", 4)) {
1071 gbe_mem_size = memparse(this_opt + 4, &this_opt);
1072 if (gbe_mem_size > CONFIG_FB_GBE_MEM * 1024 * 1024)
1073 gbe_mem_size = CONFIG_FB_GBE_MEM * 1024 * 1024;
1074 if (gbe_mem_size < TILE_SIZE)
1075 gbe_mem_size = TILE_SIZE;
1076 } else
1077 mode_option = this_opt;
1079 return 0;
1082 int __init gbefb_init(void)
1084 int i, ret = 0;
1086 #ifndef MODULE
1087 char *option = NULL;
1089 if (fb_get_options("gbefb", &option))
1090 return -ENODEV;
1091 gbefb_setup(options);
1092 #endif
1094 if (!request_mem_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) {
1095 printk(KERN_ERR "gbefb: couldn't reserve mmio region\n");
1096 return -EBUSY;
1099 gbe = (struct sgi_gbe *) ioremap(GBE_BASE, sizeof(struct sgi_gbe));
1100 if (!gbe) {
1101 printk(KERN_ERR "gbefb: couldn't map mmio region\n");
1102 ret = -ENXIO;
1103 goto out_release_mem_region;
1105 gbe_revision = gbe->ctrlstat & 15;
1107 gbe_tiles.cpu =
1108 dma_alloc_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),
1109 &gbe_tiles.dma, GFP_KERNEL);
1110 if (!gbe_tiles.cpu) {
1111 printk(KERN_ERR "gbefb: couldn't allocate tiles table\n");
1112 ret = -ENOMEM;
1113 goto out_unmap;
1117 if (gbe_mem_phys) {
1118 /* memory was allocated at boot time */
1119 gbe_mem = ioremap_nocache(gbe_mem_phys, gbe_mem_size);
1120 gbe_dma_addr = 0;
1121 } else {
1122 /* try to allocate memory with the classical allocator
1123 * this has high chance to fail on low memory machines */
1124 gbe_mem = dma_alloc_coherent(NULL, gbe_mem_size, &gbe_dma_addr,
1125 GFP_KERNEL);
1126 gbe_mem_phys = (unsigned long) gbe_dma_addr;
1129 #ifdef CONFIG_X86
1130 mtrr_add(gbe_mem_phys, gbe_mem_size, MTRR_TYPE_WRCOMB, 1);
1131 #endif
1133 if (!gbe_mem) {
1134 printk(KERN_ERR "gbefb: couldn't map framebuffer\n");
1135 ret = -ENXIO;
1136 goto out_tiles_free;
1139 /* map framebuffer memory into tiles table */
1140 for (i = 0; i < (gbe_mem_size >> TILE_SHIFT); i++)
1141 gbe_tiles.cpu[i] = (gbe_mem_phys >> TILE_SHIFT) + i;
1143 fb_info.currcon = -1;
1144 fb_info.fbops = &gbefb_ops;
1145 fb_info.pseudo_palette = pseudo_palette;
1146 fb_info.flags = FBINFO_DEFAULT;
1147 fb_info.screen_base = gbe_mem;
1148 fb_alloc_cmap(&fb_info.cmap, 256, 0);
1150 /* reset GBE */
1151 gbe_reset();
1153 /* turn on default video mode */
1154 if (fb_find_mode(&par_current.var, &fb_info, mode_option, NULL, 0,
1155 default_mode, 8) == 0)
1156 par_current.var = *default_var;
1157 fb_info.var = par_current.var;
1158 gbefb_check_var(&par_current.var, &fb_info);
1159 gbefb_encode_fix(&fb_info.fix, &fb_info.var);
1160 fb_info.par = &par_current;
1162 if (register_framebuffer(&fb_info) < 0) {
1163 ret = -ENXIO;
1164 printk(KERN_ERR "gbefb: couldn't register framebuffer\n");
1165 goto out_gbe_unmap;
1168 printk(KERN_INFO "fb%d: %s rev %d @ 0x%08x using %dkB memory\n",
1169 fb_info.node, fb_info.fix.id, gbe_revision, (unsigned) GBE_BASE,
1170 gbe_mem_size >> 10);
1172 return 0;
1174 out_gbe_unmap:
1175 if (gbe_dma_addr)
1176 dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);
1177 else
1178 iounmap(gbe_mem);
1179 out_tiles_free:
1180 dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),
1181 (void *)gbe_tiles.cpu, gbe_tiles.dma);
1182 out_unmap:
1183 iounmap(gbe);
1184 out_release_mem_region:
1185 release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
1186 return ret;
1189 void __exit gbefb_exit(void)
1191 unregister_framebuffer(&fb_info);
1192 gbe_turn_off();
1193 if (gbe_dma_addr)
1194 dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);
1195 else
1196 iounmap(gbe_mem);
1197 dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),
1198 (void *)gbe_tiles.cpu, gbe_tiles.dma);
1199 release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
1200 iounmap(gbe);
1203 module_init(gbefb_init);
1205 #ifdef MODULE
1206 module_exit(gbefb_exit);
1207 #endif
1209 MODULE_LICENSE("GPL");