summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Zapolskiy <vladimir.zapolskiy@linaro.org>2026-02-26 16:37:35 +0300
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>2026-03-11 03:05:36 +0300
commit3a594bb454ba1ecb005f753007fa1bb5c5e68bae (patch)
tree7bc2d900d846a0864a42cd91bc5bcc00f29336b4
parent535b7f106991c7d8f0e5b8e1769bfb8b1ce9d3d6 (diff)
downloadlinux-3a594bb454ba1ecb005f753007fa1bb5c5e68bae.tar.xz
media: i2c: og01a1b: Switch from .s_stream to .enable_streams/.disable_streams
The change allows to simplify the driver code, in particular the explicit locking scheme for stream on/off or format update serialization can be dropped in favour to the one provided by the V4L2 core internals. Signed-off-by: Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org> [Sakari Ailus: Fix error handling for enable_streams callback.] Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
-rw-r--r--drivers/media/i2c/og01a1b.c90
1 files changed, 34 insertions, 56 deletions
diff --git a/drivers/media/i2c/og01a1b.c b/drivers/media/i2c/og01a1b.c
index 7b892b26203c..4b6b9ac24594 100644
--- a/drivers/media/i2c/og01a1b.c
+++ b/drivers/media/i2c/og01a1b.c
@@ -442,9 +442,6 @@ struct og01a1b {
/* Current mode */
const struct og01a1b_mode *cur_mode;
-
- /* To serialize asynchronus callbacks */
- struct mutex mutex;
};
static u64 to_pixel_rate(u32 f_index)
@@ -616,7 +613,6 @@ static int og01a1b_init_controls(struct og01a1b *og01a1b)
if (ret)
return ret;
- ctrl_hdlr->lock = &og01a1b->mutex;
og01a1b->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr,
&og01a1b_ctrl_ops,
V4L2_CID_LINK_FREQ,
@@ -686,74 +682,66 @@ static void og01a1b_update_pad_format(const struct og01a1b_mode *mode,
fmt->field = V4L2_FIELD_NONE;
}
-static int og01a1b_start_streaming(struct og01a1b *og01a1b)
+static int og01a1b_enable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state, u32 pad,
+ u64 streams_mask)
{
+ struct og01a1b *og01a1b = to_og01a1b(sd);
+ unsigned int link_freq_index = og01a1b->cur_mode->link_freq_index;
const struct og01a1b_reg_list *reg_list;
- int link_freq_index, ret;
+ int ret;
- link_freq_index = og01a1b->cur_mode->link_freq_index;
- reg_list = &link_freq_configs[link_freq_index].reg_list;
+ ret = pm_runtime_resume_and_get(og01a1b->dev);
+ if (ret)
+ return ret;
+ reg_list = &link_freq_configs[link_freq_index].reg_list;
ret = og01a1b_write_reg_list(og01a1b, reg_list);
if (ret) {
- dev_err(og01a1b->dev, "failed to set plls");
- return ret;
+ dev_err(og01a1b->dev, "failed to set plls: %d\n", ret);
+ goto error;
}
reg_list = &og01a1b->cur_mode->reg_list;
ret = og01a1b_write_reg_list(og01a1b, reg_list);
if (ret) {
- dev_err(og01a1b->dev, "failed to set mode");
- return ret;
+ dev_err(og01a1b->dev, "failed to set mode: %d\n", ret);
+ goto error;
}
ret = __v4l2_ctrl_handler_setup(og01a1b->sd.ctrl_handler);
if (ret)
- return ret;
+ goto error;
ret = og01a1b_write_reg(og01a1b, OG01A1B_REG_MODE_SELECT,
OG01A1B_REG_VALUE_08BIT,
OG01A1B_MODE_STREAMING);
if (ret) {
- dev_err(og01a1b->dev, "failed to set stream");
- return ret;
+ dev_err(og01a1b->dev, "failed to start streaming: %d\n", ret);
+ goto error;
}
return 0;
-}
-static void og01a1b_stop_streaming(struct og01a1b *og01a1b)
-{
- if (og01a1b_write_reg(og01a1b, OG01A1B_REG_MODE_SELECT,
- OG01A1B_REG_VALUE_08BIT, OG01A1B_MODE_STANDBY))
- dev_err(og01a1b->dev, "failed to set stream");
+error:
+ pm_runtime_put_autosuspend(og01a1b->dev);
+
+ return ret;
}
-static int og01a1b_set_stream(struct v4l2_subdev *sd, int enable)
+static int og01a1b_disable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state, u32 pad,
+ u64 streams_mask)
{
struct og01a1b *og01a1b = to_og01a1b(sd);
- int ret = 0;
-
- mutex_lock(&og01a1b->mutex);
- if (enable) {
- ret = pm_runtime_resume_and_get(og01a1b->dev);
- if (ret) {
- mutex_unlock(&og01a1b->mutex);
- return ret;
- }
+ int ret;
- ret = og01a1b_start_streaming(og01a1b);
- if (ret) {
- enable = 0;
- og01a1b_stop_streaming(og01a1b);
- pm_runtime_put(og01a1b->dev);
- }
- } else {
- og01a1b_stop_streaming(og01a1b);
- pm_runtime_put(og01a1b->dev);
- }
+ ret = og01a1b_write_reg(og01a1b, OG01A1B_REG_MODE_SELECT,
+ OG01A1B_REG_VALUE_08BIT, OG01A1B_MODE_STANDBY);
+ if (ret)
+ dev_err(og01a1b->dev, "failed to stop streaming: %d\n", ret);
- mutex_unlock(&og01a1b->mutex);
+ pm_runtime_put_autosuspend(og01a1b->dev);
return ret;
}
@@ -771,7 +759,6 @@ static int og01a1b_set_format(struct v4l2_subdev *sd,
height, fmt->format.width,
fmt->format.height);
- mutex_lock(&og01a1b->mutex);
og01a1b_update_pad_format(mode, &fmt->format);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
*v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format;
@@ -794,8 +781,6 @@ static int og01a1b_set_format(struct v4l2_subdev *sd,
h_blank);
}
- mutex_unlock(&og01a1b->mutex);
-
return 0;
}
@@ -805,15 +790,12 @@ static int og01a1b_get_format(struct v4l2_subdev *sd,
{
struct og01a1b *og01a1b = to_og01a1b(sd);
- mutex_lock(&og01a1b->mutex);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
fmt->format = *v4l2_subdev_state_get_format(sd_state,
fmt->pad);
else
og01a1b_update_pad_format(og01a1b->cur_mode, &fmt->format);
- mutex_unlock(&og01a1b->mutex);
-
return 0;
}
@@ -849,18 +831,14 @@ static int og01a1b_enum_frame_size(struct v4l2_subdev *sd,
static int og01a1b_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
- struct og01a1b *og01a1b = to_og01a1b(sd);
-
- mutex_lock(&og01a1b->mutex);
og01a1b_update_pad_format(&supported_modes[0],
v4l2_subdev_state_get_format(fh->state, 0));
- mutex_unlock(&og01a1b->mutex);
return 0;
}
static const struct v4l2_subdev_video_ops og01a1b_video_ops = {
- .s_stream = og01a1b_set_stream,
+ .s_stream = v4l2_subdev_s_stream_helper,
};
static const struct v4l2_subdev_pad_ops og01a1b_pad_ops = {
@@ -868,6 +846,8 @@ static const struct v4l2_subdev_pad_ops og01a1b_pad_ops = {
.get_fmt = og01a1b_get_format,
.enum_mbus_code = og01a1b_enum_mbus_code,
.enum_frame_size = og01a1b_enum_frame_size,
+ .enable_streams = og01a1b_enable_streams,
+ .disable_streams = og01a1b_disable_streams,
};
static const struct v4l2_subdev_ops og01a1b_subdev_ops = {
@@ -1046,7 +1026,6 @@ static void og01a1b_remove(struct i2c_client *client)
media_entity_cleanup(&sd->entity);
v4l2_ctrl_handler_free(sd->ctrl_handler);
pm_runtime_disable(og01a1b->dev);
- mutex_destroy(&og01a1b->mutex);
}
static int og01a1b_probe(struct i2c_client *client)
@@ -1135,7 +1114,6 @@ static int og01a1b_probe(struct i2c_client *client)
goto power_off;
}
- mutex_init(&og01a1b->mutex);
og01a1b->cur_mode = &supported_modes[0];
ret = og01a1b_init_controls(og01a1b);
if (ret) {
@@ -1143,6 +1121,7 @@ static int og01a1b_probe(struct i2c_client *client)
goto probe_error_v4l2_ctrl_handler_free;
}
+ og01a1b->sd.state_lock = og01a1b->ctrl_handler.lock;
og01a1b->sd.internal_ops = &og01a1b_internal_ops;
og01a1b->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
og01a1b->sd.entity.ops = &og01a1b_subdev_entity_ops;
@@ -1183,7 +1162,6 @@ probe_error_media_entity_cleanup:
probe_error_v4l2_ctrl_handler_free:
v4l2_ctrl_handler_free(og01a1b->sd.ctrl_handler);
- mutex_destroy(&og01a1b->mutex);
power_off:
og01a1b_power_off(og01a1b->dev);