s3c2440 lcd驱动源码文件是:drivers/video/s3c2410fb.c
看驱动源码首先当然是先看入口函数,这里是s3c2410fb_init函数
- int __init s3c2410fb_init(void)
- {
-
- int ret = platform_driver_register(&s3c2410fb_driver);
-
- if (ret == 0)
- ret = platform_driver_register(&s3c2412fb_driver);;
-
- return ret;
- }
出口函数,自然是注销s3c2410fb_driver平台驱动
- static void __exit s3c2410fb_cleanup(void)
- {
- platform_driver_unregister(&s3c2410fb_driver);
- platform_driver_unregister(&s3c2412fb_driver);
- }
我们研究的是s3c2440,只关心s3c2410fb_driver,s3c2412fb_driver不用理会。
- static struct platform_driver s3c2410fb_driver = {
- .probe = s3c2410fb_probe,
- .remove = s3c2410fb_remove,
- .suspend = s3c2410fb_suspend,
- .resume = s3c2410fb_resume,
- .driver = {
- .name = "s3c2410-lcd",
- .owner = THIS_MODULE,
- },
- };
这里看到s3c2410fb_driver的name字段为s3c2410-lcd。回顾这钱前面章节说过的知识,如果linux系统中存在同名的平台设备时,就会调用平台驱动的probe函数。这里,如果存在有同名"s3c2410-lcd"的平台设备,就会调用s3c2410fb_driver的s3c2410fb_probe函数。
在source insight搜索s3c2410-lcd,很快就能搜索到arch/arm/plat-s3c24xx/devs.c中有那么一段
- struct platform_device s3c_device_lcd = {
- .name = "s3c2410-lcd",
- .id = -1,
- .num_resources = ARRAY_SIZE(s3c_lcd_resource),
- .resource = s3c_lcd_resource,
- .dev = {
- .dma_mask = &s3c_device_lcd_dmamask,
- .coherent_dma_mask = 0xffffffffUL
- }
- };
-
- EXPORT_SYMBOL(s3c_device_lcd);
其中平台设备中比较重要的是成员是resource,这里是s3c_lcd_resource
- static struct resource s3c_lcd_resource[] = {
- [0] = {
- .start = S3C24XX_PA_LCD,
- .end = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_LCD,
- .end = IRQ_LCD,
- .flags = IORESOURCE_IRQ,
- }
-
- };
-
- static u64 s3c_device_lcd_dmamask = 0xffffffffUL;
那么接下来当然是要分析probe函数了
- static int __init s3c2410fb_probe(struct platform_device *pdev)
- {
- return s3c24xxfb_probe(pdev, DRV_S3C2410);
- }
s3c2410fb_probe
函数调用s3c24xxfb_probe函数,这是lcd驱动的关键函数之一,留到"linux lcd设备驱动剖析二"再分析,但是在分析这个函数前,需要来熟悉一下几个结构体。
Linux lcd驱动中有个关键词叫帧缓冲,它是linux为显示设备提供的一个接口,它允许应用程序在图形模式下直接对显示缓冲区进行读写操作,用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。
帧缓冲设备为标准字符设备,主设备号为29,对应/dev/fbn 设备文件,帧缓冲设备最关键的一个数据结构是fb_info结构体,它包括了关于帧缓冲设备属性和操作的完整描述。
- struct fb_info {
- int node;
- int flags;
- struct mutex lock;
- struct fb_var_screeninfo var;
- struct fb_fix_screeninfo fix;
- struct fb_monspecs monspecs;
- struct work_struct queue;
- struct fb_pixmap pixmap;
- struct fb_pixmap sprite;
- struct fb_cmap cmap;
- struct list_head modelist;
- struct fb_videomode *mode;
-
- char __iomem *screen_base;
- unsigned long screen_size;
- void *pseudo_palette;
- #define FBINFO_STATE_RUNNING 0
- #define FBINFO_STATE_SUSPENDED 1
- u32 state;
- void *fbcon_par;
- void *par;
- };
s3c2410fb_info
结构体,这是s3c2410抽像出来的特有信息
- struct s3c2410fb_info {
- struct device *dev;
- struct clk *clk;
-
- struct resource *mem;
- void __iomem *io;
- void __iomem *irq_base;
-
- enum s3c_drv_type drv_type;
- struct s3c2410fb_hw regs;
-
- unsigned int palette_ready;
-
-
- u32 palette_buffer[256];
- u32 pseudo_pal[16];
- };
s3c2410fb_display
结构体,关于LCD参数的描述,如分辨率,LCD类型,BPP等等
-
- struct s3c2410fb_display {
-
- unsigned type;
-
-
- unsigned short width;
- unsigned short height;
-
-
- unsigned short xres;
- unsigned short yres;
- unsigned short bpp;
-
- unsigned pixclock;
- unsigned setclkval;
- unsigned short left_margin;
- unsigned short right_margin;
- unsigned short hsync_len;
- unsigned short upper_margin;
- unsigned short lower_margin;
- unsigned short vsync_len;
-
-
- unsigned long lcdcon5;
- };
对于TQ2440的液晶屏实例为tq2440_lcd_cfg,为方便查阅这里省略了其他分辨率的参数设置
-
- static struct s3c2410fb_display tq2440_lcd_cfg __initdata = {
- .lcdcon5 = S3C2410_LCDCON5_FRM565 |
- S3C2410_LCDCON5_INVVLINE |
- S3C2410_LCDCON5_INVVFRAME |
- S3C2410_LCDCON5_PWREN |
- S3C2410_LCDCON5_HWSWP,
- .type = S3C2410_LCDCON1_TFT,
-
- #elif defined(CONFIG_FB_S3C24X0_TFT480272) /* config_EmbedSky_W43:CONFIG_FB_S3C24X0_TFT480272=y */
- .width = 480,
- .height = 272,
-
- .pixclock = 40000,
- .setclkval = 0x4,
- .xres = 480,
- .yres = 272,
- .bpp = 16,
- .left_margin = 19,
- .right_margin = 10,
- .hsync_len = 30,
- .upper_margin = 4,
- .lower_margin = 2,
- .vsync_len = 8,
- };
s3c2410fb_mach_info
结构体,它包括了s3c2410fb_display结构体
- struct s3c2410fb_mach_info {
- struct s3c2410fb_display *displays;
- unsigned num_displays;
- unsigned default_display;
-
-
- unsigned long gpcup;
- unsigned long gpcup_mask;
- unsigned long gpccon;
- unsigned long gpccon_mask;
- unsigned long gpdup;
- unsigned long gpdup_mask;
- unsigned long gpdcon;
- unsigned long gpdcon_mask;
-
-
- unsigned long lpcsel;
- };
要理解s3c24xxfb_probe函数,首先必须理清上面几个结构体之间的关系。