diff options
-rw-r--r-- | drivers/video/tegra/dc/ext/dev.c | 62 | ||||
-rw-r--r-- | drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h | 3 | ||||
-rw-r--r-- | include/video/tegra_dc_ext.h | 25 |
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; |