移植Linux系统到iMX6开发板之LVDS显示屏驱动程序的框架分析与移植

今天记录一下项目中的关于LVDS显示屏的驱动程序的分析与移植。因为驱动源码厂家已经提供好,我们需要做的就是读懂驱动程序的代码,以及平台层的匹配过程,以及如何在uboot中获取lvds参数,来匹配你的具体显示屏的参数。

首先我们来大致分析一下驱动程序的重要的结构部分:

1.mxc_ipuv3_fb.c 是imx6具体显示模块平台核心的驱动,最终用于把fb_info结构体注册到 
framebuffer驱动核心层中。 
2.mxc_dispdrv.c 通用注册handle接口,用于统一管理imx6显示模块的各种接口, 
比如lvds,lcd,hdmi等显示接口。 
3.ldb.c是LVDS 驱动的具体实现过程。

分析: 
mxc_ipuv3_fb.c中 
在mxc_ipuv3_fb.c文件中初始化mxcfb_init函数注册mxcfb_driver结构体, 
当mxcfb_driver结构体成员驱动name与平台设备层中name匹配相同时调用mxcfb_probe初始化函数。 
imx6具体显示模块平台核心的驱动的工作主要是在mxcfb_probe里完成。

以下是将重要的函数抽出来分析,并不是具体的代码程序。具体的代码程序见最后的分析。

mxcfb_probe
    mxcfb_init_fbinfo
        framebuffer_alloc
    mxcfb_option_setup
        fb_get_options(根据uboot传进来的参数,比较是否匹配,获取分辨率,bpp等参数)
    mxcfb_dispdrv_init
        mxc_dispdrv_gethandle
            if (!strcmp(entry->drv->name, name) && (entry->drv->init)) //如果uboot传进来的参数名字
            与ldb_driver里注册的名字匹配时,就会进入就会执行ldb.c文件里的ldb_disp_init函数
            entry->drv->init  //mxc_dispdrv.c 调用对应driver的init函数,这里就是ldb driver对应的init了。
    mxcfb_register
        register_framebuffer

entry->drv->init是如何调用ldb_disp_init?当ldb.c中ldb_grv结构体中的name与uboot传进来的名字
    相匹配,就会调用.init,

        static struct mxc_dispdrv_driver ldb_drv = {
    .name   = DISPDRV_LDB,
    .init   = ldb_disp_init,
    .deinit = ldb_disp_deinit,
    .setup = ldb_disp_setup,
};
  • robe() 
    第三步调用mxcfb_dispdrv_init函数,它会调用在mxc_dispdrv.c文件的mxc_dispdrv_gethandle函数; 
    根据uboot传到内核的显示设备name(ldb),在dispdrv_list链表中匹配获取对应的driver handle; 
    这里是获取的是ldb的handle,它的注册是ldb_probe()里的mxc_dispdrv_register函数的,它将自己 
    添加到dispdrv_list。通过entry->drv->init函数,当从uboot获取的显示设备名字和ldb driver里 
    注册的名字match匹配时,就会执行ldb.c文件里的ldb_disp_init函数(具体见另一个文档,告诉你 
    如何实现参数匹配),然后通过结构体fb_videomode[]来设置屏幕的分辨率、刷新频率、上下左右 
    页边距、行扫描脉宽、场扫描脉宽等参数。ldb_disp_init函数是LVDS驱动具体实现函数。
ldb_disp_init
    ret = fb_find_mode(具体硬件参数的匹配过程,分析见另一篇文章链接为:)
    return ret

上面大致框架分析好后,一定要看一下具体硬件的参数匹配过程,见上面链接(链接:iMX6开发板移植Linux系统之LVDS显示屏驱动程序分析之LVDS参数的匹配过程分析),然后就是如何设置我的参数,来匹配我的开发板了:

首先在这个结构体中,需要知道具体的参数:

/* include/linux/fb.h */
 struct fb_videomode {  
2.     const char *name;  “LDB-WSVGA”    /* 名字 */  
3.     u32 refresh;        60    /* 刷新频率 */  
4.     u32 xres;           1024  //行像素  
5.     u32 yres;           768   //列像素  
6.     u32 pixclock;       19528(14065) //时钟频率,单位ps,14430  
7.     u32 left_margin;    140   // HBPD(horizontal back porch):80  
8.     u32 right_margin;   160   // HFPD(horizontal front porth):48  
9.     u32 upper_margin;   20    // VBPD(vertical back porch),15  
10.    u32 lower_margin;   12    // VFBD(vertical front porch),2  
11.    u32 hsync_len;      20    // HSPW(horizontal sync pulse width):32  
12.    u32 vsync_len;      3     // VSPW(vertical sync pulse width):47  
13.    u32 sync;           0 
14.    u32 vmode;          
15.    u32 flag;  
16.};  

我们的参数为:

整屏刷新频率 60M 
屏幕分辨率 1024*768 
时钟频率 14065 
left_margin 40(单位像素) 
right_margin 40(单位像素) 
upper_margin 10(单位像素) 
lower_margin 3(单位像素) 
行扫描脉宽 hsync_len 80(单位像素时间) 
场扫描脉宽vsync_len 10(单位像素时间)

在i.mx6中,关于lvds液晶屏的这个结构体参数(系统lvds接口支持的lcd时序参数都在此了)所属文件为:driver/video/mxc/ldb.c

static struct fb_videomode ldb_modedb[] = {
    {
     "LDB-WXGA", 60, 1280, 800, 14065,
     40, 40,
     10, 3,
     80, 10,
     0,
     FB_VMODE_NONINTERLACED,
     FB_MODE_IS_DETAILED,},
    {
     "LDB-XGA", 60, 1024, 768, 15385,
     220, 40,
     21, 7,
     60, 10,
     0,
     FB_VMODE_NONINTERLACED,
     FB_MODE_IS_DETAILED,},
    {"LDB-WSVGA", 60, 1024, 600, 19528,
     140, 160,
     20, 12,
     20, 3,
     0,
     FB_VMODE_NONINTERLACED,
     FB_MODE_IS_DETAILED,},
    {"LDB-WSVGA480", 60, 1024, 480, 23000,
     140, 160,
     20, 12,
     20, 3,
     0,
     FB_VMODE_NONINTERLACED,
     FB_MODE_IS_DETAILED,},
    {
     "LDB-1080P60", 60, 1920, 1080, 7692,
     100, 40,
     30, 3,
     10, 2,
     0,
     FB_VMODE_NONINTERLACED,
     FB_MODE_IS_DETAILED,},
    {
     "LDB-QXGA", 30, 2048, 1536, 9746,
     5, 150,
     9, 3,
     5, 1,
     0,
     FB_VMODE_NONINTERLACED,
     FB_MODE_IS_DETAILED,},

};

我们选用”LDB-WSVGA”这个结构体里的内容作为我们的参数,将参数修改好适合我们的的参数。

经过后来做实验,发现启动后显示屏显示的有问题,显示的不完全,经过后来的搜索,我在uboot启动后,输入参数,来覆盖上面的结构体参数,屏幕显示就正常了。具体原因没有分析,以后有时间再做具体分析。 
uboot启动后输入的具体参数为:

setenv bootargs_mmc 'setenv bootargs ${bootargs} ip=off root=/dev/mmcblk0p1 rootwait rw video=mxcfb0:dev=ldb,LDB-WSVGA,if=RGB24,bpp=32 video=mxcfb1:off video=mxcfb2:off ldb=sin0 fbmem=28M fb0base=0x27b00000 '
  • 1

想一起探讨以及获得各种学习资源加我(有我博客中写的代码的原稿): 
qq:1126137994 
微信:liu1126137994 
可以共同交流关于嵌入式,操作系统,C++语言,C语言,数据结构等技术问题。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值