[PATCH] soc: qcom: pmic_glink_altmode: fix spurious DP hotplug events

From: Johan Hovold
Date: Mon Mar 24 2025 - 09:27:18 EST


The PMIC GLINK driver is currently generating DisplayPort hotplug
notifications whenever something is connected to (or disconnected from)
a port regardless of the type of notification sent by the firmware.

These notifications are forwarded to user space by the DRM subsystem as
connector "change" uevents:

KERNEL[1556.223776] change /devices/platform/soc@0/ae00000.display-subsystem/ae01000.display-controller/drm/card0 (drm)
ACTION=change
DEVPATH=/devices/platform/soc@0/ae00000.display-subsystem/ae01000.display-controller/drm/card0
SUBSYSTEM=drm
HOTPLUG=1
CONNECTOR=36
DEVNAME=/dev/dri/card0
DEVTYPE=drm_minor
SEQNUM=4176
MAJOR=226
MINOR=0

On the Lenovo ThinkPad X13s and T14s, the PMIC GLINK firmware sends two
identical notifications with orientation information when connecting a
charger, each generating a bogus DRM hotplug event. On the X13s, two
such notification are also sent every 90 seconds while a charger remains
connected, which again are forwarded to user space:

port = 1, svid = ff00, mode = 255, hpd_state = 0
payload = 01 00 00 00 00 00 00 ff 00 00 00 00 00 00 00 00

Note that the firmware only sends on of these when connecting an
ethernet adapter.

Fix the spurious hotplug events by only forwarding hotplug notifications
for the Type-C DisplayPort service id. This also reduces the number of
uevents from four to two when an actual DisplayPort altmode device is
connected:

port = 0, svid = ff01, mode = 2, hpd_state = 0
payload = 00 01 02 00 f2 0c 01 ff 03 00 00 00 00 00 00 00
port = 0, svid = ff01, mode = 2, hpd_state = 1
payload = 00 01 02 00 f2 0c 01 ff 43 00 00 00 00 00 00 00

Fixes: 080b4e24852b ("soc: qcom: pmic_glink: Introduce altmode support")
Cc: stable@xxxxxxxxxxxxxxx # 6.3
Cc: Bjorn Andersson <andersson@xxxxxxxxxx>
Reported-by: Clayton Craft <clayton@xxxxxxxxxxxxx>
Signed-off-by: Johan Hovold <johan+linaro@xxxxxxxxxx>
---

Clayton reported seeing display flickering with recent RC kernels, which
may possibly be related to these spurious events being generated with
even greater frequency.

That still remains to be fully understood, but the spurious events, that
on the X13s are generated every 90 seconds, should be fixed either way.

Johan


drivers/soc/qcom/pmic_glink_altmode.c | 30 +++++++++++++++++----------
1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c
index bd06ce161804..7f11acd33323 100644
--- a/drivers/soc/qcom/pmic_glink_altmode.c
+++ b/drivers/soc/qcom/pmic_glink_altmode.c
@@ -218,21 +218,29 @@ static void pmic_glink_altmode_worker(struct work_struct *work)
{
struct pmic_glink_altmode_port *alt_port = work_to_altmode_port(work);
struct pmic_glink_altmode *altmode = alt_port->altmode;
+ enum drm_connector_status conn_status;

typec_switch_set(alt_port->typec_switch, alt_port->orientation);

- if (alt_port->svid == USB_TYPEC_DP_SID && alt_port->mode == 0xff)
- pmic_glink_altmode_safe(altmode, alt_port);
- else if (alt_port->svid == USB_TYPEC_DP_SID)
- pmic_glink_altmode_enable_dp(altmode, alt_port, alt_port->mode,
- alt_port->hpd_state, alt_port->hpd_irq);
- else
- pmic_glink_altmode_enable_usb(altmode, alt_port);
+ if (alt_port->svid == USB_TYPEC_DP_SID) {
+ if (alt_port->mode == 0xff) {
+ pmic_glink_altmode_safe(altmode, alt_port);
+ } else {
+ pmic_glink_altmode_enable_dp(altmode, alt_port,
+ alt_port->mode,
+ alt_port->hpd_state,
+ alt_port->hpd_irq);
+ }

- drm_aux_hpd_bridge_notify(&alt_port->bridge->dev,
- alt_port->hpd_state ?
- connector_status_connected :
- connector_status_disconnected);
+ if (alt_port->hpd_state)
+ conn_status = connector_status_connected;
+ else
+ conn_status = connector_status_disconnected;
+
+ drm_aux_hpd_bridge_notify(&alt_port->bridge->dev, conn_status);
+ } else {
+ pmic_glink_altmode_enable_usb(altmode, alt_port);
+ }

pmic_glink_altmode_request(altmode, ALTMODE_PAN_ACK, alt_port->index);
}
--
2.48.1