summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/tegra/dc/ext/dev.c62
-rw-r--r--drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h3
-rw-r--r--include/video/tegra_dc_ext.h25
3 files changed, 86 insertions, 4 deletions
diff --git a/drivers/video/tegra/dc/ext/dev.c b/drivers/video/tegra/dc/ext/dev.c
index 38dc4a928ee8..22aa82248173 100644
--- a/drivers/video/tegra/dc/ext/dev.c
+++ b/drivers/video/tegra/dc/ext/dev.c
@@ -114,6 +114,9 @@ struct tegra_dc_ext_flip_data {
bool dirty_rect_valid;
};
+static void tegra_dc_ext_unpin_window(struct tegra_dc_ext_win *win);
+static int tegra_dc_ext_set_vblank(struct tegra_dc_ext *ext, bool enable);
+
static inline s64 tegra_timespec_to_ns(const struct tegra_timespec *ts)
{
return ((s64) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
@@ -230,9 +233,16 @@ void tegra_dc_ext_enable(struct tegra_dc_ext *ext)
void tegra_dc_ext_disable(struct tegra_dc_ext *ext)
{
int i;
+ unsigned long int windows = 0;
+
set_enable(ext, false);
/*
+ * Disable vblank requests
+ */
+ tegra_dc_ext_set_vblank(ext, false);
+
+ /*
* Flush the flip queue -- note that this must be called with dc->lock
* unlocked or else it will hang.
*/
@@ -241,6 +251,24 @@ void tegra_dc_ext_disable(struct tegra_dc_ext *ext)
flush_workqueue(win->flip_wq);
}
+
+ /*
+ * Blank all windows owned by dcext driver, unpin buffers that were
+ * removed from screen, and advance syncpt.
+ */
+ if (ext->dc->enabled) {
+ for (i = 0; i < DC_N_WINDOWS; i++) {
+ if (ext->win[i].user)
+ 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]);
+ tegra_dc_disable_window(ext->dc, i);
+ }
+ }
+
}
int tegra_dc_ext_check_windowattr(struct tegra_dc_ext *ext,
@@ -441,6 +469,31 @@ static int tegra_dc_ext_set_windowattr(struct tegra_dc_ext *ext,
return err;
}
+static int tegra_dc_ext_set_vblank(struct tegra_dc_ext *ext, bool enable)
+{
+ struct tegra_dc *dc;
+ int ret = 0;
+
+ if (ext->vblank_enabled == enable)
+ return 0;
+
+ dc = ext->dc;
+
+ if (enable) {
+ tegra_dc_hold_dc_out(dc);
+ tegra_dc_vsync_enable(dc);
+ } else if (ext->vblank_enabled) {
+ tegra_dc_vsync_disable(dc);
+ tegra_dc_release_dc_out(dc);
+ }
+
+ if (!ret) {
+ ext->vblank_enabled = enable;
+ return 0;
+ }
+ return 1;
+}
+
static void tegra_dc_ext_unpin_handles(struct tegra_dc_dmabuf *unpin_handles[],
int nr_unpin)
{
@@ -1602,6 +1655,15 @@ static long tegra_dc_ioctl(struct file *filp, unsigned int cmd,
#endif
}
+ case TEGRA_DC_EXT_SET_VBLANK:
+ {
+ struct tegra_dc_ext_set_vblank args;
+
+ if (copy_from_user(&args, user_arg, sizeof(args)))
+ return -EFAULT;
+
+ return tegra_dc_ext_set_vblank(user->ext, args.enable);
+ }
default:
return -EINVAL;
}
diff --git a/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h b/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
index cb34047768f3..7c549c9875d9 100644
--- a/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
+++ b/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
@@ -86,13 +86,14 @@ struct tegra_dc_ext {
} cursor;
bool enabled;
+ bool vblank_enabled;
};
#define TEGRA_DC_EXT_EVENT_MASK_ALL \
(TEGRA_DC_EXT_EVENT_HOTPLUG | TEGRA_DC_EXT_EVENT_BANDWIDTH_INC | \
TEGRA_DC_EXT_EVENT_BANDWIDTH_DEC)
-#define TEGRA_DC_EXT_EVENT_MAX_SZ 8
+#define TEGRA_DC_EXT_EVENT_MAX_SZ 16
struct tegra_dc_ext_event_list {
struct tegra_dc_ext_event event;
diff --git a/include/video/tegra_dc_ext.h b/include/video/tegra_dc_ext.h
index 78e344d5ad6f..95fe6dae5436 100644
--- a/include/video/tegra_dc_ext.h
+++ b/include/video/tegra_dc_ext.h
@@ -187,6 +187,15 @@ struct tegra_dc_ext_flip_3 {
};
/*
+ * vblank control - enable or disable vblank events
+ */
+
+struct tegra_dc_ext_set_vblank {
+ __u8 enable;
+ __u8 reserved[3]; /* unused - must be 0 */
+};
+
+/*
* Cursor image format:
*
* Tegra hardware supports two different cursor formats:
@@ -433,6 +442,9 @@ struct tegra_dc_ext_feature {
#define TEGRA_DC_EXT_FLIP3 \
_IOWR('D', 0x14, struct tegra_dc_ext_flip_3)
+#define TEGRA_DC_EXT_SET_VBLANK \
+ _IOW('D', 0x15, struct tegra_dc_ext_set_vblank)
+
enum tegra_dc_ext_control_output_type {
TEGRA_DC_EXT_DSI,
TEGRA_DC_EXT_LVDS,
@@ -483,13 +495,20 @@ struct tegra_dc_ext_event {
char data[0];
};
-#define TEGRA_DC_EXT_EVENT_HOTPLUG 0x1
+#define TEGRA_DC_EXT_EVENT_HOTPLUG (1 << 0)
struct tegra_dc_ext_control_event_hotplug {
__u32 handle;
};
-#define TEGRA_DC_EXT_EVENT_BANDWIDTH_INC 0x3
-#define TEGRA_DC_EXT_EVENT_BANDWIDTH_DEC 0x4
+#define TEGRA_DC_EXT_EVENT_VBLANK (1 << 1)
+struct tegra_dc_ext_control_event_vblank {
+ __u32 handle;
+ __u32 reserved; /* unused */
+ __u64 timestamp_ns;
+};
+
+#define TEGRA_DC_EXT_EVENT_BANDWIDTH_INC (1 << 2)
+#define TEGRA_DC_EXT_EVENT_BANDWIDTH_DEC (1 << 3)
struct tegra_dc_ext_control_event_bandwidth {
__u32 handle;
__u32 total_bw;