Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/atomic: Let drivers decide which planes to async flip

Currently, DRM atomic uAPI allows only primary planes to be flipped
asynchronously. However, each driver might be able to perform async
flips in other different plane types. To enable drivers to set their own
restrictions on which type of plane they can or cannot flip, use the
existing atomic_async_check() from struct drm_plane_helper_funcs to
enhance this flexibility, thus allowing different plane types to be able
to do async flips as well.

Create a new parameter for the atomic_async_check(), `bool flip`. This
parameter is used to distinguish when this function is being called from
a plane update from a full page flip.

In order to prevent regressions and such, we keep the current policy: we
skip the driver check for the primary plane, because it is always
allowed to do async flips on it.

Signed-off-by: André Almeida <andrealmeid@igalia.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: Christopher Snowhill <chris@kode54.net>
Tested-by: Christopher Snowhill <chris@kode54.net>
Link: https://patchwork.freedesktop.org/patch/msgid/20250127-tonyk-async_flip-v12-1-0f7f8a8610d3@igalia.com
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

authored by

André Almeida and committed by
Dmitry Baryshkov
fd40a63c 6fe52b63

+42 -18
+1 -1
drivers/gpu/drm/drm_atomic_helper.c
··· 1966 1966 return -EBUSY; 1967 1967 } 1968 1968 1969 - ret = funcs->atomic_async_check(plane, state); 1969 + ret = funcs->atomic_async_check(plane, state, false); 1970 1970 if (ret != 0) 1971 1971 drm_dbg_atomic(dev, 1972 1972 "[PLANE:%d:%s] driver async check failed\n",
+27 -10
drivers/gpu/drm/drm_atomic_uapi.c
··· 27 27 * Daniel Vetter <daniel.vetter@ffwll.ch> 28 28 */ 29 29 30 - #include <drm/drm_atomic_uapi.h> 31 30 #include <drm/drm_atomic.h> 31 + #include <drm/drm_atomic_helper.h> 32 + #include <drm/drm_atomic_uapi.h> 32 33 #include <drm/drm_framebuffer.h> 33 34 #include <drm/drm_print.h> 34 35 #include <drm/drm_drv.h> ··· 1064 1063 struct drm_plane *plane = obj_to_plane(obj); 1065 1064 struct drm_plane_state *plane_state; 1066 1065 struct drm_mode_config *config = &plane->dev->mode_config; 1066 + const struct drm_plane_helper_funcs *plane_funcs = plane->helper_private; 1067 1067 1068 1068 plane_state = drm_atomic_get_plane_state(state, plane); 1069 1069 if (IS_ERR(plane_state)) { ··· 1072 1070 break; 1073 1071 } 1074 1072 1075 - if (async_flip && 1076 - (plane_state->plane->type != DRM_PLANE_TYPE_PRIMARY || 1077 - (prop != config->prop_fb_id && 1078 - prop != config->prop_in_fence_fd && 1079 - prop != config->prop_fb_damage_clips))) { 1080 - ret = drm_atomic_plane_get_property(plane, plane_state, 1081 - prop, &old_val); 1082 - ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); 1083 - break; 1073 + if (async_flip) { 1074 + /* check if the prop does a nop change */ 1075 + if ((prop != config->prop_fb_id && 1076 + prop != config->prop_in_fence_fd && 1077 + prop != config->prop_fb_damage_clips)) { 1078 + ret = drm_atomic_plane_get_property(plane, plane_state, 1079 + prop, &old_val); 1080 + ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); 1081 + } 1082 + 1083 + /* ask the driver if this non-primary plane is supported */ 1084 + if (plane->type != DRM_PLANE_TYPE_PRIMARY) { 1085 + ret = -EINVAL; 1086 + 1087 + if (plane_funcs && plane_funcs->atomic_async_check) 1088 + ret = plane_funcs->atomic_async_check(plane, state, true); 1089 + 1090 + if (ret) { 1091 + drm_dbg_atomic(prop->dev, 1092 + "[PLANE:%d:%s] does not support async flips\n", 1093 + obj->id, plane->name); 1094 + break; 1095 + } 1096 + } 1084 1097 } 1085 1098 1086 1099 ret = drm_atomic_plane_set_property(plane,
+2 -1
drivers/gpu/drm/loongson/lsdc_plane.c
··· 171 171 }; 172 172 173 173 static int lsdc_cursor_plane_atomic_async_check(struct drm_plane *plane, 174 - struct drm_atomic_state *state) 174 + struct drm_atomic_state *state, 175 + bool flip) 175 176 { 176 177 struct drm_plane_state *new_state; 177 178 struct drm_crtc_state *crtc_state;
+1 -1
drivers/gpu/drm/mediatek/mtk_plane.c
··· 101 101 } 102 102 103 103 static int mtk_plane_atomic_async_check(struct drm_plane *plane, 104 - struct drm_atomic_state *state) 104 + struct drm_atomic_state *state, bool flip) 105 105 { 106 106 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, 107 107 plane);
+1 -1
drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
··· 368 368 } 369 369 370 370 static int mdp5_plane_atomic_async_check(struct drm_plane *plane, 371 - struct drm_atomic_state *state) 371 + struct drm_atomic_state *state, bool flip) 372 372 { 373 373 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, 374 374 plane);
+1 -1
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
··· 1072 1072 } 1073 1073 1074 1074 static int vop_plane_atomic_async_check(struct drm_plane *plane, 1075 - struct drm_atomic_state *state) 1075 + struct drm_atomic_state *state, bool flip) 1076 1076 { 1077 1077 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, 1078 1078 plane);
+2 -1
drivers/gpu/drm/tegra/dc.c
··· 1025 1025 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); 1026 1026 } 1027 1027 1028 - static int tegra_cursor_atomic_async_check(struct drm_plane *plane, struct drm_atomic_state *state) 1028 + static int tegra_cursor_atomic_async_check(struct drm_plane *plane, struct drm_atomic_state *state, 1029 + bool flip) 1029 1030 { 1030 1031 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane); 1031 1032 struct drm_crtc_state *crtc_state;
+1 -1
drivers/gpu/drm/vc4/vc4_plane.c
··· 2338 2338 } 2339 2339 2340 2340 static int vc4_plane_atomic_async_check(struct drm_plane *plane, 2341 - struct drm_atomic_state *state) 2341 + struct drm_atomic_state *state, bool flip) 2342 2342 { 2343 2343 struct vc4_dev *vc4 = to_vc4_dev(plane->dev); 2344 2344 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
+6 -1
include/drm/drm_modeset_helper_vtables.h
··· 1400 1400 * given update can be committed asynchronously, that is, if it can 1401 1401 * jump ahead of the state currently queued for update. 1402 1402 * 1403 + * This function is also used by drm_atomic_set_property() to determine 1404 + * if the plane can be flipped in async. The flip flag is used to 1405 + * distinguish if the function is used for just the plane state or for a 1406 + * flip. 1407 + * 1403 1408 * RETURNS: 1404 1409 * 1405 1410 * Return 0 on success and any error returned indicates that the update 1406 1411 * can not be applied in asynchronous manner. 1407 1412 */ 1408 1413 int (*atomic_async_check)(struct drm_plane *plane, 1409 - struct drm_atomic_state *state); 1414 + struct drm_atomic_state *state, bool flip); 1410 1415 1411 1416 /** 1412 1417 * @atomic_async_update: