]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
drm: xlnx: zynqmp: Update planes asynchronously in the legacy entry
authorHyun Kwon <hyun.kwon@xilinx.com>
Thu, 26 Apr 2018 22:00:57 +0000 (15:00 -0700)
committerMichal Simek <michal.simek@xilinx.com>
Wed, 2 May 2018 06:29:56 +0000 (08:29 +0200)
With the atomic modesetting, the legacy APIs create a commit for single
change. This serializes each changes with vsync interval as each commit
is synchronous to vsync. So, if application is changing both crtc and
plane within single vsync interval, only one will be taken in a single
interval, and it gives half of the framerate.

This patch makes the plane update asynchronous to vsync, meaning the plane
update from the legacy set plane API happens immediately when there's
no atomic commit queued for the given plane. The implementation is based
on drm_atomic_helper_update_plane() but enables the async update.

Signed-off-by: Hyun Kwon <hyun.kwon@xilinx.com>
Tested-by: Tejas Upadhyay <tejas.upadhyay@xilinx.com>
Tested-by: Devarsh Thakkar <devarsht@xilinx.com>
Tested-by: Preetesh Parekh <preetesh@xilinx.com>
Reviewed-by: Satish Kumar Nagireddy <satishna@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
drivers/gpu/drm/xlnx/zynqmp_disp.c

index fc0423b37c186eaa99f933d3ad8672961b02083b..807fedebd3d3202449cfc36f701f641b89c9b635 100644 (file)
@@ -2547,8 +2547,57 @@ zynqmp_disp_plane_atomic_get_property(struct drm_plane *plane,
        return ret;
 }
 
+static int
+zynqmp_disp_plane_atomic_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,
+                                     u32 src_x, u32 src_y,
+                                     u32 src_w, u32 src_h,
+                                     struct drm_modeset_acquire_ctx *ctx)
+{
+       struct drm_atomic_state *state;
+       struct drm_plane_state *plane_state;
+       int ret;
+
+       state = drm_atomic_state_alloc(plane->dev);
+       if (!state)
+               return -ENOMEM;
+
+       state->acquire_ctx = ctx;
+       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)
+               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)
+               state->legacy_cursor_update = true;
+
+       /* Do async-update if possible */
+       state->async_update = !drm_atomic_helper_async_check(plane->dev, state);
+       ret = drm_atomic_commit(state);
+fail:
+       drm_atomic_state_put(state);
+       return ret;
+}
+
 static struct drm_plane_funcs zynqmp_disp_plane_funcs = {
-       .update_plane           = drm_atomic_helper_update_plane,
+       .update_plane           = zynqmp_disp_plane_atomic_update_plane,
        .disable_plane          = drm_atomic_helper_disable_plane,
        .atomic_set_property    = zynqmp_disp_plane_atomic_set_property,
        .atomic_get_property    = zynqmp_disp_plane_atomic_get_property,
@@ -2593,9 +2642,40 @@ zynqmp_disp_plane_atomic_disable(struct drm_plane *plane,
        zynqmp_disp_plane_disable(plane);
 }
 
+static int zynqmp_disp_plane_atomic_async_check(struct drm_plane *plane,
+                                               struct drm_plane_state *state)
+{
+       return 0;
+}
+
+static void
+zynqmp_disp_plane_atomic_async_update(struct drm_plane *plane,
+                                     struct drm_plane_state *new_state)
+{
+       struct drm_plane_state *old_state =
+               drm_atomic_get_old_plane_state(new_state->state, plane);
+
+        /* Update the current state with new configurations */
+       drm_atomic_set_fb_for_plane(plane->state, new_state->fb);
+       plane->state->crtc = new_state->crtc;
+       plane->state->crtc_x = new_state->crtc_x;
+       plane->state->crtc_y = new_state->crtc_y;
+       plane->state->crtc_w = new_state->crtc_w;
+       plane->state->crtc_h = new_state->crtc_h;
+       plane->state->src_x = new_state->src_x;
+       plane->state->src_y = new_state->src_y;
+       plane->state->src_w = new_state->src_w;
+       plane->state->src_h = new_state->src_h;
+       plane->state->state = new_state->state;
+
+       zynqmp_disp_plane_atomic_update(plane, old_state);
+}
+
 static const struct drm_plane_helper_funcs zynqmp_disp_plane_helper_funcs = {
-       .atomic_update  = zynqmp_disp_plane_atomic_update,
-       .atomic_disable = zynqmp_disp_plane_atomic_disable,
+       .atomic_update          = zynqmp_disp_plane_atomic_update,
+       .atomic_disable         = zynqmp_disp_plane_atomic_disable,
+       .atomic_async_check     = zynqmp_disp_plane_atomic_async_check,
+       .atomic_async_update    = zynqmp_disp_plane_atomic_async_update,
 };
 
 static int zynqmp_disp_create_plane(struct zynqmp_disp *disp)