^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");