Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Michel Dänzer and committed by
Alex Deucher
f837297a 5dd20bba

+86 -10
+41 -7
drivers/gpu/drm/drm_crtc.c
··· 5398 5398 int drm_mode_page_flip_ioctl(struct drm_device *dev, 5399 5399 void *data, struct drm_file *file_priv) 5400 5400 { 5401 - struct drm_mode_crtc_page_flip *page_flip = data; 5401 + struct drm_mode_crtc_page_flip_target *page_flip = data; 5402 5402 struct drm_crtc *crtc; 5403 5403 struct drm_framebuffer *fb = NULL; 5404 5404 struct drm_pending_vblank_event *e = NULL; 5405 - u32 target_vblank = 0; 5405 + u32 target_vblank = page_flip->sequence; 5406 5406 int ret = -EINVAL; 5407 5407 5408 - if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || 5409 - page_flip->reserved != 0) 5408 + if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS) 5409 + return -EINVAL; 5410 + 5411 + if (page_flip->sequence != 0 && !(page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET)) 5412 + return -EINVAL; 5413 + 5414 + /* Only one of the DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags 5415 + * can be specified 5416 + */ 5417 + if ((page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) == DRM_MODE_PAGE_FLIP_TARGET) 5410 5418 return -EINVAL; 5411 5419 5412 5420 if ((page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC) && !dev->mode_config.async_page_flip) ··· 5425 5417 return -ENOENT; 5426 5418 5427 5419 if (crtc->funcs->page_flip_target) { 5420 + u32 current_vblank; 5428 5421 int r; 5429 5422 5430 5423 r = drm_crtc_vblank_get(crtc); 5431 5424 if (r) 5432 5425 return r; 5433 5426 5434 - target_vblank = drm_crtc_vblank_count(crtc) + 5435 - !(page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC); 5436 - } else if (crtc->funcs->page_flip == NULL) { 5427 + current_vblank = drm_crtc_vblank_count(crtc); 5428 + 5429 + switch (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) { 5430 + case DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE: 5431 + if ((int)(target_vblank - current_vblank) > 1) { 5432 + DRM_DEBUG("Invalid absolute flip target %u, " 5433 + "must be <= %u\n", target_vblank, 5434 + current_vblank + 1); 5435 + drm_crtc_vblank_put(crtc); 5436 + return -EINVAL; 5437 + } 5438 + break; 5439 + case DRM_MODE_PAGE_FLIP_TARGET_RELATIVE: 5440 + if (target_vblank != 0 && target_vblank != 1) { 5441 + DRM_DEBUG("Invalid relative flip target %u, " 5442 + "must be 0 or 1\n", target_vblank); 5443 + drm_crtc_vblank_put(crtc); 5444 + return -EINVAL; 5445 + } 5446 + target_vblank += current_vblank; 5447 + break; 5448 + default: 5449 + target_vblank = current_vblank + 5450 + !(page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC); 5451 + break; 5452 + } 5453 + } else if (crtc->funcs->page_flip == NULL || 5454 + (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET)) { 5437 5455 return -EINVAL; 5438 5456 } 5439 5457
+8
drivers/gpu/drm/drm_ioctl.c
··· 228 228 static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv) 229 229 { 230 230 struct drm_get_cap *req = data; 231 + struct drm_crtc *crtc; 231 232 232 233 req->value = 0; 233 234 switch (req->capability) { ··· 254 253 break; 255 254 case DRM_CAP_ASYNC_PAGE_FLIP: 256 255 req->value = dev->mode_config.async_page_flip; 256 + break; 257 + case DRM_CAP_PAGE_FLIP_TARGET: 258 + req->value = 1; 259 + drm_for_each_crtc(crtc, dev) { 260 + if (!crtc->funcs->page_flip_target) 261 + req->value = 0; 262 + } 257 263 break; 258 264 case DRM_CAP_CURSOR_WIDTH: 259 265 if (dev->mode_config.cursor_width)
+1
include/uapi/drm/drm.h
··· 646 646 #define DRM_CAP_CURSOR_WIDTH 0x8 647 647 #define DRM_CAP_CURSOR_HEIGHT 0x9 648 648 #define DRM_CAP_ADDFB2_MODIFIERS 0x10 649 + #define DRM_CAP_PAGE_FLIP_TARGET 0x11 649 650 650 651 /** DRM_IOCTL_GET_CAP ioctl argument type */ 651 652 struct drm_get_cap {
+36 -3
include/uapi/drm/drm_mode.h
··· 520 520 521 521 #define DRM_MODE_PAGE_FLIP_EVENT 0x01 522 522 #define DRM_MODE_PAGE_FLIP_ASYNC 0x02 523 - #define DRM_MODE_PAGE_FLIP_FLAGS (DRM_MODE_PAGE_FLIP_EVENT|DRM_MODE_PAGE_FLIP_ASYNC) 523 + #define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4 524 + #define DRM_MODE_PAGE_FLIP_TARGET_RELATIVE 0x8 525 + #define DRM_MODE_PAGE_FLIP_TARGET (DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE | \ 526 + DRM_MODE_PAGE_FLIP_TARGET_RELATIVE) 527 + #define DRM_MODE_PAGE_FLIP_FLAGS (DRM_MODE_PAGE_FLIP_EVENT | \ 528 + DRM_MODE_PAGE_FLIP_ASYNC | \ 529 + DRM_MODE_PAGE_FLIP_TARGET) 524 530 525 531 /* 526 532 * Request a page flip on the specified crtc. ··· 549 543 * 'as soon as possible', meaning that it not delay waiting for vblank. 550 544 * This may cause tearing on the screen. 551 545 * 552 - * The reserved field must be zero until we figure out something 553 - * clever to use it for. 546 + * The reserved field must be zero. 554 547 */ 555 548 556 549 struct drm_mode_crtc_page_flip { ··· 557 552 __u32 fb_id; 558 553 __u32 flags; 559 554 __u32 reserved; 555 + __u64 user_data; 556 + }; 557 + 558 + /* 559 + * Request a page flip on the specified crtc. 560 + * 561 + * Same as struct drm_mode_crtc_page_flip, but supports new flags and 562 + * re-purposes the reserved field: 563 + * 564 + * The sequence field must be zero unless either of the 565 + * DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags is specified. When 566 + * the ABSOLUTE flag is specified, the sequence field denotes the absolute 567 + * vblank sequence when the flip should take effect. When the RELATIVE 568 + * flag is specified, the sequence field denotes the relative (to the 569 + * current one when the ioctl is called) vblank sequence when the flip 570 + * should take effect. NOTE: DRM_IOCTL_WAIT_VBLANK must still be used to 571 + * make sure the vblank sequence before the target one has passed before 572 + * calling this ioctl. The purpose of the 573 + * DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags is merely to clarify 574 + * the target for when code dealing with a page flip runs during a 575 + * vertical blank period. 576 + */ 577 + 578 + struct drm_mode_crtc_page_flip_target { 579 + __u32 crtc_id; 580 + __u32 fb_id; 581 + __u32 flags; 582 + __u32 sequence; 560 583 __u64 user_data; 561 584 }; 562 585