LCD能够支持彩色图像的显示和视频的播放,是一种很重要的输出设备,在一些嵌入式人机交互系统中,也往往需要lcd进行显示。Linux内核已经支持了s3c2416的lcd控制器。
1. lcd设备
lcd设备包含了名字、独有的资源等等一些驱动程序的硬件或自定义信息。 通过platform_add_devices(platform_device_register)函数将定义的平台设备注册到内核中,用于匹配设备驱动。
内核在drivers\video\fbdev\s3c-fb.c中实现了s3c2416 lcd驱动,lcd设备平台代码如下:
Eastar: /arch/arm/mach-s3c24xx/mach-home2416.c
static struct s3c_fb_pd_win home2416_fb_win[] = {[0]= {.default_bpp = 16,.max_bpp = 32,.xres = 800,.yres = 480,},};static struct fb_videomode home2416_lcd_timing = {.pixclock = 41094,.left_margin = 19,.right_margin = 37,.upper_margin = 10,.lower_margin = 26,.hsync_len = 27,.vsync_len = 13,.xres = 800,.yres = 480,};static void s3c2416_fb_gpio_setup_24bpp(void){unsignedint gpio;for(gpio = S3C2410_GPC(1); gpio <= S3C2410_GPC(4); gpio++) {s3c_gpio_cfgpin(gpio,S3C_GPIO_SFN(2));s3c_gpio_setpull(gpio,S3C_GPIO_PULL_NONE);}for(gpio = S3C2410_GPC(8); gpio <= S3C2410_GPC(15); gpio++) {s3c_gpio_cfgpin(gpio,S3C_GPIO_SFN(2));s3c_gpio_setpull(gpio,S3C_GPIO_PULL_NONE);}for(gpio = S3C2410_GPD(0); gpio <= S3C2410_GPD(15); gpio++) {s3c_gpio_cfgpin(gpio,S3C_GPIO_SFN(2));s3c_gpio_setpull(gpio,S3C_GPIO_PULL_NONE);}}static struct s3c_fb_platdata home2416_fb_platdata = {.win[0] = &home2416_fb_win[0],.vtiming = &home2416_lcd_timing,.setup_gpio = s3c2416_fb_gpio_setup_24bpp,.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,};static struct resource s3c_fb_resource[]= {[0]= DEFINE_RES_MEM(S3C_PA_FB, SZ_16K),[1]= DEFINE_RES_IRQ(IRQ_LCD_VSYNC),[2]= DEFINE_RES_IRQ(IRQ_LCD_FIFO),[3]= DEFINE_RES_IRQ(IRQ_LCD_SYSTEM),};struct platform_device s3c_device_fb = {.name = "s3c-fb",.id = -1,.num_resources = ARRAY_SIZE(s3c_fb_resource),.resource = s3c_fb_resource,.dev = {.dma_mask = &samsung_device_dma_mask,.coherent_dma_mask = DMA_BIT_MASK(32),},};void __init s3c_fb_set_platdata(structs3c_fb_platdata *pd){s3c_set_platdata(pd,sizeof(struct s3c_fb_platdata),&s3c_device_fb);}
在板级初始化函数 home2416_machine_init() 中加入lcd平台数据 s3c_fb_set_platdata(&home2416_fb_platdata) ,在 static struct platform_device *home2416_devices[] 板级平台设备列表中加入 &s3c_device_fb ,使lcd设备能够注册到内核中。
内核在 drivers\video\backlight\pwm_bl.c 中实现了基于pwm方式的lcd背光驱动,背光设备平台代码如下:
Eastar: arch/arm/mach-s3c24**/mach-home2416.c
static int s3c2416_backlight_init(structdevice *dev){gpio_request(S3C2410_GPB(0),"Backlight"); //使用的IO口为: GPB.0gpio_direction_output(S3C2410_GPB(0),0);s3c_gpio_setpull(S3C2410_GPB(0),S3C_GPIO_PULL_NONE);s3c_gpio_cfgpin(S3C2410_GPB(0),S3C2410_GPB0_TOUT0);return 0;}static int s3c2416_backlight_notify(struct device *dev, int brightness){if(!brightness){gpio_direction_output(S3C2410_GPB(0),0);}else{gpio_direction_output(S3C2410_GPB(0),0);s3c_gpio_setpull(S3C2410_GPB(0),S3C_GPIO_PULL_NONE);s3c_gpio_cfgpin(S3C2410_GPB(0),S3C2410_GPB0_TOUT0);}return brightness;}static void s3c2416_backlight_exit(struct device *dev){gpio_direction_output(S3C2410_GPB(0),0);}static struct platform_pwm_backlight_data backlight_data ={.max_brightness= 100,.dft_brightness= 50,.enable_gpio = -1,.init = s3c2416_backlight_init,.notify = s3c2416_backlight_notify,.exit = s3c2416_backlight_exit,};static struct platform_device s3c2416_backlight ={.name= "pwm-backlight",.dev = {.parent= &samsung_device_pwm.dev,.platform_data= &backlight_data,},.id = -1,};static struct pwm_lookup s3c2416_pwm_lookup[] = {PWM_LOOKUP("samsung-pwm",0, "pwm-backlight", NULL, 36296, PWM_POLARITY_NORMAL),};
在板级初始化函数home2416_machine_init ()中把pwm背光映射到pwm设备表中pwm_add_table(s3c2416_pwm_lookup, ARRAY_SIZE(s3c2416_pwm_lookup)),在static struct platform_device *home2416_devices[]板级平台设备列表中加入&s3c2416_backlight,使背光设备能够注册到内核中。
修改drivers\tty\vt\vt.c,禁止lcd开机一段时间后自动关屏:
static int blankinterval = 0;
修改drivers/video/console/fbcon.c,禁止光标闪烁:
static int fbcon_cursor_noblink = 1;
2、内核配置
Linux配置支持lcd设备驱动,选中 Device Drivers->Graphics support->Frame buffer Devices->Samsumg S3C framebuffer support :

Linux配置支持lcd背光驱动,选中DeviceDrivers->Graphics support->Backlight & LCD device support->Generic PWM based Backlight Driver。

Linux配置开机logo,DeviceDrivers->Graphics support->Bootup logo->Standard 224-color Linux logo。

3、lcd测试
cat /proc/devices可以知道lcd主设备号为29,次设备号为0,在/dev目录中创建fb0设备文件。
mknod /dev/fb0 c 29 0
lcd显示黑屏。
mknod /dev/zero c 1 5dd if=/dev/zero of=/dev/fb0
4、应用编程
应用程序可以通过设备文件访问lcd,lcd纯色显示应用测试代码lcd_test.c如下。
#include "fcntl.h"#include "unistd.h"#include "stdio.h"#include "stdlib.h"#include "sys/mman.h"void screen_clear(unsigned short*ppixel, unsigned short color){int i;for(i=0; i<800*480; i++)ppixel[i]= color;}int main(void){unsignedshort colors[] = {0xffff, 0x0000, 0xf800,0x07e0,0x001f, 0xffe0, 0xf81f, 0x7ff};int screen_size;int fd;int index;unsignedshort *ppixel;fd= open("/dev/fb0", O_RDWR);if(fd == -1) {printf("Openframebuffer failed\n");exit(1);}screen_size= 800*480*2;ppixel=(unsigned short *)mmap(0, screen_size,PROT_READ|PROT_WRITE,MAP_SHARED, fd,0);if(ppixel == (unsigned short *)-1) {printf("Mapframebuffer failed\n");exit(1);}while(1) {screen_clear(ppixel,colors[index]);index++;if(index >= sizeof(colors)/sizeof(colors[0]))index= 0;sleep(2);}umap(ppixel,screen_size);close(fd);return0;}
用arm-linux-gcc静态编译,使之生成arm cpu可执行的指令,并且可脱离任何库独立运行:
arm-linux-gcc -static -o lcd_test
lcd_test.c,生成lcd_test可执行文件。复制可执行文件到根文件系统,目标板启动后在目录输入./lcd_test即可执行。
5、附录
| 文件 | 源码下载 |
|---|---|
| bootloader源码以及使用说明 | https://pan.baidu.com/s/1slczwhJ |
| Qt5.8官网源码 | https://pan.baidu.com/s/1eRDJtNs |
| 本系列例程的根文件系统 | https://pan.baidu.com/s/1nuGmSqt |
| opev3.2.0官网源码 | https://pan.baidu.com/s/1i5btLGT |
| yaffs官网源码 | https://pan.baidu.com/s/1pLpuHw3 |
| busybox-1.26.2官网源码 | https://pan.baidu.com/s/1bpkZynt |
| tslib官网源码 | https://pan.baidu.com/s/1i4EtjfR |
| mplayer-1.3.0官网源码 | https://pan.baidu.com/s/1i5MGRhb |
| 基于S3C2416修改的linux-4.10.10源码 | https://pan.baidu.com/s/1sl0fXlr |
