summaryrefslogtreecommitdiff
path: root/drivers/media/v4l2-core/v4l2-flash-led-class.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-flash-led-class.c')
-rw-r--r--drivers/media/v4l2-core/v4l2-flash-led-class.c139
1 files changed, 77 insertions, 62 deletions
diff --git a/drivers/media/v4l2-core/v4l2-flash-led-class.c b/drivers/media/v4l2-core/v4l2-flash-led-class.c
index 7b8288108e8a..4ceef217de83 100644
--- a/drivers/media/v4l2-core/v4l2-flash-led-class.c
+++ b/drivers/media/v4l2-core/v4l2-flash-led-class.c
@@ -18,7 +18,7 @@
#include <media/v4l2-flash-led-class.h>
#define has_flash_op(v4l2_flash, op) \
- (v4l2_flash && v4l2_flash->ops->op)
+ (v4l2_flash && v4l2_flash->ops && v4l2_flash->ops->op)
#define call_flash_op(v4l2_flash, op, arg) \
(has_flash_op(v4l2_flash, op) ? \
@@ -110,7 +110,7 @@ static void v4l2_flash_set_led_brightness(struct v4l2_flash *v4l2_flash,
led_set_brightness_sync(&v4l2_flash->fled_cdev->led_cdev,
brightness);
} else {
- led_set_brightness_sync(&v4l2_flash->iled_cdev->led_cdev,
+ led_set_brightness_sync(v4l2_flash->iled_cdev,
brightness);
}
}
@@ -133,7 +133,7 @@ static int v4l2_flash_update_led_brightness(struct v4l2_flash *v4l2_flash,
return 0;
led_cdev = &v4l2_flash->fled_cdev->led_cdev;
} else {
- led_cdev = &v4l2_flash->iled_cdev->led_cdev;
+ led_cdev = v4l2_flash->iled_cdev;
}
ret = led_update_brightness(led_cdev);
@@ -197,7 +197,7 @@ static int v4l2_flash_s_ctrl(struct v4l2_ctrl *c)
{
struct v4l2_flash *v4l2_flash = v4l2_ctrl_to_v4l2_flash(c);
struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
- struct led_classdev *led_cdev = &fled_cdev->led_cdev;
+ struct led_classdev *led_cdev = fled_cdev ? &fled_cdev->led_cdev : NULL;
struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
bool external_strobe;
int ret = 0;
@@ -299,11 +299,26 @@ static void __fill_ctrl_init_data(struct v4l2_flash *v4l2_flash,
struct v4l2_flash_ctrl_data *ctrl_init_data)
{
struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
- const struct led_flash_ops *fled_cdev_ops = fled_cdev->ops;
- struct led_classdev *led_cdev = &fled_cdev->led_cdev;
+ struct led_classdev *led_cdev = fled_cdev ? &fled_cdev->led_cdev : NULL;
struct v4l2_ctrl_config *ctrl_cfg;
u32 mask;
+ /* Init INDICATOR_INTENSITY ctrl data */
+ if (v4l2_flash->iled_cdev) {
+ ctrl_init_data[INDICATOR_INTENSITY].cid =
+ V4L2_CID_FLASH_INDICATOR_INTENSITY;
+ ctrl_cfg = &ctrl_init_data[INDICATOR_INTENSITY].config;
+ __lfs_to_v4l2_ctrl_config(&flash_cfg->intensity,
+ ctrl_cfg);
+ ctrl_cfg->id = V4L2_CID_FLASH_INDICATOR_INTENSITY;
+ ctrl_cfg->min = 0;
+ ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE |
+ V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
+ }
+
+ if (!led_cdev || WARN_ON(!(led_cdev->flags & LED_DEV_CAP_FLASH)))
+ return;
+
/* Init FLASH_FAULT ctrl data */
if (flash_cfg->flash_faults) {
ctrl_init_data[FLASH_FAULT].cid = V4L2_CID_FLASH_FAULT;
@@ -331,27 +346,11 @@ static void __fill_ctrl_init_data(struct v4l2_flash *v4l2_flash,
/* Init TORCH_INTENSITY ctrl data */
ctrl_init_data[TORCH_INTENSITY].cid = V4L2_CID_FLASH_TORCH_INTENSITY;
ctrl_cfg = &ctrl_init_data[TORCH_INTENSITY].config;
- __lfs_to_v4l2_ctrl_config(&flash_cfg->torch_intensity, ctrl_cfg);
+ __lfs_to_v4l2_ctrl_config(&flash_cfg->intensity, ctrl_cfg);
ctrl_cfg->id = V4L2_CID_FLASH_TORCH_INTENSITY;
ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE |
V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
- /* Init INDICATOR_INTENSITY ctrl data */
- if (v4l2_flash->iled_cdev) {
- ctrl_init_data[INDICATOR_INTENSITY].cid =
- V4L2_CID_FLASH_INDICATOR_INTENSITY;
- ctrl_cfg = &ctrl_init_data[INDICATOR_INTENSITY].config;
- __lfs_to_v4l2_ctrl_config(&flash_cfg->indicator_intensity,
- ctrl_cfg);
- ctrl_cfg->id = V4L2_CID_FLASH_INDICATOR_INTENSITY;
- ctrl_cfg->min = 0;
- ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE |
- V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
- }
-
- if (!(led_cdev->flags & LED_DEV_CAP_FLASH))
- return;
-
/* Init FLASH_STROBE ctrl data */
ctrl_init_data[FLASH_STROBE].cid = V4L2_CID_FLASH_STROBE;
ctrl_cfg = &ctrl_init_data[FLASH_STROBE].config;
@@ -376,7 +375,7 @@ static void __fill_ctrl_init_data(struct v4l2_flash *v4l2_flash,
}
/* Init STROBE_STATUS ctrl data */
- if (fled_cdev_ops->strobe_get) {
+ if (has_flash_op(fled_cdev, strobe_get)) {
ctrl_init_data[STROBE_STATUS].cid =
V4L2_CID_FLASH_STROBE_STATUS;
ctrl_cfg = &ctrl_init_data[STROBE_STATUS].config;
@@ -386,7 +385,7 @@ static void __fill_ctrl_init_data(struct v4l2_flash *v4l2_flash,
}
/* Init FLASH_TIMEOUT ctrl data */
- if (fled_cdev_ops->timeout_set) {
+ if (has_flash_op(fled_cdev, timeout_set)) {
ctrl_init_data[FLASH_TIMEOUT].cid = V4L2_CID_FLASH_TIMEOUT;
ctrl_cfg = &ctrl_init_data[FLASH_TIMEOUT].config;
__lfs_to_v4l2_ctrl_config(&fled_cdev->timeout, ctrl_cfg);
@@ -394,7 +393,7 @@ static void __fill_ctrl_init_data(struct v4l2_flash *v4l2_flash,
}
/* Init FLASH_INTENSITY ctrl data */
- if (fled_cdev_ops->flash_brightness_set) {
+ if (has_flash_op(fled_cdev, flash_brightness_set)) {
ctrl_init_data[FLASH_INTENSITY].cid = V4L2_CID_FLASH_INTENSITY;
ctrl_cfg = &ctrl_init_data[FLASH_INTENSITY].config;
__lfs_to_v4l2_ctrl_config(&fled_cdev->brightness, ctrl_cfg);
@@ -486,7 +485,9 @@ static int __sync_device_with_v4l2_controls(struct v4l2_flash *v4l2_flash)
struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
int ret = 0;
- v4l2_flash_set_led_brightness(v4l2_flash, ctrls[TORCH_INTENSITY]);
+ if (ctrls[TORCH_INTENSITY])
+ v4l2_flash_set_led_brightness(v4l2_flash,
+ ctrls[TORCH_INTENSITY]);
if (ctrls[INDICATOR_INTENSITY])
v4l2_flash_set_led_brightness(v4l2_flash,
@@ -528,24 +529,23 @@ static int v4l2_flash_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct v4l2_flash *v4l2_flash = v4l2_subdev_to_v4l2_flash(sd);
struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
- struct led_classdev *led_cdev = &fled_cdev->led_cdev;
- struct led_classdev_flash *iled_cdev = v4l2_flash->iled_cdev;
- struct led_classdev *led_cdev_ind = NULL;
+ struct led_classdev *led_cdev = fled_cdev ? &fled_cdev->led_cdev : NULL;
+ struct led_classdev *led_cdev_ind = v4l2_flash->iled_cdev;
int ret = 0;
if (!v4l2_fh_is_singular(&fh->vfh))
return 0;
- mutex_lock(&led_cdev->led_access);
-
- led_sysfs_disable(led_cdev);
- led_trigger_remove(led_cdev);
+ if (led_cdev) {
+ mutex_lock(&led_cdev->led_access);
- mutex_unlock(&led_cdev->led_access);
+ led_sysfs_disable(led_cdev);
+ led_trigger_remove(led_cdev);
- if (iled_cdev) {
- led_cdev_ind = &iled_cdev->led_cdev;
+ mutex_unlock(&led_cdev->led_access);
+ }
+ if (led_cdev_ind) {
mutex_lock(&led_cdev_ind->led_access);
led_sysfs_disable(led_cdev_ind);
@@ -560,9 +560,11 @@ static int v4l2_flash_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
return 0;
out_sync_device:
- mutex_lock(&led_cdev->led_access);
- led_sysfs_enable(led_cdev);
- mutex_unlock(&led_cdev->led_access);
+ if (led_cdev) {
+ mutex_lock(&led_cdev->led_access);
+ led_sysfs_enable(led_cdev);
+ mutex_unlock(&led_cdev->led_access);
+ }
if (led_cdev_ind) {
mutex_lock(&led_cdev_ind->led_access);
@@ -577,25 +579,26 @@ static int v4l2_flash_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct v4l2_flash *v4l2_flash = v4l2_subdev_to_v4l2_flash(sd);
struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
- struct led_classdev *led_cdev = &fled_cdev->led_cdev;
- struct led_classdev_flash *iled_cdev = v4l2_flash->iled_cdev;
+ struct led_classdev *led_cdev = fled_cdev ? &fled_cdev->led_cdev : NULL;
+ struct led_classdev *led_cdev_ind = v4l2_flash->iled_cdev;
int ret = 0;
if (!v4l2_fh_is_singular(&fh->vfh))
return 0;
- mutex_lock(&led_cdev->led_access);
+ if (led_cdev) {
+ mutex_lock(&led_cdev->led_access);
- if (v4l2_flash->ctrls[STROBE_SOURCE])
- ret = v4l2_ctrl_s_ctrl(v4l2_flash->ctrls[STROBE_SOURCE],
+ if (v4l2_flash->ctrls[STROBE_SOURCE])
+ ret = v4l2_ctrl_s_ctrl(
+ v4l2_flash->ctrls[STROBE_SOURCE],
V4L2_FLASH_STROBE_SOURCE_SOFTWARE);
- led_sysfs_enable(led_cdev);
-
- mutex_unlock(&led_cdev->led_access);
+ led_sysfs_enable(led_cdev);
- if (iled_cdev) {
- struct led_classdev *led_cdev_ind = &iled_cdev->led_cdev;
+ mutex_unlock(&led_cdev->led_access);
+ }
+ if (led_cdev_ind) {
mutex_lock(&led_cdev_ind->led_access);
led_sysfs_enable(led_cdev_ind);
mutex_unlock(&led_cdev_ind->led_access);
@@ -611,25 +614,19 @@ static const struct v4l2_subdev_internal_ops v4l2_flash_subdev_internal_ops = {
static const struct v4l2_subdev_ops v4l2_flash_subdev_ops;
-struct v4l2_flash *v4l2_flash_init(
+static struct v4l2_flash *__v4l2_flash_init(
struct device *dev, struct fwnode_handle *fwn,
- struct led_classdev_flash *fled_cdev,
- struct led_classdev_flash *iled_cdev,
- const struct v4l2_flash_ops *ops,
- struct v4l2_flash_config *config)
+ struct led_classdev_flash *fled_cdev, struct led_classdev *iled_cdev,
+ const struct v4l2_flash_ops *ops, struct v4l2_flash_config *config)
{
struct v4l2_flash *v4l2_flash;
- struct led_classdev *led_cdev;
struct v4l2_subdev *sd;
int ret;
- if (!fled_cdev || !ops || !config)
+ if (!config)
return ERR_PTR(-EINVAL);
- led_cdev = &fled_cdev->led_cdev;
-
- v4l2_flash = devm_kzalloc(led_cdev->dev, sizeof(*v4l2_flash),
- GFP_KERNEL);
+ v4l2_flash = devm_kzalloc(dev, sizeof(*v4l2_flash), GFP_KERNEL);
if (!v4l2_flash)
return ERR_PTR(-ENOMEM);
@@ -638,7 +635,7 @@ struct v4l2_flash *v4l2_flash_init(
v4l2_flash->iled_cdev = iled_cdev;
v4l2_flash->ops = ops;
sd->dev = dev;
- sd->fwnode = fwn ? fwn : dev_fwnode(led_cdev->dev);
+ sd->fwnode = fwn ? fwn : dev_fwnode(dev);
v4l2_subdev_init(sd, &v4l2_flash_subdev_ops);
sd->internal_ops = &v4l2_flash_subdev_internal_ops;
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
@@ -670,8 +667,26 @@ err_init_controls:
return ERR_PTR(ret);
}
+
+struct v4l2_flash *v4l2_flash_init(
+ struct device *dev, struct fwnode_handle *fwn,
+ struct led_classdev_flash *fled_cdev,
+ const struct v4l2_flash_ops *ops,
+ struct v4l2_flash_config *config)
+{
+ return __v4l2_flash_init(dev, fwn, fled_cdev, NULL, ops, config);
+}
EXPORT_SYMBOL_GPL(v4l2_flash_init);
+struct v4l2_flash *v4l2_flash_indicator_init(
+ struct device *dev, struct fwnode_handle *fwn,
+ struct led_classdev *iled_cdev,
+ struct v4l2_flash_config *config)
+{
+ return __v4l2_flash_init(dev, fwn, NULL, iled_cdev, NULL, config);
+}
+EXPORT_SYMBOL_GPL(v4l2_flash_indicator_init);
+
void v4l2_flash_release(struct v4l2_flash *v4l2_flash)
{
struct v4l2_subdev *sd;