소스 검색

Update v5.11 patches

Changes:
 - cameras
   - Add VBLANK control support
   - Clean up OV5693 driver

Links:
 - kernel: https://github.com/linux-surface/kernel/commit/28c9e3b2bd2d24f9fc2f81c10df5cb414276d81c
 - cameras: https://github.com/linux-surface/kernel/commit/74f01bb065f6221309954a6299990f4e887d4c3a
Maximilian Luz 4 년 전
부모
커밋
9b99e541d6
1개의 변경된 파일3858개의 추가작업 그리고 0개의 파일을 삭제
  1. 3858 0
      patches/5.11/0009-cameras.patch

+ 3858 - 0
patches/5.11/0009-cameras.patch

@@ -7315,3 +7315,3861 @@ index 924d99d20328..e1e388cc9f45 100644
 -- 
 2.30.1
 
+From 08a3bb7988c47cd2857802bfe4c438cf1e395582 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Mon, 8 Feb 2021 21:44:38 +0000
+Subject: [PATCH] media: i2c: Tidy up ov5693_init_controls()
+
+The ov5693 driver initialises a bunch of v4l2 controls and throws away
+the pointers. This seems weird, let's not do that.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 46 ++++++++++++++++++++++----------------
+ drivers/media/i2c/ov5693.h | 12 +++++++++-
+ 2 files changed, 38 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 1a85800df7ed..a9747ab783d7 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -1610,7 +1610,6 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 	struct i2c_client *client = v4l2_get_subdevdata(&ov5693->sd);
+ 	const struct v4l2_ctrl_ops *ops = &ov5693_ctrl_ops;
+ 	struct v4l2_fwnode_device_properties props;
+-	struct v4l2_ctrl *ctrl;
+ 	unsigned int i;
+ 	int ret;
+ 	int hblank;
+@@ -1628,15 +1627,17 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 				     NULL);
+ 
+ 	/* link freq */
+-	ctrl = v4l2_ctrl_new_int_menu(&ov5693->ctrl_handler, NULL,
+-				      V4L2_CID_LINK_FREQ,
+-				      0, 0, link_freq_menu_items);
+-	if (ctrl)
+-		ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
++	ov5693->ctrls.link_freq = v4l2_ctrl_new_int_menu(&ov5693->ctrl_handler,
++							 NULL, V4L2_CID_LINK_FREQ,
++							 0, 0, link_freq_menu_items);
++	if (ov5693->ctrls.link_freq)
++		ov5693->ctrls.link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+ 
+ 	/* pixel rate */
+-	v4l2_ctrl_new_std(&ov5693->ctrl_handler, NULL, V4L2_CID_PIXEL_RATE,
+-			  0, OV5693_PIXEL_RATE, 1, OV5693_PIXEL_RATE);
++	ov5693->ctrls.pixel_rate = v4l2_ctrl_new_std(&ov5693->ctrl_handler, NULL,
++						     V4L2_CID_PIXEL_RATE, 0,
++						     OV5693_PIXEL_RATE, 1,
++						     OV5693_PIXEL_RATE);
+ 
+ 	if (ov5693->ctrl_handler.error) {
+ 		ov5693_remove(client);
+@@ -1645,25 +1646,32 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 
+ 	/* Exposure */
+ 
+-	v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops, V4L2_CID_EXPOSURE, 16, 1048575, 16,
+-			  512);
++	ov5693->ctrls.exposure = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
++						   V4L2_CID_EXPOSURE, 16,
++						   1048575, 16, 512);
+ 
+ 	/* Gain */
+ 
+-	v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops, V4L2_CID_ANALOGUE_GAIN, 1, 1023, 1, 128);
+-	v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops, V4L2_CID_DIGITAL_GAIN, 1, 3999, 1, 1000);
++	ov5693->ctrls.analogue_gain = v4l2_ctrl_new_std(&ov5693->ctrl_handler,
++							ops, V4L2_CID_ANALOGUE_GAIN,
++							1, 1023, 1, 128);
++	ov5693->ctrls.digital_gain = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
++						       V4L2_CID_DIGITAL_GAIN, 1,
++						       3999, 1, 1000);
+ 
+ 	/* Flip */
+ 
+-	v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
+-	v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
++	ov5693->ctrls.hflip = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
++						V4L2_CID_HFLIP, 0, 1, 1, 0);
++	ov5693->ctrls.vflip = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
++						V4L2_CID_VFLIP, 0, 1, 1, 0);
+ 
+ 	hblank = OV5693_PPL_DEFAULT - ov5693->mode->width;
+-	ov5693->hblank = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
+-					   V4L2_CID_HBLANK, hblank, hblank,
+-					   1, hblank);
+-	if (ov5693->hblank)
+-		ov5693->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
++	ov5693->ctrls.hblank = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
++						 V4L2_CID_HBLANK, hblank, hblank,
++						 1, hblank);
++	if (ov5693->ctrls.hblank)
++		ov5693->ctrls.hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+ 
+ 	/* set properties from fwnode (e.g. rotation, orientation) */
+ 	ret = v4l2_fwnode_device_parse(&client->dev, &props);
+diff --git a/drivers/media/i2c/ov5693.h b/drivers/media/i2c/ov5693.h
+index 9a508e1f3624..26819cf3f4d2 100644
+--- a/drivers/media/i2c/ov5693.h
++++ b/drivers/media/i2c/ov5693.h
+@@ -270,7 +270,17 @@ struct ov5693_device {
+ 
+ 	bool has_vcm;
+ 
+-	struct v4l2_ctrl *hblank;
++	struct ov5693_v4l2_ctrls {
++		struct v4l2_ctrl *link_freq;
++		struct v4l2_ctrl *pixel_rate;
++		struct v4l2_ctrl *exposure;
++		struct v4l2_ctrl *analogue_gain;
++		struct v4l2_ctrl *digital_gain;
++		struct v4l2_ctrl *hflip;
++		struct v4l2_ctrl *vflip;
++		struct v4l2_ctrl *hblank;
++	} ctrls;
++
+ };
+ 
+ enum ov5693_tok_type {
+-- 
+2.30.1
+
+From 252fa0aaa35d6f4f8a1bc83737070c22df65279e Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Mon, 8 Feb 2021 21:46:49 +0000
+Subject: [PATCH] media: i2c: Remove OV5693_PPL_DEFAULT
+
+No need for this macro, the PPL setting is against the mode structs.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index a9747ab783d7..7fb368eec327 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -105,8 +105,6 @@ MODULE_PARM_DESC(up_delay,
+ #define OV5693_PIXEL_ARRAY_WIDTH	2592U
+ #define OV5693_PIXEL_ARRAY_HEIGHT	1944U
+ 
+-#define	OV5693_PPL_DEFAULT		2800
+-
+ static int vcm_ad_i2c_wr8(struct i2c_client *client, u8 reg, u8 val)
+ {
+ 	int err;
+@@ -1666,7 +1664,7 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 	ov5693->ctrls.vflip = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
+ 						V4L2_CID_VFLIP, 0, 1, 1, 0);
+ 
+-	hblank = OV5693_PPL_DEFAULT - ov5693->mode->width;
++	hblank = ov5693->mode->pixels_per_line - ov5693->mode->width;
+ 	ov5693->ctrls.hblank = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
+ 						 V4L2_CID_HBLANK, hblank, hblank,
+ 						 1, hblank);
+-- 
+2.30.1
+
+From a887349f340c1c4289e2c7510d2f13942c3b5fa3 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Mon, 8 Feb 2021 22:53:02 +0000
+Subject: [PATCH] media: i2c: Add vblank control to ov5693 driver
+
+The latest libcamera requires a V4L2_CID_VBLANK control in each sensor
+driver; add a skeleton one to the ov5693 to fulfill the requirement.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 12 ++++++++++++
+ drivers/media/i2c/ov5693.h |  3 +++
+ 2 files changed, 15 insertions(+)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 7fb368eec327..1950d7ac2d54 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -946,6 +946,10 @@ static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl)
+ 		return ov5693_flip_horz_configure(dev, !!ctrl->val);
+ 	case V4L2_CID_VFLIP:
+ 		return ov5693_flip_vert_configure(dev, !!ctrl->val);
++	case V4L2_CID_VBLANK:
++		ret = ov5693_write_reg(client, OV5693_16BIT, OV5693_TIMING_VTS_H,
++				       dev->mode->height + ctrl->val);
++		break;
+ 	default:
+ 		ret = -EINVAL;
+ 	}
+@@ -1611,6 +1615,7 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 	unsigned int i;
+ 	int ret;
+ 	int hblank;
++	int vblank_max, vblank_min, vblank_def;
+ 
+ 	ret = v4l2_ctrl_handler_init(&ov5693->ctrl_handler,
+ 				     ARRAY_SIZE(ov5693_controls));
+@@ -1671,6 +1676,13 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 	if (ov5693->ctrls.hblank)
+ 		ov5693->ctrls.hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+ 
++	vblank_max = OV5693_TIMING_MAX_VTS - ov5693->mode->height;
++	vblank_def = ov5693->mode->lines_per_frame - ov5693->mode->height;
++	vblank_min = ov5693->mode->lines_per_frame - ov5693->mode->height;
++	ov5693->ctrls.vblank = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
++						 V4L2_CID_VBLANK, vblank_min,
++						 vblank_max, 1, vblank_def);
++
+ 	/* set properties from fwnode (e.g. rotation, orientation) */
+ 	ret = v4l2_fwnode_device_parse(&client->dev, &props);
+ 	if (ret)
+diff --git a/drivers/media/i2c/ov5693.h b/drivers/media/i2c/ov5693.h
+index 26819cf3f4d2..9d7eed97963b 100644
+--- a/drivers/media/i2c/ov5693.h
++++ b/drivers/media/i2c/ov5693.h
+@@ -131,6 +131,8 @@
+ /*High 8-bit, and low 8-bit HTS address is 0x380f*/
+ #define OV5693_TIMING_VTS_L			0x380f
+ 
++#define OV5693_TIMING_MAX_VTS			0xffff
++
+ #define OV5693_MWB_RED_GAIN_H			0x3400
+ #define OV5693_MWB_GREEN_GAIN_H			0x3402
+ #define OV5693_MWB_BLUE_GAIN_H			0x3404
+@@ -279,6 +281,7 @@ struct ov5693_device {
+ 		struct v4l2_ctrl *hflip;
+ 		struct v4l2_ctrl *vflip;
+ 		struct v4l2_ctrl *hblank;
++		struct v4l2_ctrl *vblank;
+ 	} ctrls;
+ 
+ };
+-- 
+2.30.1
+
+From a30ff7e85e20058b44895896cc607afeff6b3cfc Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Wed, 10 Feb 2021 00:36:32 +0000
+Subject: [PATCH] media: i2c: update exposure control for ov5693
+
+The exposure control for ov5693 currently is in units of 1/16th of a line,
+but I think the framework expects it in units of lines. Set the control to
+work in lines and simply apply the multiplication when configuring the chip
+registers instead.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 23 ++++++++++++++++++++---
+ 1 file changed, 20 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 1950d7ac2d54..cea767230aa9 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -801,6 +801,12 @@ static int ov5693_exposure_configure(struct ov5693_device *sensor, u32 exposure)
+ {
+ 	int ret;
+ 
++	/*
++	 * The control for exposure seems to be in units of lines, but the chip
++	 * datasheet specifies exposure is in units of 1/16th of a line.
++	 */
++	exposure = exposure * 16;
++
+ 	ov5693_get_exposure(sensor);
+ 	ret = ov5693_write_reg(sensor->i2c_client, OV5693_8BIT,
+ 			OV5693_EXPOSURE_CTRL_HH_REG, OV5693_EXPOSURE_CTRL_HH(exposure));
+@@ -910,6 +916,16 @@ static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl)
+ 	struct i2c_client *client = v4l2_get_subdevdata(&dev->sd);
+ 	int ret = 0;
+ 
++	/* If VBLANK is altered we need to update exposure to compensate */
++	if (ctrl->id == V4L2_CID_VBLANK) {
++		int exposure_max;
++		exposure_max = dev->mode->lines_per_frame - 8;
++		__v4l2_ctrl_modify_range(dev->ctrls.exposure, dev->ctrls.exposure->minimum,
++					 exposure_max, dev->ctrls.exposure->step,
++					 dev->ctrls.exposure->val < exposure_max ?
++					 dev->ctrls.exposure->val : exposure_max);
++	}
++
+ 	switch (ctrl->id) {
+ 	case V4L2_CID_FOCUS_ABSOLUTE:
+ 		dev_dbg(&client->dev, "%s: CID_FOCUS_ABSOLUTE:%d.\n",
+@@ -1616,6 +1632,7 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 	int ret;
+ 	int hblank;
+ 	int vblank_max, vblank_min, vblank_def;
++	int exposure_max;
+ 
+ 	ret = v4l2_ctrl_handler_init(&ov5693->ctrl_handler,
+ 				     ARRAY_SIZE(ov5693_controls));
+@@ -1648,10 +1665,10 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 	}
+ 
+ 	/* Exposure */
+-
++	exposure_max = ov5693->mode->lines_per_frame - 8;
+ 	ov5693->ctrls.exposure = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
+-						   V4L2_CID_EXPOSURE, 16,
+-						   1048575, 16, 512);
++						   V4L2_CID_EXPOSURE, 1,
++						   exposure_max, 1, 123);
+ 
+ 	/* Gain */
+ 
+-- 
+2.30.1
+
+From 14cb1065b1f464fe00330c4fb764157e1cda8173 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Wed, 10 Feb 2021 00:39:42 +0000
+Subject: [PATCH] media: i2c: Fix incorrect bit-setting
+
+The bitmask macros to set the exposure for the ov5693 are not quite right.
+Update them so that they're setting the correct bits in the registers.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index cea767230aa9..f681dbfcec56 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -63,11 +63,11 @@ MODULE_PARM_DESC(up_delay,
+ /* Exposure/gain */
+ 
+ #define OV5693_EXPOSURE_CTRL_HH_REG		0x3500
+-#define OV5693_EXPOSURE_CTRL_HH(v)		(((v) & GENMASK(18, 16)) >> 16)
++#define OV5693_EXPOSURE_CTRL_HH(v)		(((v) & GENMASK(14, 12)) >> 12)
+ #define OV5693_EXPOSURE_CTRL_H_REG		0x3501
+-#define OV5693_EXPOSURE_CTRL_H(v)		(((v) & GENMASK(15, 8)) >> 8)
++#define OV5693_EXPOSURE_CTRL_H(v)		(((v) & GENMASK(11, 4)) >> 4)
+ #define OV5693_EXPOSURE_CTRL_L_REG		0x3502
+-#define OV5693_EXPOSURE_CTRL_L(v)		((v) & GENMASK(7, 0))
++#define OV5693_EXPOSURE_CTRL_L(v)		(((v) & GENMASK(3, 0)) << 4)
+ #define OV5693_EXPOSURE_GAIN_MANUAL_REG		0x3509
+ 
+ #define OV5693_GAIN_CTRL_H_REG			0x3504
+-- 
+2.30.1
+
+From 6edf21c2eeed5c8ac2656ff6de0b465fd852deb2 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Wed, 10 Feb 2021 16:25:48 +0000
+Subject: [PATCH] media: i2c: Don't set stream on during mode config
+
+Currently the register lists for the ov5693 include setting stream on.
+That register shouldn't be set until the control is called, so remove
+this setting from all of the modes.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.h | 16 ----------------
+ 1 file changed, 16 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.h b/drivers/media/i2c/ov5693.h
+index 9d7eed97963b..965208078c2b 100644
+--- a/drivers/media/i2c/ov5693.h
++++ b/drivers/media/i2c/ov5693.h
+@@ -581,7 +581,6 @@ static struct ov5693_reg const ov5693_654x496[] = {
+ 	{OV5693_8BIT, 0x3820, 0x04},
+ 	{OV5693_8BIT, 0x3821, 0x1f},
+ 	{OV5693_8BIT, 0x5002, 0x80},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+@@ -626,7 +625,6 @@ static struct ov5693_reg const ov5693_1296x976[] = {
+ 	{OV5693_8BIT, 0x3821, 0x1e},
+ 	{OV5693_8BIT, 0x5002, 0x00},
+ 	{OV5693_8BIT, 0x5041, 0x84}, /* scale is auto enabled */
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ 
+ };
+@@ -656,7 +654,6 @@ static struct ov5693_reg const ov5693_336x256[] = {
+ 	{OV5693_8BIT, 0x3820, 0x04},
+ 	{OV5693_8BIT, 0x3821, 0x1f},
+ 	{OV5693_8BIT, 0x5002, 0x80},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+@@ -683,7 +680,6 @@ static struct ov5693_reg const ov5693_368x304[] = {
+ 	{OV5693_8BIT, 0x3820, 0x04},
+ 	{OV5693_8BIT, 0x3821, 0x1f},
+ 	{OV5693_8BIT, 0x5002, 0x80},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+@@ -715,7 +711,6 @@ static struct ov5693_reg const ov5693_192x160[] = {
+ 	{OV5693_8BIT, 0x3820, 0x04},
+ 	{OV5693_8BIT, 0x3821, 0x1f},
+ 	{OV5693_8BIT, 0x5002, 0x80},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+@@ -742,7 +737,6 @@ static struct ov5693_reg const ov5693_736x496[] = {
+ 	{OV5693_8BIT, 0x3820, 0x04},
+ 	{OV5693_8BIT, 0x3821, 0x1f},
+ 	{OV5693_8BIT, 0x5002, 0x80},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ #endif
+@@ -771,7 +765,6 @@ static struct ov5693_reg const ov5693_736x496[] = {
+ 	{OV5693_8BIT, 0x3820, 0x01},
+ 	{OV5693_8BIT, 0x3821, 0x1f},
+ 	{OV5693_8BIT, 0x5002, 0x00},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ */
+@@ -802,7 +795,6 @@ static struct ov5693_reg const ov5693_976x556[] = {
+ 	{OV5693_8BIT, 0x3820, 0x00},
+ 	{OV5693_8BIT, 0x3821, 0x1e},
+ 	{OV5693_8BIT, 0x5002, 0x80},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+@@ -841,7 +833,6 @@ static struct ov5693_reg const ov5693_1296x736[] = {
+ 	{OV5693_8BIT, 0x3821, 0x1e},
+ 	{OV5693_8BIT, 0x5002, 0x00},
+ 	{OV5693_8BIT, 0x5041, 0x84}, /* scale is auto enabled */
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+@@ -868,7 +859,6 @@ static struct ov5693_reg const ov5693_1636p_30fps[] = {
+ 	{OV5693_8BIT, 0x3820, 0x00},
+ 	{OV5693_8BIT, 0x3821, 0x1e},
+ 	{OV5693_8BIT, 0x5002, 0x80},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ #endif
+@@ -904,7 +894,6 @@ static struct ov5693_reg const ov5693_1616x1216_30fps[] = {
+ 	{OV5693_8BIT, 0x3821, 0x1e},	/*MIRROR control*/
+ 	{OV5693_8BIT, 0x5002, 0x00},
+ 	{OV5693_8BIT, 0x5041, 0x84},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+@@ -935,7 +924,6 @@ static struct ov5693_reg const ov5693_1940x1096[] = {
+ 	{OV5693_8BIT, 0x3820, 0x00},
+ 	{OV5693_8BIT, 0x3821, 0x1e},
+ 	{OV5693_8BIT, 0x5002, 0x80},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+@@ -1029,7 +1017,6 @@ static struct ov5693_reg const ov5693_2592x1944_30fps[] = {
+ 	{OV5693_8BIT, 0x3820, 0x00},
+ 	{OV5693_8BIT, 0x3821, 0x1e},
+ 	{OV5693_8BIT, 0x5002, 0x00},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ #endif
+@@ -1073,7 +1060,6 @@ static struct ov5693_reg const ov5693_1424x1168_30fps[] = {
+ 	{OV5693_8BIT, 0x3821, 0x1e},
+ 	{OV5693_8BIT, 0x5002, 0x00},
+ 	{OV5693_8BIT, 0x5041, 0x84}, /* scale is auto enabled */
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ #endif
+@@ -1114,7 +1100,6 @@ static struct ov5693_reg const ov5693_736x496_30fps[] = {
+ 	{OV5693_8BIT, 0x3821, 0x1e},
+ 	{OV5693_8BIT, 0x5002, 0x00},
+ 	{OV5693_8BIT, 0x5041, 0x84}, /* scale is auto enabled */
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+@@ -1141,7 +1126,6 @@ static struct ov5693_reg const ov5693_2576x1936_30fps[] = {
+ 	{OV5693_8BIT, 0x3820, 0x00},
+ 	{OV5693_8BIT, 0x3821, 0x1e},
+ 	{OV5693_8BIT, 0x5002, 0x00},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+-- 
+2.30.1
+
+From bfab6b01e4e984f7fce2e10168b0fe4242ceee83 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Wed, 10 Feb 2021 16:35:24 +0000
+Subject: [PATCH] media: i2c: Update gain control for ov5693
+
+The gain control of the ov5693 driver is setting the wrong bits and
+defining an invalid maximum value; change (and use) the bitshifting
+macros and update the control's ranges.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index f681dbfcec56..51eb3b05d121 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -71,9 +71,9 @@ MODULE_PARM_DESC(up_delay,
+ #define OV5693_EXPOSURE_GAIN_MANUAL_REG		0x3509
+ 
+ #define OV5693_GAIN_CTRL_H_REG			0x3504
+-#define OV5693_GAIN_CTRL_H(v)			(((v) & GENMASK(9, 8)) >> 8)
++#define OV5693_GAIN_CTRL_H(v)			((v >> 4) & GENMASK(2, 0))
+ #define OV5693_GAIN_CTRL_L_REG			0x3505
+-#define OV5693_GAIN_CTRL_L(v)			((v) & GENMASK(7, 0))
++#define OV5693_GAIN_CTRL_L(v)			((v << 4) & GENMASK(7, 4))
+ 
+ #define OV5693_FORMAT1_REG			0x3820
+ #define OV5693_FORMAT1_FLIP_VERT_ISP_EN		BIT(2)
+@@ -889,9 +889,13 @@ static int ov5693_analog_gain_configure(struct ov5693_device *sensor, u32 gain)
+ {
+ 	int ret;
+ 
+-	/* Analog gain */
++	/*
++	 * As with exposure, the lowest 4 bits are fractional bits. Setting
++	 * those is not supported, so we have a tiny bit of bit shifting to
++	 * do.
++	 */
+ 	ret = ov5693_write_reg(sensor->i2c_client, OV5693_8BIT,
+-				OV5693_AGC_L, gain & 0xff);
++				OV5693_AGC_L, OV5693_GAIN_CTRL_L(gain));
+ 	if (ret) {
+ 		dev_err(&sensor->i2c_client->dev, "%s: write %x error, aborted\n",
+ 			__func__, OV5693_AGC_L);
+@@ -899,7 +903,7 @@ static int ov5693_analog_gain_configure(struct ov5693_device *sensor, u32 gain)
+ 	}
+ 
+ 	ret = ov5693_write_reg(sensor->i2c_client, OV5693_8BIT,
+-				OV5693_AGC_H, (gain >> 8) & 0xff);
++				OV5693_AGC_H, OV5693_GAIN_CTRL_H(gain));
+ 	if (ret) {
+ 		dev_err(&sensor->i2c_client->dev, "%s: write %x error, aborted\n",
+ 			__func__, OV5693_AGC_H);
+@@ -1674,10 +1678,10 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 
+ 	ov5693->ctrls.analogue_gain = v4l2_ctrl_new_std(&ov5693->ctrl_handler,
+ 							ops, V4L2_CID_ANALOGUE_GAIN,
+-							1, 1023, 1, 128);
++							1, 127, 1, 8);
+ 	ov5693->ctrls.digital_gain = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
+ 						       V4L2_CID_DIGITAL_GAIN, 1,
+-						       3999, 1, 1000);
++						       4095, 1, 1024);
+ 
+ 	/* Flip */
+ 
+-- 
+2.30.1
+
+From 052136967d4972f1c91817e35eb9d9538e80a832 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Wed, 10 Feb 2021 23:44:39 +0000
+Subject: [PATCH] media: i2c: Fixup gain read
+
+This function reads the bits from the gain registers poorly. Update
+it to do that properly (although, it probably just needs to be deleted)
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 17 +++++++++++------
+ 1 file changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 51eb3b05d121..952558c4f33b 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -770,30 +770,35 @@ static int ov5693_t_focus_rel(struct v4l2_subdev *sd, s32 value)
+ 
+ static int ov5693_get_exposure(struct ov5693_device *sensor)
+ {
+-	u16 reg_v, reg_v2;
++	u32 exposure = 0;
++	u16 tmp;
+ 	int ret = 0;
+ 
+ 	/* get exposure */
+ 	ret = ov5693_read_reg(sensor->i2c_client, OV5693_8BIT,
+ 			      OV5693_EXPOSURE_L,
+-			      &reg_v);
++			      &tmp);
+ 	if (ret)
+ 		return ret;
+ 
++	exposure |= ((tmp >> 4) & 0b1111);
++
+ 	ret = ov5693_read_reg(sensor->i2c_client, OV5693_8BIT,
+ 			      OV5693_EXPOSURE_M,
+-			      &reg_v2);
++			      &tmp);
+ 	if (ret)
+ 		return ret;
+ 
+-	reg_v += reg_v2 << 8;
++	exposure |= (tmp << 4);
+ 	ret = ov5693_read_reg(sensor->i2c_client, OV5693_8BIT,
+ 			      OV5693_EXPOSURE_H,
+-			      &reg_v2);
++			      &tmp);
+ 	if (ret)
+ 		return ret;
+ 
+-	printk("exposure set to: %u\n", reg_v + (((u32)reg_v2 << 16)));
++	exposure |= (tmp << 12);
++
++	printk("exposure set to: %u\n", exposure);
+ 	return ret;
+ }
+ 
+-- 
+2.30.1
+
+From 3139bc00474507b373240f08f11f798643b490c8 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Thu, 11 Feb 2021 00:40:10 +0000
+Subject: [PATCH] media: i2c: Update controls on stream
+
+Currently the ov5693 driver throws away control setting by simply loading
+each mode's default registers. Instead, re-set the user defined controls
+during stream with __v4l2_ctrl_handler_setup()
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 952558c4f33b..dd31083eeb7b 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -1492,6 +1492,12 @@ static int ov5693_s_stream(struct v4l2_subdev *sd, int enable)
+ 		}
+ 	}
+ 
++	ret = __v4l2_ctrl_handler_setup(&dev->ctrl_handler);
++	if (ret) {
++		power_down(sd);
++		return ret;
++	}
++
+ 	ret = ov5693_write_reg(client, OV5693_8BIT, OV5693_SW_STREAM,
+ 			       enable ? OV5693_START_STREAMING :
+ 			       OV5693_STOP_STREAMING);
+-- 
+2.30.1
+
+From 4be03779770b9b17c12cf2ac8775501c8623105f Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Thu, 11 Feb 2021 23:29:15 +0000
+Subject: [PATCH] media: i2c: Correct link frequency value
+
+The link frequency is given by vts * hts * fps * bits / lanes / 2. In the
+case of the ov5693 driver that works out to 400MHz, not 640Mhz. Correct
+the macro.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.h | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.h b/drivers/media/i2c/ov5693.h
+index 965208078c2b..7f1d31a82d3d 100644
+--- a/drivers/media/i2c/ov5693.h
++++ b/drivers/media/i2c/ov5693.h
+@@ -186,13 +186,13 @@
+ #define OV5693_OTP_MODE_READ		1
+ 
+ /* link freq and pixel rate required for IPU3 */
+-#define OV5693_LINK_FREQ_640MHZ		640000000
++#define OV5693_LINK_FREQ_400MHZ		400000000
+ /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample
+  * To avoid integer overflow, dividing by bits_per_sample first.
+  */
+-#define OV5693_PIXEL_RATE		(OV5693_LINK_FREQ_640MHZ / 10) * 2 * 2
++#define OV5693_PIXEL_RATE		(OV5693_LINK_FREQ_400MHZ / 10) * 2 * 2
+ static const s64 link_freq_menu_items[] = {
+-	OV5693_LINK_FREQ_640MHZ
++	OV5693_LINK_FREQ_400MHZ
+ };
+ 
+ #define OV5693_NUM_SUPPLIES             2
+-- 
+2.30.1
+
+From 58ae978d22ef1b1128226a3c16afc5bc2f191286 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Mon, 25 Jan 2021 23:12:09 +0000
+Subject: [PATCH] media: i2c: Cleanup ov5693 driver
+
+This commit performs some cleanup to the ov5693 driver:
+
+1. Superfluous words in variable names dropped; "i2c_client" becomes
+   "client", "input_lock" becomes "lock"
+2. ov5693_configure_gpios() is does error handling properly, and uses
+   gpiod_get_optional()
+3. The name of the struct ov5693_device variable in each functions, which
+   previously was a mix of dev, sensor or ov5693, is standardised to the
+   latter.
+4. The list of headers is alphabetised (and probably also needs trimming)
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 309 +++++++++++++++++++------------------
+ drivers/media/i2c/ov5693.h |   5 +-
+ 2 files changed, 165 insertions(+), 149 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index dd31083eeb7b..0643390c872a 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -16,25 +16,25 @@
+  *
+  */
+ 
++#include <linux/acpi.h>
+ #include <linux/clk.h>
+-#include <linux/module.h>
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/string.h>
++#include <linux/delay.h>
++#include <linux/device.h>
+ #include <linux/errno.h>
++#include <linux/i2c.h>
+ #include <linux/init.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
+ #include <linux/kmod.h>
+-#include <linux/device.h>
+-#include <linux/delay.h>
+-#include <linux/slab.h>
+-#include <linux/i2c.h>
++#include <linux/module.h>
+ #include <linux/moduleparam.h>
++#include <linux/mm.h>
++#include <linux/regulator/consumer.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/types.h>
+ #include <media/v4l2-device.h>
+ #include <media/v4l2-fwnode.h>
+-#include <linux/io.h>
+-#include <linux/acpi.h>
+-#include <linux/regulator/consumer.h>
+ 
+ #include "ov5693.h"
+ #include "ad5823.h"
+@@ -485,12 +485,12 @@ static int ov5693_read_otp_reg_array(struct i2c_client *client, u16 size,
+ static int __ov5693_otp_read(struct v4l2_subdev *sd, u8 *buf)
+ {
+ 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 	int ret;
+ 	int i;
+ 	u8 *b = buf;
+ 
+-	dev->otp_size = 0;
++	ov5693->otp_size = 0;
+ 	for (i = 1; i < OV5693_OTP_BANK_MAX; i++) {
+ 		/*set bank NO and OTP read mode. */
+ 		ret = ov5693_write_reg(client, OV5693_8BIT, OV5693_OTP_BANK_REG,
+@@ -529,7 +529,7 @@ static int __ov5693_otp_read(struct v4l2_subdev *sd, u8 *buf)
+ 		//Intel OTP map, try to read 320byts first.
+ 		if (i == 21) {
+ 			if ((*b) == 0) {
+-				dev->otp_size = 320;
++				ov5693->otp_size = 320;
+ 				break;
+ 			}
+ 			/* (*b) != 0 */
+@@ -538,7 +538,7 @@ static int __ov5693_otp_read(struct v4l2_subdev *sd, u8 *buf)
+ 		} else if (i ==
+ 			   24) {		//if the first 320bytes data doesn't not exist, try to read the next 32bytes data.
+ 			if ((*b) == 0) {
+-				dev->otp_size = 32;
++				ov5693->otp_size = 32;
+ 				break;
+ 			}
+ 			/* (*b) != 0 */
+@@ -547,11 +547,11 @@ static int __ov5693_otp_read(struct v4l2_subdev *sd, u8 *buf)
+ 		} else if (i ==
+ 			   27) {		//if the prvious 32bytes data doesn't exist, try to read the next 32bytes data again.
+ 			if ((*b) == 0) {
+-				dev->otp_size = 32;
++				ov5693->otp_size = 32;
+ 				break;
+ 			}
+ 			/* (*b) != 0 */
+-			dev->otp_size = 0;	// no OTP data.
++			ov5693->otp_size = 0;	// no OTP data.
+ 			break;
+ 		}
+ 
+@@ -598,20 +598,20 @@ static void *ov5693_otp_read(struct v4l2_subdev *sd)
+ 	return buf;
+ }
+ 
+-static int ov5693_update_bits(struct ov5693_device *sensor, u16 address,
++static int ov5693_update_bits(struct ov5693_device *ov5693, u16 address,
+ 			      u16 mask, u16 bits)
+ {
+ 	u16 value = 0;
+ 	int ret;
+ 
+-	ret = ov5693_read_reg(sensor->i2c_client, OV5693_8BIT, address, &value);
++	ret = ov5693_read_reg(ov5693->client, OV5693_8BIT, address, &value);
+ 	if (ret)
+ 		return ret;
+ 
+ 	value &= ~mask;
+ 	value |= bits;
+ 
+-	ret = ov5693_write_reg(sensor->i2c_client, OV5693_8BIT, address, value);
++	ret = ov5693_write_reg(ov5693->client, OV5693_8BIT, address, value);
+ 	if (ret)
+ 		return ret;
+ 
+@@ -620,13 +620,13 @@ static int ov5693_update_bits(struct ov5693_device *sensor, u16 address,
+ 
+ /* Flip */
+ 
+-static int ov5693_flip_vert_configure(struct ov5693_device *sensor, bool enable)
++static int ov5693_flip_vert_configure(struct ov5693_device *ov5693, bool enable)
+ {
+ 	u8 bits = OV5693_FORMAT1_FLIP_VERT_ISP_EN |
+ 		  OV5693_FORMAT1_FLIP_VERT_SENSOR_EN;
+ 	int ret;
+ 
+-	ret = ov5693_update_bits(sensor, OV5693_FORMAT1_REG, bits,
++	ret = ov5693_update_bits(ov5693, OV5693_FORMAT1_REG, bits,
+ 				 enable ? bits : 0);
+ 	if (ret)
+ 		return ret;
+@@ -634,13 +634,13 @@ static int ov5693_flip_vert_configure(struct ov5693_device *sensor, bool enable)
+ 	return 0;
+ }
+ 
+-static int ov5693_flip_horz_configure(struct ov5693_device *sensor, bool enable)
++static int ov5693_flip_horz_configure(struct ov5693_device *ov5693, bool enable)
+ {
+ 	u8 bits = OV5693_FORMAT2_FLIP_HORZ_ISP_EN |
+ 		  OV5693_FORMAT2_FLIP_HORZ_SENSOR_EN;
+ 	int ret;
+ 
+-	ret = ov5693_update_bits(sensor, OV5693_FORMAT2_REG, bits,
++	ret = ov5693_update_bits(ov5693, OV5693_FORMAT2_REG, bits,
+ 				 enable ? bits : 0);
+ 	if (ret)
+ 		return ret;
+@@ -721,14 +721,14 @@ static int ad5823_t_focus_abs(struct v4l2_subdev *sd, s32 value)
+ 
+ static int ov5693_t_focus_abs(struct v4l2_subdev *sd, s32 value)
+ {
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+ 	int ret = 0;
+ 
+ 	dev_dbg(&client->dev, "%s: FOCUS_POS: 0x%x\n", __func__, value);
+ 	value = clamp(value, 0, OV5693_VCM_MAX_FOCUS_POS);
+-	if (dev->vcm == VCM_DW9714) {
+-		if (dev->vcm_update) {
++	if (ov5693->vcm == VCM_DW9714) {
++		if (ov5693->vcm_update) {
+ 			ret = vcm_dw_i2c_write(client, VCM_PROTECTION_OFF);
+ 			if (ret)
+ 				return ret;
+@@ -738,17 +738,17 @@ static int ov5693_t_focus_abs(struct v4l2_subdev *sd, s32 value)
+ 			ret = vcm_dw_i2c_write(client, VCM_PROTECTION_ON);
+ 			if (ret)
+ 				return ret;
+-			dev->vcm_update = false;
++			ov5693->vcm_update = false;
+ 		}
+ 		ret = vcm_dw_i2c_write(client,
+ 				       vcm_val(value, VCM_DEFAULT_S));
+-	} else if (dev->vcm == VCM_AD5823) {
++	} else if (ov5693->vcm == VCM_AD5823) {
+ 		ad5823_t_focus_abs(sd, value);
+ 	}
+ 	if (ret == 0) {
+-		dev->number_of_steps = value - dev->focus;
+-		dev->focus = value;
+-		dev->timestamp_t_focus_abs = ktime_get();
++		ov5693->number_of_steps = value - ov5693->focus;
++		ov5693->focus = value;
++		ov5693->timestamp_t_focus_abs = ktime_get();
+ 	} else
+ 		dev_err(&client->dev,
+ 			"%s: i2c failed. ret %d\n", __func__, ret);
+@@ -758,9 +758,9 @@ static int ov5693_t_focus_abs(struct v4l2_subdev *sd, s32 value)
+ 
+ static int ov5693_t_focus_rel(struct v4l2_subdev *sd, s32 value)
+ {
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 
+-	return ov5693_t_focus_abs(sd, dev->focus + value);
++	return ov5693_t_focus_abs(sd, ov5693->focus + value);
+ }
+ 
+ #define DELAY_PER_STEP_NS	1000000
+@@ -768,14 +768,14 @@ static int ov5693_t_focus_rel(struct v4l2_subdev *sd, s32 value)
+ 
+ /* Exposure */
+ 
+-static int ov5693_get_exposure(struct ov5693_device *sensor)
++static int ov5693_get_exposure(struct ov5693_device *ov5693)
+ {
+ 	u32 exposure = 0;
+ 	u16 tmp;
+ 	int ret = 0;
+ 
+ 	/* get exposure */
+-	ret = ov5693_read_reg(sensor->i2c_client, OV5693_8BIT,
++	ret = ov5693_read_reg(ov5693->client, OV5693_8BIT,
+ 			      OV5693_EXPOSURE_L,
+ 			      &tmp);
+ 	if (ret)
+@@ -783,14 +783,14 @@ static int ov5693_get_exposure(struct ov5693_device *sensor)
+ 
+ 	exposure |= ((tmp >> 4) & 0b1111);
+ 
+-	ret = ov5693_read_reg(sensor->i2c_client, OV5693_8BIT,
++	ret = ov5693_read_reg(ov5693->client, OV5693_8BIT,
+ 			      OV5693_EXPOSURE_M,
+ 			      &tmp);
+ 	if (ret)
+ 		return ret;
+ 
+ 	exposure |= (tmp << 4);
+-	ret = ov5693_read_reg(sensor->i2c_client, OV5693_8BIT,
++	ret = ov5693_read_reg(ov5693->client, OV5693_8BIT,
+ 			      OV5693_EXPOSURE_H,
+ 			      &tmp);
+ 	if (ret)
+@@ -802,7 +802,7 @@ static int ov5693_get_exposure(struct ov5693_device *sensor)
+ 	return ret;
+ }
+ 
+-static int ov5693_exposure_configure(struct ov5693_device *sensor, u32 exposure)
++static int ov5693_exposure_configure(struct ov5693_device *ov5693, u32 exposure)
+ {
+ 	int ret;
+ 
+@@ -812,40 +812,40 @@ static int ov5693_exposure_configure(struct ov5693_device *sensor, u32 exposure)
+ 	 */
+ 	exposure = exposure * 16;
+ 
+-	ov5693_get_exposure(sensor);
+-	ret = ov5693_write_reg(sensor->i2c_client, OV5693_8BIT,
++	ov5693_get_exposure(ov5693);
++	ret = ov5693_write_reg(ov5693->client, OV5693_8BIT,
+ 			OV5693_EXPOSURE_CTRL_HH_REG, OV5693_EXPOSURE_CTRL_HH(exposure));
+ 	if (ret)
+ 		return ret;
+ 
+-	ret = ov5693_write_reg(sensor->i2c_client, OV5693_8BIT,
++	ret = ov5693_write_reg(ov5693->client, OV5693_8BIT,
+ 			OV5693_EXPOSURE_CTRL_H_REG, OV5693_EXPOSURE_CTRL_H(exposure));
+ 	if (ret)
+ 		return ret;
+ 
+-	ret = ov5693_write_reg(sensor->i2c_client, OV5693_8BIT,
++	ret = ov5693_write_reg(ov5693->client, OV5693_8BIT,
+ 			OV5693_EXPOSURE_CTRL_L_REG, OV5693_EXPOSURE_CTRL_L(exposure));
+ 	if (ret)
+ 		return ret;
+-	ov5693_get_exposure(sensor);
++	ov5693_get_exposure(ov5693);
+ 
+ 	return 0;
+ }
+ 
+ /* Gain */
+ 
+-static int ov5693_get_gain(struct ov5693_device *sensor, u32 *gain)
++static int ov5693_get_gain(struct ov5693_device *ov5693, u32 *gain)
+ {
+ 	u16 gain_l, gain_h;
+ 	int ret = 0;
+ 
+-	ret = ov5693_read_reg(sensor->i2c_client, OV5693_8BIT,
++	ret = ov5693_read_reg(ov5693->client, OV5693_8BIT,
+ 			      OV5693_GAIN_CTRL_L_REG,
+ 			      &gain_l);
+ 	if (ret)
+ 		return ret;
+ 
+-	ret = ov5693_read_reg(sensor->i2c_client, OV5693_8BIT,
++	ret = ov5693_read_reg(ov5693->client, OV5693_8BIT,
+ 			      OV5693_GAIN_CTRL_H_REG,
+ 			      &gain_h);
+ 	if (ret)
+@@ -856,33 +856,33 @@ static int ov5693_get_gain(struct ov5693_device *sensor, u32 *gain)
+ 
+ 	return ret;
+ }
+-static int ov5693_gain_configure(struct ov5693_device *sensor, u32 gain)
++static int ov5693_gain_configure(struct ov5693_device *ov5693, u32 gain)
+ {
+ 	int ret;
+ 
+ 	/* A 1.0 gain is 0x400 */
+ 	gain = (gain * 1024)/1000;
+ 
+-	ret = ov5693_write_reg(sensor->i2c_client, OV5693_16BIT,
++	ret = ov5693_write_reg(ov5693->client, OV5693_16BIT,
+ 			OV5693_MWB_RED_GAIN_H, gain);
+ 	if (ret) {
+-		dev_err(&sensor->i2c_client->dev, "%s: write %x error, aborted\n",
++		dev_err(&ov5693->client->dev, "%s: write %x error, aborted\n",
+ 			__func__, OV5693_MWB_RED_GAIN_H);
+ 		return ret;
+ 	}
+ 
+-	ret = ov5693_write_reg(sensor->i2c_client, OV5693_16BIT,
++	ret = ov5693_write_reg(ov5693->client, OV5693_16BIT,
+ 			OV5693_MWB_GREEN_GAIN_H, gain);
+ 	if (ret) {
+-		dev_err(&sensor->i2c_client->dev, "%s: write %x error, aborted\n",
++		dev_err(&ov5693->client->dev, "%s: write %x error, aborted\n",
+ 			__func__, OV5693_MWB_RED_GAIN_H);
+ 		return ret;
+ 	}
+ 
+-	ret = ov5693_write_reg(sensor->i2c_client, OV5693_16BIT,
++	ret = ov5693_write_reg(ov5693->client, OV5693_16BIT,
+ 			OV5693_MWB_BLUE_GAIN_H, gain);
+ 	if (ret) {
+-		dev_err(&sensor->i2c_client->dev, "%s: write %x error, aborted\n",
++		dev_err(&ov5693->client->dev, "%s: write %x error, aborted\n",
+ 			__func__, OV5693_MWB_RED_GAIN_H);
+ 		return ret;
+ 	}
+@@ -890,7 +890,7 @@ static int ov5693_gain_configure(struct ov5693_device *sensor, u32 gain)
+ 	return 0;
+ }
+ 
+-static int ov5693_analog_gain_configure(struct ov5693_device *sensor, u32 gain)
++static int ov5693_analog_gain_configure(struct ov5693_device *ov5693, u32 gain)
+ {
+ 	int ret;
+ 
+@@ -899,18 +899,18 @@ static int ov5693_analog_gain_configure(struct ov5693_device *sensor, u32 gain)
+ 	 * those is not supported, so we have a tiny bit of bit shifting to
+ 	 * do.
+ 	 */
+-	ret = ov5693_write_reg(sensor->i2c_client, OV5693_8BIT,
++	ret = ov5693_write_reg(ov5693->client, OV5693_8BIT,
+ 				OV5693_AGC_L, OV5693_GAIN_CTRL_L(gain));
+ 	if (ret) {
+-		dev_err(&sensor->i2c_client->dev, "%s: write %x error, aborted\n",
++		dev_err(&ov5693->client->dev, "%s: write %x error, aborted\n",
+ 			__func__, OV5693_AGC_L);
+ 		return ret;
+ 	}
+ 
+-	ret = ov5693_write_reg(sensor->i2c_client, OV5693_8BIT,
++	ret = ov5693_write_reg(ov5693->client, OV5693_8BIT,
+ 				OV5693_AGC_H, OV5693_GAIN_CTRL_H(gain));
+ 	if (ret) {
+-		dev_err(&sensor->i2c_client->dev, "%s: write %x error, aborted\n",
++		dev_err(&ov5693->client->dev, "%s: write %x error, aborted\n",
+ 			__func__, OV5693_AGC_H);
+ 		return ret;
+ 	}
+@@ -920,60 +920,60 @@ static int ov5693_analog_gain_configure(struct ov5693_device *sensor, u32 gain)
+ 
+ static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl)
+ {
+-	struct ov5693_device *dev =
++	struct ov5693_device *ov5693 =
+ 	    container_of(ctrl->handler, struct ov5693_device, ctrl_handler);
+-	struct i2c_client *client = v4l2_get_subdevdata(&dev->sd);
++	struct i2c_client *client = v4l2_get_subdevdata(&ov5693->sd);
+ 	int ret = 0;
+ 
+ 	/* If VBLANK is altered we need to update exposure to compensate */
+ 	if (ctrl->id == V4L2_CID_VBLANK) {
+ 		int exposure_max;
+-		exposure_max = dev->mode->lines_per_frame - 8;
+-		__v4l2_ctrl_modify_range(dev->ctrls.exposure, dev->ctrls.exposure->minimum,
+-					 exposure_max, dev->ctrls.exposure->step,
+-					 dev->ctrls.exposure->val < exposure_max ?
+-					 dev->ctrls.exposure->val : exposure_max);
++		exposure_max = ov5693->mode->lines_per_frame - 8;
++		__v4l2_ctrl_modify_range(ov5693->ctrls.exposure, ov5693->ctrls.exposure->minimum,
++					 exposure_max, ov5693->ctrls.exposure->step,
++					 ov5693->ctrls.exposure->val < exposure_max ?
++					 ov5693->ctrls.exposure->val : exposure_max);
+ 	}
+ 
+ 	switch (ctrl->id) {
+ 	case V4L2_CID_FOCUS_ABSOLUTE:
+ 		dev_dbg(&client->dev, "%s: CID_FOCUS_ABSOLUTE:%d.\n",
+ 			__func__, ctrl->val);
+-		ret = ov5693_t_focus_abs(&dev->sd, ctrl->val);
++		ret = ov5693_t_focus_abs(&ov5693->sd, ctrl->val);
+ 		break;
+ 	case V4L2_CID_FOCUS_RELATIVE:
+ 		dev_dbg(&client->dev, "%s: CID_FOCUS_RELATIVE:%d.\n",
+ 			__func__, ctrl->val);
+-		ret = ov5693_t_focus_rel(&dev->sd, ctrl->val);
++		ret = ov5693_t_focus_rel(&ov5693->sd, ctrl->val);
+ 		break;
+ 	case V4L2_CID_EXPOSURE:
+ 		dev_dbg(&client->dev, "%s: CID_EXPOSURE:%d.\n",
+ 			__func__, ctrl->val);
+-		ret = ov5693_exposure_configure(dev, ctrl->val);
++		ret = ov5693_exposure_configure(ov5693, ctrl->val);
+ 		if (ret)
+ 			return ret;
+ 		break;
+ 	case V4L2_CID_ANALOGUE_GAIN:
+ 		dev_dbg(&client->dev, "%s: CID_ANALOGUE_GAIN:%d.\n",
+ 			__func__, ctrl->val);
+-		ret = ov5693_analog_gain_configure(dev, ctrl->val);
++		ret = ov5693_analog_gain_configure(ov5693, ctrl->val);
+ 		if (ret)
+ 			return ret;
+ 		break;
+ 	case V4L2_CID_DIGITAL_GAIN:
+ 		dev_dbg(&client->dev, "%s: CID_DIGITAL_GAIN:%d.\n",
+ 			__func__, ctrl->val);
+-		ret = ov5693_gain_configure(dev, ctrl->val);
++		ret = ov5693_gain_configure(ov5693, ctrl->val);
+ 		if (ret)
+ 			return ret;
+ 		break;
+ 	case V4L2_CID_HFLIP:
+-		return ov5693_flip_horz_configure(dev, !!ctrl->val);
++		return ov5693_flip_horz_configure(ov5693, !!ctrl->val);
+ 	case V4L2_CID_VFLIP:
+-		return ov5693_flip_vert_configure(dev, !!ctrl->val);
++		return ov5693_flip_vert_configure(ov5693, !!ctrl->val);
+ 	case V4L2_CID_VBLANK:
+ 		ret = ov5693_write_reg(client, OV5693_16BIT, OV5693_TIMING_VTS_H,
+-				       dev->mode->height + ctrl->val);
++				       ov5693->mode->height + ctrl->val);
+ 		break;
+ 	default:
+ 		ret = -EINVAL;
+@@ -983,16 +983,16 @@ static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl)
+ 
+ static int ov5693_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+ {
+-	struct ov5693_device *dev =
++	struct ov5693_device *ov5693 =
+ 	    container_of(ctrl->handler, struct ov5693_device, ctrl_handler);
+ 	int ret = 0;
+ 
+ 	switch (ctrl->id) {
+ 	case V4L2_CID_EXPOSURE_ABSOLUTE:
+-		ret = ov5693_q_exposure(&dev->sd, &ctrl->val);
++		ret = ov5693_q_exposure(&ov5693->sd, &ctrl->val);
+ 		break;
+ 	case V4L2_CID_AUTOGAIN:
+-		ret = ov5693_get_gain(dev, &ctrl->val);
++		ret = ov5693_get_gain(ov5693, &ctrl->val);
+ 		break;
+ 	case V4L2_CID_FOCUS_ABSOLUTE:
+ 		/* NOTE: there was atomisp-specific function ov5693_q_focus_abs() */
+@@ -1034,12 +1034,12 @@ static const struct v4l2_ctrl_config ov5693_controls[] = {
+ 	},
+ };
+ 
+-static int ov5693_isp_configure(struct ov5693_device *sensor)
++static int ov5693_isp_configure(struct ov5693_device *ov5693)
+ {
+ 	int ret;
+ 
+ 	/* Enable lens correction. */
+-	ret = ov5693_write_reg(sensor->i2c_client, OV5693_8BIT,
++	ret = ov5693_write_reg(ov5693->client, OV5693_8BIT,
+ 			   OV5693_ISP_CTRL0_REG, 0x86);
+ 	if (ret)
+ 		return ret;
+@@ -1049,18 +1049,18 @@ static int ov5693_isp_configure(struct ov5693_device *sensor)
+ 
+ static int ov5693_init(struct v4l2_subdev *sd)
+ {
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+ 	int ret;
+ 
+-	if (!dev->has_vcm)
++	if (!ov5693->has_vcm)
+ 		return 0;
+ 
+ 	dev_info(&client->dev, "%s\n", __func__);
+-	mutex_lock(&dev->input_lock);
+-	dev->vcm_update = false;
++	mutex_lock(&ov5693->lock);
++	ov5693->vcm_update = false;
+ 
+-	if (dev->vcm == VCM_AD5823) {
++	if (ov5693->vcm == VCM_AD5823) {
+ 		ret = vcm_ad_i2c_wr8(client, 0x01, 0x01); /* vcm init test */
+ 		if (ret)
+ 			dev_err(&client->dev,
+@@ -1079,16 +1079,16 @@ static int ov5693_init(struct v4l2_subdev *sd)
+ 	}
+ 
+ 	/*change initial focus value for ad5823*/
+-	if (dev->vcm == VCM_AD5823) {
+-		dev->focus = AD5823_INIT_FOCUS_POS;
++	if (ov5693->vcm == VCM_AD5823) {
++		ov5693->focus = AD5823_INIT_FOCUS_POS;
+ 		ov5693_t_focus_abs(sd, AD5823_INIT_FOCUS_POS);
+ 	} else {
+-		dev->focus = 0;
++		ov5693->focus = 0;
+ 		ov5693_t_focus_abs(sd, 0);
+ 	}
+ 
+-	ov5693_isp_configure(dev);
+-	mutex_unlock(&dev->input_lock);
++	ov5693_isp_configure(ov5693);
++	mutex_unlock(&ov5693->lock);
+ 
+ 	return 0;
+ }
+@@ -1096,32 +1096,32 @@ static int ov5693_init(struct v4l2_subdev *sd)
+ static int __power_up(struct v4l2_subdev *sd)
+ {
+ 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+-	struct ov5693_device *sensor = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 	int ret;
+ 
+-	ret = clk_prepare_enable(sensor->clk);
++	ret = clk_prepare_enable(ov5693->clk);
+ 	if (ret) {
+ 		dev_err(&client->dev, "Error enabling clock\n");
+ 		return -EINVAL;
+ 	}
+ 
+-	if (sensor->indicator_led)
+-		gpiod_set_value_cansleep(sensor->indicator_led, 1);
++	if (ov5693->indicator_led)
++		gpiod_set_value_cansleep(ov5693->indicator_led, 1);
+ 
+ 	ret = regulator_bulk_enable(OV5693_NUM_SUPPLIES,
+-			sensor->supplies);
++			ov5693->supplies);
+ 	if (ret)
+ 		goto fail_power;
+ 
+-	gpiod_set_value_cansleep(sensor->reset, 0);
++	gpiod_set_value_cansleep(ov5693->reset, 0);
+ 
+ 	__cci_delay(up_delay);
+ 
+ 	return 0;
+ 
+ fail_power:
+-	if (sensor->indicator_led)
+-		gpiod_set_value_cansleep(sensor->indicator_led, 0);
++	if (ov5693->indicator_led)
++		gpiod_set_value_cansleep(ov5693->indicator_led, 0);
+ 	dev_err(&client->dev, "sensor power-up failed\n");
+ 
+ 	return ret;
+@@ -1129,17 +1129,17 @@ static int __power_up(struct v4l2_subdev *sd)
+ 
+ static int power_down(struct v4l2_subdev *sd)
+ {
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 
+-	dev->focus = OV5693_INVALID_CONFIG;
++	ov5693->focus = OV5693_INVALID_CONFIG;
+ 
+-	gpiod_set_value_cansleep(dev->reset, 1);
++	gpiod_set_value_cansleep(ov5693->reset, 1);
+ 
+-	clk_disable_unprepare(dev->clk);
++	clk_disable_unprepare(ov5693->clk);
+ 
+-	if (dev->indicator_led)
+-		gpiod_set_value_cansleep(dev->indicator_led, 0);
+-	return regulator_bulk_disable(OV5693_NUM_SUPPLIES, dev->supplies);
++	if (ov5693->indicator_led)
++		gpiod_set_value_cansleep(ov5693->indicator_led, 0);
++	return regulator_bulk_disable(OV5693_NUM_SUPPLIES, ov5693->supplies);
+ }
+ 
+ static int power_up(struct v4l2_subdev *sd)
+@@ -1265,7 +1265,7 @@ static int get_resolution_index(int w, int h)
+ /* TODO: remove it. */
+ static int startup(struct v4l2_subdev *sd)
+ {
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+ 	int ret = 0;
+ 
+@@ -1282,7 +1282,7 @@ static int startup(struct v4l2_subdev *sd)
+ 		return ret;
+ 	}
+ 
+-	ret = ov5693_write_reg_array(client, ov5693_res[dev->fmt_idx].regs);
++	ret = ov5693_write_reg_array(client, ov5693_res[ov5693->fmt_idx].regs);
+ 	if (ret) {
+ 		dev_err(&client->dev, "ov5693 write register err.\n");
+ 		return ret;
+@@ -1296,7 +1296,7 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 			  struct v4l2_subdev_format *format)
+ {
+ 	struct v4l2_mbus_framefmt *fmt = &format->format;
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+ 	int ret = 0;
+ 	int idx;
+@@ -1307,7 +1307,7 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 	if (!fmt)
+ 		return -EINVAL;
+ 
+-	mutex_lock(&dev->input_lock);
++	mutex_lock(&ov5693->lock);
+ 	idx = nearest_resolution_index(fmt->width, fmt->height);
+ 	if (idx == -1) {
+ 		/* return the largest resolution */
+@@ -1325,8 +1325,8 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 		goto mutex_unlock;
+ 	}
+ 
+-	dev->fmt_idx = get_resolution_index(fmt->width, fmt->height);
+-	if (dev->fmt_idx == -1) {
++	ov5693->fmt_idx = get_resolution_index(fmt->width, fmt->height);
++	if (ov5693->fmt_idx == -1) {
+ 		dev_err(&client->dev, "get resolution fail\n");
+ 		ret = -EINVAL;
+ 		goto mutex_unlock;
+@@ -1339,9 +1339,9 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 			continue;
+ 		}
+ 
+-		mutex_unlock(&dev->input_lock);
++		mutex_unlock(&ov5693->lock);
+ 		ov5693_init(sd);
+-		mutex_lock(&dev->input_lock);
++		mutex_lock(&ov5693->lock);
+ 		ret = startup(sd);
+ 		if (ret)
+ 			dev_err(&client->dev, " startup() FAILED!\n");
+@@ -1353,8 +1353,6 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 		goto mutex_unlock;
+ 	}
+ 
+-
+-
+ 	/*
+ 	 * After sensor settings are set to HW, sometimes stream is started.
+ 	 * This would cause ISP timeout because ISP is not ready to receive
+@@ -1366,19 +1364,19 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 		dev_warn(&client->dev, "ov5693 stream off err\n");
+ 
+ mutex_unlock:
+-	mutex_unlock(&dev->input_lock);
++	mutex_unlock(&ov5693->lock);
+ 	return ret;
+ }
+ 
+ static const struct v4l2_rect *
+-__ov5693_get_pad_crop(struct ov5693_device *dev, struct v4l2_subdev_pad_config *cfg,
++__ov5693_get_pad_crop(struct ov5693_device *ov5693, struct v4l2_subdev_pad_config *cfg,
+ 		      unsigned int pad, enum v4l2_subdev_format_whence which)
+ {
+ 	switch (which) {
+ 	case V4L2_SUBDEV_FORMAT_TRY:
+-		return v4l2_subdev_get_try_crop(&dev->sd, cfg, pad);
++		return v4l2_subdev_get_try_crop(&ov5693->sd, cfg, pad);
+ 	case V4L2_SUBDEV_FORMAT_ACTIVE:
+-		return &dev->mode->crop;
++		return &ov5693->mode->crop;
+ 	}
+ 
+ 	return NULL;
+@@ -1389,12 +1387,12 @@ static int ov5693_get_selection(struct v4l2_subdev *sd,
+ {
+ 	switch (sel->target) {
+ 	case V4L2_SEL_TGT_CROP: {
+-		struct ov5693_device *dev = to_ov5693_sensor(sd);
++		struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 
+-		mutex_lock(&dev->input_lock);
+-		sel->r = *__ov5693_get_pad_crop(dev, cfg, sel->pad,
++		mutex_lock(&ov5693->lock);
++		sel->r = *__ov5693_get_pad_crop(ov5693, cfg, sel->pad,
+ 						sel->which);
+-		mutex_unlock(&dev->input_lock);
++		mutex_unlock(&ov5693->lock);
+ 
+ 		return 0;
+ 	}
+@@ -1424,7 +1422,7 @@ static int ov5693_get_fmt(struct v4l2_subdev *sd,
+ 			  struct v4l2_subdev_format *format)
+ {
+ 	struct v4l2_mbus_framefmt *fmt = &format->format;
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 
+ 	if (format->pad)
+ 		return -EINVAL;
+@@ -1432,8 +1430,8 @@ static int ov5693_get_fmt(struct v4l2_subdev *sd,
+ 	if (!fmt)
+ 		return -EINVAL;
+ 
+-	fmt->width = ov5693_res[dev->fmt_idx].width;
+-	fmt->height = ov5693_res[dev->fmt_idx].height;
++	fmt->width = ov5693_res[ov5693->fmt_idx].width;
++	fmt->height = ov5693_res[ov5693->fmt_idx].height;
+ 	fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
+ 
+ 	return 0;
+@@ -1481,7 +1479,7 @@ static int ov5693_s_stream(struct v4l2_subdev *sd, int enable)
+ 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+ 	int ret;
+ 
+-	mutex_lock(&dev->input_lock);
++	mutex_lock(&dev->lock);
+ 
+ 	/* power_on() here before streaming for regular PCs. */
+ 	if (enable) {
+@@ -1507,26 +1505,26 @@ static int ov5693_s_stream(struct v4l2_subdev *sd, int enable)
+ 		power_down(sd);
+ 
+ out:
+-	mutex_unlock(&dev->input_lock);
++	mutex_unlock(&dev->lock);
+ 
+ 	return ret;
+ }
+ 
+ static int ov5693_s_config(struct v4l2_subdev *sd, int irq)
+ {
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+ 	int ret = 0;
+ 
+-	mutex_lock(&dev->input_lock);
++	mutex_lock(&ov5693->lock);
+ 	ret = power_up(sd);
+ 	if (ret) {
+ 		dev_err(&client->dev, "ov5693 power-up err.\n");
+ 		goto fail_power_on;
+ 	}
+ 
+-	if (!dev->vcm)
+-		dev->vcm = vcm_detect(client);
++	if (!ov5693->vcm)
++		ov5693->vcm = vcm_detect(client);
+ 
+ 	/* config & detect sensor */
+ 	ret = ov5693_detect(client);
+@@ -1535,7 +1533,7 @@ static int ov5693_s_config(struct v4l2_subdev *sd, int irq)
+ 		goto fail_power_on;
+ 	}
+ 
+-	dev->otp_data = ov5693_otp_read(sd);
++	ov5693->otp_data = ov5693_otp_read(sd);
+ 
+ 	/* turn off sensor, after probed */
+ 	ret = power_down(sd);
+@@ -1543,24 +1541,24 @@ static int ov5693_s_config(struct v4l2_subdev *sd, int irq)
+ 		dev_err(&client->dev, "ov5693 power-off err.\n");
+ 		goto fail_power_on;
+ 	}
+-	mutex_unlock(&dev->input_lock);
++	mutex_unlock(&ov5693->lock);
+ 
+ 	return ret;
+ 
+ fail_power_on:
+ 	power_down(sd);
+ 	dev_err(&client->dev, "sensor power-gating failed\n");
+-	mutex_unlock(&dev->input_lock);
++	mutex_unlock(&ov5693->lock);
+ 	return ret;
+ }
+ 
+ static int ov5693_g_frame_interval(struct v4l2_subdev *sd,
+ 				   struct v4l2_subdev_frame_interval *interval)
+ {
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 
+ 	interval->interval.numerator = 1;
+-	interval->interval.denominator = ov5693_res[dev->fmt_idx].fps;
++	interval->interval.denominator = ov5693_res[ov5693->fmt_idx].fps;
+ 
+ 	return 0;
+ }
+@@ -1725,7 +1723,7 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 		return ret;
+ 
+ 	/* Use same lock for controls as for everything else. */
+-	ov5693->ctrl_handler.lock = &ov5693->input_lock;
++	ov5693->ctrl_handler.lock = &ov5693->lock;
+ 	ov5693->sd.ctrl_handler = &ov5693->ctrl_handler;
+ 
+ 	return 0;
+@@ -1733,21 +1731,38 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 
+ static int ov5693_configure_gpios(struct ov5693_device *ov5693)
+ {
+-	ov5693->reset = gpiod_get_index(&ov5693->i2c_client->dev, "reset", 0,
++	int ret;
++
++	ov5693->reset = gpiod_get_optional(&ov5693->client->dev, "reset",
+                                         GPIOD_OUT_HIGH);
+         if (IS_ERR(ov5693->reset)) {
+-                dev_err(&ov5693->i2c_client->dev, "Couldn't find reset GPIO\n");
+-                return -EINVAL;
++                dev_err(&ov5693->client->dev, "Couldn't find reset GPIO\n");
++                return PTR_ERR(ov5693->reset);
++        }
++
++	ov5693->powerdown = gpiod_get_optional(&ov5693->client->dev, "powerdown",
++                                        GPIOD_OUT_HIGH);
++        if (IS_ERR(ov5693->powerdown)) {
++                dev_err(&ov5693->client->dev, "Couldn't find powerdown GPIO\n");
++                ret = PTR_ERR(ov5693->powerdown);
++		goto err_put_reset;
+         }
+ 
+-        ov5693->indicator_led = gpiod_get_index_optional(&ov5693->i2c_client->dev, "indicator-led", 0,
++        ov5693->indicator_led = gpiod_get_optional(&ov5693->client->dev, "indicator-led",
+                                         GPIOD_OUT_HIGH);
+         if (IS_ERR(ov5693->indicator_led)) {
+-                dev_err(&ov5693->i2c_client->dev, "Couldn't find indicator-led GPIO\n");
+-                return -EINVAL;
++                dev_err(&ov5693->client->dev, "Couldn't find indicator-led GPIO\n");
++                ret = PTR_ERR(ov5693->indicator_led);
++		goto err_put_powerdown;
+         }
+ 
+         return 0;
++err_put_reset:
++	gpiod_put(ov5693->reset);
++err_put_powerdown:
++	gpiod_put(ov5693->powerdown);
++
++	return ret;
+ }
+ 
+ static int ov5693_get_regulators(struct ov5693_device *ov5693)
+@@ -1757,7 +1772,7 @@ static int ov5693_get_regulators(struct ov5693_device *ov5693)
+ 	for (i = 0; i < OV5693_NUM_SUPPLIES; i++)
+ 		ov5693->supplies[i].supply = ov5693_supply_names[i];
+ 
+-	return regulator_bulk_get(&ov5693->i2c_client->dev,
++	return regulator_bulk_get(&ov5693->client->dev,
+ 				       OV5693_NUM_SUPPLIES,
+ 				       ov5693->supplies);
+ }
+@@ -1773,13 +1788,13 @@ static int ov5693_probe(struct i2c_client *client)
+ 	if (!ov5693)
+ 		return -ENOMEM;
+ 
+-	ov5693->i2c_client = client;
++	ov5693->client = client;
+ 
+ 	/* check if VCM device exists */
+ 	/* TODO: read from SSDB */
+ 	ov5693->has_vcm = false;
+ 
+-	mutex_init(&ov5693->input_lock);
++	mutex_init(&ov5693->lock);
+ 
+ 	v4l2_i2c_subdev_init(&ov5693->sd, client, &ov5693_ops);
+ 
+diff --git a/drivers/media/i2c/ov5693.h b/drivers/media/i2c/ov5693.h
+index 7f1d31a82d3d..70ccb3aae4c7 100644
+--- a/drivers/media/i2c/ov5693.h
++++ b/drivers/media/i2c/ov5693.h
+@@ -241,14 +241,15 @@ enum vcm_type {
+  * ov5693 device structure.
+  */
+ struct ov5693_device {
+-	struct i2c_client *i2c_client;
++	struct i2c_client *client;
+ 	struct v4l2_subdev sd;
+ 	struct media_pad pad;
+ 	struct v4l2_mbus_framefmt format;
+-	struct mutex input_lock;
++	struct mutex lock;
+ 	struct v4l2_ctrl_handler ctrl_handler;
+ 
+         struct gpio_desc *reset;
++	struct gpio_desc *powerdown;
+         struct gpio_desc *indicator_led;
+         struct regulator_bulk_data supplies[OV5693_NUM_SUPPLIES];
+ 	struct clk *clk;
+-- 
+2.30.1
+
+From 7782702ee9456f20e2a43b92e78513760cd74342 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Thu, 28 Jan 2021 12:04:38 +0000
+Subject: [PATCH] media: i2c: Add pm_runtime support to ov5693 driver
+
+The ov5693 driver currently uses hacky and horrible power up/down methods
+called directly in s_stream. Add pm_runtime support and use that in
+s_stream instead. Replace all other uses of the power+up/down() calls with
+the single ov5693_sensor_stream() for now.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 183 +++++++++++++++++++++++++++++--------
+ drivers/media/i2c/ov5693.h |   1 +
+ 2 files changed, 146 insertions(+), 38 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 0643390c872a..f2eaa5f71a31 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -29,6 +29,7 @@
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
+ #include <linux/mm.h>
++#include <linux/pm_runtime.h>
+ #include <linux/regulator/consumer.h>
+ #include <linux/slab.h>
+ #include <linux/string.h>
+@@ -935,6 +936,10 @@ static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl)
+ 					 ov5693->ctrls.exposure->val : exposure_max);
+ 	}
+ 
++	/* Only apply changes to the controls if the device is powered up */
++	if (!pm_runtime_get_if_in_use(&ov5693->client->dev))
++		return 0;
++
+ 	switch (ctrl->id) {
+ 	case V4L2_CID_FOCUS_ABSOLUTE:
+ 		dev_dbg(&client->dev, "%s: CID_FOCUS_ABSOLUTE:%d.\n",
+@@ -950,27 +955,23 @@ static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl)
+ 		dev_dbg(&client->dev, "%s: CID_EXPOSURE:%d.\n",
+ 			__func__, ctrl->val);
+ 		ret = ov5693_exposure_configure(ov5693, ctrl->val);
+-		if (ret)
+-			return ret;
+ 		break;
+ 	case V4L2_CID_ANALOGUE_GAIN:
+ 		dev_dbg(&client->dev, "%s: CID_ANALOGUE_GAIN:%d.\n",
+ 			__func__, ctrl->val);
+ 		ret = ov5693_analog_gain_configure(ov5693, ctrl->val);
+-		if (ret)
+-			return ret;
+ 		break;
+ 	case V4L2_CID_DIGITAL_GAIN:
+ 		dev_dbg(&client->dev, "%s: CID_DIGITAL_GAIN:%d.\n",
+ 			__func__, ctrl->val);
+ 		ret = ov5693_gain_configure(ov5693, ctrl->val);
+-		if (ret)
+-			return ret;
+ 		break;
+ 	case V4L2_CID_HFLIP:
+-		return ov5693_flip_horz_configure(ov5693, !!ctrl->val);
++		ret = ov5693_flip_horz_configure(ov5693, !!ctrl->val);
++		break;
+ 	case V4L2_CID_VFLIP:
+-		return ov5693_flip_vert_configure(ov5693, !!ctrl->val);
++		ret = ov5693_flip_vert_configure(ov5693, !!ctrl->val);
++		break;
+ 	case V4L2_CID_VBLANK:
+ 		ret = ov5693_write_reg(client, OV5693_16BIT, OV5693_TIMING_VTS_H,
+ 				       ov5693->mode->height + ctrl->val);
+@@ -978,6 +979,9 @@ static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl)
+ 	default:
+ 		ret = -EINVAL;
+ 	}
++
++	pm_runtime_put(&ov5693->client->dev);
++
+ 	return ret;
+ }
+ 
+@@ -1093,6 +1097,106 @@ static int ov5693_init(struct v4l2_subdev *sd)
+ 	return 0;
+ }
+ 
++static int ov5693_sw_standby(struct ov5693_device *ov5693, bool standby)
++{
++	return ov5693_write_reg(ov5693->client, OV5693_8BIT, OV5693_SW_STREAM,
++			       standby ? OV5693_STOP_STREAMING : OV5693_START_STREAMING);
++}
++
++static void ov5693_sensor_powerdown(struct ov5693_device *ov5693)
++{
++	gpiod_set_value_cansleep(ov5693->reset, 1);
++	gpiod_set_value_cansleep(ov5693->powerdown, 1);
++
++	regulator_bulk_disable(OV5693_NUM_SUPPLIES, ov5693->supplies);
++
++	clk_disable_unprepare(ov5693->clk);
++	gpiod_set_value_cansleep(ov5693->indicator_led, 0);
++}
++
++
++static int ov5693_sensor_powerup(struct ov5693_device *ov5693)
++{
++	int ret = 0;
++
++	gpiod_set_value_cansleep(ov5693->reset, 1);
++	gpiod_set_value_cansleep(ov5693->powerdown, 1);
++
++	ret = clk_prepare_enable(ov5693->clk);
++	if (ret) {
++		dev_err(&ov5693->client->dev, "Failed to enable clk\n");
++		goto fail_power;
++	}
++
++	ret = regulator_bulk_enable(OV5693_NUM_SUPPLIES, ov5693->supplies);
++	if (ret) {
++		dev_err(&ov5693->client->dev, "Failed to enable regulators\n");
++		goto fail_power;
++	}
++
++	gpiod_set_value_cansleep(ov5693->reset, 0);
++	gpiod_set_value_cansleep(ov5693->powerdown, 0);
++	gpiod_set_value_cansleep(ov5693->indicator_led, 1);
++
++	usleep_range(20000, 25000);
++
++	return 0;
++
++fail_power:
++	ov5693_sensor_powerdown(ov5693);
++	return ret;
++}
++
++static int __maybe_unused ov5693_sensor_suspend(struct device *dev)
++{
++	struct i2c_client *client = i2c_verify_client(dev);
++	struct v4l2_subdev *sd = i2c_get_clientdata(client);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
++	int ret;
++
++	mutex_lock(&ov5693->lock);
++
++	if (ov5693->streaming) {
++		ret = ov5693_sw_standby(ov5693, true);
++		if (ret)
++			goto out_unlock;
++	}
++
++	ov5693_sensor_powerdown(ov5693);
++
++out_unlock:
++	mutex_unlock(&ov5693->lock);
++	return ret;
++}
++
++static int __maybe_unused ov5693_sensor_resume(struct device *dev)
++{
++	struct i2c_client *client = i2c_verify_client(dev);
++	struct v4l2_subdev *sd = i2c_get_clientdata(client);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
++	int ret;
++
++	mutex_lock(&ov5693->lock);
++
++	ret = ov5693_sensor_powerup(ov5693);
++	if (ret)
++		goto out_unlock;
++
++	if (ov5693->streaming) {
++		ret = ov5693_sw_standby(ov5693, false);
++		if (ret)
++			goto err_power;
++	}
++
++	goto out_unlock;
++
++err_power:
++	ov5693_sensor_powerdown(ov5693);
++out_unlock:
++	mutex_unlock(&ov5693->lock);
++	return ret;
++}
++
+ static int __power_up(struct v4l2_subdev *sd)
+ {
+ 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+@@ -1134,6 +1238,7 @@ static int power_down(struct v4l2_subdev *sd)
+ 	ov5693->focus = OV5693_INVALID_CONFIG;
+ 
+ 	gpiod_set_value_cansleep(ov5693->reset, 1);
++	gpiod_set_value_cansleep(ov5693->powerdown, 1);
+ 
+ 	clk_disable_unprepare(ov5693->clk);
+ 
+@@ -1333,7 +1438,7 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 	}
+ 
+ 	for (cnt = 0; cnt < OV5693_POWER_UP_RETRY_NUM; cnt++) {
+-		ret = power_up(sd);
++		ret = ov5693_sensor_powerup(ov5693);
+ 		if (ret) {
+ 			dev_err(&client->dev, "power up failed\n");
+ 			continue;
+@@ -1475,38 +1580,34 @@ static int ov5693_detect(struct i2c_client *client)
+ 
+ static int ov5693_s_stream(struct v4l2_subdev *sd, int enable)
+ {
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
+-	struct i2c_client *client = v4l2_get_subdevdata(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 	int ret;
+ 
+-	mutex_lock(&dev->lock);
+-
+-	/* power_on() here before streaming for regular PCs. */
+ 	if (enable) {
+-		ret = power_up(sd);
+-		if (ret) {
+-			dev_err(&client->dev, "sensor power-up error\n");
+-			goto out;
+-		}
++		ret = pm_runtime_get_sync(&ov5693->client->dev);
++		if (ret < 0)
++			goto err_power_down;
+ 	}
+ 
+-	ret = __v4l2_ctrl_handler_setup(&dev->ctrl_handler);
+-	if (ret) {
+-		power_down(sd);
+-		return ret;
+-	}
++	ret = __v4l2_ctrl_handler_setup(&ov5693->ctrl_handler);
++	if (ret)
++		goto err_power_down;
+ 
+-	ret = ov5693_write_reg(client, OV5693_8BIT, OV5693_SW_STREAM,
+-			       enable ? OV5693_START_STREAMING :
+-			       OV5693_STOP_STREAMING);
++	mutex_lock(&ov5693->lock);
++	ret = ov5693_sw_standby(ov5693, !enable);
++	mutex_unlock(&ov5693->lock);
++
++	if (ret)
++		goto err_power_down;
++	ov5693->streaming = !!enable;
+ 
+ 	/* power_off() here after streaming for regular PCs. */
+ 	if (!enable)
+-		power_down(sd);
+-
+-out:
+-	mutex_unlock(&dev->lock);
++		pm_runtime_put(&ov5693->client->dev);
+ 
++	return 0;
++err_power_down:
++	pm_runtime_put_noidle(&ov5693->client->dev);
+ 	return ret;
+ }
+ 
+@@ -1517,7 +1618,7 @@ static int ov5693_s_config(struct v4l2_subdev *sd, int irq)
+ 	int ret = 0;
+ 
+ 	mutex_lock(&ov5693->lock);
+-	ret = power_up(sd);
++	ret = ov5693_sensor_powerup(ov5693);
+ 	if (ret) {
+ 		dev_err(&client->dev, "ov5693 power-up err.\n");
+ 		goto fail_power_on;
+@@ -1536,17 +1637,14 @@ static int ov5693_s_config(struct v4l2_subdev *sd, int irq)
+ 	ov5693->otp_data = ov5693_otp_read(sd);
+ 
+ 	/* turn off sensor, after probed */
+-	ret = power_down(sd);
+-	if (ret) {
+-		dev_err(&client->dev, "ov5693 power-off err.\n");
+-		goto fail_power_on;
+-	}
++	ov5693_sensor_powerdown(ov5693);
++
+ 	mutex_unlock(&ov5693->lock);
+ 
+ 	return ret;
+ 
+ fail_power_on:
+-	power_down(sd);
++	ov5693_sensor_powerdown(ov5693);
+ 	dev_err(&client->dev, "sensor power-gating failed\n");
+ 	mutex_unlock(&ov5693->lock);
+ 	return ret;
+@@ -1830,6 +1928,9 @@ static int ov5693_probe(struct i2c_client *client)
+ 	if (ret)
+ 		ov5693_remove(client);
+ 
++	pm_runtime_enable(&client->dev);
++	pm_runtime_set_suspended(&client->dev);
++
+ 	ret = v4l2_async_register_subdev_sensor_common(&ov5693->sd);
+ 	if (ret) {
+ 		dev_err(&client->dev, "failed to register V4L2 subdev: %d", ret);
+@@ -1839,6 +1940,7 @@ static int ov5693_probe(struct i2c_client *client)
+ 	return ret;
+ 
+ media_entity_cleanup:
++	pm_runtime_disable(&client->dev);
+ 	media_entity_cleanup(&ov5693->sd.entity);
+ out_put_reset:
+         gpiod_put(ov5693->reset);
+@@ -1848,6 +1950,10 @@ static int ov5693_probe(struct i2c_client *client)
+ 	return ret;
+ }
+ 
++static const struct dev_pm_ops ov5693_pm_ops = {
++	SET_RUNTIME_PM_OPS(ov5693_sensor_suspend, ov5693_sensor_resume, NULL)
++};
++
+ static const struct acpi_device_id ov5693_acpi_match[] = {
+ 	{"INT33BE"},
+ 	{},
+@@ -1858,6 +1964,7 @@ static struct i2c_driver ov5693_driver = {
+ 	.driver = {
+ 		.name = "ov5693",
+ 		.acpi_match_table = ov5693_acpi_match,
++		.pm = &ov5693_pm_ops,
+ 	},
+ 	.probe_new = ov5693_probe,
+ 	.remove = ov5693_remove,
+diff --git a/drivers/media/i2c/ov5693.h b/drivers/media/i2c/ov5693.h
+index 70ccb3aae4c7..b78d3b474a43 100644
+--- a/drivers/media/i2c/ov5693.h
++++ b/drivers/media/i2c/ov5693.h
+@@ -256,6 +256,7 @@ struct ov5693_device {
+ 
+ 	/* Current mode */
+ 	const struct ov5693_resolution *mode;
++	bool streaming;
+ 
+ 	struct camera_sensor_platform_data *platform_data;
+ 	ktime_t timestamp_t_focus_abs;
+-- 
+2.30.1
+
+From 103d1e9d84c51990aea3d5ddb43e64fafb03908d Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Thu, 28 Jan 2021 12:07:36 +0000
+Subject: [PATCH] media: i2c: Remove old power methods from ov5693
+
+Now that we have replaced the power_up/down() methods with a unified
+function and pm_runtime support, we can remove these old methods from the
+driver entirely along with some macros and a header.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 114 -------------------------------------
+ 1 file changed, 114 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index f2eaa5f71a31..ce26ce86fbd5 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -27,7 +27,6 @@
+ #include <linux/kernel.h>
+ #include <linux/kmod.h>
+ #include <linux/module.h>
+-#include <linux/moduleparam.h>
+ #include <linux/mm.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/regulator/consumer.h>
+@@ -40,27 +39,6 @@
+ #include "ov5693.h"
+ #include "ad5823.h"
+ 
+-#define __cci_delay(t) \
+-	do { \
+-		if ((t) < 10) { \
+-			usleep_range((t) * 1000, ((t) + 1) * 1000); \
+-		} else { \
+-			msleep((t)); \
+-		} \
+-	} while (0)
+-
+-/* Value 30ms reached through experimentation on byt ecs.
+- * The DS specifies a much lower value but when using a smaller value
+- * the I2C bus sometimes locks up permanently when starting the camera.
+- * This issue could not be reproduced on cht, so we can reduce the
+- * delay value to a lower value when insmod.
+- */
+-static uint up_delay = 30;
+-module_param(up_delay, uint, 0644);
+-MODULE_PARM_DESC(up_delay,
+-		 "Delay prior to the first CCI transaction for ov5693");
+-
+-
+ /* Exposure/gain */
+ 
+ #define OV5693_EXPOSURE_CTRL_HH_REG		0x3500
+@@ -1197,93 +1175,6 @@ static int __maybe_unused ov5693_sensor_resume(struct device *dev)
+ 	return ret;
+ }
+ 
+-static int __power_up(struct v4l2_subdev *sd)
+-{
+-	struct i2c_client *client = v4l2_get_subdevdata(sd);
+-	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+-	int ret;
+-
+-	ret = clk_prepare_enable(ov5693->clk);
+-	if (ret) {
+-		dev_err(&client->dev, "Error enabling clock\n");
+-		return -EINVAL;
+-	}
+-
+-	if (ov5693->indicator_led)
+-		gpiod_set_value_cansleep(ov5693->indicator_led, 1);
+-
+-	ret = regulator_bulk_enable(OV5693_NUM_SUPPLIES,
+-			ov5693->supplies);
+-	if (ret)
+-		goto fail_power;
+-
+-	gpiod_set_value_cansleep(ov5693->reset, 0);
+-
+-	__cci_delay(up_delay);
+-
+-	return 0;
+-
+-fail_power:
+-	if (ov5693->indicator_led)
+-		gpiod_set_value_cansleep(ov5693->indicator_led, 0);
+-	dev_err(&client->dev, "sensor power-up failed\n");
+-
+-	return ret;
+-}
+-
+-static int power_down(struct v4l2_subdev *sd)
+-{
+-	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+-
+-	ov5693->focus = OV5693_INVALID_CONFIG;
+-
+-	gpiod_set_value_cansleep(ov5693->reset, 1);
+-	gpiod_set_value_cansleep(ov5693->powerdown, 1);
+-
+-	clk_disable_unprepare(ov5693->clk);
+-
+-	if (ov5693->indicator_led)
+-		gpiod_set_value_cansleep(ov5693->indicator_led, 0);
+-	return regulator_bulk_disable(OV5693_NUM_SUPPLIES, ov5693->supplies);
+-}
+-
+-static int power_up(struct v4l2_subdev *sd)
+-{
+-	static const int retry_count = 4;
+-	int i, ret;
+-
+-	for (i = 0; i < retry_count; i++) {
+-		ret = __power_up(sd);
+-		if (!ret)
+-			return 0;
+-
+-		power_down(sd);
+-	}
+-	return ret;
+-}
+-
+-static int ov5693_s_power(struct v4l2_subdev *sd, int on)
+-{
+-	struct i2c_client *client = v4l2_get_subdevdata(sd);
+-	int ret;
+-
+-	dev_info(&client->dev, "%s: on %d\n", __func__, on);
+-
+-	if (on == 0)
+-		return power_down(sd);
+-
+-	/* on == 1 */
+-	ret = power_up(sd);
+-	if (!ret) {
+-		ret = ov5693_init(sd);
+-		/* restore settings */
+-		ov5693_res = ov5693_res_video;
+-		N_RES = N_RES_VIDEO;
+-	}
+-
+-	return ret;
+-}
+-
+ /*
+  * distance - calculate the distance
+  * @res: resolution
+@@ -1694,10 +1585,6 @@ static const struct v4l2_subdev_video_ops ov5693_video_ops = {
+ 	.g_frame_interval = ov5693_g_frame_interval,
+ };
+ 
+-static const struct v4l2_subdev_core_ops ov5693_core_ops = {
+-	.s_power = ov5693_s_power,
+-};
+-
+ static const struct v4l2_subdev_pad_ops ov5693_pad_ops = {
+ 	.enum_mbus_code = ov5693_enum_mbus_code,
+ 	.enum_frame_size = ov5693_enum_frame_size,
+@@ -1707,7 +1594,6 @@ static const struct v4l2_subdev_pad_ops ov5693_pad_ops = {
+ };
+ 
+ static const struct v4l2_subdev_ops ov5693_ops = {
+-	.core = &ov5693_core_ops,
+ 	.video = &ov5693_video_ops,
+ 	.pad = &ov5693_pad_ops,
+ };
+-- 
+2.30.1
+
+From faea14734a72b8dcc08860d85709fad37fe15567 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Thu, 28 Jan 2021 12:14:00 +0000
+Subject: [PATCH] media: i2c: Trim unused headers from ov5693
+
+The ov5693 driver includes a ton of unecessary headers,
+trim the list down.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 8 --------
+ 1 file changed, 8 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index ce26ce86fbd5..b3b391a49fdb 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -20,19 +20,11 @@
+ #include <linux/clk.h>
+ #include <linux/delay.h>
+ #include <linux/device.h>
+-#include <linux/errno.h>
+ #include <linux/i2c.h>
+-#include <linux/init.h>
+-#include <linux/io.h>
+-#include <linux/kernel.h>
+-#include <linux/kmod.h>
+ #include <linux/module.h>
+-#include <linux/mm.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/regulator/consumer.h>
+ #include <linux/slab.h>
+-#include <linux/string.h>
+-#include <linux/types.h>
+ #include <media/v4l2-device.h>
+ #include <media/v4l2-fwnode.h>
+ 
+-- 
+2.30.1
+
+From bcb92e99e64d26c45b463436002e445fff6c0d47 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Sat, 13 Feb 2021 21:39:35 +0000
+Subject: [PATCH] media: i2c: Remove VCM stuff
+
+This all needs binning, since we have no idea if it's right. It needs to
+be moved to a driver for the VCM device I guess.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 325 +------------------------------------
+ 1 file changed, 1 insertion(+), 324 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index b3b391a49fdb..2c82b6578de9 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -76,72 +76,6 @@
+ #define OV5693_PIXEL_ARRAY_WIDTH	2592U
+ #define OV5693_PIXEL_ARRAY_HEIGHT	1944U
+ 
+-static int vcm_ad_i2c_wr8(struct i2c_client *client, u8 reg, u8 val)
+-{
+-	int err;
+-	struct i2c_msg msg;
+-	u8 buf[2];
+-
+-	buf[0] = reg;
+-	buf[1] = val;
+-
+-	msg.addr = VCM_ADDR;
+-	msg.flags = 0;
+-	msg.len = 2;
+-	msg.buf = &buf[0];
+-
+-	err = i2c_transfer(client->adapter, &msg, 1);
+-	if (err != 1) {
+-		dev_err(&client->dev, "%s: vcm i2c fail, err code = %d\n",
+-			__func__, err);
+-		return -EIO;
+-	}
+-	return 0;
+-}
+-
+-static int ad5823_i2c_write(struct i2c_client *client, u8 reg, u8 val)
+-{
+-	struct i2c_msg msg;
+-	u8 buf[2];
+-
+-	buf[0] = reg;
+-	buf[1] = val;
+-	msg.addr = AD5823_VCM_ADDR;
+-	msg.flags = 0;
+-	msg.len = 0x02;
+-	msg.buf = &buf[0];
+-
+-	if (i2c_transfer(client->adapter, &msg, 1) != 1)
+-		return -EIO;
+-	return 0;
+-}
+-
+-static int ad5823_i2c_read(struct i2c_client *client, u8 reg, u8 *val)
+-{
+-	struct i2c_msg msg[2];
+-	u8 buf[2];
+-
+-	buf[0] = reg;
+-	buf[1] = 0;
+-
+-	msg[0].addr = AD5823_VCM_ADDR;
+-	msg[0].flags = 0;
+-	msg[0].len = 0x01;
+-	msg[0].buf = &buf[0];
+-
+-	msg[1].addr = 0x0c;
+-	msg[1].flags = I2C_M_RD;
+-	msg[1].len = 0x01;
+-	msg[1].buf = &buf[1];
+-	*val = 0;
+-	if (i2c_transfer(client->adapter, msg, 2) != 2)
+-		return -EIO;
+-	*val = buf[1];
+-	return 0;
+-}
+-
+-static const u32 ov5693_embedded_effective_size = 28;
+-
+ /* i2c read/write stuff */
+ static int ov5693_read_reg(struct i2c_client *client,
+ 			   u16 data_length, u16 reg, u16 *val)
+@@ -215,69 +149,6 @@ static int ov5693_i2c_write(struct i2c_client *client, u16 len, u8 *data)
+ 	return ret == num_msg ? 0 : -EIO;
+ }
+ 
+-static int vcm_dw_i2c_write(struct i2c_client *client, u16 data)
+-{
+-	struct i2c_msg msg;
+-	const int num_msg = 1;
+-	int ret;
+-	__be16 val;
+-
+-	val = cpu_to_be16(data);
+-	msg.addr = VCM_ADDR;
+-	msg.flags = 0;
+-	msg.len = OV5693_16BIT;
+-	msg.buf = (void *)&val;
+-
+-	ret = i2c_transfer(client->adapter, &msg, 1);
+-
+-	return ret == num_msg ? 0 : -EIO;
+-}
+-
+-/*
+- * Theory: per datasheet, the two VCMs both allow for a 2-byte read.
+- * The DW9714 doesn't actually specify what this does (it has a
+- * two-byte write-only protocol, but specifies the read sequence as
+- * legal), but it returns the same data (zeroes) always, after an
+- * undocumented initial NAK.  The AD5823 has a one-byte address
+- * register to which all writes go, and subsequent reads will cycle
+- * through the 8 bytes of registers.  Notably, the default values (the
+- * device is always power-cycled affirmatively, so we can rely on
+- * these) in AD5823 are not pairwise repetitions of the same 16 bit
+- * word.  So all we have to do is sequentially read two bytes at a
+- * time and see if we detect a difference in any of the first four
+- * pairs.
+- */
+-static int vcm_detect(struct i2c_client *client)
+-{
+-	int i, ret;
+-	struct i2c_msg msg;
+-	u16 data0 = 0, data;
+-
+-	for (i = 0; i < 4; i++) {
+-		msg.addr = VCM_ADDR;
+-		msg.flags = I2C_M_RD;
+-		msg.len = sizeof(data);
+-		msg.buf = (u8 *)&data;
+-		ret = i2c_transfer(client->adapter, &msg, 1);
+-
+-		/*
+-		 * DW9714 always fails the first read and returns
+-		 * zeroes for subsequent ones
+-		 */
+-		if (i == 0 && ret == -EREMOTEIO) {
+-			data0 = 0;
+-			continue;
+-		}
+-
+-		if (i == 0)
+-			data0 = data;
+-
+-		if (data != data0)
+-			return VCM_AD5823;
+-	}
+-	return ret == 1 ? VCM_DW9714 : ret;
+-}
+-
+ static int ov5693_write_reg(struct i2c_client *client, u16 data_length,
+ 			    u16 reg, u16 val)
+ {
+@@ -654,89 +525,6 @@ static int ov5693_q_exposure(struct v4l2_subdev *sd, s32 *value)
+ 	return ret;
+ }
+ 
+-static int ad5823_t_focus_vcm(struct v4l2_subdev *sd, u16 val)
+-{
+-	struct i2c_client *client = v4l2_get_subdevdata(sd);
+-	int ret = -EINVAL;
+-	u8 vcm_code;
+-
+-	ret = ad5823_i2c_read(client, AD5823_REG_VCM_CODE_MSB, &vcm_code);
+-	if (ret)
+-		return ret;
+-
+-	/* set reg VCM_CODE_MSB Bit[1:0] */
+-	vcm_code = (vcm_code & VCM_CODE_MSB_MASK) |
+-		   ((val >> 8) & ~VCM_CODE_MSB_MASK);
+-	ret = ad5823_i2c_write(client, AD5823_REG_VCM_CODE_MSB, vcm_code);
+-	if (ret)
+-		return ret;
+-
+-	/* set reg VCM_CODE_LSB Bit[7:0] */
+-	ret = ad5823_i2c_write(client, AD5823_REG_VCM_CODE_LSB, (val & 0xff));
+-	if (ret)
+-		return ret;
+-
+-	/* set required vcm move time */
+-	vcm_code = AD5823_RESONANCE_PERIOD / AD5823_RESONANCE_COEF
+-		   - AD5823_HIGH_FREQ_RANGE;
+-	ret = ad5823_i2c_write(client, AD5823_REG_VCM_MOVE_TIME, vcm_code);
+-
+-	return ret;
+-}
+-
+-static int ad5823_t_focus_abs(struct v4l2_subdev *sd, s32 value)
+-{
+-	value = min(value, AD5823_MAX_FOCUS_POS);
+-	return ad5823_t_focus_vcm(sd, value);
+-}
+-
+-static int ov5693_t_focus_abs(struct v4l2_subdev *sd, s32 value)
+-{
+-	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+-	struct i2c_client *client = v4l2_get_subdevdata(sd);
+-	int ret = 0;
+-
+-	dev_dbg(&client->dev, "%s: FOCUS_POS: 0x%x\n", __func__, value);
+-	value = clamp(value, 0, OV5693_VCM_MAX_FOCUS_POS);
+-	if (ov5693->vcm == VCM_DW9714) {
+-		if (ov5693->vcm_update) {
+-			ret = vcm_dw_i2c_write(client, VCM_PROTECTION_OFF);
+-			if (ret)
+-				return ret;
+-			ret = vcm_dw_i2c_write(client, DIRECT_VCM);
+-			if (ret)
+-				return ret;
+-			ret = vcm_dw_i2c_write(client, VCM_PROTECTION_ON);
+-			if (ret)
+-				return ret;
+-			ov5693->vcm_update = false;
+-		}
+-		ret = vcm_dw_i2c_write(client,
+-				       vcm_val(value, VCM_DEFAULT_S));
+-	} else if (ov5693->vcm == VCM_AD5823) {
+-		ad5823_t_focus_abs(sd, value);
+-	}
+-	if (ret == 0) {
+-		ov5693->number_of_steps = value - ov5693->focus;
+-		ov5693->focus = value;
+-		ov5693->timestamp_t_focus_abs = ktime_get();
+-	} else
+-		dev_err(&client->dev,
+-			"%s: i2c failed. ret %d\n", __func__, ret);
+-
+-	return ret;
+-}
+-
+-static int ov5693_t_focus_rel(struct v4l2_subdev *sd, s32 value)
+-{
+-	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+-
+-	return ov5693_t_focus_abs(sd, ov5693->focus + value);
+-}
+-
+-#define DELAY_PER_STEP_NS	1000000
+-#define DELAY_MAX_PER_STEP_NS	(1000000 * 1023)
+-
+ /* Exposure */
+ 
+ static int ov5693_get_exposure(struct ov5693_device *ov5693)
+@@ -911,16 +699,6 @@ static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl)
+ 		return 0;
+ 
+ 	switch (ctrl->id) {
+-	case V4L2_CID_FOCUS_ABSOLUTE:
+-		dev_dbg(&client->dev, "%s: CID_FOCUS_ABSOLUTE:%d.\n",
+-			__func__, ctrl->val);
+-		ret = ov5693_t_focus_abs(&ov5693->sd, ctrl->val);
+-		break;
+-	case V4L2_CID_FOCUS_RELATIVE:
+-		dev_dbg(&client->dev, "%s: CID_FOCUS_RELATIVE:%d.\n",
+-			__func__, ctrl->val);
+-		ret = ov5693_t_focus_rel(&ov5693->sd, ctrl->val);
+-		break;
+ 	case V4L2_CID_EXPOSURE:
+ 		dev_dbg(&client->dev, "%s: CID_EXPOSURE:%d.\n",
+ 			__func__, ctrl->val);
+@@ -983,90 +761,6 @@ static const struct v4l2_ctrl_ops ov5693_ctrl_ops = {
+ 	.g_volatile_ctrl = ov5693_g_volatile_ctrl
+ };
+ 
+-static const struct v4l2_ctrl_config ov5693_controls[] = {
+-	{
+-		.ops = &ov5693_ctrl_ops,
+-		.id = V4L2_CID_FOCUS_ABSOLUTE,
+-		.type = V4L2_CTRL_TYPE_INTEGER,
+-		.name = "focus move absolute",
+-		.min = 0,
+-		.max = OV5693_VCM_MAX_FOCUS_POS,
+-		.step = 1,
+-		.def = 0,
+-		.flags = 0,
+-	},
+-	{
+-		.ops = &ov5693_ctrl_ops,
+-		.id = V4L2_CID_FOCUS_RELATIVE,
+-		.type = V4L2_CTRL_TYPE_INTEGER,
+-		.name = "focus move relative",
+-		.min = OV5693_VCM_MAX_FOCUS_NEG,
+-		.max = OV5693_VCM_MAX_FOCUS_POS,
+-		.step = 1,
+-		.def = 0,
+-		.flags = 0,
+-	},
+-};
+-
+-static int ov5693_isp_configure(struct ov5693_device *ov5693)
+-{
+-	int ret;
+-
+-	/* Enable lens correction. */
+-	ret = ov5693_write_reg(ov5693->client, OV5693_8BIT,
+-			   OV5693_ISP_CTRL0_REG, 0x86);
+-	if (ret)
+-		return ret;
+-
+-	return 0;
+-}
+-
+-static int ov5693_init(struct v4l2_subdev *sd)
+-{
+-	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+-	struct i2c_client *client = v4l2_get_subdevdata(sd);
+-	int ret;
+-
+-	if (!ov5693->has_vcm)
+-		return 0;
+-
+-	dev_info(&client->dev, "%s\n", __func__);
+-	mutex_lock(&ov5693->lock);
+-	ov5693->vcm_update = false;
+-
+-	if (ov5693->vcm == VCM_AD5823) {
+-		ret = vcm_ad_i2c_wr8(client, 0x01, 0x01); /* vcm init test */
+-		if (ret)
+-			dev_err(&client->dev,
+-				"vcm reset failed\n");
+-		/*change the mode*/
+-		ret = ad5823_i2c_write(client, AD5823_REG_VCM_CODE_MSB,
+-				       AD5823_RING_CTRL_ENABLE);
+-		if (ret)
+-			dev_err(&client->dev,
+-				"vcm enable ringing failed\n");
+-		ret = ad5823_i2c_write(client, AD5823_REG_MODE,
+-				       AD5823_ARC_RES1);
+-		if (ret)
+-			dev_err(&client->dev,
+-				"vcm change mode failed\n");
+-	}
+-
+-	/*change initial focus value for ad5823*/
+-	if (ov5693->vcm == VCM_AD5823) {
+-		ov5693->focus = AD5823_INIT_FOCUS_POS;
+-		ov5693_t_focus_abs(sd, AD5823_INIT_FOCUS_POS);
+-	} else {
+-		ov5693->focus = 0;
+-		ov5693_t_focus_abs(sd, 0);
+-	}
+-
+-	ov5693_isp_configure(ov5693);
+-	mutex_unlock(&ov5693->lock);
+-
+-	return 0;
+-}
+-
+ static int ov5693_sw_standby(struct ov5693_device *ov5693, bool standby)
+ {
+ 	return ov5693_write_reg(ov5693->client, OV5693_8BIT, OV5693_SW_STREAM,
+@@ -1327,9 +1021,6 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 			continue;
+ 		}
+ 
+-		mutex_unlock(&ov5693->lock);
+-		ov5693_init(sd);
+-		mutex_lock(&ov5693->lock);
+ 		ret = startup(sd);
+ 		if (ret)
+ 			dev_err(&client->dev, " startup() FAILED!\n");
+@@ -1507,9 +1198,6 @@ static int ov5693_s_config(struct v4l2_subdev *sd, int irq)
+ 		goto fail_power_on;
+ 	}
+ 
+-	if (!ov5693->vcm)
+-		ov5693->vcm = vcm_detect(client);
+-
+ 	/* config & detect sensor */
+ 	ret = ov5693_detect(client);
+ 	if (ret) {
+@@ -1617,24 +1305,17 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 	struct i2c_client *client = v4l2_get_subdevdata(&ov5693->sd);
+ 	const struct v4l2_ctrl_ops *ops = &ov5693_ctrl_ops;
+ 	struct v4l2_fwnode_device_properties props;
+-	unsigned int i;
+ 	int ret;
+ 	int hblank;
+ 	int vblank_max, vblank_min, vblank_def;
+ 	int exposure_max;
+ 
+-	ret = v4l2_ctrl_handler_init(&ov5693->ctrl_handler,
+-				     ARRAY_SIZE(ov5693_controls));
++	ret = v4l2_ctrl_handler_init(&ov5693->ctrl_handler, 8);
+ 	if (ret) {
+ 		ov5693_remove(client);
+ 		return ret;
+ 	}
+ 
+-	for (i = 0; i < ARRAY_SIZE(ov5693_controls); i++)
+-		v4l2_ctrl_new_custom(&ov5693->ctrl_handler,
+-				     &ov5693_controls[i],
+-				     NULL);
+-
+ 	/* link freq */
+ 	ov5693->ctrls.link_freq = v4l2_ctrl_new_int_menu(&ov5693->ctrl_handler,
+ 							 NULL, V4L2_CID_LINK_FREQ,
+@@ -1766,10 +1447,6 @@ static int ov5693_probe(struct i2c_client *client)
+ 
+ 	ov5693->client = client;
+ 
+-	/* check if VCM device exists */
+-	/* TODO: read from SSDB */
+-	ov5693->has_vcm = false;
+-
+ 	mutex_init(&ov5693->lock);
+ 
+ 	v4l2_i2c_subdev_init(&ov5693->sd, client, &ov5693_ops);
+-- 
+2.30.1
+
+From da0b81ee826e58b1e5e5530cee2f77c9ffa4bbba Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Sat, 13 Feb 2021 22:16:08 +0000
+Subject: [PATCH] media: i2c: Tidy up ov5693 sensor init
+
+The initialisation of a mode when the sensor is activated is a bit messy,
+so lets tidy that up a bit to bring it in line with other drivers.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 100 ++++++++++++++++---------------------
+ 1 file changed, 42 insertions(+), 58 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 2c82b6578de9..313bc9177328 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -767,6 +767,42 @@ static int ov5693_sw_standby(struct ov5693_device *ov5693, bool standby)
+ 			       standby ? OV5693_STOP_STREAMING : OV5693_START_STREAMING);
+ }
+ 
++static int ov5693_sw_reset(struct ov5693_device *ov5693)
++{
++	return ov5693_write_reg(ov5693->client, OV5693_8BIT, OV5693_SW_RESET,
++				0x01);
++}
++
++static int ov5693_sensor_init(struct ov5693_device *ov5693)
++{
++	struct i2c_client *client = ov5693->client;
++	int ret = 0;
++
++	ret = ov5693_sw_reset(ov5693);
++	if (ret) {
++		dev_err(&client->dev, "ov5693 reset err.\n");
++		return ret;
++	}
++
++	ret = ov5693_write_reg_array(client, ov5693_global_setting);
++	if (ret) {
++		dev_err(&client->dev, "ov5693 write register err.\n");
++		return ret;
++	}
++
++	ret = ov5693_write_reg_array(client, ov5693_res[ov5693->fmt_idx].regs);
++	if (ret) {
++		dev_err(&client->dev, "ov5693 write register err.\n");
++		return ret;
++	}
++
++	ret = ov5693_sw_standby(ov5693, true);
++	if (ret)
++		dev_err(&client->dev, "ov5693 stream off error\n");
++
++	return ret;
++}
++
+ static void ov5693_sensor_powerdown(struct ov5693_device *ov5693)
+ {
+ 	gpiod_set_value_cansleep(ov5693->reset, 1);
+@@ -846,6 +882,12 @@ static int __maybe_unused ov5693_sensor_resume(struct device *dev)
+ 	if (ret)
+ 		goto out_unlock;
+ 
++	ret = ov5693_sensor_init(ov5693);
++	if (ret) {
++		dev_err(&client->dev, "ov5693 sensor init failure\n");
++		goto err_power;
++	}
++
+ 	if (ov5693->streaming) {
+ 		ret = ov5693_sw_standby(ov5693, false);
+ 		if (ret)
+@@ -944,35 +986,6 @@ static int get_resolution_index(int w, int h)
+ 	return -1;
+ }
+ 
+-/* TODO: remove it. */
+-static int startup(struct v4l2_subdev *sd)
+-{
+-	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+-	struct i2c_client *client = v4l2_get_subdevdata(sd);
+-	int ret = 0;
+-
+-	ret = ov5693_write_reg(client, OV5693_8BIT,
+-			       OV5693_SW_RESET, 0x01);
+-	if (ret) {
+-		dev_err(&client->dev, "ov5693 reset err.\n");
+-		return ret;
+-	}
+-
+-	ret = ov5693_write_reg_array(client, ov5693_global_setting);
+-	if (ret) {
+-		dev_err(&client->dev, "ov5693 write register err.\n");
+-		return ret;
+-	}
+-
+-	ret = ov5693_write_reg_array(client, ov5693_res[ov5693->fmt_idx].regs);
+-	if (ret) {
+-		dev_err(&client->dev, "ov5693 write register err.\n");
+-		return ret;
+-	}
+-
+-	return ret;
+-}
+-
+ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 			  struct v4l2_subdev_pad_config *cfg,
+ 			  struct v4l2_subdev_format *format)
+@@ -982,7 +995,6 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+ 	int ret = 0;
+ 	int idx;
+-	int cnt;
+ 
+ 	if (format->pad)
+ 		return -EINVAL;
+@@ -1014,34 +1026,6 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 		goto mutex_unlock;
+ 	}
+ 
+-	for (cnt = 0; cnt < OV5693_POWER_UP_RETRY_NUM; cnt++) {
+-		ret = ov5693_sensor_powerup(ov5693);
+-		if (ret) {
+-			dev_err(&client->dev, "power up failed\n");
+-			continue;
+-		}
+-
+-		ret = startup(sd);
+-		if (ret)
+-			dev_err(&client->dev, " startup() FAILED!\n");
+-		else
+-			break;
+-	}
+-	if (cnt == OV5693_POWER_UP_RETRY_NUM) {
+-		dev_err(&client->dev, "power up failed, gave up\n");
+-		goto mutex_unlock;
+-	}
+-
+-	/*
+-	 * After sensor settings are set to HW, sometimes stream is started.
+-	 * This would cause ISP timeout because ISP is not ready to receive
+-	 * data yet. So add stop streaming here.
+-	 */
+-	ret = ov5693_write_reg(client, OV5693_8BIT, OV5693_SW_STREAM,
+-			       OV5693_STOP_STREAMING);
+-	if (ret)
+-		dev_warn(&client->dev, "ov5693 stream off err\n");
+-
+ mutex_unlock:
+ 	mutex_unlock(&ov5693->lock);
+ 	return ret;
+-- 
+2.30.1
+
+From 58c8f883b0c227f30a7317e2206e8ab6939dd7cd Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Fri, 12 Feb 2021 16:14:04 +0000
+Subject: [PATCH] media: i2c: cleanup macros in ov5693.h
+
+Lots of orphaned or duplicated macros in this header file. Clean
+those up a bit so it's less ugly.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.h | 89 +-------------------------------------
+ 1 file changed, 2 insertions(+), 87 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.h b/drivers/media/i2c/ov5693.h
+index b78d3b474a43..6502777eb5f3 100644
+--- a/drivers/media/i2c/ov5693.h
++++ b/drivers/media/i2c/ov5693.h
+@@ -37,68 +37,23 @@
+  */
+ #define ENABLE_NON_PREVIEW	1
+ 
+-#define OV5693_POWER_UP_RETRY_NUM 5
+-
+ /* Defines for register writes and register array processing */
+-#define I2C_MSG_LENGTH		0x2
+-#define I2C_RETRY_COUNT		5
+-
+-#define OV5693_FOCAL_LENGTH_NUM	334	/*3.34mm*/
+-#define OV5693_FOCAL_LENGTH_DEM	100
+-#define OV5693_F_NUMBER_DEFAULT_NUM	24
+-#define OV5693_F_NUMBER_DEM	10
++#define I2C_MSG_LENGTH         0x2
+ 
+ #define MAX_FMTS		1
+ 
+-/* sensor_mode_data read_mode adaptation */
+-#define OV5693_READ_MODE_BINNING_ON	0x0400
+-#define OV5693_READ_MODE_BINNING_OFF	0x00
+-#define OV5693_INTEGRATION_TIME_MARGIN	8
+-
+-#define OV5693_MAX_EXPOSURE_VALUE	0xFFF1
+-#define OV5693_MAX_GAIN_VALUE		0xFF
+-
+-/*
+- * focal length bits definition:
+- * bits 31-16: numerator, bits 15-0: denominator
+- */
+-#define OV5693_FOCAL_LENGTH_DEFAULT 0x1B70064
+-
+-/*
+- * current f-number bits definition:
+- * bits 31-16: numerator, bits 15-0: denominator
+- */
+-#define OV5693_F_NUMBER_DEFAULT 0x18000a
+-
+-/*
+- * f-number range bits definition:
+- * bits 31-24: max f-number numerator
+- * bits 23-16: max f-number denominator
+- * bits 15-8: min f-number numerator
+- * bits 7-0: min f-number denominator
+- */
+-#define OV5693_F_NUMBER_RANGE 0x180a180a
+ #define OV5693_ID	0x5690
+ 
+-#define OV5693_FINE_INTG_TIME_MIN 0
+-#define OV5693_FINE_INTG_TIME_MAX_MARGIN 0
+-#define OV5693_COARSE_INTG_TIME_MIN 1
+-#define OV5693_COARSE_INTG_TIME_MAX_MARGIN 6
+-
+-#define OV5693_BIN_FACTOR_MAX 4
+ /*
+  * OV5693 System control registers
+  */
+-#define OV5693_SW_SLEEP				0x0100
+ #define OV5693_SW_RESET				0x0103
+ #define OV5693_SW_STREAM			0x0100
+ 
+ #define OV5693_SC_CMMN_CHIP_ID_H		0x300A
+ #define OV5693_SC_CMMN_CHIP_ID_L		0x300B
+-#define OV5693_SC_CMMN_SCCB_ID			0x300C
+ #define OV5693_SC_CMMN_SUB_ID			0x302A /* process, version*/
+-/*Bit[7:4] Group control, Bit[3:0] Group ID*/
+-#define OV5693_GROUP_ACCESS			0x3208
++
+ /*
+ *Bit[3:0] Bit[19:16] of exposure,
+ *remaining 16 bits lies in Reg0x3501&Reg0x3502
+@@ -110,18 +65,6 @@
+ #define OV5693_AGC_H				0x350A
+ #define OV5693_AGC_L				0x350B /*Bit[7:0] of gain*/
+ 
+-#define OV5693_HORIZONTAL_START_H		0x3800 /*Bit[11:8]*/
+-#define OV5693_HORIZONTAL_START_L		0x3801 /*Bit[7:0]*/
+-#define OV5693_VERTICAL_START_H			0x3802 /*Bit[11:8]*/
+-#define OV5693_VERTICAL_START_L			0x3803 /*Bit[7:0]*/
+-#define OV5693_HORIZONTAL_END_H			0x3804 /*Bit[11:8]*/
+-#define OV5693_HORIZONTAL_END_L			0x3805 /*Bit[7:0]*/
+-#define OV5693_VERTICAL_END_H			0x3806 /*Bit[11:8]*/
+-#define OV5693_VERTICAL_END_L			0x3807 /*Bit[7:0]*/
+-#define OV5693_HORIZONTAL_OUTPUT_SIZE_H		0x3808 /*Bit[3:0]*/
+-#define OV5693_HORIZONTAL_OUTPUT_SIZE_L		0x3809 /*Bit[7:0]*/
+-#define OV5693_VERTICAL_OUTPUT_SIZE_H		0x380a /*Bit[3:0]*/
+-#define OV5693_VERTICAL_OUTPUT_SIZE_L		0x380b /*Bit[7:0]*/
+ /*High 8-bit, and low 8-bit HTS address is 0x380d*/
+ #define OV5693_TIMING_HTS_H			0x380C
+ /*High 8-bit, and low 8-bit HTS address is 0x380d*/
+@@ -141,34 +84,6 @@
+ #define OV5693_START_STREAMING			0x01
+ #define OV5693_STOP_STREAMING			0x00
+ 
+-#define VCM_ADDR           0x0c
+-#define VCM_CODE_MSB       0x04
+-
+-#define OV5693_INVALID_CONFIG	0xffffffff
+-
+-#define OV5693_VCM_SLEW_STEP			0x30F0
+-#define OV5693_VCM_SLEW_STEP_MAX		0x7
+-#define OV5693_VCM_SLEW_STEP_MASK		0x7
+-#define OV5693_VCM_CODE				0x30F2
+-#define OV5693_VCM_SLEW_TIME			0x30F4
+-#define OV5693_VCM_SLEW_TIME_MAX		0xffff
+-#define OV5693_VCM_ENABLE			0x8000
+-
+-#define OV5693_VCM_MAX_FOCUS_NEG       -1023
+-#define OV5693_VCM_MAX_FOCUS_POS       1023
+-
+-#define DLC_ENABLE 1
+-#define DLC_DISABLE 0
+-#define VCM_PROTECTION_OFF     0xeca3
+-#define VCM_PROTECTION_ON      0xdc51
+-#define VCM_DEFAULT_S 0x0
+-#define vcm_step_s(a) (u8)(a & 0xf)
+-#define vcm_step_mclk(a) (u8)((a >> 4) & 0x3)
+-#define vcm_dlc_mclk(dlc, mclk) (u16)((dlc << 3) | mclk | 0xa104)
+-#define vcm_tsrc(tsrc) (u16)(tsrc << 3 | 0xf200)
+-#define vcm_val(data, s) (u16)(data << 4 | s)
+-#define DIRECT_VCM vcm_dlc_mclk(0, 0)
+-
+ /* Defines for OTP Data Registers */
+ #define OV5693_FRAME_OFF_NUM		0x4202
+ #define OV5693_OTP_BYTE_MAX		32	//change to 32 as needed by otpdata
+-- 
+2.30.1
+
+From 044cf8819322eeaa99c8e52499b6764357fd21c6 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Fri, 12 Feb 2021 16:19:09 +0000
+Subject: [PATCH] media: i2c: use devm_kzalloc() to initialise ov5693
+
+There's a memory leak in probe because we're not using devres; swtich
+so that we are.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 313bc9177328..d092ed698eb3 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -1425,7 +1425,7 @@ static int ov5693_probe(struct i2c_client *client)
+ 
+ 	dev_info(&client->dev, "%s() called", __func__);
+ 
+-	ov5693 = kzalloc(sizeof(*ov5693), GFP_KERNEL);
++	ov5693 = devm_kzalloc(&client->dev, sizeof(*ov5693), GFP_KERNEL);
+ 	if (!ov5693)
+ 		return -ENOMEM;
+ 
+-- 
+2.30.1
+
+From 0477079d23bb8559d318d0803f0e7d06d9e45be6 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Fri, 12 Feb 2021 16:26:21 +0000
+Subject: [PATCH] media: i2c: Check for supported clk rate in probe
+
+The ov5693 driver is configured to support a 19.2MHz external clock only.
+Check that we do indeed have that value and if not, exit with -EINVAL.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 8 ++++++++
+ drivers/media/i2c/ov5693.h | 2 ++
+ 2 files changed, 10 insertions(+)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index d092ed698eb3..8082d37841da 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -1421,6 +1421,7 @@ static int ov5693_get_regulators(struct ov5693_device *ov5693)
+ static int ov5693_probe(struct i2c_client *client)
+ {
+ 	struct ov5693_device *ov5693;
++	u32 clk_rate;
+ 	int ret = 0;
+ 
+ 	dev_info(&client->dev, "%s() called", __func__);
+@@ -1441,6 +1442,13 @@ static int ov5693_probe(struct i2c_client *client)
+ 		return -EINVAL;
+ 	}
+ 
++	clk_rate = clk_get_rate(ov5693->clk);
++	if (clk_rate != OV5693_XVCLK_FREQ) {
++		dev_err(&client->dev, "Unsupported clk freq %u, expected %u\n",
++			clk_rate, OV5693_XVCLK_FREQ);
++		return -EINVAL;
++	}
++
+ 	ret = ov5693_configure_gpios(ov5693);
+         if (ret)
+                 goto out_free;
+diff --git a/drivers/media/i2c/ov5693.h b/drivers/media/i2c/ov5693.h
+index 6502777eb5f3..0dfbbe9a0ff2 100644
+--- a/drivers/media/i2c/ov5693.h
++++ b/drivers/media/i2c/ov5693.h
+@@ -100,6 +100,8 @@
+ #define OV5693_OTP_READ_ONETIME		16
+ #define OV5693_OTP_MODE_READ		1
+ 
++#define OV5693_XVCLK_FREQ		19200000
++
+ /* link freq and pixel rate required for IPU3 */
+ #define OV5693_LINK_FREQ_400MHZ		400000000
+ /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample
+-- 
+2.30.1
+
+From f8dec837099fd628522f29a33e4a0688be938b27 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Sat, 13 Feb 2021 23:17:50 +0000
+Subject: [PATCH] media: i2c: Use devres to fetch gpios
+
+Use devres; it'll simplify error handling through this function
+and probe.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 22 +++++-----------------
+ 1 file changed, 5 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 8082d37841da..c580159079d2 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -1270,8 +1270,6 @@ static int ov5693_remove(struct i2c_client *client)
+ 
+ 	dev_info(&client->dev, "%s...\n", __func__);
+ 
+-	gpiod_put(ov5693->reset);
+-	gpiod_put(ov5693->indicator_led);
+ 	while (i--)
+ 		regulator_put(ov5693->supplies[i].consumer);
+ 
+@@ -1372,38 +1370,28 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 
+ static int ov5693_configure_gpios(struct ov5693_device *ov5693)
+ {
+-	int ret;
+-
+-	ov5693->reset = gpiod_get_optional(&ov5693->client->dev, "reset",
++	ov5693->reset = devm_gpiod_get_optional(&ov5693->client->dev, "reset",
+                                         GPIOD_OUT_HIGH);
+         if (IS_ERR(ov5693->reset)) {
+                 dev_err(&ov5693->client->dev, "Couldn't find reset GPIO\n");
+                 return PTR_ERR(ov5693->reset);
+         }
+ 
+-	ov5693->powerdown = gpiod_get_optional(&ov5693->client->dev, "powerdown",
++	ov5693->powerdown = devm_gpiod_get_optional(&ov5693->client->dev, "powerdown",
+                                         GPIOD_OUT_HIGH);
+         if (IS_ERR(ov5693->powerdown)) {
+                 dev_err(&ov5693->client->dev, "Couldn't find powerdown GPIO\n");
+-                ret = PTR_ERR(ov5693->powerdown);
+-		goto err_put_reset;
++                return PTR_ERR(ov5693->powerdown);
+         }
+ 
+-        ov5693->indicator_led = gpiod_get_optional(&ov5693->client->dev, "indicator-led",
++        ov5693->indicator_led = devm_gpiod_get_optional(&ov5693->client->dev, "indicator-led",
+                                         GPIOD_OUT_HIGH);
+         if (IS_ERR(ov5693->indicator_led)) {
+                 dev_err(&ov5693->client->dev, "Couldn't find indicator-led GPIO\n");
+-                ret = PTR_ERR(ov5693->indicator_led);
+-		goto err_put_powerdown;
++                return PTR_ERR(ov5693->indicator_led);
+         }
+ 
+         return 0;
+-err_put_reset:
+-	gpiod_put(ov5693->reset);
+-err_put_powerdown:
+-	gpiod_put(ov5693->powerdown);
+-
+-	return ret;
+ }
+ 
+ static int ov5693_get_regulators(struct ov5693_device *ov5693)
+-- 
+2.30.1
+
+From 0385044877ff117385d9042666cbffaf68dae788 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Sat, 13 Feb 2021 23:20:47 +0000
+Subject: [PATCH] media: i2c: Use devres to fetch regulators
+
+As before, use devres to simplify error handling and driver removal
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index c580159079d2..9f61b470f8ba 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -1266,13 +1266,9 @@ static int ov5693_remove(struct i2c_client *client)
+ {
+ 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ 	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+-	unsigned int i = OV5693_NUM_SUPPLIES;
+ 
+ 	dev_info(&client->dev, "%s...\n", __func__);
+ 
+-	while (i--)
+-		regulator_put(ov5693->supplies[i].consumer);
+-
+ 	v4l2_async_unregister_subdev(sd);
+ 
+ 	media_entity_cleanup(&ov5693->sd.entity);
+@@ -1401,7 +1397,7 @@ static int ov5693_get_regulators(struct ov5693_device *ov5693)
+ 	for (i = 0; i < OV5693_NUM_SUPPLIES; i++)
+ 		ov5693->supplies[i].supply = ov5693_supply_names[i];
+ 
+-	return regulator_bulk_get(&ov5693->client->dev,
++	return devm_regulator_bulk_get(&ov5693->client->dev,
+ 				       OV5693_NUM_SUPPLIES,
+ 				       ov5693->supplies);
+ }
+-- 
+2.30.1
+
+From f5a33a3fec053a1fef75409be2b5cabf6aa0896a Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Sun, 14 Feb 2021 12:39:14 +0000
+Subject: [PATCH] media: i2c: remove debug print
+
+The exposure configure function has a debug print. It's working fine,
+so bin it.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 37 -------------------------------------
+ 1 file changed, 37 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 9f61b470f8ba..622a7ddf4063 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -526,41 +526,6 @@ static int ov5693_q_exposure(struct v4l2_subdev *sd, s32 *value)
+ }
+ 
+ /* Exposure */
+-
+-static int ov5693_get_exposure(struct ov5693_device *ov5693)
+-{
+-	u32 exposure = 0;
+-	u16 tmp;
+-	int ret = 0;
+-
+-	/* get exposure */
+-	ret = ov5693_read_reg(ov5693->client, OV5693_8BIT,
+-			      OV5693_EXPOSURE_L,
+-			      &tmp);
+-	if (ret)
+-		return ret;
+-
+-	exposure |= ((tmp >> 4) & 0b1111);
+-
+-	ret = ov5693_read_reg(ov5693->client, OV5693_8BIT,
+-			      OV5693_EXPOSURE_M,
+-			      &tmp);
+-	if (ret)
+-		return ret;
+-
+-	exposure |= (tmp << 4);
+-	ret = ov5693_read_reg(ov5693->client, OV5693_8BIT,
+-			      OV5693_EXPOSURE_H,
+-			      &tmp);
+-	if (ret)
+-		return ret;
+-
+-	exposure |= (tmp << 12);
+-
+-	printk("exposure set to: %u\n", exposure);
+-	return ret;
+-}
+-
+ static int ov5693_exposure_configure(struct ov5693_device *ov5693, u32 exposure)
+ {
+ 	int ret;
+@@ -571,7 +536,6 @@ static int ov5693_exposure_configure(struct ov5693_device *ov5693, u32 exposure)
+ 	 */
+ 	exposure = exposure * 16;
+ 
+-	ov5693_get_exposure(ov5693);
+ 	ret = ov5693_write_reg(ov5693->client, OV5693_8BIT,
+ 			OV5693_EXPOSURE_CTRL_HH_REG, OV5693_EXPOSURE_CTRL_HH(exposure));
+ 	if (ret)
+@@ -586,7 +550,6 @@ static int ov5693_exposure_configure(struct ov5693_device *ov5693, u32 exposure)
+ 			OV5693_EXPOSURE_CTRL_L_REG, OV5693_EXPOSURE_CTRL_L(exposure));
+ 	if (ret)
+ 		return ret;
+-	ov5693_get_exposure(ov5693);
+ 
+ 	return 0;
+ }
+-- 
+2.30.1
+
+From 7ea821a1907225382ec148ee1d0bbbf8369ee113 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Sun, 14 Feb 2021 14:32:50 +0000
+Subject: [PATCH] media: i2c: Remove unused resolutions from ov5693
+
+The list of resolutions in here is really unmaintanably long. For now just
+bin all of the ones that are not part of ov5693_res_video, which is the
+only array of resolutions in use anyway.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.h | 357 +------------------------------------
+ 1 file changed, 1 insertion(+), 356 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.h b/drivers/media/i2c/ov5693.h
+index 0dfbbe9a0ff2..29e6735112da 100644
+--- a/drivers/media/i2c/ov5693.h
++++ b/drivers/media/i2c/ov5693.h
+@@ -474,34 +474,7 @@ static struct ov5693_reg const ov5693_global_setting[] = {
+ };
+ 
+ #if ENABLE_NON_PREVIEW
+-/*
+- * 654x496 30fps 17ms VBlanking 2lane 10Bit (Scaling)
+- */
+-static struct ov5693_reg const ov5693_654x496[] = {
+-	{OV5693_8BIT, 0x3501, 0x3d},
+-	{OV5693_8BIT, 0x3502, 0x00},
+-	{OV5693_8BIT, 0x3708, 0xe6},
+-	{OV5693_8BIT, 0x3709, 0xc7},
+-	{OV5693_8BIT, 0x3803, 0x00},
+-	{OV5693_8BIT, 0x3806, 0x07},
+-	{OV5693_8BIT, 0x3807, 0xa3},
+-	{OV5693_8BIT, 0x3808, 0x02},
+-	{OV5693_8BIT, 0x3809, 0x90},
+-	{OV5693_8BIT, 0x380a, 0x01},
+-	{OV5693_8BIT, 0x380b, 0xf0},
+-	{OV5693_8BIT, 0x380c, 0x0a},
+-	{OV5693_8BIT, 0x380d, 0x80},
+-	{OV5693_8BIT, 0x380e, 0x07},
+-	{OV5693_8BIT, 0x380f, 0xc0},
+-	{OV5693_8BIT, 0x3811, 0x08},
+-	{OV5693_8BIT, 0x3813, 0x02},
+-	{OV5693_8BIT, 0x3814, 0x31},
+-	{OV5693_8BIT, 0x3815, 0x31},
+-	{OV5693_8BIT, 0x3820, 0x04},
+-	{OV5693_8BIT, 0x3821, 0x1f},
+-	{OV5693_8BIT, 0x5002, 0x80},
+-	{OV5693_TOK_TERM, 0, 0}
+-};
++
+ 
+ /*
+  * 1296x976 30fps 17ms VBlanking 2lane 10Bit (Scaling)
+@@ -660,62 +633,10 @@ static struct ov5693_reg const ov5693_736x496[] = {
+ };
+ #endif
+ 
+-/*
+-static struct ov5693_reg const ov5693_736x496[] = {
+-	{OV5693_8BIT, 0x3501, 0x7b},
+-	{OV5693_8BIT, 0x3502, 0x00},
+-	{OV5693_8BIT, 0x3708, 0xe6},
+-	{OV5693_8BIT, 0x3709, 0xc3},
+-	{OV5693_8BIT, 0x3803, 0x00},
+-	{OV5693_8BIT, 0x3806, 0x07},
+-	{OV5693_8BIT, 0x3807, 0xa3},
+-	{OV5693_8BIT, 0x3808, 0x02},
+-	{OV5693_8BIT, 0x3809, 0xe0},
+-	{OV5693_8BIT, 0x380a, 0x01},
+-	{OV5693_8BIT, 0x380b, 0xf0},
+-	{OV5693_8BIT, 0x380c, 0x0d},
+-	{OV5693_8BIT, 0x380d, 0xb0},
+-	{OV5693_8BIT, 0x380e, 0x05},
+-	{OV5693_8BIT, 0x380f, 0xf2},
+-	{OV5693_8BIT, 0x3811, 0x08},
+-	{OV5693_8BIT, 0x3813, 0x02},
+-	{OV5693_8BIT, 0x3814, 0x31},
+-	{OV5693_8BIT, 0x3815, 0x31},
+-	{OV5693_8BIT, 0x3820, 0x01},
+-	{OV5693_8BIT, 0x3821, 0x1f},
+-	{OV5693_8BIT, 0x5002, 0x00},
+-	{OV5693_TOK_TERM, 0, 0}
+-};
+-*/
+ /*
+  * 976x556 30fps 8.8ms VBlanking 2lane 10Bit (Scaling)
+  */
+ #if ENABLE_NON_PREVIEW
+-static struct ov5693_reg const ov5693_976x556[] = {
+-	{OV5693_8BIT, 0x3501, 0x7b},
+-	{OV5693_8BIT, 0x3502, 0x00},
+-	{OV5693_8BIT, 0x3708, 0xe2},
+-	{OV5693_8BIT, 0x3709, 0xc3},
+-	{OV5693_8BIT, 0x3803, 0xf0},
+-	{OV5693_8BIT, 0x3806, 0x06},
+-	{OV5693_8BIT, 0x3807, 0xa7},
+-	{OV5693_8BIT, 0x3808, 0x03},
+-	{OV5693_8BIT, 0x3809, 0xd0},
+-	{OV5693_8BIT, 0x380a, 0x02},
+-	{OV5693_8BIT, 0x380b, 0x2C},
+-	{OV5693_8BIT, 0x380c, 0x0a},
+-	{OV5693_8BIT, 0x380d, 0x80},
+-	{OV5693_8BIT, 0x380e, 0x07},
+-	{OV5693_8BIT, 0x380f, 0xc0},
+-	{OV5693_8BIT, 0x3811, 0x10},
+-	{OV5693_8BIT, 0x3813, 0x02},
+-	{OV5693_8BIT, 0x3814, 0x11},
+-	{OV5693_8BIT, 0x3815, 0x11},
+-	{OV5693_8BIT, 0x3820, 0x00},
+-	{OV5693_8BIT, 0x3821, 0x1e},
+-	{OV5693_8BIT, 0x5002, 0x80},
+-	{OV5693_TOK_TERM, 0, 0}
+-};
+ 
+ /*DS from 2624x1492*/
+ static struct ov5693_reg const ov5693_1296x736[] = {
+@@ -782,40 +703,6 @@ static struct ov5693_reg const ov5693_1636p_30fps[] = {
+ };
+ #endif
+ 
+-static struct ov5693_reg const ov5693_1616x1216_30fps[] = {
+-	{OV5693_8BIT, 0x3501, 0x7b},
+-	{OV5693_8BIT, 0x3502, 0x80},
+-	{OV5693_8BIT, 0x3708, 0xe2},
+-	{OV5693_8BIT, 0x3709, 0xc3},
+-	{OV5693_8BIT, 0x3800, 0x00},	/*{3800,3801} Array X start*/
+-	{OV5693_8BIT, 0x3801, 0x08},	/* 04 //{3800,3801} Array X start*/
+-	{OV5693_8BIT, 0x3802, 0x00},	/*{3802,3803} Array Y start*/
+-	{OV5693_8BIT, 0x3803, 0x04},	/* 00  //{3802,3803} Array Y start*/
+-	{OV5693_8BIT, 0x3804, 0x0a},	/*{3804,3805} Array X end*/
+-	{OV5693_8BIT, 0x3805, 0x37},	/* 3b  //{3804,3805} Array X end*/
+-	{OV5693_8BIT, 0x3806, 0x07},	/*{3806,3807} Array Y end*/
+-	{OV5693_8BIT, 0x3807, 0x9f},	/* a3  //{3806,3807} Array Y end*/
+-	{OV5693_8BIT, 0x3808, 0x06},	/*{3808,3809} Final output H size*/
+-	{OV5693_8BIT, 0x3809, 0x50},	/*{3808,3809} Final output H size*/
+-	{OV5693_8BIT, 0x380a, 0x04},	/*{380a,380b} Final output V size*/
+-	{OV5693_8BIT, 0x380b, 0xc0},	/*{380a,380b} Final output V size*/
+-	{OV5693_8BIT, 0x380c, 0x0a},	/*{380c,380d} HTS*/
+-	{OV5693_8BIT, 0x380d, 0x80},	/*{380c,380d} HTS*/
+-	{OV5693_8BIT, 0x380e, 0x07},	/*{380e,380f} VTS*/
+-	{OV5693_8BIT, 0x380f, 0xc0},	/* bc	//{380e,380f} VTS*/
+-	{OV5693_8BIT, 0x3810, 0x00},	/*{3810,3811} windowing X offset*/
+-	{OV5693_8BIT, 0x3811, 0x10},	/*{3810,3811} windowing X offset*/
+-	{OV5693_8BIT, 0x3812, 0x00},	/*{3812,3813} windowing Y offset*/
+-	{OV5693_8BIT, 0x3813, 0x06},	/*{3812,3813} windowing Y offset*/
+-	{OV5693_8BIT, 0x3814, 0x11},	/*X subsample control*/
+-	{OV5693_8BIT, 0x3815, 0x11},	/*Y subsample control*/
+-	{OV5693_8BIT, 0x3820, 0x00},	/*FLIP/Binnning control*/
+-	{OV5693_8BIT, 0x3821, 0x1e},	/*MIRROR control*/
+-	{OV5693_8BIT, 0x5002, 0x00},
+-	{OV5693_8BIT, 0x5041, 0x84},
+-	{OV5693_TOK_TERM, 0, 0}
+-};
+-
+ /*
+  * 1940x1096 30fps 8.8ms VBlanking 2lane 10bit (Scaling)
+  */
+@@ -878,37 +765,6 @@ static struct ov5693_reg const ov5693_2592x1456_30fps[] = {
+ };
+ #endif
+ 
+-static struct ov5693_reg const ov5693_2576x1456_30fps[] = {
+-	{OV5693_8BIT, 0x3501, 0x7b},
+-	{OV5693_8BIT, 0x3502, 0x00},
+-	{OV5693_8BIT, 0x3708, 0xe2},
+-	{OV5693_8BIT, 0x3709, 0xc3},
+-	{OV5693_8BIT, 0x3800, 0x00},
+-	{OV5693_8BIT, 0x3801, 0x00},
+-	{OV5693_8BIT, 0x3802, 0x00},
+-	{OV5693_8BIT, 0x3803, 0xf0},
+-	{OV5693_8BIT, 0x3804, 0x0a},
+-	{OV5693_8BIT, 0x3805, 0x3f},
+-	{OV5693_8BIT, 0x3806, 0x06},
+-	{OV5693_8BIT, 0x3807, 0xa4},
+-	{OV5693_8BIT, 0x3808, 0x0a},
+-	{OV5693_8BIT, 0x3809, 0x10},
+-	{OV5693_8BIT, 0x380a, 0x05},
+-	{OV5693_8BIT, 0x380b, 0xb0},
+-	{OV5693_8BIT, 0x380c, 0x0a},
+-	{OV5693_8BIT, 0x380d, 0x80},
+-	{OV5693_8BIT, 0x380e, 0x07},
+-	{OV5693_8BIT, 0x380f, 0xc0},
+-	{OV5693_8BIT, 0x3811, 0x18},
+-	{OV5693_8BIT, 0x3813, 0x00},
+-	{OV5693_8BIT, 0x3814, 0x11},
+-	{OV5693_8BIT, 0x3815, 0x11},
+-	{OV5693_8BIT, 0x3820, 0x00},
+-	{OV5693_8BIT, 0x3821, 0x1e},
+-	{OV5693_8BIT, 0x5002, 0x00},
+-	{OV5693_TOK_TERM, 0, 0}
+-};
+-
+ /*
+  * 2592x1944 30fps 0.6ms VBlanking 2lane 10Bit
+  */
+@@ -940,49 +796,6 @@ static struct ov5693_reg const ov5693_2592x1944_30fps[] = {
+ };
+ #endif
+ 
+-/*
+- * 11:9 Full FOV Output, expected FOV Res: 2346x1920
+- * ISP Effect Res: 1408x1152
+- * Sensor out: 1424x1168, DS From: 2380x1952
+- *
+- * WA: Left Offset: 8, Hor scal: 64
+- */
+-#if ENABLE_NON_PREVIEW
+-static struct ov5693_reg const ov5693_1424x1168_30fps[] = {
+-	{OV5693_8BIT, 0x3501, 0x3b}, /* long exposure[15:8] */
+-	{OV5693_8BIT, 0x3502, 0x80}, /* long exposure[7:0] */
+-	{OV5693_8BIT, 0x3708, 0xe2},
+-	{OV5693_8BIT, 0x3709, 0xc3},
+-	{OV5693_8BIT, 0x3800, 0x00}, /* TIMING_X_ADDR_START */
+-	{OV5693_8BIT, 0x3801, 0x50}, /* 80 */
+-	{OV5693_8BIT, 0x3802, 0x00}, /* TIMING_Y_ADDR_START */
+-	{OV5693_8BIT, 0x3803, 0x02}, /* 2 */
+-	{OV5693_8BIT, 0x3804, 0x09}, /* TIMING_X_ADDR_END */
+-	{OV5693_8BIT, 0x3805, 0xdd}, /* 2525 */
+-	{OV5693_8BIT, 0x3806, 0x07}, /* TIMING_Y_ADDR_END */
+-	{OV5693_8BIT, 0x3807, 0xa1}, /* 1953 */
+-	{OV5693_8BIT, 0x3808, 0x05}, /* TIMING_X_OUTPUT_SIZE */
+-	{OV5693_8BIT, 0x3809, 0x90}, /* 1424 */
+-	{OV5693_8BIT, 0x380a, 0x04}, /* TIMING_Y_OUTPUT_SIZE */
+-	{OV5693_8BIT, 0x380b, 0x90}, /* 1168 */
+-	{OV5693_8BIT, 0x380c, 0x0a}, /* TIMING_HTS */
+-	{OV5693_8BIT, 0x380d, 0x80},
+-	{OV5693_8BIT, 0x380e, 0x07}, /* TIMING_VTS */
+-	{OV5693_8BIT, 0x380f, 0xc0},
+-	{OV5693_8BIT, 0x3810, 0x00}, /* TIMING_ISP_X_WIN */
+-	{OV5693_8BIT, 0x3811, 0x02}, /* 2 */
+-	{OV5693_8BIT, 0x3812, 0x00}, /* TIMING_ISP_Y_WIN */
+-	{OV5693_8BIT, 0x3813, 0x00}, /* 0 */
+-	{OV5693_8BIT, 0x3814, 0x11}, /* TIME_X_INC */
+-	{OV5693_8BIT, 0x3815, 0x11}, /* TIME_Y_INC */
+-	{OV5693_8BIT, 0x3820, 0x00},
+-	{OV5693_8BIT, 0x3821, 0x1e},
+-	{OV5693_8BIT, 0x5002, 0x00},
+-	{OV5693_8BIT, 0x5041, 0x84}, /* scale is auto enabled */
+-	{OV5693_TOK_TERM, 0, 0}
+-};
+-#endif
+-
+ /*
+  * 3:2 Full FOV Output, expected FOV Res: 2560x1706
+  * ISP Effect Res: 720x480
+@@ -1022,173 +835,6 @@ static struct ov5693_reg const ov5693_736x496_30fps[] = {
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+-static struct ov5693_reg const ov5693_2576x1936_30fps[] = {
+-	{OV5693_8BIT, 0x3501, 0x7b},
+-	{OV5693_8BIT, 0x3502, 0x00},
+-	{OV5693_8BIT, 0x3708, 0xe2},
+-	{OV5693_8BIT, 0x3709, 0xc3},
+-	{OV5693_8BIT, 0x3803, 0x00},
+-	{OV5693_8BIT, 0x3806, 0x07},
+-	{OV5693_8BIT, 0x3807, 0xa3},
+-	{OV5693_8BIT, 0x3808, 0x0a},
+-	{OV5693_8BIT, 0x3809, 0x10},
+-	{OV5693_8BIT, 0x380a, 0x07},
+-	{OV5693_8BIT, 0x380b, 0x90},
+-	{OV5693_8BIT, 0x380c, 0x0a},
+-	{OV5693_8BIT, 0x380d, 0x80},
+-	{OV5693_8BIT, 0x380e, 0x07},
+-	{OV5693_8BIT, 0x380f, 0xc0},
+-	{OV5693_8BIT, 0x3811, 0x18},
+-	{OV5693_8BIT, 0x3813, 0x00},
+-	{OV5693_8BIT, 0x3814, 0x11},
+-	{OV5693_8BIT, 0x3815, 0x11},
+-	{OV5693_8BIT, 0x3820, 0x00},
+-	{OV5693_8BIT, 0x3821, 0x1e},
+-	{OV5693_8BIT, 0x5002, 0x00},
+-	{OV5693_TOK_TERM, 0, 0}
+-};
+-
+-static struct ov5693_resolution ov5693_res_preview[] = {
+-	{
+-		.desc = "ov5693_736x496_30fps",
+-		.width = 736,
+-		.height = 496,
+-		.pix_clk_freq = 160,
+-		.fps = 30,
+-		.used = 0,
+-		.pixels_per_line = 2688,
+-		.lines_per_frame = 1984,
+-		.bin_factor_x = 1,
+-		.bin_factor_y = 1,
+-		.bin_mode = 0,
+-		.regs = ov5693_736x496_30fps,
+-	},
+-	{
+-		.desc = "ov5693_1616x1216_30fps",
+-		.width = 1616,
+-		.height = 1216,
+-		.pix_clk_freq = 160,
+-		.fps = 30,
+-		.used = 0,
+-		.pixels_per_line = 2688,
+-		.lines_per_frame = 1984,
+-		.bin_factor_x = 1,
+-		.bin_factor_y = 1,
+-		.bin_mode = 0,
+-		.regs = ov5693_1616x1216_30fps,
+-	},
+-	{
+-		.desc = "ov5693_5M_30fps",
+-		.width = 2576,
+-		.height = 1456,
+-		.pix_clk_freq = 160,
+-		.fps = 30,
+-		.used = 0,
+-		.pixels_per_line = 2688,
+-		.lines_per_frame = 1984,
+-		.bin_factor_x = 1,
+-		.bin_factor_y = 1,
+-		.bin_mode = 0,
+-		.regs = ov5693_2576x1456_30fps,
+-	},
+-	{
+-		.desc = "ov5693_5M_30fps",
+-		.width = 2576,
+-		.height = 1936,
+-		.pix_clk_freq = 160,
+-		.fps = 30,
+-		.used = 0,
+-		.pixels_per_line = 2688,
+-		.lines_per_frame = 1984,
+-		.bin_factor_x = 1,
+-		.bin_factor_y = 1,
+-		.bin_mode = 0,
+-		.regs = ov5693_2576x1936_30fps,
+-	},
+-};
+-
+-#define N_RES_PREVIEW (ARRAY_SIZE(ov5693_res_preview))
+-
+-/*
+- * Disable non-preview configurations until the configuration selection is
+- * improved.
+- */
+-#if ENABLE_NON_PREVIEW
+-struct ov5693_resolution ov5693_res_still[] = {
+-	{
+-		.desc = "ov5693_736x496_30fps",
+-		.width = 736,
+-		.height = 496,
+-		.pix_clk_freq = 160,
+-		.fps = 30,
+-		.used = 0,
+-		.pixels_per_line = 2688,
+-		.lines_per_frame = 1984,
+-		.bin_factor_x = 1,
+-		.bin_factor_y = 1,
+-		.bin_mode = 0,
+-		.regs = ov5693_736x496_30fps,
+-	},
+-	{
+-		.desc = "ov5693_1424x1168_30fps",
+-		.width = 1424,
+-		.height = 1168,
+-		.pix_clk_freq = 160,
+-		.fps = 30,
+-		.used = 0,
+-		.pixels_per_line = 2688,
+-		.lines_per_frame = 1984,
+-		.bin_factor_x = 1,
+-		.bin_factor_y = 1,
+-		.bin_mode = 0,
+-		.regs = ov5693_1424x1168_30fps,
+-	},
+-	{
+-		.desc = "ov5693_1616x1216_30fps",
+-		.width = 1616,
+-		.height = 1216,
+-		.pix_clk_freq = 160,
+-		.fps = 30,
+-		.used = 0,
+-		.pixels_per_line = 2688,
+-		.lines_per_frame = 1984,
+-		.bin_factor_x = 1,
+-		.bin_factor_y = 1,
+-		.bin_mode = 0,
+-		.regs = ov5693_1616x1216_30fps,
+-	},
+-	{
+-		.desc = "ov5693_5M_30fps",
+-		.width = 2592,
+-		.height = 1456,
+-		.pix_clk_freq = 160,
+-		.fps = 30,
+-		.used = 0,
+-		.pixels_per_line = 2688,
+-		.lines_per_frame = 1984,
+-		.bin_factor_x = 1,
+-		.bin_factor_y = 1,
+-		.bin_mode = 0,
+-		.regs = ov5693_2592x1456_30fps,
+-	},
+-	{
+-		.desc = "ov5693_5M_30fps",
+-		.width = 2592,
+-		.height = 1944,
+-		.pix_clk_freq = 160,
+-		.fps = 30,
+-		.used = 0,
+-		.pixels_per_line = 2688,
+-		.lines_per_frame = 1984,
+-		.bin_factor_x = 1,
+-		.bin_factor_y = 1,
+-		.bin_mode = 0,
+-		.regs = ov5693_2592x1944_30fps,
+-	},
+-};
+-
+-#define N_RES_STILL (ARRAY_SIZE(ov5693_res_still))
+-
+ struct ov5693_resolution ov5693_res_video[] = {
+ 	{
+ 		.desc = "ov5693_736x496_30fps",
+@@ -1343,4 +989,3 @@ struct ov5693_resolution ov5693_res_video[] = {
+ 
+ static struct ov5693_resolution *ov5693_res = ov5693_res_video;
+ static unsigned long N_RES = N_RES_VIDEO;
+-#endif
+-- 
+2.30.1
+
+From 2d4ebcefd309fd583a75fe1d61242ede4d341237 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Sun, 14 Feb 2021 14:45:58 +0000
+Subject: [PATCH] media: i2c: update set_fmt() for ov5693
+
+The set_fmt() function is a bit messy still, using home grown solutions to
+find the closest supported resolution instead of the v4l2 helpers. It also
+fails to update control ranges to account for the new mode (though this is
+moot currently as they're all the same, but the probably shouldn't be).
+
+Fix it up a little.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 148 ++++++++++---------------------------
+ drivers/media/i2c/ov5693.h |   5 +-
+ 2 files changed, 40 insertions(+), 113 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 622a7ddf4063..09c84006d5c9 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -753,7 +753,7 @@ static int ov5693_sensor_init(struct ov5693_device *ov5693)
+ 		return ret;
+ 	}
+ 
+-	ret = ov5693_write_reg_array(client, ov5693_res[ov5693->fmt_idx].regs);
++	ret = ov5693_write_reg_array(client, ov5693->mode->regs);
+ 	if (ret) {
+ 		dev_err(&client->dev, "ov5693 write register err.\n");
+ 		return ret;
+@@ -866,128 +866,56 @@ static int __maybe_unused ov5693_sensor_resume(struct device *dev)
+ 	return ret;
+ }
+ 
+-/*
+- * distance - calculate the distance
+- * @res: resolution
+- * @w: width
+- * @h: height
+- *
+- * Get the gap between res_w/res_h and w/h.
+- * distance = (res_w/res_h - w/h) / (w/h) * 8192
+- * res->width/height smaller than w/h wouldn't be considered.
+- * The gap of ratio larger than 1/8 wouldn't be considered.
+- * Returns the value of gap or -1 if fail.
+- */
+-#define LARGEST_ALLOWED_RATIO_MISMATCH 1024
+-static int distance(struct ov5693_resolution *res, u32 w, u32 h)
+-{
+-	int ratio;
+-	int distance;
+-
+-	if (w == 0 || h == 0 ||
+-	    res->width < w || res->height < h)
+-		return -1;
+-
+-	ratio = res->width << 13;
+-	ratio /= w;
+-	ratio *= h;
+-	ratio /= res->height;
+-
+-	distance = abs(ratio - 8192);
+-
+-	if (distance > LARGEST_ALLOWED_RATIO_MISMATCH)
+-		return -1;
+-
+-	return distance;
+-}
+-
+-/* Return the nearest higher resolution index
+- * Firstly try to find the approximate aspect ratio resolution
+- * If we find multiple same AR resolutions, choose the
+- * minimal size.
+- */
+-static int nearest_resolution_index(int w, int h)
+-{
+-	int i;
+-	int idx = -1;
+-	int dist;
+-	int min_dist = INT_MAX;
+-	int min_res_w = INT_MAX;
+-	struct ov5693_resolution *tmp_res = NULL;
+-
+-	for (i = 0; i < N_RES; i++) {
+-		tmp_res = &ov5693_res[i];
+-		dist = distance(tmp_res, w, h);
+-		if (dist == -1)
+-			continue;
+-		if (dist < min_dist) {
+-			min_dist = dist;
+-			idx = i;
+-			min_res_w = ov5693_res[i].width;
+-			continue;
+-		}
+-		if (dist == min_dist && ov5693_res[i].width < min_res_w)
+-			idx = i;
+-	}
+-
+-	return idx;
+-}
+-
+-static int get_resolution_index(int w, int h)
+-{
+-	int i;
+-
+-	for (i = 0; i < N_RES; i++) {
+-		if (w != ov5693_res[i].width)
+-			continue;
+-		if (h != ov5693_res[i].height)
+-			continue;
+-
+-		return i;
+-	}
+-
+-	return -1;
+-}
+-
+ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 			  struct v4l2_subdev_pad_config *cfg,
+ 			  struct v4l2_subdev_format *format)
+ {
+-	struct v4l2_mbus_framefmt *fmt = &format->format;
+ 	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+-	struct i2c_client *client = v4l2_get_subdevdata(sd);
++	const struct ov5693_resolution *mode;
++	int exposure_max;
+ 	int ret = 0;
+-	int idx;
++	int hblank;
+ 
+ 	if (format->pad)
+ 		return -EINVAL;
+-	if (!fmt)
+-		return -EINVAL;
+ 
+ 	mutex_lock(&ov5693->lock);
+-	idx = nearest_resolution_index(fmt->width, fmt->height);
+-	if (idx == -1) {
+-		/* return the largest resolution */
+-		fmt->width = ov5693_res[N_RES - 1].width;
+-		fmt->height = ov5693_res[N_RES - 1].height;
+-	} else {
+-		fmt->width = ov5693_res[idx].width;
+-		fmt->height = ov5693_res[idx].height;
+-	}
+ 
+-	fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
++	mode = v4l2_find_nearest_size(ov5693_res_video, ARRAY_SIZE(ov5693_res_video),
++				      width, height, format->format.width,
++				      format->format.height);
++
++	if (!mode)
++		return -EINVAL;
++
++	format->format.width = mode->width;
++	format->format.height = mode->height;
++	format->format.code = MEDIA_BUS_FMT_SBGGR10_1X10;
++
+ 	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+-		cfg->try_fmt = *fmt;
+-		ret = 0;
++		*v4l2_subdev_get_try_format(sd, cfg, format->pad) = format->format;
+ 		goto mutex_unlock;
+ 	}
+ 
+-	ov5693->fmt_idx = get_resolution_index(fmt->width, fmt->height);
+-	if (ov5693->fmt_idx == -1) {
+-		dev_err(&client->dev, "get resolution fail\n");
+-		ret = -EINVAL;
+-		goto mutex_unlock;
+-	}
++	ov5693->mode = mode;
++
++	/* Update limits and set FPS to default */
++	__v4l2_ctrl_modify_range(ov5693->ctrls.vblank,
++				 mode->lines_per_frame - mode->height,
++				 OV5693_TIMING_MAX_VTS - mode->height,
++				 1, mode->lines_per_frame - mode->height);
++	__v4l2_ctrl_s_ctrl(ov5693->ctrls.vblank,
++			   mode->lines_per_frame - mode->height);
++
++	hblank = mode->pixels_per_line - mode->width;
++	__v4l2_ctrl_modify_range(ov5693->ctrls.hblank, hblank, hblank, 1, hblank);
++
++	exposure_max = mode->lines_per_frame - 8;
++	__v4l2_ctrl_modify_range(ov5693->ctrls.exposure,
++				 ov5693->ctrls.exposure->minimum, exposure_max,
++				 ov5693->ctrls.exposure->step,
++				 ov5693->ctrls.exposure->val < exposure_max ?
++				 ov5693->ctrls.exposure->val : exposure_max);
+ 
+ mutex_unlock:
+ 	mutex_unlock(&ov5693->lock);
+@@ -1056,8 +984,8 @@ static int ov5693_get_fmt(struct v4l2_subdev *sd,
+ 	if (!fmt)
+ 		return -EINVAL;
+ 
+-	fmt->width = ov5693_res[ov5693->fmt_idx].width;
+-	fmt->height = ov5693_res[ov5693->fmt_idx].height;
++	fmt->width = ov5693->mode->width;
++	fmt->height = ov5693->mode->height;
+ 	fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
+ 
+ 	return 0;
+@@ -1174,7 +1102,7 @@ static int ov5693_g_frame_interval(struct v4l2_subdev *sd,
+ 	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 
+ 	interval->interval.numerator = 1;
+-	interval->interval.denominator = ov5693_res[ov5693->fmt_idx].fps;
++	interval->interval.denominator = ov5693->mode->fps;
+ 
+ 	return 0;
+ }
+diff --git a/drivers/media/i2c/ov5693.h b/drivers/media/i2c/ov5693.h
+index 29e6735112da..0377853f8b2b 100644
+--- a/drivers/media/i2c/ov5693.h
++++ b/drivers/media/i2c/ov5693.h
+@@ -127,8 +127,8 @@ struct ov5693_resolution {
+ 	u8 *desc;
+ 	const struct ov5693_reg *regs;
+ 	int res;
+-	int width;
+-	int height;
++	u32 width;
++	u32 height;
+ 	int fps;
+ 	int pix_clk_freq;
+ 	u16 pixels_per_line;
+@@ -178,7 +178,6 @@ struct ov5693_device {
+ 	struct camera_sensor_platform_data *platform_data;
+ 	ktime_t timestamp_t_focus_abs;
+ 	int vt_pix_clk_freq_mhz;
+-	int fmt_idx;
+ 	int run_mode;
+ 	int otp_size;
+ 	u8 *otp_data;
+-- 
+2.30.1
+