我是靠谱客的博主 超帅刺猬,最近开发中收集的这篇文章主要介绍移植较新(Linux3.19)内核至mini2440开发板(二)——LCD的移植,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

在这篇文章中我们将移植LCD驱动,因为博主的屏是P35,所有以下的讲解主要建立在P35屏的基础上,其他的屏理论上移植过程也是一样的,只需要按照数据手册对个别参数进行修改即可。

1在Linux3.19内核中,已经对s3c2440的lcd控制器进行了很完善的支持,我们在移植时只需要对相关的结构体赋值,然后调用初始化函数进行初始化即可。

首先,针对不同的lcd屏,主要的区别有如下几个参数:

VBP(vertical back porch):表示在一帧图像开始时,垂直同步信号以后的无效的行数,对应驱动中的upper_margin;

  VFB(vertical front porch):表示在一帧图像结束后,垂直同步信号以前的无效的行数,对应驱动中的lower_margin;

  VSPW(vertical sync pulse width):表示垂直同步脉冲的宽度,用行数计算,对应驱动中的vsync_len;

  HBP(horizontal back porch):表示从水平同步信号开始到一行的有效数据开始之间的VCLK的个数,对应驱动中的left_margin;

  HFP(horizontal front porth):表示一行的有效数据结束到下一个水平同步信号开始之间的VCLK的个数,对应驱动中的right_margin;

        HSPW(horizontal sync pulse width):表示水平同步信号的宽度,用VCLK计算,对应驱动中的hsync_len;


具体可参考这篇博客:http://blog.csdn.net/l627859442/article/details/7699560


从数据手册中我们可以得到这些数据的典型值。

首先,我们可以可为这些数据定义如下宏,并计算出pixclock的值

/*
* 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)

然后我们需要根据屏的数据手册增加如下函数:

static struct s3c2410fb_display mini2440_lcd_cfg[] __initdata = {
/* mini2440 + 3.5" TFT (LCD-P35,
ZQ3506_V0
+ touchscreen*/
[0] = {
_LCD_DECLARE(
/* clock */
6,
/* xres, margin_right, margin_left, hsync */
320, 2, 8, 1,
/* yres, margin_top, margin_bottom, vsync */
240, 12, 4, 1,
/* refresh rate */
60),
.lcdcon5	= (S3C2410_LCDCON5_FRM565 |
S3C2410_LCDCON5_INVVCLK |
S3C2410_LCDCON5_INVVFRAME |
S3C2410_LCDCON5_INVVLINE |
S3C2410_LCDCON5_HWSWP ),
},
};
其中 _LCD_DECLARE宏定义中的相关数据来自数据手册给的典型值,然后进行微调试凑所得。其中,lcdcon5寄存器的设置可参考如下说明:

 LCDCON5寄存器:

                 VSTATUS :当前VSYNC信号扫描状态,指明当前VSYNC同步信号处于何种扫描阶段。

                 HSTATUS :当前HSYNC信号扫描状态,指明当前HSYNC同步信号处于何种扫描阶段。
                 BPP24BL :设定24bpp显示模式时,视频资料在显示缓冲区中的排列顺序(即低位有效还是高位有效)。
                                        对于16bpp的 64K色显示模式,该设置位无意义。
                 FRM565 :对于16bpp显示模式,有2中形式,一种是RGB=5:5:5:1,另一种是5:6:5。后一 种模式最为
                                     常用,它的含义是表示64K种色彩的16bit RGB资料中,红色(R)占了5bit,绿色(G)占了
                                     6bit,兰色(B)占了5bit。
                 INVVCLK 、INVLINE 、INVFRAME 、INVVD :通过前面提到的‘Figure 15-6’的时序图,我们知
                                 道,CPU的LCD控制器输出的时序默认是正脉冲,而LCD需要VSYNC(VFRAME)、
                                 VLINE(HSYNC)均为负脉冲,因此 INVLINE 和 INVFRAME 必须设为“1 ”,即选择反相输
                                  出。 INVVDEN , INVPWREN , INVLEND 的功能同前面的类似。
                 PWREN :LCD电源使能控制。在CPU LCD控制器的输出信号中,有一个电源使能管脚LCD_PWREN,用
                                    来做为LCD屏电源的开关信号。
                 ENLEND :对普通的TFT屏无效,可以不考虑。

                 INVVDEN、INVPWREN、INVLEND:是否翻转这些信号,一般为正常,不需要翻转。

                  BSWP 、HWSWP : 为字节(Byte)或半字(Half-Word)交换使能。由于不同的GUI对
                                              FrameBuffer(显示缓冲区)的管理不同,必要时需要通过调整 BSWP 和 HWSWP
                                             来适应GUI。


之后,我们需要根据具体的硬件连接对连接到lcd的相关的管脚进行复用功能的设置,具体连接方式可参考开发板的原理图,代码如下:

/* todo - put into gpio header */
#define S3C2410_GPCCON_MASK(x)	(3 << ((x) * 2))
#define S3C2410_GPDCON_MASK(x)	(3 << ((x) * 2))
static struct s3c2410fb_mach_info mini2440_fb_info __initdata = {
.displays
= &mini2440_lcd_cfg[0], /* not constant! see init */
.num_displays
= 1,
.default_display = 0,
/* Enable VD[2..7], VD[10..15], VD[18..23] and VCLK, syncs, VDEN
* and disable the pull down resistors on pins we are using for LCD
* data. */
.gpcup
= (0xf << 1) | (0x3f << 10),
.gpccon
= (S3C2410_GPC1_VCLK
| S3C2410_GPC2_VLINE |
S3C2410_GPC3_VFRAME | S3C2410_GPC4_VM |
S3C2410_GPC10_VD2
| S3C2410_GPC11_VD3 |
S3C2410_GPC12_VD4
| S3C2410_GPC13_VD5 |
S3C2410_GPC14_VD6
| S3C2410_GPC15_VD7),
.gpccon_mask	= (S3C2410_GPCCON_MASK(1)
| S3C2410_GPCCON_MASK(2)
|
S3C2410_GPCCON_MASK(3)
| S3C2410_GPCCON_MASK(4)
|
S3C2410_GPCCON_MASK(10) | S3C2410_GPCCON_MASK(11) |
S3C2410_GPCCON_MASK(12) | S3C2410_GPCCON_MASK(13) |
S3C2410_GPCCON_MASK(14) | S3C2410_GPCCON_MASK(15)),
.gpdup
= (0x3f << 2) | (0x3f << 10),
.gpdcon
= (S3C2410_GPD2_VD10
| S3C2410_GPD3_VD11 |
S3C2410_GPD4_VD12
| S3C2410_GPD5_VD13 |
S3C2410_GPD6_VD14
| S3C2410_GPD7_VD15 |
S3C2410_GPD10_VD18 | S3C2410_GPD11_VD19 |
S3C2410_GPD12_VD20 | S3C2410_GPD13_VD21 |
S3C2410_GPD14_VD22 | S3C2410_GPD15_VD23),
.gpdcon_mask	= (S3C2410_GPDCON_MASK(2)
| S3C2410_GPDCON_MASK(3) |
S3C2410_GPDCON_MASK(4)
| S3C2410_GPDCON_MASK(5) |
S3C2410_GPDCON_MASK(6)
| S3C2410_GPDCON_MASK(7) |
S3C2410_GPDCON_MASK(10) | S3C2410_GPDCON_MASK(11)|
S3C2410_GPDCON_MASK(12) | S3C2410_GPDCON_MASK(13)|
S3C2410_GPDCON_MASK(14) | S3C2410_GPDCON_MASK(15)),
};


以上已经完成了对lcd的信息配置,然后增加以下函数,以选择我们刚添加的那个lcd配置:

<pre name="code" class="cpp">/*
* mini2440_features string
*
* t = Touchscreen present
* c = camera [TODO]
* 0-9 LCD configuration
*
*/
static char mini2440_features_str[12] __initdata = "0t";
static int __init mini2440_features_setup(char *str)
{
if (str)
strlcpy(mini2440_features_str, str, sizeof(mini2440_features_str));
return 1;
}
__setup("mini2440=", mini2440_features_setup);
#define FEATURE_SCREEN (1 << 0)
#define FEATURE_BACKLIGHT (1 << 1)
#define FEATURE_TOUCH (1 << 2)
#define FEATURE_CAMERA (1 << 3)
struct mini2440_features_t {
<span style="white-space:pre">	</span>int count;
<span style="white-space:pre">	</span>int done;
<span style="white-space:pre">	</span>int lcd_index;
<span style="white-space:pre">	</span>struct platform_device *optional[8];
};
static void __init mini2440_parse_features(
<span style="white-space:pre">
</span>struct mini2440_features_t * features,
<span style="white-space:pre">
</span>const char * features_str )
{
<span style="white-space:pre">	</span>const char * fp = features_str;
<span style="white-space:pre">	</span>features->count = 0;
<span style="white-space:pre">	</span>features->done = 0;
<span style="white-space:pre">	</span>features->lcd_index = -1;
<span style="white-space:pre">	</span>while (*fp) {
<span style="white-space:pre">
</span>char f = *fp++;
<span style="white-space:pre">
</span>switch (f) {
<span style="white-space:pre">
</span>case '0'...'9':<span style="white-space:pre">	</span>/* tft screen */
<span style="white-space:pre">
</span>if (features->done & FEATURE_SCREEN) {
<span style="white-space:pre">
</span>printk(KERN_INFO "MINI2440: '%c' ignored, "
<span style="white-space:pre">
</span>"screen type already setn", f);
<span style="white-space:pre">
</span>} else {
<span style="white-space:pre">
</span>int li = f - '0';
<span style="white-space:pre">
</span>if (li >= ARRAY_SIZE(mini2440_lcd_cfg))
<span style="white-space:pre">
</span>printk(KERN_INFO "MINI2440: "
<span style="white-space:pre">
</span>"'%c' out of range LCD moden", f);
<span style="white-space:pre">
</span>else {
<span style="white-space:pre">
</span>features->optional[features->count++] =
<span style="white-space:pre">
</span>&s3c_device_lcd;
<span style="white-space:pre">
</span>features->lcd_index = li;
<span style="white-space:pre">
</span>}
<span style="white-space:pre">
</span>}
<span style="white-space:pre">
</span>features->done |= FEATURE_SCREEN;
<span style="white-space:pre">
</span>break;
<span style="white-space:pre">
</span>/*case 'b':
<span style="white-space:pre">
</span>if (features->done & FEATURE_BACKLIGHT)
<span style="white-space:pre">
</span>printk(KERN_INFO "MINI2440: '%c' ignored, "
<span style="white-space:pre">
</span>"backlight already setn", f);
<span style="white-space:pre">
</span>else {
<span style="white-space:pre">
</span>features->optional[features->count++] =
<span style="white-space:pre">
</span>&mini2440_led_backlight;
<span style="white-space:pre">
</span>}
<span style="white-space:pre">
</span>features->done |= FEATURE_BACKLIGHT;
<span style="white-space:pre">
</span>break;<span style="font-family: Arial, Helvetica, sans-serif;">*/</span>


<pre name="code" class="cpp"><span style="white-space:pre">
</span>case 't':
<span style="white-space:pre">
</span>printk(KERN_INFO "MINI2440: '%c' ignored, "
<span style="white-space:pre">
</span>"touchscreen not compiled inn", f);
<span style="white-space:pre">
</span>break;
<span style="white-space:pre">
</span>case 'c':
<span style="white-space:pre">
</span>if (features->done & FEATURE_CAMERA)
<span style="white-space:pre">
</span>printk(KERN_INFO "MINI2440: '%c' ignored, "
<span style="white-space:pre">
</span>"camera already registeredn", f);
<span style="white-space:pre">
</span>else
<span style="white-space:pre">
</span>features->optional[features->count++] =
<span style="white-space:pre">
</span>&s3c_device_camif;
<span style="white-space:pre">
</span>features->done |= FEATURE_CAMERA;
<span style="white-space:pre">
</span>break;
<span style="white-space:pre">
</span>}
<span style="white-space:pre">	</span>}
}



其中的<span style="font-family: Arial, Helvetica, sans-serif;">static char mini2440_features_str[12] __initdata = "0t";</span><span style="font-family: Arial, Helvetica, sans-serif;">0是因为在结构体数组</span><span style="font-family: Arial, Helvetica, sans-serif;">static struct s3c2410fb_display mini2440_lcd_cfg[] __initdata中我们的屏P35是第0个,读者可根据具体情况填入相应的数字。</span>


添加如下头文件:

#include <mach/gpio-samsung.h>

#include <linux/gpio.h>

#include <plat/gpio-cfg.h>

将 函数进行如下修改:

static void __init mini2440_machine_init(void)
{
struct mini2440_features_t features = { 0 };
int i;
printk(KERN_INFO "MINI2440: Option string mini2440=%sn",
mini2440_features_str);
/* Parse the feature string */
mini2440_parse_features(&features, mini2440_features_str);
/* turn LCD on */
s3c_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND);
/* Turn the backlight early on */
WARN_ON(gpio_request_one(S3C2410_GPG(4), GPIOF_OUT_INIT_HIGH, NULL));
gpio_free(S3C2410_GPG(4));
/* remove pullup on optional PWM backlight -- unused on 3.5 and 7"s */
gpio_request_one(S3C2410_GPB(1), GPIOF_IN, NULL);
s3c_gpio_setpull(S3C2410_GPB(1), S3C_GPIO_PULL_UP);
gpio_free(S3C2410_GPB(1));
if (features.lcd_index != -1) {
int li;
mini2440_fb_info.displays =
&mini2440_lcd_cfg[features.lcd_index];
printk(KERN_INFO "MINI2440: LCD");
for (li = 0; li < ARRAY_SIZE(mini2440_lcd_cfg); li++)
if (li == features.lcd_index)
printk(" [%d:%dx%d]", li,
mini2440_lcd_cfg[li].width,
mini2440_lcd_cfg[li].height);
else
printk(" %d:%dx%d", li,
mini2440_lcd_cfg[li].width,
mini2440_lcd_cfg[li].height);
printk("n");
s3c24xx_fb_set_platdata(&mini2440_fb_info);
}
s3c_i2c0_set_platdata(NULL);
s3c_nand_set_platdata(&mini2440_nand_info);
platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));
if (features.count)	/* the optional features */
platform_add_devices(features.optional, features.count);
}

重新编译烧录到板子上后重启,此时我们我们已经可以看到那个经典的小企鹅了。关于触摸屏的一直将在以后的文章中进行。

最后

以上就是超帅刺猬为你收集整理的移植较新(Linux3.19)内核至mini2440开发板(二)——LCD的移植的全部内容,希望文章能够帮你解决移植较新(Linux3.19)内核至mini2440开发板(二)——LCD的移植所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部