diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_hotplug.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_hotplug.c | 53 |
1 files changed, 43 insertions, 10 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c index 4f6f560e093e..3f1d7b804a66 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug.c @@ -89,6 +89,15 @@ enum hpd_pin intel_hpd_pin_default(struct drm_i915_private *dev_priv, { enum phy phy = intel_port_to_phy(dev_priv, port); + /* + * RKL + TGP PCH is a special case; we effectively choose the hpd_pin + * based on the DDI rather than the PHY (i.e., the last two outputs + * shold be HPD_PORT_{D,E} rather than {C,D}. Note that this differs + * from the behavior of both TGL+TGP and RKL+CMP. + */ + if (IS_ROCKETLAKE(dev_priv) && HAS_PCH_TGP(dev_priv)) + return HPD_PORT_A + port - PORT_A; + switch (phy) { case PHY_F: return IS_CNL_WITH_PORT_F(dev_priv) ? HPD_PORT_E : HPD_PORT_F; @@ -274,24 +283,30 @@ intel_encoder_hotplug(struct intel_encoder *encoder, { struct drm_device *dev = connector->base.dev; enum drm_connector_status old_status; + u64 old_epoch_counter; + bool ret = false; drm_WARN_ON(dev, !mutex_is_locked(&dev->mode_config.mutex)); old_status = connector->base.status; + old_epoch_counter = connector->base.epoch_counter; connector->base.status = drm_helper_probe_detect(&connector->base, NULL, false); - if (old_status == connector->base.status) - return INTEL_HOTPLUG_UNCHANGED; - - drm_dbg_kms(&to_i915(dev)->drm, - "[CONNECTOR:%d:%s] status updated from %s to %s\n", - connector->base.base.id, - connector->base.name, - drm_get_connector_status_name(old_status), - drm_get_connector_status_name(connector->base.status)); + if (old_epoch_counter != connector->base.epoch_counter) + ret = true; - return INTEL_HOTPLUG_CHANGED; + if (ret) { + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s (epoch counter %llu->%llu)\n", + connector->base.base.id, + connector->base.name, + drm_get_connector_status_name(old_status), + drm_get_connector_status_name(connector->base.status), + old_epoch_counter, + connector->base.epoch_counter); + return INTEL_HOTPLUG_CHANGED; + } + return INTEL_HOTPLUG_UNCHANGED; } static bool intel_encoder_has_hpd_pulse(struct intel_encoder *encoder) @@ -347,6 +362,24 @@ static void i915_digport_work_func(struct work_struct *work) } } +/** + * intel_hpd_trigger_irq - trigger an hpd irq event for a port + * @dig_port: digital port + * + * Trigger an HPD interrupt event for the given port, emulating a short pulse + * generated by the sink, and schedule the dig port work to handle it. + */ +void intel_hpd_trigger_irq(struct intel_digital_port *dig_port) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + + spin_lock_irq(&i915->irq_lock); + i915->hotplug.short_port_mask |= BIT(dig_port->base.port); + spin_unlock_irq(&i915->irq_lock); + + queue_work(i915->hotplug.dp_wq, &i915->hotplug.dig_port_work); +} + /* * Handle hotplug events outside the interrupt handler proper. */ |