mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-23 20:53:53 +08: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
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 New Issue
Block a user