diff mbox series

media: i2c: st-vgxy61: Convert to CCI register access helpers

Message ID 20240112095228.2842812-1-julien.massot@collabora.com (mailing list archive)
State New
Headers show
Series media: i2c: st-vgxy61: Convert to CCI register access helpers | expand

Commit Message

Julien Massot Jan. 12, 2024, 9:52 a.m. UTC
Use the new common CCI register access helpers to replace the private
register access helpers in the st-vgxy61 driver. This simplifies the
driver by reducing the amount of code.

st-vgxy61 devices use little endianness arrangement, therefore
the driver uses the CCI_REGx_LE registers definition.

Signed-off-by: Julien Massot <julien.massot@collabora.com>
---
 drivers/media/i2c/Kconfig     |   1 +
 drivers/media/i2c/st-vgxy61.c | 390 +++++++++++++---------------------
 2 files changed, 154 insertions(+), 237 deletions(-)

Comments

Benjamin Mugnier Feb. 9, 2024, 8:55 a.m. UTC | #1
Hi Julien

Thank you for your patch, and sorry for the late reply.
I tested it, and it works great.

On 1/12/24 10:52, Julien Massot wrote:
[...]
> @@ -1623,37 +1536,33 @@ static int vgxy61_configure(struct vgxy61_dev *sensor)
>  static int vgxy61_patch(struct vgxy61_dev *sensor)
>  {
>  	struct i2c_client *client = sensor->i2c_client;
> -	int patch, ret;
> +	u64 patch;
> +	int ret;
>  
>  	ret = vgxy61_write_array(sensor, VGXY61_REG_FWPATCH_START_ADDR,
>  				 sizeof(patch_array), patch_array);
> -	if (ret)
> -		return ret;
> -
> -	ret = vgxy61_write_reg(sensor, VGXY61_REG_STBY, 0x10, NULL);
> +	cci_write(sensor->regmap, VGXY61_REG_STBY, 0x10, &ret);
>  	if (ret)
>  		return ret;
>  
>  	ret = vgxy61_poll_reg(sensor, VGXY61_REG_STBY, 0, VGXY61_TIMEOUT_MS);
> -	if (ret)
> +	cci_read(sensor->regmap, VGXY61_REG_FWPATCH_REVISION, &patch, &ret);
> +	if (ret < 0)
>  		return ret;
>  
> -	patch = vgxy61_read_reg(sensor, VGXY61_REG_FWPATCH_REVISION);
> -	if (patch < 0)
> -		return patch;
> -
>  	if (patch != (VGXY61_FWPATCH_REVISION_MAJOR << 12) +
>  		     (VGXY61_FWPATCH_REVISION_MINOR << 8) +
>  		     VGXY61_FWPATCH_REVISION_MICRO) {
> -		dev_err(&client->dev, "bad patch version expected %d.%d.%d got %d.%d.%d\n",
> +		dev_err(&client->dev,
> +			"bad patch version expected %d.%d.%d got %u.%u.%u\n",
>  			VGXY61_FWPATCH_REVISION_MAJOR,
>  			VGXY61_FWPATCH_REVISION_MINOR,
>  			VGXY61_FWPATCH_REVISION_MICRO,
> -			patch >> 12, (patch >> 8) & 0x0f, patch & 0xff);
> +			(u16)patch >> 12, ((u16)patch >> 8) & 0x0f, (u16)patch & 0xff);

Checkpatch is complaining about this line being 87 characters long
instead of 80.
Could a maintainer apply with correct line wrap ? Thank you.

With that fixed :
Reviewed-by: Benjamin Mugnier <benjamin.mugnier@foss.st.com>

>  		return -ENODEV;
>  	}
> -	dev_dbg(&client->dev, "patch %d.%d.%d applied\n",
> -		patch >> 12, (patch >> 8) & 0x0f, patch & 0xff);
> +	dev_dbg(&client->dev, "patch %u.%u.%u applied\n",
> +		(u16)patch >> 12, ((u16)patch >> 8) & 0x0f, (u16)patch & 0xff);
>  
>  	return 0;
>  }
[...]
diff mbox series

Patch

diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index d0dfab513154..3961510fcf79 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -658,6 +658,7 @@  config VIDEO_S5K6A3
 
 config VIDEO_ST_VGXY61
 	tristate "ST VGXY61 sensor support"
+	select V4L2_CCI_I2C
 	depends on OF && GPIOLIB
 	help
 	  This is a Video4Linux2 sensor driver for the ST VGXY61
diff --git a/drivers/media/i2c/st-vgxy61.c b/drivers/media/i2c/st-vgxy61.c
index e4d37a197724..2d64466d7ecf 100644
--- a/drivers/media/i2c/st-vgxy61.c
+++ b/drivers/media/i2c/st-vgxy61.c
@@ -12,6 +12,7 @@ 
 #include <linux/iopoll.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/units.h>
 
@@ -19,79 +20,74 @@ 
 
 #include <media/mipi-csi2.h>
 #include <media/v4l2-async.h>
+#include <media/v4l2-cci.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-event.h>
 #include <media/v4l2-fwnode.h>
 #include <media/v4l2-subdev.h>
 
-#define VGXY61_REG_8BIT(n)				((1 << 16) | (n))
-#define VGXY61_REG_16BIT(n)				((2 << 16) | (n))
-#define VGXY61_REG_32BIT(n)				((4 << 16) | (n))
-#define VGXY61_REG_SIZE_SHIFT				16
-#define VGXY61_REG_ADDR_MASK				0xffff
-
-#define VGXY61_REG_MODEL_ID				VGXY61_REG_16BIT(0x0000)
+#define VGXY61_REG_MODEL_ID				CCI_REG16_LE(0x0000)
 #define VG5661_MODEL_ID					0x5661
 #define VG5761_MODEL_ID					0x5761
-#define VGXY61_REG_REVISION				VGXY61_REG_16BIT(0x0002)
-#define VGXY61_REG_FWPATCH_REVISION			VGXY61_REG_16BIT(0x0014)
-#define VGXY61_REG_FWPATCH_START_ADDR			VGXY61_REG_8BIT(0x2000)
-#define VGXY61_REG_SYSTEM_FSM				VGXY61_REG_8BIT(0x0020)
+#define VGXY61_REG_REVISION				CCI_REG16_LE(0x0002)
+#define VGXY61_REG_FWPATCH_REVISION			CCI_REG16_LE(0x0014)
+#define VGXY61_REG_FWPATCH_START_ADDR			CCI_REG8(0x2000)
+#define VGXY61_REG_SYSTEM_FSM				CCI_REG8(0x0020)
 #define VGXY61_SYSTEM_FSM_SW_STBY			0x03
 #define VGXY61_SYSTEM_FSM_STREAMING			0x04
-#define VGXY61_REG_NVM					VGXY61_REG_8BIT(0x0023)
+#define VGXY61_REG_NVM					CCI_REG8(0x0023)
 #define VGXY61_NVM_OK					0x04
-#define VGXY61_REG_STBY					VGXY61_REG_8BIT(0x0201)
+#define VGXY61_REG_STBY					CCI_REG8(0x0201)
 #define VGXY61_STBY_NO_REQ				0
 #define VGXY61_STBY_REQ_TMP_READ			BIT(2)
-#define VGXY61_REG_STREAMING				VGXY61_REG_8BIT(0x0202)
+#define VGXY61_REG_STREAMING				CCI_REG8(0x0202)
 #define VGXY61_STREAMING_NO_REQ				0
 #define VGXY61_STREAMING_REQ_STOP			BIT(0)
 #define VGXY61_STREAMING_REQ_START			BIT(1)
-#define VGXY61_REG_EXT_CLOCK				VGXY61_REG_32BIT(0x0220)
-#define VGXY61_REG_CLK_PLL_PREDIV			VGXY61_REG_8BIT(0x0224)
-#define VGXY61_REG_CLK_SYS_PLL_MULT			VGXY61_REG_8BIT(0x0225)
-#define VGXY61_REG_GPIO_0_CTRL				VGXY61_REG_8BIT(0x0236)
-#define VGXY61_REG_GPIO_1_CTRL				VGXY61_REG_8BIT(0x0237)
-#define VGXY61_REG_GPIO_2_CTRL				VGXY61_REG_8BIT(0x0238)
-#define VGXY61_REG_GPIO_3_CTRL				VGXY61_REG_8BIT(0x0239)
-#define VGXY61_REG_SIGNALS_POLARITY_CTRL		VGXY61_REG_8BIT(0x023b)
-#define VGXY61_REG_LINE_LENGTH				VGXY61_REG_16BIT(0x0300)
-#define VGXY61_REG_ORIENTATION				VGXY61_REG_8BIT(0x0302)
-#define VGXY61_REG_VT_CTRL				VGXY61_REG_8BIT(0x0304)
-#define VGXY61_REG_FORMAT_CTRL				VGXY61_REG_8BIT(0x0305)
-#define VGXY61_REG_OIF_CTRL				VGXY61_REG_16BIT(0x0306)
-#define VGXY61_REG_OIF_ROI0_CTRL			VGXY61_REG_8BIT(0x030a)
-#define VGXY61_REG_ROI0_START_H				VGXY61_REG_16BIT(0x0400)
-#define VGXY61_REG_ROI0_START_V				VGXY61_REG_16BIT(0x0402)
-#define VGXY61_REG_ROI0_END_H				VGXY61_REG_16BIT(0x0404)
-#define VGXY61_REG_ROI0_END_V				VGXY61_REG_16BIT(0x0406)
-#define VGXY61_REG_PATGEN_CTRL				VGXY61_REG_32BIT(0x0440)
+#define VGXY61_REG_EXT_CLOCK				CCI_REG32_LE(0x0220)
+#define VGXY61_REG_CLK_PLL_PREDIV			CCI_REG8(0x0224)
+#define VGXY61_REG_CLK_SYS_PLL_MULT			CCI_REG8(0x0225)
+#define VGXY61_REG_GPIO_0_CTRL				CCI_REG8(0x0236)
+#define VGXY61_REG_GPIO_1_CTRL				CCI_REG8(0x0237)
+#define VGXY61_REG_GPIO_2_CTRL				CCI_REG8(0x0238)
+#define VGXY61_REG_GPIO_3_CTRL				CCI_REG8(0x0239)
+#define VGXY61_REG_SIGNALS_POLARITY_CTRL		CCI_REG8(0x023b)
+#define VGXY61_REG_LINE_LENGTH				CCI_REG16_LE(0x0300)
+#define VGXY61_REG_ORIENTATION				CCI_REG8(0x0302)
+#define VGXY61_REG_VT_CTRL				CCI_REG8(0x0304)
+#define VGXY61_REG_FORMAT_CTRL				CCI_REG8(0x0305)
+#define VGXY61_REG_OIF_CTRL				CCI_REG16_LE(0x0306)
+#define VGXY61_REG_OIF_ROI0_CTRL			CCI_REG8(0x030a)
+#define VGXY61_REG_ROI0_START_H				CCI_REG16_LE(0x0400)
+#define VGXY61_REG_ROI0_START_V				CCI_REG16_LE(0x0402)
+#define VGXY61_REG_ROI0_END_H				CCI_REG16_LE(0x0404)
+#define VGXY61_REG_ROI0_END_V				CCI_REG16_LE(0x0406)
+#define VGXY61_REG_PATGEN_CTRL				CCI_REG32_LE(0x0440)
 #define VGXY61_PATGEN_LONG_ENABLE			BIT(16)
 #define VGXY61_PATGEN_SHORT_ENABLE			BIT(0)
 #define VGXY61_PATGEN_LONG_TYPE_SHIFT			18
 #define VGXY61_PATGEN_SHORT_TYPE_SHIFT			4
-#define VGXY61_REG_FRAME_CONTENT_CTRL			VGXY61_REG_8BIT(0x0478)
-#define VGXY61_REG_COARSE_EXPOSURE_LONG			VGXY61_REG_16BIT(0x0500)
-#define VGXY61_REG_COARSE_EXPOSURE_SHORT		VGXY61_REG_16BIT(0x0504)
-#define VGXY61_REG_ANALOG_GAIN				VGXY61_REG_8BIT(0x0508)
-#define VGXY61_REG_DIGITAL_GAIN_LONG			VGXY61_REG_16BIT(0x050a)
-#define VGXY61_REG_DIGITAL_GAIN_SHORT			VGXY61_REG_16BIT(0x0512)
-#define VGXY61_REG_FRAME_LENGTH				VGXY61_REG_16BIT(0x051a)
-#define VGXY61_REG_SIGNALS_CTRL				VGXY61_REG_16BIT(0x0522)
+#define VGXY61_REG_FRAME_CONTENT_CTRL			CCI_REG8(0x0478)
+#define VGXY61_REG_COARSE_EXPOSURE_LONG			CCI_REG16_LE(0x0500)
+#define VGXY61_REG_COARSE_EXPOSURE_SHORT		CCI_REG16_LE(0x0504)
+#define VGXY61_REG_ANALOG_GAIN				CCI_REG8(0x0508)
+#define VGXY61_REG_DIGITAL_GAIN_LONG			CCI_REG16_LE(0x050a)
+#define VGXY61_REG_DIGITAL_GAIN_SHORT			CCI_REG16_LE(0x0512)
+#define VGXY61_REG_FRAME_LENGTH				CCI_REG16_LE(0x051a)
+#define VGXY61_REG_SIGNALS_CTRL				CCI_REG16_LE(0x0522)
 #define VGXY61_SIGNALS_GPIO_ID_SHIFT			4
-#define VGXY61_REG_READOUT_CTRL				VGXY61_REG_8BIT(0x0530)
-#define VGXY61_REG_HDR_CTRL				VGXY61_REG_8BIT(0x0532)
-#define VGXY61_REG_PATGEN_LONG_DATA_GR			VGXY61_REG_16BIT(0x092c)
-#define VGXY61_REG_PATGEN_LONG_DATA_R			VGXY61_REG_16BIT(0x092e)
-#define VGXY61_REG_PATGEN_LONG_DATA_B			VGXY61_REG_16BIT(0x0930)
-#define VGXY61_REG_PATGEN_LONG_DATA_GB			VGXY61_REG_16BIT(0x0932)
-#define VGXY61_REG_PATGEN_SHORT_DATA_GR			VGXY61_REG_16BIT(0x0950)
-#define VGXY61_REG_PATGEN_SHORT_DATA_R			VGXY61_REG_16BIT(0x0952)
-#define VGXY61_REG_PATGEN_SHORT_DATA_B			VGXY61_REG_16BIT(0x0954)
-#define VGXY61_REG_PATGEN_SHORT_DATA_GB			VGXY61_REG_16BIT(0x0956)
-#define VGXY61_REG_BYPASS_CTRL				VGXY61_REG_8BIT(0x0a60)
+#define VGXY61_REG_READOUT_CTRL				CCI_REG8(0x0530)
+#define VGXY61_REG_HDR_CTRL				CCI_REG8(0x0532)
+#define VGXY61_REG_PATGEN_LONG_DATA_GR			CCI_REG16_LE(0x092c)
+#define VGXY61_REG_PATGEN_LONG_DATA_R			CCI_REG16_LE(0x092e)
+#define VGXY61_REG_PATGEN_LONG_DATA_B			CCI_REG16_LE(0x0930)
+#define VGXY61_REG_PATGEN_LONG_DATA_GB			CCI_REG16_LE(0x0932)
+#define VGXY61_REG_PATGEN_SHORT_DATA_GR			CCI_REG16_LE(0x0950)
+#define VGXY61_REG_PATGEN_SHORT_DATA_R			CCI_REG16_LE(0x0952)
+#define VGXY61_REG_PATGEN_SHORT_DATA_B			CCI_REG16_LE(0x0954)
+#define VGXY61_REG_PATGEN_SHORT_DATA_GB			CCI_REG16_LE(0x0956)
+#define VGXY61_REG_BYPASS_CTRL				CCI_REG8(0x0a60)
 
 #define VGX661_WIDTH					1464
 #define VGX661_HEIGHT					1104
@@ -384,6 +380,7 @@  static const struct vgxy61_mode_info vgx761_mode_data[] = {
 
 struct vgxy61_dev {
 	struct i2c_client *i2c_client;
+	struct regmap *regmap;
 	struct v4l2_subdev sd;
 	struct media_pad pad;
 	struct regulator_bulk_data supplies[ARRAY_SIZE(vgxy61_supply_name)];
@@ -510,82 +507,6 @@  static unsigned int get_chunk_size(struct vgxy61_dev *sensor)
 	return max(max_write_len, 1);
 }
 
-static int vgxy61_read_multiple(struct vgxy61_dev *sensor, u32 reg,
-				unsigned int len)
-{
-	struct i2c_client *client = sensor->i2c_client;
-	struct i2c_msg msg[2];
-	u8 buf[2];
-	u8 val[sizeof(u32)] = {0};
-	int ret;
-
-	if (len > sizeof(u32))
-		return -EINVAL;
-	buf[0] = reg >> 8;
-	buf[1] = reg & 0xff;
-
-	msg[0].addr = client->addr;
-	msg[0].flags = client->flags;
-	msg[0].buf = buf;
-	msg[0].len = sizeof(buf);
-
-	msg[1].addr = client->addr;
-	msg[1].flags = client->flags | I2C_M_RD;
-	msg[1].buf = val;
-	msg[1].len = len;
-
-	ret = i2c_transfer(client->adapter, msg, 2);
-	if (ret < 0) {
-		dev_dbg(&client->dev, "%s: %x i2c_transfer, reg: %x => %d\n",
-			__func__, client->addr, reg, ret);
-		return ret;
-	}
-
-	return get_unaligned_le32(val);
-}
-
-static inline int vgxy61_read_reg(struct vgxy61_dev *sensor, u32 reg)
-{
-	return vgxy61_read_multiple(sensor, reg & VGXY61_REG_ADDR_MASK,
-				     (reg >> VGXY61_REG_SIZE_SHIFT) & 7);
-}
-
-static int vgxy61_write_multiple(struct vgxy61_dev *sensor, u32 reg,
-				 const u8 *data, unsigned int len, int *err)
-{
-	struct i2c_client *client = sensor->i2c_client;
-	struct i2c_msg msg;
-	u8 buf[VGXY61_WRITE_MULTIPLE_CHUNK_MAX + 2];
-	unsigned int i;
-	int ret;
-
-	if (err && *err)
-		return *err;
-
-	if (len > VGXY61_WRITE_MULTIPLE_CHUNK_MAX)
-		return -EINVAL;
-	buf[0] = reg >> 8;
-	buf[1] = reg & 0xff;
-	for (i = 0; i < len; i++)
-		buf[i + 2] = data[i];
-
-	msg.addr = client->addr;
-	msg.flags = client->flags;
-	msg.buf = buf;
-	msg.len = len + 2;
-
-	ret = i2c_transfer(client->adapter, &msg, 1);
-	if (ret < 0) {
-		dev_dbg(&client->dev, "%s: i2c_transfer, reg: %x => %d\n",
-			__func__, reg, ret);
-		if (err)
-			*err = ret;
-		return ret;
-	}
-
-	return 0;
-}
-
 static int vgxy61_write_array(struct vgxy61_dev *sensor, u32 reg,
 			      unsigned int nb, const u8 *array)
 {
@@ -595,7 +516,8 @@  static int vgxy61_write_array(struct vgxy61_dev *sensor, u32 reg,
 
 	while (nb) {
 		sz = min(nb, chunk_size);
-		ret = vgxy61_write_multiple(sensor, reg, array, sz, NULL);
+		ret = regmap_bulk_write(sensor->regmap, CCI_REG_ADDR(reg),
+					array, sz);
 		if (ret < 0)
 			return ret;
 		nb -= sz;
@@ -606,24 +528,17 @@  static int vgxy61_write_array(struct vgxy61_dev *sensor, u32 reg,
 	return 0;
 }
 
-static inline int vgxy61_write_reg(struct vgxy61_dev *sensor, u32 reg, u32 val,
-				   int *err)
-{
-	return vgxy61_write_multiple(sensor, reg & VGXY61_REG_ADDR_MASK,
-				     (u8 *)&val,
-				     (reg >> VGXY61_REG_SIZE_SHIFT) & 7, err);
-}
-
 static int vgxy61_poll_reg(struct vgxy61_dev *sensor, u32 reg, u8 poll_val,
 			   unsigned int timeout_ms)
 {
 	const unsigned int loop_delay_ms = 10;
+	u64 val;
 	int ret;
 
-	return read_poll_timeout(vgxy61_read_reg, ret,
-				 ((ret < 0) || (ret == poll_val)),
+	return read_poll_timeout(cci_read, ret,
+				 ((ret < 0) || (val == poll_val)),
 				 loop_delay_ms * 1000, timeout_ms * 1000,
-				 false, sensor, reg);
+				 false, sensor->regmap, reg, &val, NULL);
 }
 
 static int vgxy61_wait_state(struct vgxy61_dev *sensor, int state,
@@ -662,11 +577,11 @@  static int vgxy61_apply_exposure(struct vgxy61_dev *sensor)
 	int ret = 0;
 
 	 /* We first set expo to zero to avoid forbidden parameters couple */
-	vgxy61_write_reg(sensor, VGXY61_REG_COARSE_EXPOSURE_SHORT, 0, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_COARSE_EXPOSURE_LONG,
-			 sensor->expo_long, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_COARSE_EXPOSURE_SHORT,
-			 sensor->expo_short, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_COARSE_EXPOSURE_SHORT, 0, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_COARSE_EXPOSURE_LONG,
+		  sensor->expo_long, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_COARSE_EXPOSURE_SHORT,
+		  sensor->expo_short, &ret);
 
 	return ret;
 }
@@ -827,8 +742,8 @@  static int vgxy61_update_analog_gain(struct vgxy61_dev *sensor, u32 target)
 	sensor->analog_gain = target;
 
 	if (sensor->streaming)
-		return vgxy61_write_reg(sensor, VGXY61_REG_ANALOG_GAIN, target,
-					NULL);
+		return cci_write(sensor->regmap, VGXY61_REG_ANALOG_GAIN, target,
+				 NULL);
 	return 0;
 }
 
@@ -842,10 +757,10 @@  static int vgxy61_apply_digital_gain(struct vgxy61_dev *sensor,
 	 * DIGITAL_GAIN_SHORT_CH0 is enough to configure the gain of all
 	 * four sub pixels.
 	 */
-	vgxy61_write_reg(sensor, VGXY61_REG_DIGITAL_GAIN_LONG, digital_gain,
-			 &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_DIGITAL_GAIN_SHORT, digital_gain,
-			 &ret);
+	cci_write(sensor->regmap, VGXY61_REG_DIGITAL_GAIN_LONG, digital_gain,
+		  &ret);
+	cci_write(sensor->regmap, VGXY61_REG_DIGITAL_GAIN_SHORT, digital_gain,
+		  &ret);
 
 	return ret;
 }
@@ -870,7 +785,7 @@  static int vgxy61_apply_patgen(struct vgxy61_dev *sensor, u32 index)
 
 	if (pattern)
 		reg |= VGXY61_PATGEN_LONG_ENABLE | VGXY61_PATGEN_SHORT_ENABLE;
-	return vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_CTRL, reg, NULL);
+	return cci_write(sensor->regmap, VGXY61_REG_PATGEN_CTRL, reg, NULL);
 }
 
 static int vgxy61_update_patgen(struct vgxy61_dev *sensor, u32 pattern)
@@ -887,15 +802,13 @@  static int vgxy61_apply_gpiox_strobe_mode(struct vgxy61_dev *sensor,
 					  unsigned int idx)
 {
 	static const u8 index2val[] = {0x0, 0x1, 0x3};
-	int reg;
+	u16 mask, val;
 
-	reg = vgxy61_read_reg(sensor, VGXY61_REG_SIGNALS_CTRL);
-	if (reg < 0)
-		return reg;
-	reg &= ~(0xf << (idx * VGXY61_SIGNALS_GPIO_ID_SHIFT));
-	reg |= index2val[mode] << (idx * VGXY61_SIGNALS_GPIO_ID_SHIFT);
+	mask = 0xf << (idx * VGXY61_SIGNALS_GPIO_ID_SHIFT);
+	val = index2val[mode] << (idx * VGXY61_SIGNALS_GPIO_ID_SHIFT);
 
-	return vgxy61_write_reg(sensor, VGXY61_REG_SIGNALS_CTRL, reg, NULL);
+	return cci_update_bits(sensor->regmap, VGXY61_REG_SIGNALS_CTRL,
+			       mask, val, NULL);
 }
 
 static int vgxy61_update_gpios_strobe_mode(struct vgxy61_dev *sensor,
@@ -940,12 +853,12 @@  static int vgxy61_update_gpios_strobe_polarity(struct vgxy61_dev *sensor,
 	if (sensor->streaming)
 		return -EBUSY;
 
-	vgxy61_write_reg(sensor, VGXY61_REG_GPIO_0_CTRL, polarity << 1, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_GPIO_1_CTRL, polarity << 1, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_GPIO_2_CTRL, polarity << 1, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_GPIO_3_CTRL, polarity << 1, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_SIGNALS_POLARITY_CTRL, polarity,
-			 &ret);
+	cci_write(sensor->regmap, VGXY61_REG_GPIO_0_CTRL, polarity << 1, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_GPIO_1_CTRL, polarity << 1, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_GPIO_2_CTRL, polarity << 1, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_GPIO_3_CTRL, polarity << 1, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_SIGNALS_POLARITY_CTRL, polarity,
+		  &ret);
 
 	return ret;
 }
@@ -1057,8 +970,8 @@  static int vgxy61_update_exposure(struct vgxy61_dev *sensor, u16 new_expo_long,
 
 static int vgxy61_apply_framelength(struct vgxy61_dev *sensor)
 {
-	return vgxy61_write_reg(sensor, VGXY61_REG_FRAME_LENGTH,
-				sensor->frame_length, NULL);
+	return cci_write(sensor->regmap, VGXY61_REG_FRAME_LENGTH,
+			 sensor->frame_length, NULL);
 }
 
 static int vgxy61_update_vblank(struct vgxy61_dev *sensor, u16 vblank,
@@ -1086,8 +999,8 @@  static int vgxy61_apply_hdr(struct vgxy61_dev *sensor,
 {
 	static const u8 index2val[] = {0x1, 0x4, 0xa};
 
-	return vgxy61_write_reg(sensor, VGXY61_REG_HDR_CTRL, index2val[index],
-				NULL);
+	return cci_write(sensor->regmap, VGXY61_REG_HDR_CTRL, index2val[index],
+			 NULL);
 }
 
 static int vgxy61_update_hdr(struct vgxy61_dev *sensor,
@@ -1133,16 +1046,16 @@  static int vgxy61_apply_settings(struct vgxy61_dev *sensor)
 	if (ret)
 		return ret;
 
-	ret = vgxy61_write_reg(sensor, VGXY61_REG_ANALOG_GAIN,
-			       sensor->analog_gain, NULL);
+	ret = cci_write(sensor->regmap, VGXY61_REG_ANALOG_GAIN,
+			sensor->analog_gain, NULL);
 	if (ret)
 		return ret;
 	ret = vgxy61_apply_digital_gain(sensor, sensor->digital_gain);
 	if (ret)
 		return ret;
 
-	ret = vgxy61_write_reg(sensor, VGXY61_REG_ORIENTATION,
-			       sensor->hflip | (sensor->vflip << 1), NULL);
+	ret = cci_write(sensor->regmap, VGXY61_REG_ORIENTATION,
+			sensor->hflip | (sensor->vflip << 1), NULL);
 	if (ret)
 		return ret;
 
@@ -1174,19 +1087,19 @@  static int vgxy61_stream_enable(struct vgxy61_dev *sensor)
 	if (ret)
 		return ret;
 
-	vgxy61_write_reg(sensor, VGXY61_REG_FORMAT_CTRL,
-			 get_bpp_by_code(sensor->fmt.code), &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_OIF_ROI0_CTRL,
-			 get_data_type_by_code(sensor->fmt.code), &ret);
-
-	vgxy61_write_reg(sensor, VGXY61_REG_READOUT_CTRL,
-			 sensor->current_mode->bin_mode, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_ROI0_START_H, crop->left, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_ROI0_END_H,
-			 crop->left + crop->width - 1, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_ROI0_START_V, crop->top, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_ROI0_END_V,
-			 crop->top + crop->height - 1, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_FORMAT_CTRL,
+		  get_bpp_by_code(sensor->fmt.code), &ret);
+	cci_write(sensor->regmap, VGXY61_REG_OIF_ROI0_CTRL,
+		  get_data_type_by_code(sensor->fmt.code), &ret);
+
+	cci_write(sensor->regmap, VGXY61_REG_READOUT_CTRL,
+		  sensor->current_mode->bin_mode, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_ROI0_START_H, crop->left, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_ROI0_END_H,
+		  crop->left + crop->width - 1, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_ROI0_START_V, crop->top, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_ROI0_END_V,
+		  crop->top + crop->height - 1, &ret);
 	if (ret)
 		goto err_rpm_put;
 
@@ -1194,8 +1107,8 @@  static int vgxy61_stream_enable(struct vgxy61_dev *sensor)
 	if (ret)
 		goto err_rpm_put;
 
-	ret = vgxy61_write_reg(sensor, VGXY61_REG_STREAMING,
-			       VGXY61_STREAMING_REQ_START, NULL);
+	ret = cci_write(sensor->regmap, VGXY61_REG_STREAMING,
+			VGXY61_STREAMING_REQ_START, NULL);
 	if (ret)
 		goto err_rpm_put;
 
@@ -1225,8 +1138,8 @@  static int vgxy61_stream_disable(struct vgxy61_dev *sensor)
 	struct i2c_client *client = v4l2_get_subdevdata(&sensor->sd);
 	int ret;
 
-	ret = vgxy61_write_reg(sensor, VGXY61_REG_STREAMING,
-			       VGXY61_STREAMING_REQ_STOP, NULL);
+	ret = cci_write(sensor->regmap, VGXY61_REG_STREAMING,
+			VGXY61_STREAMING_REQ_STOP, NULL);
 	if (ret)
 		goto err_str_dis;
 
@@ -1582,7 +1495,7 @@  static int vgxy61_configure(struct vgxy61_dev *sensor)
 {
 	u32 sensor_freq;
 	u8 prediv, mult;
-	int line_length;
+	u64 line_length;
 	int ret = 0;
 
 	compute_pll_parameters_by_freq(sensor->clk_freq, &prediv, &mult);
@@ -1592,28 +1505,28 @@  static int vgxy61_configure(struct vgxy61_dev *sensor)
 	/* Video timing ISP path (pixel clock)  requires 804/5 mhz = 160 mhz */
 	sensor->pclk = sensor_freq / 5;
 
-	line_length = vgxy61_read_reg(sensor, VGXY61_REG_LINE_LENGTH);
-	if (line_length < 0)
-		return line_length;
-	sensor->line_length = line_length;
-	vgxy61_write_reg(sensor, VGXY61_REG_EXT_CLOCK, sensor->clk_freq, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_CLK_PLL_PREDIV, prediv, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_CLK_SYS_PLL_MULT, mult, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_OIF_CTRL, sensor->oif_ctrl, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_FRAME_CONTENT_CTRL, 0, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_BYPASS_CTRL, 4, &ret);
+	cci_read(sensor->regmap, VGXY61_REG_LINE_LENGTH, &line_length, &ret);
+	if (ret < 0)
+		return ret;
+	sensor->line_length = (u16)line_length;
+	cci_write(sensor->regmap, VGXY61_REG_EXT_CLOCK, sensor->clk_freq, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_CLK_PLL_PREDIV, prediv, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_CLK_SYS_PLL_MULT, mult, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_OIF_CTRL, sensor->oif_ctrl, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_FRAME_CONTENT_CTRL, 0, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_BYPASS_CTRL, 4, &ret);
 	if (ret)
 		return ret;
 	vgxy61_update_gpios_strobe_polarity(sensor, sensor->gpios_polarity);
 	/* Set pattern generator solid to middle value */
-	vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_LONG_DATA_GR, 0x800, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_LONG_DATA_R, 0x800, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_LONG_DATA_B, 0x800, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_LONG_DATA_GB, 0x800, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_SHORT_DATA_GR, 0x800, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_SHORT_DATA_R, 0x800, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_SHORT_DATA_B, 0x800, &ret);
-	vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_SHORT_DATA_GB, 0x800, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_PATGEN_LONG_DATA_GR, 0x800, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_PATGEN_LONG_DATA_R, 0x800, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_PATGEN_LONG_DATA_B, 0x800, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_PATGEN_LONG_DATA_GB, 0x800, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_PATGEN_SHORT_DATA_GR, 0x800, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_PATGEN_SHORT_DATA_R, 0x800, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_PATGEN_SHORT_DATA_B, 0x800, &ret);
+	cci_write(sensor->regmap, VGXY61_REG_PATGEN_SHORT_DATA_GB, 0x800, &ret);
 	if (ret)
 		return ret;
 
@@ -1623,37 +1536,33 @@  static int vgxy61_configure(struct vgxy61_dev *sensor)
 static int vgxy61_patch(struct vgxy61_dev *sensor)
 {
 	struct i2c_client *client = sensor->i2c_client;
-	int patch, ret;
+	u64 patch;
+	int ret;
 
 	ret = vgxy61_write_array(sensor, VGXY61_REG_FWPATCH_START_ADDR,
 				 sizeof(patch_array), patch_array);
-	if (ret)
-		return ret;
-
-	ret = vgxy61_write_reg(sensor, VGXY61_REG_STBY, 0x10, NULL);
+	cci_write(sensor->regmap, VGXY61_REG_STBY, 0x10, &ret);
 	if (ret)
 		return ret;
 
 	ret = vgxy61_poll_reg(sensor, VGXY61_REG_STBY, 0, VGXY61_TIMEOUT_MS);
-	if (ret)
+	cci_read(sensor->regmap, VGXY61_REG_FWPATCH_REVISION, &patch, &ret);
+	if (ret < 0)
 		return ret;
 
-	patch = vgxy61_read_reg(sensor, VGXY61_REG_FWPATCH_REVISION);
-	if (patch < 0)
-		return patch;
-
 	if (patch != (VGXY61_FWPATCH_REVISION_MAJOR << 12) +
 		     (VGXY61_FWPATCH_REVISION_MINOR << 8) +
 		     VGXY61_FWPATCH_REVISION_MICRO) {
-		dev_err(&client->dev, "bad patch version expected %d.%d.%d got %d.%d.%d\n",
+		dev_err(&client->dev,
+			"bad patch version expected %d.%d.%d got %u.%u.%u\n",
 			VGXY61_FWPATCH_REVISION_MAJOR,
 			VGXY61_FWPATCH_REVISION_MINOR,
 			VGXY61_FWPATCH_REVISION_MICRO,
-			patch >> 12, (patch >> 8) & 0x0f, patch & 0xff);
+			(u16)patch >> 12, ((u16)patch >> 8) & 0x0f, (u16)patch & 0xff);
 		return -ENODEV;
 	}
-	dev_dbg(&client->dev, "patch %d.%d.%d applied\n",
-		patch >> 12, (patch >> 8) & 0x0f, patch & 0xff);
+	dev_dbg(&client->dev, "patch %u.%u.%u applied\n",
+		(u16)patch >> 12, ((u16)patch >> 8) & 0x0f, (u16)patch & 0xff);
 
 	return 0;
 }
@@ -1661,11 +1570,12 @@  static int vgxy61_patch(struct vgxy61_dev *sensor)
 static int vgxy61_detect_cut_version(struct vgxy61_dev *sensor)
 {
 	struct i2c_client *client = sensor->i2c_client;
-	int device_rev;
+	u64 device_rev;
+	int ret;
 
-	device_rev = vgxy61_read_reg(sensor, VGXY61_REG_REVISION);
-	if (device_rev < 0)
-		return device_rev;
+	ret = cci_read(sensor->regmap, VGXY61_REG_REVISION, &device_rev, NULL);
+	if (ret < 0)
+		return ret;
 
 	switch (device_rev >> 8) {
 	case 0xA:
@@ -1687,17 +1597,17 @@  static int vgxy61_detect_cut_version(struct vgxy61_dev *sensor)
 static int vgxy61_detect(struct vgxy61_dev *sensor)
 {
 	struct i2c_client *client = sensor->i2c_client;
-	int id = 0;
-	int ret, st;
+	u64 st, id = 0;
+	int ret;
 
-	id = vgxy61_read_reg(sensor, VGXY61_REG_MODEL_ID);
-	if (id < 0)
-		return id;
+	ret = cci_read(sensor->regmap, VGXY61_REG_MODEL_ID, &id, NULL);
+	if (ret < 0)
+		return ret;
 	if (id != VG5661_MODEL_ID && id != VG5761_MODEL_ID) {
-		dev_warn(&client->dev, "Unsupported sensor id %x\n", id);
+		dev_warn(&client->dev, "Unsupported sensor id %x\n", (u16)id);
 		return -ENODEV;
 	}
-	dev_dbg(&client->dev, "detected sensor id = 0x%04x\n", id);
+	dev_dbg(&client->dev, "detected sensor id = 0x%04x\n", (u16)id);
 	sensor->id = id;
 
 	ret = vgxy61_wait_state(sensor, VGXY61_SYSTEM_FSM_SW_STBY,
@@ -1705,11 +1615,11 @@  static int vgxy61_detect(struct vgxy61_dev *sensor)
 	if (ret)
 		return ret;
 
-	st = vgxy61_read_reg(sensor, VGXY61_REG_NVM);
-	if (st < 0)
+	ret = cci_read(sensor->regmap, VGXY61_REG_NVM, &st, NULL);
+	if (ret < 0)
 		return st;
 	if (st != VGXY61_NVM_OK)
-		dev_warn(&client->dev, "Bad nvm state got %d\n", st);
+		dev_warn(&client->dev, "Bad nvm state got %u\n", (u8)st);
 
 	ret = vgxy61_detect_cut_version(sensor);
 	if (ret)
@@ -1832,6 +1742,12 @@  static int vgxy61_probe(struct i2c_client *client)
 	sensor->analog_gain = 0;
 	sensor->digital_gain = 256;
 
+	sensor->regmap = devm_cci_regmap_init_i2c(client, 16);
+	if (IS_ERR(sensor->regmap)) {
+		ret = PTR_ERR(sensor->regmap);
+		return dev_err_probe(dev, ret, "Failed to init regmap\n");
+	}
+
 	handle = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0, 0);
 	if (!handle) {
 		dev_err(dev, "handle node not found\n");