关于LCD 设备资料可参考如下资料:
frame buffer 设备是图形硬件的抽象,它代表了图形硬件的侦缓冲区,允许应用程序通过指定的接口访问图形硬件。因此,应用程序不必关心底层硬件细节。
设备通过特定的设备节点访问,通常在 /dev 目录下,如 /dev/fb*。
更 多关于 frame buffer device 的资料可以在以下两个文件中找到: linux /Documentation/fb/framebuffer.txt 和 linux /Documentation/fb /interal.txt,但这些资料内容不多,还需要看看结合代码具体分析。
Linux Frame Buffer 驱动程序层次结构Frame Buffer 设备驱动可以从三个层次来看:
在 Linux 内核中,Frame Buffer 设备驱动的源码主要在以下两个文件中,它们处于 frame buffer 驱动体系结构的中间层,它为上层的用户程序提供系统调用,也为底层特定硬件驱动提供了接口:
头文件 fb.h 定义了所有的数据结构:
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 结构,然后注册它。
一个 LCD controller 驱动程序实现一个 LCD controller 驱动程序主要做如下两步:
由于大多数 LDC controller 没有自己的显存,需要分配一块系统内存作为显存。这块系统内存的起始地址和长度之后会被存放在 fb_fix_screeninfo 的 smem_start 和 smem_len 域中。该内存应该是物理上连续的。
对于带独立显存的显卡,使用 request_mem_region 和 ioremap 将显卡外设内存映射到处理器虚拟地址空间。
实现 fb_ops 结构目前还没有讨论的 file_operations 方法是 ioctl ()。用户应用程序使用 ioctrl 系统调用操作 LCD 硬件。fb_ops 结构中定义的方法为这些操作提供支持。注意, fb_ops 结构不是 file_operations 结构。fb_ops 是底层操作的抽象,而 file_operations 为上层系统调用接口提供支持。
下面考虑需要实现哪些方法。ioctl 命令和 fb_ops 结构中的接口之间的关系如下所示:
FBIOGET_VSCREENINFO fb_get_var FBIOPUT_VSCREENINFO fb_set_var FBIOGET_FSCREENINFO fb_get_fix FBIOPUTCMAP fb_set_cmap FBIOGETCMAP fb_get_cmap FBIOPAN_DISPLAY fb_pan_display
只要我们实现了那些 fb_XXX 函数,那么用户应用程序就可以使用 FBIOXXXX 宏来操作 LDC 硬件了。那怎么实现那些接口呢?可以参考下 linux/drivers/video 目录下的驱动程序。
在众多接口中, fb_set_var 是最重要的。它用于设置 video mode 等信息。下面是实现 fb_set_var 函数的通用步骤:
其中第四步是底层硬件操作。