@@ -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;
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@redhat.com> --- drivers/media/i2c/ov02c10.c | 51 +++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 28 deletions(-)