From a8a198cefe5cbb5fb5bec00d613233b0431d7ebf Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 14 Aug 2026 16:56:50 +0200 Subject: [PATCH] drm/simple-kms: Add create_plane_state hook The simple-kms helper provides a reset_plane hook to let drivers override the default plane reset. However, the reset hook is overloaded: it is used to create the initial software state at probe time, but also to reset both the hardware and software state during suspend/resume. These two roles have different expectations, and reset is not fallible which makes error handling difficult. The atomic_create_state pattern was introduced to untangle this by providing a hook that only allocates and initializes a pristine state without any side effect. Add a create_plane_state hook to struct drm_simple_display_pipe_funcs. When provided, drm_simple_kms_plane_reset() will use it to allocate a fresh state, falling back to reset_plane and then to the default drm_atomic_helper_plane_reset(). This will allow simple-kms drivers to be converted to the atomic_create_state pattern. Reviewed-by: Thomas Zimmermann Link: https://patch.msgid.link/20260814-drm-no-more-plane-reset-v2-1-82d2963dd134@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_simple_kms_helper.c | 26 +++++++++++++++++++++++-- include/drm/drm_simple_kms_helper.h | 1 + 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c index 8e1d07b9f1e3..528968ea5c4b 100644 --- a/drivers/gpu/drm/drm_simple_kms_helper.c +++ b/drivers/gpu/drm/drm_simple_kms_helper.c @@ -281,15 +281,37 @@ static const struct drm_plane_helper_funcs drm_simple_kms_plane_helper_funcs = { .atomic_update = drm_simple_kms_plane_atomic_update, }; +static void drm_simple_kms_plane_destroy_state(struct drm_plane *plane, + struct drm_plane_state *state); + static void drm_simple_kms_plane_reset(struct drm_plane *plane) { struct drm_simple_display_pipe *pipe; pipe = container_of(plane, struct drm_simple_display_pipe, plane); - if (!pipe->funcs || !pipe->funcs->reset_plane) + if (!pipe->funcs) return drm_atomic_helper_plane_reset(plane); - return pipe->funcs->reset_plane(pipe); + if (pipe->funcs->create_plane_state) { + struct drm_plane_state *state; + + if (plane->state) { + drm_simple_kms_plane_destroy_state(plane, plane->state); + plane->state = NULL; + } + + state = pipe->funcs->create_plane_state(pipe); + if (WARN_ON(IS_ERR(state))) + return; + + plane->state = state; + return; + } + + if (pipe->funcs->reset_plane) + return pipe->funcs->reset_plane(pipe); + + return drm_atomic_helper_plane_reset(plane); } static struct drm_plane_state *drm_simple_kms_plane_duplicate_state(struct drm_plane *plane) diff --git a/include/drm/drm_simple_kms_helper.h b/include/drm/drm_simple_kms_helper.h index cb672ce0e856..b58f6d532820 100644 --- a/include/drm/drm_simple_kms_helper.h +++ b/include/drm/drm_simple_kms_helper.h @@ -44,6 +44,7 @@ struct drm_simple_display_pipe_funcs { void (*destroy_crtc_state)(struct drm_simple_display_pipe *pipe, struct drm_crtc_state *crtc_state); void (*reset_plane)(struct drm_simple_display_pipe *pipe); + struct drm_plane_state * (*create_plane_state)(struct drm_simple_display_pipe *pipe); struct drm_plane_state * (*duplicate_plane_state)(struct drm_simple_display_pipe *pipe); void (*destroy_plane_state)(struct drm_simple_display_pipe *pipe, struct drm_plane_state *plane_state);