[PATCH v3 8/8] drm/xen: replace struct drm_simple_display_pipe with regular atomic helpers
Ze Huang <[email protected]> Mon, 27 Jul 2026 03:45:21 +0800
| Newsgroups | org.ozlabs.lists.linux-aspeed,dev.linux.lists.imx,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel,org.xenproject.lists.xen-devel |
|---|---|
| Message-ID | <20260727-drm-simple-kms-removal-v3-8-cd5dc89858c6@oss.qualcomm.com> |
Replace the 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 the GEM framebuffer prepare helper explicitly. Use commit-local plane state in the CRTC enable path and pass the new plane source position to the backend mode-set request. Handle pending page-flip events through the commit-local CRTC state in the plane update path. Signed-off-by: Ze Huang <[email protected]> --- Changes in v3: - Use commit-local plane state in the CRTC enable path. - Pass the new plane source position to the xen_drm_front_mode_set. - Make the container helpers static inline. --- drivers/gpu/drm/xen/xen_drm_front.h | 6 +- drivers/gpu/drm/xen/xen_drm_front_kms.c | 188 +++++++++++++++++++++++--------- 2 files changed, 142 insertions(+), 52 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..9896ea35b743 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_kms.c +++ b/drivers/gpu/drm/xen/xen_drm_front_kms.c @@ -30,10 +30,16 @@ */ #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) +static inline struct xen_drm_front_drm_pipeline * +xen_drm_pipeline_from_crtc(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 inline struct xen_drm_front_drm_pipeline * +xen_drm_pipeline_from_plane(struct drm_plane *plane) +{ + return container_of(plane, struct xen_drm_front_drm_pipeline, plane); } static void fb_destroy(struct drm_framebuffer *fb) @@ -94,7 +100,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,24 +111,21 @@ 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 *commit) { - struct xen_drm_front_drm_pipeline *pipeline = - to_xen_drm_pipeline(pipe); - struct drm_crtc *crtc = &pipe->crtc; - struct drm_framebuffer *fb = plane_state->fb; + struct xen_drm_front_drm_pipeline *pipeline = xen_drm_pipeline_from_crtc(crtc); + struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(commit, &pipeline->plane); + struct drm_framebuffer *fb = pstate->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, + ret = xen_drm_front_mode_set(pipeline, pstate->crtc_x, pstate->crtc_y, fb->width, fb->height, fb->format->cpp[0] * 8, xen_drm_front_fb_to_cookie(fb)); - if (ret) { DRM_ERROR("Failed to enable display: %d\n", ret); pipeline->conn_connected = false; @@ -131,13 +134,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 *commit) { - struct xen_drm_front_drm_pipeline *pipeline = - to_xen_drm_pipeline(pipe); + struct xen_drm_front_drm_pipeline *pipeline = xen_drm_pipeline_from_crtc(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 +180,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 *commit, 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(commit, + &pipeline->plane); /* * If old_plane_state->fb is NULL and plane_state->fb is not, @@ -193,8 +197,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 +226,29 @@ 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 *commit) { + struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(commit, plane); + struct drm_crtc_state *crtc_state = NULL; + int ret; + + if (plane_state->crtc) { + crtc_state = drm_atomic_get_crtc_state(commit, plane_state->crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + } + + 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 || !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,16 +263,17 @@ 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 *commit) { - 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(commit, plane); + struct xen_drm_front_drm_pipeline *pipeline = xen_drm_pipeline_from_plane(plane); + struct drm_crtc *crtc = &pipeline->crtc; + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(commit, crtc); struct drm_pending_vblank_event *event; int idx; - event = crtc->state->event; + event = crtc_state ? crtc_state->event : NULL; if (event) { struct drm_device *dev = crtc->dev; unsigned long flags; @@ -259,13 +281,13 @@ static void display_update(struct drm_simple_display_pipe *pipe, WARN_ON(pipeline->pending_event); spin_lock_irqsave(&dev->event_lock, flags); - crtc->state->event = NULL; + crtc_state->event = NULL; pipeline->pending_event = event; 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 +300,17 @@ 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, commit, 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); + struct xen_drm_front_drm_pipeline *pipeline = xen_drm_pipeline_from_crtc(crtc); if (mode->hdisplay != pipeline->width) return MODE_ERROR; @@ -301,12 +321,53 @@ 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 *commit) +{ + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(commit, crtc); + int ret; + + if (crtc_state->enable) { + ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); + if (ret) + return ret; + } + + return drm_atomic_add_affected_planes(commit, 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 +392,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, 0, + &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.43.0