summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.c26
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.h12
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_host.c4
-rw-r--r--drivers/video/fbdev/msm/msm_mdss_io_8974.c229
4 files changed, 160 insertions, 111 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index a349b09906d7..d74d891a761c 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -35,8 +35,6 @@
/* Master structure to hold all the information about the DSI/panel */
static struct mdss_dsi_data *mdss_dsi_res;
-static struct dsi_drv_cm_data shared_ctrl_data;
-
static int mdss_dsi_pinctrl_set_state(struct mdss_dsi_ctrl_pdata *ctrl_pdata,
bool active);
@@ -1939,12 +1937,12 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
ctrl_pdata->refresh_clk_rate = true;
break;
case MDSS_EVENT_LINK_READY:
+ mdss_dsi_get_hw_revision(ctrl_pdata);
rc = mdss_dsi_on(pdata);
mdss_dsi_op_mode_config(pdata->panel_info.mipi.mode,
pdata);
break;
case MDSS_EVENT_UNBLANK:
- mdss_dsi_get_hw_revision(ctrl_pdata);
if (ctrl_pdata->refresh_clk_rate)
rc = mdss_dsi_clk_refresh(pdata);
@@ -2450,6 +2448,8 @@ static int mdss_dsi_res_init(struct platform_device *pdev)
goto mem_fail;
}
+ mutex_init(&sdata->phy_reg_lock);
+
for (i = 0; i < DSI_CTRL_MAX; i++) {
mdss_dsi_res->ctrl_pdata[i] = devm_kzalloc(&pdev->dev,
sizeof(struct mdss_dsi_ctrl_pdata),
@@ -2741,18 +2741,15 @@ int mdss_dsi_retrieve_ctrl_resources(struct platform_device *pdev, int mode,
return rc;
}
- ctrl->shared_ctrl_data = &shared_ctrl_data;
- rc = msm_dss_ioremap_byname(pdev,
- &ctrl->shared_ctrl_data->phy_regulator_io,
+ rc = msm_dss_ioremap_byname(pdev, &ctrl->phy_regulator_io,
"dsi_phy_regulator");
if (rc)
pr_debug("%s:%d unable to remap dsi phy regulator resources\n",
__func__, __LINE__);
else
pr_info("%s: phy_regulator_base=%p phy_regulator_size=%x\n",
- __func__,
- ctrl->shared_ctrl_data->phy_regulator_io.base,
- ctrl->shared_ctrl_data->phy_regulator_io.len);
+ __func__, ctrl->phy_regulator_io.base,
+ ctrl->phy_regulator_io.len);
pr_info("%s: ctrl_base=%p ctrl_size=%x phy_base=%p phy_size=%x\n",
__func__, ctrl->ctrl_base, ctrl->reg_size, ctrl->phy_io.base,
@@ -3094,6 +3091,7 @@ int dsi_panel_device_register(struct platform_device *ctrl_pdev,
mdss_dsi_panel_pwm_enable(ctrl_pdata);
pinfo->blank_state = MDSS_PANEL_BLANK_UNBLANK;
mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1);
+ ctrl_pdata->is_phyreg_enabled = 1;
ctrl_pdata->ctrl_state |=
(CTRL_STATE_PANEL_INIT | CTRL_STATE_MDP_ACTIVE);
} else {
@@ -3109,18 +3107,16 @@ int dsi_panel_device_register(struct platform_device *ctrl_pdev,
if (pinfo->pdest == DISPLAY_1) {
mdss_debug_register_io("dsi0_ctrl", &ctrl_pdata->ctrl_io, NULL);
mdss_debug_register_io("dsi0_phy", &ctrl_pdata->phy_io, NULL);
- if (ctrl_pdata->shared_ctrl_data->phy_regulator_io.len)
+ if (ctrl_pdata->phy_regulator_io.len)
mdss_debug_register_io("dsi0_phy_regulator",
- &ctrl_pdata->shared_ctrl_data->phy_regulator_io,
- NULL);
+ &ctrl_pdata->phy_regulator_io, NULL);
ctrl_pdata->ndx = 0;
} else {
mdss_debug_register_io("dsi1_ctrl", &ctrl_pdata->ctrl_io, NULL);
mdss_debug_register_io("dsi1_phy", &ctrl_pdata->phy_io, NULL);
- if (ctrl_pdata->shared_ctrl_data->phy_regulator_io.len)
+ if (ctrl_pdata->phy_regulator_io.len)
mdss_debug_register_io("dsi1_phy_regulator",
- &ctrl_pdata->shared_ctrl_data->phy_regulator_io,
- NULL);
+ &ctrl_pdata->phy_regulator_io, NULL);
ctrl_pdata->ndx = 1;
}
diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h
index 2600590a24af..858231f95b4f 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.h
+++ b/drivers/video/fbdev/msm/mdss_dsi.h
@@ -251,6 +251,9 @@ struct dsi_shared_data {
/* DSI core regulators */
struct dss_module_power power_data[DSI_MAX_PM];
+
+ /* Shared mutex for DSI PHY regulator */
+ struct mutex phy_reg_lock;
};
struct mdss_dsi_data {
@@ -305,11 +308,6 @@ struct dsi_kickoff_action {
void *data;
};
-struct dsi_drv_cm_data {
- struct dss_io_data phy_regulator_io;
- int phy_disable_refcount;
-};
-
struct dsi_pinctrl_res {
struct pinctrl *pinctrl;
struct pinctrl_state *gpio_state_active;
@@ -360,6 +358,7 @@ struct mdss_dsi_ctrl_pdata {
struct dss_io_data ctrl_io;
struct dss_io_data mmss_misc_io;
struct dss_io_data phy_io;
+ struct dss_io_data phy_regulator_io;
int reg_size;
u32 core_clk_cnt;
u32 link_clk_cnt;
@@ -403,7 +402,6 @@ struct mdss_dsi_ctrl_pdata {
struct mdss_rect roi;
struct pwm_device *pwm_bl;
- struct dsi_drv_cm_data *shared_ctrl_data;
u32 pclk_rate;
u32 byte_clk_rate;
bool refresh_clk_rate; /* flag to recalculate clk_rate */
@@ -445,6 +443,8 @@ struct mdss_dsi_ctrl_pdata {
bool core_power;
bool mmss_clamp;
char dlane_swap; /* data lane swap */
+ bool is_phyreg_enabled;
+
struct dsi_buf tx_buf;
struct dsi_buf rx_buf;
diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c
index 2ed624ec2203..2a0779e739d5 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_host.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_host.c
@@ -265,9 +265,9 @@ void mdss_dsi_read_hw_revision(struct mdss_dsi_ctrl_pdata *ctrl)
void mdss_dsi_get_hw_revision(struct mdss_dsi_ctrl_pdata *ctrl)
{
- mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 1);
+ mdss_dsi_clk_ctrl(ctrl, DSI_CORE_CLKS, 1);
ctrl->shared_data->hw_rev = MIPI_INP(ctrl->ctrl_base);
- mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 0);
+ mdss_dsi_clk_ctrl(ctrl, DSI_CORE_CLKS, 0);
pr_debug("%s: ndx=%d hw_rev=%x\n", __func__,
ctrl->ndx, ctrl->shared_data->hw_rev);
diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
index c951a56e4774..f884af10b793 100644
--- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c
+++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
@@ -122,11 +122,10 @@ static void mdss_dsi_phy_regulator_disable(struct mdss_dsi_ctrl_pdata *ctrl)
MDSS_DSI_HW_REV_104))
return;
- MIPI_OUTP(ctrl->shared_ctrl_data->phy_regulator_io.base
- + 0x018, 0x000);
+ MIPI_OUTP(ctrl->phy_regulator_io.base + 0x018, 0x000);
}
-static void mdss_dsi_phy_lane_shutdown(struct mdss_dsi_ctrl_pdata *ctrl)
+static void mdss_dsi_phy_shutdown(struct mdss_dsi_ctrl_pdata *ctrl)
{
if (!ctrl) {
pr_err("%s: Invalid input data\n", __func__);
@@ -141,41 +140,6 @@ static void mdss_dsi_phy_lane_shutdown(struct mdss_dsi_ctrl_pdata *ctrl)
}
-void mdss_dsi_phy_disable(struct mdss_dsi_ctrl_pdata *ctrl)
-{
- struct mdss_dsi_ctrl_pdata *other_ctrl;
- if (ctrl == NULL) {
- pr_err("%s: Invalid input data\n", __func__);
- return;
- }
-
- ctrl->shared_ctrl_data->phy_disable_refcount++;
-
- /*
- * In split-dsi configuration, the phy should be disabled for the
- * first controller only when the second controller is disabled.
- * This is true regardless of whether broadcast mode is enabled.
- */
- if (!mdss_dsi_is_hw_config_split(ctrl->shared_data) ||
- ctrl->shared_ctrl_data->phy_disable_refcount == 2) {
-
- other_ctrl = mdss_dsi_get_other_ctrl(ctrl);
- if (other_ctrl)
- mdss_dsi_phy_lane_shutdown(other_ctrl);
-
- mdss_dsi_phy_lane_shutdown(ctrl);
-
- mdss_dsi_phy_regulator_disable(ctrl);
-
- /*
- * Wait for the registers writes to complete in order to
- * ensure that the phy is completely disabled
- */
- wmb();
- ctrl->shared_ctrl_data->phy_disable_refcount = 0;
- }
-}
-
/**
* mdss_dsi_lp_cd_rx() -- enable LP and CD at receiving
* @ctrl: pointer to DSI controller structure
@@ -211,27 +175,26 @@ static void mdss_dsi_28nm_phy_regulator_enable(
if (pd->reg_ldo_mode) {
/* Regulator ctrl 0 */
- MIPI_OUTP(ctrl_pdata->shared_ctrl_data->phy_regulator_io.base,
- 0x0);
+ MIPI_OUTP(ctrl_pdata->phy_regulator_io.base, 0x0);
/* Regulator ctrl - CAL_PWR_CFG */
- MIPI_OUTP((ctrl_pdata->shared_ctrl_data->phy_regulator_io.base)
+ MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
+ 0x18, pd->regulator[6]);
/* Add H/w recommended delay */
udelay(1000);
/* Regulator ctrl - TEST */
- MIPI_OUTP((ctrl_pdata->shared_ctrl_data->phy_regulator_io.base)
+ MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
+ 0x14, pd->regulator[5]);
/* Regulator ctrl 3 */
- MIPI_OUTP((ctrl_pdata->shared_ctrl_data->phy_regulator_io.base)
+ MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
+ 0xc, pd->regulator[3]);
/* Regulator ctrl 2 */
- MIPI_OUTP((ctrl_pdata->shared_ctrl_data->phy_regulator_io.base)
+ MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
+ 0x8, pd->regulator[2]);
/* Regulator ctrl 1 */
- MIPI_OUTP((ctrl_pdata->shared_ctrl_data->phy_regulator_io.base)
+ MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
+ 0x4, pd->regulator[1]);
/* Regulator ctrl 4 */
- MIPI_OUTP((ctrl_pdata->shared_ctrl_data->phy_regulator_io.base)
+ MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
+ 0x10, pd->regulator[4]);
/* LDO ctrl */
if (MIPI_INP(ctrl_pdata->ctrl_base) == MDSS_DSI_HW_REV_103_1)
@@ -240,34 +203,34 @@ static void mdss_dsi_28nm_phy_regulator_enable(
MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x1dc, 0x0d);
} else {
/* Regulator ctrl 0 */
- MIPI_OUTP(ctrl_pdata->shared_ctrl_data->phy_regulator_io.base,
+ MIPI_OUTP(ctrl_pdata->phy_regulator_io.base,
0x0);
/* Regulator ctrl - CAL_PWR_CFG */
- MIPI_OUTP((ctrl_pdata->shared_ctrl_data->phy_regulator_io.base)
+ MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
+ 0x18, pd->regulator[6]);
/* Add H/w recommended delay */
udelay(1000);
/* Regulator ctrl 1 */
- MIPI_OUTP((ctrl_pdata->shared_ctrl_data->phy_regulator_io.base)
+ MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
+ 0x4, pd->regulator[1]);
/* Regulator ctrl 2 */
- MIPI_OUTP((ctrl_pdata->shared_ctrl_data->phy_regulator_io.base)
+ MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
+ 0x8, pd->regulator[2]);
/* Regulator ctrl 3 */
- MIPI_OUTP((ctrl_pdata->shared_ctrl_data->phy_regulator_io.base)
+ MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
+ 0xc, pd->regulator[3]);
/* Regulator ctrl 4 */
- MIPI_OUTP((ctrl_pdata->shared_ctrl_data->phy_regulator_io.base)
+ MIPI_OUTP((ctrl_pdata->phy_regulator_io.base)
+ 0x10, pd->regulator[4]);
/* LDO ctrl */
MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x1dc, 0x00);
/* Regulator ctrl 0 */
- MIPI_OUTP(ctrl_pdata->shared_ctrl_data->phy_regulator_io.base,
+ MIPI_OUTP(ctrl_pdata->phy_regulator_io.base,
pd->regulator[0]);
}
}
-static void mdss_dsi_28nm_phy_init(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+static void mdss_dsi_28nm_phy_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
struct mdss_dsi_phy_ctrl *pd;
int i, off, ln, offset;
@@ -279,10 +242,10 @@ static void mdss_dsi_28nm_phy_init(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
pd = &(((ctrl_pdata->panel_data).panel_info.mipi).dsi_phy_db);
- /* Strength ctrl 0 */
- MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0184, pd->strength[0]);
-
- mdss_dsi_28nm_phy_regulator_enable(ctrl_pdata);
+ /* Strength ctrl 0 for 28nm PHY*/
+ if ((ctrl_pdata->shared_data->hw_rev <= MDSS_DSI_HW_REV_103) &&
+ (ctrl_pdata->shared_data->hw_rev != MDSS_DSI_HW_REV_103))
+ MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0184, pd->strength[0]);
off = 0x0140; /* phy timing ctrl 0 - 11 */
for (i = 0; i < 12; i++) {
@@ -338,7 +301,7 @@ static void mdss_dsi_20nm_phy_regulator_enable(struct mdss_dsi_ctrl_pdata
void __iomem *phy_io_base;
pd = &(((ctrl_pdata->panel_data).panel_info.mipi).dsi_phy_db);
- phy_io_base = ctrl_pdata->shared_ctrl_data->phy_regulator_io.base;
+ phy_io_base = ctrl_pdata->phy_regulator_io.base;
if (pd->regulator_len != 7) {
pr_err("%s: wrong regulator settings\n", __func__);
@@ -481,6 +444,38 @@ static void mdss_dsi_8996_pll_source_from_left(
MIPI_OUTP((ctrl->phy_io.base) + DSIPHY_CMN_GLBL_TEST_CTRL, data);
}
+static void mdss_dsi_8996_phy_regulator_enable(
+ struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ struct mdss_dsi_phy_ctrl *pd;
+ int j, off, ln, cnt, ln_off;
+ char *ip;
+ void __iomem *base;
+
+ pd = &(((ctrl->panel_data).panel_info.mipi).dsi_phy_db);
+ /* 4 lanes + clk lane configuration */
+ for (ln = 0; ln < 5; ln++) {
+ /*
+ * data lane offset frome base: 0x100
+ * data lane size: 0x80
+ */
+ base = ctrl->phy_io.base +
+ DATALANE_OFFSET_FROM_BASE_8996;
+ base += (ln * DATALANE_SIZE_8996); /* lane base */
+
+ /* vreg ctrl, 1 * 5 */
+ cnt = 1;
+ ln_off = cnt * ln;
+ ip = &pd->regulator[ln_off];
+ off = 0x64;
+ for (j = 0; j < cnt; j++, off += 4)
+ MIPI_OUTP(base + off, *ip++);
+ }
+
+ wmb(); /* make sure registers committed */
+
+}
+
static void mdss_dsi_8996_phy_config(struct mdss_dsi_ctrl_pdata *ctrl)
{
struct mdss_dsi_phy_ctrl *pd;
@@ -548,14 +543,6 @@ static void mdss_dsi_8996_phy_config(struct mdss_dsi_ctrl_pdata *ctrl)
off = 0x38;
for (j = 0; j < cnt; j++, off += 4)
MIPI_OUTP(base + off, *ip++);
-
- /* vreg ctrl, 1 * 5 */
- cnt = 1;
- ln_off = cnt * ln;
- ip = &pd->regulator[ln_off];
- off = 0x64;
- for (j = 0; j < cnt; j++, off += 4)
- MIPI_OUTP(base + off, *ip++);
}
wmb(); /* make sure registers committed */
@@ -581,47 +568,113 @@ static void mdss_dsi_8996_phy_config(struct mdss_dsi_ctrl_pdata *ctrl)
wmb(); /* make sure registers committed */
}
-static void mdss_dsi_20nm_phy_init(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+static void mdss_dsi_phy_regulator_ctrl(struct mdss_dsi_ctrl_pdata *ctrl,
+ bool enable)
{
- if (!ctrl_pdata) {
+ struct mdss_dsi_ctrl_pdata *other_ctrl;
+ struct dsi_shared_data *sdata;
+
+ if (!ctrl) {
pr_err("%s: Invalid input data\n", __func__);
return;
}
- mdss_dsi_20nm_phy_regulator_enable(ctrl_pdata);
+ sdata = ctrl->shared_data;
- mdss_dsi_20nm_phy_config(ctrl_pdata);
+ mutex_lock(&sdata->phy_reg_lock);
+ if (enable) {
+ switch (ctrl->shared_data->hw_rev) {
+ case MDSS_DSI_HW_REV_104:
+ case MDSS_DSI_HW_REV_104_1:
+ mdss_dsi_8996_phy_regulator_enable(ctrl);
+ break;
+ case MDSS_DSI_HW_REV_103:
+ mdss_dsi_20nm_phy_regulator_enable(ctrl);
+ break;
+ default:
+ mdss_dsi_28nm_phy_regulator_enable(ctrl);
+ break;
+ }
+ ctrl->is_phyreg_enabled = 1;
+ } else {
+ /*
+ * In split-dsi/dual-dsi configuration, the dsi phy regulator
+ * should be turned off only when both the DSI devices are
+ * going to be turned off since it is shared.
+ */
+ if (mdss_dsi_is_hw_config_split(ctrl->shared_data) ||
+ mdss_dsi_is_hw_config_dual(ctrl->shared_data)) {
+ other_ctrl = mdss_dsi_get_other_ctrl(ctrl);
+ if (other_ctrl && !other_ctrl->is_phyreg_enabled)
+ mdss_dsi_phy_regulator_disable(ctrl);
+ } else {
+ mdss_dsi_phy_regulator_disable(ctrl);
+ }
+ ctrl->is_phyreg_enabled = 0;
+ }
+ mutex_unlock(&sdata->phy_reg_lock);
}
-static void mdss_dsi_8996_phy_init(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+static void mdss_dsi_phy_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, bool enable)
{
- if (!ctrl_pdata) {
+ struct mdss_dsi_ctrl_pdata *other_ctrl;
+ if (!ctrl) {
pr_err("%s: Invalid input data\n", __func__);
return;
}
- mdss_dsi_8996_phy_config(ctrl_pdata);
+ if (enable) {
+ switch (ctrl->shared_data->hw_rev) {
+ case MDSS_DSI_HW_REV_104:
+ case MDSS_DSI_HW_REV_104_1:
+ mdss_dsi_8996_phy_config(ctrl);
+ break;
+ case MDSS_DSI_HW_REV_103:
+ mdss_dsi_20nm_phy_config(ctrl);
+ break;
+ default:
+ mdss_dsi_28nm_phy_config(ctrl);
+ break;
+ }
+ } else {
+ /*
+ * In split-dsi configuration, the phy should be disabled for
+ * the first controller only when the second controller is
+ * disabled. This is true regardless of whether broadcast
+ * mode is enabled.
+ */
+ if (mdss_dsi_is_hw_config_split(ctrl->shared_data)) {
+ other_ctrl = mdss_dsi_get_other_ctrl(ctrl);
+ if (mdss_dsi_is_right_ctrl(ctrl) && other_ctrl) {
+ mdss_dsi_phy_shutdown(other_ctrl);
+ mdss_dsi_phy_shutdown(ctrl);
+ }
+ } else {
+ mdss_dsi_phy_shutdown(ctrl);
+ }
+ }
}
-static void mdss_dsi_phy_init(struct mdss_dsi_ctrl_pdata *ctrl)
+void mdss_dsi_phy_disable(struct mdss_dsi_ctrl_pdata *ctrl)
{
- if (!ctrl) {
+ if (ctrl == NULL) {
pr_err("%s: Invalid input data\n", __func__);
return;
}
- switch (ctrl->shared_data->hw_rev) {
- case MDSS_DSI_HW_REV_104:
- case MDSS_DSI_HW_REV_104_1:
- mdss_dsi_8996_phy_init(ctrl);
- break;
- case MDSS_DSI_HW_REV_103:
- mdss_dsi_20nm_phy_init(ctrl);
- break;
- default:
- mdss_dsi_28nm_phy_init(ctrl);
- break;
- }
+ mdss_dsi_phy_ctrl(ctrl, false);
+ mdss_dsi_phy_regulator_ctrl(ctrl, false);
+ /*
+ * Wait for the registers writes to complete in order to
+ * ensure that the phy is completely disabled
+ */
+ wmb();
+}
+
+void mdss_dsi_phy_init(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ mdss_dsi_phy_regulator_ctrl(ctrl, true);
+ mdss_dsi_phy_ctrl(ctrl, true);
}
void mdss_dsi_core_clk_deinit(struct device *dev, struct dsi_shared_data *sdata)