移植较新(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 set\n", 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 mode\n", 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 set\n", 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 in\n", 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 registered\n", 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=%s\n",
			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);
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值