diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dp.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1aac59e83bf..5dde80f9e65 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -717,6 +717,51 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, } } +static void ironlake_edp_panel_on (struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long timeout = jiffies + msecs_to_jiffies(5000); + u32 pp, pp_status; + + pp_status = I915_READ(PCH_PP_STATUS); + if (pp_status & PP_ON) + return; + + pp = I915_READ(PCH_PP_CONTROL); + pp |= PANEL_UNLOCK_REGS | POWER_TARGET_ON; + I915_WRITE(PCH_PP_CONTROL, pp); + do { + pp_status = I915_READ(PCH_PP_STATUS); + } while (((pp_status & PP_ON) == 0) && !time_after(jiffies, timeout)); + + if (time_after(jiffies, timeout)) + DRM_DEBUG_KMS("panel on wait timed out: 0x%08x\n", pp_status); + + pp &= ~(PANEL_UNLOCK_REGS | EDP_FORCE_VDD); + I915_WRITE(PCH_PP_CONTROL, pp); +} + +static void ironlake_edp_panel_off (struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long timeout = jiffies + msecs_to_jiffies(5000); + u32 pp, pp_status; + + pp = I915_READ(PCH_PP_CONTROL); + pp &= ~POWER_TARGET_ON; + I915_WRITE(PCH_PP_CONTROL, pp); + do { + pp_status = I915_READ(PCH_PP_STATUS); + } while ((pp_status & PP_ON) && !time_after(jiffies, timeout)); + + if (time_after(jiffies, timeout)) + DRM_DEBUG_KMS("panel off wait timed out\n"); + + /* Make sure VDD is enabled so DP AUX will work */ + pp |= EDP_FORCE_VDD; + I915_WRITE(PCH_PP_CONTROL, pp); +} + static void ironlake_edp_backlight_on (struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -751,14 +796,18 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) if (mode != DRM_MODE_DPMS_ON) { if (dp_reg & DP_PORT_EN) { intel_dp_link_down(intel_encoder, dp_priv->DP); - if (IS_eDP(intel_encoder)) + if (IS_eDP(intel_encoder)) { ironlake_edp_backlight_off(dev); + ironlake_edp_panel_off(dev); + } } } else { if (!(dp_reg & DP_PORT_EN)) { intel_dp_link_train(intel_encoder, dp_priv->DP, dp_priv->link_configuration); - if (IS_eDP(intel_encoder)) + if (IS_eDP(intel_encoder)) { + ironlake_edp_panel_on(dev); ironlake_edp_backlight_on(dev); + } } } dp_priv->dpms_mode = mode; |