mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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,
 | 
					int drm_mode_page_flip_ioctl(struct drm_device *dev,
 | 
				
			||||||
			     void *data, struct drm_file *file_priv)
 | 
								     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_crtc *crtc;
 | 
				
			||||||
	struct drm_framebuffer *fb = NULL;
 | 
						struct drm_framebuffer *fb = NULL;
 | 
				
			||||||
	struct drm_pending_vblank_event *e = NULL;
 | 
						struct drm_pending_vblank_event *e = NULL;
 | 
				
			||||||
	u32 target_vblank = 0;
 | 
						u32 target_vblank = page_flip->sequence;
 | 
				
			||||||
	int ret = -EINVAL;
 | 
						int ret = -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
 | 
						if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS)
 | 
				
			||||||
	    page_flip->reserved != 0)
 | 
							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;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC) && !dev->mode_config.async_page_flip)
 | 
						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;
 | 
							return -ENOENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (crtc->funcs->page_flip_target) {
 | 
						if (crtc->funcs->page_flip_target) {
 | 
				
			||||||
 | 
							u32 current_vblank;
 | 
				
			||||||
		int r;
 | 
							int r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		r = drm_crtc_vblank_get(crtc);
 | 
							r = drm_crtc_vblank_get(crtc);
 | 
				
			||||||
		if (r)
 | 
							if (r)
 | 
				
			||||||
			return r;
 | 
								return r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		target_vblank = drm_crtc_vblank_count(crtc) +
 | 
							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);
 | 
									!(page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC);
 | 
				
			||||||
	} else if (crtc->funcs->page_flip == NULL) {
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else if (crtc->funcs->page_flip == NULL ||
 | 
				
			||||||
 | 
							   (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET)) {
 | 
				
			||||||
		return -EINVAL;
 | 
							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)
 | 
					static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct drm_get_cap *req = data;
 | 
						struct drm_get_cap *req = data;
 | 
				
			||||||
 | 
						struct drm_crtc *crtc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	req->value = 0;
 | 
						req->value = 0;
 | 
				
			||||||
	switch (req->capability) {
 | 
						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:
 | 
						case DRM_CAP_ASYNC_PAGE_FLIP:
 | 
				
			||||||
		req->value = dev->mode_config.async_page_flip;
 | 
							req->value = dev->mode_config.async_page_flip;
 | 
				
			||||||
		break;
 | 
							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:
 | 
						case DRM_CAP_CURSOR_WIDTH:
 | 
				
			||||||
		if (dev->mode_config.cursor_width)
 | 
							if (dev->mode_config.cursor_width)
 | 
				
			||||||
			req->value = 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_WIDTH		0x8
 | 
				
			||||||
#define DRM_CAP_CURSOR_HEIGHT		0x9
 | 
					#define DRM_CAP_CURSOR_HEIGHT		0x9
 | 
				
			||||||
#define DRM_CAP_ADDFB2_MODIFIERS	0x10
 | 
					#define DRM_CAP_ADDFB2_MODIFIERS	0x10
 | 
				
			||||||
 | 
					#define DRM_CAP_PAGE_FLIP_TARGET	0x11
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** DRM_IOCTL_GET_CAP ioctl argument type */
 | 
					/** DRM_IOCTL_GET_CAP ioctl argument type */
 | 
				
			||||||
struct drm_get_cap {
 | 
					struct drm_get_cap {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -520,7 +520,13 @@ struct drm_color_lut {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DRM_MODE_PAGE_FLIP_EVENT 0x01
 | 
					#define DRM_MODE_PAGE_FLIP_EVENT 0x01
 | 
				
			||||||
#define DRM_MODE_PAGE_FLIP_ASYNC 0x02
 | 
					#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.
 | 
					 * 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.
 | 
					 * 'as soon as possible', meaning that it not delay waiting for vblank.
 | 
				
			||||||
 * This may cause tearing on the screen.
 | 
					 * This may cause tearing on the screen.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * The reserved field must be zero until we figure out something
 | 
					 * The reserved field must be zero.
 | 
				
			||||||
 * clever to use it for.
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct drm_mode_crtc_page_flip {
 | 
					struct drm_mode_crtc_page_flip {
 | 
				
			||||||
| 
						 | 
					@ -555,6 +560,34 @@ struct drm_mode_crtc_page_flip {
 | 
				
			||||||
	__u64 user_data;
 | 
						__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 */
 | 
					/* create a dumb scanout buffer */
 | 
				
			||||||
struct drm_mode_create_dumb {
 | 
					struct drm_mode_create_dumb {
 | 
				
			||||||
	__u32 height;
 | 
						__u32 height;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue