diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-07 13:11:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-07 13:11:22 +0000 |
commit | b20732900e4636a467c0183a47f7396700f5f743 (patch) | |
tree | 42f079ff82e701ebcb76829974b4caca3e5b6798 /drivers/media/i2c | |
parent | Adding upstream version 6.8.12. (diff) | |
download | linux-b20732900e4636a467c0183a47f7396700f5f743.tar.xz linux-b20732900e4636a467c0183a47f7396700f5f743.zip |
Adding upstream version 6.9.7.upstream/6.9.7
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/media/i2c')
41 files changed, 1048 insertions, 1953 deletions
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 4c3435921f..56f276b920 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -224,6 +224,7 @@ config VIDEO_IMX412 config VIDEO_IMX415 tristate "Sony IMX415 sensor support" depends on OF_GPIO + select V4L2_CCI_I2C help This is a Video4Linux2 sensor driver for the Sony IMX415 camera. @@ -658,6 +659,7 @@ config VIDEO_S5K6A3 config VIDEO_ST_VGXY61 tristate "ST VGXY61 sensor support" + select V4L2_CCI_I2C depends on OF && GPIOLIB help This is a Video4Linux2 sensor driver for the ST VGXY61 diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 409b9a37f0..4829cbe324 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -1057,11 +1057,11 @@ static int adv7182_init(struct adv7180_state *state) ADV7180_REG_EXTENDED_OUTPUT_CONTROL, 0x17); } - } - else + } else { adv7180_write(state, ADV7180_REG_EXTENDED_OUTPUT_CONTROL, 0x07); + } adv7180_write(state, ADV7180_REG_OUTPUT_CONTROL, 0x0c); adv7180_write(state, ADV7180_REG_CTRL_2, 0x40); } diff --git a/drivers/media/i2c/adv7343.c b/drivers/media/i2c/adv7343.c index ff21cd4744..4fbe4e1857 100644 --- a/drivers/media/i2c/adv7343.c +++ b/drivers/media/i2c/adv7343.c @@ -403,7 +403,7 @@ adv7343_get_pdata(struct i2c_client *client) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) return client->dev.platform_data; - np = of_graph_get_next_endpoint(client->dev.of_node, NULL); + np = of_graph_get_endpoint_by_regs(client->dev.of_node, 0, -1); if (!np) return NULL; diff --git a/drivers/media/i2c/adv748x/adv748x.h b/drivers/media/i2c/adv748x/adv748x.h index 6f90f78f58..d2b5e722e9 100644 --- a/drivers/media/i2c/adv748x/adv748x.h +++ b/drivers/media/i2c/adv748x/adv748x.h @@ -173,7 +173,6 @@ struct adv748x_afe { * * @endpoints: parsed device node endpoints for each port * - * @i2c_addresses: I2C Page addresses * @i2c_clients: I2C clients for the page accesses * @regmap: regmap configuration pages. * diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 810fa8826f..319db3e847 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -3204,8 +3204,8 @@ static int adv76xx_parse_dt(struct adv76xx_state *state) np = state->i2c_clients[ADV76XX_PAGE_IO]->dev.of_node; - /* Parse the endpoint. */ - endpoint = of_graph_get_next_endpoint(np, NULL); + /* FIXME: Parse the endpoint. */ + endpoint = of_graph_get_endpoint_by_regs(np, -1, -1); if (!endpoint) return -EINVAL; diff --git a/drivers/media/i2c/alvium-csi2.c b/drivers/media/i2c/alvium-csi2.c index 34ff7fad38..e65702e3f7 100644 --- a/drivers/media/i2c/alvium-csi2.c +++ b/drivers/media/i2c/alvium-csi2.c @@ -1170,40 +1170,32 @@ static int alvium_set_bayer_pattern(struct alvium_dev *alvium, return 0; } -static int alvium_get_frame_interval(struct alvium_dev *alvium) +static int alvium_get_frame_interval(struct alvium_dev *alvium, + u64 *min_fr, u64 *max_fr) { - u64 dft_fr, min_fr, max_fr; int ret = 0; - alvium_read(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_RW, - &dft_fr, &ret); alvium_read(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_MIN_R, - &min_fr, &ret); + min_fr, &ret); alvium_read(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_MAX_R, - &max_fr, &ret); - if (ret) - return ret; - - alvium->dft_fr = dft_fr; - alvium->min_fr = min_fr; - alvium->max_fr = max_fr; + max_fr, &ret); - return 0; + return ret; } -static int alvium_set_frame_rate(struct alvium_dev *alvium) +static int alvium_set_frame_rate(struct alvium_dev *alvium, u64 fr) { struct device *dev = &alvium->i2c_client->dev; int ret; ret = alvium_write_hshake(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_RW, - alvium->fr); + fr); if (ret) { dev_err(dev, "Fail to set frame rate lanes reg\n"); return ret; } - dev_dbg(dev, "set frame rate: %llu us\n", alvium->fr); + dev_dbg(dev, "set frame rate: %llu us\n", fr); return 0; } @@ -1472,7 +1464,7 @@ static int alvium_get_hw_features_params(struct alvium_dev *alvium) ret = alvium_get_img_height_params(alvium); if (ret) { - dev_err(dev, "Fail to read img heigth regs\n"); + dev_err(dev, "Fail to read img height regs\n"); return ret; } @@ -1647,44 +1639,28 @@ static int alvium_hw_init(struct alvium_dev *alvium) } /* --------------- Subdev Operations --------------- */ - -static int alvium_g_frame_interval(struct v4l2_subdev *sd, +static int alvium_s_frame_interval(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_interval *fi) { struct alvium_dev *alvium = sd_to_alvium(sd); - - /* - * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2 - * subdev active state API. - */ - if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) - return -EINVAL; - - fi->interval = alvium->frame_interval; - - return 0; -} - -static int alvium_set_frame_interval(struct alvium_dev *alvium, - struct v4l2_subdev_frame_interval *fi) -{ struct device *dev = &alvium->i2c_client->dev; u64 req_fr, min_fr, max_fr; + struct v4l2_fract *interval; int ret; + if (alvium->streaming) + return -EBUSY; + if (fi->interval.denominator == 0) return -EINVAL; - ret = alvium_get_frame_interval(alvium); + ret = alvium_get_frame_interval(alvium, &min_fr, &max_fr); if (ret) { dev_err(dev, "Fail to get frame interval\n"); return ret; } - min_fr = alvium->min_fr; - max_fr = alvium->max_fr; - dev_dbg(dev, "fi->interval.numerator = %d\n", fi->interval.numerator); dev_dbg(dev, "fi->interval.denominator = %d\n", @@ -1692,39 +1668,17 @@ static int alvium_set_frame_interval(struct alvium_dev *alvium, req_fr = (u64)((fi->interval.denominator * USEC_PER_SEC) / fi->interval.numerator); + req_fr = clamp(req_fr, min_fr, max_fr); - if (req_fr >= max_fr && req_fr <= min_fr) - req_fr = alvium->dft_fr; + interval = v4l2_subdev_state_get_interval(sd_state, 0); - alvium->fr = req_fr; - alvium->frame_interval.numerator = fi->interval.numerator; - alvium->frame_interval.denominator = fi->interval.denominator; + interval->numerator = fi->interval.numerator; + interval->denominator = fi->interval.denominator; - return 0; -} - -static int alvium_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_frame_interval *fi) -{ - struct alvium_dev *alvium = sd_to_alvium(sd); - int ret; - - /* - * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2 - * subdev active state API. - */ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) - return -EINVAL; - - if (alvium->streaming) - return -EBUSY; - - ret = alvium_set_frame_interval(alvium, fi); - if (!ret) - ret = alvium_set_frame_rate(alvium); + return 0; - return ret; + return alvium_set_frame_rate(alvium, req_fr); } static int alvium_enum_mbus_code(struct v4l2_subdev *sd, @@ -1872,6 +1826,7 @@ static int alvium_init_state(struct v4l2_subdev *sd, { struct alvium_dev *alvium = sd_to_alvium(sd); struct alvium_mode *mode = &alvium->mode; + struct v4l2_fract *interval; struct v4l2_subdev_format sd_fmt = { .which = V4L2_SUBDEV_FORMAT_TRY, .format = alvium_csi2_default_fmt, @@ -1889,6 +1844,11 @@ static int alvium_init_state(struct v4l2_subdev *sd, *v4l2_subdev_state_get_crop(state, 0) = sd_crop.rect; *v4l2_subdev_state_get_format(state, 0) = sd_fmt.format; + /* Setup initial frame interval*/ + interval = v4l2_subdev_state_get_interval(state, 0); + interval->numerator = 1; + interval->denominator = ALVIUM_DEFAULT_FR_HZ; + return 0; } @@ -2258,7 +2218,7 @@ static const struct v4l2_subdev_pad_ops alvium_pad_ops = { .set_fmt = alvium_set_fmt, .get_selection = alvium_get_selection, .set_selection = alvium_set_selection, - .get_frame_interval = alvium_g_frame_interval, + .get_frame_interval = v4l2_subdev_get_frame_interval, .set_frame_interval = alvium_s_frame_interval, }; @@ -2279,11 +2239,6 @@ static int alvium_subdev_init(struct alvium_dev *alvium) struct v4l2_subdev *sd = &alvium->sd; int ret; - /* Setup initial frame interval*/ - alvium->frame_interval.numerator = 1; - alvium->frame_interval.denominator = ALVIUM_DEFAULT_FR_HZ; - alvium->fr = ALVIUM_DEFAULT_FR_HZ; - /* Setup the initial mode */ alvium->mode.fmt = alvium_csi2_default_fmt; alvium->mode.width = alvium_csi2_default_fmt.width; diff --git a/drivers/media/i2c/alvium-csi2.h b/drivers/media/i2c/alvium-csi2.h index b85a25169e..9463f8604f 100644 --- a/drivers/media/i2c/alvium-csi2.h +++ b/drivers/media/i2c/alvium-csi2.h @@ -442,11 +442,6 @@ struct alvium_dev { s32 inc_sharp; struct alvium_mode mode; - struct v4l2_fract frame_interval; - u64 dft_fr; - u64 min_fr; - u64 max_fr; - u64 fr; u8 h_sup_csi_lanes; u64 link_freq; diff --git a/drivers/media/i2c/ar0521.c b/drivers/media/i2c/ar0521.c index c7d5fa532a..09331cf95c 100644 --- a/drivers/media/i2c/ar0521.c +++ b/drivers/media/i2c/ar0521.c @@ -314,7 +314,7 @@ static void ar0521_calc_pll(struct ar0521_dev *sensor) * In the clock tree: * MIPI_CLK = PIXEL_CLOCK * bpp / 2 / 2 * - * Generic pixel_rate to bus clock frequencey equation: + * Generic pixel_rate to bus clock frequency equation: * MIPI_CLK = V4L2_CID_PIXEL_RATE * bpp / lanes / 2 * * From which we derive the PIXEL_CLOCK to use in the clock tree: @@ -327,7 +327,7 @@ static void ar0521_calc_pll(struct ar0521_dev *sensor) * * TODO: in case we have less data lanes we have to reduce the desired * VCO not to exceed the limits specified by the datasheet and - * consequentially reduce the obtained pixel clock. + * consequently reduce the obtained pixel clock. */ pixel_clock = AR0521_PIXEL_CLOCK_RATE * 2 / sensor->lane_count; bpp = ar0521_code_to_bpp(sensor); @@ -806,7 +806,7 @@ static const struct initial_reg { REGS(be(0x3F00), be(0x0017), /* 3F00: BM_T0 */ be(0x02DD), /* 3F02: BM_T1 */ - /* 3F04: if Ana_gain less than 2, use noise_floor0, multipl */ + /* 3F04: if Ana_gain less than 2, use noise_floor0, multiply */ be(0x0020), /* 3F06: if Ana_gain between 4 and 7, use noise_floor2 and */ be(0x0040), diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index e21287d50c..e1ae0f9fad 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -674,7 +674,7 @@ static int ccs_set_ctrl(struct v4l2_ctrl *ctrl) break; } - pm_status = pm_runtime_get_if_active(&client->dev, true); + pm_status = pm_runtime_get_if_active(&client->dev); if (!pm_status) return 0; diff --git a/drivers/media/i2c/ccs/ccs-quirk.h b/drivers/media/i2c/ccs/ccs-quirk.h index 0b1a64958d..392c971096 100644 --- a/drivers/media/i2c/ccs/ccs-quirk.h +++ b/drivers/media/i2c/ccs/ccs-quirk.h @@ -28,11 +28,11 @@ struct ccs_sensor; * @reg_access: Register access quirk. The quirk may divert the access * to another register, or no register at all. * - * @write: Is this read (false) or write (true) access? - * @reg: Pointer to the register to access - * @value: Register value, set by the caller on write, or + * -write: Is this read (false) or write (true) access? + * -reg: Pointer to the register to access + * -val: Register value, set by the caller on write, or * by the quirk on read - * @return: 0 on success, -ENOIOCTLCMD if no register + * -return: 0 on success, -ENOIOCTLCMD if no register * access may be done by the caller (default read * value is zero), else negative error code on error * @flags: Quirk flags diff --git a/drivers/media/i2c/dw9714.c b/drivers/media/i2c/dw9714.c index cc09b32ede..84d29bcf0c 100644 --- a/drivers/media/i2c/dw9714.c +++ b/drivers/media/i2c/dw9714.c @@ -157,6 +157,8 @@ static int dw9714_probe(struct i2c_client *client) return rval; } + usleep_range(1000, 2000); + v4l2_i2c_subdev_init(&dw9714_dev->sd, client, &dw9714_ops); dw9714_dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c index b148b1bd2b..10b6ad66d1 100644 --- a/drivers/media/i2c/imx214.c +++ b/drivers/media/i2c/imx214.c @@ -968,7 +968,7 @@ static const struct v4l2_subdev_internal_ops imx214_internal_ops = { static const struct regmap_config sensor_regmap_config = { .reg_bits = 16, .val_bits = 8, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static int imx214_get_regulators(struct device *dev, struct imx214 *imx214) diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c index 352da68b8b..3800de974e 100644 --- a/drivers/media/i2c/imx274.c +++ b/drivers/media/i2c/imx274.c @@ -151,7 +151,7 @@ struct reg_8 { static const struct regmap_config imx274_regmap_config = { .reg_bits = 16, .val_bits = 8, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; /* diff --git a/drivers/media/i2c/imx319.c b/drivers/media/i2c/imx319.c index e47eff672e..8fe3933f31 100644 --- a/drivers/media/i2c/imx319.c +++ b/drivers/media/i2c/imx319.c @@ -70,7 +70,7 @@ #define IMX319_REG_ORIENTATION 0x0101 /* default link frequency and external clock */ -#define IMX319_LINK_FREQ_DEFAULT 482400000 +#define IMX319_LINK_FREQ_DEFAULT 482400000LL #define IMX319_EXT_CLK 19200000 #define IMX319_LINK_FREQ_INDEX 0 @@ -107,8 +107,7 @@ struct imx319_mode { struct imx319_hwcfg { u32 ext_clk; /* sensor external clk */ - s64 *link_freqs; /* CSI-2 link frequencies */ - unsigned int nr_of_link_freqs; + unsigned long link_freq_bitmap; }; struct imx319 { @@ -129,7 +128,6 @@ struct imx319 { const struct imx319_mode *cur_mode; struct imx319_hwcfg *hwcfg; - s64 link_def_freq; /* CSI-2 link default frequency */ /* * Mutex for serialized access: @@ -1654,7 +1652,10 @@ static const char * const imx319_test_pattern_menu[] = { "Pseudorandom Sequence (PN9)", }; -/* supported link frequencies */ +/* + * When adding more than the one below, make sure the disallowed ones will + * actually be disabled in the LINK_FREQ control. + */ static const s64 link_freq_menu_items[] = { IMX319_LINK_FREQ_DEFAULT, }; @@ -2058,7 +2059,7 @@ imx319_set_pad_format(struct v4l2_subdev *sd, *framefmt = fmt->format; } else { imx319->cur_mode = mode; - pixel_rate = imx319->link_def_freq * 2 * 4; + pixel_rate = IMX319_LINK_FREQ_DEFAULT * 2 * 4; do_div(pixel_rate, 10); __v4l2_ctrl_s_ctrl_int64(imx319->pixel_rate, pixel_rate); /* Update limits and set FPS to default */ @@ -2255,7 +2256,7 @@ static int imx319_init_controls(struct imx319 *imx319) imx319->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */ - pixel_rate = imx319->link_def_freq * 2 * 4; + pixel_rate = IMX319_LINK_FREQ_DEFAULT * 2 * 4; do_div(pixel_rate, 10); /* By default, PIXEL_RATE is read only */ imx319->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops, @@ -2332,7 +2333,6 @@ static struct imx319_hwcfg *imx319_get_hwcfg(struct device *dev) }; struct fwnode_handle *ep; struct fwnode_handle *fwnode = dev_fwnode(dev); - unsigned int i; int ret; if (!fwnode) @@ -2364,24 +2364,14 @@ static struct imx319_hwcfg *imx319_get_hwcfg(struct device *dev) goto out_err; } - dev_dbg(dev, "num of link freqs: %d", bus_cfg.nr_of_link_frequencies); - if (!bus_cfg.nr_of_link_frequencies) { - dev_warn(dev, "no link frequencies defined"); - goto out_err; - } - - cfg->nr_of_link_freqs = bus_cfg.nr_of_link_frequencies; - cfg->link_freqs = devm_kcalloc(dev, - bus_cfg.nr_of_link_frequencies + 1, - sizeof(*cfg->link_freqs), GFP_KERNEL); - if (!cfg->link_freqs) + ret = v4l2_link_freq_to_bitmap(dev, bus_cfg.link_frequencies, + bus_cfg.nr_of_link_frequencies, + link_freq_menu_items, + ARRAY_SIZE(link_freq_menu_items), + &cfg->link_freq_bitmap); + if (ret) goto out_err; - for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) { - cfg->link_freqs[i] = bus_cfg.link_frequencies[i]; - dev_dbg(dev, "link_freq[%d] = %lld", i, cfg->link_freqs[i]); - } - v4l2_fwnode_endpoint_free(&bus_cfg); fwnode_handle_put(ep); return cfg; @@ -2397,7 +2387,6 @@ static int imx319_probe(struct i2c_client *client) struct imx319 *imx319; bool full_power; int ret; - u32 i; imx319 = devm_kzalloc(&client->dev, sizeof(*imx319), GFP_KERNEL); if (!imx319) @@ -2425,20 +2414,6 @@ static int imx319_probe(struct i2c_client *client) goto error_probe; } - imx319->link_def_freq = link_freq_menu_items[IMX319_LINK_FREQ_INDEX]; - for (i = 0; i < imx319->hwcfg->nr_of_link_freqs; i++) { - if (imx319->hwcfg->link_freqs[i] == imx319->link_def_freq) { - dev_dbg(&client->dev, "link freq index %d matched", i); - break; - } - } - - if (i == imx319->hwcfg->nr_of_link_freqs) { - dev_err(&client->dev, "no link frequency supported"); - ret = -EINVAL; - goto error_probe; - } - /* Set default mode to max resolution */ imx319->cur_mode = &supported_modes[0]; diff --git a/drivers/media/i2c/imx334.c b/drivers/media/i2c/imx334.c index 6725b3e2a7..40863d87d3 100644 --- a/drivers/media/i2c/imx334.c +++ b/drivers/media/i2c/imx334.c @@ -136,7 +136,7 @@ struct imx334_mode { * @vblank: Vertical blanking in lines * @cur_mode: Pointer to current selected sensor mode * @mutex: Mutex for serializing sensor controls - * @menu_skip_mask: Menu skip mask for link_freq_ctrl + * @link_freq_bitmap: Menu bitmap for link_freq_ctrl * @cur_code: current selected format code */ struct imx334 { @@ -158,7 +158,7 @@ struct imx334 { u32 vblank; const struct imx334_mode *cur_mode; struct mutex mutex; - unsigned long menu_skip_mask; + unsigned long link_freq_bitmap; u32 cur_code; }; @@ -954,9 +954,9 @@ static int imx334_init_state(struct v4l2_subdev *sd, imx334_fill_pad_format(imx334, imx334->cur_mode, &fmt); __v4l2_ctrl_modify_range(imx334->link_freq_ctrl, 0, - __fls(imx334->menu_skip_mask), - ~(imx334->menu_skip_mask), - __ffs(imx334->menu_skip_mask)); + __fls(imx334->link_freq_bitmap), + ~(imx334->link_freq_bitmap), + __ffs(imx334->link_freq_bitmap)); mutex_unlock(&imx334->mutex); @@ -1112,7 +1112,6 @@ static int imx334_parse_hw_config(struct imx334 *imx334) }; struct fwnode_handle *ep; unsigned long rate; - unsigned int i, j; int ret; if (!fwnode) @@ -1157,26 +1156,10 @@ static int imx334_parse_hw_config(struct imx334 *imx334) goto done_endpoint_free; } - if (!bus_cfg.nr_of_link_frequencies) { - dev_err(imx334->dev, "no link frequencies defined"); - ret = -EINVAL; - goto done_endpoint_free; - } - - for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) { - for (j = 0; j < ARRAY_SIZE(link_freq); j++) { - if (bus_cfg.link_frequencies[i] == link_freq[j]) { - set_bit(j, &imx334->menu_skip_mask); - break; - } - } - - if (j == ARRAY_SIZE(link_freq)) { - ret = dev_err_probe(imx334->dev, -EINVAL, - "no supported link freq found\n"); - goto done_endpoint_free; - } - } + ret = v4l2_link_freq_to_bitmap(imx334->dev, bus_cfg.link_frequencies, + bus_cfg.nr_of_link_frequencies, + link_freq, ARRAY_SIZE(link_freq), + &imx334->link_freq_bitmap); done_endpoint_free: v4l2_fwnode_endpoint_free(&bus_cfg); @@ -1310,8 +1293,8 @@ static int imx334_init_controls(struct imx334 *imx334) imx334->link_freq_ctrl = v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx334_ctrl_ops, V4L2_CID_LINK_FREQ, - __fls(imx334->menu_skip_mask), - __ffs(imx334->menu_skip_mask), + __fls(imx334->link_freq_bitmap), + __ffs(imx334->link_freq_bitmap), link_freq); if (imx334->link_freq_ctrl) @@ -1386,7 +1369,7 @@ static int imx334_probe(struct i2c_client *client) } /* Set default mode to max resolution */ - imx334->cur_mode = &supported_modes[__ffs(imx334->menu_skip_mask)]; + imx334->cur_mode = &supported_modes[__ffs(imx334->link_freq_bitmap)]; imx334->cur_code = imx334_mbus_codes[0]; imx334->vblank = imx334->cur_mode->vblank; diff --git a/drivers/media/i2c/imx335.c b/drivers/media/i2c/imx335.c index 7a37eb327f..dab6d080bc 100644 --- a/drivers/media/i2c/imx335.c +++ b/drivers/media/i2c/imx335.c @@ -45,11 +45,28 @@ /* Group hold register */ #define IMX335_REG_HOLD 0x3001 +/* Test pattern generator */ +#define IMX335_REG_TPG 0x329e +#define IMX335_TPG_ALL_000 0 +#define IMX335_TPG_ALL_FFF 1 +#define IMX335_TPG_ALL_555 2 +#define IMX335_TPG_ALL_AAA 3 +#define IMX335_TPG_TOG_555_AAA 4 +#define IMX335_TPG_TOG_AAA_555 5 +#define IMX335_TPG_TOG_000_555 6 +#define IMX335_TPG_TOG_555_000 7 +#define IMX335_TPG_TOG_000_FFF 8 +#define IMX335_TPG_TOG_FFF_000 9 +#define IMX335_TPG_H_COLOR_BARS 10 +#define IMX335_TPG_V_COLOR_BARS 11 + /* Input clock rate */ #define IMX335_INCLK_RATE 24000000 /* CSI2 HW configuration */ -#define IMX335_LINK_FREQ 594000000 +#define IMX335_LINK_FREQ_594MHz 594000000LL +#define IMX335_LINK_FREQ_445MHz 445500000LL + #define IMX335_NUM_DATA_LANES 4 #define IMX335_REG_MIN 0x00 @@ -99,7 +116,6 @@ static const char * const imx335_supply_name[] = { * @vblank_min: Minimum vertical blanking in lines * @vblank_max: Maximum vertical blanking in lines * @pclk: Sensor pixel clock - * @link_freq_idx: Link frequency index * @reg_list: Register list for sensor mode */ struct imx335_mode { @@ -111,7 +127,6 @@ struct imx335_mode { u32 vblank_min; u32 vblank_max; u64 pclk; - u32 link_freq_idx; struct imx335_reg_list reg_list; }; @@ -134,6 +149,7 @@ struct imx335_mode { * @vblank: Vertical blanking in lines * @cur_mode: Pointer to current selected sensor mode * @mutex: Mutex for serializing sensor controls + * @link_freq_bitmap: Menu bitmap for link_freq_ctrl * @cur_mbus_code: Currently selected media bus format code */ struct imx335 { @@ -157,19 +173,46 @@ struct imx335 { u32 vblank; const struct imx335_mode *cur_mode; struct mutex mutex; + unsigned long link_freq_bitmap; u32 cur_mbus_code; }; -static const s64 link_freq[] = { - IMX335_LINK_FREQ, +static const char * const imx335_tpg_menu[] = { + "Disabled", + "All 000h", + "All FFFh", + "All 555h", + "All AAAh", + "Toggle 555/AAAh", + "Toggle AAA/555h", + "Toggle 000/555h", + "Toggle 555/000h", + "Toggle 000/FFFh", + "Toggle FFF/000h", + "Horizontal color bars", + "Vertical color bars", +}; + +static const int imx335_tpg_val[] = { + IMX335_TPG_ALL_000, + IMX335_TPG_ALL_000, + IMX335_TPG_ALL_FFF, + IMX335_TPG_ALL_555, + IMX335_TPG_ALL_AAA, + IMX335_TPG_TOG_555_AAA, + IMX335_TPG_TOG_AAA_555, + IMX335_TPG_TOG_000_555, + IMX335_TPG_TOG_555_000, + IMX335_TPG_TOG_000_FFF, + IMX335_TPG_TOG_FFF_000, + IMX335_TPG_H_COLOR_BARS, + IMX335_TPG_V_COLOR_BARS, }; /* Sensor mode registers */ static const struct imx335_reg mode_2592x1940_regs[] = { {0x3000, 0x01}, {0x3002, 0x00}, - {0x300c, 0x3b}, - {0x300d, 0x2a}, {0x3018, 0x04}, {0x302c, 0x3c}, {0x302e, 0x20}, @@ -177,10 +220,6 @@ static const struct imx335_reg mode_2592x1940_regs[] = { {0x3074, 0xc8}, {0x3076, 0x28}, {0x304c, 0x00}, - {0x314c, 0xc6}, - {0x315a, 0x02}, - {0x3168, 0xa0}, - {0x316a, 0x7e}, {0x31a1, 0x00}, {0x3288, 0x21}, {0x328a, 0x02}, @@ -249,7 +288,7 @@ static const struct imx335_reg mode_2592x1940_regs[] = { {0x3794, 0x7a}, {0x3796, 0xa1}, {0x37b0, 0x36}, - {0x3a00, 0x01}, + {0x3a00, 0x00}, }; static const struct imx335_reg raw10_framefmt_regs[] = { @@ -266,6 +305,65 @@ static const struct imx335_reg raw12_framefmt_regs[] = { {0x341d, 0x00}, }; +static const struct imx335_reg mipi_data_rate_1188Mbps[] = { + {0x300c, 0x3b}, + {0x300d, 0x2a}, + {0x314c, 0xc6}, + {0x314d, 0x00}, + {0x315a, 0x02}, + {0x3168, 0xa0}, + {0x316a, 0x7e}, + {0x319e, 0x01}, + {0x3a18, 0x8f}, + {0x3a1a, 0x4f}, + {0x3a1c, 0x47}, + {0x3a1e, 0x37}, + {0x3a1f, 0x01}, + {0x3a20, 0x4f}, + {0x3a22, 0x87}, + {0x3a24, 0x4f}, + {0x3a26, 0x7f}, + {0x3a28, 0x3f}, +}; + +static const struct imx335_reg mipi_data_rate_891Mbps[] = { + {0x300c, 0x3b}, + {0x300d, 0x2a}, + {0x314c, 0x29}, + {0x314d, 0x01}, + {0x315a, 0x06}, + {0x3168, 0xa0}, + {0x316a, 0x7e}, + {0x319e, 0x02}, + {0x3a18, 0x7f}, + {0x3a1a, 0x37}, + {0x3a1c, 0x37}, + {0x3a1e, 0xf7}, + {0x3a20, 0x3f}, + {0x3a22, 0x6f}, + {0x3a24, 0x3f}, + {0x3a26, 0x5f}, + {0x3a28, 0x2f}, +}; + +static const s64 link_freq[] = { + /* Corresponds to 1188Mbps data lane rate */ + IMX335_LINK_FREQ_594MHz, + /* Corresponds to 891Mbps data lane rate */ + IMX335_LINK_FREQ_445MHz, +}; + +static const struct imx335_reg_list link_freq_reglist[] = { + { + .num_of_regs = ARRAY_SIZE(mipi_data_rate_1188Mbps), + .regs = mipi_data_rate_1188Mbps, + }, + { + .num_of_regs = ARRAY_SIZE(mipi_data_rate_891Mbps), + .regs = mipi_data_rate_891Mbps, + }, +}; + static const u32 imx335_mbus_codes[] = { MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB10_1X10, @@ -280,7 +378,6 @@ static const struct imx335_mode supported_mode = { .vblank_min = 2560, .vblank_max = 133060, .pclk = 396000000, - .link_freq_idx = 0, .reg_list = { .num_of_regs = ARRAY_SIZE(mode_2592x1940_regs), .regs = mode_2592x1940_regs, @@ -405,7 +502,8 @@ static int imx335_update_controls(struct imx335 *imx335, { int ret; - ret = __v4l2_ctrl_s_ctrl(imx335->link_freq_ctrl, mode->link_freq_idx); + ret = __v4l2_ctrl_s_ctrl(imx335->link_freq_ctrl, + __ffs(imx335->link_freq_bitmap)); if (ret) return ret; @@ -456,6 +554,49 @@ error_release_group_hold: return ret; } +static int imx335_update_test_pattern(struct imx335 *imx335, u32 pattern_index) +{ + int ret; + + if (pattern_index >= ARRAY_SIZE(imx335_tpg_val)) + return -EINVAL; + + if (pattern_index) { + const struct imx335_reg tpg_enable_regs[] = { + { 0x3148, 0x10 }, + { 0x3280, 0x00 }, + { 0x329c, 0x01 }, + { 0x32a0, 0x11 }, + { 0x3302, 0x00 }, + { 0x3303, 0x00 }, + { 0x336c, 0x00 }, + }; + + ret = imx335_write_reg(imx335, IMX335_REG_TPG, 1, + imx335_tpg_val[pattern_index]); + if (ret) + return ret; + + ret = imx335_write_regs(imx335, tpg_enable_regs, + ARRAY_SIZE(tpg_enable_regs)); + } else { + const struct imx335_reg tpg_disable_regs[] = { + { 0x3148, 0x00 }, + { 0x3280, 0x01 }, + { 0x329c, 0x00 }, + { 0x32a0, 0x10 }, + { 0x3302, 0x32 }, + { 0x3303, 0x00 }, + { 0x336c, 0x01 }, + }; + + ret = imx335_write_regs(imx335, tpg_disable_regs, + ARRAY_SIZE(tpg_disable_regs)); + } + + return ret; +} + /** * imx335_set_ctrl() - Set subdevice control * @ctrl: pointer to v4l2_ctrl structure @@ -476,26 +617,31 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl) u32 exposure; int ret; - switch (ctrl->id) { - case V4L2_CID_VBLANK: + /* Propagate change of current control to all related controls */ + if (ctrl->id == V4L2_CID_VBLANK) { imx335->vblank = imx335->vblank_ctrl->val; dev_dbg(imx335->dev, "Received vblank %u, new lpfr %u\n", imx335->vblank, imx335->vblank + imx335->cur_mode->height); - ret = __v4l2_ctrl_modify_range(imx335->exp_ctrl, - IMX335_EXPOSURE_MIN, - imx335->vblank + - imx335->cur_mode->height - - IMX335_EXPOSURE_OFFSET, - 1, IMX335_EXPOSURE_DEFAULT); - break; - case V4L2_CID_EXPOSURE: - /* Set controls only if sensor is in power on state */ - if (!pm_runtime_get_if_in_use(imx335->dev)) - return 0; + return __v4l2_ctrl_modify_range(imx335->exp_ctrl, + IMX335_EXPOSURE_MIN, + imx335->vblank + + imx335->cur_mode->height - + IMX335_EXPOSURE_OFFSET, + 1, IMX335_EXPOSURE_DEFAULT); + } + /* + * Applying V4L2 control value only happens + * when power is up for streaming. + */ + if (pm_runtime_get_if_in_use(imx335->dev) == 0) + return 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: exposure = ctrl->val; analog_gain = imx335->again_ctrl->val; @@ -504,7 +650,9 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl) ret = imx335_update_exp_gain(imx335, exposure, analog_gain); - pm_runtime_put(imx335->dev); + break; + case V4L2_CID_TEST_PATTERN: + ret = imx335_update_test_pattern(imx335, ctrl->val); break; default: @@ -512,6 +660,8 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl) ret = -EINVAL; } + pm_runtime_put(imx335->dev); + return ret; } @@ -691,6 +841,13 @@ static int imx335_init_state(struct v4l2_subdev *sd, fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; imx335_fill_pad_format(imx335, &supported_mode, &fmt); + mutex_lock(&imx335->mutex); + __v4l2_ctrl_modify_range(imx335->link_freq_ctrl, 0, + __fls(imx335->link_freq_bitmap), + ~(imx335->link_freq_bitmap), + __ffs(imx335->link_freq_bitmap)); + mutex_unlock(&imx335->mutex); + return imx335_set_pad_format(sd, sd_state, &fmt); } @@ -755,6 +912,14 @@ static int imx335_start_streaming(struct imx335 *imx335) const struct imx335_reg_list *reg_list; int ret; + /* Setup PLL */ + reg_list = &link_freq_reglist[__ffs(imx335->link_freq_bitmap)]; + ret = imx335_write_regs(imx335, reg_list->regs, reg_list->num_of_regs); + if (ret) { + dev_err(imx335->dev, "%s failed to set plls\n", __func__); + return ret; + } + /* Write sensor mode registers */ reg_list = &imx335->cur_mode->reg_list; ret = imx335_write_regs(imx335, reg_list->regs, @@ -939,19 +1104,10 @@ static int imx335_parse_hw_config(struct imx335 *imx335) goto done_endpoint_free; } - if (!bus_cfg.nr_of_link_frequencies) { - dev_err(imx335->dev, "no link frequencies defined\n"); - ret = -EINVAL; - goto done_endpoint_free; - } - - for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) - if (bus_cfg.link_frequencies[i] == IMX335_LINK_FREQ) - goto done_endpoint_free; - - dev_err(imx335->dev, "no compatible link frequencies found\n"); - - ret = -EINVAL; + ret = v4l2_link_freq_to_bitmap(imx335->dev, bus_cfg.link_frequencies, + bus_cfg.nr_of_link_frequencies, + link_freq, ARRAY_SIZE(link_freq), + &imx335->link_freq_bitmap); done_endpoint_free: v4l2_fwnode_endpoint_free(&bus_cfg); @@ -1055,7 +1211,7 @@ static int imx335_init_controls(struct imx335 *imx335) u32 lpfr; int ret; - ret = v4l2_ctrl_handler_init(ctrl_hdlr, 6); + ret = v4l2_ctrl_handler_init(ctrl_hdlr, 7); if (ret) return ret; @@ -1089,6 +1245,12 @@ static int imx335_init_controls(struct imx335 *imx335) mode->vblank_max, 1, mode->vblank); + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, + &imx335_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(imx335_tpg_menu) - 1, + 0, 0, imx335_tpg_menu); + /* Read only controls */ imx335->pclk_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, &imx335_ctrl_ops, @@ -1099,9 +1261,8 @@ static int imx335_init_controls(struct imx335 *imx335) imx335->link_freq_ctrl = v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx335_ctrl_ops, V4L2_CID_LINK_FREQ, - ARRAY_SIZE(link_freq) - - 1, - mode->link_freq_idx, + __fls(imx335->link_freq_bitmap), + __ffs(imx335->link_freq_bitmap), link_freq); if (imx335->link_freq_ctrl) imx335->link_freq_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; diff --git a/drivers/media/i2c/imx355.c b/drivers/media/i2c/imx355.c index 8c995c5874..7e9c2f65fa 100644 --- a/drivers/media/i2c/imx355.c +++ b/drivers/media/i2c/imx355.c @@ -56,7 +56,7 @@ #define IMX355_REG_ORIENTATION 0x0101 /* default link frequency and external clock */ -#define IMX355_LINK_FREQ_DEFAULT 360000000 +#define IMX355_LINK_FREQ_DEFAULT 360000000LL #define IMX355_EXT_CLK 19200000 #define IMX355_LINK_FREQ_INDEX 0 @@ -93,8 +93,7 @@ struct imx355_mode { struct imx355_hwcfg { u32 ext_clk; /* sensor external clk */ - s64 *link_freqs; /* CSI-2 link frequencies */ - unsigned int nr_of_link_freqs; + unsigned long link_freq_bitmap; }; struct imx355 { @@ -115,7 +114,6 @@ struct imx355 { const struct imx355_mode *cur_mode; struct imx355_hwcfg *hwcfg; - s64 link_def_freq; /* CSI-2 link default frequency */ /* * Mutex for serialized access: @@ -879,7 +877,10 @@ static const char * const imx355_test_pattern_menu[] = { "Pseudorandom Sequence (PN9)", }; -/* supported link frequencies */ +/* + * When adding more than the one below, make sure the disallowed ones will + * actually be disabled in the LINK_FREQ control. + */ static const s64 link_freq_menu_items[] = { IMX355_LINK_FREQ_DEFAULT, }; @@ -1356,7 +1357,7 @@ imx355_set_pad_format(struct v4l2_subdev *sd, *framefmt = fmt->format; } else { imx355->cur_mode = mode; - pixel_rate = imx355->link_def_freq * 2 * 4; + pixel_rate = IMX355_LINK_FREQ_DEFAULT * 2 * 4; do_div(pixel_rate, 10); __v4l2_ctrl_s_ctrl_int64(imx355->pixel_rate, pixel_rate); /* Update limits and set FPS to default */ @@ -1543,7 +1544,7 @@ static int imx355_init_controls(struct imx355 *imx355) imx355->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */ - pixel_rate = imx355->link_def_freq * 2 * 4; + pixel_rate = IMX355_LINK_FREQ_DEFAULT * 2 * 4; do_div(pixel_rate, 10); /* By default, PIXEL_RATE is read only */ imx355->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops, @@ -1620,7 +1621,6 @@ static struct imx355_hwcfg *imx355_get_hwcfg(struct device *dev) }; struct fwnode_handle *ep; struct fwnode_handle *fwnode = dev_fwnode(dev); - unsigned int i; int ret; if (!fwnode) @@ -1652,24 +1652,14 @@ static struct imx355_hwcfg *imx355_get_hwcfg(struct device *dev) goto out_err; } - dev_dbg(dev, "num of link freqs: %d", bus_cfg.nr_of_link_frequencies); - if (!bus_cfg.nr_of_link_frequencies) { - dev_warn(dev, "no link frequencies defined"); - goto out_err; - } - - cfg->nr_of_link_freqs = bus_cfg.nr_of_link_frequencies; - cfg->link_freqs = devm_kcalloc(dev, - bus_cfg.nr_of_link_frequencies + 1, - sizeof(*cfg->link_freqs), GFP_KERNEL); - if (!cfg->link_freqs) + ret = v4l2_link_freq_to_bitmap(dev, bus_cfg.link_frequencies, + bus_cfg.nr_of_link_frequencies, + link_freq_menu_items, + ARRAY_SIZE(link_freq_menu_items), + &cfg->link_freq_bitmap); + if (ret) goto out_err; - for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) { - cfg->link_freqs[i] = bus_cfg.link_frequencies[i]; - dev_dbg(dev, "link_freq[%d] = %lld", i, cfg->link_freqs[i]); - } - v4l2_fwnode_endpoint_free(&bus_cfg); fwnode_handle_put(ep); return cfg; @@ -1684,7 +1674,6 @@ static int imx355_probe(struct i2c_client *client) { struct imx355 *imx355; int ret; - u32 i; imx355 = devm_kzalloc(&client->dev, sizeof(*imx355), GFP_KERNEL); if (!imx355) @@ -1709,20 +1698,6 @@ static int imx355_probe(struct i2c_client *client) goto error_probe; } - imx355->link_def_freq = link_freq_menu_items[IMX355_LINK_FREQ_INDEX]; - for (i = 0; i < imx355->hwcfg->nr_of_link_freqs; i++) { - if (imx355->hwcfg->link_freqs[i] == imx355->link_def_freq) { - dev_dbg(&client->dev, "link freq index %d matched", i); - break; - } - } - - if (i == imx355->hwcfg->nr_of_link_freqs) { - dev_err(&client->dev, "no link frequency supported"); - ret = -EINVAL; - goto error_probe; - } - /* Set default mode to max resolution */ imx355->cur_mode = &supported_modes[0]; diff --git a/drivers/media/i2c/imx415.c b/drivers/media/i2c/imx415.c index 1e5f20c3ed..a20b0db330 100644 --- a/drivers/media/i2c/imx415.c +++ b/drivers/media/i2c/imx415.c @@ -16,6 +16,7 @@ #include <linux/slab.h> #include <linux/videodev2.h> +#include <media/v4l2-cci.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-fwnode.h> #include <media/v4l2-subdev.h> @@ -28,76 +29,65 @@ #define IMX415_NUM_CLK_PARAM_REGS 11 -#define IMX415_REG_8BIT(n) ((1 << 16) | (n)) -#define IMX415_REG_16BIT(n) ((2 << 16) | (n)) -#define IMX415_REG_24BIT(n) ((3 << 16) | (n)) -#define IMX415_REG_SIZE_SHIFT 16 -#define IMX415_REG_ADDR_MASK 0xffff - -#define IMX415_MODE IMX415_REG_8BIT(0x3000) +#define IMX415_MODE CCI_REG8(0x3000) #define IMX415_MODE_OPERATING (0) #define IMX415_MODE_STANDBY BIT(0) -#define IMX415_REGHOLD IMX415_REG_8BIT(0x3001) +#define IMX415_REGHOLD CCI_REG8(0x3001) #define IMX415_REGHOLD_INVALID (0) #define IMX415_REGHOLD_VALID BIT(0) -#define IMX415_XMSTA IMX415_REG_8BIT(0x3002) +#define IMX415_XMSTA CCI_REG8(0x3002) #define IMX415_XMSTA_START (0) #define IMX415_XMSTA_STOP BIT(0) -#define IMX415_BCWAIT_TIME IMX415_REG_16BIT(0x3008) -#define IMX415_CPWAIT_TIME IMX415_REG_16BIT(0x300A) -#define IMX415_WINMODE IMX415_REG_8BIT(0x301C) -#define IMX415_ADDMODE IMX415_REG_8BIT(0x3022) -#define IMX415_REVERSE IMX415_REG_8BIT(0x3030) +#define IMX415_BCWAIT_TIME CCI_REG16_LE(0x3008) +#define IMX415_CPWAIT_TIME CCI_REG16_LE(0x300a) +#define IMX415_WINMODE CCI_REG8(0x301c) +#define IMX415_ADDMODE CCI_REG8(0x3022) +#define IMX415_REVERSE CCI_REG8(0x3030) #define IMX415_HREVERSE_SHIFT (0) #define IMX415_VREVERSE_SHIFT BIT(0) -#define IMX415_ADBIT IMX415_REG_8BIT(0x3031) -#define IMX415_MDBIT IMX415_REG_8BIT(0x3032) -#define IMX415_SYS_MODE IMX415_REG_8BIT(0x3033) -#define IMX415_OUTSEL IMX415_REG_8BIT(0x30C0) -#define IMX415_DRV IMX415_REG_8BIT(0x30C1) -#define IMX415_VMAX IMX415_REG_24BIT(0x3024) -#define IMX415_HMAX IMX415_REG_16BIT(0x3028) -#define IMX415_SHR0 IMX415_REG_24BIT(0x3050) -#define IMX415_GAIN_PCG_0 IMX415_REG_16BIT(0x3090) +#define IMX415_ADBIT CCI_REG8(0x3031) +#define IMX415_MDBIT CCI_REG8(0x3032) +#define IMX415_SYS_MODE CCI_REG8(0x3033) +#define IMX415_OUTSEL CCI_REG8(0x30c0) +#define IMX415_DRV CCI_REG8(0x30c1) +#define IMX415_VMAX CCI_REG24_LE(0x3024) +#define IMX415_HMAX CCI_REG16_LE(0x3028) +#define IMX415_SHR0 CCI_REG24_LE(0x3050) +#define IMX415_GAIN_PCG_0 CCI_REG16_LE(0x3090) #define IMX415_AGAIN_MIN 0 #define IMX415_AGAIN_MAX 100 #define IMX415_AGAIN_STEP 1 -#define IMX415_BLKLEVEL IMX415_REG_16BIT(0x30E2) +#define IMX415_BLKLEVEL CCI_REG16_LE(0x30e2) #define IMX415_BLKLEVEL_DEFAULT 50 -#define IMX415_TPG_EN_DUOUT IMX415_REG_8BIT(0x30E4) -#define IMX415_TPG_PATSEL_DUOUT IMX415_REG_8BIT(0x30E6) -#define IMX415_TPG_COLORWIDTH IMX415_REG_8BIT(0x30E8) -#define IMX415_TESTCLKEN_MIPI IMX415_REG_8BIT(0x3110) -#define IMX415_INCKSEL1 IMX415_REG_8BIT(0x3115) -#define IMX415_INCKSEL2 IMX415_REG_8BIT(0x3116) -#define IMX415_INCKSEL3 IMX415_REG_16BIT(0x3118) -#define IMX415_INCKSEL4 IMX415_REG_16BIT(0x311A) -#define IMX415_INCKSEL5 IMX415_REG_8BIT(0x311E) -#define IMX415_DIG_CLP_MODE IMX415_REG_8BIT(0x32C8) -#define IMX415_WRJ_OPEN IMX415_REG_8BIT(0x3390) -#define IMX415_SENSOR_INFO IMX415_REG_16BIT(0x3F12) -#define IMX415_SENSOR_INFO_MASK 0xFFF +#define IMX415_TPG_EN_DUOUT CCI_REG8(0x30e4) +#define IMX415_TPG_PATSEL_DUOUT CCI_REG8(0x30e6) +#define IMX415_TPG_COLORWIDTH CCI_REG8(0x30e8) +#define IMX415_TESTCLKEN_MIPI CCI_REG8(0x3110) +#define IMX415_INCKSEL1 CCI_REG8(0x3115) +#define IMX415_INCKSEL2 CCI_REG8(0x3116) +#define IMX415_INCKSEL3 CCI_REG16_LE(0x3118) +#define IMX415_INCKSEL4 CCI_REG16_LE(0x311a) +#define IMX415_INCKSEL5 CCI_REG8(0x311e) +#define IMX415_DIG_CLP_MODE CCI_REG8(0x32c8) +#define IMX415_WRJ_OPEN CCI_REG8(0x3390) +#define IMX415_SENSOR_INFO CCI_REG16_LE(0x3f12) +#define IMX415_SENSOR_INFO_MASK 0xfff #define IMX415_CHIP_ID 0x514 -#define IMX415_LANEMODE IMX415_REG_16BIT(0x4001) +#define IMX415_LANEMODE CCI_REG16_LE(0x4001) #define IMX415_LANEMODE_2 1 #define IMX415_LANEMODE_4 3 -#define IMX415_TXCLKESC_FREQ IMX415_REG_16BIT(0x4004) -#define IMX415_INCKSEL6 IMX415_REG_8BIT(0x400C) -#define IMX415_TCLKPOST IMX415_REG_16BIT(0x4018) -#define IMX415_TCLKPREPARE IMX415_REG_16BIT(0x401A) -#define IMX415_TCLKTRAIL IMX415_REG_16BIT(0x401C) -#define IMX415_TCLKZERO IMX415_REG_16BIT(0x401E) -#define IMX415_THSPREPARE IMX415_REG_16BIT(0x4020) -#define IMX415_THSZERO IMX415_REG_16BIT(0x4022) -#define IMX415_THSTRAIL IMX415_REG_16BIT(0x4024) -#define IMX415_THSEXIT IMX415_REG_16BIT(0x4026) -#define IMX415_TLPX IMX415_REG_16BIT(0x4028) -#define IMX415_INCKSEL7 IMX415_REG_8BIT(0x4074) - -struct imx415_reg { - u32 address; - u32 val; -}; +#define IMX415_TXCLKESC_FREQ CCI_REG16_LE(0x4004) +#define IMX415_INCKSEL6 CCI_REG8(0x400c) +#define IMX415_TCLKPOST CCI_REG16_LE(0x4018) +#define IMX415_TCLKPREPARE CCI_REG16_LE(0x401a) +#define IMX415_TCLKTRAIL CCI_REG16_LE(0x401c) +#define IMX415_TCLKZERO CCI_REG16_LE(0x401e) +#define IMX415_THSPREPARE CCI_REG16_LE(0x4020) +#define IMX415_THSZERO CCI_REG16_LE(0x4022) +#define IMX415_THSTRAIL CCI_REG16_LE(0x4024) +#define IMX415_THSEXIT CCI_REG16_LE(0x4026) +#define IMX415_TLPX CCI_REG16_LE(0x4028) +#define IMX415_INCKSEL7 CCI_REG8(0x4074) static const char *const imx415_supply_names[] = { "dvdd", @@ -118,13 +108,13 @@ static const s64 link_freq_menu_items[] = { struct imx415_clk_params { u64 lane_rate; u64 inck; - struct imx415_reg regs[IMX415_NUM_CLK_PARAM_REGS]; + struct cci_reg_sequence regs[IMX415_NUM_CLK_PARAM_REGS]; }; /* INCK Settings - includes all lane rate and INCK dependent registers */ static const struct imx415_clk_params imx415_clk_params[] = { { - .lane_rate = 594000000, + .lane_rate = 594000000UL, .inck = 27000000, .regs[0] = { IMX415_BCWAIT_TIME, 0x05D }, .regs[1] = { IMX415_CPWAIT_TIME, 0x042 }, @@ -139,7 +129,37 @@ static const struct imx415_clk_params imx415_clk_params[] = { .regs[10] = { IMX415_TXCLKESC_FREQ, 0x06C0 }, }, { - .lane_rate = 720000000, + .lane_rate = 594000000UL, + .inck = 37125000, + .regs[0] = { IMX415_BCWAIT_TIME, 0x07F }, + .regs[1] = { IMX415_CPWAIT_TIME, 0x05B }, + .regs[2] = { IMX415_SYS_MODE, 0x7 }, + .regs[3] = { IMX415_INCKSEL1, 0x00 }, + .regs[4] = { IMX415_INCKSEL2, 0x24 }, + .regs[5] = { IMX415_INCKSEL3, 0x080 }, + .regs[6] = { IMX415_INCKSEL4, 0x0E0 }, + .regs[7] = { IMX415_INCKSEL5, 0x24 }, + .regs[8] = { IMX415_INCKSEL6, 0x0 }, + .regs[9] = { IMX415_INCKSEL7, 0x1 }, + .regs[10] = { IMX415_TXCLKESC_FREQ, 0x0984 }, + }, + { + .lane_rate = 594000000UL, + .inck = 74250000, + .regs[0] = { IMX415_BCWAIT_TIME, 0x0FF }, + .regs[1] = { IMX415_CPWAIT_TIME, 0x0B6 }, + .regs[2] = { IMX415_SYS_MODE, 0x7 }, + .regs[3] = { IMX415_INCKSEL1, 0x00 }, + .regs[4] = { IMX415_INCKSEL2, 0x28 }, + .regs[5] = { IMX415_INCKSEL3, 0x080 }, + .regs[6] = { IMX415_INCKSEL4, 0x0E0 }, + .regs[7] = { IMX415_INCKSEL5, 0x28 }, + .regs[8] = { IMX415_INCKSEL6, 0x0 }, + .regs[9] = { IMX415_INCKSEL7, 0x1 }, + .regs[10] = { IMX415_TXCLKESC_FREQ, 0x1290 }, + }, + { + .lane_rate = 720000000UL, .inck = 24000000, .regs[0] = { IMX415_BCWAIT_TIME, 0x054 }, .regs[1] = { IMX415_CPWAIT_TIME, 0x03B }, @@ -154,7 +174,22 @@ static const struct imx415_clk_params imx415_clk_params[] = { .regs[10] = { IMX415_TXCLKESC_FREQ, 0x0600 }, }, { - .lane_rate = 891000000, + .lane_rate = 720000000UL, + .inck = 72000000, + .regs[0] = { IMX415_BCWAIT_TIME, 0x0F8 }, + .regs[1] = { IMX415_CPWAIT_TIME, 0x0B0 }, + .regs[2] = { IMX415_SYS_MODE, 0x9 }, + .regs[3] = { IMX415_INCKSEL1, 0x00 }, + .regs[4] = { IMX415_INCKSEL2, 0x28 }, + .regs[5] = { IMX415_INCKSEL3, 0x0A0 }, + .regs[6] = { IMX415_INCKSEL4, 0x0E0 }, + .regs[7] = { IMX415_INCKSEL5, 0x28 }, + .regs[8] = { IMX415_INCKSEL6, 0x0 }, + .regs[9] = { IMX415_INCKSEL7, 0x1 }, + .regs[10] = { IMX415_TXCLKESC_FREQ, 0x1200 }, + }, + { + .lane_rate = 891000000UL, .inck = 27000000, .regs[0] = { IMX415_BCWAIT_TIME, 0x05D }, .regs[1] = { IMX415_CPWAIT_TIME, 0x042 }, @@ -169,7 +204,37 @@ static const struct imx415_clk_params imx415_clk_params[] = { .regs[10] = { IMX415_TXCLKESC_FREQ, 0x06C0 }, }, { - .lane_rate = 1440000000, + .lane_rate = 891000000UL, + .inck = 37125000, + .regs[0] = { IMX415_BCWAIT_TIME, 0x07F }, + .regs[1] = { IMX415_CPWAIT_TIME, 0x05B }, + .regs[2] = { IMX415_SYS_MODE, 0x5 }, + .regs[3] = { IMX415_INCKSEL1, 0x00 }, + .regs[4] = { IMX415_INCKSEL2, 0x24 }, + .regs[5] = { IMX415_INCKSEL3, 0x0C0 }, + .regs[6] = { IMX415_INCKSEL4, 0x0E0 }, + .regs[7] = { IMX415_INCKSEL5, 0x24 }, + .regs[8] = { IMX415_INCKSEL6, 0x0 }, + .regs[9] = { IMX415_INCKSEL7, 0x1 }, + .regs[10] = { IMX415_TXCLKESC_FREQ, 0x0948 }, + }, + { + .lane_rate = 891000000UL, + .inck = 74250000, + .regs[0] = { IMX415_BCWAIT_TIME, 0x0FF }, + .regs[1] = { IMX415_CPWAIT_TIME, 0x0B6 }, + .regs[2] = { IMX415_SYS_MODE, 0x5 }, + .regs[3] = { IMX415_INCKSEL1, 0x00 }, + .regs[4] = { IMX415_INCKSEL2, 0x28 }, + .regs[5] = { IMX415_INCKSEL3, 0x0C0 }, + .regs[6] = { IMX415_INCKSEL4, 0x0E0 }, + .regs[7] = { IMX415_INCKSEL5, 0x28 }, + .regs[8] = { IMX415_INCKSEL6, 0x0 }, + .regs[9] = { IMX415_INCKSEL7, 0x1 }, + .regs[10] = { IMX415_TXCLKESC_FREQ, 0x1290 }, + }, + { + .lane_rate = 1440000000UL, .inck = 24000000, .regs[0] = { IMX415_BCWAIT_TIME, 0x054 }, .regs[1] = { IMX415_CPWAIT_TIME, 0x03B }, @@ -184,7 +249,22 @@ static const struct imx415_clk_params imx415_clk_params[] = { .regs[10] = { IMX415_TXCLKESC_FREQ, 0x0600 }, }, { - .lane_rate = 1485000000, + .lane_rate = 1440000000UL, + .inck = 72000000, + .regs[0] = { IMX415_BCWAIT_TIME, 0x0F8 }, + .regs[1] = { IMX415_CPWAIT_TIME, 0x0B0 }, + .regs[2] = { IMX415_SYS_MODE, 0x8 }, + .regs[3] = { IMX415_INCKSEL1, 0x00 }, + .regs[4] = { IMX415_INCKSEL2, 0x28 }, + .regs[5] = { IMX415_INCKSEL3, 0x0A0 }, + .regs[6] = { IMX415_INCKSEL4, 0x0E0 }, + .regs[7] = { IMX415_INCKSEL5, 0x28 }, + .regs[8] = { IMX415_INCKSEL6, 0x1 }, + .regs[9] = { IMX415_INCKSEL7, 0x0 }, + .regs[10] = { IMX415_TXCLKESC_FREQ, 0x1200 }, + }, + { + .lane_rate = 1485000000UL, .inck = 27000000, .regs[0] = { IMX415_BCWAIT_TIME, 0x05D }, .regs[1] = { IMX415_CPWAIT_TIME, 0x042 }, @@ -198,10 +278,175 @@ static const struct imx415_clk_params imx415_clk_params[] = { .regs[9] = { IMX415_INCKSEL7, 0x0 }, .regs[10] = { IMX415_TXCLKESC_FREQ, 0x06C0 }, }, + { + .lane_rate = 1485000000UL, + .inck = 37125000, + .regs[0] = { IMX415_BCWAIT_TIME, 0x07F }, + .regs[1] = { IMX415_CPWAIT_TIME, 0x05B }, + .regs[2] = { IMX415_SYS_MODE, 0x8 }, + .regs[3] = { IMX415_INCKSEL1, 0x00 }, + .regs[4] = { IMX415_INCKSEL2, 0x24 }, + .regs[5] = { IMX415_INCKSEL3, 0x0A0 }, + .regs[6] = { IMX415_INCKSEL4, 0x0E0 }, + .regs[7] = { IMX415_INCKSEL5, 0x24 }, + .regs[8] = { IMX415_INCKSEL6, 0x1 }, + .regs[9] = { IMX415_INCKSEL7, 0x0 }, + .regs[10] = { IMX415_TXCLKESC_FREQ, 0x0948 }, + }, + { + .lane_rate = 1485000000UL, + .inck = 74250000, + .regs[0] = { IMX415_BCWAIT_TIME, 0x0FF }, + .regs[1] = { IMX415_CPWAIT_TIME, 0x0B6 }, + .regs[2] = { IMX415_SYS_MODE, 0x8 }, + .regs[3] = { IMX415_INCKSEL1, 0x00 }, + .regs[4] = { IMX415_INCKSEL2, 0x28 }, + .regs[5] = { IMX415_INCKSEL3, 0x0A0 }, + .regs[6] = { IMX415_INCKSEL4, 0x0E0 }, + .regs[7] = { IMX415_INCKSEL5, 0x28 }, + .regs[8] = { IMX415_INCKSEL6, 0x1 }, + .regs[9] = { IMX415_INCKSEL7, 0x0 }, + .regs[10] = { IMX415_TXCLKESC_FREQ, 0x1290 }, + }, + { + .lane_rate = 1782000000UL, + .inck = 27000000, + .regs[0] = { IMX415_BCWAIT_TIME, 0x05D }, + .regs[1] = { IMX415_CPWAIT_TIME, 0x042 }, + .regs[2] = { IMX415_SYS_MODE, 0x4 }, + .regs[3] = { IMX415_INCKSEL1, 0x00 }, + .regs[4] = { IMX415_INCKSEL2, 0x23 }, + .regs[5] = { IMX415_INCKSEL3, 0x0C6 }, + .regs[6] = { IMX415_INCKSEL4, 0x0E7 }, + .regs[7] = { IMX415_INCKSEL5, 0x23 }, + .regs[8] = { IMX415_INCKSEL6, 0x1 }, + .regs[9] = { IMX415_INCKSEL7, 0x0 }, + .regs[10] = { IMX415_TXCLKESC_FREQ, 0x06C0 }, + }, + { + .lane_rate = 1782000000UL, + .inck = 37125000, + .regs[0] = { IMX415_BCWAIT_TIME, 0x07F }, + .regs[1] = { IMX415_CPWAIT_TIME, 0x05B }, + .regs[2] = { IMX415_SYS_MODE, 0x4 }, + .regs[3] = { IMX415_INCKSEL1, 0x00 }, + .regs[4] = { IMX415_INCKSEL2, 0x24 }, + .regs[5] = { IMX415_INCKSEL3, 0x0C0 }, + .regs[6] = { IMX415_INCKSEL4, 0x0E0 }, + .regs[7] = { IMX415_INCKSEL5, 0x24 }, + .regs[8] = { IMX415_INCKSEL6, 0x1 }, + .regs[9] = { IMX415_INCKSEL7, 0x0 }, + .regs[10] = { IMX415_TXCLKESC_FREQ, 0x0948 }, + }, + { + .lane_rate = 1782000000UL, + .inck = 74250000, + .regs[0] = { IMX415_BCWAIT_TIME, 0x0FF }, + .regs[1] = { IMX415_CPWAIT_TIME, 0x0B6 }, + .regs[2] = { IMX415_SYS_MODE, 0x4 }, + .regs[3] = { IMX415_INCKSEL1, 0x00 }, + .regs[4] = { IMX415_INCKSEL2, 0x28 }, + .regs[5] = { IMX415_INCKSEL3, 0x0C0 }, + .regs[6] = { IMX415_INCKSEL4, 0x0E0 }, + .regs[7] = { IMX415_INCKSEL5, 0x28 }, + .regs[8] = { IMX415_INCKSEL6, 0x1 }, + .regs[9] = { IMX415_INCKSEL7, 0x0 }, + .regs[10] = { IMX415_TXCLKESC_FREQ, 0x1290 }, + }, + { + .lane_rate = 2079000000UL, + .inck = 27000000, + .regs[0] = { IMX415_BCWAIT_TIME, 0x05D }, + .regs[1] = { IMX415_CPWAIT_TIME, 0x042 }, + .regs[2] = { IMX415_SYS_MODE, 0x2 }, + .regs[3] = { IMX415_INCKSEL1, 0x00 }, + .regs[4] = { IMX415_INCKSEL2, 0x23 }, + .regs[5] = { IMX415_INCKSEL3, 0x0E7 }, + .regs[6] = { IMX415_INCKSEL4, 0x0E7 }, + .regs[7] = { IMX415_INCKSEL5, 0x23 }, + .regs[8] = { IMX415_INCKSEL6, 0x1 }, + .regs[9] = { IMX415_INCKSEL7, 0x0 }, + .regs[10] = { IMX415_TXCLKESC_FREQ, 0x06C0 }, + }, + { + .lane_rate = 2079000000UL, + .inck = 37125000, + .regs[0] = { IMX415_BCWAIT_TIME, 0x07F }, + .regs[1] = { IMX415_CPWAIT_TIME, 0x05B }, + .regs[2] = { IMX415_SYS_MODE, 0x2 }, + .regs[3] = { IMX415_INCKSEL1, 0x00 }, + .regs[4] = { IMX415_INCKSEL2, 0x24 }, + .regs[5] = { IMX415_INCKSEL3, 0x0E0 }, + .regs[6] = { IMX415_INCKSEL4, 0x0E0 }, + .regs[7] = { IMX415_INCKSEL5, 0x24 }, + .regs[8] = { IMX415_INCKSEL6, 0x1 }, + .regs[9] = { IMX415_INCKSEL7, 0x0 }, + .regs[10] = { IMX415_TXCLKESC_FREQ, 0x0948 }, + }, + { + .lane_rate = 2079000000UL, + .inck = 74250000, + .regs[0] = { IMX415_BCWAIT_TIME, 0x0FF }, + .regs[1] = { IMX415_CPWAIT_TIME, 0x0B6 }, + .regs[2] = { IMX415_SYS_MODE, 0x2 }, + .regs[3] = { IMX415_INCKSEL1, 0x00 }, + .regs[4] = { IMX415_INCKSEL2, 0x28 }, + .regs[5] = { IMX415_INCKSEL3, 0x0E0 }, + .regs[6] = { IMX415_INCKSEL4, 0x0E0 }, + .regs[7] = { IMX415_INCKSEL5, 0x28 }, + .regs[8] = { IMX415_INCKSEL6, 0x1 }, + .regs[9] = { IMX415_INCKSEL7, 0x0 }, + .regs[10] = { IMX415_TXCLKESC_FREQ, 0x1290 }, + }, + { + .lane_rate = 2376000000UL, + .inck = 27000000, + .regs[0] = { IMX415_BCWAIT_TIME, 0x05D }, + .regs[1] = { IMX415_CPWAIT_TIME, 0x042 }, + .regs[2] = { IMX415_SYS_MODE, 0x0 }, + .regs[3] = { IMX415_INCKSEL1, 0x00 }, + .regs[4] = { IMX415_INCKSEL2, 0x23 }, + .regs[5] = { IMX415_INCKSEL3, 0x108 }, + .regs[6] = { IMX415_INCKSEL4, 0x0E7 }, + .regs[7] = { IMX415_INCKSEL5, 0x23 }, + .regs[8] = { IMX415_INCKSEL6, 0x1 }, + .regs[9] = { IMX415_INCKSEL7, 0x0 }, + .regs[10] = { IMX415_TXCLKESC_FREQ, 0x06C0 }, + }, + { + .lane_rate = 2376000000UL, + .inck = 37125000, + .regs[0] = { IMX415_BCWAIT_TIME, 0x07F }, + .regs[1] = { IMX415_CPWAIT_TIME, 0x05B }, + .regs[2] = { IMX415_SYS_MODE, 0x0 }, + .regs[3] = { IMX415_INCKSEL1, 0x00 }, + .regs[4] = { IMX415_INCKSEL2, 0x24 }, + .regs[5] = { IMX415_INCKSEL3, 0x100 }, + .regs[6] = { IMX415_INCKSEL4, 0x0E0 }, + .regs[7] = { IMX415_INCKSEL5, 0x24 }, + .regs[8] = { IMX415_INCKSEL6, 0x1 }, + .regs[9] = { IMX415_INCKSEL7, 0x0 }, + .regs[10] = { IMX415_TXCLKESC_FREQ, 0x0948 }, + }, + { + .lane_rate = 2376000000UL, + .inck = 74250000, + .regs[0] = { IMX415_BCWAIT_TIME, 0x0FF }, + .regs[1] = { IMX415_CPWAIT_TIME, 0x0B6 }, + .regs[2] = { IMX415_SYS_MODE, 0x0 }, + .regs[3] = { IMX415_INCKSEL1, 0x00 }, + .regs[4] = { IMX415_INCKSEL2, 0x28 }, + .regs[5] = { IMX415_INCKSEL3, 0x100 }, + .regs[6] = { IMX415_INCKSEL4, 0x0E0 }, + .regs[7] = { IMX415_INCKSEL5, 0x28 }, + .regs[8] = { IMX415_INCKSEL6, 0x1 }, + .regs[9] = { IMX415_INCKSEL7, 0x0 }, + .regs[10] = { IMX415_TXCLKESC_FREQ, 0x1290 }, + }, }; /* all-pixel 2-lane 720 Mbps 15.74 Hz mode */ -static const struct imx415_reg imx415_mode_2_720[] = { +static const struct cci_reg_sequence imx415_mode_2_720[] = { { IMX415_VMAX, 0x08CA }, { IMX415_HMAX, 0x07F0 }, { IMX415_LANEMODE, IMX415_LANEMODE_2 }, @@ -217,7 +462,7 @@ static const struct imx415_reg imx415_mode_2_720[] = { }; /* all-pixel 2-lane 1440 Mbps 30.01 Hz mode */ -static const struct imx415_reg imx415_mode_2_1440[] = { +static const struct cci_reg_sequence imx415_mode_2_1440[] = { { IMX415_VMAX, 0x08CA }, { IMX415_HMAX, 0x042A }, { IMX415_LANEMODE, IMX415_LANEMODE_2 }, @@ -233,7 +478,7 @@ static const struct imx415_reg imx415_mode_2_1440[] = { }; /* all-pixel 4-lane 891 Mbps 30 Hz mode */ -static const struct imx415_reg imx415_mode_4_891[] = { +static const struct cci_reg_sequence imx415_mode_4_891[] = { { IMX415_VMAX, 0x08CA }, { IMX415_HMAX, 0x044C }, { IMX415_LANEMODE, IMX415_LANEMODE_4 }, @@ -250,7 +495,7 @@ static const struct imx415_reg imx415_mode_4_891[] = { struct imx415_mode_reg_list { u32 num_of_regs; - const struct imx415_reg *regs; + const struct cci_reg_sequence *regs; }; /* @@ -323,11 +568,6 @@ static const struct imx415_mode supported_modes[] = { }, }; -static const struct regmap_config imx415_regmap_config = { - .reg_bits = 16, - .val_bits = 8, -}; - static const char *const imx415_test_pattern_menu[] = { "disabled", "solid black", @@ -369,7 +609,7 @@ struct imx415 { * This table includes fixed register settings and a bunch of undocumented * registers that have to be set to another value than default. */ -static const struct imx415_reg imx415_init_table[] = { +static const struct cci_reg_sequence imx415_init_table[] = { /* use all-pixel readout mode, no flip */ { IMX415_WINMODE, 0x00 }, { IMX415_ADDMODE, 0x00 }, @@ -382,77 +622,77 @@ static const struct imx415_reg imx415_init_table[] = { { IMX415_DRV, 0x00 }, /* SONY magic registers */ - { IMX415_REG_8BIT(0x32D4), 0x21 }, - { IMX415_REG_8BIT(0x32EC), 0xA1 }, - { IMX415_REG_8BIT(0x3452), 0x7F }, - { IMX415_REG_8BIT(0x3453), 0x03 }, - { IMX415_REG_8BIT(0x358A), 0x04 }, - { IMX415_REG_8BIT(0x35A1), 0x02 }, - { IMX415_REG_8BIT(0x36BC), 0x0C }, - { IMX415_REG_8BIT(0x36CC), 0x53 }, - { IMX415_REG_8BIT(0x36CD), 0x00 }, - { IMX415_REG_8BIT(0x36CE), 0x3C }, - { IMX415_REG_8BIT(0x36D0), 0x8C }, - { IMX415_REG_8BIT(0x36D1), 0x00 }, - { IMX415_REG_8BIT(0x36D2), 0x71 }, - { IMX415_REG_8BIT(0x36D4), 0x3C }, - { IMX415_REG_8BIT(0x36D6), 0x53 }, - { IMX415_REG_8BIT(0x36D7), 0x00 }, - { IMX415_REG_8BIT(0x36D8), 0x71 }, - { IMX415_REG_8BIT(0x36DA), 0x8C }, - { IMX415_REG_8BIT(0x36DB), 0x00 }, - { IMX415_REG_8BIT(0x3724), 0x02 }, - { IMX415_REG_8BIT(0x3726), 0x02 }, - { IMX415_REG_8BIT(0x3732), 0x02 }, - { IMX415_REG_8BIT(0x3734), 0x03 }, - { IMX415_REG_8BIT(0x3736), 0x03 }, - { IMX415_REG_8BIT(0x3742), 0x03 }, - { IMX415_REG_8BIT(0x3862), 0xE0 }, - { IMX415_REG_8BIT(0x38CC), 0x30 }, - { IMX415_REG_8BIT(0x38CD), 0x2F }, - { IMX415_REG_8BIT(0x395C), 0x0C }, - { IMX415_REG_8BIT(0x3A42), 0xD1 }, - { IMX415_REG_8BIT(0x3A4C), 0x77 }, - { IMX415_REG_8BIT(0x3AE0), 0x02 }, - { IMX415_REG_8BIT(0x3AEC), 0x0C }, - { IMX415_REG_8BIT(0x3B00), 0x2E }, - { IMX415_REG_8BIT(0x3B06), 0x29 }, - { IMX415_REG_8BIT(0x3B98), 0x25 }, - { IMX415_REG_8BIT(0x3B99), 0x21 }, - { IMX415_REG_8BIT(0x3B9B), 0x13 }, - { IMX415_REG_8BIT(0x3B9C), 0x13 }, - { IMX415_REG_8BIT(0x3B9D), 0x13 }, - { IMX415_REG_8BIT(0x3B9E), 0x13 }, - { IMX415_REG_8BIT(0x3BA1), 0x00 }, - { IMX415_REG_8BIT(0x3BA2), 0x06 }, - { IMX415_REG_8BIT(0x3BA3), 0x0B }, - { IMX415_REG_8BIT(0x3BA4), 0x10 }, - { IMX415_REG_8BIT(0x3BA5), 0x14 }, - { IMX415_REG_8BIT(0x3BA6), 0x18 }, - { IMX415_REG_8BIT(0x3BA7), 0x1A }, - { IMX415_REG_8BIT(0x3BA8), 0x1A }, - { IMX415_REG_8BIT(0x3BA9), 0x1A }, - { IMX415_REG_8BIT(0x3BAC), 0xED }, - { IMX415_REG_8BIT(0x3BAD), 0x01 }, - { IMX415_REG_8BIT(0x3BAE), 0xF6 }, - { IMX415_REG_8BIT(0x3BAF), 0x02 }, - { IMX415_REG_8BIT(0x3BB0), 0xA2 }, - { IMX415_REG_8BIT(0x3BB1), 0x03 }, - { IMX415_REG_8BIT(0x3BB2), 0xE0 }, - { IMX415_REG_8BIT(0x3BB3), 0x03 }, - { IMX415_REG_8BIT(0x3BB4), 0xE0 }, - { IMX415_REG_8BIT(0x3BB5), 0x03 }, - { IMX415_REG_8BIT(0x3BB6), 0xE0 }, - { IMX415_REG_8BIT(0x3BB7), 0x03 }, - { IMX415_REG_8BIT(0x3BB8), 0xE0 }, - { IMX415_REG_8BIT(0x3BBA), 0xE0 }, - { IMX415_REG_8BIT(0x3BBC), 0xDA }, - { IMX415_REG_8BIT(0x3BBE), 0x88 }, - { IMX415_REG_8BIT(0x3BC0), 0x44 }, - { IMX415_REG_8BIT(0x3BC2), 0x7B }, - { IMX415_REG_8BIT(0x3BC4), 0xA2 }, - { IMX415_REG_8BIT(0x3BC8), 0xBD }, - { IMX415_REG_8BIT(0x3BCA), 0xBD }, + { CCI_REG8(0x32D4), 0x21 }, + { CCI_REG8(0x32EC), 0xA1 }, + { CCI_REG8(0x3452), 0x7F }, + { CCI_REG8(0x3453), 0x03 }, + { CCI_REG8(0x358A), 0x04 }, + { CCI_REG8(0x35A1), 0x02 }, + { CCI_REG8(0x36BC), 0x0C }, + { CCI_REG8(0x36CC), 0x53 }, + { CCI_REG8(0x36CD), 0x00 }, + { CCI_REG8(0x36CE), 0x3C }, + { CCI_REG8(0x36D0), 0x8C }, + { CCI_REG8(0x36D1), 0x00 }, + { CCI_REG8(0x36D2), 0x71 }, + { CCI_REG8(0x36D4), 0x3C }, + { CCI_REG8(0x36D6), 0x53 }, + { CCI_REG8(0x36D7), 0x00 }, + { CCI_REG8(0x36D8), 0x71 }, + { CCI_REG8(0x36DA), 0x8C }, + { CCI_REG8(0x36DB), 0x00 }, + { CCI_REG8(0x3724), 0x02 }, + { CCI_REG8(0x3726), 0x02 }, + { CCI_REG8(0x3732), 0x02 }, + { CCI_REG8(0x3734), 0x03 }, + { CCI_REG8(0x3736), 0x03 }, + { CCI_REG8(0x3742), 0x03 }, + { CCI_REG8(0x3862), 0xE0 }, + { CCI_REG8(0x38CC), 0x30 }, + { CCI_REG8(0x38CD), 0x2F }, + { CCI_REG8(0x395C), 0x0C }, + { CCI_REG8(0x3A42), 0xD1 }, + { CCI_REG8(0x3A4C), 0x77 }, + { CCI_REG8(0x3AE0), 0x02 }, + { CCI_REG8(0x3AEC), 0x0C }, + { CCI_REG8(0x3B00), 0x2E }, + { CCI_REG8(0x3B06), 0x29 }, + { CCI_REG8(0x3B98), 0x25 }, + { CCI_REG8(0x3B99), 0x21 }, + { CCI_REG8(0x3B9B), 0x13 }, + { CCI_REG8(0x3B9C), 0x13 }, + { CCI_REG8(0x3B9D), 0x13 }, + { CCI_REG8(0x3B9E), 0x13 }, + { CCI_REG8(0x3BA1), 0x00 }, + { CCI_REG8(0x3BA2), 0x06 }, + { CCI_REG8(0x3BA3), 0x0B }, + { CCI_REG8(0x3BA4), 0x10 }, + { CCI_REG8(0x3BA5), 0x14 }, + { CCI_REG8(0x3BA6), 0x18 }, + { CCI_REG8(0x3BA7), 0x1A }, + { CCI_REG8(0x3BA8), 0x1A }, + { CCI_REG8(0x3BA9), 0x1A }, + { CCI_REG8(0x3BAC), 0xED }, + { CCI_REG8(0x3BAD), 0x01 }, + { CCI_REG8(0x3BAE), 0xF6 }, + { CCI_REG8(0x3BAF), 0x02 }, + { CCI_REG8(0x3BB0), 0xA2 }, + { CCI_REG8(0x3BB1), 0x03 }, + { CCI_REG8(0x3BB2), 0xE0 }, + { CCI_REG8(0x3BB3), 0x03 }, + { CCI_REG8(0x3BB4), 0xE0 }, + { CCI_REG8(0x3BB5), 0x03 }, + { CCI_REG8(0x3BB6), 0xE0 }, + { CCI_REG8(0x3BB7), 0x03 }, + { CCI_REG8(0x3BB8), 0xE0 }, + { CCI_REG8(0x3BBA), 0xE0 }, + { CCI_REG8(0x3BBC), 0xDA }, + { CCI_REG8(0x3BBE), 0x88 }, + { CCI_REG8(0x3BC0), 0x44 }, + { CCI_REG8(0x3BC2), 0x7B }, + { CCI_REG8(0x3BC4), 0xA2 }, + { CCI_REG8(0x3BC8), 0xBD }, + { CCI_REG8(0x3BCA), 0xBD }, }; static inline struct imx415 *to_imx415(struct v4l2_subdev *sd) @@ -460,74 +700,26 @@ static inline struct imx415 *to_imx415(struct v4l2_subdev *sd) return container_of(sd, struct imx415, subdev); } -static int imx415_read(struct imx415 *sensor, u32 addr) -{ - u8 data[3] = { 0 }; - int ret; - - ret = regmap_raw_read(sensor->regmap, addr & IMX415_REG_ADDR_MASK, data, - (addr >> IMX415_REG_SIZE_SHIFT) & 3); - if (ret < 0) - return ret; - - return (data[2] << 16) | (data[1] << 8) | data[0]; -} - -static int imx415_write(struct imx415 *sensor, u32 addr, u32 value) -{ - u8 data[3] = { value & 0xff, (value >> 8) & 0xff, value >> 16 }; - int ret; - - ret = regmap_raw_write(sensor->regmap, addr & IMX415_REG_ADDR_MASK, - data, (addr >> IMX415_REG_SIZE_SHIFT) & 3); - if (ret < 0) - dev_err_ratelimited(sensor->dev, - "%u-bit write to 0x%04x failed: %d\n", - ((addr >> IMX415_REG_SIZE_SHIFT) & 3) * 8, - addr & IMX415_REG_ADDR_MASK, ret); - - return 0; -} - static int imx415_set_testpattern(struct imx415 *sensor, int val) { - int ret; + int ret = 0; if (val) { - ret = imx415_write(sensor, IMX415_BLKLEVEL, 0x00); - if (ret) - return ret; - ret = imx415_write(sensor, IMX415_TPG_EN_DUOUT, 0x01); - if (ret) - return ret; - ret = imx415_write(sensor, IMX415_TPG_PATSEL_DUOUT, val - 1); - if (ret) - return ret; - ret = imx415_write(sensor, IMX415_TPG_COLORWIDTH, 0x01); - if (ret) - return ret; - ret = imx415_write(sensor, IMX415_TESTCLKEN_MIPI, 0x20); - if (ret) - return ret; - ret = imx415_write(sensor, IMX415_DIG_CLP_MODE, 0x00); - if (ret) - return ret; - ret = imx415_write(sensor, IMX415_WRJ_OPEN, 0x00); + cci_write(sensor->regmap, IMX415_BLKLEVEL, 0x00, &ret); + cci_write(sensor->regmap, IMX415_TPG_EN_DUOUT, 0x01, &ret); + cci_write(sensor->regmap, IMX415_TPG_PATSEL_DUOUT, + val - 1, &ret); + cci_write(sensor->regmap, IMX415_TPG_COLORWIDTH, 0x01, &ret); + cci_write(sensor->regmap, IMX415_TESTCLKEN_MIPI, 0x20, &ret); + cci_write(sensor->regmap, IMX415_DIG_CLP_MODE, 0x00, &ret); + cci_write(sensor->regmap, IMX415_WRJ_OPEN, 0x00, &ret); } else { - ret = imx415_write(sensor, IMX415_BLKLEVEL, - IMX415_BLKLEVEL_DEFAULT); - if (ret) - return ret; - ret = imx415_write(sensor, IMX415_TPG_EN_DUOUT, 0x00); - if (ret) - return ret; - ret = imx415_write(sensor, IMX415_TESTCLKEN_MIPI, 0x00); - if (ret) - return ret; - ret = imx415_write(sensor, IMX415_DIG_CLP_MODE, 0x01); - if (ret) - return ret; - ret = imx415_write(sensor, IMX415_WRJ_OPEN, 0x01); + cci_write(sensor->regmap, IMX415_BLKLEVEL, + IMX415_BLKLEVEL_DEFAULT, &ret); + cci_write(sensor->regmap, IMX415_TPG_EN_DUOUT, 0x00, &ret); + cci_write(sensor->regmap, IMX415_TESTCLKEN_MIPI, 0x00, &ret); + cci_write(sensor->regmap, IMX415_DIG_CLP_MODE, 0x01, &ret); + cci_write(sensor->regmap, IMX415_WRJ_OPEN, 0x01, &ret); } return 0; } @@ -553,19 +745,21 @@ static int imx415_s_ctrl(struct v4l2_ctrl *ctrl) /* clamp the exposure value to VMAX. */ vmax = format->height + sensor->vblank->cur.val; ctrl->val = min_t(int, ctrl->val, vmax); - ret = imx415_write(sensor, IMX415_SHR0, vmax - ctrl->val); + ret = cci_write(sensor->regmap, IMX415_SHR0, + vmax - ctrl->val, NULL); break; case V4L2_CID_ANALOGUE_GAIN: /* analogue gain in 0.3 dB step size */ - ret = imx415_write(sensor, IMX415_GAIN_PCG_0, ctrl->val); + ret = cci_write(sensor->regmap, IMX415_GAIN_PCG_0, + ctrl->val, NULL); break; case V4L2_CID_HFLIP: case V4L2_CID_VFLIP: flip = (sensor->hflip->val << IMX415_HREVERSE_SHIFT) | (sensor->vflip->val << IMX415_VREVERSE_SHIFT); - ret = imx415_write(sensor, IMX415_REVERSE, flip); + ret = cci_write(sensor->regmap, IMX415_REVERSE, flip, NULL); break; case V4L2_CID_TEST_PATTERN: @@ -679,8 +873,6 @@ static int imx415_ctrls_init(struct imx415 *sensor) static int imx415_set_mode(struct imx415 *sensor, int mode) { - const struct imx415_reg *reg; - unsigned int i; int ret = 0; if (mode >= ARRAY_SIZE(supported_modes)) { @@ -688,34 +880,29 @@ static int imx415_set_mode(struct imx415 *sensor, int mode) return -EINVAL; } - for (i = 0; i < supported_modes[mode].reg_list.num_of_regs; ++i) { - reg = &supported_modes[mode].reg_list.regs[i]; - ret = imx415_write(sensor, reg->address, reg->val); - if (ret) - return ret; - } + cci_multi_reg_write(sensor->regmap, + supported_modes[mode].reg_list.regs, + supported_modes[mode].reg_list.num_of_regs, + &ret); - for (i = 0; i < IMX415_NUM_CLK_PARAM_REGS; ++i) { - reg = &sensor->clk_params->regs[i]; - ret = imx415_write(sensor, reg->address, reg->val); - if (ret) - return ret; - } + cci_multi_reg_write(sensor->regmap, + sensor->clk_params->regs, + IMX415_NUM_CLK_PARAM_REGS, + &ret); return 0; } static int imx415_setup(struct imx415 *sensor, struct v4l2_subdev_state *state) { - unsigned int i; int ret; - for (i = 0; i < ARRAY_SIZE(imx415_init_table); ++i) { - ret = imx415_write(sensor, imx415_init_table[i].address, - imx415_init_table[i].val); - if (ret) - return ret; - } + ret = cci_multi_reg_write(sensor->regmap, + imx415_init_table, + ARRAY_SIZE(imx415_init_table), + NULL); + if (ret) + return ret; return imx415_set_mode(sensor, sensor->cur_mode); } @@ -724,7 +911,8 @@ static int imx415_wakeup(struct imx415 *sensor) { int ret; - ret = imx415_write(sensor, IMX415_MODE, IMX415_MODE_OPERATING); + ret = cci_write(sensor->regmap, IMX415_MODE, + IMX415_MODE_OPERATING, NULL); if (ret) return ret; @@ -743,21 +931,18 @@ static int imx415_stream_on(struct imx415 *sensor) int ret; ret = imx415_wakeup(sensor); - if (ret) - return ret; - - return imx415_write(sensor, IMX415_XMSTA, IMX415_XMSTA_START); + return cci_write(sensor->regmap, IMX415_XMSTA, + IMX415_XMSTA_START, &ret); } static int imx415_stream_off(struct imx415 *sensor) { int ret; - ret = imx415_write(sensor, IMX415_XMSTA, IMX415_XMSTA_STOP); - if (ret) - return ret; - - return imx415_write(sensor, IMX415_MODE, IMX415_MODE_STANDBY); + ret = cci_write(sensor->regmap, IMX415_XMSTA, + IMX415_XMSTA_STOP, NULL); + return cci_write(sensor->regmap, IMX415_MODE, + IMX415_MODE_STANDBY, &ret); } static int imx415_s_stream(struct v4l2_subdev *sd, int enable) @@ -992,6 +1177,7 @@ static void imx415_power_off(struct imx415 *sensor) static int imx415_identify_model(struct imx415 *sensor) { int model, ret; + u64 chip_id; /* * While most registers can be read when the sensor is in standby, this @@ -1002,14 +1188,14 @@ static int imx415_identify_model(struct imx415 *sensor) return dev_err_probe(sensor->dev, ret, "failed to get sensor out of standby\n"); - ret = imx415_read(sensor, IMX415_SENSOR_INFO); + ret = cci_read(sensor->regmap, IMX415_SENSOR_INFO, &chip_id, NULL); if (ret < 0) { dev_err_probe(sensor->dev, ret, "failed to read sensor information\n"); goto done; } - model = ret & IMX415_SENSOR_INFO_MASK; + model = chip_id & IMX415_SENSOR_INFO_MASK; switch (model) { case IMX415_CHIP_ID: @@ -1024,7 +1210,7 @@ static int imx415_identify_model(struct imx415 *sensor) ret = 0; done: - imx415_write(sensor, IMX415_MODE, IMX415_MODE_STANDBY); + cci_write(sensor->regmap, IMX415_MODE, IMX415_MODE_STANDBY, &ret); return ret; } @@ -1173,7 +1359,7 @@ static int imx415_probe(struct i2c_client *client) if (ret) return ret; - sensor->regmap = devm_regmap_init_i2c(client, &imx415_regmap_config); + sensor->regmap = devm_cci_regmap_init_i2c(client, 16); if (IS_ERR(sensor->regmap)) return PTR_ERR(sensor->regmap); diff --git a/drivers/media/i2c/isl7998x.c b/drivers/media/i2c/isl7998x.c index 89e13ebbce..c7089035bb 100644 --- a/drivers/media/i2c/isl7998x.c +++ b/drivers/media/i2c/isl7998x.c @@ -1337,7 +1337,7 @@ static const struct regmap_config isl7998x_regmap = { .rd_table = &isl7998x_readable_table, .wr_table = &isl7998x_writeable_table, .volatile_table = &isl7998x_volatile_table, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static int isl7998x_mc_init(struct isl7998x *isl7998x) diff --git a/drivers/media/i2c/max2175.c b/drivers/media/i2c/max2175.c index 70c2a2948f..cd73d2096a 100644 --- a/drivers/media/i2c/max2175.c +++ b/drivers/media/i2c/max2175.c @@ -257,7 +257,7 @@ static const struct regmap_config max2175_regmap_config = { .reg_defaults = max2175_reg_defaults, .num_reg_defaults = ARRAY_SIZE(max2175_reg_defaults), .volatile_table = &max2175_volatile_regs, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; struct max2175 { diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c index 0ed8561edf..599a5bc7cb 100644 --- a/drivers/media/i2c/msp3400-driver.c +++ b/drivers/media/i2c/msp3400-driver.c @@ -309,23 +309,15 @@ static void msp_wake_thread(struct i2c_client *client) wake_up_interruptible(&state->wq); } -int msp_sleep(struct msp_state *state, int timeout) +int msp_sleep(struct msp_state *state, int msec) { - DECLARE_WAITQUEUE(wait, current); - - add_wait_queue(&state->wq, &wait); - if (!kthread_should_stop()) { - if (timeout < 0) { - set_current_state(TASK_INTERRUPTIBLE); - schedule(); - } else { - schedule_timeout_interruptible - (msecs_to_jiffies(timeout)); - } - } + long timeout; + + timeout = msec < 0 ? MAX_SCHEDULE_TIMEOUT : msecs_to_jiffies(msec); + + wait_event_freezable_timeout(state->wq, kthread_should_stop() || + state->restart, timeout); - remove_wait_queue(&state->wq, &wait); - try_to_freeze(); return state->restart; } diff --git a/drivers/media/i2c/msp3400-driver.h b/drivers/media/i2c/msp3400-driver.h index 2bb9d5ff1b..7d391714ea 100644 --- a/drivers/media/i2c/msp3400-driver.h +++ b/drivers/media/i2c/msp3400-driver.h @@ -134,7 +134,7 @@ int msp_read_dsp(struct i2c_client *client, int addr); int msp_reset(struct i2c_client *client); void msp_set_scart(struct i2c_client *client, int in, int out); void msp_update_volume(struct msp_state *state); -int msp_sleep(struct msp_state *state, int timeout); +int msp_sleep(struct msp_state *state, int msec); /* msp3400-kthreads.c */ const char *msp_standard_std_name(int std); diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index 596200d024..f4b4812123 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -1078,7 +1078,7 @@ mt9p031_get_pdata(struct i2c_client *client) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) return client->dev.platform_data; - np = of_graph_get_next_endpoint(client->dev.of_node, NULL); + np = of_graph_get_endpoint_by_regs(client->dev.of_node, 0, -1); if (!np) return NULL; diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 3ca76eeae7..302120ff12 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -988,7 +988,7 @@ static const struct regmap_config mt9v032_regmap_config = { .reg_bits = 8, .val_bits = 16, .max_register = 0xff, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; /* ----------------------------------------------------------------------------- @@ -1006,7 +1006,7 @@ mt9v032_get_pdata(struct i2c_client *client) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) return client->dev.platform_data; - np = of_graph_get_next_endpoint(client->dev.of_node, NULL); + np = of_graph_get_endpoint_by_regs(client->dev.of_node, 0, -1); if (!np) return NULL; diff --git a/drivers/media/i2c/ov08x40.c b/drivers/media/i2c/ov08x40.c index abbb0b774d..48df077522 100644 --- a/drivers/media/i2c/ov08x40.c +++ b/drivers/media/i2c/ov08x40.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2022 Intel Corporation. +#include <asm-generic/unaligned.h> #include <linux/acpi.h> #include <linux/i2c.h> #include <linux/module.h> @@ -34,7 +35,7 @@ /* V_TIMING internal */ #define OV08X40_REG_VTS 0x380e -#define OV08X40_VTS_30FPS 0x1388 +#define OV08X40_VTS_30FPS 0x09c4 /* the VTS need to be half in normal mode */ #define OV08X40_VTS_BIN_30FPS 0x115c #define OV08X40_VTS_MAX 0x7fff @@ -44,8 +45,9 @@ /* Exposure control */ #define OV08X40_REG_EXPOSURE 0x3500 -#define OV08X40_EXPOSURE_MAX_MARGIN 31 -#define OV08X40_EXPOSURE_MIN 1 +#define OV08X40_EXPOSURE_MAX_MARGIN 8 +#define OV08X40_EXPOSURE_BIN_MAX_MARGIN 2 +#define OV08X40_EXPOSURE_MIN 4 #define OV08X40_EXPOSURE_STEP 1 #define OV08X40_EXPOSURE_DEFAULT 0x40 @@ -94,6 +96,12 @@ /* Vertical Window Offset */ #define OV08X40_REG_V_WIN_OFFSET 0x3813 +/* Burst Register */ +#define OV08X40_REG_XTALK_FIRST_A 0x5a80 +#define OV08X40_REG_XTALK_LAST_A 0x5b9f +#define OV08X40_REG_XTALK_FIRST_B 0x5bc0 +#define OV08X40_REG_XTALK_LAST_B 0x5f1f + enum { OV08X40_LINK_FREQ_400MHZ_INDEX, }; @@ -126,13 +134,17 @@ struct ov08x40_mode { u32 vts_def; u32 vts_min; - /* HTS */ - u32 hts; + /* Line Length Pixels */ + u32 llp; /* Index of Link frequency config to be used */ u32 link_freq_index; /* Default register values */ struct ov08x40_reg_list reg_list; + + /* Exposure calculation */ + u16 exposure_margin; + u16 exposure_shift; }; static const struct ov08x40_reg mipi_data_rate_800mbps[] = { @@ -665,1158 +677,6 @@ static const struct ov08x40_reg mode_3856x2416_regs[] = { {0x3502, 0x10}, {0x3508, 0x0f}, {0x3509, 0x80}, - {0x5a80, 0x75}, - {0x5a81, 0x75}, - {0x5a82, 0x75}, - {0x5a83, 0x75}, - {0x5a84, 0x75}, - {0x5a85, 0x75}, - {0x5a86, 0x75}, - {0x5a87, 0x75}, - {0x5a88, 0x75}, - {0x5a89, 0x75}, - {0x5a8a, 0x75}, - {0x5a8b, 0x75}, - {0x5a8c, 0x75}, - {0x5a8d, 0x75}, - {0x5a8e, 0x75}, - {0x5a8f, 0x75}, - {0x5a90, 0x75}, - {0x5a91, 0x75}, - {0x5a92, 0x75}, - {0x5a93, 0x75}, - {0x5a94, 0x75}, - {0x5a95, 0x75}, - {0x5a96, 0x75}, - {0x5a97, 0x75}, - {0x5a98, 0x75}, - {0x5a99, 0x75}, - {0x5a9a, 0x75}, - {0x5a9b, 0x75}, - {0x5a9c, 0x75}, - {0x5a9d, 0x75}, - {0x5a9e, 0x75}, - {0x5a9f, 0x75}, - {0x5aa0, 0x75}, - {0x5aa1, 0x75}, - {0x5aa2, 0x75}, - {0x5aa3, 0x75}, - {0x5aa4, 0x75}, - {0x5aa5, 0x75}, - {0x5aa6, 0x75}, - {0x5aa7, 0x75}, - {0x5aa8, 0x75}, - {0x5aa9, 0x75}, - {0x5aaa, 0x75}, - {0x5aab, 0x75}, - {0x5aac, 0x75}, - {0x5aad, 0x75}, - {0x5aae, 0x75}, - {0x5aaf, 0x75}, - {0x5ab0, 0x75}, - {0x5ab1, 0x75}, - {0x5ab2, 0x75}, - {0x5ab3, 0x75}, - {0x5ab4, 0x75}, - {0x5ab5, 0x75}, - {0x5ab6, 0x75}, - {0x5ab7, 0x75}, - {0x5ab8, 0x75}, - {0x5ab9, 0x75}, - {0x5aba, 0x75}, - {0x5abb, 0x75}, - {0x5abc, 0x75}, - {0x5abd, 0x75}, - {0x5abe, 0x75}, - {0x5abf, 0x75}, - {0x5ac0, 0x75}, - {0x5ac1, 0x75}, - {0x5ac2, 0x75}, - {0x5ac3, 0x75}, - {0x5ac4, 0x75}, - {0x5ac5, 0x75}, - {0x5ac6, 0x75}, - {0x5ac7, 0x75}, - {0x5ac8, 0x75}, - {0x5ac9, 0x75}, - {0x5aca, 0x75}, - {0x5acb, 0x75}, - {0x5acc, 0x75}, - {0x5acd, 0x75}, - {0x5ace, 0x75}, - {0x5acf, 0x75}, - {0x5ad0, 0x75}, - {0x5ad1, 0x75}, - {0x5ad2, 0x75}, - {0x5ad3, 0x75}, - {0x5ad4, 0x75}, - {0x5ad5, 0x75}, - {0x5ad6, 0x75}, - {0x5ad7, 0x75}, - {0x5ad8, 0x75}, - {0x5ad9, 0x75}, - {0x5ada, 0x75}, - {0x5adb, 0x75}, - {0x5adc, 0x75}, - {0x5add, 0x75}, - {0x5ade, 0x75}, - {0x5adf, 0x75}, - {0x5ae0, 0x75}, - {0x5ae1, 0x75}, - {0x5ae2, 0x75}, - {0x5ae3, 0x75}, - {0x5ae4, 0x75}, - {0x5ae5, 0x75}, - {0x5ae6, 0x75}, - {0x5ae7, 0x75}, - {0x5ae8, 0x75}, - {0x5ae9, 0x75}, - {0x5aea, 0x75}, - {0x5aeb, 0x75}, - {0x5aec, 0x75}, - {0x5aed, 0x75}, - {0x5aee, 0x75}, - {0x5aef, 0x75}, - {0x5af0, 0x75}, - {0x5af1, 0x75}, - {0x5af2, 0x75}, - {0x5af3, 0x75}, - {0x5af4, 0x75}, - {0x5af5, 0x75}, - {0x5af6, 0x75}, - {0x5af7, 0x75}, - {0x5af8, 0x75}, - {0x5af9, 0x75}, - {0x5afa, 0x75}, - {0x5afb, 0x75}, - {0x5afc, 0x75}, - {0x5afd, 0x75}, - {0x5afe, 0x75}, - {0x5aff, 0x75}, - {0x5b00, 0x75}, - {0x5b01, 0x75}, - {0x5b02, 0x75}, - {0x5b03, 0x75}, - {0x5b04, 0x75}, - {0x5b05, 0x75}, - {0x5b06, 0x75}, - {0x5b07, 0x75}, - {0x5b08, 0x75}, - {0x5b09, 0x75}, - {0x5b0a, 0x75}, - {0x5b0b, 0x75}, - {0x5b0c, 0x75}, - {0x5b0d, 0x75}, - {0x5b0e, 0x75}, - {0x5b0f, 0x75}, - {0x5b10, 0x75}, - {0x5b11, 0x75}, - {0x5b12, 0x75}, - {0x5b13, 0x75}, - {0x5b14, 0x75}, - {0x5b15, 0x75}, - {0x5b16, 0x75}, - {0x5b17, 0x75}, - {0x5b18, 0x75}, - {0x5b19, 0x75}, - {0x5b1a, 0x75}, - {0x5b1b, 0x75}, - {0x5b1c, 0x75}, - {0x5b1d, 0x75}, - {0x5b1e, 0x75}, - {0x5b1f, 0x75}, - {0x5b20, 0x75}, - {0x5b21, 0x75}, - {0x5b22, 0x75}, - {0x5b23, 0x75}, - {0x5b24, 0x75}, - {0x5b25, 0x75}, - {0x5b26, 0x75}, - {0x5b27, 0x75}, - {0x5b28, 0x75}, - {0x5b29, 0x75}, - {0x5b2a, 0x75}, - {0x5b2b, 0x75}, - {0x5b2c, 0x75}, - {0x5b2d, 0x75}, - {0x5b2e, 0x75}, - {0x5b2f, 0x75}, - {0x5b30, 0x75}, - {0x5b31, 0x75}, - {0x5b32, 0x75}, - {0x5b33, 0x75}, - {0x5b34, 0x75}, - {0x5b35, 0x75}, - {0x5b36, 0x75}, - {0x5b37, 0x75}, - {0x5b38, 0x75}, - {0x5b39, 0x75}, - {0x5b3a, 0x75}, - {0x5b3b, 0x75}, - {0x5b3c, 0x75}, - {0x5b3d, 0x75}, - {0x5b3e, 0x75}, - {0x5b3f, 0x75}, - {0x5b40, 0x75}, - {0x5b41, 0x75}, - {0x5b42, 0x75}, - {0x5b43, 0x75}, - {0x5b44, 0x75}, - {0x5b45, 0x75}, - {0x5b46, 0x75}, - {0x5b47, 0x75}, - {0x5b48, 0x75}, - {0x5b49, 0x75}, - {0x5b4a, 0x75}, - {0x5b4b, 0x75}, - {0x5b4c, 0x75}, - {0x5b4d, 0x75}, - {0x5b4e, 0x75}, - {0x5b4f, 0x75}, - {0x5b50, 0x75}, - {0x5b51, 0x75}, - {0x5b52, 0x75}, - {0x5b53, 0x75}, - {0x5b54, 0x75}, - {0x5b55, 0x75}, - {0x5b56, 0x75}, - {0x5b57, 0x75}, - {0x5b58, 0x75}, - {0x5b59, 0x75}, - {0x5b5a, 0x75}, - {0x5b5b, 0x75}, - {0x5b5c, 0x75}, - {0x5b5d, 0x75}, - {0x5b5e, 0x75}, - {0x5b5f, 0x75}, - {0x5b60, 0x75}, - {0x5b61, 0x75}, - {0x5b62, 0x75}, - {0x5b63, 0x75}, - {0x5b64, 0x75}, - {0x5b65, 0x75}, - {0x5b66, 0x75}, - {0x5b67, 0x75}, - {0x5b68, 0x75}, - {0x5b69, 0x75}, - {0x5b6a, 0x75}, - {0x5b6b, 0x75}, - {0x5b6c, 0x75}, - {0x5b6d, 0x75}, - {0x5b6e, 0x75}, - {0x5b6f, 0x75}, - {0x5b70, 0x75}, - {0x5b71, 0x75}, - {0x5b72, 0x75}, - {0x5b73, 0x75}, - {0x5b74, 0x75}, - {0x5b75, 0x75}, - {0x5b76, 0x75}, - {0x5b77, 0x75}, - {0x5b78, 0x75}, - {0x5b79, 0x75}, - {0x5b7a, 0x75}, - {0x5b7b, 0x75}, - {0x5b7c, 0x75}, - {0x5b7d, 0x75}, - {0x5b7e, 0x75}, - {0x5b7f, 0x75}, - {0x5b80, 0x75}, - {0x5b81, 0x75}, - {0x5b82, 0x75}, - {0x5b83, 0x75}, - {0x5b84, 0x75}, - {0x5b85, 0x75}, - {0x5b86, 0x75}, - {0x5b87, 0x75}, - {0x5b88, 0x75}, - {0x5b89, 0x75}, - {0x5b8a, 0x75}, - {0x5b8b, 0x75}, - {0x5b8c, 0x75}, - {0x5b8d, 0x75}, - {0x5b8e, 0x75}, - {0x5b8f, 0x75}, - {0x5b90, 0x75}, - {0x5b91, 0x75}, - {0x5b92, 0x75}, - {0x5b93, 0x75}, - {0x5b94, 0x75}, - {0x5b95, 0x75}, - {0x5b96, 0x75}, - {0x5b97, 0x75}, - {0x5b98, 0x75}, - {0x5b99, 0x75}, - {0x5b9a, 0x75}, - {0x5b9b, 0x75}, - {0x5b9c, 0x75}, - {0x5b9d, 0x75}, - {0x5b9e, 0x75}, - {0x5b9f, 0x75}, - {0x5bc0, 0x75}, - {0x5bc1, 0x75}, - {0x5bc2, 0x75}, - {0x5bc3, 0x75}, - {0x5bc4, 0x75}, - {0x5bc5, 0x75}, - {0x5bc6, 0x75}, - {0x5bc7, 0x75}, - {0x5bc8, 0x75}, - {0x5bc9, 0x75}, - {0x5bca, 0x75}, - {0x5bcb, 0x75}, - {0x5bcc, 0x75}, - {0x5bcd, 0x75}, - {0x5bce, 0x75}, - {0x5bcf, 0x75}, - {0x5bd0, 0x75}, - {0x5bd1, 0x75}, - {0x5bd2, 0x75}, - {0x5bd3, 0x75}, - {0x5bd4, 0x75}, - {0x5bd5, 0x75}, - {0x5bd6, 0x75}, - {0x5bd7, 0x75}, - {0x5bd8, 0x75}, - {0x5bd9, 0x75}, - {0x5bda, 0x75}, - {0x5bdb, 0x75}, - {0x5bdc, 0x75}, - {0x5bdd, 0x75}, - {0x5bde, 0x75}, - {0x5bdf, 0x75}, - {0x5be0, 0x75}, - {0x5be1, 0x75}, - {0x5be2, 0x75}, - {0x5be3, 0x75}, - {0x5be4, 0x75}, - {0x5be5, 0x75}, - {0x5be6, 0x75}, - {0x5be7, 0x75}, - {0x5be8, 0x75}, - {0x5be9, 0x75}, - {0x5bea, 0x75}, - {0x5beb, 0x75}, - {0x5bec, 0x75}, - {0x5bed, 0x75}, - {0x5bee, 0x75}, - {0x5bef, 0x75}, - {0x5bf0, 0x75}, - {0x5bf1, 0x75}, - {0x5bf2, 0x75}, - {0x5bf3, 0x75}, - {0x5bf4, 0x75}, - {0x5bf5, 0x75}, - {0x5bf6, 0x75}, - {0x5bf7, 0x75}, - {0x5bf8, 0x75}, - {0x5bf9, 0x75}, - {0x5bfa, 0x75}, - {0x5bfb, 0x75}, - {0x5bfc, 0x75}, - {0x5bfd, 0x75}, - {0x5bfe, 0x75}, - {0x5bff, 0x75}, - {0x5c00, 0x75}, - {0x5c01, 0x75}, - {0x5c02, 0x75}, - {0x5c03, 0x75}, - {0x5c04, 0x75}, - {0x5c05, 0x75}, - {0x5c06, 0x75}, - {0x5c07, 0x75}, - {0x5c08, 0x75}, - {0x5c09, 0x75}, - {0x5c0a, 0x75}, - {0x5c0b, 0x75}, - {0x5c0c, 0x75}, - {0x5c0d, 0x75}, - {0x5c0e, 0x75}, - {0x5c0f, 0x75}, - {0x5c10, 0x75}, - {0x5c11, 0x75}, - {0x5c12, 0x75}, - {0x5c13, 0x75}, - {0x5c14, 0x75}, - {0x5c15, 0x75}, - {0x5c16, 0x75}, - {0x5c17, 0x75}, - {0x5c18, 0x75}, - {0x5c19, 0x75}, - {0x5c1a, 0x75}, - {0x5c1b, 0x75}, - {0x5c1c, 0x75}, - {0x5c1d, 0x75}, - {0x5c1e, 0x75}, - {0x5c1f, 0x75}, - {0x5c20, 0x75}, - {0x5c21, 0x75}, - {0x5c22, 0x75}, - {0x5c23, 0x75}, - {0x5c24, 0x75}, - {0x5c25, 0x75}, - {0x5c26, 0x75}, - {0x5c27, 0x75}, - {0x5c28, 0x75}, - {0x5c29, 0x75}, - {0x5c2a, 0x75}, - {0x5c2b, 0x75}, - {0x5c2c, 0x75}, - {0x5c2d, 0x75}, - {0x5c2e, 0x75}, - {0x5c2f, 0x75}, - {0x5c30, 0x75}, - {0x5c31, 0x75}, - {0x5c32, 0x75}, - {0x5c33, 0x75}, - {0x5c34, 0x75}, - {0x5c35, 0x75}, - {0x5c36, 0x75}, - {0x5c37, 0x75}, - {0x5c38, 0x75}, - {0x5c39, 0x75}, - {0x5c3a, 0x75}, - {0x5c3b, 0x75}, - {0x5c3c, 0x75}, - {0x5c3d, 0x75}, - {0x5c3e, 0x75}, - {0x5c3f, 0x75}, - {0x5c40, 0x75}, - {0x5c41, 0x75}, - {0x5c42, 0x75}, - {0x5c43, 0x75}, - {0x5c44, 0x75}, - {0x5c45, 0x75}, - {0x5c46, 0x75}, - {0x5c47, 0x75}, - {0x5c48, 0x75}, - {0x5c49, 0x75}, - {0x5c4a, 0x75}, - {0x5c4b, 0x75}, - {0x5c4c, 0x75}, - {0x5c4d, 0x75}, - {0x5c4e, 0x75}, - {0x5c4f, 0x75}, - {0x5c50, 0x75}, - {0x5c51, 0x75}, - {0x5c52, 0x75}, - {0x5c53, 0x75}, - {0x5c54, 0x75}, - {0x5c55, 0x75}, - {0x5c56, 0x75}, - {0x5c57, 0x75}, - {0x5c58, 0x75}, - {0x5c59, 0x75}, - {0x5c5a, 0x75}, - {0x5c5b, 0x75}, - {0x5c5c, 0x75}, - {0x5c5d, 0x75}, - {0x5c5e, 0x75}, - {0x5c5f, 0x75}, - {0x5c60, 0x75}, - {0x5c61, 0x75}, - {0x5c62, 0x75}, - {0x5c63, 0x75}, - {0x5c64, 0x75}, - {0x5c65, 0x75}, - {0x5c66, 0x75}, - {0x5c67, 0x75}, - {0x5c68, 0x75}, - {0x5c69, 0x75}, - {0x5c6a, 0x75}, - {0x5c6b, 0x75}, - {0x5c6c, 0x75}, - {0x5c6d, 0x75}, - {0x5c6e, 0x75}, - {0x5c6f, 0x75}, - {0x5c70, 0x75}, - {0x5c71, 0x75}, - {0x5c72, 0x75}, - {0x5c73, 0x75}, - {0x5c74, 0x75}, - {0x5c75, 0x75}, - {0x5c76, 0x75}, - {0x5c77, 0x75}, - {0x5c78, 0x75}, - {0x5c79, 0x75}, - {0x5c7a, 0x75}, - {0x5c7b, 0x75}, - {0x5c7c, 0x75}, - {0x5c7d, 0x75}, - {0x5c7e, 0x75}, - {0x5c7f, 0x75}, - {0x5c80, 0x75}, - {0x5c81, 0x75}, - {0x5c82, 0x75}, - {0x5c83, 0x75}, - {0x5c84, 0x75}, - {0x5c85, 0x75}, - {0x5c86, 0x75}, - {0x5c87, 0x75}, - {0x5c88, 0x75}, - {0x5c89, 0x75}, - {0x5c8a, 0x75}, - {0x5c8b, 0x75}, - {0x5c8c, 0x75}, - {0x5c8d, 0x75}, - {0x5c8e, 0x75}, - {0x5c8f, 0x75}, - {0x5c90, 0x75}, - {0x5c91, 0x75}, - {0x5c92, 0x75}, - {0x5c93, 0x75}, - {0x5c94, 0x75}, - {0x5c95, 0x75}, - {0x5c96, 0x75}, - {0x5c97, 0x75}, - {0x5c98, 0x75}, - {0x5c99, 0x75}, - {0x5c9a, 0x75}, - {0x5c9b, 0x75}, - {0x5c9c, 0x75}, - {0x5c9d, 0x75}, - {0x5c9e, 0x75}, - {0x5c9f, 0x75}, - {0x5ca0, 0x75}, - {0x5ca1, 0x75}, - {0x5ca2, 0x75}, - {0x5ca3, 0x75}, - {0x5ca4, 0x75}, - {0x5ca5, 0x75}, - {0x5ca6, 0x75}, - {0x5ca7, 0x75}, - {0x5ca8, 0x75}, - {0x5ca9, 0x75}, - {0x5caa, 0x75}, - {0x5cab, 0x75}, - {0x5cac, 0x75}, - {0x5cad, 0x75}, - {0x5cae, 0x75}, - {0x5caf, 0x75}, - {0x5cb0, 0x75}, - {0x5cb1, 0x75}, - {0x5cb2, 0x75}, - {0x5cb3, 0x75}, - {0x5cb4, 0x75}, - {0x5cb5, 0x75}, - {0x5cb6, 0x75}, - {0x5cb7, 0x75}, - {0x5cb8, 0x75}, - {0x5cb9, 0x75}, - {0x5cba, 0x75}, - {0x5cbb, 0x75}, - {0x5cbc, 0x75}, - {0x5cbd, 0x75}, - {0x5cbe, 0x75}, - {0x5cbf, 0x75}, - {0x5cc0, 0x75}, - {0x5cc1, 0x75}, - {0x5cc2, 0x75}, - {0x5cc3, 0x75}, - {0x5cc4, 0x75}, - {0x5cc5, 0x75}, - {0x5cc6, 0x75}, - {0x5cc7, 0x75}, - {0x5cc8, 0x75}, - {0x5cc9, 0x75}, - {0x5cca, 0x75}, - {0x5ccb, 0x75}, - {0x5ccc, 0x75}, - {0x5ccd, 0x75}, - {0x5cce, 0x75}, - {0x5ccf, 0x75}, - {0x5cd0, 0x75}, - {0x5cd1, 0x75}, - {0x5cd2, 0x75}, - {0x5cd3, 0x75}, - {0x5cd4, 0x75}, - {0x5cd5, 0x75}, - {0x5cd6, 0x75}, - {0x5cd7, 0x75}, - {0x5cd8, 0x75}, - {0x5cd9, 0x75}, - {0x5cda, 0x75}, - {0x5cdb, 0x75}, - {0x5cdc, 0x75}, - {0x5cdd, 0x75}, - {0x5cde, 0x75}, - {0x5cdf, 0x75}, - {0x5ce0, 0x75}, - {0x5ce1, 0x75}, - {0x5ce2, 0x75}, - {0x5ce3, 0x75}, - {0x5ce4, 0x75}, - {0x5ce5, 0x75}, - {0x5ce6, 0x75}, - {0x5ce7, 0x75}, - {0x5ce8, 0x75}, - {0x5ce9, 0x75}, - {0x5cea, 0x75}, - {0x5ceb, 0x75}, - {0x5cec, 0x75}, - {0x5ced, 0x75}, - {0x5cee, 0x75}, - {0x5cef, 0x75}, - {0x5cf0, 0x75}, - {0x5cf1, 0x75}, - {0x5cf2, 0x75}, - {0x5cf3, 0x75}, - {0x5cf4, 0x75}, - {0x5cf5, 0x75}, - {0x5cf6, 0x75}, - {0x5cf7, 0x75}, - {0x5cf8, 0x75}, - {0x5cf9, 0x75}, - {0x5cfa, 0x75}, - {0x5cfb, 0x75}, - {0x5cfc, 0x75}, - {0x5cfd, 0x75}, - {0x5cfe, 0x75}, - {0x5cff, 0x75}, - {0x5d00, 0x75}, - {0x5d01, 0x75}, - {0x5d02, 0x75}, - {0x5d03, 0x75}, - {0x5d04, 0x75}, - {0x5d05, 0x75}, - {0x5d06, 0x75}, - {0x5d07, 0x75}, - {0x5d08, 0x75}, - {0x5d09, 0x75}, - {0x5d0a, 0x75}, - {0x5d0b, 0x75}, - {0x5d0c, 0x75}, - {0x5d0d, 0x75}, - {0x5d0e, 0x75}, - {0x5d0f, 0x75}, - {0x5d10, 0x75}, - {0x5d11, 0x75}, - {0x5d12, 0x75}, - {0x5d13, 0x75}, - {0x5d14, 0x75}, - {0x5d15, 0x75}, - {0x5d16, 0x75}, - {0x5d17, 0x75}, - {0x5d18, 0x75}, - {0x5d19, 0x75}, - {0x5d1a, 0x75}, - {0x5d1b, 0x75}, - {0x5d1c, 0x75}, - {0x5d1d, 0x75}, - {0x5d1e, 0x75}, - {0x5d1f, 0x75}, - {0x5d20, 0x75}, - {0x5d21, 0x75}, - {0x5d22, 0x75}, - {0x5d23, 0x75}, - {0x5d24, 0x75}, - {0x5d25, 0x75}, - {0x5d26, 0x75}, - {0x5d27, 0x75}, - {0x5d28, 0x75}, - {0x5d29, 0x75}, - {0x5d2a, 0x75}, - {0x5d2b, 0x75}, - {0x5d2c, 0x75}, - {0x5d2d, 0x75}, - {0x5d2e, 0x75}, - {0x5d2f, 0x75}, - {0x5d30, 0x75}, - {0x5d31, 0x75}, - {0x5d32, 0x75}, - {0x5d33, 0x75}, - {0x5d34, 0x75}, - {0x5d35, 0x75}, - {0x5d36, 0x75}, - {0x5d37, 0x75}, - {0x5d38, 0x75}, - {0x5d39, 0x75}, - {0x5d3a, 0x75}, - {0x5d3b, 0x75}, - {0x5d3c, 0x75}, - {0x5d3d, 0x75}, - {0x5d3e, 0x75}, - {0x5d3f, 0x75}, - {0x5d40, 0x75}, - {0x5d41, 0x75}, - {0x5d42, 0x75}, - {0x5d43, 0x75}, - {0x5d44, 0x75}, - {0x5d45, 0x75}, - {0x5d46, 0x75}, - {0x5d47, 0x75}, - {0x5d48, 0x75}, - {0x5d49, 0x75}, - {0x5d4a, 0x75}, - {0x5d4b, 0x75}, - {0x5d4c, 0x75}, - {0x5d4d, 0x75}, - {0x5d4e, 0x75}, - {0x5d4f, 0x75}, - {0x5d50, 0x75}, - {0x5d51, 0x75}, - {0x5d52, 0x75}, - {0x5d53, 0x75}, - {0x5d54, 0x75}, - {0x5d55, 0x75}, - {0x5d56, 0x75}, - {0x5d57, 0x75}, - {0x5d58, 0x75}, - {0x5d59, 0x75}, - {0x5d5a, 0x75}, - {0x5d5b, 0x75}, - {0x5d5c, 0x75}, - {0x5d5d, 0x75}, - {0x5d5e, 0x75}, - {0x5d5f, 0x75}, - {0x5d60, 0x75}, - {0x5d61, 0x75}, - {0x5d62, 0x75}, - {0x5d63, 0x75}, - {0x5d64, 0x75}, - {0x5d65, 0x75}, - {0x5d66, 0x75}, - {0x5d67, 0x75}, - {0x5d68, 0x75}, - {0x5d69, 0x75}, - {0x5d6a, 0x75}, - {0x5d6b, 0x75}, - {0x5d6c, 0x75}, - {0x5d6d, 0x75}, - {0x5d6e, 0x75}, - {0x5d6f, 0x75}, - {0x5d70, 0x75}, - {0x5d71, 0x75}, - {0x5d72, 0x75}, - {0x5d73, 0x75}, - {0x5d74, 0x75}, - {0x5d75, 0x75}, - {0x5d76, 0x75}, - {0x5d77, 0x75}, - {0x5d78, 0x75}, - {0x5d79, 0x75}, - {0x5d7a, 0x75}, - {0x5d7b, 0x75}, - {0x5d7c, 0x75}, - {0x5d7d, 0x75}, - {0x5d7e, 0x75}, - {0x5d7f, 0x75}, - {0x5d80, 0x75}, - {0x5d81, 0x75}, - {0x5d82, 0x75}, - {0x5d83, 0x75}, - {0x5d84, 0x75}, - {0x5d85, 0x75}, - {0x5d86, 0x75}, - {0x5d87, 0x75}, - {0x5d88, 0x75}, - {0x5d89, 0x75}, - {0x5d8a, 0x75}, - {0x5d8b, 0x75}, - {0x5d8c, 0x75}, - {0x5d8d, 0x75}, - {0x5d8e, 0x75}, - {0x5d8f, 0x75}, - {0x5d90, 0x75}, - {0x5d91, 0x75}, - {0x5d92, 0x75}, - {0x5d93, 0x75}, - {0x5d94, 0x75}, - {0x5d95, 0x75}, - {0x5d96, 0x75}, - {0x5d97, 0x75}, - {0x5d98, 0x75}, - {0x5d99, 0x75}, - {0x5d9a, 0x75}, - {0x5d9b, 0x75}, - {0x5d9c, 0x75}, - {0x5d9d, 0x75}, - {0x5d9e, 0x75}, - {0x5d9f, 0x75}, - {0x5da0, 0x75}, - {0x5da1, 0x75}, - {0x5da2, 0x75}, - {0x5da3, 0x75}, - {0x5da4, 0x75}, - {0x5da5, 0x75}, - {0x5da6, 0x75}, - {0x5da7, 0x75}, - {0x5da8, 0x75}, - {0x5da9, 0x75}, - {0x5daa, 0x75}, - {0x5dab, 0x75}, - {0x5dac, 0x75}, - {0x5dad, 0x75}, - {0x5dae, 0x75}, - {0x5daf, 0x75}, - {0x5db0, 0x75}, - {0x5db1, 0x75}, - {0x5db2, 0x75}, - {0x5db3, 0x75}, - {0x5db4, 0x75}, - {0x5db5, 0x75}, - {0x5db6, 0x75}, - {0x5db7, 0x75}, - {0x5db8, 0x75}, - {0x5db9, 0x75}, - {0x5dba, 0x75}, - {0x5dbb, 0x75}, - {0x5dbc, 0x75}, - {0x5dbd, 0x75}, - {0x5dbe, 0x75}, - {0x5dbf, 0x75}, - {0x5dc0, 0x75}, - {0x5dc1, 0x75}, - {0x5dc2, 0x75}, - {0x5dc3, 0x75}, - {0x5dc4, 0x75}, - {0x5dc5, 0x75}, - {0x5dc6, 0x75}, - {0x5dc7, 0x75}, - {0x5dc8, 0x75}, - {0x5dc9, 0x75}, - {0x5dca, 0x75}, - {0x5dcb, 0x75}, - {0x5dcc, 0x75}, - {0x5dcd, 0x75}, - {0x5dce, 0x75}, - {0x5dcf, 0x75}, - {0x5dd0, 0x75}, - {0x5dd1, 0x75}, - {0x5dd2, 0x75}, - {0x5dd3, 0x75}, - {0x5dd4, 0x75}, - {0x5dd5, 0x75}, - {0x5dd6, 0x75}, - {0x5dd7, 0x75}, - {0x5dd8, 0x75}, - {0x5dd9, 0x75}, - {0x5dda, 0x75}, - {0x5ddb, 0x75}, - {0x5ddc, 0x75}, - {0x5ddd, 0x75}, - {0x5dde, 0x75}, - {0x5ddf, 0x75}, - {0x5de0, 0x75}, - {0x5de1, 0x75}, - {0x5de2, 0x75}, - {0x5de3, 0x75}, - {0x5de4, 0x75}, - {0x5de5, 0x75}, - {0x5de6, 0x75}, - {0x5de7, 0x75}, - {0x5de8, 0x75}, - {0x5de9, 0x75}, - {0x5dea, 0x75}, - {0x5deb, 0x75}, - {0x5dec, 0x75}, - {0x5ded, 0x75}, - {0x5dee, 0x75}, - {0x5def, 0x75}, - {0x5df0, 0x75}, - {0x5df1, 0x75}, - {0x5df2, 0x75}, - {0x5df3, 0x75}, - {0x5df4, 0x75}, - {0x5df5, 0x75}, - {0x5df6, 0x75}, - {0x5df7, 0x75}, - {0x5df8, 0x75}, - {0x5df9, 0x75}, - {0x5dfa, 0x75}, - {0x5dfb, 0x75}, - {0x5dfc, 0x75}, - {0x5dfd, 0x75}, - {0x5dfe, 0x75}, - {0x5dff, 0x75}, - {0x5e00, 0x75}, - {0x5e01, 0x75}, - {0x5e02, 0x75}, - {0x5e03, 0x75}, - {0x5e04, 0x75}, - {0x5e05, 0x75}, - {0x5e06, 0x75}, - {0x5e07, 0x75}, - {0x5e08, 0x75}, - {0x5e09, 0x75}, - {0x5e0a, 0x75}, - {0x5e0b, 0x75}, - {0x5e0c, 0x75}, - {0x5e0d, 0x75}, - {0x5e0e, 0x75}, - {0x5e0f, 0x75}, - {0x5e10, 0x75}, - {0x5e11, 0x75}, - {0x5e12, 0x75}, - {0x5e13, 0x75}, - {0x5e14, 0x75}, - {0x5e15, 0x75}, - {0x5e16, 0x75}, - {0x5e17, 0x75}, - {0x5e18, 0x75}, - {0x5e19, 0x75}, - {0x5e1a, 0x75}, - {0x5e1b, 0x75}, - {0x5e1c, 0x75}, - {0x5e1d, 0x75}, - {0x5e1e, 0x75}, - {0x5e1f, 0x75}, - {0x5e20, 0x75}, - {0x5e21, 0x75}, - {0x5e22, 0x75}, - {0x5e23, 0x75}, - {0x5e24, 0x75}, - {0x5e25, 0x75}, - {0x5e26, 0x75}, - {0x5e27, 0x75}, - {0x5e28, 0x75}, - {0x5e29, 0x75}, - {0x5e2a, 0x75}, - {0x5e2b, 0x75}, - {0x5e2c, 0x75}, - {0x5e2d, 0x75}, - {0x5e2e, 0x75}, - {0x5e2f, 0x75}, - {0x5e30, 0x75}, - {0x5e31, 0x75}, - {0x5e32, 0x75}, - {0x5e33, 0x75}, - {0x5e34, 0x75}, - {0x5e35, 0x75}, - {0x5e36, 0x75}, - {0x5e37, 0x75}, - {0x5e38, 0x75}, - {0x5e39, 0x75}, - {0x5e3a, 0x75}, - {0x5e3b, 0x75}, - {0x5e3c, 0x75}, - {0x5e3d, 0x75}, - {0x5e3e, 0x75}, - {0x5e3f, 0x75}, - {0x5e40, 0x75}, - {0x5e41, 0x75}, - {0x5e42, 0x75}, - {0x5e43, 0x75}, - {0x5e44, 0x75}, - {0x5e45, 0x75}, - {0x5e46, 0x75}, - {0x5e47, 0x75}, - {0x5e48, 0x75}, - {0x5e49, 0x75}, - {0x5e4a, 0x75}, - {0x5e4b, 0x75}, - {0x5e4c, 0x75}, - {0x5e4d, 0x75}, - {0x5e4e, 0x75}, - {0x5e4f, 0x75}, - {0x5e50, 0x75}, - {0x5e51, 0x75}, - {0x5e52, 0x75}, - {0x5e53, 0x75}, - {0x5e54, 0x75}, - {0x5e55, 0x75}, - {0x5e56, 0x75}, - {0x5e57, 0x75}, - {0x5e58, 0x75}, - {0x5e59, 0x75}, - {0x5e5a, 0x75}, - {0x5e5b, 0x75}, - {0x5e5c, 0x75}, - {0x5e5d, 0x75}, - {0x5e5e, 0x75}, - {0x5e5f, 0x75}, - {0x5e60, 0x75}, - {0x5e61, 0x75}, - {0x5e62, 0x75}, - {0x5e63, 0x75}, - {0x5e64, 0x75}, - {0x5e65, 0x75}, - {0x5e66, 0x75}, - {0x5e67, 0x75}, - {0x5e68, 0x75}, - {0x5e69, 0x75}, - {0x5e6a, 0x75}, - {0x5e6b, 0x75}, - {0x5e6c, 0x75}, - {0x5e6d, 0x75}, - {0x5e6e, 0x75}, - {0x5e6f, 0x75}, - {0x5e70, 0x75}, - {0x5e71, 0x75}, - {0x5e72, 0x75}, - {0x5e73, 0x75}, - {0x5e74, 0x75}, - {0x5e75, 0x75}, - {0x5e76, 0x75}, - {0x5e77, 0x75}, - {0x5e78, 0x75}, - {0x5e79, 0x75}, - {0x5e7a, 0x75}, - {0x5e7b, 0x75}, - {0x5e7c, 0x75}, - {0x5e7d, 0x75}, - {0x5e7e, 0x75}, - {0x5e7f, 0x75}, - {0x5e80, 0x75}, - {0x5e81, 0x75}, - {0x5e82, 0x75}, - {0x5e83, 0x75}, - {0x5e84, 0x75}, - {0x5e85, 0x75}, - {0x5e86, 0x75}, - {0x5e87, 0x75}, - {0x5e88, 0x75}, - {0x5e89, 0x75}, - {0x5e8a, 0x75}, - {0x5e8b, 0x75}, - {0x5e8c, 0x75}, - {0x5e8d, 0x75}, - {0x5e8e, 0x75}, - {0x5e8f, 0x75}, - {0x5e90, 0x75}, - {0x5e91, 0x75}, - {0x5e92, 0x75}, - {0x5e93, 0x75}, - {0x5e94, 0x75}, - {0x5e95, 0x75}, - {0x5e96, 0x75}, - {0x5e97, 0x75}, - {0x5e98, 0x75}, - {0x5e99, 0x75}, - {0x5e9a, 0x75}, - {0x5e9b, 0x75}, - {0x5e9c, 0x75}, - {0x5e9d, 0x75}, - {0x5e9e, 0x75}, - {0x5e9f, 0x75}, - {0x5ea0, 0x75}, - {0x5ea1, 0x75}, - {0x5ea2, 0x75}, - {0x5ea3, 0x75}, - {0x5ea4, 0x75}, - {0x5ea5, 0x75}, - {0x5ea6, 0x75}, - {0x5ea7, 0x75}, - {0x5ea8, 0x75}, - {0x5ea9, 0x75}, - {0x5eaa, 0x75}, - {0x5eab, 0x75}, - {0x5eac, 0x75}, - {0x5ead, 0x75}, - {0x5eae, 0x75}, - {0x5eaf, 0x75}, - {0x5eb0, 0x75}, - {0x5eb1, 0x75}, - {0x5eb2, 0x75}, - {0x5eb3, 0x75}, - {0x5eb4, 0x75}, - {0x5eb5, 0x75}, - {0x5eb6, 0x75}, - {0x5eb7, 0x75}, - {0x5eb8, 0x75}, - {0x5eb9, 0x75}, - {0x5eba, 0x75}, - {0x5ebb, 0x75}, - {0x5ebc, 0x75}, - {0x5ebd, 0x75}, - {0x5ebe, 0x75}, - {0x5ebf, 0x75}, - {0x5ec0, 0x75}, - {0x5ec1, 0x75}, - {0x5ec2, 0x75}, - {0x5ec3, 0x75}, - {0x5ec4, 0x75}, - {0x5ec5, 0x75}, - {0x5ec6, 0x75}, - {0x5ec7, 0x75}, - {0x5ec8, 0x75}, - {0x5ec9, 0x75}, - {0x5eca, 0x75}, - {0x5ecb, 0x75}, - {0x5ecc, 0x75}, - {0x5ecd, 0x75}, - {0x5ece, 0x75}, - {0x5ecf, 0x75}, - {0x5ed0, 0x75}, - {0x5ed1, 0x75}, - {0x5ed2, 0x75}, - {0x5ed3, 0x75}, - {0x5ed4, 0x75}, - {0x5ed5, 0x75}, - {0x5ed6, 0x75}, - {0x5ed7, 0x75}, - {0x5ed8, 0x75}, - {0x5ed9, 0x75}, - {0x5eda, 0x75}, - {0x5edb, 0x75}, - {0x5edc, 0x75}, - {0x5edd, 0x75}, - {0x5ede, 0x75}, - {0x5edf, 0x75}, - {0x5ee0, 0x75}, - {0x5ee1, 0x75}, - {0x5ee2, 0x75}, - {0x5ee3, 0x75}, - {0x5ee4, 0x75}, - {0x5ee5, 0x75}, - {0x5ee6, 0x75}, - {0x5ee7, 0x75}, - {0x5ee8, 0x75}, - {0x5ee9, 0x75}, - {0x5eea, 0x75}, - {0x5eeb, 0x75}, - {0x5eec, 0x75}, - {0x5eed, 0x75}, - {0x5eee, 0x75}, - {0x5eef, 0x75}, - {0x5ef0, 0x75}, - {0x5ef1, 0x75}, - {0x5ef2, 0x75}, - {0x5ef3, 0x75}, - {0x5ef4, 0x75}, - {0x5ef5, 0x75}, - {0x5ef6, 0x75}, - {0x5ef7, 0x75}, - {0x5ef8, 0x75}, - {0x5ef9, 0x75}, - {0x5efa, 0x75}, - {0x5efb, 0x75}, - {0x5efc, 0x75}, - {0x5efd, 0x75}, - {0x5efe, 0x75}, - {0x5eff, 0x75}, - {0x5f00, 0x75}, - {0x5f01, 0x75}, - {0x5f02, 0x75}, - {0x5f03, 0x75}, - {0x5f04, 0x75}, - {0x5f05, 0x75}, - {0x5f06, 0x75}, - {0x5f07, 0x75}, - {0x5f08, 0x75}, - {0x5f09, 0x75}, - {0x5f0a, 0x75}, - {0x5f0b, 0x75}, - {0x5f0c, 0x75}, - {0x5f0d, 0x75}, - {0x5f0e, 0x75}, - {0x5f0f, 0x75}, - {0x5f10, 0x75}, - {0x5f11, 0x75}, - {0x5f12, 0x75}, - {0x5f13, 0x75}, - {0x5f14, 0x75}, - {0x5f15, 0x75}, - {0x5f16, 0x75}, - {0x5f17, 0x75}, - {0x5f18, 0x75}, - {0x5f19, 0x75}, - {0x5f1a, 0x75}, - {0x5f1b, 0x75}, - {0x5f1c, 0x75}, - {0x5f1d, 0x75}, - {0x5f1e, 0x75}, - {0x5f1f, 0x75}, }; static const struct ov08x40_reg mode_1928x1208_regs[] = { @@ -2354,7 +1214,7 @@ static const char * const ov08x40_test_pattern_menu[] = { /* Configurations for supported link frequencies */ #define OV08X40_LINK_FREQ_400MHZ 400000000ULL - +#define OV08X40_SCLK_96MHZ 96000000ULL #define OV08X40_EXT_CLK 19200000 #define OV08X40_DATA_LANES 4 @@ -2392,26 +1252,30 @@ static const struct ov08x40_mode supported_modes[] = { .height = 2416, .vts_def = OV08X40_VTS_30FPS, .vts_min = OV08X40_VTS_30FPS, - .hts = 640, + .llp = 0x10aa, /* in normal mode, tline time = 2 * HTS / SCLK */ .lanes = 4, .reg_list = { .num_of_regs = ARRAY_SIZE(mode_3856x2416_regs), .regs = mode_3856x2416_regs, }, .link_freq_index = OV08X40_LINK_FREQ_400MHZ_INDEX, + .exposure_shift = 1, + .exposure_margin = OV08X40_EXPOSURE_MAX_MARGIN, }, { .width = 1928, .height = 1208, .vts_def = OV08X40_VTS_BIN_30FPS, .vts_min = OV08X40_VTS_BIN_30FPS, - .hts = 720, + .llp = 0x960, .lanes = 4, .reg_list = { .num_of_regs = ARRAY_SIZE(mode_1928x1208_regs), .regs = mode_1928x1208_regs, }, .link_freq_index = OV08X40_LINK_FREQ_400MHZ_INDEX, + .exposure_shift = 0, + .exposure_margin = OV08X40_EXPOSURE_BIN_MAX_MARGIN, }, }; @@ -2432,6 +1296,9 @@ struct ov08x40 { /* Mutex for serialized access */ struct mutex mutex; + + /* True if the device has been identified */ + bool identified; }; #define to_ov08x40(_sd) container_of(_sd, struct ov08x40, sd) @@ -2472,6 +1339,40 @@ static int ov08x40_read_reg(struct ov08x40 *ov08x, return 0; } +static int ov08x40_burst_fill_regs(struct ov08x40 *ov08x, u16 first_reg, + u16 last_reg, u8 val) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd); + struct i2c_msg msgs; + size_t i, num_regs; + int ret; + + num_regs = last_reg - first_reg + 1; + msgs.addr = client->addr; + msgs.flags = 0; + msgs.len = 2 + num_regs; + msgs.buf = kmalloc(msgs.len, GFP_KERNEL); + + if (!msgs.buf) + return -ENOMEM; + + put_unaligned_be16(first_reg, msgs.buf); + + for (i = 0; i < num_regs; ++i) + msgs.buf[2 + i] = val; + + ret = i2c_transfer(client->adapter, &msgs, 1); + + kfree(msgs.buf); + + if (ret != 1) { + dev_err(&client->dev, "Failed regs transferred: %d\n", ret); + return -EIO; + } + + return 0; +} + /* Write registers up to 4 at a time */ static int ov08x40_write_reg(struct ov08x40 *ov08x, u16 reg, u32 len, u32 __val) @@ -2664,13 +1565,23 @@ static int ov08x40_set_ctrl(struct v4l2_ctrl *ctrl) struct ov08x40, ctrl_handler); struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd); s64 max; + int exp; + int fll; int ret = 0; /* Propagate change of current control to all related controls */ switch (ctrl->id) { case V4L2_CID_VBLANK: /* Update max exposure while meeting expected vblanking */ - max = ov08x->cur_mode->height + ctrl->val - OV08X40_EXPOSURE_MAX_MARGIN; + /* + * because in normal mode, 1 HTS = 0.5 tline + * fps = sclk / hts / vts + * so the vts value needs to be double + */ + max = ((ov08x->cur_mode->height + ctrl->val) << + ov08x->cur_mode->exposure_shift) - + ov08x->cur_mode->exposure_margin; + __v4l2_ctrl_modify_range(ov08x->exposure, ov08x->exposure->minimum, max, ov08x->exposure->step, max); @@ -2694,15 +1605,20 @@ static int ov08x40_set_ctrl(struct v4l2_ctrl *ctrl) ret = ov08x40_update_digital_gain(ov08x, ctrl->val); break; case V4L2_CID_EXPOSURE: + exp = (ctrl->val << ov08x->cur_mode->exposure_shift) - + ov08x->cur_mode->exposure_margin; + ret = ov08x40_write_reg(ov08x, OV08X40_REG_EXPOSURE, OV08X40_REG_VALUE_24BIT, - ctrl->val); + exp); break; case V4L2_CID_VBLANK: + fll = ((ov08x->cur_mode->height + ctrl->val) << + ov08x->cur_mode->exposure_shift); + ret = ov08x40_write_reg(ov08x, OV08X40_REG_VTS, OV08X40_REG_VALUE_16BIT, - ov08x->cur_mode->height - + ctrl->val); + fll); break; case V4L2_CID_TEST_PATTERN: ret = ov08x40_enable_test_pattern(ov08x, ctrl->val); @@ -2812,6 +1728,7 @@ ov08x40_set_pad_format(struct v4l2_subdev *sd, s64 h_blank; s64 pixel_rate; s64 link_freq; + u64 steps; mutex_lock(&ov08x->mutex); @@ -2839,13 +1756,22 @@ ov08x40_set_pad_format(struct v4l2_subdev *sd, ov08x->cur_mode->height; vblank_min = ov08x->cur_mode->vts_min - ov08x->cur_mode->height; + + /* + * The frame length line should be aligned to a multiple of 4, + * as provided by the sensor vendor, in normal mode. + */ + steps = mode->exposure_shift == 1 ? 4 : 1; + __v4l2_ctrl_modify_range(ov08x->vblank, vblank_min, OV08X40_VTS_MAX - ov08x->cur_mode->height, - 1, + steps, vblank_def); __v4l2_ctrl_s_ctrl(ov08x->vblank, vblank_def); - h_blank = ov08x->cur_mode->hts; + + h_blank = ov08x->cur_mode->llp - ov08x->cur_mode->width; + __v4l2_ctrl_modify_range(ov08x->hblank, h_blank, h_blank, 1, h_blank); } @@ -2887,6 +1813,22 @@ static int ov08x40_start_streaming(struct ov08x40 *ov08x) return ret; } + /* Use i2c burst to write register on full size registers */ + if (ov08x->cur_mode->exposure_shift == 1) { + ret = ov08x40_burst_fill_regs(ov08x, OV08X40_REG_XTALK_FIRST_A, + OV08X40_REG_XTALK_LAST_A, 0x75); + if (ret == 0) + ret = ov08x40_burst_fill_regs(ov08x, + OV08X40_REG_XTALK_FIRST_B, + OV08X40_REG_XTALK_LAST_B, + 0x75); + } + + if (ret) { + dev_err(&client->dev, "%s failed to set regs\n", __func__); + return ret; + } + /* Apply customized values from user */ ret = __v4l2_ctrl_handler_setup(ov08x->sd.ctrl_handler); if (ret) @@ -2948,6 +1890,9 @@ static int ov08x40_identify_module(struct ov08x40 *ov08x) int ret; u32 val; + if (ov08x->identified) + return 0; + ret = ov08x40_read_reg(ov08x, OV08X40_REG_CHIP_ID, OV08X40_REG_VALUE_24BIT, &val); if (ret) @@ -2956,9 +1901,11 @@ static int ov08x40_identify_module(struct ov08x40 *ov08x) if (val != OV08X40_CHIP_ID) { dev_err(&client->dev, "chip id mismatch: %x!=%x\n", OV08X40_CHIP_ID, val); - return -EIO; + return -ENXIO; } + ov08x->identified = true; + return 0; } @@ -3035,7 +1982,8 @@ static int ov08x40_init_controls(struct ov08x40 *ov08x) OV08X40_VTS_MAX - mode->height, 1, vblank_def); - hblank = ov08x->cur_mode->hts; + hblank = ov08x->cur_mode->llp - ov08x->cur_mode->width; + ov08x->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov08x40_ctrl_ops, V4L2_CID_HBLANK, hblank, hblank, 1, hblank); @@ -3175,6 +2123,7 @@ static int ov08x40_probe(struct i2c_client *client) { struct ov08x40 *ov08x; int ret; + bool full_power; /* Check HW config */ ret = ov08x40_check_hwcfg(&client->dev); @@ -3190,11 +2139,14 @@ static int ov08x40_probe(struct i2c_client *client) /* Initialize subdev */ v4l2_i2c_subdev_init(&ov08x->sd, client, &ov08x40_subdev_ops); - /* Check module identity */ - ret = ov08x40_identify_module(ov08x); - if (ret) { - dev_err(&client->dev, "failed to find sensor: %d\n", ret); - return ret; + full_power = acpi_dev_state_d0(&client->dev); + if (full_power) { + /* Check module identity */ + ret = ov08x40_identify_module(ov08x); + if (ret) { + dev_err(&client->dev, "failed to find sensor: %d\n", ret); + return ret; + } } /* Set default mode to max resolution */ @@ -3222,11 +2174,8 @@ static int ov08x40_probe(struct i2c_client *client) if (ret < 0) goto error_media_entity; - /* - * Device is already turned on by i2c-core with ACPI domain PM. - * Enable runtime PM and turn off the device. - */ - pm_runtime_set_active(&client->dev); + if (full_power) + pm_runtime_set_active(&client->dev); pm_runtime_enable(&client->dev); pm_runtime_idle(&client->dev); @@ -3270,11 +2219,13 @@ static struct i2c_driver ov08x40_i2c_driver = { }, .probe = ov08x40_probe, .remove = ov08x40_remove, + .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; module_i2c_driver(ov08x40_i2c_driver); MODULE_AUTHOR("Jason Chen <jason.z.chen@intel.com>"); +MODULE_AUTHOR("Qingwu Zhang <qingwu.zhang@intel.com>"); MODULE_AUTHOR("Shawn Tu"); MODULE_DESCRIPTION("OmniVision OV08X40 sensor driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c index 1d0ef72a64..d1653d7431 100644 --- a/drivers/media/i2c/ov2659.c +++ b/drivers/media/i2c/ov2659.c @@ -1388,7 +1388,7 @@ ov2659_get_pdata(struct i2c_client *client) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) return client->dev.platform_data; - endpoint = of_graph_get_next_endpoint(client->dev.of_node, NULL); + endpoint = of_graph_get_endpoint_by_regs(client->dev.of_node, 0, -1); if (!endpoint) return NULL; diff --git a/drivers/media/i2c/ov2680.c b/drivers/media/i2c/ov2680.c index 39d321e2b7..4577a8977c 100644 --- a/drivers/media/i2c/ov2680.c +++ b/drivers/media/i2c/ov2680.c @@ -1116,25 +1116,24 @@ static int ov2680_parse_dt(struct ov2680_dev *sensor) sensor->pixel_rate = sensor->link_freq[0] * 2; do_div(sensor->pixel_rate, 10); - /* Verify bus cfg */ - if (bus_cfg.bus.mipi_csi2.num_data_lanes != 1) { - ret = dev_err_probe(dev, -EINVAL, - "only a 1-lane CSI2 config is supported"); - goto out_free_bus_cfg; + if (!bus_cfg.nr_of_link_frequencies) { + dev_warn(dev, "Consider passing 'link-frequencies' in DT\n"); + goto skip_link_freq_validation; } for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) if (bus_cfg.link_frequencies[i] == sensor->link_freq[0]) break; - if (bus_cfg.nr_of_link_frequencies == 0 || - bus_cfg.nr_of_link_frequencies == i) { + if (bus_cfg.nr_of_link_frequencies == i) { ret = dev_err_probe(dev, -EINVAL, "supported link freq %lld not found\n", sensor->link_freq[0]); goto out_free_bus_cfg; } +skip_link_freq_validation: + ret = 0; out_free_bus_cfg: v4l2_fwnode_endpoint_free(&bus_cfg); return ret; diff --git a/drivers/media/i2c/ov2740.c b/drivers/media/i2c/ov2740.c index 552935ccb4..57906df7be 100644 --- a/drivers/media/i2c/ov2740.c +++ b/drivers/media/i2c/ov2740.c @@ -768,14 +768,15 @@ static int ov2740_init_controls(struct ov2740 *ov2740) cur_mode = ov2740->cur_mode; size = ARRAY_SIZE(link_freq_menu_items); - ov2740->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &ov2740_ctrl_ops, - V4L2_CID_LINK_FREQ, - size - 1, 0, - link_freq_menu_items); + ov2740->link_freq = + v4l2_ctrl_new_int_menu(ctrl_hdlr, &ov2740_ctrl_ops, + V4L2_CID_LINK_FREQ, size - 1, + ov2740->supported_modes->link_freq_index, + link_freq_menu_items); if (ov2740->link_freq) ov2740->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; - pixel_rate = to_pixel_rate(OV2740_LINK_FREQ_360MHZ_INDEX); + pixel_rate = to_pixel_rate(ov2740->supported_modes->link_freq_index); ov2740->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov2740_ctrl_ops, V4L2_CID_PIXEL_RATE, 0, pixel_rate, 1, pixel_rate); diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c index a26ac11c98..3b22b9e127 100644 --- a/drivers/media/i2c/ov5645.c +++ b/drivers/media/i2c/ov5645.c @@ -118,7 +118,6 @@ static inline struct ov5645 *to_ov5645(struct v4l2_subdev *sd) static const struct reg_value ov5645_global_init_setting[] = { { 0x3103, 0x11 }, - { 0x3008, 0x82 }, { 0x3008, 0x42 }, { 0x3103, 0x03 }, { 0x3503, 0x07 }, @@ -627,6 +626,10 @@ static int ov5645_set_register_array(struct ov5645 *ov5645, ret = ov5645_write_reg(ov5645, settings->reg, settings->val); if (ret < 0) return ret; + + if (settings->reg == OV5645_SYSTEM_CTRL0 && + settings->val == OV5645_SYSTEM_CTRL0_START) + usleep_range(1000, 2000); } return 0; @@ -1056,7 +1059,7 @@ static int ov5645_probe(struct i2c_client *client) ov5645->i2c_client = client; ov5645->dev = dev; - endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); + endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1); if (!endpoint) { dev_err(dev, "endpoint node not found\n"); return -EINVAL; diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c index 96c0fd4ff5..7e1ecdf248 100644 --- a/drivers/media/i2c/ov5647.c +++ b/drivers/media/i2c/ov5647.c @@ -1363,7 +1363,7 @@ static int ov5647_parse_dt(struct ov5647 *sensor, struct device_node *np) struct device_node *ep; int ret; - ep = of_graph_get_next_endpoint(np, NULL); + ep = of_graph_get_endpoint_by_regs(np, 0, -1); if (!ep) return -EINVAL; diff --git a/drivers/media/i2c/ov64a40.c b/drivers/media/i2c/ov64a40.c index 4fba4c2cb0..541bf74581 100644 --- a/drivers/media/i2c/ov64a40.c +++ b/drivers/media/i2c/ov64a40.c @@ -3287,7 +3287,7 @@ static int ov64a40_set_ctrl(struct v4l2_ctrl *ctrl) exp_max, 1, exp_val); } - pm_status = pm_runtime_get_if_active(ov64a40->dev, true); + pm_status = pm_runtime_get_if_active(ov64a40->dev); if (!pm_status) return 0; diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index af8d01f78c..cf6be509af 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -1568,7 +1568,7 @@ static int s5c73m3_get_dt_data(struct s5c73m3 *state) "failed to request gpio S5C73M3_RST\n"); gpiod_set_consumer_name(state->reset, "S5C73M3_RST"); - node_ep = of_graph_get_next_endpoint(node, NULL); + node_ep = of_graph_get_endpoint_by_regs(node, 0, -1); if (!node_ep) { dev_warn(dev, "no endpoint defined for node: %pOF\n", node); return 0; diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c index de079d2c92..6b11039c35 100644 --- a/drivers/media/i2c/s5k5baf.c +++ b/drivers/media/i2c/s5k5baf.c @@ -1849,7 +1849,7 @@ static int s5k5baf_parse_device_node(struct s5k5baf *state, struct device *dev) state->mclk_frequency); } - node_ep = of_graph_get_next_endpoint(node, NULL); + node_ep = of_graph_get_endpoint_by_regs(node, 0, -1); if (!node_ep) { dev_err(dev, "no endpoint defined at node %pOF\n", node); return -EINVAL; diff --git a/drivers/media/i2c/st-vgxy61.c b/drivers/media/i2c/st-vgxy61.c index e4d37a1977..b9e7c57027 100644 --- a/drivers/media/i2c/st-vgxy61.c +++ b/drivers/media/i2c/st-vgxy61.c @@ -12,6 +12,7 @@ #include <linux/iopoll.h> #include <linux/module.h> #include <linux/pm_runtime.h> +#include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/units.h> @@ -19,79 +20,74 @@ #include <media/mipi-csi2.h> #include <media/v4l2-async.h> +#include <media/v4l2-cci.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-event.h> #include <media/v4l2-fwnode.h> #include <media/v4l2-subdev.h> -#define VGXY61_REG_8BIT(n) ((1 << 16) | (n)) -#define VGXY61_REG_16BIT(n) ((2 << 16) | (n)) -#define VGXY61_REG_32BIT(n) ((4 << 16) | (n)) -#define VGXY61_REG_SIZE_SHIFT 16 -#define VGXY61_REG_ADDR_MASK 0xffff - -#define VGXY61_REG_MODEL_ID VGXY61_REG_16BIT(0x0000) +#define VGXY61_REG_MODEL_ID CCI_REG16_LE(0x0000) #define VG5661_MODEL_ID 0x5661 #define VG5761_MODEL_ID 0x5761 -#define VGXY61_REG_REVISION VGXY61_REG_16BIT(0x0002) -#define VGXY61_REG_FWPATCH_REVISION VGXY61_REG_16BIT(0x0014) -#define VGXY61_REG_FWPATCH_START_ADDR VGXY61_REG_8BIT(0x2000) -#define VGXY61_REG_SYSTEM_FSM VGXY61_REG_8BIT(0x0020) +#define VGXY61_REG_REVISION CCI_REG16_LE(0x0002) +#define VGXY61_REG_FWPATCH_REVISION CCI_REG16_LE(0x0014) +#define VGXY61_REG_FWPATCH_START_ADDR CCI_REG8(0x2000) +#define VGXY61_REG_SYSTEM_FSM CCI_REG8(0x0020) #define VGXY61_SYSTEM_FSM_SW_STBY 0x03 #define VGXY61_SYSTEM_FSM_STREAMING 0x04 -#define VGXY61_REG_NVM VGXY61_REG_8BIT(0x0023) +#define VGXY61_REG_NVM CCI_REG8(0x0023) #define VGXY61_NVM_OK 0x04 -#define VGXY61_REG_STBY VGXY61_REG_8BIT(0x0201) +#define VGXY61_REG_STBY CCI_REG8(0x0201) #define VGXY61_STBY_NO_REQ 0 #define VGXY61_STBY_REQ_TMP_READ BIT(2) -#define VGXY61_REG_STREAMING VGXY61_REG_8BIT(0x0202) +#define VGXY61_REG_STREAMING CCI_REG8(0x0202) #define VGXY61_STREAMING_NO_REQ 0 #define VGXY61_STREAMING_REQ_STOP BIT(0) #define VGXY61_STREAMING_REQ_START BIT(1) -#define VGXY61_REG_EXT_CLOCK VGXY61_REG_32BIT(0x0220) -#define VGXY61_REG_CLK_PLL_PREDIV VGXY61_REG_8BIT(0x0224) -#define VGXY61_REG_CLK_SYS_PLL_MULT VGXY61_REG_8BIT(0x0225) -#define VGXY61_REG_GPIO_0_CTRL VGXY61_REG_8BIT(0x0236) -#define VGXY61_REG_GPIO_1_CTRL VGXY61_REG_8BIT(0x0237) -#define VGXY61_REG_GPIO_2_CTRL VGXY61_REG_8BIT(0x0238) -#define VGXY61_REG_GPIO_3_CTRL VGXY61_REG_8BIT(0x0239) -#define VGXY61_REG_SIGNALS_POLARITY_CTRL VGXY61_REG_8BIT(0x023b) -#define VGXY61_REG_LINE_LENGTH VGXY61_REG_16BIT(0x0300) -#define VGXY61_REG_ORIENTATION VGXY61_REG_8BIT(0x0302) -#define VGXY61_REG_VT_CTRL VGXY61_REG_8BIT(0x0304) -#define VGXY61_REG_FORMAT_CTRL VGXY61_REG_8BIT(0x0305) -#define VGXY61_REG_OIF_CTRL VGXY61_REG_16BIT(0x0306) -#define VGXY61_REG_OIF_ROI0_CTRL VGXY61_REG_8BIT(0x030a) -#define VGXY61_REG_ROI0_START_H VGXY61_REG_16BIT(0x0400) -#define VGXY61_REG_ROI0_START_V VGXY61_REG_16BIT(0x0402) -#define VGXY61_REG_ROI0_END_H VGXY61_REG_16BIT(0x0404) -#define VGXY61_REG_ROI0_END_V VGXY61_REG_16BIT(0x0406) -#define VGXY61_REG_PATGEN_CTRL VGXY61_REG_32BIT(0x0440) +#define VGXY61_REG_EXT_CLOCK CCI_REG32_LE(0x0220) +#define VGXY61_REG_CLK_PLL_PREDIV CCI_REG8(0x0224) +#define VGXY61_REG_CLK_SYS_PLL_MULT CCI_REG8(0x0225) +#define VGXY61_REG_GPIO_0_CTRL CCI_REG8(0x0236) +#define VGXY61_REG_GPIO_1_CTRL CCI_REG8(0x0237) +#define VGXY61_REG_GPIO_2_CTRL CCI_REG8(0x0238) +#define VGXY61_REG_GPIO_3_CTRL CCI_REG8(0x0239) +#define VGXY61_REG_SIGNALS_POLARITY_CTRL CCI_REG8(0x023b) +#define VGXY61_REG_LINE_LENGTH CCI_REG16_LE(0x0300) +#define VGXY61_REG_ORIENTATION CCI_REG8(0x0302) +#define VGXY61_REG_VT_CTRL CCI_REG8(0x0304) +#define VGXY61_REG_FORMAT_CTRL CCI_REG8(0x0305) +#define VGXY61_REG_OIF_CTRL CCI_REG16_LE(0x0306) +#define VGXY61_REG_OIF_ROI0_CTRL CCI_REG8(0x030a) +#define VGXY61_REG_ROI0_START_H CCI_REG16_LE(0x0400) +#define VGXY61_REG_ROI0_START_V CCI_REG16_LE(0x0402) +#define VGXY61_REG_ROI0_END_H CCI_REG16_LE(0x0404) +#define VGXY61_REG_ROI0_END_V CCI_REG16_LE(0x0406) +#define VGXY61_REG_PATGEN_CTRL CCI_REG32_LE(0x0440) #define VGXY61_PATGEN_LONG_ENABLE BIT(16) #define VGXY61_PATGEN_SHORT_ENABLE BIT(0) #define VGXY61_PATGEN_LONG_TYPE_SHIFT 18 #define VGXY61_PATGEN_SHORT_TYPE_SHIFT 4 -#define VGXY61_REG_FRAME_CONTENT_CTRL VGXY61_REG_8BIT(0x0478) -#define VGXY61_REG_COARSE_EXPOSURE_LONG VGXY61_REG_16BIT(0x0500) -#define VGXY61_REG_COARSE_EXPOSURE_SHORT VGXY61_REG_16BIT(0x0504) -#define VGXY61_REG_ANALOG_GAIN VGXY61_REG_8BIT(0x0508) -#define VGXY61_REG_DIGITAL_GAIN_LONG VGXY61_REG_16BIT(0x050a) -#define VGXY61_REG_DIGITAL_GAIN_SHORT VGXY61_REG_16BIT(0x0512) -#define VGXY61_REG_FRAME_LENGTH VGXY61_REG_16BIT(0x051a) -#define VGXY61_REG_SIGNALS_CTRL VGXY61_REG_16BIT(0x0522) +#define VGXY61_REG_FRAME_CONTENT_CTRL CCI_REG8(0x0478) +#define VGXY61_REG_COARSE_EXPOSURE_LONG CCI_REG16_LE(0x0500) +#define VGXY61_REG_COARSE_EXPOSURE_SHORT CCI_REG16_LE(0x0504) +#define VGXY61_REG_ANALOG_GAIN CCI_REG8(0x0508) +#define VGXY61_REG_DIGITAL_GAIN_LONG CCI_REG16_LE(0x050a) +#define VGXY61_REG_DIGITAL_GAIN_SHORT CCI_REG16_LE(0x0512) +#define VGXY61_REG_FRAME_LENGTH CCI_REG16_LE(0x051a) +#define VGXY61_REG_SIGNALS_CTRL CCI_REG16_LE(0x0522) #define VGXY61_SIGNALS_GPIO_ID_SHIFT 4 -#define VGXY61_REG_READOUT_CTRL VGXY61_REG_8BIT(0x0530) -#define VGXY61_REG_HDR_CTRL VGXY61_REG_8BIT(0x0532) -#define VGXY61_REG_PATGEN_LONG_DATA_GR VGXY61_REG_16BIT(0x092c) -#define VGXY61_REG_PATGEN_LONG_DATA_R VGXY61_REG_16BIT(0x092e) -#define VGXY61_REG_PATGEN_LONG_DATA_B VGXY61_REG_16BIT(0x0930) -#define VGXY61_REG_PATGEN_LONG_DATA_GB VGXY61_REG_16BIT(0x0932) -#define VGXY61_REG_PATGEN_SHORT_DATA_GR VGXY61_REG_16BIT(0x0950) -#define VGXY61_REG_PATGEN_SHORT_DATA_R VGXY61_REG_16BIT(0x0952) -#define VGXY61_REG_PATGEN_SHORT_DATA_B VGXY61_REG_16BIT(0x0954) -#define VGXY61_REG_PATGEN_SHORT_DATA_GB VGXY61_REG_16BIT(0x0956) -#define VGXY61_REG_BYPASS_CTRL VGXY61_REG_8BIT(0x0a60) +#define VGXY61_REG_READOUT_CTRL CCI_REG8(0x0530) +#define VGXY61_REG_HDR_CTRL CCI_REG8(0x0532) +#define VGXY61_REG_PATGEN_LONG_DATA_GR CCI_REG16_LE(0x092c) +#define VGXY61_REG_PATGEN_LONG_DATA_R CCI_REG16_LE(0x092e) +#define VGXY61_REG_PATGEN_LONG_DATA_B CCI_REG16_LE(0x0930) +#define VGXY61_REG_PATGEN_LONG_DATA_GB CCI_REG16_LE(0x0932) +#define VGXY61_REG_PATGEN_SHORT_DATA_GR CCI_REG16_LE(0x0950) +#define VGXY61_REG_PATGEN_SHORT_DATA_R CCI_REG16_LE(0x0952) +#define VGXY61_REG_PATGEN_SHORT_DATA_B CCI_REG16_LE(0x0954) +#define VGXY61_REG_PATGEN_SHORT_DATA_GB CCI_REG16_LE(0x0956) +#define VGXY61_REG_BYPASS_CTRL CCI_REG8(0x0a60) #define VGX661_WIDTH 1464 #define VGX661_HEIGHT 1104 @@ -384,6 +380,7 @@ static const struct vgxy61_mode_info vgx761_mode_data[] = { struct vgxy61_dev { struct i2c_client *i2c_client; + struct regmap *regmap; struct v4l2_subdev sd; struct media_pad pad; struct regulator_bulk_data supplies[ARRAY_SIZE(vgxy61_supply_name)]; @@ -510,82 +507,6 @@ static unsigned int get_chunk_size(struct vgxy61_dev *sensor) return max(max_write_len, 1); } -static int vgxy61_read_multiple(struct vgxy61_dev *sensor, u32 reg, - unsigned int len) -{ - struct i2c_client *client = sensor->i2c_client; - struct i2c_msg msg[2]; - u8 buf[2]; - u8 val[sizeof(u32)] = {0}; - int ret; - - if (len > sizeof(u32)) - return -EINVAL; - buf[0] = reg >> 8; - buf[1] = reg & 0xff; - - msg[0].addr = client->addr; - msg[0].flags = client->flags; - msg[0].buf = buf; - msg[0].len = sizeof(buf); - - msg[1].addr = client->addr; - msg[1].flags = client->flags | I2C_M_RD; - msg[1].buf = val; - msg[1].len = len; - - ret = i2c_transfer(client->adapter, msg, 2); - if (ret < 0) { - dev_dbg(&client->dev, "%s: %x i2c_transfer, reg: %x => %d\n", - __func__, client->addr, reg, ret); - return ret; - } - - return get_unaligned_le32(val); -} - -static inline int vgxy61_read_reg(struct vgxy61_dev *sensor, u32 reg) -{ - return vgxy61_read_multiple(sensor, reg & VGXY61_REG_ADDR_MASK, - (reg >> VGXY61_REG_SIZE_SHIFT) & 7); -} - -static int vgxy61_write_multiple(struct vgxy61_dev *sensor, u32 reg, - const u8 *data, unsigned int len, int *err) -{ - struct i2c_client *client = sensor->i2c_client; - struct i2c_msg msg; - u8 buf[VGXY61_WRITE_MULTIPLE_CHUNK_MAX + 2]; - unsigned int i; - int ret; - - if (err && *err) - return *err; - - if (len > VGXY61_WRITE_MULTIPLE_CHUNK_MAX) - return -EINVAL; - buf[0] = reg >> 8; - buf[1] = reg & 0xff; - for (i = 0; i < len; i++) - buf[i + 2] = data[i]; - - msg.addr = client->addr; - msg.flags = client->flags; - msg.buf = buf; - msg.len = len + 2; - - ret = i2c_transfer(client->adapter, &msg, 1); - if (ret < 0) { - dev_dbg(&client->dev, "%s: i2c_transfer, reg: %x => %d\n", - __func__, reg, ret); - if (err) - *err = ret; - return ret; - } - - return 0; -} - static int vgxy61_write_array(struct vgxy61_dev *sensor, u32 reg, unsigned int nb, const u8 *array) { @@ -595,7 +516,8 @@ static int vgxy61_write_array(struct vgxy61_dev *sensor, u32 reg, while (nb) { sz = min(nb, chunk_size); - ret = vgxy61_write_multiple(sensor, reg, array, sz, NULL); + ret = regmap_bulk_write(sensor->regmap, CCI_REG_ADDR(reg), + array, sz); if (ret < 0) return ret; nb -= sz; @@ -606,24 +528,17 @@ static int vgxy61_write_array(struct vgxy61_dev *sensor, u32 reg, return 0; } -static inline int vgxy61_write_reg(struct vgxy61_dev *sensor, u32 reg, u32 val, - int *err) -{ - return vgxy61_write_multiple(sensor, reg & VGXY61_REG_ADDR_MASK, - (u8 *)&val, - (reg >> VGXY61_REG_SIZE_SHIFT) & 7, err); -} - static int vgxy61_poll_reg(struct vgxy61_dev *sensor, u32 reg, u8 poll_val, unsigned int timeout_ms) { const unsigned int loop_delay_ms = 10; + u64 val; int ret; - return read_poll_timeout(vgxy61_read_reg, ret, - ((ret < 0) || (ret == poll_val)), + return read_poll_timeout(cci_read, ret, + ((ret < 0) || (val == poll_val)), loop_delay_ms * 1000, timeout_ms * 1000, - false, sensor, reg); + false, sensor->regmap, reg, &val, NULL); } static int vgxy61_wait_state(struct vgxy61_dev *sensor, int state, @@ -662,11 +577,11 @@ static int vgxy61_apply_exposure(struct vgxy61_dev *sensor) int ret = 0; /* We first set expo to zero to avoid forbidden parameters couple */ - vgxy61_write_reg(sensor, VGXY61_REG_COARSE_EXPOSURE_SHORT, 0, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_COARSE_EXPOSURE_LONG, - sensor->expo_long, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_COARSE_EXPOSURE_SHORT, - sensor->expo_short, &ret); + cci_write(sensor->regmap, VGXY61_REG_COARSE_EXPOSURE_SHORT, 0, &ret); + cci_write(sensor->regmap, VGXY61_REG_COARSE_EXPOSURE_LONG, + sensor->expo_long, &ret); + cci_write(sensor->regmap, VGXY61_REG_COARSE_EXPOSURE_SHORT, + sensor->expo_short, &ret); return ret; } @@ -714,7 +629,7 @@ static int vgxy61_try_fmt_internal(struct v4l2_subdev *sd, const struct vgxy61_mode_info **new_mode) { struct vgxy61_dev *sensor = to_vgxy61_dev(sd); - const struct vgxy61_mode_info *mode = sensor->sensor_modes; + const struct vgxy61_mode_info *mode; unsigned int index; for (index = 0; index < ARRAY_SIZE(vgxy61_supported_codes); index++) { @@ -827,8 +742,8 @@ static int vgxy61_update_analog_gain(struct vgxy61_dev *sensor, u32 target) sensor->analog_gain = target; if (sensor->streaming) - return vgxy61_write_reg(sensor, VGXY61_REG_ANALOG_GAIN, target, - NULL); + return cci_write(sensor->regmap, VGXY61_REG_ANALOG_GAIN, target, + NULL); return 0; } @@ -842,10 +757,10 @@ static int vgxy61_apply_digital_gain(struct vgxy61_dev *sensor, * DIGITAL_GAIN_SHORT_CH0 is enough to configure the gain of all * four sub pixels. */ - vgxy61_write_reg(sensor, VGXY61_REG_DIGITAL_GAIN_LONG, digital_gain, - &ret); - vgxy61_write_reg(sensor, VGXY61_REG_DIGITAL_GAIN_SHORT, digital_gain, - &ret); + cci_write(sensor->regmap, VGXY61_REG_DIGITAL_GAIN_LONG, digital_gain, + &ret); + cci_write(sensor->regmap, VGXY61_REG_DIGITAL_GAIN_SHORT, digital_gain, + &ret); return ret; } @@ -870,7 +785,7 @@ static int vgxy61_apply_patgen(struct vgxy61_dev *sensor, u32 index) if (pattern) reg |= VGXY61_PATGEN_LONG_ENABLE | VGXY61_PATGEN_SHORT_ENABLE; - return vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_CTRL, reg, NULL); + return cci_write(sensor->regmap, VGXY61_REG_PATGEN_CTRL, reg, NULL); } static int vgxy61_update_patgen(struct vgxy61_dev *sensor, u32 pattern) @@ -887,15 +802,13 @@ static int vgxy61_apply_gpiox_strobe_mode(struct vgxy61_dev *sensor, unsigned int idx) { static const u8 index2val[] = {0x0, 0x1, 0x3}; - int reg; + u16 mask, val; - reg = vgxy61_read_reg(sensor, VGXY61_REG_SIGNALS_CTRL); - if (reg < 0) - return reg; - reg &= ~(0xf << (idx * VGXY61_SIGNALS_GPIO_ID_SHIFT)); - reg |= index2val[mode] << (idx * VGXY61_SIGNALS_GPIO_ID_SHIFT); + mask = 0xf << (idx * VGXY61_SIGNALS_GPIO_ID_SHIFT); + val = index2val[mode] << (idx * VGXY61_SIGNALS_GPIO_ID_SHIFT); - return vgxy61_write_reg(sensor, VGXY61_REG_SIGNALS_CTRL, reg, NULL); + return cci_update_bits(sensor->regmap, VGXY61_REG_SIGNALS_CTRL, + mask, val, NULL); } static int vgxy61_update_gpios_strobe_mode(struct vgxy61_dev *sensor, @@ -940,12 +853,12 @@ static int vgxy61_update_gpios_strobe_polarity(struct vgxy61_dev *sensor, if (sensor->streaming) return -EBUSY; - vgxy61_write_reg(sensor, VGXY61_REG_GPIO_0_CTRL, polarity << 1, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_GPIO_1_CTRL, polarity << 1, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_GPIO_2_CTRL, polarity << 1, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_GPIO_3_CTRL, polarity << 1, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_SIGNALS_POLARITY_CTRL, polarity, - &ret); + cci_write(sensor->regmap, VGXY61_REG_GPIO_0_CTRL, polarity << 1, &ret); + cci_write(sensor->regmap, VGXY61_REG_GPIO_1_CTRL, polarity << 1, &ret); + cci_write(sensor->regmap, VGXY61_REG_GPIO_2_CTRL, polarity << 1, &ret); + cci_write(sensor->regmap, VGXY61_REG_GPIO_3_CTRL, polarity << 1, &ret); + cci_write(sensor->regmap, VGXY61_REG_SIGNALS_POLARITY_CTRL, polarity, + &ret); return ret; } @@ -1057,8 +970,8 @@ static int vgxy61_update_exposure(struct vgxy61_dev *sensor, u16 new_expo_long, static int vgxy61_apply_framelength(struct vgxy61_dev *sensor) { - return vgxy61_write_reg(sensor, VGXY61_REG_FRAME_LENGTH, - sensor->frame_length, NULL); + return cci_write(sensor->regmap, VGXY61_REG_FRAME_LENGTH, + sensor->frame_length, NULL); } static int vgxy61_update_vblank(struct vgxy61_dev *sensor, u16 vblank, @@ -1086,8 +999,8 @@ static int vgxy61_apply_hdr(struct vgxy61_dev *sensor, { static const u8 index2val[] = {0x1, 0x4, 0xa}; - return vgxy61_write_reg(sensor, VGXY61_REG_HDR_CTRL, index2val[index], - NULL); + return cci_write(sensor->regmap, VGXY61_REG_HDR_CTRL, index2val[index], + NULL); } static int vgxy61_update_hdr(struct vgxy61_dev *sensor, @@ -1133,16 +1046,16 @@ static int vgxy61_apply_settings(struct vgxy61_dev *sensor) if (ret) return ret; - ret = vgxy61_write_reg(sensor, VGXY61_REG_ANALOG_GAIN, - sensor->analog_gain, NULL); + ret = cci_write(sensor->regmap, VGXY61_REG_ANALOG_GAIN, + sensor->analog_gain, NULL); if (ret) return ret; ret = vgxy61_apply_digital_gain(sensor, sensor->digital_gain); if (ret) return ret; - ret = vgxy61_write_reg(sensor, VGXY61_REG_ORIENTATION, - sensor->hflip | (sensor->vflip << 1), NULL); + ret = cci_write(sensor->regmap, VGXY61_REG_ORIENTATION, + sensor->hflip | (sensor->vflip << 1), NULL); if (ret) return ret; @@ -1174,19 +1087,19 @@ static int vgxy61_stream_enable(struct vgxy61_dev *sensor) if (ret) return ret; - vgxy61_write_reg(sensor, VGXY61_REG_FORMAT_CTRL, - get_bpp_by_code(sensor->fmt.code), &ret); - vgxy61_write_reg(sensor, VGXY61_REG_OIF_ROI0_CTRL, - get_data_type_by_code(sensor->fmt.code), &ret); - - vgxy61_write_reg(sensor, VGXY61_REG_READOUT_CTRL, - sensor->current_mode->bin_mode, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_ROI0_START_H, crop->left, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_ROI0_END_H, - crop->left + crop->width - 1, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_ROI0_START_V, crop->top, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_ROI0_END_V, - crop->top + crop->height - 1, &ret); + cci_write(sensor->regmap, VGXY61_REG_FORMAT_CTRL, + get_bpp_by_code(sensor->fmt.code), &ret); + cci_write(sensor->regmap, VGXY61_REG_OIF_ROI0_CTRL, + get_data_type_by_code(sensor->fmt.code), &ret); + + cci_write(sensor->regmap, VGXY61_REG_READOUT_CTRL, + sensor->current_mode->bin_mode, &ret); + cci_write(sensor->regmap, VGXY61_REG_ROI0_START_H, crop->left, &ret); + cci_write(sensor->regmap, VGXY61_REG_ROI0_END_H, + crop->left + crop->width - 1, &ret); + cci_write(sensor->regmap, VGXY61_REG_ROI0_START_V, crop->top, &ret); + cci_write(sensor->regmap, VGXY61_REG_ROI0_END_V, + crop->top + crop->height - 1, &ret); if (ret) goto err_rpm_put; @@ -1194,8 +1107,8 @@ static int vgxy61_stream_enable(struct vgxy61_dev *sensor) if (ret) goto err_rpm_put; - ret = vgxy61_write_reg(sensor, VGXY61_REG_STREAMING, - VGXY61_STREAMING_REQ_START, NULL); + ret = cci_write(sensor->regmap, VGXY61_REG_STREAMING, + VGXY61_STREAMING_REQ_START, NULL); if (ret) goto err_rpm_put; @@ -1225,8 +1138,8 @@ static int vgxy61_stream_disable(struct vgxy61_dev *sensor) struct i2c_client *client = v4l2_get_subdevdata(&sensor->sd); int ret; - ret = vgxy61_write_reg(sensor, VGXY61_REG_STREAMING, - VGXY61_STREAMING_REQ_STOP, NULL); + ret = cci_write(sensor->regmap, VGXY61_REG_STREAMING, + VGXY61_STREAMING_REQ_STOP, NULL); if (ret) goto err_str_dis; @@ -1582,7 +1495,7 @@ static int vgxy61_configure(struct vgxy61_dev *sensor) { u32 sensor_freq; u8 prediv, mult; - int line_length; + u64 line_length; int ret = 0; compute_pll_parameters_by_freq(sensor->clk_freq, &prediv, &mult); @@ -1592,28 +1505,28 @@ static int vgxy61_configure(struct vgxy61_dev *sensor) /* Video timing ISP path (pixel clock) requires 804/5 mhz = 160 mhz */ sensor->pclk = sensor_freq / 5; - line_length = vgxy61_read_reg(sensor, VGXY61_REG_LINE_LENGTH); - if (line_length < 0) - return line_length; - sensor->line_length = line_length; - vgxy61_write_reg(sensor, VGXY61_REG_EXT_CLOCK, sensor->clk_freq, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_CLK_PLL_PREDIV, prediv, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_CLK_SYS_PLL_MULT, mult, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_OIF_CTRL, sensor->oif_ctrl, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_FRAME_CONTENT_CTRL, 0, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_BYPASS_CTRL, 4, &ret); + cci_read(sensor->regmap, VGXY61_REG_LINE_LENGTH, &line_length, &ret); + if (ret < 0) + return ret; + sensor->line_length = (u16)line_length; + cci_write(sensor->regmap, VGXY61_REG_EXT_CLOCK, sensor->clk_freq, &ret); + cci_write(sensor->regmap, VGXY61_REG_CLK_PLL_PREDIV, prediv, &ret); + cci_write(sensor->regmap, VGXY61_REG_CLK_SYS_PLL_MULT, mult, &ret); + cci_write(sensor->regmap, VGXY61_REG_OIF_CTRL, sensor->oif_ctrl, &ret); + cci_write(sensor->regmap, VGXY61_REG_FRAME_CONTENT_CTRL, 0, &ret); + cci_write(sensor->regmap, VGXY61_REG_BYPASS_CTRL, 4, &ret); if (ret) return ret; vgxy61_update_gpios_strobe_polarity(sensor, sensor->gpios_polarity); /* Set pattern generator solid to middle value */ - vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_LONG_DATA_GR, 0x800, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_LONG_DATA_R, 0x800, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_LONG_DATA_B, 0x800, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_LONG_DATA_GB, 0x800, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_SHORT_DATA_GR, 0x800, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_SHORT_DATA_R, 0x800, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_SHORT_DATA_B, 0x800, &ret); - vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_SHORT_DATA_GB, 0x800, &ret); + cci_write(sensor->regmap, VGXY61_REG_PATGEN_LONG_DATA_GR, 0x800, &ret); + cci_write(sensor->regmap, VGXY61_REG_PATGEN_LONG_DATA_R, 0x800, &ret); + cci_write(sensor->regmap, VGXY61_REG_PATGEN_LONG_DATA_B, 0x800, &ret); + cci_write(sensor->regmap, VGXY61_REG_PATGEN_LONG_DATA_GB, 0x800, &ret); + cci_write(sensor->regmap, VGXY61_REG_PATGEN_SHORT_DATA_GR, 0x800, &ret); + cci_write(sensor->regmap, VGXY61_REG_PATGEN_SHORT_DATA_R, 0x800, &ret); + cci_write(sensor->regmap, VGXY61_REG_PATGEN_SHORT_DATA_B, 0x800, &ret); + cci_write(sensor->regmap, VGXY61_REG_PATGEN_SHORT_DATA_GB, 0x800, &ret); if (ret) return ret; @@ -1623,37 +1536,33 @@ static int vgxy61_configure(struct vgxy61_dev *sensor) static int vgxy61_patch(struct vgxy61_dev *sensor) { struct i2c_client *client = sensor->i2c_client; - int patch, ret; + u64 patch; + int ret; ret = vgxy61_write_array(sensor, VGXY61_REG_FWPATCH_START_ADDR, sizeof(patch_array), patch_array); - if (ret) - return ret; - - ret = vgxy61_write_reg(sensor, VGXY61_REG_STBY, 0x10, NULL); + cci_write(sensor->regmap, VGXY61_REG_STBY, 0x10, &ret); if (ret) return ret; ret = vgxy61_poll_reg(sensor, VGXY61_REG_STBY, 0, VGXY61_TIMEOUT_MS); - if (ret) + cci_read(sensor->regmap, VGXY61_REG_FWPATCH_REVISION, &patch, &ret); + if (ret < 0) return ret; - patch = vgxy61_read_reg(sensor, VGXY61_REG_FWPATCH_REVISION); - if (patch < 0) - return patch; - if (patch != (VGXY61_FWPATCH_REVISION_MAJOR << 12) + (VGXY61_FWPATCH_REVISION_MINOR << 8) + VGXY61_FWPATCH_REVISION_MICRO) { - dev_err(&client->dev, "bad patch version expected %d.%d.%d got %d.%d.%d\n", + dev_err(&client->dev, + "bad patch version expected %d.%d.%d got %u.%u.%u\n", VGXY61_FWPATCH_REVISION_MAJOR, VGXY61_FWPATCH_REVISION_MINOR, VGXY61_FWPATCH_REVISION_MICRO, - patch >> 12, (patch >> 8) & 0x0f, patch & 0xff); + (u16)patch >> 12, ((u16)patch >> 8) & 0x0f, (u16)patch & 0xff); return -ENODEV; } - dev_dbg(&client->dev, "patch %d.%d.%d applied\n", - patch >> 12, (patch >> 8) & 0x0f, patch & 0xff); + dev_dbg(&client->dev, "patch %u.%u.%u applied\n", + (u16)patch >> 12, ((u16)patch >> 8) & 0x0f, (u16)patch & 0xff); return 0; } @@ -1661,11 +1570,12 @@ static int vgxy61_patch(struct vgxy61_dev *sensor) static int vgxy61_detect_cut_version(struct vgxy61_dev *sensor) { struct i2c_client *client = sensor->i2c_client; - int device_rev; + u64 device_rev; + int ret; - device_rev = vgxy61_read_reg(sensor, VGXY61_REG_REVISION); - if (device_rev < 0) - return device_rev; + ret = cci_read(sensor->regmap, VGXY61_REG_REVISION, &device_rev, NULL); + if (ret < 0) + return ret; switch (device_rev >> 8) { case 0xA: @@ -1687,17 +1597,17 @@ static int vgxy61_detect_cut_version(struct vgxy61_dev *sensor) static int vgxy61_detect(struct vgxy61_dev *sensor) { struct i2c_client *client = sensor->i2c_client; - int id = 0; - int ret, st; + u64 st, id = 0; + int ret; - id = vgxy61_read_reg(sensor, VGXY61_REG_MODEL_ID); - if (id < 0) - return id; + ret = cci_read(sensor->regmap, VGXY61_REG_MODEL_ID, &id, NULL); + if (ret < 0) + return ret; if (id != VG5661_MODEL_ID && id != VG5761_MODEL_ID) { - dev_warn(&client->dev, "Unsupported sensor id %x\n", id); + dev_warn(&client->dev, "Unsupported sensor id %x\n", (u16)id); return -ENODEV; } - dev_dbg(&client->dev, "detected sensor id = 0x%04x\n", id); + dev_dbg(&client->dev, "detected sensor id = 0x%04x\n", (u16)id); sensor->id = id; ret = vgxy61_wait_state(sensor, VGXY61_SYSTEM_FSM_SW_STBY, @@ -1705,11 +1615,11 @@ static int vgxy61_detect(struct vgxy61_dev *sensor) if (ret) return ret; - st = vgxy61_read_reg(sensor, VGXY61_REG_NVM); - if (st < 0) + ret = cci_read(sensor->regmap, VGXY61_REG_NVM, &st, NULL); + if (ret < 0) return st; if (st != VGXY61_NVM_OK) - dev_warn(&client->dev, "Bad nvm state got %d\n", st); + dev_warn(&client->dev, "Bad nvm state got %u\n", (u8)st); ret = vgxy61_detect_cut_version(sensor); if (ret) @@ -1832,6 +1742,12 @@ static int vgxy61_probe(struct i2c_client *client) sensor->analog_gain = 0; sensor->digital_gain = 256; + sensor->regmap = devm_cci_regmap_init_i2c(client, 16); + if (IS_ERR(sensor->regmap)) { + ret = PTR_ERR(sensor->regmap); + return dev_err_probe(dev, ret, "Failed to init regmap\n"); + } + handle = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0, 0); if (!handle) { dev_err(dev, "handle node not found\n"); diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 558152575d..3192a334aa 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -1895,7 +1895,7 @@ static int tc358743_probe_of(struct tc358743_state *state) return dev_err_probe(dev, PTR_ERR(refclk), "failed to get refclk\n"); - ep = of_graph_get_next_endpoint(dev->of_node, NULL); + ep = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1); if (!ep) { dev_err(dev, "missing endpoint node\n"); return -EINVAL; diff --git a/drivers/media/i2c/tc358746.c b/drivers/media/i2c/tc358746.c index 106de4271d..d676adc440 100644 --- a/drivers/media/i2c/tc358746.c +++ b/drivers/media/i2c/tc358746.c @@ -843,14 +843,14 @@ static unsigned long tc358746_find_pll_settings(struct tc358746 *tc358746, if (fin < 4 * HZ_PER_MHZ || fin > 40 * HZ_PER_MHZ) continue; - tmp = fout * p * postdiv; + tmp = fout * postdiv; do_div(tmp, fin); mul = tmp; if (mul > 511) continue; tmp = mul * fin; - do_div(tmp, p * postdiv); + do_div(tmp, postdiv); delta = abs(fout - tmp); if (delta < min_delta) { diff --git a/drivers/media/i2c/tda1997x.c b/drivers/media/i2c/tda1997x.c index 1ea703a990..8e4a0718c4 100644 --- a/drivers/media/i2c/tda1997x.c +++ b/drivers/media/i2c/tda1997x.c @@ -2310,7 +2310,7 @@ static int tda1997x_parse_dt(struct tda1997x_state *state) pdata->vidout_sel_de = DE_FREF_SEL_DE_VHREF; np = state->client->dev.of_node; - ep = of_graph_get_next_endpoint(np, NULL); + ep = of_graph_get_endpoint_by_regs(np, 0, -1); if (!ep) return -EINVAL; diff --git a/drivers/media/i2c/thp7312.c b/drivers/media/i2c/thp7312.c index 2806887514..19bd923a73 100644 --- a/drivers/media/i2c/thp7312.c +++ b/drivers/media/i2c/thp7312.c @@ -1052,7 +1052,7 @@ static int thp7312_s_ctrl(struct v4l2_ctrl *ctrl) if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE) return -EINVAL; - if (!pm_runtime_get_if_active(thp7312->dev, true)) + if (!pm_runtime_get_if_active(thp7312->dev)) return 0; switch (ctrl->id) { diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index 5a561e5bf6..f9c9c80c33 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -987,7 +987,7 @@ tvp514x_get_pdata(struct i2c_client *client) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) return client->dev.platform_data; - endpoint = of_graph_get_next_endpoint(client->dev.of_node, NULL); + endpoint = of_graph_get_endpoint_by_regs(client->dev.of_node, 0, -1); if (!endpoint) return NULL; diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 9fc586cfdc..64b91aa3c8 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1817,7 +1817,7 @@ static struct regmap_config tvp5150_config = { .val_bits = 8, .max_register = 0xff, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .rd_table = &tvp5150_readable_table, .volatile_reg = tvp5150_volatile_reg, diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index 30831b4b56..6a04ffae53 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c @@ -893,7 +893,7 @@ tvp7002_get_pdata(struct i2c_client *client) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) return client->dev.platform_data; - endpoint = of_graph_get_next_endpoint(client->dev.of_node, NULL); + endpoint = of_graph_get_endpoint_by_regs(client->dev.of_node, 0, -1); if (!endpoint) return NULL; |