summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/drm_crtc.c
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2016-08-08 16:23:39 +0900
committerAlex Deucher <alexander.deucher@amd.com>2016-08-10 14:28:09 -0400
commitf837297ad82480024d3ad08cd84f6670bcafa862 (patch)
tree42aca44491b3f0ea57170b0290eb382a51fc8c7c /drivers/gpu/drm/drm_crtc.c
parent5dd20bbae8a39100e1cf4a7fcc8ecd598c09d992 (diff)
drm: Add DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags v2
These flags allow userspace to explicitly specify the target vertical blank period when a flip should take effect. v2: * Add new struct drm_mode_crtc_page_flip_target instead of modifying struct drm_mode_crtc_page_flip, to make sure all existing userspace code keeps compiling (Daniel Vetter) Acked-by: Christian König <christian.koenig@amd.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r--drivers/gpu/drm/drm_crtc.c48
1 files changed, 41 insertions, 7 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index a316f7336aeb..93b9821f7f24 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -5398,15 +5398,23 @@ out:
int drm_mode_page_flip_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
- struct drm_mode_crtc_page_flip *page_flip = data;
+ struct drm_mode_crtc_page_flip_target *page_flip = data;
struct drm_crtc *crtc;
struct drm_framebuffer *fb = NULL;
struct drm_pending_vblank_event *e = NULL;
- u32 target_vblank = 0;
+ u32 target_vblank = page_flip->sequence;
int ret = -EINVAL;
- if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
- page_flip->reserved != 0)
+ if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS)
+ return -EINVAL;
+
+ if (page_flip->sequence != 0 && !(page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET))
+ return -EINVAL;
+
+ /* Only one of the DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags
+ * can be specified
+ */
+ if ((page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) == DRM_MODE_PAGE_FLIP_TARGET)
return -EINVAL;
if ((page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC) && !dev->mode_config.async_page_flip)
@@ -5417,15 +5425,41 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
return -ENOENT;
if (crtc->funcs->page_flip_target) {
+ u32 current_vblank;
int r;
r = drm_crtc_vblank_get(crtc);
if (r)
return r;
- target_vblank = drm_crtc_vblank_count(crtc) +
- !(page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC);
- } else if (crtc->funcs->page_flip == NULL) {
+ current_vblank = drm_crtc_vblank_count(crtc);
+
+ switch (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) {
+ case DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE:
+ if ((int)(target_vblank - current_vblank) > 1) {
+ DRM_DEBUG("Invalid absolute flip target %u, "
+ "must be <= %u\n", target_vblank,
+ current_vblank + 1);
+ drm_crtc_vblank_put(crtc);
+ return -EINVAL;
+ }
+ break;
+ case DRM_MODE_PAGE_FLIP_TARGET_RELATIVE:
+ if (target_vblank != 0 && target_vblank != 1) {
+ DRM_DEBUG("Invalid relative flip target %u, "
+ "must be 0 or 1\n", target_vblank);
+ drm_crtc_vblank_put(crtc);
+ return -EINVAL;
+ }
+ target_vblank += current_vblank;
+ break;
+ default:
+ target_vblank = current_vblank +
+ !(page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC);
+ break;
+ }
+ } else if (crtc->funcs->page_flip == NULL ||
+ (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET)) {
return -EINVAL;
}