diff options
author | Jon Mayo <jmayo@nvidia.com> | 2012-01-11 14:59:55 -0800 |
---|---|---|
committer | Rohan Somvanshi <rsomvanshi@nvidia.com> | 2012-01-19 10:15:43 -0800 |
commit | 5ae39e080c57790d333ac56d9c19ec2fe0bc11e7 (patch) | |
tree | 454c67ae3bb707e53ef93cee3e7ace3304bf7b27 /drivers | |
parent | 8b30829abe0fc6cf247a915cfcdbfa2432a713a1 (diff) |
video: tegra: dc: 1-shot bandwidth calculation
In one-shot mode(DSI) report emc rate as disabled to reduce bandwidth in
this idle state. Use this same tegra_dc_clear_bandwidth() function to handle
display disable for all types of displays.
Bug 914917
Change-Id: I84ca1341d71999b3558f9dadb103b258a1a6ab6f
Signed-off-by: Jon Mayo <jmayo@nvidia.com>
Reviewed-on: http://git-master/r/74652
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Kevin Huang (Eng-SW) <kevinh@nvidia.com>
Tested-by: Xin Xie <xxie@nvidia.com>
Reviewed-on: http://git-master/r/75536
Reviewed-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
Tested-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/tegra/dc/dc.c | 30 | ||||
-rw-r--r-- | drivers/video/tegra/dc/dc_priv.h | 1 |
2 files changed, 25 insertions, 6 deletions
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index e6fc06546785..e542dd19d667 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -977,11 +977,21 @@ unsigned long tegra_dc_get_bandwidth(struct tegra_dc_win *windows[], int n) return tegra_dc_find_max_bandwidth(windows, n); } +/* to save power, call when display memory clients would be idle */ +static void tegra_dc_clear_bandwidth(struct tegra_dc *dc) +{ + if (dc->emc_clk_rate) + clk_disable(dc->emc_clk); + dc->emc_clk_rate = 0; +} + static void tegra_dc_program_bandwidth(struct tegra_dc *dc) { unsigned i; if (dc->emc_clk_rate != dc->new_emc_clk_rate) { + if (!dc->emc_clk_rate) /* going from 0 to non-zero */ + clk_enable(dc->emc_clk); dc->emc_clk_rate = dc->new_emc_clk_rate; clk_set_rate(dc->emc_clk, dc->emc_clk_rate); } @@ -1253,6 +1263,9 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n) if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) tegra_dc_writel(dc, NC_HOST_TRIG, DC_CMD_STATE_CONTROL); + /* update EMC clock if calculated bandwidth has changed */ + tegra_dc_program_bandwidth(dc); + mutex_unlock(&dc->lock); return 0; @@ -1952,9 +1965,6 @@ static void tegra_dc_vblank(struct work_struct *work) mutex_lock(&dc->lock); - /* update EMC clock if calculated bandwidth has changed */ - tegra_dc_program_bandwidth(dc); - /* Update the SD brightness */ if (dc->enabled && dc->out->sd_settings) nvsd_updated = nvsd_update_brightness(dc); @@ -1972,6 +1982,13 @@ static void tegra_dc_vblank(struct work_struct *work) } } +static void tegra_dc_one_shot_worker(struct work_struct *work) +{ + struct tegra_dc *dc = container_of(work, struct tegra_dc, one_shot_work); + /* memory client has gone idle */ + tegra_dc_clear_bandwidth(dc); +} + /* return an arbitrarily large number if count overflow occurs. * make it a nice base-10 number to show up in stats output */ static u64 tegra_dc_underflow_count(struct tegra_dc *dc, unsigned reg) @@ -2075,6 +2092,8 @@ static void tegra_dc_one_shot_irq(struct tegra_dc *dc, unsigned long status) } if (status & FRAME_END_INT) { + schedule_work(&dc->one_shot_work); + /* Mark the frame_end as complete. */ if (!completion_done(&dc->frame_end_complete)) complete(&dc->frame_end_complete); @@ -2334,7 +2353,6 @@ static bool _tegra_dc_controller_enable(struct tegra_dc *dc) tegra_dc_setup_clk(dc, dc->clk); clk_enable(dc->clk); - clk_enable(dc->emc_clk); /* do not accept interrupts during initialization */ tegra_dc_writel(dc, 0, DC_CMD_INT_ENABLE); @@ -2366,7 +2384,6 @@ static bool _tegra_dc_controller_reset_enable(struct tegra_dc *dc) tegra_dc_setup_clk(dc, dc->clk); clk_enable(dc->clk); - clk_enable(dc->emc_clk); if (dc->ndev->id == 0 && tegra_dcs[1] != NULL) { mutex_lock(&tegra_dcs[1]->lock); @@ -2443,7 +2460,7 @@ static void _tegra_dc_controller_disable(struct tegra_dc *dc) if (dc->out_ops && dc->out_ops->disable) dc->out_ops->disable(dc); - clk_disable(dc->emc_clk); + tegra_dc_clear_bandwidth(dc); clk_disable(dc->clk); tegra_dvfs_set_rate(dc->clk, 0); @@ -2716,6 +2733,7 @@ static int tegra_dc_probe(struct nvhost_device *ndev) #endif INIT_WORK(&dc->vblank_work, tegra_dc_vblank); INIT_DELAYED_WORK(&dc->underflow_work, tegra_dc_underflow_worker); + INIT_WORK(&dc->one_shot_work, tegra_dc_one_shot_worker); tegra_dc_init_lut_defaults(&dc->fb_lut); diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h index 1451db8b5440..e516bfd72c85 100644 --- a/drivers/video/tegra/dc/dc_priv.h +++ b/drivers/video/tegra/dc/dc_priv.h @@ -138,6 +138,7 @@ struct tegra_dc { #endif struct tegra_dc_lut fb_lut; struct delayed_work underflow_work; + struct work_struct one_shot_work; }; static inline void tegra_dc_io_start(struct tegra_dc *dc) |