Re: [Intel-gfx] [RFC PATCH 3/3] drm/i915: add support for per-pipe power sequencing on vlv

2013-09-05 Thread Ville Syrjälä
On Tue, Sep 03, 2013 at 02:43:39PM +0300, Jani Nikula wrote:
> VLV has per-pipe PP registers. Set up power sequencing on mode set. The
> connector init time setup is problematic, since we don't have a pipe at
> that time. Cook up something.
> 
> Signed-off-by: Jani Nikula 
> ---
>  drivers/gpu/drm/i915/intel_dp.c |  139 
> +++
>  1 file changed, 97 insertions(+), 42 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 0ba72f1..95d67fc 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -237,24 +237,47 @@ intel_hrawclk(struct drm_device *dev)
>   }
>  }
>  
> +static void
> +intel_dp_init_panel_power_sequencer(struct drm_device *dev,
> + struct intel_dp *intel_dp,
> + struct edp_power_seq *out);
> +static void
> +intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
> + struct intel_dp *intel_dp,
> + struct edp_power_seq *out);
> +
> +static u32 _pp_ctrl_reg(struct intel_dp *intel_dp)
> +{
> + struct drm_device *dev = intel_dp_to_dev(intel_dp);
> + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> + int pipe = to_intel_crtc(intel_dig_port->base.base.crtc)->pipe;
> +
> + return HAS_PCH_SPLIT(dev) ? PCH_PP_CONTROL : VLV_PIPE_PP_CONTROL(pipe);
> +}
> +
> +static u32 _pp_stat_reg(struct intel_dp *intel_dp)
> +{
> + struct drm_device *dev = intel_dp_to_dev(intel_dp);
> + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> + int pipe = to_intel_crtc(intel_dig_port->base.base.crtc)->pipe;
> +
> + return HAS_PCH_SPLIT(dev) ? PCH_PP_STATUS : VLV_PIPE_PP_STATUS(pipe);
> +}
> +
>  static bool ironlake_edp_have_panel_power(struct intel_dp *intel_dp)
>  {
>   struct drm_device *dev = intel_dp_to_dev(intel_dp);
>   struct drm_i915_private *dev_priv = dev->dev_private;
> - u32 pp_stat_reg;
>  
> - pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
> - return (I915_READ(pp_stat_reg) & PP_ON) != 0;
> + return (I915_READ(_pp_stat_reg(intel_dp)) & PP_ON) != 0;
>  }
>  
>  static bool ironlake_edp_have_panel_vdd(struct intel_dp *intel_dp)
>  {
>   struct drm_device *dev = intel_dp_to_dev(intel_dp);
>   struct drm_i915_private *dev_priv = dev->dev_private;
> - u32 pp_ctrl_reg;
>  
> - pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
> - return (I915_READ(pp_ctrl_reg) & EDP_FORCE_VDD) != 0;
> + return (I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD) != 0;
>  }
>  
>  static void
> @@ -262,19 +285,15 @@ intel_dp_check_edp(struct intel_dp *intel_dp)
>  {
>   struct drm_device *dev = intel_dp_to_dev(intel_dp);
>   struct drm_i915_private *dev_priv = dev->dev_private;
> - u32 pp_stat_reg, pp_ctrl_reg;
>  
>   if (!is_edp(intel_dp))
>   return;
>  
> - pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
> - pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
> -
>   if (!ironlake_edp_have_panel_power(intel_dp) && 
> !ironlake_edp_have_panel_vdd(intel_dp)) {
>   WARN(1, "eDP powered off while attempting aux channel 
> communication.\n");
>   DRM_DEBUG_KMS("Status 0x%08x Control 0x%08x\n",
> - I915_READ(pp_stat_reg),
> - I915_READ(pp_ctrl_reg));
> +   I915_READ(_pp_stat_reg(intel_dp)),
> +   I915_READ(_pp_ctrl_reg(intel_dp)));
>   }
>  }
>  
> @@ -948,8 +967,8 @@ static void ironlake_wait_panel_status(struct intel_dp 
> *intel_dp,
>   struct drm_i915_private *dev_priv = dev->dev_private;
>   u32 pp_stat_reg, pp_ctrl_reg;
>  
> - pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
> - pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
> + pp_stat_reg = _pp_stat_reg(intel_dp);
> + pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
>  
>   DRM_DEBUG_KMS("mask %08x value %08x status %08x control %08x\n",
>   mask, value,
> @@ -991,11 +1010,8 @@ static  u32 ironlake_get_pp_control(struct intel_dp 
> *intel_dp)
>   struct drm_device *dev = intel_dp_to_dev(intel_dp);
>   struct drm_i915_private *dev_priv = dev->dev_private;
>   u32 control;
> - u32 pp_ctrl_reg;
> -
> - pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
> - control = I915_READ(pp_ctrl_reg);
>  
> + control = I915_READ(_pp_ctrl_reg(intel_dp));
>   control &= ~PANEL_UNLOCK_MASK;
>   control |= PANEL_UNLOCK_REGS;
>   return control;
> @@ -1028,8 +1044,8 @@ void ironlake_edp_panel_vdd_on(struct intel_dp 
> *intel_dp)
>   pp = ironlake_get_pp_control(intel_dp);
>   pp |= EDP_FORCE_VDD;
>  
> - pp_stat_reg = IS_

[Intel-gfx] [RFC PATCH 3/3] drm/i915: add support for per-pipe power sequencing on vlv

2013-09-03 Thread Jani Nikula
VLV has per-pipe PP registers. Set up power sequencing on mode set. The
connector init time setup is problematic, since we don't have a pipe at
that time. Cook up something.

Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/i915/intel_dp.c |  139 +++
 1 file changed, 97 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 0ba72f1..95d67fc 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -237,24 +237,47 @@ intel_hrawclk(struct drm_device *dev)
}
 }
 
+static void
+intel_dp_init_panel_power_sequencer(struct drm_device *dev,
+   struct intel_dp *intel_dp,
+   struct edp_power_seq *out);
+static void
+intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
+   struct intel_dp *intel_dp,
+   struct edp_power_seq *out);
+
+static u32 _pp_ctrl_reg(struct intel_dp *intel_dp)
+{
+   struct drm_device *dev = intel_dp_to_dev(intel_dp);
+   struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+   int pipe = to_intel_crtc(intel_dig_port->base.base.crtc)->pipe;
+
+   return HAS_PCH_SPLIT(dev) ? PCH_PP_CONTROL : VLV_PIPE_PP_CONTROL(pipe);
+}
+
+static u32 _pp_stat_reg(struct intel_dp *intel_dp)
+{
+   struct drm_device *dev = intel_dp_to_dev(intel_dp);
+   struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+   int pipe = to_intel_crtc(intel_dig_port->base.base.crtc)->pipe;
+
+   return HAS_PCH_SPLIT(dev) ? PCH_PP_STATUS : VLV_PIPE_PP_STATUS(pipe);
+}
+
 static bool ironlake_edp_have_panel_power(struct intel_dp *intel_dp)
 {
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct drm_i915_private *dev_priv = dev->dev_private;
-   u32 pp_stat_reg;
 
-   pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
-   return (I915_READ(pp_stat_reg) & PP_ON) != 0;
+   return (I915_READ(_pp_stat_reg(intel_dp)) & PP_ON) != 0;
 }
 
 static bool ironlake_edp_have_panel_vdd(struct intel_dp *intel_dp)
 {
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct drm_i915_private *dev_priv = dev->dev_private;
-   u32 pp_ctrl_reg;
 
-   pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
-   return (I915_READ(pp_ctrl_reg) & EDP_FORCE_VDD) != 0;
+   return (I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD) != 0;
 }
 
 static void
@@ -262,19 +285,15 @@ intel_dp_check_edp(struct intel_dp *intel_dp)
 {
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct drm_i915_private *dev_priv = dev->dev_private;
-   u32 pp_stat_reg, pp_ctrl_reg;
 
if (!is_edp(intel_dp))
return;
 
-   pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
-   pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
-
if (!ironlake_edp_have_panel_power(intel_dp) && 
!ironlake_edp_have_panel_vdd(intel_dp)) {
WARN(1, "eDP powered off while attempting aux channel 
communication.\n");
DRM_DEBUG_KMS("Status 0x%08x Control 0x%08x\n",
-   I915_READ(pp_stat_reg),
-   I915_READ(pp_ctrl_reg));
+ I915_READ(_pp_stat_reg(intel_dp)),
+ I915_READ(_pp_ctrl_reg(intel_dp)));
}
 }
 
@@ -948,8 +967,8 @@ static void ironlake_wait_panel_status(struct intel_dp 
*intel_dp,
struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp_stat_reg, pp_ctrl_reg;
 
-   pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
-   pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+   pp_stat_reg = _pp_stat_reg(intel_dp);
+   pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
 
DRM_DEBUG_KMS("mask %08x value %08x status %08x control %08x\n",
mask, value,
@@ -991,11 +1010,8 @@ static  u32 ironlake_get_pp_control(struct intel_dp 
*intel_dp)
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct drm_i915_private *dev_priv = dev->dev_private;
u32 control;
-   u32 pp_ctrl_reg;
-
-   pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
-   control = I915_READ(pp_ctrl_reg);
 
+   control = I915_READ(_pp_ctrl_reg(intel_dp));
control &= ~PANEL_UNLOCK_MASK;
control |= PANEL_UNLOCK_REGS;
return control;
@@ -1028,8 +1044,8 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
pp = ironlake_get_pp_control(intel_dp);
pp |= EDP_FORCE_VDD;
 
-   pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
-   pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+   pp_stat_reg = _pp_stat_reg(intel_dp);
+   pp_ctr