3. 好了,在硬件工程师的帮助下,硬件接好了,那就该我们做软件的干活了,编写驱动吧
1) 让我们首先看一下 RGB数据结构的定义
在 s3c2410fb.c 中找到如下信息
static struct s3c2410fb_rgb xxx_tft_rgb_16 = {
red: {offset:11, length:5,},
green: {offset:5, length:6,},
blue: {offset:0, length:5,},
transp: {offset:0, length:0,},
};
这是对 16 位色的 RGB 颜色进行定义,R:G:B:I = 5:6:5:0,即我们常说的565 显示方式。呵呵,为了让有些朋友更好的理解,我多罗嗦几句,我们随便写一个 16 位数据的颜色数据(为了分析的方便,我把它写成二进制)
RGB = 10101101 10111001
根据上面的结构定义我们来分析一下 RGB 各是多少(因为没有透明色,我们不去分析)
a) blue: {offset: 0, length: 5} 偏移量为 0,长度为 5,我们从那个 RGB 中提取出来便是“11001”
b) green:{offset: 5, length: 6} 偏移量为 5,长度为 6,我们从那个 RGB 中提取出来便是 101 101
c) red: {offset: 11, length: 5 } 偏移量为 11,长度为 5,我们从那个 RGB 中提取出来便是 10101
d) 我们得到了一个 RGB 值为 13:45:200,就是这个颜色
e) 那么反过来,有了 RGB的值我们该如何,因为 RGB 的有效位数都不足一个字节(8 位),那我们只能忍痛割爱了,舍弃掉低位数据,代码如下
r=(rDat&0xF8);
g=(gDat&0xFC);
b=(bDat&0xF8);
hight=r|(g>>5);
low=(g<<3)|(b>>3);
color=(hight<<8)|low;
记住,这段代码在 GUI 程序中是有用的
2) 对于 8 位色(256 色)的数据结构定义
static struct s3c2410fb_rgb rgb_8 = {
red: {offset:0, length:4,},
green: {offset:0, length:4,},
blue: {offset:0, length:4,},
transp: {offset:0, length:0,},
};
这是原程序中给出的定义,我感觉有些错误,我认为应该为 R:G:B = 3:3:2
static struct s3c2410fb_rgb rgb_8 = {
red: {offset:5, length:3,},
green: {offset:2, length:3,},
blue: {offset:0, length:2,},
transp: {offset:0, length:0,},
};
因为没有亲自去调试,所以没有什么发言权,希望做过这方面的朋友给我一个答案。
3) 对于 CSTN 屏,一般都能达到 12 位色(4096 色)的,S3C2410 这颗芯片也是支持的,但是在软件方面要做的工作比较大,因为从原有的代码,我们找不到任何 12位色显示的迹象,另外 Linux 本身好像也不支持 12 位色的,如果你要作的事情比较简单,那你就自己写代码吧。我在此给出 12位色的数据结构定义
static struct s3c2410fb_rgb xxx_stn_rgb_12 = {
red: {offset:8, length:4,},
green: {offset:4, length:4,},
blue: {offset:0, length:4,},
transp: {offset:0, length:0,},
};
但是要完成 12 位色 CSTN 屏驱动程序的编写还有一些工作要做,稍后我会适当的向大家介绍。
4) 接着看下面的代码,其中要修改的部分已经用绿色标出,下面分别进行介绍。
a) 颜色位数
bpp:16
如果你的 LCD 屏是 TFT 的,那一般都可以达到 16 位色或 24 位色,这也要看硬件怎么连接了,根据情况进行设置即可;
如果你的 LCD屏是 CSTN的,按照常规 LCD手册的介绍,一般都可以支持到8 位色(256色),而实际的 CSTN屏的显示效果都可以达到 12 位色(4096色),那可有很大的区别的,如果你要选择便宜的屏又要丰富的颜色,那就费点劲,完成 12 位色的驱动。
b) LCD屏的宽度和高度
xres: 240
yres: 320
这个就不用多说了,你的屏的分辨率是多少就设置成多少呗。
c) 寄存器的设置,这些也不困难。下面就让我们一起一口一口的将 S3C2410 的LCD寄存器统统吃掉! 首先介绍一下我这块屏,这是日立的一块 TFT 屏,大小为 640X240,可以支持到 16位色。 与驱动有关的一张表
图二 LCD屏资料
有了这些信息,让我们看一下 LCD寄存器的设置。
LCD控制器1
- LINECNT --- 这是一个只读的数据,我们当然没有必要理它
- CLKVAL --- 这可是一个很有用的参数,其实没必要管它后面的计算,我们可以通过实际的测试来得出一个有效的值,对于320x240 的屏一般设置为 7 就可以了,而对于 640x480 的屏,该值可以小一点。对于后面的计算公式及注释(STN: CLKVAL >= 2,TFT: CLKVAL >= 0),我不知道该如何去理解,因为在实际的应用中我点了一块 640X240 的CSTN 屏,当我的 CLKVAL = 1 时才达到了一个最佳的效果,这似乎与说明书相违背,我也解释不清为什么?!
- PNRMODE --- 这个应该不用多做解释,大家一看都明白了,对于 TFT 屏,只能设置成 11,而对于 CSTN 屏,可能需要根据实际屏的信息去设置,我遇到的屏都设置成 10,即 8bit 单扫描模式。对于4bit单扫描、4bit 双扫描、8bit 单扫描的说明在 s3c2410 的手册中有详细的介绍,大家可以去参考一下。
- BPPMODE --- 这个参数更不用多说了吧,就是设置屏的颜色位数喽。
- 这些参数的设置都很简单,我给出我这块屏的定义:
lcdcon1: LCD1_BPP_16T | LCD1_PNR_TFT | LCD1_CLKVAL(1), - 同时,我也给出一块 CSTN 屏的寄存器参数信息
lcdcon1: LCD1_BPP_12S | LCD1_PNR_8S | LCD1_CLKVAL(9),
LCD控制器2
对于 TFT 屏必须要填,至于什么意思怎么翻译,相信大家都比我的水平强,自己翻译吧。我只说明从 LCD中如何将这个值“扣”出来。
很容易,看一下图二 LCD屏资料,对比一下得出如下信息:
- LCD2_VBPD:
Vertical back porch 典型值为 7 - LCD2_VFPD:
Vertical front porch 典型值为 4 - LCD2_VSPW:
Vsync Valid width 典型值为 2 - 关于 LINEVAL 在程序的后面将会提到,此处不必理会。
- 经过分析,我们知道了如何设置 LCD2:
lcdcon2: LCD2_VBPD(7) | LCD2_VFPD(4) | LCD2_VSPW(2), - 对于 STN(CSTN)屏,这个寄存器的设置最简单,将 VBPD、VFPD、VSPW 都设置成 Zero 就可以了。即
lcdcon2: LCD2_VBPD(0) | LCD2_VFPD(0) | LCD2_VSPW(0),