diff options
author | Hans de Goede <hdegoede@redhat.com> | 2023-01-27 21:37:25 +0100 |
---|---|---|
committer | Hans de Goede <hdegoede@redhat.com> | 2023-02-03 10:22:34 +0100 |
commit | b6e10ff6c23deb7f01d342875f7a69bae067c3c8 (patch) | |
tree | e667cbb632bf0562f14b9d0ef795223749bac20e /drivers/media/v4l2-core/v4l2-subdev.c | |
parent | 39f09320500c74a9777fc274d15acd3f0bac41ae (diff) |
media: v4l2-core: Make the v4l2-core code enable/disable the privacy LED if present
Make v4l2_async_register_subdev_sensor() try to get a privacy LED
associated with the sensor and extend the call_s_stream() wrapper to
enable/disable the privacy LED if found.
This makes the core handle privacy LED control, rather then having to
duplicate this code in all the sensor drivers.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Link: https://lore.kernel.org/r/20230127203729.10205-2-hdegoede@redhat.com
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-subdev.c')
-rw-r--r-- | drivers/media/v4l2-core/v4l2-subdev.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 4988a25bd8f4..6630fb30bc7d 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -9,6 +9,7 @@ */ #include <linux/ioctl.h> +#include <linux/leds.h> #include <linux/mm.h> #include <linux/module.h> #include <linux/slab.h> @@ -23,6 +24,8 @@ #include <media/v4l2-fh.h> #include <media/v4l2-event.h> +#include "v4l2-subdev-priv.h" + #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd) { @@ -322,6 +325,15 @@ static int call_s_stream(struct v4l2_subdev *sd, int enable) { int ret; +#if IS_REACHABLE(CONFIG_LEDS_CLASS) + if (!IS_ERR_OR_NULL(sd->privacy_led)) { + if (enable) + led_set_brightness(sd->privacy_led, + sd->privacy_led->max_brightness); + else + led_set_brightness(sd->privacy_led, 0); + } +#endif ret = sd->ops->video->s_stream(sd, enable); if (!enable && ret < 0) { @@ -1090,6 +1102,7 @@ void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops) sd->grp_id = 0; sd->dev_priv = NULL; sd->host_priv = NULL; + sd->privacy_led = NULL; #if defined(CONFIG_MEDIA_CONTROLLER) sd->entity.name = sd->name; sd->entity.obj_type = MEDIA_ENTITY_TYPE_V4L2_SUBDEV; @@ -1105,3 +1118,36 @@ void v4l2_subdev_notify_event(struct v4l2_subdev *sd, v4l2_subdev_notify(sd, V4L2_DEVICE_NOTIFY_EVENT, (void *)ev); } EXPORT_SYMBOL_GPL(v4l2_subdev_notify_event); + +int v4l2_subdev_get_privacy_led(struct v4l2_subdev *sd) +{ +#if IS_REACHABLE(CONFIG_LEDS_CLASS) + sd->privacy_led = led_get(sd->dev, "privacy-led"); + if (IS_ERR(sd->privacy_led) && PTR_ERR(sd->privacy_led) != -ENOENT) + return dev_err_probe(sd->dev, PTR_ERR(sd->privacy_led), + "getting privacy LED\n"); + + if (!IS_ERR_OR_NULL(sd->privacy_led)) { + mutex_lock(&sd->privacy_led->led_access); + led_sysfs_disable(sd->privacy_led); + led_trigger_remove(sd->privacy_led); + led_set_brightness(sd->privacy_led, 0); + mutex_unlock(&sd->privacy_led->led_access); + } +#endif + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_subdev_get_privacy_led); + +void v4l2_subdev_put_privacy_led(struct v4l2_subdev *sd) +{ +#if IS_REACHABLE(CONFIG_LEDS_CLASS) + if (!IS_ERR_OR_NULL(sd->privacy_led)) { + mutex_lock(&sd->privacy_led->led_access); + led_sysfs_enable(sd->privacy_led); + mutex_unlock(&sd->privacy_led->led_access); + led_put(sd->privacy_led); + } +#endif +} +EXPORT_SYMBOL_GPL(v4l2_subdev_put_privacy_led); |