itop4412 LCD设备驱动详解(二)之DRIVER

来源:互联网 发布:治安管理专业算法学吗 编辑:程序博客网 时间:2024/05/17 03:19

LCD的工作,在kernel中有device和driver两个描述,这也是必然。
在 分析一中我们看了device,现在我们来看看driver。
注:在驱动分析中,我们会在数据手册和原理图中查看。首先来看看lcd驱动框架(ps 该框图来自网上)
这里写图片描述
由上图可以看出 lcd的应用层 通过 内核的fbmem接口 再调用驱动xxxfb.c的内容
而fbmem接口是内核提供的,所有驱动设计人员主要的任务就是定义一个fb_info 结构体(该结构由内核提供),然后填充结构体中的内容做好相应的初始化后,提交给内核就可以了。
//———————————-
首先驱动文件在: 在kernel/drivers/video/samsung/目录下。我现在用的设备涉及的驱动如下:
(ps:这里以itop 提供的4.3寸WXCAT43屏为参考,(主要贵的买不起的哇%>_<%) )
s3cfb_wa101s.c ——设备参数相关文件
s3cfb_fimd6x.c —— 具体平台硬件相关文件
s3cfb_ops.c ——-fb 操作集合
s3cfb_main.c ——-驱动框架

好,首先来,分析s3cfb_main.c ,当然在介绍该.c时,会把之前所有的.c都牵扯进来,毕竟驱动框架调用了其他c文件的接口。(这一节主要介绍probe函数调用的接口功能,接口具体实现在下一节中介绍)

static struct platform_driver s3cfb_driver = {    .probe      = s3cfb_probe, //探测设备    .remove     = s3cfb_remove,//设备移除#ifndef CONFIG_HAS_EARLYSUSPEND     .suspend    = s3cfb_suspend,//设备暂定    .resume     = s3cfb_resume, //设备恢复#endif    .driver     = {        .name   = S3CFB_NAME, //设备名字,在s3cfb.h 当中定义,与device匹配的关键,定义如下                              //#define S3CFB_NAME      "s3cfb"        .owner  = THIS_MODULE,#ifdef CONFIG_EXYNOS_DEV_PD        .pm = &s3cfb_pm_ops, //pm电源管理集合#endif    },};static int s3cfb_register(void){    platform_driver_register(&s3cfb_driver); 平台设备的注册    return 0;}static void s3cfb_unregister(void){    platform_driver_unregister(&s3cfb_driver);平台设备的卸载}module_init(s3cfb_register);module_exit(s3cfb_unregister);
s3cfb_probe 是重点 ,现在着重介绍:static int s3cfb_probe(struct platform_device *pdev);   

probe函数的主要作用是获取device资源,获取设备资源,初始化设备,注册和使能设备等
里面涉及的结构体将在必要时介绍。下面是probe函数代码简化,我把一些出错判断和调试信息等删除了以便分析.
下面是我简单的画的一个数据结构体指向草图,希望对你有帮助。
这里写图片描述
// 现在来看看probe框架,里面函数具体介绍放在probe框架介绍之后

 static int s3cfb_probe(struct platform_device *pdev){    struct s3c_platform_fb *pdata = NULL; //s3c平台资源结构体    struct resource *res = NULL; //资源指针    struct s3cfb_global *fbdev[2]; //lcd driver全局指针结构体指针,是分析驱动的核心指针  #ifdef CONFIG_EXYNOS_DEV_PD    /* to use the runtime PM helper functions */    pm_runtime_enable(&pdev->dev);    /* enable the power domain */    pm_runtime_get_sync(&pdev->dev); #endif #ifndef CONFIG_TC4_EVT    lcd_regulator = regulator_get(NULL, "vdd33_lcd");      regulator_enable(lcd_regulator);    //yulu #endif    /*----------------------------------------------*/            pm_runtime_enable ,pm_runtime_get_sysnc 是运行时电源管理(运行时PM)的支持,是在电源管理的核心(PM core)下借助于以下方式实现的。regular_get ,regular_enable   是电源管理制regulator 机制。现在android/linux为模块设备供电有两种,一种GPIO供电,另一个就是电源管理芯片。电源管理芯片可以为多设备供电,且这些设备电压电流有所同。为这些设备提供的稳压器代码模型即为regulator。   这里不做详细要求,如有兴趣请查阅相关资料    /*-----------------------------------------------*/      fbfimd = kzalloc(sizeof(struct s3cfb_fimd_desc), GFP_KERNEL);//创建fimd 设备描述      if (FIMD_MAX == 2)// 接入设备dual 判断,这里显然只有一个,这个宏在s3cfb.h 中        fbfimd->dual = 1;    else        fbfimd->dual = 0;    for (i = 0; i < FIMD_MAX; i++) {//根据要描述的fimd,进行分配空间,初始化等操作        /* global structure */  //分配全局数据区,通过上面的数据结构体可以很清晰看出来        fbfimd->fbdev[i] = kzalloc(sizeof(struct s3cfb_global), GFP_KERNEL);        fbdev[i] = fbfimd->fbdev[i];        fbdev[i]->dev = &pdev->dev; //让global指向了platform 的设备,也就是        //上一节中介绍的平台设备描述,struct platform_device s3c_device_fb 里面有设备的io        //中断资源等 //这个函数是获取具体设备的参数的,跟s3cfb_wa101s.c有关             // 在这个函数中我们看到如何通过硬件拨码开关选择lcd硬件        //讲在下面介绍        s3cfb_set_lcd_info(fbdev[i]);        /* platform_data */        //通过这个函数获得上一篇中介绍的上s3c_platform_fb        //现在让我们回顾一下 在dev-fimd-s5p.c 中有 s3cfb_set_platdat 函数中        /*            struct s3c_platform_fb *npd;........            s3cfb_get_clk_name(npd->clk_name);            npd->cfg_gpio = s3cfb_cfg_gpio;            npd->backlight_on = s3cfb_backlight_on;            npd->backlight_off = s3cfb_backlight_off;            npd->lcd_on = s3cfb_lcd_on;            npd->lcd_off = s3cfb_lcd_off;            npd->clk_on = s3cfb_clk_on;            npd->clk_off = s3cfb_clk_off;            */        //现在知道作用了吧          pdata = to_fb_plat(&pdev->dev);        if (pdata->cfg_gpio)            pdata->cfg_gpio(pdev);//初始化io,将在下面介绍        if (pdata->clk_on)            pdata->clk_on(pdev, &fbdev[i]->clock);//初始化时钟            //将在下面介绍                    /* io memory */        //从平台设备中获取io资源,申请io资源,映射io资源        res = platform_get_resource(pdev, IORESOURCE_MEM, i);        res = request_mem_region(res->start,                    res->end - res->start + 1, pdev->name);        fbdev[i]->regs = ioremap(res->start, res->end - res->start + 1);        /* irq */ 从平台驱动获取frame中断        fbdev[i]->irq = platform_get_irq(pdev, 0);        request_irq(fbdev[i]->irq, s3cfb_irq_frame, IRQF_SHARED,pdev->name, fbdev[i])        // 如有必要获取fifo中断        #ifdef CONFIG_FB_S5P_TRACE_UNDERRUN        if (request_irq(platform_get_irq(pdev, 1), s3cfb_irq_fifo,IRQF_DISABLED, pdev->name, fbdev[i]))         s3cfb_set_fifo_interrupt(fbdev[i], 1);        dev_info(fbdev[i]->dev, "fifo underrun trace\n");        #endif        /* hw setting */        /*故名思议这是对硬件的初始化,里面主要是对exynos4412的寄存器设置所有会调到 s3cfb_fimd6x.c 中的寄存器操作,将在下面详细介绍*/        s3cfb_init_global(fbdev[i]);        fbdev[i]->system_state = POWER_ON;//设置设备工作状态power on        /* alloc fb_info */        /* 这个函数在s3cfb_ops.c 文件中   -------fb 操作集合*/        /*这个函数的作用是申请struct fb_info 结构体,初始化fb_info 结构体的信息*/        /*fb_info 结构体 上与内核接口耦合的关系,我们写lcd驱动就是除了初始化相关硬件以外*/        /*就是把fb_info 结构体初始化后 注册到内核,供 fb_mem 调用,上层才能跟底层结合起来*/        /*该函数具体内容将在接下来介绍*/        s3cfb_alloc_framebuffer(fbdev[i], i);         /* register fb_info */        /*这个函数在s3cfb_ops.c 文件中 主要是向内核注册fb_info ,将在以后介绍*/        if (s3cfb_register_framebuffer(fbdev[i]))         /* enable display */        /*s3cfb_set_clock 向VIDCON0 配置相应的时钟参数*/        s3cfb_set_clock(fbdev[i]);        /* --------选择windows通道,使能wins窗口,将在接下来*/        s3cfb_enable_window(fbdev[0], pdata->default_win);        #ifdef CONFIG_FB_S5P_SOFTBUTTON_UI /* Add Menu UI */        s3cfb_enable_window(fbdev[0], 4);        #endif        /*设置窗口状态,/* screen: unblanked, hsync: on,  vsync: on */        s3cfb_update_power_state(fbdev[i], pdata->default_win,                    FB_BLANK_UNBLANK);        /*2.真正使能lcd模块,设置exynos的基础器,所以与硬件有关*/        /*具体函数在 s3cfb_fimd6x.c 。将在接下来介绍*/        s3cfb_display_on(fbdev[i]);        #ifdef CONFIG_FB_S5P_LCD_INIT        /* panel control */        if (pdata->backlight_on) //判断是否开启背光            pdata->backlight_on(pdev);        if (pdata->lcd_on)  //判断是启动lcd            pdata->lcd_on(pdev);        #endif        /*在/sys/class/下创建一个属性文件 okprobe 函数就此结束*/           ret = device_create_file(&(pdev->dev), &dev_attr_win_power);        return 0;}

好了我们再来回顾了probe函数的主要作用和流程:
1. 获取平台设备 device中的资源
2. 对设备做了一下相应的初始化
3. 申请了fb_info ,根据要求进行了填充
4. 向内核提交了fb_info
5. 使能设备等
6. 创建属性文件

这是probe功能,remove是做相应的逆操作,在这里不做介绍了。

后:在上面的介绍中是只有简单介绍了probe中主要有哪些函数和一些功能,
那么在下一节中将会介绍,这些函数的具体实现和原理
未完待续。。。。。

0 0
原创粉丝点击