aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2009-12-11 14:07:17 -0500
committerEric Anholt <eric@anholt.net>2009-12-16 17:00:05 -0500
commitb01f2c3a4a37d09a47ad73ccbb46d554d21cfeb0 (patch)
tree66624c9810c8175e403a047113f35aef61e925b6
parentb295d1b6e3e3f240d27cbe556d33ff5eb54721a7 (diff)
drm/i915: only enable hotplug for detected outputs
This patch changes around our hotplug enable code a bit to only enable it for ports we actually detect and initialize. This prevents problems with stuck or spurious interrupts on outputs that aren't actually wired up, and is generally more correct. Fixes FDO bug #23183. Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c4
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c30
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h7
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c2
-rw-r--r--drivers/gpu/drm/i915/intel_display.c26
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c6
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c5
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c3
-rw-r--r--drivers/gpu/drm/i915/intel_tv.c2
9 files changed, 59 insertions, 26 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 28d99b8a049..e3e5d509423 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1249,6 +1249,8 @@ static int i915_load_modeset_init(struct drm_device *dev,
1249 if (ret) 1249 if (ret)
1250 goto destroy_ringbuffer; 1250 goto destroy_ringbuffer;
1251 1251
1252 intel_modeset_init(dev);
1253
1252 ret = drm_irq_install(dev); 1254 ret = drm_irq_install(dev);
1253 if (ret) 1255 if (ret)
1254 goto destroy_ringbuffer; 1256 goto destroy_ringbuffer;
@@ -1263,8 +1265,6 @@ static int i915_load_modeset_init(struct drm_device *dev,
1263 1265
1264 I915_WRITE(INSTPM, (1 << 5) | (1 << 21)); 1266 I915_WRITE(INSTPM, (1 << 5) | (1 << 21));
1265 1267
1266 intel_modeset_init(dev);
1267
1268 drm_helper_initial_config(dev); 1268 drm_helper_initial_config(dev);
1269 1269
1270 return 0; 1270 return 0;
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 85f4c5de97e..1733eea8784 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1084,6 +1084,10 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
1084 (void) I915_READ(IER); 1084 (void) I915_READ(IER);
1085} 1085}
1086 1086
1087/*
1088 * Must be called after intel_modeset_init or hotplug interrupts won't be
1089 * enabled correctly.
1090 */
1087int i915_driver_irq_postinstall(struct drm_device *dev) 1091int i915_driver_irq_postinstall(struct drm_device *dev)
1088{ 1092{
1089 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 1093 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -1106,19 +1110,23 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
1106 if (I915_HAS_HOTPLUG(dev)) { 1110 if (I915_HAS_HOTPLUG(dev)) {
1107 u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); 1111 u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
1108 1112
1109 /* Leave other bits alone */ 1113 /* Note HDMI and DP share bits */
1110 hotplug_en |= HOTPLUG_EN_MASK; 1114 if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
1115 hotplug_en |= HDMIB_HOTPLUG_INT_EN;
1116 if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
1117 hotplug_en |= HDMIC_HOTPLUG_INT_EN;
1118 if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
1119 hotplug_en |= HDMID_HOTPLUG_INT_EN;
1120 if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
1121 hotplug_en |= SDVOC_HOTPLUG_INT_EN;
1122 if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
1123 hotplug_en |= SDVOB_HOTPLUG_INT_EN;
1124 if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS)
1125 hotplug_en |= CRT_HOTPLUG_INT_EN;
1126 /* Ignore TV since it's buggy */
1127
1111 I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); 1128 I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
1112 1129
1113 dev_priv->hotplug_supported_mask = CRT_HOTPLUG_INT_STATUS |
1114 TV_HOTPLUG_INT_STATUS | SDVOC_HOTPLUG_INT_STATUS |
1115 SDVOB_HOTPLUG_INT_STATUS;
1116 if (IS_G4X(dev)) {
1117 dev_priv->hotplug_supported_mask |=
1118 HDMIB_HOTPLUG_INT_STATUS |
1119 HDMIC_HOTPLUG_INT_STATUS |
1120 HDMID_HOTPLUG_INT_STATUS;
1121 }
1122 /* Enable in IER... */ 1130 /* Enable in IER... */
1123 enable_mask |= I915_DISPLAY_PORT_INTERRUPT; 1131 enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
1124 /* and unmask in IMR */ 1132 /* and unmask in IMR */
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 974b3cf7061..f79b13324fa 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -879,13 +879,6 @@
879#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) 879#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2)
880#define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */ 880#define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */
881#define CRT_FORCE_HOTPLUG_MASK 0xfffffe1f 881#define CRT_FORCE_HOTPLUG_MASK 0xfffffe1f
882#define HOTPLUG_EN_MASK (HDMIB_HOTPLUG_INT_EN | \
883 HDMIC_HOTPLUG_INT_EN | \
884 HDMID_HOTPLUG_INT_EN | \
885 SDVOB_HOTPLUG_INT_EN | \
886 SDVOC_HOTPLUG_INT_EN | \
887 CRT_HOTPLUG_INT_EN)
888
889 882
890#define PORT_HOTPLUG_STAT 0x61114 883#define PORT_HOTPLUG_STAT 0x61114
891#define HDMIB_HOTPLUG_INT_STATUS (1 << 29) 884#define HDMIB_HOTPLUG_INT_STATUS (1 << 29)
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 9f3d3e56341..ddefc871edf 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -548,4 +548,6 @@ void intel_crt_init(struct drm_device *dev)
548 drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); 548 drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
549 549
550 drm_sysfs_connector_add(connector); 550 drm_sysfs_connector_add(connector);
551
552 dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS;
551} 553}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ef9c6139ee3..c21dede6461 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4400,29 +4400,43 @@ static void intel_setup_outputs(struct drm_device *dev)
4400 bool found = false; 4400 bool found = false;
4401 4401
4402 if (I915_READ(SDVOB) & SDVO_DETECTED) { 4402 if (I915_READ(SDVOB) & SDVO_DETECTED) {
4403 DRM_DEBUG_KMS("probing SDVOB\n");
4403 found = intel_sdvo_init(dev, SDVOB); 4404 found = intel_sdvo_init(dev, SDVOB);
4404 if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) 4405 if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) {
4406 DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
4405 intel_hdmi_init(dev, SDVOB); 4407 intel_hdmi_init(dev, SDVOB);
4408 }
4406 4409
4407 if (!found && SUPPORTS_INTEGRATED_DP(dev)) 4410 if (!found && SUPPORTS_INTEGRATED_DP(dev)) {
4411 DRM_DEBUG_KMS("probing DP_B\n");
4408 intel_dp_init(dev, DP_B); 4412 intel_dp_init(dev, DP_B);
4413 }
4409 } 4414 }
4410 4415
4411 /* Before G4X SDVOC doesn't have its own detect register */ 4416 /* Before G4X SDVOC doesn't have its own detect register */
4412 4417
4413 if (I915_READ(SDVOB) & SDVO_DETECTED) 4418 if (I915_READ(SDVOB) & SDVO_DETECTED) {
4419 DRM_DEBUG_KMS("probing SDVOC\n");
4414 found = intel_sdvo_init(dev, SDVOC); 4420 found = intel_sdvo_init(dev, SDVOC);
4421 }
4415 4422
4416 if (!found && (I915_READ(SDVOC) & SDVO_DETECTED)) { 4423 if (!found && (I915_READ(SDVOC) & SDVO_DETECTED)) {
4417 4424
4418 if (SUPPORTS_INTEGRATED_HDMI(dev)) 4425 if (SUPPORTS_INTEGRATED_HDMI(dev)) {
4426 DRM_DEBUG_KMS("probing HDMI on SDVOC\n");
4419 intel_hdmi_init(dev, SDVOC); 4427 intel_hdmi_init(dev, SDVOC);
4420 if (SUPPORTS_INTEGRATED_DP(dev)) 4428 }
4429 if (SUPPORTS_INTEGRATED_DP(dev)) {
4430 DRM_DEBUG_KMS("probing DP_C\n");
4421 intel_dp_init(dev, DP_C); 4431 intel_dp_init(dev, DP_C);
4432 }
4422 } 4433 }
4423 4434
4424 if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED)) 4435 if (SUPPORTS_INTEGRATED_DP(dev) &&
4436 (I915_READ(DP_D) & DP_DETECTED)) {
4437 DRM_DEBUG_KMS("probing DP_D\n");
4425 intel_dp_init(dev, DP_D); 4438 intel_dp_init(dev, DP_D);
4439 }
4426 } else if (IS_I8XX(dev)) 4440 } else if (IS_I8XX(dev))
4427 intel_dvo_init(dev); 4441 intel_dvo_init(dev);
4428 4442
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 4e7aa8b7b93..1349d9fd01c 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1402,14 +1402,20 @@ intel_dp_init(struct drm_device *dev, int output_reg)
1402 break; 1402 break;
1403 case DP_B: 1403 case DP_B:
1404 case PCH_DP_B: 1404 case PCH_DP_B:
1405 dev_priv->hotplug_supported_mask |=
1406 HDMIB_HOTPLUG_INT_STATUS;
1405 name = "DPDDC-B"; 1407 name = "DPDDC-B";
1406 break; 1408 break;
1407 case DP_C: 1409 case DP_C:
1408 case PCH_DP_C: 1410 case PCH_DP_C:
1411 dev_priv->hotplug_supported_mask |=
1412 HDMIC_HOTPLUG_INT_STATUS;
1409 name = "DPDDC-C"; 1413 name = "DPDDC-C";
1410 break; 1414 break;
1411 case DP_D: 1415 case DP_D:
1412 case PCH_DP_D: 1416 case PCH_DP_D:
1417 dev_priv->hotplug_supported_mask |=
1418 HDMID_HOTPLUG_INT_STATUS;
1413 name = "DPDDC-D"; 1419 name = "DPDDC-D";
1414 break; 1420 break;
1415 } 1421 }
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index f04dbbe7d40..06431941b23 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -303,21 +303,26 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
303 if (sdvox_reg == SDVOB) { 303 if (sdvox_reg == SDVOB) {
304 intel_output->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT); 304 intel_output->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
305 intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB"); 305 intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB");
306 dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
306 } else if (sdvox_reg == SDVOC) { 307 } else if (sdvox_reg == SDVOC) {
307 intel_output->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT); 308 intel_output->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
308 intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC"); 309 intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC");
310 dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
309 } else if (sdvox_reg == HDMIB) { 311 } else if (sdvox_reg == HDMIB) {
310 intel_output->clone_mask = (1 << INTEL_HDMID_CLONE_BIT); 312 intel_output->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
311 intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOE, 313 intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOE,
312 "HDMIB"); 314 "HDMIB");
315 dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
313 } else if (sdvox_reg == HDMIC) { 316 } else if (sdvox_reg == HDMIC) {
314 intel_output->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT); 317 intel_output->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
315 intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOD, 318 intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOD,
316 "HDMIC"); 319 "HDMIC");
320 dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
317 } else if (sdvox_reg == HDMID) { 321 } else if (sdvox_reg == HDMID) {
318 intel_output->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT); 322 intel_output->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
319 intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOF, 323 intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOF,
320 "HDMID"); 324 "HDMID");
325 dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
321 } 326 }
322 if (!intel_output->ddc_bus) 327 if (!intel_output->ddc_bus)
323 goto err_connector; 328 goto err_connector;
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 24a3dc99716..de5144c8c15 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2662,6 +2662,7 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
2662 2662
2663bool intel_sdvo_init(struct drm_device *dev, int output_device) 2663bool intel_sdvo_init(struct drm_device *dev, int output_device)
2664{ 2664{
2665 struct drm_i915_private *dev_priv = dev->dev_private;
2665 struct drm_connector *connector; 2666 struct drm_connector *connector;
2666 struct intel_output *intel_output; 2667 struct intel_output *intel_output;
2667 struct intel_sdvo_priv *sdvo_priv; 2668 struct intel_sdvo_priv *sdvo_priv;
@@ -2708,10 +2709,12 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
2708 intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS"); 2709 intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS");
2709 sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA, 2710 sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
2710 "SDVOB/VGA DDC BUS"); 2711 "SDVOB/VGA DDC BUS");
2712 dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS;
2711 } else { 2713 } else {
2712 intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS"); 2714 intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS");
2713 sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA, 2715 sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
2714 "SDVOC/VGA DDC BUS"); 2716 "SDVOC/VGA DDC BUS");
2717 dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS;
2715 } 2718 }
2716 2719
2717 if (intel_output->ddc_bus == NULL) 2720 if (intel_output->ddc_bus == NULL)
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 552ec110b74..1d5b9b7b033 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1840,6 +1840,8 @@ intel_tv_init(struct drm_device *dev)
1840 drm_connector_attach_property(connector, 1840 drm_connector_attach_property(connector,
1841 dev->mode_config.tv_bottom_margin_property, 1841 dev->mode_config.tv_bottom_margin_property,
1842 tv_priv->margin[TV_MARGIN_BOTTOM]); 1842 tv_priv->margin[TV_MARGIN_BOTTOM]);
1843
1844 dev_priv->hotplug_supported_mask |= TV_HOTPLUG_INT_STATUS;
1843out: 1845out:
1844 drm_sysfs_connector_add(connector); 1846 drm_sysfs_connector_add(connector);
1845} 1847}