The TC358767/TC358867/TC9595 are all capable of operating in multiple
modes, DPI-to-(e)DP, DSI-to-(e)DP, DSI-to-DPI. Only the first mode is
currently supported. It is possible to find out the mode in which the
bridge should be operated by testing connected endpoints in DT.

Port allocation:
port@0 - DSI input
port@1 - DPI input/output
port@2 - eDP output

Possible connections:
DPI -> port@1 -> port@2 -> eDP :: [port@0 is not connected]
DSI -> port@0 -> port@2 -> eDP :: [port@1 is not connected]
DSI -> port@0 -> port@1 -> DPI :: [port@2 is not connected]

Add function to determine the bridge mode based on connected endpoints.

Signed-off-by: Marek Vasut <ma...@denx.de>
Cc: Jonas Karlman <jo...@kwiboo.se>
Cc: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
Cc: Maxime Ripard <max...@cerno.tech>
Cc: Neil Armstrong <narmstr...@baylibre.com>
Cc: Sam Ravnborg <s...@ravnborg.org>
---
V2: - New patch
---
 drivers/gpu/drm/bridge/tc358767.c | 46 ++++++++++++++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/tc358767.c 
b/drivers/gpu/drm/bridge/tc358767.c
index 7dae18de76c97..4af0ad5db2148 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -1684,6 +1684,50 @@ static int tc_probe_edp_bridge_endpoint(struct tc_data 
*tc)
        return ret;
 }
 
+static int tc_probe_bridge_endpoint(struct tc_data *tc)
+{
+       struct device *dev = tc->dev;
+       struct of_endpoint endpoint;
+       struct device_node *node = NULL;
+       const u8 mode_dpi_to_edp = BIT(1) | BIT(2);
+       const u8 mode_dsi_to_edp = BIT(0) | BIT(2);
+       const u8 mode_dsi_to_dpi = BIT(0) | BIT(1);
+       u8 mode = 0;
+
+       /*
+        * Determine bridge configuration.
+        *
+        * Port allocation:
+        * port@0 - DSI input
+        * port@1 - DPI input/output
+        * port@2 - eDP output
+        *
+        * Possible connections:
+        * DPI -> port@1 -> port@2 -> eDP :: [port@0 is not connected]
+        * DSI -> port@0 -> port@2 -> eDP :: [port@1 is not connected]
+        * DSI -> port@0 -> port@1 -> DPI :: [port@2 is not connected]
+        */
+
+       for_each_endpoint_of_node(dev->of_node, node) {
+               of_graph_parse_endpoint(node, &endpoint);
+               if (endpoint.port > 2)
+                       return -EINVAL;
+
+               mode |= BIT(endpoint.port);
+       }
+
+       if (mode == mode_dpi_to_edp)
+               return tc_probe_edp_bridge_endpoint(tc);
+       else if (mode == mode_dsi_to_dpi)
+               dev_warn(dev, "The mode DSI-to-DPI is not supported!\n");
+       else if (mode == mode_dsi_to_edp)
+               dev_warn(dev, "The mode DSI-to-(e)DP is not supported!\n");
+       else
+               dev_warn(dev, "Invalid mode (0x%x) is not supported!\n", mode);
+
+       return -EINVAL;
+}
+
 static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
        struct device *dev = &client->dev;
@@ -1696,7 +1740,7 @@ static int tc_probe(struct i2c_client *client, const 
struct i2c_device_id *id)
 
        tc->dev = dev;
 
-       ret = tc_probe_edp_bridge_endpoint(tc);
+       ret = tc_probe_bridge_endpoint(tc);
        if (ret)
                return ret;
 
-- 
2.34.1

Reply via email to