aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.15/950-0722-media-i2c-Add-support-for-19.2MHz-clock-to-ov7251.patch
diff options
context:
space:
mode:
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.patch144
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");