genode/repos/dde_linux/patches/intel_fb_hotplug.patch

98 lines
3.1 KiB
Diff

--- a/drivers/gpu/drm/i915/intel_hotplug.c
+++ b/drivers/gpu/drm/i915/intel_hotplug.c
@@ -336,11 +336,10 @@
/*
* Handle hotplug events outside the interrupt handler proper.
*/
-static void i915_hotplug_work_func(struct work_struct *work)
+static void i915_hotplug_work_func_x(struct work_struct *work,
+ struct drm_i915_private *dev_priv,
+ struct drm_device *dev)
{
- struct drm_i915_private *dev_priv =
- container_of(work, struct drm_i915_private, hotplug.hotplug_work);
- struct drm_device *dev = &dev_priv->drm;
struct intel_connector *intel_connector;
struct intel_encoder *intel_encoder;
struct drm_connector *connector;
@@ -353,7 +352,7 @@
spin_lock_irq(&dev_priv->irq_lock);
- hpd_event_bits = dev_priv->hotplug.event_bits;
+ hpd_event_bits = dev_priv->hotplug.event_bits | dev_priv->hotplug.recheck_event_bits;
dev_priv->hotplug.event_bits = 0;
/* Disable hotplug on connectors that hit an irq storm. */
@@ -379,8 +378,40 @@
drm_connector_list_iter_end(&conn_iter);
mutex_unlock(&dev->mode_config.mutex);
- if (changed)
+ if (changed) {
+ dev_priv->hotplug.recheck_event_bits = 0;
drm_kms_helper_hotplug_event(dev);
+ } else {
+ if (hpd_event_bits && !dev_priv->hotplug.recheck_event_bits) {
+ unsigned long delay = msecs_to_jiffies(2000);
+ schedule_delayed_work(&dev_priv->hotplug.recheck_hotplug, delay);
+ }
+
+ if (hpd_event_bits != dev_priv->hotplug.recheck_event_bits)
+ dev_priv->hotplug.recheck_event_bits |= hpd_event_bits;
+ }
+}
+
+static void i915_hotplug_work_func(struct work_struct *work)
+{
+ struct drm_i915_private *dev_priv =
+ container_of(work, struct drm_i915_private, hotplug.hotplug_work);
+ struct drm_device *dev = &dev_priv->drm;
+
+ i915_hotplug_work_func_x(work, dev_priv, dev);
+}
+
+static void i915_hotplug_recheck_func(struct work_struct *work)
+{
+ struct drm_i915_private *dev_priv =
+ container_of(work, typeof(*dev_priv),
+ hotplug.recheck_hotplug.work);
+ struct drm_device *dev = &dev_priv->drm;
+
+ i915_hotplug_work_func_x(work, dev_priv, dev);
+
+ /* re-try just once */
+ dev_priv->hotplug.recheck_event_bits = 0;
}
@@ -604,6 +635,8 @@
INIT_WORK(&dev_priv->hotplug.poll_init_work, i915_hpd_poll_init_work);
INIT_DELAYED_WORK(&dev_priv->hotplug.reenable_work,
intel_hpd_irq_storm_reenable_work);
+ INIT_DELAYED_WORK(&dev_priv->hotplug.recheck_hotplug,
+ i915_hotplug_recheck_func);
}
void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)
@@ -620,6 +653,7 @@
cancel_work_sync(&dev_priv->hotplug.hotplug_work);
cancel_work_sync(&dev_priv->hotplug.poll_init_work);
cancel_delayed_work_sync(&dev_priv->hotplug.reenable_work);
+ cancel_delayed_work_sync(&dev_priv->hotplug.recheck_hotplug);
}
bool intel_hpd_disable(struct drm_i915_private *dev_priv, enum hpd_pin pin)
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -278,7 +278,9 @@
} state;
} stats[HPD_NUM_PINS];
u32 event_bits;
+ u32 recheck_event_bits;
struct delayed_work reenable_work;
+ struct delayed_work recheck_hotplug;
struct intel_digital_port *irq_port[I915_MAX_PORTS];
u32 long_port_mask;