summaryrefslogtreecommitdiff
path: root/drivers/media/v4l2-core
diff options
context:
space:
mode:
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);