16dd7b6ceSThomas Zimmermann // SPDX-License-Identifier: GPL-2.0-or-later 26dd7b6ceSThomas Zimmermann 3820c1707SThomas Zimmermann #include <linux/dma-resv.h> 41ea28bc5SChristian 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> 8720cf96dSVille Syrjälä #include <drm/drm_framebuffer.h> 9820c1707SThomas Zimmermann #include <drm/drm_gem.h> 106dd7b6ceSThomas Zimmermann #include <drm/drm_gem_atomic_helper.h> 116dd7b6ceSThomas Zimmermann #include <drm/drm_gem_framebuffer_helper.h> 126dd7b6ceSThomas Zimmermann #include <drm/drm_simple_kms_helper.h> 136dd7b6ceSThomas Zimmermann 146dd7b6ceSThomas Zimmermann #include "drm_internal.h" 156dd7b6ceSThomas Zimmermann 166dd7b6ceSThomas Zimmermann /** 176dd7b6ceSThomas Zimmermann * DOC: overview 186dd7b6ceSThomas Zimmermann * 196dd7b6ceSThomas Zimmermann * The GEM atomic helpers library implements generic atomic-commit 206dd7b6ceSThomas Zimmermann * functions for drivers that use GEM objects. Currently, it provides 21820c1707SThomas Zimmermann * synchronization helpers, and plane state and framebuffer BO mappings 22820c1707SThomas Zimmermann * for planes with shadow buffers. 23820c1707SThomas Zimmermann * 24820c1707SThomas Zimmermann * Before scanout, a plane's framebuffer needs to be synchronized with 25820c1707SThomas Zimmermann * possible writers that draw into the framebuffer. All drivers should 26820c1707SThomas Zimmermann * call drm_gem_plane_helper_prepare_fb() from their implementation of 27820c1707SThomas Zimmermann * struct &drm_plane_helper.prepare_fb . It sets the plane's fence from 28820c1707SThomas Zimmermann * the framebuffer so that the DRM core can synchronize access automatically. 29820c1707SThomas Zimmermann * drm_gem_plane_helper_prepare_fb() can also be used directly as 30*00b5497dSThomas Zimmermann * implementation of prepare_fb. 31820c1707SThomas Zimmermann * 32820c1707SThomas Zimmermann * .. code-block:: c 33820c1707SThomas Zimmermann * 34820c1707SThomas Zimmermann * #include <drm/drm_gem_atomic_helper.h> 35820c1707SThomas Zimmermann * 36820c1707SThomas Zimmermann * struct drm_plane_helper_funcs driver_plane_helper_funcs = { 37820c1707SThomas Zimmermann * ..., 38820c1707SThomas Zimmermann * . prepare_fb = drm_gem_plane_helper_prepare_fb, 39820c1707SThomas Zimmermann * }; 40820c1707SThomas Zimmermann * 419dc9067dSThomas Zimmermann * A driver using a shadow buffer copies the content of the shadow buffers 429dc9067dSThomas Zimmermann * into the HW's framebuffer memory during an atomic update. This requires 439dc9067dSThomas Zimmermann * a mapping of the shadow buffer into kernel address space. The mappings 449dc9067dSThomas Zimmermann * cannot be established by commit-tail functions, such as atomic_update, 459dc9067dSThomas Zimmermann * as this would violate locking rules around dma_buf_vmap(). 469dc9067dSThomas Zimmermann * 479dc9067dSThomas Zimmermann * The helpers for shadow-buffered planes establish and release mappings, 489dc9067dSThomas Zimmermann * and provide struct drm_shadow_plane_state, which stores the plane's mapping 490ae865efSCai Huoqing * for commit-tail functions. 509dc9067dSThomas Zimmermann * 519dc9067dSThomas Zimmermann * Shadow-buffered planes can easily be enabled by using the provided macros 529dc9067dSThomas Zimmermann * %DRM_GEM_SHADOW_PLANE_FUNCS and %DRM_GEM_SHADOW_PLANE_HELPER_FUNCS. 539dc9067dSThomas Zimmermann * These macros set up the plane and plane-helper callbacks to point to the 549dc9067dSThomas Zimmermann * shadow-buffer helpers. 559dc9067dSThomas Zimmermann * 569dc9067dSThomas Zimmermann * .. code-block:: c 579dc9067dSThomas Zimmermann * 58820c1707SThomas Zimmermann * #include <drm/drm_gem_atomic_helper.h> 599dc9067dSThomas Zimmermann * 609dc9067dSThomas Zimmermann * struct drm_plane_funcs driver_plane_funcs = { 619dc9067dSThomas Zimmermann * ..., 629dc9067dSThomas Zimmermann * DRM_GEM_SHADOW_PLANE_FUNCS, 639dc9067dSThomas Zimmermann * }; 649dc9067dSThomas Zimmermann * 659dc9067dSThomas Zimmermann * struct drm_plane_helper_funcs driver_plane_helper_funcs = { 669dc9067dSThomas Zimmermann * ..., 679dc9067dSThomas Zimmermann * DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, 689dc9067dSThomas Zimmermann * }; 699dc9067dSThomas Zimmermann * 709dc9067dSThomas Zimmermann * In the driver's atomic-update function, shadow-buffer mappings are available 719dc9067dSThomas Zimmermann * from the plane state. Use to_drm_shadow_plane_state() to upcast from 729dc9067dSThomas Zimmermann * struct drm_plane_state. 739dc9067dSThomas Zimmermann * 749dc9067dSThomas Zimmermann * .. code-block:: c 759dc9067dSThomas Zimmermann * 769dc9067dSThomas Zimmermann * void driver_plane_atomic_update(struct drm_plane *plane, 779dc9067dSThomas Zimmermann * struct drm_plane_state *old_plane_state) 789dc9067dSThomas Zimmermann * { 799dc9067dSThomas Zimmermann * struct drm_plane_state *plane_state = plane->state; 809dc9067dSThomas Zimmermann * struct drm_shadow_plane_state *shadow_plane_state = 819dc9067dSThomas Zimmermann * to_drm_shadow_plane_state(plane_state); 829dc9067dSThomas Zimmermann * 839dc9067dSThomas Zimmermann * // access shadow buffer via shadow_plane_state->map 849dc9067dSThomas Zimmermann * } 859dc9067dSThomas Zimmermann * 869dc9067dSThomas Zimmermann * A mapping address for each of the framebuffer's buffer object is stored in 879dc9067dSThomas Zimmermann * struct &drm_shadow_plane_state.map. The mappings are valid while the state 889dc9067dSThomas Zimmermann * is being used. 899dc9067dSThomas Zimmermann * 909dc9067dSThomas Zimmermann * Drivers that use struct drm_simple_display_pipe can use 919dc9067dSThomas Zimmermann * %DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS to initialize the rsp 929dc9067dSThomas Zimmermann * callbacks. Access to shadow-buffer mappings is similar to regular 939dc9067dSThomas Zimmermann * atomic_update. 949dc9067dSThomas Zimmermann * 959dc9067dSThomas Zimmermann * .. code-block:: c 969dc9067dSThomas Zimmermann * 979dc9067dSThomas Zimmermann * struct drm_simple_display_pipe_funcs driver_pipe_funcs = { 989dc9067dSThomas Zimmermann * ..., 999dc9067dSThomas Zimmermann * DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS, 1009dc9067dSThomas Zimmermann * }; 1019dc9067dSThomas Zimmermann * 1029dc9067dSThomas Zimmermann * void driver_pipe_enable(struct drm_simple_display_pipe *pipe, 1039dc9067dSThomas Zimmermann * struct drm_crtc_state *crtc_state, 1049dc9067dSThomas Zimmermann * struct drm_plane_state *plane_state) 1059dc9067dSThomas Zimmermann * { 1069dc9067dSThomas Zimmermann * struct drm_shadow_plane_state *shadow_plane_state = 1079dc9067dSThomas Zimmermann * to_drm_shadow_plane_state(plane_state); 1089dc9067dSThomas Zimmermann * 1099dc9067dSThomas Zimmermann * // access shadow buffer via shadow_plane_state->map 1109dc9067dSThomas Zimmermann * } 1116dd7b6ceSThomas Zimmermann */ 1126dd7b6ceSThomas Zimmermann 1136dd7b6ceSThomas Zimmermann /* 114820c1707SThomas Zimmermann * Plane Helpers 115820c1707SThomas Zimmermann */ 116820c1707SThomas Zimmermann 117820c1707SThomas Zimmermann /** 118820c1707SThomas Zimmermann * drm_gem_plane_helper_prepare_fb() - Prepare a GEM backed framebuffer 119820c1707SThomas Zimmermann * @plane: Plane 120820c1707SThomas Zimmermann * @state: Plane state the fence will be attached to 121820c1707SThomas Zimmermann * 122820c1707SThomas Zimmermann * This function extracts the exclusive fence from &drm_gem_object.resv and 123820c1707SThomas Zimmermann * attaches it to plane state for the atomic helper to wait on. This is 124820c1707SThomas Zimmermann * necessary to correctly implement implicit synchronization for any buffers 125820c1707SThomas Zimmermann * shared as a struct &dma_buf. This function can be used as the 126820c1707SThomas Zimmermann * &drm_plane_helper_funcs.prepare_fb callback. 127820c1707SThomas Zimmermann * 128820c1707SThomas Zimmermann * There is no need for &drm_plane_helper_funcs.cleanup_fb hook for simple 129820c1707SThomas Zimmermann * GEM based framebuffer drivers which have their buffers always pinned in 130820c1707SThomas Zimmermann * memory. 131820c1707SThomas Zimmermann * 1327d30963fSDaniel Vetter * This function is the default implementation for GEM drivers of 1337d30963fSDaniel Vetter * &drm_plane_helper_funcs.prepare_fb if no callback is provided. 134820c1707SThomas Zimmermann */ 1351ea28bc5SChristian König int drm_gem_plane_helper_prepare_fb(struct drm_plane *plane, 1361ea28bc5SChristian König struct drm_plane_state *state) 137820c1707SThomas Zimmermann { 1381ea28bc5SChristian König struct dma_fence *fence = dma_fence_get(state->fence); 1391ea28bc5SChristian König enum dma_resv_usage usage; 1401ea28bc5SChristian König size_t i; 141c382df71SChristian König int ret; 142820c1707SThomas Zimmermann 143820c1707SThomas Zimmermann if (!state->fb) 144820c1707SThomas Zimmermann return 0; 145820c1707SThomas Zimmermann 1461ea28bc5SChristian König /* 1471ea28bc5SChristian König * Only add the kernel fences here if there is already a fence set via 1481ea28bc5SChristian König * explicit fencing interfaces on the atomic ioctl. 1491ea28bc5SChristian König * 1501ea28bc5SChristian König * This way explicit fencing can be used to overrule implicit fencing, 1511ea28bc5SChristian König * which is important to make explicit fencing use-cases work: One 1521ea28bc5SChristian König * example is using one buffer for 2 screens with different refresh 1531ea28bc5SChristian König * rates. Implicit fencing will clamp rendering to the refresh rate of 1541ea28bc5SChristian König * the slower screen, whereas explicit fence allows 2 independent 1551ea28bc5SChristian König * render and display loops on a single buffer. If a driver allows 1561ea28bc5SChristian König * obeys both implicit and explicit fences for plane updates, then it 1571ea28bc5SChristian König * will break all the benefits of explicit fencing. 158c382df71SChristian König */ 1591ea28bc5SChristian König usage = fence ? DMA_RESV_USAGE_KERNEL : DMA_RESV_USAGE_WRITE; 1601ea28bc5SChristian König 1611ea28bc5SChristian König for (i = 0; i < state->fb->format->num_planes; ++i) { 1621ea28bc5SChristian König struct drm_gem_object *obj = drm_gem_fb_get_obj(state->fb, i); 1631ea28bc5SChristian König struct dma_fence *new; 1641ea28bc5SChristian König 165746b9c62SThomas Zimmermann if (!obj) { 166746b9c62SThomas Zimmermann ret = -EINVAL; 167746b9c62SThomas Zimmermann goto error; 168746b9c62SThomas Zimmermann } 1691ea28bc5SChristian König 1701ea28bc5SChristian König ret = dma_resv_get_singleton(obj->resv, usage, &new); 1711ea28bc5SChristian König if (ret) 1721ea28bc5SChristian König goto error; 1731ea28bc5SChristian König 1741ea28bc5SChristian König if (new && fence) { 1751ea28bc5SChristian König struct dma_fence_chain *chain = dma_fence_chain_alloc(); 1761ea28bc5SChristian König 1771ea28bc5SChristian König if (!chain) { 1781ea28bc5SChristian König ret = -ENOMEM; 1791ea28bc5SChristian König goto error; 1801ea28bc5SChristian König } 1811ea28bc5SChristian König 1821ea28bc5SChristian König dma_fence_chain_init(chain, fence, new, 1); 1831ea28bc5SChristian König fence = &chain->base; 1841ea28bc5SChristian König 1851ea28bc5SChristian König } else if (new) { 1861ea28bc5SChristian König fence = new; 1871ea28bc5SChristian König } 1881ea28bc5SChristian König } 1891ea28bc5SChristian König 1901ea28bc5SChristian König dma_fence_put(state->fence); 1911ea28bc5SChristian König state->fence = fence; 192820c1707SThomas Zimmermann return 0; 1931ea28bc5SChristian König 1941ea28bc5SChristian König error: 1951ea28bc5SChristian König dma_fence_put(fence); 1961ea28bc5SChristian König return ret; 197820c1707SThomas Zimmermann } 198820c1707SThomas Zimmermann EXPORT_SYMBOL_GPL(drm_gem_plane_helper_prepare_fb); 199820c1707SThomas Zimmermann 200820c1707SThomas Zimmermann /* 2016dd7b6ceSThomas Zimmermann * Shadow-buffered Planes 2026dd7b6ceSThomas Zimmermann */ 2036dd7b6ceSThomas Zimmermann 2049dc9067dSThomas Zimmermann /** 205b7156502SThomas Zimmermann * __drm_gem_duplicate_shadow_plane_state - duplicates shadow-buffered plane state 206b7156502SThomas Zimmermann * @plane: the plane 207b7156502SThomas Zimmermann * @new_shadow_plane_state: the new shadow-buffered plane state 208b7156502SThomas Zimmermann * 209b7156502SThomas Zimmermann * This function duplicates shadow-buffered plane state. This is helpful for drivers 210b7156502SThomas Zimmermann * that subclass struct drm_shadow_plane_state. 211b7156502SThomas Zimmermann * 212b7156502SThomas Zimmermann * The function does not duplicate existing mappings of the shadow buffers. 213b7156502SThomas Zimmermann * Mappings are maintained during the atomic commit by the plane's prepare_fb 214b7156502SThomas Zimmermann * and cleanup_fb helpers. See drm_gem_prepare_shadow_fb() and drm_gem_cleanup_shadow_fb() 215b7156502SThomas Zimmermann * for corresponding helpers. 216b7156502SThomas Zimmermann */ 217b7156502SThomas Zimmermann void 218b7156502SThomas Zimmermann __drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane, 219b7156502SThomas Zimmermann struct drm_shadow_plane_state *new_shadow_plane_state) 220b7156502SThomas Zimmermann { 221b7156502SThomas Zimmermann __drm_atomic_helper_plane_duplicate_state(plane, &new_shadow_plane_state->base); 222b7156502SThomas Zimmermann } 223b7156502SThomas Zimmermann EXPORT_SYMBOL(__drm_gem_duplicate_shadow_plane_state); 224b7156502SThomas Zimmermann 225b7156502SThomas Zimmermann /** 2269dc9067dSThomas Zimmermann * drm_gem_duplicate_shadow_plane_state - duplicates shadow-buffered plane state 2279dc9067dSThomas Zimmermann * @plane: the plane 2289dc9067dSThomas Zimmermann * 2299dc9067dSThomas Zimmermann * This function implements struct &drm_plane_funcs.atomic_duplicate_state for 2309dc9067dSThomas Zimmermann * shadow-buffered planes. It assumes the existing state to be of type 2319dc9067dSThomas Zimmermann * struct drm_shadow_plane_state and it allocates the new state to be of this 2329dc9067dSThomas Zimmermann * type. 2339dc9067dSThomas Zimmermann * 2349dc9067dSThomas Zimmermann * The function does not duplicate existing mappings of the shadow buffers. 2359dc9067dSThomas Zimmermann * Mappings are maintained during the atomic commit by the plane's prepare_fb 2369dc9067dSThomas Zimmermann * and cleanup_fb helpers. See drm_gem_prepare_shadow_fb() and drm_gem_cleanup_shadow_fb() 2379dc9067dSThomas Zimmermann * for corresponding helpers. 2389dc9067dSThomas Zimmermann * 2399dc9067dSThomas Zimmermann * Returns: 2409dc9067dSThomas Zimmermann * A pointer to a new plane state on success, or NULL otherwise. 2419dc9067dSThomas Zimmermann */ 2429dc9067dSThomas Zimmermann struct drm_plane_state * 2436dd7b6ceSThomas Zimmermann drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane) 2446dd7b6ceSThomas Zimmermann { 2456dd7b6ceSThomas Zimmermann struct drm_plane_state *plane_state = plane->state; 2466dd7b6ceSThomas Zimmermann struct drm_shadow_plane_state *new_shadow_plane_state; 2476dd7b6ceSThomas Zimmermann 2486dd7b6ceSThomas Zimmermann if (!plane_state) 2496dd7b6ceSThomas Zimmermann return NULL; 2506dd7b6ceSThomas Zimmermann 2516dd7b6ceSThomas Zimmermann new_shadow_plane_state = kzalloc(sizeof(*new_shadow_plane_state), GFP_KERNEL); 2526dd7b6ceSThomas Zimmermann if (!new_shadow_plane_state) 2536dd7b6ceSThomas Zimmermann return NULL; 254b7156502SThomas Zimmermann __drm_gem_duplicate_shadow_plane_state(plane, new_shadow_plane_state); 2556dd7b6ceSThomas Zimmermann 2566dd7b6ceSThomas Zimmermann return &new_shadow_plane_state->base; 2576dd7b6ceSThomas Zimmermann } 2589dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_duplicate_shadow_plane_state); 2596dd7b6ceSThomas Zimmermann 2609dc9067dSThomas Zimmermann /** 261b7156502SThomas Zimmermann * __drm_gem_destroy_shadow_plane_state - cleans up shadow-buffered plane state 262b7156502SThomas Zimmermann * @shadow_plane_state: the shadow-buffered plane state 263b7156502SThomas Zimmermann * 264b7156502SThomas Zimmermann * This function cleans up shadow-buffered plane state. Helpful for drivers that 265b7156502SThomas Zimmermann * subclass struct drm_shadow_plane_state. 266b7156502SThomas Zimmermann */ 267b7156502SThomas Zimmermann void __drm_gem_destroy_shadow_plane_state(struct drm_shadow_plane_state *shadow_plane_state) 268b7156502SThomas Zimmermann { 269b7156502SThomas Zimmermann __drm_atomic_helper_plane_destroy_state(&shadow_plane_state->base); 270b7156502SThomas Zimmermann } 271b7156502SThomas Zimmermann EXPORT_SYMBOL(__drm_gem_destroy_shadow_plane_state); 272b7156502SThomas Zimmermann 273b7156502SThomas Zimmermann /** 2749dc9067dSThomas Zimmermann * drm_gem_destroy_shadow_plane_state - deletes shadow-buffered plane state 2759dc9067dSThomas Zimmermann * @plane: the plane 2769dc9067dSThomas Zimmermann * @plane_state: the plane state of type struct drm_shadow_plane_state 2779dc9067dSThomas Zimmermann * 2789dc9067dSThomas Zimmermann * This function implements struct &drm_plane_funcs.atomic_destroy_state 2799dc9067dSThomas Zimmermann * for shadow-buffered planes. It expects that mappings of shadow buffers 2809dc9067dSThomas Zimmermann * have been released already. 2819dc9067dSThomas Zimmermann */ 2829dc9067dSThomas Zimmermann void drm_gem_destroy_shadow_plane_state(struct drm_plane *plane, 2836dd7b6ceSThomas Zimmermann struct drm_plane_state *plane_state) 2846dd7b6ceSThomas Zimmermann { 2856dd7b6ceSThomas Zimmermann struct drm_shadow_plane_state *shadow_plane_state = 2866dd7b6ceSThomas Zimmermann to_drm_shadow_plane_state(plane_state); 2876dd7b6ceSThomas Zimmermann 288b7156502SThomas Zimmermann __drm_gem_destroy_shadow_plane_state(shadow_plane_state); 2896dd7b6ceSThomas Zimmermann kfree(shadow_plane_state); 2906dd7b6ceSThomas Zimmermann } 2919dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_destroy_shadow_plane_state); 2926dd7b6ceSThomas Zimmermann 2939dc9067dSThomas Zimmermann /** 294b7156502SThomas Zimmermann * __drm_gem_reset_shadow_plane - resets a shadow-buffered plane 295b7156502SThomas Zimmermann * @plane: the plane 296b7156502SThomas Zimmermann * @shadow_plane_state: the shadow-buffered plane state 297b7156502SThomas Zimmermann * 298b7156502SThomas Zimmermann * This function resets state for shadow-buffered planes. Helpful 299b7156502SThomas Zimmermann * for drivers that subclass struct drm_shadow_plane_state. 300b7156502SThomas Zimmermann */ 301b7156502SThomas Zimmermann void __drm_gem_reset_shadow_plane(struct drm_plane *plane, 302b7156502SThomas Zimmermann struct drm_shadow_plane_state *shadow_plane_state) 303b7156502SThomas Zimmermann { 304b7156502SThomas Zimmermann __drm_atomic_helper_plane_reset(plane, &shadow_plane_state->base); 305b7156502SThomas Zimmermann } 306b7156502SThomas Zimmermann EXPORT_SYMBOL(__drm_gem_reset_shadow_plane); 307b7156502SThomas Zimmermann 308b7156502SThomas Zimmermann /** 3099dc9067dSThomas Zimmermann * drm_gem_reset_shadow_plane - resets a shadow-buffered plane 3109dc9067dSThomas Zimmermann * @plane: the plane 3119dc9067dSThomas Zimmermann * 3129dc9067dSThomas Zimmermann * This function implements struct &drm_plane_funcs.reset_plane for 3139dc9067dSThomas Zimmermann * shadow-buffered planes. It assumes the current plane state to be 3149dc9067dSThomas Zimmermann * of type struct drm_shadow_plane and it allocates the new state of 3159dc9067dSThomas Zimmermann * this type. 3169dc9067dSThomas Zimmermann */ 3179dc9067dSThomas Zimmermann void drm_gem_reset_shadow_plane(struct drm_plane *plane) 3186dd7b6ceSThomas Zimmermann { 3196dd7b6ceSThomas Zimmermann struct drm_shadow_plane_state *shadow_plane_state; 3206dd7b6ceSThomas Zimmermann 3216dd7b6ceSThomas Zimmermann if (plane->state) { 3226dd7b6ceSThomas Zimmermann drm_gem_destroy_shadow_plane_state(plane, plane->state); 3236dd7b6ceSThomas Zimmermann plane->state = NULL; /* must be set to NULL here */ 3246dd7b6ceSThomas Zimmermann } 3256dd7b6ceSThomas Zimmermann 3266dd7b6ceSThomas Zimmermann shadow_plane_state = kzalloc(sizeof(*shadow_plane_state), GFP_KERNEL); 3276dd7b6ceSThomas Zimmermann if (!shadow_plane_state) 3286dd7b6ceSThomas Zimmermann return; 329b7156502SThomas Zimmermann __drm_gem_reset_shadow_plane(plane, shadow_plane_state); 3306dd7b6ceSThomas Zimmermann } 3319dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_reset_shadow_plane); 3326dd7b6ceSThomas Zimmermann 3339dc9067dSThomas Zimmermann /** 334359c6649SThomas Zimmermann * drm_gem_begin_shadow_fb_access - prepares shadow framebuffers for CPU access 3359dc9067dSThomas Zimmermann * @plane: the plane 3369dc9067dSThomas Zimmermann * @plane_state: the plane state of type struct drm_shadow_plane_state 3379dc9067dSThomas Zimmermann * 338359c6649SThomas Zimmermann * This function implements struct &drm_plane_helper_funcs.begin_fb_access. It 3399dc9067dSThomas Zimmermann * maps all buffer objects of the plane's framebuffer into kernel address 340359c6649SThomas Zimmermann * space and stores them in struct &drm_shadow_plane_state.map. The first data 341359c6649SThomas Zimmermann * bytes are available in struct &drm_shadow_plane_state.data. 3429dc9067dSThomas Zimmermann * 343359c6649SThomas Zimmermann * See drm_gem_end_shadow_fb_access() for cleanup. 3449dc9067dSThomas Zimmermann * 3459dc9067dSThomas Zimmermann * Returns: 3469dc9067dSThomas Zimmermann * 0 on success, or a negative errno code otherwise. 3479dc9067dSThomas Zimmermann */ 348359c6649SThomas Zimmermann int drm_gem_begin_shadow_fb_access(struct drm_plane *plane, struct drm_plane_state *plane_state) 3496dd7b6ceSThomas Zimmermann { 3506dd7b6ceSThomas Zimmermann struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); 3516dd7b6ceSThomas Zimmermann struct drm_framebuffer *fb = plane_state->fb; 3526dd7b6ceSThomas Zimmermann 3536dd7b6ceSThomas Zimmermann if (!fb) 3546dd7b6ceSThomas Zimmermann return 0; 3556dd7b6ceSThomas Zimmermann 35643b36232SThomas Zimmermann return drm_gem_fb_vmap(fb, shadow_plane_state->map, shadow_plane_state->data); 3576dd7b6ceSThomas Zimmermann } 358359c6649SThomas Zimmermann EXPORT_SYMBOL(drm_gem_begin_shadow_fb_access); 3596dd7b6ceSThomas Zimmermann 3609dc9067dSThomas Zimmermann /** 361359c6649SThomas Zimmermann * drm_gem_end_shadow_fb_access - releases shadow framebuffers from CPU access 3629dc9067dSThomas Zimmermann * @plane: the plane 3639dc9067dSThomas Zimmermann * @plane_state: the plane state of type struct drm_shadow_plane_state 3649dc9067dSThomas Zimmermann * 365359c6649SThomas Zimmermann * This function implements struct &drm_plane_helper_funcs.end_fb_access. It 366359c6649SThomas Zimmermann * undoes all effects of drm_gem_begin_shadow_fb_access() in reverse order. 3679dc9067dSThomas Zimmermann * 368359c6649SThomas Zimmermann * See drm_gem_begin_shadow_fb_access() for more information. 3699dc9067dSThomas Zimmermann */ 370359c6649SThomas Zimmermann void drm_gem_end_shadow_fb_access(struct drm_plane *plane, struct drm_plane_state *plane_state) 3716dd7b6ceSThomas Zimmermann { 3726dd7b6ceSThomas Zimmermann struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); 3736dd7b6ceSThomas Zimmermann struct drm_framebuffer *fb = plane_state->fb; 3746dd7b6ceSThomas Zimmermann 3756dd7b6ceSThomas Zimmermann if (!fb) 3766dd7b6ceSThomas Zimmermann return; 3776dd7b6ceSThomas Zimmermann 378f6424ecdSThomas Zimmermann drm_gem_fb_vunmap(fb, shadow_plane_state->map); 3796dd7b6ceSThomas Zimmermann } 380359c6649SThomas Zimmermann EXPORT_SYMBOL(drm_gem_end_shadow_fb_access); 3816dd7b6ceSThomas Zimmermann 3826dd7b6ceSThomas Zimmermann /** 38394d879eaSThomas Zimmermann * drm_gem_simple_kms_begin_shadow_fb_access - prepares shadow framebuffers for CPU access 3846dd7b6ceSThomas Zimmermann * @pipe: the simple display pipe 3856dd7b6ceSThomas Zimmermann * @plane_state: the plane state of type struct drm_shadow_plane_state 3866dd7b6ceSThomas Zimmermann * 38794d879eaSThomas Zimmermann * This function implements struct drm_simple_display_funcs.begin_fb_access. 3886dd7b6ceSThomas Zimmermann * 38994d879eaSThomas Zimmermann * See drm_gem_begin_shadow_fb_access() for details and 39094d879eaSThomas Zimmermann * drm_gem_simple_kms_cleanup_shadow_fb() for cleanup. 3916dd7b6ceSThomas Zimmermann * 3926dd7b6ceSThomas Zimmermann * Returns: 3936dd7b6ceSThomas Zimmermann * 0 on success, or a negative errno code otherwise. 3946dd7b6ceSThomas Zimmermann */ 395359c6649SThomas Zimmermann int drm_gem_simple_kms_begin_shadow_fb_access(struct drm_simple_display_pipe *pipe, 3966dd7b6ceSThomas Zimmermann struct drm_plane_state *plane_state) 3976dd7b6ceSThomas Zimmermann { 398359c6649SThomas Zimmermann return drm_gem_begin_shadow_fb_access(&pipe->plane, plane_state); 3996dd7b6ceSThomas Zimmermann } 400359c6649SThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_begin_shadow_fb_access); 4016dd7b6ceSThomas Zimmermann 4026dd7b6ceSThomas Zimmermann /** 40394d879eaSThomas Zimmermann * drm_gem_simple_kms_end_shadow_fb_access - releases shadow framebuffers from CPU access 4046dd7b6ceSThomas Zimmermann * @pipe: the simple display pipe 4056dd7b6ceSThomas Zimmermann * @plane_state: the plane state of type struct drm_shadow_plane_state 4066dd7b6ceSThomas Zimmermann * 40794d879eaSThomas Zimmermann * This function implements struct drm_simple_display_funcs.end_fb_access. 40894d879eaSThomas Zimmermann * It undoes all effects of drm_gem_simple_kms_begin_shadow_fb_access() in 40994d879eaSThomas Zimmermann * reverse order. 4106dd7b6ceSThomas Zimmermann * 41194d879eaSThomas Zimmermann * See drm_gem_simple_kms_begin_shadow_fb_access(). 4126dd7b6ceSThomas Zimmermann */ 413359c6649SThomas Zimmermann void drm_gem_simple_kms_end_shadow_fb_access(struct drm_simple_display_pipe *pipe, 4146dd7b6ceSThomas Zimmermann struct drm_plane_state *plane_state) 4156dd7b6ceSThomas Zimmermann { 416359c6649SThomas Zimmermann drm_gem_end_shadow_fb_access(&pipe->plane, plane_state); 4176dd7b6ceSThomas Zimmermann } 418359c6649SThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_end_shadow_fb_access); 4196dd7b6ceSThomas Zimmermann 4206dd7b6ceSThomas Zimmermann /** 4216dd7b6ceSThomas Zimmermann * drm_gem_simple_kms_reset_shadow_plane - resets a shadow-buffered plane 4226dd7b6ceSThomas Zimmermann * @pipe: the simple display pipe 4236dd7b6ceSThomas Zimmermann * 4246dd7b6ceSThomas Zimmermann * This function implements struct drm_simple_display_funcs.reset_plane 4256dd7b6ceSThomas Zimmermann * for shadow-buffered planes. 4266dd7b6ceSThomas Zimmermann */ 4276dd7b6ceSThomas Zimmermann void drm_gem_simple_kms_reset_shadow_plane(struct drm_simple_display_pipe *pipe) 4286dd7b6ceSThomas Zimmermann { 4296dd7b6ceSThomas Zimmermann drm_gem_reset_shadow_plane(&pipe->plane); 4306dd7b6ceSThomas Zimmermann } 4316dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_reset_shadow_plane); 4326dd7b6ceSThomas Zimmermann 4336dd7b6ceSThomas Zimmermann /** 4346dd7b6ceSThomas Zimmermann * drm_gem_simple_kms_duplicate_shadow_plane_state - duplicates shadow-buffered plane state 4356dd7b6ceSThomas Zimmermann * @pipe: the simple display pipe 4366dd7b6ceSThomas Zimmermann * 4376dd7b6ceSThomas Zimmermann * This function implements struct drm_simple_display_funcs.duplicate_plane_state 4386dd7b6ceSThomas Zimmermann * for shadow-buffered planes. It does not duplicate existing mappings of the shadow 4396dd7b6ceSThomas Zimmermann * buffers. Mappings are maintained during the atomic commit by the plane's prepare_fb 4406dd7b6ceSThomas Zimmermann * and cleanup_fb helpers. 4416dd7b6ceSThomas Zimmermann * 4426dd7b6ceSThomas Zimmermann * Returns: 4436dd7b6ceSThomas Zimmermann * A pointer to a new plane state on success, or NULL otherwise. 4446dd7b6ceSThomas Zimmermann */ 4456dd7b6ceSThomas Zimmermann struct drm_plane_state * 4466dd7b6ceSThomas Zimmermann drm_gem_simple_kms_duplicate_shadow_plane_state(struct drm_simple_display_pipe *pipe) 4476dd7b6ceSThomas Zimmermann { 4486dd7b6ceSThomas Zimmermann return drm_gem_duplicate_shadow_plane_state(&pipe->plane); 4496dd7b6ceSThomas Zimmermann } 4506dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_duplicate_shadow_plane_state); 4516dd7b6ceSThomas Zimmermann 4526dd7b6ceSThomas Zimmermann /** 4536dd7b6ceSThomas Zimmermann * drm_gem_simple_kms_destroy_shadow_plane_state - resets shadow-buffered plane state 4546dd7b6ceSThomas Zimmermann * @pipe: the simple display pipe 4556dd7b6ceSThomas Zimmermann * @plane_state: the plane state of type struct drm_shadow_plane_state 4566dd7b6ceSThomas Zimmermann * 4576dd7b6ceSThomas Zimmermann * This function implements struct drm_simple_display_funcs.destroy_plane_state 4586dd7b6ceSThomas Zimmermann * for shadow-buffered planes. It expects that mappings of shadow buffers 4596dd7b6ceSThomas Zimmermann * have been released already. 4606dd7b6ceSThomas Zimmermann */ 4616dd7b6ceSThomas Zimmermann void drm_gem_simple_kms_destroy_shadow_plane_state(struct drm_simple_display_pipe *pipe, 4626dd7b6ceSThomas Zimmermann struct drm_plane_state *plane_state) 4636dd7b6ceSThomas Zimmermann { 4646dd7b6ceSThomas Zimmermann drm_gem_destroy_shadow_plane_state(&pipe->plane, plane_state); 4656dd7b6ceSThomas Zimmermann } 4666dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_destroy_shadow_plane_state); 467