基本原理
通过 framebuffer ,应用程序用 mmap 把显存映射到应用程序虚拟地址空间,将要显示的数据写入这个内存空间就可以在屏幕上显示出来;
驱动程序分配系统内存作为显存;实现 file_operations 结构中的接口,为应用程序服务;实现 fb_ops 结构中的接口,控制和操作 LCD 控制器;
驱动程序将显存的起始地址和长度传给 LCD 控制器的寄存器 (一般由 fb_set_var 完成) , LDC 控制器会自动的将显存中的数据显示在
LCD 屏上。
写 framebuffer 驱动程序要做什么
简单的讲,framebuffer 驱动的功能就是分配一块内存作显存,然后对 LCD 控制器的寄存器作一些设置。
具体来说:
填充一个 fbinfo 结构
用 reigster_framebuffer (fbinfo*) 将 fbinfo 结构注册到内核
对于 fbinfo 结构,最主要的是它的 fs_ops 成员,需要针对具体设备实现 fs_ops 中的接口
考虑是否使用中断处理
考虑内存访问方式
显卡不自带显存的,分配系统内存作为显存
显卡自带显存的,用 I/O 内存接口进行访问 (request_mem_region / ioremap),
关于如何写驱动的参考资料,在网站 http: /linux-fbdev.sourceforge.net/HOWTO/index.html 可以找到
"Linux Frame buffer Driver Writing HOWTO"
什么是 frame buffer 设备
frame buffer
设备是图形硬件的抽象,它代表了图形硬件的侦缓冲区,允许应用程序通过指定的接口访问图形硬件。因此,应用程序不必关心底层硬件细节。
设备通过特定的设备节点访问,通常在 /dev 目录下,如 /dev/fb*。
更多关于 frame buffer device 的资料可以在以下两个文件中找到: linux
/Documentation/fb/framebuffer.txt 和 linux /Documentation/fb
/interal.txt,但这些资料内容不多,还需要看看结合代码具体分析。
Linux Frame Buffer 驱动程序层次结构
Frame Buffer 设备驱动可以从三个层次来看:
应用程序与系统调用;
适用于所有设备的通用代码,避免重复,包括 file_operations 结构、register/unregister framebuffer 接口等;
操作具体硬件的代码,主要是 fb_ops 结构。
在 Linux 内核中,Frame Buffer 设备驱动的源码主要在以下两个文件中,它们处于 frame buffer
驱动体系结构的中间层,它为上层的用户程序提供系统调用,也为底层特定硬件驱动提供了接口:
linux/inlcude/fb.h
linux/drivers/video/fbmem.c
数据结构
头文件 fb.h 定义了所有的数据结构:
fb_var_screeninfo:描述了一种显卡显示模式的所有信息,如宽、高、颜色深度等,不同的显示模式对应不同的信息;
fb_fix_screeninfo:定义了显卡信息,如 framebuffer 内存的起始地址,地址长度等;
fb_cmap:设备独立的 colormap 信息,可以通过 ioctl 的 FBIOGETCMAP 和 FBIOPUTCMAP 命令设置
colormap;
fb_info:包含当前 video card 的状态信息,只有 fb_info 对内核可见;
fb_ops : 应用程序使用 ioctl 系统调用操作底层的 LCD 硬件,fb_ops 结构中定义的方法用于支持这些操作;
这些结构相互之间的关系如下所示:
framebuffer
驱动主要数据结构
接口
fbmem.c 实现了所有驱动使用的通用代码,避免了重复。
全局变量:struct fb_info *registered_fb [FB_MAX]
int num_registered_fb;
这两个变量用于记录正在使用的 fb_info 结构实例。fb_info 代表 video card 的当前状态,所有的 fb_info
结构都放在数组中。当一个 frame buffer 在内核中登记时,一个新的 fb_info 结构被加入该数组,num_registered_fb 加
1。
fb_drivers 数组:static struct {
const char *name;
int (*init)(void);
int (*setup)(void);
} fb_drivers[] __initdata= { ....};
若 frame buffer 驱动程序是静态链接到内核中,一个新的 entry 必须要加到这个表中。 若该驱动程序是使用 insmod/rmmod
动态加载到内核,则不必关心这个结构。static struct file_operations fb_ops ={
owner: THIS_MODULE,
read: fb_read,
write: fb_write,
ioctl: fb_ioctl,
mmap: fb_mmap,
open: fb_open,
release: fb_release
};
这是用户应用程序的接口,fbmem.c 实现了这些函数。
register/unregister framebuffer:register_framebuffer(struct fb_info *fb_info)
unregister_framebuffer(struct fb_info *fb_info)
这是底层 frame buffer 设备驱动程序的接口。驱动程序使用这对函数实现注册和撤销操作。底层驱动程序的工作基本上是填充 fb_info
结构,然后注册它。