Commit 821450c6 authored by Egbert Eich's avatar Egbert Eich Committed by Daniel Vetter

drm/i915: (re)init HPD interrupt storm statistics

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: default avatarEgbert Eich <eich@suse.de>
Reviewed-by: default avatarJani Nikula <jani.nikula@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent b543fb04
...@@ -596,6 +596,7 @@ static inline void hotplug_irq_storm_detect(struct drm_device *dev, ...@@ -596,6 +596,7 @@ static inline void hotplug_irq_storm_detect(struct drm_device *dev,
spin_lock_irqsave(&dev_priv->irq_lock, irqflags); spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
for (i = 1; i < HPD_NUM_PINS; i++) { for (i = 1; i < HPD_NUM_PINS; i++) {
if (!(hpd[i] & hotplug_trigger) || if (!(hpd[i] & hotplug_trigger) ||
dev_priv->hpd_stats[i].hpd_mark != HPD_ENABLED) dev_priv->hpd_stats[i].hpd_mark != HPD_ENABLED)
continue; continue;
...@@ -3062,7 +3063,20 @@ void intel_irq_init(struct drm_device *dev) ...@@ -3062,7 +3063,20 @@ void intel_irq_init(struct drm_device *dev)
void intel_hpd_init(struct drm_device *dev) void intel_hpd_init(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; 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) if (dev_priv->display.hpd_irq_setup)
dev_priv->display.hpd_irq_setup(dev); dev_priv->display.hpd_irq_setup(dev);
} }
...@@ -793,10 +793,8 @@ void intel_crt_init(struct drm_device *dev) ...@@ -793,10 +793,8 @@ void intel_crt_init(struct drm_device *dev)
drm_sysfs_connector_add(connector); drm_sysfs_connector_add(connector);
if (I915_HAS_HOTPLUG(dev)) if (!I915_HAS_HOTPLUG(dev))
connector->polled = DRM_CONNECTOR_POLL_HPD; intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
else
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
/* /*
* Configure the automatic hotplug detection stuff * Configure the automatic hotplug detection stuff
......
...@@ -2787,7 +2787,6 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, ...@@ -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_init(dev, connector, &intel_dp_connector_funcs, type);
drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs); drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
connector->polled = DRM_CONNECTOR_POLL_HPD;
connector->interlace_allowed = true; connector->interlace_allowed = true;
connector->doublescan_allowed = 0; connector->doublescan_allowed = 0;
......
...@@ -171,6 +171,10 @@ struct intel_connector { ...@@ -171,6 +171,10 @@ struct intel_connector {
/* Cached EDID for eDP and LVDS. May hold ERR_PTR for invalid EDID. */ /* Cached EDID for eDP and LVDS. May hold ERR_PTR for invalid EDID. */
struct edid *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 { struct intel_crtc_config {
......
...@@ -998,7 +998,6 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, ...@@ -998,7 +998,6 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
DRM_MODE_CONNECTOR_HDMIA); DRM_MODE_CONNECTOR_HDMIA);
drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs);
connector->polled = DRM_CONNECTOR_POLL_HPD;
connector->interlace_allowed = 1; connector->interlace_allowed = 1;
connector->doublescan_allowed = 0; connector->doublescan_allowed = 0;
......
...@@ -2274,7 +2274,6 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) ...@@ -2274,7 +2274,6 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
connector = &intel_connector->base; connector = &intel_connector->base;
if (intel_sdvo_get_hotplug_support(intel_sdvo) & if (intel_sdvo_get_hotplug_support(intel_sdvo) &
intel_sdvo_connector->output_flag) { intel_sdvo_connector->output_flag) {
connector->polled = DRM_CONNECTOR_POLL_HPD;
intel_sdvo->hotplug_active |= intel_sdvo_connector->output_flag; intel_sdvo->hotplug_active |= intel_sdvo_connector->output_flag;
/* Some SDVO devices have one-shot hotplug interrupts. /* Some SDVO devices have one-shot hotplug interrupts.
* Ensure that they get re-enabled when an interrupt happens. * 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) ...@@ -2282,7 +2281,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
intel_encoder->hot_plug = intel_sdvo_enable_hotplug; intel_encoder->hot_plug = intel_sdvo_enable_hotplug;
intel_sdvo_enable_hotplug(intel_encoder); intel_sdvo_enable_hotplug(intel_encoder);
} else { } 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; encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
connector->connector_type = DRM_MODE_CONNECTOR_DVID; connector->connector_type = DRM_MODE_CONNECTOR_DVID;
...@@ -2351,7 +2350,7 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device) ...@@ -2351,7 +2350,7 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)
intel_connector = &intel_sdvo_connector->base; intel_connector = &intel_sdvo_connector->base;
connector = &intel_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; encoder->encoder_type = DRM_MODE_ENCODER_DAC;
connector->connector_type = DRM_MODE_CONNECTOR_VGA; connector->connector_type = DRM_MODE_CONNECTOR_VGA;
......
...@@ -1613,7 +1613,7 @@ intel_tv_init(struct drm_device *dev) ...@@ -1613,7 +1613,7 @@ intel_tv_init(struct drm_device *dev)
* *
* More recent chipsets favour HDMI rather than integrated S-Video. * 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_connector_init(dev, connector, &intel_tv_connector_funcs,
DRM_MODE_CONNECTOR_SVIDEO); DRM_MODE_CONNECTOR_SVIDEO);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment