FrameBuffer(LCD设备层编程)

大部分驱动程序都是内核自带的,主要是为了进行驱动移植。驱动模型分为驱动层和设备层。现在内核已经带有驱动层带代码,还缺少设备层代码。我们可以根据内核提供的LCD驱动程序,分析出设备层代码。

 在“平台设备驱动之平台设备”中,可以知道设备层步骤:

1.设备占用的资源;2.设备的平台数据结构struct platform_data(可以从设备相应的驱动程序中获得);3.定义并填充struct platform_device结构;4.注册;5.注销

而1,2中的问题可以从两个方面得到:(1)设备硬件原理图;(2)驱动层的探测函数(probe)

s3c2410fb_probe       (drivers\video\s3c2410fb.c)

 1 static int __init s3c24xxfb_probe(struct platform_device *pdev,
 2                   enum s3c_drv_type drv_type)
 3 {
 4     struct s3c2410fb_info *info;
 5     struct s3c2410fb_display *display;
 6     struct fb_info *fbinfo;
 7     struct s3c2410fb_mach_info *mach_info;
 8     struct resource *res;
 9     int ret;
10     int irq;
11     int i;
12     int size;
13     u32 lcdcon1;
14 
15     mach_info = pdev->dev.platform_data;
16     if (mach_info == NULL) {
17         dev_err(&pdev->dev,
18             "no platform data for lcd, cannot attach\n");
19         return -EINVAL;
20     }

 platform_data是平台数据结构,其对应的是mach_info,struct s3c2410fb_mach_info();   (include\mach\fb.h)

 1 struct s3c2410fb_mach_info {
 2 
 3     struct s3c2410fb_display *displays;    /* attached diplays info */
 4     unsigned num_displays;            /* number of defined displays */
 5     unsigned default_display;
 6 
 7     /* GPIOs */
 8 
 9     unsigned long    gpcup;
10     unsigned long    gpcup_mask;
11     unsigned long    gpccon;
12     unsigned long    gpccon_mask;
13     unsigned long    gpdup;
14     unsigned long    gpdup_mask;
15     unsigned long    gpdcon;
16     unsigned long    gpdcon_mask;
17 
18     /* lpc3600 control register */
19     unsigned long    lpcsel;
20 };

struct s3c2410fb_mach_info()中的struct s3c2410fb_display()

 1 struct s3c2410fb_display {
 2     /* LCD type */
 3     unsigned type;
 4 
 5     /* Screen size */
 6     unsigned short width;
 7     unsigned short height;
 8 
 9     /* Screen info */
10     unsigned short xres;
11     unsigned short yres;
12     unsigned short bpp;
13 
14     unsigned pixclock;        /* pixclock in picoseconds */
15     unsigned short left_margin;  /* value in pixels (TFT) or HCLKs (STN) */
16     unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */
17     unsigned short hsync_len;    /* value in pixels (TFT) or HCLKs (STN) */
18     unsigned short upper_margin;    /* value in lines (TFT) or 0 (STN) */
19     unsigned short lower_margin;    /* value in lines (TFT) or 0 (STN) */
20     unsigned short vsync_len;    /* value in lines (TFT) or 0 (STN) */
21 
22     /* lcd configuration registers */
23     unsigned long    lcdcon5;
24 };

平台数据已经找到,接下来是平台数据的初始化和struct platform_device的定义          (arch\arm\mach-s3c2440\mach-mini2440.c)

 1 //(arch\arm\mach-s3c2440\mach-mini2440.c)
 2 static struct s3c2410fb_display mini2440_lcd_cfg __initdata = {
 3 
 4 #if !defined (LCD_CON5)
 5     .lcdcon5    = S3C2410_LCDCON5_FRM565 |
 6               S3C2410_LCDCON5_INVVLINE |
 7               S3C2410_LCDCON5_INVVFRAME |
 8               S3C2410_LCDCON5_PWREN |
 9               S3C2410_LCDCON5_HWSWP,
10 #else
11     .lcdcon5    = LCD_CON5,
12 #endif
13 
14     .type        = S3C2410_LCDCON1_TFT,
15 
16     .width        = LCD_WIDTH,
17     .height        = LCD_HEIGHT,
18 
19     .pixclock    = LCD_PIXCLOCK,
20     .xres        = LCD_WIDTH,
21     .yres        = LCD_HEIGHT,
22     .bpp        = 16,
23     .left_margin    = LCD_LEFT_MARGIN + 1,
24     .right_margin    = LCD_RIGHT_MARGIN + 1,
25     .hsync_len    = LCD_HSYNC_LEN + 1,
26     .upper_margin    = LCD_UPPER_MARGIN + 1,
27     .lower_margin    = LCD_LOWER_MARGIN + 1,
28     .vsync_len    = LCD_VSYNC_LEN + 1,
29 };
30 
31 
32 static struct s3c2410fb_mach_info mini2440_fb_info __initdata = {
33     .displays    = &mini2440_lcd_cfg,
34     .num_displays    = 1,
35     .default_display = 0,
36 
37     .gpccon =       0xaa955699,
38     .gpccon_mask =  0xffc003cc,
39     .gpcup =        0x0000ffff,
40     .gpcup_mask =   0xffffffff,
41 
42     .gpdcon =       0xaa95aaa1,
43     .gpdcon_mask =  0xffc0fff0,
44     .gpdup =        0x0000faff,
45     .gpdup_mask =   0xffffffff,
46 
47 
48     .lpcsel        = 0xf82,
49 };
50 
51 #endif
52 
53 /* (arch\arm\plat-s3c24xx\dev.c)*/
54 
55 static struct resource s3c_lcd_resource[] = {
56     [0] = {
57         .start = S3C24XX_PA_LCD,
58         .end   = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
59         .flags = IORESOURCE_MEM,
60     },
61     [1] = {
62         .start = IRQ_LCD,
63         .end   = IRQ_LCD,
64         .flags = IORESOURCE_IRQ,
65     }
66 
67 };
68 
69 
70 //struct platform_device的定义  (arch\arm\plat-s3c24xx\dev.c)
71 
72 struct platform_device s3c_device_lcd = {
73     .name          = "s3c2410-lcd",
74     .id          = -1,
75     .num_resources      = ARRAY_SIZE(s3c_lcd_resource),
76     .resource      = s3c_lcd_resource,
77     .dev              = {
78         .dma_mask        = &s3c_device_lcd_dmamask,
79         .coherent_dma_mask    = 0xffffffffUL
80     }
81 };

我在看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), 代码如下

 1 void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)
 2 {
 3     struct s3c2410fb_mach_info *npd;
 4 
 5     npd = kmalloc(sizeof(*npd), GFP_KERNEL);
 6     if (npd) {
 7         memcpy(npd, pd, sizeof(*npd));
 8         s3c_device_lcd.dev.platform_data = npd;
 9     } else {
10         printk(KERN_ERR "no memory for LCD platform data\n");
11     }
12 }

在这个程序完成了对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

posted on 2016-03-26 21:49  tragiccandidate  阅读(464)  评论(0编辑  收藏  举报