一、Framebuffer子系统简介
Framebuffer(帧缓冲)时Linux系统位显示设备提供的一个接口。属于偏底层的显示接口。它将显示缓冲区抽象,屏蔽图像硬件的底层差异,允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。对于帧缓冲设备而言,只要在缓冲区对应位置写入颜色值,对应的屏幕位置则显示响应的颜色。
Framebuffer子系统的主要结构如下图(借图展示,侵删)。
从中可以看到,Framebuffer子系统主要通过fb_ops中的成员函数操作LCD显示器。多数的LCD操作规范,可以按照像素点格式的要求按顺序写入帧缓冲区。但是也有一些LCD操作不是很规范,这时,可以使用fb_ops中的fb_write()函数重写。例如spi接口或i2c的0.96寸、分辨率位128×64的oled屏幕,可以使用fb_write()重写。
二、i2c接口的oled屏幕驱动
1. 重要结构体
使用Framebuffer子系统,主要需要配置如下几个重要的结构体:
fb_var_screeninfo代表可修改的LCD显示参数,如分辨率和像素比特数。
fb_fix_screeninfo 代表不可修改的LCD属性参数,如显示内存的物理地址和长度等。
fb_ops,其是LCD底层硬件操作接口集。
fb_cmap,颜色映射表。
fb_info, Framebuffer子系统主要注册结构体。
fb_info具体如下:
#define OLED_WIDTH 128
#define OLED_HEIGHT 64
static struct fb_info oled_info = {
.var ={
.xres = OLED_WIDTH,
.yres = OLED_HEIGHT,
.xres_virtual = OLED_WIDTH,
.yres_virtual = OLED_HEIGHT,
.bits_per_pixel = 1,
},
.fix={
.smem_len = OLED_HEIGHT * OLED_WIDTH / 8,
.line_length = 128,
},
.fbops = &oled_fbops,
};
从上述配置fb_info结构体可以看到,主要配置屏幕的长(xres)、宽(yres)、一个像素显示需要多少位(bits_per_pixel)、显示一帧需要多少字节(smem_len)、一行多少字节(line_length)和一个fb_ops结构体。
其中oled_fbops结构体如下:
static struct fb_ops oled_fbops = {
.fb_open = oled_fb_open,
.fb_release = oled_fb_release,
.fb_write = oled_fb_write,
.fb_mmap = oled_fb_mmap,
}
fb_open、release是打开关闭设备,fb_mmap则是对设备进行抽象的函数,开辟显存的地方,使显存和屏幕显示对应。fb_write则是oled显示是i2c接口的显示屏,故需要对其进行重写。
2. 注册、卸载Framebuffer子系统
注册和卸载需要两个函数:
int register_framebuffer(struct fb_info *fb_info); //用于注册显示设备
int unregister_framebuffer(struct fb_info *fb_info); //卸载
三、总结
Framebuffer子系统是Linux系统对显示相关的硬件的一个软件抽象层,其最终是挂载到platform总线上,在probe函数中会调用相关操作。Linux显示目前有两种方式,一种是Framebuffer子系统,另一种则是DRM/KMS,前者比较简单,通过的功能也不多,后者现在是更主流的方式,也复杂很多,等学习了之后再更新。
参考书:Linux设备驱动开发详解(基于最新的Linux4.0内核) 宋宝华著