media: i2c: imx219: Convert to CCI register access helpers
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Sun, 24 Sep 2023 15:32:50 +0000 (18:32 +0300)
committerHans Verkuil <hverkuil-cisco@xs4all.nl>
Sat, 7 Oct 2023 08:55:46 +0000 (10:55 +0200)
Use the new common CCI register access helpers to replace the private
register access helpers in the imx219 driver. This simplifies the driver
by reducing the amount of code.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
drivers/media/i2c/Kconfig
drivers/media/i2c/imx219.c

index 897d02f..59ee0ca 100644 (file)
@@ -99,6 +99,7 @@ config VIDEO_IMX214
 
 config VIDEO_IMX219
        tristate "Sony IMX219 sensor support"
+       select V4L2_CCI_I2C
        help
          This is a Video4Linux2 sensor driver for the Sony
          IMX219 camera.
index af29398..9d84f09 100644 (file)
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
+
+#include <media/v4l2-cci.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-event.h>
 #include <media/v4l2-fwnode.h>
 #include <media/v4l2-mediabus.h>
-#include <asm/unaligned.h>
 
-#define IMX219_REG_VALUE_08BIT         1
-#define IMX219_REG_VALUE_16BIT         2
+/* Chip ID */
+#define IMX219_REG_CHIP_ID             CCI_REG16(0x0000)
+#define IMX219_CHIP_ID                 0x0219
 
-#define IMX219_REG_MODE_SELECT         0x0100
+#define IMX219_REG_MODE_SELECT         CCI_REG8(0x0100)
 #define IMX219_MODE_STANDBY            0x00
 #define IMX219_MODE_STREAMING          0x01
 
-/* Chip ID */
-#define IMX219_REG_CHIP_ID             0x0000
-#define IMX219_CHIP_ID                 0x0219
-
-/* External clock frequency is 24.0M */
-#define IMX219_XCLK_FREQ               24000000
+#define IMX219_REG_CSI_LANE_MODE       CCI_REG8(0x0114)
+#define IMX219_CSI_2_LANE_MODE         0x01
+#define IMX219_CSI_4_LANE_MODE         0x03
 
-/* Pixel rate is fixed for all the modes */
-#define IMX219_PIXEL_RATE              182400000
-#define IMX219_PIXEL_RATE_4LANE                280800000
+/* Analog gain control */
+#define IMX219_REG_ANALOG_GAIN         CCI_REG8(0x0157)
+#define IMX219_ANA_GAIN_MIN            0
+#define IMX219_ANA_GAIN_MAX            232
+#define IMX219_ANA_GAIN_STEP           1
+#define IMX219_ANA_GAIN_DEFAULT                0x0
 
-#define IMX219_DEFAULT_LINK_FREQ       456000000
-#define IMX219_DEFAULT_LINK_FREQ_4LANE 363000000
+/* Digital gain control */
+#define IMX219_REG_DIGITAL_GAIN                CCI_REG16(0x0158)
+#define IMX219_DGTL_GAIN_MIN           0x0100
+#define IMX219_DGTL_GAIN_MAX           0x0fff
+#define IMX219_DGTL_GAIN_DEFAULT       0x0100
+#define IMX219_DGTL_GAIN_STEP          1
 
-#define IMX219_REG_CSI_LANE_MODE       0x0114
-#define IMX219_CSI_2_LANE_MODE         0x01
-#define IMX219_CSI_4_LANE_MODE         0x03
+/* Exposure control */
+#define IMX219_REG_EXPOSURE            CCI_REG16(0x015a)
+#define IMX219_EXPOSURE_MIN            4
+#define IMX219_EXPOSURE_STEP           1
+#define IMX219_EXPOSURE_DEFAULT                0x640
+#define IMX219_EXPOSURE_MAX            65535
 
 /* V_TIMING internal */
-#define IMX219_REG_VTS                 0x0160
+#define IMX219_REG_VTS                 CCI_REG16(0x0160)
 #define IMX219_VTS_15FPS               0x0dc6
 #define IMX219_VTS_30FPS_1080P         0x06e3
 #define IMX219_VTS_30FPS_BINNED                0x06e3
 /* HBLANK control - read only */
 #define IMX219_PPL_DEFAULT             3448
 
-/* Exposure control */
-#define IMX219_REG_EXPOSURE            0x015a
-#define IMX219_EXPOSURE_MIN            4
-#define IMX219_EXPOSURE_STEP           1
-#define IMX219_EXPOSURE_DEFAULT                0x640
-#define IMX219_EXPOSURE_MAX            65535
-
-/* Analog gain control */
-#define IMX219_REG_ANALOG_GAIN         0x0157
-#define IMX219_ANA_GAIN_MIN            0
-#define IMX219_ANA_GAIN_MAX            232
-#define IMX219_ANA_GAIN_STEP           1
-#define IMX219_ANA_GAIN_DEFAULT                0x0
-
-/* Digital gain control */
-#define IMX219_REG_DIGITAL_GAIN                0x0158
-#define IMX219_DGTL_GAIN_MIN           0x0100
-#define IMX219_DGTL_GAIN_MAX           0x0fff
-#define IMX219_DGTL_GAIN_DEFAULT       0x0100
-#define IMX219_DGTL_GAIN_STEP          1
-
-#define IMX219_REG_ORIENTATION         0x0172
+#define IMX219_REG_ORIENTATION         CCI_REG8(0x0172)
 
 /* Binning  Mode */
-#define IMX219_REG_BINNING_MODE                0x0174
+#define IMX219_REG_BINNING_MODE                CCI_REG16(0x0174)
 #define IMX219_BINNING_NONE            0x0000
 #define IMX219_BINNING_2X2             0x0101
 #define IMX219_BINNING_2X2_ANALOG      0x0303
 
 /* Test Pattern Control */
-#define IMX219_REG_TEST_PATTERN                0x0600
+#define IMX219_REG_TEST_PATTERN                CCI_REG16(0x0600)
 #define IMX219_TEST_PATTERN_DISABLE    0
 #define IMX219_TEST_PATTERN_SOLID_COLOR        1
 #define IMX219_TEST_PATTERN_COLOR_BARS 2
 #define IMX219_TEST_PATTERN_PN9                4
 
 /* Test pattern colour components */
-#define IMX219_REG_TESTP_RED           0x0602
-#define IMX219_REG_TESTP_GREENR                0x0604
-#define IMX219_REG_TESTP_BLUE          0x0606
-#define IMX219_REG_TESTP_GREENB                0x0608
+#define IMX219_REG_TESTP_RED           CCI_REG16(0x0602)
+#define IMX219_REG_TESTP_GREENR                CCI_REG16(0x0604)
+#define IMX219_REG_TESTP_BLUE          CCI_REG16(0x0606)
+#define IMX219_REG_TESTP_GREENB                CCI_REG16(0x0608)
 #define IMX219_TESTP_COLOUR_MIN                0
 #define IMX219_TESTP_COLOUR_MAX                0x03ff
 #define IMX219_TESTP_COLOUR_STEP       1
 #define IMX219_TESTP_BLUE_DEFAULT      0
 #define IMX219_TESTP_GREENB_DEFAULT    0
 
+/* External clock frequency is 24.0M */
+#define IMX219_XCLK_FREQ               24000000
+
+/* Pixel rate is fixed for all the modes */
+#define IMX219_PIXEL_RATE              182400000
+#define IMX219_PIXEL_RATE_4LANE                280800000
+
+#define IMX219_DEFAULT_LINK_FREQ       456000000
+#define IMX219_DEFAULT_LINK_FREQ_4LANE 363000000
+
 /* IMX219 native and active pixel array size. */
 #define IMX219_NATIVE_WIDTH            3296U
 #define IMX219_NATIVE_HEIGHT           2480U
 #define IMX219_PIXEL_ARRAY_WIDTH       3280U
 #define IMX219_PIXEL_ARRAY_HEIGHT      2464U
 
-struct imx219_reg {
-       u16 address;
-       u8 val;
-};
-
 struct imx219_reg_list {
        unsigned int num_of_regs;
-       const struct imx219_reg *regs;
+       const struct cci_reg_sequence *regs;
 };
 
 /* Mode : resolution and related config&values */
@@ -160,53 +153,53 @@ struct imx219_mode {
        bool binning;
 };
 
-static const struct imx219_reg imx219_common_regs[] = {
-       {0x0100, 0x00}, /* Mode Select */
+static const struct cci_reg_sequence imx219_common_regs[] = {
+       { CCI_REG8(0x0100), 0x00 },     /* Mode Select */
 
        /* To Access Addresses 3000-5fff, send the following commands */
-       {0x30eb, 0x0c},
-       {0x30eb, 0x05},
-       {0x300a, 0xff},
-       {0x300b, 0xff},
-       {0x30eb, 0x05},
-       {0x30eb, 0x09},
+       { CCI_REG8(0x30eb), 0x0c },
+       { CCI_REG8(0x30eb), 0x05 },
+       { CCI_REG8(0x300a), 0xff },
+       { CCI_REG8(0x300b), 0xff },
+       { CCI_REG8(0x30eb), 0x05 },
+       { CCI_REG8(0x30eb), 0x09 },
 
        /* PLL Clock Table */
-       {0x0301, 0x05}, /* VTPXCK_DIV */
-       {0x0303, 0x01}, /* VTSYSCK_DIV */
-       {0x0304, 0x03}, /* PREPLLCK_VT_DIV 0x03 = AUTO set */
-       {0x0305, 0x03}, /* PREPLLCK_OP_DIV 0x03 = AUTO set */
-       {0x0306, 0x00}, /* PLL_VT_MPY */
-       {0x0307, 0x39},
-       {0x030b, 0x01}, /* OP_SYS_CLK_DIV */
-       {0x030c, 0x00}, /* PLL_OP_MPY */
-       {0x030d, 0x72},
+       { CCI_REG8(0x0301), 0x05 },     /* VTPXCK_DIV */
+       { CCI_REG8(0x0303), 0x01 },     /* VTSYSCK_DIV */
+       { CCI_REG8(0x0304), 0x03 },     /* PREPLLCK_VT_DIV 0x03 = AUTO set */
+       { CCI_REG8(0x0305), 0x03 },     /* PREPLLCK_OP_DIV 0x03 = AUTO set */
+       { CCI_REG8(0x0306), 0x00 },     /* PLL_VT_MPY */
+       { CCI_REG8(0x0307), 0x39 },
+       { CCI_REG8(0x030b), 0x01 },     /* OP_SYS_CLK_DIV */
+       { CCI_REG8(0x030c), 0x00 },     /* PLL_OP_MPY */
+       { CCI_REG8(0x030d), 0x72 },
 
        /* Undocumented registers */
-       {0x455e, 0x00},
-       {0x471e, 0x4b},
-       {0x4767, 0x0f},
-       {0x4750, 0x14},
-       {0x4540, 0x00},
-       {0x47b4, 0x14},
-       {0x4713, 0x30},
-       {0x478b, 0x10},
-       {0x478f, 0x10},
-       {0x4793, 0x10},
-       {0x4797, 0x0e},
-       {0x479b, 0x0e},
+       { CCI_REG8(0x455e), 0x00 },
+       { CCI_REG8(0x471e), 0x4b },
+       { CCI_REG8(0x4767), 0x0f },
+       { CCI_REG8(0x4750), 0x14 },
+       { CCI_REG8(0x4540), 0x00 },
+       { CCI_REG8(0x47b4), 0x14 },
+       { CCI_REG8(0x4713), 0x30 },
+       { CCI_REG8(0x478b), 0x10 },
+       { CCI_REG8(0x478f), 0x10 },
+       { CCI_REG8(0x4793), 0x10 },
+       { CCI_REG8(0x4797), 0x0e },
+       { CCI_REG8(0x479b), 0x0e },
 
        /* Frame Bank Register Group "A" */
-       {0x0162, 0x0d}, /* Line_Length_A */
-       {0x0163, 0x78},
-       {0x0170, 0x01}, /* X_ODD_INC_A */
-       {0x0171, 0x01}, /* Y_ODD_INC_A */
+       { CCI_REG8(0x0162), 0x0d },     /* Line_Length_A */
+       { CCI_REG8(0x0163), 0x78 },
+       { CCI_REG8(0x0170), 0x01 },     /* X_ODD_INC_A */
+       { CCI_REG8(0x0171), 0x01 },     /* Y_ODD_INC_A */
 
        /* Output setup registers */
-       {0x0114, 0x01}, /* CSI 2-Lane Mode */
-       {0x0128, 0x00}, /* DPHY Auto Mode */
-       {0x012a, 0x18}, /* EXCK_Freq */
-       {0x012b, 0x00},
+       { CCI_REG8(0x0114), 0x01 },     /* CSI 2-Lane Mode */
+       { CCI_REG8(0x0128), 0x00 },     /* DPHY Auto Mode */
+       { CCI_REG8(0x012a), 0x18 },     /* EXCK_Freq */
+       { CCI_REG8(0x012b), 0x00 },
 };
 
 /*
@@ -214,92 +207,92 @@ static const struct imx219_reg imx219_common_regs[] = {
  * driver.
  * 3280x2464 = mode 2, 1920x1080 = mode 1, 1640x1232 = mode 4, 640x480 = mode 7.
  */
-static const struct imx219_reg mode_3280x2464_regs[] = {
-       {0x0164, 0x00},
-       {0x0165, 0x00},
-       {0x0166, 0x0c},
-       {0x0167, 0xcf},
-       {0x0168, 0x00},
-       {0x0169, 0x00},
-       {0x016a, 0x09},
-       {0x016b, 0x9f},
-       {0x016c, 0x0c},
-       {0x016d, 0xd0},
-       {0x016e, 0x09},
-       {0x016f, 0xa0},
-       {0x0624, 0x0c},
-       {0x0625, 0xd0},
-       {0x0626, 0x09},
-       {0x0627, 0xa0},
+static const struct cci_reg_sequence mode_3280x2464_regs[] = {
+       { CCI_REG8(0x0164), 0x00 },
+       { CCI_REG8(0x0165), 0x00 },
+       { CCI_REG8(0x0166), 0x0c },
+       { CCI_REG8(0x0167), 0xcf },
+       { CCI_REG8(0x0168), 0x00 },
+       { CCI_REG8(0x0169), 0x00 },
+       { CCI_REG8(0x016a), 0x09 },
+       { CCI_REG8(0x016b), 0x9f },
+       { CCI_REG8(0x016c), 0x0c },
+       { CCI_REG8(0x016d), 0xd0 },
+       { CCI_REG8(0x016e), 0x09 },
+       { CCI_REG8(0x016f), 0xa0 },
+       { CCI_REG8(0x0624), 0x0c },
+       { CCI_REG8(0x0625), 0xd0 },
+       { CCI_REG8(0x0626), 0x09 },
+       { CCI_REG8(0x0627), 0xa0 },
 };
 
-static const struct imx219_reg mode_1920_1080_regs[] = {
-       {0x0164, 0x02},
-       {0x0165, 0xa8},
-       {0x0166, 0x0a},
-       {0x0167, 0x27},
-       {0x0168, 0x02},
-       {0x0169, 0xb4},
-       {0x016a, 0x06},
-       {0x016b, 0xeb},
-       {0x016c, 0x07},
-       {0x016d, 0x80},
-       {0x016e, 0x04},
-       {0x016f, 0x38},
-       {0x0624, 0x07},
-       {0x0625, 0x80},
-       {0x0626, 0x04},
-       {0x0627, 0x38},
+static const struct cci_reg_sequence mode_1920_1080_regs[] = {
+       { CCI_REG8(0x0164), 0x02 },
+       { CCI_REG8(0x0165), 0xa8 },
+       { CCI_REG8(0x0166), 0x0a },
+       { CCI_REG8(0x0167), 0x27 },
+       { CCI_REG8(0x0168), 0x02 },
+       { CCI_REG8(0x0169), 0xb4 },
+       { CCI_REG8(0x016a), 0x06 },
+       { CCI_REG8(0x016b), 0xeb },
+       { CCI_REG8(0x016c), 0x07 },
+       { CCI_REG8(0x016d), 0x80 },
+       { CCI_REG8(0x016e), 0x04 },
+       { CCI_REG8(0x016f), 0x38 },
+       { CCI_REG8(0x0624), 0x07 },
+       { CCI_REG8(0x0625), 0x80 },
+       { CCI_REG8(0x0626), 0x04 },
+       { CCI_REG8(0x0627), 0x38 },
 };
 
-static const struct imx219_reg mode_1640_1232_regs[] = {
-       {0x0164, 0x00},
-       {0x0165, 0x00},
-       {0x0166, 0x0c},
-       {0x0167, 0xcf},
-       {0x0168, 0x00},
-       {0x0169, 0x00},
-       {0x016a, 0x09},
-       {0x016b, 0x9f},
-       {0x016c, 0x06},
-       {0x016d, 0x68},
-       {0x016e, 0x04},
-       {0x016f, 0xd0},
-       {0x0624, 0x06},
-       {0x0625, 0x68},
-       {0x0626, 0x04},
-       {0x0627, 0xd0},
+static const struct cci_reg_sequence mode_1640_1232_regs[] = {
+       { CCI_REG8(0x0164), 0x00 },
+       { CCI_REG8(0x0165), 0x00 },
+       { CCI_REG8(0x0166), 0x0c },
+       { CCI_REG8(0x0167), 0xcf },
+       { CCI_REG8(0x0168), 0x00 },
+       { CCI_REG8(0x0169), 0x00 },
+       { CCI_REG8(0x016a), 0x09 },
+       { CCI_REG8(0x016b), 0x9f },
+       { CCI_REG8(0x016c), 0x06 },
+       { CCI_REG8(0x016d), 0x68 },
+       { CCI_REG8(0x016e), 0x04 },
+       { CCI_REG8(0x016f), 0xd0 },
+       { CCI_REG8(0x0624), 0x06 },
+       { CCI_REG8(0x0625), 0x68 },
+       { CCI_REG8(0x0626), 0x04 },
+       { CCI_REG8(0x0627), 0xd0 },
 };
 
-static const struct imx219_reg mode_640_480_regs[] = {
-       {0x0164, 0x03},
-       {0x0165, 0xe8},
-       {0x0166, 0x08},
-       {0x0167, 0xe7},
-       {0x0168, 0x02},
-       {0x0169, 0xf0},
-       {0x016a, 0x06},
-       {0x016b, 0xaf},
-       {0x016c, 0x02},
-       {0x016d, 0x80},
-       {0x016e, 0x01},
-       {0x016f, 0xe0},
-       {0x0624, 0x06},
-       {0x0625, 0x68},
-       {0x0626, 0x04},
-       {0x0627, 0xd0},
+static const struct cci_reg_sequence mode_640_480_regs[] = {
+       { CCI_REG8(0x0164), 0x03 },
+       { CCI_REG8(0x0165), 0xe8 },
+       { CCI_REG8(0x0166), 0x08 },
+       { CCI_REG8(0x0167), 0xe7 },
+       { CCI_REG8(0x0168), 0x02 },
+       { CCI_REG8(0x0169), 0xf0 },
+       { CCI_REG8(0x016a), 0x06 },
+       { CCI_REG8(0x016b), 0xaf },
+       { CCI_REG8(0x016c), 0x02 },
+       { CCI_REG8(0x016d), 0x80 },
+       { CCI_REG8(0x016e), 0x01 },
+       { CCI_REG8(0x016f), 0xe0 },
+       { CCI_REG8(0x0624), 0x06 },
+       { CCI_REG8(0x0625), 0x68 },
+       { CCI_REG8(0x0626), 0x04 },
+       { CCI_REG8(0x0627), 0xd0 },
 };
 
-static const struct imx219_reg raw8_framefmt_regs[] = {
-       {0x018c, 0x08},
-       {0x018d, 0x08},
-       {0x0309, 0x08},
+static const struct cci_reg_sequence raw8_framefmt_regs[] = {
+       { CCI_REG8(0x018c), 0x08 },
+       { CCI_REG8(0x018d), 0x08 },
+       { CCI_REG8(0x0309), 0x08 },
 };
 
-static const struct imx219_reg raw10_framefmt_regs[] = {
-       {0x018c, 0x0a},
-       {0x018d, 0x0a},
-       {0x0309, 0x0a},
+static const struct cci_reg_sequence raw10_framefmt_regs[] = {
+       { CCI_REG8(0x018c), 0x0a },
+       { CCI_REG8(0x018d), 0x0a },
+       { CCI_REG8(0x0309), 0x0a },
 };
 
 static const s64 imx219_link_freq_menu[] = {
@@ -460,6 +453,7 @@ struct imx219 {
        struct v4l2_subdev sd;
        struct media_pad pad;
 
+       struct regmap *regmap;
        struct clk *xclk; /* system clock to IMX219 */
        u32 xclk_freq;
 
@@ -488,78 +482,6 @@ static inline struct imx219 *to_imx219(struct v4l2_subdev *_sd)
        return container_of(_sd, struct imx219, sd);
 }
 
-/* Read registers up to 2 at a time */
-static int imx219_read_reg(struct imx219 *imx219, u16 reg, u32 len, u32 *val)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-       struct i2c_msg msgs[2];
-       u8 addr_buf[2] = { reg >> 8, reg & 0xff };
-       u8 data_buf[4] = { 0, };
-       int ret;
-
-       if (len > 4)
-               return -EINVAL;
-
-       /* 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;
-}
-
-/* Write registers up to 2 at a time */
-static int imx219_write_reg(struct imx219 *imx219, u16 reg, u32 len, u32 val)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-       u8 buf[6];
-
-       if (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;
-}
-
-/* Write a list of registers */
-static int imx219_write_regs(struct imx219 *imx219,
-                            const struct imx219_reg *regs, u32 len)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-       unsigned int i;
-       int ret;
-
-       for (i = 0; i < len; i++) {
-               ret = imx219_write_reg(imx219, regs[i].address, 1, regs[i].val);
-               if (ret) {
-                       dev_err_ratelimited(&client->dev,
-                                           "Failed to write reg 0x%4.4x. error = %d\n",
-                                           regs[i].address, ret);
-
-                       return ret;
-               }
-       }
-
-       return 0;
-}
-
 /* Get bayer order based on flip setting. */
 static u32 imx219_get_format_code(struct imx219 *imx219, u32 code)
 {
@@ -583,7 +505,7 @@ static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
        struct imx219 *imx219 =
                container_of(ctrl->handler, struct imx219, ctrl_handler);
        struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-       int ret;
+       int ret = 0;
 
        if (ctrl->id == V4L2_CID_VBLANK) {
                int exposure_max, exposure_def;
@@ -607,48 +529,45 @@ static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
 
        switch (ctrl->id) {
        case V4L2_CID_ANALOGUE_GAIN:
-               ret = imx219_write_reg(imx219, IMX219_REG_ANALOG_GAIN,
-                                      IMX219_REG_VALUE_08BIT, ctrl->val);
+               cci_write(imx219->regmap, IMX219_REG_ANALOG_GAIN,
+                         ctrl->val, &ret);
                break;
        case V4L2_CID_EXPOSURE:
-               ret = imx219_write_reg(imx219, IMX219_REG_EXPOSURE,
-                                      IMX219_REG_VALUE_16BIT, ctrl->val);
+               cci_write(imx219->regmap, IMX219_REG_EXPOSURE,
+                         ctrl->val, &ret);
                break;
        case V4L2_CID_DIGITAL_GAIN:
-               ret = imx219_write_reg(imx219, IMX219_REG_DIGITAL_GAIN,
-                                      IMX219_REG_VALUE_16BIT, ctrl->val);
+               cci_write(imx219->regmap, IMX219_REG_DIGITAL_GAIN,
+                         ctrl->val, &ret);
                break;
        case V4L2_CID_TEST_PATTERN:
-               ret = imx219_write_reg(imx219, IMX219_REG_TEST_PATTERN,
-                                      IMX219_REG_VALUE_16BIT,
-                                      imx219_test_pattern_val[ctrl->val]);
+               cci_write(imx219->regmap, IMX219_REG_TEST_PATTERN,
+                         imx219_test_pattern_val[ctrl->val], &ret);
                break;
        case V4L2_CID_HFLIP:
        case V4L2_CID_VFLIP:
-               ret = imx219_write_reg(imx219, IMX219_REG_ORIENTATION, 1,
-                                      imx219->hflip->val |
-                                      imx219->vflip->val << 1);
+               cci_write(imx219->regmap, IMX219_REG_ORIENTATION,
+                         imx219->hflip->val | imx219->vflip->val << 1, &ret);
                break;
        case V4L2_CID_VBLANK:
-               ret = imx219_write_reg(imx219, IMX219_REG_VTS,
-                                      IMX219_REG_VALUE_16BIT,
-                                      imx219->mode->height + ctrl->val);
+               cci_write(imx219->regmap, IMX219_REG_VTS,
+                         imx219->mode->height + ctrl->val, &ret);
                break;
        case V4L2_CID_TEST_PATTERN_RED:
-               ret = imx219_write_reg(imx219, IMX219_REG_TESTP_RED,
-                                      IMX219_REG_VALUE_16BIT, ctrl->val);
+               cci_write(imx219->regmap, IMX219_REG_TESTP_RED,
+                         ctrl->val, &ret);
                break;
        case V4L2_CID_TEST_PATTERN_GREENR:
-               ret = imx219_write_reg(imx219, IMX219_REG_TESTP_GREENR,
-                                      IMX219_REG_VALUE_16BIT, ctrl->val);
+               cci_write(imx219->regmap, IMX219_REG_TESTP_GREENR,
+                         ctrl->val, &ret);
                break;
        case V4L2_CID_TEST_PATTERN_BLUE:
-               ret = imx219_write_reg(imx219, IMX219_REG_TESTP_BLUE,
-                                      IMX219_REG_VALUE_16BIT, ctrl->val);
+               cci_write(imx219->regmap, IMX219_REG_TESTP_BLUE,
+                         ctrl->val, &ret);
                break;
        case V4L2_CID_TEST_PATTERN_GREENB:
-               ret = imx219_write_reg(imx219, IMX219_REG_TESTP_GREENB,
-                                      IMX219_REG_VALUE_16BIT, ctrl->val);
+               cci_write(imx219->regmap, IMX219_REG_TESTP_GREENB,
+                         ctrl->val, &ret);
                break;
        default:
                dev_info(&client->dev,
@@ -799,15 +718,15 @@ static int imx219_set_framefmt(struct imx219 *imx219,
        case MEDIA_BUS_FMT_SGRBG8_1X8:
        case MEDIA_BUS_FMT_SGBRG8_1X8:
        case MEDIA_BUS_FMT_SBGGR8_1X8:
-               return imx219_write_regs(imx219, raw8_framefmt_regs,
-                                       ARRAY_SIZE(raw8_framefmt_regs));
+               return cci_multi_reg_write(imx219->regmap, raw8_framefmt_regs,
+                                          ARRAY_SIZE(raw8_framefmt_regs), NULL);
 
        case MEDIA_BUS_FMT_SRGGB10_1X10:
        case MEDIA_BUS_FMT_SGRBG10_1X10:
        case MEDIA_BUS_FMT_SGBRG10_1X10:
        case MEDIA_BUS_FMT_SBGGR10_1X10:
-               return imx219_write_regs(imx219, raw10_framefmt_regs,
-                                       ARRAY_SIZE(raw10_framefmt_regs));
+               return cci_multi_reg_write(imx219->regmap, raw10_framefmt_regs,
+                                          ARRAY_SIZE(raw10_framefmt_regs), NULL);
        }
 
        return -EINVAL;
@@ -816,28 +735,24 @@ static int imx219_set_framefmt(struct imx219 *imx219,
 static int imx219_set_binning(struct imx219 *imx219,
                              const struct v4l2_mbus_framefmt *format)
 {
-       if (!imx219->mode->binning) {
-               return imx219_write_reg(imx219, IMX219_REG_BINNING_MODE,
-                                       IMX219_REG_VALUE_16BIT,
-                                       IMX219_BINNING_NONE);
-       }
+       if (!imx219->mode->binning)
+               return cci_write(imx219->regmap, IMX219_REG_BINNING_MODE,
+                                IMX219_BINNING_NONE, NULL);
 
        switch (format->code) {
        case MEDIA_BUS_FMT_SRGGB8_1X8:
        case MEDIA_BUS_FMT_SGRBG8_1X8:
        case MEDIA_BUS_FMT_SGBRG8_1X8:
        case MEDIA_BUS_FMT_SBGGR8_1X8:
-               return imx219_write_reg(imx219, IMX219_REG_BINNING_MODE,
-                                       IMX219_REG_VALUE_16BIT,
-                                       IMX219_BINNING_2X2_ANALOG);
+               return cci_write(imx219->regmap, IMX219_REG_BINNING_MODE,
+                                IMX219_BINNING_2X2_ANALOG, NULL);
 
        case MEDIA_BUS_FMT_SRGGB10_1X10:
        case MEDIA_BUS_FMT_SGRBG10_1X10:
        case MEDIA_BUS_FMT_SGBRG10_1X10:
        case MEDIA_BUS_FMT_SBGGR10_1X10:
-               return imx219_write_reg(imx219, IMX219_REG_BINNING_MODE,
-                                       IMX219_REG_VALUE_16BIT,
-                                       IMX219_BINNING_2X2);
+               return cci_write(imx219->regmap, IMX219_REG_BINNING_MODE,
+                                IMX219_BINNING_2X2, NULL);
        }
 
        return -EINVAL;
@@ -876,9 +791,9 @@ static int imx219_get_selection(struct v4l2_subdev *sd,
 
 static int imx219_configure_lanes(struct imx219 *imx219)
 {
-       return imx219_write_reg(imx219, IMX219_REG_CSI_LANE_MODE,
-                               IMX219_REG_VALUE_08BIT, (imx219->lanes == 2) ?
-                               IMX219_CSI_2_LANE_MODE : IMX219_CSI_4_LANE_MODE);
+       return cci_write(imx219->regmap, IMX219_REG_CSI_LANE_MODE,
+                        imx219->lanes == 2 ? IMX219_CSI_2_LANE_MODE :
+                        IMX219_CSI_4_LANE_MODE, NULL);
 };
 
 static int imx219_start_streaming(struct imx219 *imx219,
@@ -894,7 +809,8 @@ static int imx219_start_streaming(struct imx219 *imx219,
                return ret;
 
        /* Send all registers that are common to all modes */
-       ret = imx219_write_regs(imx219, imx219_common_regs, ARRAY_SIZE(imx219_common_regs));
+       ret = cci_multi_reg_write(imx219->regmap, imx219_common_regs,
+                                 ARRAY_SIZE(imx219_common_regs), NULL);
        if (ret) {
                dev_err(&client->dev, "%s failed to send mfg header\n", __func__);
                goto err_rpm_put;
@@ -909,7 +825,8 @@ static int imx219_start_streaming(struct imx219 *imx219,
 
        /* Apply default values of current mode */
        reg_list = &imx219->mode->reg_list;
-       ret = imx219_write_regs(imx219, reg_list->regs, reg_list->num_of_regs);
+       ret = cci_multi_reg_write(imx219->regmap, reg_list->regs,
+                                 reg_list->num_of_regs, NULL);
        if (ret) {
                dev_err(&client->dev, "%s failed to set mode\n", __func__);
                goto err_rpm_put;
@@ -936,8 +853,8 @@ static int imx219_start_streaming(struct imx219 *imx219,
                goto err_rpm_put;
 
        /* set stream on register */
-       ret = imx219_write_reg(imx219, IMX219_REG_MODE_SELECT,
-                              IMX219_REG_VALUE_08BIT, IMX219_MODE_STREAMING);
+       ret = cci_write(imx219->regmap, IMX219_REG_MODE_SELECT,
+                       IMX219_MODE_STREAMING, NULL);
        if (ret)
                goto err_rpm_put;
 
@@ -958,8 +875,8 @@ static void imx219_stop_streaming(struct imx219 *imx219)
        int ret;
 
        /* set stream off register */
-       ret = imx219_write_reg(imx219, IMX219_REG_MODE_SELECT,
-                              IMX219_REG_VALUE_08BIT, IMX219_MODE_STANDBY);
+       ret = cci_write(imx219->regmap, IMX219_REG_MODE_SELECT,
+                       IMX219_MODE_STANDBY, NULL);
        if (ret)
                dev_err(&client->dev, "%s failed to set stream\n", __func__);
 
@@ -1058,10 +975,9 @@ static int imx219_identify_module(struct imx219 *imx219)
 {
        struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
        int ret;
-       u32 val;
+       u64 val;
 
-       ret = imx219_read_reg(imx219, IMX219_REG_CHIP_ID,
-                             IMX219_REG_VALUE_16BIT, &val);
+       ret = cci_read(imx219->regmap, IMX219_REG_CHIP_ID, &val, NULL);
        if (ret) {
                dev_err(&client->dev, "failed to read chip id %x\n",
                        IMX219_CHIP_ID);
@@ -1069,7 +985,7 @@ static int imx219_identify_module(struct imx219 *imx219)
        }
 
        if (val != IMX219_CHIP_ID) {
-               dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
+               dev_err(&client->dev, "chip id mismatch: %x!=%llx\n",
                        IMX219_CHIP_ID, val);
                return -EIO;
        }
@@ -1293,6 +1209,13 @@ static int imx219_probe(struct i2c_client *client)
        if (imx219_check_hwcfg(dev, imx219))
                return -EINVAL;
 
+       imx219->regmap = devm_cci_regmap_init_i2c(client, 16);
+       if (IS_ERR(imx219->regmap)) {
+               ret = PTR_ERR(imx219->regmap);
+               dev_err(dev, "failed to initialize CCI: %d\n", ret);
+               return ret;
+       }
+
        /* Get system clock (xclk) */
        imx219->xclk = devm_clk_get(dev, NULL);
        if (IS_ERR(imx219->xclk)) {
@@ -1336,17 +1259,19 @@ static int imx219_probe(struct i2c_client *client)
         * streaming is started, so upon power up switch the modes to:
         * streaming -> standby
         */
-       ret = imx219_write_reg(imx219, IMX219_REG_MODE_SELECT,
-                              IMX219_REG_VALUE_08BIT, IMX219_MODE_STREAMING);
+       ret = cci_write(imx219->regmap, IMX219_REG_MODE_SELECT,
+                       IMX219_MODE_STREAMING, NULL);
        if (ret < 0)
                goto error_power_off;
+
        usleep_range(100, 110);
 
        /* put sensor back to standby mode */
-       ret = imx219_write_reg(imx219, IMX219_REG_MODE_SELECT,
-                              IMX219_REG_VALUE_08BIT, IMX219_MODE_STANDBY);
+       ret = cci_write(imx219->regmap, IMX219_REG_MODE_SELECT,
+                       IMX219_MODE_STANDBY, NULL);
        if (ret < 0)
                goto error_power_off;
+
        usleep_range(100, 110);
 
        ret = imx219_init_controls(imx219);