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-0721-media-i2c-Add-ov7251_pll_configure.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-0721-media-i2c-Add-ov7251_pll_configure.patch')
-rw-r--r-- | target/linux/bcm27xx/patches-5.15/950-0721-media-i2c-Add-ov7251_pll_configure.patch | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.15/950-0721-media-i2c-Add-ov7251_pll_configure.patch b/target/linux/bcm27xx/patches-5.15/950-0721-media-i2c-Add-ov7251_pll_configure.patch new file mode 100644 index 0000000000..0408984273 --- /dev/null +++ b/target/linux/bcm27xx/patches-5.15/950-0721-media-i2c-Add-ov7251_pll_configure.patch @@ -0,0 +1,266 @@ +From c16cebe5ebfb309074ff7cc9ddeaf37724d31512 Mon Sep 17 00:00:00 2001 +From: Daniel Scally <djrscally@gmail.com> +Date: Tue, 15 Feb 2022 23:07:32 +0000 +Subject: [PATCH] media: i2c: Add ov7251_pll_configure() + +Rather than having the pll settings hidden inside mode blobs, define +them in structs and use a dedicated function to set them. This makes +it simpler to extend the driver to support other external clock +frequencies. + +Signed-off-by: Daniel Scally <djrscally@gmail.com> +--- + drivers/media/i2c/ov7251.c | 165 ++++++++++++++++++++++++++++++------- + 1 file changed, 135 insertions(+), 30 deletions(-) + +--- a/drivers/media/i2c/ov7251.c ++++ b/drivers/media/i2c/ov7251.c +@@ -42,6 +42,16 @@ + #define OV7251_TIMING_FORMAT2_MIRROR BIT(2) + #define OV7251_PRE_ISP_00 0x5e00 + #define OV7251_PRE_ISP_00_TEST_PATTERN BIT(7) ++#define OV7251_PLL1_PRE_DIV_REG 0x30b4 ++#define OV7251_PLL1_MULT_REG 0x30b3 ++#define OV7251_PLL1_DIVIDER_REG 0x30b1 ++#define OV7251_PLL1_PIX_DIV_REG 0x30b0 ++#define OV7251_PLL1_MIPI_DIV_REG 0x30b5 ++#define OV7251_PLL2_PRE_DIV_REG 0x3098 ++#define OV7251_PLL2_MULT_REG 0x3099 ++#define OV7251_PLL2_DIVIDER_REG 0x309d ++#define OV7251_PLL2_SYS_DIV_REG 0x309a ++#define OV7251_PLL2_ADC_DIV_REG 0x309b + + struct reg_value { + u16 reg; +@@ -60,6 +70,27 @@ struct ov7251_mode_info { + struct v4l2_fract timeperframe; + }; + ++struct ov7251_pll1_config { ++ unsigned int pre_div; ++ unsigned int mult; ++ unsigned int div; ++ unsigned int pix_div; ++ unsigned int mipi_div; ++}; ++ ++struct ov7251_pll2_config { ++ unsigned int pre_div; ++ unsigned int mult; ++ unsigned int div; ++ unsigned int sys_div; ++ unsigned int adc_div; ++}; ++ ++struct ov7251_pll_configs { ++ const struct ov7251_pll1_config *pll1; ++ const struct ov7251_pll2_config *pll2; ++}; ++ + struct ov7251 { + struct i2c_client *i2c_client; + struct device *dev; +@@ -71,6 +102,8 @@ struct ov7251 { + struct clk *xclk; + u32 xclk_freq; + ++ const struct ov7251_pll_configs *pll_configs; ++ + struct regulator *io_regulator; + struct regulator *core_regulator; + struct regulator *analog_regulator; +@@ -100,6 +133,36 @@ static inline struct ov7251 *to_ov7251(s + return container_of(sd, struct ov7251, sd); + } + ++enum xclk_rate { ++ OV7251_24_MHZ, ++ OV7251_NUM_SUPPORTED_RATES ++}; ++ ++static const struct ov7251_pll1_config ov7251_pll1_config_24_mhz = { ++ .pre_div = 0x03, ++ .mult = 0x64, ++ .div = 0x01, ++ .pix_div = 0x0a, ++ .mipi_div = 0x05 ++}; ++ ++static const struct ov7251_pll2_config ov7251_pll2_config_24_mhz = { ++ .pre_div = 0x04, ++ .mult = 0x28, ++ .div = 0x00, ++ .sys_div = 0x05, ++ .adc_div = 0x04 ++}; ++ ++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_24_MHZ] = &ov7251_pll_configs_24_mhz ++}; ++ + static const struct reg_value ov7251_global_init_setting[] = { + { 0x0103, 0x01 }, + { 0x303b, 0x02 }, +@@ -118,16 +181,6 @@ static const struct reg_value ov7251_set + { 0x301c, 0xf0 }, + { 0x3023, 0x05 }, + { 0x3037, 0xf0 }, +- { 0x3098, 0x04 }, /* pll2 pre divider */ +- { 0x3099, 0x28 }, /* pll2 multiplier */ +- { 0x309a, 0x05 }, /* pll2 sys divider */ +- { 0x309b, 0x04 }, /* pll2 adc divider */ +- { 0x309d, 0x00 }, /* pll2 divider */ +- { 0x30b0, 0x0a }, /* pll1 pix divider */ +- { 0x30b1, 0x01 }, /* pll1 divider */ +- { 0x30b3, 0x64 }, /* pll1 multiplier */ +- { 0x30b4, 0x03 }, /* pll1 pre divider */ +- { 0x30b5, 0x05 }, /* pll1 mipi divider */ + { 0x3106, 0xda }, + { 0x3503, 0x07 }, + { 0x3509, 0x10 }, +@@ -256,16 +309,6 @@ static const struct reg_value ov7251_set + { 0x301c, 0x00 }, + { 0x3023, 0x05 }, + { 0x3037, 0xf0 }, +- { 0x3098, 0x04 }, /* pll2 pre divider */ +- { 0x3099, 0x28 }, /* pll2 multiplier */ +- { 0x309a, 0x05 }, /* pll2 sys divider */ +- { 0x309b, 0x04 }, /* pll2 adc divider */ +- { 0x309d, 0x00 }, /* pll2 divider */ +- { 0x30b0, 0x0a }, /* pll1 pix divider */ +- { 0x30b1, 0x01 }, /* pll1 divider */ +- { 0x30b3, 0x64 }, /* pll1 multiplier */ +- { 0x30b4, 0x03 }, /* pll1 pre divider */ +- { 0x30b5, 0x05 }, /* pll1 mipi divider */ + { 0x3106, 0xda }, + { 0x3503, 0x07 }, + { 0x3509, 0x10 }, +@@ -394,16 +437,6 @@ static const struct reg_value ov7251_set + { 0x301c, 0x00 }, + { 0x3023, 0x05 }, + { 0x3037, 0xf0 }, +- { 0x3098, 0x04 }, /* pll2 pre divider */ +- { 0x3099, 0x28 }, /* pll2 multiplier */ +- { 0x309a, 0x05 }, /* pll2 sys divider */ +- { 0x309b, 0x04 }, /* pll2 adc divider */ +- { 0x309d, 0x00 }, /* pll2 divider */ +- { 0x30b0, 0x0a }, /* pll1 pix divider */ +- { 0x30b1, 0x01 }, /* pll1 divider */ +- { 0x30b3, 0x64 }, /* pll1 multiplier */ +- { 0x30b4, 0x03 }, /* pll1 pre divider */ +- { 0x30b5, 0x05 }, /* pll1 mipi divider */ + { 0x3106, 0xda }, + { 0x3503, 0x07 }, + { 0x3509, 0x10 }, +@@ -519,6 +552,10 @@ static const struct reg_value ov7251_set + { 0x5001, 0x80 }, + }; + ++static const unsigned long supported_xclk_rates[] = { ++ [OV7251_24_MHZ] = 24000000, ++}; ++ + static const s64 link_freq[] = { + 240000000, + }; +@@ -692,6 +729,63 @@ static int ov7251_read_reg(struct ov7251 + return 0; + } + ++static int ov7251_pll_configure(struct ov7251 *ov7251) ++{ ++ const struct ov7251_pll_configs *configs; ++ int ret; ++ ++ configs = ov7251->pll_configs; ++ ++ ret = ov7251_write_reg(ov7251, OV7251_PLL1_PRE_DIV_REG, ++ configs->pll1->pre_div); ++ if (ret < 0) ++ return ret; ++ ++ ret = ov7251_write_reg(ov7251, OV7251_PLL1_MULT_REG, ++ configs->pll1->mult); ++ if (ret < 0) ++ return ret; ++ ret = ov7251_write_reg(ov7251, OV7251_PLL1_DIVIDER_REG, ++ configs->pll1->div); ++ if (ret < 0) ++ return ret; ++ ++ ret = ov7251_write_reg(ov7251, OV7251_PLL1_PIX_DIV_REG, ++ configs->pll1->pix_div); ++ if (ret < 0) ++ return ret; ++ ++ ret = ov7251_write_reg(ov7251, OV7251_PLL1_MIPI_DIV_REG, ++ configs->pll1->mipi_div); ++ if (ret < 0) ++ return ret; ++ ++ ret = ov7251_write_reg(ov7251, OV7251_PLL2_PRE_DIV_REG, ++ configs->pll2->pre_div); ++ if (ret < 0) ++ return ret; ++ ++ ret = ov7251_write_reg(ov7251, OV7251_PLL2_MULT_REG, ++ configs->pll2->mult); ++ if (ret < 0) ++ return ret; ++ ++ ret = ov7251_write_reg(ov7251, OV7251_PLL2_DIVIDER_REG, ++ configs->pll2->div); ++ if (ret < 0) ++ return ret; ++ ++ ret = ov7251_write_reg(ov7251, OV7251_PLL2_SYS_DIV_REG, ++ configs->pll2->sys_div); ++ if (ret < 0) ++ return ret; ++ ++ ret = ov7251_write_reg(ov7251, OV7251_PLL2_ADC_DIV_REG, ++ configs->pll2->adc_div); ++ ++ return ret; ++} ++ + static int ov7251_set_exposure(struct ov7251 *ov7251, s32 exposure) + { + u16 reg; +@@ -1143,6 +1237,11 @@ static int ov7251_s_stream(struct v4l2_s + mutex_lock(&ov7251->lock); + + if (enable) { ++ ret = ov7251_pll_configure(ov7251); ++ if (ret) ++ return dev_err_probe(ov7251->dev, ret, ++ "error configuring PLLs\n"); ++ + ret = ov7251_set_register_array(ov7251, + ov7251->current_mode->data, + ov7251->current_mode->data_size); +@@ -1326,6 +1425,7 @@ static int ov7251_probe(struct i2c_clien + struct ov7251 *ov7251; + u8 chip_id_high, chip_id_low, chip_rev; + int ret; ++ int i; + + ov7251 = devm_kzalloc(dev, sizeof(struct ov7251), GFP_KERNEL); + if (!ov7251) +@@ -1364,6 +1464,11 @@ static int ov7251_probe(struct i2c_clien + 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; ++ ++ ov7251->pll_configs = ov7251_pll_configs[i]; + + ov7251->io_regulator = devm_regulator_get(dev, "vdddo"); + if (IS_ERR(ov7251->io_regulator)) { |