summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.c57
-rw-r--r--drivers/video/fbdev/msm/msm_mdss_io_8974.c119
2 files changed, 119 insertions, 57 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index cdc597bebf52..cacb89d7eac9 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -1082,6 +1082,58 @@ static void mdss_dsi_validate_debugfs_info(
}
}
+/**
+ * mdss_dsi_clamp_phy_reset_config() - configure DSI phy reset mask
+ * @ctrl: pointer to DSI controller structure
+ * @enable: true to mask the reset signal, false to unmask
+ *
+ * Configure the register to mask/unmask the propagation of the mdss ahb
+ * clock reset signal to the DSI PHY. This would be necessary when the MDSS
+ * core is idle power collapsed with the DSI panel on. This function assumes
+ * that the mmss_misc_ahb clock is already on.
+ */
+static int mdss_dsi_clamp_phy_reset_config(struct mdss_dsi_ctrl_pdata *ctrl,
+ bool enable)
+{
+ u32 regval;
+
+ if (!ctrl) {
+ pr_warn_ratelimited("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!ctrl->mmss_misc_io.base) {
+ pr_warn_ratelimited("%s: mmss_misc_io not mapped\n", __func__);
+ return -EINVAL;
+ }
+
+ if ((ctrl->shared_data->hw_rev >= MDSS_DSI_HW_REV_104) &&
+ (MDSS_GET_STEP(ctrl->shared_data->hw_rev) !=
+ MDSS_DSI_HW_REV_STEP_2)) {
+ u32 clamp_reg_off = ctrl->shared_data->ulps_clamp_ctrl_off;
+
+ regval = MIPI_INP(ctrl->mmss_misc_io.base + clamp_reg_off);
+ if (enable)
+ regval = regval | BIT(30);
+ else
+ regval = regval & ~BIT(30);
+ MIPI_OUTP(ctrl->mmss_misc_io.base + clamp_reg_off, regval);
+ } else {
+ u32 phyrst_reg_off = ctrl->shared_data->ulps_phyrst_ctrl_off;
+
+ if (enable)
+ regval = BIT(0);
+ else
+ regval = 0;
+ MIPI_OUTP(ctrl->mmss_misc_io.base + phyrst_reg_off, regval);
+ }
+
+ /* make sure that clamp ctrl is updated */
+ wmb();
+
+ return 0;
+}
+
static int mdss_dsi_off(struct mdss_panel_data *pdata, int power_state)
{
int ret = 0;
@@ -1134,7 +1186,7 @@ static int mdss_dsi_off(struct mdss_panel_data *pdata, int power_state)
mdss_dsi_phy_disable(ctrl_pdata);
}
ctrl_pdata->ctrl_state &= ~CTRL_STATE_DSI_ACTIVE;
-
+ mdss_dsi_clamp_phy_reset_config(ctrl_pdata, false);
mdss_dsi_clk_ctrl(ctrl_pdata, ctrl_pdata->dsi_clk_handle,
MDSS_DSI_CORE_CLK, MDSS_DSI_CLK_OFF);
@@ -1338,6 +1390,8 @@ int mdss_dsi_on(struct mdss_panel_data *pdata)
}
ctrl_pdata->ctrl_state |= CTRL_STATE_DSI_ACTIVE;
+ mdss_dsi_clamp_phy_reset_config(ctrl_pdata, true);
+
/* DSI link clocks need to be on prior to ctrl sw reset */
mdss_dsi_clk_ctrl(ctrl_pdata, ctrl_pdata->dsi_clk_handle,
MDSS_DSI_LINK_CLK, MDSS_DSI_CLK_ON);
@@ -2908,6 +2962,7 @@ static int mdss_dsi_cont_splash_config(struct mdss_panel_info *pinfo,
ctrl_pdata->is_phyreg_enabled = 1;
if (pinfo->type == MIPI_CMD_PANEL)
mdss_dsi_set_burst_mode(ctrl_pdata);
+ mdss_dsi_clamp_phy_reset_config(ctrl_pdata, true);
} else {
/* Turn on the clocks to read the DSI and PHY revision */
mdss_dsi_clk_ctrl(ctrl_pdata, ctrl_pdata->dsi_clk_handle,
diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
index 6da526f647d9..fafc74d79ac1 100644
--- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c
+++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
@@ -1934,22 +1934,21 @@ error:
}
/**
- * mdss_dsi_clamp_ctrl() - Program DSI clamps for supporting power collapse
+ * mdss_dsi_clamp_ctrl_default() - Program DSI clamps
* @ctrl: pointer to DSI controller structure
- * @enable: 1 to enable clamps, 0 to disable clamps
+ * @enable: true to enable clamps, false to disable clamps
*
- * For idle-screen usecases with command mode panels, MDSS can be power
- * collapsed. However, DSI phy needs to remain on. To avoid any mismatch
- * between the DSI controller state, DSI phy needs to be clamped before
- * power collapsing. This function executes the required programming
- * sequence to configure these DSI clamps. This function should only be called
- * when the DSI link clocks are disabled.
+ * Execute the required programming sequence to configure DSI clamps. This
+ * function would be called whenever there are no hardware version sepcific
+ * functions for programming the DSI clamps. This function assumes that the
+ * core clocks are already on.
*/
-static int mdss_dsi_clamp_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
+static int mdss_dsi_clamp_ctrl_default(struct mdss_dsi_ctrl_pdata *ctrl,
+ bool enable)
{
struct mipi_panel_info *mipi = NULL;
u32 clamp_reg, regval = 0;
- u32 clamp_reg_off, phyrst_reg_off;
+ u32 clamp_reg_off;
if (!ctrl) {
pr_err("%s: invalid input\n", __func__);
@@ -1962,7 +1961,6 @@ static int mdss_dsi_clamp_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
}
clamp_reg_off = ctrl->shared_data->ulps_clamp_ctrl_off;
- phyrst_reg_off = ctrl->shared_data->ulps_phyrst_ctrl_off;
mipi = &ctrl->panel_data.panel_info.mipi;
/* clock lane will always be clamped */
@@ -1992,7 +1990,8 @@ static int mdss_dsi_clamp_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
}
pr_debug("%s: called for ctrl%d, enable=%d, clamp_reg=0x%08x\n",
__func__, ctrl->ndx, enable, clamp_reg);
- if (enable && !ctrl->mmss_clamp) {
+
+ if (enable) {
regval = MIPI_INP(ctrl->mmss_misc_io.base + clamp_reg_off);
/* Enable MMSS DSI Clamps */
if (ctrl->ndx == DSI_CTRL_0) {
@@ -2006,47 +2005,7 @@ static int mdss_dsi_clamp_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
MIPI_OUTP(ctrl->mmss_misc_io.base + clamp_reg_off,
regval | ((clamp_reg << 16) | BIT(31)));
}
- /* update clamp ctrl before setting phy reset disable */
- wmb();
-
- /*
- * This register write ensures that DSI PHY will not be
- * reset when mdss ahb clock reset is asserted while coming
- * out of power collapse
- */
- if (IS_MDSS_MAJOR_MINOR_SAME(ctrl->shared_data->hw_rev,
- MDSS_DSI_HW_REV_104) &&
- (MDSS_GET_STEP(ctrl->shared_data->hw_rev) !=
- MDSS_DSI_HW_REV_STEP_2)) {
-
- regval = MIPI_INP(ctrl->mmss_misc_io.base +
- clamp_reg_off);
- MIPI_OUTP(ctrl->mmss_misc_io.base + clamp_reg_off,
- regval | BIT(30));
- } else {
- MIPI_OUTP(ctrl->mmss_misc_io.base + phyrst_reg_off,
- 0x1);
- }
- /* make sure that clamp ctrl is updated before disable call */
- wmb();
- ctrl->mmss_clamp = true;
- } else if (!enable && ctrl->mmss_clamp) {
- if (IS_MDSS_MAJOR_MINOR_SAME(ctrl->shared_data->hw_rev,
- MDSS_DSI_HW_REV_104) &&
- (MDSS_GET_STEP(ctrl->shared_data->hw_rev) !=
- MDSS_DSI_HW_REV_STEP_2)) {
-
- regval = MIPI_INP(ctrl->mmss_misc_io.base +
- clamp_reg_off);
- MIPI_OUTP(ctrl->mmss_misc_io.base + clamp_reg_off,
- regval & ~BIT(30));
- } else {
- MIPI_OUTP(ctrl->mmss_misc_io.base + phyrst_reg_off,
- 0x0);
- }
- /* update clamp ctrl before unsetting phy reset disable */
- wmb();
-
+ } else {
regval = MIPI_INP(ctrl->mmss_misc_io.base + clamp_reg_off);
/* Disable MMSS DSI Clamps */
if (ctrl->ndx == DSI_CTRL_0)
@@ -2055,8 +2014,51 @@ static int mdss_dsi_clamp_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
else if (ctrl->ndx == DSI_CTRL_1)
MIPI_OUTP(ctrl->mmss_misc_io.base + clamp_reg_off,
regval & ~((clamp_reg << 16) | BIT(31)));
- /* make sure that clamp ctrl is updated before enable call */
- wmb();
+ }
+
+ /* make sure clamps are configured */
+ wmb();
+
+ return 0;
+}
+
+/**
+ * mdss_dsi_clamp_ctrl() - Program DSI clamps for supporting power collapse
+ * @ctrl: pointer to DSI controller structure
+ * @enable: 1 to enable clamps, 0 to disable clamps
+ *
+ * For idle-screen usecases with command mode panels, MDSS can be power
+ * collapsed. However, DSI phy needs to remain on. To avoid any mismatch
+ * between the DSI controller state, DSI phy needs to be clamped before
+ * power collapsing. This function executes the required programming
+ * sequence to configure these DSI clamps. This function should only be called
+ * when the DSI link clocks are disabled.
+ */
+static int mdss_dsi_clamp_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
+{
+ int rc = 0;
+
+ if (!ctrl) {
+ pr_err("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ pr_debug("%s: called for ctrl%d, enable=%d\n", __func__, ctrl->ndx,
+ enable);
+
+ if (enable && !ctrl->mmss_clamp) {
+ if (ctrl->shared_data->phy_rev < DSI_PHY_REV_30) {
+ rc = mdss_dsi_clamp_ctrl_default(ctrl, true);
+ if (rc)
+ goto error;
+ }
+ ctrl->mmss_clamp = true;
+ } else if (!enable && ctrl->mmss_clamp) {
+ if (ctrl->shared_data->phy_rev < DSI_PHY_REV_30) {
+ rc = mdss_dsi_clamp_ctrl_default(ctrl, false);
+ if (rc)
+ goto error;
+ }
ctrl->mmss_clamp = false;
} else {
pr_debug("%s: No change requested: %s -> %s\n", __func__,
@@ -2064,7 +2066,12 @@ static int mdss_dsi_clamp_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
enable ? "enabled" : "disabled");
}
- return 0;
+error:
+ if (rc)
+ pr_err("%s: failed to %s clamps for ctrl%d\n", __func__,
+ enable ? "enable" : "disable", ctrl->ndx);
+
+ return rc;
}
DEFINE_MUTEX(dsi_clk_mutex);