Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2968904
  • 博文数量: 685
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 5303
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-19 14:17
个人简介

文章分类

全部博文(685)

文章存档

2015年(116)

2014年(569)

分类: Android平台

2014-09-20 14:25:15

原文地址:http://blog.chinaunix.net/uid-26009923-id-4040712.html

一.framebuffer的初始化
1. 以s3cfb的注册过程说明
module_init(s3cfb_init);
   --> platform_driver_register(&s3cfb_driver);
         --> s3cfb_probe(struct platform_device *pdev)
 在drivers/video/samsung/s3cfb.c中
  1. static int __init s3cfb_probe(struct platform_device *pdev)
  2. {
  3.     //第一步为framebuffer分配空间
  4.     struct fb_info *fbinfo = framebuffer_alloc(sizeof(s3cfb_info_t), &pdev->dev);
  5.     //第二步初始化fbinfo 
  6.     ....
  7.     .... 
  8.     //第三步注册framebuffer
  9.     ret = register_framebuffer(&s3cfb_info[index].fb);
  10. }
2. framebuffer_alloc过程
在drivers/video/fbsysfs.c中,
主要作用就是: 申请内存,并略微初始化fb_info结构体,主要的初始化是在s3c_probe函数中
  1. struct fb_info *framebuffer_alloc(size_t size, struct device *dev)
  2. {
  3.     int fb_info_size = sizeof(struct fb_info);
  4.     struct fb_info *info;
  5.     fb_info_size += PADDING;    //为了对齐
  6.     //申请内存,并清零
  7.     info = (struct fb_info *) kzalloc(fb_info_size + size, GFP_KERNEL);
  8.     info->par = p + fb_info_size;
  9.     //device指针保存dev
  10.     info->device = dev;
  11.     return info;
  12. }
3. register_framebuffer过程
在drivers/video/fbmem.c中
主要作用是:
     1. 在全局变量数组registered_fb中查找未使用的一项,把找到的这个项号保存在fb_info中
     2. 在/dev/graphics/fb目录下创建设备结点, /dev/graphics/fb0 ls /dev/graphics/fb1就产生了
     3. 将fb_info添加到全局数组registered_fb中,并发送msg,说明注册完成
  1. int register_framebuffer(struct fb_info *fb_info)
  2. {
  3.     int i;
  4.     struct fb_event event;
  5.     struct fb_videomode mode;

  6.     if (num_registered_fb == FB_MAX)
  7.         return -ENXIO;

  8.     if (fb_check_foreignness(fb_info))
  9.         return -ENOSYS;

  10.     remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id, fb_is_primary_device(fb_info));

  11.     num_registered_fb++;
  12.     for (= 0 ; i < FB_MAX; i++)   //1.1在数组registered_fb中搜索没有使用的一项来注册
  13.         if (!registered_fb[i])
  14.             break;
  15.     fb_info->node = i;              //1.2这个i值很重要,以后open(/dev/fb0),后面的0,1,2就是这个i
  16.     mutex_init(&fb_info->lock);
  17.     mutex_init(&fb_info->mm_lock);
  18.     //2.在"/dev/grapihc"下创建fb[i]设备文件,fb_class="/dev/graphic"
  19.     fb_info->dev = device_create(fb_class, fb_info->device, MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
  20.     fb_init_device(fb_info);   //在/sys/device目录下创建/sys文件
  21.     if (fb_info->pixmap.addr == NULL) {
  22.         fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
  23.         if (fb_info->pixmap.addr) {
  24.             fb_info->pixmap.size = FBPIXMAPSIZE;
  25.             fb_info->pixmap.buf_align = 1;
  26.             fb_info->pixmap.scan_align = 1;
  27.             fb_info->pixmap.access_align = 32;
  28.             fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;
  29.         }
  30.     }
  31.     fb_info->pixmap.offset = 0;

  32.     if (!fb_info->pixmap.blit_x)
  33.         fb_info->pixmap.blit_x = ~(u32)0;

  34.     if (!fb_info->pixmap.blit_y)
  35.         fb_info->pixmap.blit_y = ~(u32)0;

  36.     if (!fb_info->modelist.prev || !fb_info->modelist.next)
  37.         INIT_LIST_HEAD(&fb_info->modelist);

  38.     fb_var_to_videomode(&mode, &fb_info->var);
  39.     fb_add_videomode(&mode, &fb_info->modelist);
  40.     registered_fb[i] = fb_info;                  //3.将初始化了的fb_info加到全局变量中

  41.     event.info = fb_info;
  42.     if (!lock_fb_info(fb_info))
  43.         return -ENODEV;
  44.     fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
  45.     unlock_fb_info(fb_info);
  46.     return 0;
  47. }
这样就注册好了framebuffer,有了/dev/graphics/fb0,但是文件操作在哪儿呢?
二.上层调用 open /dev/graphics/fb0时
通过register_framebuffer产生了设备文件/dev/graphics/fb0,但是open /dev/graphics/fb0时的文件操作是如何产生的呢?
看一下drivers/video/fbmem.c的注册过程就知道了.
module_init(fbmem_init)
    --> fbmem_init
  1. static int __init fbmem_init(void)
  2. {
  3.     proc_create("fb", 0, NULL, &fb_proc_fops);     //创建/proc/fb
  4.     register_chrdev(FB_MAJOR,"fb",&fb_fops);       //注册字符设备文件
  5.    //创建class=/dev/graphics",以后用device_create创建的设备文件都会在/dev/graphics目录下
  6.     fb_class = class_create(THIS_MODULE, "graphics");  
  7.     return 0;
  8. }

注册的文件操作结构体是fb_fops
  1. static const struct file_operations fb_fops = {
  2.     .owner =    THIS_MODULE,
  3.     .mmap =        fb_mmap,
  4.     .open =        fb_open,
  5.     .... //省略   
  6. };

上层调用open /dev/graphics/fb0时,会先调用fb_open函数
  1. static int fb_open(struct inode *inode, struct file *file)
  2. __acquires(&info->lock)
  3. __releases(&info->lock)
  4. {
  5.     //从inode中获取次设备号,来判断是哪个fb,并将次设备号转为索引值
  6.     int fbidx = iminor(inode);   
  7.     struct fb_info *info;
  8.     int res = 0;

  9.     if (fbidx >= FB_MAX)
  10.         return -ENODEV;
  11.     info = registered_fb[fbidx];  //通过索引值找在全局数组中找到fb
  12.     if (!info)
  13.         request_module("fb%d", fbidx);
  14.     info = registered_fb[fbidx];  //通过索引值找在全局数组中找到fb
  15.     if (!info)                    //为什么要调两次?
  16.         return -ENODEV;
  17.     mutex_lock(&info->lock);
  18.     if (!try_module_get(info->fbops->owner)) {  //模块引用计数加1 
  19.         res = -ENODEV;
  20.         goto out;
  21.     }
  22.     file->private_data = info;
  23.     if (info->fbops->fb_open) {              //如果fb0有open函数则调用fb0的open
  24.         res = info->fbops->fb_open(info,1);
  25.         if (res)
  26.             module_put(info->fbops->owner);
  27.     }
  28. #ifdef CONFIG_FB_DEFERRED_IO
  29.     if (info->fbdefio)
  30.         fb_deferred_io_open(info, inode, file);
  31. #endif
  32. out:
  33.     mutex_unlock(&info->lock);
  34.     return res;
  35. }

阅读(630) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~