summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAravind Venkateswaran <aravindh@codeaurora.org>2016-06-14 17:38:17 -0700
committerKyle Yan <kyan@codeaurora.org>2016-06-20 15:06:01 -0700
commitd7a02e724c03c53b23af6ade1e11e885a1b08d47 (patch)
treef05712d73d51ece01b74babcfe6ceecc884c0947
parent195ae4dadc6aba3decca56d4180ee7fedb891120 (diff)
msm: mdss: dsi: configure data lane swap for newer hw revisions
Starting with DSI PHY hardware revisions 3.0 and above, data lane swap configurations need to be programmed via the DSI PHY interface. In other cases, a new register interface has been introduced to program the lane swap configuration for DSI controller revision 2.0 and above. Refactor the existing implementation to account for these hardware changes. Change-Id: I3772c614bfee0ed13f30a38535bb814158d23226 Signed-off-by: Aravind Venkateswaran <aravindh@codeaurora.org>
-rw-r--r--Documentation/devicetree/bindings/fb/mdss-dsi.txt22
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.c137
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.h49
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_host.c17
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_phy_v3.c12
5 files changed, 215 insertions, 22 deletions
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi.txt b/Documentation/devicetree/bindings/fb/mdss-dsi.txt
index 4aeabcdd45b1..31994cf28b27 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi.txt
@@ -125,6 +125,28 @@ Optional properties:
"lane_map_1032" = <1 0 3 2>
"lane_map_2103" = <2 1 0 3>
"lane_map_3210" = <3 2 1 0>
+ where lane_map_ABCD means:
+ Logical_Lane_A = Physical_Lane_0
+ Logical_Lane_B = Physical_Lane_1
+ Logical_Lane_C = Physical_Lane_2
+ Logical_Lane_D = Physical_Lane_3
+ The lane map can vary between multiple instances
+ of the DSI controller and should be set accordingly in all
+ of them based on the board configuration.
+- qcom,lane-map-v2: An array of size 4 uint8s specifying the corresponding
+ mapping for each of the logical data lanes.
+ For example, a value of <A B C D> means
+ Logical_Lane_0 = Physical_Lane_A
+ Logical_Lane_1 = Physical_Lane_B
+ Logical_Lane_2 = Physical_Lane_C
+ Logical_Lane_3 = Physical_Lane_D
+ The default lane mapping is <0 1 2 3>.
+ Since the values are of type uint8, they need to be
+ specified as below:
+ qcom,lane-map-v2 = /bits/ 8 <0 1 2 3>
+ This binding supersedes qcom,lane-map binding and will
+ override any lane swap setting specified by qcom,lane-map.
+ Refer to qcom,lane-map for additional notes.
- qcom,pluggable Boolean to enable hotplug feature.
- qcom,timing-db-mode: Boolean specifies dsi timing mode registers are supported or not.
- qcom,display-id A string indicates the display ID for the controller.
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index 054f48fa0005..8f1ab774044d 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -3037,10 +3037,32 @@ end:
return rc;
}
+static void mdss_dsi_ctrl_validate_lane_swap_config(
+ struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ struct mipi_panel_info *mipi = &ctrl->panel_data.panel_info.mipi;
+
+ if (!mipi->data_lane0)
+ ctrl->lane_map[DSI_LOGICAL_LANE_0] = DSI_PHYSICAL_LANE_INVALID;
+ if (!mipi->data_lane1)
+ ctrl->lane_map[DSI_LOGICAL_LANE_1] = DSI_PHYSICAL_LANE_INVALID;
+ if (!mipi->data_lane2)
+ ctrl->lane_map[DSI_LOGICAL_LANE_2] = DSI_PHYSICAL_LANE_INVALID;
+ if (!mipi->data_lane3)
+ ctrl->lane_map[DSI_LOGICAL_LANE_3] = DSI_PHYSICAL_LANE_INVALID;
+}
+
static int mdss_dsi_ctrl_validate_config(struct mdss_dsi_ctrl_pdata *ctrl)
{
int rc = 0;
+ if (!ctrl) {
+ rc = -EINVAL;
+ goto error;
+ }
+
+ mdss_dsi_ctrl_validate_lane_swap_config(ctrl);
+
/*
* check to make sure that the byte interface clock is specified for
* DSI ctrl version 2 and above.
@@ -3052,6 +3074,7 @@ static int mdss_dsi_ctrl_validate_config(struct mdss_dsi_ctrl_pdata *ctrl)
rc = -EINVAL;
}
+error:
return rc;
}
@@ -3807,28 +3830,105 @@ static int mdss_dsi_irq_init(struct device *dev, int irq_no,
return ret;
}
-static void mdss_dsi_parse_lane_swap(struct device_node *np, char *dlane_swap)
+static void __set_lane_map(struct mdss_dsi_ctrl_pdata *ctrl,
+ enum dsi_physical_lane_id lane0,
+ enum dsi_physical_lane_id lane1,
+ enum dsi_physical_lane_id lane2,
+ enum dsi_physical_lane_id lane3)
+{
+ ctrl->lane_map[DSI_LOGICAL_LANE_0] = lane0;
+ ctrl->lane_map[DSI_LOGICAL_LANE_1] = lane1;
+ ctrl->lane_map[DSI_LOGICAL_LANE_2] = lane2;
+ ctrl->lane_map[DSI_LOGICAL_LANE_3] = lane3;
+}
+
+static void mdss_dsi_parse_lane_swap(struct device_node *np,
+ struct mdss_dsi_ctrl_pdata *ctrl)
{
+ int rc;
const char *data;
+ u8 temp[DSI_LOGICAL_LANE_MAX];
+ int i;
+
+ /* First, check for the newer version of the binding */
+ rc = of_property_read_u8_array(np, "qcom,lane-map-v2", temp,
+ DSI_LOGICAL_LANE_MAX);
+ if (!rc) {
+ for (i = DSI_LOGICAL_LANE_0; i < DSI_LOGICAL_LANE_MAX; i++)
+ ctrl->lane_map[i] = BIT(temp[i]);
+ return;
+ } else if (rc != -EINVAL) {
+ pr_warn("%s: invalid lane map specfied. Defaulting to <0 1 2 3>\n",
+ __func__);
+ goto set_default;
+ }
- *dlane_swap = DSI_LANE_MAP_0123;
+ /* Check if an older version of the binding is present */
data = of_get_property(np, "qcom,lane-map", NULL);
- if (data) {
- if (!strcmp(data, "lane_map_3012"))
- *dlane_swap = DSI_LANE_MAP_3012;
- else if (!strcmp(data, "lane_map_2301"))
- *dlane_swap = DSI_LANE_MAP_2301;
- else if (!strcmp(data, "lane_map_1230"))
- *dlane_swap = DSI_LANE_MAP_1230;
- else if (!strcmp(data, "lane_map_0321"))
- *dlane_swap = DSI_LANE_MAP_0321;
- else if (!strcmp(data, "lane_map_1032"))
- *dlane_swap = DSI_LANE_MAP_1032;
- else if (!strcmp(data, "lane_map_2103"))
- *dlane_swap = DSI_LANE_MAP_2103;
- else if (!strcmp(data, "lane_map_3210"))
- *dlane_swap = DSI_LANE_MAP_3210;
+ if (!data)
+ goto set_default;
+
+ if (!strcmp(data, "lane_map_3012")) {
+ ctrl->dlane_swap = DSI_LANE_MAP_3012;
+ __set_lane_map(ctrl,
+ DSI_PHYSICAL_LANE_1,
+ DSI_PHYSICAL_LANE_2,
+ DSI_PHYSICAL_LANE_3,
+ DSI_PHYSICAL_LANE_0);
+ } else if (!strcmp(data, "lane_map_2301")) {
+ ctrl->dlane_swap = DSI_LANE_MAP_2301;
+ __set_lane_map(ctrl,
+ DSI_PHYSICAL_LANE_2,
+ DSI_PHYSICAL_LANE_3,
+ DSI_PHYSICAL_LANE_0,
+ DSI_PHYSICAL_LANE_1);
+ } else if (!strcmp(data, "lane_map_1230")) {
+ ctrl->dlane_swap = DSI_LANE_MAP_1230;
+ __set_lane_map(ctrl,
+ DSI_PHYSICAL_LANE_3,
+ DSI_PHYSICAL_LANE_0,
+ DSI_PHYSICAL_LANE_1,
+ DSI_PHYSICAL_LANE_2);
+ } else if (!strcmp(data, "lane_map_0321")) {
+ ctrl->dlane_swap = DSI_LANE_MAP_0321;
+ __set_lane_map(ctrl,
+ DSI_PHYSICAL_LANE_0,
+ DSI_PHYSICAL_LANE_3,
+ DSI_PHYSICAL_LANE_2,
+ DSI_PHYSICAL_LANE_1);
+ } else if (!strcmp(data, "lane_map_1032")) {
+ ctrl->dlane_swap = DSI_LANE_MAP_1032;
+ __set_lane_map(ctrl,
+ DSI_PHYSICAL_LANE_1,
+ DSI_PHYSICAL_LANE_0,
+ DSI_PHYSICAL_LANE_3,
+ DSI_PHYSICAL_LANE_2);
+ } else if (!strcmp(data, "lane_map_2103")) {
+ ctrl->dlane_swap = DSI_LANE_MAP_2103;
+ __set_lane_map(ctrl,
+ DSI_PHYSICAL_LANE_2,
+ DSI_PHYSICAL_LANE_1,
+ DSI_PHYSICAL_LANE_0,
+ DSI_PHYSICAL_LANE_3);
+ } else if (!strcmp(data, "lane_map_3210")) {
+ ctrl->dlane_swap = DSI_LANE_MAP_3210;
+ __set_lane_map(ctrl,
+ DSI_PHYSICAL_LANE_3,
+ DSI_PHYSICAL_LANE_2,
+ DSI_PHYSICAL_LANE_1,
+ DSI_PHYSICAL_LANE_0);
+ } else {
+ pr_warn("%s: invalid lane map %s specified. defaulting to lane_map0123\n",
+ __func__, data);
}
+
+ return;
+
+set_default:
+ /* default lane mapping */
+ __set_lane_map(ctrl, DSI_PHYSICAL_LANE_0, DSI_PHYSICAL_LANE_1,
+ DSI_PHYSICAL_LANE_2, DSI_PHYSICAL_LANE_3);
+ ctrl->dlane_swap = DSI_LANE_MAP_0123;
}
static int mdss_dsi_parse_ctrl_params(struct platform_device *ctrl_pdev,
@@ -3904,8 +4004,7 @@ static int mdss_dsi_parse_ctrl_params(struct platform_device *ctrl_pdev,
ctrl_pdata->cmd_sync_wait_broadcast,
ctrl_pdata->cmd_sync_wait_trigger);
- mdss_dsi_parse_lane_swap(ctrl_pdev->dev.of_node,
- &(ctrl_pdata->dlane_swap));
+ mdss_dsi_parse_lane_swap(ctrl_pdev->dev.of_node, ctrl_pdata);
pinfo->is_pluggable = of_property_read_bool(ctrl_pdev->dev.of_node,
"qcom,pluggable");
diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h
index 6be44e070205..ecffc12ecd72 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.h
+++ b/drivers/video/fbdev/msm/mdss_dsi.h
@@ -127,6 +127,22 @@ enum dsi_lane_map_type {
DSI_LANE_MAP_3210,
};
+enum dsi_logical_lane_id {
+ DSI_LOGICAL_LANE_0 = 0,
+ DSI_LOGICAL_LANE_1,
+ DSI_LOGICAL_LANE_2,
+ DSI_LOGICAL_LANE_3,
+ DSI_LOGICAL_LANE_MAX,
+};
+
+enum dsi_physical_lane_id {
+ DSI_PHYSICAL_LANE_INVALID = 0,
+ DSI_PHYSICAL_LANE_0 = BIT(0),
+ DSI_PHYSICAL_LANE_1 = BIT(1),
+ DSI_PHYSICAL_LANE_2 = BIT(2),
+ DSI_PHYSICAL_LANE_3 = BIT(3),
+};
+
enum dsi_pm_type {
/* PANEL_PM not used as part of power_data in dsi_shared_data */
DSI_PANEL_PM,
@@ -503,7 +519,17 @@ struct mdss_dsi_ctrl_pdata {
bool ulps;
bool core_power;
bool mmss_clamp;
- char dlane_swap; /* data lane swap */
+
+ /*
+ * Data lane swap (logical to physical lane map):
+ * dlane_swap: used for DSI controller versions < 2.0, where
+ * dlane_swap is of type enum dsi_lane_map_type
+ * lane_map: used for DSI controller versions > 2.0, where
+ * lane_map[logical_lane_id] = physical_lane_id
+ */
+ char dlane_swap;
+ uint8_t lane_map[DSI_LOGICAL_LANE_MAX];
+
bool is_phyreg_enabled;
bool burst_mode_enabled;
@@ -879,4 +905,25 @@ static inline bool mdss_dsi_cmp_panel_reg(struct dsi_buf status_buf,
return status_buf.data[i] == status_val[i];
}
+static inline enum dsi_logical_lane_id mdss_dsi_physical_to_logical_lane(
+ struct mdss_dsi_ctrl_pdata *ctrl, enum dsi_physical_lane_id id)
+{
+ int i;
+
+ for (i = DSI_LOGICAL_LANE_0; i < DSI_LOGICAL_LANE_MAX; i++)
+ if (ctrl->lane_map[i] == id)
+ break;
+
+ return i;
+}
+
+static inline enum dsi_physical_lane_id mdss_dsi_logical_to_physical_lane(
+ struct mdss_dsi_ctrl_pdata *ctrl, enum dsi_logical_lane_id id)
+{
+ if (id >= DSI_LOGICAL_LANE_MAX)
+ return DSI_PHYSICAL_LANE_INVALID;
+
+ return ctrl->lane_map[id];
+}
+
#endif /* MDSS_DSI_H */
diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c
index 39b014b90e28..3785a701e3c1 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_host.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_host.c
@@ -38,6 +38,8 @@
#define LANE_STATUS 0xA8
#define MDSS_DSI_INT_CTRL 0x0110
+#define LANE_SWAP_CTRL 0x0B0
+#define LOGICAL_LANE_SWAP_CTRL 0x310
struct mdss_dsi_ctrl_pdata *ctrl_list[DSI_CTRL_MAX];
@@ -303,6 +305,18 @@ void mdss_dsi_read_phy_revision(struct mdss_dsi_ctrl_pdata *ctrl)
ctrl->shared_data->phy_rev = DSI_PHY_REV_UNKNOWN;
}
+static void mdss_dsi_config_data_lane_swap(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ if (ctrl->shared_data->hw_rev < MDSS_DSI_HW_REV_200)
+ MIPI_OUTP((ctrl->ctrl_base) + LANE_SWAP_CTRL, ctrl->dlane_swap);
+ else
+ MIPI_OUTP(ctrl->ctrl_base + LOGICAL_LANE_SWAP_CTRL,
+ ctrl->lane_map[DSI_LOGICAL_LANE_0] |
+ ctrl->lane_map[DSI_LOGICAL_LANE_1] << 4 |
+ ctrl->lane_map[DSI_LOGICAL_LANE_2] << 8 |
+ ctrl->lane_map[DSI_LOGICAL_LANE_3] << 12);
+}
+
void mdss_dsi_host_init(struct mdss_panel_data *pdata)
{
u32 dsi_ctrl, intr_ctrl;
@@ -400,8 +414,7 @@ void mdss_dsi_host_init(struct mdss_panel_data *pdata)
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0084,
data); /* DSI_TRIG_CTRL */
- /* DSI_LAN_SWAP_CTRL */
- MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x00b0, ctrl_pdata->dlane_swap);
+ mdss_dsi_config_data_lane_swap(ctrl_pdata);
/* clock out ctrl */
data = pinfo->t_clk_post & 0x3f; /* 6 bits */
diff --git a/drivers/video/fbdev/msm/mdss_dsi_phy_v3.c b/drivers/video/fbdev/msm/mdss_dsi_phy_v3.c
index 0c4dcf9db216..9f419c91661c 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_phy_v3.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_phy_v3.c
@@ -118,6 +118,16 @@ static void mdss_dsi_phy_v3_set_pll_source(
DSI_PHY_W32(ctrl->phy_io.base, CMN_CLK_CFG1, reg);
}
+static void mdss_dsi_phy_v3_lane_swap_config(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ DSI_PHY_W32(ctrl->phy_io.base, CMN_LANE_CFG0,
+ ctrl->lane_map[DSI_LOGICAL_LANE_0] |
+ ctrl->lane_map[DSI_LOGICAL_LANE_1] << 4);
+ DSI_PHY_W32(ctrl->phy_io.base, CMN_LANE_CFG1,
+ ctrl->lane_map[DSI_LOGICAL_LANE_2] |
+ ctrl->lane_map[DSI_LOGICAL_LANE_3] << 4);
+}
+
static void mdss_dsi_phy_v3_lanes_disable(struct mdss_dsi_ctrl_pdata *ctrl)
{
u32 data = DSI_PHY_R32(ctrl->phy_io.base, CMN_CTRL_0);
@@ -343,6 +353,8 @@ int mdss_dsi_phy_v3_init(struct mdss_dsi_ctrl_pdata *ctrl,
/* Enable LDO */
DSI_PHY_W32(ctrl->phy_io.base, CMN_VREG_CTRL, 0x59);
+ mdss_dsi_phy_v3_lane_swap_config(ctrl);
+
mdss_dsi_phy_v3_config_timings(ctrl);
/* Remove power down from all blocks */