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

📄 pxafb.c

📁 LINUX下PXA的LCD驱动程序原代码,值得一看,
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  linux/drivers/video/pxafb.c * *  Copyright (C) 1999 Eric A. Thomas *   Based on acornfb.c Copyright (C) Russell King. * * 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. * *	        Intel PXA250/210 LCD Controller Frame Buffer Driver * * Please direct your questions and comments on this driver to the following * email address: * *	linux-arm-kernel@lists.arm.linux.org.uk * * Clean patches should be sent to the ARM Linux Patch System.  Please see the * following web page for more information: * *	http://www.arm.linux.org.uk/developer/patches/info.shtml * * Thank you. * * * Code Status: * 1999/04/01: *	- Driver appears to be working for Brutus 320x200x8bpp mode.  Other *	  resolutions are working, but only the 8bpp mode is supported. *	  Changes need to be made to the palette encode and decode routines *	  to support 4 and 16 bpp modes.   *	  Driver is not designed to be a module.  The FrameBuffer is statically *	  allocated since dynamic allocation of a 300k buffer cannot be  *	  guaranteed.  * * 1999/06/17: *	- FrameBuffer memory is now allocated at run-time when the *	  driver is initialized.     * * 2000/04/10: Nicolas Pitre <nico@cam.org> *	- Big cleanup for dynamic selection of machine type at run time. * * 2000/07/19: Jamey Hicks <jamey@crl.dec.com> *	- Support for Bitsy aka Compaq iPAQ H3600 added. * * 2000/08/07: Tak-Shing Chan <tchan.rd@idthk.com> *	       Jeff Sutherland <jsutherland@accelent.com> *	- Resolved an issue caused by a change made to the Assabet's PLD  *	  earlier this year which broke the framebuffer driver for newer  *	  Phase 4 Assabets.  Some other parameters were changed to optimize *	  for the Sharp display. * * 2000/08/09: Cliff Brake <cbrake@accelent.com> *      - modified for Accelent *  * 2000/08/09: Kunihiko IMAI <imai@vasara.co.jp> *	- XP860 support added * * 2000/08/19: Mark Huang <mhuang@livetoy.com> *	- Allows standard options to be passed on the kernel command line *	  for most common passive displays. * * 2000/08/29: *	- s/save_flags_cli/local_irq_save/ *	- remove unneeded extra save_flags_cli in sa1100fb_enable_lcd_controller * * 2000/10/10: Erik Mouw <J.A.K.Mouw@its.tudelft.nl> *	- Updated LART stuff. Fixed some minor bugs. * * 2000/10/30: Murphy Chen <murphy@mail.dialogue.com.tw> *	- Pangolin support added * * 2000/10/31: Roman Jordan <jor@hoeft-wessel.de> *	- Huw Webpanel support added * * 2000/11/23: Eric Peng <ericpeng@coventive.com> *	- Freebird add * * 2001/02/07: Jamey Hicks <jamey.hicks@compaq.com>  *	       Cliff Brake <cbrake@accelent.com> *	- Added PM callback * * 2001/05/26: <rmk@arm.linux.org.uk> *	- Fix 16bpp so that (a) we use the right colours rather than some *	  totally random colour depending on what was in page 0, and (b) *	  we don't de-reference a NULL pointer. *	- remove duplicated implementation of consistent_alloc() *	- convert dma address types to dma_addr_t *	- remove unused 'montype' stuff *	- remove redundant zero inits of init_var after the initial *	  memzero. *	- remove allow_modeset (acornfb idea does not belong here) * * 2001/05/28: <rmk@arm.linux.org.uk> *	- massive cleanup - move machine dependent data into structures *	- I've left various #warnings in - if you see one, and know *	  the hardware concerned, please get in contact with me. * * 2001/05/31: <rmk@arm.linux.org.uk> *	- Fix LCCR1 HSW value, fix all machine type specifications to *	  keep values in line.  (Please check your machine type specs) * * 2001/06/10: <rmk@arm.linux.org.uk> *	- Fiddle with the LCD controller from task context only; mainly *	  so that we can run with interrupts on, and sleep. *	- Convert #warnings into #errors.  No pain, no gain. ;) * * 2001/06/14: <rmk@arm.linux.org.uk> *	- Make the palette BPS value for 12bpp come out correctly. *	- Take notice of "greyscale" on any colour depth. *	- Make truecolor visuals use the RGB channel encoding information. * * 2001/07/02: <rmk@arm.linux.org.uk> *	- Fix colourmap problems. * * 2001/08/03: <cbrake@accelent.com> *      - Ported from SA1100 to PXA250 */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/interrupt.h>#include <linux/slab.h>#include <linux/fb.h>#include <linux/delay.h>#include <linux/pm.h>#include <linux/init.h>#include <linux/cpufreq.h>#include <asm/hardware.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/mach-types.h>#include <asm/uaccess.h>#include <video/fbcon.h>#include <video/fbcon-mfb.h>#include <video/fbcon-cfb4.h>#include <video/fbcon-cfb8.h>#include <video/fbcon-cfb16.h>/* * debugging? */#define DEBUG 1/* * Complain if VAR is out of range. */#define DEBUG_VAR 1#undef ASSABET_PAL_VIDEO#include "pxafb.h"void (*pxafb_blank_helper)(int blank);EXPORT_SYMBOL(pxafb_blank_helper);/* * IMHO this looks wrong.  In 8BPP, length should be 8. */static struct pxafb_rgb rgb_8 = {	red:	{ offset: 8,  length: 4, },	green:	{ offset: 4,  length: 4, },	blue:	{ offset: 0,  length: 4, },	transp:	{ offset: 0,  length: 0, },};static struct pxafb_rgb def_rgb_16 = {	red:	{ offset: 11, length: 5, },	green:	{ offset: 5,  length: 6, },	blue:	{ offset: 0,  length: 5, },	transp:	{ offset: 0,  length: 0, },};static struct pxafb_mach_info pxa_fb_info __initdata = {	pixclock:	LCD_PIXCLOCK,	/* clock period in ps */	bpp:		LCD_BPP,	xres:		LCD_XRES,	yres:		LCD_YRES,	hsync_len:	LCD_HORIZONTAL_SYNC_PULSE_WIDTH,	vsync_len:	LCD_VERTICAL_SYNC_PULSE_WIDTH,	left_margin:	LCD_BEGIN_OF_LINE_WAIT_COUNT,	upper_margin:	LCD_BEGIN_FRAME_WAIT_COUNT,	right_margin:	LCD_END_OF_LINE_WAIT_COUNT,	lower_margin:	LCD_END_OF_FRAME_WAIT_COUNT,	sync:		LCD_SYNC,	lccr0:		LCD_LCCR0,	lccr3:		LCD_LCCR3};static struct pxafb_mach_info * __initpxafb_get_machine_info(struct pxafb_info *fbi){	return &pxa_fb_info;}static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *);static void set_ctrlr_state(struct pxafb_info *fbi, u_int state);static inline void pxafb_schedule_task(struct pxafb_info *fbi, u_int state){	unsigned long flags;	local_irq_save(flags);	/*	 * We need to handle two requests being made at the same time.	 * There are two important cases:	 *  1. When we are changing VT (C_REENABLE) while unblanking (C_ENABLE)	 *     We must perform the unblanking, which will do our REENABLE for us.	 *  2. When we are blanking, but immediately unblank before we have	 *     blanked.  We do the "REENABLE" thing here as well, just to be sure.	 */	if (fbi->task_state == C_ENABLE && state == C_REENABLE)		state = (u_int) -1;	if (fbi->task_state == C_DISABLE && state == C_ENABLE)		state = C_REENABLE;	if (state != (u_int)-1) {		fbi->task_state = state;		schedule_task(&fbi->task);	}	local_irq_restore(flags);}/* * Get the VAR structure pointer for the specified console */static inline struct fb_var_screeninfo *get_con_var(struct fb_info *info, int con){	struct pxafb_info *fbi = (struct pxafb_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 pxafb_info *fbi = (struct pxafb_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 pxafb_info *fbi = (struct pxafb_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;}static intpxafb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,		       u_int trans, struct fb_info *info){	struct pxafb_info *fbi = (struct pxafb_info *)info;	u_int val, ret = 1;	if (regno < fbi->palette_size) {		val = ((red >> 0) & 0xf800);		val |= ((green >> 5) & 0x07e0);		val |= ((blue >> 11) & 0x001f);		fbi->palette_cpu[regno] = val;		ret = 0;	}	return ret;}static intpxafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,		   u_int trans, struct fb_info *info){	struct pxafb_info *fbi = (struct pxafb_info *)info;	u_int val;	int ret = 1;	/*	 * 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_PSEUDOCOLOR:		ret = pxafb_setpalettereg(regno, red, green, blue, trans, info);		break;	}	return ret;}/* *  pxafb_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 int pxafb_validate_var(struct fb_var_screeninfo *var,				 struct pxafb_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 12:		/* make sure we are in passive mode */		if (!(fbi->lccr0 & LCCR0_PAS))			ret = 0;		break;	case 16:		/* cerf pda 16 bits works fine in passive mode, so don't complain */		if (machine_is_xhyper255()) {			ret = 0;		} else			/* make sure we are in active mode */			if ((fbi->lccr0 & LCCR0_PAS))				ret = 0;		break;#endif	default:		break;	}	return ret;}static inline void pxafb_set_truecolor(u_int is_true_color){	DPRINTK("true_color = %d\n", is_true_color);#ifdef CONFIG_SA1100_ASSABET	if (machine_is_assabet()) {#if 1		// phase 4 or newer Assabet's		if (is_true_color)			BCR_set(BCR_LCD_12RGB);		else			BCR_clear(BCR_LCD_12RGB);#else		// older Assabet's		if (is_true_color)			BCR_clear(BCR_LCD_12RGB);		else			BCR_set(BCR_LCD_12RGB);#endif	}#endif}static voidpxafb_hw_set_var(struct fb_var_screeninfo *var, struct pxafb_info *fbi){	fb_set_cmap(&fbi->fb.cmap, 1, pxafb_setcolreg, &fbi->fb);	/* Set board control register to handle new color depth */	pxafb_set_truecolor(var->bits_per_pixel >= 16);	pxafb_activate_var(var, fbi);}/* * pxafb_set_var(): *	Set the user defined part of the display for the specified console */static intpxafb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){	struct pxafb_info *fbi = (struct pxafb_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 = pxafb_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 12:	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;

⌨️ 快捷键说明

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