diff mbox series

[V2,09/11] drm/bridge: tc358767: Detect bridge mode from connected endpoints in DT

Message ID 20220218010054.315026-10-marex@denx.de (mailing list archive)
State New, archived
Headers show
Series drm/bridge: tc358767: Add DSI-to-DPI mode support | expand

Commit Message

Marek Vasut Feb. 18, 2022, 1 a.m. UTC
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 <marex@denx.de>
Cc: Jonas Karlman <jonas@kwiboo.se>
Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
Cc: Maxime Ripard <maxime@cerno.tech>
Cc: Neil Armstrong <narmstrong@baylibre.com>
Cc: Sam Ravnborg <sam@ravnborg.org>
---
V2: - New patch
---
 drivers/gpu/drm/bridge/tc358767.c | 46 ++++++++++++++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)

Comments

Lucas Stach Feb. 18, 2022, 6:04 p.m. UTC | #1
Am Freitag, dem 18.02.2022 um 02:00 +0100 schrieb Marek Vasut:
> 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 <marex@denx.de>
> Cc: Jonas Karlman <jonas@kwiboo.se>
> Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
> Cc: Maxime Ripard <maxime@cerno.tech>
> Cc: Neil Armstrong <narmstrong@baylibre.com>
> Cc: Sam Ravnborg <sam@ravnborg.org>

Reviewed-by: Lucas Stach <l.stach@pengutronix.de>

> ---
> 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;
>
diff mbox series

Patch

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;