概述
6.1 认识LCD相关硬件原理
LCD显示屏相关参数,如何设置参数,如何根据型号编写驱动
6.1.1 概述
0) 显示汉字,字符,图形
低压,低功耗,体积小,重量轻,超薄
1) 根据物理结构:扭曲向列型(TN-LCD),超扭曲向列型(STN-LCD),双层超扭曲向列型(DSTN-LCD)
薄膜晶体管型(TFT-LCD)
前三种显示原理相同,只是液晶分子扭曲角度不同,
TFT-LCD采用完全不同的显示方式
2) 常用参数
1]PPI(Pixel Per Inch)每平方英寸像素数目,PPI与显示密度,拟真度,显示效果正相关,目前市场TFT都是100PPI
2]分辨率 :VGA ,SVGA,UXGA SXGA+,SXVGA+为1400x1050
XGA:1280x1024
Quad-VGA:1280x960
3]BPP(Bit Per Pixel) 每个像素使用多少位表示颜色,例如黑白色只用1bit
4阶灰度2bit(2BPP)表示一个点,对于256色要用8bit(8BPP)表示一个点
3) 显示原理
内存显示完整图像,采用CRT显示器概念,一幅画像称为一帧,一帧由多行排列组成,每行由多个像素组成,每个像素色彩由若干位数据表示,单色显示器每个像素用1位即1BPP
256色显示器每个像素使用8位表示即8BPP
显示器从屏幕左上方开始一行一行取得单个像素数据并显示,显示到最右时,跳下一行知道现实所有重新调到左上方即Z字形扫描
同时使用帧扫描和行扫描信号
6.1.2 控制器:
1.控制时序和信号,从而驱动LCD。
2.用户只需通过读写LCD控制器的一些列寄存器完成配置。
3.用户需要显示的内容都是LCD控制器从帧缓冲区读取,然后发送到LCD控制器进而显示在屏幕
4.新的处理器都集成了LCD控制器,如S3C2440等
5.S3C2440的LCD控制器由一个逻辑单元组成,它把LCD图像数据从系统内存的buffer传到外部LCD驱动器。LCD控制器使用基于时间的像素都懂算法和帧速率控制思想,支持单色,2-bit per pixel(4级灰度)或者
4-bit-pixel(16级灰度)屏,并可与256色(8BPP)和4096色(12BPP)彩色STN-LCD连接
6.LCD控制器还支持1BPP,2BPP,4BPP,8BPP的调色板TFT彩色屏,并支持64K色(16BPP)和16M(24BPP)非调色板真彩色显示,根据编程满足不同需求例如单向像素数,数据线宽度,接口时序,刷新速率等
6.1.3 LCD控制器方块图
****************插入图像*******************
1.根据工作原理LCD控制器接口时序分为STN和TFT两种,根据实际需要对控制器进行不同设置产生不同时序
2.LCD控制器中控制信号有VFRAME,VLINE,VCLK和VM等
3.S3C2440作为视频数据的数据端口,是VD[23:0].
4.LCD控制器由REGBANK,LCDCDMA,VIDPRCS,TIMEGEN和LPC3600等组成
5.REGBANK:17个可编程寄存器组和一块256x16调色板内存组成,配置LCD控制器
6.LCDCDMA:专用DMA,自动把内存中视频数据传到LCD驱动器,在CPU不干预情况下显示在LCD屏。
7.VIDPRCS:接收LCDCDMA的数据,并转换为合适的数据格式,例如4/8位扫描,4位双扫显示模式,然后通过数据端口VD[23:0]传送数据到LCD驱动器
8.TIMEGEN:1]可编程逻辑组成,支持不同LCD驱动器接口时序和速率需求
2]可产生VFRAME,VLINE,VCLK和VM等时钟信号
9.数据流描述
LCDCDMA中存在FIFO存储器。如FIFO空或部分空,LCDCDMA请求从存储器取得数据,(每个突发请求,连续读4个字(16bytes),在总线传输中,不匀速总线控制权交给另一个总线)用突发的存储传输模式取得数据
传输请求被存储控制器总线仲裁器接收后,产生连续4个字数据传输control系统内存到内部的FIFO(12个FIFOL和16个FIFOH组成的28个字),
S3C2440用2个FIFO支持双扫显示模式,如单扫模式,只有一个FIFO会用到
6.1.4 控制器操作(STN和TFT两种)
视频数据在内存中存储方式:
RGB三色组成单个像素色彩。也就是三基色
1.24BPP显示使用24位表示一个像素点,每种颜色8比特,LCD控制器从内存获得某个像素的24位颜色值,然后通过VD[23:0]数据线发送LCD驱动器,像素值与VD[23:0]引脚的对应关系
******************************插入图片像素值与VD映射关系***********************
2.16BPP
3.8BPP
4.256色调色板
6.1.5 LCD控制寄存器
17个控制寄存器,包括LCDCON1-LCDCOON5,LCDSADDR1-LCDSADDR3等
6.2 LCD参数设置
根据LCD屏正确设置对应的LCD寄存器参数
1]设置VFRAME,VLINE(根据液晶屏尺寸和显示木事设置),他们对应LCDCON2寄存器的HOZVAL和LINEVAL值
HOZVAL=(水平尺寸/VD数据位)-1
彩色液晶屏,水平尺寸=3x水平像素点数
VD数据位=BBP数(不分单双扫描)
LINVAL=垂直尺寸-1(单扫描)
LINVAL=垂直尺寸/2-1(双扫描)
2]设置VCLK:直接由系统总线(AHB)工作频率HCLK直接分频得到
VCLK=HCLK/((CLKVAL+1)*2)
3]帧速率:即VSYNC信号频率。帧速率与VSYNC,VBPD,VFPD,LINEVAL,HSYNC,HBPD,HFPD,HOZVAL和CLKVAL的域有关
他们是LCDCON1/2/3/4。大多数LCD驱动器需要他们合适的帧速率。
帧速率公式:
Frame Rate = 1/[{(VSPW+1)+(VPBD+1)+(LINEVAL+1)+(VFPD+1)}*{(HSPW+1)+(HBPD+1)+(HFPD+1)+HOZVAL+1}*{2*(CLKVAL+1)/HCLK}]
VSPW,VBPD,VFPD,HSPW,HBPD,HFPD参考LCD屏幕手册
6.3 内核LCD驱动机制
Linux提供的驱动:帧缓冲(FrameBufer)设备驱动程序。实际工作只需在显示缓存中填写要显示的数据,屏幕即可显示
驱动得到显示缓存的地址,即可操作它
6.3.1 FrameBufer概述
1. 从Linux2.2.x提供的驱动程序接口
2. 把显示设备抽象为帧缓冲区设备,为图像设备提供抽象化处理,代表了一些视频设备。
3.允许APP通过定义明确界面访问图像硬件设备。软件无序了解任何硬件底层驱动内容
4.FB允许app在图形模式下直接对显示缓冲区读写和IO控制等
5.通过专门的设备结点对相应的设备进行访问,如/dev/fb0,app可将其视为显示内存的引用,将其映射到进程地址空间后,就可读写,读写可反映到具体的LCD设备
6.FB驱动支持控制台的字符显示。linux2.4种与FB控制台相关的在fbcon和其他相关目录。linux2.6放在drivers/video/console中,涵盖各种格式显示缓冲的字符输出,字体定义文件,简化FB控制台驱动程序移植
6.3.2 FB设备驱动结构
FB设备驱动基于两个文件 linux/include/linux/fb.h和 linux/drivers/video/fbdev/core/fbmem.c 其中fb.h定义FB驱动所需的几乎所有结构体,
包括struct fb_info,struct fb_var_screeninfo 和struct fb_fix_screeninfo。
1.struct fb_info
1]记录帧缓冲全部信息,包括设置参数、状态、操作函数指针等
2]每个帧缓冲设备都由一个struct fb_info描述,所有参数都是面向特定设备,工程师就是填写这些数值。
3]fb_info也是FB相关结构唯一在内核空间可见的,用户可通过ioctl()操作设备,这个结构体就是用于支持ioctl()的这些操作的
2.fb_var_screeninfo:
1]记录帧缓冲设备和指定显示模式的可修改信息。
2]包括显示屏分辨率,像素比特数,一些时序变量。
3]变量xres定义一行所占像素数目,yres定义一列所占像素数目,bits_per_pixel定义每个像素所需位数
4]参数都可通过应用程序设置
5]通过fb_opt实现
3. fb_fix_screeninfo:
1]定义硬件不可变属性,显示缓冲区映射地址的定义
2]缓冲区不应该被APP改变
4. fbmem.c linux/drivers/video/fbdev/core/fbmem.c
1]是FB设备驱动关键,为上层应用提供系统调用,为下层特定硬件驱动提供编程接口
2]底层硬件驱动乣用到这里的接口来向系统内核注册它们自己。
3]fbmem.c为所有支持FB的设备驱动提供通用接口,避免重复的工作
4]用户只需针对fbmem.c提供的底层驱动接口函数分别实现即可,也就是fb.h中的structfb_ops函数指针组
5]fbmem.c实现register_framebuffer和unregister_framebuffer,提供给下层FB驱动的接口。底层设备驱动所要做的事情就是填充fb_info结构并想系统注册或注销
6.4 内核现有LCD驱动源码分析
内核现有LCD驱动再针对具体型号和硬件资源修改
6.4.1 主要工作:初始化函数的编写和填充fb_info结构体的主要成员函数
1.编写初始化函数
1]编写初始化函数,初始化LCD控制器寄存器,通过写寄存器设置显示模式和颜色数,然后在内存中分配LCD显示缓冲区。linux中可用kmalloc()分配连续空间
2]缓冲区大小:点阵行数*点阵列数*用于表示一个像素的比特数/8.
3]缓冲区通常分配在片外SDRAM(容量大),起始地址保存在LCD控制器
4]本节LCD显示方式:320*240 ,16位彩色,需要分配显示缓冲区:320*240*2 = 150kb
5]初始化fb_info结构体,填充成员变量,调用register_framebuffer(&fb_info)将fb_info注册入内核
2.编写成员函数
1]嵌入式系统只需要实现fb_ops中的 fb_get_fix fb_get_var ,fb_set_var三个函数
2]应用程序对设备ioctl系统调用时会调用他们
3]fb_get_fix通过fb_fix_screeninfo获取系统当前状态对成员变量赋值,主要是smem_start,smem_len,最终返给应用程序。
4]fb_set_var函数传入参数是fb_var_screeninfo,需要对xres,yres和bit_per_pixel赋值
3.对于/dev/fb 主要操作
1]读写/dev/fb 等于读写屏幕缓冲区
2]映射操作(map):因linux工作在保护模式,每个应用都有自己的虚拟地址空间,应用不能直接访问物理缓冲区地址,故通过mmap()
操作file_operations结构,可将文件内容映射到用户空间。帧缓冲设备则可通过映射操作,可将屏幕缓冲区的物理地址映射到用户空间一段虚拟地址之内,之后用户就能通过读写此段虚拟地址访问屏幕缓冲区,在屏幕上绘图
3]IO控制:帧缓冲设备对设备文件的ioctl操作可读取/设置显示设备及屏幕参数(分辨率,显示颜色数和屏幕大小等)。ioctl由底层硬件驱动完成。
一般步骤:1.打开 /dev/fb设备文件;
2.用ioctl()取得当前屏幕参数(分辨率,像素比特数)
3.根据屏幕参数计算屏幕缓冲区大小
4.将屏幕缓冲区映射到用户空间
5.映射后可直接读取屏幕缓冲区,进行绘图和显示
6.4.2 s3c2410fb_init()函数分析
1.只包含了platform_driver_register()调用,参数&s3c410fb_driver,即向内核注册一个platform设备驱动,该设备是LCD设备
2.platform两个重要数据结构:platform_device和platform_driver(include/linux/platform_device.h)
3.LCD驱动(drivers/video/s3c2410fb.c)有platform_driver结构体
static struct platform_driver s3c2410fb_driver = {
.probe = s3c2410fb_probe, //初始化函数,
.remove = s3c2410fb_remove,
.suspend = s3c241fb_suspend,
.resume = s3c2410fb_resume,
.driver = {
.name = "s3c2410-lcd", //设备名字,名字一定要和struct platform_device中的name域一致才能把平台驱动和前面定义平台数据联系起来
.owner = THIS_MODULE,
},
};
6.4.3 s3c2410fb_probe()函数分析
1.关键函数
s3c2410fb_info:描述整个LCD驱动的结构体,驱动自己定义的设备数据结构,记录s3c2410fb驱动所有信息
s3c2410fb_display:定义了LCD规格和时序
fb_info:framebuffer的设备数据结构,表示一个显示设备,probe最终填充并向内核注册
s3c2410fb_mach_info:描述LCD初始化时所用的值,包含LCD控制器的GPIO,用来设置引脚的功能,和平台有关
所在目录:arch/arm/plat-samsung/include/plat/fb-s3c2410.h;
Resource:指向设备用到的IO资源,是平台驱动的结构
irq:保存中断号。
2.函数执行步骤
1.获得平台数据
2.如果mach_info为NULL,则整个驱动程序退出
3.查找当前显示屏规格,此规格定义在mach-smdk2440.c文件
4.获取设备中断号,中断号也在mach-smdk2440.c文件中定义的硬件所使用到的中断资源
5.向内核申请一段sizeof(struct s3c2410fb_info)+size的空间,size:设备私有数据空间,
6.fb_info的par指向该私有空间
7.设置驱动数据并填充驱动数据
8.映射内核资源(IO口,中断号,平台数据不定期传递来的硬件资源地址都是物理地址,内核访问硬件都是虚拟地址,故用相关函数映射物理地址为虚拟地址),映射失败退出程序
9.关闭显示器,对fbinfo赋值
10.申请中断并打开LCD时钟,使得各个LCD相关引脚输出信号。
11.显示内存容量并映射DMA资源,上层应用存储要显示的图像到此内存区,LCD控制器通过DMA从映射内容取出图像
12.初始化各个LCD控制寄存器,注册fbinfo,并为该设备创建一个sysfs中的属性
13.pdev->dev.platform_data的初始化,内核启动init进程前,会执行smdk2410_map_io函数,次函数中加入s3c24xx_fb_set_platdata(&smdk2410_lcd_platdata)
arch/arm/plat-samsung/devs.c
3.s3c2410fb_init_registers
1.保存本地中断
2.修改处理器GPIO工作方式
3.初始化LCD控制寄存器
4.让处理器的LCD控制器三地址寄存器指向正确位置,也就是LCD缓冲区,参考用户手册
5.打开video,因为probe中关闭了
6.4.4 s3c2410fb_init_remove:移除设备,释放资源(内存空间,中断线等)
1.获得fb_info信息
2.得到私有数据
3.停止LCD控制器
4.该函数释放缓冲区,停止时钟
5.得到中断线并释放
6.释放内存空间
7.想内核注销该帧缓冲
6.5 移植内核中的LCD驱动
不同开发人员设计同一种设备都具备独特性,例如访问硬件资源对应的端口地址,故驱动移植首先要明确驱动的硬件设备连接情况
然后对驱动源码进行适应具体硬件修改
6.5.1 LCD硬件电路图
1.LCD的像素同步时钟信号,水平同步信号,垂直同步信号直接连接到LCD的VCLK,VLINE和VFRAME
2.GPG4作为LCD电源信号直连到LCD_PWREN
************插入电路图**********************
6.5.2 修改源码
6.5.3 配置内核
1.make menuconfig
2.devices drivers -> Graphics support-> Support for frame buffer devices
3.在驱动程序调试阶段最好选中S3C24010 LCD debug messages
4.增加开机logo,选择bootup logo
6.6总结
分析LCD控制寄存器硬件操作,内核中自带的LCD驱动源程序基础讲述LCD移植,
内核中FB驱动的体系结构,如何操作LCD控制器
中断FB数据结构掌握
最后
以上就是大胆月饼为你收集整理的第六章--LCD驱动移植的全部内容,希望文章能够帮你解决第六章--LCD驱动移植所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复