diff options
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-flash-led-class.c')
-rw-r--r-- | drivers/media/v4l2-core/v4l2-flash-led-class.c | 139 |
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; |