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

📄 s1d13xxxfb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* drivers/video/s1d13xxxfb.c * * (c) 2004 Simtec Electronics * (c) 2005 Thibaut VARENE <varenet@parisc-linux.org> * * Driver for Epson S1D13xxx series framebuffer chips * * Adapted from *  linux/drivers/video/skeletonfb.c *  linux/drivers/video/epson1355fb.c *  linux/drivers/video/epson/s1d13xxxfb.c (2.4 driver by Epson) * * Note, currently only tested on S1D13806 with 16bit CRT. * As such, this driver might still contain some hardcoded bits relating to * S1D13806. * Making it work on other S1D13XXX chips should merely be a matter of adding * a few switch()s, some missing glue here and there maybe, and split header * files. * * TODO: - handle dual screen display (CRT and LCD at the same time). *	 - check_var(), mode change, etc. *	 - PM untested. *	 - Accelerated interfaces. *	 - Probably not SMP safe :) * * 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. */#include <linux/module.h>#include <linux/platform_device.h>#include <linux/delay.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/mm.h>#include <linux/mman.h>#include <linux/fb.h>#include <asm/io.h>#include <video/s1d13xxxfb.h>#define PFX "s1d13xxxfb: "#if 0#define dbg(fmt, args...) do { printk(KERN_INFO fmt, ## args); } while(0)#else#define dbg(fmt, args...) do { } while (0)#endifstatic const int __devinitconst s1d13xxxfb_revisions[] = {	S1D13506_CHIP_REV,	/* Rev.4 on HP Jornada 7xx S1D13506 */	S1D13806_CHIP_REV,	/* Rev.7 on .. */};/* * Here we define the default struct fb_fix_screeninfo */static struct fb_fix_screeninfo __devinitdata s1d13xxxfb_fix = {	.id		= S1D_FBID,	.type		= FB_TYPE_PACKED_PIXELS,	.visual		= FB_VISUAL_PSEUDOCOLOR,	.xpanstep	= 0,	.ypanstep	= 1,	.ywrapstep	= 0,	.accel		= FB_ACCEL_NONE,};static inline u8s1d13xxxfb_readreg(struct s1d13xxxfb_par *par, u16 regno){#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI3)	regno=((regno & 1) ? (regno & ~1L) : (regno + 1));#endif	return readb(par->regs + regno);}static inline voids1d13xxxfb_writereg(struct s1d13xxxfb_par *par, u16 regno, u8 value){#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI3)	regno=((regno & 1) ? (regno & ~1L) : (regno + 1));#endif	writeb(value, par->regs + regno);}static inline voids1d13xxxfb_runinit(struct s1d13xxxfb_par *par,			const struct s1d13xxxfb_regval *initregs,			const unsigned int size){	int i;	for (i = 0; i < size; i++) {        	if ((initregs[i].addr == S1DREG_DELAYOFF) ||				(initregs[i].addr == S1DREG_DELAYON))			mdelay((int)initregs[i].value);        	else {			s1d13xxxfb_writereg(par, initregs[i].addr, initregs[i].value);		}        }	/* make sure the hardware can cope with us */	mdelay(1);}static inline voidlcd_enable(struct s1d13xxxfb_par *par, int enable){	u8 mode = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);	if (enable)		mode |= 0x01;	else		mode &= ~0x01;	s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, mode);}static inline voidcrt_enable(struct s1d13xxxfb_par *par, int enable){	u8 mode = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);	if (enable)		mode |= 0x02;	else		mode &= ~0x02;	s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, mode);}/* framebuffer control routines */static inline voids1d13xxxfb_setup_pseudocolour(struct fb_info *info){	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;	info->var.red.length = 4;	info->var.green.length = 4;	info->var.blue.length = 4;}static inline voids1d13xxxfb_setup_truecolour(struct fb_info *info){	info->fix.visual = FB_VISUAL_TRUECOLOR;	info->var.bits_per_pixel = 16;	info->var.red.length = 5;	info->var.red.offset = 11;	info->var.green.length = 6;	info->var.green.offset = 5;	info->var.blue.length = 5;	info->var.blue.offset = 0;}/** *      s1d13xxxfb_set_par - Alters the hardware state. *      @info: frame buffer structure * *	Using the fb_var_screeninfo in fb_info we set the depth of the *	framebuffer. This function alters the par AND the *	fb_fix_screeninfo stored in fb_info. It doesn't not alter var in *	fb_info since we are using that data. This means we depend on the *	data in var inside fb_info to be supported by the hardware. *	xxxfb_check_var is always called before xxxfb_set_par to ensure this. * *	XXX TODO: write proper s1d13xxxfb_check_var(), without which that *	function is quite useless. */static ints1d13xxxfb_set_par(struct fb_info *info){	struct s1d13xxxfb_par *s1dfb = info->par;	unsigned int val;	dbg("s1d13xxxfb_set_par: bpp=%d\n", info->var.bits_per_pixel);	if ((s1dfb->display & 0x01))	/* LCD */		val = s1d13xxxfb_readreg(s1dfb, S1DREG_LCD_DISP_MODE);   /* read colour control */	else	/* CRT */		val = s1d13xxxfb_readreg(s1dfb, S1DREG_CRT_DISP_MODE);   /* read colour control */	val &= ~0x07;	switch (info->var.bits_per_pixel) {		case 4:			dbg("pseudo colour 4\n");			s1d13xxxfb_setup_pseudocolour(info);			val |= 2;			break;		case 8:			dbg("pseudo colour 8\n");			s1d13xxxfb_setup_pseudocolour(info);			val |= 3;			break;		case 16:			dbg("true colour\n");			s1d13xxxfb_setup_truecolour(info);			val |= 5;			break;		default:			dbg("bpp not supported!\n");			return -EINVAL;	}	dbg("writing %02x to display mode register\n", val);	if ((s1dfb->display & 0x01))	/* LCD */		s1d13xxxfb_writereg(s1dfb, S1DREG_LCD_DISP_MODE, val);	else	/* CRT */		s1d13xxxfb_writereg(s1dfb, S1DREG_CRT_DISP_MODE, val);	info->fix.line_length  = info->var.xres * info->var.bits_per_pixel;	info->fix.line_length /= 8;	dbg("setting line_length to %d\n", info->fix.line_length);	dbg("done setup\n");	return 0;}/** *  	s1d13xxxfb_setcolreg - sets a color register. *      @regno: Which register in the CLUT we are programming *      @red: The red value which can be up to 16 bits wide *	@green: The green value which can be up to 16 bits wide *	@blue:  The blue value which can be up to 16 bits wide. *	@transp: If supported the alpha value which can be up to 16 bits wide. *      @info: frame buffer info structure * *	Returns negative errno on error, or zero on success. */static ints1d13xxxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,			u_int transp, struct fb_info *info){	struct s1d13xxxfb_par *s1dfb = info->par;	unsigned int pseudo_val;	if (regno >= S1D_PALETTE_SIZE)		return -EINVAL;	dbg("s1d13xxxfb_setcolreg: %d: rgb=%d,%d,%d, tr=%d\n",		    regno, red, green, blue, transp);	if (info->var.grayscale)		red = green = blue = (19595*red + 38470*green + 7471*blue) >> 16;	switch (info->fix.visual) {		case FB_VISUAL_TRUECOLOR:			if (regno >= 16)				return -EINVAL;			/* deal with creating pseudo-palette entries */			pseudo_val  = (red   >> 11) << info->var.red.offset;			pseudo_val |= (green >> 10) << info->var.green.offset;			pseudo_val |= (blue  >> 11) << info->var.blue.offset;			dbg("s1d13xxxfb_setcolreg: pseudo %d, val %08x\n",				    regno, pseudo_val);#if defined(CONFIG_PLAT_MAPPI)			((u32 *)info->pseudo_palette)[regno] = cpu_to_le16(pseudo_val);#else			((u32 *)info->pseudo_palette)[regno] = pseudo_val;#endif			break;		case FB_VISUAL_PSEUDOCOLOR:			s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_ADDR, regno);			s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, red);			s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, green);			s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, blue);			break;		default:			return -ENOSYS;	}	dbg("s1d13xxxfb_setcolreg: done\n");	return 0;}/** *      s1d13xxxfb_blank - blanks the display. *      @blank_mode: the blank mode we want. *      @info: frame buffer structure that represents a single frame buffer * *      Blank the screen if blank_mode != 0, else unblank. Return 0 if *      blanking succeeded, != 0 if un-/blanking failed due to e.g. a *      video mode which doesn't support it. Implements VESA suspend *      and powerdown modes on hardware that supports disabling hsync/vsync: *      blank_mode == 2: suspend vsync *      blank_mode == 3: suspend hsync *      blank_mode == 4: powerdown * *      Returns negative errno on error, or zero on success. */static ints1d13xxxfb_blank(int blank_mode, struct fb_info *info){	struct s1d13xxxfb_par *par = info->par;	dbg("s1d13xxxfb_blank: blank=%d, info=%p\n", blank_mode, info);	switch (blank_mode) {		case FB_BLANK_UNBLANK:		case FB_BLANK_NORMAL:			if ((par->display & 0x01) != 0)				lcd_enable(par, 1);			if ((par->display & 0x02) != 0)				crt_enable(par, 1);			break;		case FB_BLANK_VSYNC_SUSPEND:		case FB_BLANK_HSYNC_SUSPEND:			break;		case FB_BLANK_POWERDOWN:			lcd_enable(par, 0);			crt_enable(par, 0);			break;		default:			return -EINVAL;	}	/* let fbcon do a soft blank for us */	return ((blank_mode == FB_BLANK_NORMAL) ? 1 : 0);}/** *      s1d13xxxfb_pan_display - Pans the display. *      @var: frame buffer variable screen structure *      @info: frame buffer structure that represents a single frame buffer * *	Pan (or wrap, depending on the `vmode' field) the display using the *  	`yoffset' field of the `var' structure (`xoffset'  not yet supported). *  	If the values don't fit, return -EINVAL. * *      Returns negative errno on error, or zero on success. */static ints1d13xxxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){	struct s1d13xxxfb_par *par = info->par;	u32 start;	if (var->xoffset != 0)	/* not yet ... */		return -EINVAL;	if (var->yoffset + info->var.yres > info->var.yres_virtual)		return -EINVAL;	start = (info->fix.line_length >> 1) * var->yoffset;	if ((par->display & 0x01)) {		/* LCD */		s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START0, (start & 0xff));		s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START1, ((start >> 8) & 0xff));		s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START2, ((start >> 16) & 0x0f));	} else {		/* CRT */		s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START0, (start & 0xff));		s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START1, ((start >> 8) & 0xff));		s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START2, ((start >> 16) & 0x0f));	}	return 0;}/* framebuffer information structures */static struct fb_ops s1d13xxxfb_fbops = {	.owner		= THIS_MODULE,	.fb_set_par	= s1d13xxxfb_set_par,	.fb_setcolreg	= s1d13xxxfb_setcolreg,	.fb_blank	= s1d13xxxfb_blank,	.fb_pan_display	= s1d13xxxfb_pan_display,	/* to be replaced by any acceleration we can */	.fb_fillrect	= cfb_fillrect,	.fb_copyarea	= cfb_copyarea,	.fb_imageblit	= cfb_imageblit,};static int s1d13xxxfb_width_tab[2][4] __devinitdata = {

⌨️ 快捷键说明

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