TI Am335LCD驱动
Posted xgbing
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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.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 <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驱动的主要内容,如果未能解决你的问题,请参考以下文章