工作
kernel\drivers\phy\rockchip\phy-rockchip-mipi-rx.c
注意!!!
从这里可以看出 mipi_csi_phy 模块
必须有两个端口,一个作为SINK 接收上一级模块的数据。一个作为 SOURCE,传输给下一级模块,作为下一级模块的数据源
enum mipi_dphy_rx_pads {
MIPI_DPHY_RX_PAD_SINK = 0,
MIPI_DPHY_RX_PAD_SOURCE,
MIPI_DPHY_RX_PADS_NUM,
};
static int rockchip_mipidphy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct v4l2_subdev *sd;
struct mipidphy_priv *priv;
struct regmap *grf;
struct resource *res;
const struct of_device_id *of_id;
const struct dphy_drv_data *drv_data;
int i, ret;
ret = rockchip_mipidphy_media_init(priv);
}
static int rockchip_mipidphy_media_init(struct mipidphy_priv *priv)
{
int ret;
/*
所以 mipi dphy模块 有2个抽象pad :
第一个端口作为SINK端口 接收上一级模块的数据
第二个端口作为SOURCE端口 ,传输给下一级模块,作为下一级模块的数据源
*/
priv->pads[MIPI_DPHY_RX_PAD_SOURCE].flags =
MEDIA_PAD_FL_SOURCE | MEDIA_PAD_FL_MUST_CONNECT;
priv->pads[MIPI_DPHY_RX_PAD_SINK].flags =
MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
//当前 Entity 主要功能
priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
/* 绑定 多媒体设备media_device---------硬件设备模块entity------------硬件设备端口 pads
struct mipidphy_priv
struct v4l2_subdev sd
struct media_entity entity;
MIPI_DPHY_RX_PADS_NUM
struct mipidphy_priv
struct media_pad pads[MIPI_DPHY_RX_PADS_NUM];
*/
ret = media_entity_pads_init(&priv->sd.entity,
MIPI_DPHY_RX_PADS_NUM, priv->pads);
if (ret < 0)
return ret;
...
}
kernel\drivers\media\media-entity.c
int media_entity_pads_init(struct media_entity *entity, u16 num_pads,
struct media_pad *pads)
{
//获取 硬件设备模块entity 所对应的 多媒体设备media_device
/*
struct mipidphy_priv
struct v4l2_subdev sd
struct media_entity entity
struct media_gobj graph_obj;
struct media_device *mdev;
*/
struct media_device *mdev = entity->graph_obj.mdev;
unsigned int i;
if (num_pads >= MEDIA_ENTITY_MAX_PADS)
return -E2BIG;
//绑定 硬件设备模块entity ----> 硬件设备端口 pads
/*
struct mipidphy_priv
struct v4l2_subdev sd
struct media_entity entity
struct media_pad *pads;(n个pad
*/
entity->num_pads = num_pads;
entity->pads = pads;
if (mdev)
mutex_lock(&mdev->graph_mutex);
//绑定 多媒体设备media_device---------硬件设备模块entity------------硬件设备端口 pads
/*
初始化 4个 硬件设备端口pads,分别指定所在的硬件设备模块entity,以及ID。并分别绑定 所在的多媒体设备media_device
*/
for (i = 0; i < num_pads; i++) {
pads[i].entity = entity;
pads[i].index = i;
/*
struct mipidphy_priv
struct v4l2_subdev subdev;
struct media_entity entity;
struct media_gobj graph_obj;
struct media_device *mdev;
MEDIA_GRAPH_PAD
struct mipidphy_priv
struct v4l2_subdev subdev;
struct media_entity entity;
struct media_pad *pads;(n个pad
struct media_gobj graph_obj;
*/
if (mdev)
media_gobj_create(mdev, MEDIA_GRAPH_PAD,
&entity->pads[i].graph_obj);
}
if (mdev)
mutex_unlock(&mdev->graph_mutex);
return 0;
}
void media_gobj_create(struct media_device *mdev,
enum media_gobj_type type,
struct media_gobj *gobj)
{
BUG_ON(!mdev);
gobj->mdev = mdev;
/* Create a per-type unique object ID */
gobj->id = media_gobj_gen_id(type, ++mdev->id);
/*
struct mipidphy_priv
struct v4l2_subdev subdev;
struct media_entity entity;
struct media_gobj graph_obj;
struct media_device *mdev;
struct list_head pads;----------+
|
struct media_pad *pads;(n个pad | 挂载到多媒体设备中的 pad 链表
struct media_gobj graph_obj; |
struct list_head list;-------+
*/
switch (type) {
case MEDIA_GRAPH_ENTITY:
list_add_tail(&gobj->list, &mdev->entities);
break;
case MEDIA_GRAPH_PAD://关联 pad ---- 多媒体设备
list_add_tail(&gobj->list, &mdev->pads);
break;
case MEDIA_GRAPH_LINK:
list_add_tail(&gobj->list, &mdev->links);
break;
case MEDIA_GRAPH_INTF_DEVNODE:
list_add_tail(&gobj->list, &mdev->interfaces);
break;
}
mdev->topology_version++;
dev_dbg_obj(__func__, gobj);
}