linux/drivers/media/v4l2-core/v4l2-device.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3    V4L2 device support.
   4
   5    Copyright (C) 2008  Hans Verkuil <hverkuil@xs4all.nl>
   6
   7 */
   8
   9#include <linux/types.h>
  10#include <linux/ioctl.h>
  11#include <linux/module.h>
  12#include <linux/i2c.h>
  13#include <linux/slab.h>
  14#if defined(CONFIG_SPI)
  15#include <linux/spi/spi.h>
  16#endif
  17#include <linux/videodev2.h>
  18#include <media/v4l2-device.h>
  19#include <media/v4l2-ctrls.h>
  20
  21int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
  22{
  23        if (v4l2_dev == NULL)
  24                return -EINVAL;
  25
  26        INIT_LIST_HEAD(&v4l2_dev->subdevs);
  27        spin_lock_init(&v4l2_dev->lock);
  28        v4l2_prio_init(&v4l2_dev->prio);
  29        kref_init(&v4l2_dev->ref);
  30        get_device(dev);
  31        v4l2_dev->dev = dev;
  32        if (dev == NULL) {
  33                /* If dev == NULL, then name must be filled in by the caller */
  34                if (WARN_ON(!v4l2_dev->name[0]))
  35                        return -EINVAL;
  36                return 0;
  37        }
  38
  39        /* Set name to driver name + device name if it is empty. */
  40        if (!v4l2_dev->name[0])
  41                snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s",
  42                        dev->driver->name, dev_name(dev));
  43        if (!dev_get_drvdata(dev))
  44                dev_set_drvdata(dev, v4l2_dev);
  45        return 0;
  46}
  47EXPORT_SYMBOL_GPL(v4l2_device_register);
  48
  49static void v4l2_device_release(struct kref *ref)
  50{
  51        struct v4l2_device *v4l2_dev =
  52                container_of(ref, struct v4l2_device, ref);
  53
  54        if (v4l2_dev->release)
  55                v4l2_dev->release(v4l2_dev);
  56}
  57
  58int v4l2_device_put(struct v4l2_device *v4l2_dev)
  59{
  60        return kref_put(&v4l2_dev->ref, v4l2_device_release);
  61}
  62EXPORT_SYMBOL_GPL(v4l2_device_put);
  63
  64int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename,
  65                                                atomic_t *instance)
  66{
  67        int num = atomic_inc_return(instance) - 1;
  68        int len = strlen(basename);
  69
  70        if (basename[len - 1] >= '0' && basename[len - 1] <= '9')
  71                snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
  72                                "%s-%d", basename, num);
  73        else
  74                snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
  75                                "%s%d", basename, num);
  76        return num;
  77}
  78EXPORT_SYMBOL_GPL(v4l2_device_set_name);
  79
  80void v4l2_device_disconnect(struct v4l2_device *v4l2_dev)
  81{
  82        if (v4l2_dev->dev == NULL)
  83                return;
  84
  85        if (dev_get_drvdata(v4l2_dev->dev) == v4l2_dev)
  86                dev_set_drvdata(v4l2_dev->dev, NULL);
  87        put_device(v4l2_dev->dev);
  88        v4l2_dev->dev = NULL;
  89}
  90EXPORT_SYMBOL_GPL(v4l2_device_disconnect);
  91
  92void v4l2_device_unregister(struct v4l2_device *v4l2_dev)
  93{
  94        struct v4l2_subdev *sd, *next;
  95
  96        /* Just return if v4l2_dev is NULL or if it was already
  97         * unregistered before. */
  98        if (v4l2_dev == NULL || !v4l2_dev->name[0])
  99                return;
 100        v4l2_device_disconnect(v4l2_dev);
 101
 102        /* Unregister subdevs */
 103        list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) {
 104                v4l2_device_unregister_subdev(sd);
 105#if IS_ENABLED(CONFIG_I2C)
 106                if (sd->flags & V4L2_SUBDEV_FL_IS_I2C) {
 107                        struct i2c_client *client = v4l2_get_subdevdata(sd);
 108
 109                        /*
 110                         * We need to unregister the i2c client
 111                         * explicitly. We cannot rely on
 112                         * i2c_del_adapter to always unregister
 113                         * clients for us, since if the i2c bus is a
 114                         * platform bus, then it is never deleted.
 115                         *
 116                         * Device tree or ACPI based devices must not
 117                         * be unregistered as they have not been
 118                         * registered by us, and would not be
 119                         * re-created by just probing the V4L2 driver.
 120                         */
 121                        if (client &&
 122                            !client->dev.of_node && !client->dev.fwnode)
 123                                i2c_unregister_device(client);
 124                        continue;
 125                }
 126#endif
 127#if defined(CONFIG_SPI)
 128                if (sd->flags & V4L2_SUBDEV_FL_IS_SPI) {
 129                        struct spi_device *spi = v4l2_get_subdevdata(sd);
 130
 131                        if (spi && !spi->dev.of_node && !spi->dev.fwnode)
 132                                spi_unregister_device(spi);
 133                        continue;
 134                }
 135#endif
 136        }
 137        /* Mark as unregistered, thus preventing duplicate unregistrations */
 138        v4l2_dev->name[0] = '\0';
 139}
 140EXPORT_SYMBOL_GPL(v4l2_device_unregister);
 141
 142int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
 143                                struct v4l2_subdev *sd)
 144{
 145#if defined(CONFIG_MEDIA_CONTROLLER)
 146        struct media_entity *entity = &sd->entity;
 147#endif
 148        int err;
 149
 150        /* Check for valid input */
 151        if (!v4l2_dev || !sd || sd->v4l2_dev || !sd->name[0])
 152                return -EINVAL;
 153
 154        /*
 155         * The reason to acquire the module here is to avoid unloading
 156         * a module of sub-device which is registered to a media
 157         * device. To make it possible to unload modules for media
 158         * devices that also register sub-devices, do not
 159         * try_module_get() such sub-device owners.
 160         */
 161        sd->owner_v4l2_dev = v4l2_dev->dev && v4l2_dev->dev->driver &&
 162                sd->owner == v4l2_dev->dev->driver->owner;
 163
 164        if (!sd->owner_v4l2_dev && !try_module_get(sd->owner))
 165                return -ENODEV;
 166
 167        sd->v4l2_dev = v4l2_dev;
 168        /* This just returns 0 if either of the two args is NULL */
 169        err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler,
 170                                    NULL, true);
 171        if (err)
 172                goto error_module;
 173
 174#if defined(CONFIG_MEDIA_CONTROLLER)
 175        /* Register the entity. */
 176        if (v4l2_dev->mdev) {
 177                err = media_device_register_entity(v4l2_dev->mdev, entity);
 178                if (err < 0)
 179                        goto error_module;
 180        }
 181#endif
 182
 183        if (sd->internal_ops && sd->internal_ops->registered) {
 184                err = sd->internal_ops->registered(sd);
 185                if (err)
 186                        goto error_unregister;
 187        }
 188
 189        spin_lock(&v4l2_dev->lock);
 190        list_add_tail(&sd->list, &v4l2_dev->subdevs);
 191        spin_unlock(&v4l2_dev->lock);
 192
 193        return 0;
 194
 195error_unregister:
 196#if defined(CONFIG_MEDIA_CONTROLLER)
 197        media_device_unregister_entity(entity);
 198#endif
 199error_module:
 200        if (!sd->owner_v4l2_dev)
 201                module_put(sd->owner);
 202        sd->v4l2_dev = NULL;
 203        return err;
 204}
 205EXPORT_SYMBOL_GPL(v4l2_device_register_subdev);
 206
 207static void v4l2_subdev_release(struct v4l2_subdev *sd)
 208{
 209        struct module *owner = !sd->owner_v4l2_dev ? sd->owner : NULL;
 210
 211        if (sd->internal_ops && sd->internal_ops->release)
 212                sd->internal_ops->release(sd);
 213        module_put(owner);
 214}
 215
 216static void v4l2_device_release_subdev_node(struct video_device *vdev)
 217{
 218        v4l2_subdev_release(video_get_drvdata(vdev));
 219        kfree(vdev);
 220}
 221
 222int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
 223{
 224        struct video_device *vdev;
 225        struct v4l2_subdev *sd;
 226        int err;
 227
 228        /* Register a device node for every subdev marked with the
 229         * V4L2_SUBDEV_FL_HAS_DEVNODE flag.
 230         */
 231        list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
 232                if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE))
 233                        continue;
 234
 235                if (sd->devnode)
 236                        continue;
 237
 238                vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
 239                if (!vdev) {
 240                        err = -ENOMEM;
 241                        goto clean_up;
 242                }
 243
 244                video_set_drvdata(vdev, sd);
 245                strscpy(vdev->name, sd->name, sizeof(vdev->name));
 246                vdev->dev_parent = sd->dev;
 247                vdev->v4l2_dev = v4l2_dev;
 248                vdev->fops = &v4l2_subdev_fops;
 249                vdev->release = v4l2_device_release_subdev_node;
 250                vdev->ctrl_handler = sd->ctrl_handler;
 251                err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
 252                                              sd->owner);
 253                if (err < 0) {
 254                        kfree(vdev);
 255                        goto clean_up;
 256                }
 257                sd->devnode = vdev;
 258#if defined(CONFIG_MEDIA_CONTROLLER)
 259                sd->entity.info.dev.major = VIDEO_MAJOR;
 260                sd->entity.info.dev.minor = vdev->minor;
 261
 262                /* Interface is created by __video_register_device() */
 263                if (vdev->v4l2_dev->mdev) {
 264                        struct media_link *link;
 265
 266                        link = media_create_intf_link(&sd->entity,
 267                                                      &vdev->intf_devnode->intf,
 268                                                      MEDIA_LNK_FL_ENABLED |
 269                                                      MEDIA_LNK_FL_IMMUTABLE);
 270                        if (!link) {
 271                                err = -ENOMEM;
 272                                goto clean_up;
 273                        }
 274                }
 275#endif
 276        }
 277        return 0;
 278
 279clean_up:
 280        list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
 281                if (!sd->devnode)
 282                        break;
 283                video_unregister_device(sd->devnode);
 284        }
 285
 286        return err;
 287}
 288EXPORT_SYMBOL_GPL(v4l2_device_register_subdev_nodes);
 289
 290void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)
 291{
 292        struct v4l2_device *v4l2_dev;
 293
 294        /* return if it isn't registered */
 295        if (sd == NULL || sd->v4l2_dev == NULL)
 296                return;
 297
 298        v4l2_dev = sd->v4l2_dev;
 299
 300        spin_lock(&v4l2_dev->lock);
 301        list_del(&sd->list);
 302        spin_unlock(&v4l2_dev->lock);
 303
 304        if (sd->internal_ops && sd->internal_ops->unregistered)
 305                sd->internal_ops->unregistered(sd);
 306        sd->v4l2_dev = NULL;
 307
 308#if defined(CONFIG_MEDIA_CONTROLLER)
 309        if (v4l2_dev->mdev) {
 310                /*
 311                 * No need to explicitly remove links, as both pads and
 312                 * links are removed by the function below, in the right order
 313                 */
 314                media_device_unregister_entity(&sd->entity);
 315        }
 316#endif
 317        if (sd->devnode)
 318                video_unregister_device(sd->devnode);
 319        else
 320                v4l2_subdev_release(sd);
 321}
 322EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);
 323