Linux驱动框架之framebuffer驱动框架
Posted 涛少&
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux驱动框架之framebuffer驱动框架相关的知识,希望对你有一定的参考价值。
1、什么是framebuffer?
(1)framebuffer帧缓冲(一屏幕数据)(简称fb)是linux内核中虚拟出的一个设备,framebuffer向应用层提供一个统一标准接口的显示设备。帧缓冲(framebuffer)
是Linux为显示设备提供的一个接口,把显存抽象后的一种设备,他允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。这种操作是抽象的,统一的。用
户不必关心物理显存的位置、换页机制等等具体细节。这些都是由Framebuffer设备驱动来完成的。
(2)从驱动来看,fb是一个典型的字符设备,而且创建了一个类/sys/class/graphics
(3)framebuffer的使用
1):打开framebuffer设备文件: /dev/fb0
2):获取framebuffer设备信息 #include <linux/fb.h>
3):mmap做映射
4):填充framebuffer
FB驱动框架相关代码:drivers\\video 这个目录中
2、相关的数据结构
1 struct fb_info { // 用来描述一个fb设备的结构体 2 int node; // 用来表示该fb设备的次设备号 3 int flags; // 一个标志位 4 struct mutex lock; /* Lock for open/release/ioctl funcs */ 5 struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */ 6 struct fb_var_screeninfo var; /* Current var */ // fb的可变参数 7 struct fb_fix_screeninfo fix; /* Current fix */ // fb的不可变参数 8 struct fb_monspecs monspecs; /* Current Monitor specs */ 9 struct work_struct queue; /* Framebuffer event queue */ 10 struct fb_pixmap pixmap; /* Image hardware mapper */ 11 struct fb_pixmap sprite; /* Cursor hardware mapper */ 12 struct fb_cmap cmap; /* Current cmap */ 13 struct list_head modelist; /* mode list */ 14 struct fb_videomode *mode; /* current mode */ 15 16 #ifdef CONFIG_FB_BACKLIGHT 17 /* assigned backlight device */ 18 /* set before framebuffer registration, 19 remove after unregister */ 20 struct backlight_device *bl_dev; 21 22 /* Backlight level curve */ 23 struct mutex bl_curve_mutex; 24 u8 bl_curve[FB_BACKLIGHT_LEVELS]; 25 #endif 26 #ifdef CONFIG_FB_DEFERRED_IO 27 struct delayed_work deferred_work; 28 struct fb_deferred_io *fbdefio; 29 #endif 30 31 struct fb_ops *fbops; // 该设备对应的操作方法 open write read ..... 32 struct device *device; /* This is the parent */ // fb设备的父设备 33 struct device *dev; /* This is this fb device */ // 本设备的device 34 int class_flag; /* private sysfs flags */ 35 #ifdef CONFIG_FB_TILEBLITTING 36 struct fb_tile_ops *tileops; /* Tile Blitting */ 37 #endif 38 char __iomem *screen_base; /* Virtual address */ // 这个就是我们的LCD的显存地址(虚拟地址) 39 unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */ // LCD显存的字节大小 40 void *pseudo_palette; /* Fake palette of 16 colors */ 41 #define FBINFO_STATE_RUNNING 0 42 #define FBINFO_STATE_SUSPENDED 1 43 u32 state; /* Hardware state i.e suspend */ 44 void *fbcon_par; /* fbcon use-only private area */ 45 /* From here on everything is device dependent */ 46 void *par; 47 /* we need the PCI or similiar aperture base/size not 48 smem_start/size as smem_start may just be an object 49 allocated inside the aperture so may not actually overlap */ 50 struct apertures_struct { 51 unsigned int count; 52 struct aperture { 53 resource_size_t base; 54 resource_size_t size; 55 } ranges[0]; 56 } *apertures; 57 };
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; /* offset from virtual to visible */// 当前显存水平偏移量 7 __u32 yoffset; /* resolution */ // 当前显存垂直偏移量 8 9 __u32 bits_per_pixel; /* guess what */ // 像素深度 10 __u32 grayscale; /* != 0 Graylevels instead of colors */ 11 12 struct fb_bitfield red; /* bitfield in fb mem if true color, */ 13 struct fb_bitfield green; /* else only length is significant */ 14 struct fb_bitfield blue; 15 struct fb_bitfield transp; /* transparency */ 16 17 __u32 nonstd; /* != 0 Non standard pixel format */ 18 19 __u32 activate; /* see FB_ACTIVATE_* */ 20 21 __u32 height; /* height of picture in mm */ // LCD的物理高度mm 22 __u32 width; /* width of picture in mm */ // LCD的物理宽度mm 23 24 __u32 accel_flags; /* (OBSOLETE) see fb_info.flags */ 25 26 /* Timing: All values in pixclocks, except pixclock (of course) */ 27 __u32 pixclock; /* pixel clock in ps (pico seconds) */ // 像素时钟 28 29 // 下面这六个就是LCD的时序参数 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 ////////////////////////////////////////////////////// 37 38 __u32 sync; /* see FB_SYNC_* */ 39 __u32 vmode; /* see FB_VMODE_* */ 40 __u32 rotate; /* angle we rotate counter clockwise */ 41 __u32 reserved[5]; /* Reserved for future compatibility */ 42 };
1 struct fb_fix_screeninfo { 2 char id[16]; /* identification string eg "TT Builtin" */ 3 unsigned long smem_start; /* Start of frame buffer mem */ // LCD显存的起始地址(物理地址) 4 /* (physical address) */ 5 __u32 smem_len; /* Length of frame buffer mem */ // LCD显存的字节大小 6 __u32 type; /* see FB_TYPE_* */ // 类型 7 __u32 type_aux; /* Interleave for interleaved Planes */ 8 __u32 visual; /* see FB_VISUAL_* */ 9 __u16 xpanstep; /* zero if no hardware panning */ 10 __u16 ypanstep; /* zero if no hardware panning */ 11 __u16 ywrapstep; /* zero if no hardware ywrap */ 12 __u32 line_length; /* length of a line in bytes */ // LCD一行的长度 (以字节为单位) 13 unsigned long mmio_start; /* Start of Memory Mapped I/O */ 14 /* (physical address) */ 15 __u32 mmio_len; /* Length of Memory Mapped I/O */ 16 __u32 accel; /* Indicate to driver which */ 17 /* specific chip/card we have */ 18 __u16 reserved[3]; /* Reserved for future compatibility */ 19 };
1 struct fb_pixmap { 2 u8 *addr; /* pointer to memory */ 3 u32 size; /* size of buffer in bytes */ 4 u32 offset; /* current offset to buffer */ 5 u32 buf_align; /* byte alignment of each bitmap */ 6 u32 scan_align; /* alignment per scanline */ 7 u32 access_align; /* alignment per read/write (bits) */ 8 u32 flags; /* see FB_PIXMAP_* */ 9 u32 blit_x; /* supported bit block dimensions (1-32)*/ 10 u32 blit_y; /* Format: blit_x = 1 << (width - 1) */ 11 /* blit_y = 1 << (height - 1) */ 12 /* if 0, will be set to 0xffffffff (all)*/ 13 /* access methods */ 14 void (*writeio)(struct fb_info *info, void __iomem *dst, void *src, unsigned int size); 15 void (*readio) (struct fb_info *info, void *dst, void __iomem *src, unsigned int size); 16 };
1 struct fb_videomode { 2 const char *name; /* optional */ 3 u32 refresh; /* optional */ 4 u32 xres; 5 u32 yres; 6 u32 pixclock; 7 u32 left_margin; 8 u32 right_margin; 9 u32 upper_margin; 10 u32 lower_margin; 11 u32 hsync_len; 12 u32 vsync_len; 13 u32 sync; 14 u32 vmode; 15 u32 flag; 16 };
1 struct fb_ops { // 这个fb_ops 就是我们fb设备的使用的 fops 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); 6 7 /* For framebuffers with strange non linear layouts or that do not 8 * work with normal memory mapped access 9 */ 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); 14 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); 18 19 /* set the video mode according to info->var */ 20 int (*fb_set_par)(struct fb_info *info); 21 22 /* set color register */ 23 int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green, 24 unsigned blue, unsigned transp, struct fb_info *info); 25 26 /* set color registers in batch */ 27 int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info); 28 29 /* blank display */ 30 int (*fb_blank)(int blank, struct fb_info *info); 31 32 /* pan display */ 33 int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info); 34 35 /* Draws a rectangle */ 36 void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect); 37 /* Copy data from area to another */ 38 void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region); 39 /* Draws a image to the display */ 40 void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image); 41 42 /* Draws cursor */ 43 int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor); 44 45 /* Rotates the display */ 46 void (*fb_rotate)(struct fb_info *info, int angle); 47 48 /* wait for blit idle, optional */ 49 int (*fb_sync)(struct fb_info *info); 50 51 /* perform fb specific ioctl (optional) */ 52 int (*fb_ioctl)(struct fb_info *info, unsigned int cmd, 53 unsigned long arg); 54 55 /* Handle 32bit compat ioctl (optional) */ 56 int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd, 57 unsigned long arg); 58 59 /* perform fb specific mmap */ 60 int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma); 61 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); 65 66 /* teardown any resources to do with this framebuffer */ 67 void (*fb_destroy)(struct fb_info *info); 68 };
2、framebuffer驱动框架的初始化函数:fbmem_init(drivers\\video\\fbmem.c)
framebuffer驱动框架部分的代码与前面说的misc驱动框架和led驱动框架一样,都是实现为一个模块的形式,可以在内核配置的时候进行动态的加载和卸载,模块的好处之前已经说过。
fbmem_init函数代码分析:
1 static int __init 2 fbmem_init(void) 3 { 4 proc_create("fb", 0, NULL, &fb_proc_fops); // 在proc文件系统中建立一个名为 fb 的目录 5 6 if (register_chrdev(FB_MAJOR,"fb",&fb_fops)) // 注册字符设备 fb 主设备号29 fb_fops 7 printk("unable to get major %d for fb devs\\n", FB_MAJOR); 8 9 fb_class = class_create(THIS_MODULE, "graphics"); // 创建设备类 /sys/class/graphics 10 if (IS_ERR(fb_class)) { 11 printk(KERN_WARNING "Unable to create fb class; errno = %ld\\n", PTR_ERR(fb_class)); 12 fb_class = NULL; 13 } 14 return 0; 15 }
(1)fb_fops变量
fb_fops是一个struct file_operations结构体类型的变量,这个结构体不是什么新鲜玩样了,framebuffer驱动框架中注册的这个file_operations结构体内容如下:
(2)对fb_fops结构体中的fb_open函数分析:
fb_open(struct inode *inode, struct file *file) (以下层次为函数的调用关系)
int fbidx = iminor(inode); // 通过inode指针获取设备的次设备号
struct fb_info *info;
info = registered_fb[fbidx]; // 找到以次设备号为下标的数组项
info->fbops->fb_open(info,1); // 调用info指向的fb_info结构体中的fb_ops结构体中的open函数(注意:fbops指针是一个fb_ops类型的结构体指针,上面说的fb_fops 是file_operations类型的结构体的变量)
1):注意:上面分析的只是open函数,那么其他的函数也是一样的原理,最终都会调用到驱动编写者向框架注册的fb_info结构体中的fb_fops中封装的函数。
2):从这里可以看出来fb的驱动框架注册的file_operations与之前讲的misc驱动框架中注册file_operations有所不同,他们的不同主要两个:
a、misc中注册的file_operations结构体中只有open函数,都是通过这个open函数获取设备的file_operations;而fb驱动框架中注册的file_operations结构体中基本函数都实现了,
真正驱动中的不同的函数是通过这个结构体中对应的函数内部进行转换的。
b、misc驱动框架下的具体驱动的操作函数也是封装在一个file_operations结构体变量中,当然这个变量是在struct miscdevice结构体中包含的;而fb驱动框架下的具体的驱动的
操作函数是封装在一个fb_ops类型的结构体变量中的,是包含在fb_info结构体中,随着fb_info变量的注册而向驱动框架注册。
3、驱动框架留给驱动工程师的接口:register_framebuffer/unregister_framebuffer(drivers\\video\\fbmem.c)
驱动框架代码是不涉及到具体的硬件操作的,主要是软件逻辑,提供服务性的代码。驱动工程师需要调用驱动框架提供的接口函数来向驱动框架注册驱动、设备。
struct fb_info结构体是驱动编写者利用fb驱动框架来编写fb驱动时需要提供的一个结构体,内部封装了很多的信息,包括LCd的硬件信息,像素、像素深度、尺寸大小等等。
其中重要的有struct fb_fix_screeninfo(可变参数)、struct fb_var_screeninfo(不可变参数)、struct fb_videomode(显示模式:显示分辨率、刷新率等的)、struct fb_ops(
这个结构体封装了open、read、write....等应用层对应到驱动的函数)。
(2)register_framebuffer函数
1 int 2 register_framebuffer(struct fb_info *fb_info) 3 { 4 int i; 5 struct fb_event event; // 定义一个fb_event 变量 6 struct fb_videomode mode; // 定义一个fb_videomode 变量 7 8 if (num_registered_fb == FB_MAX) // 如果当前注册的fb设备的数量已经满了,则不能在进行注册了 最大值32 9 return -ENXIO; 10 11 if (fb_check_foreignness(fb_info)) // 校验 12 return -ENOSYS; 13 14 remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id, // 防冲突检查 15 fb_is_primary_device(fb_info)); 16 17 num_registered_fb++; // 当前注册的设备数量 + 1 18 for (i = 0 ; i < FB_MAX; i++) // registered_fb 是fb驱动框架维护的一个用来管理记录fb设备的数组, 里面的元素就是 fb_info 指针,一个fb_info就代表一个fb设备 19 if (!registered_fb[i]) // 找到一个最小的没有被使用的次设备号 20 break; 21 fb_info->node = i; // 将次设备号存放在 fb_info->node 中 22 mutex_init(&fb_info->lock); 23 mutex_init(&fb_info->mm_lock); 24 25 fb_info->dev = device_create(fb_class, fb_info->device, // 创建设备 名字: fb+次设备号 26 MKDEV(FB_MAJOR, i), NULL, "fb%d", i); 27 if (IS_ERR(fb_info->dev)) { 28 /* Not fatal */ 29 printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\\n", i, PTR_ERR(fb_info->dev)); 30 fb_info->dev = NULL; 31 } else 32 fb_init_device(fb_info); // 初始化fb设备 33 34 if (fb_info->pixmap.addr == NULL) { // pixmap 相关的设置 35 fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL); 36 if (fb_info->pixmap.addr) { 37 fb_info->pixmap.size = FBPIXMAPSIZE; 38 fb_info->pixmap.buf_align = 1; 39 fb_info->pixmap.scan_align = 1; 40 fb_info->pixmap.access_align = 32; 41 fb_info->pixmap.flags = FB_PIXMAP_DEFAULT; 42 } 43 } 44 fb_info->pixmap.offset = 04 linux lcd驱动框架分析Linux 帧缓冲子系统详解:LCD介绍framebuffer驱动框架LCD驱动源码分析