On Wed Jun 10 12:22:37 2026 +0200, Jurison Murati wrote:
> The sensor registers are only written in the runtime PM resume
> handler; ov8865_set_fmt() merely stores the requested mode, relying on
> the sensor being runtime suspended between uses so that the next
> resume applies it.
>
> That assumption breaks when something keeps the sensor powered. On
> IPU3 platforms, ipu_bridge instantiates the VCM device with a
> DL_FLAG_PM_RUNTIME device link to the sensor, so a userspace process
> holding the VCM subdev open (e.g. wireplumber's camera monitor) pins
> the sensor runtime-active. A subsequent set_fmt() then never reaches
> the hardware: the sensor keeps streaming the mode programmed on the
> last resume while the CSI-2 receiver expects the newly negotiated
> format.
>
> On a Surface Book 2 (IPU3, ov8865 + dw9719 VCM), requesting the
> 3264x2448 mode while the hardware was left programmed for the
> 1632x1224 binned mode makes ipu3-cio2 report "frame sync error" and
> "payload length is 10340352, received 2585088" (exactly one binned
> frame) for every frame, and the inverse case stalls the stream after
> a single frame. Camera applications end up displaying one bogus frame
> forever.
>
> Program the sensor configuration and apply the control values on
> stream start instead, where the negotiated mode is always current,
> and only write the configuration in the runtime PM resume handler
> when resuming with the stream already started.
>
> Signed-off-by: Jurison Murati <[email protected]>
> Signed-off-by: Sakari Ailus <[email protected]>
Patch committed.
Thanks,
Sakari Ailus
drivers/media/i2c/ov8865.c | 34 +++++++++++++++++++++++++---------
1 file changed, 25 insertions(+), 9 deletions(-)
---
diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c
index 5b909a856128..c6d53c3d55ca 100644
--- a/drivers/media/i2c/ov8865.c
+++ b/drivers/media/i2c/ov8865.c
@@ -2609,7 +2609,7 @@ static int ov8865_s_stream(struct v4l2_subdev *subdev,
int enable)
{
struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev);
struct ov8865_state *state = &sensor->state;
- int ret;
+ int ret = 0;
if (enable) {
ret = pm_runtime_resume_and_get(sensor->dev);
@@ -2618,7 +2618,23 @@ static int ov8865_s_stream(struct v4l2_subdev *subdev,
int enable)
}
mutex_lock(&sensor->mutex);
- ret = ov8865_sw_standby(sensor, !enable);
+
+ /*
+ * The sensor may have been kept powered by something else (e.g. the
+ * VCM's runtime PM device link on IPU3 platforms), in which case
+ * runtime resume did not run and the hardware may still be
+ * configured for a previous mode. Always program the negotiated
+ * configuration on stream start.
+ */
+ if (enable) {
+ ret = ov8865_sensor_init(sensor);
+ if (!ret)
+ ret = __v4l2_ctrl_handler_setup(&sensor->ctrls.handler);
+ }
+
+ if (!ret)
+ ret = ov8865_sw_standby(sensor, !enable);
+
mutex_unlock(&sensor->mutex);
if (ret || !enable)
@@ -2914,15 +2930,15 @@ static int ov8865_resume(struct device *dev)
if (ret)
goto complete;
- ret = ov8865_sensor_init(sensor);
- if (ret)
- goto error_power;
+ if (state->streaming) {
+ ret = ov8865_sensor_init(sensor);
+ if (ret)
+ goto error_power;
- ret = __v4l2_ctrl_handler_setup(&sensor->ctrls.handler);
- if (ret)
- goto error_power;
+ ret = __v4l2_ctrl_handler_setup(&sensor->ctrls.handler);
+ if (ret)
+ goto error_power;
- if (state->streaming) {
ret = ov8865_sw_standby(sensor, false);
if (ret)
goto error_power;
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]