usb: typec: altmodes/displayport: add irq_hpd to sysfs
Subsystems (3)
PATCH v2 1/1 usb: typec: altmodes/displayport: add irq_hpd to sysfs
Add irq_hpd sysfs node to displayport driver. This allows the userspace to subscribe to irq events similar to how it can subscribe to changes in hpd.
irq_hpd is read only and returns the number of irq events generated since driver probe. pending_irq_hpd is added so that a sysfs_emit can be generated if the HPD high event belonging to the same status message is delayed until a successful configuration.
---
Changes since v1:
* fixed bracket styling error
--- .../testing/sysfs-driver-typec-displayport | 10 +++++++ drivers/usb/typec/altmodes/displayport.c | 28 +++++++++++++++++++ 2 files changed, 38 insertions(+)
Documentation/ABI/testing/sysfs-driver-typec-displayport +10 -0
@@ -62,3 +62,13 @@ Description: by VESA DisplayPort Alt Mode on USB Type-C Standard. - 0 when HPD’s logical state is low (HPD_Low) as defined by VESA DisplayPort Alt Mode on USB Type-C Standard. + +What: /sys/bus/typec/devices/.../displayport/irq_hpd +Date: June 2025 +Contact: RD Babiera <[email protected]> +Description: + IRQ_HPD events are sent over the USB PD protocol in Status Update and + Attention messages. IRQ_HPD can only be asserted when HPD is high, + and is asserted when an IRQ_HPD has been issued since the last Status + Update. This is a read only node that returns the number of IRQ events + raised in the driver's lifetime.
drivers/usb/typec/altmodes/displayport.c +28 -0
@@ -65,6 +65,13 @@ struct dp_altmode {enum dp_state state;bool hpd;bool pending_hpd; +u32 irq_hpd_count; +/* +* hpd is mandatory for irq_hpd assertion, so irq_hpd also needs its own pending flag if +* both hpd and irq_hpd are asserted in the first Status Update before the pin assignment +* is configured. +*/ +bool pending_irq_hpd;struct mutex lock;/* device lock */ struct work_struct work;
@@ -151,6 +158,7 @@ static int dp_altmode_status_update(struct dp_altmode *dp) {bool configured = !!DP_CONF_GET_PIN_ASSIGN (dp->data.conf);bool hpd = !!(dp->data.status &DP_STATUS_HPD_STATE ); +bool irq_hpd = !!(dp->data.status &DP_STATUS_IRQ_HPD );u8 con =DP_STATUS_CONNECTION (dp->data.status);int ret =0 ;
@@ -170,6 +178,8 @@ static int dp_altmode_status_update(struct dp_altmode *dp) dp->hpd = hpd; dp->pending_hpd = true; } +if (dp->hpd && dp->pending_hpd && irq_hpd) + dp->pending_irq_hpd = true; } }else { drm_connector_oob_hotplug_event(dp->connector_fwnode,
@@ -177,6 +187,10 @@ static int dp_altmode_status_update(struct dp_altmode *dp) connector_status_disconnected); dp->hpd = hpd;sysfs_notify (&dp->alt->dev.kobj,"displayport" ,"hpd" ); +if (hpd && irq_hpd) { + dp->irq_hpd_count++; +sysfs_notify (&dp->alt->dev.kobj,"displayport" ,"irq_hpd" ); + } }return ret;
@@ -196,6 +210,11 @@ static int dp_altmode_configured(struct dp_altmode *dp) connector_status_connected);sysfs_notify (&dp->alt->dev.kobj,"displayport" ,"hpd" ); dp->pending_hpd = false; +if (dp->pending_irq_hpd) { + dp->irq_hpd_count++; +sysfs_notify (&dp->alt->dev.kobj,"displayport" ,"irq_hpd" ); + dp->pending_irq_hpd = false; + } }return dp_altmode_notify (dp);
@@ -707,10 +726,19 @@ static ssize_t hpd_show(struct device *dev, struct device_attribute *attr, char }static DEVICE_ATTR_RO (hpd); +static ssize_t irq_hpd_show (struct device *dev,struct device_attribute *attr,char *buf) +{ +struct dp_altmode *dp =dev_get_drvdata (dev); + +return sysfs_emit (buf,"%d\n" , dp->irq_hpd_count); +} +static DEVICE_ATTR_RO (irq_hpd); +static struct attribute *displayport_attrs[] = { &dev_attr_configuration.attr, &dev_attr_pin_assignment.attr, &dev_attr_hpd.attr, + &dev_attr_irq_hpd.attr,NULL };
base-commit: e04c78d86a9699d136910cfc0bdcf01087e3267e
Signature · 1 line
2.50.0.rc2.761.g2dc52ea45b-goog
Quoted 11 lines · RD Babiera
Add
irq_hpdsysfs node to displayport driver. This allows the userspace to subscribe to irq events similar to how it can subscribe to changes in hpd.
irq_hpdis read only and returns the number of irq events generated since driver probe.pending_irq_hpdis added so that asysfs_emitcan be generated if the HPD high event belonging to the same status message is delayed until a successful configuration.Signed-off-by RD Babiera <[email protected]>Reviewed-by Badhri Jagan Sridharan <[email protected]>
Quoted 108 lines
---
Changes since v1:
* fixed bracket styling error--- .../testing/sysfs-driver-typec-displayport | 10 +++++++ drivers/usb/typec/altmodes/displayport.c | 28 +++++++++++++++++++ 2 files changed, 38 insertions(+)Documentation/ABI/testing/sysfs-driver-typec-displayport +10
-0@@ -62,3 +62,13 @@ Description: by VESA DisplayPort Alt Mode on USB Type-C Standard. - 0 when HPD’s logical state is low (HPD_Low) as defined by VESA DisplayPort Alt Mode on USB Type-C Standard. + +What: /sys/bus/typec/devices/.../displayport/irq_hpd +Date: June 2025 +Contact: RD Babiera <[email protected]> +Description: + IRQ_HPD events are sent over the USB PD protocol in Status Update and + Attention messages. IRQ_HPD can only be asserted when HPD is high, + and is asserted when an IRQ_HPD has been issued since the last Status + Update. This is a read only node that returns the number of IRQ events + raised in the driver's lifetime.drivers/usb/typec/altmodes/displayport.c +28
-0@@ -65,6 +65,13 @@ struct dp_altmode {enum dp_state state;bool hpd;bool pending_hpd; +u32 irq_hpd_count; +/* +* hpd is mandatory for irq_hpd assertion, so irq_hpd also needs its own pending flag if +* both hpd and irq_hpd are asserted in the first Status Update before the pin assignment +* is configured. +*/ +bool pending_irq_hpd;struct mutex lock;/* device lock */ struct work_struct work;@@ -151,6 +158,7 @@ static int dp_altmode_status_update(struct dp_altmode *dp) {bool configured = !!DP_CONF_GET_PIN_ASSIGN (dp->data.conf);bool hpd = !!(dp->data.status &DP_STATUS_HPD_STATE ); +bool irq_hpd = !!(dp->data.status &DP_STATUS_IRQ_HPD );u8 con =DP_STATUS_CONNECTION (dp->data.status);int ret =0 ;@@ -170,6 +178,8 @@ static int dp_altmode_status_update(struct dp_altmode *dp) dp->hpd = hpd; dp->pending_hpd = true; } +if (dp->hpd && dp->pending_hpd && irq_hpd) + dp->pending_irq_hpd = true; } }else { drm_connector_oob_hotplug_event(dp->connector_fwnode,@@ -177,6 +187,10 @@ static int dp_altmode_status_update(struct dp_altmode *dp) connector_status_disconnected); dp->hpd = hpd;sysfs_notify (&dp->alt->dev.kobj,"displayport" ,"hpd" ); +if (hpd && irq_hpd) { + dp->irq_hpd_count++; +sysfs_notify (&dp->alt->dev.kobj,"displayport" ,"irq_hpd" ); + } }return ret;@@ -196,6 +210,11 @@ static int dp_altmode_configured(struct dp_altmode *dp) connector_status_connected);sysfs_notify (&dp->alt->dev.kobj,"displayport" ,"hpd" ); dp->pending_hpd = false; +if (dp->pending_irq_hpd) { + dp->irq_hpd_count++; +sysfs_notify (&dp->alt->dev.kobj,"displayport" ,"irq_hpd" ); + dp->pending_irq_hpd = false; + } }return dp_altmode_notify (dp);@@ -707,10 +726,19 @@ static ssize_t hpd_show(struct device *dev, struct device_attribute *attr, char }static DEVICE_ATTR_RO (hpd); +static ssize_t irq_hpd_show (struct device *dev,struct device_attribute *attr,char *buf) +{ +struct dp_altmode *dp =dev_get_drvdata (dev); + +return sysfs_emit (buf,"%d\n" , dp->irq_hpd_count); +} +static DEVICE_ATTR_RO (irq_hpd); +static struct attribute *displayport_attrs[] = { &dev_attr_configuration.attr, &dev_attr_pin_assignment.attr, &dev_attr_hpd.attr, + &dev_attr_irq_hpd.attr,NULL };base-commit:
e04c78d86a9699d136910cfc0bdcf01087e3267eSignature · 1 line
2.50.0.rc2.761.g2dc52ea45b-goog
Signature · 1 line
heikki