aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2010-07-22 16:18:19 -0400
committerEric Anholt <eric@anholt.net>2010-07-26 14:27:04 -0400
commit9934c132989d5c488d2e15188220ce240960ce96 (patch)
treed8ffde80fb3ac3ef19cdd671df1ec6741a95f7c4 /drivers
parent4a655f043160eeae447efd3be297b6b4c397a640 (diff)
drm/i915: make sure eDP panel is turned on
When enabling the eDP port, we need to make sure the panel is turned on after training the link. If we don't, it likely won't come back after suspend or may not come up at all. For unknown reasons, unlocking the panel regs before initiating a power on sequence is necessary. There are known bugs in the PCH panel sequencing logic, apparently this is one possible workaround. Fixes https://bugs.freedesktop.org/show_bug.cgi?id=28739. Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Tested-by: "Paulo J. S. Silva" <pjssilva@gmail.com> Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c53
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 1aac59e83bff..5d4266115311 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,
717 } 717 }
718} 718}
719 719
720static void ironlake_edp_panel_on (struct drm_device *dev)
721{
722 struct drm_i915_private *dev_priv = dev->dev_private;
723 unsigned long timeout = jiffies + msecs_to_jiffies(5000);
724 u32 pp, pp_status;
725
726 pp_status = I915_READ(PCH_PP_STATUS);
727 if (pp_status & PP_ON)
728 return;
729
730 pp = I915_READ(PCH_PP_CONTROL);
731 pp |= PANEL_UNLOCK_REGS | POWER_TARGET_ON;
732 I915_WRITE(PCH_PP_CONTROL, pp);
733 do {
734 pp_status = I915_READ(PCH_PP_STATUS);
735 } while (((pp_status & PP_ON) == 0) && !time_after(jiffies, timeout));
736
737 if (time_after(jiffies, timeout))
738 DRM_DEBUG_KMS("panel on wait timed out: 0x%08x\n", pp_status);
739
740 pp &= ~(PANEL_UNLOCK_REGS | EDP_FORCE_VDD);
741 I915_WRITE(PCH_PP_CONTROL, pp);
742}
743
744static void ironlake_edp_panel_off (struct drm_device *dev)
745{
746 struct drm_i915_private *dev_priv = dev->dev_private;
747 unsigned long timeout = jiffies + msecs_to_jiffies(5000);
748 u32 pp, pp_status;
749
750 pp = I915_READ(PCH_PP_CONTROL);
751 pp &= ~POWER_TARGET_ON;
752 I915_WRITE(PCH_PP_CONTROL, pp);
753 do {
754 pp_status = I915_READ(PCH_PP_STATUS);
755 } while ((pp_status & PP_ON) && !time_after(jiffies, timeout));
756
757 if (time_after(jiffies, timeout))
758 DRM_DEBUG_KMS("panel off wait timed out\n");
759
760 /* Make sure VDD is enabled so DP AUX will work */
761 pp |= EDP_FORCE_VDD;
762 I915_WRITE(PCH_PP_CONTROL, pp);
763}
764
720static void ironlake_edp_backlight_on (struct drm_device *dev) 765static void ironlake_edp_backlight_on (struct drm_device *dev)
721{ 766{
722 struct drm_i915_private *dev_priv = dev->dev_private; 767 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -751,14 +796,18 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
751 if (mode != DRM_MODE_DPMS_ON) { 796 if (mode != DRM_MODE_DPMS_ON) {
752 if (dp_reg & DP_PORT_EN) { 797 if (dp_reg & DP_PORT_EN) {
753 intel_dp_link_down(intel_encoder, dp_priv->DP); 798 intel_dp_link_down(intel_encoder, dp_priv->DP);
754 if (IS_eDP(intel_encoder)) 799 if (IS_eDP(intel_encoder)) {
755 ironlake_edp_backlight_off(dev); 800 ironlake_edp_backlight_off(dev);
801 ironlake_edp_backlight_off(dev);
802 }
756 } 803 }
757 } else { 804 } else {
758 if (!(dp_reg & DP_PORT_EN)) { 805 if (!(dp_reg & DP_PORT_EN)) {
759 intel_dp_link_train(intel_encoder, dp_priv->DP, dp_priv->link_configuration); 806 intel_dp_link_train(intel_encoder, dp_priv->DP, dp_priv->link_configuration);
760 if (IS_eDP(intel_encoder)) 807 if (IS_eDP(intel_encoder)) {
808 ironlake_edp_panel_on(dev);
761 ironlake_edp_backlight_on(dev); 809 ironlake_edp_backlight_on(dev);
810 }
762 } 811 }
763 } 812 }
764 dp_priv->dpms_mode = mode; 813 dp_priv->dpms_mode = mode;