Framebuffer
什么是framebuffer
framebuffer从字面上理解是“帧缓冲”,一般有如下理解:
- 单纯的把framebuffer看作一块内存,这部分内存包含了将要scan out显示的数据。
- 等价于framebuffer driver。通常作为LCD控制器或者其他显示设备的驱动,FrameBuffer驱动是一个字符设备,设备节点是/dev/fbX,主设备号为29,次设备号递增,用户可以将Framebuffer看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。这种操作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等具体细节。这些都是由Framebuffer设备驱动来完成的。Framebuffer设备为上层应用程序提供系统调用,也为下一层的特定硬件驱动提供接口;那些底层硬件驱动需要用到这儿的接口来向系统内核注册它们自己。所以可以看成是一个graphic hardware-independent抽象层,上面对接应用层,下面对接LCD等硬件的驱动。
- 有一种说法是操纵lcd显示就是操纵framebuffer,表面上来看是这样的。实际上是frambuffer就是linux内核驱动申请的一片内存空间,然后lcd内有一片sram,cpu内部有个lcd控制器,它有个单独的dma用来将frambuffer中的数据拷贝到lcd的sram中去 拷贝到lcd的sram中的数据就会显示在lcd上,LCD驱动和framebuffer驱动没有必然的联系,它只是驱动LCD正常工作的,比如有信号传过来,那么LCD驱动负责把信号转成显示屏上的内容,至于什么内容这就是应用层要处理的。
- framebuffer帧缓冲(简称fb)是linux内核中虚拟出的一个设备
- framebuffer向应用层提供一个统一标准接口的显示设备
- 从驱动来看,fb是一个典型的字符设备,而且创建了一个类/sys/class/graphics
帧缓冲设备驱动的结构
我们知道在Linux中,万物都是文件。那么framebuffer也是一个文件,比如/dev/fb0。我们只需要操作/dev/fb0就可以把图像显示在显示器上了,那么这是怎么实现的呢?
先谈谈如何把文件操作和设备操作关联起来。
物理层面:
Linux中的PCI设备可以将其控制寄存器映射到物理内存空间,而后,对这些控制寄存器的访问变成了对理内存的访问,因此,这些寄存器又被称为"memio"。一旦被映射到物理内存,Linux的普通进程就可以通过mmap将这些内存I/O映射到进程地址空间,这样就可以直接访问这些寄存器了。
逻辑层面:
FrameBuffer设备属于字符设备,采用了文件层—驱动层的接口方式,Linux为帧缓冲设备定义了驱动层的接口fb_info结构,在文件层上,用户调用file_operations的函数操作,间接调用fb_info中的fb_ops函数集来操作硬件。
这里的意思是说,对于Linux系统,其事先规定了对于文件的操作,也就是上面说的file_operations函数。我们只需要让file_operations函数和fb_ops函数对应起来,就实现了文件 --> framebuffer driver的操作。这里的framebuffer dev实际上就是前文讲的是一个抽象(或者说是虚拟)的设备。接下来就需要打通从framebuffer dev到具体设备的通路,也就是framebuffer driver --> LCD driver,实际上就是把framebuffer driver的fb_ops对应到lcd_ops。至于lcd_ops到硬件,什么样的二进制代码传过去显示怎样的输出,就是具体硬件厂商的人员所需要去实现的driver。
Framebuffer的使用步骤
- 打开设备文件 /dev/fb0
- 获取当前设备信息 #include <linux/fb.h>
- mmap做映射
- 填充framebuffer
Framebuffer数据结构
kernel\include\linux\fb.h
fb_info是Linux为帧缓冲设备定义的驱动层接口。它不仅包含了底层函数,而且还有记录设备状态的数据。每个帧缓冲设备都与一个fb_info结构相对应。
struct fb_info { atomic_t count; int node; /*一个FrameBuffer设备的次设备号*/ int flags; struct mutex lock; /* Lock for open/release/ioctl funcs */ struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */ struct fb_var_screeninfo var;/* Current var */ struct fb_fix_screeninfo fix;/* Current fix */ struct fb_monspecs monspecs;/* Current Monitor specs */ struct work_struct queue; /* Framebuffer event queue */ struct fb_pixmap pixmap; /* Image hardware mapper */ struct fb_pixmap sprite; /* Cursor hardware mapper */ struct fb_cmap cmap; /* Current cmap */ struct list_head modelist; /* mode list */ struct fb_videomode *mode; /* current mode */ #ifdef CONFIG_FB_BACKLIGHT struct backlight_device *bl_dev; /* Backlight level curve */ struct mutex bl_curve_mutex; u8 bl_curve[FB_BACKLIGHT_LEVELS]; #endif #ifdef CONFIG_FB_DEFERRED_IO struct delayed_work deferred_work; struct fb_deferred_io *fbdefio; #endif struct fb_ops *fbops; struct device *device; /* This is the parent */ struct device *dev; /* This is this fb device */ int class_flag; /* private sysfs flags */ #ifdef CONFIG_FB_TILEBLITTING struct fb_tile_ops *tileops;/* Tile Blitting */ #endif char __iomem *screen_base; /* Virtual address */ unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */ void *pseudo_palette; /* Fake palette of 16 colors */ #define FBINFO_STATE_RUNNING 0 #define FBINFO_STATE_SUSPENDED 1 u32 state; /* Hardware state i.e suspend */ void *fbcon_par; /* fbcon use-only private area */ void *par; struct apertures_struct { unsigned int count; struct aperture { resource_size_t base; resource_size_t size; } ranges[0]; } *apertures; };
framebuffer驱动源码分析
1. 驱动框架部分,即framebuffer driver相关
- drivers/video/fbmem.c主要任务:fbmen_init()函数负责创建graphics类、注册FB的字符设备驱动、register_framebuffer()函数提供接口给具体framebuffer驱动编写着来注册fb设备。本文件相对于fb来说,地位和作用和misc.c文件相对于杂散类设备来说一样的,结构和分析方法也是类似的。
- drivers/video/fbsys.c这个文件是处理fb在/sys目录下的一些属性文件的。
- drivers/video/modedb.c这个文件是管理显示模式(譬如VGA、720P等就是显示模式)的。
- drivers/video/fb_notify.c这个文件是frame buff用来管理相关通知的。
2. 驱动部分, 即lcd driver相关,以三星s3fdb为例,读者没有此driver可以分析amdgpu driver
- drivers/video/samsung/s3cfb.c驱动主体
- drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c : 驱动主体
framebuffer驱动框架分析
Linux内核已经给我们封装了LCD驱动的抽象层,我们只需要调用内核封装的注册接口去实现我们的平台驱动即可。
- 内核已经给我们封装了LCD驱动的抽象层是在fbmem.c,先简单分析一下它的框架。
- 总结
framebuffer驱动分析
1. s3cfb.c
2. s3c_device_fb
3. probe函数
- struct s3c_platform_fb :这个结构体是fb的platform_data结构体,这个结构体变量就是platform设备的私有数据,这个数据在platform_device.device.platform_data中存储。在mach文件中去准备并填充这些数据,在probe函数中通过传参的platform_device指针取出来。
- struct s3cfb_global: 这个结构体主要作用是在驱动部分的2个文件(s3cfb.c和s3cfb_fimd6x.c)的函数中做数据传递用的。
参考链接:
FrameBuffer驱动程序分析 https://blog.csdn.net/yangwen123/article/details/12096483
Linux驱动开发(9)------- framebuffer驱动详解 https://blog.csdn.net/qq_45544223/article/details/106598190