media: i2c: lm3560: Fix v4l2 subdev registration

The existing driver does not call media subdev registration, making it
invisible to the media framework. Since the LM3560 supports two
independent LEDs, register each LED as a separate media entity.

Because registering LEDs before device initialization may cause access
attempts before the hardware is ready, lm3560_init_device has been moved
before the subdevice initializations.

An additional helper, lm3560_subdev_cleanup, was added to release LED0 if
the initialization of LED1 fails, and to deregister both LEDs in the
remove function.

Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
This commit is contained in:
Svyatoslav Ryhel 2026-05-06 09:48:43 +03:00 committed by Sakari Ailus
parent 621e4f762e
commit 38547c3d87

View File

@ -364,8 +364,15 @@ static int lm3560_subdev_init(struct lm3560_flash *flash,
goto err_out;
flash->subdev_led[led_no].entity.function = MEDIA_ENT_F_FLASH;
return rval;
rval = v4l2_async_register_subdev(&flash->subdev_led[led_no]);
if (rval < 0) {
dev_err(flash->dev, "failed to register V4L2 subdev");
goto error_out_media;
}
return rval;
error_out_media:
media_entity_cleanup(&flash->subdev_led[led_no].entity);
err_out:
v4l2_ctrl_handler_free(&flash->ctrls_led[led_no]);
return rval;
@ -391,6 +398,14 @@ static int lm3560_init_device(struct lm3560_flash *flash)
return rval;
}
static void lm3560_subdev_cleanup(struct lm3560_flash *flash,
enum lm3560_led_id led_no)
{
v4l2_async_unregister_subdev(&flash->subdev_led[led_no]);
v4l2_ctrl_handler_free(&flash->ctrls_led[led_no]);
media_entity_cleanup(&flash->subdev_led[led_no].entity);
}
static int lm3560_probe(struct i2c_client *client)
{
struct lm3560_flash *flash;
@ -425,17 +440,19 @@ static int lm3560_probe(struct i2c_client *client)
flash->dev = &client->dev;
mutex_init(&flash->lock);
rval = lm3560_init_device(flash);
if (rval < 0)
return rval;
rval = lm3560_subdev_init(flash, LM3560_LED0, "lm3560-led0");
if (rval < 0)
return rval;
rval = lm3560_subdev_init(flash, LM3560_LED1, "lm3560-led1");
if (rval < 0)
return rval;
rval = lm3560_init_device(flash);
if (rval < 0)
if (rval < 0) {
lm3560_subdev_cleanup(flash, LM3560_LED0);
return rval;
}
i2c_set_clientdata(client, flash);
@ -447,11 +464,8 @@ static void lm3560_remove(struct i2c_client *client)
struct lm3560_flash *flash = i2c_get_clientdata(client);
unsigned int i;
for (i = LM3560_LED0; i < LM3560_LED_MAX; i++) {
v4l2_device_unregister_subdev(&flash->subdev_led[i]);
v4l2_ctrl_handler_free(&flash->ctrls_led[i]);
media_entity_cleanup(&flash->subdev_led[i].entity);
}
for (i = LM3560_LED0; i < LM3560_LED_MAX; i++)
lm3560_subdev_cleanup(flash, i);
}
static const struct i2c_device_id lm3560_id_table[] = {