|
@@ -337,6 +337,8 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe,
|
|
|
/*
|
|
|
* Handle hotplug events outside the interrupt handler proper.
|
|
|
*/
|
|
|
+#define I915_REENABLE_HOTPLUG_DELAY (2*60*1000)
|
|
|
+
|
|
|
static void i915_hotplug_work_func(struct work_struct *work)
|
|
|
{
|
|
|
drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
|
|
@@ -375,8 +377,11 @@ static void i915_hotplug_work_func(struct work_struct *work)
|
|
|
/* if there were no outputs to poll, poll was disabled,
|
|
|
* therefore make sure it's enabled when disabling HPD on
|
|
|
* some connectors */
|
|
|
- if (hpd_disabled)
|
|
|
+ if (hpd_disabled) {
|
|
|
drm_kms_helper_poll_enable(dev);
|
|
|
+ mod_timer(&dev_priv->hotplug_reenable_timer,
|
|
|
+ jiffies + msecs_to_jiffies(I915_REENABLE_HOTPLUG_DELAY));
|
|
|
+ }
|
|
|
|
|
|
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
|
|
|
|
|
@@ -2367,6 +2372,8 @@ static void valleyview_irq_uninstall(struct drm_device *dev)
|
|
|
if (!dev_priv)
|
|
|
return;
|
|
|
|
|
|
+ del_timer_sync(&dev_priv->hotplug_reenable_timer);
|
|
|
+
|
|
|
for_each_pipe(pipe)
|
|
|
I915_WRITE(PIPESTAT(pipe), 0xffff);
|
|
|
|
|
@@ -2388,6 +2395,8 @@ static void ironlake_irq_uninstall(struct drm_device *dev)
|
|
|
if (!dev_priv)
|
|
|
return;
|
|
|
|
|
|
+ del_timer_sync(&dev_priv->hotplug_reenable_timer);
|
|
|
+
|
|
|
I915_WRITE(HWSTAM, 0xffffffff);
|
|
|
|
|
|
I915_WRITE(DEIMR, 0xffffffff);
|
|
@@ -2767,6 +2776,8 @@ static void i915_irq_uninstall(struct drm_device * dev)
|
|
|
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
|
|
int pipe;
|
|
|
|
|
|
+ del_timer_sync(&dev_priv->hotplug_reenable_timer);
|
|
|
+
|
|
|
if (I915_HAS_HOTPLUG(dev)) {
|
|
|
I915_WRITE(PORT_HOTPLUG_EN, 0);
|
|
|
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
|
|
@@ -3011,6 +3022,8 @@ static void i965_irq_uninstall(struct drm_device * dev)
|
|
|
if (!dev_priv)
|
|
|
return;
|
|
|
|
|
|
+ del_timer_sync(&dev_priv->hotplug_reenable_timer);
|
|
|
+
|
|
|
I915_WRITE(PORT_HOTPLUG_EN, 0);
|
|
|
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
|
|
|
|
|
@@ -3026,6 +3039,41 @@ static void i965_irq_uninstall(struct drm_device * dev)
|
|
|
I915_WRITE(IIR, I915_READ(IIR));
|
|
|
}
|
|
|
|
|
|
+static void i915_reenable_hotplug_timer_func(unsigned long data)
|
|
|
+{
|
|
|
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *)data;
|
|
|
+ struct drm_device *dev = dev_priv->dev;
|
|
|
+ struct drm_mode_config *mode_config = &dev->mode_config;
|
|
|
+ unsigned long irqflags;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
|
|
+ for (i = (HPD_NONE + 1); i < HPD_NUM_PINS; i++) {
|
|
|
+ struct drm_connector *connector;
|
|
|
+
|
|
|
+ if (dev_priv->hpd_stats[i].hpd_mark != HPD_DISABLED)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ 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);
|
|
|
+
|
|
|
+ if (intel_connector->encoder->hpd_pin == i) {
|
|
|
+ if (connector->polled != intel_connector->polled)
|
|
|
+ DRM_DEBUG_DRIVER("Reenabling HPD on connector %s\n",
|
|
|
+ drm_get_connector_name(connector));
|
|
|
+ connector->polled = intel_connector->polled;
|
|
|
+ if (!connector->polled)
|
|
|
+ connector->polled = DRM_CONNECTOR_POLL_HPD;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (dev_priv->display.hpd_irq_setup)
|
|
|
+ dev_priv->display.hpd_irq_setup(dev);
|
|
|
+ spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
|
|
|
+}
|
|
|
+
|
|
|
void intel_irq_init(struct drm_device *dev)
|
|
|
{
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
@@ -3038,6 +3086,8 @@ void intel_irq_init(struct drm_device *dev)
|
|
|
setup_timer(&dev_priv->gpu_error.hangcheck_timer,
|
|
|
i915_hangcheck_elapsed,
|
|
|
(unsigned long) dev);
|
|
|
+ setup_timer(&dev_priv->hotplug_reenable_timer, i915_reenable_hotplug_timer_func,
|
|
|
+ (unsigned long) dev_priv);
|
|
|
|
|
|
pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
|
|
|
|