Linux开发十五_lcd驱动

2019-07-13 09:25发布

Linux开发十五

lcd驱动

象棋小子    1048272975 lcd能够支持彩 {MOD}图像的显示和视频的播放,是一种很重要的输出设备,在一些嵌入式人机交互系统中,也往往需要lcd进行显示。Linux内核已经支持了s3c2416的lcd控制器。

1. lcd设备

lcd设备包含了名字、独有的资源等等一些驱动程序的硬件或自定义信息。通过platform_add_devices(platform_device_register)函数将定义的平台设备注册到内核中,用于匹配设备驱动。 内核在driversvideofbdevs3c-fb.c中实现了s3c2416 lcd驱动,lcd设备平台代码如下。 static struct s3c_fb_pd_winhome2416_fb_win[] = {        [0]= {               .default_bpp  = 16,               .max_bpp      = 32,               .xres           = 800,               .yres           = 480,        }, };   static struct fb_videomodehome2416_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 voids3c2416_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_platdatahome2416_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设备能够注册到内核中。 内核在driversvideoacklight pwm_bl.c中实现了基于pwm方式的lcd背光驱动,背光设备平台代码如下。 static int s3c2416_backlight_init(structdevice *dev) {        gpio_request(S3C2410_GPB(0),"Backlight");          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);          return0; }   static ints3c2416_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);        }        returnbrightness; }   static voids3c2416_backlight_exit(struct device *dev) {        gpio_direction_output(S3C2410_GPB(0),0); }   static structplatform_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_devices3c2416_backlight = {        .name= "pwm-backlight",        .dev  = {               .parent= &samsung_device_pwm.dev,               .platform_data= &backlight_data,        },        .id   = -1, };   static struct pwm_lookups3c2416_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 tyvtvt.c,禁止lcd开机一段时间后自动关屏。 static int blankinterval = 0; 修改drivers/video/console/fbcon.c,禁止光标闪烁。 static int fbcon_cursor_noblink = 1;

2. 内核配置

Linux配置支持lcd设备驱动,选中Device Drivers->Graphics support->Framebuffer Devices->Samsumg S3C framebuffer support 。 Linux配置支持lcd背光驱动,选中DeviceDrivers->Graphics support->Backlight & LCD device support->GenericPWM 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  5 dd if=/dev/zero of=/dev/fb0

4. 应用编程

应用程序可以通过设备文件访问lcd,lcd纯 {MOD}显示应用测试代码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) {        inti;        for(i=0; i<800*480; i++)               ppixel[i]= color; }   int main(void) {        unsignedshort colors[] = {0xffff, 0x0000, 0xf800,               0x07e0,0x001f, 0xffe0, 0xf81f, 0x7ff};        intscreen_size;        intfd;        intindex;        unsignedshort *ppixel;        fd= open("/dev/fb0", O_RDWR);        if(fd == -1) {               printf("Openframebuffer failed ");               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 ");               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. 附录

https://pan.baidu.com/s/1slczwhJ bootloader源码以及使用说明 https://pan.baidu.com/s/1eRDJtNs Qt5.8官网源码 https://pan.baidu.com/s/1nuGmSqt 本系列例程的根文件系统 https://pan.baidu.com/s/1i5btLGT opev3.2.0官网源码 https://pan.baidu.com/s/1pLpuHw3 yaffs官网源码  https://pan.baidu.com/s/1bpkZynt busybox-1.26.2官网源码 https://pan.baidu.com/s/1i4EtjfR tslib官网源码 https://pan.baidu.com/s/1i5MGRhb mplayer-1.3.0官网源码 https://pan.baidu.com/s/1sl0fXlr 基于S3C2416修改的linux-4.10.10源码