FrameBuffer(LCD设备层编程)
2016-03-26 21:49
260 查看
大部分驱动程序都是内核自带的,主要是为了进行驱动移植。驱动模型分为驱动层和设备层。现在内核已经带有驱动层带代码,还缺少设备层代码。我们可以根据内核提供的LCD驱动程序,分析出设备层代码。
在“平台设备驱动之平台设备”中,可以知道设备层步骤:
1.设备占用的资源;2.设备的平台数据结构struct platform_data(可以从设备相应的驱动程序中获得);3.定义并填充struct platform_device结构;4.注册;5.注销
而1,2中的问题可以从两个方面得到:(1)设备硬件原理图;(2)驱动层的探测函数(probe)
s3c2410fb_probe (drivers\video\s3c2410fb.c)
platform_data是平台数据结构,其对应的是mach_info,struct s3c2410fb_mach_info(); (include\mach\fb.h)
struct s3c2410fb_mach_info()中的struct s3c2410fb_display()
平台数据已经找到,接下来是平台数据的初始化和struct platform_device的定义 (arch\arm\mach-s3c2440\mach-mini2440.c)
我在看struct platform_device时,发现里面少了struct platform_data的定义,于是便有了在probe函数中,为什么struct s3c2410fb_mach_info *mach_info=pdev->dev.platform_data?
也就是说为什么pdev->dev.platform_data结构类型会是struct s3c2410fb_mach_info, 比如在LED驱动时,dev.platform_data的结构类型就会是s3c2410_leds_drv_data.led_pdata, 就是说platform_data是怎么实现不同数据结构之间的赋值的?
经查找资料知道,在dev.c ( arch\arm\plat-s3c24xx\dev.c)中,会调用函数void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd), 代码如下
在这个程序完成了对dev.platformdata的定义,对函数void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)的理解,可以参考http://www.cnblogs.com/armlinux/archive/2010/07/28/2396954.html
p.s. void __init s3c24xx_...注意(初始化函数)init前面的__ , 而不是_ ;之前在调程序时,遇到了这种提示,找了大半天才发现,是这错了_^_
参考资料:
《嵌入式Linux高级驱动教程》 电子工业出版社 深圳信盈达电子有限公司 陈志发 周中孝 李志超 编著
http://www.cnblogs.com/armlinux/archive/2010/07/28/2396954.html
在“平台设备驱动之平台设备”中,可以知道设备层步骤:
1.设备占用的资源;2.设备的平台数据结构struct platform_data(可以从设备相应的驱动程序中获得);3.定义并填充struct platform_device结构;4.注册;5.注销
而1,2中的问题可以从两个方面得到:(1)设备硬件原理图;(2)驱动层的探测函数(probe)
s3c2410fb_probe (drivers\video\s3c2410fb.c)
static int __init s3c24xxfb_probe(struct platform_device *pdev, enum s3c_drv_type drv_type) { struct s3c2410fb_info *info; struct s3c2410fb_display *display; struct fb_info *fbinfo; struct s3c2410fb_mach_info *mach_info; struct resource *res; int ret; int irq; int i; int size; u32 lcdcon1; mach_info = pdev->dev.platform_data; if (mach_info == NULL) { dev_err(&pdev->dev, "no platform data for lcd, cannot attach\n"); return -EINVAL; }
platform_data是平台数据结构,其对应的是mach_info,struct s3c2410fb_mach_info(); (include\mach\fb.h)
struct s3c2410fb_mach_info { struct s3c2410fb_display *displays; /* attached diplays info */ unsigned num_displays; /* number of defined displays */ unsigned default_display; /* GPIOs */ 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; /* lpc3600 control register */ unsigned long lpcsel; };
struct s3c2410fb_mach_info()中的struct s3c2410fb_display()
struct s3c2410fb_display { /* LCD type */ unsigned type; /* Screen size */ unsigned short width; unsigned short height; /* Screen info */ unsigned short xres; unsigned short yres; unsigned short bpp; unsigned pixclock; /* pixclock in picoseconds */ unsigned short left_margin; /* value in pixels (TFT) or HCLKs (STN) */ unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */ unsigned short hsync_len; /* value in pixels (TFT) or HCLKs (STN) */ unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */ unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */ unsigned short vsync_len; /* value in lines (TFT) or 0 (STN) */ /* lcd configuration registers */ unsigned long lcdcon5; };
平台数据已经找到,接下来是平台数据的初始化和struct platform_device的定义 (arch\arm\mach-s3c2440\mach-mini2440.c)
//(arch\arm\mach-s3c2440\mach-mini2440.c) static struct s3c2410fb_display mini2440_lcd_cfg __initdata = { #if !defined (LCD_CON5) .lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_INVVLINE | S3C2410_LCDCON5_INVVFRAME | S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP, #else .lcdcon5 = LCD_CON5, #endif .type = S3C2410_LCDCON1_TFT, .width = LCD_WIDTH, .height = LCD_HEIGHT, .pixclock = LCD_PIXCLOCK, .xres = LCD_WIDTH, .yres = LCD_HEIGHT, .bpp = 16, .left_margin = LCD_LEFT_MARGIN + 1, .right_margin = LCD_RIGHT_MARGIN + 1, .hsync_len = LCD_HSYNC_LEN + 1, .upper_margin = LCD_UPPER_MARGIN + 1, .lower_margin = LCD_LOWER_MARGIN + 1, .vsync_len = LCD_VSYNC_LEN + 1, }; static struct s3c2410fb_mach_info mini2440_fb_info __initdata = { .displays = &mini2440_lcd_cfg, .num_displays = 1, .default_display = 0, .gpccon = 0xaa955699, .gpccon_mask = 0xffc003cc, .gpcup = 0x0000ffff, .gpcup_mask = 0xffffffff, .gpdcon = 0xaa95aaa1, .gpdcon_mask = 0xffc0fff0, .gpdup = 0x0000faff, .gpdup_mask = 0xffffffff, .lpcsel = 0xf82, }; #endif /* (arch\arm\plat-s3c24xx\dev.c)*/ 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, } }; //struct platform_device的定义 (arch\arm\plat-s3c24xx\dev.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 } };
我在看struct platform_device时,发现里面少了struct platform_data的定义,于是便有了在probe函数中,为什么struct s3c2410fb_mach_info *mach_info=pdev->dev.platform_data?
也就是说为什么pdev->dev.platform_data结构类型会是struct s3c2410fb_mach_info, 比如在LED驱动时,dev.platform_data的结构类型就会是s3c2410_leds_drv_data.led_pdata, 就是说platform_data是怎么实现不同数据结构之间的赋值的?
经查找资料知道,在dev.c ( arch\arm\plat-s3c24xx\dev.c)中,会调用函数void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd), 代码如下
void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd) { struct s3c2410fb_mach_info *npd; npd = kmalloc(sizeof(*npd), GFP_KERNEL); if (npd) { memcpy(npd, pd, sizeof(*npd)); s3c_device_lcd.dev.platform_data = npd; } else { printk(KERN_ERR "no memory for LCD platform data\n"); } }
在这个程序完成了对dev.platformdata的定义,对函数void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)的理解,可以参考http://www.cnblogs.com/armlinux/archive/2010/07/28/2396954.html
p.s. void __init s3c24xx_...注意(初始化函数)init前面的__ , 而不是_ ;之前在调程序时,遇到了这种提示,找了大半天才发现,是这错了_^_
参考资料:
《嵌入式Linux高级驱动教程》 电子工业出版社 深圳信盈达电子有限公司 陈志发 周中孝 李志超 编著
http://www.cnblogs.com/armlinux/archive/2010/07/28/2396954.html
相关文章推荐
- 页面定时刷新或自动跳转
- JS 事件处理初探秘
- JavaScript的隐式类型转换
- NodeJS学习笔记001--概述
- angular路由
- Jquery学习
- 深入浅析JavaScript中的作用域和上下文
- Jquery选择器使用方法
- angularjs2入门实例(2)
- 【Web】JavaScript中Node节点的CURD
- ExtJs之Ajax模式的表单数据加载
- jquery学习总结
- jQuery
- JavaScript检查是否包含某个字符
- [leetcode] 24. Swap Nodes in Pairs
- jQuery中的$.grep()方法的使用
- 【LeetCode】24. Swap Nodes in Pairs
- ExtJs之Ext.comboBox的远程数据源读取程序
- javascript
- 从此不求人:自主研发一套PHP前端开发框架(8)