From 5ae39e080c57790d333ac56d9c19ec2fe0bc11e7 Mon Sep 17 00:00:00 2001 From: Jon Mayo Date: Wed, 11 Jan 2012 14:59:55 -0800 Subject: 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 Reviewed-on: http://git-master/r/74652 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Kevin Huang (Eng-SW) Tested-by: Xin Xie Reviewed-on: http://git-master/r/75536 Reviewed-by: Rohan Somvanshi Tested-by: Rohan Somvanshi --- drivers/video/tegra/dc/dc.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'drivers/video/tegra/dc/dc.c') 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); -- cgit v1.2.3