[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <npnpujjfonvzhf5c4upgajhx6hu5uqmerewmbqprvl7a3xrqgm@datubwgyucby>
Date: Thu, 24 Apr 2025 13:51:17 +0300
From: Dmitry Baryshkov <dmitry.baryshkov@....qualcomm.com>
To: Stephen Boyd <swboyd@...omium.org>
Cc: Tzung-Bi Shih <tzungbi@...nel.org>, linux-kernel@...r.kernel.org,
patches@...ts.linux.dev, Bjorn Andersson <andersson@...nel.org>,
Konrad Dybcio <konradybcio@...nel.org>, devicetree@...r.kernel.org,
Krzysztof Kozlowski <krzk+dt@...nel.org>,
Rob Herring <robh@...nel.org>, linux-arm-msm@...r.kernel.org,
linux-arm-kernel@...ts.infradead.org,
Conor Dooley <conor+dt@...nel.org>, Benson Leung <bleung@...omium.org>,
chrome-platform@...ts.linux.dev, Pin-yen Lin <treapking@...omium.org>,
Abhishek Pandit-Subedi <abhishekpandit@...omium.org>,
Łukasz Bartosik <ukaszb@...omium.org>,
Jameson Thies <jthies@...gle.com>,
Andrei Kuchynski <akuchynski@...omium.org>
Subject: Re: [PATCH 6/7] platform/chrome: cros_ec_typec: Add support for DP
altmode via drm_bridge
On Tue, Apr 15, 2025 at 05:02:06PM -0700, Stephen Boyd wrote:
> On Trogdor platforms, the USB DP altmode is entered and exited by the EC
> depending on if DP altmode is possible and if HPD is asserted for a
> port. Trogdor has two USB-C connectors but the AP only supports one DP
> controller, so the first USB-C connector to assert HPD "wins". The DP
> controller on the AP is fixed to output two lanes DP that goes to an
> analog mux that steers the DP lanes to one of the two USB-C connectors.
> The HPD state in the DP altmode is "captured" by the EC and redriven
> from a GPIO on the EC to the AP's GPIO that is muxed to the DisplayPort
> controller inside the AP SoC. This allows both HPD high/low and HPD IRQ
> to be signaled from the EC as well as making DP altmode possible on
> either USB-C connector except at the same time.
>
> Add a drm_bridge to the ChromeOS EC driver to represent this analog mux
> on Trogdor and teach the kernel that DP altmode is using this DP
> controller on the AP. When the DT node has a graph binding, we assume
> that we're muxing DP to one of many USB-C connectors and we terminate
> the bridge chain here. In almost all cases we want this bridge to be the
> one that signals HPD because the EC is the one managing HPD and
> redriving the GPIO, except for in the case that the DP altmode driver is
> enabled in which case HPD will be signaled with
> drm_bridge_connector_oob_hotplug_event(). Unfortunately Trogdor EC
> firmwares have a bug where HPD state isn't discoverable properly, so we
> skip signaling HPD in that case if the "no-hpd" property exists in the
> node.
>
> Cc: Benson Leung <bleung@...omium.org>
> Cc: Tzung-Bi Shih <tzungbi@...nel.org>
> Cc: <chrome-platform@...ts.linux.dev>
> Cc: Pin-yen Lin <treapking@...omium.org>
> Cc: Abhishek Pandit-Subedi <abhishekpandit@...omium.org>
> Cc: Łukasz Bartosik <ukaszb@...omium.org>
> Cc: Jameson Thies <jthies@...gle.com>
> Cc: Andrei Kuchynski <akuchynski@...omium.org>
> Signed-off-by: Stephen Boyd <swboyd@...omium.org>
> ---
> drivers/platform/chrome/Kconfig | 1 +
> drivers/platform/chrome/cros_ec_typec.c | 50 +++++++++++++++++++++++++
> drivers/platform/chrome/cros_ec_typec.h | 7 ++++
> 3 files changed, 58 insertions(+)
>
> diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
> index 1b2f2bd09662..0ed8637b8853 100644
> --- a/drivers/platform/chrome/Kconfig
> +++ b/drivers/platform/chrome/Kconfig
> @@ -247,6 +247,7 @@ config CROS_EC_TYPEC
> depends on MFD_CROS_EC_DEV && TYPEC
> depends on CROS_USBPD_NOTIFY
> depends on USB_ROLE_SWITCH
> + depends on DRM_BRIDGE
> default MFD_CROS_EC_DEV
> select CROS_EC_TYPEC_ALTMODES if TYPEC_DP_ALTMODE
> select CROS_EC_TYPEC_ALTMODES if TYPEC_TBT_ALTMODE
> diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
> index 2cbe29f08064..27324cf0c0c6 100644
> --- a/drivers/platform/chrome/cros_ec_typec.c
> +++ b/drivers/platform/chrome/cros_ec_typec.c
> @@ -9,6 +9,7 @@
> #include <linux/acpi.h>
> #include <linux/module.h>
> #include <linux/of.h>
> +#include <linux/of_graph.h>
> #include <linux/platform_data/cros_ec_commands.h>
> #include <linux/platform_data/cros_usbpd_notify.h>
> #include <linux/platform_device.h>
> @@ -16,6 +17,8 @@
> #include <linux/usb/typec_dp.h>
> #include <linux/usb/typec_tbt.h>
>
> +#include <drm/drm_bridge.h>
> +
> #include "cros_ec_typec.h"
> #include "cros_typec_vdm.h"
> #include "cros_typec_altmode.h"
> @@ -337,6 +340,9 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
> u32 port_num = 0;
>
> nports = device_get_child_node_count(dev);
> + /* Don't count any 'ports' child node */
> + if (of_graph_is_present(dev->of_node))
> + nports--;
Should this be a separate commit?
> if (nports == 0) {
> dev_err(dev, "No port entries found.\n");
> return -ENODEV;
> @@ -350,6 +356,10 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
> /* DT uses "reg" to specify port number. */
> port_prop = dev->of_node ? "reg" : "port-number";
> device_for_each_child_node(dev, fwnode) {
> + /* An OF graph isn't a connector */
> + if (fwnode_name_eq(fwnode, "ports"))
> + continue;
> +
... together with this chunk.
> if (fwnode_property_read_u32(fwnode, port_prop, &port_num)) {
> ret = -EINVAL;
> dev_err(dev, "No port-number for port, aborting.\n");
> @@ -417,6 +427,42 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
> return ret;
> }
>
> +static int cros_typec_dp_bridge_attach(struct drm_bridge *bridge,
> + enum drm_bridge_attach_flags flags)
> +{
> + return flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR ? 0 : -EINVAL;
> +}
> +
> +static const struct drm_bridge_funcs cros_typec_dp_bridge_funcs = {
> + .attach = cros_typec_dp_bridge_attach,
> +};
> +
> +static int cros_typec_init_dp_bridge(struct cros_typec_data *typec)
> +{
> + struct device *dev = typec->dev;
> + struct cros_typec_dp_bridge *dp_bridge;
> + struct drm_bridge *bridge;
> + struct device_node *np = dev->of_node;
> +
> + /* Not capable of DP altmode switching. Ignore. */
> + if (!of_graph_is_present(np))
> + return 0;
> +
> + dp_bridge = devm_kzalloc(dev, sizeof(*dp_bridge), GFP_KERNEL);
> + if (!dp_bridge)
> + return -ENOMEM;
> + typec->dp_bridge = dp_bridge;
> +
> + bridge = &dp_bridge->bridge;
> + bridge->funcs = &cros_typec_dp_bridge_funcs;
> + bridge->of_node = np;
> + bridge->type = DRM_MODE_CONNECTOR_DisplayPort;
> + if (!device_property_read_bool(dev, "no-hpd"))
> + bridge->ops |= DRM_BRIDGE_OP_HPD;
> +
> + return devm_drm_bridge_add(dev, bridge);
Could you please use aux-hpd-bridge instead?
BTW: what is the usecase for the no-hpd handling here?
> +}
> +
> static int cros_typec_usb_safe_state(struct cros_typec_port *port)
> {
> int ret;
--
With best wishes
Dmitry
Powered by blists - more mailing lists