From 9d38c0bc652e76456c017ee8af5daeaac63ca581 Mon Sep 17 00:00:00 2001 From: RD Babiera Date: Mon, 14 Aug 2023 17:02:26 +0000 Subject: [PATCH] BACKPORT: usb: typec: altmodes/displayport: Signal hpd when configuring pin assignment When connecting to some DisplayPort partners, the initial status update after entering DisplayPort Alt Mode notifies that the DFP_D/UFP_D is not in the connected state. This leads to sending a configure message that keeps the device in USB mode. The port partner then sets DFP_D/UFP_D to the connected state and HPD to high in the same Attention message. Currently, the HPD signal is dropped in order to handle configuration. This patch saves changes to the HPD signal when the device chooses to configure during dp_altmode_status_update, and invokes sysfs_notify if necessary for HPD after configuring. Fixes: 0e3bb7d6894d ("usb: typec: Add driver for DisplayPort alternate mode") Cc: stable@vger.kernel.org Signed-off-by: RD Babiera Acked-by: Heikki Krogerus Link: https://lore.kernel.org/all/20230726020903.1409072-1-rdbabiera@google.com/ Signed-off-by: Greg Kroah-Hartman Bug: 288137625 (cherry picked from commit 5a5ccd61cfd76156cb3e0373c300c509d05448ce) [rd: resolved minor conflict in displayport.c] Signed-off-by: RD Babiera (cherry picked from https://android-review.googlesource.com/q/commit:056a17677de932cccda77faf3f1c53a5b59c8cf5) Merged-In: I26ef49949aa0681ea6b88d8c95f5ddd54fe84664 Change-Id: I26ef49949aa0681ea6b88d8c95f5ddd54fe84664 --- drivers/usb/typec/altmodes/displayport.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index 6dd86f2a679d..9d6f2eeaaa93 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -60,6 +60,7 @@ struct dp_altmode { enum dp_state state; bool hpd; + bool pending_hpd; struct mutex lock; /* device lock */ struct work_struct work; @@ -144,8 +145,13 @@ static int dp_altmode_status_update(struct dp_altmode *dp) dp->state = DP_STATE_EXIT; } else if (!(con & DP_CONF_CURRENTLY(dp->data.conf))) { ret = dp_altmode_configure(dp, con); - if (!ret) + if (!ret) { dp->state = DP_STATE_CONFIGURE; + if (dp->hpd != hpd) { + dp->hpd = hpd; + dp->pending_hpd = true; + } + } } else { if (dp->hpd != hpd) { drm_connector_oob_hotplug_event(dp->connector_fwnode); @@ -161,6 +167,15 @@ static int dp_altmode_configured(struct dp_altmode *dp) { sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration"); sysfs_notify(&dp->alt->dev.kobj, "displayport", "pin_assignment"); + /* + * If the DFP_D/UFP_D sends a change in HPD when first notifying the + * DisplayPort driver that it is connected, then we wait until + * configuration is complete to signal HPD. + */ + if (dp->pending_hpd) { + sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd"); + dp->pending_hpd = false; + } return dp_altmode_notify(dp); }