Merge "msm: mdss: Turn off MDP GDSC in idle screen for cmd mode panels"
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index ada1281..7e6faa8 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -192,6 +192,7 @@
int handoff_pending;
struct mdss_prefill_data prefill_data;
+ bool ulps;
};
extern struct mdss_data_type *mdss_res;
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index e1786a6..cfa594c 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -2405,8 +2405,10 @@
pr_debug("Enable MDP FS\n");
if (!mdata->fs_ena) {
regulator_enable(mdata->fs);
- mdss_mdp_cx_ctrl(mdata, true);
- mdss_mdp_batfet_ctrl(mdata, true);
+ if (!mdata->ulps) {
+ mdss_mdp_cx_ctrl(mdata, true);
+ mdss_mdp_batfet_ctrl(mdata, true);
+ }
}
mdata->fs_ena = true;
} else {
@@ -2414,13 +2416,41 @@
mdss_iommu_dettach(mdata);
if (mdata->fs_ena) {
regulator_disable(mdata->fs);
- mdss_mdp_cx_ctrl(mdata, false);
- mdss_mdp_batfet_ctrl(mdata, false);
+ if (!mdata->ulps) {
+ mdss_mdp_cx_ctrl(mdata, false);
+ mdss_mdp_batfet_ctrl(mdata, false);
+ }
}
mdata->fs_ena = false;
}
}
+/**
+ * mdss_mdp_footswitch_ctrl_ulps() - MDSS GDSC control with ULPS feature
+ * @on: 1 to turn on footswitch, 0 to turn off footswitch
+ * @dev: framebuffer device node
+ *
+ * MDSS GDSC can be voted off during idle-screen usecase for MIPI DSI command
+ * mode displays with Ultra-Low Power State (ULPS) feature enabled. Upon
+ * subsequent frame update, MDSS GDSC needs to turned back on and hw state
+ * needs to be restored.
+ */
+void mdss_mdp_footswitch_ctrl_ulps(int on, struct device *dev)
+{
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+
+ pr_debug("called on=%d\n", on);
+ if (on) {
+ pm_runtime_get_sync(dev);
+ mdss_iommu_attach(mdata);
+ mdss_hw_init(mdata);
+ mdata->ulps = false;
+ } else {
+ mdata->ulps = true;
+ pm_runtime_put_sync(dev);
+ }
+}
+
static inline int mdss_mdp_suspend_sub(struct mdss_data_type *mdata)
{
mdata->suspend_fs_ena = mdata->fs_ena;
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 3afb27e..9a469a4 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -681,6 +681,8 @@
int mdss_mdp_wb_set_secure(struct msm_fb_data_type *mfd, int enable);
int mdss_mdp_wb_get_secure(struct msm_fb_data_type *mfd, uint8_t *enable);
+void mdss_mdp_ctl_restore(struct mdss_mdp_ctl *ctl);
+void mdss_mdp_footswitch_ctrl_ulps(int on, struct device *dev);
int mdss_mdp_pipe_program_pixel_extn(struct mdss_mdp_pipe *pipe);
#define mfd_to_mdp5_data(mfd) (mfd->mdp.private1)
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index b445afa..fa64448 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -1588,6 +1588,25 @@
return rc;
}
+/*
+ * mdss_mdp_ctl_restore() - restore mdp ctl path
+ * @ctl: mdp controller.
+ *
+ * This function is called whenever MDP comes out of a power collapse as
+ * a result of a screen update when DSI ULPS mode is enabled. It restores
+ * the MDP controller's software state to the hardware registers.
+ */
+void mdss_mdp_ctl_restore(struct mdss_mdp_ctl *ctl)
+{
+ u32 temp;
+
+ temp = readl_relaxed(ctl->mdata->mdp_base +
+ MDSS_MDP_REG_DISP_INTF_SEL);
+ temp |= (ctl->intf_type << ((ctl->intf_num - MDSS_MDP_INTF0) * 8));
+ writel_relaxed(temp, ctl->mdata->mdp_base +
+ MDSS_MDP_REG_DISP_INTF_SEL);
+}
+
static int mdss_mdp_ctl_start_sub(struct mdss_mdp_ctl *ctl, bool handoff)
{
struct mdss_mdp_mixer *mixer;
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index abd130e..8c7dc29 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -408,6 +408,8 @@
if (!mdss_mdp_ctl_intf_event(ctx->ctl, MDSS_EVENT_DSI_ULPS_CTRL,
(void *)1)) {
ctx->ulps = true;
+ ctx->ctl->play_cnt = 0;
+ mdss_mdp_footswitch_ctrl_ulps(0, &ctx->ctl->mfd->pdev->dev);
}
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 4a71a84..ca35aaf 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -847,6 +847,11 @@
struct mdss_mdp_ctl *ctl = mdp5_data->ctl;
if (ctl->power_on) {
+ if (mdp5_data->mdata->ulps) {
+ mdss_mdp_footswitch_ctrl_ulps(1, &mfd->pdev->dev);
+ mdss_mdp_ctl_restore(ctl);
+ }
+
if (!mdp5_data->mdata->batfet)
mdss_mdp_batfet_ctrl(mdp5_data->mdata, true);
if (!mfd->panel_info->cont_splash_enabled)
@@ -1042,11 +1047,13 @@
pipe->mixer = mdss_mdp_mixer_get(tmp,
MDSS_MDP_MIXER_MUX_DEFAULT);
}
+
+ /* ensure pipes are always reconfigured after power off/on */
+ if (ctl->play_cnt == 0)
+ pipe->params_changed++;
+
if (pipe->back_buf.num_planes) {
buf = &pipe->back_buf;
- } else if (ctl->play_cnt == 0 && pipe->front_buf.num_planes) {
- pipe->params_changed++;
- buf = &pipe->front_buf;
} else if (!pipe->params_changed) {
continue;
} else if (pipe->front_buf.num_planes) {