一、Framebuffer 设备驱动总体架构
帧缓冲设备为标准的字符型设备,在Linux中主设备号29,定义在/include/linux/major.h中的FB_MAJOR,次设备号定义帧缓冲的个数,最大允许有32个FrameBuffer,定义在/include/linux/fb.h中的FB_MAX,对应于文件系统下/dev/fb%d设备文件。
我们从上面这幅图看,帧缓冲设备在Linux中也可以看做是一个完整的子系统,大体由fbmem.c和xxxfb.c组成。向上给应用程序提供完善的设备文件操作接口(即对FrameBuffer设备进行read、write、ioctl等操作),接口在Linux提供的fbmem.c文件中实现;向下提供了硬件操作的接口,只是这些接口Linux并没有提供实现,因为这要根据具体的LCD控制器硬件进行设置,所以这就是我们要做的事情了(即xxxfb.c部分的实现)。
二 、Framebuffer 相关的重要数据结构:
1、从Framebuffer设备驱动程序结构看,该驱动主要跟fb_info结构体有关,该结构体记录了Framebuffer设备的全部信息,包括设备的设置参数、状态以及对底层硬件操作的函数指针。在Linux中,每一个Framebuffer设备都必须对应一个fb_info,fb_info在/linux/fb.h中的定义如下:(只列出重要的一些)
1 struct fb_info { 2 atomic_t count; 3 int node; ///次设备号 4 int flags; 5 struct mutex lock; //用于open、release、ioctrl功能的锁 6 struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */ 7 struct fb_var_screeninfo var; //LCD 可变参数 8 struct fb_fix_screeninfo fix; //LCD 固定参数 9 struct fb_monspecs monspecs; /* Current Monitor specs *///LCD 显示器标准 10 struct work_struct queue; //帧缓冲事件队列 11 struct fb_pixmap pixmap; ///图像硬件 mapper 12 struct fb_pixmap sprite; //光标硬件 mapper 13 struct fb_cmap cmap; //当前颜色表 14 struct list_head modelist; //模式列表 15 struct fb_videomode *mode; //当前的显示模式 16 17 #ifdef CONFIG_FB_BACKLIGHT 18 /* assigned backlight device */ 19 /* set before framebuffer registration, 20 remove after unregister */ 21 struct backlight_device *bl_dev;///对应的背光设备 22 23 /* Backlight level curve */ 24 struct mutex bl_curve_mutex; 25 u8 bl_curve[FB_BACKLIGHT_LEVELS];///背光调整 26 #endif 27 #ifdef CONFIG_FB_DEFERRED_IO 28 struct delayed_work deferred_work; 29 struct fb_deferred_io *fbdefio; 30 #endif 31 32 struct fb_ops *fbops;///---->对底层硬件设备操作的函数指针 33 struct device *device; /* This is the parent *////父设备节点 34 struct device *dev; /* This is this fb device *////当前的帧缓冲设备 35 int class_flag; /* private sysfs flags */ 36 #ifdef CONFIG_FB_TILEBLITTING 37 struct fb_tile_ops *tileops; /* Tile Blitting *///图块Blitting ? 38 #endif 39 char __iomem *screen_base; /* Virtual address *///虚拟地址 40 unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */ ///LCD IO映射的虚拟内存大小 41 void *pseudo_palette; /* Fake palette of 16 colors *///伪16色 颜色表 42 #define FBINFO_STATE_RUNNING 0 43 #define FBINFO_STATE_SUSPENDED 1 44 u32 state; /* Hardware state i.e suspend *////LCD 挂起或复位的状态 45 void *fbcon_par; /* fbcon use-only private area */ 46 /* From here on everything is device dependent */ 47 void *par; 48 /* we need the PCI or similar aperture base/size not 49 smem_start/size as smem_start may just be an object 50 allocated inside the aperture so may not actually overlap */ 51 struct apertures_struct { 52 unsigned int count; 53 struct aperture { 54 resource_size_t base; 55 resource_size_t size; 56 } ranges[0]; 57 } *apertures; 58 59 bool skip_vt_switch; /* no VT switch on suspend/resume required */ 60 };
其中,fb_var_screeninfo和fb_fix_screeninfo两个结构体跟LCD硬件属性相关,fb_var_screeninfo代表可修改的LCD显示参数,如分辨率和像素比特数;fb_fix_screeninfo代表不可修改的LCD属性参数,如显示内存的物理地址和长度等。另外一个非常重要的成员是fb_ops,其是LCD底层硬件操作接口集。
fb_ops硬件操作接口集包含很多接口,如设置可变参数fb_set_par、设置颜色寄存器fb_setcolreg、清屏接口fb_blank、画位图接口fb_imageblit、内存映射fb_mmap等等。
fb_info结构体在调用register_framebuffer之前完成初始化。一般来说,LCD设备属于平台设备,其初始化是在平台设备驱动的probe接口完成。而LCD设备所涉及的硬件初始化则在平台设备初始化中完成。
2、fb_fix_screeninfo结构体主要记录用户不可以修改的控制器的参数,该结构体的定义如下:
1 struct fb_fix_screeninfo { 2 char id[16]; //字符串形式的标识符 3 unsigned long smem_start; /fb 缓存的开始位置 4 /* (physical address) */ 5 __u32 smem_len; /* Length of frame buffer mem *///fb 缓存的长度 6 __u32 type; /* see FB_TYPE_* *////看FB_TYPE_* --> 7 __u32 type_aux; /* Interleave for interleaved Planes *///分界 8 __u32 visual; ///看FB_VISUAL_* --> 9 __u16 xpanstep; //如果没有硬件panning就赋值为0 10 __u16 ypanstep; //如果没有硬件panning就赋值为0 11 __u16 ywrapstep; //如果没有硬件ywrap就赋值为0 12 __u32 line_length; //一行的字节数 13 unsigned long mmio_start; //内存映射 IO的开始位置 14 /* (physical address) */ 15 __u32 mmio_len; //内存映射 IO的长度 16 __u32 accel; /* Indicate to driver which */ 17 /* specific chip/card we have */ 18 __u16 capabilities; /* see FB_CAP_* *///功能 ---FB_CAP_FOURCC--- Device supports FOURCC-based formats 19 __u16 reserved[2]; //为以后的兼容性保留 20 };
3、fb_var_screeninfo结构体主要记录用户可以修改的控制器的参数,比如屏幕的分辨率和每个像素的比特数等,该结构体定义如下:
1 struct fb_var_screeninfo { ///显示屏信息 2 __u32 xres; /* visible resolution*//可视区域,一行有多少个像素点 3 __u32 yres; ///可视区域,一列有多少个像素点 4 __u32 xres_virtual; /* virtual resolution*//虚拟区域,一行有多少个像素点,简单的意思就是内存中定义的区间是比较大的 5 __u32 yres_virtual;////虚拟区域,一列有多少个像素点 6 __u32 xoffset; //虚拟到可见屏幕之间的行偏移 7 __u32 yoffset; /* resolution *//虚拟到可见屏幕之间的列偏移 8 9 __u32 bits_per_pixel; /* guess what*/ 每个像素的 bit 数,这个参数不需要自己配置,而是通过上层在调用 checkvar 函数传递 bpp 的时候赋值的 10 __u32 grayscale; /* 0 = color, 1 = grayscale,*////等于零就成黑白 (灰度) 11 /* >1 = FOURCC */ 12 // 通过 pixel per bpp 来设定 red green 和 blue 的位置; pixel per bpp 可以通过 ioctl 设定 13 struct fb_bitfield red; //fb缓存的R位域 14 struct fb_bitfield green; /* else only length is significant *//fb缓存的G位域 15 struct fb_bitfield blue; //fb缓存的B位域 16 struct fb_bitfield transp; /* transparency *//透明度 17 18 __u32 nonstd; /* != 0 Non standard pixel format *///如果nonstd 不等于0,非标准的像素格式 19 20 __u32 activate; /* see FB_ACTIVATE_* */ 21 22 __u32 height; //内存中的图像高度 23 __u32 width; //内存中的图像宽度 24 25 __u32 accel_flags; /* (OBSOLETE) see fb_info.flags *////加速标志 26 27 /* Timing: All values in pixclocks, except pixclock (of course) */ 28 ///时序,这些部分就是显示器的显示方法了,和具体的液晶显示屏有关,在驱动中一般放在 具体液晶屏的配置文件 29 __u32 pixclock; /* pixel clock in ps (pico seconds) *///像素时钟 30 __u32 left_margin; /* time from sync to picture *////行切换,从同步到绘图之间的延迟 31 __u32 right_margin; /* time from picture to sync *///行切换,从绘图到同步之间的延迟 32 __u32 upper_margin; /* time from sync to picture *///帧切换,从同步到绘图之间的延迟 33 __u32 lower_margin; ////帧切换,从绘图到同步之间的延迟 34 __u32 hsync_len; /* length of horizontal sync */ //水平同步的长度 35 __u32 vsync_len; /* length of vertical sync */ //垂直同步的长度 36 __u32 sync; /* see FB_SYNC_* *////---->看 FB_SYNC_* 37 __u32 vmode; /* see FB_VMODE_* *////---->看 FB_VMODE_* 38 __u32 rotate; /* angle we rotate counter clockwise */ 39 __u32 colorspace; /* colorspace for FOURCC-based modes */ 40 __u32 reserved[4]; /* Reserved for future compatibility */ 41 };
通过下图可以对fb_var_screeninfo中涉及的时序理解更清楚一些:
4、fb_ops结构体是对底层硬件操作的函数指针,该结构体中定义了对硬件的操作有:
注: fb_ops结构与file_operations 结构不同,fb_ops是底层操作的抽象,而file_operations是提供给上层系统调用的接口,可以直接调用.
1 struct fb_ops { 2 /* open/release and usage marking */ 3 struct module *owner; 4 int (*fb_open)(struct fb_info *info, int user); 5 int (*fb_release)(struct fb_info *info, int user);
/*对于非线性布局的/常规内存映射无法工作的帧缓冲设备需要*/ 10 ssize_t (*fb_read)(struct fb_info *info, char __user *buf, 11 size_t count, loff_t *ppos); 12 ssize_t (*fb_write)(struct fb_info *info, const char __user *buf, 13 size_t count, loff_t *ppos); 15 /* checks var and eventually tweaks it to something supported, 16 * DO NOT MODIFY PAR */ 17 int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);///检查可变参数并进行设置 19 /* set the video mode according to info->var */ 20 int (*fb_set_par)(struct fb_info *info);///根据设置的值进行更新,使之有效 22 /* set color register */ 23 int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green, ////设置颜色寄存器 24 unsigned blue, unsigned transp, struct fb_info *info); 26 /* set color registers in batch */ 27 int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
29 30 int (*fb_blank)(int blank, struct fb_info *info);///显示空白 32 /*pan显示*/ 33 int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info); 36 void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);///矩形填充 38 void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);///复制数据 40 void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);///图形填充 42 /* 绘制光标 */ 43 int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor); 45 /* 旋转显示 */ 46 void (*fb_rotate)(struct fb_info *info, int angle); 48 /* 等待blit空闲 */ 49 int (*fb_sync)(struct fb_info *info); 51 /* fb 特定的 ioctl */ 52 int (*fb_ioctl)(struct fb_info *info, unsigned int cmd, 53 unsigned long arg); 55 /* 处理32bit compat ioctl (optional) */ 56 int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd, 57 unsigned long arg); 59 /* fb 特定的 mmap */ 60 int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma); 62 /* get capability given var */ 63 void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps, 64 struct fb_var_screeninfo *var); 66 /* teardown any resources to do with this framebuffer */ 67 void (*fb_destroy)(struct fb_info *info); 69 /* called at KDB enter and leave time to prepare the console */ 70 int (*fb_debug_enter)(struct fb_info *info); 71 int (*fb_debug_leave)(struct fb_info *info); 72 };
5、fb_cmap:设备独立的 colormap 信息,可以通过 ioctl 的 FBIOGETCMAP 和 FBIOPUTCMAP 命令设置 colormap;
struct fb_cmap { //颜色映射表 __u32 start; /* First entry *////第一个入口 __u32 len; /* Number of entries *///入口的数字 __u16 *red; /* Red values *///红色 __u16 *green; ///绿色 __u16 *blue; ///蓝色 __u16 *transp; //透明度,允许为空 };
这些结构相互之间的关系如下所示: