diff mbox

drm/msm/dsi: Parse lane swap information from DT

Message ID 1441305049-14610-1-git-send-email-hali@codeaurora.org
State New
Headers show

Commit Message

Hai Li Sept. 3, 2015, 6:30 p.m. UTC
Lane swap configuration is based on the board design.
This change allows the DSI host to get this information
from device tree, instead of hardcoding in driver.

Signed-off-by: Hai Li <hali@codeaurora.org>
---
 Documentation/devicetree/bindings/drm/msm/dsi.txt | 13 ++++++
 drivers/gpu/drm/msm/dsi/dsi_host.c                | 49 +++++++++++++++++------
 2 files changed, 49 insertions(+), 13 deletions(-)

Comments

Archit Taneja Sept. 6, 2015, 12:12 p.m. UTC | #1
Hi,

On 9/4/2015 12:00 AM, Hai Li wrote:
> Lane swap configuration is based on the board design.
> This change allows the DSI host to get this information
> from device tree, instead of hardcoding in driver.
>
> Signed-off-by: Hai Li <hali@codeaurora.org>
> ---
>   Documentation/devicetree/bindings/drm/msm/dsi.txt | 13 ++++++
>   drivers/gpu/drm/msm/dsi/dsi_host.c                | 49 +++++++++++++++++------
>   2 files changed, 49 insertions(+), 13 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/drm/msm/dsi.txt b/Documentation/devicetree/bindings/drm/msm/dsi.txt
> index d56923c..febcc51 100644
> --- a/Documentation/devicetree/bindings/drm/msm/dsi.txt
> +++ b/Documentation/devicetree/bindings/drm/msm/dsi.txt
> @@ -44,6 +44,17 @@ Optional properties:
>   - port: DSI controller output port. This contains one endpoint subnode, with its
>     remote-endpoint set to the phandle of the connected panel's endpoint.
>     See Documentation/devicetree/bindings/graph.txt for device graph info.
> +- qcom,dsi-logical-lane-swap: Character string to swap logical lane to physical
> +  lane mapping. Supported lane mappings:
> +  "0123": Logic 0->Phys 0; Logic 1->Phys 1; Logic 2->Phys 2; Logic 3->Phys 3;
> +  "3012": Logic 3->Phys 0; Logic 0->Phys 1; Logic 1->Phys 2; Logic 2->Phys 3;
> +  "2301": Logic 2->Phys 0; Logic 3->Phys 1; Logic 0->Phys 2; Logic 1->Phys 3;
> +  "1230": Logic 1->Phys 0; Logic 2->Phys 1; Logic 3->Phys 2; Logic 0->Phys 3;
> +  "0321": Logic 0->Phys 0; Logic 3->Phys 1; Logic 2->Phys 2; Logic 1->Phys 3;
> +  "1032": Logic 1->Phys 0; Logic 0->Phys 1; Logic 3->Phys 2; Logic 2->Phys 3;
> +  "2103": Logic 2->Phys 0; Logic 1->Phys 1; Logic 0->Phys 2; Logic 3->Phys 3;
> +  "3210": Logic 3->Phys 0; Logic 2->Phys 1; Logic 1->Phys 2; Logic 0->Phys 3;
> +  Default value is "0123", which means no lane swap.
>
>   DSI PHY:
>   Required properties:
> @@ -129,6 +140,8 @@ Example:
>   				remote-endpoint = <&panel_in>;
>   			};
>   		};
> +
> +		qcom,dsi-logical-lane-swap = "0123";
>   	};

I think we could keep this in the output port DT node instead,
since it is more of a property of how it connects to the panel.

There is a more generic way to represent lane info. It would be nice to
have a look at what's done here:

http://marc.info/?l=linux-omap&m=133605367610068&w=2

and it's usage here:

http://lxr.free-electrons.com/source/arch/arm/boot/dts/omap4-sdp.dts#L647

Thanks,
Archit


>
>   	mdss_dsi_phy0: qcom,mdss_dsi_phy@fd922a00 {
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
> index 8d82973f..eaba417 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_host.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
> @@ -131,6 +131,7 @@ struct msm_dsi_host {
>   	enum mipi_dsi_pixel_format format;
>   	unsigned long mode_flags;
>
> +	u32 dlane_swap;
>   	u32 dma_cmd_ctrl_restore;
>
>   	bool registered;
> @@ -684,19 +685,9 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
>   	data = DSI_CTRL_CLK_EN;
>
>   	DBG("lane number=%d", msm_host->lanes);
> -	if (msm_host->lanes == 2) {
> -		data |= DSI_CTRL_LANE1 | DSI_CTRL_LANE2;
> -		/* swap lanes for 2-lane panel for better performance */
> -		dsi_write(msm_host, REG_DSI_LANE_SWAP_CTRL,
> -			DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL(LANE_SWAP_1230));
> -	} else {
> -		/* Take 4 lanes as default */
> -		data |= DSI_CTRL_LANE0 | DSI_CTRL_LANE1 | DSI_CTRL_LANE2 |
> -			DSI_CTRL_LANE3;
> -		/* Do not swap lanes for 4-lane panel */
> -		dsi_write(msm_host, REG_DSI_LANE_SWAP_CTRL,
> -			DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL(LANE_SWAP_0123));
> -	}
> +	data |= ((DSI_CTRL_LANE0 << msm_host->lanes) - DSI_CTRL_LANE0);
> +	dsi_write(msm_host, REG_DSI_LANE_SWAP_CTRL,
> +		DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL(msm_host->dlane_swap));
>
>   	if (!(flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
>   		dsi_write(msm_host, REG_DSI_LANE_CTRL,
> @@ -1289,6 +1280,9 @@ static int dsi_host_attach(struct mipi_dsi_host *host,
>   	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
>   	int ret;
>
> +	if (dsi->lanes > 4 || dsi->channel > 3)
> +		return -EINVAL;
> +
>   	msm_host->channel = dsi->channel;
>   	msm_host->lanes = dsi->lanes;
>   	msm_host->format = dsi->format;
> @@ -1344,6 +1338,33 @@ static struct mipi_dsi_host_ops dsi_host_ops = {
>   	.transfer = dsi_host_transfer,
>   };
>
> +static void dsi_parse_dlane_swap(struct msm_dsi_host *msm_host,
> +				struct device_node *np)
> +{
> +	const char *lane_swap;
> +
> +	lane_swap = of_get_property(np, "qcom,dsi-logical-lane-swap", NULL);
> +
> +	if (!lane_swap)
> +		msm_host->dlane_swap = LANE_SWAP_0123;
> +	else if (!strncmp(lane_swap, "3012", 5))
> +		msm_host->dlane_swap = LANE_SWAP_3012;
> +	else if (!strncmp(lane_swap, "2301", 5))
> +		msm_host->dlane_swap = LANE_SWAP_2301;
> +	else if (!strncmp(lane_swap, "1230", 5))
> +		msm_host->dlane_swap = LANE_SWAP_1230;
> +	else if (!strncmp(lane_swap, "0321", 5))
> +		msm_host->dlane_swap = LANE_SWAP_0321;
> +	else if (!strncmp(lane_swap, "1032", 5))
> +		msm_host->dlane_swap = LANE_SWAP_1032;
> +	else if (!strncmp(lane_swap, "2103", 5))
> +		msm_host->dlane_swap = LANE_SWAP_2103;
> +	else if (!strncmp(lane_swap, "3210", 5))
> +		msm_host->dlane_swap = LANE_SWAP_3210;
> +	else
> +		msm_host->dlane_swap = LANE_SWAP_0123;
> +}
> +
>   static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
>   {
>   	struct device *dev = &msm_host->pdev->dev;
> @@ -1358,6 +1379,8 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
>   		return ret;
>   	}
>
> +	dsi_parse_dlane_swap(msm_host, np);
> +
>   	/*
>   	 * Get the first endpoint node. In our case, dsi has one output port
>   	 * to which the panel is connected. Don't return an error if a port
>
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/drm/msm/dsi.txt b/Documentation/devicetree/bindings/drm/msm/dsi.txt
index d56923c..febcc51 100644
--- a/Documentation/devicetree/bindings/drm/msm/dsi.txt
+++ b/Documentation/devicetree/bindings/drm/msm/dsi.txt
@@ -44,6 +44,17 @@  Optional properties:
 - port: DSI controller output port. This contains one endpoint subnode, with its
   remote-endpoint set to the phandle of the connected panel's endpoint.
   See Documentation/devicetree/bindings/graph.txt for device graph info.
+- qcom,dsi-logical-lane-swap: Character string to swap logical lane to physical
+  lane mapping. Supported lane mappings:
+  "0123": Logic 0->Phys 0; Logic 1->Phys 1; Logic 2->Phys 2; Logic 3->Phys 3;
+  "3012": Logic 3->Phys 0; Logic 0->Phys 1; Logic 1->Phys 2; Logic 2->Phys 3;
+  "2301": Logic 2->Phys 0; Logic 3->Phys 1; Logic 0->Phys 2; Logic 1->Phys 3;
+  "1230": Logic 1->Phys 0; Logic 2->Phys 1; Logic 3->Phys 2; Logic 0->Phys 3;
+  "0321": Logic 0->Phys 0; Logic 3->Phys 1; Logic 2->Phys 2; Logic 1->Phys 3;
+  "1032": Logic 1->Phys 0; Logic 0->Phys 1; Logic 3->Phys 2; Logic 2->Phys 3;
+  "2103": Logic 2->Phys 0; Logic 1->Phys 1; Logic 0->Phys 2; Logic 3->Phys 3;
+  "3210": Logic 3->Phys 0; Logic 2->Phys 1; Logic 1->Phys 2; Logic 0->Phys 3;
+  Default value is "0123", which means no lane swap.
 
 DSI PHY:
 Required properties:
@@ -129,6 +140,8 @@  Example:
 				remote-endpoint = <&panel_in>;
 			};
 		};
+
+		qcom,dsi-logical-lane-swap = "0123";
 	};
 
 	mdss_dsi_phy0: qcom,mdss_dsi_phy@fd922a00 {
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 8d82973f..eaba417 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -131,6 +131,7 @@  struct msm_dsi_host {
 	enum mipi_dsi_pixel_format format;
 	unsigned long mode_flags;
 
+	u32 dlane_swap;
 	u32 dma_cmd_ctrl_restore;
 
 	bool registered;
@@ -684,19 +685,9 @@  static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
 	data = DSI_CTRL_CLK_EN;
 
 	DBG("lane number=%d", msm_host->lanes);
-	if (msm_host->lanes == 2) {
-		data |= DSI_CTRL_LANE1 | DSI_CTRL_LANE2;
-		/* swap lanes for 2-lane panel for better performance */
-		dsi_write(msm_host, REG_DSI_LANE_SWAP_CTRL,
-			DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL(LANE_SWAP_1230));
-	} else {
-		/* Take 4 lanes as default */
-		data |= DSI_CTRL_LANE0 | DSI_CTRL_LANE1 | DSI_CTRL_LANE2 |
-			DSI_CTRL_LANE3;
-		/* Do not swap lanes for 4-lane panel */
-		dsi_write(msm_host, REG_DSI_LANE_SWAP_CTRL,
-			DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL(LANE_SWAP_0123));
-	}
+	data |= ((DSI_CTRL_LANE0 << msm_host->lanes) - DSI_CTRL_LANE0);
+	dsi_write(msm_host, REG_DSI_LANE_SWAP_CTRL,
+		DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL(msm_host->dlane_swap));
 
 	if (!(flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
 		dsi_write(msm_host, REG_DSI_LANE_CTRL,
@@ -1289,6 +1280,9 @@  static int dsi_host_attach(struct mipi_dsi_host *host,
 	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 	int ret;
 
+	if (dsi->lanes > 4 || dsi->channel > 3)
+		return -EINVAL;
+
 	msm_host->channel = dsi->channel;
 	msm_host->lanes = dsi->lanes;
 	msm_host->format = dsi->format;
@@ -1344,6 +1338,33 @@  static struct mipi_dsi_host_ops dsi_host_ops = {
 	.transfer = dsi_host_transfer,
 };
 
+static void dsi_parse_dlane_swap(struct msm_dsi_host *msm_host,
+				struct device_node *np)
+{
+	const char *lane_swap;
+
+	lane_swap = of_get_property(np, "qcom,dsi-logical-lane-swap", NULL);
+
+	if (!lane_swap)
+		msm_host->dlane_swap = LANE_SWAP_0123;
+	else if (!strncmp(lane_swap, "3012", 5))
+		msm_host->dlane_swap = LANE_SWAP_3012;
+	else if (!strncmp(lane_swap, "2301", 5))
+		msm_host->dlane_swap = LANE_SWAP_2301;
+	else if (!strncmp(lane_swap, "1230", 5))
+		msm_host->dlane_swap = LANE_SWAP_1230;
+	else if (!strncmp(lane_swap, "0321", 5))
+		msm_host->dlane_swap = LANE_SWAP_0321;
+	else if (!strncmp(lane_swap, "1032", 5))
+		msm_host->dlane_swap = LANE_SWAP_1032;
+	else if (!strncmp(lane_swap, "2103", 5))
+		msm_host->dlane_swap = LANE_SWAP_2103;
+	else if (!strncmp(lane_swap, "3210", 5))
+		msm_host->dlane_swap = LANE_SWAP_3210;
+	else
+		msm_host->dlane_swap = LANE_SWAP_0123;
+}
+
 static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 {
 	struct device *dev = &msm_host->pdev->dev;
@@ -1358,6 +1379,8 @@  static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 		return ret;
 	}
 
+	dsi_parse_dlane_swap(msm_host, np);
+
 	/*
 	 * Get the first endpoint node. In our case, dsi has one output port
 	 * to which the panel is connected. Don't return an error if a port