- pinctrl-names: the pin control state names; should contain "default"
 - pinctrl-0: the default pinctrl state (active)
 - pinctrl-n: the "sleep" pinctrl state
-- 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.
+- port: DSI controller output port, containing one endpoint subnode.
+
+  DSI Endpoint properties:
+  - remote-endpoint: set to phandle of the connected panel's endpoint.
+    See Documentation/devicetree/bindings/graph.txt for device graph info.
+  - qcom,data-lane-map: this describes how the logical DSI lanes are mapped
+    to the physical lanes on the given platform. The value contained in
+    index n describes what logical data lane is mapped to the physical data
+    lane n (DATAn, where n lies between 0 and 3).
+
+    For example:
+
+    qcom,data-lane-map = <3 0 1 2>;
+
+    The above mapping describes that the logical data lane DATA3 is mapped to
+    the physical data lane DATA0, logical DATA0 to physical DATA1, logic DATA1
+    to phys DATA2 and logic DATA2 to phys DATA3.
+
+    There are only a limited number of physical to logical mappings possible:
+
+    "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;
 
 DSI PHY:
 Required properties:
                port {
                        dsi0_out: endpoint {
                                remote-endpoint = <&panel_in>;
+                               lanes = <0 1 2 3>;
                        };
                };
        };
 
        enum mipi_dsi_pixel_format format;
        unsigned long mode_flags;
 
+       /* lane data parsed via DT */
+       int dlane_swap;
+       int num_data_lanes;
+
        u32 dma_cmd_ctrl_restore;
 
        bool registered;
        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,
        struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
        int ret;
 
+       if (dsi->lanes > msm_host->num_data_lanes)
+               return -EINVAL;
+
        msm_host->channel = dsi->channel;
        msm_host->lanes = dsi->lanes;
        msm_host->format = dsi->format;
        .transfer = dsi_host_transfer,
 };
 
+/*
+ * List of supported physical to logical lane mappings.
+ * For example, the 2nd entry represents the following mapping:
+ *
+ * "3012": Logic 3->Phys 0; Logic 0->Phys 1; Logic 1->Phys 2; Logic 2->Phys 3;
+ */
+static const int supported_data_lane_swaps[][4] = {
+       { 0, 1, 2, 3 },
+       { 3, 0, 1, 2 },
+       { 2, 3, 0, 1 },
+       { 1, 2, 3, 0 },
+       { 0, 3, 2, 1 },
+       { 1, 0, 3, 2 },
+       { 2, 1, 0, 3 },
+       { 3, 2, 1, 0 },
+};
+
+static int dsi_host_parse_lane_data(struct msm_dsi_host *msm_host,
+                                   struct device_node *ep)
+{
+       struct device *dev = &msm_host->pdev->dev;
+       struct property *prop;
+       u32 lane_map[4];
+       int ret, i, len, num_lanes;
+
+       prop = of_find_property(ep, "qcom,data-lane-map", &len);
+       if (!prop) {
+               dev_dbg(dev, "failed to find data lane mapping\n");
+               return -EINVAL;
+       }
+
+       num_lanes = len / sizeof(u32);
+
+       if (num_lanes < 1 || num_lanes > 4) {
+               dev_err(dev, "bad number of data lanes\n");
+               return -EINVAL;
+       }
+
+       msm_host->num_data_lanes = num_lanes;
+
+       ret = of_property_read_u32_array(ep, "qcom,data-lane-map", lane_map,
+                                        num_lanes);
+       if (ret) {
+               dev_err(dev, "failed to read lane data\n");
+               return ret;
+       }
+
+       /*
+        * compare DT specified physical-logical lane mappings with the ones
+        * supported by hardware
+        */
+       for (i = 0; i < ARRAY_SIZE(supported_data_lane_swaps); i++) {
+               const int *swap = supported_data_lane_swaps[i];
+               int j;
+
+               for (j = 0; j < num_lanes; j++) {
+                       if (swap[j] != lane_map[j])
+                               break;
+               }
+
+               if (j == num_lanes) {
+                       msm_host->dlane_swap = i;
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
 static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 {
        struct device *dev = &msm_host->pdev->dev;
                return 0;
        }
 
+       ret = dsi_host_parse_lane_data(msm_host, endpoint);
+       if (ret) {
+               dev_err(dev, "%s: invalid lane configuration %d\n",
+                       __func__, ret);
+               goto err;
+       }
+
        /* Get panel node from the output port's endpoint data */
        device_node = of_graph_get_remote_port_parent(endpoint);
        if (!device_node) {
                dev_err(dev, "%s: no valid device\n", __func__);
-               of_node_put(endpoint);
-               return -ENODEV;
+               ret = -ENODEV;
+               goto err;
        }
 
-       of_node_put(endpoint);
-       of_node_put(device_node);
-
        msm_host->device_node = device_node;
 
        if (of_property_read_bool(np, "syscon-sfpb")) {
                if (IS_ERR(msm_host->sfpb)) {
                        dev_err(dev, "%s: failed to get sfpb regmap\n",
                                __func__);
-                       return PTR_ERR(msm_host->sfpb);
+                       ret = PTR_ERR(msm_host->sfpb);
                }
        }
 
-       return 0;
+       of_node_put(device_node);
+
+err:
+       of_node_put(endpoint);
+
+       return ret;
 }
 
 int msm_dsi_host_init(struct msm_dsi *msm_dsi)