主题 : [转]通宝3.5英寸液晶屏驱动的移植 复制链接 | 浏览器收藏 | 打印
追求卓越,拒绝平庸
级别: 新手上路
UID: 16052
精华: 0
发帖: 21
金钱: 105 两
威望: 21 点
贡献值: 0 点
综合积分: 42 分
注册时间: 2010-03-13
最后登录: 2011-04-07
楼主  发表于: 2010-04-19 10:20

 [转]通宝3.5英寸液晶屏驱动的移植

通宝3.5英寸液晶屏驱动的移植
作者:Athurg        

话说:前面已经把内核linux-2.6.31成功移植到了mini2440上,可是仔细看看才发现,美中不足的是液晶屏的显示好像整体右移了一截。这个问题在移植内核前就遇到过,当时是因为烧错了内核,把NEC的那个内核zImage_N35烧了。因此,自然而然的就想到了肯定是液晶驱动的问题。
由于mini2440板子上的S3C2440是片内带液晶控制器的,因此,驱动部分用的是公共驱动,就是内核中的drivers/video/s3c2410fb.c这个了。而且从显示上来看,除了发生了位移外,没有别的问题,于是就怀疑是不是配置的问题,遂移步到arch/arm/mach-s3c2440/mach-mini2440.c,一看果然有一个结构体定义液晶的配置:

/* LCD timing and setup */

/*
* This macro simplifies the table bellow
*/
#define _LCD_DECLARE(_clock,_xres,margin_left,margin_right,hsync, \
_yres,margin_top,margin_bottom,vsync, refresh) \
.width = _xres, \
.xres = _xres, \
.height = _yres, \
.yres = _yres, \
.left_margin = margin_left, \
.right_margin = margin_right, \
.upper_margin = margin_top, \
.lower_margin = margin_bottom, \
.hsync_len = hsync, \
.vsync_len = vsync, \
.pixclock = ((_clock*100000000000LL) / \
((refresh) * \
(hsync + margin_left + _xres + margin_right) * \
(vsync + margin_top + _yres + margin_bottom))), \
.bpp = 16,\
.type = (S3C2410_LCDCON1_TFT16BPP |\
S3C2410_LCDCON1_TFT)

struct s3c2410fb_display mini2440_lcd_cfg[] = {
[0] = { /* mini2440 + 3.5" TFT + touchscreen */
_LCD_DECLARE(
7, /* The 3.5 is quite fast */
240, 21, 38, 6, /* x timing */
320, 4, 4, 2, /* y timing */
60), /* refresh rate */
.lcdcon5 = (S3C2410_LCDCON5_FRM565 |
S3C2410_LCDCON5_INVVLINE |
S3C2410_LCDCON5_INVVFRAME |
S3C2410_LCDCON5_PWREN |
S3C2410_LCDCON5_HWSWP),
},
[1] = { /* mini2440 + 7" TFT + touchscreen */
_LCD_DECLARE(
10, /* the 7" runs slower */
800, 40, 40, 48, /* x timing */
480, 29, 3, 3, /* y timing */
50), /* refresh rate */
.lcdcon5 = (S3C2410_LCDCON5_FRM565 |
S3C2410_LCDCON5_INVVLINE |
S3C2410_LCDCON5_INVVFRAME |
S3C2410_LCDCON5_PWREN),
},
/* The VGA shield can outout at several resolutions. All share
* the same timings, however, anything smaller than 1024x768
* will only be displayed in the top left corner of a 1024x768
* XGA output unless you add optional dip switches to the shield.
* Therefore timings for other resolutions have been ommited here.
*/
[2] = {
_LCD_DECLARE(
10,
1024, 1, 2, 2, /* y timing */
768, 200, 16, 16, /* x timing */
24), /* refresh rate, maximum stable,
tested with the FPGA shield */
.lcdcon5 = (S3C2410_LCDCON5_FRM565 |
S3C2410_LCDCON5_HWSWP),
},
[3] = { /* mini2440 + TPO(TongBao) 3.5" TFT + touchscreen */
_LCD_DECLARE(
7, /* The 3.5 is quite fast */
240, 1, 26, 5, /* x timing */
320, 2, 5, 2, /* y timing */
60), /* refresh rate */
.lcdcon5 = (S3C2410_LCDCON5_FRM565 |
S3C2410_LCDCON5_INVVLINE |
S3C2410_LCDCON5_INVVFRAME |
S3C2410_LCDCON5_PWREN |
S3C2410_LCDCON5_HWSWP),
},
};

这么好的代码结构,一看就明白了。再打开友善之臂前几个版本的配置(比如2.6.29的)一看,豁然开朗:

/* LCD driver info */

#if defined(CONFIG_FB_S3C2410_N240320)

#define LCD_WIDTH 240
#define LCD_HEIGHT 320
#define LCD_PIXCLOCK 100000

#define LCD_RIGHT_MARGIN 36
#define LCD_LEFT_MARGIN 19
#define LCD_HSYNC_LEN 5

#define LCD_UPPER_MARGIN 1
#define LCD_LOWER_MARGIN 5
#define LCD_VSYNC_LEN 1

#elif defined(CONFIG_FB_S3C2410_TFT640480)
#define LCD_WIDTH 640
#define LCD_HEIGHT 480
#define LCD_PIXCLOCK 80000

#define LCD_RIGHT_MARGIN 67
#define LCD_LEFT_MARGIN 40
#define LCD_HSYNC_LEN 31

#define LCD_UPPER_MARGIN 25
#define LCD_LOWER_MARGIN 5
#define LCD_VSYNC_LEN 1

#elif defined(CONFIG_FB_S3C2410_T240320)
#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

#elif defined(CONFIG_FB_S3C2410_TFT800480)
#define LCD_WIDTH 800
#define LCD_HEIGHT 480
#define LCD_PIXCLOCK 40000

#define LCD_RIGHT_MARGIN 67
#define LCD_LEFT_MARGIN 40
#define LCD_HSYNC_LEN 31

#define LCD_UPPER_MARGIN 25
#define LCD_LOWER_MARGIN 5
#define LCD_VSYNC_LEN 1

#elif defined(CONFIG_FB_S3C2410_VGA1024768)
#define LCD_WIDTH 1024
#define LCD_HEIGHT 768
#define LCD_PIXCLOCK 80000

#define LCD_RIGHT_MARGIN 15
#define LCD_LEFT_MARGIN 199
#define LCD_HSYNC_LEN 15

#define LCD_UPPER_MARGIN 1
#define LCD_LOWER_MARGIN 1
#define LCD_VSYNC_LEN 1
#define LCD_CON5 (S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_HWSWP)

#endif

这不,按葫芦画瓢,在配置液晶配置结构体数组mini2440_lcd_cfg[] 中添加下面这段内容:

[3] = { /* mini2440 + TPO(TongBao) 3.5" TFT + touchscreen */
_LCD_DECLARE(
7, /* The 3.5 is quite fast */
240, 1, 26, 5, /* x timing */
320, 2, 5, 2, /* y timing */
60), /* refresh rate */
.lcdcon5 = (S3C2410_LCDCON5_FRM565 |
S3C2410_LCDCON5_INVVLINE |
S3C2410_LCDCON5_INVVFRAME |
S3C2410_LCDCON5_PWREN |
S3C2410_LCDCON5_HWSWP),
},

同时,修改一下液晶屏幕初始化选项

static char mini2440_features_str[12] __initdata = "0tb";



static char mini2440_features_str[12] __initdata = "3t";

从液晶配置这一点来看,我觉得友善没有2.6.31内核自带的配置合理。友善采用的是宏定义的方式(配置结构体),条件编译内核。所以如果要更换液晶屏,必须重新编译下载内核。但内核采用的是参数化启动的方式(配置结构体数组),这样只需要在内核启动的时候传递一个参数即可支持新的液晶屏。比如这个地方,就可以填写为0~3,自由选择代码中定义了配置的这些液晶屏,也可以自己添加或修改这些配置,然后使用即可。