Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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