Commit aae8ba84 authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915: Make sure pipe interrupts are processed before turning off power well on BDW+

Starting from BDW the DE_PIPE interrupts for pipe B and C belong to the
relevant display power well. So we should make sure we've finished
processing them before turning off the power well.

The pipe interrupts shouldn't really happen at this point anymore since
we've already shut down the planes/pipes/whatnot, but being a bit
paranoid shouldn't hurt.
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1455907651-16397-1-git-send-email-ville.syrjala@linux.intel.comReviewed-by: default avatarImre Deak <imre.deak@intel.com>
parent 2230fde8
...@@ -3366,6 +3366,22 @@ void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, ...@@ -3366,6 +3366,22 @@ void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv,
spin_unlock_irq(&dev_priv->irq_lock); spin_unlock_irq(&dev_priv->irq_lock);
} }
void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv,
unsigned int pipe_mask)
{
spin_lock_irq(&dev_priv->irq_lock);
if (pipe_mask & 1 << PIPE_A)
GEN8_IRQ_RESET_NDX(DE_PIPE, PIPE_A);
if (pipe_mask & 1 << PIPE_B)
GEN8_IRQ_RESET_NDX(DE_PIPE, PIPE_B);
if (pipe_mask & 1 << PIPE_C)
GEN8_IRQ_RESET_NDX(DE_PIPE, PIPE_C);
spin_unlock_irq(&dev_priv->irq_lock);
/* make sure we're done processing display irqs */
synchronize_irq(dev_priv->dev->irq);
}
static void cherryview_irq_preinstall(struct drm_device *dev) static void cherryview_irq_preinstall(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
......
...@@ -993,6 +993,8 @@ static inline bool intel_irqs_enabled(struct drm_i915_private *dev_priv) ...@@ -993,6 +993,8 @@ static inline bool intel_irqs_enabled(struct drm_i915_private *dev_priv)
int intel_get_crtc_scanline(struct intel_crtc *crtc); int intel_get_crtc_scanline(struct intel_crtc *crtc);
void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv,
unsigned int pipe_mask); unsigned int pipe_mask);
void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv,
unsigned int pipe_mask);
/* intel_crt.c */ /* intel_crt.c */
void intel_crt_init(struct drm_device *dev); void intel_crt_init(struct drm_device *dev);
......
...@@ -284,6 +284,13 @@ static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv) ...@@ -284,6 +284,13 @@ static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)
1 << PIPE_C | 1 << PIPE_B); 1 << PIPE_C | 1 << PIPE_B);
} }
static void hsw_power_well_pre_disable(struct drm_i915_private *dev_priv)
{
if (IS_BROADWELL(dev_priv))
gen8_irq_power_well_pre_disable(dev_priv,
1 << PIPE_C | 1 << PIPE_B);
}
static void skl_power_well_post_enable(struct drm_i915_private *dev_priv, static void skl_power_well_post_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well) struct i915_power_well *power_well)
{ {
...@@ -309,6 +316,14 @@ static void skl_power_well_post_enable(struct drm_i915_private *dev_priv, ...@@ -309,6 +316,14 @@ static void skl_power_well_post_enable(struct drm_i915_private *dev_priv,
} }
} }
static void skl_power_well_pre_disable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
if (power_well->data == SKL_DISP_PW_2)
gen8_irq_power_well_pre_disable(dev_priv,
1 << PIPE_C | 1 << PIPE_B);
}
static void hsw_set_power_well(struct drm_i915_private *dev_priv, static void hsw_set_power_well(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well, bool enable) struct i915_power_well *power_well, bool enable)
{ {
...@@ -334,6 +349,7 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv, ...@@ -334,6 +349,7 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
} else { } else {
if (enable_requested) { if (enable_requested) {
hsw_power_well_pre_disable(dev_priv);
I915_WRITE(HSW_PWR_WELL_DRIVER, 0); I915_WRITE(HSW_PWR_WELL_DRIVER, 0);
POSTING_READ(HSW_PWR_WELL_DRIVER); POSTING_READ(HSW_PWR_WELL_DRIVER);
DRM_DEBUG_KMS("Requesting to disable the power well\n"); DRM_DEBUG_KMS("Requesting to disable the power well\n");
...@@ -709,6 +725,9 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv, ...@@ -709,6 +725,9 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
state_mask = SKL_POWER_WELL_STATE(power_well->data); state_mask = SKL_POWER_WELL_STATE(power_well->data);
is_enabled = tmp & state_mask; is_enabled = tmp & state_mask;
if (!enable && enable_requested)
skl_power_well_pre_disable(dev_priv, power_well);
if (enable) { if (enable) {
if (!enable_requested) { if (!enable_requested) {
WARN((tmp & state_mask) && WARN((tmp & state_mask) &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment