在rk 9.0之前还没有实现这个子系统,为了解决多媒体设备的复杂性和流动性,我的理解是把多媒体各个模块树状链接,可以很方便的操作各个链接点的格式分辨率等。但是这样需要代码来支持,所以就有media子系统,虽然增加了大段代码,但是这样操作更加灵活。
由于media子系统在网上很多,这里只做简单讲述,后面自己看看代码。
Media子系统是一种pipeline形式
Rk从sensor到ddr设定了4个设备如下
sensor —> DPHY —> isp —> stream
其中每个设备都认为是一个entity,是一个节点。每个都包含一个或者多个pads,可以认为是各个分叉,link就是将各个分叉pad链接起来,也就是谁链接谁。谁是源端,谁是目的端。
根据上图:
sensor有ov5695和ov2659,它们只有一个pad,因为只能输出
DPHY 就是mipi dphy 接收sensor数据,输出输出到isp,所有有2个pads
Isp 因为isp除了要接收dphy进来的数据,还要接收input参数,输出统计信息,最后将数据输出到 mainpath和selfpath(这个不清楚是否rkisp独有),4个pads
Mp和sp 接收isp处理好的数据 一个pad。
下面看下media设备的注册,以及相关操作函数
Media设备结构体
struct media_device {
/* dev->driver_data points to this struct. */
struct device *dev;
struct media_devnode devnode; //设备节点
char model[32]; //名字以及相关信息
char serial[40];
char bus_info[32];
u32 hw_revision;
u32 driver_version;
u32 entity_id;
struct list_head entities; //entity 列表
/* Protects the entities list */
spinlock_t lock;
/* Serializes graph operations. */
struct mutex graph_mutex;
int (*link_notify)(struct media_link *link, u32 flags,
unsigned int notification);//link改变后的callback函数
};
在rkisp1_plat_probe函数是初始化rkisp1_device结构体的,里面包含media_device结构,
static int rkisp1_plat_probe(struct platform_device *pdev)
{
……
strlcpy(isp_dev->media_dev.model, "rkisp1",
sizeof(isp_dev->media_dev.model));
isp_dev->media_dev.dev = &pdev->dev;
isp_dev->media_dev.link_notify = rkisp1_pipeline_link_notify;
media_device_register(&isp_dev->media_dev);
rkisp1_register_platform_subdevs (isp_dev);
media_device_register这个是公共函数,
int __must_check __media_device_register(struct media_device *mdev,
struct module *owner)
{
int ret;
if (WARN_ON(mdev->dev == NULL || mdev->model[0] == 0))
return -EINVAL;
mdev->entity_id = 1;
INIT_LIST_HEAD(&mdev->entities);
spin_lock_init(&mdev->lock);
mutex_init(&mdev->graph_mutex);
/* Register the device node. */
mdev->devnode.fops = &media_device_fops;//ioctl函数就在这里
mdev->devnode.parent = mdev->dev;
mdev->devnode.release = media_device_release;
ret = media_devnode_register(&mdev-&g