Switch from s_stream() to enable_streams() and disable_streams() pad operations. They are preferred and required for streams support. Note this also stops calling ov02c10_stop_streaming() on enable_streams() errors. If ov02c10_start_streaming() fails OV02C10_REG_STREAM_CONTROL bit 0 will have never been set so there is no need to clear it on errors. Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx> --- drivers/media/i2c/ov02c10.c | 59 +++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/drivers/media/i2c/ov02c10.c b/drivers/media/i2c/ov02c10.c index a46cacf301a2..da727e18a282 100644 --- a/drivers/media/i2c/ov02c10.c +++ b/drivers/media/i2c/ov02c10.c @@ -2,6 +2,7 @@ // 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> @@ -602,41 +603,45 @@ static void ov02c10_stop_streaming(struct ov02c10 *ov02c10) cci_write(ov02c10->regmap, OV02C10_REG_STREAM_CONTROL, 0, NULL); } -static int ov02c10_set_stream(struct v4l2_subdev *sd, int enable) +static int ov02c10_enable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + u32 pad, u64 streams_mask) { - struct ov02c10 *ov02c10 = to_ov02c10(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); - int ret = 0; + struct ov02c10 *ov02c10 = to_ov02c10(sd); + int ret; - if (ov02c10->streaming == enable) - return 0; + guard(mutex)(&ov02c10->mutex); - mutex_lock(&ov02c10->mutex); - if (enable) { - ret = pm_runtime_get_sync(&client->dev); - if (ret < 0) { - pm_runtime_put_noidle(&client->dev); - mutex_unlock(&ov02c10->mutex); - return ret; - } + ret = pm_runtime_resume_and_get(&client->dev); + if (ret) + return ret; - ret = ov02c10_start_streaming(ov02c10); - if (ret) { - enable = 0; - ov02c10_stop_streaming(ov02c10); - pm_runtime_put(&client->dev); - } - } else { - ov02c10_stop_streaming(ov02c10); + ret = ov02c10_start_streaming(ov02c10); + if (ret == 0) + ov02c10->streaming = true; + else pm_runtime_put(&client->dev); - } - - ov02c10->streaming = enable; - mutex_unlock(&ov02c10->mutex); return ret; } +static int ov02c10_disable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + u32 pad, u64 streams_mask) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ov02c10 *ov02c10 = to_ov02c10(sd); + + guard(mutex)(&ov02c10->mutex); + + ov02c10_stop_streaming(ov02c10); + ov02c10->streaming = false; + pm_runtime_put(&client->dev); + + return 0; +} + /* This function tries to get power control resources */ static int ov02c10_get_pm_resources(struct device *dev) { @@ -836,7 +841,7 @@ static int ov02c10_init_state(struct v4l2_subdev *sd, } static const struct v4l2_subdev_video_ops ov02c10_video_ops = { - .s_stream = ov02c10_set_stream, + .s_stream = v4l2_subdev_s_stream_helper, }; static const struct v4l2_subdev_pad_ops ov02c10_pad_ops = { @@ -844,6 +849,8 @@ static const struct v4l2_subdev_pad_ops ov02c10_pad_ops = { .get_fmt = ov02c10_get_format, .enum_mbus_code = ov02c10_enum_mbus_code, .enum_frame_size = ov02c10_enum_frame_size, + .enable_streams = ov02c10_enable_streams, + .disable_streams = ov02c10_disable_streams, }; static const struct v4l2_subdev_ops ov02c10_subdev_ops = { -- 2.48.1