Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3fe3d043 authored by Dirk Bender's avatar Dirk Bender Committed by Greg Kroah-Hartman
Browse files

media: mt9p031: Fix corrupted frame after restarting stream



[ Upstream commit 0961ba6dd211a4a52d1dd4c2d59be60ac2dc08c7 ]

To prevent corrupted frames after starting and stopping the sensor its
datasheet specifies a specific pause sequence to follow:

Stopping:
	Set Pause_Restart Bit -> Set Restart Bit -> Set Chip_Enable Off

Restarting:
	Set Chip_Enable On -> Clear Pause_Restart Bit

The Restart Bit is cleared automatically and must not be cleared
manually as this would cause undefined behavior.

Signed-off-by: default avatarDirk Bender <d.bender@phytec.de>
Signed-off-by: default avatarStefan Riedmueller <s.riedmueller@phytec.de>
Signed-off-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 08743f9c
Loading
Loading
Loading
Loading
+27 −1
Original line number Diff line number Diff line
@@ -78,7 +78,9 @@
#define		MT9P031_PIXEL_CLOCK_INVERT		(1 << 15)
#define		MT9P031_PIXEL_CLOCK_SHIFT(n)		((n) << 8)
#define		MT9P031_PIXEL_CLOCK_DIVIDE(n)		((n) << 0)
#define MT9P031_FRAME_RESTART				0x0b
#define MT9P031_RESTART					0x0b
#define		MT9P031_FRAME_PAUSE_RESTART		(1 << 1)
#define		MT9P031_FRAME_RESTART			(1 << 0)
#define MT9P031_SHUTTER_DELAY				0x0c
#define MT9P031_RST					0x0d
#define		MT9P031_RST_ENABLE			1
@@ -445,9 +447,23 @@ static int mt9p031_set_params(struct mt9p031 *mt9p031)
static int mt9p031_s_stream(struct v4l2_subdev *subdev, int enable)
{
	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
	struct i2c_client *client = v4l2_get_subdevdata(subdev);
	int val;
	int ret;

	if (!enable) {
		/* enable pause restart */
		val = MT9P031_FRAME_PAUSE_RESTART;
		ret = mt9p031_write(client, MT9P031_RESTART, val);
		if (ret < 0)
			return ret;

		/* enable restart + keep pause restart set */
		val |= MT9P031_FRAME_RESTART;
		ret = mt9p031_write(client, MT9P031_RESTART, val);
		if (ret < 0)
			return ret;

		/* Stop sensor readout */
		ret = mt9p031_set_output_control(mt9p031,
						 MT9P031_OUTPUT_CONTROL_CEN, 0);
@@ -467,6 +483,16 @@ static int mt9p031_s_stream(struct v4l2_subdev *subdev, int enable)
	if (ret < 0)
		return ret;

	/*
	 * - clear pause restart
	 * - don't clear restart as clearing restart manually can cause
	 *   undefined behavior
	 */
	val = MT9P031_FRAME_RESTART;
	ret = mt9p031_write(client, MT9P031_RESTART, val);
	if (ret < 0)
		return ret;

	return mt9p031_pll_enable(mt9p031);
}