zoukankan      html  css  js  c++  java
  • linux lcd设备驱动剖析一

    s3c2440 lcd驱动源码文件是:drivers/video/s3c2410fb.c

    看驱动源码首先当然是先看入口函数,这里是s3c2410fb_init函数

    [cpp] view plain?
    1. int __init s3c2410fb_init(void)  
    2. {  
    3.     /* 注册一个s3c2410fb_driver平台驱动 */  
    4.     int ret = platform_driver_register(&s3c2410fb_driver);  
    5.   
    6.     if (ret == 0)  
    7.         ret = platform_driver_register(&s3c2412fb_driver);;  
    8.   
    9.     return ret;  
    10. }  
    出口函数,自然是注销s3c2410fb_driver平台驱动

    [cpp] view plain?
    1. static void __exit s3c2410fb_cleanup(void)  
    2. {  
    3.     platform_driver_unregister(&s3c2410fb_driver);  
    4.     platform_driver_unregister(&s3c2412fb_driver);  
    5. }  
    我们研究的是s3c2440,只关心s3c2410fb_driver,s3c2412fb_driver不用理会。

    [cpp] view plain?
    1. static struct platform_driver s3c2410fb_driver = {  
    2.     .probe      = s3c2410fb_probe,  
    3.     .remove     = s3c2410fb_remove,  
    4.     .suspend    = s3c2410fb_suspend,  
    5.     .resume     = s3c2410fb_resume,  
    6.     .driver     = {  
    7.         .name   = "s3c2410-lcd",  
    8.         .owner  = THIS_MODULE,  
    9.     },  
    10. };  
    这里看到s3c2410fb_driver的name字段为s3c2410-lcd。回顾这钱前面章节说过的知识,如果linux系统中存在同名的平台设备时,就会调用平台驱动的probe函数。这里,如果存在有同名"s3c2410-lcd"的平台设备,就会调用s3c2410fb_driver的s3c2410fb_probe函数。

    在source  insight搜索s3c2410-lcd,很快就能搜索到arch/arm/plat-s3c24xx/devs.c中有那么一段

    [cpp] view plain?
    1. struct platform_device s3c_device_lcd = {  
    2.     .name         = "s3c2410-lcd",  
    3.     .id       = -1,  
    4.     .num_resources    = ARRAY_SIZE(s3c_lcd_resource),  
    5.     .resource     = s3c_lcd_resource,  
    6.     .dev              = {  
    7.         .dma_mask       = &s3c_device_lcd_dmamask,  
    8.         .coherent_dma_mask  = 0xffffffffUL  
    9.     }  
    10. };  
    11.   
    12. EXPORT_SYMBOL(s3c_device_lcd);  
    其中平台设备中比较重要的是成员是resource,这里是s3c_lcd_resource

    [cpp] view plain?
    1. static struct resource s3c_lcd_resource[] = {  
    2.     [0] = {  
    3.         .start = S3C24XX_PA_LCD,                /* 0x4D000000 */  
    4.         .end   = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,  
    5.         .flags = IORESOURCE_MEM,  
    6.     },  
    7.     [1] = {  
    8.         .start = IRQ_LCD,                       /* IRQ = 32 */  
    9.         .end   = IRQ_LCD,  
    10.         .flags = IORESOURCE_IRQ,  
    11.     }  
    12.   
    13. };  
    14.   
    15. static u64 s3c_device_lcd_dmamask = 0xffffffffUL;  
    那么接下来当然是要分析probe函数了

    [cpp] view plain?
    1. static int __init s3c2410fb_probe(struct platform_device *pdev)  
    2. {  
    3.     return s3c24xxfb_probe(pdev, DRV_S3C2410);  
    4. }  
    s3c2410fb_probe函数调用s3c24xxfb_probe函数,这是lcd驱动的关键函数之一,留到"linux lcd设备驱动剖析二"再分析,但是在分析这个函数前,需要来熟悉一下几个结构体。

    linux lcd驱动中有个关键词叫帧缓冲,它是linux为显示设备提供的一个接口,它允许应用程序在图形模式下直接对显示缓冲区进行读写操作,用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。

    帧缓冲设备为标准字符设备,主设备号为29,对应/dev/fbn 设备文件,帧缓冲设备最关键的一个数据结构是fb_info结构体,它包括了关于帧缓冲设备属性和操作的完整描述。

    [cpp] view plain?
    1. struct fb_info {  
    2.     int node;                       //用作次设备号索引  
    3.     int flags;  
    4.     struct mutex lock;              //用于open/release/ioctl函数的锁  
    5.     struct fb_var_screeninfo var;   //可变参数,重点  
    6.     struct fb_fix_screeninfo fix;   //固定参数,重点  
    7.     struct fb_monspecs monspecs;    //显示器标准  
    8.     struct work_struct queue;       //帧缓冲区队列  
    9.     struct fb_pixmap pixmap;        //图像硬件映射  
    10.     struct fb_pixmap sprite;        //光标硬件映射  
    11.     struct fb_cmap cmap;            //当前颜色表  
    12.     struct list_head modelist;      //模式链表  
    13.     struct fb_videomode *mode;      //当前video模式  
    14.   
    15.     char __iomem *screen_base;      //显存基地址  
    16.     unsigned long screen_size;      //显存大小  
    17.     void *pseudo_palette;           //伪16色颜色表  
    18. #define FBINFO_STATE_RUNNING    0  
    19. #define FBINFO_STATE_SUSPENDED  1  
    20.     u32 state;                      //硬件状态,如挂起  
    21.     void *fbcon_par;                //用作私有数据区  
    22.     void *par;                      //info->par指向了额外多申请内存空间的首地址  
    23. };  
    s3c2410fb_info结构体,这是s3c2410抽像出来的特有信息

    [cpp] view plain?
    1. struct s3c2410fb_info {  
    2.     struct device       *dev;           //设备  
    3.     struct clk          *clk;           //时钟  
    4.   
    5.     struct resource     *mem;           //资源  
    6.     void __iomem        *io;            //IO地址  
    7.     void __iomem        *irq_base;      //IRQ基数  
    8.   
    9.     enum s3c_drv_type   drv_type;       //驱动类型,S3C2410或S3C2412  
    10.     struct s3c2410fb_hw regs;           //s3c2410 lcd硬件寄存器  
    11.   
    12.     unsigned int        palette_ready;  //调色板是否就绪标志位  
    13.   
    14.     /* keep these registers in case we need to re-write palette */  
    15.     u32         palette_buffer[256];    //调色板缓冲区  
    16.     u32         pseudo_pal[16];         //伪颜色表  
    17. };  
    s3c2410fb_display结构体,关于LCD参数的描述,如分辨率,LCD类型,BPP等等

    [cpp] view plain?
    1. /* LCD description */  
    2. struct s3c2410fb_display {  
    3.     /* LCD type */  
    4.     unsigned type;  
    5.   
    6.     /* Screen size */  
    7.     unsigned short width;  
    8.     unsigned short height;  
    9.   
    10.     /* Screen info */  
    11.     unsigned short xres;  
    12.     unsigned short yres;  
    13.     unsigned short bpp;  
    14.   
    15.     unsigned pixclock;           /* pixclock in picoseconds */  
    16.     unsigned setclkval;          /* clkval */  
    17.     unsigned short left_margin;  /* value in pixels (TFT) or HCLKs (STN) */  
    18.     unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */  
    19.     unsigned short hsync_len;    /* value in pixels (TFT) or HCLKs (STN) */  
    20.     unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */  
    21.     unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */  
    22.     unsigned short vsync_len;    /* value in lines (TFT) or 0 (STN) */  
    23.   
    24.     /* lcd configuration registers */  
    25.     unsigned long   lcdcon5;  
    26. };  
    对于TQ2440的液晶屏实例为tq2440_lcd_cfg,为方便查阅这里省略了其他分辨率的参数设置

    [cpp] view plain?
    1. /* LCD driver info */  
    2. static struct s3c2410fb_display tq2440_lcd_cfg __initdata = {  
    3.     .lcdcon5    = S3C2410_LCDCON5_FRM565 |  
    4.               S3C2410_LCDCON5_INVVLINE |  
    5.               S3C2410_LCDCON5_INVVFRAME |  
    6.               S3C2410_LCDCON5_PWREN |  
    7.               S3C2410_LCDCON5_HWSWP,  
    8.     .type       = S3C2410_LCDCON1_TFT,  
    9.     /* TQ2440的液晶是4.3寸的,分辨率是480*272 */  
    10. #elif defined(CONFIG_FB_S3C24X0_TFT480272)  /* config_EmbedSky_W43:CONFIG_FB_S3C24X0_TFT480272=y */  
    11.     .width      = 480,  
    12.     .height     = 272,  
    13.   
    14.     .pixclock   = 40000,    /* HCLK 100 MHz, divisor 1 */  
    15.     .setclkval  = 0x4,  
    16.     .xres       = 480,  
    17.     .yres       = 272,  
    18.     .bpp        = 16,  
    19.     .left_margin    = 19,   /* for HFPD*/  
    20.     .right_margin   = 10,   /* for HBPD*/  
    21.     .hsync_len  = 30,       /* for HSPW*/  
    22.     .upper_margin   = 4,    /* for VFPD*/  
    23.     .lower_margin   = 2,    /* for VBPD*/  
    24.     .vsync_len  = 8,        /* for VSPW*/  
    25. };  
    s3c2410fb_mach_info结构体,它包括了s3c2410fb_display结构体

    [cpp] view plain?
    1. struct s3c2410fb_mach_info {  
    2.     struct s3c2410fb_display *displays;     //s3c2410fb_display结构体  
    3.     unsigned num_displays;                  //displays的个数  
    4.     unsigned default_display;               //默认的default_display个数  
    5.   
    6.     /* GPIOs */  
    7.     unsigned long   gpcup;                  //GPC  
    8.     unsigned long   gpcup_mask;  
    9.     unsigned long   gpccon;  
    10.     unsigned long   gpccon_mask;  
    11.     unsigned long   gpdup;                  //GPD  
    12.     unsigned long   gpdup_mask;  
    13.     unsigned long   gpdcon;  
    14.     unsigned long   gpdcon_mask;  
    15.   
    16.     /* lpc3600 control register */  
    17.     unsigned long   lpcsel;  
    18. };  
    要理解s3c24xxfb_probe函数,首先必须理清上面几个结构体之间的关系。
  • 相关阅读:
    else 的特殊用法和三目运算
    pycharm快捷键
    5、【排序算法】选择排序
    4、【排序算法】希尔排序
    3、【排序算法】直接插入排序
    1、【常见算法】不使用第三个变量交换两个数的值
    1、【排序算法】冒泡排序
    7、【树形结构】哈夫曼树
    6、【树形结构】红黑树
    5、【树形结构】AVL树
  • 原文地址:https://www.cnblogs.com/alan666/p/8312425.html
Copyright © 2011-2022 走看看