2.6.31.6已经包含了s3c2440的frame buffer LCD驱动了,我们要做的就是传递正确的platform_data给内核就可以了
1)修改LCD参数设置
根据实际的LCD屏的物理尺寸大小,修改platform_data结构中的s3c2410fb_display结构变量(arch/arm/mach-s3c2440/mach-smdk.c):
107行 static struct s3c2410fb_display smdk2440_lcd_cfg __initdata = {
.lcdcon5 = S3C2410_LCDCON5_FRM565 |
S3C2410_LCDCON5_INVVLINE |
S3C2410_LCDCON5_INVVFRAME |
S3C2410_LCDCON5_PWREN |
S3C2410_LCDCON5_HWSWP,
.type = S3C2410_LCDCON1_TFT,
.width = 320,
.height = 240,
.pixclock = 100000,
.setclkval = 0x03,
.xres = 320,
.yres = 240,
.bpp = 16,
.left_margin = 33,
.right_margin = 22,
.hsync_len = 44,
.upper_margin = 9,
.lower_margin = 3,
.vsync_len = 15,
};
static struct s3c2410_mach_info smdk2440_fb_info __initdata={
..................
..................
// .lpcsel = ((0Xce6)&~7)| 1<<4,
2)修改s3c2410fb_display结构定义,添加setclkval成员。编辑arch/arm/mach-s3c2410/include/mach/fb.h文件,具体修改内容如下:
struct s3c2410fb_display {
unsigned type;
unsigned short width;
unsigned short height;
unsigned short xres;
unsigned short yres;
unsigned short bpp;
unsigned pixclock;
unsigned setclkval;
unsigned short left_margin;
unsigned short right_margin;
unsigned short hsync_len;
unsigned short upper_margin;
unsigned short lower_margin;
unsigned short vsync_len;
unsigned long lcdcon5;
};
3)修改s3c2410 frame buffer驱动,使得计算pixclock更加简洁。编辑drivers/video/s3c2410fb.c,具体修改内容如下:
修改的地方:373,374,把394行改为395行
4)LCD驱动内核配置选项如下:
Device Drivers->
Graphics support->
Support for frame buffer devices->
[*] Enable firmware EDID
[*] Enable Video Mode Handling Helpers
<*> S3C2410 LCD framebuffer support
Console display driver support->
[*] Framebuffer Console support
Bootup logo->(添加开机LOGO)
[*]Standard 224-color Linux logo
5)添加开机Logo。具体Logo图片可以自行选择,我用的是Linux内核自带的logo图标,具体路径如下:drivers/video/logo/logo_linux_clut224.ppm。
A)使用gimp工具修改该logo图标为224色且保存为ascii码形式。之
后将修改后的logo图片文件放回到原位置。
B)内核配置选项如下:Device Drivers->Graphics support->Bootup
logo->Standard 224-color Linux logo
6)添加自己的LCD backlight控制模块。这部分实际上是可以放在s3c2440 LCD驱动里面的,但是我将LCD backlight驱动部分单独作成一个模块进行加载。backlight模块的内核部分如下:(放在/driver/video/目录下)
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <mach/regs-gpio.h>
#define DEVICE_NAME "backlight"
static int s3c2440_backlight_ioctl(struct inode *inode,struct file
*filp,unsigned cmd,unsigned long args)
{
switch(cmd) {
case 0:
s3c2410_gpio_setpin(S3C2410_GPG(4),0);
printk("<1> %s Turn OFF.\n",DEVICE_NAME);
break;
case 1:
s3c2410_gpio_setpin(S3C2410_GPG(4),1);
printk("<1> %s Turn ON.\n",DEVICE_NAME);
break;
default:
printk("<1> cmd error.\n");
break;
}
return 0;
}
static struct file_operations f_ops = {
.owner = THIS_MODULE,
.ioctl = s3c2440_backlight_ioctl,
};
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &f_ops,
};
static int s3c2440_backlight_init(void)
{
int ret;
ret = misc_register(&misc);
printk("<1> %s registered.\n",DEVICE_NAME);
s3c2410_gpio_cfgpin(S3C2410_GPG(4),(0x01 << 8));
return ret;
}
static void s3c2440_backlight_exit(void)
{
misc_deregister(&misc);
}
module_init(s3c2440_backlight_init);
module_exit(s3c2440_backlight_exit);
MODULE_LICENSE("GPL");
backlight用户态测试程序如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <string.h>
int main(int argc,char **argv)
{
int fd,on=0;
if (argc != 2) {
printf("%s [on|off]\n",argv[0]);
return -1;
}
if ((fd = open("/dev/backlight",O_RDWR)) < 0) {
printf("open /dev/backlight error.\n");
return -2;
}
if (!strncmp(argv[1],"on",2))
on = 1;
else if (!strncmp(argv[1],"off",3))
on = 0;
else {
printf("%s [on|off]\n",argv[0]);
close(fd);
return -3;
}
ioctl(fd,on);
close(fd);
return 0;
}