admin 管理员组

文章数量: 1086019

xilinx

查看设备结构体:

struct xvip_composite_device {struct v4l2_device v4l2_dev;struct media_device media_dev;struct device *dev;struct v4l2_async_notifier notifier;struct list_head entities;unsigned int num_subdevs;struct list_head dmas;u32 v4l2_caps;
};

由上面可知xvipp为一个v4l2设备,同时将其加入media框架中,notifier为v4l2同步子设备的通知器,即子设备被注册后,通知消息将会添加到该结构体中。同时定一个entites链表,用来保存整个pipeline通路上的实体。同时定义一个DMA通道的链表。

下面看一下probe函数:

static int xvip_composite_probe(struct platform_device *pdev)
{struct xvip_composite_device *xdev;int ret;xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL);if (!xdev)return -ENOMEM;xdev->dev = &pdev->dev;INIT_LIST_HEAD(&xdev->entities);INIT_LIST_HEAD(&xdev->dmas);ret = xvip_composite_v4l2_init(xdev);if (ret < 0)return ret;ret = xvip_graph_init(xdev);if (ret < 0)goto error;platform_set_drvdata(pdev, xdev);dev_info(xdev->dev, "device registered\n");return 0;error:xvip_composite_v4l2_cleanup(xdev);return ret;
}

xvip_composite_v4l2_init函数中将media设备和v4l2设备进行了注册。

xvip_graph_init函数中,初始化DMA通道,即上一篇博客中的xilinx_dma设备。接着解析praph并抽取子设备设备树节点的列表,填充entites字段。然后注册子设备通知器v4l2_async_notifier_register,在该函数中,假设子设备匹配较晚,则在链表中获取不到已有的子设备注册,此时将通知消息加入notifier_list链表中,待子设备驱动端获取;若已有子设备注册,则会执行v4l2_async_test_notify函数:

static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier,struct v4l2_subdev *sd,struct v4l2_async_subdev *asd)
{int ret;if (notifier->bound) {ret = notifier->bound(notifier, sd, asd);if (ret < 0)return ret;}ret = v4l2_device_register_subdev(notifier->v4l2_dev, sd);if (ret < 0) {if (notifier->unbind)notifier->unbind(notifier, sd, asd);return ret;}/* Remove from the waiting list */list_del(&asd->list);sd->asd = asd;sd->notifier = notifier;/* Move from the global subdevice list to notifier's done */list_move(&sd->async_list, &notifier->done);if (list_empty(&notifier->waiting) && notifier->complete)return notifier->complete(notifier);return 0;

这里回调bound和执行v4l2_device_register_subdev把子设备注册到v4l2核心层。

在我们的项目中子设备(python1300_core、rxif)的注册都晚于xvip设备,在子设备中,通过v4l2_async_register_subdev进行注册:

int v4l2_async_register_subdev(struct v4l2_subdev *sd)
{struct v4l2_async_notifier *notifier;mutex_lock(&list_lock);INIT_LIST_HEAD(&sd->async_list);list_for_each_entry(notifier, &notifier_list, list) {struct v4l2_async_subdev *asd = v4l2_async_belongs(notifier, sd);if (asd) {int ret = v4l2_async_test_notify(notifier, sd, asd);mutex_unlock(&list_lock);return ret;}}/* None matched, wait for hot-plugging */list_add(&sd->async_list, &subdev_list);mutex_unlock(&list_lock);return 0;
}

这里操作与上面v4l2_async_notifier_register互补关系;不管谁先谁后注册,最后都将实现v4l2_async_test_notify函数操作。

xilinx定义xvip_composite_device这个虚拟物体的目的就是方便对设备的统一的管理,作为这个驱动的v4l2设备管理着python_core和rxif两个子设备。而在应用层操作需要关心的是xilinx-dma.c中的dma通道设备,因为其被注册为video_device设备。

本文标签: xilinx