[PATCH v2 2/3] v4l2-flash-led-class: Create separate sub-devices for indicators

Hans Verkuil hverkuil at xs4all.nl
Thu Aug 10 13:18:03 UTC 2017


On 09/08/17 13:15, Sakari Ailus wrote:
> The V4L2 flash interface allows controlling multiple LEDs through a single
> sub-devices if, and only if, these LEDs are of different types. This
> approach scales badly for flash controllers that drive multiple flash LEDs
> or for LED specific associations. Essentially, the original assumption of a
> LED driver chip that drives a single flash LED and an indicator LED is no
> longer valid.
> 
> Address the matter by registering one sub-device per LED.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus at linux.intel.com>
> Reviewed-by: Jacek Anaszewski <jacek.anaszewski at gmail.com>
> Acked-by: Pavel Machek <pavel at ucw.cz>

Looks good, but I have the same comment about using '= {};' to zero a struct and
the use of IS_ERR instead of IS_ERR_OR_NULL for the return value check of
v4l2_flash_init as in the 1/3 patch.

After updating that you can add my:

Acked-by: Hans Verkuil <hans.verkuil at cisco.com>

Regards,

	Hans

> ---
>  drivers/leds/leds-aat1290.c                    |   4 +-
>  drivers/leds/leds-max77693.c                   |   4 +-
>  drivers/media/v4l2-core/v4l2-flash-led-class.c | 113 +++++++++++++++----------
>  drivers/staging/greybus/light.c                |  23 +++--
>  include/media/v4l2-flash-led-class.h           |  41 ++++++---
>  5 files changed, 117 insertions(+), 68 deletions(-)
> 
> diff --git a/drivers/leds/leds-aat1290.c b/drivers/leds/leds-aat1290.c
> index a21e19297745..424898e6c69d 100644
> --- a/drivers/leds/leds-aat1290.c
> +++ b/drivers/leds/leds-aat1290.c
> @@ -432,7 +432,7 @@ static void aat1290_init_v4l2_flash_config(struct aat1290_led *led,
>  	strlcpy(v4l2_sd_cfg->dev_name, led_cdev->name,
>  		sizeof(v4l2_sd_cfg->dev_name));
>  
> -	s = &v4l2_sd_cfg->torch_intensity;
> +	s = &v4l2_sd_cfg->intensity;
>  	s->min = led->mm_current_scale[0];
>  	s->max = led_cfg->max_mm_current;
>  	s->step = 1;
> @@ -504,7 +504,7 @@ static int aat1290_led_probe(struct platform_device *pdev)
>  
>  	/* Create V4L2 Flash subdev. */
>  	led->v4l2_flash = v4l2_flash_init(dev, of_fwnode_handle(sub_node),
> -					  fled_cdev, NULL, &v4l2_flash_ops,
> +					  fled_cdev, &v4l2_flash_ops,
>  					  &v4l2_sd_cfg);
>  	if (IS_ERR(led->v4l2_flash)) {
>  		ret = PTR_ERR(led->v4l2_flash);
> diff --git a/drivers/leds/leds-max77693.c b/drivers/leds/leds-max77693.c
> index 2d3062d53325..adf0f191f794 100644
> --- a/drivers/leds/leds-max77693.c
> +++ b/drivers/leds/leds-max77693.c
> @@ -856,7 +856,7 @@ static void max77693_init_v4l2_flash_config(struct max77693_sub_led *sub_led,
>  		 "%s %d-%04x", sub_led->fled_cdev.led_cdev.name,
>  		 i2c_adapter_id(i2c->adapter), i2c->addr);
>  
> -	s = &v4l2_sd_cfg->torch_intensity;
> +	s = &v4l2_sd_cfg->intensity;
>  	s->min = TORCH_IOUT_MIN;
>  	s->max = sub_led->fled_cdev.led_cdev.max_brightness * TORCH_IOUT_STEP;
>  	s->step = TORCH_IOUT_STEP;
> @@ -931,7 +931,7 @@ static int max77693_register_led(struct max77693_sub_led *sub_led,
>  
>  	/* Register in the V4L2 subsystem. */
>  	sub_led->v4l2_flash = v4l2_flash_init(dev, of_fwnode_handle(sub_node),
> -					      fled_cdev, NULL, &v4l2_flash_ops,
> +					      fled_cdev, &v4l2_flash_ops,
>  					      &v4l2_sd_cfg);
>  	if (IS_ERR(sub_led->v4l2_flash)) {
>  		ret = PTR_ERR(sub_led->v4l2_flash);
> diff --git a/drivers/media/v4l2-core/v4l2-flash-led-class.c b/drivers/media/v4l2-core/v4l2-flash-led-class.c
> index aabc85dbb8b5..4ceef217de83 100644
> --- a/drivers/media/v4l2-core/v4l2-flash-led-class.c
> +++ b/drivers/media/v4l2-core/v4l2-flash-led-class.c
> @@ -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,10 +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;
> -	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;
> @@ -330,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;
> @@ -485,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,
> @@ -527,19 +529,21 @@ 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 *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);
>  
> -	led_sysfs_disable(led_cdev);
> -	led_trigger_remove(led_cdev);
> +		led_sysfs_disable(led_cdev);
> +		led_trigger_remove(led_cdev);
>  
> -	mutex_unlock(&led_cdev->led_access);
> +		mutex_unlock(&led_cdev->led_access);
> +	}
>  
>  	if (led_cdev_ind) {
>  		mutex_lock(&led_cdev_ind->led_access);
> @@ -556,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);
> @@ -573,21 +579,24 @@ 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 *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);
> +		led_sysfs_enable(led_cdev);
>  
> -	mutex_unlock(&led_cdev->led_access);
> +		mutex_unlock(&led_cdev->led_access);
> +	}
>  
>  	if (led_cdev_ind) {
>  		mutex_lock(&led_cdev_ind->led_access);
> @@ -605,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 *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 || !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);
>  
> @@ -632,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;
> @@ -664,8 +667,26 @@ struct v4l2_flash *v4l2_flash_init(
>  
>  	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;
> diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c
> index 0771db418f84..daeae91bb728 100644
> --- a/drivers/staging/greybus/light.c
> +++ b/drivers/staging/greybus/light.c
> @@ -58,6 +58,7 @@ struct gb_light {
>  	bool			ready;
>  #if IS_REACHABLE(CONFIG_V4L2_FLASH_LED_CLASS)
>  	struct v4l2_flash	*v4l2_flash;
> +	struct v4l2_flash	*v4l2_flash_ind;
>  #endif
>  };
>  
> @@ -534,7 +535,7 @@ static int gb_lights_light_v4l2_register(struct gb_light *light)
>  {
>  	struct gb_connection *connection = get_conn_from_light(light);
>  	struct device *dev = &connection->bundle->dev;
> -	struct v4l2_flash_config sd_cfg = { {0} };
> +	struct v4l2_flash_config sd_cfg = { {0} }, sd_cfg_ind = { {0} };
>  	struct led_classdev_flash *fled;
>  	struct led_classdev *iled = NULL;
>  	struct gb_channel *channel_torch, *channel_ind, *channel_flash;
> @@ -542,12 +543,12 @@ static int gb_lights_light_v4l2_register(struct gb_light *light)
>  	channel_torch = get_channel_from_mode(light, GB_CHANNEL_MODE_TORCH);
>  	if (channel_torch)
>  		__gb_lights_channel_v4l2_config(&channel_torch->intensity_uA,
> -						&sd_cfg.torch_intensity);
> +						&sd_cfg.intensity);
>  
>  	channel_ind = get_channel_from_mode(light, GB_CHANNEL_MODE_INDICATOR);
>  	if (channel_ind) {
>  		__gb_lights_channel_v4l2_config(&channel_ind->intensity_uA,
> -						&sd_cfg.indicator_intensity);
> +						&sd_cfg_ind.intensity);
>  		iled = &channel_ind->fled.led_cdev;
>  	}
>  
> @@ -557,6 +558,8 @@ static int gb_lights_light_v4l2_register(struct gb_light *light)
>  	fled = &channel_flash->fled;
>  
>  	snprintf(sd_cfg.dev_name, sizeof(sd_cfg.dev_name), "%s", light->name);
> +	snprintf(sd_cfg_ind.dev_name, sizeof(sd_cfg_ind.dev_name),
> +		 "%s indicator", light->name);
>  
>  	/* Set the possible values to faults, in our case all faults */
>  	sd_cfg.flash_faults = LED_FAULT_OVER_VOLTAGE | LED_FAULT_TIMEOUT |
> @@ -565,16 +568,26 @@ static int gb_lights_light_v4l2_register(struct gb_light *light)
>  		LED_FAULT_UNDER_VOLTAGE | LED_FAULT_INPUT_VOLTAGE |
>  		LED_FAULT_LED_OVER_TEMPERATURE;
>  
> -	light->v4l2_flash = v4l2_flash_init(dev, NULL, fled, iled,
> -					    &v4l2_flash_ops, &sd_cfg);
> +	light->v4l2_flash = v4l2_flash_init(dev, NULL, fled, &v4l2_flash_ops,
> +					    &sd_cfg);
>  	if (IS_ERR_OR_NULL(light->v4l2_flash))
>  		return PTR_ERR(light->v4l2_flash);
>  
> +	if (channel_ind) {
> +		light->v4l2_flash_ind =
> +			v4l2_flash_indicator_init(dev, NULL, iled, &sd_cfg_ind);
> +		if (IS_ERR_OR_NULL(light->v4l2_flash_ind)) {
> +			v4l2_flash_release(light->v4l2_flash);
> +			return PTR_ERR(light->v4l2_flash_ind);
> +		}
> +	}
> +
>  	return 0;
>  }
>  
>  static void gb_lights_light_v4l2_unregister(struct gb_light *light)
>  {
> +	v4l2_flash_release(light->v4l2_flash_ind);
>  	v4l2_flash_release(light->v4l2_flash);
>  }
>  #else
> diff --git a/include/media/v4l2-flash-led-class.h b/include/media/v4l2-flash-led-class.h
> index 54e31a805a88..c3f39992f3fa 100644
> --- a/include/media/v4l2-flash-led-class.h
> +++ b/include/media/v4l2-flash-led-class.h
> @@ -56,8 +56,7 @@ struct v4l2_flash_ops {
>   * struct v4l2_flash_config - V4L2 Flash sub-device initialization data
>   * @dev_name:			the name of the media entity,
>   *				unique in the system
> - * @torch_intensity:		constraints for the LED in torch mode
> - * @indicator_intensity:	constraints for the indicator LED
> + * @intensity:			non-flash strobe constraints for the LED
>   * @flash_faults:		bitmask of flash faults that the LED flash class
>   *				device can report; corresponding LED_FAULT* bit
>   *				definitions are available in the header file
> @@ -66,8 +65,7 @@ struct v4l2_flash_ops {
>   */
>  struct v4l2_flash_config {
>  	char dev_name[32];
> -	struct led_flash_setting torch_intensity;
> -	struct led_flash_setting indicator_intensity;
> +	struct led_flash_setting intensity;
>  	u32 flash_faults;
>  	unsigned int has_external_strobe:1;
>  };
> @@ -110,8 +108,6 @@ static inline struct v4l2_flash *v4l2_ctrl_to_v4l2_flash(struct v4l2_ctrl *c)
>   * @dev:	flash device, e.g. an I2C device
>   * @fwn:	fwnode_handle of the LED, may be NULL if the same as device's
>   * @fled_cdev:	LED flash class device to wrap
> - * @iled_cdev:	LED flash class device representing indicator LED associated
> - *		with fled_cdev, may be NULL
>   * @ops:	V4L2 Flash device ops
>   * @config:	initialization data for V4L2 Flash sub-device
>   *
> @@ -124,9 +120,24 @@ static inline struct v4l2_flash *v4l2_ctrl_to_v4l2_flash(struct v4l2_ctrl *c)
>  struct v4l2_flash *v4l2_flash_init(
>  	struct device *dev, struct fwnode_handle *fwn,
>  	struct led_classdev_flash *fled_cdev,
> -	struct led_classdev *iled_cdev,
> -	const struct v4l2_flash_ops *ops,
> -	struct v4l2_flash_config *config);
> +	const struct v4l2_flash_ops *ops, struct v4l2_flash_config *config);
> +
> +/**
> + * v4l2_flash_indicator_init - initialize V4L2 indicator sub-device
> + * @dev:	flash device, e.g. an I2C device
> + * @fwn:	fwnode_handle of the LED, may be NULL if the same as device's
> + * @iled_cdev:	LED flash class device representing the indicator LED
> + * @config:	initialization data for V4L2 Flash sub-device
> + *
> + * Create V4L2 Flash sub-device wrapping given LED subsystem device.
> + *
> + * Returns: A valid pointer, or, when an error occurs, the return
> + * value is encoded using ERR_PTR(). Use IS_ERR() to check and
> + * PTR_ERR() to obtain the numeric return value.
> + */
> +struct v4l2_flash *v4l2_flash_indicator_init(
> +	struct device *dev, struct fwnode_handle *fwn,
> +	struct led_classdev *iled_cdev, struct v4l2_flash_config *config);
>  
>  /**
>   * v4l2_flash_release - release V4L2 Flash sub-device
> @@ -139,10 +150,14 @@ void v4l2_flash_release(struct v4l2_flash *v4l2_flash);
>  #else
>  static inline struct v4l2_flash *v4l2_flash_init(
>  	struct device *dev, struct fwnode_handle *fwn,
> -	struct led_classdev_flash *fled_cdev,
> -	struct led_classdev *iled_cdev,
> -	const struct v4l2_flash_ops *ops,
> -	struct v4l2_flash_config *config)
> +	struct led_classdev_flash *fled_cdev, struct v4l2_flash_config *config)
> +{
> +	return NULL;
> +}
> +
> +static inline 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 NULL;
>  }
> 



More information about the devel mailing list