]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
video: tegra: dc: ext: timestamp support for VRR
authorDaniel Solomon <daniels@nvidia.com>
Wed, 10 Jun 2015 23:08:09 +0000 (16:08 -0700)
committerJon Mayo <jmayo@nvidia.com>
Fri, 7 Aug 2015 19:50:50 +0000 (12:50 -0700)
In VRR mode, waiting on a window timestamp should not
be quantized into frames. We can simply use an exact sleep
duration to achieve better accuracy.

Use CLOCK_MONOTONIC for both VRR enabled/disabled timestamp
wait paths, instead of CLOCK_REALTIME_COARSE.

Bug 1654135

Change-Id: I6635d6ba090e0923e0e6f8ef2812c8efff57b79f
Signed-off-by: Jon McCaffrey <jmccaffrey@nvidia.com>
Signed-off-by: Daniel Solomon <daniels@nvidia.com>
Reviewed-on: http://git-master/r/755810
(cherry picked from commit bce8e66f7eca41c3bb35a30a3f07caee5236948a)
Reviewed-on: http://git-master/r/771174
Reviewed-by: Jon Mayo <jmayo@nvidia.com>
Tested-by: Jon Mayo <jmayo@nvidia.com>
drivers/video/tegra/dc/dc.c
drivers/video/tegra/dc/ext/dev.c

index 71eca05006686dbb8dcecf1951eb7c12b2317541..ee75866fc20e8d0e6c9bbcc6728691450c217662 100644 (file)
@@ -3276,7 +3276,8 @@ static void tegra_dc_continuous_irq(struct tegra_dc *dc, unsigned long status,
        }
 
        if (status & FRAME_END_INT) {
-               struct timespec tm = CURRENT_TIME;
+               struct timespec tm;
+               ktime_get_ts(&tm);
                dc->frame_end_timestamp = timespec_to_ns(&tm);
                wake_up(&dc->timestamp_wq);
 
index 4bab93bd03c9cc2556775df2cad5bc71d9b30e6b..e21d9e22bf0ee79e8b4c865d603b4c06dc460410 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/export.h>
+#include <linux/delay.h>
 #include <mach/fb.h>
 #include <linux/fb.h>
 #include <video/tegra_dc_ext.h>
@@ -44,6 +45,9 @@
 #include "../../../staging/android/sync.h"
 #endif
 
+#define TEGRA_DC_TS_MAX_DELAY_US 1000000
+#define TEGRA_DC_TS_SLACK_US 2000
+
 #ifdef CONFIG_COMPAT
 /* compat versions that happen to be the same size as the uapi version. */
 
@@ -404,6 +408,7 @@ static int tegra_dc_ext_set_windowattr(struct tegra_dc_ext *ext,
        int err = 0;
        struct tegra_dc_ext_win *ext_win = &ext->win[win->idx];
        s64 timestamp_ns;
+       struct tegra_vrr *vrr = ext->dc->out->vrr;
 
        if (flip_win->handle[TEGRA_DC_Y] == NULL) {
                win->flags = 0;
@@ -488,10 +493,29 @@ static int tegra_dc_ext_set_windowattr(struct tegra_dc_ext *ext,
                if (timestamp_ns) {
                        /* XXX: Should timestamping be overridden by "no_vsync"
                         * flag */
-                       tegra_dc_config_frame_end_intr(win->dc, true);
-                       err = wait_event_interruptible(win->dc->timestamp_wq,
-                               tegra_dc_is_within_n_vsync(win->dc, timestamp_ns));
-                       tegra_dc_config_frame_end_intr(win->dc, false);
+                       if (vrr && vrr->enable) {
+                               struct timespec tm;
+                               s64 now_ns = 0;
+                               s32 sleep_us = 0;
+                               ktime_get_ts(&tm);
+                               now_ns = timespec_to_ns(&tm);
+                               sleep_us = (s32)div_s64(timestamp_ns -
+                                       now_ns, 1000ll);
+
+                               if (sleep_us > TEGRA_DC_TS_MAX_DELAY_US)
+                                       sleep_us = TEGRA_DC_TS_MAX_DELAY_US;
+
+                               if (sleep_us > 0)
+                                       usleep_range(sleep_us, sleep_us +
+                                               TEGRA_DC_TS_SLACK_US);
+                       } else {
+                               tegra_dc_config_frame_end_intr(win->dc, true);
+                               err = wait_event_interruptible(
+                                       win->dc->timestamp_wq,
+                                       tegra_dc_is_within_n_vsync(win->dc,
+                                               timestamp_ns));
+                               tegra_dc_config_frame_end_intr(win->dc, false);
+                       }
                }
        }