aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.15/950-0826-media-i2c-imx258-Support-faster-pixel-rate-on-binned.patch
diff options
context:
space:
mode:
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
commit20ea6adbf199097c4f5f591ffee088340630dae4 (patch)
treed6719d95e136611a1c25bbf7789652d6d402779d /target/linux/bcm27xx/patches-5.15/950-0826-media-i2c-imx258-Support-faster-pixel-rate-on-binned.patch
parentbca05bd072180dc38ef740b37ded9572a6db1981 (diff)
downloadupstream-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.patch254
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;
+ }