关键词: android  camera CMM 模组 camera参数  CAMIF   V4L2  
平台信息:
内核: linux
系统: android

平台:S5PV310(samsung exynos 4210)

作者:xubin341719(欢迎转载,请注明作者)

android camera(一):camera模组CMM介绍

android camera(二):摄像头工作原理、s5PV310 摄像头接口(CAMIF)

android camera(三):camera V4L2 FIMC

android camera(四):camera 驱动 GT2005

下载:常用摄像头规格书(个别有android驱动程序)  :bf3703 30W、gc0308 30W、ov7670、gt2005 200W、gt2015 200W、NT99250 200W、s5k5ba 200W、s5k4ba

前面两篇说的有点多了,不过多了解点东西也挺好的,遇到问题时可以有更多的思路,真正驱动是从这一块开始。一般BSP的camera都是完好的,我们只用关心驱动这些就可以了。

1. V4L2

1)简介

在Linux中,摄像头方面的标准化程度比较高,这个标准就是V4L2驱动程序,这也是业界比较公认的方式。

V4L全称是Video for Linux,是Linux内核中标准的关于视频驱动程序,目前使用比较多的版本是Video for Linux 2,简称V4L2。它为Linux下的视频驱动提供了统一的接口,使得应用程序可以使用统一的API操作不同的视频设备。从内核空间到用户空间,主要的数据流和控制类均由V4L2驱动程序的框架来定义。

V4L2驱动程序一般只提供Video数据的获得,而如何实现视频预览,如何向上层发送数据,如何把纯视频流和取景器、视频录制等实际业务组织起来,都是camera的硬件抽象层需要负责的工作。

V4L2驱动核心实现为如下文件:drivers/media/video/v4l2-dev.c。

V4l2-dev.h中定义的video_device是V4L2驱动程序的核心数据结构,它为具体的摄像头sensor驱动提供了接口调用。

V4l2的采集过程(应用程序):

1)     打开设备,获得文件描述符;

2)     设置图片格式;

3)     分配缓冲区;

4)     启动采集过程,读取数据;

5)     停止采集,关闭设备。

2)数据结构

V4L2的主要数据结构是video_device,定义在v4l2_dev.h中:

[cpp] view plaincopy
  1. struct video_device
  2. {
  3. /* device ops */
  4. const struct v4l2_file_operations *fops;  /*接口函数指针*/
  5. /* sysfs */
  6. struct device dev;      /* v4l 设备结构 */
  7. struct cdev *cdev;      /* 字符设备结构*/
  8. /* Set either parent or v4l2_dev if your driver uses v4l2_device */
  9. struct device *parent;      /* 设备父指针 */
  10. struct v4l2_device *v4l2_dev;   /* v4l2设备指针*/
  11. /* device info */
  12. char name[32];  /*设备名称*/
  13. int vfl_type;
  14. /* 'minor' is set to -1 if the registration failed */
  15. int minor;    /*次设备号*/
  16. u16 num;
  17. /* use bitops to set/clear/test flags */
  18. unsigned long flags;
  19. /* attribute to differentiate multiple indices on one physical device */
  20. int index;
  21. /* V4L2 file handles */
  22. spinlock_t      fh_lock; /* Lock for all v4l2_fhs */
  23. struct list_head    fh_list; /* List of struct v4l2_fh */
  24. int debug;          /* debug 级别*/
  25. /* Video 标准变量 */
  26. v4l2_std_id tvnorms;        /* Supported tv norms */
  27. v4l2_std_id current_norm;   /* Current tvnorm */
  28. /* 回调函数 */
  29. void (*release)(struct video_device *vdev);
  30. /* ioctl 回调函数 */
  31. const struct v4l2_ioctl_ops *ioctl_ops;
  32. };

主要接口函数有:

intvideo_register_device(struct video_device *vdev, int type, int nr);

static intv4l2_ioctl(struct inode *inode, struct file *filp,       unsigned int cmd, unsigned long arg);

2.  FIMC                     

1)简介

FIMC这个模块不仅仅是一个摄像头的控制接口,它还承担着V4L2的output功能和overlay的功能。

FIMC的驱动在内核中的位置:drivers/media/video/samsung/fimc

它包含下边的文件:

fimc_regs.c
        fimc_capture.c
        fimc_dev.c
        fimc_output.c
        fimc_overlay.c
        fimc_v4l2.c

它们的组织关系如下:

可以看到,FIMC的驱动实现了v4l2所有的接口,可以分为v4l2-input设备接口,v4l2-output设备接口以及v4l2-overlay设备接口。这里我们主要关注v4l2-input设备接口,因为摄像头属于视频输入设备。

fimc_v4l2.c里面注册了很多的回调函数,都是用于实现v4l2的标准接口的,但是这些回调函数基本上都不是在fimc_v4l2.c里面实现的,而是有相应的.c分别去实现。比如:

v4l2-input设备的操作实现:fimc_capture.c
        v4l2-output设备的操作实现: fimc_output.c
        v4l2-overlay设备的操作实现: fimc_overlay.c

这些代码其实都是和具体硬件操作无关的,这个驱动把所有操作硬件寄存器的代码都写到一个文件里面了,就是fimc40_regs.c。这样把硬件相关的代码和硬件无关的代码分开来实现是非常好的方式,可以最大限度的实现代码复用。

 2) 数据结构 

FIMC的主要数据结构fimc_control,定义在fimc.h中:

[cpp] view plaincopy
  1. struct fimc_control {
  2. int             id;     /* 控制器 id */
  3. char                name[16];
  4. atomic_t            in_use;
  5. void __iomem            *regs;      /* 寄存器 i/o */
  6. struct clk          *clk;       /* interface clock */
  7. struct regulator    *regulator;     /* pd regulator */
  8. struct fimc_meminfo     mem;        /* for reserved mem */
  9. /* kernel helpers */
  10. struct mutex            lock;       /* controller lock */
  11. struct mutex            alloc_lock;
  12. struct mutex            v4l2_lock;
  13. wait_queue_head_t       wq;
  14. struct device           *dev;
  15. int             irq;
  16. /* v4l2 related */
  17. struct video_device     *vd;
  18. struct v4l2_device      v4l2_dev;
  19. /* fimc specific */
  20. struct fimc_limit       *limit;     /* H/W limitation */
  21. struct s3c_platform_camera  *cam;       /* activated camera */
  22. struct fimc_capinfo     *cap;       /* capture dev info */
  23. struct fimc_outinfo     *out;       /* output dev info */
  24. struct fimc_fbinfo      fb;     /* fimd info */
  25. struct fimc_scaler      sc;     /* scaler info */
  26. struct fimc_effect      fe;     /* fimc effect info */
  27. enum fimc_status        status;
  28. enum fimc_log           log;
  29. u32             ctx_busy[FIMC_MAX_CTXS];
  30. };

因为FIMC 一共有三套一样的控制器(fimc0, fimc1, fimc2),所以驱动里使用了一个数组来描述:

[cpp] view plaincopy
  1. struct video_device fimc_video_device[FIMC_DEVICES] = {
  2. [0] = {
  3. .fops = &fimc_fops,
  4. .ioctl_ops = &fimc_v4l2_ops,
  5. .release = fimc_vdev_release,
  6. },
  7. [1] = {
  8. .fops = &fimc_fops,
  9. .ioctl_ops = &fimc_v4l2_ops,
  10. .release = fimc_vdev_release,
  11. },
  12. [2] = {
  13. .fops = &fimc_fops,
  14. .ioctl_ops = &fimc_v4l2_ops,
  15. .release = fimc_vdev_release,
  16. },
  17. };

fb_ops结构体是针对v4l2设备的基本操作,定义如下:

[cpp] view plaincopy
  1. static const struct v4l2_file_operations fimc_fops = {
  2. .owner      = THIS_MODULE,
  3. .open       = fimc_open,
  4. .release    = fimc_release,
  5. .ioctl      = video_ioctl2,
  6. .read       = fimc_read,
  7. .write      = fimc_write,
  8. .mmap       = fimc_mmap,
  9. .poll       = fimc_poll,
  10. };

3)FIMC初始设置

在S5PV210中,FIMC初始设置代码在 /drivers/ arch/arm/mach-s5pv210/mach-smdkv310.c中:

[cpp] view plaincopy
  1. static struct s3c_platform_fimc fimc_plat = {
  2. .srclk_name = "mout_mpll",
  3. .clk_name   = "sclk_fimc",
  4. .lclk_name  = "sclk_fimc_lclk",
  5. .clk_rate   = 166750000,
  6. .default_cam    = CAMERA_CSI_C,
  7. .camera        = {
  8. &mt9p111,//5M back cam
  9. &s5k6aafx,///1.3M front cam
  10. },
  11. .hw_ver     = 0x43,
  12. };

对于GPIO的配置代码在 /drivers/ arch/arm/mach-s5pv210/setup-fimc0.c中:

[cpp] view plaincopy
  1. oid s3c_fimc0_cfg_gpio(struct platform_device *pdev)
  2. {
  3. int i = 0;
  4. /* CAM A port(b0010) : PCLK, VSYNC, HREF, DATA[0-4] */
  5. for (i = 0; i < 8; i++) {
  6. s3c_gpio_cfgpin(S5PV210_GPE0(i), S3C_GPIO_SFN(2));
  7. s3c_gpio_setpull(S5PV210_GPE0(i), S3C_GPIO_PULL_NONE);
  8. }
  9. /* CAM A port(b0010) : DATA[5-7], CLKOUT(MIPI CAM also), FIELD */
  10. for (i = 0; i < 5; i++) {
  11. s3c_gpio_cfgpin(S5PV210_GPE1(i), S3C_GPIO_SFN(2));
  12. s3c_gpio_setpull(S5PV210_GPE1(i), S3C_GPIO_PULL_NONE);
  13. }
  14. /* CAM B port(b0011) : DATA[0-7] */
  15. for (i = 0; i < 8; i++) {
  16. s3c_gpio_cfgpin(S5PV210_GPJ0(i), S3C_GPIO_SFN(3));
  17. s3c_gpio_setpull(S5PV210_GPJ0(i), S3C_GPIO_PULL_NONE);
  18. }
  19. /* CAM B port(b0011) : PCLK, VSYNC, HREF, FIELD, CLCKOUT */
  20. for (i = 0; i < 5; i++) {
  21. s3c_gpio_cfgpin(S5PV210_GPJ1(i), S3C_GPIO_SFN(3));
  22. s3c_gpio_setpull(S5PV210_GPJ1(i), S3C_GPIO_PULL_NONE);
  23. }
  24. }

4)接口函数

FIMC的主要回调函数如下,实现在fimc_v4l2.c中:

[cpp] view plaincopy
  1. onst struct v4l2_ioctl_ops fimc_v4l2_ops = {
  2. .vidioc_querycap        = fimc_querycap,
  3. .vidioc_reqbufs         = fimc_reqbufs,
  4. .vidioc_querybuf        = fimc_querybuf,
  5. .vidioc_g_ctrl          = fimc_g_ctrl,
  6. .vidioc_s_ctrl          = fimc_s_ctrl,
  7. .vidioc_s_ext_ctrls     = fimc_s_ext_ctrls,
  8. .vidioc_cropcap         = fimc_cropcap,
  9. .vidioc_g_crop          = fimc_g_crop,
  10. .vidioc_s_crop          = fimc_s_crop,
  11. .vidioc_streamon        = fimc_streamon,
  12. .vidioc_streamoff       = fimc_streamoff,
  13. .vidioc_qbuf            = fimc_qbuf,
  14. .vidioc_dqbuf           = fimc_dqbuf,
  15. .vidioc_enum_fmt_vid_cap    = fimc_enum_fmt_vid_capture,
  16. .vidioc_g_fmt_vid_cap       = fimc_g_fmt_vid_capture,
  17. .vidioc_s_fmt_vid_cap       = fimc_s_fmt_vid_capture,
  18. .vidioc_try_fmt_vid_cap     = fimc_try_fmt_vid_capture,
  19. .vidioc_enum_input      = fimc_enum_input,
  20. .vidioc_g_input         = fimc_g_input,
  21. .vidioc_s_input         = fimc_s_input,
  22. .vidioc_g_parm          = fimc_g_parm,
  23. .vidioc_s_parm          = fimc_s_parm,
  24. .vidioc_queryctrl       = fimc_queryctrl,
  25. .vidioc_querymenu       = fimc_querymenu,
  26. .vidioc_g_fmt_vid_out       = fimc_g_fmt_vid_out,
  27. .vidioc_s_fmt_vid_out       = fimc_s_fmt_vid_out,
  28. .vidioc_try_fmt_vid_out     = fimc_try_fmt_vid_out,
  29. .vidioc_g_fbuf          = fimc_g_fbuf,
  30. .vidioc_s_fbuf          = fimc_s_fbuf,
  31. .vidioc_try_fmt_vid_overlay = fimc_try_fmt_overlay,
  32. .vidioc_g_fmt_vid_overlay   = fimc_g_fmt_vid_overlay,
  33. .vidioc_s_fmt_vid_overlay   = fimc_s_fmt_vid_overlay,
  34. };

对于寄存器的操作,实现都在fimc_regs.c文件中,如

[cpp] view plaincopy
  1. int fimc_hwset_camera_source(struct fimc_control *ctrl)
  2. {
  3. struct s3c_platform_camera *cam = ctrl->cam;
  4. u32 cfg = 0;
  5. cfg |= S3C_CISRCFMT_ITU601_8BIT;
  6. cfg |= cam->order422;
  7. if (cam->type == CAM_TYPE_ITU)
  8. cfg |= cam->fmt;
  9. cfg |= S3C_CISRCFMT_SOURCEHSIZE(cam->width);
  10. cfg |= S3C_CISRCFMT_SOURCEVSIZE(cam->height);
  11. writel(cfg, ctrl->regs + S3C_CISRCFMT);
  12. return 0;
  13. }
  14. int fimc_hwset_enable_irq(struct fimc_control *ctrl, int overflow, int level)
  15. {
  16. u32 cfg = readl(ctrl->regs + S3C_CIGCTRL);
  17. cfg &= ~(S3C_CIGCTRL_IRQ_OVFEN | S3C_CIGCTRL_IRQ_LEVEL);
  18. cfg |= S3C_CIGCTRL_IRQ_ENABLE;
  19. if (overflow)
  20. cfg |= S3C_CIGCTRL_IRQ_OVFEN;
  21. if (level)
  22. cfg |= S3C_CIGCTRL_IRQ_LEVEL;
  23. writel(cfg, ctrl->regs + S3C_CIGCTRL);
  24. return 0;
  25. }

android camera(三):camera V4L2 FIMC相关推荐

  1. Android Camera 三 CameraService 和 Client 链接到 HAL

    Android Camera 一 源码路径 Android Camera 二 JNI JAVA和C/CPP图像数据传输流程分析 Android Camera 三 CameraService 和 Cli ...

  2. Android Studio:使用Camera拍照(三)为相机增加取景蒙板/浮层

    写在前面的话:每一个实例的代码都会附上相应的代码片或者图片,保证代码完整展示在博客中.最重要的是保证例程的完整性!!!方便自己也方便他人~欢迎大家交流讨论~本文为博主原创文章,未经博主允许不得转载. ...

  3. android 驱动之 camera 驱动 GT2005

    关键词:Android  camera CMM 模组 camera参数  GT2005 摄像头常见问题 平台信息: 内核:linux 系统:android 平台:S5PV310(samsung exy ...

  4. 解读Android 4.0 Camera原生应用程序的设计思路

    解读Android 4.0 Camera原生应用程序的设计思路 一篇很不错的文章: http://my.oschina.net/jerikc/blog/90791 1. 设置摄像头方向 2. 打开线程 ...

  5. Android Camera 五 Camera HAL v1

    Android Camera 一 源码路径 Android Camera 二 JNI JAVA和C/CPP图像数据传输流程分析 Android Camera 三 CameraService 和 Cli ...

  6. Android Camera 四 Camera HAL 分析

    Android Camera 一 源码路径 Android Camera 二 JNI JAVA和C/CPP图像数据传输流程分析 Android Camera 三 CameraService 和 Cli ...

  7. [Android编程心得] Camera(OpenCV)自动对焦和触摸对焦的实现

    http://blog.csdn.net/candycat1992/article/details/21617741 实现 以OpenCV的JavaCameraView为例,首先需要定制自己的Came ...

  8. Android中使用Camera类编写手机拍照App的实例教程

    Camera是Android摄像头硬件的相机类,位于硬件包"android.hardware.Camera"下.它主要用于摄像头捕获图片.启动/停止预览图片.拍照.获取视频帧等,它 ...

  9. android 自定义相机Camera

    转载请标明来自:http://blog.csdn.net/qq_38416326/article/details/70809754 项目中,有时系统的相机不能满足我们的需求,例如:实现美图,这样就需要 ...

最新文章

  1. About Firefox
  2. Vue第三部分(2):Vue-CLI构建前后端分离项目以及打包部署
  3. ES6一些常用的基本语法
  4. 国内git clone报错问题解决办法
  5. python零基础能学吗-Python编程语言好学吗?零基础转行能学Python吗?
  6. 使用表单传递参数,request处理参数出现未将对象引用设置到对象的实例
  7. Au 音频效果参考(合集)
  8. UEFI启动模式下的WIN10系统迁移指南
  9. java 设置excel宽度_javaexcel如何设置指定列宽
  10. JavaScript里的语句用分号结尾是个选项吗
  11. F5 LTM1600 HA
  12. 设置计算机关机时间快捷键,电脑怎么设定关机时间?
  13. Elasticsearch:《大数据集群学习笔记与实战》之es集群(2)es基本操作
  14. opencv建立数学坐标系绘制函数曲线
  15. 可视化编程,公网访问——全网首个基于Node-red的在线评语系统
  16. 古月居ros第十讲遇到的问题
  17. 【蓝桥刷题】——如何轻松拿捏必考数论题?(第一弹)
  18. 磁共振T1 T2 T1WI T2WI含义
  19. springbbot运行无法编译成功,找不到jar包报错:Error:(3, 46) java: 程序包org.springframework.context.annotation不存在
  20. DOS之特殊符号讲解

热门文章

  1. 卸载MySQL Connector NET无法卸载
  2. java线程 demo_Java多线程demo
  3. win11什么时候发布的_2021年初级会计师考试大纲什么时候发布?
  4. 在ubuntu16.4中安装mysql_【Linux】Ubuntu16.04环境下MySQL的安装与使用
  5. 深入理解JVM虚拟机(十):Java内存模型与多线程
  6. 现代操作系统: 第一章 引言
  7. php 批量修改文件,php如何批量修改文件名
  8. mysql为什么用索引_MySql为什么使用B+树做索引
  9. 运行iis提示服务没有及时响应启动或控制请求的解决方法
  10. python爬虫用到的一些东西