16dd7b6ceSThomas Zimmermann // SPDX-License-Identifier: GPL-2.0-or-later 26dd7b6ceSThomas Zimmermann 3820c1707SThomas Zimmermann #include <linux/dma-resv.h> 4*1ea28bc5SChristian König #include <linux/dma-fence-chain.h> 5820c1707SThomas Zimmermann 66dd7b6ceSThomas Zimmermann #include <drm/drm_atomic_state_helper.h> 7820c1707SThomas Zimmermann #include <drm/drm_atomic_uapi.h> 8820c1707SThomas Zimmermann #include <drm/drm_gem.h> 96dd7b6ceSThomas Zimmermann #include <drm/drm_gem_atomic_helper.h> 106dd7b6ceSThomas Zimmermann #include <drm/drm_gem_framebuffer_helper.h> 116dd7b6ceSThomas Zimmermann #include <drm/drm_simple_kms_helper.h> 126dd7b6ceSThomas Zimmermann 136dd7b6ceSThomas Zimmermann #include "drm_internal.h" 146dd7b6ceSThomas Zimmermann 156dd7b6ceSThomas Zimmermann /** 166dd7b6ceSThomas Zimmermann * DOC: overview 176dd7b6ceSThomas Zimmermann * 186dd7b6ceSThomas Zimmermann * The GEM atomic helpers library implements generic atomic-commit 196dd7b6ceSThomas Zimmermann * functions for drivers that use GEM objects. Currently, it provides 20820c1707SThomas Zimmermann * synchronization helpers, and plane state and framebuffer BO mappings 21820c1707SThomas Zimmermann * for planes with shadow buffers. 22820c1707SThomas Zimmermann * 23820c1707SThomas Zimmermann * Before scanout, a plane's framebuffer needs to be synchronized with 24820c1707SThomas Zimmermann * possible writers that draw into the framebuffer. All drivers should 25820c1707SThomas Zimmermann * call drm_gem_plane_helper_prepare_fb() from their implementation of 26820c1707SThomas Zimmermann * struct &drm_plane_helper.prepare_fb . It sets the plane's fence from 27820c1707SThomas Zimmermann * the framebuffer so that the DRM core can synchronize access automatically. 28820c1707SThomas Zimmermann * 29820c1707SThomas Zimmermann * drm_gem_plane_helper_prepare_fb() can also be used directly as 30820c1707SThomas Zimmermann * implementation of prepare_fb. For drivers based on 31820c1707SThomas Zimmermann * struct drm_simple_display_pipe, drm_gem_simple_display_pipe_prepare_fb() 32820c1707SThomas Zimmermann * provides equivalent functionality. 33820c1707SThomas Zimmermann * 34820c1707SThomas Zimmermann * .. code-block:: c 35820c1707SThomas Zimmermann * 36820c1707SThomas Zimmermann * #include <drm/drm_gem_atomic_helper.h> 37820c1707SThomas Zimmermann * 38820c1707SThomas Zimmermann * struct drm_plane_helper_funcs driver_plane_helper_funcs = { 39820c1707SThomas Zimmermann * ..., 40820c1707SThomas Zimmermann * . prepare_fb = drm_gem_plane_helper_prepare_fb, 41820c1707SThomas Zimmermann * }; 42820c1707SThomas Zimmermann * 43820c1707SThomas Zimmermann * struct drm_simple_display_pipe_funcs driver_pipe_funcs = { 44820c1707SThomas Zimmermann * ..., 45820c1707SThomas Zimmermann * . prepare_fb = drm_gem_simple_display_pipe_prepare_fb, 46820c1707SThomas Zimmermann * }; 479dc9067dSThomas Zimmermann * 489dc9067dSThomas Zimmermann * A driver using a shadow buffer copies the content of the shadow buffers 499dc9067dSThomas Zimmermann * into the HW's framebuffer memory during an atomic update. This requires 509dc9067dSThomas Zimmermann * a mapping of the shadow buffer into kernel address space. The mappings 519dc9067dSThomas Zimmermann * cannot be established by commit-tail functions, such as atomic_update, 529dc9067dSThomas Zimmermann * as this would violate locking rules around dma_buf_vmap(). 539dc9067dSThomas Zimmermann * 549dc9067dSThomas Zimmermann * The helpers for shadow-buffered planes establish and release mappings, 559dc9067dSThomas Zimmermann * and provide struct drm_shadow_plane_state, which stores the plane's mapping 560ae865efSCai Huoqing * for commit-tail functions. 579dc9067dSThomas Zimmermann * 589dc9067dSThomas Zimmermann * Shadow-buffered planes can easily be enabled by using the provided macros 599dc9067dSThomas Zimmermann * %DRM_GEM_SHADOW_PLANE_FUNCS and %DRM_GEM_SHADOW_PLANE_HELPER_FUNCS. 609dc9067dSThomas Zimmermann * These macros set up the plane and plane-helper callbacks to point to the 619dc9067dSThomas Zimmermann * shadow-buffer helpers. 629dc9067dSThomas Zimmermann * 639dc9067dSThomas Zimmermann * .. code-block:: c 649dc9067dSThomas Zimmermann * 65820c1707SThomas Zimmermann * #include <drm/drm_gem_atomic_helper.h> 669dc9067dSThomas Zimmermann * 679dc9067dSThomas Zimmermann * struct drm_plane_funcs driver_plane_funcs = { 689dc9067dSThomas Zimmermann * ..., 699dc9067dSThomas Zimmermann * DRM_GEM_SHADOW_PLANE_FUNCS, 709dc9067dSThomas Zimmermann * }; 719dc9067dSThomas Zimmermann * 729dc9067dSThomas Zimmermann * struct drm_plane_helper_funcs driver_plane_helper_funcs = { 739dc9067dSThomas Zimmermann * ..., 749dc9067dSThomas Zimmermann * DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, 759dc9067dSThomas Zimmermann * }; 769dc9067dSThomas Zimmermann * 779dc9067dSThomas Zimmermann * In the driver's atomic-update function, shadow-buffer mappings are available 789dc9067dSThomas Zimmermann * from the plane state. Use to_drm_shadow_plane_state() to upcast from 799dc9067dSThomas Zimmermann * struct drm_plane_state. 809dc9067dSThomas Zimmermann * 819dc9067dSThomas Zimmermann * .. code-block:: c 829dc9067dSThomas Zimmermann * 839dc9067dSThomas Zimmermann * void driver_plane_atomic_update(struct drm_plane *plane, 849dc9067dSThomas Zimmermann * struct drm_plane_state *old_plane_state) 859dc9067dSThomas Zimmermann * { 869dc9067dSThomas Zimmermann * struct drm_plane_state *plane_state = plane->state; 879dc9067dSThomas Zimmermann * struct drm_shadow_plane_state *shadow_plane_state = 889dc9067dSThomas Zimmermann * to_drm_shadow_plane_state(plane_state); 899dc9067dSThomas Zimmermann * 909dc9067dSThomas Zimmermann * // access shadow buffer via shadow_plane_state->map 919dc9067dSThomas Zimmermann * } 929dc9067dSThomas Zimmermann * 939dc9067dSThomas Zimmermann * A mapping address for each of the framebuffer's buffer object is stored in 949dc9067dSThomas Zimmermann * struct &drm_shadow_plane_state.map. The mappings are valid while the state 959dc9067dSThomas Zimmermann * is being used. 969dc9067dSThomas Zimmermann * 979dc9067dSThomas Zimmermann * Drivers that use struct drm_simple_display_pipe can use 989dc9067dSThomas Zimmermann * %DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS to initialize the rsp 999dc9067dSThomas Zimmermann * callbacks. Access to shadow-buffer mappings is similar to regular 1009dc9067dSThomas Zimmermann * atomic_update. 1019dc9067dSThomas Zimmermann * 1029dc9067dSThomas Zimmermann * .. code-block:: c 1039dc9067dSThomas Zimmermann * 1049dc9067dSThomas Zimmermann * struct drm_simple_display_pipe_funcs driver_pipe_funcs = { 1059dc9067dSThomas Zimmermann * ..., 1069dc9067dSThomas Zimmermann * DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS, 1079dc9067dSThomas Zimmermann * }; 1089dc9067dSThomas Zimmermann * 1099dc9067dSThomas Zimmermann * void driver_pipe_enable(struct drm_simple_display_pipe *pipe, 1109dc9067dSThomas Zimmermann * struct drm_crtc_state *crtc_state, 1119dc9067dSThomas Zimmermann * struct drm_plane_state *plane_state) 1129dc9067dSThomas Zimmermann * { 1139dc9067dSThomas Zimmermann * struct drm_shadow_plane_state *shadow_plane_state = 1149dc9067dSThomas Zimmermann * to_drm_shadow_plane_state(plane_state); 1159dc9067dSThomas Zimmermann * 1169dc9067dSThomas Zimmermann * // access shadow buffer via shadow_plane_state->map 1179dc9067dSThomas Zimmermann * } 1186dd7b6ceSThomas Zimmermann */ 1196dd7b6ceSThomas Zimmermann 1206dd7b6ceSThomas Zimmermann /* 121820c1707SThomas Zimmermann * Plane Helpers 122820c1707SThomas Zimmermann */ 123820c1707SThomas Zimmermann 124820c1707SThomas Zimmermann /** 125820c1707SThomas Zimmermann * drm_gem_plane_helper_prepare_fb() - Prepare a GEM backed framebuffer 126820c1707SThomas Zimmermann * @plane: Plane 127820c1707SThomas Zimmermann * @state: Plane state the fence will be attached to 128820c1707SThomas Zimmermann * 129820c1707SThomas Zimmermann * This function extracts the exclusive fence from &drm_gem_object.resv and 130820c1707SThomas Zimmermann * attaches it to plane state for the atomic helper to wait on. This is 131820c1707SThomas Zimmermann * necessary to correctly implement implicit synchronization for any buffers 132820c1707SThomas Zimmermann * shared as a struct &dma_buf. This function can be used as the 133820c1707SThomas Zimmermann * &drm_plane_helper_funcs.prepare_fb callback. 134820c1707SThomas Zimmermann * 135820c1707SThomas Zimmermann * There is no need for &drm_plane_helper_funcs.cleanup_fb hook for simple 136820c1707SThomas Zimmermann * GEM based framebuffer drivers which have their buffers always pinned in 137820c1707SThomas Zimmermann * memory. 138820c1707SThomas Zimmermann * 1397d30963fSDaniel Vetter * This function is the default implementation for GEM drivers of 1407d30963fSDaniel Vetter * &drm_plane_helper_funcs.prepare_fb if no callback is provided. 141820c1707SThomas Zimmermann */ 142*1ea28bc5SChristian König int drm_gem_plane_helper_prepare_fb(struct drm_plane *plane, 143*1ea28bc5SChristian König struct drm_plane_state *state) 144820c1707SThomas Zimmermann { 145*1ea28bc5SChristian König struct dma_fence *fence = dma_fence_get(state->fence); 146*1ea28bc5SChristian König enum dma_resv_usage usage; 147*1ea28bc5SChristian König size_t i; 148c382df71SChristian König int ret; 149820c1707SThomas Zimmermann 150820c1707SThomas Zimmermann if (!state->fb) 151820c1707SThomas Zimmermann return 0; 152820c1707SThomas Zimmermann 153*1ea28bc5SChristian König /* 154*1ea28bc5SChristian König * Only add the kernel fences here if there is already a fence set via 155*1ea28bc5SChristian König * explicit fencing interfaces on the atomic ioctl. 156*1ea28bc5SChristian König * 157*1ea28bc5SChristian König * This way explicit fencing can be used to overrule implicit fencing, 158*1ea28bc5SChristian König * which is important to make explicit fencing use-cases work: One 159*1ea28bc5SChristian König * example is using one buffer for 2 screens with different refresh 160*1ea28bc5SChristian König * rates. Implicit fencing will clamp rendering to the refresh rate of 161*1ea28bc5SChristian König * the slower screen, whereas explicit fence allows 2 independent 162*1ea28bc5SChristian König * render and display loops on a single buffer. If a driver allows 163*1ea28bc5SChristian König * obeys both implicit and explicit fences for plane updates, then it 164*1ea28bc5SChristian König * will break all the benefits of explicit fencing. 165c382df71SChristian König */ 166*1ea28bc5SChristian König usage = fence ? DMA_RESV_USAGE_KERNEL : DMA_RESV_USAGE_WRITE; 167*1ea28bc5SChristian König 168*1ea28bc5SChristian König for (i = 0; i < state->fb->format->num_planes; ++i) { 169*1ea28bc5SChristian König struct drm_gem_object *obj = drm_gem_fb_get_obj(state->fb, i); 170*1ea28bc5SChristian König struct dma_fence *new; 171*1ea28bc5SChristian König 172*1ea28bc5SChristian König if (WARN_ON_ONCE(!obj)) 173*1ea28bc5SChristian König continue; 174*1ea28bc5SChristian König 175*1ea28bc5SChristian König ret = dma_resv_get_singleton(obj->resv, usage, &new); 176*1ea28bc5SChristian König if (ret) 177*1ea28bc5SChristian König goto error; 178*1ea28bc5SChristian König 179*1ea28bc5SChristian König if (new && fence) { 180*1ea28bc5SChristian König struct dma_fence_chain *chain = dma_fence_chain_alloc(); 181*1ea28bc5SChristian König 182*1ea28bc5SChristian König if (!chain) { 183*1ea28bc5SChristian König ret = -ENOMEM; 184*1ea28bc5SChristian König goto error; 185*1ea28bc5SChristian König } 186*1ea28bc5SChristian König 187*1ea28bc5SChristian König dma_fence_chain_init(chain, fence, new, 1); 188*1ea28bc5SChristian König fence = &chain->base; 189*1ea28bc5SChristian König 190*1ea28bc5SChristian König } else if (new) { 191*1ea28bc5SChristian König fence = new; 192*1ea28bc5SChristian König } 193*1ea28bc5SChristian König } 194*1ea28bc5SChristian König 195*1ea28bc5SChristian König dma_fence_put(state->fence); 196*1ea28bc5SChristian König state->fence = fence; 197820c1707SThomas Zimmermann return 0; 198*1ea28bc5SChristian König 199*1ea28bc5SChristian König error: 200*1ea28bc5SChristian König dma_fence_put(fence); 201*1ea28bc5SChristian König return ret; 202820c1707SThomas Zimmermann } 203820c1707SThomas Zimmermann EXPORT_SYMBOL_GPL(drm_gem_plane_helper_prepare_fb); 204820c1707SThomas Zimmermann 205820c1707SThomas Zimmermann /** 206820c1707SThomas Zimmermann * drm_gem_simple_display_pipe_prepare_fb - prepare_fb helper for &drm_simple_display_pipe 207820c1707SThomas Zimmermann * @pipe: Simple display pipe 208820c1707SThomas Zimmermann * @plane_state: Plane state 209820c1707SThomas Zimmermann * 210*1ea28bc5SChristian König * This function uses drm_gem_plane_helper_prepare_fb() to extract the fences 211*1ea28bc5SChristian König * from &drm_gem_object.resv and attaches them to the plane state for the atomic 212820c1707SThomas Zimmermann * helper to wait on. This is necessary to correctly implement implicit 213820c1707SThomas Zimmermann * synchronization for any buffers shared as a struct &dma_buf. Drivers can use 214820c1707SThomas Zimmermann * this as their &drm_simple_display_pipe_funcs.prepare_fb callback. 215820c1707SThomas Zimmermann * 216*1ea28bc5SChristian König * See drm_gem_plane_helper_prepare_fb() for a discussion of implicit and 217820c1707SThomas Zimmermann * explicit fencing in atomic modeset updates. 218820c1707SThomas Zimmermann */ 219820c1707SThomas Zimmermann int drm_gem_simple_display_pipe_prepare_fb(struct drm_simple_display_pipe *pipe, 220820c1707SThomas Zimmermann struct drm_plane_state *plane_state) 221820c1707SThomas Zimmermann { 222820c1707SThomas Zimmermann return drm_gem_plane_helper_prepare_fb(&pipe->plane, plane_state); 223820c1707SThomas Zimmermann } 224820c1707SThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_display_pipe_prepare_fb); 225820c1707SThomas Zimmermann 226820c1707SThomas Zimmermann /* 2276dd7b6ceSThomas Zimmermann * Shadow-buffered Planes 2286dd7b6ceSThomas Zimmermann */ 2296dd7b6ceSThomas Zimmermann 2309dc9067dSThomas Zimmermann /** 231b7156502SThomas Zimmermann * __drm_gem_duplicate_shadow_plane_state - duplicates shadow-buffered plane state 232b7156502SThomas Zimmermann * @plane: the plane 233b7156502SThomas Zimmermann * @new_shadow_plane_state: the new shadow-buffered plane state 234b7156502SThomas Zimmermann * 235b7156502SThomas Zimmermann * This function duplicates shadow-buffered plane state. This is helpful for drivers 236b7156502SThomas Zimmermann * that subclass struct drm_shadow_plane_state. 237b7156502SThomas Zimmermann * 238b7156502SThomas Zimmermann * The function does not duplicate existing mappings of the shadow buffers. 239b7156502SThomas Zimmermann * Mappings are maintained during the atomic commit by the plane's prepare_fb 240b7156502SThomas Zimmermann * and cleanup_fb helpers. See drm_gem_prepare_shadow_fb() and drm_gem_cleanup_shadow_fb() 241b7156502SThomas Zimmermann * for corresponding helpers. 242b7156502SThomas Zimmermann */ 243b7156502SThomas Zimmermann void 244b7156502SThomas Zimmermann __drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane, 245b7156502SThomas Zimmermann struct drm_shadow_plane_state *new_shadow_plane_state) 246b7156502SThomas Zimmermann { 247b7156502SThomas Zimmermann __drm_atomic_helper_plane_duplicate_state(plane, &new_shadow_plane_state->base); 248b7156502SThomas Zimmermann } 249b7156502SThomas Zimmermann EXPORT_SYMBOL(__drm_gem_duplicate_shadow_plane_state); 250b7156502SThomas Zimmermann 251b7156502SThomas Zimmermann /** 2529dc9067dSThomas Zimmermann * drm_gem_duplicate_shadow_plane_state - duplicates shadow-buffered plane state 2539dc9067dSThomas Zimmermann * @plane: the plane 2549dc9067dSThomas Zimmermann * 2559dc9067dSThomas Zimmermann * This function implements struct &drm_plane_funcs.atomic_duplicate_state for 2569dc9067dSThomas Zimmermann * shadow-buffered planes. It assumes the existing state to be of type 2579dc9067dSThomas Zimmermann * struct drm_shadow_plane_state and it allocates the new state to be of this 2589dc9067dSThomas Zimmermann * type. 2599dc9067dSThomas Zimmermann * 2609dc9067dSThomas Zimmermann * The function does not duplicate existing mappings of the shadow buffers. 2619dc9067dSThomas Zimmermann * Mappings are maintained during the atomic commit by the plane's prepare_fb 2629dc9067dSThomas Zimmermann * and cleanup_fb helpers. See drm_gem_prepare_shadow_fb() and drm_gem_cleanup_shadow_fb() 2639dc9067dSThomas Zimmermann * for corresponding helpers. 2649dc9067dSThomas Zimmermann * 2659dc9067dSThomas Zimmermann * Returns: 2669dc9067dSThomas Zimmermann * A pointer to a new plane state on success, or NULL otherwise. 2679dc9067dSThomas Zimmermann */ 2689dc9067dSThomas Zimmermann struct drm_plane_state * 2696dd7b6ceSThomas Zimmermann drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane) 2706dd7b6ceSThomas Zimmermann { 2716dd7b6ceSThomas Zimmermann struct drm_plane_state *plane_state = plane->state; 2726dd7b6ceSThomas Zimmermann struct drm_shadow_plane_state *new_shadow_plane_state; 2736dd7b6ceSThomas Zimmermann 2746dd7b6ceSThomas Zimmermann if (!plane_state) 2756dd7b6ceSThomas Zimmermann return NULL; 2766dd7b6ceSThomas Zimmermann 2776dd7b6ceSThomas Zimmermann new_shadow_plane_state = kzalloc(sizeof(*new_shadow_plane_state), GFP_KERNEL); 2786dd7b6ceSThomas Zimmermann if (!new_shadow_plane_state) 2796dd7b6ceSThomas Zimmermann return NULL; 280b7156502SThomas Zimmermann __drm_gem_duplicate_shadow_plane_state(plane, new_shadow_plane_state); 2816dd7b6ceSThomas Zimmermann 2826dd7b6ceSThomas Zimmermann return &new_shadow_plane_state->base; 2836dd7b6ceSThomas Zimmermann } 2849dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_duplicate_shadow_plane_state); 2856dd7b6ceSThomas Zimmermann 2869dc9067dSThomas Zimmermann /** 287b7156502SThomas Zimmermann * __drm_gem_destroy_shadow_plane_state - cleans up shadow-buffered plane state 288b7156502SThomas Zimmermann * @shadow_plane_state: the shadow-buffered plane state 289b7156502SThomas Zimmermann * 290b7156502SThomas Zimmermann * This function cleans up shadow-buffered plane state. Helpful for drivers that 291b7156502SThomas Zimmermann * subclass struct drm_shadow_plane_state. 292b7156502SThomas Zimmermann */ 293b7156502SThomas Zimmermann void __drm_gem_destroy_shadow_plane_state(struct drm_shadow_plane_state *shadow_plane_state) 294b7156502SThomas Zimmermann { 295b7156502SThomas Zimmermann __drm_atomic_helper_plane_destroy_state(&shadow_plane_state->base); 296b7156502SThomas Zimmermann } 297b7156502SThomas Zimmermann EXPORT_SYMBOL(__drm_gem_destroy_shadow_plane_state); 298b7156502SThomas Zimmermann 299b7156502SThomas Zimmermann /** 3009dc9067dSThomas Zimmermann * drm_gem_destroy_shadow_plane_state - deletes shadow-buffered plane state 3019dc9067dSThomas Zimmermann * @plane: the plane 3029dc9067dSThomas Zimmermann * @plane_state: the plane state of type struct drm_shadow_plane_state 3039dc9067dSThomas Zimmermann * 3049dc9067dSThomas Zimmermann * This function implements struct &drm_plane_funcs.atomic_destroy_state 3059dc9067dSThomas Zimmermann * for shadow-buffered planes. It expects that mappings of shadow buffers 3069dc9067dSThomas Zimmermann * have been released already. 3079dc9067dSThomas Zimmermann */ 3089dc9067dSThomas Zimmermann void drm_gem_destroy_shadow_plane_state(struct drm_plane *plane, 3096dd7b6ceSThomas Zimmermann struct drm_plane_state *plane_state) 3106dd7b6ceSThomas Zimmermann { 3116dd7b6ceSThomas Zimmermann struct drm_shadow_plane_state *shadow_plane_state = 3126dd7b6ceSThomas Zimmermann to_drm_shadow_plane_state(plane_state); 3136dd7b6ceSThomas Zimmermann 314b7156502SThomas Zimmermann __drm_gem_destroy_shadow_plane_state(shadow_plane_state); 3156dd7b6ceSThomas Zimmermann kfree(shadow_plane_state); 3166dd7b6ceSThomas Zimmermann } 3179dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_destroy_shadow_plane_state); 3186dd7b6ceSThomas Zimmermann 3199dc9067dSThomas Zimmermann /** 320b7156502SThomas Zimmermann * __drm_gem_reset_shadow_plane - resets a shadow-buffered plane 321b7156502SThomas Zimmermann * @plane: the plane 322b7156502SThomas Zimmermann * @shadow_plane_state: the shadow-buffered plane state 323b7156502SThomas Zimmermann * 324b7156502SThomas Zimmermann * This function resets state for shadow-buffered planes. Helpful 325b7156502SThomas Zimmermann * for drivers that subclass struct drm_shadow_plane_state. 326b7156502SThomas Zimmermann */ 327b7156502SThomas Zimmermann void __drm_gem_reset_shadow_plane(struct drm_plane *plane, 328b7156502SThomas Zimmermann struct drm_shadow_plane_state *shadow_plane_state) 329b7156502SThomas Zimmermann { 330b7156502SThomas Zimmermann __drm_atomic_helper_plane_reset(plane, &shadow_plane_state->base); 331b7156502SThomas Zimmermann } 332b7156502SThomas Zimmermann EXPORT_SYMBOL(__drm_gem_reset_shadow_plane); 333b7156502SThomas Zimmermann 334b7156502SThomas Zimmermann /** 3359dc9067dSThomas Zimmermann * drm_gem_reset_shadow_plane - resets a shadow-buffered plane 3369dc9067dSThomas Zimmermann * @plane: the plane 3379dc9067dSThomas Zimmermann * 3389dc9067dSThomas Zimmermann * This function implements struct &drm_plane_funcs.reset_plane for 3399dc9067dSThomas Zimmermann * shadow-buffered planes. It assumes the current plane state to be 3409dc9067dSThomas Zimmermann * of type struct drm_shadow_plane and it allocates the new state of 3419dc9067dSThomas Zimmermann * this type. 3429dc9067dSThomas Zimmermann */ 3439dc9067dSThomas Zimmermann void drm_gem_reset_shadow_plane(struct drm_plane *plane) 3446dd7b6ceSThomas Zimmermann { 3456dd7b6ceSThomas Zimmermann struct drm_shadow_plane_state *shadow_plane_state; 3466dd7b6ceSThomas Zimmermann 3476dd7b6ceSThomas Zimmermann if (plane->state) { 3486dd7b6ceSThomas Zimmermann drm_gem_destroy_shadow_plane_state(plane, plane->state); 3496dd7b6ceSThomas Zimmermann plane->state = NULL; /* must be set to NULL here */ 3506dd7b6ceSThomas Zimmermann } 3516dd7b6ceSThomas Zimmermann 3526dd7b6ceSThomas Zimmermann shadow_plane_state = kzalloc(sizeof(*shadow_plane_state), GFP_KERNEL); 3536dd7b6ceSThomas Zimmermann if (!shadow_plane_state) 3546dd7b6ceSThomas Zimmermann return; 355b7156502SThomas Zimmermann __drm_gem_reset_shadow_plane(plane, shadow_plane_state); 3566dd7b6ceSThomas Zimmermann } 3579dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_reset_shadow_plane); 3586dd7b6ceSThomas Zimmermann 3599dc9067dSThomas Zimmermann /** 3609dc9067dSThomas Zimmermann * drm_gem_prepare_shadow_fb - prepares shadow framebuffers 3619dc9067dSThomas Zimmermann * @plane: the plane 3629dc9067dSThomas Zimmermann * @plane_state: the plane state of type struct drm_shadow_plane_state 3639dc9067dSThomas Zimmermann * 3649dc9067dSThomas Zimmermann * This function implements struct &drm_plane_helper_funcs.prepare_fb. It 3659dc9067dSThomas Zimmermann * maps all buffer objects of the plane's framebuffer into kernel address 3669dc9067dSThomas Zimmermann * space and stores them in &struct drm_shadow_plane_state.map. The 3679dc9067dSThomas Zimmermann * framebuffer will be synchronized as part of the atomic commit. 3689dc9067dSThomas Zimmermann * 3699dc9067dSThomas Zimmermann * See drm_gem_cleanup_shadow_fb() for cleanup. 3709dc9067dSThomas Zimmermann * 3719dc9067dSThomas Zimmermann * Returns: 3729dc9067dSThomas Zimmermann * 0 on success, or a negative errno code otherwise. 3739dc9067dSThomas Zimmermann */ 3749dc9067dSThomas Zimmermann int drm_gem_prepare_shadow_fb(struct drm_plane *plane, struct drm_plane_state *plane_state) 3756dd7b6ceSThomas Zimmermann { 3766dd7b6ceSThomas Zimmermann struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); 3776dd7b6ceSThomas Zimmermann struct drm_framebuffer *fb = plane_state->fb; 3786dd7b6ceSThomas Zimmermann int ret; 3796dd7b6ceSThomas Zimmermann 3806dd7b6ceSThomas Zimmermann if (!fb) 3816dd7b6ceSThomas Zimmermann return 0; 3826dd7b6ceSThomas Zimmermann 383820c1707SThomas Zimmermann ret = drm_gem_plane_helper_prepare_fb(plane, plane_state); 3846dd7b6ceSThomas Zimmermann if (ret) 3856dd7b6ceSThomas Zimmermann return ret; 3866dd7b6ceSThomas Zimmermann 38743b36232SThomas Zimmermann return drm_gem_fb_vmap(fb, shadow_plane_state->map, shadow_plane_state->data); 3886dd7b6ceSThomas Zimmermann } 3899dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_prepare_shadow_fb); 3906dd7b6ceSThomas Zimmermann 3919dc9067dSThomas Zimmermann /** 3929dc9067dSThomas Zimmermann * drm_gem_cleanup_shadow_fb - releases shadow framebuffers 3939dc9067dSThomas Zimmermann * @plane: the plane 3949dc9067dSThomas Zimmermann * @plane_state: the plane state of type struct drm_shadow_plane_state 3959dc9067dSThomas Zimmermann * 3969dc9067dSThomas Zimmermann * This function implements struct &drm_plane_helper_funcs.cleanup_fb. 3979dc9067dSThomas Zimmermann * This function unmaps all buffer objects of the plane's framebuffer. 3989dc9067dSThomas Zimmermann * 3990ae865efSCai Huoqing * See drm_gem_prepare_shadow_fb() for more information. 4009dc9067dSThomas Zimmermann */ 4019dc9067dSThomas Zimmermann void drm_gem_cleanup_shadow_fb(struct drm_plane *plane, struct drm_plane_state *plane_state) 4026dd7b6ceSThomas Zimmermann { 4036dd7b6ceSThomas Zimmermann struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); 4046dd7b6ceSThomas Zimmermann struct drm_framebuffer *fb = plane_state->fb; 4056dd7b6ceSThomas Zimmermann 4066dd7b6ceSThomas Zimmermann if (!fb) 4076dd7b6ceSThomas Zimmermann return; 4086dd7b6ceSThomas Zimmermann 409f6424ecdSThomas Zimmermann drm_gem_fb_vunmap(fb, shadow_plane_state->map); 4106dd7b6ceSThomas Zimmermann } 4119dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_cleanup_shadow_fb); 4126dd7b6ceSThomas Zimmermann 4136dd7b6ceSThomas Zimmermann /** 4146dd7b6ceSThomas Zimmermann * drm_gem_simple_kms_prepare_shadow_fb - prepares shadow framebuffers 4156dd7b6ceSThomas Zimmermann * @pipe: the simple display pipe 4166dd7b6ceSThomas Zimmermann * @plane_state: the plane state of type struct drm_shadow_plane_state 4176dd7b6ceSThomas Zimmermann * 4186dd7b6ceSThomas Zimmermann * This function implements struct drm_simple_display_funcs.prepare_fb. It 4196dd7b6ceSThomas Zimmermann * maps all buffer objects of the plane's framebuffer into kernel address 4206dd7b6ceSThomas Zimmermann * space and stores them in struct drm_shadow_plane_state.map. The 4216dd7b6ceSThomas Zimmermann * framebuffer will be synchronized as part of the atomic commit. 4226dd7b6ceSThomas Zimmermann * 4236dd7b6ceSThomas Zimmermann * See drm_gem_simple_kms_cleanup_shadow_fb() for cleanup. 4246dd7b6ceSThomas Zimmermann * 4256dd7b6ceSThomas Zimmermann * Returns: 4266dd7b6ceSThomas Zimmermann * 0 on success, or a negative errno code otherwise. 4276dd7b6ceSThomas Zimmermann */ 4286dd7b6ceSThomas Zimmermann int drm_gem_simple_kms_prepare_shadow_fb(struct drm_simple_display_pipe *pipe, 4296dd7b6ceSThomas Zimmermann struct drm_plane_state *plane_state) 4306dd7b6ceSThomas Zimmermann { 4316dd7b6ceSThomas Zimmermann return drm_gem_prepare_shadow_fb(&pipe->plane, plane_state); 4326dd7b6ceSThomas Zimmermann } 4336dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_prepare_shadow_fb); 4346dd7b6ceSThomas Zimmermann 4356dd7b6ceSThomas Zimmermann /** 4366dd7b6ceSThomas Zimmermann * drm_gem_simple_kms_cleanup_shadow_fb - releases shadow framebuffers 4376dd7b6ceSThomas Zimmermann * @pipe: the simple display pipe 4386dd7b6ceSThomas Zimmermann * @plane_state: the plane state of type struct drm_shadow_plane_state 4396dd7b6ceSThomas Zimmermann * 4406dd7b6ceSThomas Zimmermann * This function implements struct drm_simple_display_funcs.cleanup_fb. 4416dd7b6ceSThomas Zimmermann * This function unmaps all buffer objects of the plane's framebuffer. 4426dd7b6ceSThomas Zimmermann * 4436dd7b6ceSThomas Zimmermann * See drm_gem_simple_kms_prepare_shadow_fb(). 4446dd7b6ceSThomas Zimmermann */ 4456dd7b6ceSThomas Zimmermann void drm_gem_simple_kms_cleanup_shadow_fb(struct drm_simple_display_pipe *pipe, 4466dd7b6ceSThomas Zimmermann struct drm_plane_state *plane_state) 4476dd7b6ceSThomas Zimmermann { 4486dd7b6ceSThomas Zimmermann drm_gem_cleanup_shadow_fb(&pipe->plane, plane_state); 4496dd7b6ceSThomas Zimmermann } 4506dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_cleanup_shadow_fb); 4516dd7b6ceSThomas Zimmermann 4526dd7b6ceSThomas Zimmermann /** 4536dd7b6ceSThomas Zimmermann * drm_gem_simple_kms_reset_shadow_plane - resets a shadow-buffered plane 4546dd7b6ceSThomas Zimmermann * @pipe: the simple display pipe 4556dd7b6ceSThomas Zimmermann * 4566dd7b6ceSThomas Zimmermann * This function implements struct drm_simple_display_funcs.reset_plane 4576dd7b6ceSThomas Zimmermann * for shadow-buffered planes. 4586dd7b6ceSThomas Zimmermann */ 4596dd7b6ceSThomas Zimmermann void drm_gem_simple_kms_reset_shadow_plane(struct drm_simple_display_pipe *pipe) 4606dd7b6ceSThomas Zimmermann { 4616dd7b6ceSThomas Zimmermann drm_gem_reset_shadow_plane(&pipe->plane); 4626dd7b6ceSThomas Zimmermann } 4636dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_reset_shadow_plane); 4646dd7b6ceSThomas Zimmermann 4656dd7b6ceSThomas Zimmermann /** 4666dd7b6ceSThomas Zimmermann * drm_gem_simple_kms_duplicate_shadow_plane_state - duplicates shadow-buffered plane state 4676dd7b6ceSThomas Zimmermann * @pipe: the simple display pipe 4686dd7b6ceSThomas Zimmermann * 4696dd7b6ceSThomas Zimmermann * This function implements struct drm_simple_display_funcs.duplicate_plane_state 4706dd7b6ceSThomas Zimmermann * for shadow-buffered planes. It does not duplicate existing mappings of the shadow 4716dd7b6ceSThomas Zimmermann * buffers. Mappings are maintained during the atomic commit by the plane's prepare_fb 4726dd7b6ceSThomas Zimmermann * and cleanup_fb helpers. 4736dd7b6ceSThomas Zimmermann * 4746dd7b6ceSThomas Zimmermann * Returns: 4756dd7b6ceSThomas Zimmermann * A pointer to a new plane state on success, or NULL otherwise. 4766dd7b6ceSThomas Zimmermann */ 4776dd7b6ceSThomas Zimmermann struct drm_plane_state * 4786dd7b6ceSThomas Zimmermann drm_gem_simple_kms_duplicate_shadow_plane_state(struct drm_simple_display_pipe *pipe) 4796dd7b6ceSThomas Zimmermann { 4806dd7b6ceSThomas Zimmermann return drm_gem_duplicate_shadow_plane_state(&pipe->plane); 4816dd7b6ceSThomas Zimmermann } 4826dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_duplicate_shadow_plane_state); 4836dd7b6ceSThomas Zimmermann 4846dd7b6ceSThomas Zimmermann /** 4856dd7b6ceSThomas Zimmermann * drm_gem_simple_kms_destroy_shadow_plane_state - resets shadow-buffered plane state 4866dd7b6ceSThomas Zimmermann * @pipe: the simple display pipe 4876dd7b6ceSThomas Zimmermann * @plane_state: the plane state of type struct drm_shadow_plane_state 4886dd7b6ceSThomas Zimmermann * 4896dd7b6ceSThomas Zimmermann * This function implements struct drm_simple_display_funcs.destroy_plane_state 4906dd7b6ceSThomas Zimmermann * for shadow-buffered planes. It expects that mappings of shadow buffers 4916dd7b6ceSThomas Zimmermann * have been released already. 4926dd7b6ceSThomas Zimmermann */ 4936dd7b6ceSThomas Zimmermann void drm_gem_simple_kms_destroy_shadow_plane_state(struct drm_simple_display_pipe *pipe, 4946dd7b6ceSThomas Zimmermann struct drm_plane_state *plane_state) 4956dd7b6ceSThomas Zimmermann { 4966dd7b6ceSThomas Zimmermann drm_gem_destroy_shadow_plane_state(&pipe->plane, plane_state); 4976dd7b6ceSThomas Zimmermann } 4986dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_destroy_shadow_plane_state); 499