diff options
Diffstat (limited to 'target/linux/bcm27xx/patches-5.4/950-0827-media-i2c-imx290-Add-support-for-74.25MHz-clock.patch')
-rw-r--r-- | target/linux/bcm27xx/patches-5.4/950-0827-media-i2c-imx290-Add-support-for-74.25MHz-clock.patch | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.4/950-0827-media-i2c-imx290-Add-support-for-74.25MHz-clock.patch b/target/linux/bcm27xx/patches-5.4/950-0827-media-i2c-imx290-Add-support-for-74.25MHz-clock.patch new file mode 100644 index 0000000000..87661b7177 --- /dev/null +++ b/target/linux/bcm27xx/patches-5.4/950-0827-media-i2c-imx290-Add-support-for-74.25MHz-clock.patch @@ -0,0 +1,264 @@ +From c175c735869b0dfa8c21fc57d5bd02ca370f9117 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson <dave.stevenson@raspberrypi.com> +Date: Thu, 25 Jun 2020 08:28:51 +0100 +Subject: [PATCH] media: i2c: imx290: Add support for 74.25MHz clock + +The existing driver only supported a clock of 37.125MHz, but the +sensor also supports 74.25MHz. + +Add the relevant register modifications to support this alternate +clock frequency. + +Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> +--- + drivers/media/i2c/imx290.c | 119 ++++++++++++++++++++++++++++++------- + 1 file changed, 97 insertions(+), 22 deletions(-) + +--- a/drivers/media/i2c/imx290.c ++++ b/drivers/media/i2c/imx290.c +@@ -1,6 +1,10 @@ + // SPDX-License-Identifier: GPL-2.0 + /* +- * Sony IMX290 CMOS Image Sensor Driver ++ * Sony IMX290/327 CMOS Image Sensor Driver ++ * ++ * The IMX290 and IMX327 are very similar 1920x1080 1/2.8 CMOS image sensors. ++ * IMX327 can support up to 60fps, whilst IMX290 support up to 120fps (only ++ * 10bit and when connected over 4 CSI-2 lanes). + * + * Copyright (C) 2019 FRAMOS GmbH. + * +@@ -22,6 +26,11 @@ + #include <media/v4l2-fwnode.h> + #include <media/v4l2-subdev.h> + ++enum imx290_clk_index { ++ CLK_37_125, ++ CLK_74_25, ++}; ++ + #define IMX290_STANDBY 0x3000 + #define IMX290_REGHOLD 0x3001 + #define IMX290_XMSTA 0x3002 +@@ -60,11 +69,16 @@ struct imx290_mode { + + const struct imx290_regval *data; + u32 data_size; ++ ++ /* Clock setup can vary. Index as enum imx290_clk_index */ ++ const struct imx290_regval *clk_data[2]; ++ u32 clk_size; + }; + + struct imx290 { + struct device *dev; + struct clk *xclk; ++ u32 xclk_freq; + struct regmap *regmap; + u8 nlanes; + u8 bpp; +@@ -116,8 +130,6 @@ static const struct imx290_regval imx290 + { 0x3018, 0x65 }, + { 0x3019, 0x04 }, + { 0x301a, 0x00 }, +- { 0x3444, 0x20 }, +- { 0x3445, 0x25 }, + { 0x303a, 0x0c }, + { 0x3040, 0x00 }, + { 0x3041, 0x00 }, +@@ -171,6 +183,30 @@ static const struct imx290_regval imx290 + { 0x33b3, 0x04 }, + }; + ++static const struct imx290_regval imx290_37_125mhz_clock_1080p[] = { ++ { 0x305c, 0x18 }, ++ { 0x305d, 0x03 }, ++ { 0x305e, 0x20 }, ++ { 0x305f, 0x01 }, ++ { 0x315e, 0x1a }, ++ { 0x3164, 0x1a }, ++ { 0x3444, 0x20 }, ++ { 0x3445, 0x25 }, ++ { 0x3480, 0x49 }, ++}; ++ ++static const struct imx290_regval imx290_74_250mhz_clock_1080p[] = { ++ { 0x305c, 0x0c }, ++ { 0x305d, 0x03 }, ++ { 0x305e, 0x10 }, ++ { 0x305f, 0x01 }, ++ { 0x315e, 0x1b }, ++ { 0x3164, 0x1b }, ++ { 0x3444, 0x40 }, ++ { 0x3445, 0x4a }, ++ { 0x3480, 0x92 }, ++}; ++ + static const struct imx290_regval imx290_1080p_settings[] = { + /* mode settings */ + { 0x3007, 0x00 }, +@@ -182,13 +218,6 @@ static const struct imx290_regval imx290 + { 0x3419, 0x04 }, + { 0x3012, 0x64 }, + { 0x3013, 0x00 }, +- { 0x305c, 0x18 }, +- { 0x305d, 0x03 }, +- { 0x305e, 0x20 }, +- { 0x305f, 0x01 }, +- { 0x315e, 0x1a }, +- { 0x3164, 0x1a }, +- { 0x3480, 0x49 }, + /* data rate settings */ + { 0x3405, 0x10 }, + { 0x3446, 0x57 }, +@@ -209,6 +238,30 @@ static const struct imx290_regval imx290 + { 0x3455, 0x00 }, + }; + ++static const struct imx290_regval imx290_37_125mhz_clock_720p[] = { ++ { 0x305c, 0x20 }, ++ { 0x305d, 0x00 }, ++ { 0x305e, 0x20 }, ++ { 0x305f, 0x01 }, ++ { 0x315e, 0x1a }, ++ { 0x3164, 0x1a }, ++ { 0x3444, 0x20 }, ++ { 0x3445, 0x25 }, ++ { 0x3480, 0x49 }, ++}; ++ ++static const struct imx290_regval imx290_74_250mhz_clock_720p[] = { ++ { 0x305c, 0x10 }, ++ { 0x305d, 0x00 }, ++ { 0x305e, 0x10 }, ++ { 0x305f, 0x01 }, ++ { 0x315e, 0x1b }, ++ { 0x3164, 0x1b }, ++ { 0x3444, 0x40 }, ++ { 0x3445, 0x4a }, ++ { 0x3480, 0x92 }, ++}; ++ + static const struct imx290_regval imx290_720p_settings[] = { + /* mode settings */ + { 0x3007, 0x10 }, +@@ -220,13 +273,6 @@ static const struct imx290_regval imx290 + { 0x3419, 0x02 }, + { 0x3012, 0x64 }, + { 0x3013, 0x00 }, +- { 0x305c, 0x20 }, +- { 0x305d, 0x00 }, +- { 0x305e, 0x20 }, +- { 0x305f, 0x01 }, +- { 0x315e, 0x1a }, +- { 0x3164, 0x1a }, +- { 0x3480, 0x49 }, + /* data rate settings */ + { 0x3405, 0x10 }, + { 0x3446, 0x4f }, +@@ -312,6 +358,11 @@ static const struct imx290_mode imx290_m + .link_freq_index = FREQ_INDEX_1080P, + .data = imx290_1080p_settings, + .data_size = ARRAY_SIZE(imx290_1080p_settings), ++ .clk_data = { ++ [CLK_37_125] = imx290_37_125mhz_clock_1080p, ++ [CLK_74_25] = imx290_74_250mhz_clock_1080p, ++ }, ++ .clk_size = ARRAY_SIZE(imx290_37_125mhz_clock_1080p), + }, + { + .width = 1280, +@@ -320,6 +371,11 @@ static const struct imx290_mode imx290_m + .link_freq_index = FREQ_INDEX_720P, + .data = imx290_720p_settings, + .data_size = ARRAY_SIZE(imx290_720p_settings), ++ .clk_data = { ++ [CLK_37_125] = imx290_37_125mhz_clock_1080p, ++ [CLK_74_25] = imx290_74_250mhz_clock_1080p, ++ }, ++ .clk_size = ARRAY_SIZE(imx290_37_125mhz_clock_1080p), + }, + }; + +@@ -331,6 +387,11 @@ static const struct imx290_mode imx290_m + .link_freq_index = FREQ_INDEX_1080P, + .data = imx290_1080p_settings, + .data_size = ARRAY_SIZE(imx290_1080p_settings), ++ .clk_data = { ++ [CLK_37_125] = imx290_37_125mhz_clock_720p, ++ [CLK_74_25] = imx290_74_250mhz_clock_720p, ++ }, ++ .clk_size = ARRAY_SIZE(imx290_37_125mhz_clock_720p), + }, + { + .width = 1280, +@@ -339,6 +400,11 @@ static const struct imx290_mode imx290_m + .link_freq_index = FREQ_INDEX_720P, + .data = imx290_720p_settings, + .data_size = ARRAY_SIZE(imx290_720p_settings), ++ .clk_data = { ++ [CLK_37_125] = imx290_37_125mhz_clock_720p, ++ [CLK_74_25] = imx290_74_250mhz_clock_720p, ++ }, ++ .clk_size = ARRAY_SIZE(imx290_37_125mhz_clock_720p), + }, + }; + +@@ -712,6 +778,8 @@ static int imx290_set_hmax(struct imx290 + /* Start streaming */ + static int imx290_start_streaming(struct imx290 *imx290) + { ++ enum imx290_clk_index clk_idx = imx290->xclk_freq == 37125000 ? ++ CLK_37_125 : CLK_74_25; + int ret; + + /* Set init register settings */ +@@ -723,6 +791,14 @@ static int imx290_start_streaming(struct + return ret; + } + ++ ret = imx290_set_register_array(imx290, ++ imx290->current_mode->clk_data[clk_idx], ++ imx290->current_mode->clk_size); ++ if (ret < 0) { ++ dev_err(imx290->dev, "Could not set clock registers\n"); ++ return ret; ++ } ++ + /* Apply the register values related to current frame format */ + ret = imx290_write_current_format(imx290); + if (ret < 0) { +@@ -939,7 +1015,6 @@ static int imx290_probe(struct i2c_clien + .bus_type = V4L2_MBUS_CSI2_DPHY + }; + struct imx290 *imx290; +- u32 xclk_freq; + s64 fq; + int ret; + +@@ -1003,21 +1078,21 @@ static int imx290_probe(struct i2c_clien + } + + ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", +- &xclk_freq); ++ &imx290->xclk_freq); + if (ret) { + dev_err(dev, "Could not get xclk frequency\n"); + goto free_err; + } + + /* external clock must be 37.125 MHz */ +- if (xclk_freq != 37125000) { ++ if (imx290->xclk_freq != 37125000 && imx290->xclk_freq != 74250000) { + dev_err(dev, "External clock frequency %u is not supported\n", +- xclk_freq); ++ imx290->xclk_freq); + ret = -EINVAL; + goto free_err; + } + +- ret = clk_set_rate(imx290->xclk, xclk_freq); ++ ret = clk_set_rate(imx290->xclk, imx290->xclk_freq); + if (ret) { + dev_err(dev, "Could not set xclk frequency\n"); + goto free_err; |