TI Am335LCD驱动
生活随笔
收集整理的這篇文章主要介紹了
TI Am335LCD驱动
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
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.cchar *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_panelsfor (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;} elsedev_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_configda8xx_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_FREQpar->lcd_fck_rate = clk_get_rate(fb_clk); #endifpar->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 showpar->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的定義說明:
struct da8xx_panel定義如下:
struct da8xx_panel {const char name[25]; /* Full name <vendor>_<model> */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。
?
總結
以上是生活随笔為你收集整理的TI Am335LCD驱动的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深入理解MySQL——LRU、Free和
- 下一篇: 车更新2021