diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2011-02-07 16:46:40 -0500 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-02-11 15:32:44 -0500 |
commit | 47a05eca72991039e788b25232061f9c9df9ec23 (patch) | |
tree | 27aff34a2bae8ce6d7f40eb2a11938a98bcaee1b /drivers/gpu/drm | |
parent | bed636abeaa3d8e8279e95380cb10ecb20d1b276 (diff) |
drm/i915: disable PCH ports if needed when disabling a CRTC
Disable any PCH ports associated with a pipe when disabling it. This
should prevent transcoder disable failures due to ports still being on.
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
[ickle: introduce *_PIPE_ENABLED() macro]
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 84 |
2 files changed, 74 insertions, 25 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 6bd9659861e5..8ecf5db6fc05 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -1440,6 +1440,7 @@ | |||
1440 | #define LVDS_PORT_EN (1 << 31) | 1440 | #define LVDS_PORT_EN (1 << 31) |
1441 | /* Selects pipe B for LVDS data. Must be set on pre-965. */ | 1441 | /* Selects pipe B for LVDS data. Must be set on pre-965. */ |
1442 | #define LVDS_PIPEB_SELECT (1 << 30) | 1442 | #define LVDS_PIPEB_SELECT (1 << 30) |
1443 | #define LVDS_PIPE_MASK (1 << 30) | ||
1443 | /* LVDS dithering flag on 965/g4x platform */ | 1444 | /* LVDS dithering flag on 965/g4x platform */ |
1444 | #define LVDS_ENABLE_DITHER (1 << 25) | 1445 | #define LVDS_ENABLE_DITHER (1 << 25) |
1445 | /* LVDS sync polarity flags. Set to invert (i.e. negative) */ | 1446 | /* LVDS sync polarity flags. Set to invert (i.e. negative) */ |
@@ -1479,6 +1480,9 @@ | |||
1479 | #define LVDS_B0B3_POWER_DOWN (0 << 2) | 1480 | #define LVDS_B0B3_POWER_DOWN (0 << 2) |
1480 | #define LVDS_B0B3_POWER_UP (3 << 2) | 1481 | #define LVDS_B0B3_POWER_UP (3 << 2) |
1481 | 1482 | ||
1483 | #define LVDS_PIPE_ENABLED(V, P) \ | ||
1484 | (((V) & (LVDS_PIPE_MASK | LVDS_PORT_EN)) == ((P) << 30 | LVDS_PORT_EN)) | ||
1485 | |||
1482 | /* Video Data Island Packet control */ | 1486 | /* Video Data Island Packet control */ |
1483 | #define VIDEO_DIP_DATA 0x61178 | 1487 | #define VIDEO_DIP_DATA 0x61178 |
1484 | #define VIDEO_DIP_CTL 0x61170 | 1488 | #define VIDEO_DIP_CTL 0x61170 |
@@ -2067,6 +2071,10 @@ | |||
2067 | 2071 | ||
2068 | #define DP_PORT_EN (1 << 31) | 2072 | #define DP_PORT_EN (1 << 31) |
2069 | #define DP_PIPEB_SELECT (1 << 30) | 2073 | #define DP_PIPEB_SELECT (1 << 30) |
2074 | #define DP_PIPE_MASK (1 << 30) | ||
2075 | |||
2076 | #define DP_PIPE_ENABLED(V, P) \ | ||
2077 | (((V) & (DP_PIPE_MASK | DP_PORT_EN)) == ((P) << 30 | DP_PORT_EN)) | ||
2070 | 2078 | ||
2071 | /* Link training mode - select a suitable mode for each stage */ | 2079 | /* Link training mode - select a suitable mode for each stage */ |
2072 | #define DP_LINK_TRAIN_PAT_1 (0 << 28) | 2080 | #define DP_LINK_TRAIN_PAT_1 (0 << 28) |
@@ -3180,11 +3188,15 @@ | |||
3180 | #define ADPA_CRT_HOTPLUG_VOLREF_475MV (1<<17) | 3188 | #define ADPA_CRT_HOTPLUG_VOLREF_475MV (1<<17) |
3181 | #define ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16) | 3189 | #define ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16) |
3182 | 3190 | ||
3191 | #define ADPA_PIPE_ENABLED(V, P) \ | ||
3192 | (((V) & (ADPA_TRANS_SELECT_MASK | ADPA_DAC_ENABLE)) == ((P) << 30 | ADPA_DAC_ENABLE)) | ||
3193 | |||
3183 | /* or SDVOB */ | 3194 | /* or SDVOB */ |
3184 | #define HDMIB 0xe1140 | 3195 | #define HDMIB 0xe1140 |
3185 | #define PORT_ENABLE (1 << 31) | 3196 | #define PORT_ENABLE (1 << 31) |
3186 | #define TRANSCODER_A (0) | 3197 | #define TRANSCODER_A (0) |
3187 | #define TRANSCODER_B (1 << 30) | 3198 | #define TRANSCODER_B (1 << 30) |
3199 | #define TRANSCODER_MASK (1 << 30) | ||
3188 | #define COLOR_FORMAT_8bpc (0) | 3200 | #define COLOR_FORMAT_8bpc (0) |
3189 | #define COLOR_FORMAT_12bpc (3 << 26) | 3201 | #define COLOR_FORMAT_12bpc (3 << 26) |
3190 | #define SDVOB_HOTPLUG_ENABLE (1 << 23) | 3202 | #define SDVOB_HOTPLUG_ENABLE (1 << 23) |
@@ -3200,6 +3212,9 @@ | |||
3200 | #define HSYNC_ACTIVE_HIGH (1 << 3) | 3212 | #define HSYNC_ACTIVE_HIGH (1 << 3) |
3201 | #define PORT_DETECTED (1 << 2) | 3213 | #define PORT_DETECTED (1 << 2) |
3202 | 3214 | ||
3215 | #define HDMI_PIPE_ENABLED(V, P) \ | ||
3216 | (((V) & (TRANSCODER_MASK | PORT_ENABLE)) == ((P) << 30 | PORT_ENABLE)) | ||
3217 | |||
3203 | /* PCH SDVOB multiplex with HDMIB */ | 3218 | /* PCH SDVOB multiplex with HDMIB */ |
3204 | #define PCH_SDVOB HDMIB | 3219 | #define PCH_SDVOB HDMIB |
3205 | 3220 | ||
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 37765e01d7f1..42c64cb35738 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -1270,12 +1270,8 @@ static void assert_transcoder_disabled(struct drm_i915_private *dev_priv, | |||
1270 | static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, | 1270 | static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, |
1271 | enum pipe pipe, int reg) | 1271 | enum pipe pipe, int reg) |
1272 | { | 1272 | { |
1273 | u32 val; | 1273 | u32 val = I915_READ(reg); |
1274 | u32 sel_pipe; | 1274 | WARN(DP_PIPE_ENABLED(val, pipe), |
1275 | |||
1276 | val = I915_READ(reg); | ||
1277 | sel_pipe = (val & DP_PIPEB_SELECT) >> 30; | ||
1278 | WARN((val & DP_PORT_EN) && sel_pipe == pipe, | ||
1279 | "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", | 1275 | "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", |
1280 | reg, pipe_name(pipe)); | 1276 | reg, pipe_name(pipe)); |
1281 | } | 1277 | } |
@@ -1283,12 +1279,8 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, | |||
1283 | static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, | 1279 | static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, |
1284 | enum pipe pipe, int reg) | 1280 | enum pipe pipe, int reg) |
1285 | { | 1281 | { |
1286 | u32 val; | 1282 | u32 val = I915_READ(reg); |
1287 | u32 sel_pipe; | 1283 | WARN(HDMI_PIPE_ENABLED(val, pipe), |
1288 | |||
1289 | val = I915_READ(reg); | ||
1290 | sel_pipe = (val & TRANSCODER_B) >> 30; | ||
1291 | WARN((val & PORT_ENABLE) && sel_pipe == pipe, | ||
1292 | "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", | 1284 | "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", |
1293 | reg, pipe_name(pipe)); | 1285 | reg, pipe_name(pipe)); |
1294 | } | 1286 | } |
@@ -1298,7 +1290,6 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, | |||
1298 | { | 1290 | { |
1299 | int reg; | 1291 | int reg; |
1300 | u32 val; | 1292 | u32 val; |
1301 | u32 sel_pipe; | ||
1302 | 1293 | ||
1303 | assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_B); | 1294 | assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_B); |
1304 | assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_C); | 1295 | assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_C); |
@@ -1306,15 +1297,13 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, | |||
1306 | 1297 | ||
1307 | reg = PCH_ADPA; | 1298 | reg = PCH_ADPA; |
1308 | val = I915_READ(reg); | 1299 | val = I915_READ(reg); |
1309 | sel_pipe = (val & ADPA_TRANS_B_SELECT) >> 30; | 1300 | WARN(ADPA_PIPE_ENABLED(val, pipe), |
1310 | WARN(sel_pipe == pipe && (val & ADPA_DAC_ENABLE), | ||
1311 | "PCH VGA enabled on transcoder %c, should be disabled\n", | 1301 | "PCH VGA enabled on transcoder %c, should be disabled\n", |
1312 | pipe_name(pipe)); | 1302 | pipe_name(pipe)); |
1313 | 1303 | ||
1314 | reg = PCH_LVDS; | 1304 | reg = PCH_LVDS; |
1315 | val = I915_READ(reg); | 1305 | val = I915_READ(reg); |
1316 | sel_pipe = (val & LVDS_PIPEB_SELECT) >> 30; | 1306 | WARN(LVDS_PIPE_ENABLED(val, pipe), |
1317 | WARN(sel_pipe == pipe && (val & LVDS_PORT_EN), | ||
1318 | "PCH LVDS enabled on transcoder %c, should be disabled\n", | 1307 | "PCH LVDS enabled on transcoder %c, should be disabled\n", |
1319 | pipe_name(pipe)); | 1308 | pipe_name(pipe)); |
1320 | 1309 | ||
@@ -1628,6 +1617,53 @@ static void intel_disable_plane(struct drm_i915_private *dev_priv, | |||
1628 | intel_wait_for_vblank(dev_priv->dev, pipe); | 1617 | intel_wait_for_vblank(dev_priv->dev, pipe); |
1629 | } | 1618 | } |
1630 | 1619 | ||
1620 | static void disable_pch_dp(struct drm_i915_private *dev_priv, | ||
1621 | enum pipe pipe, int reg) | ||
1622 | { | ||
1623 | u32 val = I915_READ(reg); | ||
1624 | if (DP_PIPE_ENABLED(val, pipe)) | ||
1625 | I915_WRITE(reg, val & ~DP_PORT_EN); | ||
1626 | } | ||
1627 | |||
1628 | static void disable_pch_hdmi(struct drm_i915_private *dev_priv, | ||
1629 | enum pipe pipe, int reg) | ||
1630 | { | ||
1631 | u32 val = I915_READ(reg); | ||
1632 | if (HDMI_PIPE_ENABLED(val, pipe)) | ||
1633 | I915_WRITE(reg, val & ~PORT_ENABLE); | ||
1634 | } | ||
1635 | |||
1636 | /* Disable any ports connected to this transcoder */ | ||
1637 | static void intel_disable_pch_ports(struct drm_i915_private *dev_priv, | ||
1638 | enum pipe pipe) | ||
1639 | { | ||
1640 | u32 reg, val; | ||
1641 | |||
1642 | val = I915_READ(PCH_PP_CONTROL); | ||
1643 | I915_WRITE(PCH_PP_CONTROL, val | PANEL_UNLOCK_REGS); | ||
1644 | |||
1645 | disable_pch_dp(dev_priv, pipe, PCH_DP_B); | ||
1646 | disable_pch_dp(dev_priv, pipe, PCH_DP_C); | ||
1647 | disable_pch_dp(dev_priv, pipe, PCH_DP_D); | ||
1648 | |||
1649 | reg = PCH_ADPA; | ||
1650 | val = I915_READ(reg); | ||
1651 | if (ADPA_PIPE_ENABLED(val, pipe)) | ||
1652 | I915_WRITE(reg, val & ~ADPA_DAC_ENABLE); | ||
1653 | |||
1654 | reg = PCH_LVDS; | ||
1655 | val = I915_READ(reg); | ||
1656 | if (LVDS_PIPE_ENABLED(val, pipe)) { | ||
1657 | I915_WRITE(reg, val & ~LVDS_PORT_EN); | ||
1658 | POSTING_READ(reg); | ||
1659 | udelay(100); | ||
1660 | } | ||
1661 | |||
1662 | disable_pch_hdmi(dev_priv, pipe, HDMIB); | ||
1663 | disable_pch_hdmi(dev_priv, pipe, HDMIC); | ||
1664 | disable_pch_hdmi(dev_priv, pipe, HDMID); | ||
1665 | } | ||
1666 | |||
1631 | static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | 1667 | static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) |
1632 | { | 1668 | { |
1633 | struct drm_device *dev = crtc->dev; | 1669 | struct drm_device *dev = crtc->dev; |
@@ -2864,14 +2900,12 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) | |||
2864 | 2900 | ||
2865 | ironlake_fdi_disable(crtc); | 2901 | ironlake_fdi_disable(crtc); |
2866 | 2902 | ||
2867 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { | 2903 | /* This is a horrible layering violation; we should be doing this in |
2868 | temp = I915_READ(PCH_LVDS); | 2904 | * the connector/encoder ->prepare instead, but we don't always have |
2869 | if (temp & LVDS_PORT_EN) { | 2905 | * enough information there about the config to know whether it will |
2870 | I915_WRITE(PCH_LVDS, temp & ~LVDS_PORT_EN); | 2906 | * actually be necessary or just cause undesired flicker. |
2871 | POSTING_READ(PCH_LVDS); | 2907 | */ |
2872 | udelay(100); | 2908 | intel_disable_pch_ports(dev_priv, pipe); |
2873 | } | ||
2874 | } | ||
2875 | 2909 | ||
2876 | intel_disable_transcoder(dev_priv, pipe); | 2910 | intel_disable_transcoder(dev_priv, pipe); |
2877 | 2911 | ||