The DisplayPort standard defines a special kind of events called IRQ.
These events are used to notify DP Source about the events on the Sink
side. It is extremely important for DP MST handling, where the MST
events are reported through this IRQ.

In case of the USB-C DP AltMode there is no actual HPD pulse, but the
events are reported through the bits in the AltMode VDOs.

Rename drm_connector_oob_hotplug_event() to drm_connector_dp_oob_status()
and extend its interface to report IRQ events to the DisplayPort Sink
drivers.

Acked-by: Heikki Krogerus <[email protected]>
Signed-off-by: Dmitry Baryshkov <[email protected]>
---
 drivers/gpu/drm/drm_connector.c          | 20 ++++++++++++--------
 drivers/usb/typec/altmodes/displayport.c | 23 +++++++++++++++--------
 include/drm/drm_connector.h              | 21 +++++++++++++++++++--
 3 files changed, 46 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 3fa4d2082cd7..bb128dd0263a 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -3502,20 +3502,24 @@ struct drm_connector 
*drm_connector_find_by_fwnode(struct fwnode_handle *fwnode)
 }
 
 /**
- * drm_connector_oob_hotplug_event - Report out-of-band hotplug event to 
connector
+ * drm_connector_dp_oob_status - Report out-of-band hotplug event to 
DisplayPort connector
  * @connector_fwnode: fwnode_handle to report the event on
  * @status: hot plug detect logical state
+ * @extra_status: additional information provided by the sink without changing
+ * the HPD state (or in addition to such a change).
  *
- * 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
- * muxes the DisplayPort data and aux-lines but does not pass the altmode HPD
- * status bit to the GPU's DP HPD pin.
+ * In some cases when DisplayPort signals are being routed through the USB
+ * Type-C port the hotplug event notifications come from outside of the display
+ * driver / device. In this case hardware muxes the DisplayPort data and
+ * AUX-lines but does not pass the altmode HPD status bit to the GPU's DP HPD
+ * pin.
  *
  * 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,
-                                    enum drm_connector_status status)
+void drm_connector_dp_oob_status(struct fwnode_handle *connector_fwnode,
+                                enum drm_connector_status status,
+                                enum drm_connector_status_extra extra_status)
 {
        struct drm_connector *connector;
 
@@ -3528,7 +3532,7 @@ void drm_connector_oob_hotplug_event(struct fwnode_handle 
*connector_fwnode,
 
        drm_connector_put(connector);
 }
-EXPORT_SYMBOL(drm_connector_oob_hotplug_event);
+EXPORT_SYMBOL(drm_connector_dp_oob_status);
 
 
 /**
diff --git a/drivers/usb/typec/altmodes/displayport.c 
b/drivers/usb/typec/altmodes/displayport.c
index 263a89c5f324..ff3659b8f5a2 100644
--- a/drivers/usb/typec/altmodes/displayport.c
+++ b/drivers/usb/typec/altmodes/displayport.c
@@ -187,9 +187,11 @@ static int dp_altmode_status_update(struct dp_altmode *dp)
                                dp->pending_irq_hpd = true;
                }
        } else {
-               drm_connector_oob_hotplug_event(dp->connector_fwnode,
+               drm_connector_dp_oob_status(dp->connector_fwnode,
                                                hpd ? 
connector_status_connected :
-                                                     
connector_status_disconnected);
+                                                     
connector_status_disconnected,
+                                               (hpd && irq_hpd) ? 
DRM_CONNECTOR_DP_IRQ_HPD :
+                                                                  
DRM_CONNECTOR_NO_EXTRA_STATUS);
                dp->hpd = hpd;
                sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd");
                if (hpd && irq_hpd) {
@@ -211,8 +213,11 @@ static int dp_altmode_configured(struct dp_altmode *dp)
         * configuration is complete to signal HPD.
         */
        if (dp->pending_hpd) {
-               drm_connector_oob_hotplug_event(dp->connector_fwnode,
-                                               connector_status_connected);
+               drm_connector_dp_oob_status(dp->connector_fwnode,
+                                               connector_status_connected,
+                                               dp->pending_irq_hpd ?
+                                               DRM_CONNECTOR_DP_IRQ_HPD :
+                                               DRM_CONNECTOR_NO_EXTRA_STATUS);
                sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd");
                dp->pending_hpd = false;
                if (dp->pending_irq_hpd) {
@@ -396,8 +401,9 @@ static int dp_altmode_vdm(struct typec_altmode *alt,
                        dp->data.status = 0;
                        dp->data.conf = 0;
                        if (dp->hpd) {
-                               
drm_connector_oob_hotplug_event(dp->connector_fwnode,
-                                                               
connector_status_disconnected);
+                               
drm_connector_dp_oob_status(dp->connector_fwnode,
+                                                               
connector_status_disconnected,
+                                                               
DRM_CONNECTOR_NO_EXTRA_STATUS);
                                dp->hpd = false;
                                sysfs_notify(&dp->alt->dev.kobj, "displayport", 
"hpd");
                        }
@@ -828,8 +834,9 @@ void dp_altmode_remove(struct typec_altmode *alt)
        typec_altmode_put_plug(dp->plug_prime);
 
        if (dp->connector_fwnode) {
-               drm_connector_oob_hotplug_event(dp->connector_fwnode,
-                                               connector_status_disconnected);
+               drm_connector_dp_oob_status(dp->connector_fwnode,
+                                               connector_status_disconnected,
+                                               DRM_CONNECTOR_NO_EXTRA_STATUS);
 
                fwnode_handle_put(dp->connector_fwnode);
        }
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 5ad62c207d00..105da7c94910 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -91,6 +91,22 @@ enum drm_connector_status {
        connector_status_unknown = 3,
 };
 
+/**
+ * enum drm_connector_status_extra - additional events sent by the sink /
+ * display together or in replacement of the HPD status changes.
+ */
+enum drm_connector_status_extra {
+       /**
+        * @DRM_CONNECTOR_NO_EXTRA_STATUS: No additional status reported.
+        */
+       DRM_CONNECTOR_NO_EXTRA_STATUS,
+       /**
+        * @DRM_CONNECTOR_DP_IRQ_HPD: DisplayPort Sink has sent the
+        * IRQ_HPD (either by the HPD short pulse or via the AltMode event).
+        */
+       DRM_CONNECTOR_DP_IRQ_HPD,
+};
+
 /**
  * enum drm_connector_registration_state - userspace registration status for
  * a &drm_connector
@@ -2520,8 +2536,9 @@ drm_connector_is_unregistered(struct drm_connector 
*connector)
                DRM_CONNECTOR_UNREGISTERED;
 }
 
-void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode,
-                                    enum drm_connector_status status);
+void drm_connector_dp_oob_status(struct fwnode_handle *connector_fwnode,
+                                enum drm_connector_status status,
+                                enum drm_connector_status_extra extra_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);

-- 
2.47.3

Reply via email to