[media] v4l2-core: create MC interfaces for devnodes
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. Acked-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
This commit is contained in:
Родитель
f50d51661a
Коммит
d9c21e3e4b
|
@ -194,9 +194,12 @@ static void v4l2_device_release(struct device *cd)
|
||||||
mutex_unlock(&videodev_lock);
|
mutex_unlock(&videodev_lock);
|
||||||
|
|
||||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||||
if (v4l2_dev->mdev &&
|
if (v4l2_dev->mdev) {
|
||||||
vdev->vfl_type != VFL_TYPE_SUBDEV)
|
/* Remove interfaces and interface links */
|
||||||
media_device_unregister_entity(&vdev->entity);
|
media_devnode_remove(vdev->intf_devnode);
|
||||||
|
if (vdev->entity.type != MEDIA_ENT_T_UNKNOWN)
|
||||||
|
media_device_unregister_entity(&vdev->entity);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Do not call v4l2_device_put if there is no release callback set.
|
/* Do not call v4l2_device_put if there is no release callback set.
|
||||||
|
@ -723,6 +726,91 @@ static void determine_valid_ioctls(struct video_device *vdev)
|
||||||
BASE_VIDIOC_PRIVATE);
|
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
|
* __video_register_device - register video4linux devices
|
||||||
* @vdev: video device structure we want to register
|
* @vdev: video device structure we want to register
|
||||||
|
@ -918,22 +1006,9 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
|
||||||
/* Increase v4l2_device refcount */
|
/* Increase v4l2_device refcount */
|
||||||
v4l2_device_get(vdev->v4l2_dev);
|
v4l2_device_get(vdev->v4l2_dev);
|
||||||
|
|
||||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
|
||||||
/* Part 5: Register the entity. */
|
/* Part 5: Register the entity. */
|
||||||
if (vdev->v4l2_dev->mdev &&
|
ret = video_register_media_controller(vdev, type);
|
||||||
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
|
|
||||||
/* Part 6: Activate this minor. The char device can now be used. */
|
/* Part 6: Activate this minor. The char device can now be used. */
|
||||||
set_bit(V4L2_FL_REGISTERED, &vdev->flags);
|
set_bit(V4L2_FL_REGISTERED, &vdev->flags);
|
||||||
|
|
||||||
|
|
|
@ -258,6 +258,17 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
|
||||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||||
sd->entity.info.dev.major = VIDEO_MAJOR;
|
sd->entity.info.dev.major = VIDEO_MAJOR;
|
||||||
sd->entity.info.dev.minor = vdev->minor;
|
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
|
#endif
|
||||||
sd->devnode = vdev;
|
sd->devnode = vdev;
|
||||||
}
|
}
|
||||||
|
@ -294,7 +305,10 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)
|
||||||
|
|
||||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||||
if (v4l2_dev->mdev) {
|
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);
|
media_device_unregister_entity(&sd->entity);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -86,6 +86,7 @@ struct video_device
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||||
struct media_entity entity;
|
struct media_entity entity;
|
||||||
|
struct media_intf_devnode *intf_devnode;
|
||||||
#endif
|
#endif
|
||||||
/* device ops */
|
/* device ops */
|
||||||
const struct v4l2_file_operations *fops;
|
const struct v4l2_file_operations *fops;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче