概述
以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。
一、前言
framebuffer驱动框架包括以下两部分:
1、内核开发者实现的部分(核心层)
root@ubuntu:省略部分路径/x210_kernel/drivers/video# ls *.o built-in.o cfbfillrect.o fbcmap.o fbmem.o fb_notify.o fbsysfs.o cfbcopyarea.o cfbimgblt.o fbcvt.o fbmon.o fb.o modedb.o root@ubuntu:省略部分路径/x210_kernel/drivers/video#
通过检查内核编译结果相应目录中的.o文件,得知驱动框架核心层主要涉及的文件:
(1)drivers/video/fbmem.c(主要文件)
该文件创建graphics类,注册fb设备驱动,提供fb设备注册接口register_framebuffer。
该文件相对于fb设备,就好比misc.c文件相对于杂散类设备,其结构和分析方法类似。
(2)drivers/video/fbsysfs.c
这个文件与fb在/sys目录下的一些属性文件有关。
(3)drivers/video/modedb.c
这个文件与显示模式(比如VGA、720P等)的管理有关。
(4)drivers/video/fb_notify.c
2、驱动工程师实现的部分(操作层)
root@ubuntu:省略部分路径/x210_kernel/drivers/video# cd samsung/ root@ubuntu:省略部分路径/x210_kernel/drivers/video/samsung# ls *.o built-in.o s3cfb_fimd6x.o s3cfb.o root@ubuntu:省略部分路径/x210_kernel/drivers/video/samsung#
通过检查内核编译结果相应目录中的.o文件,得知具体操作层主要涉及的文件:
(1)drivers/video/samsung/s3cfb.c,这是驱动主要文件。
(2)drivers/video/samsung/s3cfb_fimd6x.c,里面有很多LCD硬件操作的函数。
(3)arch/arm/mach-s5pv210/mach-x210.c,负责提供platform_device。
(4)arch/arm/plat-s5p/devs.c,为platform_device提供一些硬件描述信息。
接下来,我们将对这两部分内容进行源码级别的分析。
二、fb驱动框架核心层分析
1、fbmem_init()函数
此函数位于drivers/video/fbmem.c文件中。
static int __init fbmem_init(void) { proc_create("fb", 0, NULL, &fb_proc_fops); if (register_chrdev(FB_MAJOR,"fb",&fb_fops)) printk("unable to get major %d for fb devsn", FB_MAJOR); fb_class = class_create(THIS_MODULE, "graphics"); if (IS_ERR(fb_class)) { printk(KERN_WARNING "Unable to create fb class;errno = %ldn", PTR_ERR(fb_class)); fb_class = NULL; } return 0; } #ifdef MODULE //MODULE没有定义 module_init(fbmem_init); static void __exit fbmem_exit(void) { remove_proc_entry("fb", NULL); class_destroy(fb_class); unregister_chrdev(FB_MAJOR, "fb"); } module_exit(fbmem_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Framebuffer base"); #else //MODULE没有定义,所以对于fbmem_init而言,执行的是这个 subsys_initcall(fbmem_init); #endif
(1)subsys_initcall(fbmem_init)
对于fbmem_init()函数,因为没有定义MODULE(表示以模块方式安装),因此执行的是subsys_initial(表示直接集成在内核中)。又因为是直接集成的,所以不需要卸载函数。
(2)proc_create("fb", 0, NULL, &fb_proc_fops);
fb_proc_fops和fb在proc文件系统中的表现,即cat /proc/fb的实现;
(3)register_chrdev(FB_MAJOR,"fb",&fb_fops)
利用register_chdev()函数注册fb设备,注册之后在cat /proc/devices时显示有“29 fb”。
其中,FB_MAJOR=29,而变量fb_fops的定义见下文。
(4)fb_class = class_create(THIS_MODULE, "graphics");
利用class_create()函数创建了一个名为“graphics”的类。即在/sys/class/下有graphics目录。
2、变量fb_fops
变量fb_fops定义在drivers/video/fbmem.c文件中,内容如下:
static const struct file_operations fb_fops = { .owner = THIS_MODULE, .read = fb_read, .write = fb_write, .unlocked_ioctl = fb_ioctl, //省略部分代码 };
可知其函数成员所指向的函数,分别为fb_read,fb_write,fb_ioctl。后面将讨论这些函数。
3、register_framebuffer()函数
此函数位于drivers/video/fbmem.c文件中,是fb驱动框架设计的fb设备注册接口,内容如下。
/** * register_framebuffer - registers a frame buffer device * @fb_info: frame buffer info structure * Registers a frame buffer device @fb_info. * Returns negative errno on error, or zero for success. * */ int register_framebuffer(struct fb_info *fb_info) { int i; struct fb_event event; struct fb_videomode mode; if (num_registered_fb == FB_MAX) return -ENXIO; if (fb_check_foreignness(fb_info))//判断大小端模式 return -ENOSYS; remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id, fb_is_primary_device(fb_info)); num_registered_fb++; for (i = 0 ; i < FB_MAX; i++) if (!registered_fb[i]) break; fb_info->node = i; mutex_init(&fb_info->lock); mutex_init(&fb_info->mm_lock); fb_info->dev = device_create(fb_class, fb_info->device, MKDEV(FB_MAJOR, i), NULL, "fb%d", i); if (IS_ERR(fb_info->dev)) { /* Not fatal */ printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ldn", i, PTR_ERR(fb_info->dev)); fb_info->dev = NULL; } else fb_init_device(fb_info); if (fb_info->pixmap.addr == NULL) { fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL); if (fb_info->pixmap.addr) { fb_info->pixmap.size = FBPIXMAPSIZE; fb_info->pixmap.buf_align = 1; fb_info->pixmap.scan_align = 1; fb_info->pixmap.access_align = 32; fb_info->pixmap.flags = FB_PIXMAP_DEFAULT; } } fb_info->pixmap.offset = 0; if (!fb_info->pixmap.blit_x) fb_info->pixmap.blit_x = ~(u32)0; if (!fb_info->pixmap.blit_y) fb_info->pixmap.blit_y = ~(u32)0; if (!fb_info->modelist.prev || !fb_info->modelist.next) INIT_LIST_HEAD(&fb_info->modelist); fb_var_to_videomode(&mode, &fb_info->var); fb_add_videomode(&mode, &fb_info->modelist); registered_fb[i] = fb_info; event.info = fb_info; if (!lock_fb_info(fb_info)) return -ENODEV; fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); unlock_fb_info(fb_info); return 0; }
(1)struct fb_info 结构体
此结构体的定义如下:
struct fb_info { int node; //fb_info在registered_fb数组的下标 int flags; struct mutex lock; /* Lock for open/release/ioctl funcs */ struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */ 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 */ //省略部分代码 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 */ 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; /* we need the PCI or similiar aperture base/size not smem_start/size as smem_start may just be an object allocated inside the aperture so may not actually overlap */ struct apertures_struct { unsigned int count; struct aperture { resource_size_t base; resource_size_t size; } ranges[0]; } *apertures; };
(2)fb_check_foreignness()函数
判断大小端模式。
(3)remove_conflicting_framebuffers()函数
去掉冲突的fb。
(4)device_create()函数
在/sys/class/graphic目录下创建设备?还是说创建设备文件/dev/xxx?应该是后者。
(5)fb_init_device()函数
这是fb在sys文件系统的接口函数。涉及dev_set_drvdata和dev_get_drvdata。有待深入。
(6)fb_var_to_videomode()函数
1)什么是mode?
2)fb_var_to_videomode()函数的内容
/** * fb_var_to_videomode - convert fb_var_screeninfo to fb_videomode * @mode: pointer to struct fb_videomode * @var: pointer to struct fb_var_screeninfo */ void fb_var_to_videomode(struct fb_videomode *mode, const struct fb_var_screeninfo *var) { u32 pixclock, hfreq, htotal, vtotal; mode->name = NULL; mode->xres = var->xres; mode->yres = var->yres; mode->pixclock = var->pixclock; mode->hsync_len = var->hsync_len; mode->vsync_len = var->vsync_len; mode->left_margin = var->left_margin; mode->right_margin = var->right_margin; mode->upper_margin = var->upper_margin; mode->lower_margin = var->lower_margin; mode->sync = var->sync; mode->vmode = var->vmode & FB_VMODE_MASK; mode->flag = FB_MODE_IS_FROM_VAR; mode->refresh = 0; if (!var->pixclock) return; pixclock = PICOS2KHZ(var->pixclock) * 1000; htotal = var->xres + var->right_margin + var->hsync_len + var->left_margin; vtotal = var->yres + var->lower_margin + var->vsync_len + var->upper_margin; if (var->vmode & FB_VMODE_INTERLACED) vtotal /= 2; if (var->vmode & FB_VMODE_DOUBLE) vtotal *= 2; hfreq = pixclock/htotal; mode->refresh = hfreq/vtotal; }
(7)fb_add_videomode()函数
(8)registered_fb[i] = fb_info
注册与登记该fb设备。结合fb_read等函数中对fb_info的使用。
关键点:数据如何封装、数据由谁准备由谁消费、数据如何传递。
(9)fb_notifier_call_chain()函数
待写。
最后
以上就是俏皮大神为你收集整理的framebuffer驱动详解2——fb驱动框架分析(核心层)一、前言二、fb驱动框架核心层分析的全部内容,希望文章能够帮你解决framebuffer驱动详解2——fb驱动框架分析(核心层)一、前言二、fb驱动框架核心层分析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复