aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm/dss/dsi.c
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2019-02-07 10:45:16 -0500
committerTomi Valkeinen <tomi.valkeinen@ti.com>2019-03-18 05:42:14 -0400
commitfe4ed1b457943113ee1138c939fbdeede4af6cf3 (patch)
tree1e2ecf34f7d5e5beb68a8ae2afd34f686422e40e /drivers/gpu/drm/omapdrm/dss/dsi.c
parenta0970e87b5d357c8a1ec9c18e128a8d7921c29f9 (diff)
drm/omap: dsi: Fix PM for display blank with paired dss_pll calls
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: Tomi Valkeinen <tomi.valkeinen@ti.com> Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/gpu/drm/omapdrm/dss/dsi.c')
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dsi.c60
1 files changed, 31 insertions, 29 deletions
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 5c34fba51975..5202862d89b5 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -1342,12 +1342,9 @@ static int dsi_pll_enable(struct dss_pll *pll)
1342 */ 1342 */
1343 dsi_enable_scp_clk(dsi); 1343 dsi_enable_scp_clk(dsi);
1344 1344
1345 if (!dsi->vdds_dsi_enabled) { 1345 r = regulator_enable(dsi->vdds_dsi_reg);
1346 r = regulator_enable(dsi->vdds_dsi_reg); 1346 if (r)
1347 if (r) 1347 goto err0;
1348 goto err0;
1349 dsi->vdds_dsi_enabled = true;
1350 }
1351 1348
1352 /* XXX PLL does not come out of reset without this... */ 1349 /* XXX PLL does not come out of reset without this... */
1353 dispc_pck_free_enable(dsi->dss->dispc, 1); 1350 dispc_pck_free_enable(dsi->dss->dispc, 1);
@@ -1372,36 +1369,25 @@ static int dsi_pll_enable(struct dss_pll *pll)
1372 1369
1373 return 0; 1370 return 0;
1374err1: 1371err1:
1375 if (dsi->vdds_dsi_enabled) { 1372 regulator_disable(dsi->vdds_dsi_reg);
1376 regulator_disable(dsi->vdds_dsi_reg);
1377 dsi->vdds_dsi_enabled = false;
1378 }
1379err0: 1373err0:
1380 dsi_disable_scp_clk(dsi); 1374 dsi_disable_scp_clk(dsi);
1381 dsi_runtime_put(dsi); 1375 dsi_runtime_put(dsi);
1382 return r; 1376 return r;
1383} 1377}
1384 1378
1385static void dsi_pll_uninit(struct dsi_data *dsi, bool disconnect_lanes) 1379static void dsi_pll_disable(struct dss_pll *pll)
1386{ 1380{
1381 struct dsi_data *dsi = container_of(pll, struct dsi_data, pll);
1382
1387 dsi_pll_power(dsi, DSI_PLL_POWER_OFF); 1383 dsi_pll_power(dsi, DSI_PLL_POWER_OFF);
1388 if (disconnect_lanes) { 1384
1389 WARN_ON(!dsi->vdds_dsi_enabled); 1385 regulator_disable(dsi->vdds_dsi_reg);
1390 regulator_disable(dsi->vdds_dsi_reg);
1391 dsi->vdds_dsi_enabled = false;
1392 }
1393 1386
1394 dsi_disable_scp_clk(dsi); 1387 dsi_disable_scp_clk(dsi);
1395 dsi_runtime_put(dsi); 1388 dsi_runtime_put(dsi);
1396 1389
1397 DSSDBG("PLL uninit done\n"); 1390 DSSDBG("PLL disable done\n");
1398}
1399
1400static void dsi_pll_disable(struct dss_pll *pll)
1401{
1402 struct dsi_data *dsi = container_of(pll, struct dsi_data, pll);
1403
1404 dsi_pll_uninit(dsi, true);
1405} 1391}
1406 1392
1407static int dsi_dump_dsi_clocks(struct seq_file *s, void *p) 1393static int dsi_dump_dsi_clocks(struct seq_file *s, void *p)
@@ -4089,11 +4075,11 @@ static int dsi_display_init_dsi(struct dsi_data *dsi)
4089 4075
4090 r = dss_pll_enable(&dsi->pll); 4076 r = dss_pll_enable(&dsi->pll);
4091 if (r) 4077 if (r)
4092 goto err0; 4078 return r;
4093 4079
4094 r = dsi_configure_dsi_clocks(dsi); 4080 r = dsi_configure_dsi_clocks(dsi);
4095 if (r) 4081 if (r)
4096 goto err1; 4082 goto err0;
4097 4083
4098 dss_select_dsi_clk_source(dsi->dss, dsi->module_id, 4084 dss_select_dsi_clk_source(dsi->dss, dsi->module_id,
4099 dsi->module_id == 0 ? 4085 dsi->module_id == 0 ?
@@ -4101,6 +4087,14 @@ static int dsi_display_init_dsi(struct dsi_data *dsi)
4101 4087
4102 DSSDBG("PLL OK\n"); 4088 DSSDBG("PLL OK\n");
4103 4089
4090 if (!dsi->vdds_dsi_enabled) {
4091 r = regulator_enable(dsi->vdds_dsi_reg);
4092 if (r)
4093 goto err1;
4094
4095 dsi->vdds_dsi_enabled = true;
4096 }
4097
4104 r = dsi_cio_init(dsi); 4098 r = dsi_cio_init(dsi);
4105 if (r) 4099 if (r)
4106 goto err2; 4100 goto err2;
@@ -4129,10 +4123,13 @@ static int dsi_display_init_dsi(struct dsi_data *dsi)
4129err3: 4123err3:
4130 dsi_cio_uninit(dsi); 4124 dsi_cio_uninit(dsi);
4131err2: 4125err2:
4132 dss_select_dsi_clk_source(dsi->dss, dsi->module_id, DSS_CLK_SRC_FCK); 4126 regulator_disable(dsi->vdds_dsi_reg);
4127 dsi->vdds_dsi_enabled = false;
4133err1: 4128err1:
4134 dss_pll_disable(&dsi->pll); 4129 dss_select_dsi_clk_source(dsi->dss, dsi->module_id, DSS_CLK_SRC_FCK);
4135err0: 4130err0:
4131 dss_pll_disable(&dsi->pll);
4132
4136 return r; 4133 return r;
4137} 4134}
4138 4135
@@ -4151,7 +4148,12 @@ static void dsi_display_uninit_dsi(struct dsi_data *dsi, bool disconnect_lanes,
4151 4148
4152 dss_select_dsi_clk_source(dsi->dss, dsi->module_id, DSS_CLK_SRC_FCK); 4149 dss_select_dsi_clk_source(dsi->dss, dsi->module_id, DSS_CLK_SRC_FCK);
4153 dsi_cio_uninit(dsi); 4150 dsi_cio_uninit(dsi);
4154 dsi_pll_uninit(dsi, disconnect_lanes); 4151 dss_pll_disable(&dsi->pll);
4152
4153 if (disconnect_lanes) {
4154 regulator_disable(dsi->vdds_dsi_reg);
4155 dsi->vdds_dsi_enabled = false;
4156 }
4155} 4157}
4156 4158
4157static void dsi_display_enable(struct omap_dss_device *dssdev) 4159static void dsi_display_enable(struct omap_dss_device *dssdev)