Switch to using the sub-device state lock and properly call v4l2_subdev_init_finalize() / v4l2_subdev_cleanup() on probe() / remove(). While at it also properly setup runtime-pm before registering the subdev. Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx> --- drivers/media/i2c/ov02c10.c | 51 +++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/drivers/media/i2c/ov02c10.c b/drivers/media/i2c/ov02c10.c index 09e70ffcf07a..c559a69140ec 100644 --- a/drivers/media/i2c/ov02c10.c +++ b/drivers/media/i2c/ov02c10.c @@ -2,7 +2,6 @@ // Copyright (c) 2022 Intel Corporation. #include <linux/acpi.h> -#include <linux/cleanup.h> #include <linux/clk.h> #include <linux/delay.h> #include <linux/gpio/consumer.h> @@ -387,9 +386,6 @@ struct ov02c10 { /* Current mode */ const struct ov02c10_mode *cur_mode; - /* To serialize asynchronous callbacks */ - struct mutex mutex; - /* MIPI lane info */ u32 link_freq_index; u8 mipi_lanes; @@ -490,7 +486,6 @@ static int ov02c10_init_controls(struct ov02c10 *ov02c10) if (ret) return ret; - ctrl_hdlr->lock = &ov02c10->mutex; cur_mode = ov02c10->cur_mode; ov02c10->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, @@ -608,8 +603,6 @@ static int ov02c10_enable_streams(struct v4l2_subdev *sd, struct ov02c10 *ov02c10 = to_ov02c10(sd); int ret; - guard(mutex)(&ov02c10->mutex); - ret = pm_runtime_resume_and_get(&client->dev); if (ret) return ret; @@ -628,8 +621,6 @@ static int ov02c10_disable_streams(struct v4l2_subdev *sd, struct i2c_client *client = v4l2_get_subdevdata(sd); struct ov02c10 *ov02c10 = to_ov02c10(sd); - guard(mutex)(&ov02c10->mutex); - ov02c10_stop_streaming(ov02c10); pm_runtime_put(&client->dev); @@ -718,7 +709,6 @@ static int ov02c10_set_format(struct v4l2_subdev *sd, height, fmt->format.width, fmt->format.height); - mutex_lock(&ov02c10->mutex); ov02c10_update_pad_format(mode, &fmt->format); if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { *v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format; @@ -736,7 +726,6 @@ static int ov02c10_set_format(struct v4l2_subdev *sd, __v4l2_ctrl_modify_range(ov02c10->hblank, h_blank, h_blank, 1, h_blank); } - mutex_unlock(&ov02c10->mutex); return 0; } @@ -747,14 +736,11 @@ static int ov02c10_get_format(struct v4l2_subdev *sd, { struct ov02c10 *ov02c10 = to_ov02c10(sd); - mutex_lock(&ov02c10->mutex); if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) fmt->format = *v4l2_subdev_state_get_format(sd_state, fmt->pad); else ov02c10_update_pad_format(ov02c10->cur_mode, &fmt->format); - mutex_unlock(&ov02c10->mutex); - return 0; } @@ -909,13 +895,16 @@ static int ov02c10_check_hwcfg(struct device *dev, struct ov02c10 *ov02c10) static void ov02c10_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct ov02c10 *ov02c10 = to_ov02c10(sd); v4l2_async_unregister_subdev(sd); + v4l2_subdev_cleanup(sd); media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); pm_runtime_disable(&client->dev); - mutex_destroy(&ov02c10->mutex); + if (!pm_runtime_status_suspended(&client->dev)) { + ov02c10_power_off(&client->dev); + pm_runtime_set_suspended(&client->dev); + } } static int ov02c10_probe(struct i2c_client *client) @@ -951,10 +940,9 @@ static int ov02c10_probe(struct i2c_client *client) ret = ov02c10_identify_module(ov02c10); if (ret) { dev_err(&client->dev, "failed to find sensor: %d", ret); - goto probe_error_ret; + goto probe_error_power_off; } - mutex_init(&ov02c10->mutex); ov02c10->cur_mode = &supported_modes[0]; ret = ov02c10_init_controls(ov02c10); @@ -974,31 +962,38 @@ static int ov02c10_probe(struct i2c_client *client) goto probe_error_v4l2_ctrl_handler_free; } + ov02c10->sd.state_lock = ov02c10->ctrl_handler.lock; + ret = v4l2_subdev_init_finalize(&ov02c10->sd); + if (ret < 0) { + dev_err(&client->dev, "failed to init subdev: %d", ret); + goto probe_error_media_entity_cleanup; + } + + pm_runtime_set_active(&client->dev); + pm_runtime_enable(&client->dev); + ret = v4l2_async_register_subdev_sensor(&ov02c10->sd); if (ret < 0) { dev_err(&client->dev, "failed to register V4L2 subdev: %d", ret); - goto probe_error_media_entity_cleanup; + goto probe_error_v4l2_subdev_cleanup; } - /* - * Device is already turned on by i2c-core with ACPI domain PM. - * Enable runtime PM and turn off the device. - */ - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); pm_runtime_idle(&client->dev); - return 0; +probe_error_v4l2_subdev_cleanup: + pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); + v4l2_subdev_cleanup(&ov02c10->sd); + probe_error_media_entity_cleanup: media_entity_cleanup(&ov02c10->sd.entity); probe_error_v4l2_ctrl_handler_free: v4l2_ctrl_handler_free(ov02c10->sd.ctrl_handler); - mutex_destroy(&ov02c10->mutex); -probe_error_ret: +probe_error_power_off: ov02c10_power_off(&client->dev); return ret; -- 2.48.1