|
@@ -397,37 +397,54 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
|
|
struct intel_encoder *encoder;
|
|
struct intel_encoder *encoder;
|
|
bool storm_detected = false;
|
|
bool storm_detected = false;
|
|
bool queue_dig = false, queue_hp = false;
|
|
bool queue_dig = false, queue_hp = false;
|
|
|
|
+ u32 long_hpd_pulse_mask = 0;
|
|
|
|
+ u32 short_hpd_pulse_mask = 0;
|
|
|
|
+ enum hpd_pin pin;
|
|
|
|
|
|
if (!pin_mask)
|
|
if (!pin_mask)
|
|
return;
|
|
return;
|
|
|
|
|
|
spin_lock(&dev_priv->irq_lock);
|
|
spin_lock(&dev_priv->irq_lock);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Determine whether ->hpd_pulse() exists for each pin, and
|
|
|
|
+ * whether we have a short or a long pulse. This is needed
|
|
|
|
+ * as each pin may have up to two encoders (HDMI and DP) and
|
|
|
|
+ * only the one of them (DP) will have ->hpd_pulse().
|
|
|
|
+ */
|
|
for_each_intel_encoder(&dev_priv->drm, encoder) {
|
|
for_each_intel_encoder(&dev_priv->drm, encoder) {
|
|
- enum hpd_pin pin = encoder->hpd_pin;
|
|
|
|
bool has_hpd_pulse = intel_encoder_has_hpd_pulse(encoder);
|
|
bool has_hpd_pulse = intel_encoder_has_hpd_pulse(encoder);
|
|
|
|
+ enum port port = encoder->port;
|
|
|
|
+ bool long_hpd;
|
|
|
|
|
|
|
|
+ pin = encoder->hpd_pin;
|
|
if (!(BIT(pin) & pin_mask))
|
|
if (!(BIT(pin) & pin_mask))
|
|
continue;
|
|
continue;
|
|
|
|
|
|
- if (has_hpd_pulse) {
|
|
|
|
- bool long_hpd = long_mask & BIT(pin);
|
|
|
|
- enum port port = encoder->port;
|
|
|
|
|
|
+ if (!has_hpd_pulse)
|
|
|
|
+ continue;
|
|
|
|
|
|
- DRM_DEBUG_DRIVER("digital hpd port %c - %s\n", port_name(port),
|
|
|
|
- long_hpd ? "long" : "short");
|
|
|
|
- /*
|
|
|
|
- * For long HPD pulses we want to have the digital queue happen,
|
|
|
|
- * but we still want HPD storm detection to function.
|
|
|
|
- */
|
|
|
|
- queue_dig = true;
|
|
|
|
- if (long_hpd) {
|
|
|
|
- dev_priv->hotplug.long_port_mask |= (1 << port);
|
|
|
|
- } else {
|
|
|
|
- /* for short HPD just trigger the digital queue */
|
|
|
|
- dev_priv->hotplug.short_port_mask |= (1 << port);
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
|
|
+ long_hpd = long_mask & BIT(pin);
|
|
|
|
+
|
|
|
|
+ DRM_DEBUG_DRIVER("digital hpd port %c - %s\n", port_name(port),
|
|
|
|
+ long_hpd ? "long" : "short");
|
|
|
|
+ queue_dig = true;
|
|
|
|
+
|
|
|
|
+ if (long_hpd) {
|
|
|
|
+ long_hpd_pulse_mask |= BIT(pin);
|
|
|
|
+ dev_priv->hotplug.long_port_mask |= BIT(port);
|
|
|
|
+ } else {
|
|
|
|
+ short_hpd_pulse_mask |= BIT(pin);
|
|
|
|
+ dev_priv->hotplug.short_port_mask |= BIT(port);
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Now process each pin just once */
|
|
|
|
+ for_each_hpd_pin(pin) {
|
|
|
|
+ bool long_hpd;
|
|
|
|
+
|
|
|
|
+ if (!(BIT(pin) & pin_mask))
|
|
|
|
+ continue;
|
|
|
|
|
|
if (dev_priv->hotplug.stats[pin].state == HPD_DISABLED) {
|
|
if (dev_priv->hotplug.stats[pin].state == HPD_DISABLED) {
|
|
/*
|
|
/*
|
|
@@ -444,11 +461,22 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
|
|
if (dev_priv->hotplug.stats[pin].state != HPD_ENABLED)
|
|
if (dev_priv->hotplug.stats[pin].state != HPD_ENABLED)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
- if (!has_hpd_pulse) {
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Delegate to ->hpd_pulse() if one of the encoders for this
|
|
|
|
+ * pin has it, otherwise let the hotplug_work deal with this
|
|
|
|
+ * pin directly.
|
|
|
|
+ */
|
|
|
|
+ if (((short_hpd_pulse_mask | long_hpd_pulse_mask) & BIT(pin))) {
|
|
|
|
+ long_hpd = long_hpd_pulse_mask & BIT(pin);
|
|
|
|
+ } else {
|
|
dev_priv->hotplug.event_bits |= BIT(pin);
|
|
dev_priv->hotplug.event_bits |= BIT(pin);
|
|
|
|
+ long_hpd = true;
|
|
queue_hp = true;
|
|
queue_hp = true;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (!long_hpd)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
if (intel_hpd_irq_storm_detect(dev_priv, pin)) {
|
|
if (intel_hpd_irq_storm_detect(dev_priv, pin)) {
|
|
dev_priv->hotplug.event_bits &= ~BIT(pin);
|
|
dev_priv->hotplug.event_bits &= ~BIT(pin);
|
|
storm_detected = true;
|
|
storm_detected = true;
|