Commit c3bb5b0f authored by Tony Lindgren's avatar Tony Lindgren Committed by Greg Kroah-Hartman

drm/omap: dsi: Fix PM for display blank with paired dss_pll calls

[ Upstream commit fe4ed1b4 ]

Currently dsi_display_init_dsi() calls dss_pll_enable() but it is not
paired with dss_pll_disable() in dsi_display_uninit_dsi(). This leaves
the DSS clocks enabled when the display is blanked wasting about extra
5mW of power while idle.

The clock that is left on by not calling dss_pll_disable() is
DSS_CLKCTRL bit 10 OPTFCLKEN_SYS_CLK that is the source clock for
DSI PLL.

We can fix this issue by by making the current dsi_pll_uninit() into
dsi_pll_disable(). This way we can just call dss_pll_disable() from
dsi_display_uninit_dsi() and the code becomes a bit easier to follow.

However, we need to also consider that DSI PLL can be muxed for DVI too
as pointed out by Tomi Valkeinen <tomi.valkeinen@ti.com>. In the DVI
case, we want to unconditionally disable the clocks. To get around this
issue, we separate out the DSI lane handling from dsi_pll_enable() and
dsi_pll_disable() as suggested by Tomi in an earlier experimental patch.

So we must only toggle the DSI regulator based on the vdds_dsi_enabled
flag from dsi_display_init_dsi() and dsi_display_uninit_dsi().

We need to make these two changes together to avoid breaking things
for DVI when fixing the DSI clock handling. And this all causes a
slight renumbering of the error path for dsi_display_init_dsi().
Suggested-by: default avatarTomi Valkeinen <tomi.valkeinen@ti.com>
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@ti.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 7d188953
...@@ -1342,12 +1342,9 @@ static int dsi_pll_enable(struct dss_pll *pll) ...@@ -1342,12 +1342,9 @@ static int dsi_pll_enable(struct dss_pll *pll)
*/ */
dsi_enable_scp_clk(dsi); dsi_enable_scp_clk(dsi);
if (!dsi->vdds_dsi_enabled) {
r = regulator_enable(dsi->vdds_dsi_reg); r = regulator_enable(dsi->vdds_dsi_reg);
if (r) if (r)
goto err0; goto err0;
dsi->vdds_dsi_enabled = true;
}
/* XXX PLL does not come out of reset without this... */ /* XXX PLL does not come out of reset without this... */
dispc_pck_free_enable(dsi->dss->dispc, 1); dispc_pck_free_enable(dsi->dss->dispc, 1);
...@@ -1372,36 +1369,25 @@ static int dsi_pll_enable(struct dss_pll *pll) ...@@ -1372,36 +1369,25 @@ static int dsi_pll_enable(struct dss_pll *pll)
return 0; return 0;
err1: err1:
if (dsi->vdds_dsi_enabled) {
regulator_disable(dsi->vdds_dsi_reg); regulator_disable(dsi->vdds_dsi_reg);
dsi->vdds_dsi_enabled = false;
}
err0: err0:
dsi_disable_scp_clk(dsi); dsi_disable_scp_clk(dsi);
dsi_runtime_put(dsi); dsi_runtime_put(dsi);
return r; return r;
} }
static void dsi_pll_uninit(struct dsi_data *dsi, bool disconnect_lanes) static void dsi_pll_disable(struct dss_pll *pll)
{ {
struct dsi_data *dsi = container_of(pll, struct dsi_data, pll);
dsi_pll_power(dsi, DSI_PLL_POWER_OFF); dsi_pll_power(dsi, DSI_PLL_POWER_OFF);
if (disconnect_lanes) {
WARN_ON(!dsi->vdds_dsi_enabled);
regulator_disable(dsi->vdds_dsi_reg); regulator_disable(dsi->vdds_dsi_reg);
dsi->vdds_dsi_enabled = false;
}
dsi_disable_scp_clk(dsi); dsi_disable_scp_clk(dsi);
dsi_runtime_put(dsi); dsi_runtime_put(dsi);
DSSDBG("PLL uninit done\n"); DSSDBG("PLL disable done\n");
}
static void dsi_pll_disable(struct dss_pll *pll)
{
struct dsi_data *dsi = container_of(pll, struct dsi_data, pll);
dsi_pll_uninit(dsi, true);
} }
static int dsi_dump_dsi_clocks(struct seq_file *s, void *p) static int dsi_dump_dsi_clocks(struct seq_file *s, void *p)
...@@ -4096,11 +4082,11 @@ static int dsi_display_init_dsi(struct dsi_data *dsi) ...@@ -4096,11 +4082,11 @@ static int dsi_display_init_dsi(struct dsi_data *dsi)
r = dss_pll_enable(&dsi->pll); r = dss_pll_enable(&dsi->pll);
if (r) if (r)
goto err0; return r;
r = dsi_configure_dsi_clocks(dsi); r = dsi_configure_dsi_clocks(dsi);
if (r) if (r)
goto err1; goto err0;
dss_select_dsi_clk_source(dsi->dss, dsi->module_id, dss_select_dsi_clk_source(dsi->dss, dsi->module_id,
dsi->module_id == 0 ? dsi->module_id == 0 ?
...@@ -4108,6 +4094,14 @@ static int dsi_display_init_dsi(struct dsi_data *dsi) ...@@ -4108,6 +4094,14 @@ static int dsi_display_init_dsi(struct dsi_data *dsi)
DSSDBG("PLL OK\n"); DSSDBG("PLL OK\n");
if (!dsi->vdds_dsi_enabled) {
r = regulator_enable(dsi->vdds_dsi_reg);
if (r)
goto err1;
dsi->vdds_dsi_enabled = true;
}
r = dsi_cio_init(dsi); r = dsi_cio_init(dsi);
if (r) if (r)
goto err2; goto err2;
...@@ -4136,10 +4130,13 @@ static int dsi_display_init_dsi(struct dsi_data *dsi) ...@@ -4136,10 +4130,13 @@ static int dsi_display_init_dsi(struct dsi_data *dsi)
err3: err3:
dsi_cio_uninit(dsi); dsi_cio_uninit(dsi);
err2: err2:
dss_select_dsi_clk_source(dsi->dss, dsi->module_id, DSS_CLK_SRC_FCK); regulator_disable(dsi->vdds_dsi_reg);
dsi->vdds_dsi_enabled = false;
err1: err1:
dss_pll_disable(&dsi->pll); dss_select_dsi_clk_source(dsi->dss, dsi->module_id, DSS_CLK_SRC_FCK);
err0: err0:
dss_pll_disable(&dsi->pll);
return r; return r;
} }
...@@ -4158,7 +4155,12 @@ static void dsi_display_uninit_dsi(struct dsi_data *dsi, bool disconnect_lanes, ...@@ -4158,7 +4155,12 @@ static void dsi_display_uninit_dsi(struct dsi_data *dsi, bool disconnect_lanes,
dss_select_dsi_clk_source(dsi->dss, dsi->module_id, DSS_CLK_SRC_FCK); dss_select_dsi_clk_source(dsi->dss, dsi->module_id, DSS_CLK_SRC_FCK);
dsi_cio_uninit(dsi); dsi_cio_uninit(dsi);
dsi_pll_uninit(dsi, disconnect_lanes); dss_pll_disable(&dsi->pll);
if (disconnect_lanes) {
regulator_disable(dsi->vdds_dsi_reg);
dsi->vdds_dsi_enabled = false;
}
} }
static int dsi_display_enable(struct omap_dss_device *dssdev) static int dsi_display_enable(struct omap_dss_device *dssdev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment