📄 ep93xxfb.c
字号:
/****************************************************************************** * * File: linux/drivers/video/ep93xxfb.c * * Purpose: Support CRT output on a EP9312/EP9315 evaluation board. * * Build: Define CONFIG_FB, CONFIG_FB_EP93XX * which will bring in: * CONFIG_FONT_8x8 * CONFIG_FONT_8x16 * CONFIG_FONT_ACORN_8x8 * * When building as console, define CONFIG_VT, CONFIG_VT_CONSOLE * and make sure CONFIG_CMDLINE does NOT have "console=" set. * CONFIG_EP93XX_KBD_SPI or CONFIG_EP93XX_KBD_SCANNED should also * be specified. * * History: 010529 Norman Farquhar at LynuxWorks. * * Initial version supports: * - crt only * - fixed frequency monitor timings: 640x480 * - single default video mode supported: 640x480x8 * - no module support because this is core logic * - never will be SMP * * Derived from: arm-linux-2.4.0-test11-rmk1 * linux/drivers/video/sa1100fb.c * Version 2000/08/29 * Copyright (C) 1999 Eric A. Thomas * See file for many other contributors. * * (c) Copyright 2001 LynuxWorks, Inc., San Jose, CA. All rights reserved. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive * for more details. * *============================================================================= * Overview of Frame Buffer driver *============================================================================= * * The frame buffer driver supports the core logic display controller * of the ep93xx family machines. These machines are embedded systems * and this driver provides for a few video modes with small code * footprint. Both CRT and LCD may be supported in the future. * * Generic fb driver model (skeletonfb.c, fbgen.c) is a bit whacked * so this driver has been converted back to simpler older style. * See below for list of complaints about generic fb model! * * * Linux color models supported: * * CFB8 is 8 bit packed pixel format using 256 color LUT * Believed to be similar to Microsoft Windows: * 16 colors VGA standard * 16 grays * 224 color loadable palette * Note: Linux Logo uses 6x6x6=216 color space * * Linux color models NOT supported: * * CFB4 is 4 bit packed pixel format using 16 color LUT * 16 colors VGA standard * CFB16 is 16 bit flexible format (ep93xx uses R5:G6:B5) * CFB24 is 24 bit truecolor R8:G8:B8 * CFB32 is 32 bit truecolor alpha:R8:G8:B8 * * Reminder about setting up /dev device nodes: * * console c 5,1 to virtual console driver * so that Linux bootup is visible * when fb is console. * * fb link /dev/fb0 used by applications * * fb0 c 29,0 to fbmem device * * tty link /dev/console recommended by BinZ for * tty0 link /dev/console older Linux applications * * *============================================================================= * Hardware Details *============================================================================= * * 1. Display controller uses system memory, not a dedicated frame buffer * RAM. This means that display controller bandwidth to RAM steals from * CPU bandwidth to RAM. * * So if bandwidth to memory is about 80MB/s assuming that * all accesses are 16 byte blocks taking 10 clocks on 50MHz * system bus. Then 640x480x8 60Hz is about 19MB/s, or * 1/4 of bus bandwidth which should not impact us badly. * * 2. Dual hw palettes are a way to avoid sparkle and allow updating at * anytime, not just during blank period. Pending hw palette switch * takes place once per frame during blank. * * So we keep the master palette copy in memory and update the active hw * palette by updating the inactive hw palette and then switching. * * The only complication is writing palette while switch is pending. * We assume LUTSTAT is updated synchronously with bus clock so that * writes to LUT complete to either RAM0 or RAM1, even if request to * switch RAMs comes in asynchronously, in the middle of write to LUT. * * 3. Some timing registers must be unlocked before access. * *============================================================================= * Send to www.complaints.linux.com *============================================================================= * * Generic fb model is too messy IMHO and here is my list of * problems with it. * * 1. Note ALL fbgen.c functions really take fb_info_gen, instead of * fb_info parameters, by casting info instead of changing prototype. * * 2. Messy stuff in doing encode/decode var. * * 3. The info structure holds the controlling variables for video. * But data is passed around and variables tweaked inside routines * in which you would not expect it. * * 4. It is not clear that all variables of a structure get inited * properly because it is not done in one spot. * * 5. In the driver model fbskeleton.c, initially, both the 'var' and * 'fix' data are derived from 'par'. This seems backward, and I think * reflects Linux genesis on a PC with a BIOS which has already set the * initial video mode. * * 6. For some reason, there is a local copy of 'par' which is the true * current mode (Why not use the 'par' field in info??). * * 7. Consistency checks are device specific, but fb implementation * is messy: high level video mode requests are pushed down to low * level data 'par' and then pulled back out again to high level * with a consistent, possibly changed mode, changed 'var' * * decode_var really checks var consistency and * translates var to par * * encode_var translates par to var * (one driver just passes back current var * which assumes that par set from var) * *****************************************************************************/#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/errno.h>#include <linux/delay.h>#include <linux/string.h>#include <linux/ctype.h>#include <linux/mm.h>#include <linux/tty.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/fb.h>#include <linux/delay.h>#include <linux/wrapper.h>#include <asm/hardware.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/mach-types.h>#include <asm/uaccess.h>#include <asm/proc/pgtable.h>//TBD some of these may not be needed until full implementation#include <video/fbcon.h>#include <video/fbcon-mfb.h>#include <video/fbcon-cfb4.h>#include <video/fbcon-cfb8.h>#include <video/fbcon-cfb16.h>#include "ep93xxfb.h"#define RasterSetLocked(registername,value) \ { \ outl( 0xAA, REALITI_SWLOCK ); \ outl( value, registername); \ }/* * Debug macros */#ifdef DEBUG# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)#else# define DPRINTK(fmt, args...)#endif// Max palette entries over all video modes#define MAX_PALETTE_NUM_ENTRIES 256// Max X resolution and Y resolution depend on whether LCD is supported,// and the monitor type.#define MAX_CRT_XRES 640#define MAX_CRT_YRES 480// Max bpp is fixed for low resolutions, but fundamentally depends on the// memory bandwidth which the system can allocate to the raster engine,// and so depends on application.//// TBD can create an array which determines max bpp based on passed// TBD in resolutions.//#ifdef CONFIG_FB_EP93XX_8BPP#define MAX_BPP 8#elif defined(CONFIG_FB_EP93XX_16BPP_565)#define MAX_BPP 16#else#define MAX_BPP 32#endif// Framebuffer max mem size in bytes over all video modes// Note: mypar not valid yet so need hard numbers here.#define FB_MAX_MEM_SIZE ((MAX_CRT_XRES * MAX_CRT_YRES * MAX_BPP)/8)// Framebuffer mapped mem size in bytes// This will be an integral number of pages.#define FB_MAPPED_MEM_SIZE (PAGE_ALIGN(FB_MAX_MEM_SIZE + PAGE_SIZE))/* Minimum X and Y resolutions *///TBD how realistic is this for CRT??//#define MIN_XRES 64//#define MIN_YRES 64#define EP93XX_NAME "EP93XX"#define NR_MONTYPES 1/* Local LCD controller parameters *//* These can be reduced by making better use of fb_var_screeninfo parameters.*//* Several duplicates exist in the two structures. */struct ep93xxfb_par{ dma_addr_t p_screen_base; unsigned char *v_screen_base; unsigned long screen_size; unsigned int palette_size; unsigned int xres; unsigned int yres; unsigned int bits_per_pixel; int montype; unsigned int currcon; unsigned int visual; u16 palette[16]; // Funky 16 table lookup used by // "optional" Parameter.};//TBD Linux fbmon.c tries to check monitor support for requested mode.//TBD But 2.4.0 test11 has removed this code from the build./* Fake monspecs to fill in fbinfo structure *///TBD strict VGA monitor has 60,60 instead of 50,65static struct fb_monspecs __initdata monspecs = { 30000, 70000, 50, 65, 0 /* Generic, not fixed frequency */};static char default_font_storage[40];static char *default_font = "Acorn8x8";#if defined (CONFIG_FB_LCD_EP93XX)#define DEFAULT_MODE 1#elif defined (CONFIG_FB_CX25871)#define DEFAULT_MODE 3#elif defined (CONFIG_FB_CRT_EP93XX)#define DEFAULT_MODE 0#else#error What Display Setting was that!!!#endifstatic int mode = DEFAULT_MODE;#ifdef CONFIG_FB_CX25871_OVERSCAN#define DEFAULT_OVERSCAN 1#else#define DEFAULT_OVERSCAN 0#endifstatic int overscan = DEFAULT_OVERSCAN;typedef struct _DisplayTimingValues{ const char *Name; unsigned long DisplayID; int (* RasterConfigure)(struct _DisplayTimingValues *pTimingValues); unsigned short Refresh; unsigned long VDiv; unsigned short HRes; unsigned short HFrontPorch; unsigned short HBackPorch; unsigned short HSyncWidth; unsigned short HTotalClocks; unsigned short VRes; unsigned short VFrontPorch; unsigned short VBackPorch; unsigned short VSyncWidth; unsigned short VTotalClocks;} DisplayTimingValues;typedef int (* fRasterConfigure)(DisplayTimingValues *);typedef enum{ CRT_GENERIC, Philips_LB064V02A1, CX25871, Sharp} DisplayType;#define TIMING_VALUES(NAME, DISPID, FUNC, REFRESH, VDIV, \ HRES, HFP, HBP, HSYNC, VRES, VFP, VBP, VSYNC) \{ \ Name:NAME, \ DISPID, FUNC, REFRESH, VDIV, \ HRES, HFP, HBP, HSYNC, (HRES + HFP + HBP + HSYNC), \ VRES, VFP, VBP, VSYNC, (VRES + VFP + VBP + VSYNC) \}static void InitializeCX25871For640x480NTSC(void);static int Conexant_CX25871(DisplayTimingValues *pTimingValues);static int PhilipsLCD(DisplayTimingValues *pTimingValues);DisplayTimingValues static TimingValues[]={ // // 640x480 Progressive Scan // TIMING_VALUES("CRT_GENERIC", CRT_GENERIC, (fRasterConfigure)0, 60, 0x0000c108, 640, 16, 48, 96, 480, 11, 31, 2), // // 640x480 Progressive Scan Philips LB064V02A1 on EDB9312 Board. // TIMING_VALUES("Philips LB064V02A1", Philips_LB064V02A1, PhilipsLCD, 68, 0x0000c107, 640, 16, 48, 96, 480, 11, 31, 2), // // Sharp LQ64D343 LCD Panel // TIMING_VALUES("Sharp LQ64d343", CRT_GENERIC, (fRasterConfigure)0, 60, 0x0000c205, 640, 32, 32, 96, 480, 34, 34, 4), // // 640x480 NTSC Support for Conexant CX25871 // TIMING_VALUES("Conexant CX25871", CX25871, Conexant_CX25871, 60, 0x0000c317, 640, 0, 0, 0, 480, 0, 0, 0),};#define NUM_TIMING_VALUES (sizeof(TimingValues)/sizeof(DisplayTimingValues))unsigned int master_palette[256]; /* master copy of palette data *///TBD Before fbcon started, the driver calls set_var with con=-1//TBD which initializes global_disp and puts ptr to it in info.//TBD Later on display console array keeps track of display settings.static struct display global_disp; /* Initial Display Settings */static struct fb_info fb_info; // initialized in init_fbinfo()static struct ep93xxfb_par mypar;static int ep93xxfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info);static int ep93xxfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info);static int ep93xxfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info);static int ep93xxfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);static int ep93xxfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);static int ep93xxfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, int con, struct fb_info *info);static int ep93xxfb_switch(int con, struct fb_info *info);static void ep93xxfb_blank(int blank, struct fb_info *info);static int MapFramebuffer(void);static int ConfigureRaster(struct fb_var_screeninfo *var, DisplayTimingValues *pTimingValues);static struct fb_ops ep93xxfb_ops = { owner: THIS_MODULE, fb_get_fix: ep93xxfb_get_fix, fb_get_var: ep93xxfb_get_var, fb_set_var: ep93xxfb_set_var, fb_get_cmap: ep93xxfb_get_cmap, fb_set_cmap: ep93xxfb_set_cmap, fb_ioctl: ep93xxfb_ioctl,};//-----------------------------------------------------------------------------// Local functions//-----------------------------------------------------------------------------/* * ep93xxfb_palette_write: * Encode palette data to 24bit palette format. * Write palette data to the master palette and inactive hw palette * switch palettes. And handle asynchronous palette switches. */static inline voidep93xxfb_palette_write(u_int regno, u_int red, u_int green, u_int blue, u_int trans){ unsigned int cont, i, pal; // Only supports color LUT, not gray LUT // // TBD if not in 4 or 8bpp, then does LUT logic operate? // TBD or do we need to do nothing here? // LCD: TBD RGB mapping may match spec p193. // // CRT: LUT RGB mapping is really R/G/B from high to low bits // because really determined by wiring to video DAC. // (disregard spec p 193 showing color LUT B/G/R order) // Here are the details: // // Shift mode 1 directs LUT bits 7-2 onto P5-P0, // LUT bits 15-10 onto P11-P6, and LUT bits 23-16 // onto P17-P12. // // Board wired P17-12 to video DAC Red inputs, // P11-P6 wired to video DAC Green inputs, and // P5-P0 wired to video DAC Blue inputs. // pal = ((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8); master_palette[regno] = pal; // Two cases here: // 1. If LUT switch is pending, then write inactive LUT and when // switch happens, this new palette entry will be active. // Race condition here between LUT switch and this write is okay // since we fix it below. // // 2. If LUT switch is not pending, then write here is incomplete // and whole palette will be written below.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -