[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 9/9] drm/xen: replace struct drm_simple_display_pipe with regular atomic helpers



Replace Xen frontend simple display pipe with explicit plane, CRTC and
encoder objects for each pipeline.

Keep generic plane-state validation before Xen-specific checks, and
install GEM framebuffer prepare helper explicitly.

Signed-off-by: Ze Huang <ze.huang@xxxxxxxxxxxxxxxx>
---
 drivers/gpu/drm/xen/xen_drm_front.h     |   6 +-
 drivers/gpu/drm/xen/xen_drm_front_kms.c | 177 ++++++++++++++++++++++++--------
 2 files changed, 138 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/xen/xen_drm_front.h 
b/drivers/gpu/drm/xen/xen_drm_front.h
index a987c78abe41..02138b5abef5 100644
--- a/drivers/gpu/drm/xen/xen_drm_front.h
+++ b/drivers/gpu/drm/xen/xen_drm_front.h
@@ -14,7 +14,7 @@
 #include <linux/scatterlist.h>
 
 #include <drm/drm_connector.h>
-#include <drm/drm_simple_kms_helper.h>
+#include <drm/drm_encoder.h>
 
 #include "xen_drm_front_cfg.h"
 
@@ -100,7 +100,9 @@ struct xen_drm_front_drm_pipeline {
 
        int index;
 
-       struct drm_simple_display_pipe pipe;
+       struct drm_plane plane;
+       struct drm_crtc crtc;
+       struct drm_encoder encoder;
 
        struct drm_connector conn;
        /* These are only for connector mode checking */
diff --git a/drivers/gpu/drm/xen/xen_drm_front_kms.c 
b/drivers/gpu/drm/xen/xen_drm_front_kms.c
index 48772b5fe71c..57e1bef452f8 100644
--- a/drivers/gpu/drm/xen/xen_drm_front_kms.c
+++ b/drivers/gpu/drm/xen/xen_drm_front_kms.c
@@ -31,9 +31,9 @@
 #define FRAME_DONE_TO_MS       (XEN_DRM_FRONT_WAIT_BACK_MS + 100)
 
 static struct xen_drm_front_drm_pipeline *
-to_xen_drm_pipeline(struct drm_simple_display_pipe *pipe)
+to_xen_drm_pipeline(struct drm_crtc *crtc)
 {
-       return container_of(pipe, struct xen_drm_front_drm_pipeline, pipe);
+       return container_of(crtc, struct xen_drm_front_drm_pipeline, crtc);
 }
 
 static void fb_destroy(struct drm_framebuffer *fb)
@@ -94,7 +94,7 @@ static const struct drm_mode_config_funcs mode_config_funcs = 
{
 
 static void send_pending_event(struct xen_drm_front_drm_pipeline *pipeline)
 {
-       struct drm_crtc *crtc = &pipeline->pipe.crtc;
+       struct drm_crtc *crtc = &pipeline->crtc;
        struct drm_device *dev = crtc->dev;
        unsigned long flags;
 
@@ -105,17 +105,15 @@ static void send_pending_event(struct 
xen_drm_front_drm_pipeline *pipeline)
        spin_unlock_irqrestore(&dev->event_lock, flags);
 }
 
-static void display_enable(struct drm_simple_display_pipe *pipe,
-                          struct drm_crtc_state *crtc_state,
-                          struct drm_plane_state *plane_state)
+static void xen_drm_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+                                             struct drm_atomic_commit *state)
 {
-       struct xen_drm_front_drm_pipeline *pipeline =
-                       to_xen_drm_pipeline(pipe);
-       struct drm_crtc *crtc = &pipe->crtc;
+       struct xen_drm_front_drm_pipeline *pipeline = to_xen_drm_pipeline(crtc);
+       struct drm_plane_state *plane_state = pipeline->plane.state;
        struct drm_framebuffer *fb = plane_state->fb;
        int ret, idx;
 
-       if (!drm_dev_enter(pipe->crtc.dev, &idx))
+       if (!drm_dev_enter(crtc->dev, &idx))
                return;
 
        ret = xen_drm_front_mode_set(pipeline, crtc->x, crtc->y,
@@ -131,13 +129,13 @@ static void display_enable(struct drm_simple_display_pipe 
*pipe,
        drm_dev_exit(idx);
 }
 
-static void display_disable(struct drm_simple_display_pipe *pipe)
+static void xen_drm_crtc_helper_atomic_disable(struct drm_crtc *crtc,
+                                              struct drm_atomic_commit *state)
 {
-       struct xen_drm_front_drm_pipeline *pipeline =
-                       to_xen_drm_pipeline(pipe);
+       struct xen_drm_front_drm_pipeline *pipeline = to_xen_drm_pipeline(crtc);
        int ret = 0, idx;
 
-       if (drm_dev_enter(pipe->crtc.dev, &idx)) {
+       if (drm_dev_enter(crtc->dev, &idx)) {
                ret = xen_drm_front_mode_set(pipeline, 0, 0, 0, 0, 0,
                                             xen_drm_front_fb_to_cookie(NULL));
                drm_dev_exit(idx);
@@ -177,12 +175,13 @@ static void pflip_to_worker(struct work_struct *work)
        send_pending_event(pipeline);
 }
 
-static bool display_send_page_flip(struct drm_simple_display_pipe *pipe,
+static bool display_send_page_flip(struct xen_drm_front_drm_pipeline *pipeline,
+                                  struct drm_atomic_commit *state,
                                   struct drm_plane_state *old_plane_state)
 {
        struct drm_plane_state *plane_state =
-                       drm_atomic_get_new_plane_state(old_plane_state->state,
-                                                      &pipe->plane);
+                       drm_atomic_get_new_plane_state(state,
+                                                      &pipeline->plane);
 
        /*
         * If old_plane_state->fb is NULL and plane_state->fb is not,
@@ -193,8 +192,6 @@ static bool display_send_page_flip(struct 
drm_simple_display_pipe *pipe,
         * sent to the backend as a part of display_set_config call.
         */
        if (old_plane_state->fb && plane_state->fb) {
-               struct xen_drm_front_drm_pipeline *pipeline =
-                               to_xen_drm_pipeline(pipe);
                struct xen_drm_front_drm_info *drm_info = pipeline->drm_info;
                int ret;
 
@@ -224,10 +221,30 @@ static bool display_send_page_flip(struct 
drm_simple_display_pipe *pipe,
        return false;
 }
 
-static int display_check(struct drm_simple_display_pipe *pipe,
-                        struct drm_plane_state *plane_state,
-                        struct drm_crtc_state *crtc_state)
+static int xen_drm_plane_helper_atomic_check(struct drm_plane *plane,
+                                            struct drm_atomic_commit *state)
 {
+       struct drm_plane_state *plane_state = 
drm_atomic_get_new_plane_state(state, plane);
+       struct drm_crtc *crtc = plane_state->crtc;
+       struct drm_crtc_state *crtc_state = NULL;
+       int ret;
+
+       if (crtc)
+               crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+
+       ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 false, false);
+       if (ret)
+               return ret;
+
+       if (!plane_state->visible)
+               return 0;
+
+       if (!crtc_state)
+               return 0;
+
        /*
         * Xen doesn't initialize vblanking via drm_vblank_init(), so
         * DRM helpers assume that it doesn't handle vblanking and start
@@ -242,15 +259,19 @@ static int display_check(struct drm_simple_display_pipe 
*pipe,
        return 0;
 }
 
-static void display_update(struct drm_simple_display_pipe *pipe,
-                          struct drm_plane_state *old_plane_state)
+static void xen_drm_plane_helper_atomic_update(struct drm_plane *plane,
+                                              struct drm_atomic_commit *state)
 {
-       struct xen_drm_front_drm_pipeline *pipeline =
-                       to_xen_drm_pipeline(pipe);
-       struct drm_crtc *crtc = &pipe->crtc;
+       struct drm_plane_state *old_plane_state = 
drm_atomic_get_old_plane_state(state, plane);
+       struct drm_crtc *crtc = plane->state->crtc ?: old_plane_state->crtc;
+       struct xen_drm_front_drm_pipeline *pipeline;
        struct drm_pending_vblank_event *event;
        int idx;
 
+       if (!crtc)
+               return;
+
+       pipeline = to_xen_drm_pipeline(crtc);
        event = crtc->state->event;
        if (event) {
                struct drm_device *dev = crtc->dev;
@@ -265,7 +286,7 @@ static void display_update(struct drm_simple_display_pipe 
*pipe,
                spin_unlock_irqrestore(&dev->event_lock, flags);
        }
 
-       if (!drm_dev_enter(pipe->crtc.dev, &idx)) {
+       if (!drm_dev_enter(crtc->dev, &idx)) {
                send_pending_event(pipeline);
                return;
        }
@@ -278,19 +299,19 @@ static void display_update(struct drm_simple_display_pipe 
*pipe,
         * If this is not a page flip, e.g. no flip done event from the backend
         * is expected, then send now.
         */
-       if (!display_send_page_flip(pipe, old_plane_state))
+       if (!display_send_page_flip(pipeline, state, old_plane_state))
                send_pending_event(pipeline);
 
        drm_dev_exit(idx);
 }
 
 static enum drm_mode_status
-display_mode_valid(struct drm_simple_display_pipe *pipe,
-                  const struct drm_display_mode *mode)
+xen_drm_crtc_helper_mode_valid(struct drm_crtc *crtc,
+                              const struct drm_display_mode *mode)
 {
        struct xen_drm_front_drm_pipeline *pipeline =
-                       container_of(pipe, struct xen_drm_front_drm_pipeline,
-                                    pipe);
+                       container_of(crtc, struct xen_drm_front_drm_pipeline,
+                                    crtc);
 
        if (mode->hdisplay != pipeline->width)
                return MODE_ERROR;
@@ -301,12 +322,55 @@ display_mode_valid(struct drm_simple_display_pipe *pipe,
        return MODE_OK;
 }
 
-static const struct drm_simple_display_pipe_funcs display_funcs = {
-       .mode_valid = display_mode_valid,
-       .enable = display_enable,
-       .disable = display_disable,
-       .check = display_check,
-       .update = display_update,
+static int xen_drm_crtc_helper_atomic_check(struct drm_crtc *crtc, struct 
drm_atomic_commit *state)
+{
+       struct drm_crtc_state *crtc_state = 
drm_atomic_get_new_crtc_state(state, crtc);
+       int ret;
+
+       if (!crtc_state->enable)
+               goto out;
+
+       ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state);
+       if (ret)
+               return ret;
+
+out:
+       return drm_atomic_add_affected_planes(state, crtc);
+}
+
+static const struct drm_plane_helper_funcs display_plane_helper_funcs = {
+       .prepare_fb     = drm_gem_plane_helper_prepare_fb,
+       .atomic_check   = xen_drm_plane_helper_atomic_check,
+       .atomic_update  = xen_drm_plane_helper_atomic_update,
+};
+
+static const struct drm_plane_funcs display_plane_funcs = {
+       .update_plane           = drm_atomic_helper_update_plane,
+       .disable_plane          = drm_atomic_helper_disable_plane,
+       .destroy                = drm_plane_cleanup,
+       .reset                  = drm_atomic_helper_plane_reset,
+       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+       .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
+};
+
+static const struct drm_crtc_helper_funcs display_crtc_helper_funcs = {
+       .mode_valid     = xen_drm_crtc_helper_mode_valid,
+       .atomic_check   = xen_drm_crtc_helper_atomic_check,
+       .atomic_enable  = xen_drm_crtc_helper_atomic_enable,
+       .atomic_disable = xen_drm_crtc_helper_atomic_disable,
+};
+
+static const struct drm_crtc_funcs display_crtc_funcs = {
+       .reset                  = drm_atomic_helper_crtc_reset,
+       .destroy                = drm_crtc_cleanup,
+       .set_config             = drm_atomic_helper_set_config,
+       .page_flip              = drm_atomic_helper_page_flip,
+       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+       .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
+};
+
+static const struct drm_encoder_funcs display_encoder_funcs = {
+       .destroy = drm_encoder_cleanup,
 };
 
 static int display_pipe_init(struct xen_drm_front_drm_info *drm_info,
@@ -331,10 +395,37 @@ static int display_pipe_init(struct 
xen_drm_front_drm_info *drm_info,
 
        formats = xen_drm_front_conn_get_formats(&format_count);
 
-       return drm_simple_display_pipe_init(dev, &pipeline->pipe,
-                                           &display_funcs, formats,
-                                           format_count, NULL,
-                                           &pipeline->conn);
+       ret = drm_universal_plane_init(dev, &pipeline->plane, 1,
+                                      &display_plane_funcs,
+                                      formats, format_count,
+                                      NULL,
+                                      DRM_PLANE_TYPE_PRIMARY, NULL);
+       if (ret)
+               return ret;
+
+       drm_plane_helper_add(&pipeline->plane, &display_plane_helper_funcs);
+
+       ret = drm_crtc_init_with_planes(dev, &pipeline->crtc,
+                                       &pipeline->plane, NULL,
+                                       &display_crtc_funcs, NULL);
+       if (ret)
+               return ret;
+
+       drm_crtc_helper_add(&pipeline->crtc, &display_crtc_helper_funcs);
+
+       ret = drm_encoder_init(dev, &pipeline->encoder,
+                              &display_encoder_funcs,
+                              DRM_MODE_ENCODER_NONE, NULL);
+       if (ret)
+               return ret;
+
+       pipeline->encoder.possible_crtcs = drm_crtc_mask(&pipeline->crtc);
+
+       ret = drm_connector_attach_encoder(&pipeline->conn, &pipeline->encoder);
+       if (ret)
+               return ret;
+
+       return 0;
 }
 
 int xen_drm_front_kms_init(struct xen_drm_front_drm_info *drm_info)

-- 
2.55.0




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.