diff mbox series

[2/3] media: i2c: adv7180: Allow the control of the reset pin

Message ID 20210530204410.676831-2-festevam@gmail.com
State New
Headers show
Series None | expand

Commit Message

Fabio Estevam May 30, 2021, 8:44 p.m. UTC
On a design where the ADV7180 pin is pulled down, it is not possible
to make it functional unless the GPIO connected to this pin goes
high.

Add support for the reset GPIO by introducing an optional property
called 'reset-gpios'.

Note: the reset operation is still performed via software as recommended
by the Analog Devices, but the reset GPIO still needs to go high to make
the chip operational.

Signed-off-by: Fabio Estevam <festevam@gmail.com>
---
 drivers/media/i2c/adv7180.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

Comments

Frieder Schrempf May 31, 2021, 7:02 a.m. UTC | #1
On 30.05.21 22:44, Fabio Estevam wrote:
> On a design where the ADV7180 pin is pulled down, it is not possible
> to make it functional unless the GPIO connected to this pin goes
> high.
> 
> Add support for the reset GPIO by introducing an optional property
> called 'reset-gpios'.
> 
> Note: the reset operation is still performed via software as recommended
> by the Analog Devices, but the reset GPIO still needs to go high to make
> the chip operational.
> 
> Signed-off-by: Fabio Estevam <festevam@gmail.com>
> ---
>  drivers/media/i2c/adv7180.c | 14 +++++++++++++-
>  1 file changed, 13 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
> index 44bb6fe85644..2811f2c337fa 100644
> --- a/drivers/media/i2c/adv7180.c
> +++ b/drivers/media/i2c/adv7180.c
> @@ -205,6 +205,7 @@ struct adv7180_state {
>  	struct mutex		mutex; /* mutual excl. when accessing chip */
>  	int			irq;
>  	struct gpio_desc	*pwdn_gpio;
> +	struct gpio_desc	*reset_gpio;
>  	v4l2_std_id		curr_norm;
>  	bool			powered;
>  	bool			streaming;
> @@ -473,13 +474,15 @@ static int adv7180_g_frame_interval(struct v4l2_subdev *sd,
>  
>  static void adv7180_set_power_pin(struct adv7180_state *state, bool on)
>  {
> -	if (!state->pwdn_gpio)
> +	if (!state->pwdn_gpio && !state->reset_gpio)
>  		return;
>  
>  	if (on) {
> +		gpiod_set_value_cansleep(state->reset_gpio, 0);
>  		gpiod_set_value_cansleep(state->pwdn_gpio, 0);

The datasheet specifies a delay of 5 ms between deasserting the PWRDWN and the RESET GPIO. Also this function is named adv7180_set_power_pin() which doesn't fit anymore if we also handle the RESET GPIO here.

As I was recently working with the ADV7280-M, I came up with a similar patch: https://git.kontron-electronics.de/linux/linux/-/commit/3619ed166140a0499ada7b14e5f1846a0ed7d18d.

What do you think?

>  		usleep_range(5000, 10000);
>  	} else {
> +		gpiod_set_value_cansleep(state->reset_gpio, 1);
>  		gpiod_set_value_cansleep(state->pwdn_gpio, 1);
>  	}
>  }
> @@ -1338,6 +1341,15 @@ static int adv7180_probe(struct i2c_client *client,
>  		return ret;
>  	}
>  
> +	state->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
> +						     GPIOD_OUT_HIGH);
> +	if (IS_ERR(state->reset_gpio)) {
> +		ret = PTR_ERR(state->reset_gpio);
> +		v4l_err(client, "request for reset pin failed: %d\n", ret);
> +		return ret;
> +	}
> +
> +
>  	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
>  		state->csi_client = i2c_new_dummy_device(client->adapter,
>  				ADV7180_DEFAULT_CSI_I2C_ADDR);
>
Fabio Estevam May 31, 2021, 10:48 a.m. UTC | #2
Hi Frieder,

On Mon, May 31, 2021 at 4:02 AM Frieder Schrempf
<frieder.schrempf@kontron.de> wrote:

> The datasheet specifies a delay of 5 ms between deasserting the PWRDWN and the RESET GPIO. Also this function is named adv7180_set_power_pin() which doesn't fit anymore if we also handle the RESET GPIO here.

>

> As I was recently working with the ADV7280-M, I came up with a similar patch: https://git.kontron-electronics.de/linux/linux/-/commit/3619ed166140a0499ada7b14e5f1846a0ed7d18d.

>

> What do you think?


Thanks for the review. I will send a v2 using your patch instead of mine.

Thanks,

Fabio Estevam
diff mbox series

Patch

diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
index 44bb6fe85644..2811f2c337fa 100644
--- a/drivers/media/i2c/adv7180.c
+++ b/drivers/media/i2c/adv7180.c
@@ -205,6 +205,7 @@  struct adv7180_state {
 	struct mutex		mutex; /* mutual excl. when accessing chip */
 	int			irq;
 	struct gpio_desc	*pwdn_gpio;
+	struct gpio_desc	*reset_gpio;
 	v4l2_std_id		curr_norm;
 	bool			powered;
 	bool			streaming;
@@ -473,13 +474,15 @@  static int adv7180_g_frame_interval(struct v4l2_subdev *sd,
 
 static void adv7180_set_power_pin(struct adv7180_state *state, bool on)
 {
-	if (!state->pwdn_gpio)
+	if (!state->pwdn_gpio && !state->reset_gpio)
 		return;
 
 	if (on) {
+		gpiod_set_value_cansleep(state->reset_gpio, 0);
 		gpiod_set_value_cansleep(state->pwdn_gpio, 0);
 		usleep_range(5000, 10000);
 	} else {
+		gpiod_set_value_cansleep(state->reset_gpio, 1);
 		gpiod_set_value_cansleep(state->pwdn_gpio, 1);
 	}
 }
@@ -1338,6 +1341,15 @@  static int adv7180_probe(struct i2c_client *client,
 		return ret;
 	}
 
+	state->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
+						     GPIOD_OUT_HIGH);
+	if (IS_ERR(state->reset_gpio)) {
+		ret = PTR_ERR(state->reset_gpio);
+		v4l_err(client, "request for reset pin failed: %d\n", ret);
+		return ret;
+	}
+
+
 	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
 		state->csi_client = i2c_new_dummy_device(client->adapter,
 				ADV7180_DEFAULT_CSI_I2C_ADDR);