[PATCH 1/3] media: i2c: ov9282: Convert to CCI register access helpers
From: Xiaolei Wang
Date: Sat Feb 28 2026 - 03:39:32 EST
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@xxxxxxxxxxxxx>
---
drivers/media/i2c/Kconfig | 1 +
drivers/media/i2c/ov9282.c | 290 ++++++++-----------------------------
2 files changed, 62 insertions(+), 229 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..75e41a0f588e 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;
};
/**
@@ -209,6 +201,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 +234,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 +298,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 +305,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 +336,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 +367,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 +473,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 +536,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,62 +553,11 @@ 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);
+ cci_write(ov9282->regmap, OV9282_REG_HOLD, 0, NULL);
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,
- ¤t_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_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,
- ¤t_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, ¤t_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);
-}
-
static u32 ov9282_us_to_flash_duration(struct ov9282 *ov9282, u32 value)
{
/*
@@ -740,30 +586,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 +640,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 +940,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 +954,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 +971,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 +986,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 +1004,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 +1056,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 +1225,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 +1403,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