diff options
author | Animesh Kishore <ankishore@nvidia.com> | 2011-07-14 17:14:18 +0530 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-07-18 17:30:38 -0700 |
commit | 636520e513cc2a48df9c6c8f1233c43e955080a1 (patch) | |
tree | ca6a4807e80670873eafb0a1b7bdcc265c3dba04 /drivers/video | |
parent | 0285ea73b85f3f1f662c307c13f208c5eab64178 (diff) |
video: tegra: dsi: Power optimization for dc one-shot mode
Disable TE signal from panel when display off for power saving.
Bug 851754
Change-Id: If00f9bde9c358c7b49050a32f68d04881e6641da
Reviewed-on: http://git-master/r/41031
Reviewed-by: Animesh Kishore <ankishore@nvidia.com>
Tested-by: Animesh Kishore <ankishore@nvidia.com>
Reviewed-by: Hanumanth Venkateswa Moganty <vmoganty@nvidia.com>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/tegra/dc/dsi.c | 92 |
1 files changed, 82 insertions, 10 deletions
diff --git a/drivers/video/tegra/dc/dsi.c b/drivers/video/tegra/dc/dsi.c index 2c7aef97ff69..74a27db171fc 100644 --- a/drivers/video/tegra/dc/dsi.c +++ b/drivers/video/tegra/dc/dsi.c @@ -1693,7 +1693,16 @@ static void tegra_dc_dsi_enable(struct tegra_dc *dc) dsi->info.n_init_cmd); if (err < 0) { dev_err(&dc->ndev->dev, - "dsi: error while sending dsi init cmd\n"); + "dsi: error sending dsi init cmd\n"); + goto fail; + } + } else if (dsi->info.dsi_late_resume_cmd) { + err = tegra_dsi_send_panel_cmd(dc, dsi, + dsi->info.dsi_late_resume_cmd, + dsi->info.n_late_resume_cmd); + if (err < 0) { + dev_err(&dc->ndev->dev, + "dsi: error sending late resume cmd\n"); goto fail; } } @@ -1789,32 +1798,77 @@ free_cmd_pdata: static int tegra_dc_dsi_cp_info(struct tegra_dc_dsi_data* dsi, struct tegra_dsi_out* p_dsi) { - struct tegra_dsi_cmd* p_init_cmd; + struct tegra_dsi_cmd *p_init_cmd; + struct tegra_dsi_cmd *p_early_suspend_cmd; + struct tegra_dsi_cmd *p_late_resume_cmd; struct tegra_dsi_cmd *p_suspend_cmd; int err; if (p_dsi->n_data_lanes > MAX_DSI_DATA_LANES) return -EINVAL; - p_init_cmd = kzalloc(sizeof(*p_init_cmd) * p_dsi->n_init_cmd, GFP_KERNEL); + p_init_cmd = kzalloc(sizeof(*p_init_cmd) * + p_dsi->n_init_cmd, GFP_KERNEL); if (!p_init_cmd) return -ENOMEM; + if (p_dsi->dsi_early_suspend_cmd) { + p_early_suspend_cmd = kzalloc(sizeof(*p_early_suspend_cmd) * + p_dsi->n_early_suspend_cmd, + GFP_KERNEL); + if (!p_early_suspend_cmd) { + err = -ENOMEM; + goto err_free_init_cmd; + } + } + + if (p_dsi->dsi_late_resume_cmd) { + p_late_resume_cmd = kzalloc(sizeof(*p_late_resume_cmd) * + p_dsi->n_late_resume_cmd, + GFP_KERNEL); + if (!p_late_resume_cmd) { + err = -ENOMEM; + goto err_free_p_early_suspend_cmd; + } + } + p_suspend_cmd = kzalloc(sizeof(*p_suspend_cmd) * p_dsi->n_suspend_cmd, GFP_KERNEL); if (!p_suspend_cmd) { err = -ENOMEM; - goto err_free_p_init_cmd; + goto err_free_p_late_resume_cmd; } memcpy(&dsi->info, p_dsi, sizeof(dsi->info)); + /* Copy panel init cmd */ err = tegra_dc_dsi_cp_p_cmd(p_dsi->dsi_init_cmd, p_init_cmd, p_dsi->n_init_cmd); if (err < 0) goto err_free; dsi->info.dsi_init_cmd = p_init_cmd; + /* Copy panel early suspend cmd */ + if (p_dsi->dsi_early_suspend_cmd) { + err = tegra_dc_dsi_cp_p_cmd(p_dsi->dsi_early_suspend_cmd, + p_early_suspend_cmd, + p_dsi->n_early_suspend_cmd); + if (err < 0) + goto err_free; + dsi->info.dsi_early_suspend_cmd = p_early_suspend_cmd; + } + + /* Copy panel late resume cmd */ + if (p_dsi->dsi_late_resume_cmd) { + err = tegra_dc_dsi_cp_p_cmd(p_dsi->dsi_late_resume_cmd, + p_late_resume_cmd, + p_dsi->n_late_resume_cmd); + if (err < 0) + goto err_free; + dsi->info.dsi_late_resume_cmd = p_late_resume_cmd; + } + + /* Copy panel suspend cmd */ err = tegra_dc_dsi_cp_p_cmd(p_dsi->dsi_suspend_cmd, p_suspend_cmd, p_dsi->n_suspend_cmd); if (err < 0) @@ -1849,7 +1903,11 @@ static int tegra_dc_dsi_cp_info(struct tegra_dc_dsi_data* dsi, err_free: kfree(p_suspend_cmd); -err_free_p_init_cmd: +err_free_p_late_resume_cmd: + kfree(p_late_resume_cmd); +err_free_p_early_suspend_cmd: + kfree(p_early_suspend_cmd); +err_free_init_cmd: kfree(p_init_cmd); return err; } @@ -1987,18 +2045,32 @@ static void tegra_dc_dsi_destroy(struct tegra_dc *dc) static void tegra_dc_dsi_disable(struct tegra_dc *dc) { struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc); + int err; + tegra_dc_io_start(dc); mutex_lock(&dsi->lock); if (dsi->status.dc_stream == DSI_DC_STREAM_ENABLE) tegra_dsi_stop_dc_stream(dc, dsi); + if (dsi->info.dsi_early_suspend_cmd) { + err = tegra_dsi_send_panel_cmd(dc, dsi, + dsi->info.dsi_early_suspend_cmd, + dsi->info.n_early_suspend_cmd); + if (err < 0) { + dev_err(&dc->ndev->dev, + "dsi: Error sending early suspend cmd\n"); + goto fail; + } + } + if (!dsi->ulpm) { if (tegra_dsi_enter_ulpm(dsi) < 0) printk(KERN_ERR "DSI failed to enter ulpm\n"); } - +fail: mutex_unlock(&dsi->lock); + tegra_dc_io_end(dc); } #ifdef CONFIG_PM @@ -2024,14 +2096,14 @@ static void tegra_dc_dsi_suspend(struct tegra_dc *dc) } /* Suspend Panel */ - err = tegra_dsi_send_panel_cmd(dc, dsi, dsi->info.dsi_suspend_cmd, - dsi->info.n_suspend_cmd); + err = tegra_dsi_send_panel_cmd(dc, dsi, + dsi->info.dsi_suspend_cmd, + dsi->info.n_suspend_cmd); if (err < 0) { dev_err(&dc->ndev->dev, - "dsi: Error while sending dsi suspend cmd\n"); + "dsi: Error sending suspend cmd\n"); goto fail; } - if (!dsi->ulpm) { if (tegra_dsi_enter_ulpm(dsi) < 0) { printk(KERN_ERR "DSI failed to enter ulpm\n"); |