From c6e5e01ca875770f71febe4c87f60fd57df86f6f Mon Sep 17 00:00:00 2001 From: Tobias Schramm Date: Thu, 28 May 2020 14:26:27 +0200 Subject: [PATCH 11/22] usb: typec: altmodes: displayport: Add hacky, generic altmode detection Do not mainline, hack. Signed-off-by: Tobias Schramm --- drivers/usb/typec/altmodes/displayport.c | 55 ++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index e62e5e3da01e..a3d03db476aa 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -9,6 +9,8 @@ */ #include +#include +#include #include #include #include @@ -135,15 +137,53 @@ static int dp_altmode_status_update(struct dp_altmode *dp) return ret; } +static void dp_altmode_update_extcon(struct dp_altmode *dp, bool disconnect) { + const struct device *dev = &dp->port->dev; + struct extcon_dev* edev = NULL; + + while (dev) { + edev = extcon_find_edev_by_node(dev->of_node); + if(!IS_ERR(edev)) { + break; + } + dev = dev->parent; + } + + if (IS_ERR_OR_NULL(edev)) { + return; + } + + if (disconnect || !dp->data.conf) { + extcon_set_state_sync(edev, EXTCON_DISP_DP, false); + } else { + union extcon_property_value extcon_true = { .intval = true }; + extcon_set_state(edev, EXTCON_DISP_DP, true); + if (DP_CONF_GET_PIN_ASSIGN(dp->data.conf) & DP_PIN_ASSIGN_MULTI_FUNC_MASK) { + extcon_set_state_sync(edev, EXTCON_USB_HOST, true); + extcon_set_property(edev, EXTCON_DISP_DP, EXTCON_PROP_USB_SS, + extcon_true); + } else { + extcon_set_state_sync(edev, EXTCON_USB_HOST, false); + } + extcon_sync(edev, EXTCON_DISP_DP); + extcon_set_state_sync(edev, EXTCON_USB, false); + } + +} + static int dp_altmode_configured(struct dp_altmode *dp) { int ret; sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration"); - if (!dp->data.conf) + if (!dp->data.conf) { + dp_altmode_update_extcon(dp, true); return typec_altmode_notify(dp->alt, TYPEC_STATE_USB, &dp->data); + } + + dp_altmode_update_extcon(dp, false); ret = dp_altmode_notify(dp); if (ret) @@ -170,9 +210,11 @@ static int dp_altmode_configure_vdm(struct dp_altmode *dp, u32 conf) if (ret) { if (DP_CONF_GET_PIN_ASSIGN(dp->data.conf)) dp_altmode_notify(dp); - else + else { + dp_altmode_update_extcon(dp, true); typec_altmode_notify(dp->alt, TYPEC_STATE_USB, &dp->data); + } } return ret; @@ -211,6 +253,8 @@ static void dp_altmode_work(struct work_struct *work) case DP_STATE_EXIT: if (typec_altmode_exit(dp->alt)) dev_err(&dp->alt->dev, "Exit Mode Failed!\n"); + else + dp_altmode_update_extcon(dp, true); break; default: break; @@ -521,8 +565,13 @@ int dp_altmode_probe(struct typec_altmode *alt) if (!(DP_CAP_DFP_D_PIN_ASSIGN(port->vdo) & DP_CAP_UFP_D_PIN_ASSIGN(alt->vdo)) && !(DP_CAP_UFP_D_PIN_ASSIGN(port->vdo) & - DP_CAP_DFP_D_PIN_ASSIGN(alt->vdo))) + DP_CAP_DFP_D_PIN_ASSIGN(alt->vdo))) { + dev_err(&alt->dev, "No compatible pin configuration found:"\ + "%04lx -> %04lx, %04lx <- %04lx", + DP_CAP_DFP_D_PIN_ASSIGN(port->vdo), DP_CAP_UFP_D_PIN_ASSIGN(alt->vdo), + DP_CAP_UFP_D_PIN_ASSIGN(port->vdo), DP_CAP_DFP_D_PIN_ASSIGN(alt->vdo)); return -ENODEV; + } ret = sysfs_create_group(&alt->dev.kobj, &dp_altmode_group); if (ret) -- 2.30.0