summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/dc/ext/dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/tegra/dc/ext/dev.c')
-rw-r--r--drivers/video/tegra/dc/ext/dev.c54
1 files changed, 47 insertions, 7 deletions
diff --git a/drivers/video/tegra/dc/ext/dev.c b/drivers/video/tegra/dc/ext/dev.c
index 203f1a478190..273b31755643 100644
--- a/drivers/video/tegra/dc/ext/dev.c
+++ b/drivers/video/tegra/dc/ext/dev.c
@@ -1,7 +1,7 @@
/*
* drivers/video/tegra/dc/dev.c
*
- * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
+ * Copyright (c) 2011-2014, NVIDIA CORPORATION, All rights reserved.
*
* Author: Robert Morell <rmorell@nvidia.com>
* Some code based on fbdev extensions written by:
@@ -327,6 +327,18 @@ int tegra_dc_unset_flip_callback()
}
EXPORT_SYMBOL(tegra_dc_unset_flip_callback);
+static void tegra_dc_ext_unpin_handles(struct tegra_dc_ext *ext,
+ struct nvmap_handle_ref *unpin_handles[],
+ int nr_unpin)
+{
+ int i;
+
+ for (i = 0; i < nr_unpin; i++) {
+ nvmap_unpin(ext->nvmap, unpin_handles[i]);
+ nvmap_free(ext->nvmap, unpin_handles[i]);
+ }
+}
+
static void tegra_dc_ext_flip_worker(struct work_struct *work)
{
struct tegra_dc_ext_flip_data *data =
@@ -432,10 +444,7 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work)
}
/* unpin and deref previous front buffers */
- for (i = 0; i < nr_unpin; i++) {
- nvmap_unpin(ext->nvmap, unpin_handles[i]);
- nvmap_free(ext->nvmap, unpin_handles[i]);
- }
+ tegra_dc_ext_unpin_handles(ext, unpin_handles, nr_unpin);
kfree(data);
}
@@ -533,6 +542,23 @@ static int sanitize_flip_args(struct tegra_dc_ext_user *user,
return 0;
}
+static void tegra_dc_ext_unpin_window(struct tegra_dc_ext_win *win)
+{
+ struct nvmap_handle_ref *unpin_handles[TEGRA_DC_NUM_PLANES];
+ int nr_unpin = 0;
+
+ if (win->cur_handle[TEGRA_DC_Y]) {
+ int j;
+ for (j = 0; j < TEGRA_DC_NUM_PLANES; j++) {
+ if (win->cur_handle[j])
+ unpin_handles[nr_unpin++] = win->cur_handle[j];
+ }
+ memset(win->cur_handle, 0, sizeof(win->cur_handle));
+ }
+
+ tegra_dc_ext_unpin_handles(win->ext, unpin_handles, nr_unpin);
+}
+
static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user,
struct tegra_dc_ext_flip *args)
{
@@ -865,6 +891,7 @@ static long tegra_dc_ioctl(struct file *filp, unsigned int cmd,
{
void __user *user_arg = (void __user *)arg;
struct tegra_dc_ext_user *user = filp->private_data;
+ int ret;
switch (cmd) {
case TEGRA_DC_EXT_SET_NVMAP_FD:
@@ -873,7 +900,12 @@ static long tegra_dc_ioctl(struct file *filp, unsigned int cmd,
case TEGRA_DC_EXT_GET_WINDOW:
return tegra_dc_ext_get_window(user, arg);
case TEGRA_DC_EXT_PUT_WINDOW:
- return tegra_dc_ext_put_window(user, arg);
+ ret = tegra_dc_ext_put_window(user, arg);
+ if (!ret) {
+ tegra_dc_blank(user->ext->dc, BIT(arg));
+ tegra_dc_ext_unpin_window(&user->ext->win[arg]);
+ }
+ return ret;
case TEGRA_DC_EXT_FLIP:
{
@@ -1032,11 +1064,19 @@ static int tegra_dc_release(struct inode *inode, struct file *filp)
struct tegra_dc_ext_user *user = filp->private_data;
struct tegra_dc_ext *ext = user->ext;
unsigned int i;
+ unsigned long int windows = 0;
for (i = 0; i < DC_N_WINDOWS; i++) {
- if (ext->win[i].user == user)
+ if (ext->win[i].user == user) {
tegra_dc_ext_put_window(user, i);
+ windows |= BIT(i);
+ }
}
+
+ tegra_dc_blank(ext->dc, windows);
+ for_each_set_bit(i, &windows, DC_N_WINDOWS)
+ tegra_dc_ext_unpin_window(&ext->win[i]);
+
if (ext->cursor.user == user)
tegra_dc_ext_put_cursor(user);