video: tegra: add cursor mode flipping
Adam Cheney [Thu, 15 Mar 2012 21:50:00 +0000 (14:50 -0700)]
This change adds a flag to flip windows in cursor mode.  Cursor mode
will cause flips to be skipped over if there are newer flip requests
waiting in the workqueue.

Add CURSOR_MODE to caps bitfield.

bug 942762

Change-Id: Ib52a0a5565f961cdd9650e4204cd65b86f96fee1
Signed-off-by: Adam Cheney <acheney@nvidia.com>
Reviewed-on: http://git-master/r/90418
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Robert Morell <rmorell@nvidia.com>

drivers/video/tegra/dc/ext/dev.c
drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
include/video/tegra_dc_ext.h

index 24e62ca..04553e7 100644 (file)
@@ -243,7 +243,9 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work)
        struct tegra_dc_win *wins[DC_N_WINDOWS];
        struct nvmap_handle_ref *unpin_handles[DC_N_WINDOWS *
                                               TEGRA_DC_NUM_PLANES];
+       struct nvmap_handle_ref *old_handle;
        int i, nr_unpin = 0, nr_win = 0;
+       bool skip_flip = false;
 
        for (i = 0; i < DC_N_WINDOWS; i++) {
                struct tegra_dc_ext_flip_win *flip_win = &data->win[i];
@@ -257,25 +259,36 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work)
                win = tegra_dc_get_window(ext->dc, index);
                ext_win = &ext->win[index];
 
+               if (!(atomic_dec_and_test(&ext_win->nr_pending_flips)) &&
+                       (flip_win->attr.flags & TEGRA_DC_EXT_FLIP_FLAG_CURSOR))
+                       skip_flip = true;
+
                if (win->flags & TEGRA_WIN_FLAG_ENABLED) {
                        int j;
                        for (j = 0; j < TEGRA_DC_NUM_PLANES; j++) {
-                               if (!ext_win->cur_handle[j])
+                               if (skip_flip)
+                                       old_handle = flip_win->handle[j];
+                               else
+                                       old_handle = ext_win->cur_handle[j];
+
+                               if (!old_handle)
                                        continue;
 
-                               unpin_handles[nr_unpin++] =
-                                       ext_win->cur_handle[j];
+                               unpin_handles[nr_unpin++] = old_handle;
                        }
                }
 
-               tegra_dc_ext_set_windowattr(ext, win, &data->win[i]);
+               if (!skip_flip)
+                       tegra_dc_ext_set_windowattr(ext, win, &data->win[i]);
 
                wins[nr_win++] = win;
        }
 
-       tegra_dc_update_windows(wins, nr_win);
-       /* TODO: implement swapinterval here */
-       tegra_dc_sync_windows(wins, nr_win);
+       if (!skip_flip) {
+               tegra_dc_update_windows(wins, nr_win);
+               /* TODO: implement swapinterval here */
+               tegra_dc_sync_windows(wins, nr_win);
+       }
 
        for (i = 0; i < DC_N_WINDOWS; i++) {
                struct tegra_dc_ext_flip_win *flip_win = &data->win[i];
@@ -484,10 +497,15 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user,
        for (i = 0; i < DC_N_WINDOWS; i++) {
                u32 syncpt_max;
                int index = args->win[i].index;
+               struct tegra_dc_win *win;
+               struct tegra_dc_ext_win *ext_win;
 
                if (index < 0)
                        continue;
 
+               win = tegra_dc_get_window(ext->dc, index);
+               ext_win = &ext->win[index];
+
                syncpt_max = tegra_dc_incr_syncpt_max(ext->dc, index);
 
                data->win[i].syncpt_max = syncpt_max;
@@ -499,6 +517,8 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user,
                args->post_syncpt_val = syncpt_max;
                args->post_syncpt_id = tegra_dc_get_syncpt_id(ext->dc, index);
                work_index = index;
+
+               atomic_inc(&ext->win[work_index].nr_pending_flips);
        }
        queue_work(ext->win[work_index].flip_wq, &data->work);
 
index abebd59..95a637d 100644 (file)
@@ -56,6 +56,8 @@ struct tegra_dc_ext_win {
        struct nvmap_handle_ref *cur_handle[TEGRA_DC_NUM_PLANES];
 
        struct workqueue_struct *flip_wq;
+
+       atomic_t                nr_pending_flips;
 };
 
 struct tegra_dc_ext {
@@ -90,7 +92,8 @@ struct tegra_dc_ext_event_list {
        struct list_head                list;
 };
 
-#define TEGRA_DC_EXT_CAPABILITIES      0
+#define TEGRA_DC_EXT_CAPABILITIES \
+       TEGRA_DC_EXT_CAPABILITIES_CURSOR_MODE
 
 struct tegra_dc_ext_control_user {
        struct tegra_dc_ext_control     *control;
index 8c51c70..f46074b 100644 (file)
@@ -58,6 +58,7 @@
 #define TEGRA_DC_EXT_FLIP_FLAG_INVERT_H        (1 << 0)
 #define TEGRA_DC_EXT_FLIP_FLAG_INVERT_V        (1 << 1)
 #define TEGRA_DC_EXT_FLIP_FLAG_TILED   (1 << 2)
+#define TEGRA_DC_EXT_FLIP_FLAG_CURSOR  (1 << 3)
 
 struct tegra_dc_ext_flip_windowattr {
        __s32   index;