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
12 #include <linux/delay.h>
13 #include <linux/platform_device.h>
14 #include <linux/dma-mapping.h>
15 #include <linux/errno.h>
17 #include <linux/init.h>
18 #include <linux/interrupt.h>
19 #include <linux/kernel.h>
21 #include <linux/module.h>
27 #include <asm/addrspace.h>
29 #include <asm/byteorder.h>
31 #include <asm/tlbflush.h>
33 #include <video/gbe.h>
35 static struct sgi_gbe
*gbe
;
38 struct fb_var_screeninfo var
;
39 struct gbe_timing_info timing
;
43 #ifdef CONFIG_SGI_IP32
44 #define GBE_BASE 0x16000000 /* SGI O2 */
47 #ifdef CONFIG_X86_VISWS
48 #define GBE_BASE 0xd0000000 /* SGI Visual Workstation */
51 /* macro for fastest write-though access to the framebuffer */
53 #ifdef CONFIG_CPU_R10000
54 #define pgprot_fb(_prot) (((_prot) & (~_CACHE_MASK)) | _CACHE_UNCACHED_ACCELERATED)
56 #define pgprot_fb(_prot) (((_prot) & (~_CACHE_MASK)) | _CACHE_CACHABLE_NO_WA)
60 #define pgprot_fb(_prot) ((_prot) | _PAGE_PCD)
64 * RAM we reserve for the frame buffer. This defines the maximum screen
67 #if CONFIG_FB_GBE_MEM > 8
68 #error GBE Framebuffer cannot use more than 8MB of memory
72 #define TILE_SIZE (1 << TILE_SHIFT)
73 #define TILE_MASK (TILE_SIZE - 1)
75 static unsigned int gbe_mem_size
= CONFIG_FB_GBE_MEM
* 1024*1024;
77 static dma_addr_t gbe_dma_addr
;
78 unsigned long gbe_mem_phys
;
85 static int gbe_revision
;
87 static int ypan
, ywrap
;
89 static uint32_t pseudo_palette
[16];
91 static char *mode_option __initdata
= NULL
;
93 /* default CRT mode */
94 static struct fb_var_screeninfo default_var_CRT __initdata
= {
95 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
105 .green
= { 0, 8, 0 },
107 .transp
= { 0, 0, 0 },
113 .pixclock
= 39722, /* picoseconds */
121 .vmode
= FB_VMODE_NONINTERLACED
,
124 /* default LCD mode */
125 static struct fb_var_screeninfo default_var_LCD __initdata
= {
126 /* 1600x1024, 8 bpp */
129 .xres_virtual
= 1600,
130 .yres_virtual
= 1024,
136 .green
= { 0, 8, 0 },
138 .transp
= { 0, 0, 0 },
152 .vmode
= FB_VMODE_NONINTERLACED
155 /* default modedb mode */
156 /* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
157 static struct fb_videomode default_mode_CRT __initdata
= {
169 .vmode
= FB_VMODE_NONINTERLACED
,
171 /* 1600x1024 SGI flatpanel 1600sw */
172 static struct fb_videomode default_mode_LCD __initdata
= {
173 /* 1600x1024, 8 bpp */
183 .vmode
= FB_VMODE_NONINTERLACED
,
186 struct fb_videomode
*default_mode
= &default_mode_CRT
;
187 struct fb_var_screeninfo
*default_var
= &default_var_CRT
;
189 static int flat_panel_enabled
= 0;
191 static void gbe_reset(void)
193 /* Turn on dotclock PLL */
194 gbe
->ctrlstat
= 0x300aa000;
199 * Function: gbe_turn_off
201 * Description: This should turn off the monitor and gbe. This is used
202 * when switching between the serial console and the graphics
206 void gbe_turn_off(void)
209 unsigned int val
, x
, y
, vpixen_off
;
211 /* check if pixel counter is on */
213 if (GET_GBE_FIELD(VT_XY
, FREEZE
, val
) == 1)
217 val
= gbe
->ovr_control
;
218 SET_GBE_FIELD(OVR_CONTROL
, OVR_DMA_ENABLE
, val
, 0);
219 gbe
->ovr_control
= val
;
221 val
= gbe
->frm_control
;
222 SET_GBE_FIELD(FRM_CONTROL
, FRM_DMA_ENABLE
, val
, 0);
223 gbe
->frm_control
= val
;
225 val
= gbe
->did_control
;
226 SET_GBE_FIELD(DID_CONTROL
, DID_DMA_ENABLE
, val
, 0);
227 gbe
->did_control
= val
;
230 /* We have to wait through two vertical retrace periods before
231 * the pixel DMA is turned off for sure. */
232 for (i
= 0; i
< 10000; i
++) {
233 val
= gbe
->frm_inhwctrl
;
234 if (GET_GBE_FIELD(FRM_INHWCTRL
, FRM_DMA_ENABLE
, val
)) {
237 val
= gbe
->ovr_inhwctrl
;
238 if (GET_GBE_FIELD(OVR_INHWCTRL
, OVR_DMA_ENABLE
, val
)) {
241 val
= gbe
->did_inhwctrl
;
242 if (GET_GBE_FIELD(DID_INHWCTRL
, DID_DMA_ENABLE
, val
)) {
250 printk(KERN_ERR
"gbefb: turn off DMA timed out\n");
252 /* wait for vpixen_off */
253 val
= gbe
->vt_vpixen
;
254 vpixen_off
= GET_GBE_FIELD(VT_VPIXEN
, VPIXEN_OFF
, val
);
256 for (i
= 0; i
< 100000; i
++) {
258 x
= GET_GBE_FIELD(VT_XY
, X
, val
);
259 y
= GET_GBE_FIELD(VT_XY
, Y
, val
);
266 "gbefb: wait for vpixen_off timed out\n");
267 for (i
= 0; i
< 10000; i
++) {
269 x
= GET_GBE_FIELD(VT_XY
, X
, val
);
270 y
= GET_GBE_FIELD(VT_XY
, Y
, val
);
276 printk(KERN_ERR
"gbefb: wait for vpixen_off timed out\n");
278 /* turn off pixel counter */
280 SET_GBE_FIELD(VT_XY
, FREEZE
, val
, 1);
283 for (i
= 0; i
< 10000; i
++) {
285 if (GET_GBE_FIELD(VT_XY
, FREEZE
, val
) != 1)
291 printk(KERN_ERR
"gbefb: turn off pixel clock timed out\n");
293 /* turn off dot clock */
295 SET_GBE_FIELD(DOTCLK
, RUN
, val
, 0);
298 for (i
= 0; i
< 10000; i
++) {
300 if (GET_GBE_FIELD(DOTCLK
, RUN
, val
))
306 printk(KERN_ERR
"gbefb: turn off dotclock timed out\n");
308 /* reset the frame DMA FIFO */
309 val
= gbe
->frm_size_tile
;
310 SET_GBE_FIELD(FRM_SIZE_TILE
, FRM_FIFO_RESET
, val
, 1);
311 gbe
->frm_size_tile
= val
;
312 SET_GBE_FIELD(FRM_SIZE_TILE
, FRM_FIFO_RESET
, val
, 0);
313 gbe
->frm_size_tile
= val
;
316 static void gbe_turn_on(void)
321 * Check if pixel counter is off, for unknown reason this
322 * code hangs Visual Workstations
324 if (gbe_revision
< 2) {
326 if (GET_GBE_FIELD(VT_XY
, FREEZE
, val
) == 0)
330 /* turn on dot clock */
332 SET_GBE_FIELD(DOTCLK
, RUN
, val
, 1);
335 for (i
= 0; i
< 10000; i
++) {
337 if (GET_GBE_FIELD(DOTCLK
, RUN
, val
) != 1)
343 printk(KERN_ERR
"gbefb: turn on dotclock timed out\n");
345 /* turn on pixel counter */
347 SET_GBE_FIELD(VT_XY
, FREEZE
, val
, 0);
350 for (i
= 0; i
< 10000; i
++) {
352 if (GET_GBE_FIELD(VT_XY
, FREEZE
, val
))
358 printk(KERN_ERR
"gbefb: turn on pixel clock timed out\n");
361 val
= gbe
->frm_control
;
362 SET_GBE_FIELD(FRM_CONTROL
, FRM_DMA_ENABLE
, val
, 1);
363 gbe
->frm_control
= val
;
365 for (i
= 0; i
< 10000; i
++) {
366 val
= gbe
->frm_inhwctrl
;
367 if (GET_GBE_FIELD(FRM_INHWCTRL
, FRM_DMA_ENABLE
, val
) != 1)
373 printk(KERN_ERR
"gbefb: turn on DMA timed out\n");
379 static int gbefb_blank(int blank
, struct fb_info
*info
)
381 /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
383 case FB_BLANK_UNBLANK
: /* unblank */
387 case FB_BLANK_NORMAL
: /* blank */
399 * Setup flatpanel related registers.
401 static void gbefb_setup_flatpanel(struct gbe_timing_info
*timing
)
403 int fp_wid
, fp_hgt
, fp_vbs
, fp_vbe
;
406 SET_GBE_FIELD(VT_FLAGS
, HDRV_INVERT
, outputVal
,
407 (timing
->flags
& FB_SYNC_HOR_HIGH_ACT
) ? 0 : 1);
408 SET_GBE_FIELD(VT_FLAGS
, VDRV_INVERT
, outputVal
,
409 (timing
->flags
& FB_SYNC_VERT_HIGH_ACT
) ? 0 : 1);
410 gbe
->vt_flags
= outputVal
;
412 /* Turn on the flat panel */
422 SET_GBE_FIELD(FP_DE
, ON
, outputVal
, fp_vbs
);
423 SET_GBE_FIELD(FP_DE
, OFF
, outputVal
, fp_vbe
);
424 gbe
->fp_de
= outputVal
;
426 SET_GBE_FIELD(FP_HDRV
, OFF
, outputVal
, fp_wid
);
427 gbe
->fp_hdrv
= outputVal
;
429 SET_GBE_FIELD(FP_VDRV
, ON
, outputVal
, 1);
430 SET_GBE_FIELD(FP_VDRV
, OFF
, outputVal
, fp_hgt
+ 1);
431 gbe
->fp_vdrv
= outputVal
;
434 struct gbe_pll_info
{
440 static struct gbe_pll_info gbe_pll_table
[2] = {
445 static int compute_gbe_timing(struct fb_var_screeninfo
*var
,
446 struct gbe_timing_info
*timing
)
448 int pll_m
, pll_n
, pll_p
, error
, best_m
, best_n
, best_p
, best_error
;
450 struct gbe_pll_info
*gbe_pll
;
452 if (gbe_revision
< 2)
453 gbe_pll
= &gbe_pll_table
[0];
455 gbe_pll
= &gbe_pll_table
[1];
457 /* Determine valid resolution and timing
458 * GBE crystal runs at 20Mhz or 27Mhz
459 * pll_m, pll_n, pll_p define the following frequencies
460 * fvco = pll_m * 20Mhz / pll_n
461 * fout = fvco / (2**pll_p) */
462 best_error
= 1000000000;
463 best_n
= best_m
= best_p
= 0;
464 for (pll_p
= 0; pll_p
< 4; pll_p
++)
465 for (pll_m
= 1; pll_m
< 256; pll_m
++)
466 for (pll_n
= 1; pll_n
< 64; pll_n
++) {
467 pixclock
= (1000000 / gbe_pll
->clock_rate
) *
468 (pll_n
<< pll_p
) / pll_m
;
470 error
= var
->pixclock
- pixclock
;
475 if (error
< best_error
&&
477 gbe_pll
->fvco_min
/ gbe_pll
->clock_rate
&&
479 gbe_pll
->fvco_max
/ gbe_pll
->clock_rate
) {
487 if (!best_n
|| !best_m
)
488 return -EINVAL
; /* Resolution to high */
490 pixclock
= (1000000 / gbe_pll
->clock_rate
) *
491 (best_n
<< best_p
) / best_m
;
493 /* set video timing information */
495 timing
->width
= var
->xres
;
496 timing
->height
= var
->yres
;
497 timing
->pll_m
= best_m
;
498 timing
->pll_n
= best_n
;
499 timing
->pll_p
= best_p
;
500 timing
->cfreq
= gbe_pll
->clock_rate
* 1000 * timing
->pll_m
/
501 (timing
->pll_n
<< timing
->pll_p
);
502 timing
->htotal
= var
->left_margin
+ var
->xres
+
503 var
->right_margin
+ var
->hsync_len
;
504 timing
->vtotal
= var
->upper_margin
+ var
->yres
+
505 var
->lower_margin
+ var
->vsync_len
;
506 timing
->fields_sec
= 1000 * timing
->cfreq
/ timing
->htotal
*
507 1000 / timing
->vtotal
;
508 timing
->hblank_start
= var
->xres
;
509 timing
->vblank_start
= var
->yres
;
510 timing
->hblank_end
= timing
->htotal
;
511 timing
->hsync_start
= var
->xres
+ var
->right_margin
+ 1;
512 timing
->hsync_end
= timing
->hsync_start
+ var
->hsync_len
;
513 timing
->vblank_end
= timing
->vtotal
;
514 timing
->vsync_start
= var
->yres
+ var
->lower_margin
+ 1;
515 timing
->vsync_end
= timing
->vsync_start
+ var
->vsync_len
;
521 static void gbe_set_timing_info(struct gbe_timing_info
*timing
)
526 /* setup dot clock PLL */
528 SET_GBE_FIELD(DOTCLK
, M
, val
, timing
->pll_m
- 1);
529 SET_GBE_FIELD(DOTCLK
, N
, val
, timing
->pll_n
- 1);
530 SET_GBE_FIELD(DOTCLK
, P
, val
, timing
->pll_p
);
531 SET_GBE_FIELD(DOTCLK
, RUN
, val
, 0); /* do not start yet */
535 /* setup pixel counter */
537 SET_GBE_FIELD(VT_XYMAX
, MAXX
, val
, timing
->htotal
);
538 SET_GBE_FIELD(VT_XYMAX
, MAXY
, val
, timing
->vtotal
);
541 /* setup video timing signals */
543 SET_GBE_FIELD(VT_VSYNC
, VSYNC_ON
, val
, timing
->vsync_start
);
544 SET_GBE_FIELD(VT_VSYNC
, VSYNC_OFF
, val
, timing
->vsync_end
);
547 SET_GBE_FIELD(VT_HSYNC
, HSYNC_ON
, val
, timing
->hsync_start
);
548 SET_GBE_FIELD(VT_HSYNC
, HSYNC_OFF
, val
, timing
->hsync_end
);
551 SET_GBE_FIELD(VT_VBLANK
, VBLANK_ON
, val
, timing
->vblank_start
);
552 SET_GBE_FIELD(VT_VBLANK
, VBLANK_OFF
, val
, timing
->vblank_end
);
553 gbe
->vt_vblank
= val
;
555 SET_GBE_FIELD(VT_HBLANK
, HBLANK_ON
, val
,
556 timing
->hblank_start
- 5);
557 SET_GBE_FIELD(VT_HBLANK
, HBLANK_OFF
, val
,
558 timing
->hblank_end
- 3);
559 gbe
->vt_hblank
= val
;
561 /* setup internal timing signals */
563 SET_GBE_FIELD(VT_VCMAP
, VCMAP_ON
, val
, timing
->vblank_start
);
564 SET_GBE_FIELD(VT_VCMAP
, VCMAP_OFF
, val
, timing
->vblank_end
);
567 SET_GBE_FIELD(VT_HCMAP
, HCMAP_ON
, val
, timing
->hblank_start
);
568 SET_GBE_FIELD(VT_HCMAP
, HCMAP_OFF
, val
, timing
->hblank_end
);
572 temp
= timing
->vblank_start
- timing
->vblank_end
- 1;
576 if (flat_panel_enabled
)
577 gbefb_setup_flatpanel(timing
);
579 SET_GBE_FIELD(DID_START_XY
, DID_STARTY
, val
, (u32
) temp
);
580 if (timing
->hblank_end
>= 20)
581 SET_GBE_FIELD(DID_START_XY
, DID_STARTX
, val
,
582 timing
->hblank_end
- 20);
584 SET_GBE_FIELD(DID_START_XY
, DID_STARTX
, val
,
585 timing
->htotal
- (20 - timing
->hblank_end
));
586 gbe
->did_start_xy
= val
;
589 SET_GBE_FIELD(CRS_START_XY
, CRS_STARTY
, val
, (u32
) (temp
+ 1));
590 if (timing
->hblank_end
>= GBE_CRS_MAGIC
)
591 SET_GBE_FIELD(CRS_START_XY
, CRS_STARTX
, val
,
592 timing
->hblank_end
- GBE_CRS_MAGIC
);
594 SET_GBE_FIELD(CRS_START_XY
, CRS_STARTX
, val
,
595 timing
->htotal
- (GBE_CRS_MAGIC
-
596 timing
->hblank_end
));
597 gbe
->crs_start_xy
= val
;
600 SET_GBE_FIELD(VC_START_XY
, VC_STARTY
, val
, (u32
) temp
);
601 SET_GBE_FIELD(VC_START_XY
, VC_STARTX
, val
, timing
->hblank_end
- 4);
602 gbe
->vc_start_xy
= val
;
605 temp
= timing
->hblank_end
- GBE_PIXEN_MAGIC_ON
;
607 temp
+= timing
->htotal
; /* allow blank to wrap around */
609 SET_GBE_FIELD(VT_HPIXEN
, HPIXEN_ON
, val
, temp
);
610 SET_GBE_FIELD(VT_HPIXEN
, HPIXEN_OFF
, val
,
611 ((temp
+ timing
->width
-
612 GBE_PIXEN_MAGIC_OFF
) % timing
->htotal
));
613 gbe
->vt_hpixen
= val
;
616 SET_GBE_FIELD(VT_VPIXEN
, VPIXEN_ON
, val
, timing
->vblank_end
);
617 SET_GBE_FIELD(VT_VPIXEN
, VPIXEN_OFF
, val
, timing
->vblank_start
);
618 gbe
->vt_vpixen
= val
;
620 /* turn off sync on green */
622 SET_GBE_FIELD(VT_FLAGS
, SYNC_LOW
, val
, 1);
627 * Set the hardware according to 'par'.
630 static int gbefb_set_par(struct fb_info
*info
)
634 int wholeTilesX
, partTilesX
, maxPixelsPerTileX
;
636 int xpmax
, ypmax
; /* Monitor resolution */
637 int bytesPerPixel
; /* Bytes per pixel */
638 struct gbefb_par
*par
= (struct gbefb_par
*) info
->par
;
640 compute_gbe_timing(&info
->var
, &par
->timing
);
642 bytesPerPixel
= info
->var
.bits_per_pixel
/ 8;
643 info
->fix
.line_length
= info
->var
.xres_virtual
* bytesPerPixel
;
644 xpmax
= par
->timing
.width
;
645 ypmax
= par
->timing
.height
;
650 /* set timing info */
651 gbe_set_timing_info(&par
->timing
);
653 /* initialize DIDs */
655 switch (bytesPerPixel
) {
657 SET_GBE_FIELD(WID
, TYP
, val
, GBE_CMODE_I8
);
658 info
->fix
.visual
= FB_VISUAL_PSEUDOCOLOR
;
661 SET_GBE_FIELD(WID
, TYP
, val
, GBE_CMODE_ARGB5
);
662 info
->fix
.visual
= FB_VISUAL_TRUECOLOR
;
665 SET_GBE_FIELD(WID
, TYP
, val
, GBE_CMODE_RGB8
);
666 info
->fix
.visual
= FB_VISUAL_TRUECOLOR
;
669 SET_GBE_FIELD(WID
, BUF
, val
, GBE_BMODE_BOTH
);
671 for (i
= 0; i
< 32; i
++)
672 gbe
->mode_regs
[i
] = val
;
674 /* Initialize interrupts */
675 gbe
->vt_intr01
= 0xffffffff;
676 gbe
->vt_intr23
= 0xffffffff;
679 The GBE hardware uses a tiled memory to screen mapping. Tiles are
680 blocks of 512x128, 256x128 or 128x128 pixels, respectively for 8bit,
681 16bit and 32 bit modes (64 kB). They cover the screen with partial
682 tiles on the right and/or bottom of the screen if needed.
683 For exemple in 640x480 8 bit mode the mapping is:
686 <---- 512 ----><128|384 offscreen>
688 | 128 [tile 0] [tile 1]
691 4 128 [tile 2] [tile 3]
694 128 [tile 4] [tile 5]
697 v 96 [tile 6] [tile 7]
700 Tiles have the advantage that they can be allocated individually in
701 memory. However, this mapping is not linear at all, which is not
702 really convienient. In order to support linear addressing, the GBE
703 DMA hardware is fooled into thinking the screen is only one tile
704 large and but has a greater height, so that the DMA transfer covers
706 Tiles are still allocated as independent chunks of 64KB of
707 continuous physical memory and remapped so that the kernel sees the
708 framebuffer as a continuous virtual memory. The GBE tile table is
709 set up so that each tile references one of these 64k blocks:
711 GBE -> tile list framebuffer TLB <------------ CPU
712 [ tile 0 ] -> [ 64KB ] <- [ 16x 4KB page entries ] ^
713 ... ... ... linear virtual FB
714 [ tile n ] -> [ 64KB ] <- [ 16x 4KB page entries ] v
717 The GBE hardware is then told that the buffer is 512*tweaked_height,
718 with tweaked_height = real_width*real_height/pixels_per_tile.
719 Thus the GBE hardware will scan the first tile, filing the first 64k
720 covered region of the screen, and then will proceed to the next
721 tile, until the whole screen is covered.
723 Here is what would happen at 640x480 8bit:
726 ^ 11111111111111112222 11111111111111111111 ^
727 128 11111111111111112222 11111111111111111111 102 lines
728 11111111111111112222 11111111111111111111 v
729 V 11111111111111112222 11111111222222222222
730 33333333333333334444 22222222222222222222
731 33333333333333334444 22222222222222222222
732 < 512 > < 256 > 102*640+256 = 64k
734 NOTE: The only mode for which this is not working is 800x600 8bit,
735 as 800*600/512 = 937.5 which is not integer and thus causes
737 I guess this is not so important as one can use 640x480 8bit or
738 800x600 16bit anyway.
741 /* Tell gbe about the tiles table location */
742 /* tile_ptr -> [ tile 1 ] -> FB mem */
743 /* [ tile 2 ] -> FB mem */
746 SET_GBE_FIELD(FRM_CONTROL
, FRM_TILE_PTR
, val
, gbe_tiles
.dma
>> 9);
747 SET_GBE_FIELD(FRM_CONTROL
, FRM_DMA_ENABLE
, val
, 0); /* do not start */
748 SET_GBE_FIELD(FRM_CONTROL
, FRM_LINEAR
, val
, 0);
749 gbe
->frm_control
= val
;
751 maxPixelsPerTileX
= 512 / bytesPerPixel
;
755 /* Initialize the framebuffer */
757 SET_GBE_FIELD(FRM_SIZE_TILE
, FRM_WIDTH_TILE
, val
, wholeTilesX
);
758 SET_GBE_FIELD(FRM_SIZE_TILE
, FRM_RHS
, val
, partTilesX
);
760 switch (bytesPerPixel
) {
762 SET_GBE_FIELD(FRM_SIZE_TILE
, FRM_DEPTH
, val
,
766 SET_GBE_FIELD(FRM_SIZE_TILE
, FRM_DEPTH
, val
,
770 SET_GBE_FIELD(FRM_SIZE_TILE
, FRM_DEPTH
, val
,
774 gbe
->frm_size_tile
= val
;
776 /* compute tweaked height */
777 height_pix
= xpmax
* ypmax
/ maxPixelsPerTileX
;
780 SET_GBE_FIELD(FRM_SIZE_PIXEL
, FB_HEIGHT_PIX
, val
, height_pix
);
781 gbe
->frm_size_pixel
= val
;
783 /* turn off DID and overlay DMA */
784 gbe
->did_control
= 0;
785 gbe
->ovr_width_tile
= 0;
787 /* Turn off mouse cursor */
793 /* Initialize the gamma map */
795 for (i
= 0; i
< 256; i
++)
796 gbe
->gmap
[i
] = (i
<< 24) | (i
<< 16) | (i
<< 8);
798 /* Initialize the color map */
799 for (i
= 0; i
< 256; i
++) {
802 for (j
= 0; j
< 1000 && gbe
->cm_fifo
>= 63; j
++)
805 printk(KERN_ERR
"gbefb: cmap FIFO timeout\n");
807 gbe
->cmap
[i
] = (i
<< 8) | (i
<< 16) | (i
<< 24);
813 static void gbefb_encode_fix(struct fb_fix_screeninfo
*fix
,
814 struct fb_var_screeninfo
*var
)
816 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
817 strcpy(fix
->id
, "SGI GBE");
818 fix
->smem_start
= (unsigned long) gbe_mem
;
819 fix
->smem_len
= gbe_mem_size
;
820 fix
->type
= FB_TYPE_PACKED_PIXELS
;
822 fix
->accel
= FB_ACCEL_NONE
;
823 switch (var
->bits_per_pixel
) {
825 fix
->visual
= FB_VISUAL_PSEUDOCOLOR
;
828 fix
->visual
= FB_VISUAL_TRUECOLOR
;
834 fix
->line_length
= var
->xres_virtual
* var
->bits_per_pixel
/ 8;
835 fix
->mmio_start
= GBE_BASE
;
836 fix
->mmio_len
= sizeof(struct sgi_gbe
);
840 * Set a single color register. The values supplied are already
841 * rounded down to the hardware's capabilities (according to the
842 * entries in the var structure). Return != 0 for invalid regno.
845 static int gbefb_setcolreg(unsigned regno
, unsigned red
, unsigned green
,
846 unsigned blue
, unsigned transp
,
847 struct fb_info
*info
)
857 if (info
->var
.bits_per_pixel
<= 8) {
858 /* wait for the color map FIFO to have a free entry */
859 for (i
= 0; i
< 1000 && gbe
->cm_fifo
>= 63; i
++)
862 printk(KERN_ERR
"gbefb: cmap FIFO timeout\n");
865 gbe
->cmap
[regno
] = (red
<< 24) | (green
<< 16) | (blue
<< 8);
866 } else if (regno
< 16) {
867 switch (info
->var
.bits_per_pixel
) {
873 pseudo_palette
[regno
] =
874 (red
<< info
->var
.red
.offset
) |
875 (green
<< info
->var
.green
.offset
) |
876 (blue
<< info
->var
.blue
.offset
);
879 pseudo_palette
[regno
] =
880 (red
<< info
->var
.red
.offset
) |
881 (green
<< info
->var
.green
.offset
) |
882 (blue
<< info
->var
.blue
.offset
);
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;
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)
913 var
->grayscale
= 0; /* No grayscale for now */
915 if ((var
->pixclock
= compute_gbe_timing(var
, &timing
)) < 0)
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 */
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
) {
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;
949 case 16: /* RGB 1555 */
950 var
->red
.offset
= 10;
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;
959 case 32: /* RGB 8888 */
960 var
->red
.offset
= 24;
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;
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
;
985 static int gbefb_mmap(struct fb_info
*info
,
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
;
991 unsigned long phys_addr
, phys_size
;
995 if (vma
->vm_pgoff
> (~0UL >> PAGE_SHIFT
))
997 if (offset
+ size
> gbe_mem_size
)
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
;
1007 /* look for the starting tile */
1008 tile
= &gbe_tiles
.cpu
[offset
>> TILE_SHIFT
];
1009 addr
= vma
->vm_start
;
1010 offset
&= TILE_MASK
;
1012 /* remap each tile separately */
1014 phys_addr
= (((unsigned long) (*tile
)) << TILE_SHIFT
) + offset
;
1015 if ((offset
+ size
) < TILE_SIZE
)
1018 phys_size
= TILE_SIZE
- offset
;
1020 if (remap_pfn_range(vma
, addr
, phys_addr
>> PAGE_SHIFT
,
1021 phys_size
, vma
->vm_page_prot
))
1033 static struct fb_ops gbefb_ops
= {
1034 .owner
= THIS_MODULE
,
1035 .fb_check_var
= gbefb_check_var
,
1036 .fb_set_par
= gbefb_set_par
,
1037 .fb_setcolreg
= gbefb_setcolreg
,
1038 .fb_mmap
= gbefb_mmap
,
1039 .fb_blank
= gbefb_blank
,
1040 .fb_fillrect
= cfb_fillrect
,
1041 .fb_copyarea
= cfb_copyarea
,
1042 .fb_imageblit
= cfb_imageblit
,
1049 static ssize_t
gbefb_show_memsize(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
1051 return snprintf(buf
, PAGE_SIZE
, "%d\n", gbe_mem_size
);
1054 static DEVICE_ATTR(size
, S_IRUGO
, gbefb_show_memsize
, NULL
);
1056 static ssize_t
gbefb_show_rev(struct device
*device
, struct device_attribute
*attr
, char *buf
)
1058 return snprintf(buf
, PAGE_SIZE
, "%d\n", gbe_revision
);
1061 static DEVICE_ATTR(revision
, S_IRUGO
, gbefb_show_rev
, NULL
);
1063 static void __devexit
gbefb_remove_sysfs(struct device
*dev
)
1065 device_remove_file(dev
, &dev_attr_size
);
1066 device_remove_file(dev
, &dev_attr_revision
);
1069 static void gbefb_create_sysfs(struct device
*dev
)
1071 device_create_file(dev
, &dev_attr_size
);
1072 device_create_file(dev
, &dev_attr_revision
);
1079 int __init
gbefb_setup(char *options
)
1083 if (!options
|| !*options
)
1086 while ((this_opt
= strsep(&options
, ",")) != NULL
) {
1087 if (!strncmp(this_opt
, "monitor:", 8)) {
1088 if (!strncmp(this_opt
+ 8, "crt", 3)) {
1089 flat_panel_enabled
= 0;
1090 default_var
= &default_var_CRT
;
1091 default_mode
= &default_mode_CRT
;
1092 } else if (!strncmp(this_opt
+ 8, "1600sw", 6) ||
1093 !strncmp(this_opt
+ 8, "lcd", 3)) {
1094 flat_panel_enabled
= 1;
1095 default_var
= &default_var_LCD
;
1096 default_mode
= &default_mode_LCD
;
1098 } else if (!strncmp(this_opt
, "mem:", 4)) {
1099 gbe_mem_size
= memparse(this_opt
+ 4, &this_opt
);
1100 if (gbe_mem_size
> CONFIG_FB_GBE_MEM
* 1024 * 1024)
1101 gbe_mem_size
= CONFIG_FB_GBE_MEM
* 1024 * 1024;
1102 if (gbe_mem_size
< TILE_SIZE
)
1103 gbe_mem_size
= TILE_SIZE
;
1105 mode_option
= this_opt
;
1110 static int __init
gbefb_probe(struct platform_device
*p_dev
)
1113 struct fb_info
*info
;
1114 struct gbefb_par
*par
;
1116 char *options
= NULL
;
1119 info
= framebuffer_alloc(sizeof(struct gbefb_par
), &p_dev
->dev
);
1124 if (fb_get_options("gbefb", &options
))
1126 gbefb_setup(options
);
1129 if (!request_region(GBE_BASE
, sizeof(struct sgi_gbe
), "GBE")) {
1130 printk(KERN_ERR
"gbefb: couldn't reserve mmio region\n");
1132 goto out_release_framebuffer
;
1135 gbe
= (struct sgi_gbe
*) ioremap(GBE_BASE
, sizeof(struct sgi_gbe
));
1137 printk(KERN_ERR
"gbefb: couldn't map mmio region\n");
1139 goto out_release_mem_region
;
1141 gbe_revision
= gbe
->ctrlstat
& 15;
1144 dma_alloc_coherent(NULL
, GBE_TLB_SIZE
* sizeof(uint16_t),
1145 &gbe_tiles
.dma
, GFP_KERNEL
);
1146 if (!gbe_tiles
.cpu
) {
1147 printk(KERN_ERR
"gbefb: couldn't allocate tiles table\n");
1153 /* memory was allocated at boot time */
1154 gbe_mem
= ioremap_nocache(gbe_mem_phys
, gbe_mem_size
);
1156 printk(KERN_ERR
"gbefb: couldn't map framebuffer\n");
1158 goto out_tiles_free
;
1163 /* try to allocate memory with the classical allocator
1164 * this has high chance to fail on low memory machines */
1165 gbe_mem
= dma_alloc_coherent(NULL
, gbe_mem_size
, &gbe_dma_addr
,
1168 printk(KERN_ERR
"gbefb: couldn't allocate framebuffer memory\n");
1170 goto out_tiles_free
;
1173 gbe_mem_phys
= (unsigned long) gbe_dma_addr
;
1177 mtrr_add(gbe_mem_phys
, gbe_mem_size
, MTRR_TYPE_WRCOMB
, 1);
1180 /* map framebuffer memory into tiles table */
1181 for (i
= 0; i
< (gbe_mem_size
>> TILE_SHIFT
); i
++)
1182 gbe_tiles
.cpu
[i
] = (gbe_mem_phys
>> TILE_SHIFT
) + i
;
1184 info
->fbops
= &gbefb_ops
;
1185 info
->pseudo_palette
= pseudo_palette
;
1186 info
->flags
= FBINFO_DEFAULT
;
1187 info
->screen_base
= gbe_mem
;
1188 fb_alloc_cmap(&info
->cmap
, 256, 0);
1194 /* turn on default video mode */
1195 if (fb_find_mode(&par
->var
, info
, mode_option
, NULL
, 0,
1196 default_mode
, 8) == 0)
1197 par
->var
= *default_var
;
1198 info
->var
= par
->var
;
1199 gbefb_check_var(&par
->var
, info
);
1200 gbefb_encode_fix(&info
->fix
, &info
->var
);
1202 if (register_framebuffer(info
) < 0) {
1203 printk(KERN_ERR
"gbefb: couldn't register framebuffer\n");
1208 platform_set_drvdata(p_dev
, info
);
1209 gbefb_create_sysfs(&p_dev
->dev
);
1211 printk(KERN_INFO
"fb%d: %s rev %d @ 0x%08x using %dkB memory\n",
1212 info
->node
, info
->fix
.id
, gbe_revision
, (unsigned) GBE_BASE
,
1213 gbe_mem_size
>> 10);
1219 dma_free_coherent(NULL
, gbe_mem_size
, gbe_mem
, gbe_mem_phys
);
1223 dma_free_coherent(NULL
, GBE_TLB_SIZE
* sizeof(uint16_t),
1224 (void *)gbe_tiles
.cpu
, gbe_tiles
.dma
);
1227 out_release_mem_region
:
1228 release_mem_region(GBE_BASE
, sizeof(struct sgi_gbe
));
1229 out_release_framebuffer
:
1230 framebuffer_release(info
);
1235 static int __devexit
gbefb_remove(struct platform_device
* p_dev
)
1237 struct fb_info
*info
= platform_get_drvdata(p_dev
);
1239 unregister_framebuffer(info
);
1242 dma_free_coherent(NULL
, gbe_mem_size
, gbe_mem
, gbe_mem_phys
);
1245 dma_free_coherent(NULL
, GBE_TLB_SIZE
* sizeof(uint16_t),
1246 (void *)gbe_tiles
.cpu
, gbe_tiles
.dma
);
1247 release_mem_region(GBE_BASE
, sizeof(struct sgi_gbe
));
1249 gbefb_remove_sysfs(&p_dev
->dev
);
1250 framebuffer_release(info
);
1255 static struct platform_driver gbefb_driver
= {
1256 .probe
= gbefb_probe
,
1257 .remove
= __devexit_p(gbefb_remove
),
1263 static struct platform_device
*gbefb_device
;
1265 int __init
gbefb_init(void)
1267 int ret
= platform_driver_register(&gbefb_driver
);
1269 gbefb_device
= platform_device_alloc("gbefb", 0);
1271 ret
= platform_device_add(gbefb_device
);
1276 platform_device_put(gbefb_device
);
1277 platform_driver_unregister(&gbefb_driver
);
1283 void __exit
gbefb_exit(void)
1285 platform_device_unregister(gbefb_device
);
1286 platform_driver_unregister(&gbefb_driver
);
1289 module_init(gbefb_init
);
1290 module_exit(gbefb_exit
);
1292 MODULE_LICENSE("GPL");