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>
This commit is contained in:
parent
195ae4dadc
commit
d7a02e724c
5 changed files with 217 additions and 24 deletions
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
const char *data;
|
||||
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;
|
||||
}
|
||||
|
||||
*dlane_swap = DSI_LANE_MAP_0123;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
/* Check if an older version of the binding is present */
|
||||
data = of_get_property(np, "qcom,lane-map", NULL);
|
||||
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");
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Add table
Reference in a new issue