Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] v4l2-subdev: add (un)register internal ops

Some subdevs need to call into the board code after they are registered
and have a valid struct v4l2_device pointer. The s_config op was abused
for this, but now that it is removed we need a cleaner way of solving this.

So this patch adds a struct with internal ops that the v4l2 core can call.

Currently only two ops exist: register and unregister. Subdevs can implement
these to call the board code and pass it the v4l2_device pointer, which the
board code can then use to get access to the struct that embeds the
v4l2_device.

It is expected that in the future open and close ops will also be added.

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

authored by

Hans Verkuil and committed by
Mauro Carvalho Chehab
45f6f84a 3c7c9370

+29 -2
+12 -2
drivers/media/video/v4l2-device.c
··· 126 126 WARN_ON(sd->v4l2_dev != NULL); 127 127 if (!try_module_get(sd->owner)) 128 128 return -ENODEV; 129 + sd->v4l2_dev = v4l2_dev; 130 + if (sd->internal_ops && sd->internal_ops->registered) { 131 + err = sd->internal_ops->registered(sd); 132 + if (err) 133 + return err; 134 + } 129 135 /* This just returns 0 if either of the two args is NULL */ 130 136 err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler); 131 - if (err) 137 + if (err) { 138 + if (sd->internal_ops && sd->internal_ops->unregistered) 139 + sd->internal_ops->unregistered(sd); 132 140 return err; 133 - sd->v4l2_dev = v4l2_dev; 141 + } 134 142 spin_lock(&v4l2_dev->lock); 135 143 list_add_tail(&sd->list, &v4l2_dev->subdevs); 136 144 spin_unlock(&v4l2_dev->lock); ··· 154 146 spin_lock(&sd->v4l2_dev->lock); 155 147 list_del(&sd->list); 156 148 spin_unlock(&sd->v4l2_dev->lock); 149 + if (sd->internal_ops && sd->internal_ops->unregistered) 150 + sd->internal_ops->unregistered(sd); 157 151 sd->v4l2_dev = NULL; 158 152 module_put(sd->owner); 159 153 }
+17
include/media/v4l2-subdev.h
··· 411 411 const struct v4l2_subdev_sensor_ops *sensor; 412 412 }; 413 413 414 + /* 415 + * Internal ops. Never call this from drivers, only the v4l2 framework can call 416 + * these ops. 417 + * 418 + * registered: called when this subdev is registered. When called the v4l2_dev 419 + * field is set to the correct v4l2_device. 420 + * 421 + * unregistered: called when this subdev is unregistered. When called the 422 + * v4l2_dev field is still set to the correct v4l2_device. 423 + */ 424 + struct v4l2_subdev_internal_ops { 425 + int (*registered)(struct v4l2_subdev *sd); 426 + void (*unregistered)(struct v4l2_subdev *sd); 427 + }; 428 + 414 429 #define V4L2_SUBDEV_NAME_SIZE 32 415 430 416 431 /* Set this flag if this subdev is a i2c device. */ ··· 442 427 u32 flags; 443 428 struct v4l2_device *v4l2_dev; 444 429 const struct v4l2_subdev_ops *ops; 430 + /* Never call these internal ops from within a driver! */ 431 + const struct v4l2_subdev_internal_ops *internal_ops; 445 432 /* The control handler of this subdev. May be NULL. */ 446 433 struct v4l2_ctrl_handler *ctrl_handler; 447 434 /* name must be unique */