第18章LCD设备驱动之帧缓冲

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。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值