From: Egbert Eich Date: Thu, 11 Apr 2013 14:00:26 +0000 (+0200) Subject: drm/i915: Only reprobe display on encoder which has received an HPD event (v2) X-Git-Tag: next-20130521~50^2~124 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=321a1b3026ea194dd084cf3bda1e235b2986b0af;p=karo-tx-linux.git drm/i915: Only reprobe display on encoder which has received an HPD event (v2) Instead of calling into the DRM helper layer to poll all connectors for changes in connected displays probe only those connectors which have received a hotplug event. v2: Resolved conflicts with changes in previous commits. Renamed function and and added a WARN_ON() to warn of intel_hpd_irq_event() from being called without mode_config.mutex held - suggested by Jani Nikula. Signed-off-by: Egbert Eich Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index e37820199b26..7c81f0fb721a 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -541,6 +541,21 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe, crtc); } +static int intel_hpd_irq_event(struct drm_device *dev, struct drm_connector *connector) +{ + enum drm_connector_status old_status; + + WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); + old_status = connector->status; + + connector->status = connector->funcs->detect(connector, false); + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n", + connector->base.id, + drm_get_connector_name(connector), + old_status, connector->status); + return (old_status != connector->status); +} + /* * Handle hotplug events outside the interrupt handler proper. */ @@ -557,6 +572,7 @@ static void i915_hotplug_work_func(struct work_struct *work) struct drm_connector *connector; unsigned long irqflags; bool hpd_disabled = false; + bool changed = false; u32 hpd_event_bits; /* HPD irq before everything is fully set up. */ @@ -600,14 +616,20 @@ static void i915_hotplug_work_func(struct work_struct *work) spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); - list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head) - if (intel_encoder->hot_plug) - intel_encoder->hot_plug(intel_encoder); - + list_for_each_entry(connector, &mode_config->connector_list, head) { + intel_connector = to_intel_connector(connector); + intel_encoder = intel_connector->encoder; + if (hpd_event_bits & (1 << intel_encoder->hpd_pin)) { + if (intel_encoder->hot_plug) + intel_encoder->hot_plug(intel_encoder); + if (intel_hpd_irq_event(dev, connector)) + changed = true; + } + } mutex_unlock(&mode_config->mutex); - /* Just fire off a uevent and let userspace tell us what to do */ - drm_helper_hpd_irq_event(dev); + if (changed) + drm_kms_helper_hotplug_event(dev); } static void ironlake_handle_rps_change(struct drm_device *dev)