11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SGI GBE frame buffer driver 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1999 Silicon Graphics, Inc. - Jeffrey Newquist 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2002 Vivien Chappelier <vivien.chappelier@linux-mips.org> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * License. See the file COPYING in the main directory of this archive for 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * more details. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 13d052d1beff706920e82c5d55006b08e256b5df09Russell King#include <linux/platform_device.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/dma-mapping.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 165a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/gfp.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fb.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 23cd9d6f10d07f26dd8a70e519c22b6b4f8a9e3e7aFlorian Tobias Schandinat#include <linux/io.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_X86 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/mtrr.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_MIPS 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/addrspace.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/byteorder.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/tlbflush.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <video/gbe.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sgi_gbe *gbe; 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct gbefb_par { 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fb_var_screeninfo var; 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct gbe_timing_info timing; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int valid; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SGI_IP32 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GBE_BASE 0x16000000 /* SGI O2 */ 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* macro for fastest write-though access to the framebuffer */ 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_MIPS 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_CPU_R10000 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define pgprot_fb(_prot) (((_prot) & (~_CACHE_MASK)) | _CACHE_UNCACHED_ACCELERATED) 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define pgprot_fb(_prot) (((_prot) & (~_CACHE_MASK)) | _CACHE_CACHABLE_NO_WA) 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_X86 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define pgprot_fb(_prot) ((_prot) | _PAGE_PCD) 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * RAM we reserve for the frame buffer. This defines the maximum screen 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * size 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if CONFIG_FB_GBE_MEM > 8 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#error GBE Framebuffer cannot use more than 8MB of memory 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TILE_SHIFT 16 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TILE_SIZE (1 << TILE_SHIFT) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TILE_MASK (TILE_SIZE - 1) 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int gbe_mem_size = CONFIG_FB_GBE_MEM * 1024*1024; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void *gbe_mem; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic dma_addr_t gbe_dma_addr; 75b6d57ae97af3c38d28f066b5e47b7d58e468728aDmitri Vorobievstatic unsigned long gbe_mem_phys; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct { 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint16_t *cpu; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_addr_t dma; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} gbe_tiles; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gbe_revision; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ypan, ywrap; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 869058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplasstatic uint32_t pseudo_palette[16]; 878d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerferstatic uint32_t gbe_cmap[256]; 888d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerferstatic int gbe_turned_on; /* 0 turned off, 1 turned on */ 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9048c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic char *mode_option = NULL; 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* default CRT mode */ 9348c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic struct fb_var_screeninfo default_var_CRT = { 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xres = 640, 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .yres = 480, 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xres_virtual = 640, 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .yres_virtual = 480, 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xoffset = 0, 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .yoffset = 0, 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .bits_per_pixel = 8, 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .grayscale = 0, 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .red = { 0, 8, 0 }, 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .green = { 0, 8, 0 }, 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .blue = { 0, 8, 0 }, 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .transp = { 0, 0, 0 }, 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .nonstd = 0, 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .activate = 0, 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .height = -1, 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .width = -1, 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .accel_flags = 0, 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .pixclock = 39722, /* picoseconds */ 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .left_margin = 48, 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .right_margin = 16, 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .upper_margin = 33, 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lower_margin = 10, 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .hsync_len = 96, 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .vsync_len = 2, 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .sync = 0, 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .vmode = FB_VMODE_NONINTERLACED, 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* default LCD mode */ 12448c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic struct fb_var_screeninfo default_var_LCD = { 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1600x1024, 8 bpp */ 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xres = 1600, 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .yres = 1024, 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xres_virtual = 1600, 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .yres_virtual = 1024, 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xoffset = 0, 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .yoffset = 0, 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .bits_per_pixel = 8, 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .grayscale = 0, 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .red = { 0, 8, 0 }, 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .green = { 0, 8, 0 }, 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .blue = { 0, 8, 0 }, 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .transp = { 0, 0, 0 }, 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .nonstd = 0, 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .activate = 0, 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .height = -1, 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .width = -1, 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .accel_flags = 0, 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .pixclock = 9353, 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .left_margin = 20, 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .right_margin = 30, 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .upper_margin = 37, 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lower_margin = 3, 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .hsync_len = 20, 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .vsync_len = 3, 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .sync = 0, 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .vmode = FB_VMODE_NONINTERLACED 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* default modedb mode */ 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */ 15648c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic struct fb_videomode default_mode_CRT = { 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .refresh = 60, 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xres = 640, 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .yres = 480, 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .pixclock = 39722, 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .left_margin = 48, 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .right_margin = 16, 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .upper_margin = 33, 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lower_margin = 10, 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .hsync_len = 96, 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .vsync_len = 2, 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .sync = 0, 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .vmode = FB_VMODE_NONINTERLACED, 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1600x1024 SGI flatpanel 1600sw */ 17148c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic struct fb_videomode default_mode_LCD = { 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1600x1024, 8 bpp */ 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xres = 1600, 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .yres = 1024, 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .pixclock = 9353, 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .left_margin = 20, 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .right_margin = 30, 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .upper_margin = 37, 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lower_margin = 3, 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .hsync_len = 20, 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .vsync_len = 3, 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .vmode = FB_VMODE_NONINTERLACED, 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18548c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic struct fb_videomode *default_mode = &default_mode_CRT; 18648c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic struct fb_var_screeninfo *default_var = &default_var_CRT; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int flat_panel_enabled = 0; 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void gbe_reset(void) 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Turn on dotclock PLL */ 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->ctrlstat = 0x300aa000; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function: gbe_turn_off 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Parameters: (None) 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Description: This should turn off the monitor and gbe. This is used 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * when switching between the serial console and the graphics 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * console. 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 205b6d57ae97af3c38d28f066b5e47b7d58e468728aDmitri Vorobievstatic void gbe_turn_off(void) 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int val, x, y, vpixen_off; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2108d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer gbe_turned_on = 0; 2118d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check if pixel counter is on */ 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = gbe->vt_xy; 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (GET_GBE_FIELD(VT_XY, FREEZE, val) == 1) 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* turn off DMA */ 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = gbe->ovr_control; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(OVR_CONTROL, OVR_DMA_ENABLE, val, 0); 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->ovr_control = val; 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(1000); 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = gbe->frm_control; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, val, 0); 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->frm_control = val; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(1000); 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = gbe->did_control; 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(DID_CONTROL, DID_DMA_ENABLE, val, 0); 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->did_control = val; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(1000); 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We have to wait through two vertical retrace periods before 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the pixel DMA is turned off for sure. */ 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 10000; i++) { 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = gbe->frm_inhwctrl; 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (GET_GBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, val)) { 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(10); 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = gbe->ovr_inhwctrl; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (GET_GBE_FIELD(OVR_INHWCTRL, OVR_DMA_ENABLE, val)) { 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(10); 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = gbe->did_inhwctrl; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (GET_GBE_FIELD(DID_INHWCTRL, DID_DMA_ENABLE, val)) { 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(10); 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i == 10000) 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "gbefb: turn off DMA timed out\n"); 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* wait for vpixen_off */ 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = gbe->vt_vpixen; 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vpixen_off = GET_GBE_FIELD(VT_VPIXEN, VPIXEN_OFF, val); 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 100000; i++) { 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = gbe->vt_xy; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds x = GET_GBE_FIELD(VT_XY, X, val); 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds y = GET_GBE_FIELD(VT_XY, Y, val); 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (y < vpixen_off) 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(1); 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i == 100000) 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "gbefb: wait for vpixen_off timed out\n"); 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 10000; i++) { 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = gbe->vt_xy; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds x = GET_GBE_FIELD(VT_XY, X, val); 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds y = GET_GBE_FIELD(VT_XY, Y, val); 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (y > vpixen_off) 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(1); 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i == 10000) 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "gbefb: wait for vpixen_off timed out\n"); 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* turn off pixel counter */ 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_XY, FREEZE, val, 1); 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->vt_xy = val; 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(10000); 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 10000; i++) { 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = gbe->vt_xy; 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (GET_GBE_FIELD(VT_XY, FREEZE, val) != 1) 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(10); 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i == 10000) 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "gbefb: turn off pixel clock timed out\n"); 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* turn off dot clock */ 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = gbe->dotclock; 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(DOTCLK, RUN, val, 0); 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->dotclock = val; 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(10000); 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 10000; i++) { 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = gbe->dotclock; 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (GET_GBE_FIELD(DOTCLK, RUN, val)) 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(10); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i == 10000) 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "gbefb: turn off dotclock timed out\n"); 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reset the frame DMA FIFO */ 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = gbe->frm_size_tile; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(FRM_SIZE_TILE, FRM_FIFO_RESET, val, 1); 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->frm_size_tile = val; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(FRM_SIZE_TILE, FRM_FIFO_RESET, val, 0); 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->frm_size_tile = val; 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void gbe_turn_on(void) 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int val, i; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Check if pixel counter is off, for unknown reason this 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * code hangs Visual Workstations 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gbe_revision < 2) { 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = gbe->vt_xy; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (GET_GBE_FIELD(VT_XY, FREEZE, val) == 0) 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* turn on dot clock */ 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = gbe->dotclock; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(DOTCLK, RUN, val, 1); 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->dotclock = val; 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(10000); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 10000; i++) { 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = gbe->dotclock; 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (GET_GBE_FIELD(DOTCLK, RUN, val) != 1) 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(10); 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i == 10000) 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "gbefb: turn on dotclock timed out\n"); 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* turn on pixel counter */ 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_XY, FREEZE, val, 0); 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->vt_xy = val; 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(10000); 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 10000; i++) { 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = gbe->vt_xy; 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (GET_GBE_FIELD(VT_XY, FREEZE, val)) 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(10); 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i == 10000) 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "gbefb: turn on pixel clock timed out\n"); 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* turn on DMA */ 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = gbe->frm_control; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, val, 1); 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->frm_control = val; 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(1000); 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 10000; i++) { 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = gbe->frm_inhwctrl; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (GET_GBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, val) != 1) 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(10); 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i == 10000) 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "gbefb: turn on DMA timed out\n"); 3758d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer 3768d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer gbe_turned_on = 1; 3778d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer} 3788d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer 3798d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerferstatic void gbe_loadcmap(void) 3808d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer{ 3818d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer int i, j; 3828d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer 3838d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer for (i = 0; i < 256; i++) { 3848d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer for (j = 0; j < 1000 && gbe->cm_fifo >= 63; j++) 3858d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer udelay(10); 3868d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer if (j == 1000) 3878d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer printk(KERN_ERR "gbefb: cmap FIFO timeout\n"); 3888d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer 3898d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer gbe->cmap[i] = gbe_cmap[i]; 3908d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer } 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Blank the display. 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gbefb_blank(int blank, struct fb_info *info) 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */ 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (blank) { 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FB_BLANK_UNBLANK: /* unblank */ 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe_turn_on(); 4028d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer gbe_loadcmap(); 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FB_BLANK_NORMAL: /* blank */ 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe_turn_off(); 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Nothing */ 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Setup flatpanel related registers. 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void gbefb_setup_flatpanel(struct gbe_timing_info *timing) 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int fp_wid, fp_hgt, fp_vbs, fp_vbe; 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 outputVal = 0; 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_FLAGS, HDRV_INVERT, outputVal, 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (timing->flags & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1); 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_FLAGS, VDRV_INVERT, outputVal, 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (timing->flags & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1); 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->vt_flags = outputVal; 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Turn on the flat panel */ 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fp_wid = 1600; 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fp_hgt = 1024; 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fp_vbs = 0; 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fp_vbe = 1600; 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->pll_m = 4; 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->pll_n = 1; 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->pll_p = 0; 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outputVal = 0; 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(FP_DE, ON, outputVal, fp_vbs); 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(FP_DE, OFF, outputVal, fp_vbe); 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->fp_de = outputVal; 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outputVal = 0; 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(FP_HDRV, OFF, outputVal, fp_wid); 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->fp_hdrv = outputVal; 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outputVal = 0; 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(FP_VDRV, ON, outputVal, 1); 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(FP_VDRV, OFF, outputVal, fp_hgt + 1); 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->fp_vdrv = outputVal; 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct gbe_pll_info { 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int clock_rate; 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int fvco_min; 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int fvco_max; 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct gbe_pll_info gbe_pll_table[2] = { 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 20, 80, 220 }, 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 27, 80, 220 }, 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int compute_gbe_timing(struct fb_var_screeninfo *var, 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct gbe_timing_info *timing) 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int pll_m, pll_n, pll_p, error, best_m, best_n, best_p, best_error; 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int pixclock; 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct gbe_pll_info *gbe_pll; 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gbe_revision < 2) 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe_pll = &gbe_pll_table[0]; 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe_pll = &gbe_pll_table[1]; 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Determine valid resolution and timing 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GBE crystal runs at 20Mhz or 27Mhz 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pll_m, pll_n, pll_p define the following frequencies 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fvco = pll_m * 20Mhz / pll_n 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fout = fvco / (2**pll_p) */ 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds best_error = 1000000000; 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds best_n = best_m = best_p = 0; 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (pll_p = 0; pll_p < 4; pll_p++) 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (pll_m = 1; pll_m < 256; pll_m++) 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (pll_n = 1; pll_n < 64; pll_n++) { 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pixclock = (1000000 / gbe_pll->clock_rate) * 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (pll_n << pll_p) / pll_m; 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = var->pixclock - pixclock; 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (error < 0) 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = -error; 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (error < best_error && 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pll_m / pll_n > 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe_pll->fvco_min / gbe_pll->clock_rate && 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pll_m / pll_n < 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe_pll->fvco_max / gbe_pll->clock_rate) { 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds best_error = error; 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds best_m = pll_m; 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds best_n = pll_n; 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds best_p = pll_p; 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!best_n || !best_m) 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; /* Resolution to high */ 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pixclock = (1000000 / gbe_pll->clock_rate) * 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (best_n << best_p) / best_m; 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set video timing information */ 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (timing) { 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->width = var->xres; 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->height = var->yres; 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->pll_m = best_m; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->pll_n = best_n; 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->pll_p = best_p; 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->cfreq = gbe_pll->clock_rate * 1000 * timing->pll_m / 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (timing->pll_n << timing->pll_p); 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->htotal = var->left_margin + var->xres + 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->right_margin + var->hsync_len; 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->vtotal = var->upper_margin + var->yres + 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->lower_margin + var->vsync_len; 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->fields_sec = 1000 * timing->cfreq / timing->htotal * 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1000 / timing->vtotal; 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->hblank_start = var->xres; 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->vblank_start = var->yres; 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->hblank_end = timing->htotal; 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->hsync_start = var->xres + var->right_margin + 1; 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->hsync_end = timing->hsync_start + var->hsync_len; 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->vblank_end = timing->vtotal; 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->vsync_start = var->yres + var->lower_margin + 1; 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->vsync_end = timing->vsync_start + var->vsync_len; 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return pixclock; 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void gbe_set_timing_info(struct gbe_timing_info *timing) 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int temp; 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int val; 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup dot clock PLL */ 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(DOTCLK, M, val, timing->pll_m - 1); 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(DOTCLK, N, val, timing->pll_n - 1); 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(DOTCLK, P, val, timing->pll_p); 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(DOTCLK, RUN, val, 0); /* do not start yet */ 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->dotclock = val; 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(10000); 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup pixel counter */ 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_XYMAX, MAXX, val, timing->htotal); 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_XYMAX, MAXY, val, timing->vtotal); 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->vt_xymax = val; 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup video timing signals */ 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_VSYNC, VSYNC_ON, val, timing->vsync_start); 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_VSYNC, VSYNC_OFF, val, timing->vsync_end); 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->vt_vsync = val; 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_HSYNC, HSYNC_ON, val, timing->hsync_start); 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_HSYNC, HSYNC_OFF, val, timing->hsync_end); 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->vt_hsync = val; 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_VBLANK, VBLANK_ON, val, timing->vblank_start); 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_VBLANK, VBLANK_OFF, val, timing->vblank_end); 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->vt_vblank = val; 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_HBLANK, HBLANK_ON, val, 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->hblank_start - 5); 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_HBLANK, HBLANK_OFF, val, 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->hblank_end - 3); 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->vt_hblank = val; 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup internal timing signals */ 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_VCMAP, VCMAP_ON, val, timing->vblank_start); 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_VCMAP, VCMAP_OFF, val, timing->vblank_end); 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->vt_vcmap = val; 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_HCMAP, HCMAP_ON, val, timing->hblank_start); 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_HCMAP, HCMAP_OFF, val, timing->hblank_end); 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->vt_hcmap = val; 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp = timing->vblank_start - timing->vblank_end - 1; 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (temp > 0) 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp = -temp; 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (flat_panel_enabled) 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbefb_setup_flatpanel(timing); 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(DID_START_XY, DID_STARTY, val, (u32) temp); 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (timing->hblank_end >= 20) 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(DID_START_XY, DID_STARTX, val, 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->hblank_end - 20); 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(DID_START_XY, DID_STARTX, val, 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->htotal - (20 - timing->hblank_end)); 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->did_start_xy = val; 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(CRS_START_XY, CRS_STARTY, val, (u32) (temp + 1)); 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (timing->hblank_end >= GBE_CRS_MAGIC) 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(CRS_START_XY, CRS_STARTX, val, 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->hblank_end - GBE_CRS_MAGIC); 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(CRS_START_XY, CRS_STARTX, val, 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->htotal - (GBE_CRS_MAGIC - 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timing->hblank_end)); 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->crs_start_xy = val; 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VC_START_XY, VC_STARTY, val, (u32) temp); 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VC_START_XY, VC_STARTX, val, timing->hblank_end - 4); 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->vc_start_xy = val; 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp = timing->hblank_end - GBE_PIXEN_MAGIC_ON; 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (temp < 0) 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp += timing->htotal; /* allow blank to wrap around */ 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_HPIXEN, HPIXEN_ON, val, temp); 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_HPIXEN, HPIXEN_OFF, val, 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((temp + timing->width - 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GBE_PIXEN_MAGIC_OFF) % timing->htotal)); 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->vt_hpixen = val; 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_VPIXEN, VPIXEN_ON, val, timing->vblank_end); 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_VPIXEN, VPIXEN_OFF, val, timing->vblank_start); 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->vt_vpixen = val; 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* turn off sync on green */ 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(VT_FLAGS, SYNC_LOW, val, 1); 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->vt_flags = val; 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the hardware according to 'par'. 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gbefb_set_par(struct fb_info *info) 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int val; 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int wholeTilesX, partTilesX, maxPixelsPerTileX; 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int height_pix; 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int xpmax, ypmax; /* Monitor resolution */ 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int bytesPerPixel; /* Bytes per pixel */ 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct gbefb_par *par = (struct gbefb_par *) info->par; 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds compute_gbe_timing(&info->var, &par->timing); 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bytesPerPixel = info->var.bits_per_pixel / 8; 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->fix.line_length = info->var.xres_virtual * bytesPerPixel; 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds xpmax = par->timing.width; 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ypmax = par->timing.height; 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* turn off GBE */ 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe_turn_off(); 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set timing info */ 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe_set_timing_info(&par->timing); 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* initialize DIDs */ 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (bytesPerPixel) { 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_I8); 67668b06deb2b343c040485a9fc6c813577bf6d5cf5Kaj-Michael Lang info->fix.visual = FB_VISUAL_PSEUDOCOLOR; 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_ARGB5); 68068b06deb2b343c040485a9fc6c813577bf6d5cf5Kaj-Michael Lang info->fix.visual = FB_VISUAL_TRUECOLOR; 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 4: 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_RGB8); 68468b06deb2b343c040485a9fc6c813577bf6d5cf5Kaj-Michael Lang info->fix.visual = FB_VISUAL_TRUECOLOR; 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(WID, BUF, val, GBE_BMODE_BOTH); 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 32; i++) 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->mode_regs[i] = val; 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Initialize interrupts */ 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->vt_intr01 = 0xffffffff; 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->vt_intr23 = 0xffffffff; 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* HACK: 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The GBE hardware uses a tiled memory to screen mapping. Tiles are 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds blocks of 512x128, 256x128 or 128x128 pixels, respectively for 8bit, 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16bit and 32 bit modes (64 kB). They cover the screen with partial 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tiles on the right and/or bottom of the screen if needed. 701af901ca181d92aac3a7dc265144a9081a86d8f39André Goddard Rosa For example in 640x480 8 bit mode the mapping is: 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds <-------- 640 -----> 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds <---- 512 ----><128|384 offscreen> 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ^ ^ 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | 128 [tile 0] [tile 1] 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | v 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ^ 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4 128 [tile 2] [tile 3] 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8 v 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0 ^ 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 128 [tile 4] [tile 5] 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | v 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ^ 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds v 96 [tile 6] [tile 7] 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32 offscreen 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Tiles have the advantage that they can be allocated individually in 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memory. However, this mapping is not linear at all, which is not 72025985edcedea6396277003854657b5f3cb31a628Lucas De Marchi really convenient. In order to support linear addressing, the GBE 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DMA hardware is fooled into thinking the screen is only one tile 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds large and but has a greater height, so that the DMA transfer covers 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the same region. 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Tiles are still allocated as independent chunks of 64KB of 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continuous physical memory and remapped so that the kernel sees the 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds framebuffer as a continuous virtual memory. The GBE tile table is 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set up so that each tile references one of these 64k blocks: 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GBE -> tile list framebuffer TLB <------------ CPU 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [ tile 0 ] -> [ 64KB ] <- [ 16x 4KB page entries ] ^ 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ... ... ... linear virtual FB 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [ tile n ] -> [ 64KB ] <- [ 16x 4KB page entries ] v 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The GBE hardware is then told that the buffer is 512*tweaked_height, 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds with tweaked_height = real_width*real_height/pixels_per_tile. 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Thus the GBE hardware will scan the first tile, filing the first 64k 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds covered region of the screen, and then will proceed to the next 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tile, until the whole screen is covered. 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Here is what would happen at 640x480 8bit: 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds normal tiling linear 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ^ 11111111111111112222 11111111111111111111 ^ 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 128 11111111111111112222 11111111111111111111 102 lines 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11111111111111112222 11111111111111111111 v 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V 11111111111111112222 11111111222222222222 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33333333333333334444 22222222222222222222 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33333333333333334444 22222222222222222222 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds < 512 > < 256 > 102*640+256 = 64k 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NOTE: The only mode for which this is not working is 800x600 8bit, 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds as 800*600/512 = 937.5 which is not integer and thus causes 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flickering. 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds I guess this is not so important as one can use 640x480 8bit or 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 800x600 16bit anyway. 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Tell gbe about the tiles table location */ 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* tile_ptr -> [ tile 1 ] -> FB mem */ 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* [ tile 2 ] -> FB mem */ 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ... */ 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(FRM_CONTROL, FRM_TILE_PTR, val, gbe_tiles.dma >> 9); 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, val, 0); /* do not start */ 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(FRM_CONTROL, FRM_LINEAR, val, 0); 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->frm_control = val; 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maxPixelsPerTileX = 512 / bytesPerPixel; 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wholeTilesX = 1; 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds partTilesX = 0; 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Initialize the framebuffer */ 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(FRM_SIZE_TILE, FRM_WIDTH_TILE, val, wholeTilesX); 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(FRM_SIZE_TILE, FRM_RHS, val, partTilesX); 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (bytesPerPixel) { 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, val, 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GBE_FRM_DEPTH_8); 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, val, 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GBE_FRM_DEPTH_16); 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 4: 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, val, 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GBE_FRM_DEPTH_32); 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->frm_size_tile = val; 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* compute tweaked height */ 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds height_pix = xpmax * ypmax / maxPixelsPerTileX; 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_GBE_FIELD(FRM_SIZE_PIXEL, FB_HEIGHT_PIX, val, height_pix); 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->frm_size_pixel = val; 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* turn off DID and overlay DMA */ 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->did_control = 0; 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->ovr_width_tile = 0; 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Turn off mouse cursor */ 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->crs_ctl = 0; 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Turn on GBE */ 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe_turn_on(); 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Initialize the gamma map */ 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(10); 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 256; i++) 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe->gmap[i] = (i << 24) | (i << 16) | (i << 8); 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Initialize the color map */ 8178d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer for (i = 0; i < 256; i++) 8188d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer gbe_cmap[i] = (i << 8) | (i << 16) | (i << 24); 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8208d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer gbe_loadcmap(); 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void gbefb_encode_fix(struct fb_fix_screeninfo *fix, 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fb_var_screeninfo *var) 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(fix, 0, sizeof(struct fb_fix_screeninfo)); 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(fix->id, "SGI GBE"); 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fix->smem_start = (unsigned long) gbe_mem; 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fix->smem_len = gbe_mem_size; 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fix->type = FB_TYPE_PACKED_PIXELS; 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fix->type_aux = 0; 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fix->accel = FB_ACCEL_NONE; 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (var->bits_per_pixel) { 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 8: 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fix->visual = FB_VISUAL_PSEUDOCOLOR; 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fix->visual = FB_VISUAL_TRUECOLOR; 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fix->ywrapstep = 0; 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fix->xpanstep = 0; 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fix->ypanstep = 0; 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fix->line_length = var->xres_virtual * var->bits_per_pixel / 8; 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fix->mmio_start = GBE_BASE; 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fix->mmio_len = sizeof(struct sgi_gbe); 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set a single color register. The values supplied are already 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * rounded down to the hardware's capabilities (according to the 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * entries in the var structure). Return != 0 for invalid regno. 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gbefb_setcolreg(unsigned regno, unsigned red, unsigned green, 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned blue, unsigned transp, 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fb_info *info) 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (regno > 255) 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds red >>= 8; 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds green >>= 8; 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds blue >>= 8; 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8699058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplas if (info->var.bits_per_pixel <= 8) { 8708d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer gbe_cmap[regno] = (red << 24) | (green << 16) | (blue << 8); 8718d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer if (gbe_turned_on) { 8728d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer /* wait for the color map FIFO to have a free entry */ 8738d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer for (i = 0; i < 1000 && gbe->cm_fifo >= 63; i++) 8748d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer udelay(10); 8758d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer if (i == 1000) { 8768d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer printk(KERN_ERR "gbefb: cmap FIFO timeout\n"); 8778d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer return 1; 8788d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer } 8798d0b1c51eb8375f88c0886d2e9f71881e19d42a7Thomas Bogendoerfer gbe->cmap[regno] = gbe_cmap[regno]; 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8819058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplas } else if (regno < 16) { 8829058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplas switch (info->var.bits_per_pixel) { 8839058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplas case 15: 8849058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplas case 16: 8859058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplas red >>= 3; 8869058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplas green >>= 3; 8879058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplas blue >>= 3; 8889058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplas pseudo_palette[regno] = 8899058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplas (red << info->var.red.offset) | 8909058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplas (green << info->var.green.offset) | 8919058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplas (blue << info->var.blue.offset); 8929058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplas break; 8939058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplas case 32: 8949058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplas pseudo_palette[regno] = 8959058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplas (red << info->var.red.offset) | 8969058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplas (green << info->var.green.offset) | 8979058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplas (blue << info->var.blue.offset); 8989058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplas break; 8999058be43cf9f32b6c636aa6954b4f1a6b22098f6Antonino A. Daplas } 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Check video mode validity, eventually modify var to best match. 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gbefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int line_length; 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct gbe_timing_info timing; 9126405141fb3d06ec4a50d054a113e3317cad054f9roel kluin int ret; 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Limit bpp to 8, 16, and 32 */ 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (var->bits_per_pixel <= 8) 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->bits_per_pixel = 8; 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (var->bits_per_pixel <= 16) 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->bits_per_pixel = 16; 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (var->bits_per_pixel <= 32) 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->bits_per_pixel = 32; 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check the mode can be mapped linearly with the tile table trick. */ 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This requires width x height x bytes/pixel be a multiple of 512 */ 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((var->xres * var->yres * var->bits_per_pixel) & 4095) 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->grayscale = 0; /* No grayscale for now */ 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9316405141fb3d06ec4a50d054a113e3317cad054f9roel kluin ret = compute_gbe_timing(var, &timing); 9326405141fb3d06ec4a50d054a113e3317cad054f9roel kluin var->pixclock = ret; 9336405141fb3d06ec4a50d054a113e3317cad054f9roel kluin if (ret < 0) 9346405141fb3d06ec4a50d054a113e3317cad054f9roel kluin return -EINVAL; 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Adjust virtual resolution, if necessary */ 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (var->xres > var->xres_virtual || (!ywrap && !ypan)) 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->xres_virtual = var->xres; 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (var->yres > var->yres_virtual || (!ywrap && !ypan)) 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->yres_virtual = var->yres; 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (var->vmode & FB_VMODE_CONUPDATE) { 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->vmode |= FB_VMODE_YWRAP; 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->xoffset = info->var.xoffset; 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->yoffset = info->var.yoffset; 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* No grayscale for now */ 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->grayscale = 0; 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Memory limit */ 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds line_length = var->xres_virtual * var->bits_per_pixel / 8; 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (line_length * var->yres_virtual > gbe_mem_size) 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; /* Virtual resolution too high */ 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (var->bits_per_pixel) { 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 8: 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->red.offset = 0; 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->red.length = 8; 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->green.offset = 0; 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->green.length = 8; 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->blue.offset = 0; 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->blue.length = 8; 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->transp.offset = 0; 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->transp.length = 0; 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 16: /* RGB 1555 */ 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->red.offset = 10; 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->red.length = 5; 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->green.offset = 5; 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->green.length = 5; 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->blue.offset = 0; 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->blue.length = 5; 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->transp.offset = 0; 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->transp.length = 0; 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 32: /* RGB 8888 */ 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->red.offset = 24; 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->red.length = 8; 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->green.offset = 16; 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->green.length = 8; 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->blue.offset = 8; 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->blue.length = 8; 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->transp.offset = 0; 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->transp.length = 8; 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->red.msb_right = 0; 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->green.msb_right = 0; 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->blue.msb_right = 0; 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->transp.msb_right = 0; 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->left_margin = timing.htotal - timing.hsync_end; 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->right_margin = timing.hsync_start - timing.width; 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->upper_margin = timing.vtotal - timing.vsync_end; 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->lower_margin = timing.vsync_start - timing.height; 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->hsync_len = timing.hsync_end - timing.hsync_start; 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->vsync_len = timing.vsync_end - timing.vsync_start; 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1003216d526c89d144928f095f2800bc6c67e968d628Christoph Hellwigstatic int gbefb_mmap(struct fb_info *info, 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vm_area_struct *vma) 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long size = vma->vm_end - vma->vm_start; 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long addr; 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long phys_addr, phys_size; 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 *tile; 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check range */ 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 101504f8afbec37f63fafce16e454a7848426aa36202Tomi Valkeinen if (size > gbe_mem_size) 101604f8afbec37f63fafce16e454a7848426aa36202Tomi Valkeinen return -EINVAL; 101704f8afbec37f63fafce16e454a7848426aa36202Tomi Valkeinen if (offset > gbe_mem_size - size) 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* remap using the fastest write-through mode on architecture */ 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* try not polluting the cache when possible */ 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pgprot_val(vma->vm_page_prot) = 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pgprot_fb(pgprot_val(vma->vm_page_prot)); 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1025314e51b9851b4f4e8ab302243ff5a6fc6147f379Konstantin Khlebnikov /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */ 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* look for the starting tile */ 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tile = &gbe_tiles.cpu[offset >> TILE_SHIFT]; 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr = vma->vm_start; 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset &= TILE_MASK; 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* remap each tile separately */ 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds phys_addr = (((unsigned long) (*tile)) << TILE_SHIFT) + offset; 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((offset + size) < TILE_SIZE) 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds phys_size = size; 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds phys_size = TILE_SIZE - offset; 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (remap_pfn_range(vma, addr, phys_addr >> PAGE_SHIFT, 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds phys_size, vma->vm_page_prot)) 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EAGAIN; 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset = 0; 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size -= phys_size; 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr += phys_size; 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tile++; 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (size); 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct fb_ops gbefb_ops = { 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fb_check_var = gbefb_check_var, 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fb_set_par = gbefb_set_par, 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fb_setcolreg = gbefb_setcolreg, 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fb_mmap = gbefb_mmap, 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fb_blank = gbefb_blank, 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fb_fillrect = cfb_fillrect, 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fb_copyarea = cfb_copyarea, 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fb_imageblit = cfb_imageblit, 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sysfs 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1069060b8845e6bea938d65ad6f89e83507e5ff4fec4Yani Ioannoustatic ssize_t gbefb_show_memsize(struct device *dev, struct device_attribute *attr, char *buf) 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10717e81b9ddf2be0f691bf883acfe2b2ee6e55baa7eMasanari Iida return snprintf(buf, PAGE_SIZE, "%u\n", gbe_mem_size); 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(size, S_IRUGO, gbefb_show_memsize, NULL); 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1076060b8845e6bea938d65ad6f89e83507e5ff4fec4Yani Ioannoustatic ssize_t gbefb_show_rev(struct device *device, struct device_attribute *attr, char *buf) 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return snprintf(buf, PAGE_SIZE, "%d\n", gbe_revision); 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(revision, S_IRUGO, gbefb_show_rev, NULL); 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 108348c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic void gbefb_remove_sysfs(struct device *dev) 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_remove_file(dev, &dev_attr_size); 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_remove_file(dev, &dev_attr_revision); 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void gbefb_create_sysfs(struct device *dev) 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(dev, &dev_attr_size); 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(dev, &dev_attr_revision); 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialization 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 109948c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic int gbefb_setup(char *options) 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *this_opt; 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!options || !*options) 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((this_opt = strsep(&options, ",")) != NULL) { 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!strncmp(this_opt, "monitor:", 8)) { 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!strncmp(this_opt + 8, "crt", 3)) { 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flat_panel_enabled = 0; 11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default_var = &default_var_CRT; 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default_mode = &default_mode_CRT; 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (!strncmp(this_opt + 8, "1600sw", 6) || 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds !strncmp(this_opt + 8, "lcd", 3)) { 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flat_panel_enabled = 1; 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default_var = &default_var_LCD; 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default_mode = &default_mode_LCD; 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (!strncmp(this_opt, "mem:", 4)) { 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe_mem_size = memparse(this_opt + 4, &this_opt); 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gbe_mem_size > CONFIG_FB_GBE_MEM * 1024 * 1024) 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe_mem_size = CONFIG_FB_GBE_MEM * 1024 * 1024; 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gbe_mem_size < TILE_SIZE) 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe_mem_size = TILE_SIZE; 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode_option = this_opt; 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 113048c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic int gbefb_probe(struct platform_device *p_dev) 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, ret = 0; 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fb_info *info; 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct gbefb_par *par; 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef MODULE 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *options = NULL; 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info = framebuffer_alloc(sizeof(struct gbefb_par), &p_dev->dev); 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!info) 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef MODULE 1144f35691062a138484b51bf53b36ae8a4495d8fb91Julia Lawall if (fb_get_options("gbefb", &options)) { 1145f35691062a138484b51bf53b36ae8a4495d8fb91Julia Lawall ret = -ENODEV; 1146f35691062a138484b51bf53b36ae8a4495d8fb91Julia Lawall goto out_release_framebuffer; 1147f35691062a138484b51bf53b36ae8a4495d8fb91Julia Lawall } 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbefb_setup(options); 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11510fdd07f77fd9cc6a7d49076793daef06ea5d8f13Julia Lawall if (!request_mem_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) { 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "gbefb: couldn't reserve mmio region\n"); 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EBUSY; 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_release_framebuffer; 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1157ae1937f69b1f04dcb2a855d66f94860a6bcf7620Damien Cassou gbe = (struct sgi_gbe *) devm_ioremap(&p_dev->dev, GBE_BASE, 1158ae1937f69b1f04dcb2a855d66f94860a6bcf7620Damien Cassou sizeof(struct sgi_gbe)); 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!gbe) { 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "gbefb: couldn't map mmio region\n"); 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENXIO; 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_release_mem_region; 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe_revision = gbe->ctrlstat & 15; 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe_tiles.cpu = 11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_alloc_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t), 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &gbe_tiles.dma, GFP_KERNEL); 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!gbe_tiles.cpu) { 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "gbefb: couldn't allocate tiles table\n"); 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 1172ae1937f69b1f04dcb2a855d66f94860a6bcf7620Damien Cassou goto out_release_mem_region; 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gbe_mem_phys) { 11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* memory was allocated at boot time */ 1177ae1937f69b1f04dcb2a855d66f94860a6bcf7620Damien Cassou gbe_mem = devm_ioremap_nocache(&p_dev->dev, gbe_mem_phys, 1178ae1937f69b1f04dcb2a855d66f94860a6bcf7620Damien Cassou gbe_mem_size); 11796d7bf017e821f3c093c80d1ee919d8d87904701cThiemo Seufer if (!gbe_mem) { 11806d7bf017e821f3c093c80d1ee919d8d87904701cThiemo Seufer printk(KERN_ERR "gbefb: couldn't map framebuffer\n"); 11816d7bf017e821f3c093c80d1ee919d8d87904701cThiemo Seufer ret = -ENOMEM; 11826d7bf017e821f3c093c80d1ee919d8d87904701cThiemo Seufer goto out_tiles_free; 11836d7bf017e821f3c093c80d1ee919d8d87904701cThiemo Seufer } 11846d7bf017e821f3c093c80d1ee919d8d87904701cThiemo Seufer 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe_dma_addr = 0; 11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* try to allocate memory with the classical allocator 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this has high chance to fail on low memory machines */ 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe_mem = dma_alloc_coherent(NULL, gbe_mem_size, &gbe_dma_addr, 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GFP_KERNEL); 11916d7bf017e821f3c093c80d1ee919d8d87904701cThiemo Seufer if (!gbe_mem) { 11926d7bf017e821f3c093c80d1ee919d8d87904701cThiemo Seufer printk(KERN_ERR "gbefb: couldn't allocate framebuffer memory\n"); 11936d7bf017e821f3c093c80d1ee919d8d87904701cThiemo Seufer ret = -ENOMEM; 11946d7bf017e821f3c093c80d1ee919d8d87904701cThiemo Seufer goto out_tiles_free; 11956d7bf017e821f3c093c80d1ee919d8d87904701cThiemo Seufer } 11966d7bf017e821f3c093c80d1ee919d8d87904701cThiemo Seufer 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe_mem_phys = (unsigned long) gbe_dma_addr; 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_X86 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mtrr_add(gbe_mem_phys, gbe_mem_size, MTRR_TYPE_WRCOMB, 1); 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* map framebuffer memory into tiles table */ 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < (gbe_mem_size >> TILE_SHIFT); i++) 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe_tiles.cpu[i] = (gbe_mem_phys >> TILE_SHIFT) + i; 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->fbops = &gbefb_ops; 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->pseudo_palette = pseudo_palette; 12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->flags = FBINFO_DEFAULT; 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->screen_base = gbe_mem; 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fb_alloc_cmap(&info->cmap, 256, 0); 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reset GBE */ 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe_reset(); 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds par = info->par; 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* turn on default video mode */ 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fb_find_mode(&par->var, info, mode_option, NULL, 0, 12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default_mode, 8) == 0) 12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds par->var = *default_var; 12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->var = par->var; 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbefb_check_var(&par->var, info); 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbefb_encode_fix(&info->fix, &info->var); 12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (register_framebuffer(info) < 0) { 12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "gbefb: couldn't register framebuffer\n"); 12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENXIO; 12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_gbe_unmap; 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12323ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King platform_set_drvdata(p_dev, info); 12333ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King gbefb_create_sysfs(&p_dev->dev); 12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 123531b6780c15a4e3a90fe260e977f5186772ce7afbJoe Perches fb_info(info, "%s rev %d @ 0x%08x using %dkB memory\n", 123631b6780c15a4e3a90fe260e977f5186772ce7afbJoe Perches info->fix.id, gbe_revision, (unsigned)GBE_BASE, 123731b6780c15a4e3a90fe260e977f5186772ce7afbJoe Perches gbe_mem_size >> 10); 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_gbe_unmap: 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gbe_dma_addr) 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys); 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_tiles_free: 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t), 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (void *)gbe_tiles.cpu, gbe_tiles.dma); 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_release_mem_region: 12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_mem_region(GBE_BASE, sizeof(struct sgi_gbe)); 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_release_framebuffer: 12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds framebuffer_release(info); 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 125548c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic int gbefb_remove(struct platform_device* p_dev) 12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12573ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King struct fb_info *info = platform_get_drvdata(p_dev); 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unregister_framebuffer(info); 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gbe_turn_off(); 12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gbe_dma_addr) 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys); 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t), 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (void *)gbe_tiles.cpu, gbe_tiles.dma); 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_mem_region(GBE_BASE, sizeof(struct sgi_gbe)); 1266d30864392823d5f38002fa32950689e651ee11daJoshua Kinard gbefb_remove_sysfs(&p_dev->dev); 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds framebuffer_release(info); 12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12723ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic struct platform_driver gbefb_driver = { 12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = gbefb_probe, 127448c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartman .remove = gbefb_remove, 12753ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King .driver = { 12763ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King .name = "gbefb", 12773ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King }, 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1280abbf268ae8f51e19779cdf3f5fbb8144f1a5fbc3Russell Kingstatic struct platform_device *gbefb_device; 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1282b6d57ae97af3c38d28f066b5e47b7d58e468728aDmitri Vorobievstatic int __init gbefb_init(void) 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12843ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King int ret = platform_driver_register(&gbefb_driver); 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ret) { 1286abbf268ae8f51e19779cdf3f5fbb8144f1a5fbc3Russell King gbefb_device = platform_device_alloc("gbefb", 0); 1287abbf268ae8f51e19779cdf3f5fbb8144f1a5fbc3Russell King if (gbefb_device) { 1288abbf268ae8f51e19779cdf3f5fbb8144f1a5fbc3Russell King ret = platform_device_add(gbefb_device); 1289abbf268ae8f51e19779cdf3f5fbb8144f1a5fbc3Russell King } else { 1290abbf268ae8f51e19779cdf3f5fbb8144f1a5fbc3Russell King ret = -ENOMEM; 1291abbf268ae8f51e19779cdf3f5fbb8144f1a5fbc3Russell King } 1292abbf268ae8f51e19779cdf3f5fbb8144f1a5fbc3Russell King if (ret) { 1293abbf268ae8f51e19779cdf3f5fbb8144f1a5fbc3Russell King platform_device_put(gbefb_device); 12943ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King platform_driver_unregister(&gbefb_driver); 1295abbf268ae8f51e19779cdf3f5fbb8144f1a5fbc3Russell King } 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1300b6d57ae97af3c38d28f066b5e47b7d58e468728aDmitri Vorobievstatic void __exit gbefb_exit(void) 13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1302abbf268ae8f51e19779cdf3f5fbb8144f1a5fbc3Russell King platform_device_unregister(gbefb_device); 13033ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King platform_driver_unregister(&gbefb_driver); 13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(gbefb_init); 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(gbefb_exit); 13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 1310