移植较新(Linux3.19)内核至mini2440开发板(二)——LCD的移植
2015-04-26 18:32
393 查看
在这篇文章中我们将移植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);elseprintk(" %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开发板(一)
- linux-2.6.32在mini2440开发板上移植(6)之W35型LCD驱动移植
- Linux-2.6.32.2内核在mini2440上的移植----LCD驱动移植
- linux-2.6.32在mini2440开发板上移植(0)之内核准备与编译
- 移植最新内核linux-3.14.6到mini2440开发板
- Linux-2.6.32.2内核在mini2440上的移植(六)---添加LCD背光驱动
- Linux-2.6.32.2内核在mini2440上的移植----通过LCD显示内核启动信息及修改Linux LOGO
- FS2410 开发板linux-2.6.35内核 LCD 驱动移植
- linux-2.6.32在mini2440开发板上移植 ---W35型LCD驱动移植
- Linux-2.6.32.2内核在mini2440上的移植(五)---添加LCD背光驱动
- 移植Linux3.4.2版本内核到mini2440(二)--添加网卡、UVC摄像头、LCD驱动
- linux-2.6.32在mini2440开发板上移植之LCD背光控制(5)
- Linux-2.6.32.2内核在mini2440上的移植(六)---LCD驱动移植
- Linux-4.9.2内核在mini2440上的移植(九)——LCD驱动移植
- linux-2.6.32在mini2440开发板上移植(6)之W35型LCD驱动移植
- Linux-2.6.32.2内核在mini2440上的移植(六)---添加LCD背光驱动
- linux-2.6.32在mini2440开发板上移植---LCD背光控制
- Linux-2.6.32.2内核在mini2440上的移植----增加LCD背光驱动
- Linux-2.6.32.2内核在mini2440上的移植(七)---LCD驱动移植
- Linux-2.6.32.2内核在mini2440上的移植(七)---LCD驱动移植