From 50b52b6d420e85f86a579ea197b569b31bc6de43 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 14 Oct 2025 19:40:16 +0200 Subject: [PATCH] media: i2c: ov01a10: Convert to new CCI register access helpers Use the new comon CCI register access helpers to replace the private register access helpers in the ov01a10 driver. Signed-off-by: Hans de Goede Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/i2c/Kconfig | 1 + drivers/media/i2c/ov01a10.c | 219 ++++++++++-------------------------- 2 files changed, 59 insertions(+), 161 deletions(-) diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 6dcae0aa98ee4..3121c0d947cdc 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -383,6 +383,7 @@ config VIDEO_OS05B10 config VIDEO_OV01A10 tristate "OmniVision OV01A10 sensor support" + select V4L2_CCI_I2C help This is a Video4Linux2 sensor driver for the OmniVision OV01A10 camera. diff --git a/drivers/media/i2c/ov01a10.c b/drivers/media/i2c/ov01a10.c index 4f04bb8688b8b..34b7ab6eb286d 100644 --- a/drivers/media/i2c/ov01a10.c +++ b/drivers/media/i2c/ov01a10.c @@ -10,7 +10,9 @@ #include #include #include +#include +#include #include #include #include @@ -19,10 +21,10 @@ #define OV01A10_SCLK 80000000LL #define OV01A10_DATA_LANES 1 -#define OV01A10_REG_CHIP_ID 0x300a +#define OV01A10_REG_CHIP_ID CCI_REG24(0x300a) #define OV01A10_CHIP_ID 0x560141 -#define OV01A10_REG_MODE_SELECT 0x0100 +#define OV01A10_REG_MODE_SELECT CCI_REG8(0x0100) #define OV01A10_MODE_STANDBY 0x00 #define OV01A10_MODE_STREAMING 0x01 @@ -33,47 +35,47 @@ #define OV01A10_ACITVE_HEIGHT 800 /* vertical and horizontal timings */ -#define OV01A10_REG_VTS 0x380e +#define OV01A10_REG_VTS CCI_REG16(0x380e) #define OV01A10_VTS_DEF 0x0700 #define OV01A10_VTS_MIN 0x0380 #define OV01A10_VTS_MAX 0xffff #define OV01A10_HTS_DEF 1488 /* exposure controls */ -#define OV01A10_REG_EXPOSURE 0x3501 +#define OV01A10_REG_EXPOSURE CCI_REG16(0x3501) #define OV01A10_EXPOSURE_MIN 4 #define OV01A10_EXPOSURE_MAX_MARGIN 8 #define OV01A10_EXPOSURE_STEP 1 /* analog gain controls */ -#define OV01A10_REG_ANALOG_GAIN 0x3508 +#define OV01A10_REG_ANALOG_GAIN CCI_REG16(0x3508) #define OV01A10_ANAL_GAIN_MIN 0x100 #define OV01A10_ANAL_GAIN_MAX 0x3fff #define OV01A10_ANAL_GAIN_STEP 1 /* digital gain controls */ -#define OV01A10_REG_DIGITAL_GAIN_B 0x350a -#define OV01A10_REG_DIGITAL_GAIN_GB 0x3510 -#define OV01A10_REG_DIGITAL_GAIN_GR 0x3513 -#define OV01A10_REG_DIGITAL_GAIN_R 0x3516 +#define OV01A10_REG_DIGITAL_GAIN_B CCI_REG24(0x350a) +#define OV01A10_REG_DIGITAL_GAIN_GB CCI_REG24(0x3510) +#define OV01A10_REG_DIGITAL_GAIN_GR CCI_REG24(0x3513) +#define OV01A10_REG_DIGITAL_GAIN_R CCI_REG24(0x3516) #define OV01A10_DGTL_GAIN_MIN 0 #define OV01A10_DGTL_GAIN_MAX 0x3ffff #define OV01A10_DGTL_GAIN_STEP 1 #define OV01A10_DGTL_GAIN_DEFAULT 1024 /* test pattern control */ -#define OV01A10_REG_TEST_PATTERN 0x4503 +#define OV01A10_REG_TEST_PATTERN CCI_REG8(0x4503) #define OV01A10_TEST_PATTERN_ENABLE BIT(7) #define OV01A10_LINK_FREQ_400MHZ_INDEX 0 /* flip and mirror control */ -#define OV01A10_REG_FORMAT1 0x3820 +#define OV01A10_REG_FORMAT1 CCI_REG8(0x3820) #define OV01A10_VFLIP_MASK BIT(4) #define OV01A10_HFLIP_MASK BIT(3) /* window offset */ -#define OV01A10_REG_X_WIN 0x3811 -#define OV01A10_REG_Y_WIN 0x3813 +#define OV01A10_REG_X_WIN CCI_REG16(0x3810) +#define OV01A10_REG_Y_WIN CCI_REG16(0x3812) /* * The native ov01a10 bayer-pattern is GBRG, but there was a driver bug enabling @@ -84,14 +86,9 @@ */ #define OV01A10_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR10_1X10 -struct ov01a10_reg { - u16 address; - u8 val; -}; - struct ov01a10_reg_list { u32 num_of_regs; - const struct ov01a10_reg *regs; + const struct reg_sequence *regs; }; struct ov01a10_link_freq_config { @@ -109,7 +106,7 @@ struct ov01a10_mode { const struct ov01a10_reg_list reg_list; }; -static const struct ov01a10_reg mipi_data_rate_720mbps[] = { +static const struct reg_sequence mipi_data_rate_720mbps[] = { {0x0103, 0x01}, {0x0302, 0x00}, {0x0303, 0x06}, @@ -125,7 +122,7 @@ static const struct ov01a10_reg mipi_data_rate_720mbps[] = { {0x0325, 0x68}, }; -static const struct ov01a10_reg sensor_1280x800_setting[] = { +static const struct reg_sequence sensor_1280x800_setting[] = { {0x3002, 0xa1}, {0x301e, 0xf0}, {0x3022, 0x01}, @@ -282,6 +279,7 @@ static const struct ov01a10_mode supported_modes[] = { }; struct ov01a10 { + struct regmap *regmap; struct v4l2_subdev sd; struct media_pad pad; struct v4l2_ctrl_handler ctrl_handler; @@ -301,104 +299,15 @@ static inline struct ov01a10 *to_ov01a10(struct v4l2_subdev *subdev) return container_of(subdev, struct ov01a10, sd); } -static int ov01a10_read_reg(struct ov01a10 *ov01a10, u16 reg, u16 len, u32 *val) -{ - struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); - struct i2c_msg msgs[2]; - u8 addr_buf[2]; - u8 data_buf[4] = {0}; - int ret = 0; - - if (len > sizeof(data_buf)) - return -EINVAL; - - put_unaligned_be16(reg, addr_buf); - msgs[0].addr = client->addr; - msgs[0].flags = 0; - msgs[0].len = sizeof(addr_buf); - msgs[0].buf = addr_buf; - msgs[1].addr = client->addr; - msgs[1].flags = I2C_M_RD; - msgs[1].len = len; - msgs[1].buf = &data_buf[sizeof(data_buf) - len]; - - ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); - - if (ret != ARRAY_SIZE(msgs)) - return ret < 0 ? ret : -EIO; - - *val = get_unaligned_be32(data_buf); - - return 0; -} - -static int ov01a10_write_reg(struct ov01a10 *ov01a10, u16 reg, u16 len, u32 val) -{ - struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); - u8 buf[6]; - int ret = 0; - - if (len > 4) - return -EINVAL; - - put_unaligned_be16(reg, buf); - put_unaligned_be32(val << 8 * (4 - len), buf + 2); - - ret = i2c_master_send(client, buf, len + 2); - if (ret != len + 2) - return ret < 0 ? ret : -EIO; - - return 0; -} - -static int ov01a10_write_reg_list(struct ov01a10 *ov01a10, - const struct ov01a10_reg_list *r_list) -{ - struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); - unsigned int i; - int ret = 0; - - for (i = 0; i < r_list->num_of_regs; i++) { - ret = ov01a10_write_reg(ov01a10, r_list->regs[i].address, 1, - r_list->regs[i].val); - if (ret) { - dev_err_ratelimited(&client->dev, - "write reg 0x%4.4x err = %d\n", - r_list->regs[i].address, ret); - return ret; - } - } - - return 0; -} - static int ov01a10_update_digital_gain(struct ov01a10 *ov01a10, u32 d_gain) { - struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); u32 real = d_gain << 6; int ret = 0; - ret = ov01a10_write_reg(ov01a10, OV01A10_REG_DIGITAL_GAIN_B, 3, real); - if (ret) { - dev_err(&client->dev, "failed to set DIGITAL_GAIN_B\n"); - return ret; - } - - ret = ov01a10_write_reg(ov01a10, OV01A10_REG_DIGITAL_GAIN_GB, 3, real); - if (ret) { - dev_err(&client->dev, "failed to set DIGITAL_GAIN_GB\n"); - return ret; - } - - ret = ov01a10_write_reg(ov01a10, OV01A10_REG_DIGITAL_GAIN_GR, 3, real); - if (ret) { - dev_err(&client->dev, "failed to set DIGITAL_GAIN_GR\n"); - return ret; - } - - ret = ov01a10_write_reg(ov01a10, OV01A10_REG_DIGITAL_GAIN_R, 3, real); - if (ret) - dev_err(&client->dev, "failed to set DIGITAL_GAIN_R\n"); + cci_write(ov01a10->regmap, OV01A10_REG_DIGITAL_GAIN_B, real, &ret); + cci_write(ov01a10->regmap, OV01A10_REG_DIGITAL_GAIN_GB, real, &ret); + cci_write(ov01a10->regmap, OV01A10_REG_DIGITAL_GAIN_GR, real, &ret); + cci_write(ov01a10->regmap, OV01A10_REG_DIGITAL_GAIN_R, real, &ret); return ret; } @@ -408,48 +317,39 @@ static int ov01a10_test_pattern(struct ov01a10 *ov01a10, u32 pattern) if (pattern) pattern |= OV01A10_TEST_PATTERN_ENABLE; - return ov01a10_write_reg(ov01a10, OV01A10_REG_TEST_PATTERN, 1, pattern); + return cci_write(ov01a10->regmap, OV01A10_REG_TEST_PATTERN, pattern, + NULL); } /* for vflip and hflip, use 0x9 as window offset to keep the bayer */ static int ov01a10_set_hflip(struct ov01a10 *ov01a10, u32 hflip) { - int ret; u32 val, offset; + int ret = 0; offset = hflip ? 0x8 : 0x9; - ret = ov01a10_write_reg(ov01a10, OV01A10_REG_X_WIN, 1, offset); - if (ret) - return ret; + val = hflip ? 0 : FIELD_PREP(OV01A10_HFLIP_MASK, 0x1); - ret = ov01a10_read_reg(ov01a10, OV01A10_REG_FORMAT1, 1, &val); - if (ret) - return ret; + cci_write(ov01a10->regmap, OV01A10_REG_X_WIN, offset, &ret); + cci_update_bits(ov01a10->regmap, OV01A10_REG_FORMAT1, + OV01A10_HFLIP_MASK, val, &ret); - val = hflip ? val & ~OV01A10_HFLIP_MASK : - val | FIELD_PREP(OV01A10_HFLIP_MASK, 0x1); - - return ov01a10_write_reg(ov01a10, OV01A10_REG_FORMAT1, 1, val); + return ret; } static int ov01a10_set_vflip(struct ov01a10 *ov01a10, u32 vflip) { - int ret; u32 val, offset; + int ret = 0; offset = vflip ? 0x9 : 0x8; - ret = ov01a10_write_reg(ov01a10, OV01A10_REG_Y_WIN, 1, offset); - if (ret) - return ret; - - ret = ov01a10_read_reg(ov01a10, OV01A10_REG_FORMAT1, 1, &val); - if (ret) - return ret; + val = vflip ? FIELD_PREP(OV01A10_VFLIP_MASK, 0x1) : 0; - val = vflip ? val | FIELD_PREP(OV01A10_VFLIP_MASK, 0x1) : - val & ~OV01A10_VFLIP_MASK; + cci_write(ov01a10->regmap, OV01A10_REG_Y_WIN, offset, &ret); + cci_update_bits(ov01a10->regmap, OV01A10_REG_FORMAT1, + OV01A10_VFLIP_MASK, val, &ret); - return ov01a10_write_reg(ov01a10, OV01A10_REG_FORMAT1, 1, val); + return ret; } static int ov01a10_set_ctrl(struct v4l2_ctrl *ctrl) @@ -474,8 +374,8 @@ static int ov01a10_set_ctrl(struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_ANALOGUE_GAIN: - ret = ov01a10_write_reg(ov01a10, OV01A10_REG_ANALOG_GAIN, 2, - ctrl->val); + ret = cci_write(ov01a10->regmap, OV01A10_REG_ANALOG_GAIN, + ctrl->val, NULL); break; case V4L2_CID_DIGITAL_GAIN: @@ -483,13 +383,13 @@ static int ov01a10_set_ctrl(struct v4l2_ctrl *ctrl) break; case V4L2_CID_EXPOSURE: - ret = ov01a10_write_reg(ov01a10, OV01A10_REG_EXPOSURE, 2, - ctrl->val); + ret = cci_write(ov01a10->regmap, OV01A10_REG_EXPOSURE, + ctrl->val, NULL); break; case V4L2_CID_VBLANK: - ret = ov01a10_write_reg(ov01a10, OV01A10_REG_VTS, 2, - ov01a10->cur_mode->height + ctrl->val); + ret = cci_write(ov01a10->regmap, OV01A10_REG_VTS, + ov01a10->cur_mode->height + ctrl->val, NULL); break; case V4L2_CID_TEST_PATTERN: @@ -630,14 +530,16 @@ static int ov01a10_start_streaming(struct ov01a10 *ov01a10) link_freq_index = ov01a10->cur_mode->link_freq_index; reg_list = &link_freq_configs[link_freq_index].reg_list; - ret = ov01a10_write_reg_list(ov01a10, reg_list); + ret = regmap_multi_reg_write(ov01a10->regmap, reg_list->regs, + reg_list->num_of_regs); if (ret) { dev_err(&client->dev, "failed to set plls\n"); return ret; } reg_list = &ov01a10->cur_mode->reg_list; - ret = ov01a10_write_reg_list(ov01a10, reg_list); + ret = regmap_multi_reg_write(ov01a10->regmap, reg_list->regs, + reg_list->num_of_regs); if (ret) { dev_err(&client->dev, "failed to set mode\n"); return ret; @@ -647,23 +549,14 @@ static int ov01a10_start_streaming(struct ov01a10 *ov01a10) if (ret) return ret; - ret = ov01a10_write_reg(ov01a10, OV01A10_REG_MODE_SELECT, 1, - OV01A10_MODE_STREAMING); - if (ret) - dev_err(&client->dev, "failed to start streaming\n"); - - return ret; + return cci_write(ov01a10->regmap, OV01A10_REG_MODE_SELECT, + OV01A10_MODE_STREAMING, NULL); } static void ov01a10_stop_streaming(struct ov01a10 *ov01a10) { - struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); - int ret = 0; - - ret = ov01a10_write_reg(ov01a10, OV01A10_REG_MODE_SELECT, 1, - OV01A10_MODE_STANDBY); - if (ret) - dev_err(&client->dev, "failed to stop streaming\n"); + cci_write(ov01a10->regmap, OV01A10_REG_MODE_SELECT, + OV01A10_MODE_STANDBY, NULL); } static int ov01a10_set_stream(struct v4l2_subdev *sd, int enable) @@ -841,14 +734,14 @@ static int ov01a10_identify_module(struct ov01a10 *ov01a10) { struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); int ret; - u32 val; + u64 val; - ret = ov01a10_read_reg(ov01a10, OV01A10_REG_CHIP_ID, 3, &val); + ret = cci_read(ov01a10->regmap, OV01A10_REG_CHIP_ID, &val, NULL); if (ret) return ret; if (val != OV01A10_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x\n", + dev_err(&client->dev, "chip id mismatch: %x!=%llx\n", OV01A10_CHIP_ID, val); return -EIO; } @@ -879,6 +772,10 @@ static int ov01a10_probe(struct i2c_client *client) if (!ov01a10) return -ENOMEM; + ov01a10->regmap = devm_cci_regmap_init_i2c(client, 16); + if (IS_ERR(ov01a10->regmap)) + return PTR_ERR(ov01a10->regmap); + v4l2_i2c_subdev_init(&ov01a10->sd, client, &ov01a10_subdev_ops); ov01a10->sd.internal_ops = &ov01a10_internal_ops; -- 2.47.3