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>
This commit is contained in:
parent
b295d1b6e3
commit
b01f2c3a4a
|
@ -1249,6 +1249,8 @@ static int i915_load_modeset_init(struct drm_device *dev,
|
|||
if (ret)
|
||||
goto destroy_ringbuffer;
|
||||
|
||||
intel_modeset_init(dev);
|
||||
|
||||
ret = drm_irq_install(dev);
|
||||
if (ret)
|
||||
goto destroy_ringbuffer;
|
||||
|
@ -1263,8 +1265,6 @@ static int i915_load_modeset_init(struct drm_device *dev,
|
|||
|
||||
I915_WRITE(INSTPM, (1 << 5) | (1 << 21));
|
||||
|
||||
intel_modeset_init(dev);
|
||||
|
||||
drm_helper_initial_config(dev);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1084,6 +1084,10 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
|
|||
(void) I915_READ(IER);
|
||||
}
|
||||
|
||||
/*
|
||||
* Must be called after intel_modeset_init or hotplug interrupts won't be
|
||||
* enabled correctly.
|
||||
*/
|
||||
int i915_driver_irq_postinstall(struct drm_device *dev)
|
||||
{
|
||||
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)
|
|||
if (I915_HAS_HOTPLUG(dev)) {
|
||||
u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
|
||||
|
||||
/* Leave other bits alone */
|
||||
hotplug_en |= HOTPLUG_EN_MASK;
|
||||
/* Note HDMI and DP share bits */
|
||||
if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
|
||||
hotplug_en |= HDMIB_HOTPLUG_INT_EN;
|
||||
if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
|
||||
hotplug_en |= HDMIC_HOTPLUG_INT_EN;
|
||||
if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
|
||||
hotplug_en |= HDMID_HOTPLUG_INT_EN;
|
||||
if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
|
||||
hotplug_en |= SDVOC_HOTPLUG_INT_EN;
|
||||
if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
|
||||
hotplug_en |= SDVOB_HOTPLUG_INT_EN;
|
||||
if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS)
|
||||
hotplug_en |= CRT_HOTPLUG_INT_EN;
|
||||
/* Ignore TV since it's buggy */
|
||||
|
||||
I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
|
||||
|
||||
dev_priv->hotplug_supported_mask = CRT_HOTPLUG_INT_STATUS |
|
||||
TV_HOTPLUG_INT_STATUS | SDVOC_HOTPLUG_INT_STATUS |
|
||||
SDVOB_HOTPLUG_INT_STATUS;
|
||||
if (IS_G4X(dev)) {
|
||||
dev_priv->hotplug_supported_mask |=
|
||||
HDMIB_HOTPLUG_INT_STATUS |
|
||||
HDMIC_HOTPLUG_INT_STATUS |
|
||||
HDMID_HOTPLUG_INT_STATUS;
|
||||
}
|
||||
/* Enable in IER... */
|
||||
enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
|
||||
/* and unmask in IMR */
|
||||
|
|
|
@ -879,13 +879,6 @@
|
|||
#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2)
|
||||
#define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */
|
||||
#define CRT_FORCE_HOTPLUG_MASK 0xfffffe1f
|
||||
#define HOTPLUG_EN_MASK (HDMIB_HOTPLUG_INT_EN | \
|
||||
HDMIC_HOTPLUG_INT_EN | \
|
||||
HDMID_HOTPLUG_INT_EN | \
|
||||
SDVOB_HOTPLUG_INT_EN | \
|
||||
SDVOC_HOTPLUG_INT_EN | \
|
||||
CRT_HOTPLUG_INT_EN)
|
||||
|
||||
|
||||
#define PORT_HOTPLUG_STAT 0x61114
|
||||
#define HDMIB_HOTPLUG_INT_STATUS (1 << 29)
|
||||
|
|
|
@ -548,4 +548,6 @@ void intel_crt_init(struct drm_device *dev)
|
|||
drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
|
||||
|
||||
drm_sysfs_connector_add(connector);
|
||||
|
||||
dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS;
|
||||
}
|
||||
|
|
|
@ -4400,29 +4400,43 @@ static void intel_setup_outputs(struct drm_device *dev)
|
|||
bool found = false;
|
||||
|
||||
if (I915_READ(SDVOB) & SDVO_DETECTED) {
|
||||
DRM_DEBUG_KMS("probing SDVOB\n");
|
||||
found = intel_sdvo_init(dev, SDVOB);
|
||||
if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
|
||||
if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) {
|
||||
DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
|
||||
intel_hdmi_init(dev, SDVOB);
|
||||
}
|
||||
|
||||
if (!found && SUPPORTS_INTEGRATED_DP(dev))
|
||||
if (!found && SUPPORTS_INTEGRATED_DP(dev)) {
|
||||
DRM_DEBUG_KMS("probing DP_B\n");
|
||||
intel_dp_init(dev, DP_B);
|
||||
}
|
||||
}
|
||||
|
||||
/* Before G4X SDVOC doesn't have its own detect register */
|
||||
|
||||
if (I915_READ(SDVOB) & SDVO_DETECTED)
|
||||
if (I915_READ(SDVOB) & SDVO_DETECTED) {
|
||||
DRM_DEBUG_KMS("probing SDVOC\n");
|
||||
found = intel_sdvo_init(dev, SDVOC);
|
||||
}
|
||||
|
||||
if (!found && (I915_READ(SDVOC) & SDVO_DETECTED)) {
|
||||
|
||||
if (SUPPORTS_INTEGRATED_HDMI(dev))
|
||||
if (SUPPORTS_INTEGRATED_HDMI(dev)) {
|
||||
DRM_DEBUG_KMS("probing HDMI on SDVOC\n");
|
||||
intel_hdmi_init(dev, SDVOC);
|
||||
if (SUPPORTS_INTEGRATED_DP(dev))
|
||||
}
|
||||
if (SUPPORTS_INTEGRATED_DP(dev)) {
|
||||
DRM_DEBUG_KMS("probing DP_C\n");
|
||||
intel_dp_init(dev, DP_C);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED))
|
||||
if (SUPPORTS_INTEGRATED_DP(dev) &&
|
||||
(I915_READ(DP_D) & DP_DETECTED)) {
|
||||
DRM_DEBUG_KMS("probing DP_D\n");
|
||||
intel_dp_init(dev, DP_D);
|
||||
}
|
||||
} else if (IS_I8XX(dev))
|
||||
intel_dvo_init(dev);
|
||||
|
||||
|
|
|
@ -1402,14 +1402,20 @@ intel_dp_init(struct drm_device *dev, int output_reg)
|
|||
break;
|
||||
case DP_B:
|
||||
case PCH_DP_B:
|
||||
dev_priv->hotplug_supported_mask |=
|
||||
HDMIB_HOTPLUG_INT_STATUS;
|
||||
name = "DPDDC-B";
|
||||
break;
|
||||
case DP_C:
|
||||
case PCH_DP_C:
|
||||
dev_priv->hotplug_supported_mask |=
|
||||
HDMIC_HOTPLUG_INT_STATUS;
|
||||
name = "DPDDC-C";
|
||||
break;
|
||||
case DP_D:
|
||||
case PCH_DP_D:
|
||||
dev_priv->hotplug_supported_mask |=
|
||||
HDMID_HOTPLUG_INT_STATUS;
|
||||
name = "DPDDC-D";
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -303,21 +303,26 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
|
|||
if (sdvox_reg == SDVOB) {
|
||||
intel_output->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB");
|
||||
dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
|
||||
} else if (sdvox_reg == SDVOC) {
|
||||
intel_output->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC");
|
||||
dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
|
||||
} else if (sdvox_reg == HDMIB) {
|
||||
intel_output->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOE,
|
||||
"HDMIB");
|
||||
dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
|
||||
} else if (sdvox_reg == HDMIC) {
|
||||
intel_output->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOD,
|
||||
"HDMIC");
|
||||
dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
|
||||
} else if (sdvox_reg == HDMID) {
|
||||
intel_output->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOF,
|
||||
"HDMID");
|
||||
dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
|
||||
}
|
||||
if (!intel_output->ddc_bus)
|
||||
goto err_connector;
|
||||
|
|
|
@ -2662,6 +2662,7 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
|
|||
|
||||
bool intel_sdvo_init(struct drm_device *dev, int output_device)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_connector *connector;
|
||||
struct intel_output *intel_output;
|
||||
struct intel_sdvo_priv *sdvo_priv;
|
||||
|
@ -2708,10 +2709,12 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
|
|||
intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS");
|
||||
sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
|
||||
"SDVOB/VGA DDC BUS");
|
||||
dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS;
|
||||
} else {
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS");
|
||||
sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
|
||||
"SDVOC/VGA DDC BUS");
|
||||
dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS;
|
||||
}
|
||||
|
||||
if (intel_output->ddc_bus == NULL)
|
||||
|
|
|
@ -1840,6 +1840,8 @@ intel_tv_init(struct drm_device *dev)
|
|||
drm_connector_attach_property(connector,
|
||||
dev->mode_config.tv_bottom_margin_property,
|
||||
tv_priv->margin[TV_MARGIN_BOTTOM]);
|
||||
|
||||
dev_priv->hotplug_supported_mask |= TV_HOTPLUG_INT_STATUS;
|
||||
out:
|
||||
drm_sysfs_connector_add(connector);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue