1、第6章 LCD驱动移植6.1 认识LCD相关硬件原理6.2 LCD参数设置6.3 内核LCD驱动机制6.4 Linux 2.6.32的LCD驱动源码分析6.5 移植内核中的LCD驱动6.1 认识LCD相关硬件原理6.1.1 LCD概述6.1.2 LCD控制器6.1.3 LCD控制器方块图6.1.4 LCD控制器操作6.1.5 LCD控制寄存器6.1.1 LCD概述LCD(液晶显示)模块可以显示汉字、字符和图形,同时还具有低压、低功耗、体积小、重量轻和超薄等很多优点。1LCD显示屏的分类2LCD的常用参数3LCD的显示原理1LCD显示屏的分类常见的液晶显示屏按物理结构可分为4种,即扭曲向列型(T
2、N-LCD)、超扭曲向列型(STN-LCD)、双层超扭曲向列型(DSTN-LCD)和薄膜晶体管型(TFT-LCD)。在写驱动程序时要根据不同类型对LCD控制器进行控制。2LCD的常用参数市场上的LCD显示屏从厂家、型号、规格等来说不尽相同,了解LCD的主要参数对进行LCD驱动开发非常有用,因为写驱动程序时就需要对LCD的参数进行设置。PPI(Pixel Per Inch)是指每平方英寸所拥有的像素数目。分辨率:市面上的分辨率标准多种多样,主要有VGA、SVGA、UXGA和SXGA+。BPP(Bit Per Pixel),即每个像素使用多少位来表示其颜色。3LCD的显示原理一幅图像被称为一帧,每
3、帧由多个行排列组成,每行又由多个像素组成,每个像素的色彩使用若干位数据来表示。显示器从屏幕的左上方开始,一行一行地取得每个像素的数据并显示出来,当显示到一行的最右边时,跳到下一行的最左边开始显示下一行;当显示完所有行后,重新跳到左上方开始下一帧的显示。显示器沿着“Z”字形的路线进行扫描,同时使用帧扫描信号和行扫描信号来同步每一帧和每一行。6.1.2 LCD控制器LCD控制器的功能是产生控制时序和信号,从而驱动LCD。用户只需要通过读写LCD控制器的一系列寄存器来完成配置。S3C2440的LCD控制器由一个逻辑单元组成,它的作用是把LCD图像数据从一个位于系统内存的buffer传送到一个外部的L
4、CD驱动器。LCD控制器还支持1BPP、2BPP、4BPP、8BPP的调色板TFT彩色屏,并且支持64K色(16BPP)和16M色(24BPP)非调色板真彩显示。6.1.3 LCD控制器方块图LCD控制器的接口时序分为STN和TFT两种。S3C2440的LCD控制器可以同时支持STN和TFT的LCD显示屏,根据实际需要对控制器进行不同的设置可以产生不同的时序。6.1.4 LCD控制器操作S3C2440的LCD控制器分STN控制和TFT控制,目前市面上主流的LCD为TFT-LCD。S3C2440的TFT LCD控制器支持1、2、4、8BPP调色板彩色模式及16BPP、24BPP无调色板真彩模式。
5、124BPP显示216BPP38BPP4256色调色板124BPP显示24BPP显示模式使用24位表示一个像素点,每种颜色用8比特位来表示。LCD控制器从内存中获得某个像素的24位颜色值后直接通过VD23:0数据线发送给LCD驱动器。VD23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0RED76543210 GREEN 7654321 0 BLUE7 6 5 4 3 2 1 0216BPP16BPP模式用16位来表示一个像素点的值。这16位数据的格式分为两种:5:6:5 和5:5:5:1,前者使用高5位表示红色,中间6位
6、表示绿色,低5位表示蓝色;后者用高15位表示红、绿、蓝3种颜色,每种颜色用5位表示,最低位表示透明度。VD23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0RED43210NC NC NCGREEN 543210 BLUE4 3 2 1 0 38BPP8BPP显示模式使用8位来表示一个像素点,然而对3种基色平均下来,每种基色只能使用不到3位的数据来表示,即每种基色最多不过8阶,这不能表示更丰富的色彩。4字节可以表示4个8BPP的像素,字节与像素的对应顺序也是可以编程选择的。4256色调色板S3C2440为TFT显示器提供2
7、56色调色板,调色板是一块25616的内存,使用16BPP的格式来表示8BPP模式下各索引值的颜色。INDEXBitPos15 14 13 12 11 109876543210 Address00HR4 R3 R2 R1 R0 G5 G4 G3 G2 G1 G0 B4 B3 B2 B1 B0 0X4D00040001HR4 R3 R2 R1 R0 G5 G4 G3 G2 G1 G0 B4 B3 B2 B1 B0 0X4D000404 FFHR4 R3 R2 R1 R0 G5 G4 G3 G2 G1 G0 B4 B3 B2 B1 B0 0X4D0007FCNumberofDV23 22 21 2
8、0 19 15 14 13 12 11 1076543 6.1.5 LCD控制寄存器S3C2440提供了LCD控制器,其中有17个控制寄存器,包括LCDCON1LCDCON5及LCDSADDR1-LCDSADDR3等。1LCD控制寄存器LCDCON12LCD控制寄存器LCDCON23LCD控制寄存器LCDCON34LCD控制寄存器LCDCON45LCD控制寄存器LCDCON56帧内存地址寄存器1LCD控制寄存器LCDCON1LCDCON1用于选择LCD类型、设置像素时钟、使能LCD输出信号等。功功能能位位描描述述初始状态初始状态LINECNT(只读)(只读)27:18每输出一个有效行其值减10
9、CLKVAL17:8用于设置VCLK的值STN:VCLK=HCLK/(CLKVAL2)TFT:VCLK=HCLK/(CLKVAL+1)2)0MMODE7用于设置VM信号的反转效率,只用于TFT屏0PNRMODE6:5设置LCD的类型00:4位双扫描(STN)01:4位单扫描(STN)10:8位单扫描(STN)11:TFT屏0BPPMODE4:1选择BPP模式,对于TFT屏1000:1BPP1001:2BPP1010:4BPP1011:8BPP1100:16BPP1101:24BPP(STN)0ENVID0信号输出使能位信号输出使能位0:禁止,:禁止,1:使能:使能02LCD控制寄存器LCDCO
10、N2用于设置垂直方向各信号的时间参数。功功能能位位描描述述初始初始值值VBPD31:24VSYNC信号之后,还要经过(VBPD+1)个HSYNC信号周期才会出现有效行数据0LINEVAL23:14 LCD的行数:(LINEVAL+1)行0VFPD13:6一帧中的有效数据完成后,到下一个VSYNC信号有效前的无效行数目:(VFPD+1)0VSPW5:0表示表示VSYNC信号的宽度为(信号的宽度为(VSPW+1)个)个HSYNC信号信号周期,这(周期,这(VSPW+1)行的数据无效)行的数据无效03LCD控制寄存器LCDCON3用于设置水平方向各信号的时间参数。功功能能位位描描述述初始值初始值HB
11、PD25:19HSYNC信号脉冲之后,还要经过(HBPD+1)个VCLK信号周期,才出现有效数据0HOZVAL18:8LCD的水平宽度:(HOZVAL+1)个像素0HFPD7:0一行中的有效数据完后,到下一个一行中的有效数据完后,到下一个HSYNC信号有效前的无信号有效前的无效像素个数:效像素个数:HFPK+104LCD控制寄存器LCDCON4对于TFT屏,这个寄存器用来设置HSYNC信号的脉冲宽度。功功能能位位描描述述初始值初始值MVAL15:8STN屏用0HSPW7:0表示脉冲宽度为(HSPW+1)个VCLK信号周期0WLH7:0STN屏用屏用05LCD控制寄存器LCDCON5用于设置各个
12、控制信号的极性,并可从中读取状态信息。功功能能位位描描述述初始值初始值VSTATUS16:15只读,垂直状态00:处于VSYNC信号脉冲期间01:处于VSYNC信号结束到行有效之间10:处于行有效期间11:处于行有效结束到下一个VSYNC信号之间0HSTATUS14:13只读,描述水平状态00:处于HSYNC信号脉冲期间01:处于HSYNC信号结束到像素有效之间10:处于像素有效期间11:处于像素有效结束到下一个HSYNC信号之间0BPP24BL12设置TFT屏的显示模式为24BPP时,一个4字节中哪3个字节有效。0:低3字节有效;1:高3字节有效0FRM56511设置TFT屏的显示模式为16
13、BPP时,数据的格式0:5:5:5:1;1:5:6:50INVVCLK10设置VCLK信号有效沿的极性0:下降沿读取数据;1:在上升沿读取数据0INVVLINE9设置设置VLINE/HSYNC脉冲的极性脉冲的极性0:正常极性;:正常极性;1:反转的极性:反转的极性05LCD控制寄存器LCDCON5功功能能位位描描述述初始值初始值INVVFRAME8设置VFRAME/VSYNC脉冲的极性0:正常极性;1:反转的极性0INVD7设置VD数据线表示数据的极性0:正常极性;1:反转的极性0INVVDEN6设置VDEN信号的极性0:正常极性;1:反转的极性0INVPWREN5设置PWREN信号的极性0:
14、正常极性;1:反转的极性0INVLEND4设置LEND信号的极性0:正常极性;1:反转的极性0PWREN3LCD_PWREN信号输出使能0:禁止;1:使能0ENLEND2LEND信号输出使能0:禁止;1:使能0BSWP1字节交换使能0:禁止;1:使能0HWSWP0半字交换使能半字交换使能0:禁止;:禁止;1:使能:使能06帧内存地址寄存器帧内存可以很大,而真正要显示的区域称为视口,它处于帧内存之内。s3c2440有3个帧内存地址寄存器,这3个寄存器用于确定帧内存的起始地址,定位视口在帧内存的位置。功功能能位位描描述述初始值初始值LCDBANK29:21用于保存帧内存起始地址的A30:22,帧内
15、存起始地址必须为4M对齐0LCDBASEU20:0对于双扫描,用于表示上半帧的内存起始地址对于双扫描,用于表示上半帧的内存起始地址对于单扫描,用于表示帧的内存起始地址对于单扫描,用于表示帧的内存起始地址06帧内存地址寄存器功功能能位位描描述述初始值初始值LCDBASEL20:0对于双扫描,用于保存下半帧的起始地址对于双扫描,用于保存下半帧的起始地址对于单扫描,用于保存帧的结束地址对于单扫描,用于保存帧的结束地址其值按如下公式计算:其值按如下公式计算:L C D B A S E L=C L D B A S E U+(PAGEWIDTH+OFFSIZE)*(LINEVAL+1)0功功能能位位描描述
16、述初始值初始值OFFSIZE21:11虚拟屏长度表示上一行最后一个数据与下一行第一个数据间地址差值的一半,即以半字为单位的地址差0PAGEWIDTH10:0虚拟屏的宽度,这个值决定视口的宽度,以半字虚拟屏的宽度,这个值决定视口的宽度,以半字为单位为单位06.2 LCD参数设置LCD驱动编写的主要任务就是根据所使用的LCD屏正确地设置对应的LCD寄存器参数。前面已经讲述了S3C2440 LCD各控制寄存器。1设置VFRAME、VLINE2设置VCLK3帧速率1设置VFRAME、VLINEVFRAME和VLINE信号可以根据液晶屏的尺寸和显示模式来设置,它们对应LCDCON2寄存器的HOZVAL和
17、LINEVAL值,设置方法如下:HOZVAL=(水平尺寸/VD数据位)-1彩色液晶屏:水平尺寸=3 水平像素点数VD数据位=BBP数(不分单双扫描)LINVAL=垂直尺寸-1(单扫描)LINVAL=垂直尺寸/2-1(双扫描)2设置VCLKLCD控制器输出的VCLK是直接由系统总线(AHB)的工作频率HCLK直接分频得到的。VCLK=HCLK/(CLKVAL+1)2)3帧速率帧速率就是VSYNC信号的频率。帧速率与VSYNC、VBPD、VFPD、LINEVAL、HSYNC、HBPD、HFPD、HOZVAL和CLKVAL的域有关,它们是LCDCON1/2/3/4。大多数LCD驱动器需要它们合适的帧
18、速率。帧速率按如下公式计算:Frame Rate=1/(VSPW+1)+(VBPD+1)+(LINEVAL+1)+(VFPD+1)*(HSPW+1)+(HBPD+1)+(HFPD+1)+HOZVAL+1*2*(CLKVAL+1)/HCLK6.3 内核LCD驱动机制6.3.1 FrameBuffer概述6.3.2 FrameBuffer 设备驱动的结构6.3.1 FrameBuffer概述帧缓冲区是把显示设备抽象成为帧缓冲区设备区。帧缓冲区允许上层应用程序在图形模式下直接对显示缓冲区进行读写和I/O控制等操作。通过专门的设备结点可对相应的设备进行访问。应用程序可以将它看成是显示内存的一个引用,将
19、其映射到进程地址空间之后,就可以进行读写操作,而读写操作可以反映到具体的LCD设备上。6.3.2 FrameBuffer 设备驱动的结构FrameBuffer设备驱动基于两个文件,linux/include/linux/fb.h和linux/drivers/video/fbmem.c。其中,fb.h定义了Framebuffer驱动所要用到的几乎所有的结构体,这些结构主要包括struct fb_info、struct fb_var_screeninfo和struct fb_fix_screeninfo。下面分别讲述这几个结构体。1struct fb_infostruct fb_info记录了帧缓
20、冲的全部信息,包括设置参数、状态、操作函数指针等。2fb_var_screeninfostruct fb_var_screeninfo记录了帧缓冲设备和指定显示模式的可修改信息。它包括显示屏幕的分辨率、每个像素的比特数和一些时序变量。3fb_fix_screeninfo而fb_fix_screeninfo定义了硬件的不可变属性,显示缓冲区的映射地址也被定义在这里,它表示缓冲区不应该被应用程序所改变。4fbmem.cfbmem.c是Framebuffer设备驱动技术的关键。它为上层应用程序提供系统调用也为下一层的特定硬件驱动提供编程接口;那些底层硬件驱动需要用到这里的接口来向系统内核注册它们自己
21、。6.4 Linux 2.6.32的LCD驱动源码分析6.4.1 LCD驱动开发的主要工作6.4.2 s3c2410fb_init()函数分析6.4.3 s3c2410fb_probe()函数分析6.4.4 s3c2410fb_remove()函数分析6.4.1 LCD驱动开发的主要工作LCD驱动开发的工作包括两个方面,分别是初始化函数的编写和填充fb_info结构体中的主要成员函数,下面分别讲述。1编写初始化函数初始化函数首先初始化各个LCD控制器寄存器,通过写寄存器来设置显示的模式和颜色数,然后在内存中分配LCD显示缓冲区。最后是初始化一个fb_info结构体,填充其中的成员变量,并调用r
22、egister_framebuffer(&fb_info),将fb_info注册入内核。2编写成员函数对于嵌入式系统的简单实现,编写结构fb_info中函数指针fb_ops对应的成员函数只需要下列3个函数就可以了。struct fb_ops.int(*fb_get_fix)(struct fb_fix_screeninfo*fix,int con,struct fb_info*info);int(*fb_get_var)(struct fb_var_screeninfo*var,int con,struct fb_info*info);int(*fb_set_var)(struct fb_va
23、r_screeninfo*var,int con,struct fb_info*info);.6.4.2 s3c2410fb_init()函数分析首先要分析的是s3c2410fb_init()函数,该函数内容相对简单,在s3c2410fb_init()函数体内只是包装了对平台驱动注册函数platform_driver_register()的调用,它的参数是&s3c2410fb_driver。这里是向内核注册一个platform 设备驱动的意思,该platform设备是LCD设备。6.4.3 s3c2410fb_probe()函数分析799 static int _init s3c24xxfb_
24、probe(struct platform_device*pdev,800 enum s3c_drv_type drv_type)801 802 struct s3c2410fb_info*info;803 struct s3c2410fb_display*display;804 struct fb_info*fbinfo;805 struct s3c2410fb_mach_info*mach_info;806 struct resource*res;807 int ret;808 int irq;809 int i;810 int size;811 u32 lcdcon1;8126.4.3
25、s3c2410fb_probe()函数分析813 mach_info=pdev-dev.platform_data;814 if(mach_info=NULL)815 dev_err(&pdev-dev,816 no platform data for lcd,cannot attachn);817 return-EINVAL;818 8196.4.3 s3c2410fb_probe()函数分析820 if(mach_info-default_display=mach_info-num_displays)821 dev_err(&pdev-dev,default is%d but only%d
26、 displaysn,822 mach_info-default_display,mach_info-num_displays);823 return-EINVAL;824 825826 display=mach_info-displays+mach_info-default_display;6.4.3 s3c2410fb_probe()函数分析827828 irq=platform_get_irq(pdev,0);829 if(irq dev,no irq for devicen);831 return-ENOENT;832 6.4.3 s3c2410fb_probe()函数分析833834
27、 fbinfo=framebuffer_alloc(sizeof(struct s3c2410fb_info),&pdev-dev);835 if(!fbinfo)836 return-ENOMEM;6.4.3 s3c2410fb_probe()函数分析837838 platform_set_drvdata(pdev,fbinfo);839840 info=fbinfo-par;841 info-dev=&pdev-dev;842 info-drv_type=drv_type;6.4.3 s3c2410fb_probe()函数分析843844 res=platform_get_resource
28、(pdev,IORESOURCE_MEM,0);845 if(res=NULL)846 dev_err(&pdev-dev,failed to get memory registersn);847 ret=-ENXIO;848 goto dealloc_fb;849 850851 size=(res-end-res-start)+1;852 info-mem=request_mem_region(res-start,size,pdev-name);853 if(info-mem=NULL)854 dev_err(&pdev-dev,failed to get memory regionn);8
29、55 ret=-ENOENT;856 goto dealloc_fb;857 858859 info-io=ioremap(res-start,size);860 if(info-io=NULL)861 dev_err(&pdev-dev,ioremap()of registers failedn);862 ret=-ENXIO;863 goto release_mem;864 865866info-irq_base=info-io+(drv_type=DRV_S3C2412)?S3C2412_LCDINTBASE:S3C2410_LCDINTBASE);6.4.3 s3c2410fb_pro
30、be()函数分析867868 dprintk(devinitn);869870 strcpy(fbinfo-fix.id,driver_name);871872 /*Stop the video*/873 lcdcon1=readl(info-io+S3C2410_LCDCON1);874 writel(lcdcon1&S3C2410_LCDCON1_ENVID,info-io+S3C2410_ LCDCON1);875876 fbinfo-fix.type =FB_TYPE_PACKED_PIXELS;877 fbinfo-fix.type_aux =0;878 fbinfo-fix.xpa
31、nstep =0;879 fbinfo-fix.ypanstep =0;880 fbinfo-fix.ywrapstep =0;881 fbinfo-fix.accel =FB_ACCEL_NONE;882883 fbinfo-var.nonstd =0;884 fbinfo-var.activate =FB_ACTIVATE_NOW;885 fbinfo-var.accel_flags =0;886 fbinfo-var.vmode =FB_VMODE_NONINTERLACED;887888 fbinfo-fbops =&s3c2410fb_ops;889 fbinfo-flags =FB
32、INFO_FLAG_DEFAULT;890 fbinfo-pseudo_palette =&info-pseudo_pal;891892 for(i=0;i palette_bufferi=PALETTE_BUFF_CLEAR;6.4.3 s3c2410fb_probe()函数分析894895 ret=request_irq(irq,s3c2410fb_irq,IRQF_DISABLED,pdev-name,info);896 if(ret)897 dev_err(&pdev-dev,cannot get irq%d-err%dn,irq,ret);898 ret=-EBUSY;899 got
33、o release_regs;900 901902 info-clk=clk_get(NULL,lcd);903 if(!info-clk|IS_ERR(info-clk)904 printk(KERN_ERR failed to get lcd clock sourcen);905 ret=-ENOENT;906 goto release_irq;907 908909 clk_enable(info-clk);910 dprintk(got and enabled clockn);911912 msleep(1);6.4.4 s3c2410fb_remove()函数分析现在解释s3c2410
34、fb_driver中的最后一个关键函数s3c2410fb_remove()。顾名思义该函数要将这个platform设备从系统中移除,可以推测它的作用应该释放掉所有的资源,包括内存空间。中断线等。和前文一样,我们在它的实现代码中一步步解释。static int s3c2410fb_remove(struct platform_device*pdev)struct fb_info *fbinfo=platform_get_drvdata(pdev);/*该函数从platform_device中获得fb_info信息*/struct s3c2410fb_info*info=fbinfo-par;/得
35、到私有数据 int irq;s3c2410fb_stop_lcd(info);6.5 移植内核中的LCD驱动6.5.1 LCD硬件电路图6.5.2 修改LCD源码6.5.3 配置内核6.5.1 LCD硬件电路图写驱动程序前先了解一下电路连接情况。LCD的像素同步时钟信号、水平同步信号、垂直同步信号直接连接到LCD的VCLK、VLINE和VFRAME上,用GPG4作为LCD的电源信号直接连接到LCD_PWREN上。6.5.2 修改LCD源码本章用的源码是linux2.6.32中的LCD驱动源码,文件为drivers/video/s3c2410fb.c和drivers/video/s3c2410fb.h。6.5.3 配置内核做完以上工作,我们就可以对LCD进行配置了。进入内核源码所在的目录,输入make menuconfig进入配置菜单。
侵权处理QQ:3464097650--上传资料QQ:3464097650
【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。