/**
  * drm_connector_oob_hotplug_event - Report out-of-band hotplug event to connector
  * @connector_fwnode: fwnode_handle to report the event on
+ * @status: hot plug detect logical state
  *
  * On some hardware a hotplug event notification may come from outside the display
  * driver / device. An example of this is some USB Type-C setups where the hardware
  * This function can be used to report these out-of-band events after obtaining
  * a drm_connector reference through calling drm_connector_find_by_fwnode().
  */
-void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode)
+void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode,
+                                    enum drm_connector_status status)
 {
        struct drm_connector *connector;
 
                return;
 
        if (connector->funcs->oob_hotplug_event)
-               connector->funcs->oob_hotplug_event(connector);
+               connector->funcs->oob_hotplug_event(connector, status);
 
        drm_connector_put(connector);
 }
 
        /* Whether or not to count short HPD IRQs in HPD storms */
        u8 hpd_short_storm_enabled;
 
+       /* Last state reported by oob_hotplug_event for each encoder */
+       unsigned long oob_hotplug_last_state;
+
        /*
         * if we get a HPD irq from DP and a HPD irq from non-DP
         * the non-DP HPD could block the workqueue on a mode config
 
        return intel_modeset_synced_crtcs(state, conn);
 }
 
-static void intel_dp_oob_hotplug_event(struct drm_connector *connector)
+static void intel_dp_oob_hotplug_event(struct drm_connector *connector,
+                                      enum drm_connector_status hpd_state)
 {
        struct intel_encoder *encoder = intel_attached_encoder(to_intel_connector(connector));
        struct drm_i915_private *i915 = to_i915(connector->dev);
+       bool hpd_high = hpd_state == connector_status_connected;
+       unsigned int hpd_pin = encoder->hpd_pin;
+       bool need_work = false;
 
        spin_lock_irq(&i915->irq_lock);
-       i915->display.hotplug.event_bits |= BIT(encoder->hpd_pin);
+       if (hpd_high != test_bit(hpd_pin, &i915->display.hotplug.oob_hotplug_last_state)) {
+               i915->display.hotplug.event_bits |= BIT(hpd_pin);
+
+               __assign_bit(hpd_pin, &i915->display.hotplug.oob_hotplug_last_state, hpd_high);
+               need_work = true;
+       }
        spin_unlock_irq(&i915->irq_lock);
-       queue_delayed_work(i915->unordered_wq, &i915->display.hotplug.hotplug_work, 0);
+
+       if (need_work)
+               queue_delayed_work(i915->unordered_wq, &i915->display.hotplug.hotplug_work, 0);
 }
 
 static const struct drm_connector_funcs intel_dp_connector_funcs = {
 
                        }
                }
        } else {
-               if (dp->hpd != hpd) {
-                       drm_connector_oob_hotplug_event(dp->connector_fwnode);
-                       dp->hpd = hpd;
-                       sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd");
-               }
+               drm_connector_oob_hotplug_event(dp->connector_fwnode,
+                                               hpd ? connector_status_connected :
+                                                     connector_status_disconnected);
+               dp->hpd = hpd;
+               sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd");
        }
 
        return ret;
         * configuration is complete to signal HPD.
         */
        if (dp->pending_hpd) {
-               drm_connector_oob_hotplug_event(dp->connector_fwnode);
+               drm_connector_oob_hotplug_event(dp->connector_fwnode,
+                                               connector_status_connected);
                sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd");
                dp->pending_hpd = false;
        }
        cancel_work_sync(&dp->work);
 
        if (dp->connector_fwnode) {
-               if (dp->hpd)
-                       drm_connector_oob_hotplug_event(dp->connector_fwnode);
+               drm_connector_oob_hotplug_event(dp->connector_fwnode,
+                                               connector_status_disconnected);
 
                fwnode_handle_put(dp->connector_fwnode);
        }
 
         * This will get called when a hotplug-event for a drm-connector
         * has been received from a source outside the display driver / device.
         */
-       void (*oob_hotplug_event)(struct drm_connector *connector);
+       void (*oob_hotplug_event)(struct drm_connector *connector,
+                                 enum drm_connector_status status);
 
        /**
         * @debugfs_init:
                DRM_CONNECTOR_UNREGISTERED;
 }
 
-void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode);
+void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode,
+                                    enum drm_connector_status status);
 const char *drm_get_connector_type_name(unsigned int connector_type);
 const char *drm_get_connector_status_name(enum drm_connector_status status);
 const char *drm_get_subpixel_order_name(enum subpixel_order order);