工作:
kernel\drivers\media\platform\rockchip\cif\mipi-csi2.c
这里的说明很关键 !!!
对于 mipi-csi 部分
必须要有5个端口
端口 0 用于接受 sensor 的图像数据
端口 1 2 3 4 用于输出 端口0的数据。作为下一级模块的数据源
/*
* there must be 5 pads: 1 input pad from sensor, and
* the 4 virtual channel output pads
*/
#define CSI2_SINK_PAD 0
#define CSI2_NUM_SINK_PADS 1
#define CSI2_NUM_SRC_PADS 4
#define CSI2_NUM_PADS 5
enum csi2_pads {
RK_CSI2_PAD_SINK = 0,
RK_CSI2X_PAD_SOURCE0,
RK_CSI2X_PAD_SOURCE1,
RK_CSI2X_PAD_SOURCE2,
RK_CSI2X_PAD_SOURCE3
};
kernel\drivers\media\platform\rockchip\cif\mipi-csi2.c
{
const struct of_device_id *match;
struct device *dev = &pdev->dev;
struct device_node *node = pdev->dev.of_node;
struct csi2_dev *csi2 = NULL;
struct resource *res;
const struct csi2_match_data *data;
int ret, irq;
...
//绑定 多媒体设备media_device---------硬件设备模块entity------------硬件设备端口 pads
csi2_media_init(&csi2->sd);
}
#define MEDIA_PAD_FL_SINK (1 << 0)
#define MEDIA_PAD_FL_SOURCE (1 << 1)
#define MEDIA_PAD_FL_MUST_CONNECT (1 << 2)
static int csi2_media_init(struct v4l2_subdev *sd)
{
struct csi2_dev *csi2 = sd_to_dev(sd);
int i = 0, num_pads = 0;
num_pads = csi2->match_data->num_pads;//5
/*
设置 pad[] 属性。
pad0 : MEDIA_PAD_FL_SINK
pad1 - pad3 : MEDIA_PAD_FL_SOURCE
*/
for (i = 0; i < num_pads; i++) {
csi2->pad[i].flags = (i == CSI2_SINK_PAD) ? MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
}
//增加 pad[0] pad[1] 属性:必须连接???
// pad[0]
csi2->pad[RK_CSI2X_PAD_SOURCE0].flags =
MEDIA_PAD_FL_SOURCE | MEDIA_PAD_FL_MUST_CONNECT;
csi2->pad[RK_CSI2_PAD_SINK].flags =
MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
/* set a default mbus format
设置默认格式
*/
csi2->format_mbus.code = MEDIA_BUS_FMT_UYVY8_2X8;
csi2->format_mbus.field = V4L2_FIELD_NONE;
csi2->format_mbus.width = RKCIF_DEFAULT_WIDTH;
csi2->format_mbus.height = RKCIF_DEFAULT_HEIGHT;
csi2->crop.top = 0;
csi2->crop.left = 0;
csi2->crop.width = RKCIF_DEFAULT_WIDTH;
csi2->crop.height = RKCIF_DEFAULT_HEIGHT;
/*
参数1
struct csi2_dev
struct v4l2_subdev sd;
struct media_entity entity;
参数2 :5
参数3
struct csi2_dev
struct media_pad pad[CSI2_NUM_PADS];
struct csi2_dev
+---------struct media_pad pad[CSI2_NUM_PADS];
| struct media_gobj graph_obj;
| struct media_device *mdev;----------------+
| struct list_head list; ------>------+ |
| +--------struct media_entity *entity; | |
| | | |
| | struct v4l2_subdev sd; | | 绑定 pad--多媒体设备
| +-------struct media_entity entity; | |
+---------------struct media_pad *pads;(n个pad) | |
| |
struct media_gobj graph_obj; | |
struct media_device *mdev; -------|---+
struct list_head pads; ---<---+ 将所有pad 挂载到多媒体设备中的 pads 链表
struct list_head entities;
struct list_head links;
*/
return media_entity_pads_init(&sd->entity, num_pads, csi2->pad);
}
/*
参数1
struct csi2_dev
struct v4l2_subdev sd;
struct media_entity entity;
参数2 :5
参数3
struct csi2_dev
struct media_pad pad[CSI2_NUM_PADS];
*/
int media_entity_pads_init(struct media_entity *entity, u16 num_pads,
struct media_pad *pads)
{
//获取 硬件设备模块entity 所对应的 多媒体设备media_device
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;
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 多媒体设备 rkcif_mipi的 video_device -> v4l2_device -> media_device (多媒体设备)
struct csi2_dev
struct v4l2_subdev sd;
struct media_entity entity;
struct media_gobj graph_obj;
struct media_device *mdev;
参数2 代表当前 所要挂载的载体对象是 设备模型抽象对象media_entity
参数3 设备模块抽象中用于关联所属的多媒体设备的 图形对象
struct csi2_dev
struct v4l2_subdev sd;
struct media_entity entity;
struct media_pad *pads
truct 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;
}
/*
参数1 多媒体设备 rkcif_mipi的 video_device -> v4l2_device -> media_device (多媒体设备)
struct csi2_dev
struct v4l2_subdev sd;
struct media_entity entity;
struct media_gobj graph_obj;
struct media_device *mdev;
参数2 MEDIA_GRAPH_PAD
参数3 设备模块抽象中用于关联所属的多媒体设备的 图形对象
struct csi2_dev
struct v4l2_subdev sd;
struct media_entity entity;
struct media_pad *pads
truct media_gobj graph_obj;
struct csi2_dev
+---------struct media_pad pad[CSI2_NUM_PADS];
| struct media_gobj graph_obj;
| struct media_device *mdev;----------------+
| struct list_head list; ------>------+ |
| +--------struct media_entity *entity; | |
| | | |
| | struct v4l2_subdev sd; | | 绑定 pad--多媒体设备
| +-------struct media_entity entity; | |
+---------------struct media_pad *pads;(n个pad) | |
| |
struct media_gobj graph_obj; | |
struct media_device *mdev; -------|---+
struct list_head pads; ---<---+ 将所有pad 挂载到多媒体设备中的 pads 链表
struct list_head entities;
struct list_head links;
*/
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 csi2_dev
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://关联 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: //关联 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);
}