接着上 一篇,程序看到了probe函数中。
831 mach_info = pdev->dev.platform_data;
832 if (mach_info == NULL) {
833 dev_err(&pdev->dev,
834 "no platform data for lcd, cannot attach\n");
835 return -EINVAL;
836 }
首先获取平台设备中定义的数据,先看struct s3c2410fb_mach_info这个结构体类型的定义:
/* arch/arm/mach-s3c2410/include/mach/fb.h */
51 struct s3c2410fb_mach_info {
52
53 struct s3c2410fb_display *displays; /* attached diplays info */
54 unsigned num_displays; /* number of defined displays */
55 unsigned default_display;
56
57 /* GPIOs */
58
59 unsigned long gpcup;
60 unsigned long gpcup_mask;
61 unsigned long gpccon;
62 unsigned long gpccon_mask;
63 unsigned long gpdup;
64 unsigned long gpdup_mask;
65 unsigned long gpdcon;
66 unsigned long gpdcon_mask;
67
68 /* lpc3600 control register */
69 unsigned long lpcsel;
70 };
我们再来看看这个结构体的定义:
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,
};
再看gpio口定义之前,我们先来看mini2440与lcd的连线。
1. 数据线
lcd总共有18位数据线,r、g、b分别占6位,他们连接到s3c2440的lcd控制器数据线上,分别是VD18~VD23、VD10~VD15、VD2~VD7,但是这些数据线它是复用的,不仅可以作为lcd的数据线,还可以当作普通的gpio口用,所以再使用这些数据线的时候还需要指明这些gpio口的作用。这就这里配置这些gpio口的目的。
2. 行、场信号线
HSYNC、VSYNC也称水平同步信号和垂直同步信号。lcd显示时,是z字形方式扫描,当HSYNC信号出现时,表示一行扫描结束。当VSYNC信号出现时,表示一帧数据结束。所以VSYNC信号的频率为lcd的显示频率,表示一秒钟显示多少帧图像。
3. MCLK
MCLK为lcd的像素时钟,一周期MCLK信号传输一个像素数据,这样数据就源源不断的发送给lcd。
4. RESET、DE
RESET为复位信号线,DE为数据有效数据线。
再来看另外一个数据结构类型定义:
25 /* LCD description */
26 struct s3c2410fb_display {
27 /* LCD type */
28 unsigned type;
29
30 /* Screen size */
31 unsigned short width;
32 unsigned short height;
33
34 /* Screen info */
35 unsigned short xres;
36 unsigned short yres;
37 unsigned short bpp;
38
39 unsigned pixclock; /* pixclock in picoseconds */
40 unsigned short left_margin; /* value in pixels (TFT) or HCLKs (STN) */
41 unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */
42 unsigned short hsync_len; /* value in pixels (TFT) or HCLKs (STN) */
43 unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */
44 unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */
45 unsigned short vsync_len; /* value in lines (TFT) or 0 (STN) */
46
47 /* lcd configuration registers */
48 unsigned long lcdcon5;
49 };
struct s3c2410fb_display描述lcd的显示参数,width和height为像素的宽度与高度,bpp为数据线宽度,是16位还是18位等等,pixclock为像素时钟。mini2440相关定义如下:
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,
};
与TD035STED4 lcd屏相关定义如下:
#define LCD_WIDTH 240
#define LCD_HEIGHT 320
#define LCD_PIXCLOCK 170000
#define LCD_RIGHT_MARGIN 25
#define LCD_LEFT_MARGIN 0
#define LCD_HSYNC_LEN 4
#define LCD_UPPER_MARGIN 1
#define LCD_LOWER_MARGIN 4
#define LCD_VSYNC_LEN 1
struct s3c2410fb_mach_info这个结构是有了,那么它是如何赋值给平台设备的呢。
调用的是s3c24xx_fb_set_platdata这个函数,该函数定义如下:
172 void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)
173 {
174 struct s3c2410fb_mach_info *npd;
175
176 npd = kmalloc(sizeof(*npd), GFP_KERNEL);
177 if (npd) {
178 memcpy(npd, pd, sizeof(*npd));
179 s3c_device_lcd.dev.platform_data = npd;
180 } else {
181 printk(KERN_ERR "no memory for LCD platform data\n");
182 }
183 }
我们看,的确赋值给了s3c_device_lcd这个平台设备。