diff options
author | Álvaro Fernández Rojas <noltari@gmail.com> | 2022-05-16 23:40:32 +0200 |
---|---|---|
committer | Álvaro Fernández Rojas <noltari@gmail.com> | 2022-05-17 15:11:22 +0200 |
commit | 20ea6adbf199097c4f5f591ffee088340630dae4 (patch) | |
tree | d6719d95e136611a1c25bbf7789652d6d402779d /target/linux/bcm27xx/patches-5.15/950-0826-media-i2c-imx258-Support-faster-pixel-rate-on-binned.patch | |
parent | bca05bd072180dc38ef740b37ded9572a6db1981 (diff) | |
download | upstream-20ea6adbf199097c4f5f591ffee088340630dae4.tar.gz upstream-20ea6adbf199097c4f5f591ffee088340630dae4.tar.bz2 upstream-20ea6adbf199097c4f5f591ffee088340630dae4.zip |
bcm27xx: add support for linux v5.15
Build system: x86_64
Build-tested: bcm2708, bcm2709, bcm2710, bcm2711
Run-tested: bcm2708/RPiB+, bcm2709/RPi3B, bcm2710/RPi3B, bcm2711/RPi4B
Signed-off-by: Marty Jones <mj8263788@gmail.com>
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Diffstat (limited to 'target/linux/bcm27xx/patches-5.15/950-0826-media-i2c-imx258-Support-faster-pixel-rate-on-binned.patch')
-rw-r--r-- | target/linux/bcm27xx/patches-5.15/950-0826-media-i2c-imx258-Support-faster-pixel-rate-on-binned.patch | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.15/950-0826-media-i2c-imx258-Support-faster-pixel-rate-on-binned.patch b/target/linux/bcm27xx/patches-5.15/950-0826-media-i2c-imx258-Support-faster-pixel-rate-on-binned.patch new file mode 100644 index 0000000000..af8b8e1670 --- /dev/null +++ b/target/linux/bcm27xx/patches-5.15/950-0826-media-i2c-imx258-Support-faster-pixel-rate-on-binned.patch @@ -0,0 +1,254 @@ +From abf839bec9fa64ce922d63b2625b02e8e5c5b7bb Mon Sep 17 00:00:00 2001 +From: Dave Stevenson <dave.stevenson@raspberrypi.com> +Date: Fri, 1 Apr 2022 18:56:54 +0100 +Subject: [PATCH] media: i2c: imx258: Support faster pixel rate on + binned modes + +With the binned modes, there is little point in faithfully +reproducing the horizontal line length of 5352 pixels on the CSI2 +bus, and the FIFO between the pixel array and MIPI serialiser +allows us to remove that dependency. + +Allow the pixel array to run with the normal settings, with the MIPI +serialiser at half the rate. This requires some additional +information for the link frequency to pixel rate function that +needs to be added to the configuration tables. + +Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> +--- + drivers/media/i2c/imx258.c | 107 ++++++++++++++++++++++++------------- + 1 file changed, 70 insertions(+), 37 deletions(-) + +--- a/drivers/media/i2c/imx258.c ++++ b/drivers/media/i2c/imx258.c +@@ -104,6 +104,11 @@ struct imx258_reg_list { + const struct imx258_reg *regs; + }; + ++struct imx258_link_cfg { ++ unsigned int lf_to_pix_rate_factor; ++ struct imx258_reg_list reg_list; ++}; ++ + #define IMX258_LANE_CONFIGS 2 + #define IMX258_2_LANE_MODE 0 + #define IMX258_4_LANE_MODE 1 +@@ -113,8 +118,8 @@ struct imx258_link_freq_config { + u64 link_frequency; + u32 pixels_per_line; + +- /* PLL registers for this link frequency */ +- struct imx258_reg_list reg_list[IMX258_LANE_CONFIGS]; ++ /* Configuration for this link frequency / num lanes selection */ ++ struct imx258_link_cfg link_cfg[IMX258_LANE_CONFIGS]; + }; + + /* Mode : resolution and related config&values */ +@@ -273,7 +278,7 @@ static const struct imx258_reg mipi_640m + static const struct imx258_reg mipi_642mbps_24mhz_2l[] = { + { 0x0136, 0x18 }, + { 0x0137, 0x00 }, +- { 0x0301, 0x0A }, ++ { 0x0301, 0x05 }, + { 0x0303, 0x02 }, + { 0x0305, 0x04 }, + { 0x0306, 0x00 }, +@@ -690,14 +695,22 @@ enum { + }; + + /* +- * pixel_rate = link_freq * data-rate * nr_of_lanes / bits_per_sample +- * data rate => double data rate; +- * number of lanes => (configurable 2 or 4); +- * bits per pixel => 10 ++ * Pixel rate does not necessarily relate to link frequency on this sensor as ++ * there is a FIFO between the pixel array pipeline and the MIPI serializer. ++ * The recommendation from Sony is that the pixel array is always run with a ++ * line length of 5352 pixels, which means that there is a large amount of ++ * blanking time for the 1048x780 mode. There is no need to replicate this ++ * blanking on the CSI2 bus, and the configuration of register 0x0301 allows the ++ * divider to be altered. ++ * ++ * The actual factor between link frequency and pixel rate is in the ++ * imx258_link_cfg, so use this to convert between the two. ++ * bits per pixel being 10, and D-PHY being DDR is assumed by this function, so ++ * the value is only the combination of number of lanes and pixel clock divider. + */ +-static u64 link_freq_to_pixel_rate(u64 f, unsigned int nlanes) ++static u64 link_freq_to_pixel_rate(u64 f, const struct imx258_link_cfg *link_cfg) + { +- f *= 2 * nlanes; ++ f *= 2 * link_cfg->lf_to_pix_rate_factor; + do_div(f, 10); + + return f; +@@ -722,31 +735,33 @@ static const s64 link_freq_menu_items_24 + IMX258_LINK_FREQ_321MHZ, + }; + ++#define REGS(_list) { .num_of_regs = ARRAY_SIZE(_list), .regs = _list, } ++ + /* Link frequency configs */ + static const struct imx258_link_freq_config link_freq_configs_19_2[] = { + [IMX258_LINK_FREQ_1267MBPS] = { + .pixels_per_line = IMX258_PPL_DEFAULT, +- .reg_list = { ++ .link_cfg = { + [IMX258_2_LANE_MODE] = { +- .num_of_regs = ARRAY_SIZE(mipi_1267mbps_19_2mhz_2l), +- .regs = mipi_1267mbps_19_2mhz_2l, ++ .lf_to_pix_rate_factor = 2 * 2, ++ .reg_list = REGS(mipi_1267mbps_19_2mhz_2l), + }, + [IMX258_4_LANE_MODE] = { +- .num_of_regs = ARRAY_SIZE(mipi_1267mbps_19_2mhz_4l), +- .regs = mipi_1267mbps_19_2mhz_4l, ++ .lf_to_pix_rate_factor = 4, ++ .reg_list = REGS(mipi_1267mbps_19_2mhz_4l), + }, + } + }, + [IMX258_LINK_FREQ_640MBPS] = { + .pixels_per_line = IMX258_PPL_DEFAULT, +- .reg_list = { ++ .link_cfg = { + [IMX258_2_LANE_MODE] = { +- .num_of_regs = ARRAY_SIZE(mipi_640mbps_19_2mhz_2l), +- .regs = mipi_640mbps_19_2mhz_2l, ++ .lf_to_pix_rate_factor = 2, ++ .reg_list = REGS(mipi_640mbps_19_2mhz_2l), + }, + [IMX258_4_LANE_MODE] = { +- .num_of_regs = ARRAY_SIZE(mipi_640mbps_19_2mhz_4l), +- .regs = mipi_640mbps_19_2mhz_4l, ++ .lf_to_pix_rate_factor = 4, ++ .reg_list = REGS(mipi_640mbps_19_2mhz_4l), + }, + } + }, +@@ -755,27 +770,27 @@ static const struct imx258_link_freq_con + static const struct imx258_link_freq_config link_freq_configs_24[] = { + [IMX258_LINK_FREQ_1267MBPS] = { + .pixels_per_line = IMX258_PPL_DEFAULT, +- .reg_list = { ++ .link_cfg = { + [IMX258_2_LANE_MODE] = { +- .num_of_regs = ARRAY_SIZE(mipi_1272mbps_24mhz_2l), +- .regs = mipi_1272mbps_24mhz_2l, ++ .lf_to_pix_rate_factor = 2, ++ .reg_list = REGS(mipi_1272mbps_24mhz_2l), + }, + [IMX258_4_LANE_MODE] = { +- .num_of_regs = ARRAY_SIZE(mipi_1272mbps_24mhz_4l), +- .regs = mipi_1272mbps_24mhz_4l, ++ .lf_to_pix_rate_factor = 4, ++ .reg_list = REGS(mipi_1272mbps_24mhz_4l), + }, + } + }, + [IMX258_LINK_FREQ_640MBPS] = { + .pixels_per_line = IMX258_PPL_DEFAULT, +- .reg_list = { ++ .link_cfg = { + [IMX258_2_LANE_MODE] = { +- .num_of_regs = ARRAY_SIZE(mipi_642mbps_24mhz_2l), +- .regs = mipi_642mbps_24mhz_2l, ++ .lf_to_pix_rate_factor = 2 * 2, ++ .reg_list = REGS(mipi_642mbps_24mhz_2l), + }, + [IMX258_4_LANE_MODE] = { +- .num_of_regs = ARRAY_SIZE(mipi_642mbps_24mhz_4l), +- .regs = mipi_642mbps_24mhz_4l, ++ .lf_to_pix_rate_factor = 4, ++ .reg_list = REGS(mipi_642mbps_24mhz_4l), + }, + } + }, +@@ -857,7 +872,7 @@ struct imx258 { + + const struct imx258_link_freq_config *link_freq_configs; + const s64 *link_freq_menu_items; +- unsigned int nlanes; ++ unsigned int lane_mode_idx; + unsigned int csi2_flags; + + /* +@@ -1212,8 +1227,10 @@ static int imx258_set_pad_format(struct + struct v4l2_subdev_format *fmt) + { + struct imx258 *imx258 = to_imx258(sd); +- const struct imx258_mode *mode; ++ const struct imx258_link_freq_config *link_freq_cfgs; ++ const struct imx258_link_cfg *link_cfg; + struct v4l2_mbus_framefmt *framefmt; ++ const struct imx258_mode *mode; + s32 vblank_def; + s32 vblank_min; + s64 h_blank; +@@ -1236,7 +1253,11 @@ static int imx258_set_pad_format(struct + __v4l2_ctrl_s_ctrl(imx258->link_freq, mode->link_freq_index); + + link_freq = imx258->link_freq_menu_items[mode->link_freq_index]; +- pixel_rate = link_freq_to_pixel_rate(link_freq, imx258->nlanes); ++ link_freq_cfgs = ++ &imx258->link_freq_configs[mode->link_freq_index]; ++ ++ link_cfg = &link_freq_cfgs->link_cfg[imx258->lane_mode_idx]; ++ pixel_rate = link_freq_to_pixel_rate(link_freq, link_cfg); + __v4l2_ctrl_modify_range(imx258->pixel_rate, pixel_rate, + pixel_rate, 1, pixel_rate); + /* Update limits and set FPS to default */ +@@ -1333,7 +1354,8 @@ static int imx258_start_streaming(struct + /* Setup PLL */ + link_freq_index = imx258->cur_mode->link_freq_index; + link_freq_cfg = &imx258->link_freq_configs[link_freq_index]; +- reg_list = &link_freq_cfg->reg_list[imx258->nlanes == 2 ? 0 : 1]; ++ ++ reg_list = &link_freq_cfg->link_cfg[imx258->lane_mode_idx].reg_list; + ret = imx258_write_regs(imx258, reg_list->regs, reg_list->num_of_regs); + if (ret) { + dev_err(&client->dev, "%s failed to set plls\n", __func__); +@@ -1543,8 +1565,10 @@ static const struct v4l2_subdev_internal + static int imx258_init_controls(struct imx258 *imx258) + { + struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd); ++ const struct imx258_link_freq_config *link_freq_cfgs; + struct v4l2_fwnode_device_properties props; + struct v4l2_ctrl_handler *ctrl_hdlr; ++ const struct imx258_link_cfg *link_cfg; + s64 vblank_def; + s64 vblank_min; + s64 pixel_rate; +@@ -1567,8 +1591,11 @@ static int imx258_init_controls(struct i + if (imx258->link_freq) + imx258->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; + ++ link_freq_cfgs = &imx258->link_freq_configs[0]; ++ link_cfg = link_freq_cfgs[imx258->lane_mode_idx].link_cfg; + pixel_rate = link_freq_to_pixel_rate(imx258->link_freq_menu_items[0], +- imx258->nlanes); ++ link_cfg); ++ + /* By default, PIXEL_RATE is read only */ + imx258->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops, + V4L2_CID_PIXEL_RATE, +@@ -1739,10 +1766,16 @@ static int imx258_probe(struct i2c_clien + } + + /* Get number of data lanes */ +- imx258->nlanes = ep.bus.mipi_csi2.num_data_lanes; +- if (imx258->nlanes != 2 && imx258->nlanes != 4) { ++ switch (ep.bus.mipi_csi2.num_data_lanes) { ++ case 2: ++ imx258->lane_mode_idx = IMX258_2_LANE_MODE; ++ break; ++ case 4: ++ imx258->lane_mode_idx = IMX258_4_LANE_MODE; ++ break; ++ default: + dev_err(&client->dev, "Invalid data lanes: %u\n", +- imx258->nlanes); ++ ep.bus.mipi_csi2.num_data_lanes); + ret = -EINVAL; + goto error_endpoint_poweron; + } |