[PATCH 9/9] drm/xen: replace struct drm_simple_display_pipe with regular atomic helpers
Ze Huang
ze.huang at oss.qualcomm.com
Sat Jul 4 11:31:18 PDT 2026
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 at oss.qualcomm.com>
---
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
More information about the linux-arm-kernel
mailing list