camera驱动框架分析(上)

前言

  camera驱动框架涉及到的知识点比较多,特别是camera本身的接口就有很多,有些是直接连接到soc的camif口上的,有些是通过usb接口导出的,如usb camera。我这里主要讨论前者,也就是与soc直连的。我认为凡是涉及到usb的,都不是一两句话可以说明白的!如有错误,欢迎指正,谢谢!!!

环境说明

涉及到的基础知识点:
字符设备驱动
设备模型
平台设备驱动
v4l2框架
i2c驱动框架

涉及到的术语:
camera : 指的是整个camera,包括它本身的硬件连接方式及支持i2c控制的i2c设备
sensor : 指的是支持i2c控制的i2c设备,它属于camera的一部分,在内核实现里也能体现出来
camera host: 指的是与camera相连接的,一般内嵌在soc里面的控制器

涉及到的文件夹:
drivers/media/platform/soc_camera/ 主要存放camera host驱动,通用的camera驱动也存放在此
drivers/media/i2c/soc_camera/ 主要存放sensor驱动

分析所采用的内核版本:

VERSION = 3                                                                                                                                                   
PATCHLEVEL = 15                                                                 
SUBLEVEL = 0                                                                    
EXTRAVERSION =                                                                  
NAME = Shuffling Zombie Juror    

camera的驱动包括通用camera的驱动、camera host的驱动以及sensor的驱动,下面一个个来分析

这里先插一张图,来自:http://blog.csdn.net/kickxxx/article/details/8484498(该图片及图片后的文字是在我写完这篇博文后发现的,我认为对理解camera驱动会有帮助,所以就摘抄了^_^)
soc camera 子系统 系统架构图

Soc camera sub-system对应着drivers/media/video/下的soc_camera.c soc_camera_platform.c

Soc camera host 是host端实现,是由平台厂商实现的,向上实现soc_camera_host_ops接口,向下操作Camera host硬件以及通过平台特定的接口操作Soc camera device

Soc camera device 是平台的camera device(同时也是subdev),由驱动开发者来实现v4l2_subdev_call调用的subdev 接口,同时还要为soc camera host实现平台特定的操作接口;向下操作camera sensor或者video AD芯片。

Camera host hardware是平台硬件相关的,不同的平台有不同的host硬件,比如imx51的ipu,三星s5pv210的fimc控制器等。

soc_camera_host,soc_camera_device,v4l2_device,v4l2_subdev关系如下:理论上系统内可以有多个soc_camera_host,物理上soc_camera_host就是系统的camera处理模块驱动一个soc_camera_host可以对应多个soc_camera_device,物理上soc_camera_device是一个camera接口,每个soc_camera_host对应一个v4l2_dev每个soc_camera_device,系统会为他们创建设备节点/dev/videoX。每个soc_camera_device有多个v4l2_subdev,物理上v4l2_subdev可以是sensor,video AD芯片v4l2_subdev可以通过i2c挂接到v4l2_device,也可以通过soc_camera_link提供的add_device来增加,这依赖于sensor和video AD芯片挂接到MCU camera接口的方式。

通用camera驱动

对应文件drivers/media/platform/soc_camera/soc_camera.c

static struct platform_driver __refdata soc_camera_pdrv = {.probe = soc_camera_pdrv_probe,.remove  = soc_camera_pdrv_remove,.driver  = {.name   = "soc-camera-pdrv",.owner  = THIS_MODULE,},
};module_platform_driver(soc_camera_pdrv);

从这里可以看出,我们要使该驱动probe得到调用,先得注册一个平台设备,且名字为soc-camera-pdrv。通用camera的驱动就是定义了一套数据结构,然后告诉大家,你如果想用通用的camera驱动,那就照着数据结构填好,然后用soc-camera-pdrv的名字通过平台总线注册上来就可以了。平台设备的注册可以通过两种方式来实现,一种是通过设备树,它是最新的一种机制,通过dts文件来描述硬件信息,使得内核里面不会再硬编码一堆和用于描述硬件信息的代码。对应到这里的硬件信息就是camera sensor硬件信息以及camera硬件布线信息。另一种就是以前采用的方式,直接用代码在板子相关的启动文件里来描述那些信息并通过平台设备的注册。soc_camera_pdrv里面没有设备树的相关支持,说明这类设备的添加还是采用后面那种方式,通过下面的命令输出也可以证实这一点:

我用命令(grep -rns soc-camera-pdrv arch/arm*/)搜索一下,就可以得到以下结果:

arch/arm/mach-shmobile/board-lager.c:394:   platform_device_register_data(&platform_bus, "soc-camera-pdrv", 1,
arch/arm/mach-shmobile/board-bockw.c:606:   platform_device_register_data(&platform_bus, "soc-camera-pdrv", 0,
arch/arm/mach-shmobile/board-bockw.c:609:   platform_device_register_data(&platform_bus, "soc-camera-pdrv", 1,
arch/arm/mach-shmobile/board-mackerel.c:1224:   .name   = "soc-camera-pdrv",
arch/arm/mach-shmobile/board-armadillo800eva.c:910: .name   = "soc-camera-pdrv",
arch/arm/mach-shmobile/board-marzen.c:299:  .name   = "soc-camera-pdrv",                \
arch/arm/mach-at91/board-sam9m10g45ek.c:241:    .name   = "soc-camera-pdrv",
arch/arm/mach-omap1/board-ams-delta.c:435:  .name   = "soc-camera-pdrv",
arch/arm/mach-pxa/ezx.c:788:    .name   = "soc-camera-pdrv",
arch/arm/mach-pxa/ezx.c:1062:   .name   = "soc-camera-pdrv",
arch/arm/mach-pxa/em-x270.c:1034:   .name   = "soc-camera-pdrv",
arch/arm/mach-pxa/palmz72.c:339:    .name   = "soc-camera-pdrv",
arch/arm/mach-pxa/pcm990-baseboard.c:507:       .name   = "soc-camera-pdrv",
arch/arm/mach-pxa/pcm990-baseboard.c:513:       .name   = "soc-camera-pdrv",
arch/arm/mach-pxa/mioa701.c:682:MIO_SIMPLE_DEV(mioa701_camera,    "soc-camera-pdrv",&iclink);
arch/arm/mach-imx/mach-imx27_visstrim_m10.c:572:    platform_device_register_resndata(NULL, "soc-camera-pdrv", 0, NULL, 0,
arch/arm/mach-imx/mach-mx31_3ds.c:248:  .name   = "soc-camera-pdrv",
arch/arm/mach-imx/mach-mx31_3ds.c:412:  REGULATOR_SUPPLY("cmos_2v8", "soc-camera-pdrv.0"),
arch/arm/mach-imx/mach-mx31_3ds.c:444:  REGULATOR_SUPPLY("cmos_vcore", "soc-camera-pdrv.0"),
arch/arm/mach-imx/mach-mx35_3ds.c:305:  .name   = "soc-camera-pdrv",
arch/arm/mach-imx/mach-mx35_3ds.c:324:  REGULATOR_SUPPLY("cmos_vio", "soc-camera-pdrv.0"),
arch/arm/mach-imx/mach-mx27_3ds.c:272:  REGULATOR_SUPPLY("cmos_2v8", "soc-camera-pdrv.0"),
arch/arm/mach-imx/mach-mx27_3ds.c:302:  REGULATOR_SUPPLY("cmos_vcore", "soc-camera-pdrv.0"),
arch/arm/mach-imx/mach-mx27_3ds.c:410:  .name   = "soc-camera-pdrv",
arch/arm/mach-imx/mx31moboard-smartbot.c:91:        .name   = "soc-camera-pdrv",
arch/arm/mach-imx/mx31moboard-marxbot.c:181:        .name   = "soc-camera-pdrv",
arch/arm/mach-imx/mach-pcm037.c:329:    .name   = "soc-camera-pdrv",
arch/arm/mach-imx/mach-pcm037.c:337:    .name   = "soc-camera-pdrv",

我选一个稍微简单的mach来进行后面的分析,at91平台(arch/arm/mach-at91/board-sam9m10g45ek.c),我把相关的代码截取出来:

   * soc-camera OV2640                                                            */                                                                             #if defined(CONFIG_SOC_CAMERA_OV2640) || \                                      defined(CONFIG_SOC_CAMERA_OV2640_MODULE)                                    static unsigned long isi_camera_query_bus_param(struct soc_camera_link *link)   {                                                                               /* ISI board for ek using default 8-bits connection */                      return SOCAM_DATAWIDTH_8;                                                   }                                                                               static int i2c_camera_power(struct device *dev, int on)                         {                                                                               /* enable or disable the camera */                                          pr_debug("%s: %s the camera\n", __func__, on ? "ENABLE" : "DISABLE");       at91_set_gpio_output(AT91_PIN_PD13, !on);                                   if (!on)                                                                    goto out;                                                               /* If enabled, give a reset impulse */                                      at91_set_gpio_output(AT91_PIN_PD12, 0);                                     msleep(20);                                                                 at91_set_gpio_output(AT91_PIN_PD12, 1);                                     msleep(100);                                                                out:                                                                            return 0;                                                                   }                                                                               static struct i2c_board_info i2c_camera = {                                     I2C_BOARD_INFO("ov2640", 0x30),                                             };                                                                              static struct soc_camera_link iclink_ov2640 = {                                 .bus_id         = 0,                                                        .board_info     = &i2c_camera,                                              .i2c_adapter_id     = 0,                                                    .power          = i2c_camera_power,                                         .query_bus_param    = isi_camera_query_bus_param,                           };                                                                              static struct platform_device isi_ov2640 = {                                    .name   = "soc-camera-pdrv",                                                .id = 0,                                                                    .dev    = {                                                                 .platform_data = &iclink_ov2640,                                        },                                                                          };                                                                              #endif   

最重要的结构就是soc_camera_link,它是所有camera这类设备都需要用到的结构体。bus_id用来描述它是连接到哪条soc camera host总线上,后面会再讲这个。board_info用来描述i2c设备的信息,比如它的型号名称,它的i2c地址,相信研究过i2c驱动的人都比较熟悉。i2c_adapter_id用来描述i2c设备挂载哪条i2c总线上。sensor的控制一般通过i2c来实现,所以这里才会有i2c设备的描述,因为需要对应的i2c驱动来驱动它啊。power一般指sensor的电源模块的开启和关闭,一般是单独通过一个gpio来控制的。query_bus_param这个成员先不看吧,用到的时候再看。

总之,通过上面的信息以及后面的平台设备注册后,就将soc-camera-pdrv平台设备添加到平台总线了。也就是说只要这段代码编译进入了内核并调用了这段代码,那么soc_camera_pdrv_probe就一定会执行了。下面继续分析前面列出来的soc_camera_pdrv_probe吧!

soc_camera_pdrv_probe的实现很短,为了方面说明,也贴出来吧:

static int soc_camera_pdrv_probe(struct platform_device *pdev)
{struct soc_camera_desc *sdesc = pdev->dev.platform_data;struct soc_camera_subdev_desc *ssdd = &sdesc->subdev_desc;struct soc_camera_device *icd;int ret;if (!sdesc)return -EINVAL;icd = devm_kzalloc(&pdev->dev, sizeof(*icd), GFP_KERNEL);if (!icd)return -ENOMEM;/** In the asynchronous case ssdd->num_regulators == 0 yet, so, the below* regulator allocation is a dummy. They are actually requested by the* subdevice driver, using soc_camera_power_init(). Also note, that in* that case regulators are attached to the I2C device and not to the* camera platform device.*/ret = devm_regulator_bulk_get(&pdev->dev, ssdd->sd_pdata.num_regulators,ssdd->sd_pdata.regulators);if (ret < 0)return ret;icd->iface = sdesc->host_desc.bus_id;icd->sdesc = sdesc;icd->pdev = &pdev->dev;platform_set_drvdata(pdev, icd);icd->user_width     = DEFAULT_WIDTH;icd->user_height    = DEFAULT_HEIGHT;return soc_camera_device_register(icd);
}

这里我们会开始接触第二个重要的数据结构soc_camera_device,它在内核里代表的就是一个camera sensor设备。有一点需要提前说明下,我们之前谈到数据结构soc_camera_link,对应到驱动使用的时候,将其拆分成两个结构体了,我想也是为了代码更清晰吧!对应的结构如下:

struct soc_camera_desc {struct soc_camera_subdev_desc subdev_desc;struct soc_camera_host_desc host_desc;
};

因此,soc_camera_pdrv_probe里面的icd->iface = sdesc->host_desc.bus_id其实就是上面我说过的bus_id,用来描述它是连接到哪条soc camera host线上。soc_camera_pdrv_probe主要是创建对象 soc_camera_device,它代表着一个camera sensor设备。当然可以有多个这样的设备同时存在,且都由该驱动负责创建。并将platform设备传过来的各种数据放到soc_camera_device里面,最终调用soc_camera_device_register将该camera sensor注册。

soc_camera_device_register的代码就不贴了,它其实主要就做了一件事情,将代表着camera sensor的对象soc_camera_device放到了全局链表devices中,其他的就是做参数检查等等。

好了,到这里,我们的系统里的devices全局链表里已经有一个用于代表camera sensor的设备了,它就在这里静静的等待着负责它的驱动的到来,我们应该可以想象到,负责它的就是camera host咯。顺便说一下,如果我们仅仅需要写一个sensor驱动,那么到这里,就算完成了一小半了,剩下的就是完成我们camera sensor里对应的i2c设备的驱动(参考drivers/media/i2c/soc_camera/,里面有一些已经实现了的i2c sensor驱动),至于camera host驱动,一般对应的soc的sdk都会实现啦。

未完,待续!
2015年6月

转载于:https://www.cnblogs.com/rongpmcu/p/7662738.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/391118.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

探索感染了COVID-19的动物的数据

数据 (The data) With the number of cases steadily rising day by day, COVID-19 has been pretty much in the headlines of every newspaper known to man. Despite the massive amount of attention, a topic that has remained mostly untouched (some exceptions being …

Facebook哭晕在厕所,调查显示用VR体验社交的用户仅为19%

美国娱乐软件协会ESA调查显示&#xff0c;有74%的用户使用VR玩游戏&#xff0c;而仅有19%的用户会用VR进行社交。 当我们说到VR社交&#xff0c;必然离不开Facebook。在刚刚结束的F8大会上&#xff0c;小扎展示了VR社交平台Facebook Spaces测试版&#xff0c;巧的是此前也有好…

解决Javascript疲劳的方法-以及其他所有疲劳

Learn your fundamentals, and never worry again. 了解您的基础知识&#xff0c;再也不用担心。 新工具让我担心 (New Tools Worry Me) When JavaScripts shiny tool of the day comes out, I sometimes overreact. 当JavaScript一天一度的闪亮工具问世时&#xff0c;我有时R…

已知两点坐标拾取怎么操作_已知的操作员学习-第4部分

已知两点坐标拾取怎么操作有关深层学习的FAU讲义 (FAU LECTURE NOTES ON DEEP LEARNING) These are the lecture notes for FAU’s YouTube Lecture “Deep Learning”. This is a full transcript of the lecture video & matching slides. We hope, you enjoy this as mu…

北京供销大数据集团发布SinoBBD Cloud 一体化推动产业云发展

9月5日&#xff0c;第五届全球云计算大会在上海世博展览馆盛大开幕&#xff0c;国内外顶尖企业汇聚一堂&#xff0c;新一代云计算技术产品纷纷亮相。作为国内领先的互联网基础服务提供商&#xff0c;北京供销大数据集团(以下简称“SinoBBD”)受邀参加此次大会&#xff0c;并正式…

“陪护机器人”研报:距离真正“陪护”还差那么一点

一款有“缺陷”的机器人&#xff0c;怎能做到真正的“陪护”&#xff1f; 近日&#xff0c;鼎盛智能发布了一款名为Ibotn的&#xff08;爱蹦&#xff09;幼儿陪伴机器人&#xff0c;核心看点就是通过人脸识别、场景识别等计算机视觉技术来实现机器人对儿童的陪护。不过&#xf…

【转】消息队列应用场景

一、消息队列概述 消息队列中间件是分布式系统中重要的组件&#xff0c;主要解决应用耦合&#xff0c;异步消息&#xff0c;流量削锋等问题。实现高性能&#xff0c;高可用&#xff0c;可伸缩和最终一致性架构。是大型分布式系统不可缺少的中间件。 目前在生产环境&#xff0c;…

lime 模型_使用LIME的糖尿病预测模型解释— OneZeroBlog

lime 模型Article outline文章大纲 Introduction 介绍 Data Background 资料背景 Aim of the article 本文的目的 Exploratory analysis 探索性分析 Training a Random Forest Model 训练随机森林模型 Global Importance 全球重要性 Local Importance 当地重要性 介绍 (Introd…

Linux第三周作业

1.三个法宝 ①存储程序计算机工作模型&#xff0c;计算机系统最最基础性的逻辑结构&#xff1b; ②函数调用堆栈&#xff0c;堆栈完成了计算机的基本功能&#xff1a;函数的参数传递机制和局部变量存取 &#xff1b; ③中断&#xff0c;多道程序操作系统的基点&#xff0c;没有…

RESTful API浅谈

2019独角兽企业重金招聘Python工程师标准>>> 上半年时候&#xff0c;部门有组织的讨论了一下实践微服务的技术话题&#xff0c;主要内容是SOA服务和微服务各自的优势和难点&#xff0c;其中有提到关于RESTful API设计方法。 正好最近在深入的学习HTTP协议&#xff0…

变量的作用域和生存期:_生存分析简介:

变量的作用域和生存期:In the previous article, I have described the Kaplan-Meier estimator. To give a quick recap, it is a non-parametric method to approximating the true survival function. This time, I will focus on another approach to visualizing a surviv…

您的网卡配置暂不支持1000M宽带说明

国内宽带网速越来越快&#xff0c;运营商更是在今年初纷纷推进千兆宽带业务。为了让用户更好地了解网络状况&#xff0c;360宽带测速器发布新版&#xff0c;优化了宽带测速范围&#xff0c;可有效支持最高1000&#xff2d;的带宽测量。此外&#xff0c;宽带测速器能检测用户网卡…

永无止境_永无止境地死:

永无止境Wir befinden uns mitten in der COVID-19-Pandemie und damit auch im Mittelpunkt einer medialen Geschichte, die durch eine noch nie dagewesene Komplexitt und Dynamik gekennzeichnet ist. Wie kann Informationsdesign helfen, diese Explosion von Nachrich…

HDU4612 Warm up —— 边双联通分量 + 重边 + 缩点 + 树上最长路

题目链接&#xff1a;http://acm.split.hdu.edu.cn/showproblem.php?pid4612 Warm up Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 7206 Accepted Submission(s): 1681 Problem DescriptionN planets are …

吴恩达神经网络1-2-2_图神经网络进行药物发现-第1部分

吴恩达神经网络1-2-2预测溶解度 (Predicting Solubility) 相关资料 (Related Material) Jupyter Notebook for the article Jupyter Notebook的文章 Drug Discovery with Graph Neural Networks — part 2 图神经网络进行药物发现-第2部分 Introduction to Cheminformatics 化学…

论文搜索源

中国科学院文献情报中心 见下图 中国计算机学会推荐国际学术会议和期刊目录 EI学术会议中心,        engieer village 转载于:https://www.cnblogs.com/cxy-941228/p/7693097.html

重学TCP协议(10)SYN flood 攻击

1.SYN flood 攻击 SYN Flood&#xff08;半开放攻击&#xff09;是一种拒绝服务&#xff08;DDoS&#xff09;攻击&#xff0c;其目的是通过消耗所有可用的服务器资源使服务器不可用于合法流量。通过重复发送初始连接请求&#xff08;SYN&#xff09;数据包&#xff0c;攻击者能…

python 数据框缺失值_Python:处理数据框中的缺失值

python 数据框缺失值介绍 (Introduction) In the last article we went through on how to find the missing values. This link has the details on the how to find missing values in the data frame. https://medium.com/kallepalliravi/python-finding-missing-values-in-…

Spring Cloud 5分钟搭建教程(附上一个分布式日志系统项目作为参考) - 推荐

http://blog.csdn.net/lc0817/article/details/53266212/ https://github.com/leoChaoGlut/log-sys 上面是我基于Spring Cloud ,Spring Boot 和 Docker 搭建的一个分布式日志系统. 目前已在我司使用. 想要学习Spring Cloud, Spring Boot以及Spring 全家桶的童鞋,可以参考学习,如…

51nod1832(二叉树/高精度模板+dfs)

题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId1832 题意: 中文题诶~ 思路: 若二叉树中有 k 个节点只有一个子树, 则答案为 1 << k. 详情参见:http://blog.csdn.net/gyhguoge01234/article/details/77836484 代码: 1 #include <iostream&g…