工作:
以设备通知器为线索,从顶向下,依次找到下一级设备,添加到V4L2设备种,循环处理。将全部的子设备整理到 V4L2设备中,这样可以通过V4L2设备直接管理所包含的各个子设备。


即这样

所有设备注册是按照这个图来的。前面分析的是 tp2855_1@44 --> mipi csi phy --> csi2_dev 。这3个都是subdev,只有rkcif_mipi是video

sensor 模块       mipi物理层          mipi协议解析        VICAP模块
sensor-------->csi2_dcphy0  ------> mipi0_csi2 -----> rkcif_mipi_lvds

&rkcif_mipi_lvds {                               status = "okay";                                rockchip,cif-monitor = <3 2 25 1000 5>;port {                                          /* MIPI CSI-2 endpoint */                     cif_mipi_in: endpoint {                       remote-endpoint = <&mipi_csi2_output>;      data-lanes = <1 2 3 4>;                     };                                            };
};

kernel\drivers\media\platform\rockchip\cif\dev.c

static const struct of_device_id rkcif_plat_of_match[] = {{.compatible = "rockchip,rkcif-dvp",.data = &rkcif_dvp_match_data,},{.compatible = "rockchip,rkcif-mipi-lvds",.data = &rkcif_mipi_lvds_match_data,},{},
};//已经成功探测到其中一个子设备,只是把子设备 mipi csi的subdev放入cif_dev->sensors的数组中存储/*参数1 rkcif_device->v4l2_async_notifier参数2 相关联的 mipi csi 的 v4l2_subdev参数3 相关联的 mipi csi 的dts节点*/
static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,struct v4l2_subdev *subdev,struct v4l2_async_subdev *asd)
{//当前 rkcif_device 设备信息struct rkcif_device *cif_dev = container_of(notifier,struct rkcif_device, notifier);struct rkcif_async_subdev *s_asd = container_of(asd,struct rkcif_async_subdev, asd);if (cif_dev->num_sensors == ARRAY_SIZE(cif_dev->sensors)) {v4l2_err(&cif_dev->v4l2_dev,"%s: the num of subdev is beyond %d\n",__func__, cif_dev->num_sensors);return -EBUSY;}//将  相关联的 mipi csi 的 v4l2_subdev 添加到 rkcif_device设备的子sensor[]数组中cif_dev->sensors[cif_dev->num_sensors].lanes = s_asd->lanes;cif_dev->sensors[cif_dev->num_sensors].mbus = s_asd->mbus;cif_dev->sensors[cif_dev->num_sensors].sd = subdev;++cif_dev->num_sensors;v4l2_err(subdev, "Async registered subdev\n");return 0;
}static int rkcif_plat_probe(struct platform_device *pdev)
{const struct of_device_id *match;//设备对应的设备树节点  rkcif_mipi_lvdsstruct device_node *node = pdev->dev.of_node;struct device *dev = &pdev->dev;struct rkcif_device *cif_dev;const struct rkcif_match_data *data;int ret;//分配 rkcif_device 空间cif_dev = devm_kzalloc(dev, sizeof(*cif_dev), GFP_KERNEL);//初始化 rkcif_devicedev_set_drvdata(dev, cif_dev);cif_dev->dev = dev;/*参数1 struct rkcif_device参数2 设备对应的设备树节点信息  rkcif_mipi_lvdsstruct platform_devicestruct device    dev;struct device_node  *of_node; */ret = rkcif_plat_init(cif_dev, node, data->inf_id);if (ret) {rkcif_detach_hw(cif_dev);return ret;}return 0;
}int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int inf_id)
{struct device *dev = cif_dev->dev;struct v4l2_device *v4l2_dev;int ret;
.../* 初始化  rkcif_device->v4l2_device
参数1 struct rkcif_devicestruct device *dev;参数2 struct rkcif_devicestruct v4l2_device v4l2_dev;
动作1工作       struct rkcif_devicestruct device *dev;-------------+struct v4l2_device v4l2_dev;   |struct device *dev;---------+*/ret = v4l2_device_register(cif_dev->dev, &cif_dev->v4l2_dev);...ret = rkcif_register_platform_subdevs(cif_dev);return ret;
}static int rkcif_register_platform_subdevs(struct rkcif_device *cif_dev)
{int stream_num = 0, ret;
...ret = cif_subdev_notifier(cif_dev);...return ret;
}static int cif_subdev_notifier(struct rkcif_device *cif_dev)
{struct v4l2_async_notifier *ntf = &cif_dev->notifier;struct device *dev = cif_dev->dev;int ret;/*
动作2
结果:struct rkcif_devicestruct device *dev;struct device_node  *of_node; //A associated device tree node           如 节点 rkcif_mipi_lvds                      struct    device_node *child;  //Aa                 第一个子节点      如 节点  port                struct  device_node *child; // Aa-1           第一个子节点      如 节点      cif_mipi_in: endpointstruct fwnode_handle fwnode;               struct v4l2_async_notifier notifier;    const struct v4l2_async_notifier_operations *ops ;(init)struct list_head waiting;//等待通知链表struct v4l2_async_subdev **subdevs;//subdevs数组             |//subdevs[n] 将远端目标节点封装为 v4l2_async_subdev 结构 保存在该数组                |enum v4l2_async_match_type match_type = V4L2_ASYNC_MATCH_FWNODE  设备树fwnode匹配方式                |union match                struct fwnode_handle *fwnode;----------------------------->>>>>------------------------相连接的远程节点 mipi_csi2_output 的 父节点port的 fwnode               */ret = v4l2_async_notifier_parse_fwnode_endpoints(dev, ntf, sizeof(struct rkcif_async_subdev), rkcif_fwnode_parse);ntf->ops = &subdev_notifier_ops;/*参1 struct rkcif_devicestruct v4l2_device v4l2_dev;参2struct rkcif_devicestruct v4l2_async_notifier    notifier;*/ret = v4l2_async_notifier_register(&cif_dev->v4l2_dev, ntf);return ret;
}kernel\drivers\media\v4l2-core\v4l2-async.cint v4l2_async_notifier_register(struct v4l2_device *v4l2_dev,struct v4l2_async_notifier *notifier)
{int ret;if (WARN_ON(!v4l2_dev || notifier->sd))return -EINVAL;//动作3//注意这里!!// 初始化了 通知器的根V4L2设备/*  struct rkcif_devicestruct v4l2_device   v4l2_dev;//V4L2设备-------+struct v4l2_async_notifier    notifier;         | struct v4l2_device *v4l2_dev;-------------+*/notifier->v4l2_dev = v4l2_dev;//参数:rkcif_device->v4l2_async_notifierret = __v4l2_async_notifier_register(notifier);if (ret)notifier->v4l2_dev = NULL;return ret;
}static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
{struct device *dev =notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL;struct v4l2_async_subdev *asd;int ret;int i;/*动作4工作:获取子设备对应的远端关联节点的父节点信息,并添加到待探索链表中struct rkcif_devicestruct device *dev;struct device_node    *of_node; //A associated device tree node           如 节点 rkcif_mipi_lvds                      struct    device_node *child;  //Aa                 第一个子节点      如 节点  port                struct  device_node *child; // Aa-1           第一个子节点      如 节点      cif_mipi_in: endpointstruct fwnode_handle fwnode;               struct v4l2_async_notifier notifier;    const struct v4l2_async_notifier_operations *ops ;(init)+---struct list_head waiting;//等待通知链表| struct v4l2_async_subdev **subdevs;//subdevs数组 保存 对应的远端关联节点的父节点信息           +-------|//subdevs[n] 将远端目标节点封装为 v4l2_async_subdev 结构 保存在该数组               |enum v4l2_async_match_type match_type = V4L2_ASYNC_MATCH_FWNODE  设备树fwnode匹配方式                |union match                struct fwnode_handle *fwnode;----------------------------->>>>>------------------------相连接的远程节点 mipi_csi2_output 的 父节点port的 fwnode                           */for (i = 0; i < notifier->num_subdevs; i++) {//获取  对应的远端关联节点的父节点信息asd = notifier->subdevs[i];//挂载 到等待队列list_add_tail(&asd->list, &notifier->waiting);}/*这里是一个循环探索的过程,执行四轮第一轮:传入参数:struct rkcif_devicestruct v4l2_async_notifier notifierrkcif_device 设备1 遍历全局链表 subdev_list ,搜索到当前异步通知器是waiting链表中的子设备信息,即mipi csi设备。说明探索到已挂在的子设备2 将mipi csi设备 添加到  V4L2 子设备链表中 !!3 执行 rkcif_device设备的 notifier->ops->bound()函数4 绑定 mipi csi设备 通知器struct rkcif_device          struct v4l2_async_notifier notifier ----------+|struct csi2_dev                                   |struct v4l2_async_notifier notifier-----------+struct v4l2_async_notifier *parent;-------+第二轮:传入参数:struct csi2_dev  struct v4l2_async_notifier notifiermipi cis 设备1 遍历全局链表 subdev_list ,搜索到当前异步通知器是waiting链表中的子设备信息,即 mipi csi dphy 设备。说明探索到已挂在的子设备2 将 mipi csi dphy 设备 添加到  V4L2 子设备链表中 !!3 执行 mipi cis 设备的 notifier->ops->bound()函数4 绑定 mipi csi dphy 设备 通知器struct rkcif_device       struct v4l2_async_notifier notifier ----------+|struct csi2_dev                                   |struct v4l2_async_notifier notifier-----------+struct v4l2_async_notifier *parent;-------+|struct mipidphy_priv                              |struct v4l2_async_notifier notifier-----------+struct v4l2_async_notifier *parent;-------+第三轮: 传入参数 struct mipidphy_priv  struct v4l2_async_notifier notifiermipi csi dphy 设备1 遍历全局链表 subdev_list ,搜索到当前异步通知器是waiting链表中的子设备信息,即 sensor 设备。说明探索到已挂在的子设备2 将 sensor 设备 添加到  V4L2 子设备链表中 !!3 执行 mipi csi dphy 设备的 notifier->ops->bound()函数4 绑定 sensor 设备 通知器struct rkcif_device          struct v4l2_async_notifier notifier ----------+|struct csi2_dev                                   |struct v4l2_async_notifier notifier-----------+struct v4l2_async_notifier *parent;-------+|struct mipidphy_priv                              |struct v4l2_async_notifier notifier-----------+struct v4l2_async_notifier *parent;-------+|struct techpoint                                  |struct v4l2_async_notifier notifier-----------+struct v4l2_async_notifier *parent;-------+第四轮:传入参数:struct techpointstruct v4l2_async_notifier notifiersensor 设备由于sensort 已经是最后一级模块,他没有子设备。直接返回 !!!*/ret = v4l2_async_notifier_try_all_subdevs(notifier);if (ret < 0)goto err_unbind;/*    参数1  当前设备异步通知器              * 条件不满足,暂时不进入分析,不满足原因如下* 1. notifier->parent == NULL* 2. notifier->v4l2_dev == NULL所以其他三个subdev设备 独自初始化时 不满足该函数运行条件只有 rkcif_mipi 能执行该函数本文暂时没有分析这里!!!*/ret = v4l2_async_notifier_try_complete(notifier);if (ret < 0)goto err_unbind;/** 以上2个函数可以看出来,v4l2_dev为空时都不会执行* 将这个notifer挂载到链表notifier_list上*//* Keep also completed notifiers on the list */list_add(&notifier->list, &notifier_list);mutex_unlock(&list_lock);return 0;err_unbind:/** On failure, unbind all sub-devices registered through this notifier.*/v4l2_async_notifier_unbind_all_subdevs(notifier);err_unlock:mutex_unlock(&list_lock);return ret;
}

截止到v4l2_async_notifier_try_all_subdevs()之前 ,目前所作的工作 :

 struct rkcif_device+---struct v4l2_device  v4l2_dev; |     struct device *dev;------+|                                 |绑定|   struct device *dev; ---------+|        struct device_node  *of_node; //A associated device tree node           如 节点 rkcif_mipi_lvds                      |         struct  device_node *child;  //Aa                 第一个子节点      如 节点  port                |               struct  device_node *child; // Aa-1           第一个子节点      如 节点      cif_mipi_in: endpoint|                  struct fwnode_handle fwnode;                ||  struct v4l2_async_notifier notifier;
绑定+-------struct v4l2_device   v4l2_dev;//通知器的根V4L2设备const struct v4l2_async_notifier_operations *ops ;(init)+-------struct list_head waiting;//等待探索的子设备链表,记录设备树所描述的远程关联子设备,等待探索
挂载|     struct v4l2_async_subdev **subdevs;//subdevs数组              +-----------|//subdevs[n] 将设备树所描述的远端目标节点封装为 v4l2_async_subdev 结构 保存在该数组                |enum v4l2_async_match_type match_type = V4L2_ASYNC_MATCH_FWNODE  设备树fwnode匹配方式                |union match                struct fwnode_handle *fwnode;----------------------------关联->>>>>------------------------相连接的远程节点 mipi_csi2_output 的 父节点port的 fwnode

结合之前的分析 四个部分就有了这样的关系:

                                                         sensorLIST_HEAD(notifier_list)----+                    LIST_HEAD(subdev_list)----+    |                                              ||                                              || 挂载                                         | 挂载|                                              |
struct techpoint                                            |                                              |struct v4l2_async_notifier *subdev_notifier; -----------+                                              |struct v4l2_subdev *sd; ---------+                                                                 || bind                                                            |struct v4l2_subdev subdev;-----------+  ---------------------------------------------------------------+const struct v4l2_subdev_ops *ops(init!!!)          struct v4l2_device *v4l2_dev; (NULL)        struct i2c_client *client;struct device dev;                 struct device_node  *of_node; // A              如节点 tp2855_1@44 struct device_node *child;  //Aa           如节点         ports   +-------struct fwnode_handle *fwnode; |    +---struct device_node *child; // Aa-1     如节点         ucam_out0|  |           |   ||   ||   |                                 mipi_csi_dphy|   || |                                           LIST_HEAD(notifier_list)-----+         LIST_HEAD(subdev_list)------+| |                                                                        |                                     ||   |                                                                        |挂载                                 |挂载|   |           struct mipidphy_priv                                         |                                     ||   |       +-------struct v4l2_async_notifier notifier; --------------------+                                     || |       |           const struct v4l2_async_notifier_operations *ops; (init!!!)                                ||   |       |   +-------struct list_head waiting;//等待探索的子设备链表,记录设备树所描述的远程关联子设备,等待探索||    |       |   |       struct v4l2_async_subdev **subdevs;//数组                                                    ||   |       |   +-----------|//subdevs[n] 将远端目标节点封装为 v4l2_async_subdev 结构 保存在该数组                 ||    |       |               |enum v4l2_async_match_type match_type = V4L2_ASYNC_MATCH_FWNODE                       ||  |       |               |union match                                                                           |+---|-------|--------------------struct fwnode_handle *fwnode;                                                    ||       |           struct v4l2_subdev *sd ------------+                                                       ||      |                                              |                                                       ||       |       struct v4l2_subdev sd;-----------------+ ------------------------------------------------------+|     |           const struct v4l2_subdev_ops *ops   |       |           struct v4l2_device *v4l2_dev; (NULL)|       +------------struct v4l2_async_notifier *subdev_notifier;|                 |               struct device *dev;|                    struct device_node  *of_node; //A associated device tree node           如 节点 csi_dphy0                        |                     struct  device_node *child;  //Aa                 第一个子节点      如 节点  ports               |                           struct  device_node *child; // Aa-1           第一个子节点      如 节点      port@0 |                               struct  device_node *child; //Aa-1-1      第一个子节点      如 节点          csi_dphy1_input: endpoint@1|------------------------------------remote-endpoint = <&ucam_out0> 设备树属性struct  device_node *sibling; // Aa-2     第二个子节点      如 节点      port@1 +-----------------------------------struct fwnode_handle *fwnode; |        +---------------------------struct device_node *child; //Aa-2-1  第一个子节点      如 节点          csi_dphy1_output: endpoint@0|      |                               remote-endpoint = <&mipi_csi2_input> 设备树属性|      ||      ||      ||      |                       |       |                                               |       |                                               mipi_csi   |        |                                                                       LIST_HEAD(notifier_list)-----+       LIST_HEAD(subdev_list)----+|       |                                                                                                    |                                 ||     |                                                                                                    |                                 ||       |                       struct csi2_dev                                                              |                                 ||       |                           struct device *dev;== platform_device *pdev->dev                         |                                 ||      |               +-----------struct v4l2_async_notifier notifier;-------------------------------------+                                 ||     |               |               const struct v4l2_async_notifier_operations *ops; (init !!!!)                                          ||       |               |       +-------struct list_head waiting;//等待探索的子设备链表,记录设备树所描述的远程关联子设备,等待探索             ||       |               |       |       struct v4l2_async_subdev **subdevs;//subdevs数组                                                       ||     |               |       +-----------|//subdevs[n] 将远端目标节点封装为 v4l2_async_subdev 结构 保存在该数组                             ||        |               |                   |enum v4l2_async_match_type match_type = V4L2_ASYNC_MATCH_FWNODE  设备树fwnode匹配方式             ||     |               |                   |union match                                                                                       |+-------|---------------|-----------------------struct fwnode_handle *fwnode;                                                                  ||              |               struct v4l2_subdev *sd -----+                                                                          ||              |                                           |                                                                          ||               |                                           |                                                                          ||               |           struct v4l2_subdev  sd; --------+--------------------------------------------------------------------------+|             |               const struct v4l2_subdev_ops *ops;|             |               struct v4l2_device *v4l2_dev; (NULL)|               |               struct device *dev;== platform_device *pdev->dev|              +---------------struct v4l2_async_notifier notifier;|                              |                           struct device *dev;|                                    struct device_node  *of_node; //A associated device tree node           如 节点 mipi_csi2                        |                                     struct  device_node *child;  //Aa                 第一个子节点      如 节点  ports               |                                           struct  device_node *child; // Aa-1           第一个子节点      如 节点      port@0|                                                struct  device_node *child; //Aa-1-1      第一个子节点      如 节点          mipi_csi2_input: endpoint@1+---------------------------------------------------remote-endpoint = <&csi_dphy0_output>; 设备树属性            struct  device_node *sibling; // Aa-2     第二个子节点      如 节点      port@1 +-----------------------------------------------struct fwnode_handle *fwnode; |                                                struct  device_node *child; //Aa-2-1  第一个子节点      如 节点          mipi_csi2_output: endpoint@0|      +-------------------------------------------remote-endpoint = <&csi_dphy0_output>; |       ||       ||       |                                          rkcif_mipi|     |                   struct rkcif_device|        |                   +---struct v4l2_device v4l2_dev; //最重要的v4l2设备|     |                   |       struct device *dev;------+|        |                   |                                |绑定|       |                   |   struct device *dev; ---------+|        |                   |       struct device_node  *of_node; //A associated device tree node           如 节点 rkcif_mipi_lvds                      |     |                   |           struct  device_node *child;  //Aa                 第一个子节点      如 节点  port                |       |                   |               struct  device_node *child; // Aa-1           第一个子节点      如 节点      cif_mipi_in: endpoint|      |                   |                   struct fwnode_handle fwnode;            |       +-------------------------------------------remote-endpoint = <&mipi_csi2_output>; 设备树属性     |                          |   struct v4l2_async_notifier notifier;|                       绑定+-------struct v4l2_device   v4l2_dev;//通知器的根V4L2设备|                                 const struct v4l2_async_notifier_operations *ops ;(init)|                           +-------struct list_head waiting;//等待探索的子设备链表,记录设备树所描述的远程关联子设备,等待探索|                     挂载|     struct v4l2_async_subdev **subdevs;//subdevs数组              |                           +-----------|//subdevs[n] 将设备树所描述的远端目标节点封装为 v4l2_async_subdev 结构 保存在该数组                |                                       |enum v4l2_async_match_type match_type = V4L2_ASYNC_MATCH_FWNODE  设备树fwnode匹配方式                |                                       |union match                +---------------------------------------------struct fwnode_handle *fwnode;

总结前面的工作:
动作1 初始化 V4L2设备
动作2 将V4L2设备 作为通知器根V4L2设备
动作3 将设备树描述的远程子设备信息 添加到 子设备数组subdevs[] 以及 通知器等待探索的子设备链表 waiting

即将要做的:

动作4
前面已经通过设备树 拿到了关联子设备的信息,那么接下来 就要探索所关联的子设备是否存在,意思就是 探索一下自己关联的远程子设备是否已经 存在于 v4l2_subdev全局链表 subdev_list,是的话就说明子设备部分已经存在,那么就可以继续 处理两者之间的关系

首先 既然 关联子设备已经存在于 v4l2_subdev全局链表 subdev_list,那么就说明探索到了子设备部分,所以从 通知器等待探索的子设备链表 waiting 中删除 子设备。本来嘛,都已经找到了,就必要在这里排队了。并且也从v4l2_subdev全局链表 subdev_list 中删除子设备。已经找到了,不用挂在这里了。

然后建立 两者间的关系

注意执行第一轮 rkcif_device 部分的 v4l2_async_notifier_try_all_subdevs()时候,在最后面 初始化了 子设备通知器的父通知器,相当于打开了这里mipi csi的阀门同理后续都会初始化各自子设备通知器的父通知器的,分别从这里开始执行,重复动作4,建立各自的联系。

再由前面的关系图的相互绑定关系
最后得到这样的关系图:

static int v4l2_async_notifier_try_all_subdevs(struct v4l2_async_notifier *notifier)
{/*这里是个阀门,只能从 rkcif_device 开始执行在 rkcif_device 执行这里之前 2855,mipi csi phy, mipi csi 三个subdev 的通知器都没有初始化自己的 父通知器 或 本设备通知器更没有根V4L2设备,只有 rkcif_device 的通知器才有根V4L2设备从rkcif_device 执行 v4l2_async_notifier_try_all_subdevs 后,指定当前设备与子设备mipi csi 的通知器 公用一个公共V4L2通知器。所以后续  mipi csi,mipi csi phy,2855 依次执行v4l2_async_notifier_try_all_subdevs()。共享公共的V4L2通知器。*/struct v4l2_device *v4l2_dev = v4l2_async_notifier_find_v4l2_dev(notifier);struct v4l2_subdev *sd;//如果  排除  2855,mipi csi phy, mipi csiif (!v4l2_dev)return 0;again:/* 遍历 v4l2_subdev全局链表 subdev_list,此时 subdev_list链表上有3个subdev,* 分别是 2855的, mipi csi phy的及 mipi csi 的这里会被2855终结跳出,因为他没有子设备。*/list_for_each_entry(sd, &subdev_list, async_list) {struct v4l2_async_subdev *asd;int ret;/*遍历全局链表 subdev_list ,搜索当前异步通知器是waiting链表中的子设备|------------LIST_HEAD(subdev_list)----------------------||                                                         ||--------------subdev-------subdev------subdev-----------|struct rkcif_devicestruct v4l2_async_notifier notifier; +---struct list_head waiting;//等待通知链表| struct v4l2_async_subdev **subdevs;//subdevs数组 保存 对应的远端关联节点的父节点信息           +-------|//subdevs[n] 将远端目标节点封装为 v4l2_async_subdev 结构 保存在该数组               |enum v4l2_async_match_type match_type = V4L2_ASYNC_MATCH_FWNODE  设备树fwnode匹配方式                |union match                struct fwnode_handle *fwnode;----------------------------->>>>>------------------------相连接的远程节点 mipi_csi2_output 的 父节点port的 fwnode       * 首先从 rkcif_device->v4l2_async_notifier->waiting 上取下每一个 asd   (子设备描述v4l2_async_subdev 链表 waiting) * 对于当前的rkcif_mipi来说其nontifier->waiting上的asd只有一个, 这个asd指向mipi csi dts的节点* 于是 subdev_list上取出mipi csi 的subdev时* 这个这个asd就和mipi csi 匹配上了*/asd = v4l2_async_find_match(notifier, sd);//获取 相关联的子设备的描述信息(mipi csi dts的节点信息)if (!asd)continue;/*参数1 rkcif_device->v4l2_async_notifier                    当前设备通知管理器参数2 rkcif_device->v4l2_dev                              当前设备 V4L2驱动参数3 相关联的子设备 mipi csi 的 v4l2_subdev           当前设备的子设备subdev参数4 相关联的子设备 mipi csi 的dts节点 描述            当前设备的子设备描述*/ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asd);if (ret < 0)return ret;/** v4l2_async_match_notify() may lead to registering a* new notifier and thus changing the async subdevs* list. In order to proceed safely from here, restart* parsing the list from the beginning.*/goto again;}return 0;
}static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,struct v4l2_device *v4l2_dev,struct v4l2_subdev *sd,struct v4l2_async_subdev *asd)
{struct v4l2_async_notifier *subdev_notifier;int ret;/*目前已知的 工作 : 动作struct rkcif_device           //V4L2 设备驱动                          +---struct v4l2_device *v4l2_dev;            |       //链表,用于跟踪已注册的子设备        |    +---struct list_head subdevs;             |    |                                        |   |                                         |    |           struct csi2_dev               | |               // V4L2子设备             |    |               struct v4l2_subdev sd; |    |                   //指向的所属的 V4L2 设备驱动+---|-------------------struct v4l2_device *v4l2_dev;|                   //挂载到 sub-devices子设备链表+---------------------struct list_head list;参数1 rkcif_device->v4l2_async_notifier->v4l2_dev参数2 相关联的 mipi csi 的 v4l2_subdev*/ret = v4l2_device_register_subdev(v4l2_dev, sd);if (ret < 0)return ret;/*对于rkcif_mipi 只是把mipi csi的subdev放入cif_dev->sensors的数组中存储参数1 rkcif_device->v4l2_async_notifier                    当前设备通知管理器参数2 相关联的子设备 mipi csi 的 v4l2_subdev             当前设备的子设备subdev参数3 相关联的子设备 mipi csi 的dts节点 描述            当前设备的子设备描述struct rkcif_device       //用于记录rkcif sensor 信息struct rkcif_sensor_info   sensors[RKCIF_MAX_SENSOR];//V4L2子设备struct v4l2_subdev *sd; -------------------+|struct csi2_dev                                       |// V4L2子设备                                  |struct v4l2_subdev sd -------------------------+*/ret = v4l2_async_notifier_call_bound(notifier, sd, asd);if (ret < 0) {v4l2_device_unregister_subdev(sd);return ret;}/* Remove from the waiting list 将 当前设备的子设备描述 从当前设备的 异步通知 所管理的 子设备描述链表 waiting 上删除 (子设备描述v4l2_async_subdev 链表 waiting)struct rkcif_devicestruct v4l2_async_notifier notifier;  struct list_head waiting;//等待通知链表从 waiting 中删除 子设备信息*/list_del(&asd->list);sd->asd = asd;/*绑定 notifier,即使用同一个 V4L2 的通知器struct rkcif_devicestruct v4l2_async_notifier notifier ----------+||struct csi2_dev                                     |struct v4l2_subdev sd                         |struct v4l2_async_notifier notifier ------+*/sd->notifier = notifier;/* Move from the global subdevice list to notifier's done *//*之前sd通过自己的async_list挂载到全局subdev_list,现在将其从全局subdev_list移除,并且挂载到 notifier->done注意notifier是管理者的notifier对于 rkcif_mipi  就是 先从全局subdev_list链表中 删掉 mipi csi 子设备的 subdev。然后将他挂载到 自己的 rkcif_device->v4l2_async_notifier->donestruct rkcif_devicestruct v4l2_async_notifier notifier//已经完成探测的子设备链表struct list_head done; -----------+|struct csi2_dev                           | 已经完成探测,加到完成链表struct v4l2_subdev sd                 |struct list_head async_list;------+*/list_move(&sd->async_list, &notifier->done);/* 参数struct csi2_devstruct v4l2_subdev sd 得到  struct csi2_devstruct v4l2_async_notifier notifier遍历全局通知器链表notifier_list 找到 mipi csi 的通知器,这样就能找到下一级子设备*/subdev_notifier = v4l2_async_find_subdev_notifier(sd);if (!subdev_notifier || subdev_notifier->parent)return 0;/** Proceed with checking for the sub-device notifier's async* sub-devices, and return the result. The error will be handled by the* caller.*//*struct rkcif_devicestruct v4l2_async_notifier notifier ----------+|struct csi2_dev                                   |struct v4l2_async_notifier notifier           |struct v4l2_async_notifier *parent;-------+*/// 指定 mipi csi 的异步通知器 的父通知器 是 rkcif_mipi的异步通知器subdev_notifier->parent = notifier;/** 这是一个嵌套函数* 脑补一下后面是怎么执行的* 继续从subdev_list上找到mipi csi phy的subdev* 将mipi csi phy 的subdev挂载到v4l2_dev->subdevs上* 将mipi csi phy 的sd从subdev_list上移除挂载到mipi csi的notifier->done上* * 接着找到mipi csi phy的notifer* 继续从subdev_list上找到2855的subdev* 将2855 的subdev挂载到v4l2_dev->subdevs上* 将2855 的sd从subdev_list上移除挂载到mipi csi phy的notifier->done上* * 接着找到2855的notifer* 由于notifier->v4l2_device 上没有设备,所以就不会找的subdev* 于是就退出嵌套*//*参数1  mipi csi 的异步通知器*/return v4l2_async_notifier_try_all_subdevs(subdev_notifier);
}

基于RV1126 Video分析-----图像处理模块所代表的V4L2设备注册相关推荐

  1. 基于RV1126 Video分析-----sensor模块所代表的subdev子设备注册

    工作: static LIST_HEAD(notifier_list); //异步通知链表 static LIST_HEAD(subdev_list);//v4l2_subdev 链表LIST_HEA ...

  2. 基于RV1126 Video分析-----驱动各模块总览

    一 通用理论 硬件链接: 一般情况下,Camera和SOC有两个接口进行连接,分为为MIPI接口和I2C接口,其中MIPI接口用来传输图像的数据,数据传输路径为从Sensor传输到SOC.另一个接口为 ...

  3. 基于RV1126 Video分析-----mipi dphy模块所代表的subdev子设备注册

    工作: LIST_HEAD(notifier_list)----+ LIST_HEAD(subdev_list)----+ | || || 挂载 | 挂载| | struct techpoint | ...

  4. 基于RV1126 Video分析-----mipi协议解析模块所代表的subdev子设备注册

    工作: sensorLIST_HEAD(notifier_list)----+ LIST_HEAD(subdev_list)----+ | || || 挂载 | 挂载| | struct techpo ...

  5. 基于RV1126 Video分析-----sensor 的 media模块注册

    工作 kernel\drivers\media\i2c\techpoint\techpoint_v4l2.c static int techpoint_probe(struct i2c_client ...

  6. 基于matlab 论文知网,基于MATLAB的校园图像处理与分析

    内容介绍 原文档由会员 jiji888 发布 基于MATLAB的校园图像处理与分析 2.13万字 我自己原创的毕业设计,今年最新的,仅在本站独家提交,大家放心使用 摘要 随着计算机科学技术的不断发展以 ...

  7. PLUS模型有两大模块,一是基于土地扩张分析策略的规则挖掘框架,二是基于多类型随机补丁种子的CA模型,此外该模型还内嵌了Markov chain,以便于对土地利用数量需要作出预测。

    工业革命以来,社会生产力迅速提高,人类活动频繁,此外人口与日俱增对土地的需求与改造更加强烈,人-地关系日益紧张.此外,土地资源的不合理开发利用更是造成了水土流失.植被退化.水资源短缺.区域气候变化.生 ...

  8. 基于Ti Omap3x 分析v4l2架构

    1 概述 本文将基于Ti Omap3x这个典型的实例来分析v4l2在具体media场景中的应用.通过分析app层的行为以及driver层的实现来对整个多媒体框架有一个大概的认识.内容主要包括主要包括v ...

  9. 基于MATLAB的数字图像处理的设计与实现 转

    基于MAT [摘要]数字图像处理是一门新兴技术,随着计算机硬件的发展,数字图像的实时处理已经成为可能,由于数字图像处理的各种算法的出现,使得其处理速度越来越快,能更好的为人们服务.数字图像处理是一种通 ...

最新文章

  1. 单点登录系统实现基于SpringBoot
  2. win10 编译姿态估计AlphaPose
  3. 主c++ 辅lua luabind protobuf
  4. SAP CRM Appointment应用里Date profile的配置
  5. 谁去过顽皮,谁去过尼斯? 圣诞老人为您提供Java 11建议!
  6. NYOJ2括号配对问题
  7. Flutter的滚动以及sliver约束
  8. 项目成功的关键是在投资最少的时候找出错误
  9. S5PV210 Uboot开发与移植02:Uboot配置与编译
  10. 压缩感知(Compressed sensing)from wiki
  11. 如何查看并杀死僵尸进程?
  12. 蓝牙打印 设置打印样式_双编辑模式 打印自由更轻松!——海鸟贴纸打印机蓝牙按键版体验...
  13. 双层优化模型【简述】
  14. Java、对字符串中的字符排序
  15. 知其然知其所以然 itoa实现 整型转字符串
  16. 台式计算机cpu品牌,台式电脑CPU天梯图2018年9月最新版 桌面CPU性能排名
  17. 教程二:windows api(c mfc vs2017)实现U盘插拔检测,获取U盘容量,U盘内容移动,开启和关闭U盘以及获取盘符等
  18. 每天叫醒的不是闹钟而是励志文章梦想
  19. hey 安装_如何使用“ Hey Siri”在Mac上启动Siri
  20. 论文投稿必看,审稿人意见互相矛盾,作者该怎么办?

热门文章

  1. R语言ggplot2 | 告别AI和PS,地表最全R语言拼图
  2. 夜深人静做游戏---之一
  3. 全球与中国超辐射发光二极管(SLED)市场深度研究分析报告
  4. 输入法打字英文字母间距很大?
  5. 9.Redis 数据备份与恢复
  6. python unitest框架,Python unittest框架操作实例解析
  7. OpenGL 超级宝典笔记 —— 雾
  8. 营销学之父科特勒:互联网思维要选准卖点
  9. win7---虚拟wifi无法启动承载网络
  10. Thymeleaf语法标签