TI Am335LCD驱动
发布日期:2021-09-16 16:46:42 浏览次数:6 分类:技术文章

本文共 7548 字,大约阅读时间需要 25 分钟。

drivers/video/da8xx-fb.c

platformdriver的名称是

#define DRIVER_NAME "da8xx_lcdc"

 

arch/arm/mach-omap2/devices.c中:

int __init am33xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata){	int id = 0;	struct platform_device *pdev;	struct omap_hwmod *oh;	char *oh_name = "lcdc"; //驱动代码在arch/arm/mach-omap2/omap_hwmod_33xx_data.c	char *dev_name = "da8xx_lcdc";	oh = omap_hwmod_lookup(oh_name);	if (!oh) {		pr_err("Could not look up LCD%d hwmod\n", id);		return -ENODEV;	}	pdev = omap_device_build(dev_name, id, oh, pdata,			sizeof(struct da8xx_lcdc_platform_data), NULL, 0, 0);	if (IS_ERR(pdev)) {		WARN(1, "Can't build omap_device for %s:%s.\n",			dev_name, oh->name);		return PTR_ERR(pdev);	}	return 0;}

这个函数是设置struct da8xx_lcdc_platform_data

board-am335xevm.c:

static const struct display_panel consys_disp_panel = {	WVGA,	32,	32,	COLOR_ACTIVE,};static struct lcd_ctrl_config consys_lcd_cfg = {	&consys_disp_panel,	.ac_bias		= 255,	.ac_bias_intrpt		= 0,	.dma_burst_sz		= 16,	.bpp			= 32,     1个像素用多少位表示,这里其实是24位。在probe的代码使用了。	.fdd			= 0x80,	.tft_alt_mode		= 1,	.stn_565_mode		= 0,	.mono_8bit_mode		= 0,	.invert_line_clock	= 0,	.invert_frm_clock	= 0,	.sync_edge		= 1,	.sync_ctrl		= 1,	.raster_order		= 0,};struct da8xx_lcdc_platform_data samsung_AMS369FG06_pdata = {	.manu_name		= "SamSung",	.controller_data	= &consys_lcd_cfg,	.type			= "samsung_AMS369FG06",};
static void lcdc_init(int evm_id, int profile){	struct da8xx_lcdc_platform_data *lcdc_pdata;	setup_pin_mux(lcdc_pin_mux);	if (conf_disp_pll(300000000)) {		pr_info("Failed configure display PLL, not attempting to"				"register LCDC\n");		return;	}	switch (evm_id) {	case GEN_PURP_EVM:	case GEN_PURP_DDR3_EVM:		/*lcdc_pdata = &TFC_S9700RTWV35TR_01B_pdata;*/		lcdc_pdata = &samsung_AMS369FG06_pdata;		break;	case EVM_SK:		lcdc_pdata = &NHD_480272MF_ATXI_pdata;		break;	default:		pr_err("LCDC not supported on this evm (%d)\n",evm_id);		return;	}	lcdc_pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;	if (am33xx_register_lcdc(lcdc_pdata))  //设置		pr_info("Failed to register LCDC device\n");	return;}

回到开头来看Da8xx-fb.c:

static int __devinit fb_probe(struct platform_device *device){	struct da8xx_lcdc_platform_data *fb_pdata =						device->dev.platform_data;	struct lcd_ctrl_config *lcd_cfg;	struct da8xx_panel *lcdc_info;	struct fb_info *da8xx_fb_info;	struct clk *fb_clk = NULL;	struct da8xx_fb_par *par;	resource_size_t len;	int ret, i;	unsigned long ulcm;代码略    下面的代码申请LCD寄存器的虚拟地址,(这个resource是在哪定义的,还没找到)	lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0);	if (!lcdc_regs) {		dev_err(&device->dev,			"Can not get memory resource for LCD controller\n");		return -ENOENT;	}	len = resource_size(lcdc_regs);	lcdc_regs = request_mem_region(lcdc_regs->start, len, lcdc_regs->name);	if (!lcdc_regs)		return -EBUSY;	da8xx_fb_reg_base = (resource_size_t)ioremap(lcdc_regs->start, len);代码略    //上面定义了一些预定义的配置,见known_lcd_panels	for (i = 0, lcdc_info = known_lcd_panels;		i < ARRAY_SIZE(known_lcd_panels);		i++, lcdc_info++) {		if (strcmp(fb_pdata->type, lcdc_info->name) == 0)			break;	}	if (i == ARRAY_SIZE(known_lcd_panels)) {		dev_err(&device->dev, "GLCD: No valid panel found\n");		ret = -ENODEV;		goto err_pm_runtime_disable;	} else		dev_info(&device->dev, "GLCD: Found %s panel\n",					fb_pdata->type);	lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data; //得到board-am335xevm.c中定义的lcd_ctrl_config	da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par),					&device->dev);	if (!da8xx_fb_info) {		dev_dbg(&device->dev, "Memory allocation failed for fb_info\n");		ret = -ENOMEM;		goto err_pm_runtime_disable;	}下面初始化par变量。	par = da8xx_fb_info->par;	par->dev = &device->dev;	par->lcdc_clk = fb_clk;#ifdef CONFIG_CPU_FREQ	par->lcd_fck_rate = clk_get_rate(fb_clk);#endif	par->pxl_clk = lcdc_info->pxl_clk;	if (fb_pdata->panel_power_ctrl) {		par->panel_power_ctrl = fb_pdata->panel_power_ctrl;		par->panel_power_ctrl(1);	}调用lcd_init(),芯片级的初始化操作。	if (lcd_init(par, lcd_cfg, lcdc_info) < 0) {		dev_err(&device->dev, "lcd_init failed\n");		ret = -EFAULT;		goto err_release_fb;	}	/* allocate frame buffer */	par->vram_size = lcdc_info->width * lcdc_info->height * lcd_cfg->bpp; //得到总共所需位数	ulcm = lcm((lcdc_info->width * lcd_cfg->bpp)/8, PAGE_SIZE); //内存对齐	par->vram_size = roundup(par->vram_size/8, ulcm); //1个字节8位,除8得到字节数。	par->vram_size = par->vram_size * LCD_NUM_BUFFERS; //需求申请的内存的个数为LCD_NUM_BUFFERS    申请DMA内存区域	par->vram_virt = dma_alloc_coherent(NULL,					    par->vram_size,					    (resource_size_t *) &par->vram_phys,					    GFP_KERNEL | GFP_DMA);	if (!par->vram_virt) {		dev_err(&device->dev,			"GLCD: kmalloc for frame buffer failed\n");		ret = -EINVAL;		goto err_release_fb;	}	da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt;	da8xx_fb_fix.smem_start    = par->vram_phys;	da8xx_fb_fix.smem_len      = par->vram_size;	da8xx_fb_fix.line_length   = (lcdc_info->width * lcd_cfg->bpp) / 8;       memcpy(par->vram_virt,kernel_logo,par->vram_size);//add by jiachenghui for kernel logo show       	par->dma_start = par->vram_phys;	par->dma_end   = par->dma_start + lcdc_info->height *		da8xx_fb_fix.line_length - 1;	/* allocate palette buffer */	par->v_palette_base = dma_alloc_coherent(NULL,					       PALETTE_SIZE,					       (resource_size_t *)					       &par->p_palette_base,					       GFP_KERNEL | GFP_DMA);	if (!par->v_palette_base) {		dev_err(&device->dev,			"GLCD: kmalloc for palette buffer failed\n");		ret = -EINVAL;		goto err_release_fb_mem;	}	memset(par->v_palette_base, 0, PALETTE_SIZE);	par->irq = platform_get_irq(device, 0);	if (par->irq < 0) {		ret = -ENOENT;		goto err_release_pl_mem;	}代码略(设置结构da8xx_fb_info)	dev_set_drvdata(&device->dev, da8xx_fb_info);  //platform_driver其它函数可以得到它,见resume和suspend函数。	/* initialize the vsync wait queue */	init_waitqueue_head(&par->vsync_wait);	par->vsync_timeout = HZ / 5;	par->which_dma_channel_done = -1;	spin_lock_init(&par->lock_for_chan_update);	/* Register the Frame Buffer  */	if (register_framebuffer(da8xx_fb_info) < 0) {    //见(2)		dev_err(&device->dev,			"GLCD: Frame Buffer Registration Failed!\n");		ret = -EINVAL;		goto err_dealloc_cmap;	}
  1. known_lcd_panels的定义说明:

static struct da8xx_panel known_lcd_panels[] = {	/* Sharp LCD035Q3DG01 */	[0] = {		.name = "Sharp_LCD035Q3DG01",		.width = 320,		.height = 240,		.hfp = 8,		.hbp = 6,		.hsw = 0,		.vfp = 2,		.vbp = 2,		.vsw = 0,		.pxl_clk = 4608000,		.invert_pxl_clk = 1,	},代码略	[10] = {		 /* samsung AMS369FG06-0 */		.name = "samsung_AMS369FG06",		.width = 480,		.height = 800,		.hfp = 8,		.hbp = 7,		.hsw = 1,		.vfp = 8,		.vbp = 7,		.vsw = 1,		.pxl_clk = 19200000,		.invert_pxl_clk = 0,	},};

struct da8xx_panel定义如下:

struct da8xx_panel {	const char	name[25];	/* Full name 
_
*/ unsigned short width; unsigned short height; int hfp; /* Horizontal front porch */ int hbp; /* Horizontal back porch */ int hsw; /* Horizontal Sync Pulse Width */ int vfp; /* Vertical front porch */ int vbp; /* Vertical back porch */ int vsw; /* Vertical Sync Pulse Width */ unsigned int pxl_clk; /* Pixel clock */ unsigned char invert_pxl_clk; /* Invert Pixel clock */};

2. register_framebuffer()

int register_framebuffer(struct fb_info *fb_info)

它注册结构fb_info到framebuff系统,fb_info中有一个重要的成员是fb_ops结构。例如:

static struct fb_ops da8xx_fb_ops = {	.owner = THIS_MODULE,	.fb_check_var = fb_check_var,	.fb_setcolreg = fb_setcolreg,	.fb_pan_display = da8xx_pan_display,	.fb_ioctl = fb_ioctl,	.fb_fillrect = cfb_fillrect,	.fb_copyarea = cfb_copyarea,	.fb_imageblit = cfb_imageblit,	.fb_blank = cfb_blank,};

fb_ops的函数中都有一个参数fb_info。

 

转载地址:https://blog.csdn.net/xgbing/article/details/102810027 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:android audio/linux alsa音频-应用层基础
下一篇:s5p4418显示驱动

发表评论

最新留言

哈哈,博客排版真的漂亮呢~
[***.90.31.176]2024年04月11日 22时17分45秒