summaryrefslogtreecommitdiffstats
path: root/drivers/video/tegra/dc/dsi.c
diff options
context:
space:
mode:
authorJon Mayo <jmayo@nvidia.com>2012-07-17 18:56:44 -0400
committerDan Willemsen <dwillemsen@nvidia.com>2015-03-18 15:03:21 -0400
commit7ee8d237919e033682b67ffcbf74d484704bb664 (patch)
tree97cd32a7443b6aa41fa38bee2ac87468c40e6962 /drivers/video/tegra/dc/dsi.c
parentd8e5a40e3591240043ab79d32fd6158f6dc791b5 (diff)
video: tegra: dc: power optimize DC and host1x clk
Use threaded IRQ to support enabling clocks in interrupt handling. Use io_start and io_end to hold and release host1x clock. Disable IRQ after it is first requested to balance enable/disable. Use disable_irq_nosync() anywhere dc->lock is held to avoid deadlock. Change tegra_dc_update_windows() to always be balanced with tegra_dc_sync_windows(). Sync points (from host1x) are potentially lost if clock gated after update, generally this only affects applications that update at a slow frame rate. To balance update and sync calls, Colormap/LUT code now performs a sync_windows on a LUT change, this makes LUT changes slower and take effect immediately. Add a nosync version of tegra_dc_dsi_write_data to be used within dsi module. Bug 1036025 Bug 1031933 Bug 1030415 Bug 1029041 Bug 1028716 Bug 1025621 Bug 1020592 Bug 1013506 Bug 1002768 Bug 955184 Bug 929609 Bug 899059 Bug 887342 Change-Id: Idc9b4c2922ad3d476d57fdf760acae76f0c837e2 Signed-off-by: Jon Mayo <jmayo@nvidia.com> Reviewed-on: http://git-master/r/146107 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Kevin Huang (Eng-SW) <kevinh@nvidia.com> Rebase-Id: Rf3a400e426699cbd7bf2065691efe14d43c8a695
Diffstat (limited to 'drivers/video/tegra/dc/dsi.c')
-rw-r--r--drivers/video/tegra/dc/dsi.c47
1 files changed, 32 insertions, 15 deletions
diff --git a/drivers/video/tegra/dc/dsi.c b/drivers/video/tegra/dc/dsi.c
index adfa05385..552489ef1 100644
--- a/drivers/video/tegra/dc/dsi.c
+++ b/drivers/video/tegra/dc/dsi.c
@@ -1632,8 +1632,7 @@ static int tegra_dsi_wait_frame_end(struct tegra_dc *dc,
1632 reinit_completion(&dc->frame_end_complete); 1632 reinit_completion(&dc->frame_end_complete);
1633 1633
1634 /* unmask frame end interrupt */ 1634 /* unmask frame end interrupt */
1635 val = tegra_dc_readl(dc, DC_CMD_INT_MASK); 1635 val = tegra_dc_unmask_interrupt(dc, FRAME_END_INT);
1636 tegra_dc_writel(dc, val | FRAME_END_INT, DC_CMD_INT_MASK);
1637 1636
1638 timeout = wait_for_completion_interruptible_timeout( 1637 timeout = wait_for_completion_interruptible_timeout(
1639 &dc->frame_end_complete, 1638 &dc->frame_end_complete,
@@ -2548,15 +2547,13 @@ static void tegra_dc_dsi_idle_work(struct work_struct *work)
2548 tegra_dsi_host_suspend(dsi->dc); 2547 tegra_dsi_host_suspend(dsi->dc);
2549} 2548}
2550 2549
2551int tegra_dsi_write_data(struct tegra_dc *dc, 2550static int tegra_dsi_write_data_nosync(struct tegra_dc *dc,
2552 struct tegra_dc_dsi_data *dsi, 2551 struct tegra_dc_dsi_data *dsi,
2553 u8 *pdata, u8 data_id, u16 data_len) 2552 u8 *pdata, u8 data_id, u16 data_len)
2554{ 2553{
2555 int err = 0; 2554 int err = 0;
2556 struct dsi_status *init_status; 2555 struct dsi_status *init_status;
2557 2556
2558 tegra_dc_io_start(dc);
2559
2560 init_status = tegra_dsi_prepare_host_transmission( 2557 init_status = tegra_dsi_prepare_host_transmission(
2561 dc, dsi, DSI_LP_OP_WRITE); 2558 dc, dsi, DSI_LP_OP_WRITE);
2562 if (IS_ERR_OR_NULL(init_status)) { 2559 if (IS_ERR_OR_NULL(init_status)) {
@@ -2570,10 +2567,27 @@ fail:
2570 err = tegra_dsi_restore_state(dc, dsi, init_status); 2567 err = tegra_dsi_restore_state(dc, dsi, init_status);
2571 if (err < 0) 2568 if (err < 0)
2572 dev_err(&dc->ndev->dev, "Failed to restore prev state\n"); 2569 dev_err(&dc->ndev->dev, "Failed to restore prev state\n");
2570
2571 return err;
2572}
2573
2574int tegra_dsi_write_data(struct tegra_dc *dc,
2575 struct tegra_dc_dsi_data *dsi,
2576 u8 *pdata, u8 data_id, u16 data_len)
2577{
2578 int err;
2579
2580 tegra_dc_io_start(dc);
2581 tegra_dc_dsi_hold_host(dc);
2582
2583 err = tegra_dsi_write_data_nosync(dc, dsi, pdata, data_id, data_len);
2584
2585 tegra_dc_dsi_release_host(dc);
2573 tegra_dc_io_end(dc); 2586 tegra_dc_io_end(dc);
2574 2587
2575 return err; 2588 return err;
2576} 2589}
2590
2577EXPORT_SYMBOL(tegra_dsi_write_data); 2591EXPORT_SYMBOL(tegra_dsi_write_data);
2578 2592
2579static int tegra_dsi_send_panel_cmd(struct tegra_dc *dc, 2593static int tegra_dsi_send_panel_cmd(struct tegra_dc *dc,
@@ -2598,7 +2612,7 @@ static int tegra_dsi_send_panel_cmd(struct tegra_dc *dc,
2598 } else if (cur_cmd->cmd_type == TEGRA_DSI_DELAY_MS) { 2612 } else if (cur_cmd->cmd_type == TEGRA_DSI_DELAY_MS) {
2599 mdelay(cur_cmd->sp_len_dly.delay_ms); 2613 mdelay(cur_cmd->sp_len_dly.delay_ms);
2600 } else { 2614 } else {
2601 err = tegra_dsi_write_data(dc, dsi, 2615 err = tegra_dsi_write_data_nosync(dc, dsi,
2602 cur_cmd->pdata, 2616 cur_cmd->pdata,
2603 cur_cmd->data_id, 2617 cur_cmd->data_id,
2604 cur_cmd->sp_len_dly.data_len); 2618 cur_cmd->sp_len_dly.data_len);
@@ -2724,9 +2738,8 @@ int tegra_dsi_start_host_cmd_v_blank_dcs(struct tegra_dc_dsi_data * dsi,
2724 return -EINVAL; 2738 return -EINVAL;
2725 2739
2726 mutex_lock(&dsi->lock); 2740 mutex_lock(&dsi->lock);
2727 tegra_dc_dsi_hold_host(dc);
2728
2729 tegra_dc_io_start(dc); 2741 tegra_dc_io_start(dc);
2742 tegra_dc_dsi_hold_host(dc);
2730 2743
2731#if DSI_USE_SYNC_POINTS 2744#if DSI_USE_SYNC_POINTS
2732 atomic_set(&dsi_syncpt_rst, 1); 2745 atomic_set(&dsi_syncpt_rst, 1);
@@ -2750,8 +2763,8 @@ int tegra_dsi_start_host_cmd_v_blank_dcs(struct tegra_dc_dsi_data * dsi,
2750 tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_CONTROL); 2763 tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_CONTROL);
2751 2764
2752fail: 2765fail:
2753 tegra_dc_io_end(dc);
2754 tegra_dc_dsi_release_host(dc); 2766 tegra_dc_dsi_release_host(dc);
2767 tegra_dc_io_end(dc);
2755 mutex_unlock(&dsi->lock); 2768 mutex_unlock(&dsi->lock);
2756 return err; 2769 return err;
2757 2770
@@ -2766,9 +2779,8 @@ void tegra_dsi_stop_host_cmd_v_blank_dcs(struct tegra_dc_dsi_data * dsi)
2766 u32 cnt; 2779 u32 cnt;
2767 2780
2768 mutex_lock(&dsi->lock); 2781 mutex_lock(&dsi->lock);
2769 tegra_dc_dsi_hold_host(dc);
2770
2771 tegra_dc_io_start(dc); 2782 tegra_dc_io_start(dc);
2783 tegra_dc_dsi_hold_host(dc);
2772 2784
2773 if (atomic_read(&dsi_syncpt_rst)) { 2785 if (atomic_read(&dsi_syncpt_rst)) {
2774 tegra_dsi_wait_frame_end(dc, dsi, 2); 2786 tegra_dsi_wait_frame_end(dc, dsi, 2);
@@ -2782,9 +2794,9 @@ void tegra_dsi_stop_host_cmd_v_blank_dcs(struct tegra_dc_dsi_data * dsi)
2782 for (cnt = 0; cnt < 8; cnt++) 2794 for (cnt = 0; cnt < 8; cnt++)
2783 tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_DATA_0 + cnt); 2795 tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_DATA_0 + cnt);
2784 2796
2797 tegra_dc_dsi_release_host(dc);
2785 tegra_dc_io_end(dc); 2798 tegra_dc_io_end(dc);
2786 2799
2787 tegra_dc_dsi_release_host(dc);
2788 mutex_unlock(&dsi->lock); 2800 mutex_unlock(&dsi->lock);
2789} 2801}
2790EXPORT_SYMBOL(tegra_dsi_stop_host_cmd_v_blank_dcs); 2802EXPORT_SYMBOL(tegra_dsi_stop_host_cmd_v_blank_dcs);
@@ -3189,9 +3201,14 @@ static void _tegra_dc_dsi_enable(struct tegra_dc *dc)
3189 u32 i; 3201 u32 i;
3190 3202
3191 mutex_lock(&dsi->lock); 3203 mutex_lock(&dsi->lock);
3204 tegra_dc_io_start(dc);
3192 tegra_dc_dsi_hold_host(dc); 3205 tegra_dc_dsi_hold_host(dc);
3193 3206
3194 tegra_dc_io_start(dc); 3207 /* Stop DC stream before configuring DSI registers
3208 * to avoid visible glitches on panel during transition
3209 * from bootloader to kernel driver
3210 */
3211 tegra_dsi_stop_dc_stream(dc, dsi);
3195 3212
3196 if (dsi->enabled) { 3213 if (dsi->enabled) {
3197 if (dsi->ulpm) { 3214 if (dsi->ulpm) {
@@ -3309,8 +3326,8 @@ static void _tegra_dc_dsi_enable(struct tegra_dc *dc)
3309 if (dsi->status.driven == DSI_DRIVEN_MODE_DC) 3326 if (dsi->status.driven == DSI_DRIVEN_MODE_DC)
3310 tegra_dsi_start_dc_stream(dc, dsi); 3327 tegra_dsi_start_dc_stream(dc, dsi);
3311fail: 3328fail:
3312 tegra_dc_io_end(dc);
3313 tegra_dc_dsi_release_host(dc); 3329 tegra_dc_dsi_release_host(dc);
3330 tegra_dc_io_end(dc);
3314 mutex_unlock(&dsi->lock); 3331 mutex_unlock(&dsi->lock);
3315} 3332}
3316 3333
@@ -3856,8 +3873,8 @@ static void tegra_dc_dsi_disable(struct tegra_dc *dc)
3856 int err; 3873 int err;
3857 struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc); 3874 struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc);
3858 3875
3859 tegra_dc_io_start(dc);
3860 mutex_lock(&dsi->lock); 3876 mutex_lock(&dsi->lock);
3877 tegra_dc_io_start(dc);
3861 3878
3862 if (dsi->status.dc_stream == DSI_DC_STREAM_ENABLE) 3879 if (dsi->status.dc_stream == DSI_DC_STREAM_ENABLE)
3863 tegra_dsi_stop_dc_stream_at_frame_end(dc, dsi, 2); 3880 tegra_dsi_stop_dc_stream_at_frame_end(dc, dsi, 2);