概述
18.2 帧缓冲
18.2.1 帧缓冲的概念
帧缓冲(framebuffer)是 Linux 系统为显示设备提供的一个接口,它将显示缓冲区抽象,屏蔽图像硬件的底层差异,允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。对于帧缓冲设备,只要在显示缓冲区中与显示点对应的区域写入颜色值,对应的颜色会自动在屏幕上显示。
帧缓冲设备为标准字符设备,主设备号为 29,对应于/dev/fbn 设备文件。嵌入式系统中的 Qt/Embedded 等图形用户界面环境也基于帧缓冲而设计。
18.2.2 显示缓冲区与显示点
在帧缓冲设备中,对屏幕显示点的操作通过读写显示缓冲区来完成,在不同的色彩模式下,显示缓冲区和屏幕上的显示点有不同的对应关系,表 18.2~表 18.4 分别给出了 16 级灰度、8 位色和 16位色情况下显示缓冲区与显示点的对应关系。
表 18.2 16 级灰度显示缓冲区与显示点的对应关系
表 18.3 8 位色时显示缓冲区与显示点的对应关系
表 18.4 16 位色时显示缓冲区与显示点的对应关系
18.2.3 Linux 帧缓冲相关数据结构与函数
1.fb_info 结构体
帧缓冲设备最关键的一个数据结构体是fb_info 结构体,包括关于帧缓冲设备属性和操作的完整描述,这个结构体的定义如代码清单 18.1 所示。
代码清单 18.1 fb_info 结构体
include/linux/fb.h
struct fb_info {
int node;
int flags;
struct fb_var_screeninfo var; /* Current var */
struct fb_fix_screeninfo fix; /* Current fix */
struct fb_monspecs monspecs; /* Current Monitor specs */
struct work_struct queue; /* Framebuffer event queue */
struct fb_pixmap pixmap; /* Image hardware mapper */
struct fb_pixmap sprite; /* Cursor hardware mapper */
struct fb_cmap cmap; /* Current cmap */
struct list_head modelist; /* mode list */
struct fb_videomode *mode; /* current mode */
#ifdef CONFIG_FB_BACKLIGHT
/* assigned backlight device */
/* set before framebuffer registration,
remove after unregister */
struct backlight_device *bl_dev;
/* Backlight level curve */
struct mutex bl_curve_mutex;
u8 bl_curve[FB_BACKLIGHT_LEVELS];
#endif
#ifdef CONFIG_FB_DEFERRED_IO
struct delayed_work deferred_work;
struct fb_deferred_io *fbdefio;
#endif
struct fb_ops *fbops;
struct device *device; /* This is the parent */
struct device *dev; /* This is this fb device */
int class_flag; /* private sysfs flags */
#ifdef CONFIG_FB_TILEBLITTING
struct fb_tile_ops *tileops; /* Tile Blitting */
#endif
char __iomem *screen_base; /* Virtual address */
unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */
void *pseudo_palette; /* Fake palette of 16 colors */
#define FBINFO_STATE_RUNNING 0
#define FBINFO_STATE_SUSPENDED 1
u32 state; /* Hardware state i.e suspend */
void *fbcon_par; /* fbcon use-only private area */
/* From here on everything is device dependent */
void *par;
};
fb_info 结构体中记录了帧缓冲设备的全部信息,包括设备的设置参数、状态以及操作函数指针。每一个帧缓冲设备都必须对应一个fb_info 结构体。
2.fb_ops 结构体
fb_info 结构体中的成员变量 fbops 为指向底层操作的函数的指针,这些函数需要驱动程序开发人员编写的,其定义如代码清单 18.2 所示。
代码清单 18.2 fb_ops 结构体
/*
* Frame buffer operations
*
* LOCKING NOTE: those functions must _ALL_ be called with the console
* semaphore held, this is the only suitable locking mechanism we have
* in 2.6. Some may be called at interrupt time at this point though.
*/
struct fb_ops {
/* open/release and usage marking */
struct module *owner;
int (*fb_open)(struct fb_info *info, int user);
int (*fb_release)(struct fb_info *info, int user);
/* For framebuffers with strange non linear layouts or that do not
* work with normal memory mapped access
*/
ssize_t (*fb_read)(struct fb_info *info, char __user *buf, size_t count, loff_t *ppos);
ssize_t (*fb_write)(struct fb_info *info, const char __user *buf, size_t count, loff_t *ppos);
/* checks var and eventually tweaks it to something supported,
* DO NOT MODIFY PAR */
int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
/* set the video mode according to info->var */
int (*fb_set_par)(struct fb_info *info);
/* set color register */
int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp, struct fb_info *info);
/* set color registers in batch */
int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
/* blank display */
int (*fb_blank)(int blank, struct fb_info *info);
/* pan display */
int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
/* Draws a rectangle */
void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
/* Copy data from area to another */
void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
/* Draws a image to the display */
void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
/* Draws cursor */
int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
/* Rotates the display */
void (*fb_rotate)(struct fb_info *info, int angle);
/* wait for blit idle, optional */
int (*fb_sync)(struct fb_info *info);
/* perform fb specific ioctl (optional) */
int (*fb_ioctl)(struct fb_info *info, unsigned int cmd, unsigned long arg);
/* Handle 32bit compat ioctl (optional) */
int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd, unsigned long arg);
/* perform fb specific mmap */
int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
/* save current hardware state */
void (*fb_save_state)(struct fb_info *info);
/* restore saved state */
void (*fb_restore_state)(struct fb_info *info);
/* get capability given var */
void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps, struct fb_var_screeninfo *var);
};
分析:
fb_ops 的 fb_check_var()成员函数用于检查可以修改的屏幕参数并调整到合适的值,fb_set_par()则使得用户设置的屏幕参数在硬件上有效。
3.fb_var_screeninfo 和 fb_fix_screeninfo 结构体
fb_info 结构体中的 fb_var_screeninfo 和 fb_fix_screeninfo 成员也是结构体,fb_var_screeninfo 记录用户可修改的显示控制器参数,包括屏幕分辨率和每个像素点的比特数。fb_var_screeninfo 中的 xres 定义屏幕一行有多少个点,yres 定义屏幕一列有多少个点,bits_per_pixel 定义每个点用多少个字节表示。而 fb_fix_screeninfo 中记录用户不能修改的显示控制器的参数,如屏幕缓冲区的物理地址、长度。当对帧缓冲设备进行映射操作时,就是从 fb_fix_screeninfo 中取得缓冲区物理地址的。上述数据成员都需要在驱动程序中初始化和设置。
fb_var_screeninfo和fb_fix_screeninfo结构体的定义分别如代码清单18.3和代码清单18.4所示。
代码清单 18.3 fb_var_screeninfo 结构体
include/linux/fb.h
struct fb_var_screeninfo {
__u32 xres; /* visible resolution */
__u32 yres;
__u32 xres_virtual; /* virtual resolution */
__u32 yres_virtual;
__u32 xoffset; /* offset from virtual to visible */
__u32 yoffset; /* resolution */
__u32 bits_per_pixel; /* guess what */
__u32 grayscale; /* != 0 Graylevels instead of colors */
struct fb_bitfield red; /* bitfield in fb mem if true color, */
struct fb_bitfield green; /* else only length is significant */
struct fb_bitfield blue;
struct fb_bitfield transp; /* transparency */
__u32 nonstd; /* != 0 Non standard pixel format */
__u32 activate; /* see FB_ACTIVATE_* */
__u32 height; /* height of picture in mm */
__u32 width; /* width of picture in mm */
__u32 accel_flags; /* (OBSOLETE) see fb_info.flags */
/* Timing: All values in pixclocks, except pixclock (of course) */
__u32 pixclock; /* pixel clock in ps (pico seconds) */
__u32 left_margin; /* time from sync to picture */
__u32 right_margin; /* time from picture to sync */
__u32 upper_margin; /* time from sync to picture */
__u32 lower_margin;
__u32 hsync_len; /* length of horizontal sync */
__u32 vsync_len; /* length of vertical sync */
__u32 sync; /* see FB_SYNC_* */
__u32 vmode; /* see FB_VMODE_* */
__u32 rotate; /* angle we rotate counter clockwise */
__u32 reserved[5]; /* Reserved for future compatibility */
};
代码清单 18.4 fb_fix_screeninfo 结构体
struct fb_fix_screeninfo {
char id[16]; /* identification string eg "TT Builtin" */
unsigned long smem_start; /* Start of frame buffer mem */
/* (physical address) */
__u32 smem_len; /* Length of frame buffer mem */
__u32 type; /* see FB_TYPE_* */
__u32 type_aux; /* Interleave for interleaved Planes */
__u32 visual; /* see FB_VISUAL_* */
__u16 xpanstep; /* zero if no hardware panning */
__u16 ypanstep; /* zero if no hardware panning */
__u16 ywrapstep; /* zero if no hardware ywrap */
__u32 line_length; /* length of a line in bytes */
unsigned long mmio_start; /* Start of Memory Mapped I/O */
/* (physical address) */
__u32 mmio_len; /* Length of Memory Mapped I/O */
__u32 accel; /* Indicate to driver which */
/* specific chip/card we have */
__u16 reserved[3]; /* Reserved for future compatibility */
};
备注:
fb_fix_screeninfo 结构体中的visual属性记录屏幕使用的色彩模式,在 Linux 系统中,支持的色彩模式包括如下几种。
Monochrome(FB_VISUAL_MONO01、FB_VISUAL_MONO10),每个像素是黑或白。
Pseudo color(FB_VISUAL_PSEUDOCOLOR、FB_VISUAL_STATIC_PSEUDOCOLOR),即伪彩色,采用索引颜色显示。
True color(FB_VISUAL_TRUECOLOR),真彩色,分成红、绿、蓝三基色。
Direct color(FB_VISUAL_DIRECTCOLOR),每个像素颜色也是由红、绿、蓝组成,不过每个颜色值是个索引,需要查表。
Grayscale displays,灰度显示,红、绿、蓝的值都一样。
4.fb_bitfield 结构体
fb_bitfield 结构体描述每一像素显示缓冲区的组织方式,包含位域偏移、位域长度和 MSB(最高有效位)指示,如代码清单 18.5所示。
代码清单 18.5 fb_bitfield 结构体
/* Interpretation of offset for color fields: All offsets are from the right,
* inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you
* can use the offset as right argument to <<). A pixel afterwards is a bit
* stream and is written to video memory as that unmodified. This implies
* big-endian byte order if bits_per_pixel is greater than 8.
*/
struct fb_bitfield {
__u32 offset; /* 位域偏移 */
__u32 length; /* 位域长度 */
__u32 msb_right; /*!=0: MSB 在右边 */
};
5.fb_cmap 结构体
fb_cmap 结构体记录设备无关的颜色表信息,用户空间通过 ioctl()的 FBIOGETCMAP 和FBIOPUTCMAP 命令读取或设定颜色表。
struct fb_cmap {
u32 start; /* 第 1 个元素入口 */
u32 len; /* 元素数量 */
/* R、G、B、透明度*/
u16 *red;
u16 *green;
u16 *blue;
u16 *transp;
};
6.文件操作结构体
作为一种字符设备,帧缓冲设备的文件操作结构体定义在drivers/video/fbmem.c中。如代码清单 18.8 所示。
代码清单 18.8 帧缓冲设备文件操作结构体
static const struct file_operations fb_fops = {
.owner = THIS_MODULE,
.read = fb_read,
.write = fb_write,
.ioctl = fb_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = fb_compat_ioctl,
#endif
.mmap = fb_mmap,
.open = fb_open,
.release = fb_release,
#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
.get_unmapped_area = get_fb_unmapped_area,
#endif
#ifdef CONFIG_FB_DEFERRED_IO
.fsync = fb_deferred_io_fsync,
#endif
};
分析:
帧缓冲设备驱动的文件操作接口函数在 fbmem.c 中统一实现,一般不需要驱动工程师编写。
7.注册与注销帧缓冲设备
Linux 内核提供register_framebuffer()和 unregister_framebuffer()函数分别注册和注销帧缓冲设备,这两个函数都接收 fb _ info结构体指针为参数,原型为:
linux/fb.h
int register_framebuffer(struct fb _ info *fb _ info);
int unregister_framebuffer(struct fb _ info *fb _ info);
对于 register_framebuffer()函数,如果注册的帧缓冲设备数超过FB_MAX(目前定义为32),则函数返回-ENXIO,注册成功则返回 0。
最后
以上就是贪玩睫毛膏为你收集整理的第18章LCD设备驱动之帧缓冲的全部内容,希望文章能够帮你解决第18章LCD设备驱动之帧缓冲所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复