summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorRakesh Iyer <riyer@nvidia.com>2012-07-19 12:44:08 -0700
committerLokesh Pathak <lpathak@nvidia.com>2012-07-25 03:32:19 -0700
commitbf132a4184143d5780ca747d024768e021b590d5 (patch)
treea5d4283ba1507390969ba11054ec9860b12ece1c /drivers
parent786ba00860c7dc3143c62bcbe5d371203238cd1d (diff)
video: tegra: dc: synchronize dsi clock-gating
The one shot thread will clock gate the modules periodically. This will ensure relevant paths in dc driver have an active dc clock and dsi host. Bug 1013172 Change-Id: Ibb505e35044f31405c06cb9fa0d6fdf78aafd4a6 Signed-off-by: Rakesh Iyer <riyer@nvidia.com> Reviewed-on: http://git-master/r/117137 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Jon Mayo <jmayo@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Animesh Kishore <ankishore@nvidia.com> Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/tegra/dc/csc.c2
-rw-r--r--drivers/video/tegra/dc/dc.c92
-rw-r--r--drivers/video/tegra/dc/dc_priv.h14
-rw-r--r--drivers/video/tegra/dc/dsi.c76
-rw-r--r--drivers/video/tegra/dc/nvsd.c5
-rw-r--r--drivers/video/tegra/dc/window.c4
6 files changed, 141 insertions, 52 deletions
diff --git a/drivers/video/tegra/dc/csc.c b/drivers/video/tegra/dc/csc.c
index 74fa900352a1..09db5fee4c6f 100644
--- a/drivers/video/tegra/dc/csc.c
+++ b/drivers/video/tegra/dc/csc.c
@@ -54,10 +54,12 @@ int tegra_dc_update_csc(struct tegra_dc *dc, int win_idx)
return -EFAULT;
}
+ tegra_dc_hold_dc_out(dc);
tegra_dc_writel(dc, WINDOW_A_SELECT << win_idx,
DC_CMD_DISPLAY_WINDOW_HEADER);
tegra_dc_set_csc(dc, &dc->windows[win_idx].csc);
+ tegra_dc_release_dc_out(dc);
mutex_unlock(&dc->lock);
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index 1f7e2ce67682..dc263fbc301e 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -82,7 +82,7 @@ struct tegra_dc *tegra_dcs[TEGRA_MAX_DC];
DEFINE_MUTEX(tegra_dc_lock);
DEFINE_MUTEX(shared_lock);
-static inline void tegra_dc_clk_enable(struct tegra_dc *dc)
+void tegra_dc_clk_enable(struct tegra_dc *dc)
{
if (!tegra_is_clk_enabled(dc->clk)) {
clk_enable(dc->clk);
@@ -90,7 +90,7 @@ static inline void tegra_dc_clk_enable(struct tegra_dc *dc)
}
}
-static inline void tegra_dc_clk_disable(struct tegra_dc *dc)
+void tegra_dc_clk_disable(struct tegra_dc *dc)
{
if (tegra_is_clk_enabled(dc->clk)) {
clk_disable(dc->clk);
@@ -98,6 +98,18 @@ static inline void tegra_dc_clk_disable(struct tegra_dc *dc)
}
}
+void tegra_dc_hold_dc_out(struct tegra_dc *dc)
+{
+ if (dc->out_ops->hold)
+ dc->out_ops->hold(dc);
+}
+
+void tegra_dc_release_dc_out(struct tegra_dc *dc)
+{
+ if (dc->out_ops->release)
+ dc->out_ops->release(dc);
+}
+
#define DUMP_REG(a) do { \
snprintf(buff, sizeof(buff), "%-32s\t%03x\t%08lx\n", \
#a, a, tegra_dc_readl(dc, a)); \
@@ -121,8 +133,9 @@ static void _dump_regs(struct tegra_dc *dc, void *data,
int i;
char buff[256];
+ mutex_lock(&dc->lock);
+ tegra_dc_hold_dc_out(dc);
tegra_dc_io_start(dc);
- tegra_dc_clk_enable(dc);
DUMP_REG(DC_CMD_DISPLAY_COMMAND_OPTION0);
DUMP_REG(DC_CMD_DISPLAY_COMMAND);
@@ -272,8 +285,9 @@ static void _dump_regs(struct tegra_dc *dc, void *data,
DUMP_REG(DC_COM_PM1_DUTY_CYCLE);
DUMP_REG(DC_DISP_SD_CONTROL);
- tegra_dc_clk_disable(dc);
tegra_dc_io_end(dc);
+ tegra_dc_release_dc_out(dc);
+ mutex_unlock(&dc->lock);
}
#undef DUMP_REG
@@ -488,9 +502,13 @@ int tegra_dc_get_stride(struct tegra_dc *dc, unsigned win)
if (!dc->enabled)
return 0;
BUG_ON(win > DC_N_WINDOWS);
+ mutex_lock(&dc->lock);
+ tegra_dc_hold_dc_out(dc);
tegra_dc_writel(dc, WINDOW_A_SELECT << win,
DC_CMD_DISPLAY_WINDOW_HEADER);
stride = tegra_dc_readl(dc, DC_WIN_LINE_STRIDE);
+ tegra_dc_release_dc_out(dc);
+ mutex_unlock(&dc->lock);
return GET_LINE_STRIDE(stride);
}
EXPORT_SYMBOL(tegra_dc_get_stride);
@@ -550,17 +568,6 @@ static void tegra_dc_set_scaling_filter(struct tegra_dc *dc)
}
}
-void tegra_dc_host_suspend(struct tegra_dc *dc)
-{
- tegra_dsi_host_suspend(dc);
- tegra_dc_clk_disable(dc);
-}
-
-void tegra_dc_host_resume(struct tegra_dc *dc) {
- tegra_dc_clk_enable(dc);
- tegra_dsi_host_resume(dc);
-}
-
static inline void disable_dc_irq(unsigned int irq)
{
disable_irq(irq);
@@ -577,9 +584,11 @@ u32 tegra_dc_incr_syncpt_max(struct tegra_dc *dc, int i)
u32 max;
mutex_lock(&dc->lock);
+ tegra_dc_hold_dc_out(dc);
max = nvhost_syncpt_incr_max_ext(dc->ndev,
dc->syncpt[i].id, ((dc->enabled) ? 1 : 0));
dc->syncpt[i].max = max;
+ tegra_dc_release_dc_out(dc);
mutex_unlock(&dc->lock);
return max;
@@ -588,11 +597,14 @@ u32 tegra_dc_incr_syncpt_max(struct tegra_dc *dc, int i)
void tegra_dc_incr_syncpt_min(struct tegra_dc *dc, int i, u32 val)
{
mutex_lock(&dc->lock);
- if ( dc->enabled )
+ if (dc->enabled) {
+ tegra_dc_hold_dc_out(dc);
while (dc->syncpt[i].min < val) {
dc->syncpt[i].min++;
nvhost_syncpt_cpu_incr_ext(dc->ndev, dc->syncpt[i].id);
}
+ tegra_dc_release_dc_out(dc);
+ }
mutex_unlock(&dc->lock);
}
@@ -609,8 +621,7 @@ tegra_dc_config_pwm(struct tegra_dc *dc, struct tegra_dc_pwm_params *cfg)
return;
}
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
- tegra_dc_host_resume(dc);
+ tegra_dc_hold_dc_out(dc);
ctrl = ((cfg->period << PM_PERIOD_SHIFT) |
(cfg->clk_div << PM_CLK_DIVIDER_SHIFT) |
@@ -644,6 +655,7 @@ tegra_dc_config_pwm(struct tegra_dc *dc, struct tegra_dc_pwm_params *cfg)
break;
}
tegra_dc_writel(dc, cmd_state, DC_CMD_STATE_ACCESS);
+ tegra_dc_release_dc_out(dc);
mutex_unlock(&dc->lock);
}
EXPORT_SYMBOL(tegra_dc_config_pwm);
@@ -790,6 +802,9 @@ EXPORT_SYMBOL(tegra_dc_get_out_max_pixclock);
void tegra_dc_enable_crc(struct tegra_dc *dc)
{
u32 val;
+
+ mutex_lock(&dc->lock);
+ tegra_dc_hold_dc_out(dc);
tegra_dc_io_start(dc);
val = CRC_ALWAYS_ENABLE | CRC_INPUT_DATA_ACTIVE_DATA |
@@ -797,15 +812,21 @@ void tegra_dc_enable_crc(struct tegra_dc *dc)
tegra_dc_writel(dc, val, DC_COM_CRC_CONTROL);
tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
+ tegra_dc_release_dc_out(dc);
+ mutex_unlock(&dc->lock);
}
void tegra_dc_disable_crc(struct tegra_dc *dc)
{
+ mutex_lock(&dc->lock);
+ tegra_dc_hold_dc_out(dc);
tegra_dc_writel(dc, 0x0, DC_COM_CRC_CONTROL);
tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
tegra_dc_io_end(dc);
+ tegra_dc_release_dc_out(dc);
+ mutex_unlock(&dc->lock);
}
u32 tegra_dc_read_checksum_latched(struct tegra_dc *dc)
@@ -821,7 +842,11 @@ u32 tegra_dc_read_checksum_latched(struct tegra_dc *dc)
* DC_COM_CRC_CHECKSUM_LATCHED is available after VBLANK */
mdelay(TEGRA_CRC_LATCHED_DELAY);
+ mutex_lock(&dc->lock);
+ tegra_dc_hold_dc_out(dc);
crc = tegra_dc_readl(dc, DC_COM_CRC_CHECKSUM_LATCHED);
+ tegra_dc_release_dc_out(dc);
+ mutex_unlock(&dc->lock);
crc_error:
return crc;
}
@@ -860,6 +885,7 @@ static void tegra_dc_vblank(struct work_struct *work)
return;
}
+ tegra_dc_hold_dc_out(dc);
/* use the new frame's bandwidth setting instead of max(current, new),
* skip this if we're using tegra_dc_one_shot_worker() */
if (!(dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE))
@@ -886,6 +912,7 @@ static void tegra_dc_vblank(struct work_struct *work)
if (!dc->vblank_ref_count)
tegra_dc_mask_interrupt(dc, V_BLANK_INT);
+ tegra_dc_release_dc_out(dc);
mutex_unlock(&dc->lock);
/* Do the actual brightness update outside of the mutex */
@@ -908,8 +935,8 @@ static void tegra_dc_one_shot_worker(struct work_struct *work)
/* memory client has gone idle */
tegra_dc_clear_bandwidth(dc);
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
- tegra_dc_host_suspend(dc);
+ if (dc->out_ops->idle)
+ dc->out_ops->idle(dc);
mutex_unlock(&dc->lock);
}
@@ -1505,8 +1532,20 @@ void tegra_dc_blank(struct tegra_dc *dc)
static void _tegra_dc_disable(struct tegra_dc *dc)
{
+ if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) {
+ mutex_lock(&dc->one_shot_lock);
+ cancel_delayed_work_sync(&dc->one_shot_work);
+ }
+
+ tegra_dc_hold_dc_out(dc);
+
_tegra_dc_controller_disable(dc);
tegra_dc_io_end(dc);
+
+ tegra_dc_release_dc_out(dc);
+
+ if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
+ mutex_unlock(&dc->one_shot_lock);
}
void tegra_dc_disable(struct tegra_dc *dc)
@@ -1516,16 +1555,9 @@ void tegra_dc_disable(struct tegra_dc *dc)
/* it's important that new underflow work isn't scheduled before the
* lock is acquired. */
cancel_delayed_work_sync(&dc->underflow_work);
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) {
- mutex_lock(&dc->one_shot_lock);
- cancel_delayed_work_sync(&dc->one_shot_work);
- }
mutex_lock(&dc->lock);
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
- tegra_dc_host_resume(dc);
-
if (dc->enabled) {
dc->enabled = false;
@@ -1538,8 +1570,6 @@ void tegra_dc_disable(struct tegra_dc *dc)
#endif
mutex_unlock(&dc->lock);
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
- mutex_unlock(&dc->one_shot_lock);
print_mode_info(dc, dc->mode);
}
@@ -1605,12 +1635,12 @@ static void tegra_dc_underflow_worker(struct work_struct *work)
to_delayed_work(work), struct tegra_dc, underflow_work);
mutex_lock(&dc->lock);
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
- tegra_dc_host_resume(dc);
+ tegra_dc_hold_dc_out(dc);
if (dc->enabled) {
tegra_dc_underflow_handler(dc);
}
+ tegra_dc_release_dc_out(dc);
mutex_unlock(&dc->lock);
}
diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h
index fb1243593587..332c80f9cbb6 100644
--- a/drivers/video/tegra/dc/dc_priv.h
+++ b/drivers/video/tegra/dc/dc_priv.h
@@ -75,6 +75,12 @@ struct tegra_dc_out_ops {
void (*enable)(struct tegra_dc *dc);
/* disable output. dc clocks are on at this point */
void (*disable)(struct tegra_dc *dc);
+ /* hold output. keeps dc clocks on. */
+ void (*hold)(struct tegra_dc *dc);
+ /* release output. dc clocks may turn off after this. */
+ void (*release)(struct tegra_dc *dc);
+ /* idle routine of output. dc clocks may turn off after this. */
+ void (*idle)(struct tegra_dc *dc);
/* suspend output. dc clocks are on at this point */
void (*suspend)(struct tegra_dc *dc);
/* resume output. dc clocks are on at this point */
@@ -369,6 +375,14 @@ void tegra_dc_set_out_pin_polars(struct tegra_dc *dc,
/* defined in dc.c, used in bandwidth.c */
unsigned int tegra_dc_has_multiple_dc(void);
+/* defined in dc.c, used in dsi.c */
+void tegra_dc_clk_enable(struct tegra_dc *dc);
+void tegra_dc_clk_disable(struct tegra_dc *dc);
+
+/* defined in dc.c, used in nvsd.c and dsi.c */
+void tegra_dc_hold_dc_out(struct tegra_dc *dc);
+void tegra_dc_release_dc_out(struct tegra_dc *dc);
+
/* defined in bandwidth.c, used in dc.c */
void tegra_dc_clear_bandwidth(struct tegra_dc *dc);
void tegra_dc_program_bandwidth(struct tegra_dc *dc, bool use_new);
diff --git a/drivers/video/tegra/dc/dsi.c b/drivers/video/tegra/dc/dsi.c
index ba8a451a4b4f..935e98bc2f87 100644
--- a/drivers/video/tegra/dc/dsi.c
+++ b/drivers/video/tegra/dc/dsi.c
@@ -294,6 +294,9 @@ const u32 init_reg[] = {
DSI_PKT_LEN_6_7,
};
+static int tegra_dsi_host_suspend(struct tegra_dc *dc);
+static int tegra_dsi_host_resume(struct tegra_dc *dc);
+
inline unsigned long tegra_dsi_readl(struct tegra_dc_dsi_data *dsi, u32 reg)
{
unsigned long ret;
@@ -2118,6 +2121,39 @@ static int _tegra_dsi_write_data(struct tegra_dc_dsi_data *dsi,
return err;
}
+static void tegra_dc_dsi_hold_host(struct tegra_dc *dc)
+{
+ struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc);
+
+ if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE) {
+ /*
+ * The reference count should never be more than 1.
+ */
+ BUG_ON(tegra_is_clk_enabled(dc->clk) > 1);
+
+ if (dsi->host_suspended)
+ tegra_dsi_host_resume(dc);
+
+ /*
+ * Take an extra refrence to count for the clk_disable in
+ * tegra_dc_release_host.
+ */
+ clk_enable(dc->clk);
+ }
+}
+
+static void tegra_dc_dsi_release_host(struct tegra_dc *dc)
+{
+ if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
+ clk_disable(dc->clk);
+}
+
+static void tegra_dc_dsi_idle(struct tegra_dc *dc)
+{
+ if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
+ tegra_dsi_host_suspend(dc);
+}
+
int tegra_dsi_write_data(struct tegra_dc *dc,
struct tegra_dc_dsi_data *dsi,
u8 *pdata, u8 data_id, u16 data_len)
@@ -2127,9 +2163,6 @@ int tegra_dsi_write_data(struct tegra_dc *dc,
tegra_dc_io_start(dc);
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
- tegra_dc_host_resume(dc);
-
init_status = tegra_dsi_prepare_host_transmission(
dc, dsi, DSI_LP_OP_WRITE);
if (IS_ERR_OR_NULL(init_status)) {
@@ -2144,6 +2177,7 @@ fail:
if (err < 0)
dev_err(&dc->ndev->dev, "Failed to restore prev state\n");
tegra_dc_io_end(dc);
+
return err;
}
EXPORT_SYMBOL(tegra_dsi_write_data);
@@ -2289,10 +2323,10 @@ int tegra_dsi_start_host_cmd_v_blank_dcs(struct tegra_dc_dsi_data * dsi,
return -EINVAL;
mutex_lock(&dsi->lock);
+ tegra_dc_dsi_hold_host(dc);
+
tegra_dc_io_start(dc);
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
- tegra_dc_host_resume(dc);
err = tegra_dsi_dcs_pkt_seq_ctrl_init(dsi, cmd);
if (err < 0) {
@@ -2313,6 +2347,7 @@ int tegra_dsi_start_host_cmd_v_blank_dcs(struct tegra_dc_dsi_data * dsi,
fail:
tegra_dc_io_end(dc);
+ tegra_dc_dsi_release_host(dc);
mutex_unlock(&dsi->lock);
return err;
@@ -2327,10 +2362,9 @@ void tegra_dsi_stop_host_cmd_v_blank_dcs(struct tegra_dc_dsi_data * dsi)
u32 cnt;
mutex_lock(&dsi->lock);
- tegra_dc_io_start(dc);
+ tegra_dc_dsi_hold_host(dc);
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
- tegra_dc_host_resume(dc);
+ tegra_dc_io_start(dc);
tegra_dsi_writel(dsi, TEGRA_DSI_DISABLE, DSI_INIT_SEQ_CONTROL);
@@ -2339,6 +2373,8 @@ void tegra_dsi_stop_host_cmd_v_blank_dcs(struct tegra_dc_dsi_data * dsi)
tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_DATA_0 + cnt);
tegra_dc_io_end(dc);
+
+ tegra_dc_dsi_release_host(dc);
mutex_unlock(&dsi->lock);
}
EXPORT_SYMBOL(tegra_dsi_stop_host_cmd_v_blank_dcs);
@@ -2750,11 +2786,10 @@ static void tegra_dc_dsi_enable(struct tegra_dc *dc)
int err;
u32 val;
- tegra_dc_io_start(dc);
mutex_lock(&dsi->lock);
+ tegra_dc_dsi_hold_host(dc);
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
- tegra_dc_host_resume(dc);
+ tegra_dc_io_start(dc);
/* Stop DC stream before configuring DSI registers
* to avoid visible glitches on panel during transition
* from bootloader to kernel driver
@@ -2866,8 +2901,9 @@ static void tegra_dc_dsi_enable(struct tegra_dc *dc)
if (dsi->status.driven == DSI_DRIVEN_MODE_DC)
tegra_dsi_start_dc_stream(dc, dsi);
fail:
- mutex_unlock(&dsi->lock);
tegra_dc_io_end(dc);
+ tegra_dc_dsi_release_host(dc);
+ mutex_unlock(&dsi->lock);
}
static void _tegra_dc_dsi_init(struct tegra_dc *dc)
@@ -3261,8 +3297,7 @@ fail:
return err;
}
-
-int tegra_dsi_host_suspend(struct tegra_dc *dc)
+static int tegra_dsi_host_suspend(struct tegra_dc *dc)
{
int err = 0;
struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc);
@@ -3270,6 +3305,8 @@ int tegra_dsi_host_suspend(struct tegra_dc *dc)
if (dsi->host_suspended)
return 0;
+ dsi->host_suspended = true;
+
tegra_dsi_stop_dc_stream(dc, dsi);
err = tegra_dsi_deep_sleep(dc, dsi, dsi->info.suspend_aggr);
@@ -3277,13 +3314,12 @@ int tegra_dsi_host_suspend(struct tegra_dc *dc)
dev_err(&dc->ndev->dev,
"DSI failed to enter deep sleep\n");
- dsi->host_suspended = true;
+ tegra_dc_clk_disable(dc);
return err;
}
-
-int tegra_dsi_host_resume(struct tegra_dc *dc)
+static int tegra_dsi_host_resume(struct tegra_dc *dc)
{
int val = 0;
int err = 0;
@@ -3292,6 +3328,7 @@ int tegra_dsi_host_resume(struct tegra_dc *dc)
if (!dsi->host_suspended)
return 0;
+ tegra_dc_clk_enable(dc);
switch (dsi->info.suspend_aggr) {
case DSI_HOST_SUSPEND_LV0:
tegra_dsi_clk_enable(dsi);
@@ -3336,9 +3373,9 @@ int tegra_dsi_host_resume(struct tegra_dc *dc)
"is not supported.\n");
}
+ tegra_dsi_start_dc_stream(dc, dsi);
dsi->enabled = true;
dsi->host_suspended = false;
- tegra_dsi_start_dc_stream(dc, dsi);
fail:
return err;
}
@@ -3432,6 +3469,9 @@ struct tegra_dc_out_ops tegra_dc_dsi_ops = {
.destroy = tegra_dc_dsi_destroy,
.enable = tegra_dc_dsi_enable,
.disable = tegra_dc_dsi_disable,
+ .hold = tegra_dc_dsi_hold_host,
+ .release = tegra_dc_dsi_release_host,
+ .idle = tegra_dc_dsi_idle,
#ifdef CONFIG_PM
.suspend = tegra_dc_dsi_suspend,
.resume = tegra_dc_dsi_resume,
diff --git a/drivers/video/tegra/dc/nvsd.c b/drivers/video/tegra/dc/nvsd.c
index e3058b596f69..6e76ee0f1702 100644
--- a/drivers/video/tegra/dc/nvsd.c
+++ b/drivers/video/tegra/dc/nvsd.c
@@ -809,9 +809,12 @@ static ssize_t nvsd_settings_store(struct kobject *kobj,
mutex_unlock(&dc->lock);
return -ENODEV;
}
- mutex_unlock(&dc->lock);
+ tegra_dc_hold_dc_out(dc);
nvsd_init(dc, sd_settings);
+ tegra_dc_release_dc_out(dc);
+
+ mutex_unlock(&dc->lock);
/* Update backlight state IFF we're disabling! */
if (!sd_settings->enable && sd_settings->bl_device) {
diff --git a/drivers/video/tegra/dc/window.c b/drivers/video/tegra/dc/window.c
index 5161dd4f7003..0b4350d49418 100644
--- a/drivers/video/tegra/dc/window.c
+++ b/drivers/video/tegra/dc/window.c
@@ -219,8 +219,7 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
return -EFAULT;
}
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
- tegra_dc_host_resume(dc);
+ tegra_dc_hold_dc_out(dc);
if (no_vsync)
tegra_dc_writel(dc, WRITE_MUX_ACTIVE | READ_MUX_ACTIVE,
@@ -424,6 +423,7 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL);
trace_printk("%s:update_mask=%#lx\n", dc->ndev->name, update_mask);
+ tegra_dc_release_dc_out(dc);
mutex_unlock(&dc->lock);
if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
mutex_unlock(&dc->one_shot_lock);