Linux v4l2架构学习总链接

二,mipi csi 与mipi csi phy

这里直接贴出来bount函数

static const struct
v4l2_async_notifier_operations csi2_async_ops = {.bound = csi2_notifier_bound,.unbind = csi2_notifier_unbind,
};static int
csi2_notifier_bound(struct v4l2_async_notifier *notifier,struct v4l2_subdev *sd,struct v4l2_async_subdev *asd)
{struct csi2_dev *csi2 = container_of(notifier,struct csi2_dev,notifier);struct csi2_sensor *sensor;struct media_link *link;unsigned int pad, ret;if (csi2->num_sensors == ARRAY_SIZE(csi2->sensors))return -EBUSY;sensor = &csi2->sensors[csi2->num_sensors++];/** 这里的sd是mipi csi phy的subdev*/sensor->sd = sd;/** mipi csi phy 的entity有2个pad* 1个sink pad,1个source pad* 这里是要找到source pad* 为什么要找source呢?* 因为source才是下一级需要的* 可以看到这里只考虑了一个pad* 因为写驱动的人知道source media 及 sink media的pad的个数*/for (pad = 0; pad < sd->entity.num_pads; pad++)if (sensor->sd->entity.pads[pad].flags& MEDIA_PAD_FL_SOURCE)break;/** 这里表示没有找到source pad* 返回-ENXIO*/if (pad == sensor->sd->entity.num_pads) {dev_err(csi2->dev,"failed to find src pad for %s\n",sd->name);return -ENXIO;}/** 这里重点分析*/ret = media_create_pad_link(&sensor->sd->entity, pad,&csi2->sd.entity, RK_CSI2_PAD_SINK,0/* csi2->num_sensors != 1 ? 0 : MEDIA_LNK_FL_ENABLED */);if (ret) {dev_err(csi2->dev,"failed to create link for %s\n",sd->name);return ret;}/** 从entity的links链表上,找到第一个link* 主意这个entity是mipi-csi的,不是mipi-csi-phy的*/link = list_first_entry(&csi2->sd.entity.links, struct media_link, list);ret = media_entity_setup_link(link, MEDIA_LNK_FL_ENABLED);if (ret) {dev_err(csi2->dev,"failed to create link for %s\n",sensor->sd->name);return ret;}return 0;
}

 csi2_notifier_bound() -> media_create_pad_link()

int
media_create_pad_link(struct media_entity *source, u16 source_pad,struct media_entity *sink, u16 sink_pad, u32 flags)
{struct media_link *link;struct media_link *backlink;BUG_ON(source == NULL || sink == NULL);BUG_ON(source_pad >= source->num_pads);BUG_ON(sink_pad >= sink->num_pads);/** 创建一个link* 这个link连接到source的links链表*/link = media_add_link(&source->links);if (link == NULL)return -ENOMEM;/** link的source指向source的source pad* link的sink指向sink的sink pad*/link->source = &source->pads[source_pad];link->sink = &sink->pads[sink_pad];link->flags = flags & ~MEDIA_LNK_FL_INTERFACE_LINK;/* Initialize graph object embedded at the new link *//** 之前分析imx291 mipi-csi-phy mipi-csi的时候* 都是因为这个graph_obj.mdev为NULL* 而无法深入分析* 那么现在的source其mdev是怎么得到的呢?* 在函数 v4l2_device_register_subdev中* 调用 media_device_register_entity 设置的* 这里建议去看* v4l2_async_subdev_notifier_register 分析* https://blog.csdn.net/ldl617/article/details/115548594* 另外主意这里的所有点entity都已经链接到了media的entities链表* * media_gobj_create已经分析了很多次了* 将link通过greph_obj链接到media的links链表*/media_gobj_create(source->graph_obj.mdev, MEDIA_GRAPH_LINK,&link->graph_obj);/* Create the backlink. Backlinks are used to help graph traversal and* are not reported to userspace.*//** 创建一个backlink,链接到sink底links* 虽说是反向link* 但是source和sink指向还是没有改变的* 最后is_backlink = true 用于表示这是个反向link*/backlink = media_add_link(&sink->links);if (backlink == NULL) {__media_entity_remove_link(source, link);return -ENOMEM;}backlink->source = &source->pads[source_pad];backlink->sink = &sink->pads[sink_pad];backlink->flags = flags;backlink->is_backlink = true;/* Initialize graph object embedded at the new link *//** 将backlink通过graph_obj链接到media的links*/media_gobj_create(sink->graph_obj.mdev, MEDIA_GRAPH_LINK,&backlink->graph_obj);/*    * link和backlink关联起来*/link->reverse = backlink;backlink->reverse = link;/** 更新sink的links和backlinks数量* 更新source的links数量*/sink->num_backlinks++;sink->num_links++;source->num_links++;return 0;
}

csi2_notifier_bound() -> media_entity_setup_link()

media_entity_setup_link(link, MEDIA_LNK_FL_ENABLED);
int media_entity_setup_link(struct media_link *link, u32 flags)
{int ret;mutex_lock(&link->graph_obj.mdev->graph_mutex);ret = __media_entity_setup_link(link, flags);mutex_unlock(&link->graph_obj.mdev->graph_mutex);return ret;
}int __media_entity_setup_link(struct media_link *link, u32 flags)
{const u32 mask = MEDIA_LNK_FL_ENABLED;struct media_device *mdev;struct media_entity *source, *sink;int ret = -EBUSY;if (link == NULL)return -EINVAL;/* The non-modifiable link flags must not be modified. *//** link->flags 这里是0* flag = MEDIA_LNK_FL_ENABLE* 所以if不满足*/if ((link->flags & ~mask) != (flags & ~mask))return -EINVAL;if (link->flags & MEDIA_LNK_FL_IMMUTABLE)return link->flags == flags ? 0 : -EINVAL;if (link->flags == flags)return 0;/** 分别找到source entity* 和sink entity*/source = link->source->entity;sink = link->sink->entity;/** stream_count值大于0,可以认为启动了数据流传输* 这里没有,所以为0*/if (!(link->flags & MEDIA_LNK_FL_DYNAMIC) &&(source->stream_count || sink->stream_count))return -EBUSY;/** 找到所属的media*/mdev = source->graph_obj.mdev;/** 调用media->ops->link_notify* 基于RV1126平台imx291分析 --- media注册* https://blog.csdn.net/ldl617/article/details/115677554* 可以看上面的分析,medv没有ops,所以这里不分析*/if (mdev->ops && mdev->ops->link_notify) {ret = mdev->ops->link_notify(link, flags,MEDIA_DEV_NOTIFY_PRE_LINK_CH);if (ret < 0)return ret;}ret = __media_entity_setup_link_notify(link, flags);if (mdev->ops && mdev->ops->link_notify)mdev->ops->link_notify(link, flags,MEDIA_DEV_NOTIFY_POST_LINK_CH);return ret;
}

csi2_notifier_bound() -> media_entity_setup_link() -> __media_entity_setup_link_notify()

static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
{int ret;/* Notify both entities. *//** source entity 是mipi-csi-phy* sink entity 是mipi csi* mipi csi entity有ops = csi_entity_ops*//* source entity没有ops */ret = media_entity_call(link->source->entity, link_setup,link->source, link->sink, flags);if (ret < 0 && ret != -ENOIOCTLCMD)return ret;/* * 调用 csi_entity_ops.link_setup * 对应 csi2_link_setup*/ret = media_entity_call(link->sink->entity, link_setup,link->sink, link->source, flags);if (ret < 0 && ret != -ENOIOCTLCMD) {media_entity_call(link->source->entity, link_setup,link->source, link->sink, link->flags);return ret;}/** 更新link->flags为ENABLE* 同时backlink的也更新一下*/link->flags = flags;link->reverse->flags = link->flags;return 0;
}

csi2_notifier_bound() -> media_entity_setup_link() -> __media_entity_setup_link_notify() -> csi2_link_setup()

static int csi2_link_setup(struct media_entity *entity,const struct media_pad *local,const struct media_pad *remote, u32 flags)
{struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);struct csi2_dev *csi2 = sd_to_dev(sd);struct v4l2_subdev *remote_sd;int ret = 0;/** 根据上下文分析* entity是sink entity* local 是sink pad * remote 是source pad* remote->entity是 source mentity* flags 是 MEDIA_LNK_FL_ENABLED*//** sd.entity == remote->entity* 根据entity找到subdev* 这里的remote_sd就是mipi-csi-phy的subdev*/remote_sd = media_entity_to_v4l2_subdev(remote->entity);mutex_lock(&csi2->lock);/** local->flags = 0*/if (local->flags & MEDIA_PAD_FL_SOURCE) {if (flags & MEDIA_LNK_FL_ENABLED) {if (csi2->sink_linked[local->index - 1]) {ret = -EBUSY;goto out;}csi2->sink_linked[local->index - 1] = true;} else {csi2->sink_linked[local->index - 1] = false;}} else {if (flags & MEDIA_LNK_FL_ENABLED) {if (csi2->src_sd) {ret = -EBUSY;goto out;}/** csi2通过src_sd直接关联到mipi-csi-phy的subdev*/csi2->src_sd = remote_sd;} else {csi2->src_sd = NULL;}}out:mutex_unlock(&csi2->lock);return ret;
}

最后链接情况如下

基于RV1126平台imx291分析 --- media部件连接 二相关推荐

  1. 基于.NET平台的分层架构实战(二)——需求分析与数据库设计

    基于.NET平台的分层架构实战(五)--接口的设计与实现 · 基于.NET平台的分层架构实战(四)--实体类的设计与实现 · 基于.NET平台的分层架构实战(三)--架构概要设计 · 基于.NET平台 ...

  2. 产品分享:Qt+Arm基于RV1126平台的内窥镜软硬整套解决方案(实时影像、冻结、拍照、录像、背光调整、硬件光源调整,其他产品也可使用该平台,如视频监控,物联网产品等等)

    ​若该文为原创文章,转载请注明原文出处 本文章博客地址:[https://hpzwl.blog.csdn.net/article/details/118887440 长期持续带来更多项目与技术分享,咨 ...

  3. 艾伟:基于.NET平台的Windows编程实战(四)—— 数据库操作类的编写

    本系列文章导航 基于.NET平台的Windows编程实战(一)--前言 基于.NET平台的Windows编程实战(二)-- 需求分析与数据库设计 基于.NET平台的Windows编程实战(四)-- 数 ...

  4. 基于边缘计算平台的分析与研究

    摘 要:边缘计算作为万物互联时代的关键技术,具有广泛的应用场景.文章首先分析了边缘计算平台在推广中面临的问题:随后从架构出发分析了典型边缘计算平台,并列举了边缘计算应用场景的需求参数,最后提出了一种边 ...

  5. 基于SOA的区域卫生信息平台案例分析(转)

    这篇文章是在学习过程中baidud到得,觉得在学习阶段可以看看,用的是ESB做的系统集成. 以下是原文: 一.政策与现状 国务院在<关于深化医药卫生体制改革意见>中明确提出要大力推进医药卫 ...

  6. 基于HiKariCP组件,分析连接池原理

    池塘里养:Connection: 一.设计与原理 1.基础案例 HiKariCP作为SpringBoot2框架的默认连接池,号称是跑的最快的连接池,数据库连接池与之前两篇提到的线程池和对象池,从设计的 ...

  7. android手机舆情分析,基于Android平台的环境公共舆情监督系统研究

    摘要: 近年来,随着我国社会经济的持续发展和人民生活水平的不断提高,人们的环境保护意识也在不断增长,其中城市环境质量问题逐渐成为了人们普遍关注的焦点,也成为环保部门和环保从业人员的重点研究方向.环境监 ...

  8. ESP8266(基于arduino平台)每篇一个知识点—1.wifi STA模式连接指定wifi

    ESP8266(基于arduino平台)每篇一个知识点--1.wifi STA模式连接指定wifi 一.ESP8266(基于arduino平台)每篇一个知识点--1.wifi STA模式连接指定wif ...

  9. 基于 Thingsboard 平台自定义 RPC 控制类小部件示例

    基于 Thingsboard 平台自定义 RPC 控制类小部件示例 1. 小部件介绍 2. 创建小部件 3. 部件编辑器 3.1 简介 3.2 资源 / HTML / CSS 3.3 JavaScri ...

  10. 浅谈基于物联网技术的地下综合管廊智慧管控平台建设分析

    摘要:本文以物联网.GIS等技术为基础,采用文献研究等方法,在探究我国地下综合管廊管廊现状及相关技术飾基础上,对其智慧管控平台的建设展开了研究,希望能为相关研究及建设提供有价值的参考. 关键词:物联网 ...

最新文章

  1. Filter及FilterChain的使用具体解释
  2. 贴片按键开关_轻触开关的常用类型和规格型号
  3. 百万TPS高吞吐、秒级低延迟,阿里​搜索离线平台如何实现?
  4. 【程序5】 题目:利用条件运算符的嵌套来完成此题:学习成绩=90分的同学用A表示,60-89分之间的用B表示,60分以下的用C表示。 1.程序分析:(ab)?a:b这是条件运算符的基本例子。...
  5. 三维重建9:点云图像的滤波方法小结
  6. sql性能优化之多表联查
  7. php 点击选择图片上传,php上传多张图片时,选择图片后即可预览的问题
  8. 网络爬虫--2.HTTP和HTTPS
  9. 从Java到C++——常量的使用规则
  10. 移动开发者周刊第一期,大家收到了么?
  11. 复习笔记08 常用API
  12. 【Android系统源码修改】获取屏幕亮度、设置屏幕亮度
  13. AutoSAR入门到精通讲解 (AuroSAR-CP描述) 1.1 AutoSAR-CP简介
  14. oracle 无法归档日志,报all online log need archiving
  15. Excel利用公式向导快速设置成绩的评级系统!
  16. isInterrupted、interrupt和interrupted
  17. 20岁以后增高方法大全
  18. 修改数据库表字段长度
  19. 大学计算机成绩构成,大学计算机平时成绩占多少?
  20. Fliqo 因FlashPlayer EOL不支持 - 不能使用,怎么办?

热门文章

  1. Python 练习题6-13
  2. android镊 姩瀹夎 apk,用java寫的jodconverter借用openoffice來轉換office成pdf的示例代碼...
  3. Android、netassist进行UDP通信
  4. java并发包原理及使用场景
  5. Eclipse 模板使用
  6. Matlab 求全要素生产率,如何用DEAP进行全要素生产率分析
  7. matlab视频教程矩阵,《机器学习》之矩阵和Matlab教程(适合初学)
  8. 《Java语言程序设计与数据结构》编程练习答案(第十七章)
  9. 《Java语言程序设计与数据结构》编程练习答案(第一章)
  10. (java)五大常用算法