linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH resend 0/4] media: hi556: Add reset / clk / regulator support
@ 2024-04-15  9:41 Hans de Goede
  2024-04-15  9:41 ` [PATCH resend 1/4] media: hi556: Return -EPROBE_DEFER if no endpoint is found Hans de Goede
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Hans de Goede @ 2024-04-15  9:41 UTC (permalink / raw)
  To: Sakari Ailus, Rui Miguel Silva
  Cc: Hans de Goede, Mauro Carvalho Chehab, Kate Hsuan, Kieran Bingham,
	linux-media

Hi All,

Because there have been 0 reactions to my original patch submission, here
is a resend of my patch-series to make the hi556 driver work on x86_64
devices where the power-up / down sequence is not fully handledin ACPI
(as is done on chromebooks) but where instead the driver is expected
to do it itself.

This has been successfully tested on a "HP Spectre x360 13.5 (2023)":
https://github.com/intel/ipu6-drivers/issues/202

Regards,

Hans


Hans de Goede (4):
  media: hi556: Return -EPROBE_DEFER if no endpoint is found
  media: hi556: Add support for reset GPIO
  media: hi556: Add support for external clock
  media: hi556: Add support for avdd regulator

 drivers/media/i2c/hi556.c | 95 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 88 insertions(+), 7 deletions(-)

-- 
2.44.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH resend 1/4] media: hi556: Return -EPROBE_DEFER if no endpoint is found
  2024-04-15  9:41 [PATCH resend 0/4] media: hi556: Add reset / clk / regulator support Hans de Goede
@ 2024-04-15  9:41 ` Hans de Goede
  2024-04-15 11:25   ` Sakari Ailus
  2024-04-15  9:41 ` [PATCH resend 2/4] media: hi556: Add support for reset GPIO Hans de Goede
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 6+ messages in thread
From: Hans de Goede @ 2024-04-15  9:41 UTC (permalink / raw)
  To: Sakari Ailus, Rui Miguel Silva
  Cc: Hans de Goede, Mauro Carvalho Chehab, Kate Hsuan, Kieran Bingham,
	linux-media

With ipu bridge, endpoints may only be created when ipu bridge has
initialised. This may happen after the sensor driver has first probed.

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

diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c
index 38c77d515786..96bae9914d52 100644
--- a/drivers/media/i2c/hi556.c
+++ b/drivers/media/i2c/hi556.c
@@ -1206,8 +1206,13 @@ static int hi556_check_hwcfg(struct device *dev)
 	int ret = 0;
 	unsigned int i, j;
 
-	if (!fwnode)
-		return -ENXIO;
+	/*
+	 * Sometimes the fwnode graph is initialized by the bridge driver,
+	 * wait for this.
+	 */
+	ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
+	if (!ep)
+		return -EPROBE_DEFER;
 
 	ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk);
 	if (ret) {
@@ -1220,10 +1225,6 @@ static int hi556_check_hwcfg(struct device *dev)
 		return -EINVAL;
 	}
 
-	ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
-	if (!ep)
-		return -ENXIO;
-
 	ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
 	fwnode_handle_put(ep);
 	if (ret)
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH resend 2/4] media: hi556: Add support for reset GPIO
  2024-04-15  9:41 [PATCH resend 0/4] media: hi556: Add reset / clk / regulator support Hans de Goede
  2024-04-15  9:41 ` [PATCH resend 1/4] media: hi556: Return -EPROBE_DEFER if no endpoint is found Hans de Goede
@ 2024-04-15  9:41 ` Hans de Goede
  2024-04-15  9:41 ` [PATCH resend 3/4] media: hi556: Add support for external clock Hans de Goede
  2024-04-15  9:41 ` [PATCH resend 4/4] media: hi556: Add support for avdd regulator Hans de Goede
  3 siblings, 0 replies; 6+ messages in thread
From: Hans de Goede @ 2024-04-15  9:41 UTC (permalink / raw)
  To: Sakari Ailus, Rui Miguel Silva
  Cc: Hans de Goede, Mauro Carvalho Chehab, Kate Hsuan, Kieran Bingham,
	linux-media

On some ACPI platforms, such as Chromebooks the ACPI methods to
change the power-state (_PS0 and _PS3) fully take care of powering
on/off the sensor.

On other ACPI platforms, such as e.g. various HP models with IPU6 +
hi556 sensor, the sensor driver must control the reset GPIO itself.

Add support for having the driver control an optional reset GPIO.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/media/i2c/hi556.c | 45 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c
index 96bae9914d52..f5a39b83598b 100644
--- a/drivers/media/i2c/hi556.c
+++ b/drivers/media/i2c/hi556.c
@@ -4,6 +4,7 @@
 #include <asm/unaligned.h>
 #include <linux/acpi.h>
 #include <linux/delay.h>
+#include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
@@ -633,6 +634,9 @@ struct hi556 {
 	struct v4l2_ctrl *hblank;
 	struct v4l2_ctrl *exposure;
 
+	/* GPIOs, clocks, etc. */
+	struct gpio_desc *reset_gpio;
+
 	/* Current mode */
 	const struct hi556_mode *cur_mode;
 
@@ -1276,6 +1280,25 @@ static void hi556_remove(struct i2c_client *client)
 	mutex_destroy(&hi556->mutex);
 }
 
+static int hi556_suspend(struct device *dev)
+{
+	struct v4l2_subdev *sd = dev_get_drvdata(dev);
+	struct hi556 *hi556 = to_hi556(sd);
+
+	gpiod_set_value_cansleep(hi556->reset_gpio, 1);
+	return 0;
+}
+
+static int hi556_resume(struct device *dev)
+{
+	struct v4l2_subdev *sd = dev_get_drvdata(dev);
+	struct hi556 *hi556 = to_hi556(sd);
+
+	gpiod_set_value_cansleep(hi556->reset_gpio, 0);
+	usleep_range(5000, 5500);
+	return 0;
+}
+
 static int hi556_probe(struct i2c_client *client)
 {
 	struct hi556 *hi556;
@@ -1295,12 +1318,24 @@ static int hi556_probe(struct i2c_client *client)
 
 	v4l2_i2c_subdev_init(&hi556->sd, client, &hi556_subdev_ops);
 
+	hi556->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
+						    GPIOD_OUT_HIGH);
+	if (IS_ERR(hi556->reset_gpio))
+		return dev_err_probe(&client->dev, PTR_ERR(hi556->reset_gpio),
+				     "failed to get reset GPIO\n");
+
 	full_power = acpi_dev_state_d0(&client->dev);
 	if (full_power) {
+		/* Ensure non ACPI managed resources are enabled */
+		ret = hi556_resume(&client->dev);
+		if (ret)
+			return dev_err_probe(&client->dev, ret,
+					     "failed to power on sensor\n");
+
 		ret = hi556_identify_module(hi556);
 		if (ret) {
 			dev_err(&client->dev, "failed to find sensor: %d", ret);
-			return ret;
+			goto probe_error_power_off;
 		}
 	}
 
@@ -1345,9 +1380,16 @@ static int hi556_probe(struct i2c_client *client)
 	v4l2_ctrl_handler_free(hi556->sd.ctrl_handler);
 	mutex_destroy(&hi556->mutex);
 
+probe_error_power_off:
+	if (full_power)
+		hi556_suspend(&client->dev);
+
 	return ret;
 }
 
+static DEFINE_RUNTIME_DEV_PM_OPS(hi556_pm_ops, hi556_suspend, hi556_resume,
+				 NULL);
+
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id hi556_acpi_ids[] = {
 	{"INT3537"},
@@ -1361,6 +1403,7 @@ static struct i2c_driver hi556_i2c_driver = {
 	.driver = {
 		.name = "hi556",
 		.acpi_match_table = ACPI_PTR(hi556_acpi_ids),
+		.pm = pm_sleep_ptr(&hi556_pm_ops),
 	},
 	.probe = hi556_probe,
 	.remove = hi556_remove,
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH resend 3/4] media: hi556: Add support for external clock
  2024-04-15  9:41 [PATCH resend 0/4] media: hi556: Add reset / clk / regulator support Hans de Goede
  2024-04-15  9:41 ` [PATCH resend 1/4] media: hi556: Return -EPROBE_DEFER if no endpoint is found Hans de Goede
  2024-04-15  9:41 ` [PATCH resend 2/4] media: hi556: Add support for reset GPIO Hans de Goede
@ 2024-04-15  9:41 ` Hans de Goede
  2024-04-15  9:41 ` [PATCH resend 4/4] media: hi556: Add support for avdd regulator Hans de Goede
  3 siblings, 0 replies; 6+ messages in thread
From: Hans de Goede @ 2024-04-15  9:41 UTC (permalink / raw)
  To: Sakari Ailus, Rui Miguel Silva
  Cc: Hans de Goede, Mauro Carvalho Chehab, Kate Hsuan, Kieran Bingham,
	linux-media

On some ACPI platforms, such as Chromebooks the ACPI methods to
change the power-state (_PS0 and _PS3) fully take care of powering
on/off the sensor.

On other ACPI platforms, such as e.g. various HP models with IPU6 +
hi556 sensor, the sensor driver must control the sensor's clock itself.

Add support for having the driver control an optional clock.

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

diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c
index f5a39b83598b..b783e0f56687 100644
--- a/drivers/media/i2c/hi556.c
+++ b/drivers/media/i2c/hi556.c
@@ -3,6 +3,7 @@
 
 #include <asm/unaligned.h>
 #include <linux/acpi.h>
+#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
@@ -636,6 +637,7 @@ struct hi556 {
 
 	/* GPIOs, clocks, etc. */
 	struct gpio_desc *reset_gpio;
+	struct clk *clk;
 
 	/* Current mode */
 	const struct hi556_mode *cur_mode;
@@ -1286,6 +1288,7 @@ static int hi556_suspend(struct device *dev)
 	struct hi556 *hi556 = to_hi556(sd);
 
 	gpiod_set_value_cansleep(hi556->reset_gpio, 1);
+	clk_disable_unprepare(hi556->clk);
 	return 0;
 }
 
@@ -1293,6 +1296,11 @@ static int hi556_resume(struct device *dev)
 {
 	struct v4l2_subdev *sd = dev_get_drvdata(dev);
 	struct hi556 *hi556 = to_hi556(sd);
+	int ret;
+
+	ret = clk_prepare_enable(hi556->clk);
+	if (ret)
+		return ret;
 
 	gpiod_set_value_cansleep(hi556->reset_gpio, 0);
 	usleep_range(5000, 5500);
@@ -1324,6 +1332,11 @@ static int hi556_probe(struct i2c_client *client)
 		return dev_err_probe(&client->dev, PTR_ERR(hi556->reset_gpio),
 				     "failed to get reset GPIO\n");
 
+	hi556->clk = devm_clk_get_optional(&client->dev, "clk");
+	if (IS_ERR(hi556->clk))
+		return dev_err_probe(&client->dev, PTR_ERR(hi556->clk),
+				     "failed to get clock\n");
+
 	full_power = acpi_dev_state_d0(&client->dev);
 	if (full_power) {
 		/* Ensure non ACPI managed resources are enabled */
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH resend 4/4] media: hi556: Add support for avdd regulator
  2024-04-15  9:41 [PATCH resend 0/4] media: hi556: Add reset / clk / regulator support Hans de Goede
                   ` (2 preceding siblings ...)
  2024-04-15  9:41 ` [PATCH resend 3/4] media: hi556: Add support for external clock Hans de Goede
@ 2024-04-15  9:41 ` Hans de Goede
  3 siblings, 0 replies; 6+ messages in thread
From: Hans de Goede @ 2024-04-15  9:41 UTC (permalink / raw)
  To: Sakari Ailus, Rui Miguel Silva
  Cc: Hans de Goede, Mauro Carvalho Chehab, Kate Hsuan, Kieran Bingham,
	linux-media

On some ACPI platforms, such as Chromebooks the ACPI methods to
change the power-state (_PS0 and _PS3) fully take care of powering
on/off the sensor.

On other ACPI platforms, such as e.g. various HP models with IPU6 +
hi556 sensor, the sensor driver must control the avdd regulator itself.

Add support for having the driver control the sensor's avdd regulator.
Note this relies on the regulator-core providing a dummy regulator
(which it does by default) on platforms where Linux is not aware of
the avdd regulator.

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

diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c
index b783e0f56687..5641c249d4b1 100644
--- a/drivers/media/i2c/hi556.c
+++ b/drivers/media/i2c/hi556.c
@@ -9,6 +9,7 @@
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-fwnode.h>
@@ -638,6 +639,7 @@ struct hi556 {
 	/* GPIOs, clocks, etc. */
 	struct gpio_desc *reset_gpio;
 	struct clk *clk;
+	struct regulator *avdd;
 
 	/* Current mode */
 	const struct hi556_mode *cur_mode;
@@ -1286,8 +1288,17 @@ static int hi556_suspend(struct device *dev)
 {
 	struct v4l2_subdev *sd = dev_get_drvdata(dev);
 	struct hi556 *hi556 = to_hi556(sd);
+	int ret;
 
 	gpiod_set_value_cansleep(hi556->reset_gpio, 1);
+
+	ret = regulator_disable(hi556->avdd);
+	if (ret) {
+		dev_err(dev, "failed to disable avdd: %d\n", ret);
+		gpiod_set_value_cansleep(hi556->reset_gpio, 0);
+		return ret;
+	}
+
 	clk_disable_unprepare(hi556->clk);
 	return 0;
 }
@@ -1302,6 +1313,13 @@ static int hi556_resume(struct device *dev)
 	if (ret)
 		return ret;
 
+	ret = regulator_enable(hi556->avdd);
+	if (ret) {
+		dev_err(dev, "failed to enable avdd: %d\n", ret);
+		clk_disable_unprepare(hi556->clk);
+		return ret;
+	}
+
 	gpiod_set_value_cansleep(hi556->reset_gpio, 0);
 	usleep_range(5000, 5500);
 	return 0;
@@ -1337,6 +1355,12 @@ static int hi556_probe(struct i2c_client *client)
 		return dev_err_probe(&client->dev, PTR_ERR(hi556->clk),
 				     "failed to get clock\n");
 
+	/* The regulator core will provide a "dummy" regulator if necessary */
+	hi556->avdd = devm_regulator_get(&client->dev, "avdd");
+	if (IS_ERR(hi556->avdd))
+		return dev_err_probe(&client->dev, PTR_ERR(hi556->avdd),
+				     "failed to get avdd regulator\n");
+
 	full_power = acpi_dev_state_d0(&client->dev);
 	if (full_power) {
 		/* Ensure non ACPI managed resources are enabled */
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH resend 1/4] media: hi556: Return -EPROBE_DEFER if no endpoint is found
  2024-04-15  9:41 ` [PATCH resend 1/4] media: hi556: Return -EPROBE_DEFER if no endpoint is found Hans de Goede
@ 2024-04-15 11:25   ` Sakari Ailus
  0 siblings, 0 replies; 6+ messages in thread
From: Sakari Ailus @ 2024-04-15 11:25 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Rui Miguel Silva, Mauro Carvalho Chehab, Kate Hsuan,
	Kieran Bingham, linux-media

Hi Hans,

On Mon, Apr 15, 2024 at 11:41:30AM +0200, Hans de Goede wrote:
> With ipu bridge, endpoints may only be created when ipu bridge has
> initialised. This may happen after the sensor driver has first probed.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  drivers/media/i2c/hi556.c | 13 +++++++------
>  1 file changed, 7 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c
> index 38c77d515786..96bae9914d52 100644
> --- a/drivers/media/i2c/hi556.c
> +++ b/drivers/media/i2c/hi556.c
> @@ -1206,8 +1206,13 @@ static int hi556_check_hwcfg(struct device *dev)
>  	int ret = 0;
>  	unsigned int i, j;
>  
> -	if (!fwnode)
> -		return -ENXIO;
> +	/*
> +	 * Sometimes the fwnode graph is initialized by the bridge driver,
> +	 * wait for this.
> +	 */
> +	ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
> +	if (!ep)
> +		return -EPROBE_DEFER;
>  
>  	ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk);
>  	if (ret) {

The endpoint needs to be put here. It might be more practical to parse the
endpoint right away so the error handling becomes easier.

> @@ -1220,10 +1225,6 @@ static int hi556_check_hwcfg(struct device *dev)
>  		return -EINVAL;
>  	}
>  
> -	ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
> -	if (!ep)
> -		return -ENXIO;
> -
>  	ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
>  	fwnode_handle_put(ep);
>  	if (ret)

-- 
Kind regards,

Sakari Ailus

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2024-04-15 11:25 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-15  9:41 [PATCH resend 0/4] media: hi556: Add reset / clk / regulator support Hans de Goede
2024-04-15  9:41 ` [PATCH resend 1/4] media: hi556: Return -EPROBE_DEFER if no endpoint is found Hans de Goede
2024-04-15 11:25   ` Sakari Ailus
2024-04-15  9:41 ` [PATCH resend 2/4] media: hi556: Add support for reset GPIO Hans de Goede
2024-04-15  9:41 ` [PATCH resend 3/4] media: hi556: Add support for external clock Hans de Goede
2024-04-15  9:41 ` [PATCH resend 4/4] media: hi556: Add support for avdd regulator Hans de Goede

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).