diff mbox

[5/9] drm/i915: Setup EDP PSR AUX Registers

Message ID 1359570291-2170-6-git-send-email-rodrigo.vivi@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Rodrigo Vivi Jan. 30, 2013, 6:24 p.m. UTC
From: Shobhit Kumar <shobhit.kumar@intel.com>

Signed-off-by: Shobhit Kumar <shobhit.kumar@intel.com>

v2: Created aux_clock_divider function to avoid duplicated code.
    Unfortunatelly dp_aux_ch and psr_aux_ch aren't so similar to reuse full code.

Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/i915_reg.h  | 13 ++++++
 drivers/gpu/drm/i915/intel_dp.c  | 89 +++++++++++++++++++++++++++++++---------
 drivers/gpu/drm/i915/intel_drv.h |  1 +
 3 files changed, 83 insertions(+), 20 deletions(-)

Comments

Jani Nikula Jan. 31, 2013, 10:17 a.m. UTC | #1
On Wed, 30 Jan 2013, Rodrigo Vivi <rodrigo.vivi@gmail.com> wrote:
> From: Shobhit Kumar <shobhit.kumar@intel.com>
>
> Signed-off-by: Shobhit Kumar <shobhit.kumar@intel.com>
>
> v2: Created aux_clock_divider function to avoid duplicated code.

Bikeshed, that could be a prep patch, but I won't insist on it.

Other comments below.

>     Unfortunatelly dp_aux_ch and psr_aux_ch aren't so similar to reuse full code.
>
> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
> ---
>  drivers/gpu/drm/i915/i915_reg.h  | 13 ++++++
>  drivers/gpu/drm/i915/intel_dp.c  | 89 +++++++++++++++++++++++++++++++---------
>  drivers/gpu/drm/i915/intel_drv.h |  1 +
>  3 files changed, 83 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 7bb3134..10732dc 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -1563,6 +1563,19 @@
>  #define BCLRPAT(pipe) _PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B)
>  #define VSYNCSHIFT(trans) _TRANSCODER(trans, _VSYNCSHIFT_A, _VSYNCSHIFT_B)
>  
> +#define EDP_PSR_AUX_CTL			0x64810
> +#define EDP_PSR_AUX_DATA1		0x64814
> +#define EDP_PSR_AUX_DATA2		0x64818
> +#define EDP_PSR_AUX_DATA3		0x6481c
> +#define EDP_PSR_AUX_DATA4		0x64820
> +#define EDP_PSR_AUX_DATA5		0x64824
> +#define EDP_PSR_STATUS_CTL		0x64840
> +#define   EDP_PSR_STATUS_MASK		(7<<29)
> +#define EDP_PSR_PERF_CNT		0x64844
> +#define EDP_PSR_DEBUG_CTL		0x64860
> +#define   EDP_PSR_DEBUG_MASK_MEMUP	(1<<26)
> +#define   EDP_PSR_DEBUG_MASK_HPD	(1<<25)
> +
>  /* VGA port control */
>  #define ADPA			0x61100
>  #define PCH_ADPA                0xe1100
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index aeb0ef1..fe83e05 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -364,6 +364,34 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq)
>  	return status;
>  }
>  
> +static uint32_t get_aux_clock_divider(struct intel_dp *intel_dp)
> +{
> +	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> +	struct drm_device *dev = intel_dig_port->base.base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +	/* The clock divider is based off the hrawclk,
> +	 * and would like to run at 2MHz. So, take the
> +	 * hrawclk value and divide by 2 and use that
> +	 *
> +	 * Note that PCH attached eDP panels should use a 125MHz input
> +	 * clock divider.
> +	 */
> +	if (is_cpu_edp(intel_dp)) {
> +		if (HAS_DDI(dev))
> +			return intel_ddi_get_cdclk_freq(dev_priv) >> 1;
> +		else if (IS_VALLEYVIEW(dev))
> +			return 100;
> +		else if (IS_GEN6(dev) || IS_GEN7(dev))
> +			return 200; /* SNB & IVB eDP input clock at 400Mhz */
> +		else
> +			return 225; /* eDP input clock at 450Mhz */
> +	} else if (HAS_PCH_SPLIT(dev))
> +		return DIV_ROUND_UP(intel_pch_rawclk(dev), 2);
> +	else
> +		return intel_hrawclk(dev) / 2;
> +}
> +
>  static int
>  intel_dp_aux_ch(struct intel_dp *intel_dp,
>  		uint8_t *send, int send_bytes,
> @@ -411,26 +439,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
>  	}
>  
>  	intel_dp_check_edp(intel_dp);
> -	/* The clock divider is based off the hrawclk,
> -	 * and would like to run at 2MHz. So, take the
> -	 * hrawclk value and divide by 2 and use that
> -	 *
> -	 * Note that PCH attached eDP panels should use a 125MHz input
> -	 * clock divider.
> -	 */
> -	if (is_cpu_edp(intel_dp)) {
> -		if (HAS_DDI(dev))
> -			aux_clock_divider = intel_ddi_get_cdclk_freq(dev_priv) >> 1;
> -		else if (IS_VALLEYVIEW(dev))
> -			aux_clock_divider = 100;
> -		else if (IS_GEN6(dev) || IS_GEN7(dev))
> -			aux_clock_divider = 200; /* SNB & IVB eDP input clock at 400Mhz */
> -		else
> -			aux_clock_divider = 225; /* eDP input clock at 450Mhz */
> -	} else if (HAS_PCH_SPLIT(dev))
> -		aux_clock_divider = DIV_ROUND_UP(intel_pch_rawclk(dev), 2);
> -	else
> -		aux_clock_divider = intel_hrawclk(dev) / 2;
> +	aux_clock_divider = get_aux_clock_divider(intel_dp);
>  
>  	if (IS_GEN6(dev))
>  		precharge = 3;
> @@ -1440,6 +1449,46 @@ static bool is_edp_psr(struct intel_dp *intel_dp)
>  	return (is_edp(intel_dp) && (intel_dp->psr_dpcd[0] & 0x1));
>  }
>  
> +static void intel_edp_psr_setup(struct intel_dp *intel_dp)
> +{
> +	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	uint32_t aux_clock_divider;
> +	int precharge = 0x3;
> +	int msg_size = 5;	/* Header(4) + Message(1) */
> +
> +	/* No need to setup if already done as these setting are persistent
> +	 * until power states are entered */

I find "no need to setup" a not good enough reason to not do it every
time. However, the specs say you're not supposed to fiddle with the aux
regs while PSR is enabled, which *is* a good reason. So maybe update the
comment, so we'll know what we're doing if we decide to change this in
the future?

> +	if (intel_dp->psr_setup)
> +		return;
> +
> +	/* Setup AUX registers */
> +	/* Write command on DPCD 0x0600 */
> +	I915_WRITE(EDP_PSR_AUX_DATA1, 0x80060000);
> +
> +	/* Set the state to normal operation D0 in DPCD 0x0600 */
> +	I915_WRITE(EDP_PSR_AUX_DATA2, 0x01000000);

I really really don't like just slamming magic 32-bit values into
registers. Copy-pasting from intel_dp_aux_native_write() and
intel_dp_aux_ch(), you could do something like this here to clarify a
bit:

	uint16_t address = DP_SET_POWER;
	uint8_t msg[] = {
		AUX_NATIVE_WRITE << 4,
		address >> 8,
		address & 0xff,
		0, /* len - 1 */
		DP_SET_POWER_D0,
	};

	for (i = 0; i < sizeof(msg); i += 4)
		I915_WRITE(EDP_PSR_AUX_DATA1 + i,
			   pack_aux(msg + i, sizeof(msg) - i));

The above could be cleaned up too, maybe there's common bits to be found
with the regular aux write stuff etc. But IMHO with that it's already
much easier to figure out, without looking at the specs, what's going
on, and you can (almost?) ditch the comments too.

BR,
Jani.


> +
> +	aux_clock_divider = get_aux_clock_divider(intel_dp);
> +
> +	I915_WRITE(EDP_PSR_AUX_CTL,
> +		   DP_AUX_CH_CTL_TIME_OUT_400us |
> +		   (msg_size << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
> +		   (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
> +		   (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT));
> +
> +	/* Setup the debug register */
> +	I915_WRITE(EDP_PSR_DEBUG_CTL, I915_READ(EDP_PSR_DEBUG_CTL) |
> +			EDP_PSR_DEBUG_MASK_MEMUP |
> +			EDP_PSR_DEBUG_MASK_HPD);
> +
> +	/* This flag can be made to 0 from pm code so as to reinitialize the
> +	 * AUX register in case of power states, returning from which will not
> +	 * maintain the AUX register settings
> +	 */
> +	intel_dp->psr_setup = 1;
> +}
> +
>  static void intel_enable_dp(struct intel_encoder *encoder)
>  {
>  	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index d4b3bac..3fa2dd0 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -383,6 +383,7 @@ struct intel_dp {
>  	int backlight_on_delay;
>  	int backlight_off_delay;
>  	struct delayed_work panel_vdd_work;
> +	uint8_t psr_setup;
>  	bool want_panel_vdd;
>  	struct intel_connector *attached_connector;
>  };
> -- 
> 1.7.11.7
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
Paulo Zanoni Jan. 31, 2013, 9:35 p.m. UTC | #2
Hi

In addition to Jani's comments:

2013/1/30 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
> From: Shobhit Kumar <shobhit.kumar@intel.com>
>
> Signed-off-by: Shobhit Kumar <shobhit.kumar@intel.com>
>
> v2: Created aux_clock_divider function to avoid duplicated code.
>     Unfortunatelly dp_aux_ch and psr_aux_ch aren't so similar to reuse full code.
>

DDI A AUX channel transactions must not be sent while SRD is enabled.
SRD must be completely disabled before DDI A AUX channel transaction
can be sent. So I think we should put a big WARN_ON inside
intel_dp_aux_ch checking for this restriction. This WARN could maybe
go in a separate patch.

SRD AUX channel transactions must not be sent while DDI A AUX is being
used. This patch may also include a big WARN on the newly-added
function.

More below:

> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
> ---
>  drivers/gpu/drm/i915/i915_reg.h  | 13 ++++++
>  drivers/gpu/drm/i915/intel_dp.c  | 89 +++++++++++++++++++++++++++++++---------
>  drivers/gpu/drm/i915/intel_drv.h |  1 +
>  3 files changed, 83 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 7bb3134..10732dc 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -1563,6 +1563,19 @@
>  #define BCLRPAT(pipe) _PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B)
>  #define VSYNCSHIFT(trans) _TRANSCODER(trans, _VSYNCSHIFT_A, _VSYNCSHIFT_B)
>
> +#define EDP_PSR_AUX_CTL                        0x64810
> +#define EDP_PSR_AUX_DATA1              0x64814
> +#define EDP_PSR_AUX_DATA2              0x64818
> +#define EDP_PSR_AUX_DATA3              0x6481c
> +#define EDP_PSR_AUX_DATA4              0x64820
> +#define EDP_PSR_AUX_DATA5              0x64824
> +#define EDP_PSR_STATUS_CTL             0x64840
> +#define   EDP_PSR_STATUS_MASK          (7<<29)
> +#define EDP_PSR_PERF_CNT               0x64844
> +#define EDP_PSR_DEBUG_CTL              0x64860
> +#define   EDP_PSR_DEBUG_MASK_MEMUP     (1<<26)
> +#define   EDP_PSR_DEBUG_MASK_HPD       (1<<25)
> +
>  /* VGA port control */
>  #define ADPA                   0x61100
>  #define PCH_ADPA                0xe1100
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index aeb0ef1..fe83e05 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -364,6 +364,34 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq)
>         return status;
>  }
>
> +static uint32_t get_aux_clock_divider(struct intel_dp *intel_dp)
> +{
> +       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> +       struct drm_device *dev = intel_dig_port->base.base.dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +       /* The clock divider is based off the hrawclk,
> +        * and would like to run at 2MHz. So, take the
> +        * hrawclk value and divide by 2 and use that
> +        *
> +        * Note that PCH attached eDP panels should use a 125MHz input
> +        * clock divider.
> +        */
> +       if (is_cpu_edp(intel_dp)) {
> +               if (HAS_DDI(dev))
> +                       return intel_ddi_get_cdclk_freq(dev_priv) >> 1;
> +               else if (IS_VALLEYVIEW(dev))
> +                       return 100;
> +               else if (IS_GEN6(dev) || IS_GEN7(dev))
> +                       return 200; /* SNB & IVB eDP input clock at 400Mhz */
> +               else
> +                       return 225; /* eDP input clock at 450Mhz */
> +       } else if (HAS_PCH_SPLIT(dev))
> +               return DIV_ROUND_UP(intel_pch_rawclk(dev), 2);
> +       else
> +               return intel_hrawclk(dev) / 2;
> +}
> +
>  static int
>  intel_dp_aux_ch(struct intel_dp *intel_dp,
>                 uint8_t *send, int send_bytes,
> @@ -411,26 +439,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
>         }
>
>         intel_dp_check_edp(intel_dp);
> -       /* The clock divider is based off the hrawclk,
> -        * and would like to run at 2MHz. So, take the
> -        * hrawclk value and divide by 2 and use that
> -        *
> -        * Note that PCH attached eDP panels should use a 125MHz input
> -        * clock divider.
> -        */
> -       if (is_cpu_edp(intel_dp)) {
> -               if (HAS_DDI(dev))
> -                       aux_clock_divider = intel_ddi_get_cdclk_freq(dev_priv) >> 1;
> -               else if (IS_VALLEYVIEW(dev))
> -                       aux_clock_divider = 100;
> -               else if (IS_GEN6(dev) || IS_GEN7(dev))
> -                       aux_clock_divider = 200; /* SNB & IVB eDP input clock at 400Mhz */
> -               else
> -                       aux_clock_divider = 225; /* eDP input clock at 450Mhz */
> -       } else if (HAS_PCH_SPLIT(dev))
> -               aux_clock_divider = DIV_ROUND_UP(intel_pch_rawclk(dev), 2);
> -       else
> -               aux_clock_divider = intel_hrawclk(dev) / 2;
> +       aux_clock_divider = get_aux_clock_divider(intel_dp);
>
>         if (IS_GEN6(dev))
>                 precharge = 3;
> @@ -1440,6 +1449,46 @@ static bool is_edp_psr(struct intel_dp *intel_dp)
>         return (is_edp(intel_dp) && (intel_dp->psr_dpcd[0] & 0x1));
>  }
>
> +static void intel_edp_psr_setup(struct intel_dp *intel_dp)
> +{
> +       struct drm_device *dev = intel_dp_to_dev(intel_dp);
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       uint32_t aux_clock_divider;
> +       int precharge = 0x3;
> +       int msg_size = 5;       /* Header(4) + Message(1) */
> +
> +       /* No need to setup if already done as these setting are persistent
> +        * until power states are entered */
> +       if (intel_dp->psr_setup)
> +               return;
> +
> +       /* Setup AUX registers */
> +       /* Write command on DPCD 0x0600 */
> +       I915_WRITE(EDP_PSR_AUX_DATA1, 0x80060000);
> +
> +       /* Set the state to normal operation D0 in DPCD 0x0600 */
> +       I915_WRITE(EDP_PSR_AUX_DATA2, 0x01000000);
> +
> +       aux_clock_divider = get_aux_clock_divider(intel_dp);
> +
> +       I915_WRITE(EDP_PSR_AUX_CTL,
> +                  DP_AUX_CH_CTL_TIME_OUT_400us |
> +                  (msg_size << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
> +                  (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
> +                  (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT));

On DP_AUX_CH the message "goes" after we write 1 to bit 31. And then
we wait for the "done" bit. How does it work here?

Also, on DP_AUX_CH we try at least 5 times. Shouldn't we do this here too?

> +
> +       /* Setup the debug register */
> +       I915_WRITE(EDP_PSR_DEBUG_CTL, I915_READ(EDP_PSR_DEBUG_CTL) |
> +                       EDP_PSR_DEBUG_MASK_MEMUP |
> +                       EDP_PSR_DEBUG_MASK_HPD);

Why?

> +
> +       /* This flag can be made to 0 from pm code so as to reinitialize the
> +        * AUX register in case of power states, returning from which will not
> +        * maintain the AUX register settings
> +        */
> +       intel_dp->psr_setup = 1;
> +}
> +
>  static void intel_enable_dp(struct intel_encoder *encoder)
>  {
>         struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index d4b3bac..3fa2dd0 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -383,6 +383,7 @@ struct intel_dp {
>         int backlight_on_delay;
>         int backlight_off_delay;
>         struct delayed_work panel_vdd_work;
> +       uint8_t psr_setup;

bool psr_setup_done ?

>         bool want_panel_vdd;
>         struct intel_connector *attached_connector;
>  };
> --
> 1.7.11.7
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 7bb3134..10732dc 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1563,6 +1563,19 @@ 
 #define BCLRPAT(pipe) _PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B)
 #define VSYNCSHIFT(trans) _TRANSCODER(trans, _VSYNCSHIFT_A, _VSYNCSHIFT_B)
 
+#define EDP_PSR_AUX_CTL			0x64810
+#define EDP_PSR_AUX_DATA1		0x64814
+#define EDP_PSR_AUX_DATA2		0x64818
+#define EDP_PSR_AUX_DATA3		0x6481c
+#define EDP_PSR_AUX_DATA4		0x64820
+#define EDP_PSR_AUX_DATA5		0x64824
+#define EDP_PSR_STATUS_CTL		0x64840
+#define   EDP_PSR_STATUS_MASK		(7<<29)
+#define EDP_PSR_PERF_CNT		0x64844
+#define EDP_PSR_DEBUG_CTL		0x64860
+#define   EDP_PSR_DEBUG_MASK_MEMUP	(1<<26)
+#define   EDP_PSR_DEBUG_MASK_HPD	(1<<25)
+
 /* VGA port control */
 #define ADPA			0x61100
 #define PCH_ADPA                0xe1100
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index aeb0ef1..fe83e05 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -364,6 +364,34 @@  intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq)
 	return status;
 }
 
+static uint32_t get_aux_clock_divider(struct intel_dp *intel_dp)
+{
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = intel_dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	/* The clock divider is based off the hrawclk,
+	 * and would like to run at 2MHz. So, take the
+	 * hrawclk value and divide by 2 and use that
+	 *
+	 * Note that PCH attached eDP panels should use a 125MHz input
+	 * clock divider.
+	 */
+	if (is_cpu_edp(intel_dp)) {
+		if (HAS_DDI(dev))
+			return intel_ddi_get_cdclk_freq(dev_priv) >> 1;
+		else if (IS_VALLEYVIEW(dev))
+			return 100;
+		else if (IS_GEN6(dev) || IS_GEN7(dev))
+			return 200; /* SNB & IVB eDP input clock at 400Mhz */
+		else
+			return 225; /* eDP input clock at 450Mhz */
+	} else if (HAS_PCH_SPLIT(dev))
+		return DIV_ROUND_UP(intel_pch_rawclk(dev), 2);
+	else
+		return intel_hrawclk(dev) / 2;
+}
+
 static int
 intel_dp_aux_ch(struct intel_dp *intel_dp,
 		uint8_t *send, int send_bytes,
@@ -411,26 +439,7 @@  intel_dp_aux_ch(struct intel_dp *intel_dp,
 	}
 
 	intel_dp_check_edp(intel_dp);
-	/* The clock divider is based off the hrawclk,
-	 * and would like to run at 2MHz. So, take the
-	 * hrawclk value and divide by 2 and use that
-	 *
-	 * Note that PCH attached eDP panels should use a 125MHz input
-	 * clock divider.
-	 */
-	if (is_cpu_edp(intel_dp)) {
-		if (HAS_DDI(dev))
-			aux_clock_divider = intel_ddi_get_cdclk_freq(dev_priv) >> 1;
-		else if (IS_VALLEYVIEW(dev))
-			aux_clock_divider = 100;
-		else if (IS_GEN6(dev) || IS_GEN7(dev))
-			aux_clock_divider = 200; /* SNB & IVB eDP input clock at 400Mhz */
-		else
-			aux_clock_divider = 225; /* eDP input clock at 450Mhz */
-	} else if (HAS_PCH_SPLIT(dev))
-		aux_clock_divider = DIV_ROUND_UP(intel_pch_rawclk(dev), 2);
-	else
-		aux_clock_divider = intel_hrawclk(dev) / 2;
+	aux_clock_divider = get_aux_clock_divider(intel_dp);
 
 	if (IS_GEN6(dev))
 		precharge = 3;
@@ -1440,6 +1449,46 @@  static bool is_edp_psr(struct intel_dp *intel_dp)
 	return (is_edp(intel_dp) && (intel_dp->psr_dpcd[0] & 0x1));
 }
 
+static void intel_edp_psr_setup(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t aux_clock_divider;
+	int precharge = 0x3;
+	int msg_size = 5;	/* Header(4) + Message(1) */
+
+	/* No need to setup if already done as these setting are persistent
+	 * until power states are entered */
+	if (intel_dp->psr_setup)
+		return;
+
+	/* Setup AUX registers */
+	/* Write command on DPCD 0x0600 */
+	I915_WRITE(EDP_PSR_AUX_DATA1, 0x80060000);
+
+	/* Set the state to normal operation D0 in DPCD 0x0600 */
+	I915_WRITE(EDP_PSR_AUX_DATA2, 0x01000000);
+
+	aux_clock_divider = get_aux_clock_divider(intel_dp);
+
+	I915_WRITE(EDP_PSR_AUX_CTL,
+		   DP_AUX_CH_CTL_TIME_OUT_400us |
+		   (msg_size << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
+		   (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
+		   (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT));
+
+	/* Setup the debug register */
+	I915_WRITE(EDP_PSR_DEBUG_CTL, I915_READ(EDP_PSR_DEBUG_CTL) |
+			EDP_PSR_DEBUG_MASK_MEMUP |
+			EDP_PSR_DEBUG_MASK_HPD);
+
+	/* This flag can be made to 0 from pm code so as to reinitialize the
+	 * AUX register in case of power states, returning from which will not
+	 * maintain the AUX register settings
+	 */
+	intel_dp->psr_setup = 1;
+}
+
 static void intel_enable_dp(struct intel_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d4b3bac..3fa2dd0 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -383,6 +383,7 @@  struct intel_dp {
 	int backlight_on_delay;
 	int backlight_off_delay;
 	struct delayed_work panel_vdd_work;
+	uint8_t psr_setup;
 	bool want_panel_vdd;
 	struct intel_connector *attached_connector;
 };