⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s1d13706fb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * linux/drivers/video/s1d13706fb.c *	-- Support for the Epson S1D13706 LCD/CRT controller * * Copyright (C) 2003 Heiko Degenhardt <linux@sentec-elektronik.de> *                    Michael Huhn <michael.huhn@sentec-elektronik.de> *   * based on linux/drivers/video/skeletonfb.c, which was *  Created 28 Dec 1997 by Geert Uytterhoeven * * Some ideas were "stolen" from  *    linux/drivers/video/epson1355fb.c *    that is "Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>" * and from s1d13xxxfb.c and a file called "s1d13706.h" that was *    generated by S1D13706CFG.EXE both are *    "Copyright(c) 2000, 2001 Epson Research and Development, Inc" * * HINT: If someone feels that we used his code but didn't give him * credits here, please email us! It was a quite complicated thing to * get all that working, so may be we just forgot someone! Thanks! *   * 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. *  *//* * CHANGES * * 20030312  *    Creation *    (mihu, hede) *//* *  * ATTENTION! * This stuff is _really_ experimental, currently! * Feedback is really welcome! * *//* define DBUG below if you want to get more verbose output of the   driver *//*#define DBUG*/#include <asm/io.h>#include <linux/config.h>#include <linux/delay.h>#include <linux/errno.h>#include <linux/fb.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/mm.h>#include <linux/module.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/tty.h>#include <video/fbcon-cfb8.h>#include <video/fbcon-mfb.h>#include <video/fbcon.h>#include <asm/coldfire.h>/* -----------------------------------------------------------------------------   Sanity checks -----------------------------------------------------------------------------*//* Are you compiling for our board? * If not I think you know how to solve the error. ;)  */#ifdef CONFIG_COBRA5272/* S1D13706 supports 4Bpp, 8Bpp, 16Bpp */#ifdef CONFIG_FB_S1D13706    #if defined (FBCON_HAS_CFB4) && defined (FBCON_HAS_CFB8)        #error More than one colordepth specified    #endif    #if defined (FBCON_HAS_CFB4) && defined (FBCON_HAS_CFB16)        #error More than one colordepth specified    #endif    #if defined (FBCON_HAS_CFB8) && defined (FBCON_HAS_CFB16)        #error More than one colordepth specified    #endif#include "s1d13706fb.h"#else	#error lcd controller not supported#endif/* Check if at least one supported colordepth was configured */#if !defined (FBCON_HAS_CFB4) && !defined (FBCON_HAS_CFB8) && \    !defined (FBCON_HAS_CFB16)    #error No colordepth specified#endifstatic inline u8 s1d13706_read_reg(int index){	return readb(S1D13706_REG_OFFSET + index);}static inline void s1d13706_write_reg(u8 data, int index){	writeb(data, S1D13706_REG_OFFSET + index);}static inline u16 s1d13706_read_reg16(int index){	return s1d13706_read_reg(index) + (s1d13706_read_reg(index+1) << 8);}static inline void s1d13706_write_reg16(u16 data, int index){	s1d13706_write_reg((data&0xff), index);	s1d13706_write_reg(((data>>8)&0xff), index + 1);}#else /* not on the COBRA5272 board */#error unknown architecture#endifstatic int current_par_valid = 0;static struct display disp;static struct fb_var_screeninfo default_var;static struct fb_fix_screeninfo current_fix = {   id:      "S1D13706",   smem_start: (__u32)S1D13706_FB_BASE, /* initially, we'll fill it later */   smem_len:   320*240, /* initially, we'll fill it later */   type:    FB_TYPE_PACKED_PIXELS, /* this should always be true for dragonballs */   visual:     FB_VISUAL_PSEUDOCOLOR, /* this should depend on LCD used */   line_length:   320,   accel:      FB_ACCEL_NONE, /* but still like a breeze ;-) */};static int currcon = 0;/* ------------------- chipset specific functions -------------------------- */static void s1d13706_detect(void){	u8 rev;	rev = s1d13706_read_reg(S1D13706_REVISION_CODE_REG);	if ((rev & 0xfc) != 0x28) {		printk(KERN_WARNING "Epson 13706 not detected\n");	}		s1d13706_encode_var(&default_var, NULL, NULL);#ifdef DBUG	printk("s1d13706_detect done\n");#endif}static int s1d13706_encode_fix(struct fb_fix_screeninfo *fix,			    const void *raw_par,			    struct fb_info_gen *info){	const struct s1d13706_par *par = raw_par;	memset(fix, 0, sizeof *fix);	fix->type= FB_TYPE_PACKED_PIXELS;	if (!par)		BUG();	if (par->bpp == 1) {		fix->visual = FB_VISUAL_MONO10;	} else if (par->bpp <= 8) {		fix->visual = FB_VISUAL_PSEUDOCOLOR;	} else {		fix->visual = FB_VISUAL_TRUECOLOR;	}	fix->line_length = par->xres;	fix->mmio_start = S1D13706_FB_BASE;	fix->smem_start = S1D13706_FB_BASE;	fix->mmio_len = S1D13706_SRAM_SIZE;	fix->smem_len = S1D13706_SRAM_SIZE;#ifdef DBUG	printk("s1d13706_encode_fix done\n");#endif	return 0;}static int s1d13706_set_bpp(struct s1d13706_par *par, int bpp){	int code;	u8 disp;	u16 bytes_per_line;	switch(bpp) {	case 1:		code = 0; break;	case 2:		code = 1; break;	case 4:		code = 2; break;	case 8:		code = 3; break;	case 16:		code = 4; break;	default:		return -EINVAL; break;	}	disp = s1d13706_read_reg(S1D13706_DISPLAY_MODE_REG);	disp &= ~0x07;       /* Bits 2:0 */	disp |= code;	s1d13706_write_reg(disp, S1D13706_DISPLAY_MODE_REG);	bytes_per_line = ((par->xres * bpp) >> 3) - 1;   /* horizontal displ. period reg */	s1d13706_write_reg16(bytes_per_line, S1D13706_HOR_DISPLAY_MODE_REG);	par->bpp = bpp;#ifdef DBUG	printk("s1d13706_set_bpp started\n");#endif	return 0;}static int s1d13706_decode_var(const struct fb_var_screeninfo *var,			    void *raw_par,			    struct fb_info_gen *info){	struct s1d13706_par *par = raw_par;	int ret;#ifdef DBUG	printk("s1d13706_decode_var started\n");#endif	if (!par)		BUG();	/*	 * Don't allow setting any of these yet: xres and yres don't	 * make sense for LCD panels; xres_virtual and yres_virtual	 * should be supported fine by our hardware though.	 */	if (var->xres != par->xres ||	    var->yres != par->yres ||	    var->xres != var->xres_virtual ||	    var->yres != var->yres_virtual ||	    var->xoffset != 0 ||	    var->yoffset != 0){#ifdef DBUG	printk("s1d13706_decode_var returned -EINVAL\n");#endif		return -EINVAL;	}	if(var->bits_per_pixel != par->bpp) {		ret = s1d13706_set_bpp(par, var->bits_per_pixel);		if (ret)			goto out_err;	}#ifdef DBUG	printk("s1d13706_decode_var returned 0\n");#endif	return 0;	out_err:#ifdef DBUG	printk("s1d13706_decode_var returned %i\n", ret);#endif	return ret;}static void dump_panel_data(void){	u8 panel = s1d13706_read_reg(S1D13706_PANEL_TYPE_REG);	int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } };   char *type[] = {"STN", "TFT", "HR-TFT", "D-DFT"};	printk("%s %s panel, width %d bits\n",	       panel & 0x40 ? "color" : "mono",	       *(type[panel & 0x03]),	       (width[panel&1][(panel>>4)&3]));	printk("resolution %d x %d\n",          /* hor. display period reg.: */	       (s1d13706_read_reg(S1D13706_HOR_DISPLAY_MODE_REG) + 1) * 8,          /* vert. displ. period reg.: */	       ((s1d13706_read_reg16(S1D13706_VERT_DISPLAY_MODE_REG0)+ 1) ));#ifdef DBUG	printk("dump_panel_data done\n");#endif}static int s1d13706_bpp_to_var(int bpp, struct fb_var_screeninfo *var){	switch(bpp) {	case 1:	case 2:	case 4:	case 8:		var->bits_per_pixel = bpp;		var->red.offset = var->green.offset = var->blue.offset = 0;		var->red.length = var->green.length = var->blue.length = bpp;		break;	case 16:		var->bits_per_pixel = 16;		var->red.offset = 11;		var->red.length = 5;		var->green.offset = 5;		var->green.length = 6;		var->blue.offset = 0;		var->blue.length = 5;		break;	}#ifdef DBUG	printk("s1d13706_bpp_to_var done\n");#endif	return 0;}static int s1d13706_encode_var(struct fb_var_screeninfo *var, const void *raw_par,			    struct fb_info_gen *info){	u8 panel, display;	u32 xres, xres_virtual, yres, yres_virtual;	static int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 18, -1 } };	static int bpp_tab[8] = { 1, 2, 4, 8, 16, -1 };	int bpp, hw_bpp;	int is_color, is_tft;	int lcd_enabled;   int xoffset, yoffset;	display = s1d13706_read_reg(S1D13706_DISPLAY_MODE_REG);	panel = s1d13706_read_reg(S1D13706_PANEL_TYPE_REG);	is_color = (panel & 0x40) != 0;	is_tft   = (panel & 0x03) == 0x01;	bpp = bpp_tab[(display) & 0x07];/* BPP is in Bits 2:0 */	s1d13706_bpp_to_var(bpp, var);	lcd_enabled = (display & 0x80) == 0;/* when disabled, data outputs are zero*/	hw_bpp = width[is_tft][(panel>>4)&0x03];   /* Horizontal display period register: */	xres = s1d13706_read_reg(S1D13706_HOR_DISPLAY_MODE_REG) + 1;   /* Vertical display period register: */	yres = s1d13706_read_reg16(S1D13706_VERT_DISPLAY_MODE_REG0) + 1;	xres *= 8;   /* horizontal total resolution: */   xres_virtual = s1d13706_read_reg(S1D13706_HOR_TOTAL_REG);	xres_virtual *= 8;   /* vertical total resolution: */   yres_virtual = s1d13706_read_reg16(S1D13706_VERT_TOTAL_REG0);   /* hor. display period start pos. reg. */   xoffset = s1d13706_read_reg16(S1D13706_HOR_DISP_PERIOD_START_POS_REG0);	yoffset = s1d13706_read_reg16(S1D13706_VERT_DISP_PERIOD_START_POS_REG0);	var->xres = xres;	var->yres = yres;	var->xres_virtual = xres_virtual;	var->yres_virtual = yres_virtual;	var->xoffset = xoffset;   var->yoffset = yoffset;	var->bits_per_pixel = bpp;	var->grayscale = !is_color;#ifdef DBUG	printk("s1d13706_encode_var done\n");#endif	return 0;}static void get_panel_data(struct s1d13706_par *par){	u8 panel;	u8 display;	int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } };	int bpp_tab[8] = { 1, 2, 4, 8, 16, -1 };	panel = s1d13706_read_reg(S1D13706_PANEL_TYPE_REG) & 0x3F;	display = s1d13706_read_reg(S1D13706_DISPLAY_MODE_REG);	par->panel_width = width[panel&1][(panel>>4)&3];   /* horiz. display period reg.: */	par->panel_xres = (s1d13706_read_reg(S1D13706_HOR_DISPLAY_MODE_REG) + 1) * 8;   /* vert. displ. period reg.: */   par->panel_yres = (s1d13706_read_reg16(S1D13706_VERT_DISPLAY_MODE_REG0) + 1);	par->bpp = bpp_tab[(display) & 0x07]; /* BPP is in Bits 2:0 */	par->mem_bpp = par->bpp;	par->xres =	par->panel_xres;	par->yres = par->panel_yres;;#ifdef DBUG	printk("get_panel_data done\n");#endif}static void s1d13706_get_par(void *raw_par, struct fb_info_gen *info){	struct s1d13706_par *par = raw_par;	get_panel_data(par);#ifdef DBUG	printk("s1d13706_get_par done\n");#endif}static void s1d13706_set_par(const void *par, struct fb_info_gen *info){#ifdef DBUG	printk("s1d13706_set_par done\n");#endif}static int s1d13706_getcolreg(unsigned regno, unsigned *red, unsigned *green,			   unsigned *blue, unsigned *transp,			   struct fb_info *info){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -