Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b01f2c3a authored by Jesse Barnes's avatar Jesse Barnes Committed by Eric Anholt
Browse files

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: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: default avatarEric Anholt <eric@anholt.net>
parent b295d1b6
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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;
+19 −11
Original line number Diff line number Diff line
@@ -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 */
+0 −7
Original line number Diff line number Diff line
@@ -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)
+2 −0
Original line number Diff line number Diff line
@@ -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;
}
+20 −6
Original line number Diff line number Diff line
@@ -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);

Loading