On 09/06/2015 02:03 PM, Mauro Carvalho Chehab wrote:
> V4L2 device (and subdevice) nodes should create an interface, if the
> Media Controller support is enabled.
>
> Please notice that radio devices should not create an entity, as radio
> input/output is either via wires or via ALSA.
>
> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
>
> diff --git a/drivers/media/v4l2-core/v4l2-dev.c
> b/drivers/media/v4l2-core/v4l2-dev.c
> index 44b330589787..07123dd569c4 100644
> --- a/drivers/media/v4l2-core/v4l2-dev.c
> +++ b/drivers/media/v4l2-core/v4l2-dev.c
> @@ -194,9 +194,12 @@ static void v4l2_device_release(struct device *cd)
> mutex_unlock(&videodev_lock);
>
> #if defined(CONFIG_MEDIA_CONTROLLER)
> - if (v4l2_dev->mdev &&
> - vdev->vfl_type != VFL_TYPE_SUBDEV)
> - media_device_unregister_entity(&vdev->entity);
> + if (v4l2_dev->mdev) {
> + /* Remove interfaces and interface links */
> + media_devnode_remove(vdev->intf_devnode);
> + if (vdev->entity.type != MEDIA_ENT_T_UNKNOWN)
> + media_device_unregister_entity(&vdev->entity);
> + }
> #endif
>
> /* Do not call v4l2_device_put if there is no release callback set.
> @@ -713,6 +716,92 @@ static void determine_valid_ioctls(struct video_device
> *vdev)
> BASE_VIDIOC_PRIVATE);
> }
>
> +
> +static int video_register_media_controller(struct video_device *vdev, int
> type)
> +{
> +#if defined(CONFIG_MEDIA_CONTROLLER)
> + u32 intf_type;
> + int ret;
> +
> + if (!vdev->v4l2_dev->mdev)
> + return 0;
> +
> + vdev->entity.type = MEDIA_ENT_T_UNKNOWN;
> +
> + switch (type) {
> + case VFL_TYPE_GRABBER:
> + intf_type = MEDIA_INTF_T_V4L_VIDEO;
> + vdev->entity.type = MEDIA_ENT_T_V4L2_VIDEO;
> + break;
> + case VFL_TYPE_VBI:
> + intf_type = MEDIA_INTF_T_V4L_VBI;
> + vdev->entity.type = MEDIA_ENT_T_V4L2_VBI;
> + break;
> + case VFL_TYPE_SDR:
> + intf_type = MEDIA_INTF_T_V4L_SWRADIO;
> + vdev->entity.type = MEDIA_ENT_T_V4L2_SWRADIO;
> + break;
> + case VFL_TYPE_RADIO:
> + intf_type = MEDIA_INTF_T_V4L_RADIO;
> + /*
> + * Radio doesn't have an entity at the V4L2 side to represent
> + * radio input or output. Instead, the audio input/output goes
> + * via either physical wires or ALSA.
> + */
> + break;
> + case VFL_TYPE_SUBDEV:
> + intf_type = MEDIA_INTF_T_V4L_SUBDEV;
> + /* Entity will be created via v4l2_device_register_subdev() */
> + break;
> + default:
> + return 0;
> + }
> +
> + if (vdev->entity.type != MEDIA_ENT_T_UNKNOWN) {
> + vdev->entity.name = vdev->name;
> +
> + /* Needed just for backward compatibility with legacy MC API */
> + vdev->entity.info.dev.major = VIDEO_MAJOR;
> + vdev->entity.info.dev.minor = vdev->minor;
> +
> + ret = media_device_register_entity(vdev->v4l2_dev->mdev,
> + &vdev->entity);
> + if (ret < 0) {
> + printk(KERN_WARNING
> + "%s: media_device_register_entity failed\n",
> + __func__);
> + return ret;
> + }
> + }
> +
> + vdev->intf_devnode = media_devnode_create(vdev->v4l2_dev->mdev,
> + intf_type,
> + 0, VIDEO_MAJOR,
> + vdev->minor,
> + GFP_KERNEL);
> + if (!vdev->intf_devnode) {
> + media_device_unregister_entity(&vdev->entity);
> + return -ENOMEM;
> + }
> +
> + if (vdev->entity.type != MEDIA_ENT_T_UNKNOWN) {
> + struct media_link *link;
> +
> + link = media_create_intf_link(&vdev->entity,
> + &vdev->intf_devnode->intf, 0);
> + if (!link) {
> + media_devnode_remove(vdev->intf_devnode);
> + media_device_unregister_entity(&vdev->entity);
> + return -ENOMEM;
> + }
> + }
> +
> + /* FIXME: how to create the other interface links? */
> +
> +#endif
> + return 0;
> +}
> +
> /**
> * __video_register_device - register video4linux devices
> * @vdev: video device structure we want to register
> @@ -908,22 +997,9 @@ int __video_register_device(struct video_device *vdev,
> int type, int nr,
> /* Increase v4l2_device refcount */
> v4l2_device_get(vdev->v4l2_dev);
>
> -#if defined(CONFIG_MEDIA_CONTROLLER)
> /* Part 5: Register the entity. */
> - if (vdev->v4l2_dev->mdev &&
> - vdev->vfl_type != VFL_TYPE_SUBDEV) {
> - vdev->entity.type = MEDIA_ENT_T_V4L2_VIDEO;
> - vdev->entity.name = vdev->name;
> - vdev->entity.info.dev.major = VIDEO_MAJOR;
> - vdev->entity.info.dev.minor = vdev->minor;
> - ret = media_device_register_entity(vdev->v4l2_dev->mdev,
> - &vdev->entity);
> - if (ret < 0)
> - printk(KERN_WARNING
> - "%s: media_device_register_entity failed\n",
> - __func__);
> - }
> -#endif
> + ret = video_register_media_controller(vdev, type);
> +
This is weird. The 'ret' value is ignored. This was also the case in the
original
code, but I don't see why it is ignored. I think that if this fails, then an
error
should be returned. Otherwise you'll have an incomplete media graph.
Regards,
Hans
> /* Part 6: Activate this minor. The char device can now be used. */
> set_bit(V4L2_FL_REGISTERED, &vdev->flags);
>
> diff --git a/drivers/media/v4l2-core/v4l2-device.c
> b/drivers/media/v4l2-core/v4l2-device.c
> index 5b0a30b9252b..e788a085ba96 100644
> --- a/drivers/media/v4l2-core/v4l2-device.c
> +++ b/drivers/media/v4l2-core/v4l2-device.c
> @@ -249,6 +249,17 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device
> *v4l2_dev)
> #if defined(CONFIG_MEDIA_CONTROLLER)
> sd->entity.info.dev.major = VIDEO_MAJOR;
> sd->entity.info.dev.minor = vdev->minor;
> +
> + /* Interface is created by __video_register_device() */
> + if (vdev->v4l2_dev->mdev) {
> + struct media_link *link;
> +
> + link = media_create_intf_link(&sd->entity,
> + &vdev->intf_devnode->intf,
> + 0);
> + if (!link)
> + goto clean_up;
> + }
> #endif
> sd->devnode = vdev;
> }
> @@ -285,7 +296,10 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev
> *sd)
>
> #if defined(CONFIG_MEDIA_CONTROLLER)
> if (v4l2_dev->mdev) {
> - media_entity_remove_links(&sd->entity);
> + /*
> + * No need to explicitly remove links, as both pads and
> + * links are removed by the function below, in the right order
> + */
> media_device_unregister_entity(&sd->entity);
> }
> #endif
> diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
> index acbcd2f5fe7f..eeabf20e87a6 100644
> --- a/include/media/v4l2-dev.h
> +++ b/include/media/v4l2-dev.h
> @@ -86,6 +86,7 @@ struct video_device
> {
> #if defined(CONFIG_MEDIA_CONTROLLER)
> struct media_entity entity;
> + struct media_intf_devnode *intf_devnode;
> #endif
> /* device ops */
> const struct v4l2_file_operations *fops;
>
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html