diff mbox series

[02/13] media: mt9m114: Add support for clock-frequency property

Message ID 20250504101336.18748-3-hdegoede@redhat.com
State New
Headers show
Series media: mt9m114: Changes to make it work with atomisp devices | expand

Commit Message

Hans de Goede May 4, 2025, 10:13 a.m. UTC
Add support for platforms that do not have a clock provider, but instead
specify the clock frequency by using the "clock-frequency" property.

E.g. ACPI platforms turn the clock on/off through ACPI power-resources
depending on the runtime-pm state, so there is no clock provider.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/media/i2c/mt9m114.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

Comments

Laurent Pinchart May 9, 2025, 6:51 p.m. UTC | #1
Hi Hans,

On Sun, May 04, 2025 at 12:13:23PM +0200, Hans de Goede wrote:
> Add support for platforms that do not have a clock provider, but instead
> specify the clock frequency by using the "clock-frequency" property.
> 
> E.g. ACPI platforms turn the clock on/off through ACPI power-resources
> depending on the runtime-pm state, so there is no clock provider.

https://lore.kernel.org/r/20250321130329.342236-1-mehdi.djait@linux.intel.com
is a solution to this problem that will scale better.

> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  drivers/media/i2c/mt9m114.c | 20 ++++++++++++++++----
>  1 file changed, 16 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/media/i2c/mt9m114.c b/drivers/media/i2c/mt9m114.c
> index 5f0b0ad8f885..be1d2ec64b89 100644
> --- a/drivers/media/i2c/mt9m114.c
> +++ b/drivers/media/i2c/mt9m114.c
> @@ -377,6 +377,7 @@ struct mt9m114 {
>  	struct gpio_desc *reset;
>  	struct regulator_bulk_data supplies[3];
>  	struct v4l2_fwnode_endpoint bus_cfg;
> +	u32 clk_freq;
>  
>  	struct {
>  		unsigned int m;
> @@ -2122,14 +2123,13 @@ static int mt9m114_power_on(struct mt9m114 *sensor)
>  
>  	/* Perform a hard reset if available, or a soft reset otherwise. */
>  	if (sensor->reset) {
> -		long freq = clk_get_rate(sensor->clk);
>  		unsigned int duration;
>  
>  		/*
>  		 * The minimum duration is 50 clock cycles, thus typically
>  		 * around 2µs. Double it to be safe.
>  		 */
> -		duration = DIV_ROUND_UP(2 * 50 * 1000000, freq);
> +		duration = DIV_ROUND_UP(2 * 50 * 1000000, sensor->clk_freq);
>  
>  		gpiod_set_value(sensor->reset, 1);
>  		fsleep(duration);
> @@ -2249,7 +2249,7 @@ static int mt9m114_clk_init(struct mt9m114 *sensor)
>  	 * for 16-bit per pixel, transmitted in DDR over a single lane. For
>  	 * parallel mode, the sensor ouputs one pixel in two PIXCLK cycles.
>  	 */
> -	sensor->pixrate = clk_get_rate(sensor->clk) * sensor->pll.m
> +	sensor->pixrate = sensor->clk_freq * sensor->pll.m
>  			/ ((sensor->pll.n + 1) * (sensor->pll.p + 1));
>  
>  	link_freq = sensor->bus_cfg.bus_type == V4L2_MBUS_CSI2_DPHY
> @@ -2360,13 +2360,25 @@ static int mt9m114_probe(struct i2c_client *client)
>  		return ret;
>  
>  	/* Acquire clocks, GPIOs and regulators. */
> -	sensor->clk = devm_clk_get(dev, NULL);
> +	sensor->clk = devm_clk_get_optional(dev, NULL);
>  	if (IS_ERR(sensor->clk)) {
>  		ret = PTR_ERR(sensor->clk);
>  		dev_err_probe(dev, ret, "Failed to get clock\n");
>  		goto error_ep_free;
>  	}
>  
> +	if (sensor->clk) {
> +		sensor->clk_freq = clk_get_rate(sensor->clk);
> +	} else {
> +		ret = fwnode_property_read_u32(dev_fwnode(dev),
> +					       "clock-frequency",
> +					       &sensor->clk_freq);
> +		if (ret) {
> +			dev_err_probe(dev, ret, "Failed to read clock-freq\n");
> +			goto error_ep_free;
> +		}
> +	}
> +
>  	sensor->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
>  	if (IS_ERR(sensor->reset)) {
>  		ret = PTR_ERR(sensor->reset);
Hans de Goede May 10, 2025, 2:01 p.m. UTC | #2
Hi,

On 9-May-25 8:51 PM, Laurent Pinchart wrote:
> Hi Hans,
> 
> On Sun, May 04, 2025 at 12:13:23PM +0200, Hans de Goede wrote:
>> Add support for platforms that do not have a clock provider, but instead
>> specify the clock frequency by using the "clock-frequency" property.
>>
>> E.g. ACPI platforms turn the clock on/off through ACPI power-resources
>> depending on the runtime-pm state, so there is no clock provider.
> 
> https://lore.kernel.org/r/20250321130329.342236-1-mehdi.djait@linux.intel.com
> is a solution to this problem that will scale better.

I agree. Depending on how the timing wrt upstreaming works out,
we may still need this patch before merging 13/13 (adding of
the actual ACPI hw-id table). I'll move this to be patch 12/13
for v2. So that we can at least merge 1-11 of v2 (assuming there
will be no more review comments on v2).

Laurent, if the patch you linked to is not ready yet would you
then be ok with temporarily taking this patch? I'm happy to commit
to moving this driver over to the new helper once the helper is
upstream.

Regards,

Hans



> 
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>> ---
>>  drivers/media/i2c/mt9m114.c | 20 ++++++++++++++++----
>>  1 file changed, 16 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/media/i2c/mt9m114.c b/drivers/media/i2c/mt9m114.c
>> index 5f0b0ad8f885..be1d2ec64b89 100644
>> --- a/drivers/media/i2c/mt9m114.c
>> +++ b/drivers/media/i2c/mt9m114.c
>> @@ -377,6 +377,7 @@ struct mt9m114 {
>>  	struct gpio_desc *reset;
>>  	struct regulator_bulk_data supplies[3];
>>  	struct v4l2_fwnode_endpoint bus_cfg;
>> +	u32 clk_freq;
>>  
>>  	struct {
>>  		unsigned int m;
>> @@ -2122,14 +2123,13 @@ static int mt9m114_power_on(struct mt9m114 *sensor)
>>  
>>  	/* Perform a hard reset if available, or a soft reset otherwise. */
>>  	if (sensor->reset) {
>> -		long freq = clk_get_rate(sensor->clk);
>>  		unsigned int duration;
>>  
>>  		/*
>>  		 * The minimum duration is 50 clock cycles, thus typically
>>  		 * around 2µs. Double it to be safe.
>>  		 */
>> -		duration = DIV_ROUND_UP(2 * 50 * 1000000, freq);
>> +		duration = DIV_ROUND_UP(2 * 50 * 1000000, sensor->clk_freq);
>>  
>>  		gpiod_set_value(sensor->reset, 1);
>>  		fsleep(duration);
>> @@ -2249,7 +2249,7 @@ static int mt9m114_clk_init(struct mt9m114 *sensor)
>>  	 * for 16-bit per pixel, transmitted in DDR over a single lane. For
>>  	 * parallel mode, the sensor ouputs one pixel in two PIXCLK cycles.
>>  	 */
>> -	sensor->pixrate = clk_get_rate(sensor->clk) * sensor->pll.m
>> +	sensor->pixrate = sensor->clk_freq * sensor->pll.m
>>  			/ ((sensor->pll.n + 1) * (sensor->pll.p + 1));
>>  
>>  	link_freq = sensor->bus_cfg.bus_type == V4L2_MBUS_CSI2_DPHY
>> @@ -2360,13 +2360,25 @@ static int mt9m114_probe(struct i2c_client *client)
>>  		return ret;
>>  
>>  	/* Acquire clocks, GPIOs and regulators. */
>> -	sensor->clk = devm_clk_get(dev, NULL);
>> +	sensor->clk = devm_clk_get_optional(dev, NULL);
>>  	if (IS_ERR(sensor->clk)) {
>>  		ret = PTR_ERR(sensor->clk);
>>  		dev_err_probe(dev, ret, "Failed to get clock\n");
>>  		goto error_ep_free;
>>  	}
>>  
>> +	if (sensor->clk) {
>> +		sensor->clk_freq = clk_get_rate(sensor->clk);
>> +	} else {
>> +		ret = fwnode_property_read_u32(dev_fwnode(dev),
>> +					       "clock-frequency",
>> +					       &sensor->clk_freq);
>> +		if (ret) {
>> +			dev_err_probe(dev, ret, "Failed to read clock-freq\n");
>> +			goto error_ep_free;
>> +		}
>> +	}
>> +
>>  	sensor->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
>>  	if (IS_ERR(sensor->reset)) {
>>  		ret = PTR_ERR(sensor->reset);
>
diff mbox series

Patch

diff --git a/drivers/media/i2c/mt9m114.c b/drivers/media/i2c/mt9m114.c
index 5f0b0ad8f885..be1d2ec64b89 100644
--- a/drivers/media/i2c/mt9m114.c
+++ b/drivers/media/i2c/mt9m114.c
@@ -377,6 +377,7 @@  struct mt9m114 {
 	struct gpio_desc *reset;
 	struct regulator_bulk_data supplies[3];
 	struct v4l2_fwnode_endpoint bus_cfg;
+	u32 clk_freq;
 
 	struct {
 		unsigned int m;
@@ -2122,14 +2123,13 @@  static int mt9m114_power_on(struct mt9m114 *sensor)
 
 	/* Perform a hard reset if available, or a soft reset otherwise. */
 	if (sensor->reset) {
-		long freq = clk_get_rate(sensor->clk);
 		unsigned int duration;
 
 		/*
 		 * The minimum duration is 50 clock cycles, thus typically
 		 * around 2µs. Double it to be safe.
 		 */
-		duration = DIV_ROUND_UP(2 * 50 * 1000000, freq);
+		duration = DIV_ROUND_UP(2 * 50 * 1000000, sensor->clk_freq);
 
 		gpiod_set_value(sensor->reset, 1);
 		fsleep(duration);
@@ -2249,7 +2249,7 @@  static int mt9m114_clk_init(struct mt9m114 *sensor)
 	 * for 16-bit per pixel, transmitted in DDR over a single lane. For
 	 * parallel mode, the sensor ouputs one pixel in two PIXCLK cycles.
 	 */
-	sensor->pixrate = clk_get_rate(sensor->clk) * sensor->pll.m
+	sensor->pixrate = sensor->clk_freq * sensor->pll.m
 			/ ((sensor->pll.n + 1) * (sensor->pll.p + 1));
 
 	link_freq = sensor->bus_cfg.bus_type == V4L2_MBUS_CSI2_DPHY
@@ -2360,13 +2360,25 @@  static int mt9m114_probe(struct i2c_client *client)
 		return ret;
 
 	/* Acquire clocks, GPIOs and regulators. */
-	sensor->clk = devm_clk_get(dev, NULL);
+	sensor->clk = devm_clk_get_optional(dev, NULL);
 	if (IS_ERR(sensor->clk)) {
 		ret = PTR_ERR(sensor->clk);
 		dev_err_probe(dev, ret, "Failed to get clock\n");
 		goto error_ep_free;
 	}
 
+	if (sensor->clk) {
+		sensor->clk_freq = clk_get_rate(sensor->clk);
+	} else {
+		ret = fwnode_property_read_u32(dev_fwnode(dev),
+					       "clock-frequency",
+					       &sensor->clk_freq);
+		if (ret) {
+			dev_err_probe(dev, ret, "Failed to read clock-freq\n");
+			goto error_ep_free;
+		}
+	}
+
 	sensor->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
 	if (IS_ERR(sensor->reset)) {
 		ret = PTR_ERR(sensor->reset);