工作


kernel\drivers\media\i2c\techpoint\techpoint_v4l2.c
static int techpoint_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
...
//PAD_MAX == 4
for (index = 0; index < PAD_MAX; index++)
//所以 可以知道 techpoint 只有四个下一级 source pad 。没有上一级(SLNK) pad
techpoint->pad[index].flags = MEDIA_PAD_FL_SOURCE;
sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
ret = media_entity_pads_init(&sd->entity, PAD_MAX, techpoint->pad);
/*
参数1
struct techpoint
struct v4l2_subdev subdev
struct media_entity entity
参数2 4
参数3
struct techpoint
struct media_pad pad[PAD_MAX];
struct techpoint
+--------struct media_pad pad[4];
| struct media_gobj graph_obj;
| struct media_device *mdev; --------------+
绑定 entity--pad | struct list_head list; ------->----+ |
| +-------struct media_entity *entity; | |
| | struct v4l2_subdev subdev; | | 绑定 pad--多媒体设备
| |-------struct media_entity entity; | |
+---------------struct media_pad *pads;(四个pad) | |
//该模块所属的多媒体设备 | |
struct media_gobj graph_obj; | |
struct media_device *mdev; ------|---+
//多媒体设备下的pads链表 |
struct list_head pads; ---<--+ 将所有pad 挂载到多媒体设备中的 pads 链表
struct list_head entities;
struct list_head links;
*/
ret = media_entity_pads_init(&sd->entity, PAD_MAX, techpoint->pad);
}
/*
参数1
struct techpoint
struct v4l2_subdev subdev
struct media_entity entity
参数2 4
参数3
struct techpoint
struct media_pad pad[PAD_MAX];
*/
int media_entity_pads_init(struct media_entity *entity, u16 num_pads,
struct media_pad *pads)
{
//获取 硬件设备模块entity 所对应的 多媒体设备media_device
/*
struct techpoint
struct v4l2_subdev subdev;
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
entity->num_pads = num_pads; //4个
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;
/*
参数1 多媒体设备
struct techpoint
struct v4l2_subdev subdev
struct media_entity entity
struct media_gobj graph_obj;
struct media_device *mdev;
参数2 MEDIA_GRAPH_PAD
参数3 端口抽象中用于关联所属的多媒体设备的 图形对象
struct techpoint
struct v4l2_subdev subdev
struct media_entity entity
struct media_pad *pads
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;
}
/*
struct techpoint
struct v4l2_subdev subdev;
struct media_entity entity;
struct media_gobj graph_obj;
struct media_device *mdev;
struct techpoint
struct v4l2_subdev subdev;
struct media_entity entity;
struct media_pad *pads;(n个pad
struct media_gobj graph_obj;
*/
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 techpoint
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);
}
这篇博客详细解析了Linux内核中媒体设备驱动的初始化过程,特别是`techpoint_probe`函数如何配置和初始化`techpoint`设备的端口。通过`media_entity_pads_init`函数,将设备的源端口与多媒体设备进行绑定,建立实体与端口之间的关系,并将这些端口加入到多媒体设备的pads链表中,确保设备正确接入系统。

5858

被折叠的 条评论
为什么被折叠?



