diff mbox

[v2,4/6] drm/tinydrm/mipi-dbi: Add poweron-reset functions

Message ID 20180107174405.35008-5-noralf@tronnes.org (mailing list archive)
State New, archived
Headers show

Commit Message

Noralf Trønnes Jan. 7, 2018, 5:44 p.m. UTC
Split out common poweron-reset functionality.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/gpu/drm/tinydrm/mi0283qt.c | 20 ++----------
 drivers/gpu/drm/tinydrm/mipi-dbi.c | 63 ++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/tinydrm/st7586.c   |  9 ++----
 drivers/gpu/drm/tinydrm/st7735r.c  |  8 ++---
 include/drm/tinydrm/mipi-dbi.h     |  2 ++
 5 files changed, 73 insertions(+), 29 deletions(-)

Comments

Noralf Trønnes Jan. 7, 2018, 8:03 p.m. UTC | #1
Den 07.01.2018 18.44, skrev Noralf Trønnes:
> Split out common poweron-reset functionality.
>
> Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
> ---
>   drivers/gpu/drm/tinydrm/mi0283qt.c | 20 ++----------
>   drivers/gpu/drm/tinydrm/mipi-dbi.c | 63 ++++++++++++++++++++++++++++++++++++++
>   drivers/gpu/drm/tinydrm/st7586.c   |  9 ++----
>   drivers/gpu/drm/tinydrm/st7735r.c  |  8 ++---
>   include/drm/tinydrm/mipi-dbi.h     |  2 ++
>   5 files changed, 73 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c
> index c69a4d958f24..2a78bcd35045 100644
> --- a/drivers/gpu/drm/tinydrm/mi0283qt.c
> +++ b/drivers/gpu/drm/tinydrm/mi0283qt.c
> @@ -49,31 +49,17 @@
>   
>   static int mi0283qt_init(struct mipi_dbi *mipi)
>   {
> -	struct tinydrm_device *tdev = &mipi->tinydrm;
> -	struct device *dev = tdev->drm->dev;
>   	u8 addr_mode;
>   	int ret;
>   
>   	DRM_DEBUG_KMS("\n");
>   
> -	ret = regulator_enable(mipi->regulator);
> -	if (ret) {
> -		DRM_DEV_ERROR(dev, "Failed to enable regulator %d\n", ret);
> +	ret = mipi_dbi_poweron_conditional_reset(mipi);
> +	if (ret < 0)
>   		return ret;
> -	}
> -
> -	/* Avoid flicker by skipping setup if the bootloader has done it */
> -	if (mipi_dbi_display_is_on(mipi))
> +	if (ret > 0)
>   		return 0;
>   
> -	mipi_dbi_hw_reset(mipi);
> -	ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET);
> -	if (ret) {
> -		DRM_DEV_ERROR(dev, "Error sending command %d\n", ret);
> -		regulator_disable(mipi->regulator);
> -		return ret;
> -	}
> -
>   	msleep(20);
>   
>   	mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_OFF);
> diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c b/drivers/gpu/drm/tinydrm/mipi-dbi.c
> index ecc5c81a93ac..eea6803ff223 100644
> --- a/drivers/gpu/drm/tinydrm/mipi-dbi.c
> +++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c
> @@ -463,6 +463,7 @@ bool mipi_dbi_display_is_on(struct mipi_dbi *mipi)
>   
>   	val &= ~DCS_POWER_MODE_RESERVED_MASK;
>   
> +	/* The poweron/reset value is 08h DCS_POWER_MODE_DISPLAY_NORMAL_MODE */
>   	if (val != (DCS_POWER_MODE_DISPLAY |
>   	    DCS_POWER_MODE_DISPLAY_NORMAL_MODE | DCS_POWER_MODE_SLEEP_MODE))
>   		return false;
> @@ -473,6 +474,68 @@ bool mipi_dbi_display_is_on(struct mipi_dbi *mipi)
>   }
>   EXPORT_SYMBOL(mipi_dbi_display_is_on);
>   
> +static int mipi_dbi_por_conditional(struct mipi_dbi *mipi, bool cond)
> +{
> +	struct device *dev = mipi->tinydrm.drm->dev;
> +	int ret;
> +
> +	if (mipi->regulator) {
> +		ret = regulator_enable(mipi->regulator);
> +		if (ret) {
> +			DRM_DEV_ERROR(dev, "Failed to enable regulator (%d)\n", ret);
> +			return ret;
> +		}
> +	}
> +
> +	if (cond && mipi_dbi_display_is_on(mipi))
> +		return 1;
> +
> +	mipi_dbi_hw_reset(mipi);
> +	ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET);
> +	if (ret) {
> +		DRM_DEV_ERROR(dev, "Failed to send reset command (%d)\n", ret);
> +		if (mipi->regulator)
> +			regulator_disable(mipi->regulator);
> +		return ret;
> +	}

I forgot about the case where we don't have hw reset:

     /*
      * If we did a hw reset, we know the controller is in Sleep mode and
      * per MIPI DSC spec should wait 5ms after soft reset. If we didn't,
      * we assume worst case and wait 120ms.
      */
     if (mipi->reset)
         usleep_range(5000, 20000);
     else
         msleep(120);

Noralf.

> +
> +	return 0;
> +}
> +
> +/**
> + * mipi_dbi_poweron_reset - MIPI DBI poweron and reset
> + * @mipi: MIPI DBI structure
> + *
> + * This function enables the regulator if used and does a hardware and software
> + * reset.
> + *
> + * Returns:
> + * Zero on success, or a negative error code.
> + */
> +int mipi_dbi_poweron_reset(struct mipi_dbi *mipi)
> +{
> +	return mipi_dbi_por_conditional(mipi, false);
> +}
> +EXPORT_SYMBOL(mipi_dbi_poweron_reset);
> +
> +/**
> + * mipi_dbi_poweron_conditional_reset - MIPI DBI poweron and conditional reset
> + * @mipi: MIPI DBI structure
> + *
> + * This function enables the regulator if used and if the display is off, it
> + * does a hardware and software reset. If mipi_dbi_display_is_on() determines
> + * that the display is on, no reset is performed.
> + *
> + * Returns:
> + * Zero if the controller was reset, 1 if the display was already on, or a
> + * negative error code.
> + */
> +int mipi_dbi_poweron_conditional_reset(struct mipi_dbi *mipi)
> +{
> +	return mipi_dbi_por_conditional(mipi, true);
> +}
> +EXPORT_SYMBOL(mipi_dbi_poweron_conditional_reset);
> +
>   #if IS_ENABLED(CONFIG_SPI)
>   
>   /**
> diff --git a/drivers/gpu/drm/tinydrm/st7586.c b/drivers/gpu/drm/tinydrm/st7586.c
> index 9fd4423c8e70..a6396ef9cc4a 100644
> --- a/drivers/gpu/drm/tinydrm/st7586.c
> +++ b/drivers/gpu/drm/tinydrm/st7586.c
> @@ -179,19 +179,16 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
>   {
>   	struct tinydrm_device *tdev = pipe_to_tinydrm(pipe);
>   	struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
> -	struct device *dev = tdev->drm->dev;
>   	int ret;
>   	u8 addr_mode;
>   
>   	DRM_DEBUG_KMS("\n");
>   
> -	mipi_dbi_hw_reset(mipi);
> -	ret = mipi_dbi_command(mipi, ST7586_AUTO_READ_CTRL, 0x9f);
> -	if (ret) {
> -		DRM_DEV_ERROR(dev, "Error sending command %d\n", ret);
> +	ret = mipi_dbi_poweron_reset(mipi);
> +	if (ret)
>   		return;
> -	}
>   
> +	mipi_dbi_command(mipi, ST7586_AUTO_READ_CTRL, 0x9f);
>   	mipi_dbi_command(mipi, ST7586_OTP_RW_CTRL, 0x00);
>   
>   	msleep(10);
> diff --git a/drivers/gpu/drm/tinydrm/st7735r.c b/drivers/gpu/drm/tinydrm/st7735r.c
> index 1f38e15da676..650257ad0193 100644
> --- a/drivers/gpu/drm/tinydrm/st7735r.c
> +++ b/drivers/gpu/drm/tinydrm/st7735r.c
> @@ -46,13 +46,9 @@ static void jd_t18003_t01_pipe_enable(struct drm_simple_display_pipe *pipe,
>   
>   	DRM_DEBUG_KMS("\n");
>   
> -	mipi_dbi_hw_reset(mipi);
> -
> -	ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET);
> -	if (ret) {
> -		DRM_DEV_ERROR(dev, "Error sending command %d\n", ret);
> +	ret = mipi_dbi_poweron_reset(mipi);
> +	if (ret)
>   		return;
> -	}
>   
>   	msleep(150);
>   
> diff --git a/include/drm/tinydrm/mipi-dbi.h b/include/drm/tinydrm/mipi-dbi.h
> index 6441d9a9161a..795a4a2205bb 100644
> --- a/include/drm/tinydrm/mipi-dbi.h
> +++ b/include/drm/tinydrm/mipi-dbi.h
> @@ -73,6 +73,8 @@ void mipi_dbi_pipe_enable(struct drm_simple_display_pipe *pipe,
>   void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe);
>   void mipi_dbi_hw_reset(struct mipi_dbi *mipi);
>   bool mipi_dbi_display_is_on(struct mipi_dbi *mipi);
> +int mipi_dbi_poweron_reset(struct mipi_dbi *mipi);
> +int mipi_dbi_poweron_conditional_reset(struct mipi_dbi *mipi);
>   u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len);
>   
>   int mipi_dbi_command_read(struct mipi_dbi *mipi, u8 cmd, u8 *val);
David Lechner Jan. 9, 2018, 1:38 a.m. UTC | #2
On 01/07/2018 11:44 AM, Noralf Trønnes wrote:
> Split out common poweron-reset functionality.
> 
> Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
> ---
>   drivers/gpu/drm/tinydrm/mi0283qt.c | 20 ++----------
>   drivers/gpu/drm/tinydrm/mipi-dbi.c | 63 ++++++++++++++++++++++++++++++++++++++
>   drivers/gpu/drm/tinydrm/st7586.c   |  9 ++----
>   drivers/gpu/drm/tinydrm/st7735r.c  |  8 ++---
>   include/drm/tinydrm/mipi-dbi.h     |  2 ++
>   5 files changed, 73 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c
> index c69a4d958f24..2a78bcd35045 100644
> --- a/drivers/gpu/drm/tinydrm/mi0283qt.c
> +++ b/drivers/gpu/drm/tinydrm/mi0283qt.c
> @@ -49,31 +49,17 @@
>   
>   static int mi0283qt_init(struct mipi_dbi *mipi)
>   {
> -	struct tinydrm_device *tdev = &mipi->tinydrm;
> -	struct device *dev = tdev->drm->dev;
>   	u8 addr_mode;
>   	int ret;
>   
>   	DRM_DEBUG_KMS("\n");
>   
> -	ret = regulator_enable(mipi->regulator);
> -	if (ret) {
> -		DRM_DEV_ERROR(dev, "Failed to enable regulator %d\n", ret);
> +	ret = mipi_dbi_poweron_conditional_reset(mipi);
> +	if (ret < 0)
>   		return ret;
> -	}
> -
> -	/* Avoid flicker by skipping setup if the bootloader has done it */
> -	if (mipi_dbi_display_is_on(mipi))
> +	if (ret > 0)
>   		return 0;

If I am reading the patch right, it looks like there are two

	if (ret > 0)
    		return 0;

in a row with nothing in between when this is applied.

>   
> -	mipi_dbi_hw_reset(mipi);
> -	ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET);
> -	if (ret) {
> -		DRM_DEV_ERROR(dev, "Error sending command %d\n", ret);
> -		regulator_disable(mipi->regulator);
> -		return ret;
> -	}
> -
>   	msleep(20);
>   
>   	mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_OFF);
> diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c b/drivers/gpu/drm/tinydrm/mipi-dbi.c
> index ecc5c81a93ac..eea6803ff223 100644
> --- a/drivers/gpu/drm/tinydrm/mipi-dbi.c
> +++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c
> @@ -463,6 +463,7 @@ bool mipi_dbi_display_is_on(struct mipi_dbi *mipi)
>   
>   	val &= ~DCS_POWER_MODE_RESERVED_MASK;
>   
> +	/* The poweron/reset value is 08h DCS_POWER_MODE_DISPLAY_NORMAL_MODE */
>   	if (val != (DCS_POWER_MODE_DISPLAY |
>   	    DCS_POWER_MODE_DISPLAY_NORMAL_MODE | DCS_POWER_MODE_SLEEP_MODE))
>   		return false;
> @@ -473,6 +474,68 @@ bool mipi_dbi_display_is_on(struct mipi_dbi *mipi)
>   }
>   EXPORT_SYMBOL(mipi_dbi_display_is_on);
>   
> +static int mipi_dbi_por_conditional(struct mipi_dbi *mipi, bool cond)

I know it is long, but it would be nice to spell out poweron_reset here
instead of "por".

> +{
> +	struct device *dev = mipi->tinydrm.drm->dev;
> +	int ret;
> +
> +	if (mipi->regulator) {
> +		ret = regulator_enable(mipi->regulator);
> +		if (ret) {
> +			DRM_DEV_ERROR(dev, "Failed to enable regulator (%d)\n", ret);
> +			return ret;
> +		}
> +	}
> +
> +	if (cond && mipi_dbi_display_is_on(mipi))
> +		return 1;
> +
> +	mipi_dbi_hw_reset(mipi);
> +	ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET);

It seems unnecessary to do a soft reset after a hard reset, but I suppose some displays
don't have a hard reset and the extra soft reset shouldn't hurt anything.

> +	if (ret) {
> +		DRM_DEV_ERROR(dev, "Failed to send reset command (%d)\n", ret);
> +		if (mipi->regulator)
> +			regulator_disable(mipi->regulator);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * mipi_dbi_poweron_reset - MIPI DBI poweron and reset
> + * @mipi: MIPI DBI structure
> + *
> + * This function enables the regulator if used and does a hardware and software
> + * reset.
> + *
> + * Returns:
> + * Zero on success, or a negative error code.
> + */
> +int mipi_dbi_poweron_reset(struct mipi_dbi *mipi)
> +{
> +	return mipi_dbi_por_conditional(mipi, false);
> +}
> +EXPORT_SYMBOL(mipi_dbi_poweron_reset);
> +
> +/**
> + * mipi_dbi_poweron_conditional_reset - MIPI DBI poweron and conditional reset
> + * @mipi: MIPI DBI structure
> + *
> + * This function enables the regulator if used and if the display is off, it
> + * does a hardware and software reset. If mipi_dbi_display_is_on() determines
> + * that the display is on, no reset is performed.
> + *
> + * Returns:
> + * Zero if the controller was reset, 1 if the display was already on, or a
> + * negative error code.
> + */
> +int mipi_dbi_poweron_conditional_reset(struct mipi_dbi *mipi)
> +{
> +	return mipi_dbi_por_conditional(mipi, true);
> +}
> +EXPORT_SYMBOL(mipi_dbi_poweron_conditional_reset);
> +
>   #if IS_ENABLED(CONFIG_SPI)
>   
>   /**
> diff --git a/drivers/gpu/drm/tinydrm/st7586.c b/drivers/gpu/drm/tinydrm/st7586.c
> index 9fd4423c8e70..a6396ef9cc4a 100644
> --- a/drivers/gpu/drm/tinydrm/st7586.c
> +++ b/drivers/gpu/drm/tinydrm/st7586.c
> @@ -179,19 +179,16 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
>   {
>   	struct tinydrm_device *tdev = pipe_to_tinydrm(pipe);
>   	struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
> -	struct device *dev = tdev->drm->dev;
>   	int ret;
>   	u8 addr_mode;
>   
>   	DRM_DEBUG_KMS("\n");
>   
> -	mipi_dbi_hw_reset(mipi);
> -	ret = mipi_dbi_command(mipi, ST7586_AUTO_READ_CTRL, 0x9f);
> -	if (ret) {
> -		DRM_DEV_ERROR(dev, "Error sending command %d\n", ret);
> +	ret = mipi_dbi_poweron_reset(mipi);
> +	if (ret)
>   		return;
> -	}
>   
> +	mipi_dbi_command(mipi, ST7586_AUTO_READ_CTRL, 0x9f);
>   	mipi_dbi_command(mipi, ST7586_OTP_RW_CTRL, 0x00);
>   
>   	msleep(10);
> diff --git a/drivers/gpu/drm/tinydrm/st7735r.c b/drivers/gpu/drm/tinydrm/st7735r.c
> index 1f38e15da676..650257ad0193 100644
> --- a/drivers/gpu/drm/tinydrm/st7735r.c
> +++ b/drivers/gpu/drm/tinydrm/st7735r.c
> @@ -46,13 +46,9 @@ static void jd_t18003_t01_pipe_enable(struct drm_simple_display_pipe *pipe,
>   
>   	DRM_DEBUG_KMS("\n");
>   
> -	mipi_dbi_hw_reset(mipi);
> -
> -	ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET);
> -	if (ret) {
> -		DRM_DEV_ERROR(dev, "Error sending command %d\n", ret);
> +	ret = mipi_dbi_poweron_reset(mipi);
> +	if (ret)
>   		return;
> -	}
>   
>   	msleep(150);
>   
> diff --git a/include/drm/tinydrm/mipi-dbi.h b/include/drm/tinydrm/mipi-dbi.h
> index 6441d9a9161a..795a4a2205bb 100644
> --- a/include/drm/tinydrm/mipi-dbi.h
> +++ b/include/drm/tinydrm/mipi-dbi.h
> @@ -73,6 +73,8 @@ void mipi_dbi_pipe_enable(struct drm_simple_display_pipe *pipe,
>   void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe);
>   void mipi_dbi_hw_reset(struct mipi_dbi *mipi);
>   bool mipi_dbi_display_is_on(struct mipi_dbi *mipi);
> +int mipi_dbi_poweron_reset(struct mipi_dbi *mipi);
> +int mipi_dbi_poweron_conditional_reset(struct mipi_dbi *mipi);
>   u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len);
>   
>   int mipi_dbi_command_read(struct mipi_dbi *mipi, u8 cmd, u8 *val);
>
David Lechner Jan. 9, 2018, 1:40 a.m. UTC | #3
On 01/08/2018 07:38 PM, David Lechner wrote:
> On 01/07/2018 11:44 AM, Noralf Trønnes wrote:
>> Split out common poweron-reset functionality.
>>
>> Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
>> ---
>>   drivers/gpu/drm/tinydrm/mi0283qt.c | 20 ++----------
>>   drivers/gpu/drm/tinydrm/mipi-dbi.c | 63 ++++++++++++++++++++++++++++++++++++++
>>   drivers/gpu/drm/tinydrm/st7586.c   |  9 ++----
>>   drivers/gpu/drm/tinydrm/st7735r.c  |  8 ++---
>>   include/drm/tinydrm/mipi-dbi.h     |  2 ++
>>   5 files changed, 73 insertions(+), 29 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c
>> index c69a4d958f24..2a78bcd35045 100644
>> --- a/drivers/gpu/drm/tinydrm/mi0283qt.c
>> +++ b/drivers/gpu/drm/tinydrm/mi0283qt.c
>> @@ -49,31 +49,17 @@
>>   static int mi0283qt_init(struct mipi_dbi *mipi)
>>   {
>> -    struct tinydrm_device *tdev = &mipi->tinydrm;
>> -    struct device *dev = tdev->drm->dev;
>>       u8 addr_mode;
>>       int ret;
>>       DRM_DEBUG_KMS("\n");
>> -    ret = regulator_enable(mipi->regulator);
>> -    if (ret) {
>> -        DRM_DEV_ERROR(dev, "Failed to enable regulator %d\n", ret);
>> +    ret = mipi_dbi_poweron_conditional_reset(mipi);
>> +    if (ret < 0)
>>           return ret;
>> -    }
>> -
>> -    /* Avoid flicker by skipping setup if the bootloader has done it */
>> -    if (mipi_dbi_display_is_on(mipi))
>> +    if (ret > 0)
>>           return 0;
> 
> If I am reading the patch right, it looks like there are two
> 
>      if (ret > 0)
>             return 0;
> 
> in a row with nothing in between when this is applied.
> 

I see now that I missed < vs. >. Probably better to say (ret == 1) instead of (ret > 0).
Noralf Trønnes Jan. 9, 2018, 3:01 p.m. UTC | #4
Den 09.01.2018 02.38, skrev David Lechner:
> On 01/07/2018 11:44 AM, Noralf Trønnes wrote:
>> Split out common poweron-reset functionality.
>>
>> Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
>> ---
>>   drivers/gpu/drm/tinydrm/mi0283qt.c | 20 ++----------
>>   drivers/gpu/drm/tinydrm/mipi-dbi.c | 63 
>> ++++++++++++++++++++++++++++++++++++++
>>   drivers/gpu/drm/tinydrm/st7586.c   |  9 ++----
>>   drivers/gpu/drm/tinydrm/st7735r.c  |  8 ++---
>>   include/drm/tinydrm/mipi-dbi.h     |  2 ++
>>   5 files changed, 73 insertions(+), 29 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c 
>> b/drivers/gpu/drm/tinydrm/mi0283qt.c
>> index c69a4d958f24..2a78bcd35045 100644
>> --- a/drivers/gpu/drm/tinydrm/mi0283qt.c
>> +++ b/drivers/gpu/drm/tinydrm/mi0283qt.c
>> @@ -49,31 +49,17 @@
>>     static int mi0283qt_init(struct mipi_dbi *mipi)
>>   {
>> -    struct tinydrm_device *tdev = &mipi->tinydrm;
>> -    struct device *dev = tdev->drm->dev;
>>       u8 addr_mode;
>>       int ret;
>>         DRM_DEBUG_KMS("\n");
>>   -    ret = regulator_enable(mipi->regulator);
>> -    if (ret) {
>> -        DRM_DEV_ERROR(dev, "Failed to enable regulator %d\n", ret);
>> +    ret = mipi_dbi_poweron_conditional_reset(mipi);
>> +    if (ret < 0)
>>           return ret;
>> -    }
>> -
>> -    /* Avoid flicker by skipping setup if the bootloader has done it */
>> -    if (mipi_dbi_display_is_on(mipi))
>> +    if (ret > 0)
>>           return 0;
>
> If I am reading the patch right, it looks like there are two
>
>     if (ret > 0)
>            return 0;
>
> in a row with nothing in between when this is applied.
>
>>   -    mipi_dbi_hw_reset(mipi);
>> -    ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET);
>> -    if (ret) {
>> -        DRM_DEV_ERROR(dev, "Error sending command %d\n", ret);
>> -        regulator_disable(mipi->regulator);
>> -        return ret;
>> -    }
>> -
>>       msleep(20);
>>         mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_OFF);
>> diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c 
>> b/drivers/gpu/drm/tinydrm/mipi-dbi.c
>> index ecc5c81a93ac..eea6803ff223 100644
>> --- a/drivers/gpu/drm/tinydrm/mipi-dbi.c
>> +++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c
>> @@ -463,6 +463,7 @@ bool mipi_dbi_display_is_on(struct mipi_dbi *mipi)
>>         val &= ~DCS_POWER_MODE_RESERVED_MASK;
>>   +    /* The poweron/reset value is 08h 
>> DCS_POWER_MODE_DISPLAY_NORMAL_MODE */
>>       if (val != (DCS_POWER_MODE_DISPLAY |
>>           DCS_POWER_MODE_DISPLAY_NORMAL_MODE | 
>> DCS_POWER_MODE_SLEEP_MODE))
>>           return false;
>> @@ -473,6 +474,68 @@ bool mipi_dbi_display_is_on(struct mipi_dbi *mipi)
>>   }
>>   EXPORT_SYMBOL(mipi_dbi_display_is_on);
>>   +static int mipi_dbi_por_conditional(struct mipi_dbi *mipi, bool cond)
>
> I know it is long, but it would be nice to spell out poweron_reset here
> instead of "por".
>
>> +{
>> +    struct device *dev = mipi->tinydrm.drm->dev;
>> +    int ret;
>> +
>> +    if (mipi->regulator) {
>> +        ret = regulator_enable(mipi->regulator);
>> +        if (ret) {
>> +            DRM_DEV_ERROR(dev, "Failed to enable regulator (%d)\n", 
>> ret);
>> +            return ret;
>> +        }
>> +    }
>> +
>> +    if (cond && mipi_dbi_display_is_on(mipi))
>> +        return 1;
>> +
>> +    mipi_dbi_hw_reset(mipi);
>> +    ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET);
>
> It seems unnecessary to do a soft reset after a hard reset, but I 
> suppose some displays
> don't have a hard reset and the extra soft reset shouldn't hurt anything.
>

Both ILI9341 and ST7735R (not ST7586S) lists soft reset as part of the
Power Flow Chart, but it's not explicit about it being required or not:

Power on sequence
HW reset
SW reset
State is now Sleep in

I looked in the MIPI DBI spec and there's nothing about requiring both
hw _and_ soft reset. But I have seen hard and soft reset in many panel
init's, so I think we keep this as the default. It has a 5ms penalty.
I could shave that off in mipi_dbi_hw_reset(). It keeps reset low for
20ms, but the spec says it just has to be longer than 9us with noise
spikes less than 20ns wide:

-    msleep(20);
+    usleep_range(20, 1000);

Noralf.

>> +    if (ret) {
>> +        DRM_DEV_ERROR(dev, "Failed to send reset command (%d)\n", ret);
>> +        if (mipi->regulator)
>> +            regulator_disable(mipi->regulator);
>> +        return ret;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +/**
>> + * mipi_dbi_poweron_reset - MIPI DBI poweron and reset
>> + * @mipi: MIPI DBI structure
>> + *
>> + * This function enables the regulator if used and does a hardware 
>> and software
>> + * reset.
>> + *
>> + * Returns:
>> + * Zero on success, or a negative error code.
>> + */
>> +int mipi_dbi_poweron_reset(struct mipi_dbi *mipi)
>> +{
>> +    return mipi_dbi_por_conditional(mipi, false);
>> +}
>> +EXPORT_SYMBOL(mipi_dbi_poweron_reset);
>> +
>> +/**
>> + * mipi_dbi_poweron_conditional_reset - MIPI DBI poweron and 
>> conditional reset
>> + * @mipi: MIPI DBI structure
>> + *
>> + * This function enables the regulator if used and if the display is 
>> off, it
>> + * does a hardware and software reset. If mipi_dbi_display_is_on() 
>> determines
>> + * that the display is on, no reset is performed.
>> + *
>> + * Returns:
>> + * Zero if the controller was reset, 1 if the display was already 
>> on, or a
>> + * negative error code.
>> + */
>> +int mipi_dbi_poweron_conditional_reset(struct mipi_dbi *mipi)
>> +{
>> +    return mipi_dbi_por_conditional(mipi, true);
>> +}
>> +EXPORT_SYMBOL(mipi_dbi_poweron_conditional_reset);
>> +
>>   #if IS_ENABLED(CONFIG_SPI)
>>     /**
>> diff --git a/drivers/gpu/drm/tinydrm/st7586.c 
>> b/drivers/gpu/drm/tinydrm/st7586.c
>> index 9fd4423c8e70..a6396ef9cc4a 100644
>> --- a/drivers/gpu/drm/tinydrm/st7586.c
>> +++ b/drivers/gpu/drm/tinydrm/st7586.c
>> @@ -179,19 +179,16 @@ static void st7586_pipe_enable(struct 
>> drm_simple_display_pipe *pipe,
>>   {
>>       struct tinydrm_device *tdev = pipe_to_tinydrm(pipe);
>>       struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
>> -    struct device *dev = tdev->drm->dev;
>>       int ret;
>>       u8 addr_mode;
>>         DRM_DEBUG_KMS("\n");
>>   -    mipi_dbi_hw_reset(mipi);
>> -    ret = mipi_dbi_command(mipi, ST7586_AUTO_READ_CTRL, 0x9f);
>> -    if (ret) {
>> -        DRM_DEV_ERROR(dev, "Error sending command %d\n", ret);
>> +    ret = mipi_dbi_poweron_reset(mipi);
>> +    if (ret)
>>           return;
>> -    }
>>   +    mipi_dbi_command(mipi, ST7586_AUTO_READ_CTRL, 0x9f);
>>       mipi_dbi_command(mipi, ST7586_OTP_RW_CTRL, 0x00);
>>         msleep(10);
>> diff --git a/drivers/gpu/drm/tinydrm/st7735r.c 
>> b/drivers/gpu/drm/tinydrm/st7735r.c
>> index 1f38e15da676..650257ad0193 100644
>> --- a/drivers/gpu/drm/tinydrm/st7735r.c
>> +++ b/drivers/gpu/drm/tinydrm/st7735r.c
>> @@ -46,13 +46,9 @@ static void jd_t18003_t01_pipe_enable(struct 
>> drm_simple_display_pipe *pipe,
>>         DRM_DEBUG_KMS("\n");
>>   -    mipi_dbi_hw_reset(mipi);
>> -
>> -    ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET);
>> -    if (ret) {
>> -        DRM_DEV_ERROR(dev, "Error sending command %d\n", ret);
>> +    ret = mipi_dbi_poweron_reset(mipi);
>> +    if (ret)
>>           return;
>> -    }
>>         msleep(150);
>>   diff --git a/include/drm/tinydrm/mipi-dbi.h 
>> b/include/drm/tinydrm/mipi-dbi.h
>> index 6441d9a9161a..795a4a2205bb 100644
>> --- a/include/drm/tinydrm/mipi-dbi.h
>> +++ b/include/drm/tinydrm/mipi-dbi.h
>> @@ -73,6 +73,8 @@ void mipi_dbi_pipe_enable(struct 
>> drm_simple_display_pipe *pipe,
>>   void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe);
>>   void mipi_dbi_hw_reset(struct mipi_dbi *mipi);
>>   bool mipi_dbi_display_is_on(struct mipi_dbi *mipi);
>> +int mipi_dbi_poweron_reset(struct mipi_dbi *mipi);
>> +int mipi_dbi_poweron_conditional_reset(struct mipi_dbi *mipi);
>>   u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len);
>>     int mipi_dbi_command_read(struct mipi_dbi *mipi, u8 cmd, u8 *val);
>>
>
David Lechner Jan. 10, 2018, 3:04 a.m. UTC | #5
On 01/09/2018 09:01 AM, Noralf Trønnes wrote:
> 
> Den 09.01.2018 02.38, skrev David Lechner:
>> On 01/07/2018 11:44 AM, Noralf Trønnes wrote:
>>> Split out common poweron-reset functionality.
>>>
>>> Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
>>> ---
>>>   drivers/gpu/drm/tinydrm/mi0283qt.c | 20 ++----------
>>>   drivers/gpu/drm/tinydrm/mipi-dbi.c | 63 ++++++++++++++++++++++++++++++++++++++
>>>   drivers/gpu/drm/tinydrm/st7586.c   |  9 ++----
>>>   drivers/gpu/drm/tinydrm/st7735r.c  |  8 ++---
>>>   include/drm/tinydrm/mipi-dbi.h     |  2 ++
>>>   5 files changed, 73 insertions(+), 29 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c
>>> index c69a4d958f24..2a78bcd35045 100644
>>> --- a/drivers/gpu/drm/tinydrm/mi0283qt.c
>>> +++ b/drivers/gpu/drm/tinydrm/mi0283qt.c
>>> @@ -49,31 +49,17 @@
>>>     static int mi0283qt_init(struct mipi_dbi *mipi)
>>>   {
>>> -    struct tinydrm_device *tdev = &mipi->tinydrm;
>>> -    struct device *dev = tdev->drm->dev;
>>>       u8 addr_mode;
>>>       int ret;
>>>         DRM_DEBUG_KMS("\n");
>>>   -    ret = regulator_enable(mipi->regulator);
>>> -    if (ret) {
>>> -        DRM_DEV_ERROR(dev, "Failed to enable regulator %d\n", ret);
>>> +    ret = mipi_dbi_poweron_conditional_reset(mipi);
>>> +    if (ret < 0)
>>>           return ret;
>>> -    }
>>> -
>>> -    /* Avoid flicker by skipping setup if the bootloader has done it */
>>> -    if (mipi_dbi_display_is_on(mipi))
>>> +    if (ret > 0)
>>>           return 0;
>>
>> If I am reading the patch right, it looks like there are two
>>
>>     if (ret > 0)
>>            return 0;
>>
>> in a row with nothing in between when this is applied.
>>
>>>   -    mipi_dbi_hw_reset(mipi);
>>> -    ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET);
>>> -    if (ret) {
>>> -        DRM_DEV_ERROR(dev, "Error sending command %d\n", ret);
>>> -        regulator_disable(mipi->regulator);
>>> -        return ret;
>>> -    }
>>> -
>>>       msleep(20);
>>>         mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_OFF);
>>> diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c b/drivers/gpu/drm/tinydrm/mipi-dbi.c
>>> index ecc5c81a93ac..eea6803ff223 100644
>>> --- a/drivers/gpu/drm/tinydrm/mipi-dbi.c
>>> +++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c
>>> @@ -463,6 +463,7 @@ bool mipi_dbi_display_is_on(struct mipi_dbi *mipi)
>>>         val &= ~DCS_POWER_MODE_RESERVED_MASK;
>>>   +    /* The poweron/reset value is 08h DCS_POWER_MODE_DISPLAY_NORMAL_MODE */
>>>       if (val != (DCS_POWER_MODE_DISPLAY |
>>>           DCS_POWER_MODE_DISPLAY_NORMAL_MODE | DCS_POWER_MODE_SLEEP_MODE))
>>>           return false;
>>> @@ -473,6 +474,68 @@ bool mipi_dbi_display_is_on(struct mipi_dbi *mipi)
>>>   }
>>>   EXPORT_SYMBOL(mipi_dbi_display_is_on);
>>>   +static int mipi_dbi_por_conditional(struct mipi_dbi *mipi, bool cond)
>>
>> I know it is long, but it would be nice to spell out poweron_reset here
>> instead of "por".
>>
>>> +{
>>> +    struct device *dev = mipi->tinydrm.drm->dev;
>>> +    int ret;
>>> +
>>> +    if (mipi->regulator) {
>>> +        ret = regulator_enable(mipi->regulator);
>>> +        if (ret) {
>>> +            DRM_DEV_ERROR(dev, "Failed to enable regulator (%d)\n", ret);
>>> +            return ret;
>>> +        }
>>> +    }
>>> +
>>> +    if (cond && mipi_dbi_display_is_on(mipi))
>>> +        return 1;
>>> +
>>> +    mipi_dbi_hw_reset(mipi);
>>> +    ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET);
>>
>> It seems unnecessary to do a soft reset after a hard reset, but I suppose some displays
>> don't have a hard reset and the extra soft reset shouldn't hurt anything.
>>
> 
> Both ILI9341 and ST7735R (not ST7586S) lists soft reset as part of the
> Power Flow Chart, but it's not explicit about it being required or not:
> 
> Power on sequence
> HW reset
> SW reset
> State is now Sleep in
> 
> I looked in the MIPI DBI spec and there's nothing about requiring both
> hw _and_ soft reset. But I have seen hard and soft reset in many panel
> init's, so I think we keep this as the default. It has a 5ms penalty.
> I could shave that off in mipi_dbi_hw_reset(). It keeps reset low for
> 20ms, but the spec says it just has to be longer than 9us with noise
> spikes less than 20ns wide:
> 
> -    msleep(20);
> +    usleep_range(20, 1000);
> 

Sounds good to me.
diff mbox

Patch

diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c
index c69a4d958f24..2a78bcd35045 100644
--- a/drivers/gpu/drm/tinydrm/mi0283qt.c
+++ b/drivers/gpu/drm/tinydrm/mi0283qt.c
@@ -49,31 +49,17 @@ 
 
 static int mi0283qt_init(struct mipi_dbi *mipi)
 {
-	struct tinydrm_device *tdev = &mipi->tinydrm;
-	struct device *dev = tdev->drm->dev;
 	u8 addr_mode;
 	int ret;
 
 	DRM_DEBUG_KMS("\n");
 
-	ret = regulator_enable(mipi->regulator);
-	if (ret) {
-		DRM_DEV_ERROR(dev, "Failed to enable regulator %d\n", ret);
+	ret = mipi_dbi_poweron_conditional_reset(mipi);
+	if (ret < 0)
 		return ret;
-	}
-
-	/* Avoid flicker by skipping setup if the bootloader has done it */
-	if (mipi_dbi_display_is_on(mipi))
+	if (ret > 0)
 		return 0;
 
-	mipi_dbi_hw_reset(mipi);
-	ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET);
-	if (ret) {
-		DRM_DEV_ERROR(dev, "Error sending command %d\n", ret);
-		regulator_disable(mipi->regulator);
-		return ret;
-	}
-
 	msleep(20);
 
 	mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_OFF);
diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c b/drivers/gpu/drm/tinydrm/mipi-dbi.c
index ecc5c81a93ac..eea6803ff223 100644
--- a/drivers/gpu/drm/tinydrm/mipi-dbi.c
+++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c
@@ -463,6 +463,7 @@  bool mipi_dbi_display_is_on(struct mipi_dbi *mipi)
 
 	val &= ~DCS_POWER_MODE_RESERVED_MASK;
 
+	/* The poweron/reset value is 08h DCS_POWER_MODE_DISPLAY_NORMAL_MODE */
 	if (val != (DCS_POWER_MODE_DISPLAY |
 	    DCS_POWER_MODE_DISPLAY_NORMAL_MODE | DCS_POWER_MODE_SLEEP_MODE))
 		return false;
@@ -473,6 +474,68 @@  bool mipi_dbi_display_is_on(struct mipi_dbi *mipi)
 }
 EXPORT_SYMBOL(mipi_dbi_display_is_on);
 
+static int mipi_dbi_por_conditional(struct mipi_dbi *mipi, bool cond)
+{
+	struct device *dev = mipi->tinydrm.drm->dev;
+	int ret;
+
+	if (mipi->regulator) {
+		ret = regulator_enable(mipi->regulator);
+		if (ret) {
+			DRM_DEV_ERROR(dev, "Failed to enable regulator (%d)\n", ret);
+			return ret;
+		}
+	}
+
+	if (cond && mipi_dbi_display_is_on(mipi))
+		return 1;
+
+	mipi_dbi_hw_reset(mipi);
+	ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "Failed to send reset command (%d)\n", ret);
+		if (mipi->regulator)
+			regulator_disable(mipi->regulator);
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * mipi_dbi_poweron_reset - MIPI DBI poweron and reset
+ * @mipi: MIPI DBI structure
+ *
+ * This function enables the regulator if used and does a hardware and software
+ * reset.
+ *
+ * Returns:
+ * Zero on success, or a negative error code.
+ */
+int mipi_dbi_poweron_reset(struct mipi_dbi *mipi)
+{
+	return mipi_dbi_por_conditional(mipi, false);
+}
+EXPORT_SYMBOL(mipi_dbi_poweron_reset);
+
+/**
+ * mipi_dbi_poweron_conditional_reset - MIPI DBI poweron and conditional reset
+ * @mipi: MIPI DBI structure
+ *
+ * This function enables the regulator if used and if the display is off, it
+ * does a hardware and software reset. If mipi_dbi_display_is_on() determines
+ * that the display is on, no reset is performed.
+ *
+ * Returns:
+ * Zero if the controller was reset, 1 if the display was already on, or a
+ * negative error code.
+ */
+int mipi_dbi_poweron_conditional_reset(struct mipi_dbi *mipi)
+{
+	return mipi_dbi_por_conditional(mipi, true);
+}
+EXPORT_SYMBOL(mipi_dbi_poweron_conditional_reset);
+
 #if IS_ENABLED(CONFIG_SPI)
 
 /**
diff --git a/drivers/gpu/drm/tinydrm/st7586.c b/drivers/gpu/drm/tinydrm/st7586.c
index 9fd4423c8e70..a6396ef9cc4a 100644
--- a/drivers/gpu/drm/tinydrm/st7586.c
+++ b/drivers/gpu/drm/tinydrm/st7586.c
@@ -179,19 +179,16 @@  static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
 {
 	struct tinydrm_device *tdev = pipe_to_tinydrm(pipe);
 	struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
-	struct device *dev = tdev->drm->dev;
 	int ret;
 	u8 addr_mode;
 
 	DRM_DEBUG_KMS("\n");
 
-	mipi_dbi_hw_reset(mipi);
-	ret = mipi_dbi_command(mipi, ST7586_AUTO_READ_CTRL, 0x9f);
-	if (ret) {
-		DRM_DEV_ERROR(dev, "Error sending command %d\n", ret);
+	ret = mipi_dbi_poweron_reset(mipi);
+	if (ret)
 		return;
-	}
 
+	mipi_dbi_command(mipi, ST7586_AUTO_READ_CTRL, 0x9f);
 	mipi_dbi_command(mipi, ST7586_OTP_RW_CTRL, 0x00);
 
 	msleep(10);
diff --git a/drivers/gpu/drm/tinydrm/st7735r.c b/drivers/gpu/drm/tinydrm/st7735r.c
index 1f38e15da676..650257ad0193 100644
--- a/drivers/gpu/drm/tinydrm/st7735r.c
+++ b/drivers/gpu/drm/tinydrm/st7735r.c
@@ -46,13 +46,9 @@  static void jd_t18003_t01_pipe_enable(struct drm_simple_display_pipe *pipe,
 
 	DRM_DEBUG_KMS("\n");
 
-	mipi_dbi_hw_reset(mipi);
-
-	ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET);
-	if (ret) {
-		DRM_DEV_ERROR(dev, "Error sending command %d\n", ret);
+	ret = mipi_dbi_poweron_reset(mipi);
+	if (ret)
 		return;
-	}
 
 	msleep(150);
 
diff --git a/include/drm/tinydrm/mipi-dbi.h b/include/drm/tinydrm/mipi-dbi.h
index 6441d9a9161a..795a4a2205bb 100644
--- a/include/drm/tinydrm/mipi-dbi.h
+++ b/include/drm/tinydrm/mipi-dbi.h
@@ -73,6 +73,8 @@  void mipi_dbi_pipe_enable(struct drm_simple_display_pipe *pipe,
 void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe);
 void mipi_dbi_hw_reset(struct mipi_dbi *mipi);
 bool mipi_dbi_display_is_on(struct mipi_dbi *mipi);
+int mipi_dbi_poweron_reset(struct mipi_dbi *mipi);
+int mipi_dbi_poweron_conditional_reset(struct mipi_dbi *mipi);
 u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len);
 
 int mipi_dbi_command_read(struct mipi_dbi *mipi, u8 cmd, u8 *val);