For async flip on aplane there should be no property change except the fb id. This check was done in the set_property. Move this check to atomic_check(). This will work for both plane property async_flip and the legacy DRM_MODE_PAGE_FLIP_ASYNC flag.
Signed-off-by: Arun R Murthy <[email protected]> --- drivers/gpu/drm/drm_atomic.c | 120 +++++++++++++++++++++++++++++++++++++- drivers/gpu/drm/drm_atomic_uapi.c | 57 ------------------ 2 files changed, 118 insertions(+), 59 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 52738b80ddbeb124896f6124df5628e2ac27faa4..fc938ea467e239edd6be77b7467c45ac8c8379fd 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -31,6 +31,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_uapi.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> #include <drm/drm_bridge.h> #include <drm/drm_debugfs.h> @@ -397,10 +398,27 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state, } EXPORT_SYMBOL(drm_atomic_get_crtc_state); +static int drm_atomic_crtc_async_check(const struct drm_crtc_state *old_crtc_state, + const struct drm_crtc_state *new_crtc_state) +{ + struct drm_crtc *crtc = new_crtc_state->crtc; + + if (!new_crtc_state->async_flip) + return 0; + + if (drm_atomic_crtc_needs_modeset(new_crtc_state)) { + drm_dbg_kms(crtc->dev, "[CRTC:%d:%s] modeset required\n", + crtc->base.id, crtc->name); + return -EINVAL; + } + return 0; +} + static int drm_atomic_crtc_check(const struct drm_crtc_state *old_crtc_state, const struct drm_crtc_state *new_crtc_state) { struct drm_crtc *crtc = new_crtc_state->crtc; + int ret = 0; /* NOTE: we explicitly don't enforce constraints such as primary * layer covering entire screen, since that is something we want @@ -455,7 +473,9 @@ static int drm_atomic_crtc_check(const struct drm_crtc_state *old_crtc_state, return -EINVAL; } - return 0; + ret = drm_atomic_crtc_async_check(old_crtc_state, new_crtc_state); + + return ret; } static void drm_atomic_crtc_print_state(struct drm_printer *p, @@ -691,6 +711,96 @@ plane_switching_crtc(const struct drm_plane_state *old_plane_state, return true; } +static int drm_atomic_plane_async_check(const struct drm_plane_state *old_plane_state, + const struct drm_plane_state *new_plane_state) +{ + struct drm_plane *plane = new_plane_state->plane; + struct drm_crtc *crtc = new_plane_state->crtc; + struct drm_crtc_state *new_crtc_state = crtc->state; + + if (!new_plane_state->async_flip) + return 0; + + /* + * If its the first async flip then certain properties like modifier/pixel can + * change and will be considered as a sync flip itself + */ + if (!old_plane_state->async_flip) + return 0; + + /* For async flip on a plane there should be no change apart from fb id */ + if (new_crtc_state->active) { + drm_dbg_kms(plane->dev, "[CRTC:%d:%s] not active\n", + crtc->base.id, crtc->name); + return -EINVAL; + } + + if (old_plane_state->fb->modifier != new_plane_state->fb->modifier) { + drm_dbg_kms(plane->dev, + "[PLANE:%d:%s] Modifier cannot be changed in async flip\n", + plane->base.id, plane->name); + return -EINVAL; + } + + if (old_plane_state->fb->format != new_plane_state->fb->format) { + drm_dbg_kms(plane->dev, + "[PLANE:%d:%s] Pixel format cannot be changed in async flip\n", + plane->base.id, plane->name); + return -EINVAL; + } + + if (old_plane_state->rotation != new_plane_state->rotation) { + drm_dbg_kms(plane->dev, + "[PLANE:%d:%s] Rotation cannot be changed in async flip\n", + plane->base.id, plane->name); + return -EINVAL; + } + + if (!drm_rect_equals(&old_plane_state->src, &new_plane_state->src) || + !drm_rect_equals(&old_plane_state->dst, &new_plane_state->dst)) { + drm_dbg_kms(plane->dev, + "[PLANE:%d:%s] Size/co-ordinates cannot be changed in async flip\n", + plane->base.id, plane->name); + return -EINVAL; + } + + if (old_plane_state->alpha != new_plane_state->alpha) { + drm_dbg_kms(plane->dev, + "[PLANES:%d:%s] Alpha value cannot be changed in async flip\n", + plane->base.id, plane->name); + return -EINVAL; + } + + if (old_plane_state->pixel_blend_mode != new_plane_state->pixel_blend_mode) { + drm_dbg_kms(plane->dev, + "[PLANE:%d:%s] Pixel blend mode cannot be changed in async flip\n", + plane->base.id, plane->name); + return -EINVAL; + } + + if (old_plane_state->color_encoding != new_plane_state->color_encoding) { + drm_dbg_kms(plane->dev, + "[PLANE:%d:%s] Color encoding cannot be changed in async flip\n", + plane->base.id, plane->name); + return -EINVAL; + } + + if (old_plane_state->color_range != new_plane_state->color_range) { + drm_dbg_kms(plane->dev, + "[PLANE:%d:%s] Color range cannot be changed in async flip\n", + plane->base.id, plane->name); + return -EINVAL; + } + if (old_plane_state->scaling_filter != new_plane_state->scaling_filter) { + drm_dbg_kms(plane->dev, + "[PLANE:%d:%s] Scaling filter cannot be changed in async flip\n", + plane->base.id, plane->name); + return -EINVAL; + } + + return 0; +} + /** * drm_atomic_plane_check - check plane state * @old_plane_state: old plane state to check @@ -707,9 +817,11 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state, struct drm_plane *plane = new_plane_state->plane; struct drm_crtc *crtc = new_plane_state->crtc; const struct drm_framebuffer *fb = new_plane_state->fb; + const struct drm_plane_helper_funcs *helper_private = plane->helper_private; unsigned int fb_width, fb_height; struct drm_mode_rect *clips; uint32_t num_clips; + int ret = 0; /* either *both* CRTC and FB must be set, or neither */ if (crtc && !fb) { @@ -809,7 +921,11 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state, return -EINVAL; } - return 0; + drm_atomic_plane_async_check(old_plane_state, new_plane_state); + if (helper_private && helper_private->atomic_async_check) + ret = helper_private->atomic_async_check(plane, new_plane_state->state, true); + + return ret; } static void drm_atomic_colorop_print_state(struct drm_printer *p, diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index eb4d7146f1f92eec58aba99ce6f5b678c0959b66..7b8e3b6ca3a5a93d3afbb923f20dacbd21cfc08b 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -28,7 +28,6 @@ */ #include <drm/drm_atomic.h> -#include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_uapi.h> #include <drm/drm_framebuffer.h> #include <drm/drm_print.h> @@ -1142,19 +1141,6 @@ int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state, return ret; } -static int drm_atomic_check_prop_changes(int ret, uint64_t old_val, uint64_t prop_value, - struct drm_property *prop) -{ - if (ret != 0 || old_val != prop_value) { - drm_dbg_atomic(prop->dev, - "[PROP:%d:%s] No prop can be changed during async flip\n", - prop->base.id, prop->name); - return -EINVAL; - } - - return 0; -} - int drm_atomic_set_property(struct drm_atomic_state *state, struct drm_file *file_priv, struct drm_mode_object *obj, @@ -1163,7 +1149,6 @@ int drm_atomic_set_property(struct drm_atomic_state *state, bool async_flip) { struct drm_mode_object *ref; - u64 old_val; int ret; if (!drm_property_change_valid_get(prop, prop_value, &ref)) @@ -1180,13 +1165,6 @@ int drm_atomic_set_property(struct drm_atomic_state *state, break; } - if (async_flip) { - ret = drm_atomic_connector_get_property(connector, connector_state, - prop, &old_val); - ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); - break; - } - ret = drm_atomic_connector_set_property(connector, connector_state, file_priv, prop, prop_value); @@ -1203,13 +1181,6 @@ int drm_atomic_set_property(struct drm_atomic_state *state, break; } - if (async_flip) { - ret = drm_atomic_crtc_get_property(crtc, crtc_state, - prop, &old_val); - ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); - break; - } - ret = drm_atomic_crtc_set_property(crtc, crtc_state, prop, prop_value); break; @@ -1218,7 +1189,6 @@ int drm_atomic_set_property(struct drm_atomic_state *state, struct drm_plane *plane = obj_to_plane(obj); struct drm_plane_state *plane_state; struct drm_mode_config *config = &plane->dev->mode_config; - const struct drm_plane_helper_funcs *plane_funcs = plane->helper_private; plane_state = drm_atomic_get_plane_state(state, plane); if (IS_ERR(plane_state)) { @@ -1226,33 +1196,6 @@ int drm_atomic_set_property(struct drm_atomic_state *state, break; } - if (async_flip) { - /* no-op changes are always allowed */ - ret = drm_atomic_plane_get_property(plane, plane_state, - prop, &old_val); - ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); - - /* fail everything that isn't no-op or a pure flip */ - if (ret && prop != config->prop_fb_id && - prop != config->prop_in_fence_fd && - prop != config->prop_fb_damage_clips) { - break; - } - - if (ret && plane->type != DRM_PLANE_TYPE_PRIMARY) { - /* ask the driver if this non-primary plane is supported */ - if (plane_funcs && plane_funcs->atomic_async_check) - ret = plane_funcs->atomic_async_check(plane, state, true); - - if (ret) { - drm_dbg_atomic(prop->dev, - "[PLANE:%d:%s] does not support async flips\n", - obj->id, plane->name); - break; - } - } - } - ret = drm_atomic_plane_set_property(plane, plane_state, file_priv, prop, prop_value); -- 2.25.1
