If the client does not set the ATOMIC capability, do not wait for vblank before returning an DRM_IOCTL_MODE_SETPLANE call. In this way, a legacy framework (eg non-atomic Weston) can call several SETPLANE within the same Vsync cycle. This is implemented by setting the legacy_cursor_update flag, to behave the same way as DRM_IOCTL_MODE_CURSOR (not vblank synced). Change-Id: Ia241b6c88411c675bf589c17d4a44db6d02f669f Signed-off-by: Fabien Dessenne <fabien.dessenne@xxxxxx> --- drivers/gpu/drm/sti/sti_cursor.c | 4 +- drivers/gpu/drm/sti/sti_gdp.c | 4 +- drivers/gpu/drm/sti/sti_hqvdp.c | 4 +- drivers/gpu/drm/sti/sti_plane.c | 144 +++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/sti/sti_plane.h | 8 +++ 5 files changed, 158 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c index cca75bd..ea0dbae 100644 --- a/drivers/gpu/drm/sti/sti_cursor.c +++ b/drivers/gpu/drm/sti/sti_cursor.c @@ -346,8 +346,8 @@ static int sti_cursor_late_register(struct drm_plane *drm_plane) } static const struct drm_plane_funcs sti_cursor_plane_helpers_funcs = { - .update_plane = drm_atomic_helper_update_plane, - .disable_plane = drm_atomic_helper_disable_plane, + .update_plane = sti_plane_update_plane, + .disable_plane = sti_plane_disable_plane, .destroy = sti_cursor_destroy, .set_property = drm_atomic_helper_plane_set_property, .reset = sti_plane_reset, diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index 81df309..a379bbe 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c @@ -882,8 +882,8 @@ static int sti_gdp_late_register(struct drm_plane *drm_plane) } static const struct drm_plane_funcs sti_gdp_plane_helpers_funcs = { - .update_plane = drm_atomic_helper_update_plane, - .disable_plane = drm_atomic_helper_disable_plane, + .update_plane = sti_plane_update_plane, + .disable_plane = sti_plane_disable_plane, .destroy = sti_gdp_destroy, .set_property = drm_atomic_helper_plane_set_property, .reset = sti_plane_reset, diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index f88130f..65ca43f 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c @@ -1252,8 +1252,8 @@ static int sti_hqvdp_late_register(struct drm_plane *drm_plane) } static const struct drm_plane_funcs sti_hqvdp_plane_helpers_funcs = { - .update_plane = drm_atomic_helper_update_plane, - .disable_plane = drm_atomic_helper_disable_plane, + .update_plane = sti_plane_update_plane, + .disable_plane = sti_plane_disable_plane, .destroy = sti_hqvdp_destroy, .set_property = drm_atomic_helper_plane_set_property, .reset = sti_plane_reset, diff --git a/drivers/gpu/drm/sti/sti_plane.c b/drivers/gpu/drm/sti/sti_plane.c index ca4b371..22cf30d 100644 --- a/drivers/gpu/drm/sti/sti_plane.c +++ b/drivers/gpu/drm/sti/sti_plane.c @@ -7,6 +7,7 @@ */ #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -130,3 +131,146 @@ void sti_plane_init_property(struct sti_plane *plane, DRM_DEBUG_DRIVER("drm plane:%d mapped to %s\n", plane->drm_plane.base.id, sti_plane_to_str(plane)); } + +int sti_plane_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int crtc_x, int crtc_y, + unsigned int crtc_w, unsigned int crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h) +{ + /* + * Forked from drm_atomic_helper_update_plane(). + * Here we do not wait for vblank if the client is not atomic, so + * DRM_IOCTL_MODE_SETPLANE returns before vblank. + */ + + struct drm_atomic_state *state; + struct drm_plane_state *plane_state; + struct sti_private *private = plane->dev->dev_private; + int ret = 0; + + state = drm_atomic_state_alloc(plane->dev); + if (!state) + return -ENOMEM; + + state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); +retry: + plane_state = drm_atomic_get_plane_state(state, plane); + if (IS_ERR(plane_state)) { + ret = PTR_ERR(plane_state); + goto fail; + } + + ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); + if (ret != 0) + goto fail; + drm_atomic_set_fb_for_plane(plane_state, fb); + plane_state->crtc_x = crtc_x; + plane_state->crtc_y = crtc_y; + plane_state->crtc_w = crtc_w; + plane_state->crtc_h = crtc_h; + plane_state->src_x = src_x; + plane_state->src_y = src_y; + plane_state->src_w = src_w; + plane_state->src_h = src_h; + + if ((plane == crtc->cursor) || !private->filp->atomic) + state->legacy_cursor_update = true; + + ret = drm_atomic_commit(state); + if (ret != 0) + goto fail; + + /* Driver takes ownership of state on successful commit. */ + return 0; +fail: + if (ret == -EDEADLK) + goto backoff; + + drm_atomic_state_free(state); + + return ret; +backoff: + drm_atomic_state_clear(state); + drm_atomic_legacy_backoff(state); + + /* + * Someone might have exchanged the framebuffer while we dropped locks + * in the backoff code. We need to fix up the fb refcount tracking the + * core does for us. + */ + plane->old_fb = plane->fb; + + goto retry; +} + +int sti_plane_disable_plane(struct drm_plane *plane) +{ + /* + * Forked from drm_atomic_helper_disable_plane(). + * Here we do not wait for vblank if the client is not atomic, so + * DRM_IOCTL_MODE_SETPLANE returns before vblank. + */ + struct drm_atomic_state *state; + struct drm_plane_state *plane_state; + struct sti_private *private = plane->dev->dev_private; + int ret = 0; + + /* + * FIXME: Without plane->crtc set we can't get at the implicit legacy + * acquire context. The real fix will be to wire the acquire ctx through + * everywhere we need it, but meanwhile prevent chaos by just skipping + * this noop. The critical case is the cursor ioctls which a) only grab + * crtc/cursor-plane locks (so we need the crtc to get at the right + * acquire context) and b) can try to disable the plane multiple times. + */ + if (!plane->crtc) + return 0; + + state = drm_atomic_state_alloc(plane->dev); + if (!state) + return -ENOMEM; + + state->acquire_ctx = drm_modeset_legacy_acquire_ctx(plane->crtc); +retry: + plane_state = drm_atomic_get_plane_state(state, plane); + if (IS_ERR(plane_state)) { + ret = PTR_ERR(plane_state); + goto fail; + } + + if ((plane_state->crtc && (plane == plane->crtc->cursor)) || + !private->filp->atomic) + plane_state->state->legacy_cursor_update = true; + + ret = __drm_atomic_helper_disable_plane(plane, plane_state); + if (ret != 0) + goto fail; + + ret = drm_atomic_commit(state); + if (ret != 0) + goto fail; + + /* Driver takes ownership of state on successful commit. */ + return 0; +fail: + if (ret == -EDEADLK) + goto backoff; + + drm_atomic_state_free(state); + + return ret; +backoff: + drm_atomic_state_clear(state); + drm_atomic_legacy_backoff(state); + + /* + * Someone might have exchanged the framebuffer while we dropped locks + * in the backoff code. We need to fix up the fb refcount tracking the + * core does for us. + */ + plane->old_fb = plane->fb; + + goto retry; +} diff --git a/drivers/gpu/drm/sti/sti_plane.h b/drivers/gpu/drm/sti/sti_plane.h index ce3e8d6..1372b9c 100644 --- a/drivers/gpu/drm/sti/sti_plane.h +++ b/drivers/gpu/drm/sti/sti_plane.h @@ -83,4 +83,12 @@ void sti_plane_update_fps(struct sti_plane *plane, void sti_plane_init_property(struct sti_plane *plane, enum drm_plane_type type); void sti_plane_reset(struct drm_plane *plane); + +int sti_plane_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int crtc_x, int crtc_y, + unsigned int crtc_w, unsigned int crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h); +int sti_plane_disable_plane(struct drm_plane *plane); #endif -- 2.7.4 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel