forked from mirrors/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>
This commit is contained in:
		
							parent
							
								
									5dd20bbae8
								
							
						
					
					
						commit
						f837297ad8
					
				
					 4 changed files with 86 additions and 10 deletions
				
			
		| 
						 | 
				
			
			@ -5398,15 +5398,23 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,
 | 
			
		|||
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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -228,6 +228,7 @@ static int drm_getstats(struct drm_device *dev, void *data,
 | 
			
		|||
static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_get_cap *req = data;
 | 
			
		||||
	struct drm_crtc *crtc;
 | 
			
		||||
 | 
			
		||||
	req->value = 0;
 | 
			
		||||
	switch (req->capability) {
 | 
			
		||||
| 
						 | 
				
			
			@ -254,6 +255,13 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_
 | 
			
		|||
	case DRM_CAP_ASYNC_PAGE_FLIP:
 | 
			
		||||
		req->value = dev->mode_config.async_page_flip;
 | 
			
		||||
		break;
 | 
			
		||||
	case DRM_CAP_PAGE_FLIP_TARGET:
 | 
			
		||||
		req->value = 1;
 | 
			
		||||
		drm_for_each_crtc(crtc, dev) {
 | 
			
		||||
			if (!crtc->funcs->page_flip_target)
 | 
			
		||||
				req->value = 0;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case DRM_CAP_CURSOR_WIDTH:
 | 
			
		||||
		if (dev->mode_config.cursor_width)
 | 
			
		||||
			req->value = dev->mode_config.cursor_width;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -646,6 +646,7 @@ struct drm_gem_open {
 | 
			
		|||
#define DRM_CAP_CURSOR_WIDTH		0x8
 | 
			
		||||
#define DRM_CAP_CURSOR_HEIGHT		0x9
 | 
			
		||||
#define DRM_CAP_ADDFB2_MODIFIERS	0x10
 | 
			
		||||
#define DRM_CAP_PAGE_FLIP_TARGET	0x11
 | 
			
		||||
 | 
			
		||||
/** DRM_IOCTL_GET_CAP ioctl argument type */
 | 
			
		||||
struct drm_get_cap {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -520,7 +520,13 @@ struct drm_color_lut {
 | 
			
		|||
 | 
			
		||||
#define DRM_MODE_PAGE_FLIP_EVENT 0x01
 | 
			
		||||
#define DRM_MODE_PAGE_FLIP_ASYNC 0x02
 | 
			
		||||
#define DRM_MODE_PAGE_FLIP_FLAGS (DRM_MODE_PAGE_FLIP_EVENT|DRM_MODE_PAGE_FLIP_ASYNC)
 | 
			
		||||
#define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4
 | 
			
		||||
#define DRM_MODE_PAGE_FLIP_TARGET_RELATIVE 0x8
 | 
			
		||||
#define DRM_MODE_PAGE_FLIP_TARGET (DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE | \
 | 
			
		||||
				   DRM_MODE_PAGE_FLIP_TARGET_RELATIVE)
 | 
			
		||||
#define DRM_MODE_PAGE_FLIP_FLAGS (DRM_MODE_PAGE_FLIP_EVENT | \
 | 
			
		||||
				  DRM_MODE_PAGE_FLIP_ASYNC | \
 | 
			
		||||
				  DRM_MODE_PAGE_FLIP_TARGET)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Request a page flip on the specified crtc.
 | 
			
		||||
| 
						 | 
				
			
			@ -543,8 +549,7 @@ struct drm_color_lut {
 | 
			
		|||
 * 'as soon as possible', meaning that it not delay waiting for vblank.
 | 
			
		||||
 * This may cause tearing on the screen.
 | 
			
		||||
 *
 | 
			
		||||
 * The reserved field must be zero until we figure out something
 | 
			
		||||
 * clever to use it for.
 | 
			
		||||
 * The reserved field must be zero.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
struct drm_mode_crtc_page_flip {
 | 
			
		||||
| 
						 | 
				
			
			@ -555,6 +560,34 @@ struct drm_mode_crtc_page_flip {
 | 
			
		|||
	__u64 user_data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Request a page flip on the specified crtc.
 | 
			
		||||
 *
 | 
			
		||||
 * Same as struct drm_mode_crtc_page_flip, but supports new flags and
 | 
			
		||||
 * re-purposes the reserved field:
 | 
			
		||||
 *
 | 
			
		||||
 * The sequence field must be zero unless either of the
 | 
			
		||||
 * DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags is specified. When
 | 
			
		||||
 * the ABSOLUTE flag is specified, the sequence field denotes the absolute
 | 
			
		||||
 * vblank sequence when the flip should take effect. When the RELATIVE
 | 
			
		||||
 * flag is specified, the sequence field denotes the relative (to the
 | 
			
		||||
 * current one when the ioctl is called) vblank sequence when the flip
 | 
			
		||||
 * should take effect. NOTE: DRM_IOCTL_WAIT_VBLANK must still be used to
 | 
			
		||||
 * make sure the vblank sequence before the target one has passed before
 | 
			
		||||
 * calling this ioctl. The purpose of the
 | 
			
		||||
 * DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags is merely to clarify
 | 
			
		||||
 * the target for when code dealing with a page flip runs during a
 | 
			
		||||
 * vertical blank period.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
struct drm_mode_crtc_page_flip_target {
 | 
			
		||||
	__u32 crtc_id;
 | 
			
		||||
	__u32 fb_id;
 | 
			
		||||
	__u32 flags;
 | 
			
		||||
	__u32 sequence;
 | 
			
		||||
	__u64 user_data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* create a dumb scanout buffer */
 | 
			
		||||
struct drm_mode_create_dumb {
 | 
			
		||||
	__u32 height;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue