video: tegra: dc: Optimize OS idle display wakeup
Animesh Kishore [Thu, 22 Aug 2013 07:12:24 +0000 (12:12 +0530)]
-Granularize MSF interrupt mask/unmask zone.
-Fix host not entering OS idle suspend.
-Remove unnessary display client wakeup.

Bug 1268656

Change-Id: I7a933bfec302771cfce02aa81893e997e58af986
Signed-off-by: Animesh Kishore <ankishore@nvidia.com>
Signed-off-by: Vineel Kumar Reddy Kovvuri <vineelkumarr@nvidia.com>
Reviewed-on: http://git-master/r/219755
(cherry picked from commit a6e330c6a4b5c06db88d4436eaeb1981ca74fe00)
Reviewed-on: http://git-master/r/265485
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
GVS: Gerrit_Virtual_Submit

drivers/video/tegra/dc/csc.c
drivers/video/tegra/dc/dc.c
drivers/video/tegra/dc/dc_priv.h
drivers/video/tegra/dc/dsi.c
drivers/video/tegra/dc/ext/cursor.c
drivers/video/tegra/dc/lut.c
drivers/video/tegra/dc/nvsd.c
drivers/video/tegra/dc/window.c

index 12434b3..6d2deab 100644 (file)
@@ -54,14 +54,12 @@ int tegra_dc_update_csc(struct tegra_dc *dc, int win_idx)
                return -EFAULT;
        }
 
-       tegra_dc_io_start(dc);
-       tegra_dc_hold_dc_out(dc);
+       tegra_dc_get(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);
-       tegra_dc_io_end(dc);
+       tegra_dc_put(dc);
 
        mutex_unlock(&dc->lock);
 
index 2831329..b13df76 100644 (file)
@@ -284,22 +284,34 @@ void tegra_dc_clk_disable(struct tegra_dc *dc)
        }
 }
 
-void tegra_dc_hold_dc_out(struct tegra_dc *dc)
+void tegra_dc_get(struct tegra_dc *dc)
 {
+       tegra_dc_io_start(dc);
+
        /* extra reference to dc clk */
        clk_prepare_enable(dc->clk);
+}
+
+void tegra_dc_put(struct tegra_dc *dc)
+{
+       /* balance extra dc clk reference */
+       clk_disable_unprepare(dc->clk);
+
+       tegra_dc_io_end(dc);
+}
 
-       if (dc->out_ops->hold)
+void tegra_dc_hold_dc_out(struct tegra_dc *dc)
+{
+       tegra_dc_get(dc);
+       if (dc->out_ops && dc->out_ops->hold)
                dc->out_ops->hold(dc);
 }
 
 void tegra_dc_release_dc_out(struct tegra_dc *dc)
 {
-       if (dc->out_ops->release)
+       if (dc->out_ops && dc->out_ops->release)
                dc->out_ops->release(dc);
-
-       /* balance extra dc clk reference */
-       clk_disable_unprepare(dc->clk);
+       tegra_dc_put(dc);
 }
 
 #define DUMP_REG(a) do {                       \
@@ -315,8 +327,7 @@ static void _dump_regs(struct tegra_dc *dc, void *data,
        char buff[256];
 
        mutex_lock(&dc->lock);
-       tegra_dc_io_start(dc);
-       tegra_dc_hold_dc_out(dc);
+       tegra_dc_get(dc);
 
        DUMP_REG(DC_CMD_DISPLAY_COMMAND_OPTION0);
        DUMP_REG(DC_CMD_DISPLAY_COMMAND);
@@ -481,8 +492,7 @@ static void _dump_regs(struct tegra_dc *dc, void *data,
        DUMP_REG(DC_COM_CMU_CSC_KBB);
 #endif
 
-       tegra_dc_release_dc_out(dc);
-       tegra_dc_io_end(dc);
+       tegra_dc_put(dc);
        mutex_unlock(&dc->lock);
 }
 
@@ -699,13 +709,11 @@ int tegra_dc_get_stride(struct tegra_dc *dc, unsigned win)
                return 0;
        BUG_ON(win > DC_N_WINDOWS);
        mutex_lock(&dc->lock);
-       tegra_dc_io_start(dc);
-       tegra_dc_hold_dc_out(dc);
+       tegra_dc_get(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);
-       tegra_dc_io_end(dc);
+       tegra_dc_put(dc);
        mutex_unlock(&dc->lock);
        return GET_LINE_STRIDE(stride);
 }
@@ -901,14 +909,13 @@ int tegra_dc_update_cmu(struct tegra_dc *dc, struct tegra_dc_cmu *cmu)
                mutex_unlock(&dc->lock);
                return 0;
        }
-       tegra_dc_io_start(dc);
-       tegra_dc_hold_dc_out(dc);
+
+       tegra_dc_get(dc);
 
        ret = _tegra_dc_update_cmu(dc, cmu);
        tegra_dc_set_color_control(dc);
 
-       tegra_dc_release_dc_out(dc);
-       tegra_dc_io_end(dc);
+       tegra_dc_put(dc);
        mutex_unlock(&dc->lock);
 
        return ret;
@@ -947,13 +954,11 @@ u32 tegra_dc_incr_syncpt_max(struct tegra_dc *dc, int i)
        u32 max;
 
        mutex_lock(&dc->lock);
-       tegra_dc_io_start(dc);
-       tegra_dc_hold_dc_out(dc);
+       tegra_dc_get(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);
-       tegra_dc_io_end(dc);
+       tegra_dc_put(dc);
        mutex_unlock(&dc->lock);
 
        return max;
@@ -963,14 +968,12 @@ void tegra_dc_incr_syncpt_min(struct tegra_dc *dc, int i, u32 val)
 {
        mutex_lock(&dc->lock);
        if (dc->enabled) {
-               tegra_dc_io_start(dc);
-               tegra_dc_hold_dc_out(dc);
+               tegra_dc_get(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);
-               tegra_dc_io_end(dc);
+               tegra_dc_put(dc);
        }
        mutex_unlock(&dc->lock);
 }
@@ -988,8 +991,7 @@ tegra_dc_config_pwm(struct tegra_dc *dc, struct tegra_dc_pwm_params *cfg)
                return;
        }
 
-       tegra_dc_io_start(dc);
-       tegra_dc_hold_dc_out(dc);
+       tegra_dc_get(dc);
 
        ctrl = ((cfg->period << PM_PERIOD_SHIFT) |
                (cfg->clk_div << PM_CLK_DIVIDER_SHIFT) |
@@ -1023,8 +1025,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);
-       tegra_dc_io_end(dc);
+       tegra_dc_put(dc);
        mutex_unlock(&dc->lock);
 }
 EXPORT_SYMBOL(tegra_dc_config_pwm);
@@ -1181,30 +1182,26 @@ void tegra_dc_enable_crc(struct tegra_dc *dc)
        u32 val;
 
        mutex_lock(&dc->lock);
-       tegra_dc_io_start(dc);
-       tegra_dc_hold_dc_out(dc);
+       tegra_dc_get(dc);
 
        val = CRC_ALWAYS_ENABLE | CRC_INPUT_DATA_ACTIVE_DATA |
                CRC_ENABLE_ENABLE;
        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);
-       tegra_dc_io_end(dc);
+       tegra_dc_put(dc);
        mutex_unlock(&dc->lock);
 }
 
 void tegra_dc_disable_crc(struct tegra_dc *dc)
 {
        mutex_lock(&dc->lock);
-       tegra_dc_io_start(dc);
-       tegra_dc_hold_dc_out(dc);
+       tegra_dc_get(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_release_dc_out(dc);
-       tegra_dc_io_end(dc);
+       tegra_dc_put(dc);
        mutex_unlock(&dc->lock);
 }
 
@@ -1224,11 +1221,9 @@ u32 tegra_dc_read_checksum_latched(struct tegra_dc *dc)
 #endif
 
        mutex_lock(&dc->lock);
-       tegra_dc_io_start(dc);
-       tegra_dc_hold_dc_out(dc);
+       tegra_dc_get(dc);
        crc = tegra_dc_readl(dc, DC_COM_CRC_CHECKSUM_LATCHED);
-       tegra_dc_release_dc_out(dc);
-       tegra_dc_io_end(dc);
+       tegra_dc_put(dc);
        mutex_unlock(&dc->lock);
 crc_error:
        return crc;
@@ -1276,12 +1271,14 @@ int tegra_dc_wait_for_vsync(struct tegra_dc *dc)
         * c) Initialize completion for next iteration.
         */
 
-       tegra_dc_hold_dc_out(dc);
+       tegra_dc_get(dc);
        dc->out->user_needs_vblank = true;
+       tegra_dc_unmask_interrupt(dc, MSF_INT);
 
        ret = wait_for_completion_interruptible(&dc->out->user_vblank_comp);
        init_completion(&dc->out->user_vblank_comp);
-       tegra_dc_release_dc_out(dc);
+       tegra_dc_mask_interrupt(dc, MSF_INT);
+       tegra_dc_put(dc);
 
        return ret;
 }
@@ -1315,8 +1312,7 @@ static void tegra_dc_vblank(struct work_struct *work)
                return;
        }
 
-       tegra_dc_io_start(dc);
-       tegra_dc_hold_dc_out(dc);
+       tegra_dc_get(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))
@@ -1343,8 +1339,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);
-       tegra_dc_io_end(dc);
+       tegra_dc_put(dc);
        mutex_unlock(&dc->lock);
 
        /* Do the actual brightness update outside of the mutex dc->lock */
@@ -1361,7 +1356,7 @@ static void tegra_dc_one_shot_worker(struct work_struct *work)
        /* memory client has gone idle */
        tegra_dc_clear_bandwidth(dc);
 
-       if (dc->out_ops->idle) {
+       if (dc->out_ops && dc->out_ops->idle) {
                tegra_dc_io_start(dc);
                dc->out_ops->idle(dc);
                tegra_dc_io_end(dc);
@@ -1451,8 +1446,7 @@ static void tegra_dc_vpulse2(struct work_struct *work)
                return;
        }
 
-       tegra_dc_io_start(dc);
-       tegra_dc_hold_dc_out(dc);
+       tegra_dc_get(dc);
 
        /* Clear the V_PULSE2_FLIP if no update */
        if (!tegra_dc_windows_are_dirty(dc))
@@ -1473,8 +1467,7 @@ static void tegra_dc_vpulse2(struct work_struct *work)
        if (!dc->vpulse2_ref_count)
                tegra_dc_mask_interrupt(dc, V_PULSE2_INT);
 
-       tegra_dc_release_dc_out(dc);
-       tegra_dc_io_end(dc);
+       tegra_dc_put(dc);
        mutex_unlock(&dc->lock);
 
        /* Do the actual brightness update outside of the mutex dc->lock */
@@ -1569,17 +1562,13 @@ static irqreturn_t tegra_dc_irq(int irq, void *ptr)
                return IRQ_HANDLED;
        }
 
-       clk_prepare_enable(dc->clk);
-       tegra_dc_io_start(dc);
-       tegra_dc_hold_dc_out(dc);
+       tegra_dc_get(dc);
 
        if (!nvhost_module_powered_ext(dc->ndev)) {
                WARN(1, "IRQ when DC not powered!\n");
                status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
                tegra_dc_writel(dc, status, DC_CMD_INT_STATUS);
-               tegra_dc_release_dc_out(dc);
-               tegra_dc_io_end(dc);
-               clk_disable_unprepare(dc->clk);
+               tegra_dc_put(dc);
                mutex_unlock(&dc->lock);
                return IRQ_HANDLED;
        }
@@ -1615,9 +1604,7 @@ static irqreturn_t tegra_dc_irq(int irq, void *ptr)
                if (tegra_dc_update_mode(dc))
                        need_disable = 1; /* force display off on error */
 
-       tegra_dc_release_dc_out(dc);
-       tegra_dc_io_end(dc);
-       clk_disable_unprepare(dc->clk);
+       tegra_dc_put(dc);
        mutex_unlock(&dc->lock);
 
        if (need_disable)
@@ -2013,7 +2000,7 @@ static void _tegra_dc_controller_disable(struct tegra_dc *dc)
 {
        unsigned i;
 
-       tegra_dc_hold_dc_out(dc);
+       tegra_dc_get(dc);
 
        if (dc->out && dc->out->prepoweroff)
                dc->out->prepoweroff();
@@ -2057,7 +2044,7 @@ static void _tegra_dc_controller_disable(struct tegra_dc *dc)
                dc->out_ops->postpoweroff(dc);
 
        tegra_dc_clk_disable(dc);
-       tegra_dc_release_dc_out(dc);
+       tegra_dc_put(dc);
 }
 
 void tegra_dc_stats_enable(struct tegra_dc *dc, bool enable)
@@ -2221,14 +2208,12 @@ static void tegra_dc_underflow_worker(struct work_struct *work)
                to_delayed_work(work), struct tegra_dc, underflow_work);
 
        mutex_lock(&dc->lock);
-       tegra_dc_io_start(dc);
-       tegra_dc_hold_dc_out(dc);
+       tegra_dc_get(dc);
 
        if (dc->enabled) {
                tegra_dc_underflow_handler(dc);
        }
-       tegra_dc_release_dc_out(dc);
-       tegra_dc_io_end(dc);
+       tegra_dc_put(dc);
        mutex_unlock(&dc->lock);
 }
 
index 0846e34..a341b43 100644 (file)
@@ -299,6 +299,10 @@ 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_get(struct tegra_dc *dc);
+void tegra_dc_put(struct tegra_dc *dc);
+
+/* defined in dc.c, used in window.c */
 void tegra_dc_hold_dc_out(struct tegra_dc *dc);
 void tegra_dc_release_dc_out(struct tegra_dc *dc);
 
index 191b30c..0b80e59 100644 (file)
@@ -1751,10 +1751,6 @@ static void tegra_dsi_stop_dc_stream(struct tegra_dc *dc,
        /* extra reference to dc clk */
        clk_prepare_enable(dc->clk);
 
-       /* Mask the MSF interrupt. */
-       if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
-               tegra_dc_mask_interrupt(dc, MSF_INT);
-
        tegra_dc_writel(dc, DISP_CTRL_MODE_STOP, DC_CMD_DISPLAY_COMMAND);
        tegra_dc_writel(dc, 0, DC_DISP_DISP_WIN_OPTIONS);
        tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
@@ -1853,9 +1849,6 @@ static void tegra_dsi_start_dc_stream(struct tegra_dc *dc,
                tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
                tegra_dc_writel(dc, GENERAL_ACT_REQ | NC_HOST_TRIG,
                                                DC_CMD_STATE_CONTROL);
-
-               /* Unmask the MSF interrupt. */
-               tegra_dc_unmask_interrupt(dc, MSF_INT);
        } else {
                /* set continuous mode */
                tegra_dc_writel(dc, DISP_CTRL_MODE_C_DISPLAY,
index 9eaeb1f..35a86d4 100644 (file)
@@ -163,16 +163,14 @@ int tegra_dc_ext_set_cursor_image(struct tegra_dc_ext_user *user,
        ext->cursor.cur_handle = handle;
 
        mutex_lock(&dc->lock);
-       tegra_dc_io_start(dc);
-       tegra_dc_hold_dc_out(dc);
+       tegra_dc_get(dc);
 
        set_cursor_image_hw(dc, args, phys_addr);
 
        tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
        tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
 
-       tegra_dc_release_dc_out(dc);
-       tegra_dc_io_end(dc);
+       tegra_dc_put(dc);
        /* XXX sync here? */
 
        mutex_unlock(&dc->lock);
@@ -216,8 +214,7 @@ int tegra_dc_ext_set_cursor(struct tegra_dc_ext_user *user,
        enable = !!(args->flags & TEGRA_DC_EXT_CURSOR_FLAGS_VISIBLE);
 
        mutex_lock(&dc->lock);
-       tegra_dc_io_start(dc);
-       tegra_dc_hold_dc_out(dc);
+       tegra_dc_get(dc);
 
        val = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
        if (!!(val & CURSOR_ENABLE) != enable) {
@@ -236,8 +233,7 @@ int tegra_dc_ext_set_cursor(struct tegra_dc_ext_user *user,
        /* TODO: need to sync here?  hopefully can avoid this, but need to
         * figure out interaction w/ rest of GENERAL_ACT_REQ */
 
-       tegra_dc_release_dc_out(dc);
-       tegra_dc_io_end(dc);
+       tegra_dc_put(dc);
        mutex_unlock(&dc->lock);
 
        mutex_unlock(&ext->cursor.lock);
@@ -271,16 +267,14 @@ int tegra_dc_ext_cursor_clip(struct tegra_dc_ext_user *user,
        }
 
        mutex_lock(&dc->lock);
-       tegra_dc_io_start(dc);
-       tegra_dc_hold_dc_out(dc);
+       tegra_dc_get(dc);
 
        reg_val = tegra_dc_readl(dc, DC_DISP_CURSOR_START_ADDR);
        reg_val &= ~CURSOR_CLIP_SHIFT_BITS(3); /* Clear out the old value */
        tegra_dc_writel(dc, reg_val | CURSOR_CLIP_SHIFT_BITS(*args),
                        DC_DISP_CURSOR_START_ADDR);
 
-       tegra_dc_release_dc_out(dc);
-       tegra_dc_io_end(dc);
+       tegra_dc_put(dc);
        mutex_unlock(&dc->lock);
 
        mutex_unlock(&ext->cursor.lock);
index 892d9f9..5be0cbb 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/tegra/dc/lut.c
  *
- * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
+ * Copyright (c) 2010-2013, NVIDIA CORPORATION, All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -85,12 +85,10 @@ static int tegra_dc_update_winlut(struct tegra_dc *dc, int win_idx, int fbovr)
        struct tegra_dc_win *win = &dc->windows[win_idx];
 
        mutex_lock(&dc->lock);
-       tegra_dc_io_start(dc);
-       tegra_dc_hold_dc_out(dc);
+       tegra_dc_get(dc);
 
        if (!dc->enabled) {
-               tegra_dc_release_dc_out(dc);
-               tegra_dc_io_end(dc);
+               tegra_dc_put(dc);
                mutex_unlock(&dc->lock);
                return -EFAULT;
        }
@@ -115,8 +113,7 @@ static int tegra_dc_update_winlut(struct tegra_dc *dc, int win_idx, int fbovr)
        tegra_dc_update_windows(&win, 1);
        tegra_dc_sync_windows(&win, 1);
 
-       tegra_dc_release_dc_out(dc);
-       tegra_dc_io_end(dc);
+       tegra_dc_put(dc);
        return 0;
 }
 
index f52ba49..75cc856 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/tegra/dc/nvsd.c
  *
- * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
+ * Copyright (c) 2010-2013, NVIDIA CORPORATION, All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -1089,11 +1089,9 @@ static ssize_t nvsd_settings_store(struct kobject *kobj,
                                return -ENODEV;
                        }
 
-                       tegra_dc_io_start(dc);
-                       tegra_dc_hold_dc_out(dc);
+                       tegra_dc_get(dc);
                        nvsd_init(dc, sd_settings);
-                       tegra_dc_release_dc_out(dc);
-                       tegra_dc_io_end(dc);
+                       tegra_dc_put(dc);
 
                        mutex_unlock(&dc->lock);
 
index 36111e3..58113ab 100644 (file)
@@ -220,8 +220,8 @@ int tegra_dc_sync_windows(struct tegra_dc_win *windows[], int n)
                tegra_dc_windows_are_clean(windows, n),
                HZ);
 #endif
-       /* tegra_dc_io_start() done in update_windows */
-       tegra_dc_io_end(windows[0]->dc);
+       /* tegra_dc_hold_dc_out() called in update_windows */
+       tegra_dc_release_dc_out(windows[0]->dc);
        return ret;
 }
 EXPORT_SYMBOL(tegra_dc_sync_windows);
@@ -343,7 +343,6 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
                return -EFAULT;
        }
 
-       tegra_dc_io_start(dc);
        tegra_dc_hold_dc_out(dc);
 
        if (no_vsync)
@@ -570,7 +569,6 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
 
        tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL);
 
-       tegra_dc_release_dc_out(dc);
        /* tegra_dc_io_end() is called in tegra_dc_sync_windows() */
        mutex_unlock(&dc->lock);
        if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)