本篇文章仅为防止忘记v4l2 异步注册写的,个人觉的写的不够详细,仅供参考,
dts如下
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2022 Rockchip Electronics Co., Ltd.
*
*/
/ {
cam_ircut0: cam_ircut {
status = "okay";
compatible = "rockchip,ircut";
ircut-open-gpios = <&gpio4 RK_PA0 GPIO_ACTIVE_HIGH>;
ircut-close-gpios = <&gpio4 RK_PA1 GPIO_ACTIVE_HIGH>;
rockchip,camera-module-index = <0>;
rockchip,camera-module-facing = "back";
};
};
&csi2_dcphy0 {
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
mipidphy0_in_ucam0: endpoint@1 {
reg = <1>;
remote-endpoint = <&ov13855_out0>;
data-lanes = <1 2 3 4>;
};
};
port@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
csidcphy0_out: endpoint@0 {
reg = <0>;
remote-endpoint = <&mipi0_csi2_input>;
};
};
};
};
&csi2_dphy0_hw {
status = "okay";
};
&i2c4 {
status = "okay";
pinctrl-0 = <&i2c4m0_xfer>;
dw9763: dw9763@c {
compatible = "dongwoon,dw9763";
status = "okay";
reg = <0xc>;
rockchip,camera-module-index = <0>;
rockchip,vcm-start-current = <10>;
rockchip,vcm-rated-current = <85>;
//rockchip,vcm-step-mode = <5>;
rockchip,camera-module-facing = "back";
vdd-gpio = <&aw_gpio1 0 GPIO_ACTIVE_HIGH>;
};
ov13855: ov13855@10 {
compatible = "ovti,ov13855";
status = "okay";
reg = <0x10>;
clocks = <&cru CLK_MIPI_CAMARAOUT_M1>;
clock-names = "xvclk";
pinctrl-names = "default";
pinctrl-0 = <&mipim0_camera1_clk>;
power-domains = <&power RK3588_PD_VI>;
reset-gpios = <&gpio1 RK_PB0 GPIO_ACTIVE_HIGH>;
pwdn-gpios = <&gpio1 RK_PA4 GPIO_ACTIVE_HIGH>;
//lf-gpios = <&aw_gpio1 0 GPIO_ACTIVE_HIGH>;
//iovdd-gpios = <&aw_gpio1 1 GPIO_ACTIVE_HIGH>;
vaf-gpios = <&aw_gpio1 2 GPIO_ACTIVE_HIGH>;
avdd-gpios = <&aw_gpio1 3 GPIO_ACTIVE_HIGH>;
dvdd-gpios = <&aw_gpio1 4 GPIO_ACTIVE_HIGH>;
rockchip,camera-module-index = <0>;
rockchip,camera-module-facing = "back";
rockchip,camera-module-name = "CMK-OT2016-FV1";
rockchip,camera-module-lens-name = "default";
lens-focus = <&dw9763>;
port {
ov13855_out0: endpoint {
remote-endpoint = <&mipidphy0_in_ucam0>;
data-lanes = <1 2 3 4>;
};
};
};
};
&mipi0_csi2 {
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
mipi0_csi2_input: endpoint@1 {
reg = <1>;
remote-endpoint = <&csidcphy0_out>;
};
};
port@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
mipi0_csi2_output: endpoint@0 {
reg = <0>;
remote-endpoint = <&cif_mipi_in0>;
};
};
};
};
&pinctrl {
cam {
/*
mipidphy0_pwr: mipidphy0-pwr {
rockchip,pins =
<1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
};
*/
};
};
&rkcif {
status = "okay";
};
&rkcif_mipi_lvds {
status = "okay";
port {
cif_mipi_in0: endpoint {
remote-endpoint = <&mipi0_csi2_output>;
};
};
};
&rkcif_mipi_lvds_sditf {
status = "okay";
port {
mipi_lvds_sditf: endpoint {
remote-endpoint = <&isp0_vir0>;
};
};
};
&rkcif_mmu {
status = "okay";
};
&rkisp0 {
status = "okay";
};
&isp0_mmu {
status = "okay";
};
&rkisp0_vir0 {
status = "okay";
port {
#address-cells = <1>;
#size-cells = <0>;
isp0_vir0: endpoint@0 {
reg = <0>;
remote-endpoint = <&mipi_lvds_sditf>;
};
};
};
kernel-5.10/driver/phy/rockchip/phy-rockchip-csi-dphy.c
rockchip_csi2_dphy_probe==>rockchip_csi2dphy_media_init
static int rockchip_csi2dphy_media_init(struct csi2_dphy *dphy)
{
int ret;
//media entity后面再分析
dphy->pads[CSI2_DPHY_RX_PAD_SOURCE].flags =
MEDIA_PAD_FL_SOURCE | MEDIA_PAD_FL_MUST_CONNECT;
dphy->pads[CSI2_DPHY_RX_PAD_SINK].flags =
MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
dphy->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
ret = media_entity_pads_init(&dphy->sd.entity,
CSI2_DPHY_RX_PADS_NUM, dphy->pads);
if (ret < 0)
return ret;
v4l2_async_notifier_init(&dphy->notifier);
ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port( .................................A
dphy->dev, &dphy->notifier,
sizeof(struct sensor_async_subdev), 0,
rockchip_csi2_dphy_fwnode_parse);
if (ret < 0)
return ret;
dphy->sd.subdev_notifier = &dphy->notifier;
dphy->notifier.ops = &rockchip_csi2_dphy_async_ops;
ret = v4l2_async_subdev_notifier_register(&dphy->sd, &dphy->notifier); ....................................B
if (ret) {
dev_err(dphy->dev,
"failed to register async notifier : %d\n", ret);
v4l2_async_notifier_cleanup(&dphy->notifier);
return ret;
}
return v4l2_async_register_subdev(&dphy->sd); ............................................C
}
A部分
先看A部分v4l2_async_notifier_parse_fwnode_endpoints_by_port
kernel-5.10\drivers\media\v4l2-core\v4l2-fwnode.c
int
v4l2_async_notifier_parse_fwnode_endpoints_by_port(struct device *dev,
struct v4l2_async_notifier *notifier,
size_t asd_struct_size,
unsigned int port,
parse_endpoint_func parse_endpoint)
{
return __v4l2_async_notifier_parse_fwnode_ep(dev, notifier,
asd_struct_size,
port, true,
parse_endpoint);
}
EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_endpoints_by_port);
具体调用__v4l2_async_notifier_parse_fwnode_ep
static int
__v4l2_async_notifier_parse_fwnode_ep(struct device *dev,
struct v4l2_async_notifier *notifier,
size_t asd_struct_size,
unsigned int port,
bool has_port,
parse_endpoint_func parse_endpoint)
{
struct fwnode_handle *fwnode;
int ret = 0;
if (WARN_ON(asd_struct_size < sizeof(struct v4l2_async_subdev)))
return -EINVAL;
fwnode_graph_for_each_endpoint(dev_fwnode(dev), fwnode) {
struct fwnode_handle *dev_fwnode;
bool is_available;
/*fwnode_graph_get_port_parent具体调用
* struct fwnode_handle *
* fwnode_graph_get_port_parent(const struct fwnode_handle *endpoint)
* {
* struct fwnode_handle *port, *parent;
*
* port = fwnode_get_parent(endpoint);
* parent = fwnode_call_ptr_op(port, graph_get_port_parent);
*
* fwnode_handle_put(port);
*
* return parent;
* }
* EXPORT_SYMBOL_GPL(fwnode_graph_get_port_parent);
*最后具体调用kernel-5.10\drivers\of\property.c中的函数
*下面的fwnode_device_is_available也是调用property.c中的fwnode_device_is_available ===》fwnode_device_is_available,判断dts中的status是否为okay
*/
dev_fwnode = fwnode_graph_get_port_parent(fwnode);
is_available = fwnode_device_is_available(dev_fwnode);
printk("====>fwnode:%s,dev_fwnode:%s,is_available %d",fwnode->dev->of_node->full_name,dev_fwnode->dev->of_node->full_name,is_available);
fwnode_handle_put(dev_fwnode);
if (!is_available)
continue;
if (has_port) {
struct fwnode_endpoint ep;
ret = fwnode_graph_parse_endpoint(fwnode, &ep);
if (ret)
break;
if (ep.port != port)
continue;
}
ret = v4l2_async_notifier_fwnode_parse_endpoint(dev,
notifier,
fwnode,
asd_struct_size,
parse_endpoint);
if (ret < 0)
break;
}
fwnode_handle_put(fwnode);
return ret;
}
static int
v4l2_async_notifier_fwnode_parse_endpoint(struct device *dev,
struct v4l2_async_notifier *notifier,
struct fwnode_handle *endpoint,
unsigned int asd_struct_size,
parse_endpoint_func parse_endpoint)
{
struct v4l2_fwnode_endpoint vep = { .bus_type = 0 };
struct v4l2_async_subdev *asd;
int ret;
asd = kzalloc(asd_struct_size, GFP_KERNEL);
if (!asd)
return -ENOMEM;
asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
asd->match.fwnode =
fwnode_graph_get_remote_port_parent(endpoint);
printk("====>asd->match.fwnode %s \n",asd->match.fwnode->dev->of_node->full_name);
if (!asd->match.fwnode) {
dev_dbg(dev, "no remote endpoint found\n");
ret = -ENOTCONN;
goto out_err;
}
ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &vep);
if (ret) {
dev_warn(dev, "unable to parse V4L2 fwnode endpoint (%d)\n",
ret);
goto out_err;
}
ret = parse_endpoint ? parse_endpoint(dev, &vep, asd) : 0;
if (ret == -ENOTCONN)
dev_dbg(dev, "ignoring port@%u/endpoint@%u\n", vep.base.port,
vep.base.id);
else if (ret < 0)
dev_warn(dev,
"driver could not parse port@%u/endpoint@%u (%d)\n",
vep.base.port, vep.base.id, ret);
v4l2_fwnode_endpoint_free(&vep);
if (ret < 0)
goto out_err;
ret = v4l2_async_notifier_add_subdev(notifier, asd);
if (ret < 0) {
/* not an error if asd already exists */
if (ret == -EEXIST)
ret = 0;
goto out_err;
}
return 0;
out_err:
fwnode_handle_put(asd->match.fwnode);
kfree(asd);
return ret == -ENOTCONN ? 0 : ret;
}
这是subdev异步注册的其中一个关键步骤list_add_tail(&asd->asd_list, ¬ifier->asd_list);
注意asd->match.fwnode是endpoint的父节点,比如asd->match.fwnode mipi0-csi2@fdd10000,下次注册mipi0-csi2是会用当前的subdev与asd上的fwnode进行对比,如果是同意个节点则匹配上
这里贴一下打印的log,按注册顺序
====>dev : rkcif-mipi-lvds
[ 8.185161][ T1] ====>dev_fwnode:rkcif-mipi-lvds
[ 8.185181][ T1] ====>asd->match.fwnode mipi0-csi2@fdd10000
[ 8.185189][ T1] ===== begin parsing endpoint /rkcif-mipi-lvds/port/endpoint
[ 8.185195][ T1] fwnode video bus type not specified (0), mbus type not specified (0)
[ 8.185206][ T1] ===== end parsing endpoint /rkcif-mipi-lvds/port/endpoint
[ 8.185276][ T1] rkcif rkcif-mipi-lvds1: Adding to iommu group 16
[ 8.185292][ T1] rkcif rkcif-mipi-lvds1: rkcif driver version: v00.01.0a
[ 8.185335][ T1] rkcif rkcif-mipi-lvds1: attach to cif hw node
[ 8.185341][ T1] rkcif rkcif-mipi-lvds1: rkcif wait line 0
[ 8.185989][ T1] ====>dev : rkcif-mipi-lvds1
[ 8.185996][ T1] ====>dev_fwnode:rkcif-mipi-lvds1
[ 8.186017][ T1] ====>asd->match.fwnode mipi1-csi2@fdd20000
[ 8.186023][ T1] ===== begin parsing endpoint /rkcif-mipi-lvds1/port/endpoint
[ 8.186028][ T1] fwnode video bus type not specified (0), mbus type not specified (0)
[ 8.186037][ T1] ===== end parsing endpoint /rkcif-mipi-lvds1/port/endpoint
[ 8.186904][ T1] ====>dev : mipi0-csi2@fdd10000
[ 8.186912][ T1] ====>dev_fwnode:mipi0-csi2@fdd10000
[ 8.186918][ T1] ====>ep:0,ep->id:1
[ 8.186923][ T1] ====>asd->match.fwnode csi2-dcphy0
[ 8.186930][ T1] ===== begin parsing endpoint /mipi0-csi2@fdd10000/ports/port@0/endpoint@1
[ 8.186936][ T1] fwnode video bus type not specified (0), mbus type not specified (0)
[ 8.186946][ T1] ===== end parsing endpoint /mipi0-csi2@fdd10000/ports/port@0/endpoint@1
[ 8.186952][ T1] ====>dev_fwnode:mipi0-csi2@fdd10000
[ 8.186957][ T1] ====>ep:1,ep->id:0
[ 8.186966][ T1] rkcif rkcif-mipi-lvds: Entity type for entity rockchip-mipi-csi2 was not initialized!
[ 8.186972][ T1] rockchip-mipi-csi2: Async registered subdev
[ 8.186979][ T1] rockchip-mipi-csi2: probe success, v4l2_dev:rkcif-mipi-lvds!
[ 8.187065][ T1] ====>dev : mipi1-csi2@fdd20000
[ 8.187070][ T1] ====>dev_fwnode:mipi1-csi2@fdd20000
[ 8.187076][ T1] ====>ep:0,ep->id:1
[ 8.187085][ T1] ====>asd->match.fwnode csi2-dcphy1
[ 8.187091][ T1] ===== begin parsing endpoint /mipi1-csi2@fdd20000/ports/port@0/endpoint@1
[ 8.187097][ T1] fwnode video bus type not specified (0), mbus type not specified (0)
[ 8.187105][ T1] ===== end parsing endpoint /mipi1-csi2@fdd20000/ports/port@0/endpoint@1
[ 8.187111][ T1] ====>dev_fwnode:mipi1-csi2@fdd20000
[ 8.187116][ T1] ====>ep:1,ep->id:0
[ 8.187122][ T1] rkcif rkcif-mipi-lvds1: Entity type for entity rockchip-mipi-csi2 was not initialized!
[ 8.187128][ T1] rockchip-mipi-csi2: Async registered subdev
[ 8.187135][ T1] rockchip-mipi-csi2: probe success, v4l2_dev:rkcif-mipi-lvds1!
[ 8.187531][ T1] rkisp_hw fdcb0000.rkisp: Adding to iommu group 14
[ 8.187687][ T1] rkisp_hw fdcb0000.rkisp: is_thunderboot: 0
[ 8.187694][ T1] rkisp_hw fdcb0000.rkisp: max input:0x0@0fps
[ 8.187700][ T1] rkisp_hw fdcb0000.rkisp: Missing rockchip,grf property
[ 8.187773][ T1] rkisp_hw fdcb0000.rkisp: no find phandle sram
[ 8.187877][ T1] rkisp_hw fdcc0000.rkisp: Adding to iommu group 15
[ 8.188072][ T1] rkisp_hw fdcc0000.rkisp: is_thunderboot: 0
[ 8.188078][ T1] rkisp_hw fdcc0000.rkisp: max input:0x0@0fps
[ 8.188083][ T1] rkisp_hw fdcc0000.rkisp: Missing rockchip,grf property
[ 8.188152][ T1] rkisp_hw fdcc0000.rkisp: no find phandle sram
[ 8.188448][ T1] rkisp rkisp0-vir0: rkisp driver version: v01.09.00
[ 8.188574][ T1] rkisp rkisp0-vir0: Entity type for entity rkisp-isp-subdev was not initialized!
[ 8.189026][ T1] ====>dev : rkisp0-vir0
[ 8.189032][ T1] ====>dev_fwnode:rkisp0-vir0
[ 8.189039][ T1] ====>asd->match.fwnode rkcif-mipi-lvds-sditf
[ 8.189045][ T1] ===== begin parsing endpoint /rkisp0-vir0/port/endpoint@0
[ 8.189051][ T1] fwnode video bus type not specified (0), mbus type not specified (0)
[ 8.189060][ T1] ===== end parsing endpoint /rkisp0-vir0/port/endpoint@0
[ 8.189102][ T1] rkisp rkisp1-vir0: rkisp driver version: v01.09.00
[ 8.189219][ T1] rkisp rkisp1-vir0: Entity type for entity rkisp-isp-subdev was not initialized!
[ 8.189652][ T1] ====>dev : rkisp1-vir0
[ 8.189658][ T1] ====>dev_fwnode:rkisp1-vir0
[ 8.189663][ T1] ====>asd->match.fwnode rkcif-mipi-lvds1-sditf
[ 8.189669][ T1] ===== begin parsing endpoint /rkisp1-vir0/port/endpoint@0
[ 8.189675][ T1] fwnode video bus type not specified (0), mbus type not specified (0)
[ 8.189684][ T1] ===== end parsing endpoint /rkisp1-vir0/port/endpoint@0
[ 9.289965][ T1] ov13855 4-0010: driver version: 00.01.02
[ 9.290169][ T1] ov13855 4-0010: could not get default pinstate
[ 9.290181][ T1] ov13855 4-0010: could not get sleep pinstate
[ 9.298546][ T1] ov13855 4-0010: Detected OV00d855 sensor, REVISION 0xb0
[ 9.310223][ T217] vendor storage:20190527 ret = 0
[ 9.327207][ T1] ov13855 5-0010: driver version: 00.01.02
[ 9.327330][ T1] ov13855 5-0010: could not get default pinstate
[ 9.327342][ T1] ov13855 5-0010: could not get sleep pinstate
[ 9.336122][ T1] ov13855 5-0010: Detected OV00d855 sensor, REVISION 0xb0
[ 9.369541][ T1] registered taskstats version 1
[ 9.441305][ T9] ====>dev : csi2-dcphy0
[ 9.441344][ T9] ====>dev_fwnode:csi2-dcphy0
[ 9.441356][ T9] ====>ep:0,ep->id:1
[ 9.441456][ T9] ====>asd->match.fwnode ov13855@10
[ 9.441471][ T9] ===== begin parsing endpoint /csi2-dcphy0/ports/port@0/endpoint@1
[ 9.441484][ T9] fwnode video bus type not specified (0), mbus type not specified (0)
[ 9.441505][ T9] ===== end parsing endpoint /csi2-dcphy0/ports/port@0/endpoint@1
[ 9.441523][ T9] ====>dev_fwnode:csi2-dcphy0
[ 9.441533][ T9] ====>ep:1,ep->id:0
[ 9.441574][ T9] rockchip-csi2-dphy csi2-dcphy0: dphy0 matches m00_b_ov13855 4-0010:bus type 5
[ 9.441600][ T9] rockchip-csi2-dphy csi2-dcphy0: csi2_dphy_update_sensor_mbus fail to get dphy param, used default value
[ 9.442858][ T9] rockchip-csi2-dphy csi2-dcphy0: csi2_dphy_update_sensor_mbus fail to get dphy param, used default value
[ 9.442909][ T9] rkcif-mipi-lvds: Async subdev notifier completed
[ 9.442922][ T9] rockchip-csi2-dphy csi2-dcphy0: csi2 dphy0 probe successfully!
[ 9.442995][ T193] rockchip-csi2-dphy csi2-dcphy0: csi2_dphy_update_sensor_mbus fail to get dphy param, used default value
[ 9.443171][ T9] ====>dev : csi2-dcphy1
[ 9.443186][ T9] ====>dev_fwnode:csi2-dcphy1
[ 9.443197][ T9] ====>ep:0,ep->id:1
[ 9.443233][ T9] ====>asd->match.fwnode ov13855@10
[ 9.443246][ T9] ===== begin parsing endpoint /csi2-dcphy1/ports/port@0/endpoint@1
[ 9.443257][ T9] fwnode video bus type not specified (0), mbus type not specified (0)
[ 9.443273][ T9] ===== end parsing endpoint /csi2-dcphy1/ports/port@0/endpoint@1
[ 9.443464][ T193] rockchip-csi2-dphy csi2-dcphy0: csi2_dphy_update_sensor_mbus fail to get dphy param, used default value
[ 9.443492][ T193] rockchip-csi2-dphy csi2-dcphy0: csi2_dphy_update_sensor_mbus fail to get dphy param, used default value
[ 9.443523][ T193] rkisp0-vir0: Async subdev notifier completed
[ 9.443626][ T9] ====>dev_fwnode:csi2-dcphy1
[ 9.443642][ T9] ====>ep:1,ep->id:0
[ 9.443668][ T9] rockchip-csi2-dphy csi2-dcphy1: dphy1 matches m01_f_ov13855 5-0010:bus type 5
[ 9.443686][ T9] rockchip-csi2-dphy csi2-dcphy1: csi2_dphy_update_sensor_mbus fail to get dphy param, used default value
[ 9.445319][ T9] rockchip-csi2-dphy csi2-dcphy1: csi2_dphy_update_sensor_mbus fail to get dphy param, used default value
[ 9.445367][ T9] rkcif-mipi-lvds1: Async subdev notifier completed
[ 9.445380][ T9] rockchip-csi2-dphy csi2-dcphy1: csi2 dphy1 probe successfully!
[ 9.445446][ T194] rockchip-csi2-dphy csi2-dcphy1: csi2_dphy_update_sensor_mbus fail to get dphy param, used default value
[ 9.446089][ T194] rockchip-csi2-dphy csi2-dcphy1: csi2_dphy_update_sensor_mbus fail to get dphy param, used default value
[ 9.446113][ T194] rockchip-csi2-dphy csi2-dcphy1: csi2_dphy_update_sensor_mbus fail to get dphy param, used default value
[ 9.446134][ T194] rkisp1-vir0: Async subdev notifier completed
总的来说这个函数就是找到endpoint的远程父节点,并将asd添加到notifier->asd_list上,此处也可参考v4l2_async_notifier_parse_fwnode_endpoints_by_port 分析
B部分
函数v4l2_async_subdev_notifier_register
->__v4l2_async_notifier_register
static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
{
struct v4l2_async_subdev *asd;
int ret, i = 0;
INIT_LIST_HEAD(¬ifier->waiting);
INIT_LIST_HEAD(¬ifier->done);
mutex_lock(&list_lock);
list_for_each_entry(asd, & notifier->asd_list, asd_list) {
ret = v4l2_async_notifier_asd_valid(notifier, asd, i++);
if (ret)
goto err_unlock;
list_add_tail(&asd->list, & notifier->waiting);
}
ret = v4l2_async_notifier_try_all_subdevs(notifier);
if (ret < 0)
goto err_unbind;
ret = v4l2_async_notifier_try_complete(notifier);
if (ret < 0)
goto err_unbind;
/* Keep also completed notifiers on the list */
list_add(¬ifier->list, ¬ifier_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;
}
遍历notifier->asd_list,将上面A部分注册的asd->list加入notifier->waiting
v4l2_async_notifier_try_all_subdevs函数需要v4l2_dev注册后才能完成,也就是再没有注册v4l2_dev前,所有的subdev都不会和asd匹配
C部分
函数v4l2_async_register_subdev初始化sd->async_list并加入subdev_list
sensor==》 mipi csi2_dcphy0==》mipi0_csi2==》rkcif_mipi_lvds – – – >rkcif_mipi_lvds_sditf ==> rkisp0_vir0
注册的顺序可参考上面的log
rkcif_mipi_lvds 注册完成后notifier_list链表上有1个notifier,是mipi0-csi2@fdd10000的
mipi0_csi2注册后,notifier_list链表上有1个notifier,是csi2-dcphy0,此时notifier_list上的mipi0-csi2@fdd10000的notifier已经和sd匹配,已经从队列中移除
按log顺序是,接着是ov13855 sensor注册,notifier_list链表上有2个notifier,分别是csi2-dcphy0和ov13855 sensor 上附带的af或flash的
csi2_dcphy0注册后,此时notifier_list上的csi2-dcphy0的notifier已经和sd匹配,已经从队列中移除,af或flash注册是的notifier_list清空
感觉我将的不够清楚的可以参考https://blog.csdn.net/ldl617/category_11006713.html