工作:
kernel\drivers\phy\rockchip\phy-rockchip-mipi-rx.c
static const struct
v4l2_async_notifier_operations rockchip_mipidphy_async_ops = {
.bound = rockchip_mipidphy_notifier_bound,
.unbind = rockchip_mipidphy_notifier_unbind,
};
/* The .bound() notifier callback when a match is found */
/*
如对于 mipi csi phy
参数1 当前设备通知管理器 mipidphy_priv->v4l2_async_notifier
参数2 当前设备的子设备subdev 相关联的子设备 sensor(tp2855) 的 v4l2_subdev
参数3 当前设备的子设备描述 相关联的子设备 sensor(tp2855) 的dts节点 描述
*/
static int
rockchip_mipidphy_notifier_bound(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *sd,
struct v4l2_async_subdev *asd)
{
struct mipidphy_priv *priv = container_of(notifier,
struct mipidphy_priv,
notifier);
struct sensor_async_subdev *s_asd = container_of(asd,
struct sensor_async_subdev, asd);
struct mipidphy_sensor *sensor;
unsigned int pad, ret;
if (priv->num_sensors == ARRAY_SIZE(priv->sensors))
return -EBUSY;
sensor = &priv->sensors[priv->num_sensors++];
sensor->lanes = s_asd->lanes;
sensor->mbus = s_asd->mbus;
//
sensor->sd = sd;
dev_info(priv->dev, "match %s:bus type %d\n", sd->name, s_asd->mbus.type);
/*
tp2855 有4个source pad。属性都是 MEDIA_PAD_FL_SOURCE
这里只是获取了 第一个 source pad
*/
for (pad = 0; pad < sensor->sd->entity.num_pads; pad++)
if (sensor->sd->entity.pads[pad].flags & MEDIA_PAD_FL_SOURCE)
break;
if (pad == sensor->sd->entity.num_pads) {
dev_err(priv->dev,
"failed to find src pad for %s\n",
sensor->sd->name);
return -ENXIO;
}
/*
参数1 sensor(tp2855) 的 entity 子设备的entity
参数2 sensor(tp2855) 的 entity 中的第一个source pad 下标编号 子设备的entity中的 source pad 下标编号
参数3 mipi csi phy 的 entity 当前设备的entity
参数4 MIPI_DPHY_RX_PAD_SINK
0
工作:
一
1. 创建 sensor(tp2855) 设备抽象 的 链接抽象
2. 关联 sensor(tp2855)设备抽象 ---------- sensor(tp2855) 的 抽象链接 ------------ mipi csi phy设备抽象
3. 关联 sensor(tp2855)设备抽象 的 链接抽象 与 sensor(tp2855) 搭载的多媒体
4. 指定 sensor(tp2855)设备抽象 与 链接抽象 搭载同一个 多媒体设备
二
1. 创建 mipi csi phy设备抽象 的 链接抽象
2. 关联 sensor(tp2855)设备抽象 ---------- mipi csi phy的 抽象链接 ------------ mipi csi phy设备抽象
3. 关联 mipi csi phy 设备抽象 的 链接抽象 与 mipi csi phy 搭载的多媒体
4. 指定 mipi csi phy 设备抽象 与 链接抽象 搭载同一个 多媒体设备
三 此时
sensor(tp2855)设备抽象 ---- sensor(tp2855) 的 抽象链接 ---- mipi csi phy设备抽象
---- mipi csi phy的 抽象链接 ----
关联 这两个link : link和backlink
*/
ret = media_create_pad_link(
&sensor->sd->entity, pad,
&priv->sd.entity, MIPI_DPHY_RX_PAD_SINK,
priv->num_sensors != 1 ? 0 : MEDIA_LNK_FL_ENABLED);
if (ret) {
dev_err(priv->dev,
"failed to create link for %s\n",
sensor->sd->name);
return ret;
}
return 0;
}
kernel\drivers\media\media-entity.c
/*
参数1 sensor(tp2855_1) 的 entity 子设备的entity
参数2 sensor(tp2855_1) 的 entity 中的第一个source pad 下标编号 子设备的entity中的 source pad 下标编号
参数3 mipi csi phy 的 entity 当前设备的entity
参数4 MIPI_DPHY_RX_PAD_SINK
0
*/
/*
工作
sensor link
sensor |----------------------------------|
| #-------------# #-------------# | mipi csi phy
|---------------------------| +--|->| source pad | | sink pad | |-----+ |----------------------------------|
| entity | | | #-------------# #-------------# | | | entity |
| #-------------# | | |----------------------------------| | | #-------------# #-------------#|
| | source1 pad |----|----+ mipi csi phy link +-----|-->| sink pad | | source1 pad ||
| #-------------# | | |----------------------------------| | | #-------------# #-------------#|
| #-------------# | | | #-------------# #-------------# | | |----------------------------------|
| | source2 pad |----| +--|->| source pad | | sink pad | |-----+
| #-------------# | | #-------------# #-------------# |
| #-------------# | |----------------------------------|
| | source3 pad |----|--->
| #-------------# |
| #-------------# |
| | source4 pad |----|--->
| #-------------# |
|---------------------------|
此时
sensor(tp2855)设备抽象 ---- sensor(tp2855) 的 抽象链接 ---- mipi csi phy设备抽象
---- mipi csi phy 的 抽象链接 ----
关联 这两个link : link和backlink
*/
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);
/*
参数 子设备 tp2855 的entity中的 links
创建子设备的 entity 的连接抽象(media_link)
struct media_entity { struct media_link {
struct list_head links; -----------创建绑定---------->struct list_head list;
并返回 media_link
*/
link = media_add_link(&source->links);
if (link == NULL)
return -ENOMEM;
//初始化 子设备的entity中的 连接抽象(media_link)
/*
链接管道 子设备 sensor ----- sensor link ----- mipidphy_priv
sensor mipi csi phy
|---------------------------| sensor link |----------------------------------|
| entity | |----------------------------------| | entity |
| #-------------# | | #-------------# #-------------# | | #-------------# #-------------#|
| | source1 pad |----|--->---|->| source pad | | sink pad | |-->----|-->| sink pad | | source1 pad ||
| #-------------# | | #-------------# #-------------# | | #-------------# #-------------#|
| #-------------# | |----------------------------------| |----------------------------------|
| | source2 pad |----|--->
| #-------------# |
| #-------------# |
| | source3 pad |----|--->
| #-------------# |
| #-------------# |
| | source4 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
绑定 子设备 tp2855 link ----- 多媒体设备
struct techpoint
struct v4l2_subdev subdev;
struct media_entity entity; struct media_link
struct list_head links; ---------> struct list_head list;
struct media_gobj graph_obj;
struct media_device *mdev------+
struct list_head list; -----|-----+
| |
struct media_gobj graph_obj; 指定同一个 多媒体设备 | |
struct media_device *mdev; -----------------------------------+ | 关联
struct list_head links; -----------------------------------------+
*/
media_gobj_create(source->graph_obj.mdev, MEDIA_GRAPH_LINK,
&link->graph_obj);
//关于反向链接
/*
struct mipidphy_priv
struct v4l2_subdev sd;
struct media_entity entity; struct media_link {
struct list_head links;-----创建绑定-----> struct list_head list;
*/
backlink = media_add_link(&sink->links);
if (backlink == NULL) {
__media_entity_remove_link(source, link);
return -ENOMEM;
}
/*
链接管道 子设备 sensor ----- 反向link ----- mipidphy_priv
sensor mipi csi phy
|---------------------------| mipi csi phy link |----------------------------------|
| entity | |----------------------------------| | entity |
| #-------------# | | #-------------# #-------------# | | #-------------# #-------------#|
| | source1 pad |----|--->---|->| source pad | | sink pad | |-->----|-->| sink pad | | source1 pad ||
| #-------------# | | #-------------# #-------------# | | #-------------# #-------------#|
| #-------------# | |----------------------------------| |----------------------------------|
| | source2 pad |----|--->
| #-------------# |
| #-------------# |
| | source3 pad |----|--->
| #-------------# |
| #-------------# |
| | source4 pad |----|--->
| #-------------# |
|---------------------------|
*/
backlink->source = &source->pads[source_pad];
backlink->sink = &sink->pads[sink_pad];
backlink->flags = flags;
backlink->is_backlink = true;
/*
将设备 mipi csi phy 的link 挂载到媒体设备
struct mipidphy_priv
struct v4l2_subdev sd; (backlink)
struct media_entity entity; struct media_link {
struct list_head links; ---创建绑定---> struct list_head list;
struct media_gobj graph_obj------+
struct list_head list; ---|------+
| |
struct media_gobj graph_obj 指定同一个 多媒体设备 | |
struct media_device *mdev; --------------------------------------------------+ | 关联
struct list_head links ---------------------------------------------------------+
*/
media_gobj_create(sink->graph_obj.mdev, MEDIA_GRAPH_LINK,
&backlink->graph_obj);
/*
* link和backlink关联起来
*/
link->reverse = backlink;
backlink->reverse = link;
sink->num_backlinks++;
sink->num_links++;
source->num_links++;
return 0;
}
EXPORT_SYMBOL_GPL(media_create_pad_link);