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]

Reply via email to