Linux Framebuffer(二) -- 驱动框架

  • 了解Linux Framebuffer的驱动框架

1.Framebuffer 驱动位置
在这里插入图片描述  对于驱动开发人员来说,其实只需要针对具体的硬件平台SOC和具体的LCD(焊接连接到该SOC的引脚上)来进行第一部分的寄存器编程(红色部分)。而第二、三、四部分内容(绿色部分)已经被抽象并实现在Linux driver发布源码中了,LCD驱动开发人员只需要理解framebuffer内部的框架和接口使用即可。
在这里插入图片描述

2.Framebuffer的驱动框架
在这里插入图片描述

  帧缓冲设备为标准的字符型设备,在Linux中主设备号29,定义在/include/linux/major.h中的FB_MAJOR,次设备号定义帧缓冲的个数,最大允许有32个FrameBuffer,定义在/include/linux/fb.h中的FB_MAX,对应于文件系统下/dev/fb%d设备文件。
在这里插入图片描述

  在嵌入式系统中一般没有专门的显存,而仅仅是从RAM(SDRAM)空间中分配一段显示缓冲区,典型结构如下图所示:
在这里插入图片描述

2.Framebuffer 相关的重要数据结构

  从Framebuffer设备驱动程序结构看,该驱动主要跟fb_info结构体有关,该结构体记录了Framebuffer设备的全部信息,包括设备的设置参数、状态以及对底层硬件操作的函数指针。在Linux中,每一个Framebuffer设备都必须对应一个fb_info,fb_info在/linux/fb.h中的定义如下:

2.1.struct fb_info

 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 代表可修改的LCD显示参数,如分辨率和像素比特数;
  • fb_fix_screeninfo 代表不可修改的LCD属性参数,如显示内存的物理地址和长度等。
  • fb_ops,其是LCD底层硬件操作接口集。
    fb_ops硬件操作接口集包含很多接口,如设置可变参数fb_set_par、设置颜色寄存器fb_setcolreg、清屏接口fb_blank、画位图接口fb_imageblit、内存映射fb_mmap等等。

  These structures are fb_var_screeninfo, fb_fix_screeninfo, fb_cmap, and fb_info. The first three are made available to and from user space code.struct fb_info structure should always be allocated dynamically, using framebuffer_alloc(),which is a kernel (framebuffer core) helper functions to allocate memory for instance of framebuffer devices, along with their private data memory:

struct fb_info *framebuffer_alloc(size_t size, struct device *dev);
void framebuffer_release(struct fb_info *info)

  fb_info结构体在调用register_framebuffer之前完成初始化。一般来说,LCD设备属于平台设备,其初始化是在平台设备驱动的probe接口完成。而LCD设备所涉及的硬件初始化则在平台设备初始化中完成。

2.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 };

2.3.struct 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中涉及的时序理解更清楚一些:
在这里插入图片描述

2.4.fb_ops结构体

  对底层硬件操作的函数指针,该结构体中定义了对硬件的操作有:

 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 };

   fb_ops结构与file_operations 结构不同,fb_ops是底层操作的抽象,而file_operations是提供给上层系统调用的接口,可以直接调用。

2.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;           //透明度,允许为空
};

这些结构相互之间的关系如下所示:在这里插入图片描述

3.Framebuffer模块初始化

3.1.初始化Framebuffer

  FrameBuffer驱动是以模块的形式注册到系统中,在模块初始化时,创建FrameBuffer对应的设备文件及proc文件,并注册FrameBuffer设备操作接口函数fb_fops。

static int __init  fbmem_init(void)
{
    proc_create("fb", 0, NULL, &fb_proc_fops);///向 proc 文件系统报告驱动状态和参数
    if (register_chrdev(FB_MAJOR,"fb",&fb_fops))///注册字符设备驱动,主设备号是29 
        printk("unable to get major %d for fb devs\n", FB_MAJOR);
        
    fb_class = class_create(THIS_MODULE, "graphics");///创建 /sys/class/graphics 设备类,配合 mdev生成设备文件
    if (IS_ERR(fb_class)) {
        printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));
        fb_class = NULL;
    }
    return 0;
}

  Framebuffer作为一个子系统,在fbmem_init中通过register_chrdev接口向系统注册一个主设备号位29的字符设备驱动。通过class_create创建graphics设备类,配合mdev机制生成供用户访问的设备文件(位于/dev目录)。

3.2.Framebuffer设备驱动的接口集fb_fops的定义为:

static const struct file_operations fb_fops = {
    .owner =    THIS_MODULE,
    .read =        fb_read,
    .write =    fb_write,//二次拷贝
    .unlocked_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
    .llseek =    default_llseek,
};

3.3. 注册Framebuffer

  linux 提供了register_framebuffer()和unregister_framebuffer()函数分别作为注册和注销帧缓冲设备,这两个函数都接受fb_info指针为参数,原型为:

int register_framebuffer(struct fb_info  *fb_info);
int Unregister_framebuffer(struct fb_info  *fb_info);

  对于register_framebuffer()而言,如果注册的帧缓冲设备超过了FB_MAX(目前定义为32),则返回为-ENXIO,注册成功则返回为0。

发布了161 篇原创文章 · 获赞 15 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_41028621/article/details/103614398
今日推荐