aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/v4l2-core
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-01-13 11:46:37 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-13 11:46:37 -0800
commit77a76b04d2be1c45b8fd746b7ef754525029340c (patch)
treeef5db67c07d538a43d160847acefe80f3c049dba /drivers/media/v4l2-core
parentMerge tag 'spi-v4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi (diff)
parent[media] Postpone the addition of MEDIA_IOC_G_TOPOLOGY (diff)
downloadlinux-dev-77a76b04d2be1c45b8fd746b7ef754525029340c.tar.xz
linux-dev-77a76b04d2be1c45b8fd746b7ef754525029340c.zip
Merge tag 'media/v4.5-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull second batch of media updates from Mauro Carvalho Chehab: "This is the second part of the media patches. It contains the media controller next generation patches, with is the result of one year of discussions and development. It also contains patches to enable media controller support at the DVB subsystem. The goal is to improve the media controller to allow proper support for other types of Video4Linux devices (radio and TV ones) and to extend the media controller functionality to allow it to be used by other subsystems like DVB, ALSA and IIO. In order to use the new functionality, a new ioctl is needed (MEDIA_IOC_G_TOPOLOGY). As we're still discussing how to pack the struct fields of this ioctl in order to avoid compat32 issues, I decided to add a patch at the end of this series commenting out the new ioctl, in order to postpone the addition of the new ioctl to the next Kernel version (4.6). With that, no userspace visible changes should happen at the media controller API, as the existing ioctls are untouched. Yet, it helps DVB, ALSA and IIO developers to develop and test the patches adding media controller support there, as the core will contain all required internal changes to allow adding support for devices that belong to those subsystems" * tag 'media/v4.5-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (177 commits) [media] Postpone the addition of MEDIA_IOC_G_TOPOLOGY [media] mxl111sf: Add a tuner entity [media] dvbdev: create links on devices with multiple frontends [media] media-entitiy: add a function to create multiple links [media] dvb-usb-v2: postpone removal of media_device [media] dvbdev: Add RF connector if needed [media] dvbdev: remove two dead functions if !CONFIG_MEDIA_CONTROLLER_DVB [media] call media_device_init() before registering the V4L2 device [media] uapi/media.h: Use u32 for the number of graph objects [media] media-entity: don't sleep at media_device_register_entity() [media] media-entity: increase max number of PADs [media] media-entity.h: document the remaining functions [media] media-device.h: use just one u32 counter for object ID [media] media-entity.h fix documentation for several parameters [media] DocBook: document media_entity_graph_walk_cleanup() [media] move documentation to the header files [media] media: Move MEDIA_ENTITY_MAX_PADS from media-entity.h to media-entity.c [media] media: Remove pre-allocated entity enumeration bitmap [media] staging: v4l: davinci_vpbe: Use the new media graph walk interface [media] staging: v4l: omap4iss: Use the new media graph walk interface ...
Diffstat (limited to 'drivers/media/v4l2-core')
-rw-r--r--drivers/media/v4l2-core/tuner-core.c10
-rw-r--r--drivers/media/v4l2-core/v4l2-dev.c111
-rw-r--r--drivers/media/v4l2-core/v4l2-device.c39
-rw-r--r--drivers/media/v4l2-core/v4l2-flash-led-class.c4
-rw-r--r--drivers/media/v4l2-core/v4l2-subdev.c8
5 files changed, 133 insertions, 39 deletions
diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c
index 581e21ad6801..76496fd282aa 100644
--- a/drivers/media/v4l2-core/tuner-core.c
+++ b/drivers/media/v4l2-core/tuner-core.c
@@ -134,8 +134,9 @@ struct tuner {
unsigned int type; /* chip type id */
void *config;
const char *name;
+
#if defined(CONFIG_MEDIA_CONTROLLER)
- struct media_pad pad;
+ struct media_pad pad[TUNER_NUM_PADS];
#endif
};
@@ -695,11 +696,12 @@ static int tuner_probe(struct i2c_client *client,
/* Should be just before return */
register_client:
#if defined(CONFIG_MEDIA_CONTROLLER)
- t->pad.flags = MEDIA_PAD_FL_SOURCE;
- t->sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_TUNER;
+ t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK;
+ t->pad[TUNER_PAD_IF_OUTPUT].flags = MEDIA_PAD_FL_SOURCE;
+ t->sd.entity.function = MEDIA_ENT_F_TUNER;
t->sd.entity.name = t->name;
- ret = media_entity_init(&t->sd.entity, 1, &t->pad, 0);
+ ret = media_entity_pads_init(&t->sd.entity, TUNER_NUM_PADS, &t->pad[0]);
if (ret < 0) {
tuner_err("failed to initialize media entity!\n");
kfree(t);
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index 6b1eaeddbdb3..d8e5994cccf1 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.function != MEDIA_ENT_F_UNKNOWN)
+ media_device_unregister_entity(&vdev->entity);
+ }
#endif
/* 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);
}
+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.function = MEDIA_ENT_F_UNKNOWN;
+
+ switch (type) {
+ case VFL_TYPE_GRABBER:
+ intf_type = MEDIA_INTF_T_V4L_VIDEO;
+ vdev->entity.function = MEDIA_ENT_F_IO_V4L;
+ break;
+ case VFL_TYPE_VBI:
+ intf_type = MEDIA_INTF_T_V4L_VBI;
+ vdev->entity.function = MEDIA_ENT_F_IO_VBI;
+ break;
+ case VFL_TYPE_SDR:
+ intf_type = MEDIA_INTF_T_V4L_SWRADIO;
+ vdev->entity.function = MEDIA_ENT_F_IO_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.function != MEDIA_ENT_F_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);
+ if (!vdev->intf_devnode) {
+ media_device_unregister_entity(&vdev->entity);
+ return -ENOMEM;
+ }
+
+ if (vdev->entity.function != MEDIA_ENT_F_UNKNOWN) {
+ struct media_link *link;
+
+ link = media_create_intf_link(&vdev->entity,
+ &vdev->intf_devnode->intf,
+ MEDIA_LNK_FL_ENABLED);
+ 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
@@ -918,22 +1006,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_DEVNODE_V4L;
- 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);
+
/* 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 7129e438f29e..06fa5f1b2cff 100644
--- a/drivers/media/v4l2-core/v4l2-device.c
+++ b/drivers/media/v4l2-core/v4l2-device.c
@@ -180,26 +180,26 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
return -ENODEV;
sd->v4l2_dev = v4l2_dev;
- if (sd->internal_ops && sd->internal_ops->registered) {
- err = sd->internal_ops->registered(sd);
- if (err)
- goto error_module;
- }
-
/* This just returns 0 if either of the two args is NULL */
err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler, NULL);
if (err)
- goto error_unregister;
+ goto error_module;
#if defined(CONFIG_MEDIA_CONTROLLER)
/* Register the entity. */
if (v4l2_dev->mdev) {
err = media_device_register_entity(v4l2_dev->mdev, entity);
if (err < 0)
- goto error_unregister;
+ goto error_module;
}
#endif
+ if (sd->internal_ops && sd->internal_ops->registered) {
+ err = sd->internal_ops->registered(sd);
+ if (err)
+ goto error_unregister;
+ }
+
spin_lock(&v4l2_dev->lock);
list_add_tail(&sd->list, &v4l2_dev->subdevs);
spin_unlock(&v4l2_dev->lock);
@@ -207,8 +207,9 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
return 0;
error_unregister:
- if (sd->internal_ops && sd->internal_ops->unregistered)
- sd->internal_ops->unregistered(sd);
+#if defined(CONFIG_MEDIA_CONTROLLER)
+ media_device_unregister_entity(entity);
+#endif
error_module:
if (!sd->owner_v4l2_dev)
module_put(sd->owner);
@@ -258,6 +259,19 @@ 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,
+ MEDIA_LNK_FL_ENABLED);
+ if (!link) {
+ err = -ENOMEM;
+ goto clean_up;
+ }
+ }
#endif
sd->devnode = vdev;
}
@@ -294,7 +308,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/drivers/media/v4l2-core/v4l2-flash-led-class.c b/drivers/media/v4l2-core/v4l2-flash-led-class.c
index 5d673357f75f..fc5ff8b215f9 100644
--- a/drivers/media/v4l2-core/v4l2-flash-led-class.c
+++ b/drivers/media/v4l2-core/v4l2-flash-led-class.c
@@ -651,11 +651,11 @@ struct v4l2_flash *v4l2_flash_init(
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
strlcpy(sd->name, config->dev_name, sizeof(sd->name));
- ret = media_entity_init(&sd->entity, 0, NULL, 0);
+ ret = media_entity_pads_init(&sd->entity, 0, NULL);
if (ret < 0)
return ERR_PTR(ret);
- sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH;
+ sd->entity.function = MEDIA_ENT_F_FLASH;
ret = v4l2_flash_init_controls(v4l2_flash, config);
if (ret < 0)
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 83615b8fb46a..d63083803144 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -526,7 +526,7 @@ static int
v4l2_subdev_link_validate_get_format(struct media_pad *pad,
struct v4l2_subdev_format *fmt)
{
- if (media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV) {
+ if (is_media_entity_v4l2_subdev(pad->entity)) {
struct v4l2_subdev *sd =
media_entity_to_v4l2_subdev(pad->entity);
@@ -535,9 +535,9 @@ v4l2_subdev_link_validate_get_format(struct media_pad *pad,
return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt);
}
- WARN(pad->entity->type != MEDIA_ENT_T_DEVNODE_V4L,
+ WARN(pad->entity->function != MEDIA_ENT_F_IO_V4L,
"Driver bug! Wrong media entity type 0x%08x, entity %s\n",
- pad->entity->type, pad->entity->name);
+ pad->entity->function, pad->entity->name);
return -EINVAL;
}
@@ -584,7 +584,7 @@ void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)
sd->host_priv = NULL;
#if defined(CONFIG_MEDIA_CONTROLLER)
sd->entity.name = sd->name;
- sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+ sd->entity.function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN;
#endif
}
EXPORT_SYMBOL(v4l2_subdev_init);