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. Signed-off-by: Maxime Ripard <[email protected]> --- drivers/gpu/drm/drm_simple_kms_helper.c | 23 +++++++++++++++++++++-- include/drm/drm_simple_kms_helper.h | 1 + 2 files changed, 22 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..efb643ab6448 100644 --- a/drivers/gpu/drm/drm_simple_kms_helper.c +++ b/drivers/gpu/drm/drm_simple_kms_helper.c @@ -284,14 +284,33 @@ static const struct drm_plane_helper_funcs drm_simple_kms_plane_helper_funcs = { 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->reset_plane) + return pipe->funcs->reset_plane(pipe); + + if (pipe->funcs->create_plane_state) { + struct drm_plane_state *state; + + if (plane->state) { + pipe->funcs->destroy_plane_state(pipe, plane->state); + plane->state = NULL; + } + + state = pipe->funcs->create_plane_state(pipe); + if (WARN_ON(IS_ERR(state))) + return; + + plane->state = state; + return; + } + + return drm_atomic_helper_plane_reset(plane); } static struct drm_plane_state *drm_simple_kms_plane_duplicate_state(struct drm_plane *plane) { struct drm_simple_display_pipe *pipe; 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 @@ -42,10 +42,11 @@ struct drm_simple_display_pipe_funcs { void (*reset_crtc)(struct drm_simple_display_pipe *pipe); struct drm_crtc_state * (*duplicate_crtc_state)(struct drm_simple_display_pipe *pipe); 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); }; -- 2.54.0
