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@vger.kernel.org # 6.3 Cc: Bjorn Andersson andersson@kernel.org Reported-by: Clayton Craft clayton@craftyguy.net Signed-off-by: Johan Hovold johan+linaro@kernel.org ---
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); }