[PATCH v2 2/2] media: i2c: imx283: Fix hang when going from large to small resolution

Jai Luthra posted 2 patches 1 month, 2 weeks ago
[PATCH v2 2/2] media: i2c: imx283: Fix hang when going from large to small resolution
Posted by Jai Luthra 1 month, 2 weeks ago
When switching between modes (e.g. full resolution to binned),
standby_cancel() previously cleared XMSTA (starting master mode data
output) before the new mode's MDSEL, crop, and timing registers were
programmed in start_streaming(). This caused the sensor to briefly
output MIPI data using the previous mode's configuration.

On receivers like imx-mipi-csis, this leads to FIFO overflow errors
when switching from a higher to a lower resolution, as the receiver is
configured for the new smaller frame size but receives stale
full-resolution data.

Fix this by moving the XMSTA and SYNCDRV register writes from
standby_cancel() to the end of start_streaming(), after all mode,
crop, and timing registers have been configured. Also explicitly stop
master mode (XMSTA=1) when stopping the stream, matching the pattern
used by other Sony sensor drivers (imx290, imx415).

Use named macros IMX283_XMSTA_START/STOP instead of raw 0/BIT(0) for
readability.

Cc: stable@vger.kernel.org
Fixes: ccb4eb4496fa ("media: i2c: Add imx283 camera sensor driver")
Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
---
 drivers/media/i2c/imx283.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/media/i2c/imx283.c b/drivers/media/i2c/imx283.c
index 9b3094a57873c6e8ff8c41d058ea3b0012642cac..1be6164c2d15524690b738aa725a6708e84487d0 100644
--- a/drivers/media/i2c/imx283.c
+++ b/drivers/media/i2c/imx283.c
@@ -129,7 +129,8 @@
 
 /* Master Mode Operation Control */
 #define IMX283_REG_XMSTA		CCI_REG8(0x3105)
-#define   IMX283_XMSTA			BIT(0)
+#define   IMX283_XMSTA_START		0
+#define   IMX283_XMSTA_STOP		BIT(0)
 
 #define IMX283_REG_SYNCDRV		CCI_REG8(0x3107)
 #define   IMX283_SYNCDRV_XHS_XVS	(0xa0 | 0x02)
@@ -1023,8 +1024,6 @@ static int imx283_standby_cancel(struct imx283 *imx283)
 	usleep_range(19000, 20000);
 
 	cci_write(imx283->cci, IMX283_REG_CLAMP, IMX283_CLPSQRST, &ret);
-	cci_write(imx283->cci, IMX283_REG_XMSTA, 0, &ret);
-	cci_write(imx283->cci, IMX283_REG_SYNCDRV, IMX283_SYNCDRV_XHS_XVS, &ret);
 
 	return ret;
 }
@@ -1117,6 +1116,10 @@ static int imx283_start_streaming(struct imx283 *imx283,
 	/* Apply customized values from controls (HMAX/VMAX/SHR) */
 	ret =  __v4l2_ctrl_handler_setup(imx283->sd.ctrl_handler);
 
+	/* Start master mode */
+	cci_write(imx283->cci, IMX283_REG_XMSTA, IMX283_XMSTA_START, &ret);
+	cci_write(imx283->cci, IMX283_REG_SYNCDRV, IMX283_SYNCDRV_XHS_XVS, &ret);
+
 	return ret;
 }
 
@@ -1153,12 +1156,14 @@ static int imx283_disable_streams(struct v4l2_subdev *sd,
 				  u64 streams_mask)
 {
 	struct imx283 *imx283 = to_imx283(sd);
-	int ret;
+	int ret = 0;
 
 	if (pad != IMAGE_PAD)
 		return -EINVAL;
 
-	ret = cci_write(imx283->cci, IMX283_REG_STANDBY, IMX283_STANDBY, NULL);
+	cci_write(imx283->cci, IMX283_REG_XMSTA, IMX283_XMSTA_STOP, &ret);
+	cci_write(imx283->cci, IMX283_REG_STANDBY, IMX283_STANDBY, &ret);
+
 	if (ret)
 		dev_err(imx283->dev, "Failed to stop stream\n");
 

-- 
2.53.0
Re: [PATCH v2 2/2] media: i2c: imx283: Fix hang when going from large to small resolution
Posted by Kieran Bingham 1 month, 2 weeks ago
Quoting Jai Luthra (2026-02-14 13:05:22)
> When switching between modes (e.g. full resolution to binned),
> standby_cancel() previously cleared XMSTA (starting master mode data
> output) before the new mode's MDSEL, crop, and timing registers were
> programmed in start_streaming(). This caused the sensor to briefly
> output MIPI data using the previous mode's configuration.
> 
> On receivers like imx-mipi-csis, this leads to FIFO overflow errors
> when switching from a higher to a lower resolution, as the receiver is
> configured for the new smaller frame size but receives stale
> full-resolution data.
> 
> Fix this by moving the XMSTA and SYNCDRV register writes from
> standby_cancel() to the end of start_streaming(), after all mode,
> crop, and timing registers have been configured. Also explicitly stop
> master mode (XMSTA=1) when stopping the stream, matching the pattern
> used by other Sony sensor drivers (imx290, imx415).
> 
> Use named macros IMX283_XMSTA_START/STOP instead of raw 0/BIT(0) for
> readability.

All seems to make sense and explains (and resolves) the issues I've seen
on my i.MX8MP board with this module.

Thanks for digging into all of this.

Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>

 
> Cc: stable@vger.kernel.org
> Fixes: ccb4eb4496fa ("media: i2c: Add imx283 camera sensor driver")
> Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
> ---
>  drivers/media/i2c/imx283.c | 15 ++++++++++-----
>  1 file changed, 10 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/media/i2c/imx283.c b/drivers/media/i2c/imx283.c
> index 9b3094a57873c6e8ff8c41d058ea3b0012642cac..1be6164c2d15524690b738aa725a6708e84487d0 100644
> --- a/drivers/media/i2c/imx283.c
> +++ b/drivers/media/i2c/imx283.c
> @@ -129,7 +129,8 @@
>  
>  /* Master Mode Operation Control */
>  #define IMX283_REG_XMSTA               CCI_REG8(0x3105)
> -#define   IMX283_XMSTA                 BIT(0)
> +#define   IMX283_XMSTA_START           0
> +#define   IMX283_XMSTA_STOP            BIT(0)
>  
>  #define IMX283_REG_SYNCDRV             CCI_REG8(0x3107)
>  #define   IMX283_SYNCDRV_XHS_XVS       (0xa0 | 0x02)
> @@ -1023,8 +1024,6 @@ static int imx283_standby_cancel(struct imx283 *imx283)
>         usleep_range(19000, 20000);
>  
>         cci_write(imx283->cci, IMX283_REG_CLAMP, IMX283_CLPSQRST, &ret);
> -       cci_write(imx283->cci, IMX283_REG_XMSTA, 0, &ret);
> -       cci_write(imx283->cci, IMX283_REG_SYNCDRV, IMX283_SYNCDRV_XHS_XVS, &ret);
>  
>         return ret;
>  }
> @@ -1117,6 +1116,10 @@ static int imx283_start_streaming(struct imx283 *imx283,
>         /* Apply customized values from controls (HMAX/VMAX/SHR) */
>         ret =  __v4l2_ctrl_handler_setup(imx283->sd.ctrl_handler);
>  
> +       /* Start master mode */
> +       cci_write(imx283->cci, IMX283_REG_XMSTA, IMX283_XMSTA_START, &ret);
> +       cci_write(imx283->cci, IMX283_REG_SYNCDRV, IMX283_SYNCDRV_XHS_XVS, &ret);
> +
>         return ret;
>  }
>  
> @@ -1153,12 +1156,14 @@ static int imx283_disable_streams(struct v4l2_subdev *sd,
>                                   u64 streams_mask)
>  {
>         struct imx283 *imx283 = to_imx283(sd);
> -       int ret;
> +       int ret = 0;
>  
>         if (pad != IMAGE_PAD)
>                 return -EINVAL;
>  
> -       ret = cci_write(imx283->cci, IMX283_REG_STANDBY, IMX283_STANDBY, NULL);
> +       cci_write(imx283->cci, IMX283_REG_XMSTA, IMX283_XMSTA_STOP, &ret);
> +       cci_write(imx283->cci, IMX283_REG_STANDBY, IMX283_STANDBY, &ret);
> +
>         if (ret)
>                 dev_err(imx283->dev, "Failed to stop stream\n");
>  
> 
> -- 
> 2.53.0
>