diff options
Diffstat (limited to 'target/linux/bcm27xx/patches-5.15/950-0722-media-i2c-Add-support-for-19.2MHz-clock-to-ov7251.patch')
-rw-r--r-- | target/linux/bcm27xx/patches-5.15/950-0722-media-i2c-Add-support-for-19.2MHz-clock-to-ov7251.patch | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.15/950-0722-media-i2c-Add-support-for-19.2MHz-clock-to-ov7251.patch b/target/linux/bcm27xx/patches-5.15/950-0722-media-i2c-Add-support-for-19.2MHz-clock-to-ov7251.patch new file mode 100644 index 0000000000..6052cfa479 --- /dev/null +++ b/target/linux/bcm27xx/patches-5.15/950-0722-media-i2c-Add-support-for-19.2MHz-clock-to-ov7251.patch @@ -0,0 +1,144 @@ +From 16af9ae925fdb05960f644b6cc84098af8aa3956 Mon Sep 17 00:00:00 2001 +From: Daniel Scally <djrscally@gmail.com> +Date: Tue, 15 Feb 2022 23:07:33 +0000 +Subject: [PATCH] media: i2c: Add support for 19.2MHz clock to ov7251 + +The OV7251 sensor is used as the IR camera sensor on the Microsoft +Surface line of tablets; this provides a 19.2MHz external clock. Add +the ability to support that rate to the driver by defining a new set +of PLL configs. Extend the clock handling in .probe() to check for +either supported frequency. + +Signed-off-by: Daniel Scally <djrscally@gmail.com> +--- + drivers/media/i2c/ov7251.c | 61 ++++++++++++++++++++++++++++---------- + 1 file changed, 45 insertions(+), 16 deletions(-) + +--- a/drivers/media/i2c/ov7251.c ++++ b/drivers/media/i2c/ov7251.c +@@ -134,10 +134,19 @@ static inline struct ov7251 *to_ov7251(s + } + + enum xclk_rate { ++ OV7251_19_2_MHZ, + OV7251_24_MHZ, + OV7251_NUM_SUPPORTED_RATES + }; + ++static const struct ov7251_pll1_config ov7251_pll1_config_19_2_mhz = { ++ .pre_div = 0x03, ++ .mult = 0x4b, ++ .div = 0x01, ++ .pix_div = 0x0a, ++ .mipi_div = 0x05 ++}; ++ + static const struct ov7251_pll1_config ov7251_pll1_config_24_mhz = { + .pre_div = 0x03, + .mult = 0x64, +@@ -146,6 +155,14 @@ static const struct ov7251_pll1_config o + .mipi_div = 0x05 + }; + ++static const struct ov7251_pll2_config ov7251_pll2_config_19_2_mhz = { ++ .pre_div = 0x04, ++ .mult = 0x32, ++ .div = 0x00, ++ .sys_div = 0x05, ++ .adc_div = 0x04 ++}; ++ + static const struct ov7251_pll2_config ov7251_pll2_config_24_mhz = { + .pre_div = 0x04, + .mult = 0x28, +@@ -154,12 +171,18 @@ static const struct ov7251_pll2_config o + .adc_div = 0x04 + }; + ++static const struct ov7251_pll_configs ov7251_pll_configs_19_2_mhz = { ++ .pll1 = &ov7251_pll1_config_19_2_mhz, ++ .pll2 = &ov7251_pll2_config_19_2_mhz ++}; ++ + static const struct ov7251_pll_configs ov7251_pll_configs_24_mhz = { + .pll1 = &ov7251_pll1_config_24_mhz, + .pll2 = &ov7251_pll2_config_24_mhz + }; + + static const struct ov7251_pll_configs *ov7251_pll_configs[] = { ++ [OV7251_19_2_MHZ] = &ov7251_pll_configs_19_2_mhz, + [OV7251_24_MHZ] = &ov7251_pll_configs_24_mhz + }; + +@@ -553,6 +576,7 @@ static const struct reg_value ov7251_set + }; + + static const unsigned long supported_xclk_rates[] = { ++ [OV7251_19_2_MHZ] = 19200000, + [OV7251_24_MHZ] = 24000000, + }; + +@@ -1424,6 +1448,7 @@ static int ov7251_probe(struct i2c_clien + struct device *dev = &client->dev; + struct ov7251 *ov7251; + u8 chip_id_high, chip_id_low, chip_rev; ++ unsigned int rate = 0; + int ret; + int i; + +@@ -1439,35 +1464,39 @@ static int ov7251_probe(struct i2c_clien + return ret; + + /* get system clock (xclk) */ +- ov7251->xclk = devm_clk_get(dev, "xclk"); ++ ov7251->xclk = devm_clk_get(dev, NULL); + if (IS_ERR(ov7251->xclk)) { + dev_err(dev, "could not get xclk"); + return PTR_ERR(ov7251->xclk); + } + ++ /* ++ * We could have either a 24MHz or 19.2MHz clock rate from either dt or ++ * ACPI. We also need to support the IPU3 case which will have both an ++ * external clock AND a clock-frequency property. ++ */ + ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", +- &ov7251->xclk_freq); +- if (ret) { +- dev_err(dev, "could not get xclk frequency\n"); +- return ret; ++ &rate); ++ if (!ret && ov7251->xclk) { ++ ret = clk_set_rate(ov7251->xclk, rate); ++ if (ret) ++ return dev_err_probe(dev, ret, ++ "failed to set clock rate\n"); ++ } else if (ret && !ov7251->xclk) { ++ return dev_err_probe(dev, ret, "invalid clock config\n"); + } + +- /* external clock must be 24MHz, allow 1% tolerance */ +- if (ov7251->xclk_freq < 23760000 || ov7251->xclk_freq > 24240000) { +- dev_err(dev, "external clock frequency %u is not supported\n", +- ov7251->xclk_freq); +- return -EINVAL; +- } ++ ov7251->xclk_freq = rate ? rate : clk_get_rate(ov7251->xclk); + +- ret = clk_set_rate(ov7251->xclk, ov7251->xclk_freq); +- if (ret) { +- dev_err(dev, "could not set xclk frequency\n"); +- return ret; +- } + for (i = 0; i < ARRAY_SIZE(supported_xclk_rates); i++) + if (ov7251->xclk_freq == supported_xclk_rates[i]) + break; + ++ if (i == ARRAY_SIZE(supported_xclk_rates)) ++ return dev_err_probe(dev, -EINVAL, ++ "clock rate %u Hz is unsupported\n", ++ ov7251->xclk_freq); ++ + ov7251->pll_configs = ov7251_pll_configs[i]; + + ov7251->io_regulator = devm_regulator_get(dev, "vdddo"); |