diff options
author | Keith Packard <keithp@keithp.com> | 2011-07-26 01:12:43 -0400 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2011-07-28 18:47:22 -0400 |
commit | f0575e92974d328e8816ed89704c985a7d7d90ac (patch) | |
tree | 15bc2e0bf6bb8138685117432ddc72ac2bbf2568 /drivers/gpu | |
parent | 59f3e272d788305e16098f0b18309919c9216d67 (diff) |
drm/i915: DP_PIPE_ENABLED must check transcoder on CPT
Display port pipe selection on CPT is not done with a bit in the
output register, rather it is controlled by a couple of bits in the
separate transcoder register which indicate which display port output
is connected to the transcoder.
This patch replaces the simplistic macro DP_PIPE_ENABLED with the
rather more complicated function dp_pipe_enabled which checks the
output register to see if that is enabled, and then goes on to either
check the output register pipe selection bit (on non-CPT) or the
transcoder DP selection bits (on CPT).
Before this patch, any time the mode of pipe A was changed, any
display port outputs on pipe B would get disabled as
intel_disable_pch_ports would ensure that the mode setting operation
could occur on pipe A without interference from other outputs
connected to that pch port
Signed-off-by: Keith Packard <keithp@keithp.com>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 45 |
2 files changed, 34 insertions, 14 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5d5def756c9e..f7315653a842 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -2083,9 +2083,6 @@ | |||
2083 | #define DP_PIPEB_SELECT (1 << 30) | 2083 | #define DP_PIPEB_SELECT (1 << 30) |
2084 | #define DP_PIPE_MASK (1 << 30) | 2084 | #define DP_PIPE_MASK (1 << 30) |
2085 | 2085 | ||
2086 | #define DP_PIPE_ENABLED(V, P) \ | ||
2087 | (((V) & (DP_PIPE_MASK | DP_PORT_EN)) == ((P) << 30 | DP_PORT_EN)) | ||
2088 | |||
2089 | /* Link training mode - select a suitable mode for each stage */ | 2086 | /* Link training mode - select a suitable mode for each stage */ |
2090 | #define DP_LINK_TRAIN_PAT_1 (0 << 28) | 2087 | #define DP_LINK_TRAIN_PAT_1 (0 << 28) |
2091 | #define DP_LINK_TRAIN_PAT_2 (1 << 28) | 2088 | #define DP_LINK_TRAIN_PAT_2 (1 << 28) |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5609c065aaf4..fc26cb4c9ba3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -979,11 +979,29 @@ static void assert_transcoder_disabled(struct drm_i915_private *dev_priv, | |||
979 | pipe_name(pipe)); | 979 | pipe_name(pipe)); |
980 | } | 980 | } |
981 | 981 | ||
982 | static bool dp_pipe_enabled(struct drm_i915_private *dev_priv, enum pipe pipe, | ||
983 | int reg, u32 port_sel, u32 val) | ||
984 | { | ||
985 | if ((val & DP_PORT_EN) == 0) | ||
986 | return false; | ||
987 | |||
988 | if (HAS_PCH_CPT(dev_priv->dev)) { | ||
989 | u32 trans_dp_ctl_reg = TRANS_DP_CTL(pipe); | ||
990 | u32 trans_dp_ctl = I915_READ(trans_dp_ctl_reg); | ||
991 | if ((trans_dp_ctl & TRANS_DP_PORT_SEL_MASK) != port_sel) | ||
992 | return false; | ||
993 | } else { | ||
994 | if ((val & DP_PIPE_MASK) != (pipe << 30)) | ||
995 | return false; | ||
996 | } | ||
997 | return true; | ||
998 | } | ||
999 | |||
982 | static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, | 1000 | static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, |
983 | enum pipe pipe, int reg) | 1001 | enum pipe pipe, int reg, u32 port_sel) |
984 | { | 1002 | { |
985 | u32 val = I915_READ(reg); | 1003 | u32 val = I915_READ(reg); |
986 | WARN(DP_PIPE_ENABLED(val, pipe), | 1004 | WARN(dp_pipe_enabled(dev_priv, pipe, reg, port_sel, val), |
987 | "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", | 1005 | "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", |
988 | reg, pipe_name(pipe)); | 1006 | reg, pipe_name(pipe)); |
989 | } | 1007 | } |
@@ -1003,9 +1021,9 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, | |||
1003 | int reg; | 1021 | int reg; |
1004 | u32 val; | 1022 | u32 val; |
1005 | 1023 | ||
1006 | assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_B); | 1024 | assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_B, TRANS_DP_PORT_SEL_B); |
1007 | assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_C); | 1025 | assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_C, TRANS_DP_PORT_SEL_C); |
1008 | assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_D); | 1026 | assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_D, TRANS_DP_PORT_SEL_D); |
1009 | 1027 | ||
1010 | reg = PCH_ADPA; | 1028 | reg = PCH_ADPA; |
1011 | val = I915_READ(reg); | 1029 | val = I915_READ(reg); |
@@ -1334,19 +1352,24 @@ static void intel_disable_plane(struct drm_i915_private *dev_priv, | |||
1334 | } | 1352 | } |
1335 | 1353 | ||
1336 | static void disable_pch_dp(struct drm_i915_private *dev_priv, | 1354 | static void disable_pch_dp(struct drm_i915_private *dev_priv, |
1337 | enum pipe pipe, int reg) | 1355 | enum pipe pipe, int reg, u32 port_sel) |
1338 | { | 1356 | { |
1339 | u32 val = I915_READ(reg); | 1357 | u32 val = I915_READ(reg); |
1340 | if (DP_PIPE_ENABLED(val, pipe)) | 1358 | if (dp_pipe_enabled(dev_priv, pipe, reg, port_sel, val)) { |
1359 | DRM_DEBUG_KMS("Disabling pch dp %x on pipe %d\n", reg, pipe); | ||
1341 | I915_WRITE(reg, val & ~DP_PORT_EN); | 1360 | I915_WRITE(reg, val & ~DP_PORT_EN); |
1361 | } | ||
1342 | } | 1362 | } |
1343 | 1363 | ||
1344 | static void disable_pch_hdmi(struct drm_i915_private *dev_priv, | 1364 | static void disable_pch_hdmi(struct drm_i915_private *dev_priv, |
1345 | enum pipe pipe, int reg) | 1365 | enum pipe pipe, int reg) |
1346 | { | 1366 | { |
1347 | u32 val = I915_READ(reg); | 1367 | u32 val = I915_READ(reg); |
1348 | if (HDMI_PIPE_ENABLED(val, pipe)) | 1368 | if (HDMI_PIPE_ENABLED(val, pipe)) { |
1369 | DRM_DEBUG_KMS("Disabling pch HDMI %x on pipe %d\n", | ||
1370 | reg, pipe); | ||
1349 | I915_WRITE(reg, val & ~PORT_ENABLE); | 1371 | I915_WRITE(reg, val & ~PORT_ENABLE); |
1372 | } | ||
1350 | } | 1373 | } |
1351 | 1374 | ||
1352 | /* Disable any ports connected to this transcoder */ | 1375 | /* Disable any ports connected to this transcoder */ |
@@ -1358,9 +1381,9 @@ static void intel_disable_pch_ports(struct drm_i915_private *dev_priv, | |||
1358 | val = I915_READ(PCH_PP_CONTROL); | 1381 | val = I915_READ(PCH_PP_CONTROL); |
1359 | I915_WRITE(PCH_PP_CONTROL, val | PANEL_UNLOCK_REGS); | 1382 | I915_WRITE(PCH_PP_CONTROL, val | PANEL_UNLOCK_REGS); |
1360 | 1383 | ||
1361 | disable_pch_dp(dev_priv, pipe, PCH_DP_B); | 1384 | disable_pch_dp(dev_priv, pipe, PCH_DP_B, TRANS_DP_PORT_SEL_B); |
1362 | disable_pch_dp(dev_priv, pipe, PCH_DP_C); | 1385 | disable_pch_dp(dev_priv, pipe, PCH_DP_C, TRANS_DP_PORT_SEL_C); |
1363 | disable_pch_dp(dev_priv, pipe, PCH_DP_D); | 1386 | disable_pch_dp(dev_priv, pipe, PCH_DP_D, TRANS_DP_PORT_SEL_D); |
1364 | 1387 | ||
1365 | reg = PCH_ADPA; | 1388 | reg = PCH_ADPA; |
1366 | val = I915_READ(reg); | 1389 | val = I915_READ(reg); |