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; }
-
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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
哈哈,博客排版真的漂亮呢~
[***.90.31.176]2024年04月11日 22时17分45秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
说说如何查看 Python Django 的版本号
2019-04-26
说说 Python Django 应用的基础目录结构
2019-04-26
说说如何在 Python 的正则表达式中使用分组
2019-04-26
说说 Python 正则表达式的匹配类型
2019-04-26
说说 Python 的贪心和非贪心匹配策略
2019-04-26
说说在 Python 中,如何找出所有字符串匹配
2019-04-26
说说 Python 正则表达式中的那些字符类别码
2019-04-26
说说 Spring Boot 的条件化注解
2019-04-26
说说如何使用 Python 在 word 中创建表格
2019-04-26
Python 基础知识考题与解答(2020 版)
2019-04-26
说说 Oracle 的 SYSDATE 函数
2019-04-26
说说 Oracle 的 NVL 与 NVL2 函数
2019-04-26
说说 TCP 协议以及三次握手流程
2019-04-26
说说 Oracle 的 TRUNC 函数
2019-04-26
系统架构设计笔记(41)—— 系统过渡计划
2019-04-26
系统架构设计笔记(42)—— 软件架构概述
2019-04-26
系统架构设计笔记(57)—— 测试自动化与面向对象的测试
2019-04-26
系统架构设计笔记(58)—— 嵌入式系统概论
2019-04-26
说说 Python 的生成器表达式
2019-04-26