All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marco Felsch <m.felsch@pengutronix.de>
To: robert.foss@linaro.org, laurent.pinchart@ideasonboard.com,
	jernej.skrabec@gmail.com, jonas@kwiboo.se, robh+dt@kernel.org,
	krzysztof.kozlowski+dt@linaro.org, sam@ravnborg.org,
	maxime@cerno.tech
Cc: devicetree@vger.kernel.org, kernel@pengutronix.de,
	dri-devel@lists.freedesktop.org
Subject: [PATCH 3/6] drm/bridge: ti-sn65dsi83: add support to swap the LVDS data lanes
Date: Mon, 30 May 2022 17:05:46 +0200	[thread overview]
Message-ID: <20220530150548.1236307-4-m.felsch@pengutronix.de> (raw)
In-Reply-To: <20220530150548.1236307-1-m.felsch@pengutronix.de>

The chip can swap the LVDS channel A/B data lanes e.g. to improve the
layout characteristic. This commit adds the feature so the system
integrator can specify it within the device-tree.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/gpu/drm/bridge/ti-sn65dsi83.c | 64 +++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
index 112fea004c8e..baf94b2b78a1 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
@@ -32,6 +32,7 @@
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/of_graph.h>
+#include <linux/property.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 
@@ -148,6 +149,8 @@ struct sn65dsi83 {
 	int				dsi_lanes;
 	bool				lvds_dual_link;
 	bool				lvds_dual_link_even_odd_swap;
+	bool				lvds_reverse_cha;
+	bool				lvds_reverse_chb;
 };
 
 static const struct regmap_range sn65dsi83_readable_ranges[] = {
@@ -441,6 +444,10 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
 	val = REG_LVDS_LANE_CHA_LVDS_TERM | REG_LVDS_LANE_CHB_LVDS_TERM;
 	if (ctx->lvds_dual_link_even_odd_swap)
 		val |= REG_LVDS_LANE_EVEN_ODD_SWAP;
+	if (ctx->lvds_reverse_cha)
+		val |= REG_LVDS_LANE_CHA_REVERSE_LVDS;
+	if (ctx->lvds_reverse_chb)
+		val |= REG_LVDS_LANE_CHB_REVERSE_LVDS;
 
 	regmap_write(ctx->regmap, REG_LVDS_LANE, val);
 	regmap_write(ctx->regmap, REG_LVDS_CM, 0x00);
@@ -566,6 +573,47 @@ static const struct drm_bridge_funcs sn65dsi83_funcs = {
 	.atomic_get_input_bus_fmts = sn65dsi83_atomic_get_input_bus_fmts,
 };
 
+static int sn65dsi83_parse_lvds_lane_order(struct sn65dsi83 *ctx, unsigned char port)
+{
+	struct device *dev = ctx->dev;
+	struct device_node *ep;
+	int lvds_lanes;
+	int ret = 0;
+
+	if (port < 2 || port > 3)
+		return -EINVAL;
+
+	ep = of_graph_get_endpoint_by_regs(dev->of_node, port, 0);
+	lvds_lanes = of_property_count_u32_elems(ep, "data-lanes");
+	if (lvds_lanes == 4) {
+		u32 lane_assignments[] = { 1, 2, 3, 4 };
+
+		of_property_read_u32_array(ep, "data-lanes", lane_assignments,
+					   lvds_lanes);
+		if (lane_assignments[0] == 4 &&
+		    lane_assignments[1] == 3 &&
+		    lane_assignments[2] == 2 &&
+		    lane_assignments[3] == 1) {
+			if (port == 2)
+				ctx->lvds_reverse_cha = true;
+			else
+				ctx->lvds_reverse_chb = true;
+		} else if (lane_assignments[0] != 1 ||
+			   lane_assignments[1] != 2 ||
+			   lane_assignments[2] != 3 ||
+			   lane_assignments[3] != 4) {
+			dev_err(dev, "Unsupported LVDS lane order\n");
+			ret = -EINVAL;
+		}
+	} else if (lvds_lanes > 0) {
+		dev_err(dev, "All 4 LVDS data-lanes must be specified\n");
+		ret = -EINVAL;
+	}
+	of_node_put(ep);
+
+	return ret;
+}
+
 static int sn65dsi83_parse_dt(struct sn65dsi83 *ctx, enum sn65dsi83_model model)
 {
 	struct drm_bridge *panel_bridge;
@@ -610,6 +658,22 @@ static int sn65dsi83_parse_dt(struct sn65dsi83 *ctx, enum sn65dsi83_model model)
 		}
 	}
 
+	/*
+	 * Todo:
+	 * Check if the reverse lane setup is working in dual-link as well.
+	 */
+	if (!ctx->lvds_dual_link) {
+		ret = sn65dsi83_parse_lvds_lane_order(ctx, 2);
+		if (ret)
+			return ret;
+
+		if (model != MODEL_SN65DSI83) {
+			ret = sn65dsi83_parse_lvds_lane_order(ctx, 3);
+			if (ret)
+				return ret;
+		}
+	}
+
 	panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 2, 0);
 	if (IS_ERR(panel_bridge)) {
 		ret = PTR_ERR(panel_bridge);
-- 
2.30.2


WARNING: multiple messages have this Message-ID (diff)
From: Marco Felsch <m.felsch@pengutronix.de>
To: robert.foss@linaro.org, laurent.pinchart@ideasonboard.com,
	jernej.skrabec@gmail.com, jonas@kwiboo.se, robh+dt@kernel.org,
	krzysztof.kozlowski+dt@linaro.org, sam@ravnborg.org,
	maxime@cerno.tech
Cc: dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	kernel@pengutronix.de
Subject: [PATCH 3/6] drm/bridge: ti-sn65dsi83: add support to swap the LVDS data lanes
Date: Mon, 30 May 2022 17:05:46 +0200	[thread overview]
Message-ID: <20220530150548.1236307-4-m.felsch@pengutronix.de> (raw)
In-Reply-To: <20220530150548.1236307-1-m.felsch@pengutronix.de>

The chip can swap the LVDS channel A/B data lanes e.g. to improve the
layout characteristic. This commit adds the feature so the system
integrator can specify it within the device-tree.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/gpu/drm/bridge/ti-sn65dsi83.c | 64 +++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
index 112fea004c8e..baf94b2b78a1 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
@@ -32,6 +32,7 @@
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/of_graph.h>
+#include <linux/property.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 
@@ -148,6 +149,8 @@ struct sn65dsi83 {
 	int				dsi_lanes;
 	bool				lvds_dual_link;
 	bool				lvds_dual_link_even_odd_swap;
+	bool				lvds_reverse_cha;
+	bool				lvds_reverse_chb;
 };
 
 static const struct regmap_range sn65dsi83_readable_ranges[] = {
@@ -441,6 +444,10 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
 	val = REG_LVDS_LANE_CHA_LVDS_TERM | REG_LVDS_LANE_CHB_LVDS_TERM;
 	if (ctx->lvds_dual_link_even_odd_swap)
 		val |= REG_LVDS_LANE_EVEN_ODD_SWAP;
+	if (ctx->lvds_reverse_cha)
+		val |= REG_LVDS_LANE_CHA_REVERSE_LVDS;
+	if (ctx->lvds_reverse_chb)
+		val |= REG_LVDS_LANE_CHB_REVERSE_LVDS;
 
 	regmap_write(ctx->regmap, REG_LVDS_LANE, val);
 	regmap_write(ctx->regmap, REG_LVDS_CM, 0x00);
@@ -566,6 +573,47 @@ static const struct drm_bridge_funcs sn65dsi83_funcs = {
 	.atomic_get_input_bus_fmts = sn65dsi83_atomic_get_input_bus_fmts,
 };
 
+static int sn65dsi83_parse_lvds_lane_order(struct sn65dsi83 *ctx, unsigned char port)
+{
+	struct device *dev = ctx->dev;
+	struct device_node *ep;
+	int lvds_lanes;
+	int ret = 0;
+
+	if (port < 2 || port > 3)
+		return -EINVAL;
+
+	ep = of_graph_get_endpoint_by_regs(dev->of_node, port, 0);
+	lvds_lanes = of_property_count_u32_elems(ep, "data-lanes");
+	if (lvds_lanes == 4) {
+		u32 lane_assignments[] = { 1, 2, 3, 4 };
+
+		of_property_read_u32_array(ep, "data-lanes", lane_assignments,
+					   lvds_lanes);
+		if (lane_assignments[0] == 4 &&
+		    lane_assignments[1] == 3 &&
+		    lane_assignments[2] == 2 &&
+		    lane_assignments[3] == 1) {
+			if (port == 2)
+				ctx->lvds_reverse_cha = true;
+			else
+				ctx->lvds_reverse_chb = true;
+		} else if (lane_assignments[0] != 1 ||
+			   lane_assignments[1] != 2 ||
+			   lane_assignments[2] != 3 ||
+			   lane_assignments[3] != 4) {
+			dev_err(dev, "Unsupported LVDS lane order\n");
+			ret = -EINVAL;
+		}
+	} else if (lvds_lanes > 0) {
+		dev_err(dev, "All 4 LVDS data-lanes must be specified\n");
+		ret = -EINVAL;
+	}
+	of_node_put(ep);
+
+	return ret;
+}
+
 static int sn65dsi83_parse_dt(struct sn65dsi83 *ctx, enum sn65dsi83_model model)
 {
 	struct drm_bridge *panel_bridge;
@@ -610,6 +658,22 @@ static int sn65dsi83_parse_dt(struct sn65dsi83 *ctx, enum sn65dsi83_model model)
 		}
 	}
 
+	/*
+	 * Todo:
+	 * Check if the reverse lane setup is working in dual-link as well.
+	 */
+	if (!ctx->lvds_dual_link) {
+		ret = sn65dsi83_parse_lvds_lane_order(ctx, 2);
+		if (ret)
+			return ret;
+
+		if (model != MODEL_SN65DSI83) {
+			ret = sn65dsi83_parse_lvds_lane_order(ctx, 3);
+			if (ret)
+				return ret;
+		}
+	}
+
 	panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 2, 0);
 	if (IS_ERR(panel_bridge)) {
 		ret = PTR_ERR(panel_bridge);
-- 
2.30.2


  parent reply	other threads:[~2022-05-30 15:06 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-30 15:05 [PATCH 0/6] TI SN65DSI83 Features Marco Felsch
2022-05-30 15:05 ` Marco Felsch
2022-05-30 15:05 ` [PATCH 1/6] drm/bridge: ti-sn65dsi83: make lvds lane register setup more readable Marco Felsch
2022-05-30 15:05   ` Marco Felsch
2022-05-30 15:05 ` [PATCH 2/6] dt-bindings: drm/bridge: ti-sn65dsi83: add documentation for reverse lvds lanes Marco Felsch
2022-05-30 15:05   ` Marco Felsch
2022-06-05 21:09   ` Rob Herring
2022-06-05 21:09     ` Rob Herring
2022-05-30 15:05 ` Marco Felsch [this message]
2022-05-30 15:05   ` [PATCH 3/6] drm/bridge: ti-sn65dsi83: add support to swap the LVDS data lanes Marco Felsch
2022-05-30 15:05 ` [PATCH 4/6] drm/bridge: ti-sn65dsi83: make use of dev_err_probe Marco Felsch
2022-05-30 15:05   ` Marco Felsch
2022-05-30 15:05 ` [PATCH 5/6] dt-bindings: drm/bridge: ti-sn65dsi83: Add reset controller documentation Marco Felsch
2022-05-30 15:05   ` Marco Felsch
2022-05-31  7:33   ` (EXT) " Alexander Stein
2022-05-31  7:33     ` Alexander Stein
2022-05-31  8:29     ` Marco Felsch
2022-05-31  8:29       ` Marco Felsch
2022-05-30 15:05 ` [PATCH 6/6] drm/bridge: ti-sn65dsi83: add support for a external reset controller Marco Felsch
2022-05-30 15:05   ` Marco Felsch
2022-07-26  9:12 ` [PATCH 0/6] TI SN65DSI83 Features Marco Felsch
2022-07-26  9:12   ` Marco Felsch
2022-08-29 15:06   ` Robert Foss
2022-08-29 15:06     ` Robert Foss
2022-08-31  8:13     ` Marco Felsch
2022-08-31  8:13       ` Marco Felsch

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220530150548.1236307-4-m.felsch@pengutronix.de \
    --to=m.felsch@pengutronix.de \
    --cc=devicetree@vger.kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=jernej.skrabec@gmail.com \
    --cc=jonas@kwiboo.se \
    --cc=kernel@pengutronix.de \
    --cc=krzysztof.kozlowski+dt@linaro.org \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=maxime@cerno.tech \
    --cc=robert.foss@linaro.org \
    --cc=robh+dt@kernel.org \
    --cc=sam@ravnborg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.