This is a note to let you know that I've just added the patch titled usb: typec: altmodes/displayport: Notify drm subsys of hotplug events to the 5.10-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: usb-typec-altmodes-displayport-notify-drm-subsys-of-.patch and it can be found in the queue-5.10 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit cb721ade68a1674d57fd79cc20a7e8a1abfe6fa3 Author: Hans de Goede <hdegoede@xxxxxxxxxx> Date: Tue Aug 17 23:52:01 2021 +0200 usb: typec: altmodes/displayport: Notify drm subsys of hotplug events [ Upstream commit 7f811394878535ed9a6849717de8c2959ae38899 ] Use the new drm_connector_oob_hotplug_event() functions to let drm/kms drivers know about DisplayPort over Type-C hotplug events. Reviewed-by: Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx> Tested-by: Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx> Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx> Reviewed-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> Reviewed-by: Lyude Paul <lyude@xxxxxxxxxx> Link: https://lore.kernel.org/r/20210817215201.795062-9-hdegoede@xxxxxxxxxx Stable-dep-of: 89434b069e46 ("usb: typec: altmodes/displayport: Signal hpd low when exiting mode") Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/drivers/usb/typec/altmodes/Kconfig b/drivers/usb/typec/altmodes/Kconfig index 60d375e9c3c7c..1a6b5e872b0d9 100644 --- a/drivers/usb/typec/altmodes/Kconfig +++ b/drivers/usb/typec/altmodes/Kconfig @@ -4,6 +4,7 @@ menu "USB Type-C Alternate Mode drivers" config TYPEC_DP_ALTMODE tristate "DisplayPort Alternate Mode driver" + depends on DRM help DisplayPort USB Type-C Alternate Mode allows DisplayPort displays and adapters to be attached to the USB Type-C diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index 0d4b1c0eeefb3..8083d5faf0c98 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -11,8 +11,10 @@ #include <linux/delay.h> #include <linux/mutex.h> #include <linux/module.h> +#include <linux/property.h> #include <linux/usb/pd_vdo.h> #include <linux/usb/typec_dp.h> +#include <drm/drm_connector.h> #include "displayport.h" #define DP_HEADER(_dp, cmd) (VDO((_dp)->alt->svid, 1, cmd) | \ @@ -57,11 +59,13 @@ struct dp_altmode { struct typec_displayport_data data; enum dp_state state; + bool hpd; struct mutex lock; /* device lock */ struct work_struct work; struct typec_altmode *alt; const struct typec_altmode *port; + struct fwnode_handle *connector_fwnode; }; static int dp_altmode_notify(struct dp_altmode *dp) @@ -122,6 +126,7 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con) 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); u8 con = DP_STATUS_CONNECTION(dp->data.status); int ret = 0; @@ -134,6 +139,11 @@ static int dp_altmode_status_update(struct dp_altmode *dp) ret = dp_altmode_configure(dp, con); if (!ret) dp->state = DP_STATE_CONFIGURE; + } else { + if (dp->hpd != hpd) { + drm_connector_oob_hotplug_event(dp->connector_fwnode); + dp->hpd = hpd; + } } return ret; @@ -526,6 +536,7 @@ static const struct attribute_group dp_altmode_group = { int dp_altmode_probe(struct typec_altmode *alt) { const struct typec_altmode *port = typec_altmode_get_partner(alt); + struct fwnode_handle *fwnode; struct dp_altmode *dp; int ret; @@ -554,6 +565,11 @@ int dp_altmode_probe(struct typec_altmode *alt) alt->desc = "DisplayPort"; alt->ops = &dp_altmode_ops; + fwnode = dev_fwnode(alt->dev.parent->parent); /* typec_port fwnode */ + dp->connector_fwnode = fwnode_find_reference(fwnode, "displayport", 0); + if (IS_ERR(dp->connector_fwnode)) + dp->connector_fwnode = NULL; + typec_altmode_set_drvdata(alt, dp); dp->state = DP_STATE_ENTER; @@ -569,6 +585,13 @@ void dp_altmode_remove(struct typec_altmode *alt) sysfs_remove_group(&alt->dev.kobj, &dp_altmode_group); cancel_work_sync(&dp->work); + + if (dp->connector_fwnode) { + if (dp->hpd) + drm_connector_oob_hotplug_event(dp->connector_fwnode); + + fwnode_handle_put(dp->connector_fwnode); + } } EXPORT_SYMBOL_GPL(dp_altmode_remove);