Framebuffer驱动全面解析
1. LCD简介
1.1 LCD屏幕
LCD由一个一个像素组成:每行有xres个像素,有yres行,它的分辨率是:xres * yres。
只要我们能控制任意一个像素的颜色,就可以在LCD上绘制文字、图片。
1.2 像素的颜色表示
用红绿蓝三颜色来表示,可以用24位数据来表示红绿蓝,也可以用16位等等格式,比如:
bpp:bits per pixel,每个像素用多少位来表示
24bpp:实际上会用到32位,其中8位未使用,其余24位中分别用8位表示红(R)、绿(G)、蓝(B)
16bpp:有rbg565,rgb555
rgb565:用5位表示红、6位表示绿、5位表示蓝
rgb555:16位数据中用5位表示红、5位表示绿、5位表示蓝,浪费一位
发送颜色过程:假设每个像素的颜色用16位来表示,那么一个LCD的所有像素点假设有xres * y res个, 需要的内存为:xres * yres * 16 / 8,也就是要设置所有像素的颜色,需要这么大小的内存。 这块内存就被称为framebuffer:
Framebuffer中每块数据对应一个像素
每块数据的大小可能是16位、32位,这跟LCD上像素的颜色格式有关
设置好LCD硬件后,只需要把颜色数据写入Framebuffer即可
1.3 从驱动角度理解LCD
驱动工程师对LCD的理解要深入硬件,比如要回答这几个问题:
Framebuffer在哪里?
谁把Framebuffer中的数据发给LCD?
统一的LCD硬件模型:
有一个MIPI标准:
MIPI表示Mobile Industry Processor Interface
,即移动产业处理器接口。是MIPI联盟发起的为移动应用处理器制定的开放标准和一个规范。主要是手机内部的接口(摄像头、显示屏接口、射频/基带接口)等标准化,从而减少手机内部接口的复杂程度及增加设计的灵活性。
对于LCD,MIPI接口可以分为3类:
MIPI-DBI (Display Bus Interface):
MIPI-DPI (Display Pixel Interface):
MIPI-DSI (Display Serial Interface):

2. Framebuffer驱动程序框架
2.1 如何编写字符设备驱动程序
字符驱动流程如图所示,一般编写字符驱动程序有以下步骤:
驱动主设备号
构造file_operations结构体,填充open/read/write等成员函数
注册驱动:register_chrdev(major, name, &fops)
入口函数
出口函数
2.2 Framebuffer驱动程序框架
概述:分为上下两层:
fbmem.c:承上启下
实现、注册file_operations结构体
把APP的调用向下转发到具体的硬件驱动程序
xxx_fb.c:硬件相关的驱动程序
实现、注册fb_info结构体
实现硬件操作
Framebuffer驱动程序框架主要分为两个层次:核心层和硬件相关层。下面是这两个层次的简要概述和关键组件:
1. 核心层(fbmem.c)
核心层主要负责处理与VFS(虚拟文件系统)的交互,以及将应用程序的调用转发到具体的硬件驱动程序。这一层通常包含以下组件:
file_operations结构体:定义了针对Framebuffer的特殊文件操作,例如open()
, release()
, ioctl()
, mmap()
等。这些操作处理来自用户空间的请求。
帧缓冲区管理:管理帧缓冲区的内存分配和释放。这可能包括请求内存区域、处理内存映射等。
事件处理:处理与Framebuffer相关的各种事件,如模式变化、显示关闭和打开等。
数据转发:将应用程序的调用(如读写操作)转发到具体的硬件驱动程序。
2. 硬件相关层(xxx_fb.c)
硬件相关层专注于与特定硬件的交互。这一层通常包含以下组件:
fb_info结构体:包含了Framebuffer的所有必要信息,如屏幕大小、颜色深度、帧缓冲区的物理地址等。
硬件操作:实现对硬件的具体操作,包括但不限于:
数据传输:实现数据从CPU内存到Framebuffer的传输,以及可能的DMA(直接内存访问)操作。
中断处理:如果硬件支持中断,注册并实现中断服务例程,以处理例如垂直同步等事件。
注册和注销:在驱动程序加载和卸载时,注册和注销fb_info
结构体。
2.3. 怎么编写Framebuffer驱动程序
概述:
分配fb_info
framebuffer_alloc
设置fb_info
var
fbops
硬件相关操作
注册fb_info
register_framebuffe
在Linux内核中,分配和设置fb_info
结构体以及注册Framebuffer设备通常涉及以下步骤:
1. 分配fb_info
使用framebuffer_alloc()
函数从内核内存中分配fb_info
结构体的内存。这个函数通常分配一个足够大的内存块,用于存储fb_info
结构体以及Framebuffer设备的私有数据。
这里sizeof(struct myfb_data)
指定了需要分配的额外内存大小,用于存储特定于驱动程序的数据。
2. 初始化fb_info
设置fb_info
结构体的基本属性,包括指向文件操作的指针、固定屏幕信息、可变屏幕信息等。
其中固定屏幕信息和可变屏幕信息是指:
在Linux Framebuffer API中,"固定屏幕信息"(fb_fix_screeninfo)和"可变屏幕信息"(fb_var_screeninfo)是两个关键的结构体,它们分别描述了Framebuffer的一些固定属性和可变属性:
固定屏幕信息(fb_fix_screeninfo)
fb_fix_screeninfo
结构体包含了一些关于Framebuffer的固定属性,这些属性在设备运行时通常不会改变。这些信息通常由Framebuffer驱动程序设置,并且在注册Framebuffer时提供给内核。固定屏幕信息主要包括:
id
:Framebuffer设备的标识符。smem_start
:Framebuffer内存的起始物理地址。smem_len
:Framebuffer内存的长度。type
:Framebuffer的类型(例如,真彩色、伪彩色等)。visual
:颜色视觉类型(例如,真彩色、伪彩色、直接色等)。xpanstep
和ypanstep
:水平和垂直的扫描线长度,决定了屏幕的水平和垂直分辨率。ywrapstep
:用于硬件支持的行间隔。line_length
:每行的字节长度。可变屏幕信息(fb_var_screeninfo)
fb_var_screeninfo
结构体定义了Framebuffer的一些可变属性,这些属性可以由用户空间程序通过ioctl调用来改变。可变屏幕信息主要包括:
xres
和yres
:屏幕的水平和垂直分辨率。xres_virtual
和yres_virtual
:虚拟屏幕的分辨率,用于支持硬件加速的滚动。bits_per_pixel
:每个像素的位数。red
、green
、blue
:颜色分量的掩码和位移。transp
:透明度掩码和位移(如果支持)。nonstd
:非标准模式标志。activate
:激活方式。在Framebuffer驱动程序中,fb_fix_screeninfo
和fb_var_screeninfo
通常在驱动加载时初始化,并在注册Framebuffer时作为参数传递给fb_info
结构体。这样,当用户空间程序需要查询或设置屏幕参数时,它们可以通过读取或写入fb_info
结构体来获取这些信息。
3. 设置var
结构体
var
结构体(fb_var_screeninfo
)定义了屏幕的可变参数,如分辨率、颜色深度、虚拟宽度等。
4. 设置fbops
结构体
fbops
(struct fb_ops
)定义了Framebuffer的操作函数,如fb_open()
, fb_release()
, fb_ioctl()
等。
5. 硬件相关操作
实现与硬件交互的函数,包括初始化硬件、设置显示模式、数据传输等。
6. 注册fb_info
使用register_framebuffer()
函数将fb_info
注册到内核中,使其成为系统的一部分。
7. 清理和注销
在模块卸载时,需要注销Framebuffer并释放分配的资源。
注意事项:
framebuffer_alloc()
时,确保提供了足够的内存来存储私有数据。fb_var_screeninfo
时,确保所有参数都符合硬件能力,并且正确反映了屏幕的特性。fbops
中的函数时,确保它们能够正确地处理来自用户空间的请求。Framebuffer驱动程序的编写需要对Linux内核的Framebuffer API有深入的了解,以及对所操作的硬件有充分的认识。
3. 编写 Framebuffer_程序框架
通用CFB(Color Frame Buffer)函数:是一组预先定义好的Framebuffer操作函数,它们提供了对Framebuffer进行基本图形操作的能力。这些函数通常在Linux内核的Framebuffer驱动框架中作为默认实现提供,以简化驱动程序的编写。
CFB函数的实现通常考虑了不同颜色深度和像素格式,使得它们可以在多种硬件配置上工作。这些函数作为Framebuffer驱动程序的fb_ops
结构体的一部分,当驱动程序注册Framebuffer设备时,它们会被关联到fb_info
结构体上。在驱动程序的fb_ops
中指定CFB函数,可以让内核知道如何操作Framebuffer进行基本的图形绘制。例如,当用户空间的应用程序请求绘制一个填充矩形时,内核会调用fb_ops
中的fb_fillrect
函数来执行这个操作。使用CFB函数的好处是它们已经被优化和测试过,可以直接用于多种显示硬件。然而,如果需要更高性能或特殊功能的图形操作,可能需要编写特定硬件的Framebuffer操作函数来替代这些通用函数。
/驱动程序的初始化入口函数:
分配fb_info指的是分配内存给要注册的framebuffer设备。
设置fb_info指的是设置可变屏幕参数,RGB的偏移量和长度(即驱动支持的是哪种格式图片,图片数据中红绿蓝的相应位置),c分配内存:这些操作的目的是为Framebuffer设备分配一块内存,这块内存将用于存储屏幕上显示的像素数据。通过分配DMA一致性内存,可以确保硬件设备(如图形加速器或LCD控制器)能够高效地访问这些数据,从而提高显示性能。
驱动程序的退出函数,当模块被卸载时调用:
作者:xace007