[PATCH v3 1/3] media: i2c: ov9282: Convert to CCI register access helpers

Xiaolei Wang posted 3 patches 1 month, 1 week ago
There is a newer version of this series
[PATCH v3 1/3] media: i2c: ov9282: Convert to CCI register access helpers
Posted by Xiaolei Wang 1 month, 1 week ago
Use the new common CCI register access helpers to replace the private
register access helpers in the ov9282 driver. This simplifies the driver
by reducing the amount of code.

Signed-off-by: Xiaolei Wang <xiaolei.wang@windriver.com>
Reviewed-by: Tarang Raval <tarang.raval@siliconsignals.io>
---
 drivers/media/i2c/Kconfig  |   1 +
 drivers/media/i2c/ov9282.c | 293 ++++++++-----------------------------
 2 files changed, 64 insertions(+), 230 deletions(-)

diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 5eb1e0e0a87a..3027e71fd8fb 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -690,6 +690,7 @@ config VIDEO_OV8865
 config VIDEO_OV9282
 	tristate "OmniVision OV9282 sensor support"
 	depends on OF_GPIO
+	select V4L2_CCI_I2C
 	help
 	  This is a Video4Linux2 sensor driver for the OmniVision
 	  OV9282 camera sensor.
diff --git a/drivers/media/i2c/ov9282.c b/drivers/media/i2c/ov9282.c
index ded9b2044ff8..8bfaa3ae4be5 100644
--- a/drivers/media/i2c/ov9282.c
+++ b/drivers/media/i2c/ov9282.c
@@ -12,38 +12,40 @@
 #include <linux/math.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 
+#include <media/v4l2-cci.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-event.h>
 #include <media/v4l2-fwnode.h>
 #include <media/v4l2-subdev.h>
 
 /* Streaming Mode */
-#define OV9282_REG_MODE_SELECT	0x0100
+#define OV9282_REG_MODE_SELECT	CCI_REG8(0x0100)
 #define OV9282_MODE_STANDBY	0x00
 #define OV9282_MODE_STREAMING	0x01
 
-#define OV9282_REG_PLL_CTRL_0D	0x030d
+#define OV9282_REG_PLL_CTRL_0D	CCI_REG8(0x030d)
 #define OV9282_PLL_CTRL_0D_RAW8		0x60
 #define OV9282_PLL_CTRL_0D_RAW10	0x50
 
-#define OV9282_REG_TIMING_HTS	0x380c
+#define OV9282_REG_TIMING_HTS	CCI_REG16(0x380c)
 #define OV9282_TIMING_HTS_MAX	0x7fff
 
 /* Lines per frame */
-#define OV9282_REG_LPFR		0x380e
+#define OV9282_REG_LPFR		CCI_REG16(0x380e)
 
 /* Chip ID */
-#define OV9282_REG_ID		0x300a
+#define OV9282_REG_ID		CCI_REG16(0x300a)
 #define OV9282_ID		0x9281
 
 /* Output enable registers */
-#define OV9282_REG_OUTPUT_ENABLE4	0x3004
+#define OV9282_REG_OUTPUT_ENABLE4	CCI_REG8(0x3004)
 #define OV9282_OUTPUT_ENABLE4_GPIO2	BIT(1)
 #define OV9282_OUTPUT_ENABLE4_D9	BIT(0)
 
-#define OV9282_REG_OUTPUT_ENABLE5	0x3005
+#define OV9282_REG_OUTPUT_ENABLE5	CCI_REG8(0x3005)
 #define OV9282_OUTPUT_ENABLE5_D8	BIT(7)
 #define OV9282_OUTPUT_ENABLE5_D7	BIT(6)
 #define OV9282_OUTPUT_ENABLE5_D6	BIT(5)
@@ -53,7 +55,7 @@
 #define OV9282_OUTPUT_ENABLE5_D2	BIT(1)
 #define OV9282_OUTPUT_ENABLE5_D1	BIT(0)
 
-#define OV9282_REG_OUTPUT_ENABLE6	0x3006
+#define OV9282_REG_OUTPUT_ENABLE6	CCI_REG8(0x3006)
 #define OV9282_OUTPUT_ENABLE6_D0	BIT(7)
 #define OV9282_OUTPUT_ENABLE6_PCLK	BIT(6)
 #define OV9282_OUTPUT_ENABLE6_HREF	BIT(5)
@@ -62,14 +64,14 @@
 #define OV9282_OUTPUT_ENABLE6_VSYNC	BIT(1)
 
 /* Exposure control */
-#define OV9282_REG_EXPOSURE	0x3500
+#define OV9282_REG_EXPOSURE	CCI_REG24(0x3500)
 #define OV9282_EXPOSURE_MIN	1
 #define OV9282_EXPOSURE_OFFSET	25
 #define OV9282_EXPOSURE_STEP	1
 #define OV9282_EXPOSURE_DEFAULT	0x0282
 
 /* AEC/AGC manual */
-#define OV9282_REG_AEC_MANUAL		0x3503
+#define OV9282_REG_AEC_MANUAL		CCI_REG8(0x3503)
 #define OV9282_DIGFRAC_GAIN_DELAY	BIT(6)
 #define OV9282_GAIN_CHANGE_DELAY	BIT(5)
 #define OV9282_GAIN_DELAY		BIT(4)
@@ -78,28 +80,28 @@
 #define OV9282_AEC_MANUAL_DEFAULT	0x00
 
 /* Analog gain control */
-#define OV9282_REG_AGAIN	0x3509
+#define OV9282_REG_AGAIN	CCI_REG8(0x3509)
 #define OV9282_AGAIN_MIN	0x10
 #define OV9282_AGAIN_MAX	0xff
 #define OV9282_AGAIN_STEP	1
 #define OV9282_AGAIN_DEFAULT	0x10
 
 /* Group hold register */
-#define OV9282_REG_HOLD		0x3308
+#define OV9282_REG_HOLD		CCI_REG8(0x3308)
 
-#define OV9282_REG_ANA_CORE_2	0x3662
+#define OV9282_REG_ANA_CORE_2	CCI_REG8(0x3662)
 #define OV9282_ANA_CORE2_RAW8	0x07
 #define OV9282_ANA_CORE2_RAW10	0x05
 
-#define OV9282_REG_TIMING_FORMAT_1	0x3820
-#define OV9282_REG_TIMING_FORMAT_2	0x3821
+#define OV9282_REG_TIMING_FORMAT_1	CCI_REG8(0x3820)
+#define OV9282_REG_TIMING_FORMAT_2	CCI_REG8(0x3821)
 #define OV9282_FLIP_BIT			BIT(2)
 
-#define OV9282_REG_MIPI_CTRL00	0x4800
+#define OV9282_REG_MIPI_CTRL00	CCI_REG8(0x4800)
 #define OV9282_GATED_CLOCK	BIT(5)
 
 /* Flash/Strobe control registers */
-#define OV9282_REG_STROBE_FRAME_SPAN		0x3925
+#define OV9282_REG_STROBE_FRAME_SPAN		CCI_REG32(0x3925)
 #define OV9282_STROBE_FRAME_SPAN_DEFAULT	0x0000001a
 
 /* Input clock rate */
@@ -139,16 +141,6 @@ static const char * const ov9282_supply_names[] = {
 
 #define OV9282_NUM_SUPPLIES ARRAY_SIZE(ov9282_supply_names)
 
-/**
- * struct ov9282_reg - ov9282 sensor register
- * @address: Register address
- * @val: Register value
- */
-struct ov9282_reg {
-	u16 address;
-	u8 val;
-};
-
 /**
  * struct ov9282_reg_list - ov9282 sensor register list
  * @num_of_regs: Number of registers in the list
@@ -156,7 +148,7 @@ struct ov9282_reg {
  */
 struct ov9282_reg_list {
 	u32 num_of_regs;
-	const struct ov9282_reg *regs;
+	const struct reg_sequence *regs;
 };
 
 /**
@@ -188,6 +180,7 @@ struct ov9282_mode {
  * struct ov9282 - ov9282 sensor device structure
  * @dev: Pointer to generic device
  * @sd: V4L2 sub-device
+ * @regmap: Regmap for sensor register access
  * @pad: Media pad. Only one pad supported
  * @reset_gpio: Sensor reset gpio
  * @inclk: Sensor input clock
@@ -209,6 +202,7 @@ struct ov9282_mode {
 struct ov9282 {
 	struct device *dev;
 	struct v4l2_subdev sd;
+	struct regmap *regmap;
 	struct media_pad pad;
 	struct gpio_desc *reset_gpio;
 	struct clk *inclk;
@@ -241,7 +235,7 @@ static const s64 link_freq[] = {
  * register arrays as some settings are written as part of ov9282_power_on,
  * and the reset will clear them.
  */
-static const struct ov9282_reg common_regs[] = {
+static const struct reg_sequence common_regs[] = {
 	{0x0302, 0x32},
 	{0x030e, 0x02},
 	{0x3001, 0x00},
@@ -305,11 +299,6 @@ static const struct ov9282_reg common_regs[] = {
 	{0x5a08, 0x84},
 };
 
-static struct ov9282_reg_list common_regs_list = {
-	.num_of_regs = ARRAY_SIZE(common_regs),
-	.regs = common_regs,
-};
-
 #define MODE_1280_800		0
 #define MODE_1280_720		1
 #define MODE_640_400		2
@@ -317,7 +306,7 @@ static struct ov9282_reg_list common_regs_list = {
 #define DEFAULT_MODE		MODE_1280_720
 
 /* Sensor mode registers */
-static const struct ov9282_reg mode_1280x800_regs[] = {
+static const struct reg_sequence mode_1280x800_regs[] = {
 	{0x3778, 0x00},
 	{0x3800, 0x00},
 	{0x3801, 0x00},
@@ -348,7 +337,7 @@ static const struct ov9282_reg mode_1280x800_regs[] = {
 	{0x4509, 0x00},
 };
 
-static const struct ov9282_reg mode_1280x720_regs[] = {
+static const struct reg_sequence mode_1280x720_regs[] = {
 	{0x3778, 0x00},
 	{0x3800, 0x00},
 	{0x3801, 0x00},
@@ -379,7 +368,7 @@ static const struct ov9282_reg mode_1280x720_regs[] = {
 	{0x4509, 0x80},
 };
 
-static const struct ov9282_reg mode_640x400_regs[] = {
+static const struct reg_sequence mode_640x400_regs[] = {
 	{0x3778, 0x10},
 	{0x3800, 0x00},
 	{0x3801, 0x00},
@@ -485,97 +474,6 @@ static inline struct ov9282 *to_ov9282(struct v4l2_subdev *subdev)
 	return container_of(subdev, struct ov9282, sd);
 }
 
-/**
- * ov9282_read_reg() - Read registers.
- * @ov9282: pointer to ov9282 device
- * @reg: register address
- * @len: length of bytes to read. Max supported bytes is 4
- * @val: pointer to register value to be filled.
- *
- * Return: 0 if successful, error code otherwise.
- */
-static int ov9282_read_reg(struct ov9282 *ov9282, u16 reg, u32 len, u32 *val)
-{
-	struct i2c_client *client = v4l2_get_subdevdata(&ov9282->sd);
-	struct i2c_msg msgs[2] = {0};
-	u8 addr_buf[2] = {0};
-	u8 data_buf[4] = {0};
-	int ret;
-
-	if (WARN_ON(len > 4))
-		return -EINVAL;
-
-	put_unaligned_be16(reg, addr_buf);
-
-	/* Write register address */
-	msgs[0].addr = client->addr;
-	msgs[0].flags = 0;
-	msgs[0].len = ARRAY_SIZE(addr_buf);
-	msgs[0].buf = addr_buf;
-
-	/* Read data from register */
-	msgs[1].addr = client->addr;
-	msgs[1].flags = I2C_M_RD;
-	msgs[1].len = len;
-	msgs[1].buf = &data_buf[4 - len];
-
-	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
-	if (ret != ARRAY_SIZE(msgs))
-		return -EIO;
-
-	*val = get_unaligned_be32(data_buf);
-
-	return 0;
-}
-
-/**
- * ov9282_write_reg() - Write register
- * @ov9282: pointer to ov9282 device
- * @reg: register address
- * @len: length of bytes. Max supported bytes is 4
- * @val: register value
- *
- * Return: 0 if successful, error code otherwise.
- */
-static int ov9282_write_reg(struct ov9282 *ov9282, u16 reg, u32 len, u32 val)
-{
-	struct i2c_client *client = v4l2_get_subdevdata(&ov9282->sd);
-	u8 buf[6] = {0};
-
-	if (WARN_ON(len > 4))
-		return -EINVAL;
-
-	put_unaligned_be16(reg, buf);
-	put_unaligned_be32(val << (8 * (4 - len)), buf + 2);
-	if (i2c_master_send(client, buf, len + 2) != len + 2)
-		return -EIO;
-
-	return 0;
-}
-
-/**
- * ov9282_write_regs() - Write a list of registers
- * @ov9282: pointer to ov9282 device
- * @regs: list of registers to be written
- * @len: length of registers array
- *
- * Return: 0 if successful, error code otherwise.
- */
-static int ov9282_write_regs(struct ov9282 *ov9282,
-			     const struct ov9282_reg *regs, u32 len)
-{
-	unsigned int i;
-	int ret;
-
-	for (i = 0; i < len; i++) {
-		ret = ov9282_write_reg(ov9282, regs[i].address, 1, regs[i].val);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
 /**
  * ov9282_update_controls() - Update control ranges based on streaming mode
  * @ov9282: pointer to ov9282 device
@@ -639,15 +537,15 @@ static int ov9282_update_exp_gain(struct ov9282 *ov9282, u32 exposure, u32 gain)
 	dev_dbg(ov9282->dev, "Set exp %u (~%u us), analog gain %u",
 		exposure, exposure_us, gain);
 
-	ret = ov9282_write_reg(ov9282, OV9282_REG_HOLD, 1, 1);
+	ret = cci_write(ov9282->regmap, OV9282_REG_HOLD, 0x01, NULL);
 	if (ret)
 		return ret;
 
-	ret = ov9282_write_reg(ov9282, OV9282_REG_EXPOSURE, 3, exposure << 4);
+	ret = cci_write(ov9282->regmap, OV9282_REG_EXPOSURE, exposure << 4, NULL);
 	if (ret)
 		goto error_release_group_hold;
 
-	ret = ov9282_write_reg(ov9282, OV9282_REG_AGAIN, 1, gain);
+	ret = cci_write(ov9282->regmap, OV9282_REG_AGAIN, gain, NULL);
 	if (ret)
 		goto error_release_group_hold;
 
@@ -656,60 +554,9 @@ static int ov9282_update_exp_gain(struct ov9282 *ov9282, u32 exposure, u32 gain)
 				       OV9282_STROBE_FRAME_SPAN_DEFAULT);
 
 error_release_group_hold:
-	ov9282_write_reg(ov9282, OV9282_REG_HOLD, 1, 0);
-
-	return ret;
-}
-
-static int ov9282_set_ctrl_hflip(struct ov9282 *ov9282, int value)
-{
-	u32 current_val;
-	int ret = ov9282_read_reg(ov9282, OV9282_REG_TIMING_FORMAT_2, 1,
-				  &current_val);
-	if (ret)
-		return ret;
+	int ret_hold = cci_write(ov9282->regmap, OV9282_REG_HOLD, 0, NULL);
 
-	if (value)
-		current_val |= OV9282_FLIP_BIT;
-	else
-		current_val &= ~OV9282_FLIP_BIT;
-
-	return ov9282_write_reg(ov9282, OV9282_REG_TIMING_FORMAT_2, 1,
-				current_val);
-}
-
-static int ov9282_set_ctrl_vflip(struct ov9282 *ov9282, int value)
-{
-	u32 current_val;
-	int ret = ov9282_read_reg(ov9282, OV9282_REG_TIMING_FORMAT_1, 1,
-				  &current_val);
-	if (ret)
-		return ret;
-
-	if (value)
-		current_val |= OV9282_FLIP_BIT;
-	else
-		current_val &= ~OV9282_FLIP_BIT;
-
-	return ov9282_write_reg(ov9282, OV9282_REG_TIMING_FORMAT_1, 1,
-				current_val);
-}
-
-static int ov9282_set_ctrl_flash_strobe_oe(struct ov9282 *ov9282, bool enable)
-{
-	u32 current_val;
-	int ret;
-
-	ret = ov9282_read_reg(ov9282, OV9282_REG_OUTPUT_ENABLE6, 1, &current_val);
-	if (ret)
-		return ret;
-
-	if (enable)
-		current_val |= OV9282_OUTPUT_ENABLE6_STROBE;
-	else
-		current_val &= ~OV9282_OUTPUT_ENABLE6_STROBE;
-
-	return ov9282_write_reg(ov9282, OV9282_REG_OUTPUT_ENABLE6, 1, current_val);
+	return ret ? ret : ret_hold;
 }
 
 static u32 ov9282_us_to_flash_duration(struct ov9282 *ov9282, u32 value)
@@ -740,30 +587,6 @@ static u32 ov9282_flash_duration_to_us(struct ov9282 *ov9282, u32 value)
 	return DIV_ROUND_UP(value * frame_width, OV9282_STROBE_SPAN_FACTOR);
 }
 
-static int ov9282_set_ctrl_flash_duration(struct ov9282 *ov9282, u32 value)
-{
-	u32 val = ov9282_us_to_flash_duration(ov9282, value);
-	int ret;
-
-	ret = ov9282_write_reg(ov9282, OV9282_REG_STROBE_FRAME_SPAN, 1,
-			       (val >> 24) & 0xff);
-	if (ret)
-		return ret;
-
-	ret = ov9282_write_reg(ov9282, OV9282_REG_STROBE_FRAME_SPAN + 1, 1,
-			       (val >> 16) & 0xff);
-	if (ret)
-		return ret;
-
-	ret = ov9282_write_reg(ov9282, OV9282_REG_STROBE_FRAME_SPAN + 2, 1,
-			       (val >> 8) & 0xff);
-	if (ret)
-		return ret;
-
-	return ov9282_write_reg(ov9282, OV9282_REG_STROBE_FRAME_SPAN + 3, 1,
-				val & 0xff);
-}
-
 /**
  * ov9282_set_ctrl() - Set subdevice control
  * @ctrl: pointer to v4l2_ctrl structure
@@ -818,23 +641,27 @@ static int ov9282_set_ctrl(struct v4l2_ctrl *ctrl)
 		break;
 	case V4L2_CID_VBLANK:
 		lpfr = ov9282->vblank + ov9282->cur_mode->height;
-		ret = ov9282_write_reg(ov9282, OV9282_REG_LPFR, 2, lpfr);
+		ret = cci_write(ov9282->regmap, OV9282_REG_LPFR, lpfr, NULL);
 		break;
 	case V4L2_CID_HFLIP:
-		ret = ov9282_set_ctrl_hflip(ov9282, ctrl->val);
+		ret = cci_update_bits(ov9282->regmap, OV9282_REG_TIMING_FORMAT_2,
+				      OV9282_FLIP_BIT, ctrl->val ? OV9282_FLIP_BIT : 0, NULL);
 		break;
 	case V4L2_CID_VFLIP:
-		ret = ov9282_set_ctrl_vflip(ov9282, ctrl->val);
+		ret = cci_update_bits(ov9282->regmap, OV9282_REG_TIMING_FORMAT_1,
+				      OV9282_FLIP_BIT, ctrl->val ? OV9282_FLIP_BIT : 0, NULL);
 		break;
 	case V4L2_CID_HBLANK:
-		ret = ov9282_write_reg(ov9282, OV9282_REG_TIMING_HTS, 2,
-				       (ctrl->val + ov9282->cur_mode->width) >> 1);
+		ret = cci_write(ov9282->regmap, OV9282_REG_TIMING_HTS,
+				(ctrl->val + ov9282->cur_mode->width) >> 1, NULL);
 		break;
 	case V4L2_CID_FLASH_STROBE_OE:
-		ret = ov9282_set_ctrl_flash_strobe_oe(ov9282, ctrl->val);
+		ret = cci_update_bits(ov9282->regmap, OV9282_REG_OUTPUT_ENABLE6,
+				      OV9282_OUTPUT_ENABLE6_STROBE,
+				      ctrl->val ? OV9282_OUTPUT_ENABLE6_STROBE : 0, NULL);
 		break;
 	case V4L2_CID_FLASH_DURATION:
-		ret = ov9282_set_ctrl_flash_duration(ov9282, ctrl->val);
+		ret = cci_write(ov9282->regmap, OV9282_REG_STROBE_FRAME_SPAN, ctrl->val, NULL);
 		break;
 	default:
 		dev_err(ov9282->dev, "Invalid control %d", ctrl->id);
@@ -1114,7 +941,7 @@ static int ov9282_get_selection(struct v4l2_subdev *sd,
  */
 static int ov9282_start_streaming(struct ov9282 *ov9282)
 {
-	const struct ov9282_reg bitdepth_regs[2][2] = {
+	const struct reg_sequence bitdepth_regs[2][2] = {
 		{
 			{OV9282_REG_PLL_CTRL_0D, OV9282_PLL_CTRL_0D_RAW10},
 			{OV9282_REG_ANA_CORE_2, OV9282_ANA_CORE2_RAW10},
@@ -1128,15 +955,16 @@ static int ov9282_start_streaming(struct ov9282 *ov9282)
 	int ret;
 
 	/* Write common registers */
-	ret = ov9282_write_regs(ov9282, common_regs_list.regs,
-				common_regs_list.num_of_regs);
+	ret = regmap_multi_reg_write(ov9282->regmap, common_regs,
+				     ARRAY_SIZE(common_regs));
 	if (ret) {
 		dev_err(ov9282->dev, "fail to write common registers");
 		return ret;
 	}
 
 	bitdepth_index = ov9282->code == MEDIA_BUS_FMT_Y10_1X10 ? 0 : 1;
-	ret = ov9282_write_regs(ov9282, bitdepth_regs[bitdepth_index], 2);
+	ret = regmap_multi_reg_write(ov9282->regmap,
+				     bitdepth_regs[bitdepth_index], 2);
 	if (ret) {
 		dev_err(ov9282->dev, "fail to write bitdepth regs");
 		return ret;
@@ -1144,7 +972,8 @@ static int ov9282_start_streaming(struct ov9282 *ov9282)
 
 	/* Write sensor mode registers */
 	reg_list = &ov9282->cur_mode->reg_list;
-	ret = ov9282_write_regs(ov9282, reg_list->regs, reg_list->num_of_regs);
+	ret = regmap_multi_reg_write(ov9282->regmap, reg_list->regs,
+				     reg_list->num_of_regs);
 	if (ret) {
 		dev_err(ov9282->dev, "fail to write initial registers");
 		return ret;
@@ -1158,8 +987,8 @@ static int ov9282_start_streaming(struct ov9282 *ov9282)
 	}
 
 	/* Start streaming */
-	ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT,
-			       1, OV9282_MODE_STREAMING);
+	ret = cci_write(ov9282->regmap, OV9282_REG_MODE_SELECT,
+			OV9282_MODE_STREAMING, NULL);
 	if (ret) {
 		dev_err(ov9282->dev, "fail to start streaming");
 		return ret;
@@ -1176,8 +1005,8 @@ static int ov9282_start_streaming(struct ov9282 *ov9282)
  */
 static int ov9282_stop_streaming(struct ov9282 *ov9282)
 {
-	return ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT,
-				1, OV9282_MODE_STANDBY);
+	return cci_write(ov9282->regmap, OV9282_REG_MODE_SELECT,
+			 OV9282_MODE_STANDBY, NULL);
 }
 
 /**
@@ -1228,14 +1057,14 @@ static int ov9282_set_stream(struct v4l2_subdev *sd, int enable)
 static int ov9282_detect(struct ov9282 *ov9282)
 {
 	int ret;
-	u32 val;
+	u64 val;
 
-	ret = ov9282_read_reg(ov9282, OV9282_REG_ID, 2, &val);
+	ret = cci_read(ov9282->regmap, OV9282_REG_ID, &val, NULL);
 	if (ret)
 		return ret;
 
 	if (val != OV9282_ID) {
-		dev_err(ov9282->dev, "chip id mismatch: %x!=%x",
+		dev_err(ov9282->dev, "chip id mismatch: %x!=%llx",
 			OV9282_ID, val);
 		return -ENXIO;
 	}
@@ -1397,9 +1226,8 @@ static int ov9282_power_on(struct device *dev)
 
 	usleep_range(400, 600);
 
-	ret = ov9282_write_reg(ov9282, OV9282_REG_MIPI_CTRL00, 1,
-			       ov9282->noncontinuous_clock ?
-					OV9282_GATED_CLOCK : 0);
+	ret = cci_write(ov9282->regmap, OV9282_REG_MIPI_CTRL00,
+			ov9282->noncontinuous_clock ? OV9282_GATED_CLOCK : 0, NULL);
 	if (ret) {
 		dev_err(ov9282->dev, "fail to write MIPI_CTRL00");
 		goto error_clk;
@@ -1576,6 +1404,11 @@ static int ov9282_probe(struct i2c_client *client)
 		return ret;
 	}
 
+	ov9282->regmap = devm_cci_regmap_init_i2c(client, 16);
+	if (IS_ERR(ov9282->regmap))
+		return dev_err_probe(ov9282->dev, PTR_ERR(ov9282->regmap),
+				     "Failed to init CCI\n");
+
 	mutex_init(&ov9282->mutex);
 
 	ret = ov9282_power_on(ov9282->dev);
-- 
2.43.0
Re: [PATCH v3 1/3] media: i2c: ov9282: Convert to CCI register access helpers
Posted by Dave Stevenson 1 month, 1 week ago
Hi Xiaolei

Thanks for the patch

On Tue, 3 Mar 2026 at 10:50, Xiaolei Wang <xiaolei.wang@windriver.com> wrote:
>
> Use the new common CCI register access helpers to replace the private
> register access helpers in the ov9282 driver. This simplifies the driver
> by reducing the amount of code.
>
> Signed-off-by: Xiaolei Wang <xiaolei.wang@windriver.com>
> Reviewed-by: Tarang Raval <tarang.raval@siliconsignals.io>
> ---
>  drivers/media/i2c/Kconfig  |   1 +
>  drivers/media/i2c/ov9282.c | 293 ++++++++-----------------------------
>  2 files changed, 64 insertions(+), 230 deletions(-)
>
> diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
> index 5eb1e0e0a87a..3027e71fd8fb 100644
> --- a/drivers/media/i2c/Kconfig
> +++ b/drivers/media/i2c/Kconfig
> @@ -690,6 +690,7 @@ config VIDEO_OV8865
>  config VIDEO_OV9282
>         tristate "OmniVision OV9282 sensor support"
>         depends on OF_GPIO
> +       select V4L2_CCI_I2C
>         help
>           This is a Video4Linux2 sensor driver for the OmniVision
>           OV9282 camera sensor.
> diff --git a/drivers/media/i2c/ov9282.c b/drivers/media/i2c/ov9282.c
> index ded9b2044ff8..8bfaa3ae4be5 100644
> --- a/drivers/media/i2c/ov9282.c
> +++ b/drivers/media/i2c/ov9282.c
> @@ -12,38 +12,40 @@
>  #include <linux/math.h>
>  #include <linux/module.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/regmap.h>
>  #include <linux/regulator/consumer.h>
>
> +#include <media/v4l2-cci.h>
>  #include <media/v4l2-ctrls.h>
>  #include <media/v4l2-event.h>
>  #include <media/v4l2-fwnode.h>
>  #include <media/v4l2-subdev.h>
>
>  /* Streaming Mode */
> -#define OV9282_REG_MODE_SELECT 0x0100
> +#define OV9282_REG_MODE_SELECT CCI_REG8(0x0100)
>  #define OV9282_MODE_STANDBY    0x00
>  #define OV9282_MODE_STREAMING  0x01
>
> -#define OV9282_REG_PLL_CTRL_0D 0x030d
> +#define OV9282_REG_PLL_CTRL_0D CCI_REG8(0x030d)
>  #define OV9282_PLL_CTRL_0D_RAW8                0x60
>  #define OV9282_PLL_CTRL_0D_RAW10       0x50
>
> -#define OV9282_REG_TIMING_HTS  0x380c
> +#define OV9282_REG_TIMING_HTS  CCI_REG16(0x380c)
>  #define OV9282_TIMING_HTS_MAX  0x7fff
>
>  /* Lines per frame */
> -#define OV9282_REG_LPFR                0x380e
> +#define OV9282_REG_LPFR                CCI_REG16(0x380e)
>
>  /* Chip ID */
> -#define OV9282_REG_ID          0x300a
> +#define OV9282_REG_ID          CCI_REG16(0x300a)
>  #define OV9282_ID              0x9281
>
>  /* Output enable registers */
> -#define OV9282_REG_OUTPUT_ENABLE4      0x3004
> +#define OV9282_REG_OUTPUT_ENABLE4      CCI_REG8(0x3004)
>  #define OV9282_OUTPUT_ENABLE4_GPIO2    BIT(1)
>  #define OV9282_OUTPUT_ENABLE4_D9       BIT(0)
>
> -#define OV9282_REG_OUTPUT_ENABLE5      0x3005
> +#define OV9282_REG_OUTPUT_ENABLE5      CCI_REG8(0x3005)
>  #define OV9282_OUTPUT_ENABLE5_D8       BIT(7)
>  #define OV9282_OUTPUT_ENABLE5_D7       BIT(6)
>  #define OV9282_OUTPUT_ENABLE5_D6       BIT(5)
> @@ -53,7 +55,7 @@
>  #define OV9282_OUTPUT_ENABLE5_D2       BIT(1)
>  #define OV9282_OUTPUT_ENABLE5_D1       BIT(0)
>
> -#define OV9282_REG_OUTPUT_ENABLE6      0x3006
> +#define OV9282_REG_OUTPUT_ENABLE6      CCI_REG8(0x3006)
>  #define OV9282_OUTPUT_ENABLE6_D0       BIT(7)
>  #define OV9282_OUTPUT_ENABLE6_PCLK     BIT(6)
>  #define OV9282_OUTPUT_ENABLE6_HREF     BIT(5)
> @@ -62,14 +64,14 @@
>  #define OV9282_OUTPUT_ENABLE6_VSYNC    BIT(1)
>
>  /* Exposure control */
> -#define OV9282_REG_EXPOSURE    0x3500
> +#define OV9282_REG_EXPOSURE    CCI_REG24(0x3500)
>  #define OV9282_EXPOSURE_MIN    1
>  #define OV9282_EXPOSURE_OFFSET 25
>  #define OV9282_EXPOSURE_STEP   1
>  #define OV9282_EXPOSURE_DEFAULT        0x0282
>
>  /* AEC/AGC manual */
> -#define OV9282_REG_AEC_MANUAL          0x3503
> +#define OV9282_REG_AEC_MANUAL          CCI_REG8(0x3503)
>  #define OV9282_DIGFRAC_GAIN_DELAY      BIT(6)
>  #define OV9282_GAIN_CHANGE_DELAY       BIT(5)
>  #define OV9282_GAIN_DELAY              BIT(4)
> @@ -78,28 +80,28 @@
>  #define OV9282_AEC_MANUAL_DEFAULT      0x00
>
>  /* Analog gain control */
> -#define OV9282_REG_AGAIN       0x3509
> +#define OV9282_REG_AGAIN       CCI_REG8(0x3509)
>  #define OV9282_AGAIN_MIN       0x10
>  #define OV9282_AGAIN_MAX       0xff
>  #define OV9282_AGAIN_STEP      1
>  #define OV9282_AGAIN_DEFAULT   0x10
>
>  /* Group hold register */
> -#define OV9282_REG_HOLD                0x3308
> +#define OV9282_REG_HOLD                CCI_REG8(0x3308)
>
> -#define OV9282_REG_ANA_CORE_2  0x3662
> +#define OV9282_REG_ANA_CORE_2  CCI_REG8(0x3662)
>  #define OV9282_ANA_CORE2_RAW8  0x07
>  #define OV9282_ANA_CORE2_RAW10 0x05
>
> -#define OV9282_REG_TIMING_FORMAT_1     0x3820
> -#define OV9282_REG_TIMING_FORMAT_2     0x3821
> +#define OV9282_REG_TIMING_FORMAT_1     CCI_REG8(0x3820)
> +#define OV9282_REG_TIMING_FORMAT_2     CCI_REG8(0x3821)
>  #define OV9282_FLIP_BIT                        BIT(2)
>
> -#define OV9282_REG_MIPI_CTRL00 0x4800
> +#define OV9282_REG_MIPI_CTRL00 CCI_REG8(0x4800)
>  #define OV9282_GATED_CLOCK     BIT(5)
>
>  /* Flash/Strobe control registers */
> -#define OV9282_REG_STROBE_FRAME_SPAN           0x3925
> +#define OV9282_REG_STROBE_FRAME_SPAN           CCI_REG32(0x3925)
>  #define OV9282_STROBE_FRAME_SPAN_DEFAULT       0x0000001a
>
>  /* Input clock rate */
> @@ -139,16 +141,6 @@ static const char * const ov9282_supply_names[] = {
>
>  #define OV9282_NUM_SUPPLIES ARRAY_SIZE(ov9282_supply_names)
>
> -/**
> - * struct ov9282_reg - ov9282 sensor register
> - * @address: Register address
> - * @val: Register value
> - */
> -struct ov9282_reg {
> -       u16 address;
> -       u8 val;
> -};
> -
>  /**
>   * struct ov9282_reg_list - ov9282 sensor register list
>   * @num_of_regs: Number of registers in the list
> @@ -156,7 +148,7 @@ struct ov9282_reg {
>   */
>  struct ov9282_reg_list {
>         u32 num_of_regs;
> -       const struct ov9282_reg *regs;
> +       const struct reg_sequence *regs;
>  };
>
>  /**
> @@ -188,6 +180,7 @@ struct ov9282_mode {
>   * struct ov9282 - ov9282 sensor device structure
>   * @dev: Pointer to generic device
>   * @sd: V4L2 sub-device
> + * @regmap: Regmap for sensor register access
>   * @pad: Media pad. Only one pad supported
>   * @reset_gpio: Sensor reset gpio
>   * @inclk: Sensor input clock
> @@ -209,6 +202,7 @@ struct ov9282_mode {
>  struct ov9282 {
>         struct device *dev;
>         struct v4l2_subdev sd;
> +       struct regmap *regmap;
>         struct media_pad pad;
>         struct gpio_desc *reset_gpio;
>         struct clk *inclk;
> @@ -241,7 +235,7 @@ static const s64 link_freq[] = {
>   * register arrays as some settings are written as part of ov9282_power_on,
>   * and the reset will clear them.
>   */
> -static const struct ov9282_reg common_regs[] = {
> +static const struct reg_sequence common_regs[] = {
>         {0x0302, 0x32},
>         {0x030e, 0x02},
>         {0x3001, 0x00},
> @@ -305,11 +299,6 @@ static const struct ov9282_reg common_regs[] = {
>         {0x5a08, 0x84},
>  };
>
> -static struct ov9282_reg_list common_regs_list = {
> -       .num_of_regs = ARRAY_SIZE(common_regs),
> -       .regs = common_regs,
> -};
> -
>  #define MODE_1280_800          0
>  #define MODE_1280_720          1
>  #define MODE_640_400           2
> @@ -317,7 +306,7 @@ static struct ov9282_reg_list common_regs_list = {
>  #define DEFAULT_MODE           MODE_1280_720
>
>  /* Sensor mode registers */
> -static const struct ov9282_reg mode_1280x800_regs[] = {
> +static const struct reg_sequence mode_1280x800_regs[] = {
>         {0x3778, 0x00},
>         {0x3800, 0x00},
>         {0x3801, 0x00},

You changed OV9282_REG_TIMING_FORMAT_[12] above to
CCI_REG8(0x382[01]). However it is used in this array of type
reg_sequence, but all the other values are still using non-CCI_REGx
register writes here.

If converting to CCI_REGx then you at least need to be consistent.
Personally I'd say do it everywhere and use cci_multi_reg_write
instead of regmap_multi_reg_write.

> @@ -348,7 +337,7 @@ static const struct ov9282_reg mode_1280x800_regs[] = {
>         {0x4509, 0x00},
>  };
>
> -static const struct ov9282_reg mode_1280x720_regs[] = {
> +static const struct reg_sequence mode_1280x720_regs[] = {
>         {0x3778, 0x00},
>         {0x3800, 0x00},
>         {0x3801, 0x00},
> @@ -379,7 +368,7 @@ static const struct ov9282_reg mode_1280x720_regs[] = {
>         {0x4509, 0x80},
>  };
>
> -static const struct ov9282_reg mode_640x400_regs[] = {
> +static const struct reg_sequence mode_640x400_regs[] = {
>         {0x3778, 0x10},
>         {0x3800, 0x00},
>         {0x3801, 0x00},
> @@ -485,97 +474,6 @@ static inline struct ov9282 *to_ov9282(struct v4l2_subdev *subdev)
>         return container_of(subdev, struct ov9282, sd);
>  }
>
> -/**
> - * ov9282_read_reg() - Read registers.
> - * @ov9282: pointer to ov9282 device
> - * @reg: register address
> - * @len: length of bytes to read. Max supported bytes is 4
> - * @val: pointer to register value to be filled.
> - *
> - * Return: 0 if successful, error code otherwise.
> - */
> -static int ov9282_read_reg(struct ov9282 *ov9282, u16 reg, u32 len, u32 *val)
> -{
> -       struct i2c_client *client = v4l2_get_subdevdata(&ov9282->sd);
> -       struct i2c_msg msgs[2] = {0};
> -       u8 addr_buf[2] = {0};
> -       u8 data_buf[4] = {0};
> -       int ret;
> -
> -       if (WARN_ON(len > 4))
> -               return -EINVAL;
> -
> -       put_unaligned_be16(reg, addr_buf);
> -
> -       /* Write register address */
> -       msgs[0].addr = client->addr;
> -       msgs[0].flags = 0;
> -       msgs[0].len = ARRAY_SIZE(addr_buf);
> -       msgs[0].buf = addr_buf;
> -
> -       /* Read data from register */
> -       msgs[1].addr = client->addr;
> -       msgs[1].flags = I2C_M_RD;
> -       msgs[1].len = len;
> -       msgs[1].buf = &data_buf[4 - len];
> -
> -       ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
> -       if (ret != ARRAY_SIZE(msgs))
> -               return -EIO;
> -
> -       *val = get_unaligned_be32(data_buf);
> -
> -       return 0;
> -}
> -
> -/**
> - * ov9282_write_reg() - Write register
> - * @ov9282: pointer to ov9282 device
> - * @reg: register address
> - * @len: length of bytes. Max supported bytes is 4
> - * @val: register value
> - *
> - * Return: 0 if successful, error code otherwise.
> - */
> -static int ov9282_write_reg(struct ov9282 *ov9282, u16 reg, u32 len, u32 val)
> -{
> -       struct i2c_client *client = v4l2_get_subdevdata(&ov9282->sd);
> -       u8 buf[6] = {0};
> -
> -       if (WARN_ON(len > 4))
> -               return -EINVAL;
> -
> -       put_unaligned_be16(reg, buf);
> -       put_unaligned_be32(val << (8 * (4 - len)), buf + 2);
> -       if (i2c_master_send(client, buf, len + 2) != len + 2)
> -               return -EIO;
> -
> -       return 0;
> -}
> -
> -/**
> - * ov9282_write_regs() - Write a list of registers
> - * @ov9282: pointer to ov9282 device
> - * @regs: list of registers to be written
> - * @len: length of registers array
> - *
> - * Return: 0 if successful, error code otherwise.
> - */
> -static int ov9282_write_regs(struct ov9282 *ov9282,
> -                            const struct ov9282_reg *regs, u32 len)
> -{
> -       unsigned int i;
> -       int ret;
> -
> -       for (i = 0; i < len; i++) {
> -               ret = ov9282_write_reg(ov9282, regs[i].address, 1, regs[i].val);
> -               if (ret)
> -                       return ret;
> -       }
> -
> -       return 0;
> -}
> -
>  /**
>   * ov9282_update_controls() - Update control ranges based on streaming mode
>   * @ov9282: pointer to ov9282 device
> @@ -639,15 +537,15 @@ static int ov9282_update_exp_gain(struct ov9282 *ov9282, u32 exposure, u32 gain)
>         dev_dbg(ov9282->dev, "Set exp %u (~%u us), analog gain %u",
>                 exposure, exposure_us, gain);
>
> -       ret = ov9282_write_reg(ov9282, OV9282_REG_HOLD, 1, 1);
> +       ret = cci_write(ov9282->regmap, OV9282_REG_HOLD, 0x01, NULL);
>         if (ret)
>                 return ret;
>
> -       ret = ov9282_write_reg(ov9282, OV9282_REG_EXPOSURE, 3, exposure << 4);
> +       ret = cci_write(ov9282->regmap, OV9282_REG_EXPOSURE, exposure << 4, NULL);
>         if (ret)
>                 goto error_release_group_hold;
>
> -       ret = ov9282_write_reg(ov9282, OV9282_REG_AGAIN, 1, gain);
> +       ret = cci_write(ov9282->regmap, OV9282_REG_AGAIN, gain, NULL);
>         if (ret)
>                 goto error_release_group_hold;
>
> @@ -656,60 +554,9 @@ static int ov9282_update_exp_gain(struct ov9282 *ov9282, u32 exposure, u32 gain)
>                                        OV9282_STROBE_FRAME_SPAN_DEFAULT);
>
>  error_release_group_hold:
> -       ov9282_write_reg(ov9282, OV9282_REG_HOLD, 1, 0);
> -
> -       return ret;
> -}
> -
> -static int ov9282_set_ctrl_hflip(struct ov9282 *ov9282, int value)
> -{
> -       u32 current_val;
> -       int ret = ov9282_read_reg(ov9282, OV9282_REG_TIMING_FORMAT_2, 1,
> -                                 &current_val);
> -       if (ret)
> -               return ret;
> +       int ret_hold = cci_write(ov9282->regmap, OV9282_REG_HOLD, 0, NULL);
>
> -       if (value)
> -               current_val |= OV9282_FLIP_BIT;
> -       else
> -               current_val &= ~OV9282_FLIP_BIT;
> -
> -       return ov9282_write_reg(ov9282, OV9282_REG_TIMING_FORMAT_2, 1,
> -                               current_val);
> -}
> -
> -static int ov9282_set_ctrl_vflip(struct ov9282 *ov9282, int value)
> -{
> -       u32 current_val;
> -       int ret = ov9282_read_reg(ov9282, OV9282_REG_TIMING_FORMAT_1, 1,
> -                                 &current_val);
> -       if (ret)
> -               return ret;
> -
> -       if (value)
> -               current_val |= OV9282_FLIP_BIT;
> -       else
> -               current_val &= ~OV9282_FLIP_BIT;
> -
> -       return ov9282_write_reg(ov9282, OV9282_REG_TIMING_FORMAT_1, 1,
> -                               current_val);
> -}
> -
> -static int ov9282_set_ctrl_flash_strobe_oe(struct ov9282 *ov9282, bool enable)
> -{
> -       u32 current_val;
> -       int ret;
> -
> -       ret = ov9282_read_reg(ov9282, OV9282_REG_OUTPUT_ENABLE6, 1, &current_val);
> -       if (ret)
> -               return ret;
> -
> -       if (enable)
> -               current_val |= OV9282_OUTPUT_ENABLE6_STROBE;
> -       else
> -               current_val &= ~OV9282_OUTPUT_ENABLE6_STROBE;
> -
> -       return ov9282_write_reg(ov9282, OV9282_REG_OUTPUT_ENABLE6, 1, current_val);
> +       return ret ? ret : ret_hold;
>  }
>
>  static u32 ov9282_us_to_flash_duration(struct ov9282 *ov9282, u32 value)
> @@ -740,30 +587,6 @@ static u32 ov9282_flash_duration_to_us(struct ov9282 *ov9282, u32 value)
>         return DIV_ROUND_UP(value * frame_width, OV9282_STROBE_SPAN_FACTOR);
>  }
>
> -static int ov9282_set_ctrl_flash_duration(struct ov9282 *ov9282, u32 value)
> -{
> -       u32 val = ov9282_us_to_flash_duration(ov9282, value);
> -       int ret;
> -
> -       ret = ov9282_write_reg(ov9282, OV9282_REG_STROBE_FRAME_SPAN, 1,
> -                              (val >> 24) & 0xff);
> -       if (ret)
> -               return ret;
> -
> -       ret = ov9282_write_reg(ov9282, OV9282_REG_STROBE_FRAME_SPAN + 1, 1,
> -                              (val >> 16) & 0xff);
> -       if (ret)
> -               return ret;
> -
> -       ret = ov9282_write_reg(ov9282, OV9282_REG_STROBE_FRAME_SPAN + 2, 1,
> -                              (val >> 8) & 0xff);
> -       if (ret)
> -               return ret;
> -
> -       return ov9282_write_reg(ov9282, OV9282_REG_STROBE_FRAME_SPAN + 3, 1,
> -                               val & 0xff);
> -}
> -
>  /**
>   * ov9282_set_ctrl() - Set subdevice control
>   * @ctrl: pointer to v4l2_ctrl structure
> @@ -818,23 +641,27 @@ static int ov9282_set_ctrl(struct v4l2_ctrl *ctrl)
>                 break;
>         case V4L2_CID_VBLANK:
>                 lpfr = ov9282->vblank + ov9282->cur_mode->height;
> -               ret = ov9282_write_reg(ov9282, OV9282_REG_LPFR, 2, lpfr);
> +               ret = cci_write(ov9282->regmap, OV9282_REG_LPFR, lpfr, NULL);
>                 break;
>         case V4L2_CID_HFLIP:
> -               ret = ov9282_set_ctrl_hflip(ov9282, ctrl->val);
> +               ret = cci_update_bits(ov9282->regmap, OV9282_REG_TIMING_FORMAT_2,
> +                                     OV9282_FLIP_BIT, ctrl->val ? OV9282_FLIP_BIT : 0, NULL);
>                 break;
>         case V4L2_CID_VFLIP:
> -               ret = ov9282_set_ctrl_vflip(ov9282, ctrl->val);
> +               ret = cci_update_bits(ov9282->regmap, OV9282_REG_TIMING_FORMAT_1,
> +                                     OV9282_FLIP_BIT, ctrl->val ? OV9282_FLIP_BIT : 0, NULL);
>                 break;
>         case V4L2_CID_HBLANK:
> -               ret = ov9282_write_reg(ov9282, OV9282_REG_TIMING_HTS, 2,
> -                                      (ctrl->val + ov9282->cur_mode->width) >> 1);
> +               ret = cci_write(ov9282->regmap, OV9282_REG_TIMING_HTS,
> +                               (ctrl->val + ov9282->cur_mode->width) >> 1, NULL);
>                 break;
>         case V4L2_CID_FLASH_STROBE_OE:
> -               ret = ov9282_set_ctrl_flash_strobe_oe(ov9282, ctrl->val);
> +               ret = cci_update_bits(ov9282->regmap, OV9282_REG_OUTPUT_ENABLE6,
> +                                     OV9282_OUTPUT_ENABLE6_STROBE,
> +                                     ctrl->val ? OV9282_OUTPUT_ENABLE6_STROBE : 0, NULL);
>                 break;
>         case V4L2_CID_FLASH_DURATION:
> -               ret = ov9282_set_ctrl_flash_duration(ov9282, ctrl->val);
> +               ret = cci_write(ov9282->regmap, OV9282_REG_STROBE_FRAME_SPAN, ctrl->val, NULL);
>                 break;
>         default:
>                 dev_err(ov9282->dev, "Invalid control %d", ctrl->id);
> @@ -1114,7 +941,7 @@ static int ov9282_get_selection(struct v4l2_subdev *sd,
>   */
>  static int ov9282_start_streaming(struct ov9282 *ov9282)
>  {
> -       const struct ov9282_reg bitdepth_regs[2][2] = {
> +       const struct reg_sequence bitdepth_regs[2][2] = {
>                 {
>                         {OV9282_REG_PLL_CTRL_0D, OV9282_PLL_CTRL_0D_RAW10},
>                         {OV9282_REG_ANA_CORE_2, OV9282_ANA_CORE2_RAW10},

Here is a more obvious example. You have CCI_REGx() register defines
being stored into a reg_sequence.
That's an obvious one for the array to be struct cci_reg_sequence and
use cci_multi_reg_write().

Otherwise the patch looks reasonable.

  Dave

> @@ -1128,15 +955,16 @@ static int ov9282_start_streaming(struct ov9282 *ov9282)
>         int ret;
>
>         /* Write common registers */
> -       ret = ov9282_write_regs(ov9282, common_regs_list.regs,
> -                               common_regs_list.num_of_regs);
> +       ret = regmap_multi_reg_write(ov9282->regmap, common_regs,
> +                                    ARRAY_SIZE(common_regs));
>         if (ret) {
>                 dev_err(ov9282->dev, "fail to write common registers");
>                 return ret;
>         }
>
>         bitdepth_index = ov9282->code == MEDIA_BUS_FMT_Y10_1X10 ? 0 : 1;
> -       ret = ov9282_write_regs(ov9282, bitdepth_regs[bitdepth_index], 2);
> +       ret = regmap_multi_reg_write(ov9282->regmap,
> +                                    bitdepth_regs[bitdepth_index], 2);
>         if (ret) {
>                 dev_err(ov9282->dev, "fail to write bitdepth regs");
>                 return ret;
> @@ -1144,7 +972,8 @@ static int ov9282_start_streaming(struct ov9282 *ov9282)
>
>         /* Write sensor mode registers */
>         reg_list = &ov9282->cur_mode->reg_list;
> -       ret = ov9282_write_regs(ov9282, reg_list->regs, reg_list->num_of_regs);
> +       ret = regmap_multi_reg_write(ov9282->regmap, reg_list->regs,
> +                                    reg_list->num_of_regs);
>         if (ret) {
>                 dev_err(ov9282->dev, "fail to write initial registers");
>                 return ret;
> @@ -1158,8 +987,8 @@ static int ov9282_start_streaming(struct ov9282 *ov9282)
>         }
>
>         /* Start streaming */
> -       ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT,
> -                              1, OV9282_MODE_STREAMING);
> +       ret = cci_write(ov9282->regmap, OV9282_REG_MODE_SELECT,
> +                       OV9282_MODE_STREAMING, NULL);
>         if (ret) {
>                 dev_err(ov9282->dev, "fail to start streaming");
>                 return ret;
> @@ -1176,8 +1005,8 @@ static int ov9282_start_streaming(struct ov9282 *ov9282)
>   */
>  static int ov9282_stop_streaming(struct ov9282 *ov9282)
>  {
> -       return ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT,
> -                               1, OV9282_MODE_STANDBY);
> +       return cci_write(ov9282->regmap, OV9282_REG_MODE_SELECT,
> +                        OV9282_MODE_STANDBY, NULL);
>  }
>
>  /**
> @@ -1228,14 +1057,14 @@ static int ov9282_set_stream(struct v4l2_subdev *sd, int enable)
>  static int ov9282_detect(struct ov9282 *ov9282)
>  {
>         int ret;
> -       u32 val;
> +       u64 val;
>
> -       ret = ov9282_read_reg(ov9282, OV9282_REG_ID, 2, &val);
> +       ret = cci_read(ov9282->regmap, OV9282_REG_ID, &val, NULL);
>         if (ret)
>                 return ret;
>
>         if (val != OV9282_ID) {
> -               dev_err(ov9282->dev, "chip id mismatch: %x!=%x",
> +               dev_err(ov9282->dev, "chip id mismatch: %x!=%llx",
>                         OV9282_ID, val);
>                 return -ENXIO;
>         }
> @@ -1397,9 +1226,8 @@ static int ov9282_power_on(struct device *dev)
>
>         usleep_range(400, 600);
>
> -       ret = ov9282_write_reg(ov9282, OV9282_REG_MIPI_CTRL00, 1,
> -                              ov9282->noncontinuous_clock ?
> -                                       OV9282_GATED_CLOCK : 0);
> +       ret = cci_write(ov9282->regmap, OV9282_REG_MIPI_CTRL00,
> +                       ov9282->noncontinuous_clock ? OV9282_GATED_CLOCK : 0, NULL);
>         if (ret) {
>                 dev_err(ov9282->dev, "fail to write MIPI_CTRL00");
>                 goto error_clk;
> @@ -1576,6 +1404,11 @@ static int ov9282_probe(struct i2c_client *client)
>                 return ret;
>         }
>
> +       ov9282->regmap = devm_cci_regmap_init_i2c(client, 16);
> +       if (IS_ERR(ov9282->regmap))
> +               return dev_err_probe(ov9282->dev, PTR_ERR(ov9282->regmap),
> +                                    "Failed to init CCI\n");
> +
>         mutex_init(&ov9282->mutex);
>
>         ret = ov9282_power_on(ov9282->dev);
> --
> 2.43.0
>
Re: [PATCH v3 1/3] media: i2c: ov9282: Convert to CCI register access helpers
Posted by xiaolei wang 1 month ago
Hi Dave,

Thanks for the review

On 3/3/26 20:51, Dave Stevenson wrote:
> CAUTION: This email comes from a non Wind River email account!
> Do not click links or open attachments unless you recognize the sender and know the content is safe.
>
> Hi Xiaolei
>
> Thanks for the patch
>
> On Tue, 3 Mar 2026 at 10:50, Xiaolei Wang <xiaolei.wang@windriver.com> wrote:
>> Use the new common CCI register access helpers to replace the private
>> register access helpers in the ov9282 driver. This simplifies the driver
>> by reducing the amount of code.
>>
>> Signed-off-by: Xiaolei Wang <xiaolei.wang@windriver.com>
>> Reviewed-by: Tarang Raval <tarang.raval@siliconsignals.io>
>> ---
>>   drivers/media/i2c/Kconfig  |   1 +
>>   drivers/media/i2c/ov9282.c | 293 ++++++++-----------------------------
>>   2 files changed, 64 insertions(+), 230 deletions(-)
>>
>> diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
>> index 5eb1e0e0a87a..3027e71fd8fb 100644
>> --- a/drivers/media/i2c/Kconfig
>> +++ b/drivers/media/i2c/Kconfig
>> @@ -690,6 +690,7 @@ config VIDEO_OV8865
>>   config VIDEO_OV9282
>>          tristate "OmniVision OV9282 sensor support"
>>          depends on OF_GPIO
>> +       select V4L2_CCI_I2C
>>          help
>>            This is a Video4Linux2 sensor driver for the OmniVision
>>            OV9282 camera sensor.
>> diff --git a/drivers/media/i2c/ov9282.c b/drivers/media/i2c/ov9282.c
>> index ded9b2044ff8..8bfaa3ae4be5 100644
>> --- a/drivers/media/i2c/ov9282.c
>> +++ b/drivers/media/i2c/ov9282.c
>> @@ -12,38 +12,40 @@
>>   #include <linux/math.h>
>>   #include <linux/module.h>
>>   #include <linux/pm_runtime.h>
>> +#include <linux/regmap.h>
>>   #include <linux/regulator/consumer.h>
>>
>> +#include <media/v4l2-cci.h>
>>   #include <media/v4l2-ctrls.h>
>>   #include <media/v4l2-event.h>
>>   #include <media/v4l2-fwnode.h>
>>   #include <media/v4l2-subdev.h>
>>
>>   /* Streaming Mode */
>> -#define OV9282_REG_MODE_SELECT 0x0100
>> +#define OV9282_REG_MODE_SELECT CCI_REG8(0x0100)
>>   #define OV9282_MODE_STANDBY    0x00
>>   #define OV9282_MODE_STREAMING  0x01
>>
>> -#define OV9282_REG_PLL_CTRL_0D 0x030d
>> +#define OV9282_REG_PLL_CTRL_0D CCI_REG8(0x030d)
>>   #define OV9282_PLL_CTRL_0D_RAW8                0x60
>>   #define OV9282_PLL_CTRL_0D_RAW10       0x50
>>
>> -#define OV9282_REG_TIMING_HTS  0x380c
>> +#define OV9282_REG_TIMING_HTS  CCI_REG16(0x380c)
>>   #define OV9282_TIMING_HTS_MAX  0x7fff
>>
>>   /* Lines per frame */
>> -#define OV9282_REG_LPFR                0x380e
>> +#define OV9282_REG_LPFR                CCI_REG16(0x380e)
>>
>>   /* Chip ID */
>> -#define OV9282_REG_ID          0x300a
>> +#define OV9282_REG_ID          CCI_REG16(0x300a)
>>   #define OV9282_ID              0x9281
>>
>>   /* Output enable registers */
>> -#define OV9282_REG_OUTPUT_ENABLE4      0x3004
>> +#define OV9282_REG_OUTPUT_ENABLE4      CCI_REG8(0x3004)
>>   #define OV9282_OUTPUT_ENABLE4_GPIO2    BIT(1)
>>   #define OV9282_OUTPUT_ENABLE4_D9       BIT(0)
>>
>> -#define OV9282_REG_OUTPUT_ENABLE5      0x3005
>> +#define OV9282_REG_OUTPUT_ENABLE5      CCI_REG8(0x3005)
>>   #define OV9282_OUTPUT_ENABLE5_D8       BIT(7)
>>   #define OV9282_OUTPUT_ENABLE5_D7       BIT(6)
>>   #define OV9282_OUTPUT_ENABLE5_D6       BIT(5)
>> @@ -53,7 +55,7 @@
>>   #define OV9282_OUTPUT_ENABLE5_D2       BIT(1)
>>   #define OV9282_OUTPUT_ENABLE5_D1       BIT(0)
>>
>> -#define OV9282_REG_OUTPUT_ENABLE6      0x3006
>> +#define OV9282_REG_OUTPUT_ENABLE6      CCI_REG8(0x3006)
>>   #define OV9282_OUTPUT_ENABLE6_D0       BIT(7)
>>   #define OV9282_OUTPUT_ENABLE6_PCLK     BIT(6)
>>   #define OV9282_OUTPUT_ENABLE6_HREF     BIT(5)
>> @@ -62,14 +64,14 @@
>>   #define OV9282_OUTPUT_ENABLE6_VSYNC    BIT(1)
>>
>>   /* Exposure control */
>> -#define OV9282_REG_EXPOSURE    0x3500
>> +#define OV9282_REG_EXPOSURE    CCI_REG24(0x3500)
>>   #define OV9282_EXPOSURE_MIN    1
>>   #define OV9282_EXPOSURE_OFFSET 25
>>   #define OV9282_EXPOSURE_STEP   1
>>   #define OV9282_EXPOSURE_DEFAULT        0x0282
>>
>>   /* AEC/AGC manual */
>> -#define OV9282_REG_AEC_MANUAL          0x3503
>> +#define OV9282_REG_AEC_MANUAL          CCI_REG8(0x3503)
>>   #define OV9282_DIGFRAC_GAIN_DELAY      BIT(6)
>>   #define OV9282_GAIN_CHANGE_DELAY       BIT(5)
>>   #define OV9282_GAIN_DELAY              BIT(4)
>> @@ -78,28 +80,28 @@
>>   #define OV9282_AEC_MANUAL_DEFAULT      0x00
>>
>>   /* Analog gain control */
>> -#define OV9282_REG_AGAIN       0x3509
>> +#define OV9282_REG_AGAIN       CCI_REG8(0x3509)
>>   #define OV9282_AGAIN_MIN       0x10
>>   #define OV9282_AGAIN_MAX       0xff
>>   #define OV9282_AGAIN_STEP      1
>>   #define OV9282_AGAIN_DEFAULT   0x10
>>
>>   /* Group hold register */
>> -#define OV9282_REG_HOLD                0x3308
>> +#define OV9282_REG_HOLD                CCI_REG8(0x3308)
>>
>> -#define OV9282_REG_ANA_CORE_2  0x3662
>> +#define OV9282_REG_ANA_CORE_2  CCI_REG8(0x3662)
>>   #define OV9282_ANA_CORE2_RAW8  0x07
>>   #define OV9282_ANA_CORE2_RAW10 0x05
>>
>> -#define OV9282_REG_TIMING_FORMAT_1     0x3820
>> -#define OV9282_REG_TIMING_FORMAT_2     0x3821
>> +#define OV9282_REG_TIMING_FORMAT_1     CCI_REG8(0x3820)
>> +#define OV9282_REG_TIMING_FORMAT_2     CCI_REG8(0x3821)
>>   #define OV9282_FLIP_BIT                        BIT(2)
>>
>> -#define OV9282_REG_MIPI_CTRL00 0x4800
>> +#define OV9282_REG_MIPI_CTRL00 CCI_REG8(0x4800)
>>   #define OV9282_GATED_CLOCK     BIT(5)
>>
>>   /* Flash/Strobe control registers */
>> -#define OV9282_REG_STROBE_FRAME_SPAN           0x3925
>> +#define OV9282_REG_STROBE_FRAME_SPAN           CCI_REG32(0x3925)
>>   #define OV9282_STROBE_FRAME_SPAN_DEFAULT       0x0000001a
>>
>>   /* Input clock rate */
>> @@ -139,16 +141,6 @@ static const char * const ov9282_supply_names[] = {
>>
>>   #define OV9282_NUM_SUPPLIES ARRAY_SIZE(ov9282_supply_names)
>>
>> -/**
>> - * struct ov9282_reg - ov9282 sensor register
>> - * @address: Register address
>> - * @val: Register value
>> - */
>> -struct ov9282_reg {
>> -       u16 address;
>> -       u8 val;
>> -};
>> -
>>   /**
>>    * struct ov9282_reg_list - ov9282 sensor register list
>>    * @num_of_regs: Number of registers in the list
>> @@ -156,7 +148,7 @@ struct ov9282_reg {
>>    */
>>   struct ov9282_reg_list {
>>          u32 num_of_regs;
>> -       const struct ov9282_reg *regs;
>> +       const struct reg_sequence *regs;
>>   };
>>
>>   /**
>> @@ -188,6 +180,7 @@ struct ov9282_mode {
>>    * struct ov9282 - ov9282 sensor device structure
>>    * @dev: Pointer to generic device
>>    * @sd: V4L2 sub-device
>> + * @regmap: Regmap for sensor register access
>>    * @pad: Media pad. Only one pad supported
>>    * @reset_gpio: Sensor reset gpio
>>    * @inclk: Sensor input clock
>> @@ -209,6 +202,7 @@ struct ov9282_mode {
>>   struct ov9282 {
>>          struct device *dev;
>>          struct v4l2_subdev sd;
>> +       struct regmap *regmap;
>>          struct media_pad pad;
>>          struct gpio_desc *reset_gpio;
>>          struct clk *inclk;
>> @@ -241,7 +235,7 @@ static const s64 link_freq[] = {
>>    * register arrays as some settings are written as part of ov9282_power_on,
>>    * and the reset will clear them.
>>    */
>> -static const struct ov9282_reg common_regs[] = {
>> +static const struct reg_sequence common_regs[] = {
>>          {0x0302, 0x32},
>>          {0x030e, 0x02},
>>          {0x3001, 0x00},
>> @@ -305,11 +299,6 @@ static const struct ov9282_reg common_regs[] = {
>>          {0x5a08, 0x84},
>>   };
>>
>> -static struct ov9282_reg_list common_regs_list = {
>> -       .num_of_regs = ARRAY_SIZE(common_regs),
>> -       .regs = common_regs,
>> -};
>> -
>>   #define MODE_1280_800          0
>>   #define MODE_1280_720          1
>>   #define MODE_640_400           2
>> @@ -317,7 +306,7 @@ static struct ov9282_reg_list common_regs_list = {
>>   #define DEFAULT_MODE           MODE_1280_720
>>
>>   /* Sensor mode registers */
>> -static const struct ov9282_reg mode_1280x800_regs[] = {
>> +static const struct reg_sequence mode_1280x800_regs[] = {
>>          {0x3778, 0x00},
>>          {0x3800, 0x00},
>>          {0x3801, 0x00},
> You changed OV9282_REG_TIMING_FORMAT_[12] above to
> CCI_REG8(0x382[01]). However it is used in this array of type
> reg_sequence, but all the other values are still using non-CCI_REGx
> register writes here.
>
> If converting to CCI_REGx then you at least need to be consistent.
> Personally I'd say do it everywhere and use cci_multi_reg_write
> instead of regmap_multi_reg_write.
Thanks for pointing it out, it is indeed a bit confusing, I overlooked 
that.
>
>> @@ -348,7 +337,7 @@ static const struct ov9282_reg mode_1280x800_regs[] = {
>>          {0x4509, 0x00},
>>   };
>>
>> -static const struct ov9282_reg mode_1280x720_regs[] = {
>> +static const struct reg_sequence mode_1280x720_regs[] = {
>>          {0x3778, 0x00},
>>          {0x3800, 0x00},
>>          {0x3801, 0x00},
>> @@ -379,7 +368,7 @@ static const struct ov9282_reg mode_1280x720_regs[] = {
>>          {0x4509, 0x80},
>>   };
>>
>> -static const struct ov9282_reg mode_640x400_regs[] = {
>> +static const struct reg_sequence mode_640x400_regs[] = {
>>          {0x3778, 0x10},
>>          {0x3800, 0x00},
>>          {0x3801, 0x00},
>> @@ -485,97 +474,6 @@ static inline struct ov9282 *to_ov9282(struct v4l2_subdev *subdev)
>>          return container_of(subdev, struct ov9282, sd);
>>   }
>>
>> -/**
>> - * ov9282_read_reg() - Read registers.
>> - * @ov9282: pointer to ov9282 device
>> - * @reg: register address
>> - * @len: length of bytes to read. Max supported bytes is 4
>> - * @val: pointer to register value to be filled.
>> - *
>> - * Return: 0 if successful, error code otherwise.
>> - */
>> -static int ov9282_read_reg(struct ov9282 *ov9282, u16 reg, u32 len, u32 *val)
>> -{
>> -       struct i2c_client *client = v4l2_get_subdevdata(&ov9282->sd);
>> -       struct i2c_msg msgs[2] = {0};
>> -       u8 addr_buf[2] = {0};
>> -       u8 data_buf[4] = {0};
>> -       int ret;
>> -
>> -       if (WARN_ON(len > 4))
>> -               return -EINVAL;
>> -
>> -       put_unaligned_be16(reg, addr_buf);
>> -
>> -       /* Write register address */
>> -       msgs[0].addr = client->addr;
>> -       msgs[0].flags = 0;
>> -       msgs[0].len = ARRAY_SIZE(addr_buf);
>> -       msgs[0].buf = addr_buf;
>> -
>> -       /* Read data from register */
>> -       msgs[1].addr = client->addr;
>> -       msgs[1].flags = I2C_M_RD;
>> -       msgs[1].len = len;
>> -       msgs[1].buf = &data_buf[4 - len];
>> -
>> -       ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
>> -       if (ret != ARRAY_SIZE(msgs))
>> -               return -EIO;
>> -
>> -       *val = get_unaligned_be32(data_buf);
>> -
>> -       return 0;
>> -}
>> -
>> -/**
>> - * ov9282_write_reg() - Write register
>> - * @ov9282: pointer to ov9282 device
>> - * @reg: register address
>> - * @len: length of bytes. Max supported bytes is 4
>> - * @val: register value
>> - *
>> - * Return: 0 if successful, error code otherwise.
>> - */
>> -static int ov9282_write_reg(struct ov9282 *ov9282, u16 reg, u32 len, u32 val)
>> -{
>> -       struct i2c_client *client = v4l2_get_subdevdata(&ov9282->sd);
>> -       u8 buf[6] = {0};
>> -
>> -       if (WARN_ON(len > 4))
>> -               return -EINVAL;
>> -
>> -       put_unaligned_be16(reg, buf);
>> -       put_unaligned_be32(val << (8 * (4 - len)), buf + 2);
>> -       if (i2c_master_send(client, buf, len + 2) != len + 2)
>> -               return -EIO;
>> -
>> -       return 0;
>> -}
>> -
>> -/**
>> - * ov9282_write_regs() - Write a list of registers
>> - * @ov9282: pointer to ov9282 device
>> - * @regs: list of registers to be written
>> - * @len: length of registers array
>> - *
>> - * Return: 0 if successful, error code otherwise.
>> - */
>> -static int ov9282_write_regs(struct ov9282 *ov9282,
>> -                            const struct ov9282_reg *regs, u32 len)
>> -{
>> -       unsigned int i;
>> -       int ret;
>> -
>> -       for (i = 0; i < len; i++) {
>> -               ret = ov9282_write_reg(ov9282, regs[i].address, 1, regs[i].val);
>> -               if (ret)
>> -                       return ret;
>> -       }
>> -
>> -       return 0;
>> -}
>> -
>>   /**
>>    * ov9282_update_controls() - Update control ranges based on streaming mode
>>    * @ov9282: pointer to ov9282 device
>> @@ -639,15 +537,15 @@ static int ov9282_update_exp_gain(struct ov9282 *ov9282, u32 exposure, u32 gain)
>>          dev_dbg(ov9282->dev, "Set exp %u (~%u us), analog gain %u",
>>                  exposure, exposure_us, gain);
>>
>> -       ret = ov9282_write_reg(ov9282, OV9282_REG_HOLD, 1, 1);
>> +       ret = cci_write(ov9282->regmap, OV9282_REG_HOLD, 0x01, NULL);
>>          if (ret)
>>                  return ret;
>>
>> -       ret = ov9282_write_reg(ov9282, OV9282_REG_EXPOSURE, 3, exposure << 4);
>> +       ret = cci_write(ov9282->regmap, OV9282_REG_EXPOSURE, exposure << 4, NULL);
>>          if (ret)
>>                  goto error_release_group_hold;
>>
>> -       ret = ov9282_write_reg(ov9282, OV9282_REG_AGAIN, 1, gain);
>> +       ret = cci_write(ov9282->regmap, OV9282_REG_AGAIN, gain, NULL);
>>          if (ret)
>>                  goto error_release_group_hold;
>>
>> @@ -656,60 +554,9 @@ static int ov9282_update_exp_gain(struct ov9282 *ov9282, u32 exposure, u32 gain)
>>                                         OV9282_STROBE_FRAME_SPAN_DEFAULT);
>>
>>   error_release_group_hold:
>> -       ov9282_write_reg(ov9282, OV9282_REG_HOLD, 1, 0);
>> -
>> -       return ret;
>> -}
>> -
>> -static int ov9282_set_ctrl_hflip(struct ov9282 *ov9282, int value)
>> -{
>> -       u32 current_val;
>> -       int ret = ov9282_read_reg(ov9282, OV9282_REG_TIMING_FORMAT_2, 1,
>> -                                 &current_val);
>> -       if (ret)
>> -               return ret;
>> +       int ret_hold = cci_write(ov9282->regmap, OV9282_REG_HOLD, 0, NULL);
>>
>> -       if (value)
>> -               current_val |= OV9282_FLIP_BIT;
>> -       else
>> -               current_val &= ~OV9282_FLIP_BIT;
>> -
>> -       return ov9282_write_reg(ov9282, OV9282_REG_TIMING_FORMAT_2, 1,
>> -                               current_val);
>> -}
>> -
>> -static int ov9282_set_ctrl_vflip(struct ov9282 *ov9282, int value)
>> -{
>> -       u32 current_val;
>> -       int ret = ov9282_read_reg(ov9282, OV9282_REG_TIMING_FORMAT_1, 1,
>> -                                 &current_val);
>> -       if (ret)
>> -               return ret;
>> -
>> -       if (value)
>> -               current_val |= OV9282_FLIP_BIT;
>> -       else
>> -               current_val &= ~OV9282_FLIP_BIT;
>> -
>> -       return ov9282_write_reg(ov9282, OV9282_REG_TIMING_FORMAT_1, 1,
>> -                               current_val);
>> -}
>> -
>> -static int ov9282_set_ctrl_flash_strobe_oe(struct ov9282 *ov9282, bool enable)
>> -{
>> -       u32 current_val;
>> -       int ret;
>> -
>> -       ret = ov9282_read_reg(ov9282, OV9282_REG_OUTPUT_ENABLE6, 1, &current_val);
>> -       if (ret)
>> -               return ret;
>> -
>> -       if (enable)
>> -               current_val |= OV9282_OUTPUT_ENABLE6_STROBE;
>> -       else
>> -               current_val &= ~OV9282_OUTPUT_ENABLE6_STROBE;
>> -
>> -       return ov9282_write_reg(ov9282, OV9282_REG_OUTPUT_ENABLE6, 1, current_val);
>> +       return ret ? ret : ret_hold;
>>   }
>>
>>   static u32 ov9282_us_to_flash_duration(struct ov9282 *ov9282, u32 value)
>> @@ -740,30 +587,6 @@ static u32 ov9282_flash_duration_to_us(struct ov9282 *ov9282, u32 value)
>>          return DIV_ROUND_UP(value * frame_width, OV9282_STROBE_SPAN_FACTOR);
>>   }
>>
>> -static int ov9282_set_ctrl_flash_duration(struct ov9282 *ov9282, u32 value)
>> -{
>> -       u32 val = ov9282_us_to_flash_duration(ov9282, value);
>> -       int ret;
>> -
>> -       ret = ov9282_write_reg(ov9282, OV9282_REG_STROBE_FRAME_SPAN, 1,
>> -                              (val >> 24) & 0xff);
>> -       if (ret)
>> -               return ret;
>> -
>> -       ret = ov9282_write_reg(ov9282, OV9282_REG_STROBE_FRAME_SPAN + 1, 1,
>> -                              (val >> 16) & 0xff);
>> -       if (ret)
>> -               return ret;
>> -
>> -       ret = ov9282_write_reg(ov9282, OV9282_REG_STROBE_FRAME_SPAN + 2, 1,
>> -                              (val >> 8) & 0xff);
>> -       if (ret)
>> -               return ret;
>> -
>> -       return ov9282_write_reg(ov9282, OV9282_REG_STROBE_FRAME_SPAN + 3, 1,
>> -                               val & 0xff);
>> -}
>> -
>>   /**
>>    * ov9282_set_ctrl() - Set subdevice control
>>    * @ctrl: pointer to v4l2_ctrl structure
>> @@ -818,23 +641,27 @@ static int ov9282_set_ctrl(struct v4l2_ctrl *ctrl)
>>                  break;
>>          case V4L2_CID_VBLANK:
>>                  lpfr = ov9282->vblank + ov9282->cur_mode->height;
>> -               ret = ov9282_write_reg(ov9282, OV9282_REG_LPFR, 2, lpfr);
>> +               ret = cci_write(ov9282->regmap, OV9282_REG_LPFR, lpfr, NULL);
>>                  break;
>>          case V4L2_CID_HFLIP:
>> -               ret = ov9282_set_ctrl_hflip(ov9282, ctrl->val);
>> +               ret = cci_update_bits(ov9282->regmap, OV9282_REG_TIMING_FORMAT_2,
>> +                                     OV9282_FLIP_BIT, ctrl->val ? OV9282_FLIP_BIT : 0, NULL);
>>                  break;
>>          case V4L2_CID_VFLIP:
>> -               ret = ov9282_set_ctrl_vflip(ov9282, ctrl->val);
>> +               ret = cci_update_bits(ov9282->regmap, OV9282_REG_TIMING_FORMAT_1,
>> +                                     OV9282_FLIP_BIT, ctrl->val ? OV9282_FLIP_BIT : 0, NULL);
>>                  break;
>>          case V4L2_CID_HBLANK:
>> -               ret = ov9282_write_reg(ov9282, OV9282_REG_TIMING_HTS, 2,
>> -                                      (ctrl->val + ov9282->cur_mode->width) >> 1);
>> +               ret = cci_write(ov9282->regmap, OV9282_REG_TIMING_HTS,
>> +                               (ctrl->val + ov9282->cur_mode->width) >> 1, NULL);
>>                  break;
>>          case V4L2_CID_FLASH_STROBE_OE:
>> -               ret = ov9282_set_ctrl_flash_strobe_oe(ov9282, ctrl->val);
>> +               ret = cci_update_bits(ov9282->regmap, OV9282_REG_OUTPUT_ENABLE6,
>> +                                     OV9282_OUTPUT_ENABLE6_STROBE,
>> +                                     ctrl->val ? OV9282_OUTPUT_ENABLE6_STROBE : 0, NULL);
>>                  break;
>>          case V4L2_CID_FLASH_DURATION:
>> -               ret = ov9282_set_ctrl_flash_duration(ov9282, ctrl->val);
>> +               ret = cci_write(ov9282->regmap, OV9282_REG_STROBE_FRAME_SPAN, ctrl->val, NULL);
>>                  break;
>>          default:
>>                  dev_err(ov9282->dev, "Invalid control %d", ctrl->id);
>> @@ -1114,7 +941,7 @@ static int ov9282_get_selection(struct v4l2_subdev *sd,
>>    */
>>   static int ov9282_start_streaming(struct ov9282 *ov9282)
>>   {
>> -       const struct ov9282_reg bitdepth_regs[2][2] = {
>> +       const struct reg_sequence bitdepth_regs[2][2] = {
>>                  {
>>                          {OV9282_REG_PLL_CTRL_0D, OV9282_PLL_CTRL_0D_RAW10},
>>                          {OV9282_REG_ANA_CORE_2, OV9282_ANA_CORE2_RAW10},
> Here is a more obvious example. You have CCI_REGx() register defines
> being stored into a reg_sequence.
> That's an obvious one for the array to be struct cci_reg_sequence and
> use cci_multi_reg_write().
>
> Otherwise the patch looks reasonable.

I will use cci_multi_reg_write() instead of regmap_multi_reg_write() in

the next version.

thanks

xiaolei

>
>    Dave
>
>> @@ -1128,15 +955,16 @@ static int ov9282_start_streaming(struct ov9282 *ov9282)
>>          int ret;
>>
>>          /* Write common registers */
>> -       ret = ov9282_write_regs(ov9282, common_regs_list.regs,
>> -                               common_regs_list.num_of_regs);
>> +       ret = regmap_multi_reg_write(ov9282->regmap, common_regs,
>> +                                    ARRAY_SIZE(common_regs));
>>          if (ret) {
>>                  dev_err(ov9282->dev, "fail to write common registers");
>>                  return ret;
>>          }
>>
>>          bitdepth_index = ov9282->code == MEDIA_BUS_FMT_Y10_1X10 ? 0 : 1;
>> -       ret = ov9282_write_regs(ov9282, bitdepth_regs[bitdepth_index], 2);
>> +       ret = regmap_multi_reg_write(ov9282->regmap,
>> +                                    bitdepth_regs[bitdepth_index], 2);
>>          if (ret) {
>>                  dev_err(ov9282->dev, "fail to write bitdepth regs");
>>                  return ret;
>> @@ -1144,7 +972,8 @@ static int ov9282_start_streaming(struct ov9282 *ov9282)
>>
>>          /* Write sensor mode registers */
>>          reg_list = &ov9282->cur_mode->reg_list;
>> -       ret = ov9282_write_regs(ov9282, reg_list->regs, reg_list->num_of_regs);
>> +       ret = regmap_multi_reg_write(ov9282->regmap, reg_list->regs,
>> +                                    reg_list->num_of_regs);
>>          if (ret) {
>>                  dev_err(ov9282->dev, "fail to write initial registers");
>>                  return ret;
>> @@ -1158,8 +987,8 @@ static int ov9282_start_streaming(struct ov9282 *ov9282)
>>          }
>>
>>          /* Start streaming */
>> -       ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT,
>> -                              1, OV9282_MODE_STREAMING);
>> +       ret = cci_write(ov9282->regmap, OV9282_REG_MODE_SELECT,
>> +                       OV9282_MODE_STREAMING, NULL);
>>          if (ret) {
>>                  dev_err(ov9282->dev, "fail to start streaming");
>>                  return ret;
>> @@ -1176,8 +1005,8 @@ static int ov9282_start_streaming(struct ov9282 *ov9282)
>>    */
>>   static int ov9282_stop_streaming(struct ov9282 *ov9282)
>>   {
>> -       return ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT,
>> -                               1, OV9282_MODE_STANDBY);
>> +       return cci_write(ov9282->regmap, OV9282_REG_MODE_SELECT,
>> +                        OV9282_MODE_STANDBY, NULL);
>>   }
>>
>>   /**
>> @@ -1228,14 +1057,14 @@ static int ov9282_set_stream(struct v4l2_subdev *sd, int enable)
>>   static int ov9282_detect(struct ov9282 *ov9282)
>>   {
>>          int ret;
>> -       u32 val;
>> +       u64 val;
>>
>> -       ret = ov9282_read_reg(ov9282, OV9282_REG_ID, 2, &val);
>> +       ret = cci_read(ov9282->regmap, OV9282_REG_ID, &val, NULL);
>>          if (ret)
>>                  return ret;
>>
>>          if (val != OV9282_ID) {
>> -               dev_err(ov9282->dev, "chip id mismatch: %x!=%x",
>> +               dev_err(ov9282->dev, "chip id mismatch: %x!=%llx",
>>                          OV9282_ID, val);
>>                  return -ENXIO;
>>          }
>> @@ -1397,9 +1226,8 @@ static int ov9282_power_on(struct device *dev)
>>
>>          usleep_range(400, 600);
>>
>> -       ret = ov9282_write_reg(ov9282, OV9282_REG_MIPI_CTRL00, 1,
>> -                              ov9282->noncontinuous_clock ?
>> -                                       OV9282_GATED_CLOCK : 0);
>> +       ret = cci_write(ov9282->regmap, OV9282_REG_MIPI_CTRL00,
>> +                       ov9282->noncontinuous_clock ? OV9282_GATED_CLOCK : 0, NULL);
>>          if (ret) {
>>                  dev_err(ov9282->dev, "fail to write MIPI_CTRL00");
>>                  goto error_clk;
>> @@ -1576,6 +1404,11 @@ static int ov9282_probe(struct i2c_client *client)
>>                  return ret;
>>          }
>>
>> +       ov9282->regmap = devm_cci_regmap_init_i2c(client, 16);
>> +       if (IS_ERR(ov9282->regmap))
>> +               return dev_err_probe(ov9282->dev, PTR_ERR(ov9282->regmap),
>> +                                    "Failed to init CCI\n");
>> +
>>          mutex_init(&ov9282->mutex);
>>
>>          ret = ov9282_power_on(ov9282->dev);
>> --
>> 2.43.0
>>