* [PATCH v4 00/18] platform/chrome: Add DT USB/DP muxing/topology support
@ 2024-09-01 4:06 Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 01/18] drm/atomic-helper: Introduce lane remapping support to bridges Stephen Boyd
` (17 more replies)
0 siblings, 18 replies; 60+ messages in thread
From: Stephen Boyd @ 2024-09-01 4:06 UTC (permalink / raw)
To: chrome-platform
Cc: linux-kernel, patches, devicetree, Douglas Anderson, Pin-yen Lin,
Andrzej Hajda, Benson Leung, Conor Dooley, Daniel Vetter,
David Airlie, Dmitry Baryshkov, dri-devel, Guenter Roeck,
Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
This series adds support for fully describing the USB/DP topology on
ChromeOS Trogdor devices in DT. Trogdor devices have a single DP phy in
the AP that is muxed to one of two usb type-c connectors depending on
which port asserts HPD first to the EC. We'd like to know which port is
connected to an external monitor to provide a better experience to the
user about things like which type-c port is displaying DP or which
type-c hub is acting up, etc. Describing the connection all the way from
the source to the connector will allow us to do this.
DRM core patches: These are used to implement lane assignment for DP
altmode configurations through the drm_bridge code. The typec code will
use this to tell the DP phy how many lanes of DP to drive and which
lanes to drive out to the USB type-c connector. Adding support for lane
assignment allows us to implement DP muxing as well, physically
splitting the DP lanes on the DP phy so that hardware doesn't have to
use an analog mux to steer two DP lanes to one or the other type-c port.
Type-c core patches: These add some devm helpers so that the next
patches in the series can skip open-coding devres helpers for
unregistering typec switches and muxes.
DRM aux hpd patches: These implement an auxiliary device for USB type-c
DP alternate mode. I took Dmitry's suggestion and moved the code that
does the remapping into this driver. The existing hpd bridge is wrapped
so as to avoid changing the current users. It also registers a typec mux
and switch (if applicable) so that the DP altmode pin assignment and
port orientation can be passed to the switch callbacks. We'll still need
to implement logic in the phy layer to handle configuration.
Cros EC typec patches: This ties together everything that comes before it in
this series. The EC typec driver registers the drm_dp_typec_bridge that
can signal HPD from the type-c connector through the bridge chain, mux
the DP phy in software so that we don't have to use an analog mux, and
implement orientation control for boards like Kukui that directly
connect the DP phy to the type-c port, necessitating lane assignment to
flip the lanes to match the cable orientation.
Changes from v3: https://lore.kernel.org/r/20240819223834.2049862-1-swboyd@chromium.org
* Use devm_add_action_or_reset() for typec patches
* Fix kernel-doc
* Document devcon_match_fn_t before extending it
* Include err.h in typec header
* Document devm_typec_switch_register()
* Remove struct cros_typec_dp_bridge and fold it into parent
* Drop unevaluatedProperties in some places
* Change name of registered typec switches to include dev_name of
parent to avoid collisions
Changes from v2: https://lore.kernel.org/r/20240815003417.1175506-1-swboyd@chromium.org
* Move most of the binding bits to usb-switch.yaml
* Move google,cros-ec-typec binding to usb/
* Implement mode-switch and orientation-switch typec controls in
drm_dp_typec_bridge driver
* Get rid of public APIs that would be used to assign pins or
orientation of the port
* Add devm helpers for typec mux and switch registration
* Add a way to match fwnodes while walking the graph based on the
endpoint
Changes from v1: https://lore.kernel.org/r/20240210070934.2549994-1-swboyd@chromium.org
* Too many to count!
* Split out the DRM bits into this series
* Moved the logic into dp-aux-hpd bridge driver
* Drive the bridge from cros_ec_typec driver instead of globbing onto
the ACPI centric cros-typec-switch driver
* During that process drop a lot of patches that aren't needed anymore
* Move the DT graph and other properties to the cros-ec-typec binding
* Skip mode-switch/orientation-switch properties because we're not
registering typec structs anymore
Stephen Boyd (18):
drm/atomic-helper: Introduce lane remapping support to bridges
drm/bridge: Verify lane assignment is going to work during
atomic_check
usb: typec: Stub out typec_switch APIs when CONFIG_TYPEC=n
usb: typec: Add device managed typec_mux_register()
usb: typec: Add device managed typec_switch_register()
drm/bridge: aux-hpd: Support USB Type-C DP altmodes via DRM lane
assignment
drm/bridge: dp_typec: Support USB Type-C orientation
drm/bridge: dp_typec: Add "no-hpd" support
drm/bridge: dp_typec: Allow users to hook hpd notify path
devcon property: Document devcon_match_fn_t
device property: Add remote endpoint to devcon matcher
dt-bindings: usb-switch: Extract endpoints to defs
dt-bindings: usb-switch: Extend for DisplayPort altmode
dt-bindings: Move google,cros-ec-typec binding to usb
dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
platform/chrome: cros_ec_typec: Add support for signaling DP HPD via
drm_bridge
platform/chrome: cros_ec_typec: Support DP muxing
platform/chrome: cros_ec_typec: Handle lack of HPD information
.../bindings/chrome/google,cros-ec-typec.yaml | 66 --
.../bindings/mfd/google,cros-ec.yaml | 7 +-
.../bindings/usb/google,cros-ec-typec.yaml | 295 +++++++++
.../devicetree/bindings/usb/usb-switch.yaml | 163 ++++-
drivers/base/property.c | 7 +-
drivers/gpu/drm/bridge/aux-hpd-bridge.c | 575 +++++++++++++++++-
drivers/gpu/drm/drm_atomic_state_helper.c | 2 +
drivers/gpu/drm/drm_bridge.c | 51 ++
drivers/platform/chrome/Kconfig | 1 +
drivers/platform/chrome/cros_ec_typec.c | 136 ++++-
drivers/platform/chrome/cros_ec_typec.h | 4 +
drivers/usb/roles/class.c | 4 +-
drivers/usb/typec/mux.c | 79 +++
drivers/usb/typec/retimer.c | 7 +-
include/drm/bridge/aux-bridge.h | 26 +
include/drm/drm_atomic.h | 31 +
include/drm/drm_bridge.h | 4 +
include/linux/property.h | 24 +-
include/linux/usb/typec_mux.h | 59 +-
19 files changed, 1433 insertions(+), 108 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/chrome/google,cros-ec-typec.yaml
create mode 100644 Documentation/devicetree/bindings/usb/google,cros-ec-typec.yaml
base-commit: 8400291e289ee6b2bf9779ff1c83a291501f017b
--
https://chromeos.dev
^ permalink raw reply [flat|nested] 60+ messages in thread
* [PATCH v4 01/18] drm/atomic-helper: Introduce lane remapping support to bridges
2024-09-01 4:06 [PATCH v4 00/18] platform/chrome: Add DT USB/DP muxing/topology support Stephen Boyd
@ 2024-09-01 4:06 ` Stephen Boyd
2024-09-20 13:41 ` Dmitry Baryshkov
2024-09-01 4:06 ` [PATCH v4 02/18] drm/bridge: Verify lane assignment is going to work during atomic_check Stephen Boyd
` (16 subsequent siblings)
17 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-09-01 4:06 UTC (permalink / raw)
To: chrome-platform
Cc: linux-kernel, patches, devicetree, Douglas Anderson, Pin-yen Lin,
Andrzej Hajda, Benson Leung, Conor Dooley, Daniel Vetter,
David Airlie, Dmitry Baryshkov, dri-devel, Guenter Roeck,
Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
Add support to the DRM atomic logic to support lane remapping between
bridges, encoders and connectors. Typically lane mapping is handled
statically in firmware, e.g. on DT we use the data-lanes property to
assign lanes when connecting display bridges. Lane assignment is dynamic
with USB-C DisplayPort altmodes, e.g. pin conf D assigns 2 lanes of DP
to pins on the USB-C connector while pin conf C assigns 4 lanes of DP to
pins on the USB-C connector. The lane assignment can't be set statically
because the DP altmode repurposes USB-C pins for the DP lanes while also
limiting the number of DP lanes or their pin assignment at runtime.
Bridge drivers should point their 'struct drm_bus_cfg::lanes' pointer to
an allocated array of 'struct drm_lane_cfg' structures and indicate the
size of this allocated array with 'struct drm_bus_cfg::num_lanes' in
their atomic_check() callback. The previous bridge in the bridge chain
can look at this information by calling
drm_bridge_next_bridge_lane_cfg() in their atomic_check() callback to
figure out what lanes need to be logically assigned to the physical
output lanes to satisfy the next bridge's lane assignment.
Cc: Andrzej Hajda <andrzej.hajda@intel.com>
Cc: Neil Armstrong <neil.armstrong@linaro.org>
Cc: Robert Foss <rfoss@kernel.org>
Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
Cc: Jonas Karlman <jonas@kwiboo.se>
Cc: Jernej Skrabec <jernej.skrabec@gmail.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: David Airlie <airlied@gmail.com>
Cc: Daniel Vetter <daniel@ffwll.ch>
Cc: <dri-devel@lists.freedesktop.org>
Cc: Pin-yen Lin <treapking@chromium.org>
Cc: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
drivers/gpu/drm/drm_atomic_state_helper.c | 2 ++
drivers/gpu/drm/drm_bridge.c | 34 +++++++++++++++++++++++
include/drm/drm_atomic.h | 31 +++++++++++++++++++++
include/drm/drm_bridge.h | 4 +++
4 files changed, 71 insertions(+)
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c
index 519228eb1095..12d574458e7b 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -779,6 +779,8 @@ EXPORT_SYMBOL(drm_atomic_helper_bridge_duplicate_state);
void drm_atomic_helper_bridge_destroy_state(struct drm_bridge *bridge,
struct drm_bridge_state *state)
{
+ kfree(state->input_bus_cfg.lanes);
+ kfree(state->output_bus_cfg.lanes);
kfree(state);
}
EXPORT_SYMBOL(drm_atomic_helper_bridge_destroy_state);
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index d44f055dbe3e..bd18c1e91dee 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -822,6 +822,40 @@ void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge,
}
EXPORT_SYMBOL(drm_atomic_bridge_chain_enable);
+/**
+ * drm_bridge_next_bridge_lane_cfg - get the lane configuration of the next bridge
+ * @bridge: bridge control structure
+ * @state: new atomic state
+ * @num_lanes: will contain the size of the returned array
+ *
+ * This function is typically called from &drm_bridge_funcs.atomic_check().
+ * The @bridge driver calls this function to determine what the next bridge in
+ * the bridge chain requires for the physical to logical lane assignments.
+ *
+ * Return: Lane configuration array of size @num_lanes for the next bridge
+ * after @bridge in the bridge chain, or NULL if the lane configuration is
+ * unchanged from the default.
+ */
+const struct drm_lane_cfg *
+drm_bridge_next_bridge_lane_cfg(struct drm_bridge *bridge,
+ struct drm_atomic_state *state,
+ u8 *num_lanes)
+{
+ const struct drm_bridge_state *next_bridge_state;
+ struct drm_bridge *next_bridge = drm_bridge_get_next_bridge(bridge);
+
+ next_bridge_state = drm_atomic_get_new_bridge_state(state, next_bridge);
+ if (!next_bridge_state) {
+ *num_lanes = 0;
+ return NULL;
+ }
+
+ *num_lanes = next_bridge_state->input_bus_cfg.num_lanes;
+
+ return next_bridge_state->input_bus_cfg.lanes;
+}
+EXPORT_SYMBOL(drm_bridge_next_bridge_lane_cfg);
+
static int drm_atomic_bridge_check(struct drm_bridge *bridge,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 4d7f4c5f2001..e1a38d0742f1 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -1122,6 +1122,27 @@ drm_atomic_crtc_effectively_active(const struct drm_crtc_state *state)
return state->active || state->self_refresh_active;
}
+/**
+ * struct drm_lane_cfg - lane configuration
+ *
+ * This structure stores the lane configuration of a physical bus between
+ * two components in an output pipeline, usually between two bridges, an
+ * encoder and a bridge, or a bridge and a connector.
+ *
+ * The lane configuration is stored in &drm_bus_cfg.
+ */
+struct drm_lane_cfg {
+ /**
+ * @logical: Logical lane number
+ */
+ u8 logical;
+
+ /**
+ * @inverted: True if lane polarity is inverted, false otherwise
+ */
+ bool inverted;
+};
+
/**
* struct drm_bus_cfg - bus configuration
*
@@ -1152,6 +1173,16 @@ struct drm_bus_cfg {
* @flags: DRM_BUS_* flags used on this bus
*/
u32 flags;
+
+ /**
+ * @lanes: Lane mapping for this bus
+ */
+ struct drm_lane_cfg *lanes;
+
+ /**
+ * @num_lanes: Number of lanes in @lanes
+ */
+ u8 num_lanes;
};
/**
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 75019d16be64..064d3c8600a9 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -963,6 +963,10 @@ drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge,
struct drm_connector_state *conn_state,
u32 output_fmt,
unsigned int *num_input_fmts);
+const struct drm_lane_cfg *
+drm_bridge_next_bridge_lane_cfg(struct drm_bridge *bridge,
+ struct drm_atomic_state *state,
+ u8 *num_lanes);
enum drm_connector_status drm_bridge_detect(struct drm_bridge *bridge);
int drm_bridge_get_modes(struct drm_bridge *bridge,
--
https://chromeos.dev
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [PATCH v4 02/18] drm/bridge: Verify lane assignment is going to work during atomic_check
2024-09-01 4:06 [PATCH v4 00/18] platform/chrome: Add DT USB/DP muxing/topology support Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 01/18] drm/atomic-helper: Introduce lane remapping support to bridges Stephen Boyd
@ 2024-09-01 4:06 ` Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 03/18] usb: typec: Stub out typec_switch APIs when CONFIG_TYPEC=n Stephen Boyd
` (15 subsequent siblings)
17 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2024-09-01 4:06 UTC (permalink / raw)
To: chrome-platform
Cc: linux-kernel, patches, devicetree, Douglas Anderson, Pin-yen Lin,
Andrzej Hajda, Benson Leung, Conor Dooley, Daniel Vetter,
David Airlie, Dmitry Baryshkov, dri-devel, Guenter Roeck,
Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
Verify during drm_atomic_bridge_check() that the lane assignment set in
a bridge's atomic_check() callback is going to be satisfied by the
previous bridge. If the next bridge is requiring something besides the
default 1:1 lane assignment on its input then there must be an output
lane assignment on the previous bridge's output. Otherwise the next
bridge won't get the lanes assigned that it needs.
Cc: Andrzej Hajda <andrzej.hajda@intel.com>
Cc: Neil Armstrong <neil.armstrong@linaro.org>
Cc: Robert Foss <rfoss@kernel.org>
Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
Cc: Jonas Karlman <jonas@kwiboo.se>
Cc: Jernej Skrabec <jernej.skrabec@gmail.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: David Airlie <airlied@gmail.com>
Cc: Daniel Vetter <daniel@ffwll.ch>
Cc: <dri-devel@lists.freedesktop.org>
Cc: Pin-yen Lin <treapking@chromium.org>
Cc: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
drivers/gpu/drm/drm_bridge.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index bd18c1e91dee..e350248ba5c2 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -860,6 +860,10 @@ static int drm_atomic_bridge_check(struct drm_bridge *bridge,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
+ u8 num_input_lanes, num_output_lanes = 0;
+ const struct drm_lane_cfg *input_lanes;
+ unsigned int i;
+
if (bridge->funcs->atomic_check) {
struct drm_bridge_state *bridge_state;
int ret;
@@ -873,12 +877,25 @@ static int drm_atomic_bridge_check(struct drm_bridge *bridge,
crtc_state, conn_state);
if (ret)
return ret;
+ num_output_lanes = bridge_state->output_bus_cfg.num_lanes;
} else if (bridge->funcs->mode_fixup) {
if (!bridge->funcs->mode_fixup(bridge, &crtc_state->mode,
&crtc_state->adjusted_mode))
return -EINVAL;
}
+ input_lanes = drm_bridge_next_bridge_lane_cfg(bridge,
+ crtc_state->state,
+ &num_input_lanes);
+ /*
+ * Ensure this bridge is aware that the next bridge wants to
+ * reassign lanes.
+ */
+ for (i = 0; i < num_input_lanes; i++) {
+ if (i != input_lanes[i].logical && !num_output_lanes)
+ return -ENOTSUPP;
+ }
+
return 0;
}
--
https://chromeos.dev
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [PATCH v4 03/18] usb: typec: Stub out typec_switch APIs when CONFIG_TYPEC=n
2024-09-01 4:06 [PATCH v4 00/18] platform/chrome: Add DT USB/DP muxing/topology support Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 01/18] drm/atomic-helper: Introduce lane remapping support to bridges Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 02/18] drm/bridge: Verify lane assignment is going to work during atomic_check Stephen Boyd
@ 2024-09-01 4:06 ` Stephen Boyd
2024-09-03 11:40 ` Heikki Krogerus
2024-09-19 10:12 ` Dmitry Baryshkov
2024-09-01 4:06 ` [PATCH v4 04/18] usb: typec: Add device managed typec_mux_register() Stephen Boyd
` (14 subsequent siblings)
17 siblings, 2 replies; 60+ messages in thread
From: Stephen Boyd @ 2024-09-01 4:06 UTC (permalink / raw)
To: chrome-platform
Cc: linux-kernel, patches, devicetree, Douglas Anderson, Pin-yen Lin,
Andrzej Hajda, Benson Leung, Conor Dooley, Daniel Vetter,
David Airlie, Dmitry Baryshkov, dri-devel, Guenter Roeck,
Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
Ease driver development by adding stubs for the typec_switch APIs when
CONFIG_TYPEC=n. Copy the same method used for the typec_mux APIs to be
consistent.
Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: <linux-usb@vger.kernel.org>
Cc: Pin-yen Lin <treapking@chromium.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
include/linux/usb/typec_mux.h | 43 +++++++++++++++++++++++++++++++----
1 file changed, 38 insertions(+), 5 deletions(-)
diff --git a/include/linux/usb/typec_mux.h b/include/linux/usb/typec_mux.h
index 2489a7857d8e..efb5ed32b813 100644
--- a/include/linux/usb/typec_mux.h
+++ b/include/linux/usb/typec_mux.h
@@ -3,6 +3,7 @@
#ifndef __USB_TYPEC_MUX
#define __USB_TYPEC_MUX
+#include <linux/err.h>
#include <linux/property.h>
#include <linux/usb/typec.h>
@@ -24,16 +25,13 @@ struct typec_switch_desc {
void *drvdata;
};
+#if IS_ENABLED(CONFIG_TYPEC)
+
struct typec_switch *fwnode_typec_switch_get(struct fwnode_handle *fwnode);
void typec_switch_put(struct typec_switch *sw);
int typec_switch_set(struct typec_switch *sw,
enum typec_orientation orientation);
-static inline struct typec_switch *typec_switch_get(struct device *dev)
-{
- return fwnode_typec_switch_get(dev_fwnode(dev));
-}
-
struct typec_switch_dev *
typec_switch_register(struct device *parent,
const struct typec_switch_desc *desc);
@@ -42,6 +40,41 @@ void typec_switch_unregister(struct typec_switch_dev *sw);
void typec_switch_set_drvdata(struct typec_switch_dev *sw, void *data);
void *typec_switch_get_drvdata(struct typec_switch_dev *sw);
+#else
+
+static inline struct typec_switch *
+fwnode_typec_switch_get(struct fwnode_handle *fwnode)
+{
+ return NULL;
+}
+static inline void typec_switch_put(struct typec_switch *sw) {}
+static inline int typec_switch_set(struct typec_switch *sw,
+ enum typec_orientation orientation)
+{
+ return 0;
+}
+
+static inline struct typec_switch_dev *
+typec_switch_register(struct device *parent,
+ const struct typec_switch_desc *desc)
+{
+ return ERR_PTR(-EOPNOTSUPP);
+}
+static inline void typec_switch_unregister(struct typec_switch_dev *sw) {}
+
+static inline void typec_switch_set_drvdata(struct typec_switch_dev *sw, void *data) {}
+static inline void *typec_switch_get_drvdata(struct typec_switch_dev *sw)
+{
+ return ERR_PTR(-EOPNOTSUPP);
+}
+
+#endif /* CONFIG_TYPEC */
+
+static inline struct typec_switch *typec_switch_get(struct device *dev)
+{
+ return fwnode_typec_switch_get(dev_fwnode(dev));
+}
+
struct typec_mux_state {
struct typec_altmode *alt;
unsigned long mode;
--
https://chromeos.dev
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [PATCH v4 04/18] usb: typec: Add device managed typec_mux_register()
2024-09-01 4:06 [PATCH v4 00/18] platform/chrome: Add DT USB/DP muxing/topology support Stephen Boyd
` (2 preceding siblings ...)
2024-09-01 4:06 ` [PATCH v4 03/18] usb: typec: Stub out typec_switch APIs when CONFIG_TYPEC=n Stephen Boyd
@ 2024-09-01 4:06 ` Stephen Boyd
2024-09-03 11:57 ` Heikki Krogerus
2024-09-01 4:06 ` [PATCH v4 05/18] usb: typec: Add device managed typec_switch_register() Stephen Boyd
` (13 subsequent siblings)
17 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-09-01 4:06 UTC (permalink / raw)
To: chrome-platform
Cc: linux-kernel, patches, devicetree, Douglas Anderson, Pin-yen Lin,
Andrzej Hajda, Benson Leung, Conor Dooley, Daniel Vetter,
David Airlie, Dmitry Baryshkov, dri-devel, Guenter Roeck,
Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
Simplify driver error paths by adding devm_typec_mux_register() which
will unregister the typec mux when the parent device is unbound.
Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: <linux-usb@vger.kernel.org>
Cc: Pin-yen Lin <treapking@chromium.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
drivers/usb/typec/mux.c | 35 +++++++++++++++++++++++++++++++++++
include/linux/usb/typec_mux.h | 7 +++++++
2 files changed, 42 insertions(+)
diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c
index 49926d6e72c7..db644bec862c 100644
--- a/drivers/usb/typec/mux.c
+++ b/drivers/usb/typec/mux.c
@@ -457,6 +457,41 @@ void typec_mux_unregister(struct typec_mux_dev *mux_dev)
}
EXPORT_SYMBOL_GPL(typec_mux_unregister);
+static void devm_typec_mux_unregister(void *mux_dev)
+{
+ typec_mux_unregister(mux_dev);
+}
+
+/**
+ * devm_typec_mux_register - resource managed typec_mux_register()
+ * @parent: Parent device
+ * @desc: Multiplexer description
+ *
+ * Register a typec mux and automatically unregister the typec mux
+ * when @parent is unbound from its driver.
+ *
+ * The arguments to this function are identical to typec_mux_register().
+ *
+ * Return: the typec_mux_dev structure on success or error pointer on error.
+ */
+struct typec_mux_dev *
+devm_typec_mux_register(struct device *parent, const struct typec_mux_desc *desc)
+{
+ int ret;
+ struct typec_mux_dev *mux_dev;
+
+ mux_dev = typec_mux_register(parent, desc);
+ if (IS_ERR(mux_dev))
+ return mux_dev;
+
+ ret = devm_add_action_or_reset(parent, devm_typec_mux_unregister, mux_dev);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return mux_dev;
+}
+EXPORT_SYMBOL_GPL(devm_typec_mux_register);
+
void typec_mux_set_drvdata(struct typec_mux_dev *mux_dev, void *data)
{
dev_set_drvdata(&mux_dev->dev, data);
diff --git a/include/linux/usb/typec_mux.h b/include/linux/usb/typec_mux.h
index efb5ed32b813..08431f0896d5 100644
--- a/include/linux/usb/typec_mux.h
+++ b/include/linux/usb/typec_mux.h
@@ -99,6 +99,8 @@ int typec_mux_set(struct typec_mux *mux, struct typec_mux_state *state);
struct typec_mux_dev *
typec_mux_register(struct device *parent, const struct typec_mux_desc *desc);
+struct typec_mux_dev *
+devm_typec_mux_register(struct device *parent, const struct typec_mux_desc *desc);
void typec_mux_unregister(struct typec_mux_dev *mux);
void typec_mux_set_drvdata(struct typec_mux_dev *mux, void *data);
@@ -123,6 +125,11 @@ typec_mux_register(struct device *parent, const struct typec_mux_desc *desc)
{
return ERR_PTR(-EOPNOTSUPP);
}
+static inline struct typec_mux_dev *
+devm_typec_mux_register(struct device *parent, const struct typec_mux_desc *desc)
+{
+ return typec_mux_register(parent, desc);
+}
static inline void typec_mux_unregister(struct typec_mux_dev *mux) {}
static inline void typec_mux_set_drvdata(struct typec_mux_dev *mux, void *data) {}
--
https://chromeos.dev
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [PATCH v4 05/18] usb: typec: Add device managed typec_switch_register()
2024-09-01 4:06 [PATCH v4 00/18] platform/chrome: Add DT USB/DP muxing/topology support Stephen Boyd
` (3 preceding siblings ...)
2024-09-01 4:06 ` [PATCH v4 04/18] usb: typec: Add device managed typec_mux_register() Stephen Boyd
@ 2024-09-01 4:06 ` Stephen Boyd
2024-09-02 11:22 ` Andy Shevchenko
2024-09-01 4:06 ` [PATCH v4 06/18] drm/bridge: aux-hpd: Support USB Type-C DP altmodes via DRM lane assignment Stephen Boyd
` (12 subsequent siblings)
17 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-09-01 4:06 UTC (permalink / raw)
To: chrome-platform
Cc: linux-kernel, patches, devicetree, Douglas Anderson, Pin-yen Lin,
Andrzej Hajda, Benson Leung, Conor Dooley, Daniel Vetter,
David Airlie, Dmitry Baryshkov, dri-devel, Guenter Roeck,
Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
Simplify driver error paths by adding devm_typec_switch_register() which
will unregister the typec switch when the parent device is unbound.
Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: <linux-usb@vger.kernel.org>
Cc: Pin-yen Lin <treapking@chromium.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
drivers/usb/typec/mux.c | 36 +++++++++++++++++++++++++++++++++++
include/linux/usb/typec_mux.h | 9 +++++++++
2 files changed, 45 insertions(+)
diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c
index db644bec862c..f420185e36e3 100644
--- a/drivers/usb/typec/mux.c
+++ b/drivers/usb/typec/mux.c
@@ -235,6 +235,42 @@ void typec_switch_unregister(struct typec_switch_dev *sw_dev)
}
EXPORT_SYMBOL_GPL(typec_switch_unregister);
+static void devm_typec_switch_unregister(void *switch_dev)
+{
+ typec_switch_unregister(switch_dev);
+}
+
+/**
+ * devm_typec_switch_register - resource managed typec_switch_register()
+ * @parent: Parent device
+ * @desc: Multiplexer description
+ *
+ * Register a typec switch and automatically unregister the typec switch
+ * when @parent is unbound from its driver.
+ *
+ * The arguments to this function are identical to typec_switch_register().
+ *
+ * Return: the typec_switch_dev structure on success or error pointer on error.
+ */
+struct typec_switch_dev *
+devm_typec_switch_register(struct device *parent,
+ const struct typec_switch_desc *desc)
+{
+ int ret;
+ struct typec_switch_dev *switch_dev;
+
+ switch_dev = typec_switch_register(parent ,desc);
+ if (IS_ERR(switch_dev))
+ return switch_dev;
+
+ ret = devm_add_action_or_reset(parent, devm_typec_switch_unregister, switch_dev);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return switch_dev;
+}
+EXPORT_SYMBOL_GPL(devm_typec_switch_register);
+
void typec_switch_set_drvdata(struct typec_switch_dev *sw_dev, void *data)
{
dev_set_drvdata(&sw_dev->dev, data);
diff --git a/include/linux/usb/typec_mux.h b/include/linux/usb/typec_mux.h
index 08431f0896d5..c30fc7f4441f 100644
--- a/include/linux/usb/typec_mux.h
+++ b/include/linux/usb/typec_mux.h
@@ -35,6 +35,9 @@ int typec_switch_set(struct typec_switch *sw,
struct typec_switch_dev *
typec_switch_register(struct device *parent,
const struct typec_switch_desc *desc);
+struct typec_switch_dev *
+devm_typec_switch_register(struct device *parent,
+ const struct typec_switch_desc *desc);
void typec_switch_unregister(struct typec_switch_dev *sw);
void typec_switch_set_drvdata(struct typec_switch_dev *sw, void *data);
@@ -60,6 +63,12 @@ typec_switch_register(struct device *parent,
{
return ERR_PTR(-EOPNOTSUPP);
}
+static inline struct typec_switch_dev *
+devm_typec_switch_register(struct device *parent,
+ const struct typec_switch_desc *desc)
+{
+ return typec_switch_register(parent, desc);
+}
static inline void typec_switch_unregister(struct typec_switch_dev *sw) {}
static inline void typec_switch_set_drvdata(struct typec_switch_dev *sw, void *data) {}
--
https://chromeos.dev
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [PATCH v4 06/18] drm/bridge: aux-hpd: Support USB Type-C DP altmodes via DRM lane assignment
2024-09-01 4:06 [PATCH v4 00/18] platform/chrome: Add DT USB/DP muxing/topology support Stephen Boyd
` (4 preceding siblings ...)
2024-09-01 4:06 ` [PATCH v4 05/18] usb: typec: Add device managed typec_switch_register() Stephen Boyd
@ 2024-09-01 4:06 ` Stephen Boyd
2024-09-02 11:35 ` Andy Shevchenko
2024-09-01 4:06 ` [PATCH v4 07/18] drm/bridge: dp_typec: Support USB Type-C orientation Stephen Boyd
` (11 subsequent siblings)
17 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-09-01 4:06 UTC (permalink / raw)
To: chrome-platform
Cc: linux-kernel, patches, devicetree, Douglas Anderson, Pin-yen Lin,
Andrzej Hajda, Benson Leung, Conor Dooley, Daniel Vetter,
David Airlie, Dmitry Baryshkov, dri-devel, Guenter Roeck,
Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
Extend the aux-hpd bridge driver to support assigning DP lanes to USB
type-c pins based on typec mux state entry. Existing users of this
driver only need the HPD signaling support, so leave that in place and
wrap the code with a variant that supports more features of USB type-c
DP altmode, i.e. pin configurations. Prefix that code with
'drm_dp_typec_bridge' to differentiate it from the existing
'drm_aux_hpd_bridge' code.
Parse the struct typec_mux_state members to determine if DP altmode has
been entered and if HPD is asserted or not. Signal HPD to the drm bridge
chain when HPD is asserted. Similarly, parse the pin assignment and map
the DP lanes to the usb-c output lanes, taking into account any lane
remapping from the data-lanes endpoint property. Pass that lane mapping
to the previous drm_bridge in the bridge chain during the atomic check
phase.
Cc: Prashant Malani <pmalani@chromium.org>
Cc: Benson Leung <bleung@chromium.org>
Cc: Tzung-Bi Shih <tzungbi@kernel.org>
Cc: <chrome-platform@lists.linux.dev>
Cc: Pin-yen Lin <treapking@chromium.org>
Cc: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
drivers/gpu/drm/bridge/aux-hpd-bridge.c | 483 +++++++++++++++++++++++-
include/drm/bridge/aux-bridge.h | 17 +
2 files changed, 488 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/bridge/aux-hpd-bridge.c b/drivers/gpu/drm/bridge/aux-hpd-bridge.c
index 6886db2d9e00..32565f88ade7 100644
--- a/drivers/gpu/drm/bridge/aux-hpd-bridge.c
+++ b/drivers/gpu/drm/bridge/aux-hpd-bridge.c
@@ -7,8 +7,14 @@
#include <linux/auxiliary_bus.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/usb/typec.h>
+#include <linux/usb/typec_dp.h>
+#include <linux/usb/typec_mux.h>
+#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_bridge.h>
+#include <drm/drm_print.h>
#include <drm/bridge/aux-bridge.h>
static DEFINE_IDA(drm_aux_hpd_bridge_ida);
@@ -18,6 +24,80 @@ struct drm_aux_hpd_bridge_data {
struct device *dev;
};
+enum dp_lane {
+ DP_ML0 = 0, /* DP pins 1/3 */
+ DP_ML1 = 1, /* DP pins 4/6 */
+ DP_ML2 = 2, /* DP pins 7/9 */
+ DP_ML3 = 3, /* DP pins 10/12 */
+};
+
+#define NUM_DP_ML (DP_ML3 + 1)
+
+enum usb_ss_lane {
+ USB_SSRX1 = 0, /* Type-C pins B11/B10 */
+ USB_SSTX1 = 1, /* Type-C pins A2/A3 */
+ USB_SSTX2 = 2, /* Type-C pins A11/A10 */
+ USB_SSRX2 = 3, /* Type-C pins B2/B3 */
+};
+
+#define NUM_USB_SS (USB_SSRX2 + 1)
+
+struct drm_dp_typec_bridge_data;
+
+/**
+ * struct drm_dp_typec_bridge_typec_port - USB type-c port associated with DP bridge
+ * @lane_mapping: Physical (array index) to logical (array value) USB type-C lane mapping
+ * @mode_switch: DP altmode switch
+ * @typec_data: Back pointer to type-c bridge data
+ */
+struct drm_dp_typec_bridge_typec_port {
+ u32 lane_mapping[NUM_USB_SS];
+ struct typec_mux_dev *mode_switch;
+ struct drm_dp_typec_bridge_data *typec_data;
+};
+
+/**
+ * struct drm_dp_typec_bridge_data - DP over USB type-c drm_bridge
+ * @dp_lanes: Physical (array value) to logical (array index) DP lane mapping
+ * @num_lanes: Number of valid lanes in @dp_lanes
+ * @hpd_bridge: hpd_bridge data
+ */
+struct drm_dp_typec_bridge_data {
+ u8 dp_lanes[NUM_DP_ML];
+ size_t num_lanes;
+ struct drm_aux_hpd_bridge_data hpd_bridge;
+};
+
+static inline struct drm_dp_typec_bridge_data *
+hpd_bridge_to_typec_bridge_data(struct drm_aux_hpd_bridge_data *hpd_data)
+{
+ return container_of(hpd_data, struct drm_dp_typec_bridge_data, hpd_bridge);
+}
+
+static inline struct drm_dp_typec_bridge_data *
+to_drm_dp_typec_bridge_data(struct drm_bridge *bridge)
+{
+ struct drm_aux_hpd_bridge_data *hpd_data;
+
+ hpd_data = container_of(bridge, struct drm_aux_hpd_bridge_data, bridge);
+
+ return hpd_bridge_to_typec_bridge_data(hpd_data);
+}
+
+struct drm_dp_typec_bridge_dev {
+ struct auxiliary_device adev;
+ size_t max_lanes;
+ size_t num_typec_ports;
+};
+
+static inline struct drm_dp_typec_bridge_dev *
+to_drm_dp_typec_bridge_dev(struct device *dev)
+{
+ struct auxiliary_device *adev = to_auxiliary_dev(dev);
+
+ return container_of(adev, struct drm_dp_typec_bridge_dev, adev);
+}
+
static void drm_aux_hpd_bridge_release(struct device *dev)
{
struct auxiliary_device *adev = to_auxiliary_dev(dev);
@@ -30,6 +110,22 @@ static void drm_aux_hpd_bridge_release(struct device *dev)
kfree(adev);
}
+static void drm_dp_typec_bridge_release(struct device *dev)
+{
+ struct drm_dp_typec_bridge_dev *typec_bridge_dev;
+ struct auxiliary_device *adev;
+
+ typec_bridge_dev = to_drm_dp_typec_bridge_dev(dev);
+ adev = &typec_bridge_dev->adev;
+
+ ida_free(&drm_aux_hpd_bridge_ida, adev->id);
+
+ of_node_put(adev->dev.platform_data);
+ of_node_put(adev->dev.of_node);
+
+ kfree(typec_bridge_dev);
+}
+
static void drm_aux_hpd_bridge_free_adev(void *_adev)
{
auxiliary_device_uninit(_adev);
@@ -133,6 +229,111 @@ struct device *drm_dp_hpd_bridge_register(struct device *parent, struct device_n
}
EXPORT_SYMBOL_GPL(drm_dp_hpd_bridge_register);
+/**
+ * devm_drm_dp_typec_bridge_alloc - Allocate a USB type-c DisplayPort bridge
+ * @parent: device instance providing this bridge
+ * @np: device node pointer corresponding to this bridge instance
+ *
+ * Creates a DRM bridge with the type set to DRM_MODE_CONNECTOR_DisplayPort,
+ * which terminates the bridge chain and is able to send the HPD events along
+ * with remap DP lanes to match USB type-c DP altmode pin assignments.
+ *
+ * Return: device instance that will handle created bridge or an error code
+ * encoded into the pointer.
+ */
+struct drm_dp_typec_bridge_dev *
+devm_drm_dp_typec_bridge_alloc(struct device *parent, struct device_node *np)
+{
+ struct drm_dp_typec_bridge_dev *typec_bridge_dev;
+ struct auxiliary_device *adev;
+ int ret, num_dp_lanes;
+ struct device_node *dp_ep __free(device_node) = NULL;
+ struct device_node *remote_ep;
+ struct device_node *ep_node;
+ struct of_endpoint ep;
+
+ typec_bridge_dev = kzalloc(sizeof(*typec_bridge_dev), GFP_KERNEL);
+ if (!typec_bridge_dev)
+ return ERR_PTR(-ENOMEM);
+ adev = &typec_bridge_dev->adev;
+
+ for_each_endpoint_of_node(np, ep_node) {
+ of_graph_parse_endpoint(ep_node, &ep);
+ /* Only consider available endpoints */
+ if (!of_device_is_available(ep_node))
+ continue;
+ /* Only consider connected nodes */
+ remote_ep = of_graph_get_remote_endpoint(ep_node);
+ of_node_put(remote_ep);
+ if (!remote_ep)
+ continue;
+
+ if (ep.port == 2)
+ dp_ep = of_node_get(ep_node);
+ else if (ep.port == 0)
+ typec_bridge_dev->num_typec_ports++;
+ }
+
+ if (!typec_bridge_dev->num_typec_ports) {
+ kfree(adev);
+ return ERR_PTR(dev_err_probe(parent, -ENODEV, "Missing typec endpoint(s) port@0\n"));
+ }
+
+ if (!dp_ep) {
+ kfree(adev);
+ return ERR_PTR(dev_err_probe(parent, -ENODEV, "Missing DP endpoint port@2\n"));
+ }
+
+ num_dp_lanes = of_property_count_u32_elems(dp_ep, "data-lanes");
+ if (num_dp_lanes < 0)
+ num_dp_lanes = NUM_DP_ML;
+
+ typec_bridge_dev->max_lanes = num_dp_lanes;
+
+ ret = ida_alloc(&drm_aux_hpd_bridge_ida, GFP_KERNEL);
+ if (ret < 0) {
+ kfree(adev);
+ return ERR_PTR(ret);
+ }
+
+ adev->id = ret;
+ adev->name = "dp_typec_bridge";
+ adev->dev.parent = parent;
+ adev->dev.of_node = of_node_get(parent->of_node);
+ adev->dev.release = drm_dp_typec_bridge_release;
+ adev->dev.platform_data = of_node_get(np);
+ ret = auxiliary_device_init(adev);
+ if (ret) {
+ of_node_put(adev->dev.platform_data);
+ of_node_put(adev->dev.of_node);
+ ida_free(&drm_aux_hpd_bridge_ida, adev->id);
+ kfree(adev);
+ return ERR_PTR(ret);
+ }
+
+ ret = devm_add_action_or_reset(parent, drm_aux_hpd_bridge_free_adev, adev);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return typec_bridge_dev;
+}
+EXPORT_SYMBOL_GPL(devm_drm_dp_typec_bridge_alloc);
+
+/**
+ * devm_drm_dp_typec_bridge_add - register a USB type-c DisplayPort bridge
+ * @dev: struct device to tie registration lifetime to
+ * @typec_bridge_dev: USB type-c DisplayPort bridge to be registered
+ *
+ * Returns: zero on success or a negative errno
+ */
+int devm_drm_dp_typec_bridge_add(struct device *dev, struct drm_dp_typec_bridge_dev *typec_bridge_dev)
+{
+ struct auxiliary_device *adev = &typec_bridge_dev->adev;
+
+ return devm_drm_dp_hpd_bridge_add(dev, adev);
+}
+EXPORT_SYMBOL_GPL(devm_drm_dp_typec_bridge_add);
+
/**
* drm_aux_hpd_bridge_notify - notify hot plug detection events
* @dev: device created for the HPD bridge
@@ -161,32 +362,290 @@ static int drm_aux_hpd_bridge_attach(struct drm_bridge *bridge,
return flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR ? 0 : -EINVAL;
}
+static int dp_lane_to_typec_lane(enum dp_lane lane)
+{
+ switch (lane) {
+ case DP_ML0:
+ return USB_SSTX2;
+ case DP_ML1:
+ return USB_SSRX2;
+ case DP_ML2:
+ return USB_SSTX1;
+ case DP_ML3:
+ return USB_SSRX1;
+ }
+
+ return -EINVAL;
+}
+
+static int typec_to_dp_lane(enum usb_ss_lane lane)
+{
+ switch (lane) {
+ case USB_SSRX1:
+ return DP_ML3;
+ case USB_SSTX1:
+ return DP_ML2;
+ case USB_SSTX2:
+ return DP_ML0;
+ case USB_SSRX2:
+ return DP_ML1;
+ }
+
+ return -EINVAL;
+}
+
+/**
+ * drm_dp_typec_bridge_assign_pins - Assign DisplayPort (DP) lanes to USB type-c pins
+ * @typec_bridge_dev: USB type-c DisplayPort bridge
+ * @conf: DisplayPort altmode configure command VDO content
+ * @port: The USB type-c output port to assign pins to
+ *
+ * Assign DP lanes to the @port's USB type-c pins for the DP altmode
+ * configuration @conf, while taking into account the USB type-c lane_mapping.
+ * Future atomic checks on this bridge will request the lane assignment from
+ * the previous bridge so that the DP signal is sent to the assigned USB type-c
+ * pins.
+ *
+ * Return: 0 on success, negative value for failure.
+ */
+static int
+drm_dp_typec_bridge_assign_pins(struct drm_dp_typec_bridge_dev *typec_bridge_dev,
+ u32 conf,
+ struct drm_dp_typec_bridge_typec_port *port)
+{
+ enum usb_ss_lane *lane_mapping = port->lane_mapping;
+ struct auxiliary_device *adev = &typec_bridge_dev->adev;
+ struct drm_aux_hpd_bridge_data *hpd_data = auxiliary_get_drvdata(adev);
+ struct drm_dp_typec_bridge_data *data;
+ u8 *dp_lanes;
+ size_t num_lanes, max_lanes;
+ int i, typec_lane;
+ u8 pin_assign;
+
+ if (!hpd_data)
+ return -EINVAL;
+
+ data = hpd_bridge_to_typec_bridge_data(hpd_data);
+ dp_lanes = data->dp_lanes;
+
+ pin_assign = DP_CONF_GET_PIN_ASSIGN(conf);
+ if (pin_assign == DP_PIN_ASSIGN_D)
+ num_lanes = 2;
+ else
+ num_lanes = 4;
+ max_lanes = typec_bridge_dev->max_lanes;
+ data->num_lanes = num_lanes = min(num_lanes, max_lanes);
+
+ for (i = 0; i < num_lanes; i++) {
+ /* Get physical type-c lane for DP lane */
+ typec_lane = dp_lane_to_typec_lane(i);
+ if (typec_lane < 0) {
+ dev_err(&adev->dev, "Invalid type-c lane configuration at DP_ML%d\n", i);
+ return -EINVAL;
+ }
+
+ /* Map physical to logical type-c lane */
+ typec_lane = lane_mapping[typec_lane];
+
+ /* Map logical type-c lane to logical DP lane */
+ dp_lanes[i] = typec_to_dp_lane(typec_lane);
+ }
+
+ return 0;
+}
+
+static int drm_dp_typec_bridge_atomic_check(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ struct drm_dp_typec_bridge_data *data;
+ struct drm_lane_cfg *in_lanes;
+ u8 *dp_lanes;
+ size_t num_lanes;
+ int i;
+
+ data = to_drm_dp_typec_bridge_data(bridge);
+ num_lanes = data->num_lanes;
+ if (!num_lanes)
+ return 0;
+ dp_lanes = data->dp_lanes;
+
+ in_lanes = kcalloc(num_lanes, sizeof(*in_lanes), GFP_KERNEL);
+ if (!in_lanes)
+ return -ENOMEM;
+
+ bridge_state->input_bus_cfg.lanes = in_lanes;
+ bridge_state->input_bus_cfg.num_lanes = num_lanes;
+
+ for (i = 0; i < num_lanes; i++)
+ in_lanes[i].logical = dp_lanes[i];
+
+ return 0;
+}
+
static const struct drm_bridge_funcs drm_aux_hpd_bridge_funcs = {
.attach = drm_aux_hpd_bridge_attach,
};
+static const struct drm_bridge_funcs drm_dp_typec_bridge_funcs = {
+ .attach = drm_aux_hpd_bridge_attach,
+ .atomic_check = drm_dp_typec_bridge_atomic_check,
+ .atomic_reset = drm_atomic_helper_bridge_reset,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+};
+
+static int
+drm_dp_typec_bridge_mode_switch_set(struct typec_mux_dev *mode_switch,
+ struct typec_mux_state *state)
+{
+ struct drm_dp_typec_bridge_typec_port *port;
+ const struct typec_displayport_data *dp_data;
+ struct drm_dp_typec_bridge_data *typec_data;
+ struct drm_dp_typec_bridge_dev *typec_bridge_dev;
+ struct device *dev;
+ int ret;
+ enum drm_connector_status status;
+
+ port = typec_mux_get_drvdata(mode_switch);
+ typec_data = port->typec_data;
+ dev = typec_data->hpd_bridge.dev;
+ typec_bridge_dev = to_drm_dp_typec_bridge_dev(dev);
+
+ if (state->mode == TYPEC_STATE_SAFE || state->mode == TYPEC_STATE_USB) {
+ drm_aux_hpd_bridge_notify(dev, connector_status_disconnected);
+ } else if (state->alt && state->alt->svid == USB_TYPEC_DP_SID) {
+ dp_data = state->data;
+ ret = drm_dp_typec_bridge_assign_pins(typec_bridge_dev, state->mode, port);
+ if (ret)
+ return ret;
+
+ if (dp_data->status & DP_STATUS_HPD_STATE)
+ status = connector_status_connected;
+ else
+ status = connector_status_disconnected;
+
+ drm_aux_hpd_bridge_notify(dev, status);
+ }
+
+ return 0;
+}
+
+static int
+drm_dp_typec_bridge_probe_typec_ports(struct drm_dp_typec_bridge_data *typec_data,
+ struct drm_dp_typec_bridge_dev *typec_bridge_dev,
+ struct device_node *np)
+{
+ struct device *dev = &typec_bridge_dev->adev.dev;
+ struct device_node *typec_ep, *remote_ep;
+ struct of_endpoint ep;
+ const u32 mapping[] = { 0, 1, 2, 3 };
+ struct drm_dp_typec_bridge_typec_port *port;
+ size_t num_ports = typec_bridge_dev->num_typec_ports;
+ struct typec_mux_desc mode_switch_desc = { };
+ struct fwnode_handle *fwnode;
+ const char *name;
+
+ port = devm_kcalloc(dev, num_ports, sizeof(*port), GFP_KERNEL);
+ if (!port)
+ return -ENOMEM;
+
+ for_each_endpoint_of_node(np, typec_ep) {
+ of_graph_parse_endpoint(typec_ep, &ep);
+ /* Only look at the usbc output port (port@0) */
+ if (ep.port != 0)
+ continue;
+ /* Only consider available endpoints */
+ if (!of_device_is_available(typec_ep))
+ continue;
+ /* Only consider connected nodes */
+ remote_ep = of_graph_get_remote_endpoint(typec_ep);
+ of_node_put(remote_ep);
+ if (!remote_ep)
+ continue;
+
+ port->typec_data = typec_data;
+ if (of_property_read_u32_array(ep.local_node, "data-lanes",
+ port->lane_mapping,
+ ARRAY_SIZE(port->lane_mapping))) {
+ memcpy(port->lane_mapping, mapping, sizeof(mapping));
+ }
+
+ fwnode = of_fwnode_handle(typec_ep);
+ name = kasprintf(GFP_KERNEL, "%s-%d", dev_name(dev), ep.id);
+ if (!name)
+ return -ENOMEM;
+
+ mode_switch_desc.set = drm_dp_typec_bridge_mode_switch_set;
+ mode_switch_desc.fwnode = fwnode;
+ mode_switch_desc.name = name;
+ mode_switch_desc.drvdata = port;
+ port->mode_switch = devm_typec_mux_register(dev, &mode_switch_desc);
+ if (IS_ERR(port->mode_switch)) {
+ kfree(name);
+ return PTR_ERR(port->mode_switch);
+ }
+
+ kfree(name);
+ port++;
+ }
+
+ return 0;
+}
+
+enum drm_aux_bridge_type {
+ DRM_AUX_HPD_BRIDGE,
+ DRM_AUX_TYPEC_BRIDGE,
+};
+
static int drm_aux_hpd_bridge_probe(struct auxiliary_device *auxdev,
const struct auxiliary_device_id *id)
{
- struct drm_aux_hpd_bridge_data *data;
+ struct device *dev = &auxdev->dev;
+ struct drm_aux_hpd_bridge_data *hpd_data;
+ struct drm_dp_typec_bridge_dev *typec_bridge_dev;
+ struct drm_dp_typec_bridge_data *typec_data;
+ struct drm_bridge *bridge;
+ struct device_node *np = dev_get_platdata(dev);
+ u8 dp_lanes[] = { DP_ML0, DP_ML1, DP_ML2, DP_ML3 };
+ int ret;
- data = devm_kzalloc(&auxdev->dev, sizeof(*data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
+ if (id->driver_data == DRM_AUX_HPD_BRIDGE) {
+ hpd_data = devm_kzalloc(dev, sizeof(*hpd_data), GFP_KERNEL);
+ if (!hpd_data)
+ return -ENOMEM;
+ bridge = &hpd_data->bridge;
+ bridge->funcs = &drm_aux_hpd_bridge_funcs;
+ } else if (id->driver_data == DRM_AUX_TYPEC_BRIDGE) {
+ typec_data = devm_kzalloc(dev, sizeof(*typec_data), GFP_KERNEL);
+ if (!typec_data)
+ return -ENOMEM;
+ hpd_data = &typec_data->hpd_bridge;
+ bridge = &hpd_data->bridge;
+ bridge->funcs = &drm_dp_typec_bridge_funcs;
+ typec_bridge_dev = to_drm_dp_typec_bridge_dev(dev);
+ memcpy(typec_data->dp_lanes, dp_lanes, sizeof(typec_data->dp_lanes));
+ ret = drm_dp_typec_bridge_probe_typec_ports(typec_data, typec_bridge_dev, np);
+ if (ret)
+ return ret;
+ } else {
+ return -ENODEV;
+ }
- data->dev = &auxdev->dev;
- data->bridge.funcs = &drm_aux_hpd_bridge_funcs;
- data->bridge.of_node = dev_get_platdata(data->dev);
- data->bridge.ops = DRM_BRIDGE_OP_HPD;
- data->bridge.type = id->driver_data;
+ hpd_data->dev = dev;
+ bridge->of_node = dev_get_platdata(dev);
+ bridge->ops = DRM_BRIDGE_OP_HPD;
+ bridge->type = DRM_MODE_CONNECTOR_DisplayPort;
- auxiliary_set_drvdata(auxdev, data);
+ auxiliary_set_drvdata(auxdev, hpd_data);
- return devm_drm_bridge_add(data->dev, &data->bridge);
+ return devm_drm_bridge_add(dev, bridge);
}
static const struct auxiliary_device_id drm_aux_hpd_bridge_table[] = {
- { .name = KBUILD_MODNAME ".dp_hpd_bridge", .driver_data = DRM_MODE_CONNECTOR_DisplayPort, },
+ { .name = KBUILD_MODNAME ".dp_hpd_bridge", .driver_data = DRM_AUX_HPD_BRIDGE, },
+ { .name = KBUILD_MODNAME ".dp_typec_bridge", .driver_data = DRM_AUX_TYPEC_BRIDGE, },
{},
};
MODULE_DEVICE_TABLE(auxiliary, drm_aux_hpd_bridge_table);
diff --git a/include/drm/bridge/aux-bridge.h b/include/drm/bridge/aux-bridge.h
index c2f5a855512f..73fc8582ec07 100644
--- a/include/drm/bridge/aux-bridge.h
+++ b/include/drm/bridge/aux-bridge.h
@@ -20,12 +20,17 @@ static inline int drm_aux_bridge_register(struct device *parent)
}
#endif
+struct drm_dp_typec_bridge_dev;
+
#if IS_ENABLED(CONFIG_DRM_AUX_HPD_BRIDGE)
struct auxiliary_device *devm_drm_dp_hpd_bridge_alloc(struct device *parent, struct device_node *np);
int devm_drm_dp_hpd_bridge_add(struct device *dev, struct auxiliary_device *adev);
struct device *drm_dp_hpd_bridge_register(struct device *parent,
struct device_node *np);
void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status);
+struct drm_dp_typec_bridge_dev *devm_drm_dp_typec_bridge_alloc(struct device *parent,
+ struct device_node *np);
+int devm_drm_dp_typec_bridge_add(struct device *dev, struct drm_dp_typec_bridge_dev *typec_bridge_dev);
#else
static inline struct auxiliary_device *devm_drm_dp_hpd_bridge_alloc(struct device *parent,
struct device_node *np)
@@ -44,6 +49,18 @@ static inline struct device *drm_dp_hpd_bridge_register(struct device *parent,
return NULL;
}
+static inline struct drm_dp_typec_bridge_dev *
+devm_drm_dp_typec_bridge_alloc(struct device *parent, struct device_node *np)
+{
+ return NULL;
+}
+
+static inline int devm_drm_dp_typec_bridge_add(struct device *dev,
+ struct drm_dp_typec_bridge_dev *typec_bridge_dev)
+{
+ return 0;
+}
+
static inline void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status)
{
}
--
https://chromeos.dev
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [PATCH v4 07/18] drm/bridge: dp_typec: Support USB Type-C orientation
2024-09-01 4:06 [PATCH v4 00/18] platform/chrome: Add DT USB/DP muxing/topology support Stephen Boyd
` (5 preceding siblings ...)
2024-09-01 4:06 ` [PATCH v4 06/18] drm/bridge: aux-hpd: Support USB Type-C DP altmodes via DRM lane assignment Stephen Boyd
@ 2024-09-01 4:06 ` Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 08/18] drm/bridge: dp_typec: Add "no-hpd" support Stephen Boyd
` (10 subsequent siblings)
17 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2024-09-01 4:06 UTC (permalink / raw)
To: chrome-platform
Cc: linux-kernel, patches, devicetree, Douglas Anderson, Pin-yen Lin,
Andrzej Hajda, Benson Leung, Conor Dooley, Daniel Vetter,
David Airlie, Dmitry Baryshkov, dri-devel, Guenter Roeck,
Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
Register an orientation switch for each type-c output node to support
flipping the lane mapping when the port is in reverse orientation. Only
do this when the orientation-switch property is present. This is mostly
useful for the case where the DP lanes are directly connected to the
usb-c-connector and the device doesn't have an orientation switch wired
down on the board between the connector and the DP controller.
Cc: Prashant Malani <pmalani@chromium.org>
Cc: Benson Leung <bleung@chromium.org>
Cc: Tzung-Bi Shih <tzungbi@kernel.org>
Cc: <chrome-platform@lists.linux.dev>
Cc: Pin-yen Lin <treapking@chromium.org>
Cc: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
drivers/gpu/drm/bridge/aux-hpd-bridge.c | 77 +++++++++++++++++++++----
1 file changed, 66 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/bridge/aux-hpd-bridge.c b/drivers/gpu/drm/bridge/aux-hpd-bridge.c
index 32565f88ade7..d2832e6481d7 100644
--- a/drivers/gpu/drm/bridge/aux-hpd-bridge.c
+++ b/drivers/gpu/drm/bridge/aux-hpd-bridge.c
@@ -47,12 +47,16 @@ struct drm_dp_typec_bridge_data;
/**
* struct drm_dp_typec_bridge_typec_port - USB type-c port associated with DP bridge
* @lane_mapping: Physical (array index) to logical (array value) USB type-C lane mapping
+ * @orientation: Orientation of USB type-c port
* @mode_switch: DP altmode switch
+ * @orientation_switch: USB type-c orientation switch
* @typec_data: Back pointer to type-c bridge data
*/
struct drm_dp_typec_bridge_typec_port {
u32 lane_mapping[NUM_USB_SS];
+ enum typec_orientation orientation;
struct typec_mux_dev *mode_switch;
+ struct typec_switch_dev *orientation_switch;
struct drm_dp_typec_bridge_data *typec_data;
};
@@ -378,17 +382,35 @@ static int dp_lane_to_typec_lane(enum dp_lane lane)
return -EINVAL;
}
-static int typec_to_dp_lane(enum usb_ss_lane lane)
+static int typec_to_dp_lane(enum usb_ss_lane lane,
+ enum typec_orientation orientation)
{
- switch (lane) {
- case USB_SSRX1:
- return DP_ML3;
- case USB_SSTX1:
- return DP_ML2;
- case USB_SSTX2:
- return DP_ML0;
- case USB_SSRX2:
- return DP_ML1;
+ switch (orientation) {
+ case TYPEC_ORIENTATION_NONE:
+ case TYPEC_ORIENTATION_NORMAL:
+ switch (lane) {
+ case USB_SSRX1:
+ return DP_ML3;
+ case USB_SSTX1:
+ return DP_ML2;
+ case USB_SSTX2:
+ return DP_ML0;
+ case USB_SSRX2:
+ return DP_ML1;
+ }
+ break;
+ case TYPEC_ORIENTATION_REVERSE:
+ switch (lane) {
+ case USB_SSRX1:
+ return DP_ML0;
+ case USB_SSTX1:
+ return DP_ML1;
+ case USB_SSTX2:
+ return DP_ML3;
+ case USB_SSRX2:
+ return DP_ML2;
+ }
+ break;
}
return -EINVAL;
@@ -413,6 +435,7 @@ drm_dp_typec_bridge_assign_pins(struct drm_dp_typec_bridge_dev *typec_bridge_dev
u32 conf,
struct drm_dp_typec_bridge_typec_port *port)
{
+ enum typec_orientation orientation = port->orientation;
enum usb_ss_lane *lane_mapping = port->lane_mapping;
struct auxiliary_device *adev = &typec_bridge_dev->adev;
struct drm_aux_hpd_bridge_data *hpd_data = auxiliary_get_drvdata(adev);
@@ -448,7 +471,7 @@ drm_dp_typec_bridge_assign_pins(struct drm_dp_typec_bridge_dev *typec_bridge_dev
typec_lane = lane_mapping[typec_lane];
/* Map logical type-c lane to logical DP lane */
- dp_lanes[i] = typec_to_dp_lane(typec_lane);
+ dp_lanes[i] = typec_to_dp_lane(typec_lane, orientation);
}
return 0;
@@ -496,6 +519,23 @@ static const struct drm_bridge_funcs drm_dp_typec_bridge_funcs = {
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
};
+static int drm_dp_typec_bridge_orientation_set(struct typec_switch_dev *sw,
+ enum typec_orientation orientation)
+{
+ struct drm_dp_typec_bridge_typec_port *port;
+
+ /*
+ * Lane remapping is in drm_dp_typec_bridge_mode_switch_set(). Whenever
+ * an orientation changes the mode will switch in and out of DP mode,
+ * HPD will deassert and reassert so that
+ * drm_dp_typec_bridge_atomic_check() sees the proper state.
+ */
+ port = typec_switch_get_drvdata(sw);
+ port->orientation = orientation;
+
+ return 0;
+}
+
static int
drm_dp_typec_bridge_mode_switch_set(struct typec_mux_dev *mode_switch,
struct typec_mux_state *state)
@@ -544,7 +584,9 @@ drm_dp_typec_bridge_probe_typec_ports(struct drm_dp_typec_bridge_data *typec_dat
struct drm_dp_typec_bridge_typec_port *port;
size_t num_ports = typec_bridge_dev->num_typec_ports;
struct typec_mux_desc mode_switch_desc = { };
+ struct typec_switch_desc orientation_switch_desc = { };
struct fwnode_handle *fwnode;
+ bool orientation = of_property_read_bool(np, "orientation-switch");
const char *name;
port = devm_kcalloc(dev, num_ports, sizeof(*port), GFP_KERNEL);
@@ -587,6 +629,19 @@ drm_dp_typec_bridge_probe_typec_ports(struct drm_dp_typec_bridge_data *typec_dat
return PTR_ERR(port->mode_switch);
}
+ if (orientation) {
+ orientation_switch_desc.set = drm_dp_typec_bridge_orientation_set,
+ orientation_switch_desc.fwnode = fwnode;
+ orientation_switch_desc.drvdata = port;
+ orientation_switch_desc.name = name;
+ port->orientation_switch = typec_switch_register(dev,
+ &orientation_switch_desc);
+ if (IS_ERR(port->orientation_switch)) {
+ kfree(name);
+ return PTR_ERR(port->orientation_switch);
+ }
+ }
+
kfree(name);
port++;
}
--
https://chromeos.dev
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [PATCH v4 08/18] drm/bridge: dp_typec: Add "no-hpd" support
2024-09-01 4:06 [PATCH v4 00/18] platform/chrome: Add DT USB/DP muxing/topology support Stephen Boyd
` (6 preceding siblings ...)
2024-09-01 4:06 ` [PATCH v4 07/18] drm/bridge: dp_typec: Support USB Type-C orientation Stephen Boyd
@ 2024-09-01 4:06 ` Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 09/18] drm/bridge: dp_typec: Allow users to hook hpd notify path Stephen Boyd
` (9 subsequent siblings)
17 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2024-09-01 4:06 UTC (permalink / raw)
To: chrome-platform
Cc: linux-kernel, patches, devicetree, Douglas Anderson, Pin-yen Lin,
Andrzej Hajda, Benson Leung, Conor Dooley, Daniel Vetter,
David Airlie, Dmitry Baryshkov, dri-devel, Guenter Roeck,
Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
Add support for HPD coming from somewhere else in the drm_bridge chain.
Skip signaling HPD sate when "no-hpd" is present in the DT node backing
the dp_typec bridge.
Add this support because some EC firmwares on Trogdor/Strongbad boards
don't properly indicate the state of the DP HPD level on a type-c port.
The EC only indicates that DP mode is entered or exited for a type-c
port. The HPD level is expressed to the DP controller via a pin on the
AP that the EC drives high or low when the type-c port partner (i.e.
monitor) asserts or deasserts HPD.
Cc: Prashant Malani <pmalani@chromium.org>
Cc: Benson Leung <bleung@chromium.org>
Cc: Tzung-Bi Shih <tzungbi@kernel.org>
Cc: <chrome-platform@lists.linux.dev>
Cc: Pin-yen Lin <treapking@chromium.org>
Cc: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
drivers/gpu/drm/bridge/aux-hpd-bridge.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/bridge/aux-hpd-bridge.c b/drivers/gpu/drm/bridge/aux-hpd-bridge.c
index d2832e6481d7..52db36aa190b 100644
--- a/drivers/gpu/drm/bridge/aux-hpd-bridge.c
+++ b/drivers/gpu/drm/bridge/aux-hpd-bridge.c
@@ -22,6 +22,7 @@ static DEFINE_IDA(drm_aux_hpd_bridge_ida);
struct drm_aux_hpd_bridge_data {
struct drm_bridge bridge;
struct device *dev;
+ bool no_hpd;
};
enum dp_lane {
@@ -355,6 +356,8 @@ void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status sta
if (!data)
return;
+ if (data->no_hpd)
+ return;
drm_bridge_hpd_notify(&data->bridge, status);
}
@@ -672,6 +675,7 @@ static int drm_aux_hpd_bridge_probe(struct auxiliary_device *auxdev,
return -ENOMEM;
bridge = &hpd_data->bridge;
bridge->funcs = &drm_aux_hpd_bridge_funcs;
+ bridge->ops = DRM_BRIDGE_OP_HPD;
} else if (id->driver_data == DRM_AUX_TYPEC_BRIDGE) {
typec_data = devm_kzalloc(dev, sizeof(*typec_data), GFP_KERNEL);
if (!typec_data)
@@ -680,6 +684,9 @@ static int drm_aux_hpd_bridge_probe(struct auxiliary_device *auxdev,
bridge = &hpd_data->bridge;
bridge->funcs = &drm_dp_typec_bridge_funcs;
typec_bridge_dev = to_drm_dp_typec_bridge_dev(dev);
+ hpd_data->no_hpd = of_property_read_bool(np, "no-hpd");
+ if (!hpd_data->no_hpd)
+ bridge->ops = DRM_BRIDGE_OP_HPD;
memcpy(typec_data->dp_lanes, dp_lanes, sizeof(typec_data->dp_lanes));
ret = drm_dp_typec_bridge_probe_typec_ports(typec_data, typec_bridge_dev, np);
if (ret)
@@ -689,8 +696,7 @@ static int drm_aux_hpd_bridge_probe(struct auxiliary_device *auxdev,
}
hpd_data->dev = dev;
- bridge->of_node = dev_get_platdata(dev);
- bridge->ops = DRM_BRIDGE_OP_HPD;
+ bridge->of_node = np;
bridge->type = DRM_MODE_CONNECTOR_DisplayPort;
auxiliary_set_drvdata(auxdev, hpd_data);
--
https://chromeos.dev
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [PATCH v4 09/18] drm/bridge: dp_typec: Allow users to hook hpd notify path
2024-09-01 4:06 [PATCH v4 00/18] platform/chrome: Add DT USB/DP muxing/topology support Stephen Boyd
` (7 preceding siblings ...)
2024-09-01 4:06 ` [PATCH v4 08/18] drm/bridge: dp_typec: Add "no-hpd" support Stephen Boyd
@ 2024-09-01 4:06 ` Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 10/18] devcon property: Document devcon_match_fn_t Stephen Boyd
` (8 subsequent siblings)
17 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2024-09-01 4:06 UTC (permalink / raw)
To: chrome-platform
Cc: linux-kernel, patches, devicetree, Douglas Anderson, Pin-yen Lin,
Andrzej Hajda, Benson Leung, Conor Dooley, Daniel Vetter,
David Airlie, Dmitry Baryshkov, dri-devel, Guenter Roeck,
Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
The previous patch added support for no-hpd to drm_dp_typec_bridge code.
Allow users of this bridge to hook the HPD notification path of the
bridge chain so that they can be made aware of the connector status
changing. This helps HPD-less users of the bridge inject the HPD state
into their code by using the connector status as a proxy for HPD being
asserted or deasserted.
In particular, this will help Trogdor/Strongbad boards that need to read
the EC's analog mux which steers the DP signal to one or the other USB
type-c ports to figure out which type-c port has HPD asserted.
Cc: Prashant Malani <pmalani@chromium.org>
Cc: Benson Leung <bleung@chromium.org>
Cc: Tzung-Bi Shih <tzungbi@kernel.org>
Cc: <chrome-platform@lists.linux.dev>
Cc: Pin-yen Lin <treapking@chromium.org>
Cc: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
drivers/gpu/drm/bridge/aux-hpd-bridge.c | 31 +++++++++++++++++++++++++
include/drm/bridge/aux-bridge.h | 9 +++++++
2 files changed, 40 insertions(+)
diff --git a/drivers/gpu/drm/bridge/aux-hpd-bridge.c b/drivers/gpu/drm/bridge/aux-hpd-bridge.c
index 52db36aa190b..8ff8716b2630 100644
--- a/drivers/gpu/drm/bridge/aux-hpd-bridge.c
+++ b/drivers/gpu/drm/bridge/aux-hpd-bridge.c
@@ -93,6 +93,8 @@ struct drm_dp_typec_bridge_dev {
struct auxiliary_device adev;
size_t max_lanes;
size_t num_typec_ports;
+ void (*hpd_notify)(void *data, enum drm_connector_status status);
+ void *hpd_data;
};
static inline struct drm_dp_typec_bridge_dev *
@@ -324,6 +326,21 @@ devm_drm_dp_typec_bridge_alloc(struct device *parent, struct device_node *np)
}
EXPORT_SYMBOL_GPL(devm_drm_dp_typec_bridge_alloc);
+/**
+ * drm_dp_typec_bridge_add_hpd_notify: Register a callback called when the
+ * bridge chain hpd state changes
+ * @typec_bridge_dev: USB type-c DisplayPort bridge
+ * @hpd_notify: callback for bridge hot plug detect events
+ * @hpd_data: data passed to @hpd_notify callback
+ */
+void drm_dp_typec_bridge_add_hpd_notify(struct drm_dp_typec_bridge_dev *typec_bridge_dev,
+ hpd_notify_fn_t hpd_notify, void *hpd_data)
+{
+ typec_bridge_dev->hpd_notify = hpd_notify;
+ typec_bridge_dev->hpd_data = hpd_data;
+}
+EXPORT_SYMBOL_GPL(drm_dp_typec_bridge_add_hpd_notify);
+
/**
* devm_drm_dp_typec_bridge_add - register a USB type-c DisplayPort bridge
* @dev: struct device to tie registration lifetime to
@@ -363,6 +380,19 @@ void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status sta
}
EXPORT_SYMBOL_GPL(drm_aux_hpd_bridge_notify);
+static void drm_dp_typec_bridge_hpd_notify(struct drm_bridge *bridge,
+ enum drm_connector_status status)
+{
+ struct drm_dp_typec_bridge_data *data;
+ struct drm_dp_typec_bridge_dev *typec_bridge_dev;
+
+ data = to_drm_dp_typec_bridge_data(bridge);
+ typec_bridge_dev = to_drm_dp_typec_bridge_dev(data->hpd_bridge.dev);
+
+ if (typec_bridge_dev->hpd_notify)
+ typec_bridge_dev->hpd_notify(typec_bridge_dev->hpd_data, status);
+}
+
static int drm_aux_hpd_bridge_attach(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags)
{
@@ -520,6 +550,7 @@ static const struct drm_bridge_funcs drm_dp_typec_bridge_funcs = {
.atomic_reset = drm_atomic_helper_bridge_reset,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .hpd_notify = drm_dp_typec_bridge_hpd_notify,
};
static int drm_dp_typec_bridge_orientation_set(struct typec_switch_dev *sw,
diff --git a/include/drm/bridge/aux-bridge.h b/include/drm/bridge/aux-bridge.h
index 73fc8582ec07..300f4a203a9b 100644
--- a/include/drm/bridge/aux-bridge.h
+++ b/include/drm/bridge/aux-bridge.h
@@ -22,6 +22,8 @@ static inline int drm_aux_bridge_register(struct device *parent)
struct drm_dp_typec_bridge_dev;
+typedef void (*hpd_notify_fn_t)(void *data, enum drm_connector_status status);
+
#if IS_ENABLED(CONFIG_DRM_AUX_HPD_BRIDGE)
struct auxiliary_device *devm_drm_dp_hpd_bridge_alloc(struct device *parent, struct device_node *np);
int devm_drm_dp_hpd_bridge_add(struct device *dev, struct auxiliary_device *adev);
@@ -30,6 +32,8 @@ struct device *drm_dp_hpd_bridge_register(struct device *parent,
void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status);
struct drm_dp_typec_bridge_dev *devm_drm_dp_typec_bridge_alloc(struct device *parent,
struct device_node *np);
+void drm_dp_typec_bridge_add_hpd_notify(struct drm_dp_typec_bridge_dev *typec_bridge_dev,
+ hpd_notify_fn_t hpd_notify, void *hpd_data);
int devm_drm_dp_typec_bridge_add(struct device *dev, struct drm_dp_typec_bridge_dev *typec_bridge_dev);
#else
static inline struct auxiliary_device *devm_drm_dp_hpd_bridge_alloc(struct device *parent,
@@ -55,6 +59,11 @@ devm_drm_dp_typec_bridge_alloc(struct device *parent, struct device_node *np)
return NULL;
}
+static inline void drm_dp_typec_bridge_add_hpd_notify(struct drm_dp_typec_bridge_dev *typec_bridge_dev,
+ hpd_notify_fn_t hpd_notify, void *hpd_data)
+{
+}
+
static inline int devm_drm_dp_typec_bridge_add(struct device *dev,
struct drm_dp_typec_bridge_dev *typec_bridge_dev)
{
--
https://chromeos.dev
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [PATCH v4 10/18] devcon property: Document devcon_match_fn_t
2024-09-01 4:06 [PATCH v4 00/18] platform/chrome: Add DT USB/DP muxing/topology support Stephen Boyd
` (8 preceding siblings ...)
2024-09-01 4:06 ` [PATCH v4 09/18] drm/bridge: dp_typec: Allow users to hook hpd notify path Stephen Boyd
@ 2024-09-01 4:06 ` Stephen Boyd
2024-09-02 11:17 ` Andy Shevchenko
2024-09-01 4:06 ` [PATCH v4 11/18] device property: Add remote endpoint to devcon matcher Stephen Boyd
` (7 subsequent siblings)
17 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-09-01 4:06 UTC (permalink / raw)
To: chrome-platform
Cc: linux-kernel, patches, devicetree, Douglas Anderson, Pin-yen Lin,
Andrzej Hajda, Benson Leung, Conor Dooley, Daniel Vetter,
David Airlie, Dmitry Baryshkov, dri-devel, Guenter Roeck,
Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
The usage of this match function is hard to understand at a glance.
Document the arguments and the return value so it is clear how to
implement the function.
Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
include/linux/property.h | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/include/linux/property.h b/include/linux/property.h
index 61fc20e5f81f..797b1eeda7d2 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -507,8 +507,25 @@ unsigned int fwnode_graph_get_endpoint_count(const struct fwnode_handle *fwnode,
int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
struct fwnode_endpoint *endpoint);
-typedef void *(*devcon_match_fn_t)(const struct fwnode_handle *fwnode, const char *id,
- void *data);
+/**
+ * devcon_match_fn_t - device connection match function
+ * @fwnode: Remote connection's device node
+ * @con_id: Identifier for the connection
+ * @data: Match function caller specific data
+ *
+ * Implement a callback with this function signature to search a fwnode's
+ * connections for a match with a function like device_connection_find_match().
+ * This function will be called possibly multiple times, once for each
+ * connection. The match function should inspect the @fwnode to look for a
+ * match. The @con_id and @data provided are the same as the @con_id and @data
+ * arguments passed to the functions that take a devcon_match_fn_t argument.
+ *
+ * Note: This function can be called multiple times.
+ *
+ * Return: Pointer to match or NULL if no match found.
+ */
+typedef void *(*devcon_match_fn_t)(const struct fwnode_handle *fwnode,
+ const char *con_id, void *data);
void *fwnode_connection_find_match(const struct fwnode_handle *fwnode,
const char *con_id, void *data,
--
https://chromeos.dev
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [PATCH v4 11/18] device property: Add remote endpoint to devcon matcher
2024-09-01 4:06 [PATCH v4 00/18] platform/chrome: Add DT USB/DP muxing/topology support Stephen Boyd
` (9 preceding siblings ...)
2024-09-01 4:06 ` [PATCH v4 10/18] devcon property: Document devcon_match_fn_t Stephen Boyd
@ 2024-09-01 4:06 ` Stephen Boyd
2024-09-02 11:12 ` Andy Shevchenko
2024-09-01 4:06 ` [PATCH v4 12/18] dt-bindings: usb-switch: Extract endpoints to defs Stephen Boyd
` (6 subsequent siblings)
17 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-09-01 4:06 UTC (permalink / raw)
To: chrome-platform
Cc: linux-kernel, patches, devicetree, Douglas Anderson, Pin-yen Lin,
Andrzej Hajda, Benson Leung, Conor Dooley, Daniel Vetter,
David Airlie, Dmitry Baryshkov, dri-devel, Guenter Roeck,
Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
When a single DT node has a graph connected to more than one
usb-c-connector node we can't differentiate which typec switch
registered for the device is associated with the USB connector because
the devcon matcher code assumes a 1:1 relationship between remote node
and typec switch. Furthermore, we don't have a #typec-switch-cells
property so there can only be one node per typec switch.
Support multiple USB typec switches exposed by one node by passing the
remote endpoint node in addition to the remote node to the devcon
matcher function (devcon_match_fn_t). With this change, typec switch
drivers can register switches with the device node pointer for a graph
endpoint so that they can support more than one typec switch if
necessary. Either way, a DT property like 'mode-switch' is always in the
graph's parent node and not in the endpoint node.
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Daniel Scally <djrscally@gmail.com>
Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Cc: Sakari Ailus <sakari.ailus@linux.intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Vinod Koul <vkoul@kernel.org>
Cc: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: Ivan Orlov <ivan.orlov0322@gmail.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: <devicetree@vger.kernel.org>
Cc: <linux-usb@vger.kernel.org>
Cc: <linux-acpi@vger.kernel.org>
Cc: Pin-yen Lin <treapking@chromium.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
drivers/base/property.c | 7 +++++--
drivers/usb/roles/class.c | 4 ++--
drivers/usb/typec/mux.c | 8 ++++++++
drivers/usb/typec/retimer.c | 7 ++++++-
include/linux/property.h | 11 +++++++----
5 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/drivers/base/property.c b/drivers/base/property.c
index 837d77e3af2b..621de33f2956 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1284,6 +1284,7 @@ static unsigned int fwnode_graph_devcon_matches(const struct fwnode_handle *fwno
{
struct fwnode_handle *node;
struct fwnode_handle *ep;
+ struct fwnode_handle *remote_ep;
unsigned int count = 0;
void *ret;
@@ -1299,7 +1300,9 @@ static unsigned int fwnode_graph_devcon_matches(const struct fwnode_handle *fwno
continue;
}
- ret = match(node, con_id, data);
+ remote_ep = fwnode_graph_get_remote_endpoint(ep);
+ ret = match(node, remote_ep, con_id, data);
+ fwnode_handle_put(remote_ep);
fwnode_handle_put(node);
if (ret) {
if (matches)
@@ -1329,7 +1332,7 @@ static unsigned int fwnode_devcon_matches(const struct fwnode_handle *fwnode,
if (IS_ERR(node))
break;
- ret = match(node, NULL, data);
+ ret = match(node, NULL, NULL, data);
fwnode_handle_put(node);
if (ret) {
if (matches)
diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c
index d7aa913ceb8a..d8bd5071d9d8 100644
--- a/drivers/usb/roles/class.c
+++ b/drivers/usb/roles/class.c
@@ -121,8 +121,8 @@ enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw)
}
EXPORT_SYMBOL_GPL(usb_role_switch_get_role);
-static void *usb_role_switch_match(const struct fwnode_handle *fwnode, const char *id,
- void *data)
+static void *usb_role_switch_match(const struct fwnode_handle *fwnode, const struct fwnode_handle *endpoint,
+ const char *id, void *data)
{
struct device *dev;
diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c
index f420185e36e3..9ddb6ec54325 100644
--- a/drivers/usb/typec/mux.c
+++ b/drivers/usb/typec/mux.c
@@ -33,6 +33,7 @@ static int switch_fwnode_match(struct device *dev, const void *fwnode)
}
static void *typec_switch_match(const struct fwnode_handle *fwnode,
+ const struct fwnode_handle *endpoint,
const char *id, void *data)
{
struct device *dev;
@@ -55,6 +56,9 @@ static void *typec_switch_match(const struct fwnode_handle *fwnode,
*/
dev = class_find_device(&typec_mux_class, NULL, fwnode,
switch_fwnode_match);
+ if (!dev)
+ dev = class_find_device(&typec_mux_class, NULL, endpoint,
+ switch_fwnode_match);
return dev ? to_typec_switch_dev(dev) : ERR_PTR(-EPROBE_DEFER);
}
@@ -299,6 +303,7 @@ static int mux_fwnode_match(struct device *dev, const void *fwnode)
}
static void *typec_mux_match(const struct fwnode_handle *fwnode,
+ const struct fwnode_handle *endpoint,
const char *id, void *data)
{
struct device *dev;
@@ -316,6 +321,9 @@ static void *typec_mux_match(const struct fwnode_handle *fwnode,
dev = class_find_device(&typec_mux_class, NULL, fwnode,
mux_fwnode_match);
+ if (!dev)
+ dev = class_find_device(&typec_mux_class, NULL, endpoint,
+ mux_fwnode_match);
return dev ? to_typec_mux_dev(dev) : ERR_PTR(-EPROBE_DEFER);
}
diff --git a/drivers/usb/typec/retimer.c b/drivers/usb/typec/retimer.c
index b519fcf358ca..ee4e6312c2d9 100644
--- a/drivers/usb/typec/retimer.c
+++ b/drivers/usb/typec/retimer.c
@@ -22,7 +22,9 @@ static int retimer_fwnode_match(struct device *dev, const void *fwnode)
return is_typec_retimer(dev) && device_match_fwnode(dev, fwnode);
}
-static void *typec_retimer_match(const struct fwnode_handle *fwnode, const char *id, void *data)
+static void *typec_retimer_match(const struct fwnode_handle *fwnode,
+ const struct fwnode_handle *endpoint,
+ const char *id, void *data)
{
struct device *dev;
@@ -31,6 +33,9 @@ static void *typec_retimer_match(const struct fwnode_handle *fwnode, const char
dev = class_find_device(&retimer_class, NULL, fwnode,
retimer_fwnode_match);
+ if (!dev)
+ dev = class_find_device(&retimer_class, NULL, endpoint,
+ retimer_fwnode_match);
return dev ? to_typec_retimer(dev) : ERR_PTR(-EPROBE_DEFER);
}
diff --git a/include/linux/property.h b/include/linux/property.h
index 797b1eeda7d2..72a89cd410db 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -510,22 +510,25 @@ int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
/**
* devcon_match_fn_t - device connection match function
* @fwnode: Remote connection's device node
+ * @endpoint: Remote connection's endpoint node
* @con_id: Identifier for the connection
* @data: Match function caller specific data
*
* Implement a callback with this function signature to search a fwnode's
* connections for a match with a function like device_connection_find_match().
* This function will be called possibly multiple times, once for each
- * connection. The match function should inspect the @fwnode to look for a
- * match. The @con_id and @data provided are the same as the @con_id and @data
- * arguments passed to the functions that take a devcon_match_fn_t argument.
+ * connection. The match function should inspect the connection's @fwnode
+ * and/or @endpoint to look for a match. The @con_id and @data provided are the
+ * same as the @con_id and @data arguments passed to the functions that take a
+ * devcon_match_fn_t argument.
*
* Note: This function can be called multiple times.
*
* Return: Pointer to match or NULL if no match found.
*/
typedef void *(*devcon_match_fn_t)(const struct fwnode_handle *fwnode,
- const char *con_id, void *data);
+ const struct fwnode_handle *endpoint,
+ const char *id, void *data);
void *fwnode_connection_find_match(const struct fwnode_handle *fwnode,
const char *con_id, void *data,
--
https://chromeos.dev
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [PATCH v4 12/18] dt-bindings: usb-switch: Extract endpoints to defs
2024-09-01 4:06 [PATCH v4 00/18] platform/chrome: Add DT USB/DP muxing/topology support Stephen Boyd
` (10 preceding siblings ...)
2024-09-01 4:06 ` [PATCH v4 11/18] device property: Add remote endpoint to devcon matcher Stephen Boyd
@ 2024-09-01 4:06 ` Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 13/18] dt-bindings: usb-switch: Extend for DisplayPort altmode Stephen Boyd
` (5 subsequent siblings)
17 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2024-09-01 4:06 UTC (permalink / raw)
To: chrome-platform
Cc: linux-kernel, patches, devicetree, Douglas Anderson, Pin-yen Lin,
Andrzej Hajda, Benson Leung, Conor Dooley, Daniel Vetter,
David Airlie, Dmitry Baryshkov, dri-devel, Guenter Roeck,
Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring (Arm)
Move the usb-switch endpoint bindings to defs so that they can be reused
by other bindings. Future users of this binding will have more than one
type-c output node when they're muxing a single DP signal to more than
one usb-c-connector. Add an example to show how this binding can be used
and accelerate binding checks.
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Cc: Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Benson Leung <bleung@chromium.org>
Cc: Guenter Roeck <groeck@chromium.org>
Cc: Prashant Malani <pmalani@chromium.org>
Cc: Tzung-Bi Shih <tzungbi@kernel.org>
Cc: <devicetree@vger.kernel.org>
Cc: <chrome-platform@lists.linux.dev>
Cc: Pin-yen Lin <treapking@chromium.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
.../devicetree/bindings/usb/usb-switch.yaml | 74 +++++++++++++++----
1 file changed, 61 insertions(+), 13 deletions(-)
diff --git a/Documentation/devicetree/bindings/usb/usb-switch.yaml b/Documentation/devicetree/bindings/usb/usb-switch.yaml
index da76118e73a5..f5dc7e23b134 100644
--- a/Documentation/devicetree/bindings/usb/usb-switch.yaml
+++ b/Documentation/devicetree/bindings/usb/usb-switch.yaml
@@ -35,9 +35,12 @@ properties:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
- $ref: /schemas/graph.yaml#/properties/port
- description:
- Super Speed (SS) Output endpoint to the Type-C connector
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+
+ properties:
+ endpoint:
+ $ref: '#/$defs/usbc-out-endpoint'
port@1:
$ref: /schemas/graph.yaml#/$defs/port-base
@@ -47,16 +50,7 @@ properties:
properties:
endpoint:
- $ref: /schemas/graph.yaml#/$defs/endpoint-base
- unevaluatedProperties: false
- properties:
- data-lanes:
- $ref: /schemas/types.yaml#/definitions/uint32-array
- minItems: 1
- maxItems: 8
- uniqueItems: true
- items:
- maximum: 8
+ $ref: '#/$defs/usbc-in-endpoint'
oneOf:
- required:
@@ -65,3 +59,57 @@ oneOf:
- ports
additionalProperties: true
+
+$defs:
+ usbc-out-endpoint:
+ $ref: /schemas/graph.yaml#/$defs/endpoint-base
+ description: Super Speed (SS) output endpoint to a type-c connector
+ unevaluatedProperties: false
+
+ usbc-in-endpoint:
+ $ref: /schemas/graph.yaml#/$defs/endpoint-base
+ description: Super Speed (SS) input endpoint from the Super Speed PHY
+ unevaluatedProperties: false
+ properties:
+ data-lanes:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ minItems: 1
+ maxItems: 8
+ uniqueItems: true
+ items:
+ maximum: 8
+
+examples:
+ # A USB orientation switch which flips the pin orientation
+ # for a usb-c-connector node.
+ - |
+ device {
+ orientation-switch;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ endpoint {
+ remote-endpoint = <&usb_c_connector>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ endpoint {
+ remote-endpoint = <&usb_ss_phy>;
+ };
+ };
+ };
+ };
+
+...
--
https://chromeos.dev
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [PATCH v4 13/18] dt-bindings: usb-switch: Extend for DisplayPort altmode
2024-09-01 4:06 [PATCH v4 00/18] platform/chrome: Add DT USB/DP muxing/topology support Stephen Boyd
` (11 preceding siblings ...)
2024-09-01 4:06 ` [PATCH v4 12/18] dt-bindings: usb-switch: Extract endpoints to defs Stephen Boyd
@ 2024-09-01 4:06 ` Stephen Boyd
2024-09-19 10:40 ` Dmitry Baryshkov
2024-09-01 4:06 ` [PATCH v4 14/18] dt-bindings: Move google,cros-ec-typec binding to usb Stephen Boyd
` (4 subsequent siblings)
17 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-09-01 4:06 UTC (permalink / raw)
To: chrome-platform
Cc: linux-kernel, patches, devicetree, Douglas Anderson, Pin-yen Lin,
Andrzej Hajda, Benson Leung, Conor Dooley, Daniel Vetter,
David Airlie, Dmitry Baryshkov, dri-devel, Guenter Roeck,
Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring (Arm)
Extend the usb-switch binding to support DisplayPort (DP) alternate
modes. A third port for the DP signal is necessary when a mode-switch is
muxing USB and DP together onto a usb type-c connector. Add data-lanes
to the usbc output node to allow a device using this binding to remap
the data lanes on the output. Add an example to show how this new port
can be used.
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Cc: Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Benson Leung <bleung@chromium.org>
Cc: Guenter Roeck <groeck@chromium.org>
Cc: Prashant Malani <pmalani@chromium.org>
Cc: Tzung-Bi Shih <tzungbi@kernel.org>
Cc: <devicetree@vger.kernel.org>
Cc: <chrome-platform@lists.linux.dev>
Cc: Pin-yen Lin <treapking@chromium.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
.../devicetree/bindings/usb/usb-switch.yaml | 89 +++++++++++++++++++
1 file changed, 89 insertions(+)
diff --git a/Documentation/devicetree/bindings/usb/usb-switch.yaml b/Documentation/devicetree/bindings/usb/usb-switch.yaml
index f5dc7e23b134..816f295f322f 100644
--- a/Documentation/devicetree/bindings/usb/usb-switch.yaml
+++ b/Documentation/devicetree/bindings/usb/usb-switch.yaml
@@ -52,6 +52,14 @@ properties:
endpoint:
$ref: '#/$defs/usbc-in-endpoint'
+ port@2:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+
+ properties:
+ endpoint:
+ $ref: '#/$defs/dp-endpoint'
+
oneOf:
- required:
- port
@@ -65,6 +73,19 @@ $defs:
$ref: /schemas/graph.yaml#/$defs/endpoint-base
description: Super Speed (SS) output endpoint to a type-c connector
unevaluatedProperties: false
+ properties:
+ data-lanes:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description: |
+ An array of physical USB Type-C data lane indexes.
+ - 0 is SSRX1 lane
+ - 1 is SSTX1 lane
+ - 2 is SSTX2 lane
+ - 3 is SSRX2 lane
+ minItems: 4
+ maxItems: 4
+ items:
+ maximum: 3
usbc-in-endpoint:
$ref: /schemas/graph.yaml#/$defs/endpoint-base
@@ -79,7 +100,75 @@ $defs:
items:
maximum: 8
+ dp-endpoint:
+ $ref: /schemas/graph.yaml#/$defs/endpoint-base
+ description: DisplayPort (DP) input from the DP PHY
+ unevaluatedProperties: false
+ properties:
+ data-lanes:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description: |
+ An array of physical DP data lane indexes
+ - 0 is DP ML0 lane
+ - 1 is DP ML1 lane
+ - 2 is DP ML2 lane
+ - 3 is DP ML3 lane
+ oneOf:
+ - items:
+ - const: 0
+ - const: 1
+ - items:
+ - const: 0
+ - const: 1
+ - const: 2
+ - const: 3
+
examples:
+ # A USB + DP mode and orientation switch which muxes DP altmode
+ # and USB onto a usb-c-connector node.
+ - |
+ device {
+ mode-switch;
+ orientation-switch;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ endpoint {
+ remote-endpoint = <&usb_c_connector>;
+ data-lanes = <0 1 2 3>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ endpoint {
+ remote-endpoint = <&usb_ss_phy>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ endpoint {
+ remote-endpoint = <&dp_phy>;
+ data-lanes = <0 1 2 3>;
+ };
+ };
+ };
+ };
+
# A USB orientation switch which flips the pin orientation
# for a usb-c-connector node.
- |
--
https://chromeos.dev
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [PATCH v4 14/18] dt-bindings: Move google,cros-ec-typec binding to usb
2024-09-01 4:06 [PATCH v4 00/18] platform/chrome: Add DT USB/DP muxing/topology support Stephen Boyd
` (12 preceding siblings ...)
2024-09-01 4:06 ` [PATCH v4 13/18] dt-bindings: usb-switch: Extend for DisplayPort altmode Stephen Boyd
@ 2024-09-01 4:06 ` Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode Stephen Boyd
` (3 subsequent siblings)
17 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2024-09-01 4:06 UTC (permalink / raw)
To: chrome-platform
Cc: linux-kernel, patches, devicetree, Douglas Anderson, Pin-yen Lin,
Andrzej Hajda, Benson Leung, Conor Dooley, Daniel Vetter,
David Airlie, Dmitry Baryshkov, dri-devel, Guenter Roeck,
Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring (Arm), Krzysztof Kozlowski
This binding is about USB type-c control. Move the binding to the usb
directory as it's a better home than chrome.
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Cc: Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Lee Jones <lee@kernel.org>
Cc: Benson Leung <bleung@chromium.org>
Cc: Guenter Roeck <groeck@chromium.org>
Cc: Prashant Malani <pmalani@chromium.org>
Cc: Tzung-Bi Shih <tzungbi@kernel.org>
Cc: <devicetree@vger.kernel.org>
Cc: <chrome-platform@lists.linux.dev>
Cc: Pin-yen Lin <treapking@chromium.org>
Suggested-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
Documentation/devicetree/bindings/mfd/google,cros-ec.yaml | 2 +-
.../bindings/{chrome => usb}/google,cros-ec-typec.yaml | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
rename Documentation/devicetree/bindings/{chrome => usb}/google,cros-ec-typec.yaml (90%)
diff --git a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
index aac8819bd00b..c991626dc22b 100644
--- a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
+++ b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
@@ -99,7 +99,7 @@ properties:
gpio-controller: true
typec:
- $ref: /schemas/chrome/google,cros-ec-typec.yaml#
+ $ref: /schemas/usb/google,cros-ec-typec.yaml#
ec-pwm:
$ref: /schemas/pwm/google,cros-ec-pwm.yaml#
diff --git a/Documentation/devicetree/bindings/chrome/google,cros-ec-typec.yaml b/Documentation/devicetree/bindings/usb/google,cros-ec-typec.yaml
similarity index 90%
rename from Documentation/devicetree/bindings/chrome/google,cros-ec-typec.yaml
rename to Documentation/devicetree/bindings/usb/google,cros-ec-typec.yaml
index 9f9816fbecbc..365523a63179 100644
--- a/Documentation/devicetree/bindings/chrome/google,cros-ec-typec.yaml
+++ b/Documentation/devicetree/bindings/usb/google,cros-ec-typec.yaml
@@ -1,10 +1,10 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/chrome/google,cros-ec-typec.yaml#
+$id: http://devicetree.org/schemas/usb/google,cros-ec-typec.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Google Chrome OS EC(Embedded Controller) Type C port driver.
+title: Google ChromeOS Embedded Controller (EC) USB type-c port driver
maintainers:
- Benson Leung <bleung@chromium.org>
--
https://chromeos.dev
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
2024-09-01 4:06 [PATCH v4 00/18] platform/chrome: Add DT USB/DP muxing/topology support Stephen Boyd
` (13 preceding siblings ...)
2024-09-01 4:06 ` [PATCH v4 14/18] dt-bindings: Move google,cros-ec-typec binding to usb Stephen Boyd
@ 2024-09-01 4:06 ` Stephen Boyd
2024-09-03 15:35 ` Lee Jones
2024-09-20 9:38 ` Dmitry Baryshkov
2024-09-01 4:06 ` [PATCH v4 16/18] platform/chrome: cros_ec_typec: Add support for signaling DP HPD via drm_bridge Stephen Boyd
` (2 subsequent siblings)
17 siblings, 2 replies; 60+ messages in thread
From: Stephen Boyd @ 2024-09-01 4:06 UTC (permalink / raw)
To: chrome-platform
Cc: linux-kernel, patches, devicetree, Douglas Anderson, Pin-yen Lin,
Andrzej Hajda, Benson Leung, Conor Dooley, Daniel Vetter,
David Airlie, Dmitry Baryshkov, dri-devel, Guenter Roeck,
Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring (Arm)
Add a DT graph binding to google,cros-ec-typec so that it can combine
DisplayPort (DP) and USB SuperSpeed (SS) data into a USB type-c endpoint
that is connected to the usb-c-connector node's SS endpoint. This also
allows us to connect the DP and USB nodes in the graph to the USB type-c
connectors, providing the full picture of the USB type-c data flows in
the system.
Allow there to be multiple typec nodes underneath the EC node so that
one DT graph exists per DP bridge. The EC is actually controlling TCPCs
and redrivers that combine the DP and USB signals together so this more
accurately reflects the hardware design without introducing yet another
DT node underneath the EC for USB type-c.
If the type-c ports are being shared between a single DP controller then
the ports need to know about each other and determine a policy to drive
DP to one type-c port. If the type-c ports each have their own dedicated
DP controller then they're able to operate independently and enter/exit
DP altmode independently as well. We can't connect the DP controller's
endpoint to one usb-c-connector port@1 endpoint and the USB controller's
endpoint to another usb-c-connector port@1 endpoint either because the
DP muxing case would have DP connected to two usb-c-connector endpoints
which the graph binding doesn't support.
Therefore, one typec node is required per the capabilities of the type-c
port(s) being managed. This also lets us indicate which type-c ports the
DP controller is wired to. For example, if DP was connected to ports 0
and 2, while port 1 was connected to another DP controller we wouldn't
be able to implement that without having some other DT property to
indicate which output ports are connected to the DP endpoint.
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Cc: Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>
Cc: Conor Dooley <conor+dt@kernel.org>
Acked-by: Lee Jones <lee@kernel.org>
Cc: Benson Leung <bleung@chromium.org>
Cc: Guenter Roeck <groeck@chromium.org>
Cc: Prashant Malani <pmalani@chromium.org>
Cc: Tzung-Bi Shih <tzungbi@kernel.org>
Cc: <devicetree@vger.kernel.org>
Cc: <chrome-platform@lists.linux.dev>
Cc: Pin-yen Lin <treapking@chromium.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
.../bindings/mfd/google,cros-ec.yaml | 7 +-
.../bindings/usb/google,cros-ec-typec.yaml | 229 ++++++++++++++++++
2 files changed, 233 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
index c991626dc22b..bbe28047d0c0 100644
--- a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
+++ b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
@@ -98,9 +98,6 @@ properties:
gpio-controller: true
- typec:
- $ref: /schemas/usb/google,cros-ec-typec.yaml#
-
ec-pwm:
$ref: /schemas/pwm/google,cros-ec-pwm.yaml#
deprecated: true
@@ -166,6 +163,10 @@ patternProperties:
type: object
$ref: /schemas/extcon/extcon-usbc-cros-ec.yaml#
+ "^typec(-[0-9])*$":
+ type: object
+ $ref: /schemas/usb/google,cros-ec-typec.yaml#
+
required:
- compatible
diff --git a/Documentation/devicetree/bindings/usb/google,cros-ec-typec.yaml b/Documentation/devicetree/bindings/usb/google,cros-ec-typec.yaml
index 365523a63179..235b86da3cdd 100644
--- a/Documentation/devicetree/bindings/usb/google,cros-ec-typec.yaml
+++ b/Documentation/devicetree/bindings/usb/google,cros-ec-typec.yaml
@@ -26,6 +26,106 @@ properties:
'#size-cells':
const: 0
+ mux-gpios:
+ description: GPIOs indicating which way the DP mux is steered
+ maxItems: 1
+
+ no-hpd:
+ description: Indicates this endpoint doesn't signal HPD for DisplayPort
+ type: boolean
+
+ mode-switch:
+ $ref: usb-switch.yaml#properties/mode-switch
+
+ orientation-switch:
+ $ref: usb-switch.yaml#properties/orientation-switch
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description: Output ports for combined DP and USB SS data
+ patternProperties:
+ "^endpoint@([0-8])$":
+ $ref: usb-switch.yaml#/$defs/usbc-out-endpoint
+ unevaluatedProperties: false
+
+ anyOf:
+ - required:
+ - endpoint@0
+ - required:
+ - endpoint@1
+ - required:
+ - endpoint@2
+ - required:
+ - endpoint@3
+ - required:
+ - endpoint@4
+ - required:
+ - endpoint@5
+ - required:
+ - endpoint@6
+ - required:
+ - endpoint@7
+ - required:
+ - endpoint@8
+
+ port@1:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description:
+ Input port to receive USB SuperSpeed (SS) data
+ patternProperties:
+ "^endpoint@([0-8])$":
+ $ref: usb-switch.yaml#/$defs/usbc-in-endpoint
+ unevaluatedProperties: false
+
+ anyOf:
+ - required:
+ - endpoint@0
+ - required:
+ - endpoint@1
+ - required:
+ - endpoint@2
+ - required:
+ - endpoint@3
+ - required:
+ - endpoint@4
+ - required:
+ - endpoint@5
+ - required:
+ - endpoint@6
+ - required:
+ - endpoint@7
+ - required:
+ - endpoint@8
+
+ port@2:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ description:
+ Input port to receive DisplayPort (DP) data
+ unevaluatedProperties: false
+
+ properties:
+ endpoint:
+ $ref: usb-switch.yaml#/$defs/dp-endpoint
+ unevaluatedProperties: false
+
+ required:
+ - endpoint
+
+ required:
+ - port@0
+
+ anyOf:
+ - required:
+ - port@1
+ - required:
+ - port@2
+
patternProperties:
'^connector@[0-9a-f]+$':
$ref: /schemas/connector/usb-connector.yaml#
@@ -35,6 +135,40 @@ patternProperties:
required:
- compatible
+allOf:
+ - if:
+ required:
+ - no-hpd
+ then:
+ properties:
+ ports:
+ required:
+ - port@2
+ - if:
+ required:
+ - mux-gpios
+ then:
+ properties:
+ ports:
+ required:
+ - port@2
+ - if:
+ required:
+ - orientation-switch
+ then:
+ properties:
+ ports:
+ required:
+ - port@2
+ - if:
+ required:
+ - mode-switch
+ then:
+ properties:
+ ports:
+ required:
+ - port@2
+
additionalProperties: false
examples:
@@ -50,6 +184,8 @@ examples:
typec {
compatible = "google,cros-ec-typec";
+ orientation-switch;
+ mode-switch;
#address-cells = <1>;
#size-cells = <0>;
@@ -60,6 +196,99 @@ examples:
power-role = "dual";
data-role = "dual";
try-power-role = "source";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ usb_c0_hs: endpoint {
+ remote-endpoint = <&usb_hub_dfp3_hs>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ usb_c0_ss: endpoint {
+ remote-endpoint = <&cros_typec_c0_ss>;
+ };
+ };
+ };
+ };
+
+ connector@1 {
+ compatible = "usb-c-connector";
+ reg = <1>;
+ power-role = "dual";
+ data-role = "dual";
+ try-power-role = "source";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ usb_c1_hs: endpoint {
+ remote-endpoint = <&usb_hub_dfp2_hs>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ usb_c1_ss: endpoint {
+ remote-endpoint = <&cros_typec_c1_ss>;
+ };
+ };
+ };
+ };
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cros_typec_c0_ss: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&usb_c0_ss>;
+ data-lanes = <0 1 2 3>;
+ };
+
+ cros_typec_c1_ss: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&usb_c1_ss>;
+ data-lanes = <2 3 0 1>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usb_in_0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&usb_ss_0_out>;
+ };
+
+ usb_in_1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&usb_ss_1_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ dp_in: endpoint {
+ remote-endpoint = <&dp_phy>;
+ data-lanes = <0 1>;
+ };
+ };
};
};
};
--
https://chromeos.dev
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [PATCH v4 16/18] platform/chrome: cros_ec_typec: Add support for signaling DP HPD via drm_bridge
2024-09-01 4:06 [PATCH v4 00/18] platform/chrome: Add DT USB/DP muxing/topology support Stephen Boyd
` (14 preceding siblings ...)
2024-09-01 4:06 ` [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode Stephen Boyd
@ 2024-09-01 4:06 ` Stephen Boyd
2024-09-04 9:35 ` Tzung-Bi Shih
2024-09-01 4:06 ` [PATCH v4 17/18] platform/chrome: cros_ec_typec: Support DP muxing Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 18/18] platform/chrome: cros_ec_typec: Handle lack of HPD information Stephen Boyd
17 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-09-01 4:06 UTC (permalink / raw)
To: chrome-platform
Cc: linux-kernel, patches, devicetree, Douglas Anderson, Pin-yen Lin,
Andrzej Hajda, Benson Leung, Conor Dooley, Daniel Vetter,
David Airlie, Dmitry Baryshkov, dri-devel, Guenter Roeck,
Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
We can imagine that logically the EC is a device that has some number of
DisplayPort (DP) connector inputs, some number of USB3 connector inputs,
and some number of USB type-c connector outputs. If you squint enough it
looks like a USB type-c dock. Logically there's a crossbar pin
assignment capability within the EC that can assign USB and DP lanes to
USB type-c lanes in the connector (i.e. USB type-c pin configurations).
In reality, the EC is a microcontroller that has some TCPCs and
redrivers connected to it over something like i2c and DP/USB from the AP
is wired directly to those ICs, not the EC.
This design allows the EC to abstract many possible USB and DP hardware
configurations away from the AP (kernel) so that the AP can largely deal
with USB and DP without thinking about USB Type-C much at all. The DP
and USB data originate in the AP, not the EC, so it helps to think that
the EC takes the DP and USB data as input to mux onto USB type-c ports
even if it really doesn't do that. With this split design, the EC
forwards the DP HPD state to the DP hardware via a GPIO that's connected
to the DP phy.
Having that HPD state signaled directly to the DP phy uses precious
hardware resources, a pin or two and a wire, and it also forces the TCPM
to live on the EC. If we want to save costs and move more control of USB
type-c to the kernel it's in our interest to get rid of the HPD pin
entirely and signal HPD to the DP phy some other way. Luckily, the EC
already exposes information about the USB Type-C stack to the kernel via
the host command interface in the "google,cros-ec-typec" compatible
driver, which parses EC messages related to USB type-c and effectively
"replays" those messages to the kernel's USB typec subsystem. This
includes the state of HPD, which can be interrogated and acted upon by
registering a 'struct typec_mux_dev' with the typec subsystem or by
hooking directly into this cros_ec_typec driver.
On DT based systems, the DP display pipeline is abstracted via a 'struct
drm_bridge'. If we want to signal HPD state from within the kernel we
need to hook into the drm_bridge framework somehow to call
drm_bridge_hpd_notify() when HPD state changes in the typec framework.
Use the newly added drm_dp_typec_bridge code to do this. When the EC
notifies AP of a type-c event, look at the port state and set the
connector state to connected or disconnected based on the HPD level when
the port is in DP mode.
Luckily all this logic is already handled by the drm_dp_typec bridge.
Register a bridge when this DT node has the 'mode-switch' property. When
cros_typec_configure_mux() puts a port into DP mode, the mode switch
registered in the drm_dp_typec bridge driver will signal HPD state to
the drm_bridge chain because the typec subsystem will configure the usbc
switches connected to the port with the data this driver provides.
Cc: Prashant Malani <pmalani@chromium.org>
Cc: Benson Leung <bleung@chromium.org>
Cc: Tzung-Bi Shih <tzungbi@kernel.org>
Cc: <chrome-platform@lists.linux.dev>
Cc: Pin-yen Lin <treapking@chromium.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
drivers/platform/chrome/Kconfig | 1 +
drivers/platform/chrome/cros_ec_typec.c | 31 +++++++++++++++++++++++++
drivers/platform/chrome/cros_ec_typec.h | 1 +
3 files changed, 33 insertions(+)
diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 7dbeb786352a..0aee8a77f1d6 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -231,6 +231,7 @@ config CROS_EC_TYPEC
depends on MFD_CROS_EC_DEV && TYPEC
depends on CROS_USBPD_NOTIFY
depends on USB_ROLE_SWITCH
+ select DRM_AUX_HPD_BRIDGE if DRM_BRIDGE && OF
default MFD_CROS_EC_DEV
help
If you say Y here, you get support for accessing Type C connector
diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
index 4d305876ec08..a57053bdec18 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/bridge/aux-bridge.h>
+
#include "cros_ec_typec.h"
#include "cros_typec_vdm.h"
@@ -334,6 +337,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--;
if (nports == 0) {
dev_err(dev, "No port entries found.\n");
return -ENODEV;
@@ -347,6 +353,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;
+
if (fwnode_property_read_u32(fwnode, port_prop, &port_num)) {
ret = -EINVAL;
dev_err(dev, "No port-number for port, aborting.\n");
@@ -413,6 +423,23 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
return ret;
}
+static int cros_typec_init_dp_bridge(struct cros_typec_data *typec)
+{
+ struct device *dev = typec->dev;
+ struct drm_dp_typec_bridge_dev *dp_dev;
+
+ /* Not capable of DP altmode switching. Ignore. */
+ if (!fwnode_property_read_bool(dev_fwnode(dev), "mode-switch"))
+ return 0;
+
+ dp_dev = devm_drm_dp_typec_bridge_alloc(dev, dev->of_node);
+ if (IS_ERR(dp_dev))
+ return PTR_ERR(dp_dev);
+ typec->dp_bridge = dp_dev;
+
+ return devm_drm_dp_typec_bridge_add(dev, dp_dev);
+}
+
static int cros_typec_usb_safe_state(struct cros_typec_port *port)
{
int ret;
@@ -1257,6 +1284,10 @@ static int cros_typec_probe(struct platform_device *pdev)
typec->num_ports = EC_USB_PD_MAX_PORTS;
}
+ ret = cros_typec_init_dp_bridge(typec);
+ if (ret < 0)
+ return ret;
+
ret = cros_typec_init_ports(typec);
if (ret < 0)
return ret;
diff --git a/drivers/platform/chrome/cros_ec_typec.h b/drivers/platform/chrome/cros_ec_typec.h
index deda180a646f..eb816d30d880 100644
--- a/drivers/platform/chrome/cros_ec_typec.h
+++ b/drivers/platform/chrome/cros_ec_typec.h
@@ -35,6 +35,7 @@ struct cros_typec_data {
unsigned int pd_ctrl_ver;
/* Array of ports, indexed by port number. */
struct cros_typec_port *ports[EC_USB_PD_MAX_PORTS];
+ struct drm_dp_typec_bridge_dev *dp_bridge;
struct notifier_block nb;
struct work_struct port_work;
bool typec_cmd_supported;
--
https://chromeos.dev
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [PATCH v4 17/18] platform/chrome: cros_ec_typec: Support DP muxing
2024-09-01 4:06 [PATCH v4 00/18] platform/chrome: Add DT USB/DP muxing/topology support Stephen Boyd
` (15 preceding siblings ...)
2024-09-01 4:06 ` [PATCH v4 16/18] platform/chrome: cros_ec_typec: Add support for signaling DP HPD via drm_bridge Stephen Boyd
@ 2024-09-01 4:06 ` Stephen Boyd
2024-09-04 9:36 ` Tzung-Bi Shih
2024-09-01 4:06 ` [PATCH v4 18/18] platform/chrome: cros_ec_typec: Handle lack of HPD information Stephen Boyd
17 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-09-01 4:06 UTC (permalink / raw)
To: chrome-platform
Cc: linux-kernel, patches, devicetree, Douglas Anderson, Pin-yen Lin,
Andrzej Hajda, Benson Leung, Conor Dooley, Daniel Vetter,
David Airlie, Dmitry Baryshkov, dri-devel, Guenter Roeck,
Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
Most ARM based chromebooks with two usb-c-connector nodes and one DP
controller are muxing the DP lanes between the two USB ports. This is
done so that the type-c ports are at least equal in capability if not
functionality. Either an analog mux is used to steer the DP signal to
one or the other port, or a DP bridge chip has two lanes (e.g. DP
ML0/ML1) wired to one type-c port while the other two (e.g. DP ML2/ML3)
are wired to another type-c port.
Implement the same algorithm that the EC has to figure out which type-c
port has actually been muxed for DP altmode. Wait for the first type-c
port to assert HPD, and treat that as the actively muxed port until the
port exits DP altmode entirely. Allow HPD to be asserted or deasserted
during this time. If the port isn't active, simply ignore those events
and skip calling cros_typec_enable_dp(). Otherwise, pass the DP
information to the typec subsystem so that the DP controller can respond
to HPD events and pin configurations.
The EC can mux the DP signal to any number of USB type-c ports. We only
need to make sure that the active USB type-c port is tracked so that DP
information about the other ports is ignored. Unfortunately, the EC
doesn't hide these details from the AP so we have to reimplement the
logic in the kernel.
Cc: Prashant Malani <pmalani@chromium.org>
Cc: Benson Leung <bleung@chromium.org>
Cc: Tzung-Bi Shih <tzungbi@kernel.org>
Cc: <chrome-platform@lists.linux.dev>
Cc: Pin-yen Lin <treapking@chromium.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
drivers/platform/chrome/cros_ec_typec.c | 31 +++++++++++++++++++++++--
drivers/platform/chrome/cros_ec_typec.h | 1 +
2 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
index a57053bdec18..57d1484ce1ef 100644
--- a/drivers/platform/chrome/cros_ec_typec.c
+++ b/drivers/platform/chrome/cros_ec_typec.c
@@ -639,6 +639,7 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
struct ec_response_usb_pd_control_v2 *pd_ctrl)
{
struct cros_typec_port *port = typec->ports[port_num];
+ bool has_dp_bridge = !!typec->dp_bridge;
struct ec_response_usb_pd_mux_info resp;
struct ec_params_usb_pd_mux_info req = {
.port = port_num,
@@ -646,6 +647,7 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
struct ec_params_usb_pd_mux_ack mux_ack;
enum typec_orientation orientation;
int ret;
+ bool dp_enabled, hpd_asserted, is_active_port;
ret = cros_ec_cmd(typec->ec, 0, EC_CMD_USB_PD_MUX_INFO,
&req, sizeof(req), &resp, sizeof(resp));
@@ -659,6 +661,25 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
if (port->mux_flags == resp.flags && port->role == pd_ctrl->role)
return 0;
+ dp_enabled = resp.flags & USB_PD_MUX_DP_ENABLED;
+ hpd_asserted = resp.flags & USB_PD_MUX_HPD_LVL;
+ /*
+ * Assume the first port to have HPD asserted is the one muxed to DP
+ * (i.e. active_port). When there's only one port this delays setting
+ * the active_port until HPD is asserted, but before that the
+ * drm_connector looks disconnected so active_port doesn't need to be
+ * set.
+ */
+ if (has_dp_bridge && hpd_asserted && !typec->active_dp_port)
+ typec->active_dp_port = port;
+
+ /*
+ * Skip calling cros_typec_enable_dp() for the non-active type-c port
+ * when muxing one DP to multiple type-c ports. This is only the case
+ * on platforms using a drm_bridge.
+ */
+ is_active_port = !has_dp_bridge || typec->active_dp_port == port;
+
port->mux_flags = resp.flags;
port->role = pd_ctrl->role;
@@ -686,8 +707,11 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
ret = cros_typec_enable_usb4(typec, port_num, pd_ctrl);
} else if (port->mux_flags & USB_PD_MUX_TBT_COMPAT_ENABLED) {
ret = cros_typec_enable_tbt(typec, port_num, pd_ctrl);
- } else if (port->mux_flags & USB_PD_MUX_DP_ENABLED) {
- ret = cros_typec_enable_dp(typec, port_num, pd_ctrl);
+ } else if (dp_enabled) {
+ ret = 0;
+ /* Ignore DP events for the non-active port */
+ if (is_active_port)
+ ret = cros_typec_enable_dp(typec, port_num, pd_ctrl);
} else if (port->mux_flags & USB_PD_MUX_SAFE_MODE) {
ret = cros_typec_usb_safe_state(port);
} else if (port->mux_flags & USB_PD_MUX_USB_ENABLED) {
@@ -704,6 +728,9 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
}
mux_ack:
+ if (has_dp_bridge && !dp_enabled && is_active_port)
+ typec->active_dp_port = NULL;
+
if (!typec->needs_mux_ack)
return ret;
diff --git a/drivers/platform/chrome/cros_ec_typec.h b/drivers/platform/chrome/cros_ec_typec.h
index eb816d30d880..f3a2b67df07c 100644
--- a/drivers/platform/chrome/cros_ec_typec.h
+++ b/drivers/platform/chrome/cros_ec_typec.h
@@ -36,6 +36,7 @@ struct cros_typec_data {
/* Array of ports, indexed by port number. */
struct cros_typec_port *ports[EC_USB_PD_MAX_PORTS];
struct drm_dp_typec_bridge_dev *dp_bridge;
+ struct cros_typec_port *active_dp_port;
struct notifier_block nb;
struct work_struct port_work;
bool typec_cmd_supported;
--
https://chromeos.dev
^ permalink raw reply related [flat|nested] 60+ messages in thread
* [PATCH v4 18/18] platform/chrome: cros_ec_typec: Handle lack of HPD information
2024-09-01 4:06 [PATCH v4 00/18] platform/chrome: Add DT USB/DP muxing/topology support Stephen Boyd
` (16 preceding siblings ...)
2024-09-01 4:06 ` [PATCH v4 17/18] platform/chrome: cros_ec_typec: Support DP muxing Stephen Boyd
@ 2024-09-01 4:06 ` Stephen Boyd
2024-09-04 9:36 ` Tzung-Bi Shih
17 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-09-01 4:06 UTC (permalink / raw)
To: chrome-platform
Cc: linux-kernel, patches, devicetree, Douglas Anderson, Pin-yen Lin,
Andrzej Hajda, Benson Leung, Conor Dooley, Daniel Vetter,
David Airlie, Dmitry Baryshkov, dri-devel, Guenter Roeck,
Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
Some EC firmwares on Trogdor/Strongbad boards don't properly indicate
the state of DP HPD on a type-c port. Instead, the EC only indicates
that a type-c port has entered or exited DP mode. To make matters worse,
on these boards the DP signal is muxed between two USB type-c
connectors, so we can't use the DP entry of a port to figure out which
type-c port is actually displaying DP.
Stash the HPD state in this case whenever the drm_bridge is notified of
a connector status change and kick off the port worker so that the
type-c port state can be re-evaluated. If an analog mux is in use, read
the mux to figure out which type-c port signaled HPD. Once we know which
port is actually signaling HPD, inject that state into the message
received from the EC. This simplifies the rest of the logic as it can
all stay the same with respect to picking the first port to assert HPD,
etc.
Cc: Prashant Malani <pmalani@chromium.org>
Cc: Benson Leung <bleung@chromium.org>
Cc: Tzung-Bi Shih <tzungbi@kernel.org>
Cc: <chrome-platform@lists.linux.dev>
Cc: Pin-yen Lin <treapking@chromium.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
drivers/platform/chrome/cros_ec_typec.c | 74 +++++++++++++++++++++++++
drivers/platform/chrome/cros_ec_typec.h | 2 +
2 files changed, 76 insertions(+)
diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
index 57d1484ce1ef..731b485634af 100644
--- a/drivers/platform/chrome/cros_ec_typec.c
+++ b/drivers/platform/chrome/cros_ec_typec.c
@@ -7,6 +7,7 @@
*/
#include <linux/acpi.h>
+#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_graph.h>
@@ -423,6 +424,17 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
return ret;
}
+static void cros_typec_dp_bridge_hpd_notify(void *data, enum drm_connector_status status)
+{
+ struct cros_typec_data *typec = data;
+
+ /* Proxy the connector status as the HPD state to replay later. */
+ typec->hpd_asserted = status == connector_status_connected;
+
+ /* Refresh port state. */
+ schedule_work(&typec->port_work);
+}
+
static int cros_typec_init_dp_bridge(struct cros_typec_data *typec)
{
struct device *dev = typec->dev;
@@ -432,9 +444,17 @@ static int cros_typec_init_dp_bridge(struct cros_typec_data *typec)
if (!fwnode_property_read_bool(dev_fwnode(dev), "mode-switch"))
return 0;
+ typec->mux_gpio = devm_gpiod_get_optional(dev, "mux", GPIOD_ASIS);
+ if (IS_ERR(typec->mux_gpio))
+ return dev_err_probe(dev, PTR_ERR(typec->mux_gpio), "failed to get mux gpio\n");
+
dp_dev = devm_drm_dp_typec_bridge_alloc(dev, dev->of_node);
if (IS_ERR(dp_dev))
return PTR_ERR(dp_dev);
+
+ if (fwnode_property_read_bool(dev_fwnode(dev), "no-hpd"))
+ drm_dp_typec_bridge_add_hpd_notify(dp_dev, cros_typec_dp_bridge_hpd_notify, typec);
+
typec->dp_bridge = dp_dev;
return devm_drm_dp_typec_bridge_add(dev, dp_dev);
@@ -635,6 +655,59 @@ static int cros_typec_enable_usb4(struct cros_typec_data *typec,
return typec_mux_set(port->mux, &port->state);
}
+/*
+ * Some ECs don't notify AP when HPD goes high or low because their firmware is
+ * broken. Capture the state of HPD in cros_typec_dp_bridge_hpd_notify() and
+ * inject the asserted state into the EC's response (deasserted is the
+ * default).
+ */
+static void cros_typec_inject_hpd(struct cros_typec_data *typec,
+ struct ec_response_usb_pd_mux_info *resp,
+ struct cros_typec_port *port)
+{
+ struct gpio_desc *mux_gpio = typec->mux_gpio;
+ int val;
+
+ /* Never registered a drm_bridge. Skip. */
+ if (!typec->dp_bridge)
+ return;
+
+ /* Don't need to inject HPD level when DP isn't enabled. */
+ if (!(resp->flags & USB_PD_MUX_DP_ENABLED))
+ return;
+
+ /*
+ * The default setting is HPD deasserted. Ignore if nothing to inject.
+ */
+ if (!typec->hpd_asserted)
+ return;
+
+ /*
+ * Only read the mux GPIO setting if we need to change the active port.
+ * Otherwise, an active port is already set and HPD going high or low
+ * doesn't change the muxed port until DP mode is exited.
+ */
+ if (!typec->active_dp_port) {
+ if (mux_gpio) {
+ val = gpiod_get_value_cansleep(mux_gpio);
+ if (val < 0) {
+ dev_err(typec->dev, "Failed to read mux gpio\n");
+ return;
+ }
+ /* Ignore HPD changes for non-active port. */
+ if (typec->ports[val] != port)
+ return;
+ }
+ } else if (port != typec->active_dp_port) {
+ /* Ignore HPD changes for non-active port. */
+ return;
+ }
+
+ /* Inject HPD from the GPIO state if EC firmware is broken. */
+ if (typec->hpd_asserted)
+ resp->flags |= USB_PD_MUX_HPD_LVL;
+}
+
static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
struct ec_response_usb_pd_control_v2 *pd_ctrl)
{
@@ -656,6 +729,7 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
port_num, ret);
return ret;
}
+ cros_typec_inject_hpd(typec, &resp, port);
/* No change needs to be made, let's exit early. */
if (port->mux_flags == resp.flags && port->role == pd_ctrl->role)
diff --git a/drivers/platform/chrome/cros_ec_typec.h b/drivers/platform/chrome/cros_ec_typec.h
index f3a2b67df07c..4ccd3d014aa6 100644
--- a/drivers/platform/chrome/cros_ec_typec.h
+++ b/drivers/platform/chrome/cros_ec_typec.h
@@ -37,6 +37,8 @@ struct cros_typec_data {
struct cros_typec_port *ports[EC_USB_PD_MAX_PORTS];
struct drm_dp_typec_bridge_dev *dp_bridge;
struct cros_typec_port *active_dp_port;
+ struct gpio_desc *mux_gpio;
+ bool hpd_asserted;
struct notifier_block nb;
struct work_struct port_work;
bool typec_cmd_supported;
--
https://chromeos.dev
^ permalink raw reply related [flat|nested] 60+ messages in thread
* Re: [PATCH v4 11/18] device property: Add remote endpoint to devcon matcher
2024-09-01 4:06 ` [PATCH v4 11/18] device property: Add remote endpoint to devcon matcher Stephen Boyd
@ 2024-09-02 11:12 ` Andy Shevchenko
2024-09-03 22:49 ` Stephen Boyd
0 siblings, 1 reply; 60+ messages in thread
From: Andy Shevchenko @ 2024-09-02 11:12 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, Dmitry Baryshkov,
dri-devel, Guenter Roeck, Jernej Skrabec, Jonas Karlman,
Krzysztof Kozlowski, Laurent Pinchart, Lee Jones,
Maarten Lankhorst, Maxime Ripard, Neil Armstrong, Prashant Malani,
Robert Foss, Rob Herring, Thomas Zimmermann, Tzung-Bi Shih,
Alexandre Belloni, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
On Sat, Aug 31, 2024 at 09:06:49PM -0700, Stephen Boyd wrote:
> When a single DT node has a graph connected to more than one
> usb-c-connector node we can't differentiate which typec switch
> registered for the device is associated with the USB connector because
> the devcon matcher code assumes a 1:1 relationship between remote node
> and typec switch. Furthermore, we don't have a #typec-switch-cells
> property so there can only be one node per typec switch.
>
> Support multiple USB typec switches exposed by one node by passing the
> remote endpoint node in addition to the remote node to the devcon
> matcher function (devcon_match_fn_t). With this change, typec switch
> drivers can register switches with the device node pointer for a graph
> endpoint so that they can support more than one typec switch if
> necessary. Either way, a DT property like 'mode-switch' is always in the
> graph's parent node and not in the endpoint node.
> Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Cc: Daniel Scally <djrscally@gmail.com>
> Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Cc: Sakari Ailus <sakari.ailus@linux.intel.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Vinod Koul <vkoul@kernel.org>
> Cc: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
> Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
> Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
> Cc: Ivan Orlov <ivan.orlov0322@gmail.com>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>
> Cc: Conor Dooley <conor+dt@kernel.org>
> Cc: <devicetree@vger.kernel.org>
> Cc: <linux-usb@vger.kernel.org>
> Cc: <linux-acpi@vger.kernel.org>
> Cc: Pin-yen Lin <treapking@chromium.org>
Is it possible to move these Cc:s after --- line below?
> Signed-off-by: Stephen Boyd <swboyd@chromium.org>
...
> /**
> * devcon_match_fn_t - device connection match function
> * @fwnode: Remote connection's device node
> + * @endpoint: Remote connection's endpoint node
> * @con_id: Identifier for the connection
> * @data: Match function caller specific data
> *
> * Implement a callback with this function signature to search a fwnode's
> * connections for a match with a function like device_connection_find_match().
> * This function will be called possibly multiple times, once for each
> - * connection. The match function should inspect the @fwnode to look for a
> - * match. The @con_id and @data provided are the same as the @con_id and @data
> - * arguments passed to the functions that take a devcon_match_fn_t argument.
> + * connection. The match function should inspect the connection's @fwnode
> + * and/or @endpoint to look for a match. The @con_id and @data provided are the
> + * same as the @con_id and @data arguments passed to the functions that take a
> + * devcon_match_fn_t argument.
So, struct fwnode_handle is a single-linked list. Can we utilise that instead
of adding a new parameter? I.o.w. do those objects (@fwnode and @endpoint) have
anything in common and can be chained?
> * Note: This function can be called multiple times.
What does this mean? Is it idempotent? Or what is the effect of being called
multiple times?
> *
> * Return: Pointer to match or NULL if no match found.
> */
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 10/18] devcon property: Document devcon_match_fn_t
2024-09-01 4:06 ` [PATCH v4 10/18] devcon property: Document devcon_match_fn_t Stephen Boyd
@ 2024-09-02 11:17 ` Andy Shevchenko
2024-09-03 22:35 ` Stephen Boyd
0 siblings, 1 reply; 60+ messages in thread
From: Andy Shevchenko @ 2024-09-02 11:17 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, Dmitry Baryshkov,
dri-devel, Guenter Roeck, Jernej Skrabec, Jonas Karlman,
Krzysztof Kozlowski, Laurent Pinchart, Lee Jones,
Maarten Lankhorst, Maxime Ripard, Neil Armstrong, Prashant Malani,
Robert Foss, Rob Herring, Thomas Zimmermann, Tzung-Bi Shih,
Alexandre Belloni, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
On Sat, Aug 31, 2024 at 09:06:48PM -0700, Stephen Boyd wrote:
> The usage of this match function is hard to understand at a glance.
> Document the arguments and the return value so it is clear how to
> implement the function.
Thank you for the patch!
...
I believe we still use "device property:" in the subject for this header file changes.
$ git log --oneline --no-merges -- include/linux/property.h
...
> +/**
> + * devcon_match_fn_t - device connection match function
> + * @fwnode: Remote connection's device node
> + * @con_id: Identifier for the connection
> + * @data: Match function caller specific data
> + *
> + * Implement a callback with this function signature to search a fwnode's
> + * connections for a match with a function like device_connection_find_match().
> + * This function will be called possibly multiple times, once for each
> + * connection. The match function should inspect the @fwnode to look for a
> + * match. The @con_id and @data provided are the same as the @con_id and @data
> + * arguments passed to the functions that take a devcon_match_fn_t argument.
> + * Note: This function can be called multiple times.
As noted in the next patch, this would be nice to elaborate (at least to me
this sounds like declaration of idempotency which is unlikely what is
meant, or am I mistaken?).
> + * Return: Pointer to match or NULL if no match found.
> + */
> +typedef void *(*devcon_match_fn_t)(const struct fwnode_handle *fwnode,
> + const char *con_id, void *data);
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 05/18] usb: typec: Add device managed typec_switch_register()
2024-09-01 4:06 ` [PATCH v4 05/18] usb: typec: Add device managed typec_switch_register() Stephen Boyd
@ 2024-09-02 11:22 ` Andy Shevchenko
0 siblings, 0 replies; 60+ messages in thread
From: Andy Shevchenko @ 2024-09-02 11:22 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, Dmitry Baryshkov,
dri-devel, Guenter Roeck, Jernej Skrabec, Jonas Karlman,
Krzysztof Kozlowski, Laurent Pinchart, Lee Jones,
Maarten Lankhorst, Maxime Ripard, Neil Armstrong, Prashant Malani,
Robert Foss, Rob Herring, Thomas Zimmermann, Tzung-Bi Shih,
Alexandre Belloni, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
On Sat, Aug 31, 2024 at 09:06:43PM -0700, Stephen Boyd wrote:
> Simplify driver error paths by adding devm_typec_switch_register() which
> will unregister the typec switch when the parent device is unbound.
...
> +struct typec_switch_dev *
> +devm_typec_switch_register(struct device *parent,
> + const struct typec_switch_desc *desc)
> +{
> + int ret;
> + struct typec_switch_dev *switch_dev;
> +
> + switch_dev = typec_switch_register(parent ,desc);
Slipped typo, i.e. wrong location of the white space character.
> + if (IS_ERR(switch_dev))
> + return switch_dev;
> +
> + ret = devm_add_action_or_reset(parent, devm_typec_switch_unregister, switch_dev);
> + if (ret)
> + return ERR_PTR(ret);
> +
> + return switch_dev;
> +}
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 06/18] drm/bridge: aux-hpd: Support USB Type-C DP altmodes via DRM lane assignment
2024-09-01 4:06 ` [PATCH v4 06/18] drm/bridge: aux-hpd: Support USB Type-C DP altmodes via DRM lane assignment Stephen Boyd
@ 2024-09-02 11:35 ` Andy Shevchenko
2024-09-03 22:20 ` Stephen Boyd
0 siblings, 1 reply; 60+ messages in thread
From: Andy Shevchenko @ 2024-09-02 11:35 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, Dmitry Baryshkov,
dri-devel, Guenter Roeck, Jernej Skrabec, Jonas Karlman,
Krzysztof Kozlowski, Laurent Pinchart, Lee Jones,
Maarten Lankhorst, Maxime Ripard, Neil Armstrong, Prashant Malani,
Robert Foss, Rob Herring, Thomas Zimmermann, Tzung-Bi Shih,
Alexandre Belloni, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
On Sat, Aug 31, 2024 at 09:06:44PM -0700, Stephen Boyd wrote:
> Extend the aux-hpd bridge driver to support assigning DP lanes to USB
> type-c pins based on typec mux state entry. Existing users of this
> driver only need the HPD signaling support, so leave that in place and
> wrap the code with a variant that supports more features of USB type-c
Isn't the proper spelling "USB Type-C"?
> DP altmode, i.e. pin configurations. Prefix that code with
> 'drm_dp_typec_bridge' to differentiate it from the existing
> 'drm_aux_hpd_bridge' code.
>
> Parse the struct typec_mux_state members to determine if DP altmode has
> been entered and if HPD is asserted or not. Signal HPD to the drm bridge
> chain when HPD is asserted. Similarly, parse the pin assignment and map
> the DP lanes to the usb-c output lanes, taking into account any lane
> remapping from the data-lanes endpoint property. Pass that lane mapping
> to the previous drm_bridge in the bridge chain during the atomic check
> phase.
...
> +static inline struct drm_dp_typec_bridge_data *
> +hpd_bridge_to_typec_bridge_data(struct drm_aux_hpd_bridge_data *hpd_data)
> +{
> + return container_of(hpd_data, struct drm_dp_typec_bridge_data, hpd_bridge);
+ container_of.h ?
With that said, can the argument be const here?
> +}
...
Ditto for the two more helpers, added in this change.
...
> +static void drm_dp_typec_bridge_release(struct device *dev)
> +{
> + struct drm_dp_typec_bridge_dev *typec_bridge_dev;
> + struct auxiliary_device *adev;
> +
> + typec_bridge_dev = to_drm_dp_typec_bridge_dev(dev);
> + adev = &typec_bridge_dev->adev;
> +
> + ida_free(&drm_aux_hpd_bridge_ida, adev->id);
> + of_node_put(adev->dev.platform_data);
> + of_node_put(adev->dev.of_node);
I'm wondering why it's not made fwnode to begin with...
From the file / function names it's not obvious that it's OF-only code. Neither
there is no explanations why this must be OF-only code (among all fwnode types
supported).
> + kfree(typec_bridge_dev);
> +}
...
> + return ERR_PTR(dev_err_probe(parent, -ENODEV, "Missing typec endpoint(s) port@0\n"));
We have a new helper for such cases.
...
> + adev->dev.of_node = of_node_get(parent->of_node);
device_set_node() ?
...
> + ret = auxiliary_device_init(adev);
> + if (ret) {
> + of_node_put(adev->dev.platform_data);
> + of_node_put(adev->dev.of_node);
> + ida_free(&drm_aux_hpd_bridge_ida, adev->id);
> + kfree(adev);
> + return ERR_PTR(ret);
Can cleanup.h be utilised here and in other error paths in this function?
> + }
> + ret = devm_add_action_or_reset(parent, drm_aux_hpd_bridge_free_adev, adev);
> + if (ret)
> + return ERR_PTR(ret);
> +
> + return typec_bridge_dev;
> +}
...
> +static int dp_lane_to_typec_lane(enum dp_lane lane)
> +{
> + switch (lane) {
> + case DP_ML0:
> + return USB_SSTX2;
> + case DP_ML1:
> + return USB_SSRX2;
> + case DP_ML2:
> + return USB_SSTX1;
> + case DP_ML3:
> + return USB_SSRX1;
> + }
> + return -EINVAL;
Hmm... This can be simply made as default case.
> +}
> +
> +static int typec_to_dp_lane(enum usb_ss_lane lane)
> +{
> + switch (lane) {
> + case USB_SSRX1:
> + return DP_ML3;
> + case USB_SSTX1:
> + return DP_ML2;
> + case USB_SSTX2:
> + return DP_ML0;
> + case USB_SSRX2:
> + return DP_ML1;
> + }
> +
> + return -EINVAL;
Ditto.
> +}
...
> + for (i = 0; i < num_lanes; i++) {
> + /* Get physical type-c lane for DP lane */
> + typec_lane = dp_lane_to_typec_lane(i);
> + if (typec_lane < 0) {
> + dev_err(&adev->dev, "Invalid type-c lane configuration at DP_ML%d\n", i);
> + return -EINVAL;
Most likely typec_lane contains an error code here. If yes, it would be rather
return typec_lane;
If no, why not make that happen?
> + }
> +
> + /* Map physical to logical type-c lane */
> + typec_lane = lane_mapping[typec_lane];
> +
> + /* Map logical type-c lane to logical DP lane */
> + dp_lanes[i] = typec_to_dp_lane(typec_lane);
> + }
...
> +static int drm_dp_typec_bridge_atomic_check(struct drm_bridge *bridge,
> + struct drm_bridge_state *bridge_state,
> + struct drm_crtc_state *crtc_state,
> + struct drm_connector_state *conn_state)
> +{
> + struct drm_dp_typec_bridge_data *data;
> + struct drm_lane_cfg *in_lanes;
> + u8 *dp_lanes;
> + size_t num_lanes;
> + int i;
Does it need to be signed? Can it theoretically overflow as num_lanes defined
as size_t?
> + data = to_drm_dp_typec_bridge_data(bridge);
> + num_lanes = data->num_lanes;
> + if (!num_lanes)
> + return 0;
> + dp_lanes = data->dp_lanes;
> +
> + in_lanes = kcalloc(num_lanes, sizeof(*in_lanes), GFP_KERNEL);
> + if (!in_lanes)
> + return -ENOMEM;
> +
> + bridge_state->input_bus_cfg.lanes = in_lanes;
> + bridge_state->input_bus_cfg.num_lanes = num_lanes;
> +
> + for (i = 0; i < num_lanes; i++)
> + in_lanes[i].logical = dp_lanes[i];
> +
> + return 0;
> +}
...
> + port->typec_data = typec_data;
> + if (of_property_read_u32_array(ep.local_node, "data-lanes",
> + port->lane_mapping,
> + ARRAY_SIZE(port->lane_mapping))) {
> + memcpy(port->lane_mapping, mapping, sizeof(mapping));
Hmm... I'm wondering if direct assignment will save a few .text bytes
port->lane_mapping = ...;
of_property_read_u32_array(ep.local_node, "data-lanes",
port->lane_mapping,
ARRAY_SIZE(port->lane_mapping));
Also note that conditional is not needed in this case.
(And again, why OF-centric code?)
> + }
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 03/18] usb: typec: Stub out typec_switch APIs when CONFIG_TYPEC=n
2024-09-01 4:06 ` [PATCH v4 03/18] usb: typec: Stub out typec_switch APIs when CONFIG_TYPEC=n Stephen Boyd
@ 2024-09-03 11:40 ` Heikki Krogerus
2024-09-19 10:12 ` Dmitry Baryshkov
1 sibling, 0 replies; 60+ messages in thread
From: Heikki Krogerus @ 2024-09-03 11:40 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, Dmitry Baryshkov,
dri-devel, Guenter Roeck, Jernej Skrabec, Jonas Karlman,
Krzysztof Kozlowski, Laurent Pinchart, Lee Jones,
Maarten Lankhorst, Maxime Ripard, Neil Armstrong, Prashant Malani,
Robert Foss, Rob Herring, Thomas Zimmermann, Tzung-Bi Shih,
Alexandre Belloni, Andy Shevchenko, Daniel Scally,
Greg Kroah-Hartman, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
On Sat, Aug 31, 2024 at 09:06:41PM -0700, Stephen Boyd wrote:
> Ease driver development by adding stubs for the typec_switch APIs when
> CONFIG_TYPEC=n. Copy the same method used for the typec_mux APIs to be
> consistent.
>
> Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: <linux-usb@vger.kernel.org>
> Cc: Pin-yen Lin <treapking@chromium.org>
> Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> ---
> include/linux/usb/typec_mux.h | 43 +++++++++++++++++++++++++++++++----
> 1 file changed, 38 insertions(+), 5 deletions(-)
>
> diff --git a/include/linux/usb/typec_mux.h b/include/linux/usb/typec_mux.h
> index 2489a7857d8e..efb5ed32b813 100644
> --- a/include/linux/usb/typec_mux.h
> +++ b/include/linux/usb/typec_mux.h
> @@ -3,6 +3,7 @@
> #ifndef __USB_TYPEC_MUX
> #define __USB_TYPEC_MUX
>
> +#include <linux/err.h>
> #include <linux/property.h>
> #include <linux/usb/typec.h>
>
> @@ -24,16 +25,13 @@ struct typec_switch_desc {
> void *drvdata;
> };
>
> +#if IS_ENABLED(CONFIG_TYPEC)
> +
> struct typec_switch *fwnode_typec_switch_get(struct fwnode_handle *fwnode);
> void typec_switch_put(struct typec_switch *sw);
> int typec_switch_set(struct typec_switch *sw,
> enum typec_orientation orientation);
>
> -static inline struct typec_switch *typec_switch_get(struct device *dev)
> -{
> - return fwnode_typec_switch_get(dev_fwnode(dev));
> -}
> -
> struct typec_switch_dev *
> typec_switch_register(struct device *parent,
> const struct typec_switch_desc *desc);
> @@ -42,6 +40,41 @@ void typec_switch_unregister(struct typec_switch_dev *sw);
> void typec_switch_set_drvdata(struct typec_switch_dev *sw, void *data);
> void *typec_switch_get_drvdata(struct typec_switch_dev *sw);
>
> +#else
> +
> +static inline struct typec_switch *
> +fwnode_typec_switch_get(struct fwnode_handle *fwnode)
> +{
> + return NULL;
> +}
> +static inline void typec_switch_put(struct typec_switch *sw) {}
> +static inline int typec_switch_set(struct typec_switch *sw,
> + enum typec_orientation orientation)
> +{
> + return 0;
> +}
> +
> +static inline struct typec_switch_dev *
> +typec_switch_register(struct device *parent,
> + const struct typec_switch_desc *desc)
> +{
> + return ERR_PTR(-EOPNOTSUPP);
> +}
> +static inline void typec_switch_unregister(struct typec_switch_dev *sw) {}
> +
> +static inline void typec_switch_set_drvdata(struct typec_switch_dev *sw, void *data) {}
> +static inline void *typec_switch_get_drvdata(struct typec_switch_dev *sw)
> +{
> + return ERR_PTR(-EOPNOTSUPP);
> +}
> +
> +#endif /* CONFIG_TYPEC */
> +
> +static inline struct typec_switch *typec_switch_get(struct device *dev)
> +{
> + return fwnode_typec_switch_get(dev_fwnode(dev));
> +}
> +
> struct typec_mux_state {
> struct typec_altmode *alt;
> unsigned long mode;
--
heikki
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 04/18] usb: typec: Add device managed typec_mux_register()
2024-09-01 4:06 ` [PATCH v4 04/18] usb: typec: Add device managed typec_mux_register() Stephen Boyd
@ 2024-09-03 11:57 ` Heikki Krogerus
0 siblings, 0 replies; 60+ messages in thread
From: Heikki Krogerus @ 2024-09-03 11:57 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, Dmitry Baryshkov,
dri-devel, Guenter Roeck, Jernej Skrabec, Jonas Karlman,
Krzysztof Kozlowski, Laurent Pinchart, Lee Jones,
Maarten Lankhorst, Maxime Ripard, Neil Armstrong, Prashant Malani,
Robert Foss, Rob Herring, Thomas Zimmermann, Tzung-Bi Shih,
Alexandre Belloni, Andy Shevchenko, Daniel Scally,
Greg Kroah-Hartman, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
> diff --git a/include/linux/usb/typec_mux.h b/include/linux/usb/typec_mux.h
> index efb5ed32b813..08431f0896d5 100644
> --- a/include/linux/usb/typec_mux.h
> +++ b/include/linux/usb/typec_mux.h
> @@ -99,6 +99,8 @@ int typec_mux_set(struct typec_mux *mux, struct typec_mux_state *state);
>
> struct typec_mux_dev *
> typec_mux_register(struct device *parent, const struct typec_mux_desc *desc);
> +struct typec_mux_dev *
> +devm_typec_mux_register(struct device *parent, const struct typec_mux_desc *desc);
> void typec_mux_unregister(struct typec_mux_dev *mux);
>
> void typec_mux_set_drvdata(struct typec_mux_dev *mux, void *data);
> @@ -123,6 +125,11 @@ typec_mux_register(struct device *parent, const struct typec_mux_desc *desc)
> {
> return ERR_PTR(-EOPNOTSUPP);
> }
> +static inline struct typec_mux_dev *
> +devm_typec_mux_register(struct device *parent, const struct typec_mux_desc *desc)
> +{
> + return typec_mux_register(parent, desc);
Please just return the error directly here.
> +}
thanks,
--
heikki
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
2024-09-01 4:06 ` [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode Stephen Boyd
@ 2024-09-03 15:35 ` Lee Jones
2024-09-20 9:38 ` Dmitry Baryshkov
1 sibling, 0 replies; 60+ messages in thread
From: Lee Jones @ 2024-09-03 15:35 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, Dmitry Baryshkov,
dri-devel, Guenter Roeck, Jernej Skrabec, Jonas Karlman,
Krzysztof Kozlowski, Laurent Pinchart, Maarten Lankhorst,
Maxime Ripard, Neil Armstrong, Prashant Malani, Robert Foss,
Rob Herring, Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring (Arm)
On Sat, 31 Aug 2024, Stephen Boyd wrote:
> Add a DT graph binding to google,cros-ec-typec so that it can combine
> DisplayPort (DP) and USB SuperSpeed (SS) data into a USB type-c endpoint
> that is connected to the usb-c-connector node's SS endpoint. This also
> allows us to connect the DP and USB nodes in the graph to the USB type-c
> connectors, providing the full picture of the USB type-c data flows in
> the system.
>
> Allow there to be multiple typec nodes underneath the EC node so that
> one DT graph exists per DP bridge. The EC is actually controlling TCPCs
> and redrivers that combine the DP and USB signals together so this more
> accurately reflects the hardware design without introducing yet another
> DT node underneath the EC for USB type-c.
>
> If the type-c ports are being shared between a single DP controller then
> the ports need to know about each other and determine a policy to drive
> DP to one type-c port. If the type-c ports each have their own dedicated
> DP controller then they're able to operate independently and enter/exit
> DP altmode independently as well. We can't connect the DP controller's
> endpoint to one usb-c-connector port@1 endpoint and the USB controller's
> endpoint to another usb-c-connector port@1 endpoint either because the
> DP muxing case would have DP connected to two usb-c-connector endpoints
> which the graph binding doesn't support.
>
> Therefore, one typec node is required per the capabilities of the type-c
> port(s) being managed. This also lets us indicate which type-c ports the
> DP controller is wired to. For example, if DP was connected to ports 0
> and 2, while port 1 was connected to another DP controller we wouldn't
> be able to implement that without having some other DT property to
> indicate which output ports are connected to the DP endpoint.
>
> Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
> Cc: Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>
> Cc: Conor Dooley <conor+dt@kernel.org>
> Acked-by: Lee Jones <lee@kernel.org>
> Cc: Benson Leung <bleung@chromium.org>
> Cc: Guenter Roeck <groeck@chromium.org>
> Cc: Prashant Malani <pmalani@chromium.org>
> Cc: Tzung-Bi Shih <tzungbi@kernel.org>
> Cc: <devicetree@vger.kernel.org>
> Cc: <chrome-platform@lists.linux.dev>
> Cc: Pin-yen Lin <treapking@chromium.org>
> Signed-off-by: Stephen Boyd <swboyd@chromium.org>
> ---
> .../bindings/mfd/google,cros-ec.yaml | 7 +-
Acked-by: Lee Jones <lee@kernel.org>
> .../bindings/usb/google,cros-ec-typec.yaml | 229 ++++++++++++++++++
> 2 files changed, 233 insertions(+), 3 deletions(-)
--
Lee Jones [李琼斯]
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 06/18] drm/bridge: aux-hpd: Support USB Type-C DP altmodes via DRM lane assignment
2024-09-02 11:35 ` Andy Shevchenko
@ 2024-09-03 22:20 ` Stephen Boyd
2024-09-04 13:00 ` Andy Shevchenko
0 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-09-03 22:20 UTC (permalink / raw)
To: Andy Shevchenko
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, Dmitry Baryshkov,
dri-devel, Guenter Roeck, Jernej Skrabec, Jonas Karlman,
Krzysztof Kozlowski, Laurent Pinchart, Lee Jones,
Maarten Lankhorst, Maxime Ripard, Neil Armstrong, Prashant Malani,
Robert Foss, Rob Herring, Thomas Zimmermann, Tzung-Bi Shih,
Alexandre Belloni, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
Quoting Andy Shevchenko (2024-09-02 04:35:46)
> On Sat, Aug 31, 2024 at 09:06:44PM -0700, Stephen Boyd wrote:
> > Extend the aux-hpd bridge driver to support assigning DP lanes to USB
> > type-c pins based on typec mux state entry. Existing users of this
> > driver only need the HPD signaling support, so leave that in place and
> > wrap the code with a variant that supports more features of USB type-c
>
> Isn't the proper spelling "USB Type-C"?
Perhaps in a title?
>
> > DP altmode, i.e. pin configurations. Prefix that code with
> > 'drm_dp_typec_bridge' to differentiate it from the existing
> > 'drm_aux_hpd_bridge' code.
> >
> > Parse the struct typec_mux_state members to determine if DP altmode has
> > been entered and if HPD is asserted or not. Signal HPD to the drm bridge
> > chain when HPD is asserted. Similarly, parse the pin assignment and map
> > the DP lanes to the usb-c output lanes, taking into account any lane
> > remapping from the data-lanes endpoint property. Pass that lane mapping
> > to the previous drm_bridge in the bridge chain during the atomic check
> > phase.
>
> ...
>
> > +static inline struct drm_dp_typec_bridge_data *
> > +hpd_bridge_to_typec_bridge_data(struct drm_aux_hpd_bridge_data *hpd_data)
> > +{
> > + return container_of(hpd_data, struct drm_dp_typec_bridge_data, hpd_bridge);
>
> + container_of.h ?
>
> With that said, can the argument be const here?
You mean 'hpd_data'? Don't think so because then we would want
container_of_const(), and to return a const pointer from this function
when drm_dp_typec_bridge_assign_pins() wants to modify struct
drm_dp_typec_bridge_data::num_lanes.
>
> > +}
>
> ...
>
> Ditto for the two more helpers, added in this change.
Ditto.
>
> ...
>
> > +static void drm_dp_typec_bridge_release(struct device *dev)
> > +{
> > + struct drm_dp_typec_bridge_dev *typec_bridge_dev;
> > + struct auxiliary_device *adev;
> > +
> > + typec_bridge_dev = to_drm_dp_typec_bridge_dev(dev);
> > + adev = &typec_bridge_dev->adev;
> > +
> > + ida_free(&drm_aux_hpd_bridge_ida, adev->id);
>
> > + of_node_put(adev->dev.platform_data);
> > + of_node_put(adev->dev.of_node);
>
> I'm wondering why it's not made fwnode to begin with...
> From the file / function names it's not obvious that it's OF-only code. Neither
> there is no explanations why this must be OF-only code (among all fwnode types
> supported).
When in Rome? The drm_bridge code doesn't work with fwnode today, and
making it support fwnode is a much larger change. I'm not going to make
drm_bridge work with fwnode. Maybe when ACPI describes elements in the
display chain we can convert drm_bridge to use fwnode.
>
> > + kfree(typec_bridge_dev);
> > +}
>
> ...
>
> > + return ERR_PTR(dev_err_probe(parent, -ENODEV, "Missing typec endpoint(s) port@0\n"));
>
> We have a new helper for such cases.
Thanks!
>
> ...
>
> > + adev->dev.of_node = of_node_get(parent->of_node);
>
> device_set_node() ?
Or device_set_of_node_from_dev()?
>
> ...
>
> > + ret = auxiliary_device_init(adev);
> > + if (ret) {
> > + of_node_put(adev->dev.platform_data);
> > + of_node_put(adev->dev.of_node);
> > + ida_free(&drm_aux_hpd_bridge_ida, adev->id);
> > + kfree(adev);
> > + return ERR_PTR(ret);
>
> Can cleanup.h be utilised here and in other error paths in this function?
It looks like we can set these later and save on the of_node_put()s
until after the auxiliary_device_init() is called. Doing that allows
them to be in one place, the release function.
> > +static int dp_lane_to_typec_lane(enum dp_lane lane)
> > +{
> > + switch (lane) {
> > + case DP_ML0:
> > + return USB_SSTX2;
> > + case DP_ML1:
> > + return USB_SSRX2;
> > + case DP_ML2:
> > + return USB_SSTX1;
> > + case DP_ML3:
> > + return USB_SSRX1;
> > + }
>
> > + return -EINVAL;
>
> Hmm... This can be simply made as default case.
And then the enum is always "covered" and the compiler doesn't complain
about missing cases (I don't think we have -Wswitch-enum)? Seems worse.
>
> > +}
>
> ...
>
> > + for (i = 0; i < num_lanes; i++) {
> > + /* Get physical type-c lane for DP lane */
> > + typec_lane = dp_lane_to_typec_lane(i);
> > + if (typec_lane < 0) {
> > + dev_err(&adev->dev, "Invalid type-c lane configuration at DP_ML%d\n", i);
> > + return -EINVAL;
>
> Most likely typec_lane contains an error code here. If yes, it would be rather
>
> return typec_lane;
>
> If no, why not make that happen?
Sure.
>
> > +static int drm_dp_typec_bridge_atomic_check(struct drm_bridge *bridge,
> > + struct drm_bridge_state *bridge_state,
> > + struct drm_crtc_state *crtc_state,
> > + struct drm_connector_state *conn_state)
> > +{
> > + struct drm_dp_typec_bridge_data *data;
> > + struct drm_lane_cfg *in_lanes;
> > + u8 *dp_lanes;
> > + size_t num_lanes;
>
> > + int i;
>
> Does it need to be signed? Can it theoretically overflow as num_lanes defined
> as size_t?
I guess it could but seems highly unlikely. Using unsigned is fine.
>
> > + port->typec_data = typec_data;
> > + if (of_property_read_u32_array(ep.local_node, "data-lanes",
> > + port->lane_mapping,
> > + ARRAY_SIZE(port->lane_mapping))) {
>
> > + memcpy(port->lane_mapping, mapping, sizeof(mapping));
>
> Hmm... I'm wondering if direct assignment will save a few .text bytes
>
> port->lane_mapping = ...;
> of_property_read_u32_array(ep.local_node, "data-lanes",
> port->lane_mapping,
> ARRAY_SIZE(port->lane_mapping));
>
> Also note that conditional is not needed in this case.
>
Ok. I'm fine with either way here. Maybe Dmitry has an opinion.
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 10/18] devcon property: Document devcon_match_fn_t
2024-09-02 11:17 ` Andy Shevchenko
@ 2024-09-03 22:35 ` Stephen Boyd
0 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2024-09-03 22:35 UTC (permalink / raw)
To: Andy Shevchenko
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, Dmitry Baryshkov,
dri-devel, Guenter Roeck, Jernej Skrabec, Jonas Karlman,
Krzysztof Kozlowski, Laurent Pinchart, Lee Jones,
Maarten Lankhorst, Maxime Ripard, Neil Armstrong, Prashant Malani,
Robert Foss, Rob Herring, Thomas Zimmermann, Tzung-Bi Shih,
Alexandre Belloni, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
Quoting Andy Shevchenko (2024-09-02 04:17:12)
> On Sat, Aug 31, 2024 at 09:06:48PM -0700, Stephen Boyd wrote:
> > The usage of this match function is hard to understand at a glance.
> > Document the arguments and the return value so it is clear how to
> > implement the function.
>
> Thank you for the patch!
>
> ...
>
> I believe we still use "device property:" in the subject for this header file changes.
> $ git log --oneline --no-merges -- include/linux/property.h
>
Ok.
>
> > +/**
> > + * devcon_match_fn_t - device connection match function
> > + * @fwnode: Remote connection's device node
> > + * @con_id: Identifier for the connection
> > + * @data: Match function caller specific data
> > + *
> > + * Implement a callback with this function signature to search a fwnode's
> > + * connections for a match with a function like device_connection_find_match().
> > + * This function will be called possibly multiple times, once for each
> > + * connection. The match function should inspect the @fwnode to look for a
> > + * match. The @con_id and @data provided are the same as the @con_id and @data
> > + * arguments passed to the functions that take a devcon_match_fn_t argument.
>
> > + * Note: This function can be called multiple times.
>
> As noted in the next patch, this would be nice to elaborate (at least to me
> this sounds like declaration of idempotency which is unlikely what is
> meant, or am I mistaken?).
I based this on something that I've already forgotten! :)
It's saying that the function you implement shouldn't have side-effects
because it will be called many times. I actually wrote above that it
will be called "possibly multiple times, once for each connection". Let
me try to remove "multiple times".
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 11/18] device property: Add remote endpoint to devcon matcher
2024-09-02 11:12 ` Andy Shevchenko
@ 2024-09-03 22:49 ` Stephen Boyd
0 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2024-09-03 22:49 UTC (permalink / raw)
To: Andy Shevchenko
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, Dmitry Baryshkov,
dri-devel, Guenter Roeck, Jernej Skrabec, Jonas Karlman,
Krzysztof Kozlowski, Laurent Pinchart, Lee Jones,
Maarten Lankhorst, Maxime Ripard, Neil Armstrong, Prashant Malani,
Robert Foss, Rob Herring, Thomas Zimmermann, Tzung-Bi Shih,
Alexandre Belloni, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
Quoting Andy Shevchenko (2024-09-02 04:12:49)
> On Sat, Aug 31, 2024 at 09:06:49PM -0700, Stephen Boyd wrote:
>
> Is it possible to move these Cc:s after --- line below?
Ok.
>
> > /**
> > * devcon_match_fn_t - device connection match function
> > * @fwnode: Remote connection's device node
> > + * @endpoint: Remote connection's endpoint node
> > * @con_id: Identifier for the connection
> > * @data: Match function caller specific data
> > *
> > * Implement a callback with this function signature to search a fwnode's
> > * connections for a match with a function like device_connection_find_match().
> > * This function will be called possibly multiple times, once for each
> > - * connection. The match function should inspect the @fwnode to look for a
> > - * match. The @con_id and @data provided are the same as the @con_id and @data
> > - * arguments passed to the functions that take a devcon_match_fn_t argument.
> > + * connection. The match function should inspect the connection's @fwnode
> > + * and/or @endpoint to look for a match. The @con_id and @data provided are the
> > + * same as the @con_id and @data arguments passed to the functions that take a
> > + * devcon_match_fn_t argument.
>
> So, struct fwnode_handle is a single-linked list. Can we utilise that instead
> of adding a new parameter? I.o.w. do those objects (@fwnode and @endpoint) have
> anything in common and can be chained?
No, we can't use that. We need to know which endpoint in the remote
fwnode is connected to the fwnode we're searching from. This is how we
know which typec mux structure is associated with which type-c port so
we can drive DP there. We might have two endpoints connected to the same
fwnode and then we wouldn't be able to differentiate the endpoint and
the typec mux to configure.
>
> > * Note: This function can be called multiple times.
>
> What does this mean? Is it idempotent? Or what is the effect of being called
> multiple times?
I've removed this note now.
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 16/18] platform/chrome: cros_ec_typec: Add support for signaling DP HPD via drm_bridge
2024-09-01 4:06 ` [PATCH v4 16/18] platform/chrome: cros_ec_typec: Add support for signaling DP HPD via drm_bridge Stephen Boyd
@ 2024-09-04 9:35 ` Tzung-Bi Shih
0 siblings, 0 replies; 60+ messages in thread
From: Tzung-Bi Shih @ 2024-09-04 9:35 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, Dmitry Baryshkov,
dri-devel, Guenter Roeck, Jernej Skrabec, Jonas Karlman,
Krzysztof Kozlowski, Laurent Pinchart, Lee Jones,
Maarten Lankhorst, Maxime Ripard, Neil Armstrong, Prashant Malani,
Robert Foss, Rob Herring, Thomas Zimmermann, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
On Sat, Aug 31, 2024 at 09:06:54PM -0700, Stephen Boyd wrote:
> We can imagine that logically the EC is a device that has some number of
> DisplayPort (DP) connector inputs, some number of USB3 connector inputs,
> and some number of USB type-c connector outputs. If you squint enough it
> looks like a USB type-c dock. Logically there's a crossbar pin
> assignment capability within the EC that can assign USB and DP lanes to
> USB type-c lanes in the connector (i.e. USB type-c pin configurations).
> In reality, the EC is a microcontroller that has some TCPCs and
> redrivers connected to it over something like i2c and DP/USB from the AP
> is wired directly to those ICs, not the EC.
>
> [...]
>
> Cc: Prashant Malani <pmalani@chromium.org>
> Cc: Benson Leung <bleung@chromium.org>
> Cc: Tzung-Bi Shih <tzungbi@kernel.org>
> Cc: <chrome-platform@lists.linux.dev>
> Cc: Pin-yen Lin <treapking@chromium.org>
> Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Reviewed-by: Tzung-Bi Shih <tzungbi@kernel.org>
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 17/18] platform/chrome: cros_ec_typec: Support DP muxing
2024-09-01 4:06 ` [PATCH v4 17/18] platform/chrome: cros_ec_typec: Support DP muxing Stephen Boyd
@ 2024-09-04 9:36 ` Tzung-Bi Shih
0 siblings, 0 replies; 60+ messages in thread
From: Tzung-Bi Shih @ 2024-09-04 9:36 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, Dmitry Baryshkov,
dri-devel, Guenter Roeck, Jernej Skrabec, Jonas Karlman,
Krzysztof Kozlowski, Laurent Pinchart, Lee Jones,
Maarten Lankhorst, Maxime Ripard, Neil Armstrong, Prashant Malani,
Robert Foss, Rob Herring, Thomas Zimmermann, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
On Sat, Aug 31, 2024 at 09:06:55PM -0700, Stephen Boyd wrote:
> Most ARM based chromebooks with two usb-c-connector nodes and one DP
> controller are muxing the DP lanes between the two USB ports. This is
> done so that the type-c ports are at least equal in capability if not
> functionality. Either an analog mux is used to steer the DP signal to
> one or the other port, or a DP bridge chip has two lanes (e.g. DP
> ML0/ML1) wired to one type-c port while the other two (e.g. DP ML2/ML3)
> are wired to another type-c port.
>
> [...]
>
> Cc: Prashant Malani <pmalani@chromium.org>
> Cc: Benson Leung <bleung@chromium.org>
> Cc: Tzung-Bi Shih <tzungbi@kernel.org>
> Cc: <chrome-platform@lists.linux.dev>
> Cc: Pin-yen Lin <treapking@chromium.org>
> Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Reviewed-by: Tzung-Bi Shih <tzungbi@kernel.org>
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 18/18] platform/chrome: cros_ec_typec: Handle lack of HPD information
2024-09-01 4:06 ` [PATCH v4 18/18] platform/chrome: cros_ec_typec: Handle lack of HPD information Stephen Boyd
@ 2024-09-04 9:36 ` Tzung-Bi Shih
2024-09-04 21:45 ` Stephen Boyd
0 siblings, 1 reply; 60+ messages in thread
From: Tzung-Bi Shih @ 2024-09-04 9:36 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, Dmitry Baryshkov,
dri-devel, Guenter Roeck, Jernej Skrabec, Jonas Karlman,
Krzysztof Kozlowski, Laurent Pinchart, Lee Jones,
Maarten Lankhorst, Maxime Ripard, Neil Armstrong, Prashant Malani,
Robert Foss, Rob Herring, Thomas Zimmermann, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
On Sat, Aug 31, 2024 at 09:06:56PM -0700, Stephen Boyd wrote:
> +static void cros_typec_inject_hpd(struct cros_typec_data *typec,
> + struct ec_response_usb_pd_mux_info *resp,
> + struct cros_typec_port *port)
> +{
[...]
> + /*
> + * Only read the mux GPIO setting if we need to change the active port.
> + * Otherwise, an active port is already set and HPD going high or low
> + * doesn't change the muxed port until DP mode is exited.
> + */
> + if (!typec->active_dp_port) {
Given that cros_typec_inject_hpd() is called before `typec->active_dp_port`
would be set (from previous patch "platform/chrome: ... Support DP muxing"),
would it possibly wrongly fall into here at the beginning? (E.g.:
cros_typec_probe() -> cros_typec_port_update() -> cros_typec_configure_mux()
-> cros_typec_inject_hpd().)
> [...]
> + /* Inject HPD from the GPIO state if EC firmware is broken. */
> + if (typec->hpd_asserted)
> + resp->flags |= USB_PD_MUX_HPD_LVL;
`typec->hpd_asserted` is shared between all typec->ports[...]. Would it be
possible that a HPD is asserted for another port but not current `port`?
E.g.: cros_typec_inject_hpd() for port 2 and cros_typec_dp_bridge_hpd_notify()
gets called due to port 1 at the same time?
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 06/18] drm/bridge: aux-hpd: Support USB Type-C DP altmodes via DRM lane assignment
2024-09-03 22:20 ` Stephen Boyd
@ 2024-09-04 13:00 ` Andy Shevchenko
2024-09-04 17:17 ` Stephen Boyd
0 siblings, 1 reply; 60+ messages in thread
From: Andy Shevchenko @ 2024-09-04 13:00 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, Dmitry Baryshkov,
dri-devel, Guenter Roeck, Jernej Skrabec, Jonas Karlman,
Krzysztof Kozlowski, Laurent Pinchart, Lee Jones,
Maarten Lankhorst, Maxime Ripard, Neil Armstrong, Prashant Malani,
Robert Foss, Rob Herring, Thomas Zimmermann, Tzung-Bi Shih,
Alexandre Belloni, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
On Tue, Sep 03, 2024 at 06:20:14PM -0400, Stephen Boyd wrote:
> Quoting Andy Shevchenko (2024-09-02 04:35:46)
> > On Sat, Aug 31, 2024 at 09:06:44PM -0700, Stephen Boyd wrote:
> > > Extend the aux-hpd bridge driver to support assigning DP lanes to USB
> > > type-c pins based on typec mux state entry. Existing users of this
> > > driver only need the HPD signaling support, so leave that in place and
> > > wrap the code with a variant that supports more features of USB type-c
> >
> > Isn't the proper spelling "USB Type-C"?
>
> Perhaps in a title?
I am talking about the commit message :-)
> > > DP altmode, i.e. pin configurations. Prefix that code with
> > > 'drm_dp_typec_bridge' to differentiate it from the existing
> > > 'drm_aux_hpd_bridge' code.
> > >
> > > Parse the struct typec_mux_state members to determine if DP altmode has
> > > been entered and if HPD is asserted or not. Signal HPD to the drm bridge
> > > chain when HPD is asserted. Similarly, parse the pin assignment and map
> > > the DP lanes to the usb-c output lanes, taking into account any lane
> > > remapping from the data-lanes endpoint property. Pass that lane mapping
> > > to the previous drm_bridge in the bridge chain during the atomic check
> > > phase.
...
> > > + adev->dev.of_node = of_node_get(parent->of_node);
> >
> > device_set_node() ?
>
> Or device_set_of_node_from_dev()?
This is quite unclear to me. The second one bumps the reference count IIRC
for no reason (in usual cases). Also only few drivers use that, I would hear
what OF people can tell about this API and its usage scope.
...
> > > +static int dp_lane_to_typec_lane(enum dp_lane lane)
> > > +{
> > > + switch (lane) {
> > > + case DP_ML0:
> > > + return USB_SSTX2;
> > > + case DP_ML1:
> > > + return USB_SSRX2;
> > > + case DP_ML2:
> > > + return USB_SSTX1;
> > > + case DP_ML3:
> > > + return USB_SSRX1;
> > > + }
> >
> > > + return -EINVAL;
> >
> > Hmm... This can be simply made as default case.
>
> And then the enum is always "covered" and the compiler doesn't complain
> about missing cases (I don't think we have -Wswitch-enum)? Seems worse.
Hmm... You mean if I remove one of the above cases I will get the warning?
> > > +}
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 06/18] drm/bridge: aux-hpd: Support USB Type-C DP altmodes via DRM lane assignment
2024-09-04 13:00 ` Andy Shevchenko
@ 2024-09-04 17:17 ` Stephen Boyd
0 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2024-09-04 17:17 UTC (permalink / raw)
To: Andy Shevchenko
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, Dmitry Baryshkov,
dri-devel, Guenter Roeck, Jernej Skrabec, Jonas Karlman,
Krzysztof Kozlowski, Laurent Pinchart, Lee Jones,
Maarten Lankhorst, Maxime Ripard, Neil Armstrong, Prashant Malani,
Robert Foss, Rob Herring, Thomas Zimmermann, Tzung-Bi Shih,
Alexandre Belloni, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
Quoting Andy Shevchenko (2024-09-04 06:00:57)
> On Tue, Sep 03, 2024 at 06:20:14PM -0400, Stephen Boyd wrote:
> > Quoting Andy Shevchenko (2024-09-02 04:35:46)
> > > On Sat, Aug 31, 2024 at 09:06:44PM -0700, Stephen Boyd wrote:
>
> > > > + adev->dev.of_node = of_node_get(parent->of_node);
> > >
> > > device_set_node() ?
> >
> > Or device_set_of_node_from_dev()?
>
> This is quite unclear to me. The second one bumps the reference count IIRC
> for no reason (in usual cases). Also only few drivers use that, I would hear
> what OF people can tell about this API and its usage scope.
Sure, but to be equivalent to the existing code from which this has been
copied it should use device_set_of_node_from_dev(). Seems fine to just
use that.
> > > > +static int dp_lane_to_typec_lane(enum dp_lane lane)
> > > > +{
> > > > + switch (lane) {
> > > > + case DP_ML0:
> > > > + return USB_SSTX2;
> > > > + case DP_ML1:
> > > > + return USB_SSRX2;
> > > > + case DP_ML2:
> > > > + return USB_SSTX1;
> > > > + case DP_ML3:
> > > > + return USB_SSRX1;
> > > > + }
> > >
> > > > + return -EINVAL;
> > >
> > > Hmm... This can be simply made as default case.
> >
> > And then the enum is always "covered" and the compiler doesn't complain
> > about missing cases (I don't think we have -Wswitch-enum)? Seems worse.
>
> Hmm... You mean if I remove one of the above cases I will get the warning?
>
Yes.
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 18/18] platform/chrome: cros_ec_typec: Handle lack of HPD information
2024-09-04 9:36 ` Tzung-Bi Shih
@ 2024-09-04 21:45 ` Stephen Boyd
2024-09-06 8:18 ` Tzung-Bi Shih
0 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-09-04 21:45 UTC (permalink / raw)
To: Tzung-Bi Shih
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, Dmitry Baryshkov,
dri-devel, Guenter Roeck, Jernej Skrabec, Jonas Karlman,
Krzysztof Kozlowski, Laurent Pinchart, Lee Jones,
Maarten Lankhorst, Maxime Ripard, Neil Armstrong, Prashant Malani,
Robert Foss, Rob Herring, Thomas Zimmermann, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
Quoting Tzung-Bi Shih (2024-09-04 02:36:45)
> On Sat, Aug 31, 2024 at 09:06:56PM -0700, Stephen Boyd wrote:
> > +static void cros_typec_inject_hpd(struct cros_typec_data *typec,
> > + struct ec_response_usb_pd_mux_info *resp,
> > + struct cros_typec_port *port)
> > +{
> [...]
> > + /*
> > + * Only read the mux GPIO setting if we need to change the active port.
> > + * Otherwise, an active port is already set and HPD going high or low
> > + * doesn't change the muxed port until DP mode is exited.
> > + */
> > + if (!typec->active_dp_port) {
>
> Given that cros_typec_inject_hpd() is called before `typec->active_dp_port`
> would be set (from previous patch "platform/chrome: ... Support DP muxing"),
> would it possibly wrongly fall into here at the beginning? (E.g.:
> cros_typec_probe() -> cros_typec_port_update() -> cros_typec_configure_mux()
> -> cros_typec_inject_hpd().)
We wouldn't get here if 'hpd_asserted' is false though. We want to fall
into this case in the beginning, i.e. 'active_dp_port' is NULL, so that
we can read the mux and figure out which port is actually selected.
If we don't have a mux gpio we assume that we aren't muxing and that
there's only one port to begin with. I'll add a comment after the if
(mux_gpio) condition with this info.
>
> > [...]
> > + /* Inject HPD from the GPIO state if EC firmware is broken. */
> > + if (typec->hpd_asserted)
> > + resp->flags |= USB_PD_MUX_HPD_LVL;
>
> `typec->hpd_asserted` is shared between all typec->ports[...]. Would it be
> possible that a HPD is asserted for another port but not current `port`?
> E.g.: cros_typec_inject_hpd() for port 2 and cros_typec_dp_bridge_hpd_notify()
> gets called due to port 1 at the same time?
I'd like to avoid synchronizing the hpd notify and this injection code,
if that's what you're asking. Thinking about this though, I've realized
that it's broken even when HPD is working on the EC. Consider this
scenario with two type-c ports C0 and C1:
Plug in C1
EC notifies AP
AP queues cros_typec_port_work()
HPD asserted
EC picks C1 for DP // First to have hpd asserted
EC notifies AP
AP tries to queue cros_typec_port_work() but it's pending. Skip.
Plug in C0
EC notifies AP
AP tries to queue cros_typec_port_work() but it's pending. Skip.
HPD asserted
EC notifies AP
AP tries to queue cros_typec_port_work() but it's pending. Skip.
Finally cros_typec_port_work() runs!
for (i = 0; i < typec->num_ports; i++) // typec->num_ports = 2
cros_typec_port_update(port_num=0)
cros_ec_cmd(EC_CMD_USB_PD_CONTROL.port=0) // In DP mode
cros_typec_configure_mux(port_num=0)
cros_ec_cmd(EC_CMD_USB_PD_MUX_INFO.port=0) // hpd asserted
if (!active_dp_port)
active_dp_port = port0
This is bad. The worker could be significantly delayed, although it's
really unlikely in practice. It would be better if the EC pushed a
message to AP about what happened, instead of having to query the EC
about the state of USB. Or the EC could have a sequence number or
something so AP could ask for the history of events. We can't fix all
the EC firmwares though, so we get what we get.
I think one solution would be to read the mux all the time and ignore
tracking the active port based on hpd state. If we do that then we don't
get tripped up by a delayed work iterating over both typec ports. The
logic will be a bit more complicated though, because we'll have to
consider all the ports when entering and exiting DP mode on one port so
that we don't assign DP to the wrong port.
Also, when hpd is broken on the EC I see an error message when I unplug
the DP cable. It's the "No valid DP mode provided." error from
cros_typec_enable_dp(). When I inject hpd that error goes away. I'll
need to look closer to understand why, but I suspect I'll need to keep
injecting hpd to avoid it.
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 18/18] platform/chrome: cros_ec_typec: Handle lack of HPD information
2024-09-04 21:45 ` Stephen Boyd
@ 2024-09-06 8:18 ` Tzung-Bi Shih
2024-09-06 23:22 ` Stephen Boyd
0 siblings, 1 reply; 60+ messages in thread
From: Tzung-Bi Shih @ 2024-09-06 8:18 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, Dmitry Baryshkov,
dri-devel, Guenter Roeck, Jernej Skrabec, Jonas Karlman,
Krzysztof Kozlowski, Laurent Pinchart, Lee Jones,
Maarten Lankhorst, Maxime Ripard, Neil Armstrong, Prashant Malani,
Robert Foss, Rob Herring, Thomas Zimmermann, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
On Wed, Sep 04, 2024 at 02:45:36PM -0700, Stephen Boyd wrote:
> Quoting Tzung-Bi Shih (2024-09-04 02:36:45)
> > On Sat, Aug 31, 2024 at 09:06:56PM -0700, Stephen Boyd wrote:
> > > +static void cros_typec_inject_hpd(struct cros_typec_data *typec,
> > > + struct ec_response_usb_pd_mux_info *resp,
> > > + struct cros_typec_port *port)
> > > +{
> > [...]
> > > + /*
> > > + * Only read the mux GPIO setting if we need to change the active port.
> > > + * Otherwise, an active port is already set and HPD going high or low
> > > + * doesn't change the muxed port until DP mode is exited.
> > > + */
> > > + if (!typec->active_dp_port) {
> >
> > Given that cros_typec_inject_hpd() is called before `typec->active_dp_port`
> > would be set (from previous patch "platform/chrome: ... Support DP muxing"),
> > would it possibly wrongly fall into here at the beginning? (E.g.:
> > cros_typec_probe() -> cros_typec_port_update() -> cros_typec_configure_mux()
> > -> cros_typec_inject_hpd().)
>
> We wouldn't get here if 'hpd_asserted' is false though. We want to fall
Ack, I overlooked that.
> > > [...]
> > > + /* Inject HPD from the GPIO state if EC firmware is broken. */
> > > + if (typec->hpd_asserted)
> > > + resp->flags |= USB_PD_MUX_HPD_LVL;
> >
> > `typec->hpd_asserted` is shared between all typec->ports[...]. Would it be
> > possible that a HPD is asserted for another port but not current `port`?
> > E.g.: cros_typec_inject_hpd() for port 2 and cros_typec_dp_bridge_hpd_notify()
> > gets called due to port 1 at the same time?
>
> I'd like to avoid synchronizing the hpd notify and this injection code,
> if that's what you're asking. Thinking about this though, I've realized
> that it's broken even when HPD is working on the EC. Consider this
> scenario with two type-c ports C0 and C1:
>
> [...]
I understood it more: originally, I was wondering if it needs an array
`typec->hpd_asserted[...]` for storing HPD for each port. But, no.
What cros_typec_dp_bridge_hpd_notify() get is just a connected/disconnected
signal. It kicks off cros_typec_port_work() for finding which port is
supposed to trigger the event (with some logic with `active_dp_port`,
`mux_gpio`, and `hpd_asserted`).
Curious about one more scenario, is it possible:
Initially, no DP port and no mux is using:
active_dp_port = NULL
hpd_asserted = false
mux_gpio = NULL
CPU A CPU B
------------------------------------------------------------------------------
cros_typec_port_work()
cros_typec_port_update(port_num=0)
[C0 connected]
cros_typec_dp_bridge_hpd_notify()
hpd_asserted = true
cros_typec_port_update(port_num=1)
cros_typec_configure_mux(port_num=1)
cros_typec_inject_hpd()
active_dp_port = C1
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 18/18] platform/chrome: cros_ec_typec: Handle lack of HPD information
2024-09-06 8:18 ` Tzung-Bi Shih
@ 2024-09-06 23:22 ` Stephen Boyd
0 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2024-09-06 23:22 UTC (permalink / raw)
To: Tzung-Bi Shih
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, Dmitry Baryshkov,
dri-devel, Guenter Roeck, Jernej Skrabec, Jonas Karlman,
Krzysztof Kozlowski, Laurent Pinchart, Lee Jones,
Maarten Lankhorst, Maxime Ripard, Neil Armstrong, Prashant Malani,
Robert Foss, Rob Herring, Thomas Zimmermann, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
Quoting Tzung-Bi Shih (2024-09-06 01:18:21)
> On Wed, Sep 04, 2024 at 02:45:36PM -0700, Stephen Boyd wrote:
> > Quoting Tzung-Bi Shih (2024-09-04 02:36:45)
> > > On Sat, Aug 31, 2024 at 09:06:56PM -0700, Stephen Boyd wrote:
> > > > + /* Inject HPD from the GPIO state if EC firmware is broken. */
> > > > + if (typec->hpd_asserted)
> > > > + resp->flags |= USB_PD_MUX_HPD_LVL;
> > >
> > > `typec->hpd_asserted` is shared between all typec->ports[...]. Would it be
> > > possible that a HPD is asserted for another port but not current `port`?
> > > E.g.: cros_typec_inject_hpd() for port 2 and cros_typec_dp_bridge_hpd_notify()
> > > gets called due to port 1 at the same time?
> >
> > I'd like to avoid synchronizing the hpd notify and this injection code,
> > if that's what you're asking. Thinking about this though, I've realized
> > that it's broken even when HPD is working on the EC. Consider this
> > scenario with two type-c ports C0 and C1:
> >
> > [...]
>
> I understood it more: originally, I was wondering if it needs an array
> `typec->hpd_asserted[...]` for storing HPD for each port. But, no.
>
> What cros_typec_dp_bridge_hpd_notify() get is just a connected/disconnected
> signal. It kicks off cros_typec_port_work() for finding which port is
> supposed to trigger the event (with some logic with `active_dp_port`,
> `mux_gpio`, and `hpd_asserted`).
Ok, cool. I intend to split this device into multiple devices, one per
DP bridge. I haven't done that though because I don't have any device
that has two independent DP controllers.
>
>
> Curious about one more scenario, is it possible:
>
> Initially, no DP port and no mux is using:
> active_dp_port = NULL
> hpd_asserted = false
> mux_gpio = NULL
>
> CPU A CPU B
> ------------------------------------------------------------------------------
> cros_typec_port_work()
> cros_typec_port_update(port_num=0)
> [C0 connected]
> cros_typec_dp_bridge_hpd_notify()
> hpd_asserted = true
The work is queued again here because it's already running.
> cros_typec_port_update(port_num=1)
> cros_typec_configure_mux(port_num=1)
> cros_typec_inject_hpd()
> active_dp_port = C1
Yeah it's a problem because we need to read the mux_gpio to figure out
which way it's steering. We can't recreate the "first to assert HPD"
logic that the EC has because we can't control when the worker runs. At
least we can skip reading the mux if only one port has entered DP mode.
I'm hoping that the scenario where both ports are in DP mode almost
never happens, but if it does then we'll have to read the mux when hpd
is asserted to figure out which port DP is muxed to.
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 03/18] usb: typec: Stub out typec_switch APIs when CONFIG_TYPEC=n
2024-09-01 4:06 ` [PATCH v4 03/18] usb: typec: Stub out typec_switch APIs when CONFIG_TYPEC=n Stephen Boyd
2024-09-03 11:40 ` Heikki Krogerus
@ 2024-09-19 10:12 ` Dmitry Baryshkov
1 sibling, 0 replies; 60+ messages in thread
From: Dmitry Baryshkov @ 2024-09-19 10:12 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
On Sat, Aug 31, 2024 at 09:06:41PM GMT, Stephen Boyd wrote:
> Ease driver development by adding stubs for the typec_switch APIs when
> CONFIG_TYPEC=n. Copy the same method used for the typec_mux APIs to be
> consistent.
>
> Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: <linux-usb@vger.kernel.org>
> Cc: Pin-yen Lin <treapking@chromium.org>
> Signed-off-by: Stephen Boyd <swboyd@chromium.org>
> ---
> include/linux/usb/typec_mux.h | 43 +++++++++++++++++++++++++++++++----
> 1 file changed, 38 insertions(+), 5 deletions(-)
>
> diff --git a/include/linux/usb/typec_mux.h b/include/linux/usb/typec_mux.h
> index 2489a7857d8e..efb5ed32b813 100644
> --- a/include/linux/usb/typec_mux.h
> +++ b/include/linux/usb/typec_mux.h
> @@ -3,6 +3,7 @@
> #ifndef __USB_TYPEC_MUX
> #define __USB_TYPEC_MUX
>
> +#include <linux/err.h>
> #include <linux/property.h>
> #include <linux/usb/typec.h>
>
> @@ -24,16 +25,13 @@ struct typec_switch_desc {
> void *drvdata;
> };
>
> +#if IS_ENABLED(CONFIG_TYPEC)
> +
> struct typec_switch *fwnode_typec_switch_get(struct fwnode_handle *fwnode);
> void typec_switch_put(struct typec_switch *sw);
> int typec_switch_set(struct typec_switch *sw,
> enum typec_orientation orientation);
>
> -static inline struct typec_switch *typec_switch_get(struct device *dev)
> -{
> - return fwnode_typec_switch_get(dev_fwnode(dev));
> -}
> -
> struct typec_switch_dev *
> typec_switch_register(struct device *parent,
> const struct typec_switch_desc *desc);
> @@ -42,6 +40,41 @@ void typec_switch_unregister(struct typec_switch_dev *sw);
> void typec_switch_set_drvdata(struct typec_switch_dev *sw, void *data);
> void *typec_switch_get_drvdata(struct typec_switch_dev *sw);
>
> +#else
> +
> +static inline struct typec_switch *
> +fwnode_typec_switch_get(struct fwnode_handle *fwnode)
> +{
> + return NULL;
> +}
> +static inline void typec_switch_put(struct typec_switch *sw) {}
> +static inline int typec_switch_set(struct typec_switch *sw,
> + enum typec_orientation orientation)
> +{
> + return 0;
> +}
Just my 2c:
The stubs above look fine from my POV, they help us to cleanup the users
of the API. The register/unregister callbacks are not. The switch
providers should clearly know whether the API is actually available or
not. Compare this to how other subsystems (regulators, interconnects,
etc) provide stubs for consumer API only.
In other words, please consider sending a patch that drops provider-side
Type-C MUX API stubs.
> +
> +static inline struct typec_switch_dev *
> +typec_switch_register(struct device *parent,
> + const struct typec_switch_desc *desc)
> +{
> + return ERR_PTR(-EOPNOTSUPP);
> +}
> +static inline void typec_switch_unregister(struct typec_switch_dev *sw) {}
> +
> +static inline void typec_switch_set_drvdata(struct typec_switch_dev *sw, void *data) {}
> +static inline void *typec_switch_get_drvdata(struct typec_switch_dev *sw)
> +{
> + return ERR_PTR(-EOPNOTSUPP);
> +}
> +
> +#endif /* CONFIG_TYPEC */
> +
> +static inline struct typec_switch *typec_switch_get(struct device *dev)
> +{
> + return fwnode_typec_switch_get(dev_fwnode(dev));
> +}
> +
> struct typec_mux_state {
> struct typec_altmode *alt;
> unsigned long mode;
> --
> https://chromeos.dev
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 13/18] dt-bindings: usb-switch: Extend for DisplayPort altmode
2024-09-01 4:06 ` [PATCH v4 13/18] dt-bindings: usb-switch: Extend for DisplayPort altmode Stephen Boyd
@ 2024-09-19 10:40 ` Dmitry Baryshkov
2024-10-10 22:43 ` Stephen Boyd
0 siblings, 1 reply; 60+ messages in thread
From: Dmitry Baryshkov @ 2024-09-19 10:40 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring (Arm)
On Sat, Aug 31, 2024 at 09:06:51PM GMT, Stephen Boyd wrote:
> Extend the usb-switch binding to support DisplayPort (DP) alternate
> modes. A third port for the DP signal is necessary when a mode-switch is
> muxing USB and DP together onto a usb type-c connector. Add data-lanes
> to the usbc output node to allow a device using this binding to remap
> the data lanes on the output. Add an example to show how this new port
> can be used.
>
> Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
> Cc: Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>
> Cc: Conor Dooley <conor+dt@kernel.org>
> Cc: Benson Leung <bleung@chromium.org>
> Cc: Guenter Roeck <groeck@chromium.org>
> Cc: Prashant Malani <pmalani@chromium.org>
> Cc: Tzung-Bi Shih <tzungbi@kernel.org>
> Cc: <devicetree@vger.kernel.org>
> Cc: <chrome-platform@lists.linux.dev>
> Cc: Pin-yen Lin <treapking@chromium.org>
> Signed-off-by: Stephen Boyd <swboyd@chromium.org>
> ---
> .../devicetree/bindings/usb/usb-switch.yaml | 89 +++++++++++++++++++
> 1 file changed, 89 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/usb/usb-switch.yaml b/Documentation/devicetree/bindings/usb/usb-switch.yaml
> index f5dc7e23b134..816f295f322f 100644
> --- a/Documentation/devicetree/bindings/usb/usb-switch.yaml
> +++ b/Documentation/devicetree/bindings/usb/usb-switch.yaml
> @@ -52,6 +52,14 @@ properties:
> endpoint:
> $ref: '#/$defs/usbc-in-endpoint'
>
> + port@2:
> + $ref: /schemas/graph.yaml#/$defs/port-base
> + unevaluatedProperties: false
> +
> + properties:
> + endpoint:
> + $ref: '#/$defs/dp-endpoint'
Is it a separate port or is it an endpoint of the same upstream-facing
(non-connector-facing) SS port?
> +
> oneOf:
> - required:
> - port
> @@ -65,6 +73,19 @@ $defs:
> $ref: /schemas/graph.yaml#/$defs/endpoint-base
> description: Super Speed (SS) output endpoint to a type-c connector
> unevaluatedProperties: false
> + properties:
> + data-lanes:
> + $ref: /schemas/types.yaml#/definitions/uint32-array
> + description: |
> + An array of physical USB Type-C data lane indexes.
> + - 0 is SSRX1 lane
> + - 1 is SSTX1 lane
> + - 2 is SSTX2 lane
> + - 3 is SSRX2 lane
> + minItems: 4
> + maxItems: 4
> + items:
> + maximum: 3
What is the usecase to delare less than 4 lanes going to the USB-C
connector?
>
> usbc-in-endpoint:
> $ref: /schemas/graph.yaml#/$defs/endpoint-base
> @@ -79,7 +100,75 @@ $defs:
> items:
> maximum: 8
>
> + dp-endpoint:
> + $ref: /schemas/graph.yaml#/$defs/endpoint-base
> + description: DisplayPort (DP) input from the DP PHY
> + unevaluatedProperties: false
> + properties:
> + data-lanes:
> + $ref: /schemas/types.yaml#/definitions/uint32-array
> + description: |
> + An array of physical DP data lane indexes
> + - 0 is DP ML0 lane
> + - 1 is DP ML1 lane
> + - 2 is DP ML2 lane
> + - 3 is DP ML3 lane
> + oneOf:
> + - items:
> + - const: 0
> + - const: 1
> + - items:
> + - const: 0
> + - const: 1
> + - const: 2
> + - const: 3
> +
> examples:
> + # A USB + DP mode and orientation switch which muxes DP altmode
> + # and USB onto a usb-c-connector node.
> + - |
> + device {
> + mode-switch;
> + orientation-switch;
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + endpoint {
> + remote-endpoint = <&usb_c_connector>;
> + data-lanes = <0 1 2 3>;
> + };
> + };
> +
> + port@1 {
> + reg = <1>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + endpoint {
> + remote-endpoint = <&usb_ss_phy>;
> + };
> + };
> +
> + port@2 {
> + reg = <2>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + endpoint {
> + remote-endpoint = <&dp_phy>;
> + data-lanes = <0 1 2 3>;
> + };
> + };
> + };
> + };
> +
> # A USB orientation switch which flips the pin orientation
> # for a usb-c-connector node.
> - |
> --
> https://chromeos.dev
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
2024-09-01 4:06 ` [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode Stephen Boyd
2024-09-03 15:35 ` Lee Jones
@ 2024-09-20 9:38 ` Dmitry Baryshkov
2024-10-23 1:15 ` Stephen Boyd
1 sibling, 1 reply; 60+ messages in thread
From: Dmitry Baryshkov @ 2024-09-20 9:38 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring (Arm)
On Sat, Aug 31, 2024 at 09:06:53PM GMT, Stephen Boyd wrote:
> Add a DT graph binding to google,cros-ec-typec so that it can combine
> DisplayPort (DP) and USB SuperSpeed (SS) data into a USB type-c endpoint
> that is connected to the usb-c-connector node's SS endpoint. This also
> allows us to connect the DP and USB nodes in the graph to the USB type-c
> connectors, providing the full picture of the USB type-c data flows in
> the system.
>
> Allow there to be multiple typec nodes underneath the EC node so that
> one DT graph exists per DP bridge. The EC is actually controlling TCPCs
> and redrivers that combine the DP and USB signals together so this more
> accurately reflects the hardware design without introducing yet another
> DT node underneath the EC for USB type-c.
>
> If the type-c ports are being shared between a single DP controller then
> the ports need to know about each other and determine a policy to drive
> DP to one type-c port. If the type-c ports each have their own dedicated
> DP controller then they're able to operate independently and enter/exit
> DP altmode independently as well. We can't connect the DP controller's
> endpoint to one usb-c-connector port@1 endpoint and the USB controller's
> endpoint to another usb-c-connector port@1 endpoint either because the
> DP muxing case would have DP connected to two usb-c-connector endpoints
> which the graph binding doesn't support.
>
> Therefore, one typec node is required per the capabilities of the type-c
> port(s) being managed. This also lets us indicate which type-c ports the
> DP controller is wired to. For example, if DP was connected to ports 0
> and 2, while port 1 was connected to another DP controller we wouldn't
> be able to implement that without having some other DT property to
> indicate which output ports are connected to the DP endpoint.
Based on our disccusions at LPC, here are several DT examples that seem
sensible to implement this case and several related cases from other
ChromeBooks.
typec {
compatible = "google,cros-ec-typec";
port {
typec_dp_in: endpoint {
remote-endpoint = <&usb_1_qmp_phy_out_dp>;
};
};
usb_c0: connector@0 {
compatible = "usb-c-connector";
reg = <0>;
ports {
port@0 {
reg = <0>;
usb_c0_hs_in: endpoint {
remote-endpoint = <&usb_hub_dfp1_hs>;
};
};
port@1 {
reg = <1>;
usb_c0_ss_in: endpoint {
remote-endpoint = <&usb_hub_dfp1_ss>;
};
};
};
};
usb_c1: connector@1 {
compatible = "usb-c-connector";
reg = <1>;
ports {
port@0 {
reg = <0>;
usb_c1_hs_in: endpoint {
remote-endpoint = <&usb_hub_dfp2_hs>;
};
};
port@1 {
reg = <1>;
usb_c1_ss_in: endpoint {
remote-endpoint = <&usb_hub_dfp2_ss>;
};
};
};
};
};
&usb_1_qmpphy {
ports {
port@0 {
endpoint@0 {
data-lanes = <0 1>;
// this might go to USB-3 hub
};
usb_1_qmp_phy_out_dp: endpoint@1 {
remote-endpoint = <&typec_dp_in>;
data-lanes = <2 3>;
};
}
};
};
-------
typec {
connector@0 {
port@1 {
endpoint@0 {
remtoe = <&usb_hub_0>;
};
endpoint@1 {
remote = <&dp_bridge_out_0>;
};
};
};
connector@1 {
port@1 {
endpoint@0 {
remtoe = <&usb_hub_1>;
};
endpoint@1 {
remote = <&dp_bridge_out_1>;
};
};
};
};
dp_bridge {
ports {
port@1 {
dp_bridge_out_0: endpoint@0 {
remote = <usb_c0_ss_dp>;
data-lanes = <0 1>;
};
dp_bridge_out_1: endpoint@1 {
remote = <usb_c1_ss_dp>;
data-lanes = <2 3>;
};
};
};
};
-------
This one is really tough example, we didn't reach a conclusion here.
If the EC doesn't handle lane remapping, dp_bridge has to get
orientation-switch and mode-switch properties (as in the end it is the
dp_bridge that handles reshuffling of the lanes for the Type-C). Per the
DisplayPort standard the lanes are fixed (e.g. DPCD 101h explicitly
names lane 0, lanes 0-1, lanes 0-1-2-3).
typec {
connector@0 {
port@1 {
endpoint@0 {
remtoe = <&usb_hub_0>;
};
endpoint@1 {
remote = <&dp_bridge_out_0>;
};
};
};
};
dp_bridge {
orientation-switch;
mode-switch;
ports {
port@1 {
dp_bridge_out_0: endpoint {
remote = <usb_c0_ss_dp>;
data-lanes = <0 1 2 3>;
};
};
};
};
-------
> Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
> Cc: Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>
> Cc: Conor Dooley <conor+dt@kernel.org>
> Acked-by: Lee Jones <lee@kernel.org>
> Cc: Benson Leung <bleung@chromium.org>
> Cc: Guenter Roeck <groeck@chromium.org>
> Cc: Prashant Malani <pmalani@chromium.org>
> Cc: Tzung-Bi Shih <tzungbi@kernel.org>
> Cc: <devicetree@vger.kernel.org>
> Cc: <chrome-platform@lists.linux.dev>
> Cc: Pin-yen Lin <treapking@chromium.org>
> Signed-off-by: Stephen Boyd <swboyd@chromium.org>
> ---
> .../bindings/mfd/google,cros-ec.yaml | 7 +-
> .../bindings/usb/google,cros-ec-typec.yaml | 229 ++++++++++++++++++
> 2 files changed, 233 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
> index c991626dc22b..bbe28047d0c0 100644
> --- a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
> +++ b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
> @@ -98,9 +98,6 @@ properties:
>
> gpio-controller: true
>
> - typec:
> - $ref: /schemas/usb/google,cros-ec-typec.yaml#
> -
> ec-pwm:
> $ref: /schemas/pwm/google,cros-ec-pwm.yaml#
> deprecated: true
> @@ -166,6 +163,10 @@ patternProperties:
> type: object
> $ref: /schemas/extcon/extcon-usbc-cros-ec.yaml#
>
> + "^typec(-[0-9])*$":
> + type: object
> + $ref: /schemas/usb/google,cros-ec-typec.yaml#
> +
> required:
> - compatible
>
> diff --git a/Documentation/devicetree/bindings/usb/google,cros-ec-typec.yaml b/Documentation/devicetree/bindings/usb/google,cros-ec-typec.yaml
> index 365523a63179..235b86da3cdd 100644
> --- a/Documentation/devicetree/bindings/usb/google,cros-ec-typec.yaml
> +++ b/Documentation/devicetree/bindings/usb/google,cros-ec-typec.yaml
> @@ -26,6 +26,106 @@ properties:
> '#size-cells':
> const: 0
>
> + mux-gpios:
> + description: GPIOs indicating which way the DP mux is steered
> + maxItems: 1
> +
> + no-hpd:
> + description: Indicates this endpoint doesn't signal HPD for DisplayPort
> + type: boolean
> +
> + mode-switch:
> + $ref: usb-switch.yaml#properties/mode-switch
> +
> + orientation-switch:
> + $ref: usb-switch.yaml#properties/orientation-switch
> +
> + ports:
> + $ref: /schemas/graph.yaml#/properties/ports
> +
> + properties:
> + port@0:
> + $ref: /schemas/graph.yaml#/$defs/port-base
> + unevaluatedProperties: false
> + description: Output ports for combined DP and USB SS data
> + patternProperties:
> + "^endpoint@([0-8])$":
> + $ref: usb-switch.yaml#/$defs/usbc-out-endpoint
> + unevaluatedProperties: false
> +
> + anyOf:
> + - required:
> + - endpoint@0
> + - required:
> + - endpoint@1
> + - required:
> + - endpoint@2
> + - required:
> + - endpoint@3
> + - required:
> + - endpoint@4
> + - required:
> + - endpoint@5
> + - required:
> + - endpoint@6
> + - required:
> + - endpoint@7
> + - required:
> + - endpoint@8
> +
> + port@1:
> + $ref: /schemas/graph.yaml#/$defs/port-base
> + unevaluatedProperties: false
> + description:
> + Input port to receive USB SuperSpeed (SS) data
> + patternProperties:
> + "^endpoint@([0-8])$":
> + $ref: usb-switch.yaml#/$defs/usbc-in-endpoint
> + unevaluatedProperties: false
> +
> + anyOf:
> + - required:
> + - endpoint@0
> + - required:
> + - endpoint@1
> + - required:
> + - endpoint@2
> + - required:
> + - endpoint@3
> + - required:
> + - endpoint@4
> + - required:
> + - endpoint@5
> + - required:
> + - endpoint@6
> + - required:
> + - endpoint@7
> + - required:
> + - endpoint@8
> +
> + port@2:
> + $ref: /schemas/graph.yaml#/$defs/port-base
> + description:
> + Input port to receive DisplayPort (DP) data
> + unevaluatedProperties: false
> +
> + properties:
> + endpoint:
> + $ref: usb-switch.yaml#/$defs/dp-endpoint
> + unevaluatedProperties: false
> +
> + required:
> + - endpoint
> +
> + required:
> + - port@0
> +
> + anyOf:
> + - required:
> + - port@1
> + - required:
> + - port@2
> +
> patternProperties:
> '^connector@[0-9a-f]+$':
> $ref: /schemas/connector/usb-connector.yaml#
> @@ -35,6 +135,40 @@ patternProperties:
> required:
> - compatible
>
> +allOf:
> + - if:
> + required:
> + - no-hpd
> + then:
> + properties:
> + ports:
> + required:
> + - port@2
> + - if:
> + required:
> + - mux-gpios
> + then:
> + properties:
> + ports:
> + required:
> + - port@2
> + - if:
> + required:
> + - orientation-switch
> + then:
> + properties:
> + ports:
> + required:
> + - port@2
> + - if:
> + required:
> + - mode-switch
> + then:
> + properties:
> + ports:
> + required:
> + - port@2
> +
> additionalProperties: false
>
> examples:
> @@ -50,6 +184,8 @@ examples:
>
> typec {
> compatible = "google,cros-ec-typec";
> + orientation-switch;
> + mode-switch;
>
> #address-cells = <1>;
> #size-cells = <0>;
> @@ -60,6 +196,99 @@ examples:
> power-role = "dual";
> data-role = "dual";
> try-power-role = "source";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> + usb_c0_hs: endpoint {
> + remote-endpoint = <&usb_hub_dfp3_hs>;
> + };
> + };
> +
> + port@1 {
> + reg = <1>;
> + usb_c0_ss: endpoint {
> + remote-endpoint = <&cros_typec_c0_ss>;
> + };
> + };
> + };
> + };
> +
> + connector@1 {
> + compatible = "usb-c-connector";
> + reg = <1>;
> + power-role = "dual";
> + data-role = "dual";
> + try-power-role = "source";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> + usb_c1_hs: endpoint {
> + remote-endpoint = <&usb_hub_dfp2_hs>;
> + };
> + };
> +
> + port@1 {
> + reg = <1>;
> + usb_c1_ss: endpoint {
> + remote-endpoint = <&cros_typec_c1_ss>;
> + };
> + };
> + };
> + };
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + cros_typec_c0_ss: endpoint@0 {
> + reg = <0>;
> + remote-endpoint = <&usb_c0_ss>;
> + data-lanes = <0 1 2 3>;
> + };
> +
> + cros_typec_c1_ss: endpoint@1 {
> + reg = <1>;
> + remote-endpoint = <&usb_c1_ss>;
> + data-lanes = <2 3 0 1>;
> + };
> + };
> +
> + port@1 {
> + reg = <1>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + usb_in_0: endpoint@0 {
> + reg = <0>;
> + remote-endpoint = <&usb_ss_0_out>;
> + };
> +
> + usb_in_1: endpoint@1 {
> + reg = <1>;
> + remote-endpoint = <&usb_ss_1_out>;
> + };
> + };
> +
> + port@2 {
> + reg = <2>;
> + dp_in: endpoint {
> + remote-endpoint = <&dp_phy>;
> + data-lanes = <0 1>;
> + };
> + };
> };
> };
> };
> --
> https://chromeos.dev
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 01/18] drm/atomic-helper: Introduce lane remapping support to bridges
2024-09-01 4:06 ` [PATCH v4 01/18] drm/atomic-helper: Introduce lane remapping support to bridges Stephen Boyd
@ 2024-09-20 13:41 ` Dmitry Baryshkov
0 siblings, 0 replies; 60+ messages in thread
From: Dmitry Baryshkov @ 2024-09-20 13:41 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul
On Sat, Aug 31, 2024 at 09:06:39PM GMT, Stephen Boyd wrote:
> Add support to the DRM atomic logic to support lane remapping between
> bridges, encoders and connectors. Typically lane mapping is handled
> statically in firmware, e.g. on DT we use the data-lanes property to
> assign lanes when connecting display bridges. Lane assignment is dynamic
> with USB-C DisplayPort altmodes, e.g. pin conf D assigns 2 lanes of DP
> to pins on the USB-C connector while pin conf C assigns 4 lanes of DP to
> pins on the USB-C connector. The lane assignment can't be set statically
> because the DP altmode repurposes USB-C pins for the DP lanes while also
> limiting the number of DP lanes or their pin assignment at runtime.
>
> Bridge drivers should point their 'struct drm_bus_cfg::lanes' pointer to
> an allocated array of 'struct drm_lane_cfg' structures and indicate the
> size of this allocated array with 'struct drm_bus_cfg::num_lanes' in
> their atomic_check() callback. The previous bridge in the bridge chain
> can look at this information by calling
> drm_bridge_next_bridge_lane_cfg() in their atomic_check() callback to
> figure out what lanes need to be logically assigned to the physical
> output lanes to satisfy the next bridge's lane assignment.
>
> Cc: Andrzej Hajda <andrzej.hajda@intel.com>
> Cc: Neil Armstrong <neil.armstrong@linaro.org>
> Cc: Robert Foss <rfoss@kernel.org>
> Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
> Cc: Jonas Karlman <jonas@kwiboo.se>
> Cc: Jernej Skrabec <jernej.skrabec@gmail.com>
> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Cc: Maxime Ripard <mripard@kernel.org>
> Cc: Thomas Zimmermann <tzimmermann@suse.de>
> Cc: David Airlie <airlied@gmail.com>
> Cc: Daniel Vetter <daniel@ffwll.ch>
> Cc: <dri-devel@lists.freedesktop.org>
> Cc: Pin-yen Lin <treapking@chromium.org>
> Cc: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> Signed-off-by: Stephen Boyd <swboyd@chromium.org>
> ---
> drivers/gpu/drm/drm_atomic_state_helper.c | 2 ++
> drivers/gpu/drm/drm_bridge.c | 34 +++++++++++++++++++++++
> include/drm/drm_atomic.h | 31 +++++++++++++++++++++
> include/drm/drm_bridge.h | 4 +++
> 4 files changed, 71 insertions(+)
I have given this a lot of thought in the last several days, thanks for
the interesting problem.
Basically, as I said during LPC, I feel that this is an overkill to be
handled in the drm_bridge layer. In most other usecases the lane
configuration is static and doesn't change. MIPI DSI standard, for
example, explicitly disallows that: "The number of Lanes used shall be a
static parameter. It shall be fixed at the time of system design or
initial configuration and may not change dynamically." (MIPI DSI 1.3,
section 6.1).
Following the struct drm_connector_hdmi introduction I think we are
getting closer and closer to the struct drm_connector_dp, which should
record all DP-related data to be used by DisplayPort connectors. An
example of a field in this struct-to-be might be `u8 num_lanes`. In the
normal DP / uDP cases it will be static, in case of USB-C AltMode it
will be dynamic and change depending on pinconf being configured.
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 13/18] dt-bindings: usb-switch: Extend for DisplayPort altmode
2024-09-19 10:40 ` Dmitry Baryshkov
@ 2024-10-10 22:43 ` Stephen Boyd
2024-10-25 6:36 ` Dmitry Baryshkov
0 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-10-10 22:43 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring
Quoting Dmitry Baryshkov (2024-09-19 03:40:19)
> On Sat, Aug 31, 2024 at 09:06:51PM GMT, Stephen Boyd wrote:
> > diff --git a/Documentation/devicetree/bindings/usb/usb-switch.yaml b/Documentation/devicetree/bindings/usb/usb-switch.yaml
> > index f5dc7e23b134..816f295f322f 100644
> > --- a/Documentation/devicetree/bindings/usb/usb-switch.yaml
> > +++ b/Documentation/devicetree/bindings/usb/usb-switch.yaml
> > @@ -52,6 +52,14 @@ properties:
> > endpoint:
> > $ref: '#/$defs/usbc-in-endpoint'
> >
> > + port@2:
> > + $ref: /schemas/graph.yaml#/$defs/port-base
> > + unevaluatedProperties: false
> > +
> > + properties:
> > + endpoint:
> > + $ref: '#/$defs/dp-endpoint'
>
> Is it a separate port or is it an endpoint of the same upstream-facing
> (non-connector-facing) SS port?
I don't quite follow this comment. This is an input DP endpoint/port.
>
> > +
> > oneOf:
> > - required:
> > - port
> > @@ -65,6 +73,19 @@ $defs:
> > $ref: /schemas/graph.yaml#/$defs/endpoint-base
> > description: Super Speed (SS) output endpoint to a type-c connector
> > unevaluatedProperties: false
> > + properties:
> > + data-lanes:
> > + $ref: /schemas/types.yaml#/definitions/uint32-array
> > + description: |
> > + An array of physical USB Type-C data lane indexes.
> > + - 0 is SSRX1 lane
> > + - 1 is SSTX1 lane
> > + - 2 is SSTX2 lane
> > + - 3 is SSRX2 lane
> > + minItems: 4
> > + maxItems: 4
> > + items:
> > + maximum: 3
>
> What is the usecase to delare less than 4 lanes going to the USB-C
> connector?
I'm not aware of any usecase. The 'maximum: 3' is the max value in the
cell, i.e. 0, 1, 2, or 3.
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
2024-09-20 9:38 ` Dmitry Baryshkov
@ 2024-10-23 1:15 ` Stephen Boyd
2024-10-25 10:49 ` Dmitry Baryshkov
0 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-10-23 1:15 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring
Quoting Dmitry Baryshkov (2024-09-20 02:38:53)
> On Sat, Aug 31, 2024 at 09:06:53PM GMT, Stephen Boyd wrote:
>
> Based on our disccusions at LPC, here are several DT examples that seem
> sensible to implement this case and several related cases from other
> ChromeBooks.
(Apologies for getting back to this late. I've been brewing on this topic
for a month; only appropriate for Halloween.)
This is the Trogdor case, one DP controller with 2 lanes DP coming out
that is steered with an analog mux controlled by the EC:
>
> typec {
> compatible = "google,cros-ec-typec";
>
> port {
> typec_dp_in: endpoint {
> remote-endpoint = <&usb_1_qmp_phy_out_dp>;
> };
> };
>
> usb_c0: connector@0 {
> compatible = "usb-c-connector";
> reg = <0>;
>
> ports {
> port@0 {
> reg = <0>;
> usb_c0_hs_in: endpoint {
> remote-endpoint = <&usb_hub_dfp1_hs>;
> };
> };
>
> port@1 {
> reg = <1>;
> usb_c0_ss_in: endpoint {
> remote-endpoint = <&usb_hub_dfp1_ss>;
> };
> };
> };
> };
>
> usb_c1: connector@1 {
> compatible = "usb-c-connector";
> reg = <1>;
>
> ports {
> port@0 {
> reg = <0>;
> usb_c1_hs_in: endpoint {
> remote-endpoint = <&usb_hub_dfp2_hs>;
> };
> };
>
> port@1 {
> reg = <1>;
> usb_c1_ss_in: endpoint {
> remote-endpoint = <&usb_hub_dfp2_ss>;
> };
> };
> };
> };
> };
>
> &usb_1_qmpphy {
> ports {
> port@0 {
> endpoint@0 {
> data-lanes = <0 1>;
> // this might go to USB-3 hub
> };
>
> usb_1_qmp_phy_out_dp: endpoint@1 {
> remote-endpoint = <&typec_dp_in>;
> data-lanes = <2 3>;
> };
> }
> };
> };
>
> -------
This is one Corsola case, one DP controller (IT6505) that's an external
bridge that has 4 lanes DP but only 2 lanes of DP are usable at a time
because 2 physical lanes are wired to one usb-c-connector while the
other 2 physical lanes are wired to the other usb-c-connector. I say
"one Corsola case" because there's also a DP bridge (ANX7625) on some
Corsola variants that only has two DP lanes with a crosspoint switch
that can send those DP lanes out of one of two pairs of lanes. The other
two lanes are for USB3 output data if the part is connected to USB3 on
the input side. I suspect this ANX7625 case can be described in the same
way as below with two output endpoints and data-lanes describing which
lanes are used for either DP endpoint.
>
> typec {
> connector@0 {
> port@1 {
> endpoint@0 {
> remtoe = <&usb_hub_0>;
> };
>
> endpoint@1 {
> remote = <&dp_bridge_out_0>;
> };
(TL;DR: I think I have a plan with the last paragraph in this section, so
I'll hack on it for a bit to see what happens.)
I'm not thrilled about having two endpoints in the SuperSpeed port@1 to
hold both signals in the Corsola case but not the Trogdor case. The
problem is that there's only one DP endpoint on Trogdor and we can't
have two remote-endpoint properties in there pointing to either
usb-c-connector. But then on Corsola we have two DP endpoints and they
both can't go to one DP input node in the typec node's graph.
To harmonize this the typec graph can have one DP input endpoint on
Trogdor while the typec graph can have two DP input endpoints on
Corsola. In both cases, the typec graph would have two USB input
endpoints, and then we can connect output endpoints to each
usb-c-connector node. It would be similar to my existing binding in this
series, except now the typec DP port can have multiple input endpoints.
I understand from our discussions at LPC that I should use
drm_connector_oob_hotplug_event() from the displayport altmode driver
(drivers/usb/typec/altmodes/displayport.c) to tell the DP bridge like
ANX7625 or IT6505 which output endpoint should be displaying DP. I think
dp_altmode_probe() looks at the usb-c-connector node's parent, e.g.
typec in the examples above, for the drm_bridge. That means we'll need
to register a drm_bridge in the cros-ec-typec compatible node? Or we
need to use the 'displayport' property in cros-ec-typec to point at the
drm_bridge node?
Either way the problem seems to be that I need to associate one
drm_bridge with two displayport altmode drivers and pass some fwnode
handle to drm_connector_oob_hotplug_event() in a way that we can map
that back to the right output endpoint in the DP bridge graph. That
seems to imply that we need to pass the fwnode for the usb-c-connector
in addition to the fwnode for the drm_bridge, so that the drm_bridge
code can look at its DT graph and find the remote node connected.
Basically something like this:
void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode,
struct fwnode_handle
*usb_connector_fwnode,
enum drm_connector_status status)
(We might as well also pass the number of lanes here)
Corsola could work with this design, but we'll need to teach
dp_altmode_probe() to look for the drm_bridge elsewhere besides as the
parent of the usb-c-connector node. That implies using the 'displayport'
property in the cros-ec-typec node or teaching dp_altmode_probe() to
look for the port@1/endpoint@1 remote-endpoint handle in the
usb-c-connector graph.
Assuming the bindings you've presented here are fine and good and I got
over the differences between Trogdor and Corsola, then I can make mostly
everything work with the drm_connector_oob_hotplug_event() signature
change from above and some tweaks to dp_altmode_probe() to look for
port@1/endpoint@1 first because that's the "logical" DP input endpoint
in the usb-c-connector binding's graph. Great! The final roadblock I'm
at is that HPD doesn't work on Trogdor, so I can't signal HPD through
the typec framework.
This series fixes that problem by "capturing" HPD state from the
upstream drm_bridge, e.g. msm_dp, by hooking the struct
drm_bridge_funcs::hpd_notify() path and injecting HPD into the typec
messages received from the EC. That's a workaround to make the typec
framework see HPD state changes that are otherwise invisible to the
kernel. Newer firmwares actually tell us the state of HPD properly, but
even then we have to read a gpio mux controlled by the EC to figure out
which usb-c-connector is actually muxing DP when HPD changes on either
typec_port. Having a drm_bridge in cros-ec-typec helped here because we
could hook this path and signal HPD if we knew the firmware was fixed.
If we don't have the drm_bridge anymore, I'm lost how to do this.
Maybe the right answer here is to introduce a drm_connector_dp_typec
structure that is created by the TCPM (cros-ec-typec) that sets a new
DRM_BRIDGE_OP_DP_TYPEC bridge op flag? And then teach
drm_bridge_connector about this new flag, similar to the HDMI one. The
drm_bridge could implement some function that maps the typec_port
(usb-c-connector) to the upstream drm_bridge (ANX7625) graph port,
possibly all in drm_bridge_connector_oob_hotplug_event() so that nothing
else really changes. It could also let us keep hooking the hpd_notify()
path for the workaround needed on Trogdor. And finally it may let us
harmonize the two DT bindings so that we only have one port@1/endpoint
node in the usb-c-connector.
> };
> };
>
> connector@1 {
> port@1 {
> endpoint@0 {
> remtoe = <&usb_hub_1>;
> };
>
> endpoint@1 {
> remote = <&dp_bridge_out_1>;
> };
> };
> };
> };
>
> dp_bridge {
> ports {
> port@1 {
> dp_bridge_out_0: endpoint@0 {
> remote = <usb_c0_ss_dp>;
> data-lanes = <0 1>;
> };
>
> dp_bridge_out_1: endpoint@1 {
> remote = <usb_c1_ss_dp>;
> data-lanes = <2 3>;
> };
> };
> };
> };
>
> -------
>
> This one is really tough example, we didn't reach a conclusion here.
> If the EC doesn't handle lane remapping, dp_bridge has to get
> orientation-switch and mode-switch properties (as in the end it is the
> dp_bridge that handles reshuffling of the lanes for the Type-C). Per the
> DisplayPort standard the lanes are fixed (e.g. DPCD 101h explicitly
> names lane 0, lanes 0-1, lanes 0-1-2-3).
Are those logical or physical lanes?
I think we'll punt on this one anyway though. We don't have any plans to
do this orientation control mechanism so far. Previous attempts failed
and we put an extra orientation switch control on the board to do the
orientation flipping.
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 13/18] dt-bindings: usb-switch: Extend for DisplayPort altmode
2024-10-10 22:43 ` Stephen Boyd
@ 2024-10-25 6:36 ` Dmitry Baryshkov
0 siblings, 0 replies; 60+ messages in thread
From: Dmitry Baryshkov @ 2024-10-25 6:36 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring
On Thu, Oct 10, 2024 at 06:43:35PM -0400, Stephen Boyd wrote:
> Quoting Dmitry Baryshkov (2024-09-19 03:40:19)
> > On Sat, Aug 31, 2024 at 09:06:51PM GMT, Stephen Boyd wrote:
> > > diff --git a/Documentation/devicetree/bindings/usb/usb-switch.yaml b/Documentation/devicetree/bindings/usb/usb-switch.yaml
> > > index f5dc7e23b134..816f295f322f 100644
> > > --- a/Documentation/devicetree/bindings/usb/usb-switch.yaml
> > > +++ b/Documentation/devicetree/bindings/usb/usb-switch.yaml
> > > @@ -52,6 +52,14 @@ properties:
> > > endpoint:
> > > $ref: '#/$defs/usbc-in-endpoint'
> > >
> > > + port@2:
> > > + $ref: /schemas/graph.yaml#/$defs/port-base
> > > + unevaluatedProperties: false
> > > +
> > > + properties:
> > > + endpoint:
> > > + $ref: '#/$defs/dp-endpoint'
> >
> > Is it a separate port or is it an endpoint of the same upstream-facing
> > (non-connector-facing) SS port?
>
> I don't quite follow this comment. This is an input DP endpoint/port.
This is the question: is this a separate port or just an endpoint on the
port?
>
> >
> > > +
> > > oneOf:
> > > - required:
> > > - port
> > > @@ -65,6 +73,19 @@ $defs:
> > > $ref: /schemas/graph.yaml#/$defs/endpoint-base
> > > description: Super Speed (SS) output endpoint to a type-c connector
> > > unevaluatedProperties: false
> > > + properties:
> > > + data-lanes:
> > > + $ref: /schemas/types.yaml#/definitions/uint32-array
> > > + description: |
> > > + An array of physical USB Type-C data lane indexes.
> > > + - 0 is SSRX1 lane
> > > + - 1 is SSTX1 lane
> > > + - 2 is SSTX2 lane
> > > + - 3 is SSRX2 lane
> > > + minItems: 4
> > > + maxItems: 4
> > > + items:
> > > + maximum: 3
> >
> > What is the usecase to delare less than 4 lanes going to the USB-C
> > connector?
>
> I'm not aware of any usecase. The 'maximum: 3' is the max value in the
> cell, i.e. 0, 1, 2, or 3.
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
2024-10-23 1:15 ` Stephen Boyd
@ 2024-10-25 10:49 ` Dmitry Baryshkov
2024-10-29 20:15 ` Stephen Boyd
0 siblings, 1 reply; 60+ messages in thread
From: Dmitry Baryshkov @ 2024-10-25 10:49 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring
On Tue, Oct 22, 2024 at 06:15:47PM -0700, Stephen Boyd wrote:
> Quoting Dmitry Baryshkov (2024-09-20 02:38:53)
> > On Sat, Aug 31, 2024 at 09:06:53PM GMT, Stephen Boyd wrote:
>
> Either way the problem seems to be that I need to associate one
> drm_bridge with two displayport altmode drivers and pass some fwnode
> handle to drm_connector_oob_hotplug_event() in a way that we can map
> that back to the right output endpoint in the DP bridge graph. That
> seems to imply that we need to pass the fwnode for the usb-c-connector
> in addition to the fwnode for the drm_bridge, so that the drm_bridge
> code can look at its DT graph and find the remote node connected.
> Basically something like this:
>
> void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode,
> struct fwnode_handle
> *usb_connector_fwnode,
> enum drm_connector_status status)
>
> (We might as well also pass the number of lanes here)
I think this is a bit of an overkill.
The drm_connector_oob_hotplug_event() is fine as it is, it gets
"fwnode_handle to report the event on".
What needs to be changed (in my humble opinion) is the
drm_connector_find_by_fwnode() function (or likely a new function is to
be added): if it can not find drm_connector for the passed fwnode, it
should look it up on the parent, then on parent's parent, etc, until we
actually find the drm_connector (good) or we reach the root (sad).
And finally after getting the drm_connector, the oob_hotplug_event()
callback should also receive the fwnode argument. This way the connector
(or the bridge) can identify the fwnode (aka usb-c-connector in our
case) that caused the event.
WDYT?
> Corsola could work with this design, but we'll need to teach
> dp_altmode_probe() to look for the drm_bridge elsewhere besides as the
> parent of the usb-c-connector node. That implies using the 'displayport'
> property in the cros-ec-typec node or teaching dp_altmode_probe() to
> look for the port@1/endpoint@1 remote-endpoint handle in the
> usb-c-connector graph.
>
> Assuming the bindings you've presented here are fine and good and I got
> over the differences between Trogdor and Corsola, then I can make mostly
> everything work with the drm_connector_oob_hotplug_event() signature
> change from above and some tweaks to dp_altmode_probe() to look for
> port@1/endpoint@1 first because that's the "logical" DP input endpoint
> in the usb-c-connector binding's graph. Great! The final roadblock I'm
> at is that HPD doesn't work on Trogdor, so I can't signal HPD through
> the typec framework.
Hmm, I thought that a normal DP's HPD GPIO works on the trogdor. Was I
misunderstanding it? But then we don't know, which USB-C connector
triggered the HPD...
> This series fixes that problem by "capturing" HPD state from the
> upstream drm_bridge, e.g. msm_dp, by hooking the struct
> drm_bridge_funcs::hpd_notify() path and injecting HPD into the typec
> messages received from the EC. That's a workaround to make the typec
> framework see HPD state changes that are otherwise invisible to the
> kernel. Newer firmwares actually tell us the state of HPD properly, but
> even then we have to read a gpio mux controlled by the EC to figure out
> which usb-c-connector is actually muxing DP when HPD changes on either
> typec_port. Having a drm_bridge in cros-ec-typec helped here because we
> could hook this path and signal HPD if we knew the firmware was fixed.
> If we don't have the drm_bridge anymore, I'm lost how to do this.
It's probably okay to add one, but let me think if we can work without
it. Can we make EC driver listen for that single HPD GPIO (by making it
an actual GPIO rather than "dp_hot") and then react to it?
>
> Maybe the right answer here is to introduce a drm_connector_dp_typec
> structure that is created by the TCPM (cros-ec-typec) that sets a new
> DRM_BRIDGE_OP_DP_TYPEC bridge op flag? And then teach
> drm_bridge_connector about this new flag, similar to the HDMI one. The
> drm_bridge could implement some function that maps the typec_port
> (usb-c-connector) to the upstream drm_bridge (ANX7625) graph port,
> possibly all in drm_bridge_connector_oob_hotplug_event() so that nothing
> else really changes. It could also let us keep hooking the hpd_notify()
> path for the workaround needed on Trogdor. And finally it may let us
> harmonize the two DT bindings so that we only have one port@1/endpoint
> node in the usb-c-connector.
I think we have lightly discussed adding drm_connector_displayport, so
that part is okay. But my gut feeling is that there should be no _typec
part in thart picture. The DRM framework shouldn't need to know all the
Type-C details.
>
>
> > };
> > };
> >
> > connector@1 {
> > port@1 {
> > endpoint@0 {
> > remtoe = <&usb_hub_1>;
> > };
> >
> > endpoint@1 {
> > remote = <&dp_bridge_out_1>;
> > };
> > };
> > };
> > };
> >
> > dp_bridge {
> > ports {
> > port@1 {
> > dp_bridge_out_0: endpoint@0 {
> > remote = <usb_c0_ss_dp>;
> > data-lanes = <0 1>;
> > };
> >
> > dp_bridge_out_1: endpoint@1 {
> > remote = <usb_c1_ss_dp>;
> > data-lanes = <2 3>;
> > };
> > };
> > };
> > };
> >
> > -------
> >
> > This one is really tough example, we didn't reach a conclusion here.
> > If the EC doesn't handle lane remapping, dp_bridge has to get
> > orientation-switch and mode-switch properties (as in the end it is the
> > dp_bridge that handles reshuffling of the lanes for the Type-C). Per the
> > DisplayPort standard the lanes are fixed (e.g. DPCD 101h explicitly
> > names lane 0, lanes 0-1, lanes 0-1-2-3).
>
> Are those logical or physical lanes?
Physical lanes as far as I understand.
>
> I think we'll punt on this one anyway though. We don't have any plans to
> do this orientation control mechanism so far. Previous attempts failed
> and we put an extra orientation switch control on the board to do the
> orientation flipping.
Okay, it's definitely easier this way.
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
2024-10-25 10:49 ` Dmitry Baryshkov
@ 2024-10-29 20:15 ` Stephen Boyd
2024-10-31 18:42 ` Dmitry Baryshkov
0 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-10-29 20:15 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring
Quoting Dmitry Baryshkov (2024-10-25 03:49:36)
> On Tue, Oct 22, 2024 at 06:15:47PM -0700, Stephen Boyd wrote:
> > Quoting Dmitry Baryshkov (2024-09-20 02:38:53)
> > > On Sat, Aug 31, 2024 at 09:06:53PM GMT, Stephen Boyd wrote:
>
> >
> > Either way the problem seems to be that I need to associate one
> > drm_bridge with two displayport altmode drivers and pass some fwnode
> > handle to drm_connector_oob_hotplug_event() in a way that we can map
> > that back to the right output endpoint in the DP bridge graph. That
> > seems to imply that we need to pass the fwnode for the usb-c-connector
> > in addition to the fwnode for the drm_bridge, so that the drm_bridge
> > code can look at its DT graph and find the remote node connected.
> > Basically something like this:
> >
> > void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode,
> > struct fwnode_handle
> > *usb_connector_fwnode,
> > enum drm_connector_status status)
> >
> > (We might as well also pass the number of lanes here)
>
> I think this is a bit of an overkill.
>
> The drm_connector_oob_hotplug_event() is fine as it is, it gets
> "fwnode_handle to report the event on".
Ok. I understand that drm_*() shouldn't know about USB or type-c in
general.
>
> What needs to be changed (in my humble opinion) is the
> drm_connector_find_by_fwnode() function (or likely a new function is to
> be added): if it can not find drm_connector for the passed fwnode, it
> should look it up on the parent, then on parent's parent, etc, until we
> actually find the drm_connector (good) or we reach the root (sad).
>
> And finally after getting the drm_connector, the oob_hotplug_event()
> callback should also receive the fwnode argument. This way the connector
> (or the bridge) can identify the fwnode (aka usb-c-connector in our
> case) that caused the event.
>
> WDYT?
Ok I think I'm following along. The dp->connector_fwnode in
displayport.c will always be the usb-c-connector node in your example?
And that will search for the connector or bridge associated with that
usb-c-connector node. Then when it comes time to call
drm_connector_oob_hotplug_event() it will take the usb-c-connector
fwnode as 'connector_fwnode' and in that function we'll make
drm_connector_find_by_fwnode() implement the parent walk? The
cros-ec-typec compatible node will register a drm_bridge in all cases,
and that is the parent of the usb-c-connector node, so the walk will end
there.
Then you want to pass the usb-c-connector fwnode to
connector->funcs->oob_hotplug_event()? So
drm_bridge_connector_oob_hotplug_event() changes to also get the
usb-c-connector fwnode. This plan should work.
At this point we need to tell the DP bridge, like IT6505, that it's one
or the other output endpoints that it should use, but we haven't
directly connected the usb-c-connector to the output ports of IT6505
because drm_of_find_panel_or_bridge() can't find the parent of the
usb-c-connector if we connect the DP bridge to the usb-c-connector
graphs. We'll need a way for the bridge to know which output port is
connected to a usb-c-connector fwnode. Some sort of API like
fwnode_graph_get_endpoint_connected_to_fwnode(bridge_fwnode, usb_c_fwnode)
that takes the bridge fwnode and traverses the graph to find the
endpoint in that's connected to 'usb_c_fwnode'. That traversal API will
need help from the intermediate node, cros-ec-typec, so maybe it is
better as a drm_bridge API that uses some new drm_bridge_funcs callback.
This way IT6505 can ask the bridge chain which output DP endpoint is
actually associated with the connector fwnode it gets from the
oob_hotplug_event() callback.
Here's the two DT snippets that I've ended up with:
typec {
compatible = "google,cros-ec-typec";
ports {
port@0 {
reg = <0>;
typec_dp_in: endpoint {
remote-endpoint = <&usb_1_qmp_phy_out_dp>;
};
};
port@1 {
reg = <1>;
typec_usb0_in: endpoint@0 {
reg = <0>;
remote-endpoint = <&usb_hub_dfp1_ss>;
};
typec_usb1_in: endpoint@1 {
reg = <1>;
remote-endpoint = <&usb_hub_dfp2_ss>;
};
}
// This port is not really needed because we know the
// mapping from input ports to usb-c-connectors
port@2 {
reg = <2>;
typec0_out: endpoint@0 {
reg = <0>;
remote-endpoint = <&usb_c0_ss_in>;
};
typec1_out: endpoint@1 {
reg = <1>;
remote-endpoint = <&usb_c1_ss_in>;
};
}
};
usb_c0: connector@0 {
compatible = "usb-c-connector";
reg = <0>;
ports {
port@0 {
reg = <0>;
usb_c0_hs_in: endpoint {
remote-endpoint = <&usb_hub_dfp1_hs>;
};
};
port@1 {
reg = <1>;
usb_c0_ss_in: endpoint {
remote-endpoint = <&typec0_out>;
};
};
};
};
usb_c1: connector@1 {
compatible = "usb-c-connector";
reg = <1>;
ports {
port@0 {
reg = <0>;
usb_c1_hs_in: endpoint {
remote-endpoint = <&usb_hub_dfp2_hs>;
};
};
port@1 {
reg = <1>;
usb_c1_ss_in: endpoint {
remote-endpoint = <&typec1_out>;
};
};
};
};
};
&usb_1_qmpphy {
ports {
port@0 {
endpoint@0 {
data-lanes = <0 1>;
// this might go to USB-3 hub
};
usb_1_qmp_phy_out_dp: endpoint@1 {
remote-endpoint = <&typec_dp_in>;
data-lanes = <2 3>;
};
}
};
};
-------
typec {
ports {
port@0 {
reg = <0>;
typec_dp0_in: endpoint@0 {
reg = <0>;
remote-endpoint = <&dp_bridge_out_0>;
};
typec_dp1_in: endpoint@1 {
reg = <1>;
remote-endpoint = <&dp_bridge_out_1>;
};
};
port@1 {
reg = <1>;
typec_usb0_in: endpoint@0 {
reg = <0>;
remote-endpoint = <&usb_hub_0_ss>;
};
typec_usb1_in: endpoint@1 {
reg = <1>;
remote-endpoint = <&usb_hub_1_ss>;
};
}
};
connector@0 {
port@1 {
endpoint@0 {
remote-endpoint = <&usb_hub_0_hs>;
};
};
};
connector@1 {
port@1 {
endpoint@0 {
remote-endpoint = <&usb_hub_1_hs>;
};
};
};
};
dp_bridge {
ports {
port@1 {
dp_bridge_out_0: endpoint@0 {
remote-endpoint = <&typec_dp0_in>;
data-lanes = <0 1>;
};
dp_bridge_out_1: endpoint@1 {
remote-endpoint = <&typec_dp1_in>;
data-lanes = <2 3>;
};
};
};
};
-------
I wonder about a case where we may take two lanes and connect them to a
usb-c-connector and then take the other two lanes and send them through
a mux to two more usb-c-connectors. I think we'll need another property
in that case that indicates which input DP endpoints correspond to the
usb-c-connector nodes.
typec {
ports {
port@0 {
reg = <0>;
typec_dp0_in: endpoint@0 {
reg = <0>;
remote-endpoint = <&dp_bridge_out_0>;
};
typec_dp1_in: endpoint@1 {
reg = <1>;
remote-endpoint = <&dp_bridge_out_1>;
};
};
port@1 {
reg = <1>;
typec_usb0_in: endpoint@0 {
reg = <0>;
remote-endpoint = <&usb_hub_0_ss>;
};
typec_usb1_in: endpoint@1 {
reg = <1>;
remote-endpoint = <&usb_hub_1_ss>;
};
typec_usb2_in: endpoint@2 {
reg = <2>;
remote-endpoint = <&usb_hub_2_ss>;
};
}
};
dp-2-usb-mapping = <0 0>, <1 1>, <1 2>;
};
This property would indicate dp endpoint 0 goes to usb-c-connector 0
while dp endpoint 1 goes to usb-c-connector 1 and 2. I don't have this
hardware but I could see how someone might do this by adding another mux
that the EC controls. I don't want to design a binding and have to
rework it in the future to handle this new case. I hope adding a new
property, or getting more information from the EC firmware, will be
sufficient to describe the linkage between the DP endpoint and the
connectors managed by the cros-ec-typec device.
>
> > Corsola could work with this design, but we'll need to teach
> > dp_altmode_probe() to look for the drm_bridge elsewhere besides as the
> > parent of the usb-c-connector node. That implies using the 'displayport'
> > property in the cros-ec-typec node or teaching dp_altmode_probe() to
> > look for the port@1/endpoint@1 remote-endpoint handle in the
> > usb-c-connector graph.
> >
> > Assuming the bindings you've presented here are fine and good and I got
> > over the differences between Trogdor and Corsola, then I can make mostly
> > everything work with the drm_connector_oob_hotplug_event() signature
> > change from above and some tweaks to dp_altmode_probe() to look for
> > port@1/endpoint@1 first because that's the "logical" DP input endpoint
> > in the usb-c-connector binding's graph. Great! The final roadblock I'm
> > at is that HPD doesn't work on Trogdor, so I can't signal HPD through
> > the typec framework.
>
> Hmm, I thought that a normal DP's HPD GPIO works on the trogdor. Was I
> misunderstanding it? But then we don't know, which USB-C connector
> triggered the HPD...
By HPD not working on Trogdor I mean that the EC doesn't tell the kernel
about the state of HPD for a usb-c-connector in software. Instead, HPD
is signaled directly to the DP controller in hardware via a GPIO. It is
as you suspect, we don't know which USB-C connector has HPD unless we
read the mux controlled by the EC and combine that with what the DP
driver knows about the state of the HPD pin.
>
> > This series fixes that problem by "capturing" HPD state from the
> > upstream drm_bridge, e.g. msm_dp, by hooking the struct
> > drm_bridge_funcs::hpd_notify() path and injecting HPD into the typec
> > messages received from the EC. That's a workaround to make the typec
> > framework see HPD state changes that are otherwise invisible to the
> > kernel. Newer firmwares actually tell us the state of HPD properly, but
> > even then we have to read a gpio mux controlled by the EC to figure out
> > which usb-c-connector is actually muxing DP when HPD changes on either
> > typec_port. Having a drm_bridge in cros-ec-typec helped here because we
> > could hook this path and signal HPD if we knew the firmware was fixed.
> > If we don't have the drm_bridge anymore, I'm lost how to do this.
>
> It's probably okay to add one, but let me think if we can work without
> it. Can we make EC driver listen for that single HPD GPIO (by making it
> an actual GPIO rather than "dp_hot") and then react to it?
I don't know how we handle the attention message, HPD_IRQ, because
that's a short pulse that the kernel may miss when this is a GPIO that
has to be triggered when both falling and rising. When the pin goes
directly to the DP controller this is fine because the hardware can
detect that. Similarly, when the EC sends the message about an HPD_IRQ
we can replay that into the type-c framework and signal attention
through drm_connector_oob_hotplug_event()/hpd_notify() paths.
>
> >
> > Maybe the right answer here is to introduce a drm_connector_dp_typec
> > structure that is created by the TCPM (cros-ec-typec) that sets a new
> > DRM_BRIDGE_OP_DP_TYPEC bridge op flag? And then teach
> > drm_bridge_connector about this new flag, similar to the HDMI one. The
> > drm_bridge could implement some function that maps the typec_port
> > (usb-c-connector) to the upstream drm_bridge (ANX7625) graph port,
> > possibly all in drm_bridge_connector_oob_hotplug_event() so that nothing
> > else really changes. It could also let us keep hooking the hpd_notify()
> > path for the workaround needed on Trogdor. And finally it may let us
> > harmonize the two DT bindings so that we only have one port@1/endpoint
> > node in the usb-c-connector.
>
> I think we have lightly discussed adding drm_connector_displayport, so
> that part is okay. But my gut feeling is that there should be no _typec
> part in thart picture. The DRM framework shouldn't need to know all the
> Type-C details.
>
Alright, got it.
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
2024-10-29 20:15 ` Stephen Boyd
@ 2024-10-31 18:42 ` Dmitry Baryshkov
2024-10-31 21:45 ` Stephen Boyd
0 siblings, 1 reply; 60+ messages in thread
From: Dmitry Baryshkov @ 2024-10-31 18:42 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring
On Tue, Oct 29, 2024 at 01:15:51PM -0700, Stephen Boyd wrote:
> Quoting Dmitry Baryshkov (2024-10-25 03:49:36)
> > On Tue, Oct 22, 2024 at 06:15:47PM -0700, Stephen Boyd wrote:
> > > Quoting Dmitry Baryshkov (2024-09-20 02:38:53)
> > > > On Sat, Aug 31, 2024 at 09:06:53PM GMT, Stephen Boyd wrote:
> >
> > >
> > > Either way the problem seems to be that I need to associate one
> > > drm_bridge with two displayport altmode drivers and pass some fwnode
> > > handle to drm_connector_oob_hotplug_event() in a way that we can map
> > > that back to the right output endpoint in the DP bridge graph. That
> > > seems to imply that we need to pass the fwnode for the usb-c-connector
> > > in addition to the fwnode for the drm_bridge, so that the drm_bridge
> > > code can look at its DT graph and find the remote node connected.
> > > Basically something like this:
> > >
> > > void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode,
> > > struct fwnode_handle
> > > *usb_connector_fwnode,
> > > enum drm_connector_status status)
> > >
> > > (We might as well also pass the number of lanes here)
> >
> > I think this is a bit of an overkill.
> >
> > The drm_connector_oob_hotplug_event() is fine as it is, it gets
> > "fwnode_handle to report the event on".
>
> Ok. I understand that drm_*() shouldn't know about USB or type-c in
> general.
>
> >
> > What needs to be changed (in my humble opinion) is the
> > drm_connector_find_by_fwnode() function (or likely a new function is to
> > be added): if it can not find drm_connector for the passed fwnode, it
> > should look it up on the parent, then on parent's parent, etc, until we
> > actually find the drm_connector (good) or we reach the root (sad).
> >
> > And finally after getting the drm_connector, the oob_hotplug_event()
> > callback should also receive the fwnode argument. This way the connector
> > (or the bridge) can identify the fwnode (aka usb-c-connector in our
> > case) that caused the event.
> >
> > WDYT?
>
> Ok I think I'm following along. The dp->connector_fwnode in
> displayport.c will always be the usb-c-connector node in your example?
> And that will search for the connector or bridge associated with that
> usb-c-connector node. Then when it comes time to call
> drm_connector_oob_hotplug_event() it will take the usb-c-connector
> fwnode as 'connector_fwnode' and in that function we'll make
> drm_connector_find_by_fwnode() implement the parent walk? The
> cros-ec-typec compatible node will register a drm_bridge in all cases,
> and that is the parent of the usb-c-connector node, so the walk will end
> there.
>
> Then you want to pass the usb-c-connector fwnode to
> connector->funcs->oob_hotplug_event()? So
> drm_bridge_connector_oob_hotplug_event() changes to also get the
> usb-c-connector fwnode. This plan should work.
Yes, that was my proposal. This way we know the origin device (bridge /
connector) and let it take care of any details on its own.
> At this point we need to tell the DP bridge, like IT6505, that it's one
> or the other output endpoints that it should use, but we haven't
> directly connected the usb-c-connector to the output ports of IT6505
> because drm_of_find_panel_or_bridge() can't find the parent of the
> usb-c-connector if we connect the DP bridge to the usb-c-connector
> graphs. We'll need a way for the bridge to know which output port is
> connected to a usb-c-connector fwnode. Some sort of API like
I think that the final bridge should be the IT6505. It can save you from
some troubles, like the inter-bridge lane negotiation. Please remember
that using lanes 2-3 as primary lanes doesn't seem to fall into the
standard DisplayPort usage. It is documented by USB-C and only because
of the orientation switching.
Maybe that's just it? Register DP_bridge (or QMP PHY) as
orientation-switch? Then you don't need any extra API for the lane
mapping? The cross-ec-typec can provide orientation information and the
USB-C-aware controller will follow the lane mapping.
>
> fwnode_graph_get_endpoint_connected_to_fwnode(bridge_fwnode, usb_c_fwnode)
>
> that takes the bridge fwnode and traverses the graph to find the
> endpoint in that's connected to 'usb_c_fwnode'. That traversal API will
> need help from the intermediate node, cros-ec-typec, so maybe it is
> better as a drm_bridge API that uses some new drm_bridge_funcs callback.
> This way IT6505 can ask the bridge chain which output DP endpoint is
> actually associated with the connector fwnode it gets from the
> oob_hotplug_event() callback.
>
> Here's the two DT snippets that I've ended up with:
>
> typec {
> compatible = "google,cros-ec-typec";
>
> ports {
> port@0 {
> reg = <0>;
> typec_dp_in: endpoint {
> remote-endpoint = <&usb_1_qmp_phy_out_dp>;
> };
> };
>
> port@1 {
> reg = <1>;
> typec_usb0_in: endpoint@0 {
> reg = <0>;
> remote-endpoint = <&usb_hub_dfp1_ss>;
> };
> typec_usb1_in: endpoint@1 {
> reg = <1>;
> remote-endpoint = <&usb_hub_dfp2_ss>;
> };
> }
>
> // This port is not really needed because we know the
> // mapping from input ports to usb-c-connectors
> port@2 {
> reg = <2>;
> typec0_out: endpoint@0 {
> reg = <0>;
> remote-endpoint = <&usb_c0_ss_in>;
> };
> typec1_out: endpoint@1 {
> reg = <1>;
> remote-endpoint = <&usb_c1_ss_in>;
> };
> }
Why do we need these two ports? Can't &usb_hub_dfpN_ss be connected
directly to the usb_cN_ss_in? I understand that you probably want to
express the internal structure of the lane switching, but I think that's
a bit of the overkill. Leaving this to the other commenters / DT
maintainers.
> };
>
> usb_c0: connector@0 {
> compatible = "usb-c-connector";
> reg = <0>;
>
> ports {
> port@0 {
> reg = <0>;
> usb_c0_hs_in: endpoint {
> remote-endpoint = <&usb_hub_dfp1_hs>;
> };
> };
>
> port@1 {
> reg = <1>;
> usb_c0_ss_in: endpoint {
> remote-endpoint = <&typec0_out>;
> };
> };
> };
> };
>
> usb_c1: connector@1 {
> compatible = "usb-c-connector";
> reg = <1>;
>
> ports {
> port@0 {
> reg = <0>;
> usb_c1_hs_in: endpoint {
> remote-endpoint = <&usb_hub_dfp2_hs>;
> };
> };
>
> port@1 {
> reg = <1>;
> usb_c1_ss_in: endpoint {
> remote-endpoint = <&typec1_out>;
> };
> };
> };
> };
> };
>
> &usb_1_qmpphy {
> ports {
> port@0 {
> endpoint@0 {
> data-lanes = <0 1>;
> // this might go to USB-3 hub
> };
>
> usb_1_qmp_phy_out_dp: endpoint@1 {
> remote-endpoint = <&typec_dp_in>;
> data-lanes = <2 3>;
> };
> }
> };
> };
>
> -------
>
> typec {
> ports {
> port@0 {
> reg = <0>;
> typec_dp0_in: endpoint@0 {
> reg = <0>;
> remote-endpoint = <&dp_bridge_out_0>;
> };
> typec_dp1_in: endpoint@1 {
> reg = <1>;
> remote-endpoint = <&dp_bridge_out_1>;
> };
> };
>
> port@1 {
> reg = <1>;
> typec_usb0_in: endpoint@0 {
> reg = <0>;
> remote-endpoint = <&usb_hub_0_ss>;
> };
> typec_usb1_in: endpoint@1 {
> reg = <1>;
> remote-endpoint = <&usb_hub_1_ss>;
> };
> }
> };
>
> connector@0 {
> port@1 {
> endpoint@0 {
> remote-endpoint = <&usb_hub_0_hs>;
port@1 is for SS lanes, so something is wrong here.
> };
> };
> };
>
> connector@1 {
> port@1 {
> endpoint@0 {
> remote-endpoint = <&usb_hub_1_hs>;
> };
> };
> };
> };
>
> dp_bridge {
> ports {
> port@1 {
> dp_bridge_out_0: endpoint@0 {
> remote-endpoint = <&typec_dp0_in>;
> data-lanes = <0 1>;
> };
>
> dp_bridge_out_1: endpoint@1 {
> remote-endpoint = <&typec_dp1_in>;
> data-lanes = <2 3>;
> };
> };
> };
> };
>
> -------
>
> I wonder about a case where we may take two lanes and connect them to a
> usb-c-connector and then take the other two lanes and send them through
> a mux to two more usb-c-connectors. I think we'll need another property
> in that case that indicates which input DP endpoints correspond to the
> usb-c-connector nodes.
>
> typec {
> ports {
> port@0 {
> reg = <0>;
> typec_dp0_in: endpoint@0 {
> reg = <0>;
> remote-endpoint = <&dp_bridge_out_0>;
> };
> typec_dp1_in: endpoint@1 {
> reg = <1>;
> remote-endpoint = <&dp_bridge_out_1>;
> };
> };
>
> port@1 {
> reg = <1>;
> typec_usb0_in: endpoint@0 {
> reg = <0>;
> remote-endpoint = <&usb_hub_0_ss>;
> };
> typec_usb1_in: endpoint@1 {
> reg = <1>;
> remote-endpoint = <&usb_hub_1_ss>;
> };
> typec_usb2_in: endpoint@2 {
> reg = <2>;
> remote-endpoint = <&usb_hub_2_ss>;
> };
> }
> };
>
> dp-2-usb-mapping = <0 0>, <1 1>, <1 2>;
dp-to-typec-mapping?
> };
>
> This property would indicate dp endpoint 0 goes to usb-c-connector 0
> while dp endpoint 1 goes to usb-c-connector 1 and 2. I don't have this
> hardware but I could see how someone might do this by adding another mux
> that the EC controls. I don't want to design a binding and have to
> rework it in the future to handle this new case. I hope adding a new
> property, or getting more information from the EC firmware, will be
> sufficient to describe the linkage between the DP endpoint and the
> connectors managed by the cros-ec-typec device.
Does it change anything from the DP point of view? It is still either
lanes 0-1 or lanes 2-3? I'd really like to inject the hotplug OOB event
to the dp_bridge letting it get one of the endpoints as a HPD even
source.
> > > Corsola could work with this design, but we'll need to teach
> > > dp_altmode_probe() to look for the drm_bridge elsewhere besides as the
> > > parent of the usb-c-connector node. That implies using the 'displayport'
> > > property in the cros-ec-typec node or teaching dp_altmode_probe() to
> > > look for the port@1/endpoint@1 remote-endpoint handle in the
> > > usb-c-connector graph.
> > >
> > > Assuming the bindings you've presented here are fine and good and I got
> > > over the differences between Trogdor and Corsola, then I can make mostly
> > > everything work with the drm_connector_oob_hotplug_event() signature
> > > change from above and some tweaks to dp_altmode_probe() to look for
> > > port@1/endpoint@1 first because that's the "logical" DP input endpoint
> > > in the usb-c-connector binding's graph. Great! The final roadblock I'm
> > > at is that HPD doesn't work on Trogdor, so I can't signal HPD through
> > > the typec framework.
> >
> > Hmm, I thought that a normal DP's HPD GPIO works on the trogdor. Was I
> > misunderstanding it? But then we don't know, which USB-C connector
> > triggered the HPD...
>
> By HPD not working on Trogdor I mean that the EC doesn't tell the kernel
> about the state of HPD for a usb-c-connector in software. Instead, HPD
> is signaled directly to the DP controller in hardware via a GPIO. It is
> as you suspect, we don't know which USB-C connector has HPD unless we
> read the mux controlled by the EC and combine that with what the DP
> driver knows about the state of the HPD pin.
I see. So the HPD event gets delivered to the DP controller, but we
really need some API to read the port? If it's not the
orientation-switch, of course.
>
> >
> > > This series fixes that problem by "capturing" HPD state from the
> > > upstream drm_bridge, e.g. msm_dp, by hooking the struct
> > > drm_bridge_funcs::hpd_notify() path and injecting HPD into the typec
> > > messages received from the EC. That's a workaround to make the typec
> > > framework see HPD state changes that are otherwise invisible to the
> > > kernel. Newer firmwares actually tell us the state of HPD properly, but
> > > even then we have to read a gpio mux controlled by the EC to figure out
> > > which usb-c-connector is actually muxing DP when HPD changes on either
> > > typec_port. Having a drm_bridge in cros-ec-typec helped here because we
> > > could hook this path and signal HPD if we knew the firmware was fixed.
> > > If we don't have the drm_bridge anymore, I'm lost how to do this.
> >
> > It's probably okay to add one, but let me think if we can work without
> > it. Can we make EC driver listen for that single HPD GPIO (by making it
> > an actual GPIO rather than "dp_hot") and then react to it?
>
> I don't know how we handle the attention message, HPD_IRQ, because
> that's a short pulse that the kernel may miss when this is a GPIO that
> has to be triggered when both falling and rising. When the pin goes
> directly to the DP controller this is fine because the hardware can
> detect that. Similarly, when the EC sends the message about an HPD_IRQ
> we can replay that into the type-c framework and signal attention
> through drm_connector_oob_hotplug_event()/hpd_notify() paths.
Ack.
>
> >
> > >
> > > Maybe the right answer here is to introduce a drm_connector_dp_typec
> > > structure that is created by the TCPM (cros-ec-typec) that sets a new
> > > DRM_BRIDGE_OP_DP_TYPEC bridge op flag? And then teach
> > > drm_bridge_connector about this new flag, similar to the HDMI one. The
> > > drm_bridge could implement some function that maps the typec_port
> > > (usb-c-connector) to the upstream drm_bridge (ANX7625) graph port,
> > > possibly all in drm_bridge_connector_oob_hotplug_event() so that nothing
> > > else really changes. It could also let us keep hooking the hpd_notify()
> > > path for the workaround needed on Trogdor. And finally it may let us
> > > harmonize the two DT bindings so that we only have one port@1/endpoint
> > > node in the usb-c-connector.
> >
> > I think we have lightly discussed adding drm_connector_displayport, so
> > that part is okay. But my gut feeling is that there should be no _typec
> > part in thart picture. The DRM framework shouldn't need to know all the
> > Type-C details.
> >
>
> Alright, got it.
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
2024-10-31 18:42 ` Dmitry Baryshkov
@ 2024-10-31 21:45 ` Stephen Boyd
2024-10-31 22:54 ` Dmitry Baryshkov
0 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-10-31 21:45 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring
Quoting Dmitry Baryshkov (2024-10-31 11:42:36)
> On Tue, Oct 29, 2024 at 01:15:51PM -0700, Stephen Boyd wrote:
> > At this point we need to tell the DP bridge, like IT6505, that it's one
> > or the other output endpoints that it should use, but we haven't
> > directly connected the usb-c-connector to the output ports of IT6505
> > because drm_of_find_panel_or_bridge() can't find the parent of the
> > usb-c-connector if we connect the DP bridge to the usb-c-connector
> > graphs. We'll need a way for the bridge to know which output port is
> > connected to a usb-c-connector fwnode. Some sort of API like
>
> I think that the final bridge should be the IT6505. It can save you from
> some troubles, like the inter-bridge lane negotiation. Please remember
> that using lanes 2-3 as primary lanes doesn't seem to fall into the
> standard DisplayPort usage. It is documented by USB-C and only because
> of the orientation switching.
If the final bridge is IT6505 then drm_of_find_panel_or_bridge() isn't
called and I think we're OK. But then we have to traverse the
remote-endpoint of the usb-c-connector to IT6505 in displayport.c in the
Corsola case while knowing to look at the parent of the usb-c-connector
node and traversing the remote-endpoint to the QMP phy in the Trogdor
case. The logic in dp_altmode_probe() is like
if (port@1/endpoint@1 exists in usb-c-connector)
connector_fwnode = port@1/endpoint@1/remote-endpoint
else if (cros-ec-typec/port exists)
connector_fwnode = cros-ec-typec/port@0/endpoint/remote-endpoint
else
original stuff
If we have the crazy three usb-c-connector design it can still work
because we'd have something like
cros-ec-typec {
port {
dp_endpoint: endpoint {
remote-endpoint = <&dp_ml0_ml1>;
};
};
usb-c-connector@0 {
port@1 {
endpoint {
remote-endpoint = <&hub_ss0>;
};
// Implicitly dp_ml0_ml1
};
};
usb-c-connector@1 {
port@1 {
endpoint@0 {
remote-endpoint = <&hub_ss1>;
};
endpoint@1 {
remote-endpoint = <&dp_ml2_ml3>;
};
};
};
usb-c-connector@2 {
port@1 {
endpoint {
remote-endpoint = <&hub_ss2>;
};
// Implicitly dp_ml0_ml1
};
};
};
(I like thinking about this 3 connector case because it combines both
Trogdor and Corsola designs so I can talk about both cases at the same
time)
I don't know what happens when we have 4 connectors though, with 2 going
to one pair of lanes and 2 going to the other 2 lanes. Maybe it's better
to always have a DP input port in cros-ec-typec to avoid this problem
and map back to the endpoint explicitly.
cros-ec-typec {
port {
dp_endpoint0: endpoint@0 {
remote-endpoint = <&dp_ml0_ml1>;
};
dp_endpoint1: endpoint@1 {
remote-endpoint = <&dp_ml2_ml3>;
};
};
usb-c-connector@0 {
port@1 {
endpoint@0 {
remote-endpoint = <&hub_ss0>;
};
endpoint@1 {
remote-endpoint = <&dp_endpoint0>;
};
};
};
usb-c-connector@1 {
port@1 {
endpoint@0 {
remote-endpoint = <&hub_ss1>;
};
endpoint@1 {
remote-endpoint = <&dp_endpoint1>;
};
};
};
usb-c-connector@2 {
port@1 {
endpoint@0 {
remote-endpoint = <&hub_ss2>;
};
endpoint@1 {
remote-endpoint = <&dp_endpoint1>;
};
};
};
};
Or use a displayport property that goes to connector node itself so that
we don't extend the graph binding of the usb-c-connector.
cros-ec-typec {
usb-c-connector@0 {
altmodes {
displayport {
connector = <&dp_ml0_ml1>;
};
};
port@1 {
endpoint@0 {
remote-endpoint = <&hub_ss0>;
};
};
};
usb-c-connector@1 {
altmodes {
displayport {
connector = <&dp_ml2_ml3>;
};
};
port@1 {
endpoint {
remote-endpoint = <&hub_ss1>;
};
};
};
usb-c-connector@2 {
altmodes {
displayport {
connector = <&dp_ml2_ml3>;
};
};
port@1 {
endpoint {
remote-endpoint = <&hub_ss2>;
};
};
};
};
it6505 {
ports {
port@1 {
dp_ml0_ml1: endpoint@0 {
remote-endpoint = <??>;
};
dp_ml2_ml3: endpoint@1 {
remote-endpoint = <??>;
};
};
};
};
The logic could look at a node like usb-c-connector@2, find
altmodes/display node, and look for a 'connector' property that points
at the endpoint of the last bridge. If we don't use the OF graph binding
it makes it easier to point at the same endpoint in the QMP phy or the
IT6505 graph from more than one usb-c-connector. This also makes it very
clear that we intend to pass that fwnode as the 'connector_fwnode' to
oob_hotplug_event().
If we want to actually populate the 'remote-endpoint' property of IT6505
we will need to make a graph in cros-ec-typec.
cros-ec-typec {
port {
dp_endpoint0: endpoint@0 {
remote-endpoint = <&dp_ml0_ml1>;
};
dp_endpoint1: endpoint@1 {
remote-endpoint = <&dp_ml2_ml3>;
};
};
usb-c-connector@0 {
altmodes {
displayport {
connector = <&dp_endpoint0>;
};
};
port@1 {
endpoint@0 {
remote-endpoint = <&hub_ss0>;
};
};
};
usb-c-connector@1 {
altmodes {
displayport {
connector = <&dp_endpoint1>;
};
};
port@1 {
endpoint {
remote-endpoint = <&hub_ss1>;
};
};
};
usb-c-connector@2 {
altmodes {
displayport {
connector = <&dp_endpoint1>;
};
};
port@1 {
endpoint {
remote-endpoint = <&hub_ss2>;
};
};
};
};
it6505 {
ports {
port@1 {
dp_ml0_ml1: endpoint@0 {
remote-endpoint = <dp_endpoint0>;
};
dp_ml2_ml3: endpoint@1 {
remote-endpoint = <dp_endpoint1>;
};
};
};
};
and then the logic in displayport.c will have to check if the
'connector' property points at a graph endpoint, traverse that to the
remote-endpoint, and consider that the connector_fwnode.
>
> Maybe that's just it? Register DP_bridge (or QMP PHY) as
> orientation-switch? Then you don't need any extra API for the lane
> mapping? The cross-ec-typec can provide orientation information and the
> USB-C-aware controller will follow the lane mapping.
I'm not really following but I don't think the DT binding discussed here
prevents that.
>
> >
> > fwnode_graph_get_endpoint_connected_to_fwnode(bridge_fwnode, usb_c_fwnode)
> >
> > that takes the bridge fwnode and traverses the graph to find the
> > endpoint in that's connected to 'usb_c_fwnode'. That traversal API will
> > need help from the intermediate node, cros-ec-typec, so maybe it is
> > better as a drm_bridge API that uses some new drm_bridge_funcs callback.
> > This way IT6505 can ask the bridge chain which output DP endpoint is
> > actually associated with the connector fwnode it gets from the
> > oob_hotplug_event() callback.
> >
> > Here's the two DT snippets that I've ended up with:
> >
> > typec {
> > compatible = "google,cros-ec-typec";
> >
> > ports {
> > port@0 {
> > reg = <0>;
> > typec_dp_in: endpoint {
> > remote-endpoint = <&usb_1_qmp_phy_out_dp>;
> > };
> > };
> >
> > port@1 {
> > reg = <1>;
> > typec_usb0_in: endpoint@0 {
> > reg = <0>;
> > remote-endpoint = <&usb_hub_dfp1_ss>;
> > };
> > typec_usb1_in: endpoint@1 {
> > reg = <1>;
> > remote-endpoint = <&usb_hub_dfp2_ss>;
> > };
> > }
> >
> > // This port is not really needed because we know the
> > // mapping from input ports to usb-c-connectors
> > port@2 {
> > reg = <2>;
> > typec0_out: endpoint@0 {
> > reg = <0>;
> > remote-endpoint = <&usb_c0_ss_in>;
> > };
> > typec1_out: endpoint@1 {
> > reg = <1>;
> > remote-endpoint = <&usb_c1_ss_in>;
> > };
> > }
>
> Why do we need these two ports? Can't &usb_hub_dfpN_ss be connected
> directly to the usb_cN_ss_in? I understand that you probably want to
> express the internal structure of the lane switching, but I think that's
> a bit of the overkill. Leaving this to the other commenters / DT
> maintainers.
We don't need port@2 because we know that DP goes there.
>
> > };
> >
> > usb_c0: connector@0 {
> > compatible = "usb-c-connector";
> > reg = <0>;
> >
> > ports {
> > port@0 {
> > reg = <0>;
> > usb_c0_hs_in: endpoint {
> > remote-endpoint = <&usb_hub_dfp1_hs>;
> > };
> > };
> >
> > port@1 {
> > reg = <1>;
> > usb_c0_ss_in: endpoint {
> > remote-endpoint = <&typec0_out>;
> > };
> > };
> > };
> > };
> >
> > usb_c1: connector@1 {
> > compatible = "usb-c-connector";
> > reg = <1>;
> >
> > ports {
> > port@0 {
> > reg = <0>;
> > usb_c1_hs_in: endpoint {
> > remote-endpoint = <&usb_hub_dfp2_hs>;
> > };
> > };
> >
> > port@1 {
> > reg = <1>;
> > usb_c1_ss_in: endpoint {
> > remote-endpoint = <&typec1_out>;
> > };
> > };
> > };
> > };
> > };
> >
> > &usb_1_qmpphy {
> > ports {
> > port@0 {
> > endpoint@0 {
> > data-lanes = <0 1>;
> > // this might go to USB-3 hub
> > };
> >
> > usb_1_qmp_phy_out_dp: endpoint@1 {
> > remote-endpoint = <&typec_dp_in>;
> > data-lanes = <2 3>;
> > };
> > }
> > };
> > };
> >
> > -------
> >
> > typec {
> > ports {
> > port@0 {
> > reg = <0>;
> > typec_dp0_in: endpoint@0 {
> > reg = <0>;
> > remote-endpoint = <&dp_bridge_out_0>;
> > };
> > typec_dp1_in: endpoint@1 {
> > reg = <1>;
> > remote-endpoint = <&dp_bridge_out_1>;
> > };
> > };
> >
> > port@1 {
> > reg = <1>;
> > typec_usb0_in: endpoint@0 {
> > reg = <0>;
> > remote-endpoint = <&usb_hub_0_ss>;
> > };
> > typec_usb1_in: endpoint@1 {
> > reg = <1>;
> > remote-endpoint = <&usb_hub_1_ss>;
> > };
> > }
> > };
> >
> > connector@0 {
> > port@1 {
> > endpoint@0 {
> > remote-endpoint = <&usb_hub_0_hs>;
>
> port@1 is for SS lanes, so something is wrong here.
I meant port@0
>
> > };
> > };
> > };
> >
> > connector@1 {
> > port@1 {
> > endpoint@0 {
> > remote-endpoint = <&usb_hub_1_hs>;
> > };
> > };
> > };
> > };
> >
> > dp_bridge {
> > ports {
> > port@1 {
> > dp_bridge_out_0: endpoint@0 {
> > remote-endpoint = <&typec_dp0_in>;
> > data-lanes = <0 1>;
> > };
> >
> > dp_bridge_out_1: endpoint@1 {
> > remote-endpoint = <&typec_dp1_in>;
> > data-lanes = <2 3>;
> > };
> > };
> > };
> > };
> >
> > -------
> >
> > I wonder about a case where we may take two lanes and connect them to a
> > usb-c-connector and then take the other two lanes and send them through
> > a mux to two more usb-c-connectors. I think we'll need another property
> > in that case that indicates which input DP endpoints correspond to the
> > usb-c-connector nodes.
> >
> > typec {
> > ports {
> > port@0 {
> > reg = <0>;
> > typec_dp0_in: endpoint@0 {
> > reg = <0>;
> > remote-endpoint = <&dp_bridge_out_0>;
> > };
> > typec_dp1_in: endpoint@1 {
> > reg = <1>;
> > remote-endpoint = <&dp_bridge_out_1>;
> > };
> > };
> >
> > port@1 {
> > reg = <1>;
> > typec_usb0_in: endpoint@0 {
> > reg = <0>;
> > remote-endpoint = <&usb_hub_0_ss>;
> > };
> > typec_usb1_in: endpoint@1 {
> > reg = <1>;
> > remote-endpoint = <&usb_hub_1_ss>;
> > };
> > typec_usb2_in: endpoint@2 {
> > reg = <2>;
> > remote-endpoint = <&usb_hub_2_ss>;
> > };
> > }
> > };
> >
> > dp-2-usb-mapping = <0 0>, <1 1>, <1 2>;
>
> dp-to-typec-mapping?
Sure
>
> > };
> >
> > This property would indicate dp endpoint 0 goes to usb-c-connector 0
> > while dp endpoint 1 goes to usb-c-connector 1 and 2. I don't have this
> > hardware but I could see how someone might do this by adding another mux
> > that the EC controls. I don't want to design a binding and have to
> > rework it in the future to handle this new case. I hope adding a new
> > property, or getting more information from the EC firmware, will be
> > sufficient to describe the linkage between the DP endpoint and the
> > connectors managed by the cros-ec-typec device.
>
> Does it change anything from the DP point of view? It is still either
> lanes 0-1 or lanes 2-3? I'd really like to inject the hotplug OOB event
> to the dp_bridge letting it get one of the endpoints as a HPD even
> source.
Nothing changes from the DP point of view. I understand that you want
the bridge to see one of its endpoints as the 'connector_fwnode' passed
to oob_hotplug_event().
>
> > > > Corsola could work with this design, but we'll need to teach
> > > > dp_altmode_probe() to look for the drm_bridge elsewhere besides as the
> > > > parent of the usb-c-connector node. That implies using the 'displayport'
> > > > property in the cros-ec-typec node or teaching dp_altmode_probe() to
> > > > look for the port@1/endpoint@1 remote-endpoint handle in the
> > > > usb-c-connector graph.
> > > >
> > > > Assuming the bindings you've presented here are fine and good and I got
> > > > over the differences between Trogdor and Corsola, then I can make mostly
> > > > everything work with the drm_connector_oob_hotplug_event() signature
> > > > change from above and some tweaks to dp_altmode_probe() to look for
> > > > port@1/endpoint@1 first because that's the "logical" DP input endpoint
> > > > in the usb-c-connector binding's graph. Great! The final roadblock I'm
> > > > at is that HPD doesn't work on Trogdor, so I can't signal HPD through
> > > > the typec framework.
> > >
> > > Hmm, I thought that a normal DP's HPD GPIO works on the trogdor. Was I
> > > misunderstanding it? But then we don't know, which USB-C connector
> > > triggered the HPD...
> >
> > By HPD not working on Trogdor I mean that the EC doesn't tell the kernel
> > about the state of HPD for a usb-c-connector in software. Instead, HPD
> > is signaled directly to the DP controller in hardware via a GPIO. It is
> > as you suspect, we don't know which USB-C connector has HPD unless we
> > read the mux controlled by the EC and combine that with what the DP
> > driver knows about the state of the HPD pin.
>
> I see. So the HPD event gets delivered to the DP controller, but we
> really need some API to read the port? If it's not the
> orientation-switch, of course.
Yes. This is needed to understand what USB type-c connector the DP
signals should go to. In the case of Corsola/IT6505 it's needed to know
which two lanes should be sent if both type-c connectors/ports are
capable of DP altmode. On Corsola, the EC could tell the kernel that
both ports are in DP altmode but the EC is also controlling the AUX
channel mux that decides which usb-c-connector type-c port is actually
displaying DP.
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
2024-10-31 21:45 ` Stephen Boyd
@ 2024-10-31 22:54 ` Dmitry Baryshkov
2024-11-08 0:28 ` Stephen Boyd
0 siblings, 1 reply; 60+ messages in thread
From: Dmitry Baryshkov @ 2024-10-31 22:54 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring
On Thu, Oct 31, 2024 at 02:45:29PM -0700, Stephen Boyd wrote:
> Quoting Dmitry Baryshkov (2024-10-31 11:42:36)
> > On Tue, Oct 29, 2024 at 01:15:51PM -0700, Stephen Boyd wrote:
> > > At this point we need to tell the DP bridge, like IT6505, that it's one
> > > or the other output endpoints that it should use, but we haven't
> > > directly connected the usb-c-connector to the output ports of IT6505
> > > because drm_of_find_panel_or_bridge() can't find the parent of the
> > > usb-c-connector if we connect the DP bridge to the usb-c-connector
> > > graphs. We'll need a way for the bridge to know which output port is
> > > connected to a usb-c-connector fwnode. Some sort of API like
> >
> > I think that the final bridge should be the IT6505. It can save you from
> > some troubles, like the inter-bridge lane negotiation. Please remember
> > that using lanes 2-3 as primary lanes doesn't seem to fall into the
> > standard DisplayPort usage. It is documented by USB-C and only because
> > of the orientation switching.
>
> If the final bridge is IT6505 then drm_of_find_panel_or_bridge() isn't
> called and I think we're OK. But then we have to traverse the
> remote-endpoint of the usb-c-connector to IT6505 in displayport.c in the
> Corsola case while knowing to look at the parent of the usb-c-connector
> node and traversing the remote-endpoint to the QMP phy in the Trogdor
> case. The logic in dp_altmode_probe() is like
>
> if (port@1/endpoint@1 exists in usb-c-connector)
> connector_fwnode = port@1/endpoint@1/remote-endpoint
> else if (cros-ec-typec/port exists)
> connector_fwnode = cros-ec-typec/port@0/endpoint/remote-endpoint
> else
> original stuff
I'd say, definitely ugh. Maybe we can add the swnode with the
"displayport" property pointing back to the DP bridge / endpoint.
But... read below.
> If we have the crazy three usb-c-connector design it can still work
> because we'd have something like
>
> cros-ec-typec {
> port {
> dp_endpoint: endpoint {
> remote-endpoint = <&dp_ml0_ml1>;
> };
> };
>
> usb-c-connector@0 {
> port@1 {
> endpoint {
> remote-endpoint = <&hub_ss0>;
> };
> // Implicitly dp_ml0_ml1
> };
> };
> usb-c-connector@1 {
> port@1 {
> endpoint@0 {
> remote-endpoint = <&hub_ss1>;
> };
> endpoint@1 {
> remote-endpoint = <&dp_ml2_ml3>;
> };
> };
> };
> usb-c-connector@2 {
> port@1 {
> endpoint {
> remote-endpoint = <&hub_ss2>;
> };
> // Implicitly dp_ml0_ml1
> };
> };
> };
>
> (I like thinking about this 3 connector case because it combines both
> Trogdor and Corsola designs so I can talk about both cases at the same
> time)
>
> I don't know what happens when we have 4 connectors though, with 2 going
> to one pair of lanes and 2 going to the other 2 lanes. Maybe it's better
> to always have a DP input port in cros-ec-typec to avoid this problem
> and map back to the endpoint explicitly.
>
> cros-ec-typec {
> port {
> dp_endpoint0: endpoint@0 {
> remote-endpoint = <&dp_ml0_ml1>;
> };
> dp_endpoint1: endpoint@1 {
> remote-endpoint = <&dp_ml2_ml3>;
> };
> };
>
> usb-c-connector@0 {
> port@1 {
> endpoint@0 {
> remote-endpoint = <&hub_ss0>;
> };
> endpoint@1 {
> remote-endpoint = <&dp_endpoint0>;
> };
> };
> };
> usb-c-connector@1 {
> port@1 {
> endpoint@0 {
> remote-endpoint = <&hub_ss1>;
> };
> endpoint@1 {
> remote-endpoint = <&dp_endpoint1>;
> };
> };
> };
> usb-c-connector@2 {
> port@1 {
> endpoint@0 {
> remote-endpoint = <&hub_ss2>;
> };
> endpoint@1 {
> remote-endpoint = <&dp_endpoint1>;
> };
> };
> };
> };
>
> Or use a displayport property that goes to connector node itself so that
> we don't extend the graph binding of the usb-c-connector.
>
> cros-ec-typec {
> usb-c-connector@0 {
> altmodes {
> displayport {
> connector = <&dp_ml0_ml1>;
I think this has been frowned upon. Not exactly this, but adding the
displayport = <&foo>.
Thus it can only go to the swnode that is generated in software by the
cros-ec driver.
> };
> };
> port@1 {
> endpoint@0 {
> remote-endpoint = <&hub_ss0>;
> };
> };
> };
> usb-c-connector@1 {
> altmodes {
> displayport {
> connector = <&dp_ml2_ml3>;
> };
> };
> port@1 {
> endpoint {
> remote-endpoint = <&hub_ss1>;
> };
> };
> };
> usb-c-connector@2 {
> altmodes {
> displayport {
> connector = <&dp_ml2_ml3>;
> };
> };
> port@1 {
> endpoint {
> remote-endpoint = <&hub_ss2>;
> };
> };
> };
> };
>
> it6505 {
> ports {
> port@1 {
> dp_ml0_ml1: endpoint@0 {
> remote-endpoint = <??>;
> };
> dp_ml2_ml3: endpoint@1 {
> remote-endpoint = <??>;
> };
> };
> };
> };
>
> The logic could look at a node like usb-c-connector@2, find
> altmodes/display node, and look for a 'connector' property that points
> at the endpoint of the last bridge. If we don't use the OF graph binding
> it makes it easier to point at the same endpoint in the QMP phy or the
> IT6505 graph from more than one usb-c-connector. This also makes it very
> clear that we intend to pass that fwnode as the 'connector_fwnode' to
> oob_hotplug_event().
>
> If we want to actually populate the 'remote-endpoint' property of IT6505
> we will need to make a graph in cros-ec-typec.
>
> cros-ec-typec {
> port {
> dp_endpoint0: endpoint@0 {
> remote-endpoint = <&dp_ml0_ml1>;
> };
> dp_endpoint1: endpoint@1 {
> remote-endpoint = <&dp_ml2_ml3>;
> };
> };
> usb-c-connector@0 {
> altmodes {
> displayport {
> connector = <&dp_endpoint0>;
> };
> };
> port@1 {
> endpoint@0 {
> remote-endpoint = <&hub_ss0>;
> };
> };
> };
> usb-c-connector@1 {
> altmodes {
> displayport {
> connector = <&dp_endpoint1>;
> };
> };
> port@1 {
> endpoint {
> remote-endpoint = <&hub_ss1>;
> };
> };
> };
> usb-c-connector@2 {
> altmodes {
> displayport {
> connector = <&dp_endpoint1>;
> };
> };
> port@1 {
> endpoint {
> remote-endpoint = <&hub_ss2>;
> };
> };
> };
> };
>
> it6505 {
> ports {
> port@1 {
> dp_ml0_ml1: endpoint@0 {
> remote-endpoint = <dp_endpoint0>;
> };
> dp_ml2_ml3: endpoint@1 {
> remote-endpoint = <dp_endpoint1>;
> };
> };
> };
> };
>
> and then the logic in displayport.c will have to check if the
> 'connector' property points at a graph endpoint, traverse that to the
> remote-endpoint, and consider that the connector_fwnode.
>
> >
> > Maybe that's just it? Register DP_bridge (or QMP PHY) as
> > orientation-switch? Then you don't need any extra API for the lane
> > mapping? The cross-ec-typec can provide orientation information and the
> > USB-C-aware controller will follow the lane mapping.
>
> I'm not really following but I don't think the DT binding discussed here
> prevents that.
I'm thinking about:
it6505 {
orientation-switch;
ports {
port@1 {
it6505_dp_out: remote-endpoint = <&cros_ec_dp>;
data-lanes = <0 1>;
};
};
};
cros-ec {
port {
cross_ec_dp: remote-endpoint = <&it6505_dp_out>;
};
connector@0 {
reg = <0>;
cros,dp-orientation = "normal";
ports {
// all USB HS and SS ports as usual;
};
};
connector@1 {
reg = <1>;
cros,dp-orientation = "reverse";
ports {
// all USB HS and SS ports as usual;
};
};
connector@2 {
reg = <2>;
cros,dp-orientation = "reverse";
ports {
// all USB HS and SS ports as usual;
};
};
connector@3 {
reg = <3>;
cros,dp-orientation = "normal";
ports {
// all USB HS and SS ports as usual;
};
};
};
The cros-ec registers single drm bridge which will generate HPD events
except on Trogdor, etc. At the same time, cros-ec requests the
typec_switch_get(). When the cros-ec detects that the connector@N it
being used for DP, it just generates corresponding typec_switch_set()
call, setting the orientation of the it6505 (or QMP PHY). The rest can
be handled either by EC's HPD code or by DP's HPD handler, the
orientation should already be a correct one.
So, yes. It requires adding the typec_switch_desc implementation _in_
the it6505 (or in any other component which handles the 0-1 or 2-3
selection). On the other hand as I wrote previously, the 0-1 / 2-3 is
the USB-C functionality, not the DP one.
[...]
>
> >
> > > > > Corsola could work with this design, but we'll need to teach
> > > > > dp_altmode_probe() to look for the drm_bridge elsewhere besides as the
> > > > > parent of the usb-c-connector node. That implies using the 'displayport'
> > > > > property in the cros-ec-typec node or teaching dp_altmode_probe() to
> > > > > look for the port@1/endpoint@1 remote-endpoint handle in the
> > > > > usb-c-connector graph.
> > > > >
> > > > > Assuming the bindings you've presented here are fine and good and I got
> > > > > over the differences between Trogdor and Corsola, then I can make mostly
> > > > > everything work with the drm_connector_oob_hotplug_event() signature
> > > > > change from above and some tweaks to dp_altmode_probe() to look for
> > > > > port@1/endpoint@1 first because that's the "logical" DP input endpoint
> > > > > in the usb-c-connector binding's graph. Great! The final roadblock I'm
> > > > > at is that HPD doesn't work on Trogdor, so I can't signal HPD through
> > > > > the typec framework.
> > > >
> > > > Hmm, I thought that a normal DP's HPD GPIO works on the trogdor. Was I
> > > > misunderstanding it? But then we don't know, which USB-C connector
> > > > triggered the HPD...
> > >
> > > By HPD not working on Trogdor I mean that the EC doesn't tell the kernel
> > > about the state of HPD for a usb-c-connector in software. Instead, HPD
> > > is signaled directly to the DP controller in hardware via a GPIO. It is
> > > as you suspect, we don't know which USB-C connector has HPD unless we
> > > read the mux controlled by the EC and combine that with what the DP
> > > driver knows about the state of the HPD pin.
> >
> > I see. So the HPD event gets delivered to the DP controller, but we
> > really need some API to read the port? If it's not the
> > orientation-switch, of course.
>
> Yes. This is needed to understand what USB type-c connector the DP
> signals should go to. In the case of Corsola/IT6505 it's needed to know
> which two lanes should be sent if both type-c connectors/ports are
> capable of DP altmode. On Corsola, the EC could tell the kernel that
> both ports are in DP altmode but the EC is also controlling the AUX
> channel mux that decides which usb-c-connector type-c port is actually
> displaying DP.
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
2024-10-31 22:54 ` Dmitry Baryshkov
@ 2024-11-08 0:28 ` Stephen Boyd
2024-11-09 7:05 ` Dmitry Baryshkov
0 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-11-08 0:28 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring
Quoting Dmitry Baryshkov (2024-10-31 15:54:49)
> On Thu, Oct 31, 2024 at 02:45:29PM -0700, Stephen Boyd wrote:
> > Quoting Dmitry Baryshkov (2024-10-31 11:42:36)
> > > On Tue, Oct 29, 2024 at 01:15:51PM -0700, Stephen Boyd wrote:
> >
> > Or use a displayport property that goes to connector node itself so that
> > we don't extend the graph binding of the usb-c-connector.
> >
> > cros-ec-typec {
> > usb-c-connector@0 {
> > altmodes {
> > displayport {
> > connector = <&dp_ml0_ml1>;
>
> I think this has been frowned upon. Not exactly this, but adding the
> displayport = <&foo>.
Do you have a pointer to that discussion? I'd like to understand the
reasoning.
>
> Thus it can only go to the swnode that is generated in software by the
> cros-ec driver.
I recall swnode as a way to sidestep figuring out the DT bindings for
usb typec. Where is this swnode being made? Somewhere inside the typec
framework?
>
> > };
> > };
> > port@1 {
> > endpoint@0 {
> > remote-endpoint = <&hub_ss0>;
> > };
> > };
> > };
> > usb-c-connector@1 {
> > altmodes {
> > displayport {
> > connector = <&dp_ml2_ml3>;
> > };
> > };
> > port@1 {
> > endpoint {
[....]
> >
> > >
> > > Maybe that's just it? Register DP_bridge (or QMP PHY) as
> > > orientation-switch? Then you don't need any extra API for the lane
> > > mapping? The cross-ec-typec can provide orientation information and the
> > > USB-C-aware controller will follow the lane mapping.
> >
> > I'm not really following but I don't think the DT binding discussed here
> > prevents that.
>
> I'm thinking about:
>
> it6505 {
> orientation-switch;
>
> ports {
> port@1 {
> it6505_dp_out: remote-endpoint = <&cros_ec_dp>;
> data-lanes = <0 1>;
> };
> };
> };
>
> cros-ec {
> port {
> cross_ec_dp: remote-endpoint = <&it6505_dp_out>;
> };
>
> connector@0 {
> reg = <0>;
> cros,dp-orientation = "normal";
>
> ports {
> // all USB HS and SS ports as usual;
> };
> };
>
> connector@1 {
> reg = <1>;
> cros,dp-orientation = "reverse";
>
> ports {
> // all USB HS and SS ports as usual;
> };
> };
>
> connector@2 {
> reg = <2>;
> cros,dp-orientation = "reverse";
>
> ports {
> // all USB HS and SS ports as usual;
> };
> };
>
> connector@3 {
> reg = <3>;
> cros,dp-orientation = "normal";
>
> ports {
> // all USB HS and SS ports as usual;
> };
> };
> };
>
> The cros-ec registers single drm bridge which will generate HPD events
> except on Trogdor, etc. At the same time, cros-ec requests the
> typec_switch_get(). When the cros-ec detects that the connector@N it
> being used for DP, it just generates corresponding typec_switch_set()
> call, setting the orientation of the it6505 (or QMP PHY). The rest can
> be handled either by EC's HPD code or by DP's HPD handler, the
> orientation should already be a correct one.
>
> So, yes. It requires adding the typec_switch_desc implementation _in_
> the it6505 (or in any other component which handles the 0-1 or 2-3
> selection). On the other hand as I wrote previously, the 0-1 / 2-3 is
> the USB-C functionality, not the DP one.
>
I don't think we should be adding typec code to pure display hardware
drivers like IT6505. To keep the driver focused on display stuff I
proposed implementing runtime lane assignment for drm_bridge chains
because DP has lanes. My understanding is that not all display
technologies have lanes, so implementing generic lane assignment
functionality is overkill/incorrect. DP has physical lanes in hardware
though, and those physical lanes are assigned to certain pins in the
type-c DP altmode spec, so it's not overkill to think about lanes when
the bridge is a DP bridge wired up to a type-c connector.
Long story short, I don't see how we can avoid _any_ lane assignment
logic in drm_bridge. The logic shouldn't walk the entire bridge chain,
but it should at least act on the bridge that is a DP bridge. I think
you're saying pretty much the same thing here, but you want the lane
remapping to be done via the typec layer whereas I want it to be done in
the drm_bridge layer. To me it looks out of place to add a
typec_switch_desc inside each DP drm_bridge because we duplicate the
logic about USB type-c DP altmode lane assignment to each DP bridge. A
DP bridge should just think about DP and not know or care about USB
type-c.
This is what's leading me to think we need some sort of lane assignment
capability at the DP connector. How that assignment flows from the DP
connector created in drm_bridge_connector.c to the hardware is where it
is less clear to me. Should that be implemented as a typec_switch_desc,
essentially out of band with drm_bridge, or as some drm_bridge_funcs
function similar to struct drm_bridge_funcs::hdmi_*()? If you look at
IT6505 in it6505_get_extcon_property() it actually wants to pull the
orientation of the type-c port with extcon_get_property(EXTCON_DISP_DP,
EXTCON_PROP_USB_TYPEC_POLARITY). Maybe pushing the orientation to the DP
bridge is backwards and we should be exposing this as some sort of
connector API that the drm_bridge can query whenever it wants.
What about ANX7625 where two DP lanes go to a cross-point switch before
leaving the chip on one of two pairs of lanes? This hardware is a DP
bridge smashed together with an orientation switch (typec_switch_desc)
so that you can simply wire the output pins up to a USB type-c connector
and support 2 lanes DP altmode. Qualcomm's QMP phy is quite similar.
Presumably we'd want the ANX driver to implement both a drm_bridge and a
typec_switch_desc if it was directly connected to a usb-c-connector
node. It's also interesting to think of the DT binding here, likely we
would have one output port in the ANX node's graph that represents the
combined DP and USB data that's connected to the SuperSpeed endpoint in
the usb-c-connector.
In the case where two lanes are wired to one USB type-c connector and
the other two lanes are wired to a different USB type-c connector it
would be odd to keep the typec_switch_desc and figure out a way to
mangle the lanes we want for a USB type-c connector by setting the
orientation of the typec_switch_desc. The chip isn't really acting as a
typec orientation control here because it isn't combining USB data and
DP data for a single USB type-c port. In fact, the type-c port has an
orientation and we actively don't want to tell the ANX7625 driver about
that port orientation because the orientation control is implemented
between the ANX part and the type-c connector by some redriver
controlled by the EC.
To satisfy all these cases it almost feels like we need to make the DP
connector have an "orientation", per your earlier DT snippet it would be
"reversed" or "normal", even though in hardware a DP connector has no
such concept because it can only be plugged in one way. All cases look
to be covered if we say that the drm_connector can have an orientation,
"normal" or "reversed", and we allow the bridge drivers to query that
whenever they want with some bridge/connector API. The typical case will
be that the orientation is normal, but we can make
drm_connector_oob_hotplug_event() change that to "reversed" when the
port is different.
This leaves us with the binding you propose above, and then some sort of
property that indicates the orientation of the DP connector. Instead of
being vendor specific I wonder if we can simply have a property like
"dp-reverse-orientation" in the connector node that the displayport.c
driver can look for to set the connector orientation to the reverse one
when DP altmode is entered on the port.
This is what I have:
it6505 {
ports {
port@1 {
it6505_dp_out: remote-endpoint = <&cros_ec_dp>;
data-lanes = <0 1>;
};
};
};
cros-ec {
port {
cross_ec_dp: remote-endpoint = <&it6505_dp_out>;
};
connector@0 {
reg = <0>;
ports {
// all USB HS and SS ports as usual;
};
};
connector@1 {
reg = <1>;
dp-reverse-orientation;
ports {
// all USB HS and SS ports as usual;
};
};
or ANX, swap out for it6505 node:
anx7625 {
ports {
port@1 {
anx7625_dp_out: remote-endpoint = <&cros_ec_dp>;
data-lanes = <0 1>;
};
};
};
and then a drm_bridge is created in cros-ec to terminate the bridge
chain. The displayport altmode driver will find the drm_bridge and the
drm_connector from the cros-ec node. When DP altmode is entered the
displayport altmode driver will set the drm_connector orientation based
on the presence of the dp-reverse-orientation property. We'll be able to
hook the hpd_notify() path in cros-ec by adding code to the drm_bridge
made there to do the HPD workaround. I'm not sure we need to use an
auxiliary device in this case, because it's a one-off solution for
cros-ec. And we don't even need to signal HPD from the cros-ec
drm_bridge because the oob_hotplug event will do it for us. If anything,
we need that displayport.c code to skip sending the hotplug event when
"no-hpd" is present in the cros-ec node. Note, this works for any number
of usb-c-connector nodes. And finally, DP bridges like IT6505 don't need
to implement a typec_switch_desc, they can simply support flipping the
orientation by querying the drm_connector for the bridge chain when they
see fit. ANX7625 can support that as well when it doesn't see the
'orientation-switch' property.
Did I miss anything? I suspect a drm_connector having an orientation is
the most controversial part of this proposal.
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
2024-11-08 0:28 ` Stephen Boyd
@ 2024-11-09 7:05 ` Dmitry Baryshkov
2024-11-12 2:16 ` Stephen Boyd
0 siblings, 1 reply; 60+ messages in thread
From: Dmitry Baryshkov @ 2024-11-09 7:05 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring
On Thu, Nov 07, 2024 at 04:28:24PM -0800, Stephen Boyd wrote:
> Quoting Dmitry Baryshkov (2024-10-31 15:54:49)
> > On Thu, Oct 31, 2024 at 02:45:29PM -0700, Stephen Boyd wrote:
> > > Quoting Dmitry Baryshkov (2024-10-31 11:42:36)
> > > > On Tue, Oct 29, 2024 at 01:15:51PM -0700, Stephen Boyd wrote:
> > >
> > > Or use a displayport property that goes to connector node itself so that
> > > we don't extend the graph binding of the usb-c-connector.
> > >
> > > cros-ec-typec {
> > > usb-c-connector@0 {
> > > altmodes {
> > > displayport {
> > > connector = <&dp_ml0_ml1>;
> >
> > I think this has been frowned upon. Not exactly this, but adding the
> > displayport = <&foo>.
>
> Do you have a pointer to that discussion? I'd like to understand the
> reasoning.
No, unfortunately I couldn't find it.
>
>
> >
> > Thus it can only go to the swnode that is generated in software by the
> > cros-ec driver.
>
> I recall swnode as a way to sidestep figuring out the DT bindings for
> usb typec. Where is this swnode being made? Somewhere inside the typec
> framework?
In the cros-ec driver?
>
> >
> > > };
> > > };
> > > port@1 {
> > > endpoint@0 {
> > > remote-endpoint = <&hub_ss0>;
> > > };
> > > };
> > > };
> > > usb-c-connector@1 {
> > > altmodes {
> > > displayport {
> > > connector = <&dp_ml2_ml3>;
> > > };
> > > };
> > > port@1 {
> > > endpoint {
> [....]
> > >
> > > >
> > > > Maybe that's just it? Register DP_bridge (or QMP PHY) as
> > > > orientation-switch? Then you don't need any extra API for the lane
> > > > mapping? The cross-ec-typec can provide orientation information and the
> > > > USB-C-aware controller will follow the lane mapping.
> > >
> > > I'm not really following but I don't think the DT binding discussed here
> > > prevents that.
> >
> > I'm thinking about:
> >
> > it6505 {
> > orientation-switch;
> >
> > ports {
> > port@1 {
> > it6505_dp_out: remote-endpoint = <&cros_ec_dp>;
> > data-lanes = <0 1>;
> > };
> > };
> > };
> >
> > cros-ec {
> > port {
> > cross_ec_dp: remote-endpoint = <&it6505_dp_out>;
> > };
> >
> > connector@0 {
> > reg = <0>;
> > cros,dp-orientation = "normal";
> >
> > ports {
> > // all USB HS and SS ports as usual;
> > };
> > };
> >
> > connector@1 {
> > reg = <1>;
> > cros,dp-orientation = "reverse";
> >
> > ports {
> > // all USB HS and SS ports as usual;
> > };
> > };
> >
> > connector@2 {
> > reg = <2>;
> > cros,dp-orientation = "reverse";
> >
> > ports {
> > // all USB HS and SS ports as usual;
> > };
> > };
> >
> > connector@3 {
> > reg = <3>;
> > cros,dp-orientation = "normal";
> >
> > ports {
> > // all USB HS and SS ports as usual;
> > };
> > };
> > };
> >
> > The cros-ec registers single drm bridge which will generate HPD events
> > except on Trogdor, etc. At the same time, cros-ec requests the
> > typec_switch_get(). When the cros-ec detects that the connector@N it
> > being used for DP, it just generates corresponding typec_switch_set()
> > call, setting the orientation of the it6505 (or QMP PHY). The rest can
> > be handled either by EC's HPD code or by DP's HPD handler, the
> > orientation should already be a correct one.
> >
> > So, yes. It requires adding the typec_switch_desc implementation _in_
> > the it6505 (or in any other component which handles the 0-1 or 2-3
> > selection). On the other hand as I wrote previously, the 0-1 / 2-3 is
> > the USB-C functionality, not the DP one.
> >
>
> I don't think we should be adding typec code to pure display hardware
> drivers like IT6505. To keep the driver focused on display stuff I
> proposed implementing runtime lane assignment for drm_bridge chains
> because DP has lanes. My understanding is that not all display
> technologies have lanes, so implementing generic lane assignment
> functionality is overkill/incorrect. DP has physical lanes in hardware
> though, and those physical lanes are assigned to certain pins in the
> type-c DP altmode spec, so it's not overkill to think about lanes when
> the bridge is a DP bridge wired up to a type-c connector.
DisplayPort has fixed lanes assignment in the standard. So any driver
that reassigns / reallocates DisplayPort lanes dynamically implements
Type-C functionality.
> Long story short, I don't see how we can avoid _any_ lane assignment
> logic in drm_bridge. The logic shouldn't walk the entire bridge chain,
> but it should at least act on the bridge that is a DP bridge. I think
> you're saying pretty much the same thing here, but you want the lane
> remapping to be done via the typec layer whereas I want it to be done in
> the drm_bridge layer. To me it looks out of place to add a
> typec_switch_desc inside each DP drm_bridge because we duplicate the
> logic about USB type-c DP altmode lane assignment to each DP bridge. A
> DP bridge should just think about DP and not know or care about USB
> type-c.
>
> This is what's leading me to think we need some sort of lane assignment
> capability at the DP connector. How that assignment flows from the DP
> connector created in drm_bridge_connector.c to the hardware is where it
> is less clear to me. Should that be implemented as a typec_switch_desc,
> essentially out of band with drm_bridge, or as some drm_bridge_funcs
> function similar to struct drm_bridge_funcs::hdmi_*()? If you look at
> IT6505 in it6505_get_extcon_property() it actually wants to pull the
> orientation of the type-c port with extcon_get_property(EXTCON_DISP_DP,
> EXTCON_PROP_USB_TYPEC_POLARITY). Maybe pushing the orientation to the DP
> bridge is backwards and we should be exposing this as some sort of
> connector API that the drm_bridge can query whenever it wants.
And it6505_get_extcon_property() / EXTCON_PROP_USB_TYPEC_POLARITY is a
Type-C code, isn't it?
> What about ANX7625 where two DP lanes go to a cross-point switch before
> leaving the chip on one of two pairs of lanes? This hardware is a DP
> bridge smashed together with an orientation switch (typec_switch_desc)
> so that you can simply wire the output pins up to a USB type-c connector
> and support 2 lanes DP altmode. Qualcomm's QMP phy is quite similar.
> Presumably we'd want the ANX driver to implement both a drm_bridge and a
> typec_switch_desc if it was directly connected to a usb-c-connector
> node. It's also interesting to think of the DT binding here, likely we
> would have one output port in the ANX node's graph that represents the
> combined DP and USB data that's connected to the SuperSpeed endpoint in
> the usb-c-connector.
>
> In the case where two lanes are wired to one USB type-c connector and
> the other two lanes are wired to a different USB type-c connector it
> would be odd to keep the typec_switch_desc and figure out a way to
> mangle the lanes we want for a USB type-c connector by setting the
> orientation of the typec_switch_desc. The chip isn't really acting as a
> typec orientation control here because it isn't combining USB data and
> DP data for a single USB type-c port. In fact, the type-c port has an
> orientation and we actively don't want to tell the ANX7625 driver about
> that port orientation because the orientation control is implemented
> between the ANX part and the type-c connector by some redriver
> controlled by the EC.
>
> To satisfy all these cases it almost feels like we need to make the DP
> connector have an "orientation", per your earlier DT snippet it would be
> "reversed" or "normal", even though in hardware a DP connector has no
> such concept because it can only be plugged in one way. All cases look
> to be covered if we say that the drm_connector can have an orientation,
> "normal" or "reversed", and we allow the bridge drivers to query that
> whenever they want with some bridge/connector API. The typical case will
> be that the orientation is normal, but we can make
> drm_connector_oob_hotplug_event() change that to "reversed" when the
> port is different.
The DP connector doesn't have the orientation, as you pointed out. Only
Type-C does.
>
> This leaves us with the binding you propose above, and then some sort of
> property that indicates the orientation of the DP connector. Instead of
> being vendor specific I wonder if we can simply have a property like
> "dp-reverse-orientation" in the connector node that the displayport.c
> driver can look for to set the connector orientation to the reverse one
> when DP altmode is entered on the port.
>
> This is what I have:
>
> it6505 {
> ports {
> port@1 {
> it6505_dp_out: remote-endpoint = <&cros_ec_dp>;
> data-lanes = <0 1>;
> };
> };
> };
>
> cros-ec {
> port {
> cross_ec_dp: remote-endpoint = <&it6505_dp_out>;
> };
>
> connector@0 {
> reg = <0>;
>
> ports {
> // all USB HS and SS ports as usual;
> };
> };
>
> connector@1 {
> reg = <1>;
> dp-reverse-orientation;
>
> ports {
> // all USB HS and SS ports as usual;
> };
> };
>
> or ANX, swap out for it6505 node:
>
> anx7625 {
> ports {
> port@1 {
> anx7625_dp_out: remote-endpoint = <&cros_ec_dp>;
> data-lanes = <0 1>;
> };
> };
> };
>
> and then a drm_bridge is created in cros-ec to terminate the bridge
> chain. The displayport altmode driver will find the drm_bridge and the
> drm_connector from the cros-ec node. When DP altmode is entered the
> displayport altmode driver will set the drm_connector orientation based
> on the presence of the dp-reverse-orientation property. We'll be able to
> hook the hpd_notify() path in cros-ec by adding code to the drm_bridge
> made there to do the HPD workaround. I'm not sure we need to use an
> auxiliary device in this case, because it's a one-off solution for
> cros-ec. And we don't even need to signal HPD from the cros-ec
> drm_bridge because the oob_hotplug event will do it for us. If anything,
> we need that displayport.c code to skip sending the hotplug event when
> "no-hpd" is present in the cros-ec node. Note, this works for any number
> of usb-c-connector nodes. And finally, DP bridges like IT6505 don't need
> to implement a typec_switch_desc, they can simply support flipping the
> orientation by querying the drm_connector for the bridge chain when they
> see fit. ANX7625 can support that as well when it doesn't see the
> 'orientation-switch' property.
>
> Did I miss anything? I suspect a drm_connector having an orientation is
> the most controversial part of this proposal.
Yes... I understand that having orientation-switch handling in the DRM
driver sounds strange, but this is what we do in the QMP PHY driver. It
makes the code easier, as it keeps lane remapping local to the place
where it belongs - to the Type-C handlers.
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
2024-11-09 7:05 ` Dmitry Baryshkov
@ 2024-11-12 2:16 ` Stephen Boyd
2024-11-15 17:17 ` Dmitry Baryshkov
0 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-11-12 2:16 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring
Quoting Dmitry Baryshkov (2024-11-08 23:05:18)
> On Thu, Nov 07, 2024 at 04:28:24PM -0800, Stephen Boyd wrote:
> > Quoting Dmitry Baryshkov (2024-10-31 15:54:49)
> > > On Thu, Oct 31, 2024 at 02:45:29PM -0700, Stephen Boyd wrote:
> > > > Quoting Dmitry Baryshkov (2024-10-31 11:42:36)
> > > > > On Tue, Oct 29, 2024 at 01:15:51PM -0700, Stephen Boyd wrote:
> > Long story short, I don't see how we can avoid _any_ lane assignment
> > logic in drm_bridge. The logic shouldn't walk the entire bridge chain,
> > but it should at least act on the bridge that is a DP bridge. I think
> > you're saying pretty much the same thing here, but you want the lane
> > remapping to be done via the typec layer whereas I want it to be done in
> > the drm_bridge layer. To me it looks out of place to add a
> > typec_switch_desc inside each DP drm_bridge because we duplicate the
> > logic about USB type-c DP altmode lane assignment to each DP bridge. A
> > DP bridge should just think about DP and not know or care about USB
> > type-c.
> >
> > This is what's leading me to think we need some sort of lane assignment
> > capability at the DP connector. How that assignment flows from the DP
> > connector created in drm_bridge_connector.c to the hardware is where it
> > is less clear to me. Should that be implemented as a typec_switch_desc,
> > essentially out of band with drm_bridge, or as some drm_bridge_funcs
> > function similar to struct drm_bridge_funcs::hdmi_*()? If you look at
> > IT6505 in it6505_get_extcon_property() it actually wants to pull the
> > orientation of the type-c port with extcon_get_property(EXTCON_DISP_DP,
> > EXTCON_PROP_USB_TYPEC_POLARITY). Maybe pushing the orientation to the DP
> > bridge is backwards and we should be exposing this as some sort of
> > connector API that the drm_bridge can query whenever it wants.
>
> And it6505_get_extcon_property() / EXTCON_PROP_USB_TYPEC_POLARITY is a
> Type-C code, isn't it?
>
Sort of? It's combining DP and USB_TYPEC enums there so it's not very
clear if it's one or the other instead of just both.
> > and then a drm_bridge is created in cros-ec to terminate the bridge
> > chain. The displayport altmode driver will find the drm_bridge and the
> > drm_connector from the cros-ec node. When DP altmode is entered the
> > displayport altmode driver will set the drm_connector orientation based
> > on the presence of the dp-reverse-orientation property. We'll be able to
> > hook the hpd_notify() path in cros-ec by adding code to the drm_bridge
> > made there to do the HPD workaround. I'm not sure we need to use an
> > auxiliary device in this case, because it's a one-off solution for
> > cros-ec. And we don't even need to signal HPD from the cros-ec
> > drm_bridge because the oob_hotplug event will do it for us. If anything,
> > we need that displayport.c code to skip sending the hotplug event when
> > "no-hpd" is present in the cros-ec node. Note, this works for any number
> > of usb-c-connector nodes. And finally, DP bridges like IT6505 don't need
> > to implement a typec_switch_desc, they can simply support flipping the
> > orientation by querying the drm_connector for the bridge chain when they
> > see fit. ANX7625 can support that as well when it doesn't see the
> > 'orientation-switch' property.
> >
> > Did I miss anything? I suspect a drm_connector having an orientation is
> > the most controversial part of this proposal.
>
> Yes... I understand that having orientation-switch handling in the DRM
> driver sounds strange, but this is what we do in the QMP PHY driver. It
> makes the code easier, as it keeps lane remapping local to the place
> where it belongs - to the Type-C handlers.
>
The QMP PHY is a type-c PHY, similar to ANX7625. It sits on the output
of the DP and USB PHYs and handles the type-c orientation and lane
merging for different USB type-c alternate modes. It's not a great
example of a plain DP bridge because it combines USB and USB type-c
features.
Either way, doing this through Type-C handlers is weird because the port
orientation in the Type-C framework is for the connector and there is an
orientation control hardware that handles the orientation already. For
example, with the IT6505 part on Corsola, the orientation is controlled
by a redriver part that the EC controls. It takes the DP and USB signals
and routes them to the correct pins on the usb-c-connector depending on
the cable orientation. The input side pinout is basically 2 or 4 lanes
DP and 2 lanes USB and the output side pinout is the USB type-c pinout
SSTXRX1 and SSTXRX2.
This redriver is equivalent to the QMP PHY type-c part. Maybe to bring
this example closer to QMP we can imagine if the QMP PHY was split into
two pairs of lanes, and the USB functionality wasn't used. The
orientation control for a usb-c-connector would be on a redriver that
takes 2 DP lanes from the QMP PHY as input. Saying that this QMP PHY is
the "orientation-switch" with that property in DT is confusing, because
it isn't controlling the orientation of the type-c port. The orientation
is handled by the redriver. That redriver may even be controlled by the
kernel as an orientation-switch.
I understand that the QMP PHY driver has implemented the lane control
for orientation with a typec_switch_desc, but the QMP PHY is a plain DP
PHY in this scenario. How would the type-c handlers work here? We
couldn't call them through the type-c framework as far as I can tell.
This is why I'm thinking the end of the bridge chain needs to have some
sort of orientation. If we had that then the place where the chain ends
and becomes muxed onto the usb-c-connector, i.e. the redriver, would be
where the DP bridge is told that it needs to flip the lanes. In the
cases I have, the redriver is the EC, and so we've combined them all
together in one node, cros-ec-typec. In the QMP PHY case the redriver is
the QMP PHY type-c part that sits on the DP and USB PHYs and sends their
signals out of the SoC.
Maybe the DT property in the ANX7625 or IT6505 node should be something
like "dp-orientation-switch" and then we have the type-c framework find
this property? Then we would need to add support for that property in
IT6505 using a typec_switch_desc, which is weird. I guess it all feels
like a hack because it's not always the case that the DP PHY is glued to
a USB type-c PHY.
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
2024-11-12 2:16 ` Stephen Boyd
@ 2024-11-15 17:17 ` Dmitry Baryshkov
2024-11-20 1:09 ` Stephen Boyd
0 siblings, 1 reply; 60+ messages in thread
From: Dmitry Baryshkov @ 2024-11-15 17:17 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring
On Mon, Nov 11, 2024 at 06:16:27PM -0800, Stephen Boyd wrote:
> Quoting Dmitry Baryshkov (2024-11-08 23:05:18)
> > On Thu, Nov 07, 2024 at 04:28:24PM -0800, Stephen Boyd wrote:
> > > Quoting Dmitry Baryshkov (2024-10-31 15:54:49)
> > > > On Thu, Oct 31, 2024 at 02:45:29PM -0700, Stephen Boyd wrote:
> > > > > Quoting Dmitry Baryshkov (2024-10-31 11:42:36)
> > > > > > On Tue, Oct 29, 2024 at 01:15:51PM -0700, Stephen Boyd wrote:
> > > Long story short, I don't see how we can avoid _any_ lane assignment
> > > logic in drm_bridge. The logic shouldn't walk the entire bridge chain,
> > > but it should at least act on the bridge that is a DP bridge. I think
> > > you're saying pretty much the same thing here, but you want the lane
> > > remapping to be done via the typec layer whereas I want it to be done in
> > > the drm_bridge layer. To me it looks out of place to add a
> > > typec_switch_desc inside each DP drm_bridge because we duplicate the
> > > logic about USB type-c DP altmode lane assignment to each DP bridge. A
> > > DP bridge should just think about DP and not know or care about USB
> > > type-c.
> > >
> > > This is what's leading me to think we need some sort of lane assignment
> > > capability at the DP connector. How that assignment flows from the DP
> > > connector created in drm_bridge_connector.c to the hardware is where it
> > > is less clear to me. Should that be implemented as a typec_switch_desc,
> > > essentially out of band with drm_bridge, or as some drm_bridge_funcs
> > > function similar to struct drm_bridge_funcs::hdmi_*()? If you look at
> > > IT6505 in it6505_get_extcon_property() it actually wants to pull the
> > > orientation of the type-c port with extcon_get_property(EXTCON_DISP_DP,
> > > EXTCON_PROP_USB_TYPEC_POLARITY). Maybe pushing the orientation to the DP
> > > bridge is backwards and we should be exposing this as some sort of
> > > connector API that the drm_bridge can query whenever it wants.
> >
> > And it6505_get_extcon_property() / EXTCON_PROP_USB_TYPEC_POLARITY is a
> > Type-C code, isn't it?
> >
>
> Sort of? It's combining DP and USB_TYPEC enums there so it's not very
> clear if it's one or the other instead of just both.
But EXTCON_PROP_USB_TYPEC_POLARITY is just a Type-C, nothing about DP in it.
>
> > > and then a drm_bridge is created in cros-ec to terminate the bridge
> > > chain. The displayport altmode driver will find the drm_bridge and the
> > > drm_connector from the cros-ec node. When DP altmode is entered the
> > > displayport altmode driver will set the drm_connector orientation based
> > > on the presence of the dp-reverse-orientation property. We'll be able to
> > > hook the hpd_notify() path in cros-ec by adding code to the drm_bridge
> > > made there to do the HPD workaround. I'm not sure we need to use an
> > > auxiliary device in this case, because it's a one-off solution for
> > > cros-ec. And we don't even need to signal HPD from the cros-ec
> > > drm_bridge because the oob_hotplug event will do it for us. If anything,
> > > we need that displayport.c code to skip sending the hotplug event when
> > > "no-hpd" is present in the cros-ec node. Note, this works for any number
> > > of usb-c-connector nodes. And finally, DP bridges like IT6505 don't need
> > > to implement a typec_switch_desc, they can simply support flipping the
> > > orientation by querying the drm_connector for the bridge chain when they
> > > see fit. ANX7625 can support that as well when it doesn't see the
> > > 'orientation-switch' property.
> > >
> > > Did I miss anything? I suspect a drm_connector having an orientation is
> > > the most controversial part of this proposal.
> >
> > Yes... I understand that having orientation-switch handling in the DRM
> > driver sounds strange, but this is what we do in the QMP PHY driver. It
> > makes the code easier, as it keeps lane remapping local to the place
> > where it belongs - to the Type-C handlers.
> >
>
> The QMP PHY is a type-c PHY, similar to ANX7625. It sits on the output
> of the DP and USB PHYs and handles the type-c orientation and lane
> merging for different USB type-c alternate modes. It's not a great
> example of a plain DP bridge because it combines USB and USB type-c
> features.
>
> Either way, doing this through Type-C handlers is weird because the port
> orientation in the Type-C framework is for the connector and there is an
> orientation control hardware that handles the orientation already. For
> example, with the IT6505 part on Corsola, the orientation is controlled
> by a redriver part that the EC controls. It takes the DP and USB signals
> and routes them to the correct pins on the usb-c-connector depending on
> the cable orientation. The input side pinout is basically 2 or 4 lanes
> DP and 2 lanes USB and the output side pinout is the USB type-c pinout
> SSTXRX1 and SSTXRX2.
>
> This redriver is equivalent to the QMP PHY type-c part. Maybe to bring
> this example closer to QMP we can imagine if the QMP PHY was split into
> two pairs of lanes, and the USB functionality wasn't used. The
> orientation control for a usb-c-connector would be on a redriver that
> takes 2 DP lanes from the QMP PHY as input. Saying that this QMP PHY is
> the "orientation-switch" with that property in DT is confusing, because
> it isn't controlling the orientation of the type-c port. The orientation
> is handled by the redriver. That redriver may even be controlled by the
> kernel as an orientation-switch.
This is clear.
>
> I understand that the QMP PHY driver has implemented the lane control
> for orientation with a typec_switch_desc, but the QMP PHY is a plain DP
> PHY in this scenario. How would the type-c handlers work here? We
> couldn't call them through the type-c framework as far as I can tell.
If QMP PHY is a plain DP PHY, it usually has no support for lane remapping
(e.g. phy-qcom-edp doesn't).
Let me reiterate, please: lane management is outside of the DisplayPort
spec, at least as far as I can understand it. All lane remapping
(especially a dynamic one) is a pure vendor extension to the standard.
I'm trying to find a way to support Corsola and Trogdor without adding
"this is done specially for Google" kind of API. Usually that doesn't
fly in the long term.
I understand that using Type-C API for the DRM bridge sounds strange.
But even the mentioned bridge uses Type-C API. It asks for the Type-C
polarity, not the DP polarity.
> This is why I'm thinking the end of the bridge chain needs to have some
> sort of orientation. If we had that then the place where the chain ends
> and becomes muxed onto the usb-c-connector, i.e. the redriver, would be
> where the DP bridge is told that it needs to flip the lanes. In the
> cases I have, the redriver is the EC, and so we've combined them all
> together in one node, cros-ec-typec. In the QMP PHY case the redriver is
> the QMP PHY type-c part that sits on the DP and USB PHYs and sends their
> signals out of the SoC.
>
> Maybe the DT property in the ANX7625 or IT6505 node should be something
> like "dp-orientation-switch" and then we have the type-c framework find
> this property? Then we would need to add support for that property in
> IT6505 using a typec_switch_desc, which is weird. I guess it all feels
> like a hack because it's not always the case that the DP PHY is glued to
> a USB type-c PHY.
I think just "orientation-switch" is enough. In the end it's not a
"typec-orientation-switch".
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
2024-11-15 17:17 ` Dmitry Baryshkov
@ 2024-11-20 1:09 ` Stephen Boyd
2024-11-21 22:59 ` Dmitry Baryshkov
0 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-11-20 1:09 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring
Quoting Dmitry Baryshkov (2024-11-15 09:17:15)
> On Mon, Nov 11, 2024 at 06:16:27PM -0800, Stephen Boyd wrote:
> > Quoting Dmitry Baryshkov (2024-11-08 23:05:18)
> > > On Thu, Nov 07, 2024 at 04:28:24PM -0800, Stephen Boyd wrote:
> > > > Quoting Dmitry Baryshkov (2024-10-31 15:54:49)
> > > > > On Thu, Oct 31, 2024 at 02:45:29PM -0700, Stephen Boyd wrote:
> > > > > > Quoting Dmitry Baryshkov (2024-10-31 11:42:36)
> > > > > > > On Tue, Oct 29, 2024 at 01:15:51PM -0700, Stephen Boyd wrote:
> > > > Long story short, I don't see how we can avoid _any_ lane assignment
> > > > logic in drm_bridge. The logic shouldn't walk the entire bridge chain,
> > > > but it should at least act on the bridge that is a DP bridge. I think
> > > > you're saying pretty much the same thing here, but you want the lane
> > > > remapping to be done via the typec layer whereas I want it to be done in
> > > > the drm_bridge layer. To me it looks out of place to add a
> > > > typec_switch_desc inside each DP drm_bridge because we duplicate the
> > > > logic about USB type-c DP altmode lane assignment to each DP bridge. A
> > > > DP bridge should just think about DP and not know or care about USB
> > > > type-c.
> > > >
> > > > This is what's leading me to think we need some sort of lane assignment
> > > > capability at the DP connector. How that assignment flows from the DP
> > > > connector created in drm_bridge_connector.c to the hardware is where it
> > > > is less clear to me. Should that be implemented as a typec_switch_desc,
> > > > essentially out of band with drm_bridge, or as some drm_bridge_funcs
> > > > function similar to struct drm_bridge_funcs::hdmi_*()? If you look at
> > > > IT6505 in it6505_get_extcon_property() it actually wants to pull the
> > > > orientation of the type-c port with extcon_get_property(EXTCON_DISP_DP,
> > > > EXTCON_PROP_USB_TYPEC_POLARITY). Maybe pushing the orientation to the DP
> > > > bridge is backwards and we should be exposing this as some sort of
> > > > connector API that the drm_bridge can query whenever it wants.
> > >
> > > And it6505_get_extcon_property() / EXTCON_PROP_USB_TYPEC_POLARITY is a
> > > Type-C code, isn't it?
> > >
> >
> > Sort of? It's combining DP and USB_TYPEC enums there so it's not very
> > clear if it's one or the other instead of just both.
>
> But EXTCON_PROP_USB_TYPEC_POLARITY is just a Type-C, nothing about DP in it.
It's extcon_get_property(it6505->extcon, EXTCON_DISP_DP,
EXTCON_PROP_USB_TYPEC_POLARITY, ...) which has EXTCON_DISP_DP in there,
so there's something about DP there. That's all I'm saying.
> >
> > I understand that the QMP PHY driver has implemented the lane control
> > for orientation with a typec_switch_desc, but the QMP PHY is a plain DP
> > PHY in this scenario. How would the type-c handlers work here? We
> > couldn't call them through the type-c framework as far as I can tell.
>
> If QMP PHY is a plain DP PHY, it usually has no support for lane remapping
> (e.g. phy-qcom-edp doesn't).
>
> Let me reiterate, please: lane management is outside of the DisplayPort
> spec, at least as far as I can understand it. All lane remapping
> (especially a dynamic one) is a pure vendor extension to the standard.
> I'm trying to find a way to support Corsola and Trogdor without adding
> "this is done specially for Google" kind of API. Usually that doesn't
> fly in the long term.
Got it.
>
> I understand that using Type-C API for the DRM bridge sounds strange.
> But even the mentioned bridge uses Type-C API. It asks for the Type-C
> polarity, not the DP polarity.
>
I understand that lane assignment isn't part of the DisplayPort spec,
while it is part of the USB Type-C DisplayPort Altmode spec.
I'm not entirely convinced that lane assignment is _only_ part of the
altmode spec and should be implemented with a typec switch though,
because I imagine some hardware design could be created that has two
DisplayPort connectors, just like these two USB-C connectors, and some
sort of HPD redriver logic similar to the EC that decides which DP port
"wins" and should have DP sent to it. Or perhaps 2 lanes DP to a DP
connector and 2 lanes DP sent to a DP to HDMI bridge (shudder). In
either case, USB type-c isn't involved.
It sounds like we're debating how to handle lane assignment in the
kernel. Either way, the code is going to be implemented in the bridge
driver because it's the one that has to change what physical lane a
logical lane is assigned to. The question is if it should be some sort
of bridge_funcs callback, or should bridge drivers hook into the typec
framework to expose an orientation switch, or something else?
I'm thinking we should introduce some sort of bridge_funcs callback that
can be called from the DP altmode driver, either parallel to the
drm_connector_oob_hotplug_event() function or from it directly. If we
can pass the fwnode for the usb-c-connector to the oob_hotplug_event
callback, maybe that's all we need to figure out which lanes go where.
And then in the 2 DP connector muxing world we can call
drm_connector_oob_hotplug_event() with one or the other DP connector
node, which will likely be children nodes of the "HPD redriver" device.
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
2024-11-20 1:09 ` Stephen Boyd
@ 2024-11-21 22:59 ` Dmitry Baryshkov
2024-12-03 23:50 ` Stephen Boyd
0 siblings, 1 reply; 60+ messages in thread
From: Dmitry Baryshkov @ 2024-11-21 22:59 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring
On Tue, Nov 19, 2024 at 08:09:31PM -0500, Stephen Boyd wrote:
> Quoting Dmitry Baryshkov (2024-11-15 09:17:15)
> > On Mon, Nov 11, 2024 at 06:16:27PM -0800, Stephen Boyd wrote:
> > > Quoting Dmitry Baryshkov (2024-11-08 23:05:18)
> > > > On Thu, Nov 07, 2024 at 04:28:24PM -0800, Stephen Boyd wrote:
> > > > > Quoting Dmitry Baryshkov (2024-10-31 15:54:49)
> > > > > > On Thu, Oct 31, 2024 at 02:45:29PM -0700, Stephen Boyd wrote:
> > > > > > > Quoting Dmitry Baryshkov (2024-10-31 11:42:36)
> > > > > > > > On Tue, Oct 29, 2024 at 01:15:51PM -0700, Stephen Boyd wrote:
> > > > > Long story short, I don't see how we can avoid _any_ lane assignment
> > > > > logic in drm_bridge. The logic shouldn't walk the entire bridge chain,
> > > > > but it should at least act on the bridge that is a DP bridge. I think
> > > > > you're saying pretty much the same thing here, but you want the lane
> > > > > remapping to be done via the typec layer whereas I want it to be done in
> > > > > the drm_bridge layer. To me it looks out of place to add a
> > > > > typec_switch_desc inside each DP drm_bridge because we duplicate the
> > > > > logic about USB type-c DP altmode lane assignment to each DP bridge. A
> > > > > DP bridge should just think about DP and not know or care about USB
> > > > > type-c.
> > > > >
> > > > > This is what's leading me to think we need some sort of lane assignment
> > > > > capability at the DP connector. How that assignment flows from the DP
> > > > > connector created in drm_bridge_connector.c to the hardware is where it
> > > > > is less clear to me. Should that be implemented as a typec_switch_desc,
> > > > > essentially out of band with drm_bridge, or as some drm_bridge_funcs
> > > > > function similar to struct drm_bridge_funcs::hdmi_*()? If you look at
> > > > > IT6505 in it6505_get_extcon_property() it actually wants to pull the
> > > > > orientation of the type-c port with extcon_get_property(EXTCON_DISP_DP,
> > > > > EXTCON_PROP_USB_TYPEC_POLARITY). Maybe pushing the orientation to the DP
> > > > > bridge is backwards and we should be exposing this as some sort of
> > > > > connector API that the drm_bridge can query whenever it wants.
> > > >
> > > > And it6505_get_extcon_property() / EXTCON_PROP_USB_TYPEC_POLARITY is a
> > > > Type-C code, isn't it?
> > > >
> > >
> > > Sort of? It's combining DP and USB_TYPEC enums there so it's not very
> > > clear if it's one or the other instead of just both.
> >
> > But EXTCON_PROP_USB_TYPEC_POLARITY is just a Type-C, nothing about DP in it.
>
> It's extcon_get_property(it6505->extcon, EXTCON_DISP_DP,
> EXTCON_PROP_USB_TYPEC_POLARITY, ...) which has EXTCON_DISP_DP in there,
> so there's something about DP there. That's all I'm saying.
>
> > >
> > > I understand that the QMP PHY driver has implemented the lane control
> > > for orientation with a typec_switch_desc, but the QMP PHY is a plain DP
> > > PHY in this scenario. How would the type-c handlers work here? We
> > > couldn't call them through the type-c framework as far as I can tell.
> >
> > If QMP PHY is a plain DP PHY, it usually has no support for lane remapping
> > (e.g. phy-qcom-edp doesn't).
> >
> > Let me reiterate, please: lane management is outside of the DisplayPort
> > spec, at least as far as I can understand it. All lane remapping
> > (especially a dynamic one) is a pure vendor extension to the standard.
> > I'm trying to find a way to support Corsola and Trogdor without adding
> > "this is done specially for Google" kind of API. Usually that doesn't
> > fly in the long term.
>
> Got it.
>
> >
> > I understand that using Type-C API for the DRM bridge sounds strange.
> > But even the mentioned bridge uses Type-C API. It asks for the Type-C
> > polarity, not the DP polarity.
> >
>
> I understand that lane assignment isn't part of the DisplayPort spec,
> while it is part of the USB Type-C DisplayPort Altmode spec.
>
> I'm not entirely convinced that lane assignment is _only_ part of the
> altmode spec
just to clarify: I'm only talking about a dynamic lane management here.
If the DP bridge hardware supports remapping lanes in a weird way and
board designers decided to use that "feature", then having a property
linke data-lanes = <2 1 3 0>; makes perfect sense to me.
> and should be implemented with a typec switch though,
> because I imagine some hardware design could be created that has two
> DisplayPort connectors, just like these two USB-C connectors, and some
> sort of HPD redriver logic similar to the EC that decides which DP port
> "wins" and should have DP sent to it. Or perhaps 2 lanes DP to a DP
> connector and 2 lanes DP sent to a DP to HDMI bridge (shudder). In
> either case, USB type-c isn't involved.
/me keeps fingers crossed that hw designers won't do such a thing
But I see your point.
>
> It sounds like we're debating how to handle lane assignment in the
> kernel. Either way, the code is going to be implemented in the bridge
> driver because it's the one that has to change what physical lane a
> logical lane is assigned to. The question is if it should be some sort
> of bridge_funcs callback, or should bridge drivers hook into the typec
> framework to expose an orientation switch, or something else?
I was assuming that orientation switch is such kind of a hook.
>
> I'm thinking we should introduce some sort of bridge_funcs callback that
> can be called from the DP altmode driver, either parallel to the
> drm_connector_oob_hotplug_event() function or from it directly. If we
> can pass the fwnode for the usb-c-connector to the oob_hotplug_event
> callback, maybe that's all we need to figure out which lanes go where.
> And then in the 2 DP connector muxing world we can call
> drm_connector_oob_hotplug_event() with one or the other DP connector
> node, which will likely be children nodes of the "HPD redriver" device.
If you call it from drm_bridge_connector's oob_hotplug_event handler,
this should fly. Does it cover your 3-DP or 4-DP usecases?
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
2024-11-21 22:59 ` Dmitry Baryshkov
@ 2024-12-03 23:50 ` Stephen Boyd
2024-12-05 18:47 ` Dmitry Baryshkov
0 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-12-03 23:50 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring
Quoting Dmitry Baryshkov (2024-11-21 14:59:42)
> On Tue, Nov 19, 2024 at 08:09:31PM -0500, Stephen Boyd wrote:
> >
> > It sounds like we're debating how to handle lane assignment in the
> > kernel. Either way, the code is going to be implemented in the bridge
> > driver because it's the one that has to change what physical lane a
> > logical lane is assigned to. The question is if it should be some sort
> > of bridge_funcs callback, or should bridge drivers hook into the typec
> > framework to expose an orientation switch, or something else?
>
> I was assuming that orientation switch is such kind of a hook.
>
> >
> > I'm thinking we should introduce some sort of bridge_funcs callback that
> > can be called from the DP altmode driver, either parallel to the
> > drm_connector_oob_hotplug_event() function or from it directly. If we
> > can pass the fwnode for the usb-c-connector to the oob_hotplug_event
> > callback, maybe that's all we need to figure out which lanes go where.
> > And then in the 2 DP connector muxing world we can call
> > drm_connector_oob_hotplug_event() with one or the other DP connector
> > node, which will likely be children nodes of the "HPD redriver" device.
>
> If you call it from drm_bridge_connector's oob_hotplug_event handler,
> this should fly. Does it cover your 3-DP or 4-DP usecases?
>
I think it will work as long as we're able to add some sort of property
to the usb-c-connector node to indicate that the DP lanes are flipped.
It feels like that should be in the displayport altmode node to keep
things tidy because the SuperSpeed port is overloaded. Maybe the drm
framework can have some API that can take the fwnode from the
oob_hotplug_event handler and tell the bridge driver which way the
orientation is.
connector {
compatible = "usb-c-connector";
altmodes {
displayport {
orientation-reversed;
}
};
ports {
...
};
};
int drm_dp_typec_orientation_flipped(struct fwnode_handle *fwnode)
{
struct fwnode_handle *altmodes;
struct fwnode_handle *dp;
altmodes = fwnode_get_named_child_node(fwnode, "altmodes");
if (!altmodes)
return -EINVAL;
dp = fwnode_get_named_child_node(altmodes, "displayport");
if (!dp)
return -EINVAL;
if (fwnode_property_read_bool(dp, "orientation-reversed"))
return 1;
return 0;
}
There's another wrinkle on some Corsola devices where the EC says
there's a usb-c-connector on the board, but in reality the DP lanes are
connected to a DP-to-HDMI bridge that is controlled by the EC which goes
to an HDMI connector on the side of the laptop. The EC does the
arbitration as usual because there's only one DP source and one or two
usb type-c connectors physically on the laptop in addition to the HDMI
connector.
The easiest way to imagine this is that we took the usb-c-connector and
jammed an HDMI dongle in there with some glue so that it can never be
removed. There isn't any USB going there either because it can't be
used. I suppose we can continue to describe this with an
altmodes/displayport node but then add some compatible like
"usb-c-hdmi-connector" or another property to the altmodes/displayport
node like "type = hdmi" that signifies this is a connector that only
outputs HDMI.
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
2024-12-03 23:50 ` Stephen Boyd
@ 2024-12-05 18:47 ` Dmitry Baryshkov
2024-12-11 21:11 ` Stephen Boyd
0 siblings, 1 reply; 60+ messages in thread
From: Dmitry Baryshkov @ 2024-12-05 18:47 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring
On Tue, Dec 03, 2024 at 03:50:58PM -0800, Stephen Boyd wrote:
> Quoting Dmitry Baryshkov (2024-11-21 14:59:42)
> > On Tue, Nov 19, 2024 at 08:09:31PM -0500, Stephen Boyd wrote:
> > >
> > > It sounds like we're debating how to handle lane assignment in the
> > > kernel. Either way, the code is going to be implemented in the bridge
> > > driver because it's the one that has to change what physical lane a
> > > logical lane is assigned to. The question is if it should be some sort
> > > of bridge_funcs callback, or should bridge drivers hook into the typec
> > > framework to expose an orientation switch, or something else?
> >
> > I was assuming that orientation switch is such kind of a hook.
> >
> > >
> > > I'm thinking we should introduce some sort of bridge_funcs callback that
> > > can be called from the DP altmode driver, either parallel to the
> > > drm_connector_oob_hotplug_event() function or from it directly. If we
> > > can pass the fwnode for the usb-c-connector to the oob_hotplug_event
> > > callback, maybe that's all we need to figure out which lanes go where.
> > > And then in the 2 DP connector muxing world we can call
> > > drm_connector_oob_hotplug_event() with one or the other DP connector
> > > node, which will likely be children nodes of the "HPD redriver" device.
> >
> > If you call it from drm_bridge_connector's oob_hotplug_event handler,
> > this should fly. Does it cover your 3-DP or 4-DP usecases?
> >
>
> I think it will work as long as we're able to add some sort of property
> to the usb-c-connector node to indicate that the DP lanes are flipped.
> It feels like that should be in the displayport altmode node to keep
> things tidy because the SuperSpeed port is overloaded. Maybe the drm
> framework can have some API that can take the fwnode from the
> oob_hotplug_event handler and tell the bridge driver which way the
> orientation is.
>
> connector {
> compatible = "usb-c-connector";
>
> altmodes {
> displayport {
> orientation-reversed;
> }
> };
>
> ports {
> ...
> };
> };
>
>
> int drm_dp_typec_orientation_flipped(struct fwnode_handle *fwnode)
> {
> struct fwnode_handle *altmodes;
> struct fwnode_handle *dp;
>
> altmodes = fwnode_get_named_child_node(fwnode, "altmodes");
> if (!altmodes)
> return -EINVAL;
>
> dp = fwnode_get_named_child_node(altmodes, "displayport");
> if (!dp)
> return -EINVAL;
>
> if (fwnode_property_read_bool(dp, "orientation-reversed"))
> return 1;
If that passes through DT maintainers, that's fine with me.
>
> return 0;
> }
>
> There's another wrinkle on some Corsola devices where the EC says
> there's a usb-c-connector on the board, but in reality the DP lanes are
> connected to a DP-to-HDMI bridge that is controlled by the EC which goes
> to an HDMI connector on the side of the laptop. The EC does the
> arbitration as usual because there's only one DP source and one or two
> usb type-c connectors physically on the laptop in addition to the HDMI
> connector.
>
> The easiest way to imagine this is that we took the usb-c-connector and
> jammed an HDMI dongle in there with some glue so that it can never be
> removed. There isn't any USB going there either because it can't be
> used. I suppose we can continue to describe this with an
> altmodes/displayport node but then add some compatible like
> "usb-c-hdmi-connector" or another property to the altmodes/displayport
> node like "type = hdmi" that signifies this is a connector that only
> outputs HDMI.
Does that DP-to-HDMI bridge talk USB-C or just pure DP? In other words,
will it be properly discovered and handled if we just leave it as a
weird usb-c-connector (maybe with an additional annotation, we have
USB_PORT_CONNECT_TYPE_HARD_WIRED for USB ports, we might have something
similar for Type-C connectors).
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
2024-12-05 18:47 ` Dmitry Baryshkov
@ 2024-12-11 21:11 ` Stephen Boyd
2024-12-11 21:16 ` Dmitry Baryshkov
0 siblings, 1 reply; 60+ messages in thread
From: Stephen Boyd @ 2024-12-11 21:11 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring
Quoting Dmitry Baryshkov (2024-12-05 10:47:08)
> On Tue, Dec 03, 2024 at 03:50:58PM -0800, Stephen Boyd wrote:
> >
> > The easiest way to imagine this is that we took the usb-c-connector and
> > jammed an HDMI dongle in there with some glue so that it can never be
> > removed. There isn't any USB going there either because it can't be
> > used. I suppose we can continue to describe this with an
> > altmodes/displayport node but then add some compatible like
> > "usb-c-hdmi-connector" or another property to the altmodes/displayport
> > node like "type = hdmi" that signifies this is a connector that only
> > outputs HDMI.
>
> Does that DP-to-HDMI bridge talk USB-C or just pure DP? In other words,
> will it be properly discovered and handled if we just leave it as a
> weird usb-c-connector (maybe with an additional annotation, we have
> USB_PORT_CONNECT_TYPE_HARD_WIRED for USB ports, we might have something
> similar for Type-C connectors).
It is pure DP. Maybe we can have a google,cros-ec-usbc-hdmi compatible
string here because this is a weird design.
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
2024-12-11 21:11 ` Stephen Boyd
@ 2024-12-11 21:16 ` Dmitry Baryshkov
2024-12-11 21:21 ` Stephen Boyd
0 siblings, 1 reply; 60+ messages in thread
From: Dmitry Baryshkov @ 2024-12-11 21:16 UTC (permalink / raw)
To: Stephen Boyd
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring
On Wed, 11 Dec 2024 at 23:11, Stephen Boyd <swboyd@chromium.org> wrote:
>
> Quoting Dmitry Baryshkov (2024-12-05 10:47:08)
> > On Tue, Dec 03, 2024 at 03:50:58PM -0800, Stephen Boyd wrote:
> > >
> > > The easiest way to imagine this is that we took the usb-c-connector and
> > > jammed an HDMI dongle in there with some glue so that it can never be
> > > removed. There isn't any USB going there either because it can't be
> > > used. I suppose we can continue to describe this with an
> > > altmodes/displayport node but then add some compatible like
> > > "usb-c-hdmi-connector" or another property to the altmodes/displayport
> > > node like "type = hdmi" that signifies this is a connector that only
> > > outputs HDMI.
> >
> > Does that DP-to-HDMI bridge talk USB-C or just pure DP? In other words,
> > will it be properly discovered and handled if we just leave it as a
> > weird usb-c-connector (maybe with an additional annotation, we have
> > USB_PORT_CONNECT_TYPE_HARD_WIRED for USB ports, we might have something
> > similar for Type-C connectors).
>
> It is pure DP. Maybe we can have a google,cros-ec-usbc-hdmi compatible
> string here because this is a weird design.
Just google,cros-ec-hdmi for the corresponding connector?
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode
2024-12-11 21:16 ` Dmitry Baryshkov
@ 2024-12-11 21:21 ` Stephen Boyd
0 siblings, 0 replies; 60+ messages in thread
From: Stephen Boyd @ 2024-12-11 21:21 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: chrome-platform, linux-kernel, patches, devicetree,
Douglas Anderson, Pin-yen Lin, Andrzej Hajda, Benson Leung,
Conor Dooley, Daniel Vetter, David Airlie, dri-devel,
Guenter Roeck, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
Laurent Pinchart, Lee Jones, Maarten Lankhorst, Maxime Ripard,
Neil Armstrong, Prashant Malani, Robert Foss, Rob Herring,
Thomas Zimmermann, Tzung-Bi Shih, Alexandre Belloni,
Andy Shevchenko, Daniel Scally, Greg Kroah-Hartman,
Heikki Krogerus, Ivan Orlov, linux-acpi, linux-usb,
Mika Westerberg, Rafael J . Wysocki, Sakari Ailus, Vinod Koul,
Rob Herring
Quoting Dmitry Baryshkov (2024-12-11 13:16:56)
> On Wed, 11 Dec 2024 at 23:11, Stephen Boyd <swboyd@chromium.org> wrote:
> >
> > It is pure DP. Maybe we can have a google,cros-ec-usbc-hdmi compatible
> > string here because this is a weird design.
>
> Just google,cros-ec-hdmi for the corresponding connector?
>
Sure.
^ permalink raw reply [flat|nested] 60+ messages in thread
end of thread, other threads:[~2024-12-11 21:21 UTC | newest]
Thread overview: 60+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-01 4:06 [PATCH v4 00/18] platform/chrome: Add DT USB/DP muxing/topology support Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 01/18] drm/atomic-helper: Introduce lane remapping support to bridges Stephen Boyd
2024-09-20 13:41 ` Dmitry Baryshkov
2024-09-01 4:06 ` [PATCH v4 02/18] drm/bridge: Verify lane assignment is going to work during atomic_check Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 03/18] usb: typec: Stub out typec_switch APIs when CONFIG_TYPEC=n Stephen Boyd
2024-09-03 11:40 ` Heikki Krogerus
2024-09-19 10:12 ` Dmitry Baryshkov
2024-09-01 4:06 ` [PATCH v4 04/18] usb: typec: Add device managed typec_mux_register() Stephen Boyd
2024-09-03 11:57 ` Heikki Krogerus
2024-09-01 4:06 ` [PATCH v4 05/18] usb: typec: Add device managed typec_switch_register() Stephen Boyd
2024-09-02 11:22 ` Andy Shevchenko
2024-09-01 4:06 ` [PATCH v4 06/18] drm/bridge: aux-hpd: Support USB Type-C DP altmodes via DRM lane assignment Stephen Boyd
2024-09-02 11:35 ` Andy Shevchenko
2024-09-03 22:20 ` Stephen Boyd
2024-09-04 13:00 ` Andy Shevchenko
2024-09-04 17:17 ` Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 07/18] drm/bridge: dp_typec: Support USB Type-C orientation Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 08/18] drm/bridge: dp_typec: Add "no-hpd" support Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 09/18] drm/bridge: dp_typec: Allow users to hook hpd notify path Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 10/18] devcon property: Document devcon_match_fn_t Stephen Boyd
2024-09-02 11:17 ` Andy Shevchenko
2024-09-03 22:35 ` Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 11/18] device property: Add remote endpoint to devcon matcher Stephen Boyd
2024-09-02 11:12 ` Andy Shevchenko
2024-09-03 22:49 ` Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 12/18] dt-bindings: usb-switch: Extract endpoints to defs Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 13/18] dt-bindings: usb-switch: Extend for DisplayPort altmode Stephen Boyd
2024-09-19 10:40 ` Dmitry Baryshkov
2024-10-10 22:43 ` Stephen Boyd
2024-10-25 6:36 ` Dmitry Baryshkov
2024-09-01 4:06 ` [PATCH v4 14/18] dt-bindings: Move google,cros-ec-typec binding to usb Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 15/18] dt-bindings: usb: Add ports to google,cros-ec-typec for DP altmode Stephen Boyd
2024-09-03 15:35 ` Lee Jones
2024-09-20 9:38 ` Dmitry Baryshkov
2024-10-23 1:15 ` Stephen Boyd
2024-10-25 10:49 ` Dmitry Baryshkov
2024-10-29 20:15 ` Stephen Boyd
2024-10-31 18:42 ` Dmitry Baryshkov
2024-10-31 21:45 ` Stephen Boyd
2024-10-31 22:54 ` Dmitry Baryshkov
2024-11-08 0:28 ` Stephen Boyd
2024-11-09 7:05 ` Dmitry Baryshkov
2024-11-12 2:16 ` Stephen Boyd
2024-11-15 17:17 ` Dmitry Baryshkov
2024-11-20 1:09 ` Stephen Boyd
2024-11-21 22:59 ` Dmitry Baryshkov
2024-12-03 23:50 ` Stephen Boyd
2024-12-05 18:47 ` Dmitry Baryshkov
2024-12-11 21:11 ` Stephen Boyd
2024-12-11 21:16 ` Dmitry Baryshkov
2024-12-11 21:21 ` Stephen Boyd
2024-09-01 4:06 ` [PATCH v4 16/18] platform/chrome: cros_ec_typec: Add support for signaling DP HPD via drm_bridge Stephen Boyd
2024-09-04 9:35 ` Tzung-Bi Shih
2024-09-01 4:06 ` [PATCH v4 17/18] platform/chrome: cros_ec_typec: Support DP muxing Stephen Boyd
2024-09-04 9:36 ` Tzung-Bi Shih
2024-09-01 4:06 ` [PATCH v4 18/18] platform/chrome: cros_ec_typec: Handle lack of HPD information Stephen Boyd
2024-09-04 9:36 ` Tzung-Bi Shih
2024-09-04 21:45 ` Stephen Boyd
2024-09-06 8:18 ` Tzung-Bi Shih
2024-09-06 23:22 ` Stephen Boyd
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).