diff options
author | Philippe Langlais <philippe.langlais@linaro.org> | 2011-05-05 15:04:02 +0200 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@stericsson.com> | 2011-09-19 15:15:01 +0200 |
commit | 99aa7a82a4c70ce5c7815ff37ea16188107ade5d (patch) | |
tree | 997cfbe52f8feb9ae974a61214fd7a59d1e401cd | |
parent | 32dab36e9248b52b368f32512ef17c69ad1a4ffb (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.c | 14 | ||||
-rw-r--r-- | arch/arm/mach-ux500/devices-db8500.c | 14 | ||||
-rw-r--r-- | drivers/video/mcde/mcde_hw.c | 205 | ||||
-rw-r--r-- | include/video/mcde.h | 9 |
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); |