]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
usb: typec: ucsi: yoga-c630: register DRM HPD bridge
authorDmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Sat, 21 Jun 2025 18:13:03 +0000 (21:13 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 24 Jun 2025 14:40:50 +0000 (15:40 +0100)
On Qualcomm platforms DisplayPort driver expects to have a drm bridge in
the final device on the USB-C chain. Register the DRM HPD bridge in
order to fulfill this requirement and to send HPD events to the DRM
driver.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20250621-c630-ucsi-v1-8-a86de5e11361@oss.qualcomm.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/typec/ucsi/Kconfig
drivers/usb/typec/ucsi/ucsi_yoga_c630.c

index 8bf8fefb4f07bccc4be90a4b7f771d91294386b0..52b53bb6dfed28c4272f8ccc5e31601aede29911 100644 (file)
@@ -85,6 +85,7 @@ config CROS_EC_UCSI
 config UCSI_LENOVO_YOGA_C630
        tristate "UCSI Interface Driver for Lenovo Yoga C630"
        depends on EC_LENOVO_YOGA_C630
+       select DRM_AUX_HPD_BRIDGE if DRM_BRIDGE && OF
        help
          This driver enables UCSI support on the Lenovo Yoga C630 laptop.
 
index f85170417d19cdc5ae39a15e2f97010259ef12f6..0187c1c4b21abc7b5429526ebb4538c28b2e2e77 100644 (file)
 #include <linux/container_of.h>
 #include <linux/module.h>
 #include <linux/notifier.h>
+#include <linux/of.h>
+#include <linux/property.h>
 #include <linux/string.h>
 #include <linux/platform_data/lenovo-yoga-c630.h>
 #include <linux/usb/typec_dp.h>
 
+#include <drm/bridge/aux-bridge.h>
+
 #include "ucsi.h"
 
 #define LENOVO_EC_USB_MUX      0x08
@@ -29,6 +33,7 @@
 struct yoga_c630_ucsi {
        struct yoga_c630_ec *ec;
        struct ucsi *ucsi;
+       struct auxiliary_device *bridge;
        struct notifier_block nb;
        u16 version;
 };
@@ -193,6 +198,13 @@ static void yoga_c630_ucsi_read_port0_status(struct yoga_c630_ucsi *uec)
                                      ccst == 1 ?
                                      TYPEC_ORIENTATION_REVERSE :
                                      TYPEC_ORIENTATION_NORMAL);
+
+       if (uec->bridge)
+               drm_aux_hpd_bridge_notify(&uec->bridge->dev,
+                                         dppn != 0 ?
+                                         connector_status_connected :
+                                         connector_status_disconnected);
+
 }
 
 static int yoga_c630_ucsi_notify(struct notifier_block *nb,
@@ -237,6 +249,24 @@ static int yoga_c630_ucsi_probe(struct auxiliary_device *adev,
        uec->ec = ec;
        uec->nb.notifier_call = yoga_c630_ucsi_notify;
 
+       device_for_each_child_node_scoped(&adev->dev, fwnode) {
+               u32 port;
+
+               ret = fwnode_property_read_u32(fwnode, "reg", &port);
+               if (ret < 0) {
+                       dev_err(&adev->dev, "missing reg property of %pfwP\n", fwnode);
+                       return ret;
+               }
+
+               /* DP is only on port0 */
+               if (port != 0)
+                       continue;
+
+               uec->bridge = devm_drm_dp_hpd_bridge_alloc(&adev->dev, to_of_node(fwnode));
+               if (IS_ERR(uec->bridge))
+                       return PTR_ERR(uec->bridge);
+       }
+
        uec->ucsi = ucsi_create(&adev->dev, &yoga_c630_ucsi_ops);
        if (IS_ERR(uec->ucsi))
                return PTR_ERR(uec->ucsi);
@@ -255,8 +285,17 @@ static int yoga_c630_ucsi_probe(struct auxiliary_device *adev,
        if (ret)
                goto err_unregister;
 
+       if (uec->bridge) {
+               ret = devm_drm_dp_hpd_bridge_add(&adev->dev, uec->bridge);
+               if (ret)
+                       goto err_ucsi_unregister;
+       }
+
        return 0;
 
+err_ucsi_unregister:
+       ucsi_unregister(uec->ucsi);
+
 err_unregister:
        yoga_c630_ec_unregister_notify(uec->ec, &uec->nb);