aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_dp.c
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2010-10-07 19:01:12 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2010-10-08 04:28:00 -0400
commit01cb9ea633ddf3e8770dfe7851e88610087098bc (patch)
treed209848d61794968a73c9c593e2e0d6035399517 /drivers/gpu/drm/i915/intel_dp.c
parent5c5313c8db9bfb549e080fc4cb0a4c3c2aa7a73d (diff)
drm/i915/dp: eDP power sequencing fixes
Enable the panel before adjusting eDP link params, make sure the panel is idle after powering it on before proceeding with other activity, delay backlight enable to avoid visible flicker. Also avoid using VDD per hw team recommendation; it can conflict with the builtin panel power sequencing logic and lead to panel power sequencing failures. Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dp.c')
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c77
1 files changed, 32 insertions, 45 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 57bfc3e7b40a..944dfe199f6e 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -788,10 +788,11 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
788} 788}
789 789
790/* Returns true if the panel was already on when called */ 790/* Returns true if the panel was already on when called */
791static bool ironlake_edp_panel_on (struct drm_device *dev) 791static bool ironlake_edp_panel_on (struct intel_dp *intel_dp)
792{ 792{
793 struct drm_device *dev = intel_dp->base.base.dev;
793 struct drm_i915_private *dev_priv = dev->dev_private; 794 struct drm_i915_private *dev_priv = dev->dev_private;
794 u32 pp; 795 u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_STATE_ON_IDLE;
795 796
796 if (I915_READ(PCH_PP_STATUS) & PP_ON) 797 if (I915_READ(PCH_PP_STATUS) & PP_ON)
797 return true; 798 return true;
@@ -803,19 +804,20 @@ static bool ironlake_edp_panel_on (struct drm_device *dev)
803 I915_WRITE(PCH_PP_CONTROL, pp); 804 I915_WRITE(PCH_PP_CONTROL, pp);
804 POSTING_READ(PCH_PP_CONTROL); 805 POSTING_READ(PCH_PP_CONTROL);
805 806
806 pp |= POWER_TARGET_ON; 807 pp |= PANEL_UNLOCK_REGS | POWER_TARGET_ON;
807 I915_WRITE(PCH_PP_CONTROL, pp); 808 I915_WRITE(PCH_PP_CONTROL, pp);
809 POSTING_READ(PCH_PP_CONTROL);
808 810
809 /* Ouch. We need to wait here for some panels, like Dell e6510 811 /* Ouch. We need to wait here for some panels, like Dell e6510
810 * https://bugs.freedesktop.org/show_bug.cgi?id=29278i 812 * https://bugs.freedesktop.org/show_bug.cgi?id=29278i
811 */ 813 */
812 msleep(300); 814 msleep(300);
813 815
814 if (wait_for(I915_READ(PCH_PP_STATUS) & PP_ON, 5000)) 816 if (wait_for((I915_READ(PCH_PP_STATUS) & idle_on_mask) == idle_on_mask,
817 5000))
815 DRM_ERROR("panel on wait timed out: 0x%08x\n", 818 DRM_ERROR("panel on wait timed out: 0x%08x\n",
816 I915_READ(PCH_PP_STATUS)); 819 I915_READ(PCH_PP_STATUS));
817 820
818 pp &= ~(PANEL_UNLOCK_REGS);
819 pp |= PANEL_POWER_RESET; /* restore panel reset bit */ 821 pp |= PANEL_POWER_RESET; /* restore panel reset bit */
820 I915_WRITE(PCH_PP_CONTROL, pp); 822 I915_WRITE(PCH_PP_CONTROL, pp);
821 POSTING_READ(PCH_PP_CONTROL); 823 POSTING_READ(PCH_PP_CONTROL);
@@ -826,7 +828,8 @@ static bool ironlake_edp_panel_on (struct drm_device *dev)
826static void ironlake_edp_panel_off (struct drm_device *dev) 828static void ironlake_edp_panel_off (struct drm_device *dev)
827{ 829{
828 struct drm_i915_private *dev_priv = dev->dev_private; 830 struct drm_i915_private *dev_priv = dev->dev_private;
829 u32 pp; 831 u32 pp, idle_off_mask = PP_ON | PP_SEQUENCE_MASK |
832 PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK;
830 833
831 pp = I915_READ(PCH_PP_CONTROL); 834 pp = I915_READ(PCH_PP_CONTROL);
832 835
@@ -837,12 +840,12 @@ static void ironlake_edp_panel_off (struct drm_device *dev)
837 840
838 pp &= ~POWER_TARGET_ON; 841 pp &= ~POWER_TARGET_ON;
839 I915_WRITE(PCH_PP_CONTROL, pp); 842 I915_WRITE(PCH_PP_CONTROL, pp);
843 POSTING_READ(PCH_PP_CONTROL);
840 844
841 if (wait_for((I915_READ(PCH_PP_STATUS) & PP_ON) == 0, 5000)) 845 if (wait_for((I915_READ(PCH_PP_STATUS) & idle_off_mask) == 0, 5000))
842 DRM_ERROR("panel off wait timed out: 0x%08x\n", 846 DRM_ERROR("panel off wait timed out: 0x%08x\n",
843 I915_READ(PCH_PP_STATUS)); 847 I915_READ(PCH_PP_STATUS));
844 848
845 /* Make sure VDD is enabled so DP AUX will work */
846 pp |= PANEL_POWER_RESET; /* restore panel reset bit */ 849 pp |= PANEL_POWER_RESET; /* restore panel reset bit */
847 I915_WRITE(PCH_PP_CONTROL, pp); 850 I915_WRITE(PCH_PP_CONTROL, pp);
848 POSTING_READ(PCH_PP_CONTROL); 851 POSTING_READ(PCH_PP_CONTROL);
@@ -853,36 +856,19 @@ static void ironlake_edp_panel_off (struct drm_device *dev)
853 msleep(300); 856 msleep(300);
854} 857}
855 858
856static void ironlake_edp_panel_vdd_on(struct drm_device *dev)
857{
858 struct drm_i915_private *dev_priv = dev->dev_private;
859 u32 pp;
860
861 pp = I915_READ(PCH_PP_CONTROL);
862 pp |= EDP_FORCE_VDD;
863 I915_WRITE(PCH_PP_CONTROL, pp);
864 POSTING_READ(PCH_PP_CONTROL);
865 msleep(300);
866}
867
868static void ironlake_edp_panel_vdd_off(struct drm_device *dev)
869{
870 struct drm_i915_private *dev_priv = dev->dev_private;
871 u32 pp;
872
873 pp = I915_READ(PCH_PP_CONTROL);
874 pp &= ~EDP_FORCE_VDD;
875 I915_WRITE(PCH_PP_CONTROL, pp);
876 POSTING_READ(PCH_PP_CONTROL);
877 msleep(300);
878}
879
880static void ironlake_edp_backlight_on (struct drm_device *dev) 859static void ironlake_edp_backlight_on (struct drm_device *dev)
881{ 860{
882 struct drm_i915_private *dev_priv = dev->dev_private; 861 struct drm_i915_private *dev_priv = dev->dev_private;
883 u32 pp; 862 u32 pp;
884 863
885 DRM_DEBUG_KMS("\n"); 864 DRM_DEBUG_KMS("\n");
865 /*
866 * If we enable the backlight right away following a panel power
867 * on, we may see slight flicker as the panel syncs with the eDP
868 * link. So delay a bit to make sure the image is solid before
869 * allowing it to appear.
870 */
871 msleep(300);
886 pp = I915_READ(PCH_PP_CONTROL); 872 pp = I915_READ(PCH_PP_CONTROL);
887 pp |= EDP_BLC_ENABLE; 873 pp |= EDP_BLC_ENABLE;
888 I915_WRITE(PCH_PP_CONTROL, pp); 874 I915_WRITE(PCH_PP_CONTROL, pp);
@@ -932,10 +918,12 @@ static void intel_dp_prepare(struct drm_encoder *encoder)
932 uint32_t dp_reg = I915_READ(intel_dp->output_reg); 918 uint32_t dp_reg = I915_READ(intel_dp->output_reg);
933 919
934 if (is_edp(intel_dp)) { 920 if (is_edp(intel_dp)) {
935 ironlake_edp_panel_off(dev);
936 ironlake_edp_backlight_off(dev); 921 ironlake_edp_backlight_off(dev);
937 ironlake_edp_panel_vdd_on(dev); 922 ironlake_edp_panel_on(intel_dp);
938 ironlake_edp_pll_on(encoder); 923 if (!is_pch_edp(intel_dp))
924 ironlake_edp_pll_on(encoder);
925 else
926 ironlake_edp_pll_off(encoder);
939 } 927 }
940 if (dp_reg & DP_PORT_EN) 928 if (dp_reg & DP_PORT_EN)
941 intel_dp_link_down(intel_dp); 929 intel_dp_link_down(intel_dp);
@@ -949,7 +937,7 @@ static void intel_dp_commit(struct drm_encoder *encoder)
949 intel_dp_start_link_train(intel_dp); 937 intel_dp_start_link_train(intel_dp);
950 938
951 if (is_edp(intel_dp)) 939 if (is_edp(intel_dp))
952 ironlake_edp_panel_on(dev); 940 ironlake_edp_panel_on(intel_dp);
953 941
954 intel_dp_complete_link_train(intel_dp); 942 intel_dp_complete_link_train(intel_dp);
955 943
@@ -966,19 +954,19 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
966 uint32_t dp_reg = I915_READ(intel_dp->output_reg); 954 uint32_t dp_reg = I915_READ(intel_dp->output_reg);
967 955
968 if (mode != DRM_MODE_DPMS_ON) { 956 if (mode != DRM_MODE_DPMS_ON) {
969 if (is_edp(intel_dp)) { 957 if (is_edp(intel_dp))
970 ironlake_edp_backlight_off(dev); 958 ironlake_edp_backlight_off(dev);
971 ironlake_edp_panel_off(dev);
972 }
973 if (dp_reg & DP_PORT_EN) 959 if (dp_reg & DP_PORT_EN)
974 intel_dp_link_down(intel_dp); 960 intel_dp_link_down(intel_dp);
975 if (is_edp(intel_dp)) 961 if (is_edp(intel_dp))
962 ironlake_edp_panel_off(dev);
963 if (is_edp(intel_dp) && !is_pch_edp(intel_dp))
976 ironlake_edp_pll_off(encoder); 964 ironlake_edp_pll_off(encoder);
977 } else { 965 } else {
978 if (!(dp_reg & DP_PORT_EN)) { 966 if (!(dp_reg & DP_PORT_EN)) {
979 intel_dp_start_link_train(intel_dp);
980 if (is_edp(intel_dp)) 967 if (is_edp(intel_dp))
981 ironlake_edp_panel_on(dev); 968 ironlake_edp_panel_on(intel_dp);
969 intel_dp_start_link_train(intel_dp);
982 intel_dp_complete_link_train(intel_dp); 970 intel_dp_complete_link_train(intel_dp);
983 if (is_edp(intel_dp)) 971 if (is_edp(intel_dp))
984 ironlake_edp_backlight_on(dev); 972 ironlake_edp_backlight_on(dev);
@@ -1445,9 +1433,10 @@ ironlake_dp_detect(struct drm_connector *connector)
1445 struct intel_dp *intel_dp = intel_attached_dp(connector); 1433 struct intel_dp *intel_dp = intel_attached_dp(connector);
1446 enum drm_connector_status status; 1434 enum drm_connector_status status;
1447 1435
1448 /* Panel needs power for AUX to work */ 1436 /* Can't disconnect eDP */
1449 if (is_edp(intel_dp)) 1437 if (is_edp(intel_dp))
1450 ironlake_edp_panel_vdd_on(connector->dev); 1438 return connector_status_connected;
1439
1451 status = connector_status_disconnected; 1440 status = connector_status_disconnected;
1452 if (intel_dp_aux_native_read(intel_dp, 1441 if (intel_dp_aux_native_read(intel_dp,
1453 0x000, intel_dp->dpcd, 1442 0x000, intel_dp->dpcd,
@@ -1458,8 +1447,6 @@ ironlake_dp_detect(struct drm_connector *connector)
1458 } 1447 }
1459 DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", intel_dp->dpcd[0], 1448 DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", intel_dp->dpcd[0],
1460 intel_dp->dpcd[1], intel_dp->dpcd[2], intel_dp->dpcd[3]); 1449 intel_dp->dpcd[1], intel_dp->dpcd[2], intel_dp->dpcd[3]);
1461 if (is_edp(intel_dp))
1462 ironlake_edp_panel_vdd_off(connector->dev);
1463 return status; 1450 return status;
1464} 1451}
1465 1452