简介
传统的显示框架;
简单,但是只能提供最基础的显示功能;
无法满足当前上层应用和底层硬件的显示需求
FB框架不能处理基于3D加速GPU显卡
应用层需要实现的:
/dev/fops
①
open
设备节点;
②调用ioctl
获取分辨率.bpp
③在用户空间分配内存;
④调用mmap
函数;
FrameBuffer
子系统框架:
分为两层:
FrameBuffer通用层(内核实现):
作用:
对下层提供接口
①申请设备号(主设备号为29\次设备号递增);
②创建类;
③创建设备节点;
④实现fops{ mmap; ioctl; }
用find命令在drivers目录下查找文件名:find ./ -name fdmem.c
drivers/video/fbdev/core/fbmem.c
FrameBuffer适配器层(BSP工程师提供):
这层代码不同厂家不一样
①初始化LCD控制器;
②分配显存;
③设置DMA;
设备树节点:
{ ①控制器地址; ②中断; ③背光; ④屏幕参数; ⑤分辨率:bpp; ⑥时序 }
;
FrameBuffer框架图:
FrameBuffer
适配器层:
创建了一个fb_info
结构体,里面有两个小结构体,一个是固定参数fix
和可变参数var
固定参数fix
:
申请一个显存,这个显存显示什么,显示LCD屏上的内容,数据从何而来,使用户空间提供,用户空间由mmap
映射,用户空间也需要一块虚拟地址来和它映射起来,此时把数据写进用户空间,就进而写到了显存里面,显存是具有DMA
功能的,DMA
会一直读数据,将数据读到LCD控制器里面,LCD控制器再把数据给到LCD屏. 那我们只需要告诉DMA
这块显存的大小,起始,DMA
就会不断往复的将一个字节的数据读到LCD控制器中去,LCD控制器就会更具之前设置好的时序自动的刷到LCD屏上.
可变参数var:
会写设备树,适配器层.c
会去解析这个设备树,设备树中的内容都是用来初始化LCD控制器的,随后会把分表率&时序赋值给var
,fb_info
拿到var
,随后将fb_info
注册到FrameBuffer
通用层中的一个fb_array
数组中去,进而FrameBuffer
通用层实现申请设备号(29)\创建类\创建设备节点\实现fops{mmap&ioctl}.
此时驱动层代码就写完了.
FrameBuffer子系统应用层调用内核驱动点亮LCD屏的全流程:
1.open
设备节点;
2.调用ioctl
获取到分辨率\bpp
;
ioct(应)
=>ioctl(驱)
=>fb_array
=> fb_info
=>var
=>{分辨率\时序\bpp}
;
3.在用户空间分配内存;
4.调用mmap函数进行用户空间和内核空间的内存映射;
mmap(应)
=>mmap(驱)
=>fb_array
=>fb_info
=>fix
=>显存中(起始基地址\长度)
从而应用层就可以进行mmap
内存映射;
5.设置DMA
显存起始地址和显存大小告诉DMA
后,DMA
就开始将数据循环往复搬进LCD控制器
中,从而在LCD屏
上显示.
注:
为了适应当前日益更新的显示硬件;
软件上能支持更多高级的控制和特性
FB
框架不能处理基于3D
加速GPU
显卡,DRM
是可以统一管理GPU
显示,所以DRM
相对于FB
更能适应新的显示硬件