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

📄 omapfb_main.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Framebuffer driver for TI OMAP boards * * Copyright (C) 2004 Nokia Corporation * Author: Imre Deak <imre.deak@nokia.com> * * Acknowledgements: *   Alex McMains <aam@ridgerun.com>       - Original driver *   Juha Yrjola <juha.yrjola@nokia.com>   - Original driver and improvements *   Dirk Behme <dirk.behme@de.bosch.com>  - changes for 2.6 kernel API *   Texas Instruments                     - H3 support * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. */#include <linux/platform_device.h>#include <linux/mm.h>#include <linux/uaccess.h>#include <mach/dma.h>#include <mach/omapfb.h>#include "lcdc.h"#include "dispc.h"#define MODULE_NAME	"omapfb"static unsigned int	def_accel;static unsigned long	def_vram[OMAPFB_PLANE_NUM];static unsigned int	def_vram_cnt;static unsigned long	def_vxres;static unsigned long	def_vyres;static unsigned int	def_rotate;static unsigned int	def_mirror;#ifdef CONFIG_FB_OMAP_MANUAL_UPDATEstatic int		manual_update = 1;#elsestatic int		manual_update;#endifstatic struct platform_device	*fbdev_pdev;static struct lcd_panel		*fbdev_panel;static struct omapfb_device	*omapfb_dev;struct caps_table_struct {	unsigned long flag;	const char *name;};static struct caps_table_struct ctrl_caps[] = {	{ OMAPFB_CAPS_MANUAL_UPDATE,  "manual update" },	{ OMAPFB_CAPS_TEARSYNC,       "tearing synchronization" },	{ OMAPFB_CAPS_PLANE_RELOCATE_MEM, "relocate plane memory" },	{ OMAPFB_CAPS_PLANE_SCALE,    "scale plane" },	{ OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE, "pixel double window" },	{ OMAPFB_CAPS_WINDOW_SCALE,   "scale window" },	{ OMAPFB_CAPS_WINDOW_OVERLAY, "overlay window" },	{ OMAPFB_CAPS_SET_BACKLIGHT,  "backlight setting" },};static struct caps_table_struct color_caps[] = {	{ 1 << OMAPFB_COLOR_RGB565,	"RGB565", },	{ 1 << OMAPFB_COLOR_YUV422,	"YUV422", },	{ 1 << OMAPFB_COLOR_YUV420,	"YUV420", },	{ 1 << OMAPFB_COLOR_CLUT_8BPP,	"CLUT8", },	{ 1 << OMAPFB_COLOR_CLUT_4BPP,	"CLUT4", },	{ 1 << OMAPFB_COLOR_CLUT_2BPP,	"CLUT2", },	{ 1 << OMAPFB_COLOR_CLUT_1BPP,	"CLUT1", },	{ 1 << OMAPFB_COLOR_RGB444,	"RGB444", },	{ 1 << OMAPFB_COLOR_YUY422,	"YUY422", },};/* * --------------------------------------------------------------------------- * LCD panel * --------------------------------------------------------------------------- */extern struct lcd_ctrl hwa742_ctrl;extern struct lcd_ctrl blizzard_ctrl;static const struct lcd_ctrl *ctrls[] = {#ifdef CONFIG_ARCH_OMAP1	&omap1_int_ctrl,#else	&omap2_int_ctrl,#endif#ifdef CONFIG_FB_OMAP_LCDC_HWA742	&hwa742_ctrl,#endif#ifdef CONFIG_FB_OMAP_LCDC_BLIZZARD	&blizzard_ctrl,#endif};#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL#ifdef CONFIG_ARCH_OMAP1extern struct lcd_ctrl_extif omap1_ext_if;#elseextern struct lcd_ctrl_extif omap2_ext_if;#endif#endifstatic void omapfb_rqueue_lock(struct omapfb_device *fbdev){	mutex_lock(&fbdev->rqueue_mutex);}static void omapfb_rqueue_unlock(struct omapfb_device *fbdev){	mutex_unlock(&fbdev->rqueue_mutex);}/* * --------------------------------------------------------------------------- * LCD controller and LCD DMA * --------------------------------------------------------------------------- *//* Lookup table to map elem size to elem type. */static const int dma_elem_type[] = {	0,	OMAP_DMA_DATA_TYPE_S8,	OMAP_DMA_DATA_TYPE_S16,	0,	OMAP_DMA_DATA_TYPE_S32,};/* * Allocate resources needed for LCD controller and LCD DMA operations. Video * memory is allocated from system memory according to the virtual display * size, except if a bigger memory size is specified explicitly as a kernel * parameter. */static int ctrl_init(struct omapfb_device *fbdev){	int r;	int i;	/* kernel/module vram parameters override boot tags/board config */	if (def_vram_cnt) {		for (i = 0; i < def_vram_cnt; i++)			fbdev->mem_desc.region[i].size =				PAGE_ALIGN(def_vram[i]);		fbdev->mem_desc.region_cnt = i;	} else {		struct omapfb_platform_data *conf;		conf = fbdev->dev->platform_data;		fbdev->mem_desc = conf->mem_desc;	}	if (!fbdev->mem_desc.region_cnt) {		struct lcd_panel *panel = fbdev->panel;		int def_size;		int bpp = panel->bpp;		/* 12 bpp is packed in 16 bits */		if (bpp == 12)			bpp = 16;		def_size = def_vxres * def_vyres * bpp / 8;		fbdev->mem_desc.region_cnt = 1;		fbdev->mem_desc.region[0].size = PAGE_ALIGN(def_size);	}	r = fbdev->ctrl->init(fbdev, 0, &fbdev->mem_desc);	if (r < 0) {		dev_err(fbdev->dev, "controller initialization failed (%d)\n",			r);		return r;	}#ifdef DEBUG	for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {		dev_dbg(fbdev->dev, "region%d phys %08x virt %p size=%lu\n",			 i,			 fbdev->mem_desc.region[i].paddr,			 fbdev->mem_desc.region[i].vaddr,			 fbdev->mem_desc.region[i].size);	}#endif	return 0;}static void ctrl_cleanup(struct omapfb_device *fbdev){	fbdev->ctrl->cleanup();}/* Must be called with fbdev->rqueue_mutex held. */static int ctrl_change_mode(struct fb_info *fbi){	int r;	unsigned long offset;	struct omapfb_plane_struct *plane = fbi->par;	struct omapfb_device *fbdev = plane->fbdev;	struct fb_var_screeninfo *var = &fbi->var;	offset = var->yoffset * fbi->fix.line_length +		 var->xoffset * var->bits_per_pixel / 8;	if (fbdev->ctrl->sync)		fbdev->ctrl->sync();	r = fbdev->ctrl->setup_plane(plane->idx, plane->info.channel_out,				 offset, var->xres_virtual,				 plane->info.pos_x, plane->info.pos_y,				 var->xres, var->yres, plane->color_mode);	if (fbdev->ctrl->set_scale != NULL)		r = fbdev->ctrl->set_scale(plane->idx,				   var->xres, var->yres,				   plane->info.out_width,				   plane->info.out_height);	return r;}/* * --------------------------------------------------------------------------- * fbdev framework callbacks and the ioctl interface * --------------------------------------------------------------------------- *//* Called each time the omapfb device is opened */static int omapfb_open(struct fb_info *info, int user){	return 0;}static void omapfb_sync(struct fb_info *info);/* Called when the omapfb device is closed. We make sure that any pending * gfx DMA operations are ended, before we return. */static int omapfb_release(struct fb_info *info, int user){	omapfb_sync(info);	return 0;}/* Store a single color palette entry into a pseudo palette or the hardware * palette if one is available. For now we support only 16bpp and thus store * the entry only to the pseudo palette. */static int _setcolreg(struct fb_info *info, u_int regno, u_int red, u_int green,			u_int blue, u_int transp, int update_hw_pal){	struct omapfb_plane_struct *plane = info->par;	struct omapfb_device *fbdev = plane->fbdev;	struct fb_var_screeninfo *var = &info->var;	int r = 0;	switch (plane->color_mode) {	case OMAPFB_COLOR_YUV422:	case OMAPFB_COLOR_YUV420:	case OMAPFB_COLOR_YUY422:		r = -EINVAL;		break;	case OMAPFB_COLOR_CLUT_8BPP:	case OMAPFB_COLOR_CLUT_4BPP:	case OMAPFB_COLOR_CLUT_2BPP:	case OMAPFB_COLOR_CLUT_1BPP:		if (fbdev->ctrl->setcolreg)			r = fbdev->ctrl->setcolreg(regno, red, green, blue,							transp, update_hw_pal);		/* Fallthrough */	case OMAPFB_COLOR_RGB565:	case OMAPFB_COLOR_RGB444:		if (r != 0)			break;		if (regno < 0) {			r = -EINVAL;			break;		}		if (regno < 16) {			u16 pal;			pal = ((red >> (16 - var->red.length)) <<					var->red.offset) |			      ((green >> (16 - var->green.length)) <<					var->green.offset) |			      (blue >> (16 - var->blue.length));			((u32 *)(info->pseudo_palette))[regno] = pal;		}		break;	default:		BUG();	}	return r;}static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,			    u_int transp, struct fb_info *info){	return _setcolreg(info, regno, red, green, blue, transp, 1);}static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info){	int count, index, r;	u16 *red, *green, *blue, *transp;	u16 trans = 0xffff;	red     = cmap->red;	green   = cmap->green;	blue    = cmap->blue;	transp  = cmap->transp;	index   = cmap->start;	for (count = 0; count < cmap->len; count++) {		if (transp)			trans = *transp++;		r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,				count == cmap->len - 1);		if (r != 0)			return r;	}	return 0;}static int omapfb_update_full_screen(struct fb_info *fbi);static int omapfb_blank(int blank, struct fb_info *fbi){	struct omapfb_plane_struct *plane = fbi->par;	struct omapfb_device *fbdev = plane->fbdev;	int do_update = 0;	int r = 0;	omapfb_rqueue_lock(fbdev);	switch (blank) {	case VESA_NO_BLANKING:		if (fbdev->state == OMAPFB_SUSPENDED) {			if (fbdev->ctrl->resume)				fbdev->ctrl->resume();			fbdev->panel->enable(fbdev->panel);			fbdev->state = OMAPFB_ACTIVE;			if (fbdev->ctrl->get_update_mode() ==					OMAPFB_MANUAL_UPDATE)				do_update = 1;		}		break;	case VESA_POWERDOWN:		if (fbdev->state == OMAPFB_ACTIVE) {			fbdev->panel->disable(fbdev->panel);			if (fbdev->ctrl->suspend)				fbdev->ctrl->suspend();			fbdev->state = OMAPFB_SUSPENDED;		}		break;	default:		r = -EINVAL;	}	omapfb_rqueue_unlock(fbdev);	if (r == 0 && do_update)		r = omapfb_update_full_screen(fbi);	return r;}static void omapfb_sync(struct fb_info *fbi){	struct omapfb_plane_struct *plane = fbi->par;	struct omapfb_device *fbdev = plane->fbdev;	omapfb_rqueue_lock(fbdev);	if (fbdev->ctrl->sync)		fbdev->ctrl->sync();	omapfb_rqueue_unlock(fbdev);}/* * Set fb_info.fix fields and also updates fbdev. * When calling this fb_info.var must be set up already. */static void set_fb_fix(struct fb_info *fbi){	struct fb_fix_screeninfo *fix = &fbi->fix;	struct fb_var_screeninfo *var = &fbi->var;	struct omapfb_plane_struct *plane = fbi->par;	struct omapfb_mem_region *rg;	int bpp;	rg = &plane->fbdev->mem_desc.region[plane->idx];	fbi->screen_base	= rg->vaddr;	fix->smem_start		= rg->paddr;	fix->smem_len		= rg->size;	fix->type = FB_TYPE_PACKED_PIXELS;	bpp = var->bits_per_pixel;	if (var->nonstd)		fix->visual = FB_VISUAL_PSEUDOCOLOR;	else switch (var->bits_per_pixel) {	case 16:	case 12:		fix->visual = FB_VISUAL_TRUECOLOR;		/* 12bpp is stored in 16 bits */		bpp = 16;		break;	case 1:	case 2:	case 4:	case 8:		fix->visual = FB_VISUAL_PSEUDOCOLOR;		break;	}	fix->accel		= FB_ACCEL_OMAP1610;	fix->line_length	= var->xres_virtual * bpp / 8;}static int set_color_mode(struct omapfb_plane_struct *plane,			  struct fb_var_screeninfo *var){	switch (var->nonstd) {	case 0:		break;	case OMAPFB_COLOR_YUV422:		var->bits_per_pixel = 16;		plane->color_mode = var->nonstd;		return 0;	case OMAPFB_COLOR_YUV420:		var->bits_per_pixel = 12;		plane->color_mode = var->nonstd;		return 0;	case OMAPFB_COLOR_YUY422:		var->bits_per_pixel = 16;		plane->color_mode = var->nonstd;		return 0;	default:		return -EINVAL;	}	switch (var->bits_per_pixel) {	case 1:		plane->color_mode = OMAPFB_COLOR_CLUT_1BPP;		return 0;	case 2:		plane->color_mode = OMAPFB_COLOR_CLUT_2BPP;		return 0;	case 4:		plane->color_mode = OMAPFB_COLOR_CLUT_4BPP;		return 0;	case 8:		plane->color_mode = OMAPFB_COLOR_CLUT_8BPP;		return 0;	case 12:		var->bits_per_pixel = 16;		plane->color_mode = OMAPFB_COLOR_RGB444;		return 0;	case 16:		plane->color_mode = OMAPFB_COLOR_RGB565;		return 0;	default:		return -EINVAL;	}}/* * Check the values in var against our capabilities and in case of out of * bound values try to adjust them. */static int set_fb_var(struct fb_info *fbi,		      struct fb_var_screeninfo *var){	int		bpp;	unsigned long	max_frame_size;	unsigned long	line_size;	int		xres_min, xres_max;	int		yres_min, yres_max;	struct omapfb_plane_struct *plane = fbi->par;	struct omapfb_device *fbdev = plane->fbdev;	struct lcd_panel *panel = fbdev->panel;	if (set_color_mode(plane, var) < 0)		return -EINVAL;

⌨️ 快捷键说明

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