Re: [PATCH v4.1 3/4] drm/bridge: analogix_dp: add the PSR function support

2016-07-15 Thread Yakir Yang

Sean,

On 07/15/2016 09:13 PM, Sean Paul wrote:

On Fri, Jul 15, 2016 at 06:55:17PM +0800, Yakir Yang wrote:

The full name of PSR is Panel Self Refresh, panel device could refresh
itself with the hardware framebuffer in panel, this would make lots of
sense to save the power consumption.

This patch have exported two symbols for platform driver to implement
the PSR function in hardware side:
- analogix_dp_active_psr()
- analogix_dp_inactive_psr()

Signed-off-by: Yakir Yang 

Reviewed-by: Sean Paul 


Thanks for your reviewed  :-D

- Yakir




---
Changes in v4.1:
- Take use of existing edp_psr_vsc struct to swap HBx and DBx setting. (Sean)
- Remove PSR_VID_CRC_FLUSH setting analogix_dp_enable_psr_crc().
- Add comment about PBx magic numbers. (Sean)

Changes in v4:
- Downgrade the PSR version print message to debug level. (Sean)
- Return 'void' instead of 'int' in analogix_dp_enable_sink_psr(). (Sean)
- Delete the unused read dpcd operations in analogix_dp_enable_sink_psr(). 
(Sean)
- Delete the arbitrary usleep_range in analogix_dp_enable_psr_crc. (Sean).
- Clean up the hardcoded values in analogix_dp_send_psr_spd(). (Sean)
- Rename "active/inactive" to "enable/disable". (Sean, Dominik)
- Keep set the PSR_VID_CRC_FLUSH gate in analogix_dp_enable_psr_crc().

Changes in v3:
- split analogix_dp_enable_psr(), make it more clearly
 analogix_dp_detect_sink_psr()
 analogix_dp_enable_sink_psr()
- remove some nosie register setting comments

Changes in v2:
- introduce in v2, splite the common Analogix DP changes out

  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 81 ++
  drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  5 ++
  drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 51 ++
  drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  | 34 +
  include/drm/bridge/analogix_dp.h   |  3 +
  5 files changed, 174 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 32715da..381b25e 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -97,6 +97,83 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device 
*dp)
return 0;
  }
  
+int analogix_dp_enable_psr(struct device *dev)

+{
+   struct analogix_dp_device *dp = dev_get_drvdata(dev);
+   struct edp_vsc_psr psr_vsc;
+
+   if (!dp->psr_support)
+   return -EINVAL;
+
+   /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
+   memset(_vsc, 0, sizeof(psr_vsc));
+   psr_vsc.sdp_header.HB0 = 0;
+   psr_vsc.sdp_header.HB1 = 0x7;
+   psr_vsc.sdp_header.HB2 = 0x2;
+   psr_vsc.sdp_header.HB3 = 0x8;
+
+   psr_vsc.DB0 = 0;
+   psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID;
+
+   analogix_dp_send_psr_spd(dp, _vsc);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
+
+int analogix_dp_disable_psr(struct device *dev)
+{
+   struct analogix_dp_device *dp = dev_get_drvdata(dev);
+   struct edp_vsc_psr psr_vsc;
+
+   if (!dp->psr_support)
+   return -EINVAL;
+
+   /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
+   memset(_vsc, 0, sizeof(psr_vsc));
+   psr_vsc.sdp_header.HB0 = 0;
+   psr_vsc.sdp_header.HB1 = 0x7;
+   psr_vsc.sdp_header.HB2 = 0x2;
+   psr_vsc.sdp_header.HB3 = 0x8;
+
+   psr_vsc.DB0 = 0;
+   psr_vsc.DB1 = 0;
+
+   analogix_dp_send_psr_spd(dp, _vsc);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_disable_psr);
+
+static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
+{
+   unsigned char psr_version;
+
+   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_SUPPORT, _version);
+   dev_dbg(dp->dev, "Panel PSR version : %x\n", psr_version);
+
+   return (psr_version & DP_PSR_IS_SUPPORTED) ? true : false;
+}
+
+static void analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
+{
+   unsigned char psr_en;
+
+   /* Disable psr function */
+   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, _en);
+   psr_en &= ~DP_PSR_ENABLE;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   /* Main-Link transmitter remains active during PSR active states */
+   psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   /* Enable psr function */
+   psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE |
+DP_PSR_CRC_VERIFICATION;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   analogix_dp_enable_psr_crc(dp);
+}
+
  static unsigned char analogix_dp_calc_edid_check_sum(unsigned char *edid_data)
  {
int i;
@@ -921,6 +998,10 @@ static void analogix_dp_commit(struct analogix_dp_device 
*dp)
  
  	/* Enable video */


Re: [PATCH v4.1 3/4] drm/bridge: analogix_dp: add the PSR function support

2016-07-15 Thread Yakir Yang

Sean,

On 07/15/2016 09:13 PM, Sean Paul wrote:

On Fri, Jul 15, 2016 at 06:55:17PM +0800, Yakir Yang wrote:

The full name of PSR is Panel Self Refresh, panel device could refresh
itself with the hardware framebuffer in panel, this would make lots of
sense to save the power consumption.

This patch have exported two symbols for platform driver to implement
the PSR function in hardware side:
- analogix_dp_active_psr()
- analogix_dp_inactive_psr()

Signed-off-by: Yakir Yang 

Reviewed-by: Sean Paul 


Thanks for your reviewed  :-D

- Yakir




---
Changes in v4.1:
- Take use of existing edp_psr_vsc struct to swap HBx and DBx setting. (Sean)
- Remove PSR_VID_CRC_FLUSH setting analogix_dp_enable_psr_crc().
- Add comment about PBx magic numbers. (Sean)

Changes in v4:
- Downgrade the PSR version print message to debug level. (Sean)
- Return 'void' instead of 'int' in analogix_dp_enable_sink_psr(). (Sean)
- Delete the unused read dpcd operations in analogix_dp_enable_sink_psr(). 
(Sean)
- Delete the arbitrary usleep_range in analogix_dp_enable_psr_crc. (Sean).
- Clean up the hardcoded values in analogix_dp_send_psr_spd(). (Sean)
- Rename "active/inactive" to "enable/disable". (Sean, Dominik)
- Keep set the PSR_VID_CRC_FLUSH gate in analogix_dp_enable_psr_crc().

Changes in v3:
- split analogix_dp_enable_psr(), make it more clearly
 analogix_dp_detect_sink_psr()
 analogix_dp_enable_sink_psr()
- remove some nosie register setting comments

Changes in v2:
- introduce in v2, splite the common Analogix DP changes out

  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 81 ++
  drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  5 ++
  drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 51 ++
  drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  | 34 +
  include/drm/bridge/analogix_dp.h   |  3 +
  5 files changed, 174 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 32715da..381b25e 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -97,6 +97,83 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device 
*dp)
return 0;
  }
  
+int analogix_dp_enable_psr(struct device *dev)

+{
+   struct analogix_dp_device *dp = dev_get_drvdata(dev);
+   struct edp_vsc_psr psr_vsc;
+
+   if (!dp->psr_support)
+   return -EINVAL;
+
+   /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
+   memset(_vsc, 0, sizeof(psr_vsc));
+   psr_vsc.sdp_header.HB0 = 0;
+   psr_vsc.sdp_header.HB1 = 0x7;
+   psr_vsc.sdp_header.HB2 = 0x2;
+   psr_vsc.sdp_header.HB3 = 0x8;
+
+   psr_vsc.DB0 = 0;
+   psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID;
+
+   analogix_dp_send_psr_spd(dp, _vsc);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
+
+int analogix_dp_disable_psr(struct device *dev)
+{
+   struct analogix_dp_device *dp = dev_get_drvdata(dev);
+   struct edp_vsc_psr psr_vsc;
+
+   if (!dp->psr_support)
+   return -EINVAL;
+
+   /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
+   memset(_vsc, 0, sizeof(psr_vsc));
+   psr_vsc.sdp_header.HB0 = 0;
+   psr_vsc.sdp_header.HB1 = 0x7;
+   psr_vsc.sdp_header.HB2 = 0x2;
+   psr_vsc.sdp_header.HB3 = 0x8;
+
+   psr_vsc.DB0 = 0;
+   psr_vsc.DB1 = 0;
+
+   analogix_dp_send_psr_spd(dp, _vsc);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_disable_psr);
+
+static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
+{
+   unsigned char psr_version;
+
+   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_SUPPORT, _version);
+   dev_dbg(dp->dev, "Panel PSR version : %x\n", psr_version);
+
+   return (psr_version & DP_PSR_IS_SUPPORTED) ? true : false;
+}
+
+static void analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
+{
+   unsigned char psr_en;
+
+   /* Disable psr function */
+   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, _en);
+   psr_en &= ~DP_PSR_ENABLE;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   /* Main-Link transmitter remains active during PSR active states */
+   psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   /* Enable psr function */
+   psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE |
+DP_PSR_CRC_VERIFICATION;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   analogix_dp_enable_psr_crc(dp);
+}
+
  static unsigned char analogix_dp_calc_edid_check_sum(unsigned char *edid_data)
  {
int i;
@@ -921,6 +998,10 @@ static void analogix_dp_commit(struct analogix_dp_device 
*dp)
  
  	/* Enable video */

analogix_dp_start_video(dp);
+
+   dp->psr_support = 

Re: [PATCH v4.1 3/4] drm/bridge: analogix_dp: add the PSR function support

2016-07-15 Thread Sean Paul
On Fri, Jul 15, 2016 at 06:55:17PM +0800, Yakir Yang wrote:
> The full name of PSR is Panel Self Refresh, panel device could refresh
> itself with the hardware framebuffer in panel, this would make lots of
> sense to save the power consumption.
> 
> This patch have exported two symbols for platform driver to implement
> the PSR function in hardware side:
> - analogix_dp_active_psr()
> - analogix_dp_inactive_psr()
> 
> Signed-off-by: Yakir Yang 

Reviewed-by: Sean Paul 

> ---
> Changes in v4.1:
> - Take use of existing edp_psr_vsc struct to swap HBx and DBx setting. (Sean)
> - Remove PSR_VID_CRC_FLUSH setting analogix_dp_enable_psr_crc().
> - Add comment about PBx magic numbers. (Sean)
> 
> Changes in v4:
> - Downgrade the PSR version print message to debug level. (Sean)
> - Return 'void' instead of 'int' in analogix_dp_enable_sink_psr(). (Sean)
> - Delete the unused read dpcd operations in analogix_dp_enable_sink_psr(). 
> (Sean)
> - Delete the arbitrary usleep_range in analogix_dp_enable_psr_crc. (Sean).
> - Clean up the hardcoded values in analogix_dp_send_psr_spd(). (Sean)
> - Rename "active/inactive" to "enable/disable". (Sean, Dominik)
> - Keep set the PSR_VID_CRC_FLUSH gate in analogix_dp_enable_psr_crc().
> 
> Changes in v3:
> - split analogix_dp_enable_psr(), make it more clearly
> analogix_dp_detect_sink_psr()
> analogix_dp_enable_sink_psr()
> - remove some nosie register setting comments
> 
> Changes in v2:
> - introduce in v2, splite the common Analogix DP changes out
> 
>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 81 
> ++
>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  5 ++
>  drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 51 ++
>  drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  | 34 +
>  include/drm/bridge/analogix_dp.h   |  3 +
>  5 files changed, 174 insertions(+)
> 
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 32715da..381b25e 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -97,6 +97,83 @@ static int analogix_dp_detect_hpd(struct 
> analogix_dp_device *dp)
>   return 0;
>  }
>  
> +int analogix_dp_enable_psr(struct device *dev)
> +{
> + struct analogix_dp_device *dp = dev_get_drvdata(dev);
> + struct edp_vsc_psr psr_vsc;
> +
> + if (!dp->psr_support)
> + return -EINVAL;
> +
> + /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
> + memset(_vsc, 0, sizeof(psr_vsc));
> + psr_vsc.sdp_header.HB0 = 0;
> + psr_vsc.sdp_header.HB1 = 0x7;
> + psr_vsc.sdp_header.HB2 = 0x2;
> + psr_vsc.sdp_header.HB3 = 0x8;
> +
> + psr_vsc.DB0 = 0;
> + psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID;
> +
> + analogix_dp_send_psr_spd(dp, _vsc);
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
> +
> +int analogix_dp_disable_psr(struct device *dev)
> +{
> + struct analogix_dp_device *dp = dev_get_drvdata(dev);
> + struct edp_vsc_psr psr_vsc;
> +
> + if (!dp->psr_support)
> + return -EINVAL;
> +
> + /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
> + memset(_vsc, 0, sizeof(psr_vsc));
> + psr_vsc.sdp_header.HB0 = 0;
> + psr_vsc.sdp_header.HB1 = 0x7;
> + psr_vsc.sdp_header.HB2 = 0x2;
> + psr_vsc.sdp_header.HB3 = 0x8;
> +
> + psr_vsc.DB0 = 0;
> + psr_vsc.DB1 = 0;
> +
> + analogix_dp_send_psr_spd(dp, _vsc);
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(analogix_dp_disable_psr);
> +
> +static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
> +{
> + unsigned char psr_version;
> +
> + analogix_dp_read_byte_from_dpcd(dp, DP_PSR_SUPPORT, _version);
> + dev_dbg(dp->dev, "Panel PSR version : %x\n", psr_version);
> +
> + return (psr_version & DP_PSR_IS_SUPPORTED) ? true : false;
> +}
> +
> +static void analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
> +{
> + unsigned char psr_en;
> +
> + /* Disable psr function */
> + analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, _en);
> + psr_en &= ~DP_PSR_ENABLE;
> + analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
> +
> + /* Main-Link transmitter remains active during PSR active states */
> + psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION;
> + analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
> +
> + /* Enable psr function */
> + psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE |
> +  DP_PSR_CRC_VERIFICATION;
> + analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
> +
> + analogix_dp_enable_psr_crc(dp);
> +}
> +
>  static unsigned char analogix_dp_calc_edid_check_sum(unsigned char 
> *edid_data)
>  {
>   int i;
> @@ -921,6 +998,10 @@ static void analogix_dp_commit(struct 

Re: [PATCH v4.1 3/4] drm/bridge: analogix_dp: add the PSR function support

2016-07-15 Thread Sean Paul
On Fri, Jul 15, 2016 at 06:55:17PM +0800, Yakir Yang wrote:
> The full name of PSR is Panel Self Refresh, panel device could refresh
> itself with the hardware framebuffer in panel, this would make lots of
> sense to save the power consumption.
> 
> This patch have exported two symbols for platform driver to implement
> the PSR function in hardware side:
> - analogix_dp_active_psr()
> - analogix_dp_inactive_psr()
> 
> Signed-off-by: Yakir Yang 

Reviewed-by: Sean Paul 

> ---
> Changes in v4.1:
> - Take use of existing edp_psr_vsc struct to swap HBx and DBx setting. (Sean)
> - Remove PSR_VID_CRC_FLUSH setting analogix_dp_enable_psr_crc().
> - Add comment about PBx magic numbers. (Sean)
> 
> Changes in v4:
> - Downgrade the PSR version print message to debug level. (Sean)
> - Return 'void' instead of 'int' in analogix_dp_enable_sink_psr(). (Sean)
> - Delete the unused read dpcd operations in analogix_dp_enable_sink_psr(). 
> (Sean)
> - Delete the arbitrary usleep_range in analogix_dp_enable_psr_crc. (Sean).
> - Clean up the hardcoded values in analogix_dp_send_psr_spd(). (Sean)
> - Rename "active/inactive" to "enable/disable". (Sean, Dominik)
> - Keep set the PSR_VID_CRC_FLUSH gate in analogix_dp_enable_psr_crc().
> 
> Changes in v3:
> - split analogix_dp_enable_psr(), make it more clearly
> analogix_dp_detect_sink_psr()
> analogix_dp_enable_sink_psr()
> - remove some nosie register setting comments
> 
> Changes in v2:
> - introduce in v2, splite the common Analogix DP changes out
> 
>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 81 
> ++
>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  5 ++
>  drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 51 ++
>  drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  | 34 +
>  include/drm/bridge/analogix_dp.h   |  3 +
>  5 files changed, 174 insertions(+)
> 
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 32715da..381b25e 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -97,6 +97,83 @@ static int analogix_dp_detect_hpd(struct 
> analogix_dp_device *dp)
>   return 0;
>  }
>  
> +int analogix_dp_enable_psr(struct device *dev)
> +{
> + struct analogix_dp_device *dp = dev_get_drvdata(dev);
> + struct edp_vsc_psr psr_vsc;
> +
> + if (!dp->psr_support)
> + return -EINVAL;
> +
> + /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
> + memset(_vsc, 0, sizeof(psr_vsc));
> + psr_vsc.sdp_header.HB0 = 0;
> + psr_vsc.sdp_header.HB1 = 0x7;
> + psr_vsc.sdp_header.HB2 = 0x2;
> + psr_vsc.sdp_header.HB3 = 0x8;
> +
> + psr_vsc.DB0 = 0;
> + psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID;
> +
> + analogix_dp_send_psr_spd(dp, _vsc);
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
> +
> +int analogix_dp_disable_psr(struct device *dev)
> +{
> + struct analogix_dp_device *dp = dev_get_drvdata(dev);
> + struct edp_vsc_psr psr_vsc;
> +
> + if (!dp->psr_support)
> + return -EINVAL;
> +
> + /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
> + memset(_vsc, 0, sizeof(psr_vsc));
> + psr_vsc.sdp_header.HB0 = 0;
> + psr_vsc.sdp_header.HB1 = 0x7;
> + psr_vsc.sdp_header.HB2 = 0x2;
> + psr_vsc.sdp_header.HB3 = 0x8;
> +
> + psr_vsc.DB0 = 0;
> + psr_vsc.DB1 = 0;
> +
> + analogix_dp_send_psr_spd(dp, _vsc);
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(analogix_dp_disable_psr);
> +
> +static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
> +{
> + unsigned char psr_version;
> +
> + analogix_dp_read_byte_from_dpcd(dp, DP_PSR_SUPPORT, _version);
> + dev_dbg(dp->dev, "Panel PSR version : %x\n", psr_version);
> +
> + return (psr_version & DP_PSR_IS_SUPPORTED) ? true : false;
> +}
> +
> +static void analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
> +{
> + unsigned char psr_en;
> +
> + /* Disable psr function */
> + analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, _en);
> + psr_en &= ~DP_PSR_ENABLE;
> + analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
> +
> + /* Main-Link transmitter remains active during PSR active states */
> + psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION;
> + analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
> +
> + /* Enable psr function */
> + psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE |
> +  DP_PSR_CRC_VERIFICATION;
> + analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
> +
> + analogix_dp_enable_psr_crc(dp);
> +}
> +
>  static unsigned char analogix_dp_calc_edid_check_sum(unsigned char 
> *edid_data)
>  {
>   int i;
> @@ -921,6 +998,10 @@ static void analogix_dp_commit(struct analogix_dp_device 
> *dp)
>  
>   /* Enable 

[PATCH v4.1 3/4] drm/bridge: analogix_dp: add the PSR function support

2016-07-15 Thread Yakir Yang
The full name of PSR is Panel Self Refresh, panel device could refresh
itself with the hardware framebuffer in panel, this would make lots of
sense to save the power consumption.

This patch have exported two symbols for platform driver to implement
the PSR function in hardware side:
- analogix_dp_active_psr()
- analogix_dp_inactive_psr()

Signed-off-by: Yakir Yang 
---
Changes in v4.1:
- Take use of existing edp_psr_vsc struct to swap HBx and DBx setting. (Sean)
- Remove PSR_VID_CRC_FLUSH setting analogix_dp_enable_psr_crc().
- Add comment about PBx magic numbers. (Sean)

Changes in v4:
- Downgrade the PSR version print message to debug level. (Sean)
- Return 'void' instead of 'int' in analogix_dp_enable_sink_psr(). (Sean)
- Delete the unused read dpcd operations in analogix_dp_enable_sink_psr(). 
(Sean)
- Delete the arbitrary usleep_range in analogix_dp_enable_psr_crc. (Sean).
- Clean up the hardcoded values in analogix_dp_send_psr_spd(). (Sean)
- Rename "active/inactive" to "enable/disable". (Sean, Dominik)
- Keep set the PSR_VID_CRC_FLUSH gate in analogix_dp_enable_psr_crc().

Changes in v3:
- split analogix_dp_enable_psr(), make it more clearly
analogix_dp_detect_sink_psr()
analogix_dp_enable_sink_psr()
- remove some nosie register setting comments

Changes in v2:
- introduce in v2, splite the common Analogix DP changes out

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 81 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  5 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 51 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  | 34 +
 include/drm/bridge/analogix_dp.h   |  3 +
 5 files changed, 174 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 32715da..381b25e 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -97,6 +97,83 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device 
*dp)
return 0;
 }
 
+int analogix_dp_enable_psr(struct device *dev)
+{
+   struct analogix_dp_device *dp = dev_get_drvdata(dev);
+   struct edp_vsc_psr psr_vsc;
+
+   if (!dp->psr_support)
+   return -EINVAL;
+
+   /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
+   memset(_vsc, 0, sizeof(psr_vsc));
+   psr_vsc.sdp_header.HB0 = 0;
+   psr_vsc.sdp_header.HB1 = 0x7;
+   psr_vsc.sdp_header.HB2 = 0x2;
+   psr_vsc.sdp_header.HB3 = 0x8;
+
+   psr_vsc.DB0 = 0;
+   psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID;
+
+   analogix_dp_send_psr_spd(dp, _vsc);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
+
+int analogix_dp_disable_psr(struct device *dev)
+{
+   struct analogix_dp_device *dp = dev_get_drvdata(dev);
+   struct edp_vsc_psr psr_vsc;
+
+   if (!dp->psr_support)
+   return -EINVAL;
+
+   /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
+   memset(_vsc, 0, sizeof(psr_vsc));
+   psr_vsc.sdp_header.HB0 = 0;
+   psr_vsc.sdp_header.HB1 = 0x7;
+   psr_vsc.sdp_header.HB2 = 0x2;
+   psr_vsc.sdp_header.HB3 = 0x8;
+
+   psr_vsc.DB0 = 0;
+   psr_vsc.DB1 = 0;
+
+   analogix_dp_send_psr_spd(dp, _vsc);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_disable_psr);
+
+static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
+{
+   unsigned char psr_version;
+
+   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_SUPPORT, _version);
+   dev_dbg(dp->dev, "Panel PSR version : %x\n", psr_version);
+
+   return (psr_version & DP_PSR_IS_SUPPORTED) ? true : false;
+}
+
+static void analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
+{
+   unsigned char psr_en;
+
+   /* Disable psr function */
+   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, _en);
+   psr_en &= ~DP_PSR_ENABLE;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   /* Main-Link transmitter remains active during PSR active states */
+   psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   /* Enable psr function */
+   psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE |
+DP_PSR_CRC_VERIFICATION;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   analogix_dp_enable_psr_crc(dp);
+}
+
 static unsigned char analogix_dp_calc_edid_check_sum(unsigned char *edid_data)
 {
int i;
@@ -921,6 +998,10 @@ static void analogix_dp_commit(struct analogix_dp_device 
*dp)
 
/* Enable video */
analogix_dp_start_video(dp);
+
+   dp->psr_support = analogix_dp_detect_sink_psr(dp);
+   if (dp->psr_support)
+   analogix_dp_enable_sink_psr(dp);
 }
 
 int analogix_dp_get_modes(struct drm_connector 

[PATCH v4.1 3/4] drm/bridge: analogix_dp: add the PSR function support

2016-07-15 Thread Yakir Yang
The full name of PSR is Panel Self Refresh, panel device could refresh
itself with the hardware framebuffer in panel, this would make lots of
sense to save the power consumption.

This patch have exported two symbols for platform driver to implement
the PSR function in hardware side:
- analogix_dp_active_psr()
- analogix_dp_inactive_psr()

Signed-off-by: Yakir Yang 
---
Changes in v4.1:
- Take use of existing edp_psr_vsc struct to swap HBx and DBx setting. (Sean)
- Remove PSR_VID_CRC_FLUSH setting analogix_dp_enable_psr_crc().
- Add comment about PBx magic numbers. (Sean)

Changes in v4:
- Downgrade the PSR version print message to debug level. (Sean)
- Return 'void' instead of 'int' in analogix_dp_enable_sink_psr(). (Sean)
- Delete the unused read dpcd operations in analogix_dp_enable_sink_psr(). 
(Sean)
- Delete the arbitrary usleep_range in analogix_dp_enable_psr_crc. (Sean).
- Clean up the hardcoded values in analogix_dp_send_psr_spd(). (Sean)
- Rename "active/inactive" to "enable/disable". (Sean, Dominik)
- Keep set the PSR_VID_CRC_FLUSH gate in analogix_dp_enable_psr_crc().

Changes in v3:
- split analogix_dp_enable_psr(), make it more clearly
analogix_dp_detect_sink_psr()
analogix_dp_enable_sink_psr()
- remove some nosie register setting comments

Changes in v2:
- introduce in v2, splite the common Analogix DP changes out

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 81 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  5 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 51 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  | 34 +
 include/drm/bridge/analogix_dp.h   |  3 +
 5 files changed, 174 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 32715da..381b25e 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -97,6 +97,83 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device 
*dp)
return 0;
 }
 
+int analogix_dp_enable_psr(struct device *dev)
+{
+   struct analogix_dp_device *dp = dev_get_drvdata(dev);
+   struct edp_vsc_psr psr_vsc;
+
+   if (!dp->psr_support)
+   return -EINVAL;
+
+   /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
+   memset(_vsc, 0, sizeof(psr_vsc));
+   psr_vsc.sdp_header.HB0 = 0;
+   psr_vsc.sdp_header.HB1 = 0x7;
+   psr_vsc.sdp_header.HB2 = 0x2;
+   psr_vsc.sdp_header.HB3 = 0x8;
+
+   psr_vsc.DB0 = 0;
+   psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID;
+
+   analogix_dp_send_psr_spd(dp, _vsc);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
+
+int analogix_dp_disable_psr(struct device *dev)
+{
+   struct analogix_dp_device *dp = dev_get_drvdata(dev);
+   struct edp_vsc_psr psr_vsc;
+
+   if (!dp->psr_support)
+   return -EINVAL;
+
+   /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
+   memset(_vsc, 0, sizeof(psr_vsc));
+   psr_vsc.sdp_header.HB0 = 0;
+   psr_vsc.sdp_header.HB1 = 0x7;
+   psr_vsc.sdp_header.HB2 = 0x2;
+   psr_vsc.sdp_header.HB3 = 0x8;
+
+   psr_vsc.DB0 = 0;
+   psr_vsc.DB1 = 0;
+
+   analogix_dp_send_psr_spd(dp, _vsc);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_disable_psr);
+
+static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
+{
+   unsigned char psr_version;
+
+   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_SUPPORT, _version);
+   dev_dbg(dp->dev, "Panel PSR version : %x\n", psr_version);
+
+   return (psr_version & DP_PSR_IS_SUPPORTED) ? true : false;
+}
+
+static void analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
+{
+   unsigned char psr_en;
+
+   /* Disable psr function */
+   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, _en);
+   psr_en &= ~DP_PSR_ENABLE;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   /* Main-Link transmitter remains active during PSR active states */
+   psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   /* Enable psr function */
+   psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE |
+DP_PSR_CRC_VERIFICATION;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   analogix_dp_enable_psr_crc(dp);
+}
+
 static unsigned char analogix_dp_calc_edid_check_sum(unsigned char *edid_data)
 {
int i;
@@ -921,6 +998,10 @@ static void analogix_dp_commit(struct analogix_dp_device 
*dp)
 
/* Enable video */
analogix_dp_start_video(dp);
+
+   dp->psr_support = analogix_dp_detect_sink_psr(dp);
+   if (dp->psr_support)
+   analogix_dp_enable_sink_psr(dp);
 }
 
 int analogix_dp_get_modes(struct drm_connector *connector)
diff --git