summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilippe Langlais <philippe.langlais@linaro.org>2011-05-05 15:04:02 +0200
committerUlf Hansson <ulf.hansson@stericsson.com>2011-09-19 15:15:01 +0200
commit99aa7a82a4c70ce5c7815ff37ea16188107ade5d (patch)
tree997cfbe52f8feb9ae974a61214fd7a59d1e401cd
parent32dab36e9248b52b368f32512ef17c69ad1a4ffb (diff)
video: mcde: Request dsi/dpi clocks only if needed
DSI clocks (HDMICLK, TVCLK) and regulator VANA should only be requested if a channel uses DSI as formatter. DPI Clock (LCDCLK) is only requested if DPI is used as formatter. ST-Ericsson Linux next: - ST-Ericsson ID: AP 329602 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I2e9a63ef58d3f11f7e2c47dbd86bf1fbbec3b71e Signed-off-by: Jimmy Rubin <jimmy.rubin@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/18030 Reviewed-by: QATOOLS Reviewed-by: Per PERSSON <per.xb.persson@stericsson.com> Conflicts: arch/arm/mach-ux500/devices-db5500.c arch/arm/mach-ux500/devices-db8500.c arch/arm/mach-ux500/include/mach/prcmu-fw-api.h arch/arm/mach-ux500/prcmu-db5500.c
-rw-r--r--arch/arm/mach-ux500/devices-db5500.c14
-rw-r--r--arch/arm/mach-ux500/devices-db8500.c14
-rw-r--r--drivers/video/mcde/mcde_hw.c205
-rw-r--r--include/video/mcde.h9
4 files changed, 157 insertions, 85 deletions
diff --git a/arch/arm/mach-ux500/devices-db5500.c b/arch/arm/mach-ux500/devices-db5500.c
index 0456e430dec..b1afed2d35f 100644
--- a/arch/arm/mach-ux500/devices-db5500.c
+++ b/arch/arm/mach-ux500/devices-db5500.c
@@ -178,16 +178,21 @@ static struct resource mcde_resources[] = {
},
};
-static int mcde_platform_enable(void)
+static int mcde_platform_enable_dsipll(void)
{
return prcmu_enable_dsipll();
}
-static int mcde_platform_disable(void)
+static int mcde_platform_disable_dsipll(void)
{
return prcmu_disable_dsipll();
}
+static int mcde_platform_set_display_clocks(void)
+{
+ return prcmu_set_display_clocks();
+}
+
static struct mcde_platform_data mcde_pdata = {
.num_dsilinks = 2,
.syncmux = 0x01,
@@ -197,8 +202,9 @@ static struct mcde_platform_data mcde_pdata = {
.clock_dsi_id = "hdmi",
.clock_dsi_lp_id = "tv",
.clock_mcde_id = "mcde",
- .platform_enable = mcde_platform_enable,
- .platform_disable = mcde_platform_disable,
+ .platform_set_clocks = mcde_platform_set_display_clocks,
+ .platform_enable_dsipll = mcde_platform_enable_dsipll,
+ .platform_disable_dsipll = mcde_platform_disable_dsipll,
};
struct platform_device u5500_mcde_device = {
diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c
index 316c90a87a5..5684e4c3fd1 100644
--- a/arch/arm/mach-ux500/devices-db8500.c
+++ b/arch/arm/mach-ux500/devices-db8500.c
@@ -341,16 +341,21 @@ static struct resource mcde_resources[] = {
},
};
-static int mcde_platform_enable(void)
+static int mcde_platform_enable_dsipll(void)
{
return prcmu_enable_dsipll();
}
-static int mcde_platform_disable(void)
+static int mcde_platform_disable_dsipll(void)
{
return prcmu_disable_dsipll();
}
+static int mcde_platform_set_display_clocks(void)
+{
+ return prcmu_set_display_clocks();
+}
+
static struct mcde_platform_data mcde_pdata = {
.num_dsilinks = 3,
/*
@@ -373,8 +378,9 @@ static struct mcde_platform_data mcde_pdata = {
.clock_dsi_lp_id = "tv",
.clock_dpi_id = "lcd",
.clock_mcde_id = "mcde",
- .platform_enable = mcde_platform_enable,
- .platform_disable = mcde_platform_disable,
+ .platform_set_clocks = mcde_platform_set_display_clocks,
+ .platform_enable_dsipll = mcde_platform_enable_dsipll,
+ .platform_disable_dsipll = mcde_platform_disable_dsipll,
};
struct platform_device u8500_mcde_device = {
diff --git a/drivers/video/mcde/mcde_hw.c b/drivers/video/mcde/mcde_hw.c
index 1b171017161..42f3faf9e29 100644
--- a/drivers/video/mcde/mcde_hw.c
+++ b/drivers/video/mcde/mcde_hw.c
@@ -74,6 +74,8 @@ static struct clk *clock_dsi_lp;
static u8 mcde_is_enabled;
static struct mutex mcde_hw_lock;
static struct delayed_work hw_timeout_work;
+static u8 enable_dsi;
+static u8 dsi_is_enabled;
static u8 mcde_dynamic_power_management = true;
@@ -414,47 +416,13 @@ static int enable_clocks_and_power(struct platform_device *pdev)
dev_warn(&pdev->dev, "%s: esram_epod regulator is null\n"
, __func__);
}
-
- if (regulator_vana) {
- ret = regulator_enable(regulator_vana);
- if (ret < 0) {
- dev_warn(&pdev->dev, "%s: regulator_enable failed\n",
- __func__);
- goto regulator_vana_err;
- }
- } else {
- dev_warn(&pdev->dev, "%s: vana regulator is null\n"
- , __func__);
- goto regulator_vana_err;
- }
#endif
-
- ret = pdata->platform_enable();
- if (ret < 0) {
- dev_warn(&pdev->dev, "%s: "
- "platform_enable failed ret = %d\n", __func__, ret);
- goto prcmu_err;
+ pdata->platform_set_clocks();
+ if (enable_dsi > 0) {
+ pdata->platform_enable_dsipll();
+ dsi_is_enabled = true;
}
- ret = clk_enable(clock_dpi);
- if (ret < 0) {
- dev_warn(&pdev->dev, "%s: "
- "clk_enable dpi failed ret = %d\n", __func__, ret);
- goto clk_dpi_err;
- }
-
- ret = clk_enable(clock_dsi);
- if (ret < 0) {
- dev_warn(&pdev->dev, "%s: "
- "clk_enable dsi failed ret = %d\n", __func__, ret);
- goto clk_dsi_err;
- }
- ret = clk_enable(clock_dsi_lp);
- if (ret < 0) {
- dev_warn(&pdev->dev, "%s: "
- "clk_enable dsi_lp failed ret = %d\n", __func__, ret);
- goto clk_dsi_lp_err;
- }
ret = clk_enable(clock_mcde);
if (ret < 0) {
dev_warn(&pdev->dev, "%s: "
@@ -465,18 +433,7 @@ static int enable_clocks_and_power(struct platform_device *pdev)
return ret;
clk_mcde_err:
- clk_disable(clock_dsi_lp);
-clk_dsi_lp_err:
- clk_disable(clock_dsi);
-clk_dsi_err:
- clk_disable(clock_dpi);
-clk_dpi_err:
- pdata->platform_disable();
-prcmu_err:
#ifdef CONFIG_REGULATOR
- if (regulator_vana)
- regulator_disable(regulator_vana);
-regulator_vana_err:
if (regulator_esram_epod)
regulator_disable(regulator_esram_epod);
regulator_esram_err:
@@ -493,27 +450,13 @@ static int disable_clocks_and_power(struct platform_device *pdev)
dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
- clk_disable(clock_dpi);
- clk_disable(clock_dsi_lp);
clk_disable(clock_mcde);
- clk_disable(clock_dsi);
-
- pdata->platform_disable();
-
-#ifdef CONFIG_REGULATOR
- if (regulator_vana) {
- ret = regulator_disable(regulator_vana);
- if (ret < 0) {
- dev_warn(&pdev->dev, "%s: regulator_disable failed\n"
- , __func__);
- goto regulator_vana_err;
- }
- } else {
- dev_warn(&pdev->dev, "%s: vana regulator is null\n"
- , __func__);
- goto regulator_vana_err;
+ if (enable_dsi > 0) {
+ pdata->platform_disable_dsipll();
+ dsi_is_enabled = false;
}
+#ifdef CONFIG_REGULATOR
if (regulator_mcde_epod) {
ret = regulator_disable(regulator_mcde_epod);
if (ret < 0) {
@@ -543,12 +486,7 @@ static int disable_clocks_and_power(struct platform_device *pdev)
regulator_esram_epod_err:
regulator_enable(regulator_mcde_epod);
regulator_mcde_epod_err:
- regulator_enable(regulator_vana);
-regulator_vana_err:
- clk_enable(clock_dpi);
- clk_enable(clock_dsi_lp);
clk_enable(clock_mcde);
- clk_enable(clock_dsi);
#endif
return ret;
}
@@ -607,6 +545,22 @@ static void update_mcde_registers(void)
MCDE_VSCRC1_VSPMAX(0xff));
}
+static void disable_formatter(struct mcde_port *port)
+{
+ if (port->type == MCDE_PORTTYPE_DSI) {
+ if (port->phy.dsi.clk_dsi)
+ clk_disable(port->phy.dsi.clk_dsi);
+ if (port->phy.dsi.clk_dsi_lp)
+ clk_disable(port->phy.dsi.clk_dsi_lp);
+ if (port->phy.dsi.reg_vana)
+ regulator_disable(port->phy.dsi.reg_vana);
+ }
+ if (port->type == MCDE_PORTTYPE_DPI) {
+ if (port->phy.dpi.clk_dpi)
+ clk_disable(port->phy.dpi.clk_dpi);
+ }
+}
+
static int disable_mcde_hw(bool force_disable)
{
int i;
@@ -635,6 +589,10 @@ static int disable_mcde_hw(bool force_disable)
cpu_relax();
udelay(100);
}
+ if (chnl->formatter_updated) {
+ disable_formatter(&chnl->port);
+ chnl->formatter_updated = false;
+ }
} else if (chnl->enabled && chnl->continous_running) {
mcde_up = true;
}
@@ -1291,6 +1249,36 @@ static int update_channel_static_registers(struct mcde_chnl_state *chnl)
int i = 0;
u8 idx;
u8 lnk = port->link;
+ int ret;
+
+ if (port->phy.dsi.reg_vana) {
+ ret = regulator_enable(port->phy.dsi.reg_vana);
+ if (ret < 0) {
+ dev_warn(&mcde_dev->dev,
+ "%s: regulator_enable failed\n",
+ __func__);
+ goto regulator_vana_err;
+ }
+ }
+
+ if (port->phy.dsi.clk_dsi) {
+ ret = clk_enable(port->phy.dsi.clk_dsi);
+ if (ret < 0) {
+ dev_warn(&mcde_dev->dev, "%s: "
+ "clk_enable dsi failed ret = %d\n",
+ __func__, ret);
+ goto clk_dsi_err;
+ }
+ }
+ if (port->phy.dsi.clk_dsi_lp) {
+ ret = clk_enable(port->phy.dsi.clk_dsi_lp);
+ if (ret < 0) {
+ dev_warn(&mcde_dev->dev, "%s: "
+ "clk_enable dsi_lp failed ret = %d\n",
+ __func__, ret);
+ goto clk_dsi_lp_err;
+ }
+ }
if (hardware_version == MCDE_CHIP_VERSION_1_0_4)
idx = chnl->id;
@@ -1304,7 +1292,7 @@ static int update_channel_static_registers(struct mcde_chnl_state *chnl)
if (hardware_version == MCDE_CHIP_VERSION_3_0_5) {
dev_err(&mcde_dev->dev,
"DSI TE polling is not supported on this HW\n");
- return -EINVAL;
+ goto dsi_link_error;
}
/* Enable DSI TE polling */
@@ -1324,7 +1312,7 @@ static int update_channel_static_registers(struct mcde_chnl_state *chnl)
dev_warn(&mcde_dev->dev,
"DSI %d data lane remap not available!\n",
lnk);
- return -EINVAL;
+ goto dsi_link_error;
}
} else
dsi_wfld(lnk, DSI_MCTL_MAIN_DATA_CTL, DLX_REMAP_EN,
@@ -1365,7 +1353,7 @@ static int update_channel_static_registers(struct mcde_chnl_state *chnl)
if (i++ == 10) {
dev_warn(&mcde_dev->dev,
"DSI lane not ready (link=%d)!\n", lnk);
- return -EINVAL;
+ goto dsi_link_error;
}
}
@@ -1389,12 +1377,40 @@ static int update_channel_static_registers(struct mcde_chnl_state *chnl)
}
}
+ if (port->type == MCDE_PORTTYPE_DPI) {
+ if (port->phy.dpi.clk_dpi) {
+ int ret;
+ ret = clk_enable(port->phy.dpi.clk_dpi);
+ if (ret < 0) {
+ dev_warn(&mcde_dev->dev, "%s: "
+ "clk_enable dsi_lp failed ret = %d\n",
+ __func__, ret);
+ goto clk_dpi_err;
+ }
+ }
+ }
+
mcde_wfld(MCDE_CR, MCDEEN, true);
chnl->formatter_updated = true;
dev_vdbg(&mcde_dev->dev, "Static registers setup, chnl=%d\n", chnl->id);
return 0;
+dsi_link_error:
+ if (port->phy.dsi.clk_dsi_lp)
+ clk_disable(port->phy.dsi.clk_dsi_lp);
+clk_dsi_lp_err:
+ if (port->phy.dsi.clk_dsi)
+ clk_disable(port->phy.dsi.clk_dsi);
+clk_dsi_err:
+ if (port->phy.dsi.reg_vana) {
+ regulator_disable(port->phy.dsi.reg_vana);
+ chnl->port.phy.dsi.reg_vana = NULL;
+ }
+regulator_vana_err:
+clk_dpi_err:
+ return -EINVAL;
+
}
/* REVIEW: Make update_* an mcde_rectangle? */
@@ -2294,6 +2310,25 @@ static struct mcde_chnl_state *_mcde_chnl_get(enum mcde_chnl chnl_id,
_mcde_chnl_apply(chnl);
chnl->reserved = true;
+ if (chnl->port.type == MCDE_PORTTYPE_DSI) {
+#ifdef CONFIG_REGULATOR
+ chnl->port.phy.dsi.reg_vana = regulator_vana;
+#else
+ chnl->port.phy.dsi.reg_vana = NULL;
+#endif
+ chnl->port.phy.dsi.clk_dsi = clock_dsi;
+ chnl->port.phy.dsi.clk_dsi_lp = clock_dsi_lp;
+ enable_dsi++;
+ if (!dsi_is_enabled && mcde_is_enabled) {
+ struct mcde_platform_data *pdata =
+ mcde_dev->dev.platform_data;
+ pdata->platform_enable_dsipll();
+ dsi_is_enabled = true;
+ }
+ } else if (chnl->port.type == MCDE_PORTTYPE_DPI) {
+ chnl->port.phy.dpi.clk_dpi = clock_dpi;
+ }
+
return chnl;
}
@@ -2681,6 +2716,20 @@ void mcde_chnl_put(struct mcde_chnl_state *chnl)
dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
chnl->reserved = false;
+ if (chnl->port.type == MCDE_PORTTYPE_DSI) {
+ chnl->port.phy.dsi.reg_vana = NULL;
+ chnl->port.phy.dsi.clk_dsi = NULL;
+ chnl->port.phy.dsi.clk_dsi_lp = NULL;
+ enable_dsi--;
+ if (dsi_is_enabled && enable_dsi == 0) {
+ struct mcde_platform_data *pdata =
+ mcde_dev->dev.platform_data;
+ pdata->platform_disable_dsipll();
+ dsi_is_enabled = false;
+ }
+ } else if (chnl->port.type == MCDE_PORTTYPE_DPI) {
+ chnl->port.phy.dpi.clk_dpi = NULL;
+ }
dev_vdbg(&mcde_dev->dev, "%s exit\n", __func__);
}
@@ -2729,6 +2778,12 @@ void mcde_chnl_disable(struct mcde_chnl_state *chnl)
udelay(100);
}
}
+ if (chnl->formatter_updated) {
+ disable_formatter(&chnl->port);
+ chnl->formatter_updated = false;
+ }
+ del_timer(&chnl->dsi_te_timer);
+ del_timer(&chnl->auto_sync_timer);
(void)disable_mcde_hw(false);
mutex_unlock(&mcde_hw_lock);
diff --git a/include/video/mcde.h b/include/video/mcde.h
index 1777e272329..31c6443fcd2 100644
--- a/include/video/mcde.h
+++ b/include/video/mcde.h
@@ -170,6 +170,9 @@ struct mcde_port {
u8 num_data_lanes;
u8 ui;
bool clk_cont;
+ struct clk *clk_dsi;
+ struct clk *clk_dsi_lp;
+ struct regulator *reg_vana;
/* DSI data lanes are swapped if true */
bool data_lanes_swap;
@@ -179,6 +182,7 @@ struct mcde_port {
bool tv_mode;
u16 clock_div; /* use 0 or 1 for no clock divider */
u32 polarity; /* see DPI_ACT_LOW_* definitions */
+ struct clk *clk_dpi;
} dpi;
} phy;
};
@@ -424,8 +428,9 @@ struct mcde_platform_data {
const char *clock_dpi_id;
const char *clock_mcde_id;
- int (*platform_enable)(void);
- int (*platform_disable)(void);
+ int (*platform_set_clocks)(void);
+ int (*platform_enable_dsipll)(void);
+ int (*platform_disable_dsipll)(void);
};
int mcde_init(void);