aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2011-02-07 16:46:40 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2011-02-11 15:32:44 -0500
commit47a05eca72991039e788b25232061f9c9df9ec23 (patch)
tree27aff34a2bae8ce6d7f40eb2a11938a98bcaee1b /drivers/gpu/drm
parentbed636abeaa3d8e8279e95380cb10ecb20d1b276 (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.h15
-rw-r--r--drivers/gpu/drm/i915/intel_display.c84
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,
1270static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, 1270static 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,
1283static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, 1279static 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
1620static 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
1628static 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 */
1637static 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
1631static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) 1667static 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