Unpowered type-c dongles can take some time to boot and be responsible, causing the probe to fail and sink never be detected without further actions from userspace. It was not a issue for older platforms because there was a hardware bridge between DDI/DP ports and type-c controller adding a implicit delay that hid this issue but ICL have type-c controllers integrated to the SOC bring this issue to users. So here after the first probe interation over every connector with a hotplug event set, it sleeps for half a second to give some time to dongles to be ready and then try to probe again every type-c connector that failed in the initial probe. Cc: Imre Deak <imre.deak@xxxxxxxxx> Signed-off-by: José Roberto de Souza <jose.souza@xxxxxxxxx> --- drivers/gpu/drm/i915/intel_dp.c | 3 +++ drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_hotplug.c | 39 +++++++++++++++++++++++----- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index cf709835fb9a..b91b9700755f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -6968,6 +6968,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); } + if (intel_port_is_tc(dev_priv, port) && !intel_dig_port->tc_legacy_port) + intel_dig_port->tc_delay_wa_needed = true; + return true; fail: diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index fd50c962eaa3..3ae95679c2a9 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1257,7 +1257,7 @@ struct intel_digital_port { /* Used for DP and ICL+ TypeC/DP and TypeC/HDMI ports. */ enum aux_ch aux_ch; enum intel_display_power_domain ddi_io_power_domain; - bool tc_legacy_port:1; + bool tc_legacy_port:1, tc_delay_wa_needed:1; enum tc_port_type tc_type; void (*write_infoframe)(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c index 72e0203bcbb2..eeac29f2dc70 100644 --- a/drivers/gpu/drm/i915/intel_hotplug.c +++ b/drivers/gpu/drm/i915/intel_hotplug.c @@ -343,7 +343,7 @@ static void i915_digport_work_func(struct work_struct *work) } static bool -i915_hotplug_iterate(struct drm_device *dev, u32 hpd_event_bits) +i915_hotplug_iterate(struct drm_device *dev, u32 hpd_event_bits, u32 *hpd_tc_delay_wa) { struct drm_connector_list_iter conn_iter; struct drm_connector *connector; @@ -356,16 +356,27 @@ i915_hotplug_iterate(struct drm_device *dev, u32 hpd_event_bits) intel_connector = to_intel_connector(connector); intel_encoder = intel_connector->encoder; - if (!intel_encoder) continue; if (hpd_event_bits & (1 << intel_encoder->hpd_pin)) { + bool ret; + DRM_DEBUG_KMS("Connector %s (pin %i) received hotplug event.\n", connector->name, intel_encoder->hpd_pin); - changed |= intel_encoder->hotplug(intel_encoder, - intel_connector); + ret = intel_encoder->hotplug(intel_encoder, + intel_connector); + changed |= ret; + + if (hpd_tc_delay_wa && !ret && + connector->status != connector_status_connected) { + struct intel_digital_port *dig_port = enc_to_dig_port(&intel_encoder->base); + + if (dig_port && dig_port->tc_delay_wa_needed && + !dig_port->dp.is_mst) + *hpd_tc_delay_wa |= (1 << intel_encoder->hpd_pin); + } } } drm_connector_list_iter_end(&conn_iter); @@ -382,7 +393,7 @@ static void i915_hotplug_work_func(struct work_struct *work) container_of(work, struct drm_i915_private, hotplug.hotplug_work); struct drm_device *dev = &dev_priv->drm; bool changed; - u32 hpd_event_bits; + u32 hpd_event_bits, hpd_tc_delay_wa = 0; mutex_lock(&dev->mode_config.mutex); DRM_DEBUG_KMS("running encoder hotplug functions\n"); @@ -397,12 +408,28 @@ static void i915_hotplug_work_func(struct work_struct *work) spin_unlock_irq(&dev_priv->irq_lock); - changed = i915_hotplug_iterate(dev, hpd_event_bits); + changed = i915_hotplug_iterate(dev, hpd_event_bits, &hpd_tc_delay_wa); mutex_unlock(&dev->mode_config.mutex); if (changed) drm_kms_helper_hotplug_event(dev); + + /* + * Unpowered type-c dongles can take some time to boot and be + * responsible, so here giving some type to those dongles to power up + * and then probing again. + */ + if (hpd_tc_delay_wa) { + msleep(500); + + mutex_lock(&dev->mode_config.mutex); + changed = i915_hotplug_iterate(dev, hpd_tc_delay_wa, NULL); + mutex_unlock(&dev->mode_config.mutex); + + if (changed) + drm_kms_helper_hotplug_event(dev); + } } -- 2.20.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx