drm/i915: (re)init HPD interrupt storm statistics
authorEgbert Eich <eich@suse.de>
Tue, 16 Apr 2013 11:36:55 +0000 (13:36 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Thu, 18 Apr 2013 07:43:29 +0000 (09:43 +0200)
When an encoder is shared on several connectors there is only
one hotplug line, thus this line needs to be shared among these
connectors.
If HPD detect only works reliably on a subset of those connectors,
we want to poll the others. Thus we need to make sure that storm
detection doesn't mess up the settings for those connectors.
Therefore we store the settings in the intel_connector struct and
restore them from there.
If nothing is set but the encoder has a hpd_pin set we assume this
connector is hotplug capable.
On init/reset we make sure the polled state of the connectors
is (re)set to the default value, the HPD interrupts are marked
enabled.

Signed-off-by: Egbert Eich <eich@suse.de>
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_tv.c

index 5ac1291c5853f737edcf6b28aedc469e8d8f7cfe..2b4967014dc65e7b7854bcbe7f3d0644b2765c90 100644 (file)
@@ -596,6 +596,7 @@ static inline void hotplug_irq_storm_detect(struct drm_device *dev,
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 
        for (i = 1; i < HPD_NUM_PINS; i++) {
+
                if (!(hpd[i] & hotplug_trigger) ||
                    dev_priv->hpd_stats[i].hpd_mark != HPD_ENABLED)
                        continue;
@@ -3062,7 +3063,20 @@ void intel_irq_init(struct drm_device *dev)
 void intel_hpd_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_mode_config *mode_config = &dev->mode_config;
+       struct drm_connector *connector;
+       int i;
 
+       for (i = 1; i < HPD_NUM_PINS; i++) {
+               dev_priv->hpd_stats[i].hpd_cnt = 0;
+               dev_priv->hpd_stats[i].hpd_mark = HPD_ENABLED;
+       }
+       list_for_each_entry(connector, &mode_config->connector_list, head) {
+               struct intel_connector *intel_connector = to_intel_connector(connector);
+               connector->polled = intel_connector->polled;
+               if (!connector->polled && I915_HAS_HOTPLUG(dev) && intel_connector->encoder->hpd_pin > HPD_NONE)
+                       connector->polled = DRM_CONNECTOR_POLL_HPD;
+       }
        if (dev_priv->display.hpd_irq_setup)
                dev_priv->display.hpd_irq_setup(dev);
 }
index 1ae2d7f39c6fbf13537b478cbc4bc40fc46006fa..c063b9f0dd519e9a2ba167b585f8f78ba6c49544 100644 (file)
@@ -793,10 +793,8 @@ void intel_crt_init(struct drm_device *dev)
 
        drm_sysfs_connector_add(connector);
 
-       if (I915_HAS_HOTPLUG(dev))
-               connector->polled = DRM_CONNECTOR_POLL_HPD;
-       else
-               connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+       if (!I915_HAS_HOTPLUG(dev))
+               intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 
        /*
         * Configure the automatic hotplug detection stuff
index 8845e82ec9ed7941762dfaaa06905936279f633b..89f89b7279007075d1ad2b3e230ddd433b8b9206 100644 (file)
@@ -2787,7 +2787,6 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
        drm_connector_init(dev, connector, &intel_dp_connector_funcs, type);
        drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
 
-       connector->polled = DRM_CONNECTOR_POLL_HPD;
        connector->interlace_allowed = true;
        connector->doublescan_allowed = 0;
 
index a124e05fb5810749a38c9054051f1f76a1b1d42c..7b97b9a1523e295ea1c3d6ddea53be3d8d225c55 100644 (file)
@@ -171,6 +171,10 @@ struct intel_connector {
 
        /* Cached EDID for eDP and LVDS. May hold ERR_PTR for invalid EDID. */
        struct edid *edid;
+
+       /* since POLL and HPD connectors may use the same HPD line keep the native
+          state of connector->polled in case hotplug storm detection changes it */
+       u8 polled;
 };
 
 struct intel_crtc_config {
index ee4a8da8311eea38fcfec396b630b7e114a1849a..89122011720b02e78574c1d65f297c314b05f9aa 100644 (file)
@@ -998,7 +998,6 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
                           DRM_MODE_CONNECTOR_HDMIA);
        drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs);
 
-       connector->polled = DRM_CONNECTOR_POLL_HPD;
        connector->interlace_allowed = 1;
        connector->doublescan_allowed = 0;
 
index f6a9f4a0d7f009640df98207ae7faca43294bacb..a618a6a45a7758a3383eb585089ecb8bff90d707 100644 (file)
@@ -2274,7 +2274,6 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
        connector = &intel_connector->base;
        if (intel_sdvo_get_hotplug_support(intel_sdvo) &
                intel_sdvo_connector->output_flag) {
-               connector->polled = DRM_CONNECTOR_POLL_HPD;
                intel_sdvo->hotplug_active |= intel_sdvo_connector->output_flag;
                /* Some SDVO devices have one-shot hotplug interrupts.
                 * Ensure that they get re-enabled when an interrupt happens.
@@ -2282,7 +2281,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
                intel_encoder->hot_plug = intel_sdvo_enable_hotplug;
                intel_sdvo_enable_hotplug(intel_encoder);
        } else {
-               connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
+               intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
        }
        encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
        connector->connector_type = DRM_MODE_CONNECTOR_DVID;
@@ -2351,7 +2350,7 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)
 
        intel_connector = &intel_sdvo_connector->base;
        connector = &intel_connector->base;
-       connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+       intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
        encoder->encoder_type = DRM_MODE_ENCODER_DAC;
        connector->connector_type = DRM_MODE_CONNECTOR_VGA;
 
index 66737265200f63bf0735d7a67ec8ca122211b6fe..b945bc54207a8ff63227e89e25bb0200af2fecaa 100644 (file)
@@ -1613,7 +1613,7 @@ intel_tv_init(struct drm_device *dev)
         *
         * More recent chipsets favour HDMI rather than integrated S-Video.
         */
-       connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+       intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 
        drm_connector_init(dev, connector, &intel_tv_connector_funcs,
                           DRM_MODE_CONNECTOR_SVIDEO);