diff mbox series

[15/28] media: ov2680: Add support for 19.2 MHz clock

Message ID 20230607164712.63579-16-hdegoede@redhat.com (mailing list archive)
State New, archived
Headers show
Series media: ov2680: Bugfixes + ACPI + selection(crop-tgt) API support | expand

Commit Message

Hans de Goede June 7, 2023, 4:46 p.m. UTC
Most x86/ACPI boards use the ov2680 with a 19.2 MHz xvclk,
rather then the expected 24MHz, add support for this.

Compensate for the lower clk by setting a higher PLL multiplier
of 69 when using 19.2 MHz vs the default multiplier of 55 for
a 24MHz xvclk.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/media/i2c/ov2680.c | 35 +++++++++++++++++++++++++++++------
 1 file changed, 29 insertions(+), 6 deletions(-)

Comments

Andy Shevchenko June 7, 2023, 8:53 p.m. UTC | #1
On Wed, Jun 07, 2023 at 06:46:59PM +0200, Hans de Goede wrote:
> Most x86/ACPI boards use the ov2680 with a 19.2 MHz xvclk,
> rather then the expected 24MHz, add support for this.
> 
> Compensate for the lower clk by setting a higher PLL multiplier
> of 69 when using 19.2 MHz vs the default multiplier of 55 for
> a 24MHz xvclk.

...

> @@ -720,12 +736,19 @@ static int ov2680_parse_dt(struct ov2680_dev *sensor)

I believe this call is solely the part of the ->probe() flow, hence...

...

> +	if (i == ARRAY_SIZE(ov2680_xvclk_freqs)) {
> +		dev_err(dev, "unsupported xvclk frequency %d Hz\n", sensor->xvclk_freq);
>  		return -EINVAL;

	return dev_err_probe(...);

?

>  	}
diff mbox series

Patch

diff --git a/drivers/media/i2c/ov2680.c b/drivers/media/i2c/ov2680.c
index 81d59206f901..b3a792b28467 100644
--- a/drivers/media/i2c/ov2680.c
+++ b/drivers/media/i2c/ov2680.c
@@ -26,14 +26,13 @@ 
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-subdev.h>
 
-#define OV2680_XVCLK_VALUE			24000000
-
 #define OV2680_CHIP_ID				0x2680
 
 #define OV2680_REG_STREAM_CTRL			CCI_REG8(0x0100)
 #define OV2680_REG_SOFT_RESET			CCI_REG8(0x0103)
 
 #define OV2680_REG_CHIP_ID			CCI_REG16(0x300a)
+#define OV2680_REG_PLL_MULTIPLIER		CCI_REG16(0x3081)
 
 #define OV2680_REG_EXPOSURE_PK			CCI_REG24(0x3500)
 #define OV2680_REG_R_MANUAL			CCI_REG8(0x3503)
@@ -68,6 +67,21 @@  static const char * const ov2680_supply_name[] = {
 
 #define OV2680_NUM_SUPPLIES ARRAY_SIZE(ov2680_supply_name)
 
+enum {
+	OV2680_19_2_MHZ,
+	OV2680_24_MHZ,
+};
+
+static const unsigned long ov2680_xvclk_freqs[] = {
+	[OV2680_19_2_MHZ] = 19200000,
+	[OV2680_24_MHZ] = 24000000,
+};
+
+static const u8 ov2680_pll_multipliers[] = {
+	[OV2680_19_2_MHZ] = 69,
+	[OV2680_24_MHZ] = 55,
+};
+
 struct ov2680_mode_info {
 	const char *name;
 	enum ov2680_mode_id id;
@@ -94,6 +108,7 @@  struct ov2680_dev {
 	struct media_pad		pad;
 	struct clk			*xvclk;
 	u32				xvclk_freq;
+	u8				pll_mult;
 	struct regulator_bulk_data	supplies[OV2680_NUM_SUPPLIES];
 
 	struct gpio_desc		*pwdn_gpio;
@@ -278,6 +293,7 @@  static int ov2680_stream_enable(struct ov2680_dev *sensor)
 {
 	int ret = 0;
 
+	cci_write(sensor->regmap, OV2680_REG_PLL_MULTIPLIER, sensor->pll_mult, &ret);
 	cci_multi_reg_write(sensor->regmap, ov2680_mode_init_data.reg_data,
 			    ov2680_mode_init_data.reg_data_size, &ret);
 	cci_multi_reg_write(sensor->regmap, sensor->current_mode->reg_data,
@@ -677,7 +693,7 @@  static int ov2680_parse_dt(struct ov2680_dev *sensor)
 {
 	struct device *dev = sensor->dev;
 	unsigned int rate = 0;
-	int ret;
+	int i, ret;
 
 	/*
 	 * The pin we want is named XSHUTDN in the datasheet. Linux sensor
@@ -720,12 +736,19 @@  static int ov2680_parse_dt(struct ov2680_dev *sensor)
 	}
 
 	sensor->xvclk_freq = rate ? rate : clk_get_rate(sensor->xvclk);
-	if (sensor->xvclk_freq != OV2680_XVCLK_VALUE) {
-		dev_err(dev, "wrong xvclk frequency %d HZ, expected: %d Hz\n",
-			sensor->xvclk_freq, OV2680_XVCLK_VALUE);
+
+	for (i = 0; i < ARRAY_SIZE(ov2680_xvclk_freqs); i++) {
+		if (sensor->xvclk_freq == ov2680_xvclk_freqs[i])
+			break;
+	}
+
+	if (i == ARRAY_SIZE(ov2680_xvclk_freqs)) {
+		dev_err(dev, "unsupported xvclk frequency %d Hz\n", sensor->xvclk_freq);
 		return -EINVAL;
 	}
 
+	sensor->pll_mult = ov2680_pll_multipliers[i];
+
 	return 0;
 }