基于framebuffer的驱动分析
framebuffer帧缓冲(简称fb)是linux内核中虚拟出的一个设备,是一个platform类型设备,设备文件位于/dev/fb*
- framebuffer的作用是:向应用层提供一个统一标准接口的显示设备。不论最终输出是通过hdmi还是lcd控制器,可以认为所有的GUI都是向fb输出画面的
- 对于现代LCD,有一种“多屏叠加”的机制,即一个LCD设备可以有多个独立虚拟屏幕,以达到画面叠加的效果。所以fb与LCD不是一对一的关系,在常见的情况下,一个LCD对应了fb0~fb4。像QT这种GUI会默认把画面输出到fb0
1.画面输出原理
- 如何输出画面?应用程序通过往显存中写数据,LCD控制器将自动把显存中的数据映射到lcd屏幕。映射是全自动的,应用层负责往显存里写数据,而驱动要做的仅仅是配置LCD控制器、创建显存罢了
- 由于显存实际是处于内核态的物理内存,所以要把这块物理内存映射到用户态,所谓“映射”就可以理解为建立了一个“符号链接”,这样应用程序就可以直接操作这块物理内存了
- 关于LCD的硬件原理详见LCD简介
- 关于如何在应用层测试fb,详见framebuffer的使用与测试
2.framebuffer驱动结构
fb的结构和misc极为类似,由内核中的fb框架实现一部分,然后再由设备驱动本身实现一部分。设备驱动本身就是一个普通的platform总线驱动
虽然每家原厂写的fb设备驱动可能有些差异,但是基本的套路还是相同的
- 在内核fb框架中,所有的fb设备公用一个主设备号(都是29),它们之间以次设备号互相区分。所以在框架中使用register_chrdev注册了一个主设备号为29的设备,而在驱动中device_create创建设备文件主设备号都为29,次设备号不同
- 由上图可以看出,内核提供了fb框架,原厂提供了fb的platform设备和驱动;不论有多少LCD屏幕,用的都是这一套platform驱动,它们的操作方式都是固定的,唯一的区别就在platform_data里的硬件参数。而我们驱动工程师重点关注的就是该硬件参数
3.修改LCD的硬件参数(2.6版本内核)
当我们板子上的LCD需要更换时,驱动中也需要进行相应的修改
- 具体的思路,是去修改platform_device中的platform_data,LCD的硬件参数都在里面,但是怎么找到这个platform_data是一门学问,因为原厂写的代码是比较复杂的。。。。具体方法详见基于platform总线的驱动分析 的文末
- 不难找到设置platform_data的地方,如图
那么目前导入的platform_data是哪一个呢?根据menuconfig和xxxxdefconfig,分析可知是ek070tn93_fb_data
:
stat