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

📄 sa1100fb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 5 页
字号:
{	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;	return (con == fbi->currcon || con == -1) ? &fbi->fb.var : &fb_display[con].var;}/* * Get the DISPLAY structure pointer for the specified console */static inline struct display *get_con_display(struct fb_info *info, int con){	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;	return (con < 0) ? fbi->fb.disp : &fb_display[con];}/* * Get the CMAP pointer for the specified console */static inline struct fb_cmap *get_con_cmap(struct fb_info *info, int con){	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;	return (con == fbi->currcon || con == -1) ? &fbi->fb.cmap : &fb_display[con].cmap;}static inline u_intchan_to_field(u_int chan, struct fb_bitfield *bf){	chan &= 0xffff;	chan >>= 16 - bf->length;	return chan << bf->offset;}/* * Convert bits-per-pixel to a hardware palette PBS value. */static inline u_intpalette_pbs(struct fb_var_screeninfo *var){	int ret = 0;	switch (var->bits_per_pixel) {#ifdef FBCON_HAS_CFB4	case 4:  ret = 0 << 12;	break;#endif#ifdef FBCON_HAS_CFB8	case 8:  ret = 1 << 12; break;#endif#ifdef FBCON_HAS_CFB16	case 16: ret = 2 << 12; break;#endif	}	return ret;}static intsa1100fb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,		       u_int trans, struct fb_info *info){	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;	u_int val, ret = 1;	if (regno < fbi->palette_size) {		val = ((red >> 4) & 0xf00);		val |= ((green >> 8) & 0x0f0);		val |= ((blue >> 12) & 0x00f);		if (regno == 0)			val |= palette_pbs(&fbi->fb.var);		fbi->palette_cpu[regno] = val;		ret = 0;	}	return ret;}static intsa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,		   u_int trans, struct fb_info *info){	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;	struct display *disp = get_con_display(info, fbi->currcon);	u_int val;	int ret = 1;	/*	 * If inverse mode was selected, invert all the colours	 * rather than the register number.  The register number	 * is what you poke into the framebuffer to produce the	 * colour you requested.	 */	if (disp->inverse) {		red   = 0xffff - red;		green = 0xffff - green;		blue  = 0xffff - blue;	}	/*	 * If greyscale is true, then we convert the RGB value	 * to greyscale no mater what visual we are using.	 */	if (fbi->fb.var.grayscale)		red = green = blue = (19595 * red + 38470 * green +					7471 * blue) >> 16;	switch (fbi->fb.disp->visual) {	case FB_VISUAL_TRUECOLOR:		/*		 * 12 or 16-bit True Colour.  We encode the RGB value		 * according to the RGB bitfield information.		 */		if (regno < 16) {			u16 *pal = fbi->fb.pseudo_palette;			val  = chan_to_field(red, &fbi->fb.var.red);			val |= chan_to_field(green, &fbi->fb.var.green);			val |= chan_to_field(blue, &fbi->fb.var.blue);			pal[regno] = val;			ret = 0;		}		break;	case FB_VISUAL_STATIC_PSEUDOCOLOR:	case FB_VISUAL_PSEUDOCOLOR:		ret = sa1100fb_setpalettereg(regno, red, green, blue, trans, info);		break;	}	return ret;}/* *  sa1100fb_display_dma_period() *    Calculate the minimum period (in picoseconds) between two DMA *    requests for the LCD controller. */static unsigned intsa1100fb_display_dma_period(struct fb_var_screeninfo *var){	unsigned int mem_bits_per_pixel;	mem_bits_per_pixel = var->bits_per_pixel;	if (mem_bits_per_pixel == 12)		mem_bits_per_pixel = 16;	/*	 * Period = pixclock * bits_per_byte * bytes_per_transfer	 *		/ memory_bits_per_pixel;	 */	return var->pixclock * 8 * 16 / mem_bits_per_pixel;}/* *  sa1100fb_decode_var(): *    Get the video params out of 'var'. If a value doesn't fit, round it up, *    if it's too big, return -EINVAL. * *    Suggestion: Round up in the following order: bits_per_pixel, xres, *    yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale, *    bitfields, horizontal timing, vertical timing. */static intsa1100fb_validate_var(struct fb_var_screeninfo *var,		      struct sa1100fb_info *fbi){	int ret = -EINVAL;	if (var->xres < MIN_XRES)		var->xres = MIN_XRES;	if (var->yres < MIN_YRES)		var->yres = MIN_YRES;	if (var->xres > fbi->max_xres)		var->xres = fbi->max_xres;	if (var->yres > fbi->max_yres)		var->yres = fbi->max_yres;	var->xres_virtual =	    var->xres_virtual < var->xres ? var->xres : var->xres_virtual;	var->yres_virtual =	    var->yres_virtual < var->yres ? var->yres : var->yres_virtual;	DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel);	switch (var->bits_per_pixel) {#ifdef FBCON_HAS_CFB4	case 4:		ret = 0; break;#endif#ifdef FBCON_HAS_CFB8	case 8:		ret = 0; break;#endif#ifdef FBCON_HAS_CFB16	case 16:	ret = 0; break;#endif	default:		break;	}#ifdef CONFIG_CPU_FREQ	printk(KERN_DEBUG "dma period = %d ps, clock = %d kHz\n",		sa1100fb_display_dma_period(var),		cpufreq_get(smp_processor_id()));#endif	return ret;}static inline void sa1100fb_set_truecolor(u_int is_true_color){	DPRINTK("true_color = %d\n", is_true_color);	if (machine_is_assabet()) {#if 1		// phase 4 or newer Assabet's		if (is_true_color)			ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);		else			ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB);#else		// older Assabet's		if (is_true_color)			ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB);		else			ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);#endif	}}static voidsa1100fb_hw_set_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi){	u_long palette_mem_size;	fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16;	palette_mem_size = fbi->palette_size * sizeof(u16);	DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);	fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);	fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;	fb_set_cmap(&fbi->fb.cmap, 1, sa1100fb_setcolreg, &fbi->fb);	/* Set board control register to handle new color depth */	sa1100fb_set_truecolor(var->bits_per_pixel >= 16);#ifdef CONFIG_SA1100_OMNIMETER#error Do we have to do this here?   We already do it at init time.	if (machine_is_omnimeter())		SetLCDContrast(DefaultLCDContrast);#endif	sa1100fb_activate_var(var, fbi);	fbi->palette_cpu[0] = (fbi->palette_cpu[0] &					 0xcfff) | palette_pbs(var);}/* * sa1100fb_set_var(): *	Set the user defined part of the display for the specified console */static intsa1100fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;	struct fb_var_screeninfo *dvar = get_con_var(&fbi->fb, con);	struct display *display = get_con_display(&fbi->fb, con);	int err, chgvar = 0, rgbidx;	DPRINTK("set_var\n");	/*	 * Decode var contents into a par structure, adjusting any	 * out of range values.	 */	err = sa1100fb_validate_var(var, fbi);	if (err)		return err;	if (var->activate & FB_ACTIVATE_TEST)		return 0;	if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)		return -EINVAL;	if (dvar->xres != var->xres)		chgvar = 1;	if (dvar->yres != var->yres)		chgvar = 1;	if (dvar->xres_virtual != var->xres_virtual)		chgvar = 1;	if (dvar->yres_virtual != var->yres_virtual)		chgvar = 1;	if (dvar->bits_per_pixel != var->bits_per_pixel)		chgvar = 1;	if (con < 0)		chgvar = 0;	switch (var->bits_per_pixel) {#ifdef FBCON_HAS_CFB4	case 4:		if (fbi->cmap_static)			display->visual	= FB_VISUAL_STATIC_PSEUDOCOLOR;		else			display->visual	= FB_VISUAL_PSEUDOCOLOR;		display->line_length	= var->xres / 2;		display->dispsw		= &fbcon_cfb4;		rgbidx			= RGB_8;		break;#endif#ifdef FBCON_HAS_CFB8	case 8:		if (fbi->cmap_static)			display->visual	= FB_VISUAL_STATIC_PSEUDOCOLOR;		else			display->visual	= FB_VISUAL_PSEUDOCOLOR;		display->line_length	= var->xres;		display->dispsw		= &fbcon_cfb8;		rgbidx			= RGB_8;		break;#endif#ifdef FBCON_HAS_CFB16	case 16:		display->visual		= FB_VISUAL_TRUECOLOR;		display->line_length	= var->xres * 2;		display->dispsw		= &fbcon_cfb16;		display->dispsw_data	= fbi->fb.pseudo_palette;		rgbidx			= RGB_16;		break;#endif	default:		rgbidx = 0;		display->dispsw = &fbcon_dummy;		break;	}	display->screen_base	= fbi->screen_cpu;	display->next_line	= display->line_length;	display->type		= fbi->fb.fix.type;	display->type_aux	= fbi->fb.fix.type_aux;	display->ypanstep	= fbi->fb.fix.ypanstep;	display->ywrapstep	= fbi->fb.fix.ywrapstep;	display->can_soft_blank	= 1;	display->inverse	= fbi->cmap_inverse;	*dvar			= *var;	dvar->activate		&= ~FB_ACTIVATE_ALL;	/*	 * Copy the RGB parameters for this display	 * from the machine specific parameters.	 */	dvar->red		= fbi->rgb[rgbidx]->red;	dvar->green		= fbi->rgb[rgbidx]->green;	dvar->blue		= fbi->rgb[rgbidx]->blue;	dvar->transp		= fbi->rgb[rgbidx]->transp;	DPRINTK("RGBT length = %d:%d:%d:%d\n",		dvar->red.length, dvar->green.length, dvar->blue.length,		dvar->transp.length);	DPRINTK("RGBT offset = %d:%d:%d:%d\n",		dvar->red.offset, dvar->green.offset, dvar->blue.offset,		dvar->transp.offset);	/*	 * Update the old var.  The fbcon drivers still use this.	 * Once they are using fbi->fb.var, this can be dropped.	 */	display->var = *dvar;	/*	 * If we are setting all the virtual consoles, also set the	 * defaults used to create new consoles.	 */	if (var->activate & FB_ACTIVATE_ALL)		fbi->fb.disp->var = *dvar;	/*	 * If the console has changed and the console has defined	 * a changevar function, call that function.	 */	if (chgvar && info && fbi->fb.changevar)		fbi->fb.changevar(con);	/* If the current console is selected, activate the new var. */	if (con != fbi->currcon)		return 0;	sa1100fb_hw_set_var(dvar, fbi);	return 0;}static int__do_set_cmap(struct fb_cmap *cmap, int kspc, int con,	      struct fb_info *info){	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;	struct fb_cmap *dcmap = get_con_cmap(info, con);	int err = 0;	if (con == -1)		con = fbi->currcon;	/* no colormap allocated? (we always have "this" colour map allocated) */	if (con >= 0)		err = fb_alloc_cmap(&fb_display[con].cmap, fbi->palette_size, 0);	if (!err && con == fbi->currcon)		err = fb_set_cmap(cmap, kspc, sa1100fb_setcolreg, info);	if (!err)		fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1);	return err;}static intsa1100fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,		  struct fb_info *info){	struct display *disp = get_con_display(info, con);	if (disp->visual == FB_VISUAL_TRUECOLOR ||	    disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)		return -EINVAL;	return __do_set_cmap(cmap, kspc, con, info);}static intsa1100fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info){	struct display *display = get_con_display(info, con);	*fix = info->fix;	fix->line_length = display->line_length;	fix->visual	 = display->visual;	return 0;}static intsa1100fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){	*var = *get_con_var(info, con);	return 0;}static intsa1100fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){	struct fb_cmap *dcmap = get_con_cmap(info, con);	fb_copy_cmap(dcmap, cmap, kspc ? 0 : 2);	return 0;}static struct fb_ops sa1100fb_ops = {	owner:		THIS_MODULE,	fb_get_fix:	sa1100fb_get_fix,	fb_get_var:	sa1100fb_get_var,	fb_set_var:	sa1100fb_set_var,	fb_get_cmap:	sa1100fb_get_cmap,	fb_set_cmap:	sa1100fb_set_cmap,};/* *  sa1100fb_switch():        *	Change to the specified console.  Palette and video mode *      are changed to the console's stored parameters. * *	Uh oh, this can be called from a tasklet (IRQ) */static int sa1100fb_switch(int con, struct fb_info *info){	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;	struct display *disp;	struct fb_cmap *cmap;	DPRINTK("con=%d info->modename=%s\n", con, fbi->fb.modename);

⌨️ 快捷键说明

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