16dd7b6ceSThomas Zimmermann // SPDX-License-Identifier: GPL-2.0-or-later 26dd7b6ceSThomas Zimmermann 3*820c1707SThomas Zimmermann #include <linux/dma-resv.h> 4*820c1707SThomas Zimmermann 56dd7b6ceSThomas Zimmermann #include <drm/drm_atomic_state_helper.h> 6*820c1707SThomas Zimmermann #include <drm/drm_atomic_uapi.h> 7*820c1707SThomas Zimmermann #include <drm/drm_gem.h> 86dd7b6ceSThomas Zimmermann #include <drm/drm_gem_atomic_helper.h> 96dd7b6ceSThomas Zimmermann #include <drm/drm_gem_framebuffer_helper.h> 106dd7b6ceSThomas Zimmermann #include <drm/drm_simple_kms_helper.h> 116dd7b6ceSThomas Zimmermann 126dd7b6ceSThomas Zimmermann #include "drm_internal.h" 136dd7b6ceSThomas Zimmermann 146dd7b6ceSThomas Zimmermann /** 156dd7b6ceSThomas Zimmermann * DOC: overview 166dd7b6ceSThomas Zimmermann * 176dd7b6ceSThomas Zimmermann * The GEM atomic helpers library implements generic atomic-commit 186dd7b6ceSThomas Zimmermann * functions for drivers that use GEM objects. Currently, it provides 19*820c1707SThomas Zimmermann * synchronization helpers, and plane state and framebuffer BO mappings 20*820c1707SThomas Zimmermann * for planes with shadow buffers. 21*820c1707SThomas Zimmermann * 22*820c1707SThomas Zimmermann * Before scanout, a plane's framebuffer needs to be synchronized with 23*820c1707SThomas Zimmermann * possible writers that draw into the framebuffer. All drivers should 24*820c1707SThomas Zimmermann * call drm_gem_plane_helper_prepare_fb() from their implementation of 25*820c1707SThomas Zimmermann * struct &drm_plane_helper.prepare_fb . It sets the plane's fence from 26*820c1707SThomas Zimmermann * the framebuffer so that the DRM core can synchronize access automatically. 27*820c1707SThomas Zimmermann * 28*820c1707SThomas Zimmermann * drm_gem_plane_helper_prepare_fb() can also be used directly as 29*820c1707SThomas Zimmermann * implementation of prepare_fb. For drivers based on 30*820c1707SThomas Zimmermann * struct drm_simple_display_pipe, drm_gem_simple_display_pipe_prepare_fb() 31*820c1707SThomas Zimmermann * provides equivalent functionality. 32*820c1707SThomas Zimmermann * 33*820c1707SThomas Zimmermann * .. code-block:: c 34*820c1707SThomas Zimmermann * 35*820c1707SThomas Zimmermann * #include <drm/drm_gem_atomic_helper.h> 36*820c1707SThomas Zimmermann * 37*820c1707SThomas Zimmermann * struct drm_plane_helper_funcs driver_plane_helper_funcs = { 38*820c1707SThomas Zimmermann * ..., 39*820c1707SThomas Zimmermann * . prepare_fb = drm_gem_plane_helper_prepare_fb, 40*820c1707SThomas Zimmermann * }; 41*820c1707SThomas Zimmermann * 42*820c1707SThomas Zimmermann * struct drm_simple_display_pipe_funcs driver_pipe_funcs = { 43*820c1707SThomas Zimmermann * ..., 44*820c1707SThomas Zimmermann * . prepare_fb = drm_gem_simple_display_pipe_prepare_fb, 45*820c1707SThomas Zimmermann * }; 469dc9067dSThomas Zimmermann * 479dc9067dSThomas Zimmermann * A driver using a shadow buffer copies the content of the shadow buffers 489dc9067dSThomas Zimmermann * into the HW's framebuffer memory during an atomic update. This requires 499dc9067dSThomas Zimmermann * a mapping of the shadow buffer into kernel address space. The mappings 509dc9067dSThomas Zimmermann * cannot be established by commit-tail functions, such as atomic_update, 519dc9067dSThomas Zimmermann * as this would violate locking rules around dma_buf_vmap(). 529dc9067dSThomas Zimmermann * 539dc9067dSThomas Zimmermann * The helpers for shadow-buffered planes establish and release mappings, 549dc9067dSThomas Zimmermann * and provide struct drm_shadow_plane_state, which stores the plane's mapping 559dc9067dSThomas Zimmermann * for commit-tail functons. 569dc9067dSThomas Zimmermann * 579dc9067dSThomas Zimmermann * Shadow-buffered planes can easily be enabled by using the provided macros 589dc9067dSThomas Zimmermann * %DRM_GEM_SHADOW_PLANE_FUNCS and %DRM_GEM_SHADOW_PLANE_HELPER_FUNCS. 599dc9067dSThomas Zimmermann * These macros set up the plane and plane-helper callbacks to point to the 609dc9067dSThomas Zimmermann * shadow-buffer helpers. 619dc9067dSThomas Zimmermann * 629dc9067dSThomas Zimmermann * .. code-block:: c 639dc9067dSThomas Zimmermann * 64*820c1707SThomas Zimmermann * #include <drm/drm_gem_atomic_helper.h> 659dc9067dSThomas Zimmermann * 669dc9067dSThomas Zimmermann * struct drm_plane_funcs driver_plane_funcs = { 679dc9067dSThomas Zimmermann * ..., 689dc9067dSThomas Zimmermann * DRM_GEM_SHADOW_PLANE_FUNCS, 699dc9067dSThomas Zimmermann * }; 709dc9067dSThomas Zimmermann * 719dc9067dSThomas Zimmermann * struct drm_plane_helper_funcs driver_plane_helper_funcs = { 729dc9067dSThomas Zimmermann * ..., 739dc9067dSThomas Zimmermann * DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, 749dc9067dSThomas Zimmermann * }; 759dc9067dSThomas Zimmermann * 769dc9067dSThomas Zimmermann * In the driver's atomic-update function, shadow-buffer mappings are available 779dc9067dSThomas Zimmermann * from the plane state. Use to_drm_shadow_plane_state() to upcast from 789dc9067dSThomas Zimmermann * struct drm_plane_state. 799dc9067dSThomas Zimmermann * 809dc9067dSThomas Zimmermann * .. code-block:: c 819dc9067dSThomas Zimmermann * 829dc9067dSThomas Zimmermann * void driver_plane_atomic_update(struct drm_plane *plane, 839dc9067dSThomas Zimmermann * struct drm_plane_state *old_plane_state) 849dc9067dSThomas Zimmermann * { 859dc9067dSThomas Zimmermann * struct drm_plane_state *plane_state = plane->state; 869dc9067dSThomas Zimmermann * struct drm_shadow_plane_state *shadow_plane_state = 879dc9067dSThomas Zimmermann * to_drm_shadow_plane_state(plane_state); 889dc9067dSThomas Zimmermann * 899dc9067dSThomas Zimmermann * // access shadow buffer via shadow_plane_state->map 909dc9067dSThomas Zimmermann * } 919dc9067dSThomas Zimmermann * 929dc9067dSThomas Zimmermann * A mapping address for each of the framebuffer's buffer object is stored in 939dc9067dSThomas Zimmermann * struct &drm_shadow_plane_state.map. The mappings are valid while the state 949dc9067dSThomas Zimmermann * is being used. 959dc9067dSThomas Zimmermann * 969dc9067dSThomas Zimmermann * Drivers that use struct drm_simple_display_pipe can use 979dc9067dSThomas Zimmermann * %DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS to initialize the rsp 989dc9067dSThomas Zimmermann * callbacks. Access to shadow-buffer mappings is similar to regular 999dc9067dSThomas Zimmermann * atomic_update. 1009dc9067dSThomas Zimmermann * 1019dc9067dSThomas Zimmermann * .. code-block:: c 1029dc9067dSThomas Zimmermann * 1039dc9067dSThomas Zimmermann * struct drm_simple_display_pipe_funcs driver_pipe_funcs = { 1049dc9067dSThomas Zimmermann * ..., 1059dc9067dSThomas Zimmermann * DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS, 1069dc9067dSThomas Zimmermann * }; 1079dc9067dSThomas Zimmermann * 1089dc9067dSThomas Zimmermann * void driver_pipe_enable(struct drm_simple_display_pipe *pipe, 1099dc9067dSThomas Zimmermann * struct drm_crtc_state *crtc_state, 1109dc9067dSThomas Zimmermann * struct drm_plane_state *plane_state) 1119dc9067dSThomas Zimmermann * { 1129dc9067dSThomas Zimmermann * struct drm_shadow_plane_state *shadow_plane_state = 1139dc9067dSThomas Zimmermann * to_drm_shadow_plane_state(plane_state); 1149dc9067dSThomas Zimmermann * 1159dc9067dSThomas Zimmermann * // access shadow buffer via shadow_plane_state->map 1169dc9067dSThomas Zimmermann * } 1176dd7b6ceSThomas Zimmermann */ 1186dd7b6ceSThomas Zimmermann 1196dd7b6ceSThomas Zimmermann /* 120*820c1707SThomas Zimmermann * Plane Helpers 121*820c1707SThomas Zimmermann */ 122*820c1707SThomas Zimmermann 123*820c1707SThomas Zimmermann /** 124*820c1707SThomas Zimmermann * drm_gem_plane_helper_prepare_fb() - Prepare a GEM backed framebuffer 125*820c1707SThomas Zimmermann * @plane: Plane 126*820c1707SThomas Zimmermann * @state: Plane state the fence will be attached to 127*820c1707SThomas Zimmermann * 128*820c1707SThomas Zimmermann * This function extracts the exclusive fence from &drm_gem_object.resv and 129*820c1707SThomas Zimmermann * attaches it to plane state for the atomic helper to wait on. This is 130*820c1707SThomas Zimmermann * necessary to correctly implement implicit synchronization for any buffers 131*820c1707SThomas Zimmermann * shared as a struct &dma_buf. This function can be used as the 132*820c1707SThomas Zimmermann * &drm_plane_helper_funcs.prepare_fb callback. 133*820c1707SThomas Zimmermann * 134*820c1707SThomas Zimmermann * There is no need for &drm_plane_helper_funcs.cleanup_fb hook for simple 135*820c1707SThomas Zimmermann * GEM based framebuffer drivers which have their buffers always pinned in 136*820c1707SThomas Zimmermann * memory. 137*820c1707SThomas Zimmermann * 138*820c1707SThomas Zimmermann * See drm_atomic_set_fence_for_plane() for a discussion of implicit and 139*820c1707SThomas Zimmermann * explicit fencing in atomic modeset updates. 140*820c1707SThomas Zimmermann */ 141*820c1707SThomas Zimmermann int drm_gem_plane_helper_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state) 142*820c1707SThomas Zimmermann { 143*820c1707SThomas Zimmermann struct drm_gem_object *obj; 144*820c1707SThomas Zimmermann struct dma_fence *fence; 145*820c1707SThomas Zimmermann 146*820c1707SThomas Zimmermann if (!state->fb) 147*820c1707SThomas Zimmermann return 0; 148*820c1707SThomas Zimmermann 149*820c1707SThomas Zimmermann obj = drm_gem_fb_get_obj(state->fb, 0); 150*820c1707SThomas Zimmermann fence = dma_resv_get_excl_rcu(obj->resv); 151*820c1707SThomas Zimmermann drm_atomic_set_fence_for_plane(state, fence); 152*820c1707SThomas Zimmermann 153*820c1707SThomas Zimmermann return 0; 154*820c1707SThomas Zimmermann } 155*820c1707SThomas Zimmermann EXPORT_SYMBOL_GPL(drm_gem_plane_helper_prepare_fb); 156*820c1707SThomas Zimmermann 157*820c1707SThomas Zimmermann /** 158*820c1707SThomas Zimmermann * drm_gem_simple_display_pipe_prepare_fb - prepare_fb helper for &drm_simple_display_pipe 159*820c1707SThomas Zimmermann * @pipe: Simple display pipe 160*820c1707SThomas Zimmermann * @plane_state: Plane state 161*820c1707SThomas Zimmermann * 162*820c1707SThomas Zimmermann * This function uses drm_gem_plane_helper_prepare_fb() to extract the exclusive fence 163*820c1707SThomas Zimmermann * from &drm_gem_object.resv and attaches it to plane state for the atomic 164*820c1707SThomas Zimmermann * helper to wait on. This is necessary to correctly implement implicit 165*820c1707SThomas Zimmermann * synchronization for any buffers shared as a struct &dma_buf. Drivers can use 166*820c1707SThomas Zimmermann * this as their &drm_simple_display_pipe_funcs.prepare_fb callback. 167*820c1707SThomas Zimmermann * 168*820c1707SThomas Zimmermann * See drm_atomic_set_fence_for_plane() for a discussion of implicit and 169*820c1707SThomas Zimmermann * explicit fencing in atomic modeset updates. 170*820c1707SThomas Zimmermann */ 171*820c1707SThomas Zimmermann int drm_gem_simple_display_pipe_prepare_fb(struct drm_simple_display_pipe *pipe, 172*820c1707SThomas Zimmermann struct drm_plane_state *plane_state) 173*820c1707SThomas Zimmermann { 174*820c1707SThomas Zimmermann return drm_gem_plane_helper_prepare_fb(&pipe->plane, plane_state); 175*820c1707SThomas Zimmermann } 176*820c1707SThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_display_pipe_prepare_fb); 177*820c1707SThomas Zimmermann 178*820c1707SThomas Zimmermann /* 1796dd7b6ceSThomas Zimmermann * Shadow-buffered Planes 1806dd7b6ceSThomas Zimmermann */ 1816dd7b6ceSThomas Zimmermann 1829dc9067dSThomas Zimmermann /** 1839dc9067dSThomas Zimmermann * drm_gem_duplicate_shadow_plane_state - duplicates shadow-buffered plane state 1849dc9067dSThomas Zimmermann * @plane: the plane 1859dc9067dSThomas Zimmermann * 1869dc9067dSThomas Zimmermann * This function implements struct &drm_plane_funcs.atomic_duplicate_state for 1879dc9067dSThomas Zimmermann * shadow-buffered planes. It assumes the existing state to be of type 1889dc9067dSThomas Zimmermann * struct drm_shadow_plane_state and it allocates the new state to be of this 1899dc9067dSThomas Zimmermann * type. 1909dc9067dSThomas Zimmermann * 1919dc9067dSThomas Zimmermann * The function does not duplicate existing mappings of the shadow buffers. 1929dc9067dSThomas Zimmermann * Mappings are maintained during the atomic commit by the plane's prepare_fb 1939dc9067dSThomas Zimmermann * and cleanup_fb helpers. See drm_gem_prepare_shadow_fb() and drm_gem_cleanup_shadow_fb() 1949dc9067dSThomas Zimmermann * for corresponding helpers. 1959dc9067dSThomas Zimmermann * 1969dc9067dSThomas Zimmermann * Returns: 1979dc9067dSThomas Zimmermann * A pointer to a new plane state on success, or NULL otherwise. 1989dc9067dSThomas Zimmermann */ 1999dc9067dSThomas Zimmermann struct drm_plane_state * 2006dd7b6ceSThomas Zimmermann drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane) 2016dd7b6ceSThomas Zimmermann { 2026dd7b6ceSThomas Zimmermann struct drm_plane_state *plane_state = plane->state; 2036dd7b6ceSThomas Zimmermann struct drm_shadow_plane_state *new_shadow_plane_state; 2046dd7b6ceSThomas Zimmermann 2056dd7b6ceSThomas Zimmermann if (!plane_state) 2066dd7b6ceSThomas Zimmermann return NULL; 2076dd7b6ceSThomas Zimmermann 2086dd7b6ceSThomas Zimmermann new_shadow_plane_state = kzalloc(sizeof(*new_shadow_plane_state), GFP_KERNEL); 2096dd7b6ceSThomas Zimmermann if (!new_shadow_plane_state) 2106dd7b6ceSThomas Zimmermann return NULL; 2116dd7b6ceSThomas Zimmermann __drm_atomic_helper_plane_duplicate_state(plane, &new_shadow_plane_state->base); 2126dd7b6ceSThomas Zimmermann 2136dd7b6ceSThomas Zimmermann return &new_shadow_plane_state->base; 2146dd7b6ceSThomas Zimmermann } 2159dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_duplicate_shadow_plane_state); 2166dd7b6ceSThomas Zimmermann 2179dc9067dSThomas Zimmermann /** 2189dc9067dSThomas Zimmermann * drm_gem_destroy_shadow_plane_state - deletes shadow-buffered plane state 2199dc9067dSThomas Zimmermann * @plane: the plane 2209dc9067dSThomas Zimmermann * @plane_state: the plane state of type struct drm_shadow_plane_state 2219dc9067dSThomas Zimmermann * 2229dc9067dSThomas Zimmermann * This function implements struct &drm_plane_funcs.atomic_destroy_state 2239dc9067dSThomas Zimmermann * for shadow-buffered planes. It expects that mappings of shadow buffers 2249dc9067dSThomas Zimmermann * have been released already. 2259dc9067dSThomas Zimmermann */ 2269dc9067dSThomas Zimmermann void drm_gem_destroy_shadow_plane_state(struct drm_plane *plane, 2276dd7b6ceSThomas Zimmermann struct drm_plane_state *plane_state) 2286dd7b6ceSThomas Zimmermann { 2296dd7b6ceSThomas Zimmermann struct drm_shadow_plane_state *shadow_plane_state = 2306dd7b6ceSThomas Zimmermann to_drm_shadow_plane_state(plane_state); 2316dd7b6ceSThomas Zimmermann 2326dd7b6ceSThomas Zimmermann __drm_atomic_helper_plane_destroy_state(&shadow_plane_state->base); 2336dd7b6ceSThomas Zimmermann kfree(shadow_plane_state); 2346dd7b6ceSThomas Zimmermann } 2359dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_destroy_shadow_plane_state); 2366dd7b6ceSThomas Zimmermann 2379dc9067dSThomas Zimmermann /** 2389dc9067dSThomas Zimmermann * drm_gem_reset_shadow_plane - resets a shadow-buffered plane 2399dc9067dSThomas Zimmermann * @plane: the plane 2409dc9067dSThomas Zimmermann * 2419dc9067dSThomas Zimmermann * This function implements struct &drm_plane_funcs.reset_plane for 2429dc9067dSThomas Zimmermann * shadow-buffered planes. It assumes the current plane state to be 2439dc9067dSThomas Zimmermann * of type struct drm_shadow_plane and it allocates the new state of 2449dc9067dSThomas Zimmermann * this type. 2459dc9067dSThomas Zimmermann */ 2469dc9067dSThomas Zimmermann void drm_gem_reset_shadow_plane(struct drm_plane *plane) 2476dd7b6ceSThomas Zimmermann { 2486dd7b6ceSThomas Zimmermann struct drm_shadow_plane_state *shadow_plane_state; 2496dd7b6ceSThomas Zimmermann 2506dd7b6ceSThomas Zimmermann if (plane->state) { 2516dd7b6ceSThomas Zimmermann drm_gem_destroy_shadow_plane_state(plane, plane->state); 2526dd7b6ceSThomas Zimmermann plane->state = NULL; /* must be set to NULL here */ 2536dd7b6ceSThomas Zimmermann } 2546dd7b6ceSThomas Zimmermann 2556dd7b6ceSThomas Zimmermann shadow_plane_state = kzalloc(sizeof(*shadow_plane_state), GFP_KERNEL); 2566dd7b6ceSThomas Zimmermann if (!shadow_plane_state) 2576dd7b6ceSThomas Zimmermann return; 2586dd7b6ceSThomas Zimmermann __drm_atomic_helper_plane_reset(plane, &shadow_plane_state->base); 2596dd7b6ceSThomas Zimmermann } 2609dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_reset_shadow_plane); 2616dd7b6ceSThomas Zimmermann 2629dc9067dSThomas Zimmermann /** 2639dc9067dSThomas Zimmermann * drm_gem_prepare_shadow_fb - prepares shadow framebuffers 2649dc9067dSThomas Zimmermann * @plane: the plane 2659dc9067dSThomas Zimmermann * @plane_state: the plane state of type struct drm_shadow_plane_state 2669dc9067dSThomas Zimmermann * 2679dc9067dSThomas Zimmermann * This function implements struct &drm_plane_helper_funcs.prepare_fb. It 2689dc9067dSThomas Zimmermann * maps all buffer objects of the plane's framebuffer into kernel address 2699dc9067dSThomas Zimmermann * space and stores them in &struct drm_shadow_plane_state.map. The 2709dc9067dSThomas Zimmermann * framebuffer will be synchronized as part of the atomic commit. 2719dc9067dSThomas Zimmermann * 2729dc9067dSThomas Zimmermann * See drm_gem_cleanup_shadow_fb() for cleanup. 2739dc9067dSThomas Zimmermann * 2749dc9067dSThomas Zimmermann * Returns: 2759dc9067dSThomas Zimmermann * 0 on success, or a negative errno code otherwise. 2769dc9067dSThomas Zimmermann */ 2779dc9067dSThomas Zimmermann int drm_gem_prepare_shadow_fb(struct drm_plane *plane, struct drm_plane_state *plane_state) 2786dd7b6ceSThomas Zimmermann { 2796dd7b6ceSThomas Zimmermann struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); 2806dd7b6ceSThomas Zimmermann struct drm_framebuffer *fb = plane_state->fb; 2816dd7b6ceSThomas Zimmermann struct drm_gem_object *obj; 2826dd7b6ceSThomas Zimmermann struct dma_buf_map map; 2836dd7b6ceSThomas Zimmermann int ret; 2846dd7b6ceSThomas Zimmermann size_t i; 2856dd7b6ceSThomas Zimmermann 2866dd7b6ceSThomas Zimmermann if (!fb) 2876dd7b6ceSThomas Zimmermann return 0; 2886dd7b6ceSThomas Zimmermann 289*820c1707SThomas Zimmermann ret = drm_gem_plane_helper_prepare_fb(plane, plane_state); 2906dd7b6ceSThomas Zimmermann if (ret) 2916dd7b6ceSThomas Zimmermann return ret; 2926dd7b6ceSThomas Zimmermann 2936dd7b6ceSThomas Zimmermann for (i = 0; i < ARRAY_SIZE(shadow_plane_state->map); ++i) { 2946dd7b6ceSThomas Zimmermann obj = drm_gem_fb_get_obj(fb, i); 2956dd7b6ceSThomas Zimmermann if (!obj) 2966dd7b6ceSThomas Zimmermann continue; 2976dd7b6ceSThomas Zimmermann ret = drm_gem_vmap(obj, &map); 2986dd7b6ceSThomas Zimmermann if (ret) 2996dd7b6ceSThomas Zimmermann goto err_drm_gem_vunmap; 3006dd7b6ceSThomas Zimmermann shadow_plane_state->map[i] = map; 3016dd7b6ceSThomas Zimmermann } 3026dd7b6ceSThomas Zimmermann 3036dd7b6ceSThomas Zimmermann return 0; 3046dd7b6ceSThomas Zimmermann 3056dd7b6ceSThomas Zimmermann err_drm_gem_vunmap: 3066dd7b6ceSThomas Zimmermann while (i) { 3076dd7b6ceSThomas Zimmermann --i; 3086dd7b6ceSThomas Zimmermann obj = drm_gem_fb_get_obj(fb, i); 3096dd7b6ceSThomas Zimmermann if (!obj) 3106dd7b6ceSThomas Zimmermann continue; 3116dd7b6ceSThomas Zimmermann drm_gem_vunmap(obj, &shadow_plane_state->map[i]); 3126dd7b6ceSThomas Zimmermann } 3136dd7b6ceSThomas Zimmermann return ret; 3146dd7b6ceSThomas Zimmermann } 3159dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_prepare_shadow_fb); 3166dd7b6ceSThomas Zimmermann 3179dc9067dSThomas Zimmermann /** 3189dc9067dSThomas Zimmermann * drm_gem_cleanup_shadow_fb - releases shadow framebuffers 3199dc9067dSThomas Zimmermann * @plane: the plane 3209dc9067dSThomas Zimmermann * @plane_state: the plane state of type struct drm_shadow_plane_state 3219dc9067dSThomas Zimmermann * 3229dc9067dSThomas Zimmermann * This function implements struct &drm_plane_helper_funcs.cleanup_fb. 3239dc9067dSThomas Zimmermann * This function unmaps all buffer objects of the plane's framebuffer. 3249dc9067dSThomas Zimmermann * 3259dc9067dSThomas Zimmermann * See drm_gem_prepare_shadow_fb() for more inforamtion. 3269dc9067dSThomas Zimmermann */ 3279dc9067dSThomas Zimmermann void drm_gem_cleanup_shadow_fb(struct drm_plane *plane, struct drm_plane_state *plane_state) 3286dd7b6ceSThomas Zimmermann { 3296dd7b6ceSThomas Zimmermann struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); 3306dd7b6ceSThomas Zimmermann struct drm_framebuffer *fb = plane_state->fb; 3316dd7b6ceSThomas Zimmermann size_t i = ARRAY_SIZE(shadow_plane_state->map); 3326dd7b6ceSThomas Zimmermann struct drm_gem_object *obj; 3336dd7b6ceSThomas Zimmermann 3346dd7b6ceSThomas Zimmermann if (!fb) 3356dd7b6ceSThomas Zimmermann return; 3366dd7b6ceSThomas Zimmermann 3376dd7b6ceSThomas Zimmermann while (i) { 3386dd7b6ceSThomas Zimmermann --i; 3396dd7b6ceSThomas Zimmermann obj = drm_gem_fb_get_obj(fb, i); 3406dd7b6ceSThomas Zimmermann if (!obj) 3416dd7b6ceSThomas Zimmermann continue; 3426dd7b6ceSThomas Zimmermann drm_gem_vunmap(obj, &shadow_plane_state->map[i]); 3436dd7b6ceSThomas Zimmermann } 3446dd7b6ceSThomas Zimmermann } 3459dc9067dSThomas Zimmermann EXPORT_SYMBOL(drm_gem_cleanup_shadow_fb); 3466dd7b6ceSThomas Zimmermann 3476dd7b6ceSThomas Zimmermann /** 3486dd7b6ceSThomas Zimmermann * drm_gem_simple_kms_prepare_shadow_fb - prepares shadow framebuffers 3496dd7b6ceSThomas Zimmermann * @pipe: the simple display pipe 3506dd7b6ceSThomas Zimmermann * @plane_state: the plane state of type struct drm_shadow_plane_state 3516dd7b6ceSThomas Zimmermann * 3526dd7b6ceSThomas Zimmermann * This function implements struct drm_simple_display_funcs.prepare_fb. It 3536dd7b6ceSThomas Zimmermann * maps all buffer objects of the plane's framebuffer into kernel address 3546dd7b6ceSThomas Zimmermann * space and stores them in struct drm_shadow_plane_state.map. The 3556dd7b6ceSThomas Zimmermann * framebuffer will be synchronized as part of the atomic commit. 3566dd7b6ceSThomas Zimmermann * 3576dd7b6ceSThomas Zimmermann * See drm_gem_simple_kms_cleanup_shadow_fb() for cleanup. 3586dd7b6ceSThomas Zimmermann * 3596dd7b6ceSThomas Zimmermann * Returns: 3606dd7b6ceSThomas Zimmermann * 0 on success, or a negative errno code otherwise. 3616dd7b6ceSThomas Zimmermann */ 3626dd7b6ceSThomas Zimmermann int drm_gem_simple_kms_prepare_shadow_fb(struct drm_simple_display_pipe *pipe, 3636dd7b6ceSThomas Zimmermann struct drm_plane_state *plane_state) 3646dd7b6ceSThomas Zimmermann { 3656dd7b6ceSThomas Zimmermann return drm_gem_prepare_shadow_fb(&pipe->plane, plane_state); 3666dd7b6ceSThomas Zimmermann } 3676dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_prepare_shadow_fb); 3686dd7b6ceSThomas Zimmermann 3696dd7b6ceSThomas Zimmermann /** 3706dd7b6ceSThomas Zimmermann * drm_gem_simple_kms_cleanup_shadow_fb - releases shadow framebuffers 3716dd7b6ceSThomas Zimmermann * @pipe: the simple display pipe 3726dd7b6ceSThomas Zimmermann * @plane_state: the plane state of type struct drm_shadow_plane_state 3736dd7b6ceSThomas Zimmermann * 3746dd7b6ceSThomas Zimmermann * This function implements struct drm_simple_display_funcs.cleanup_fb. 3756dd7b6ceSThomas Zimmermann * This function unmaps all buffer objects of the plane's framebuffer. 3766dd7b6ceSThomas Zimmermann * 3776dd7b6ceSThomas Zimmermann * See drm_gem_simple_kms_prepare_shadow_fb(). 3786dd7b6ceSThomas Zimmermann */ 3796dd7b6ceSThomas Zimmermann void drm_gem_simple_kms_cleanup_shadow_fb(struct drm_simple_display_pipe *pipe, 3806dd7b6ceSThomas Zimmermann struct drm_plane_state *plane_state) 3816dd7b6ceSThomas Zimmermann { 3826dd7b6ceSThomas Zimmermann drm_gem_cleanup_shadow_fb(&pipe->plane, plane_state); 3836dd7b6ceSThomas Zimmermann } 3846dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_cleanup_shadow_fb); 3856dd7b6ceSThomas Zimmermann 3866dd7b6ceSThomas Zimmermann /** 3876dd7b6ceSThomas Zimmermann * drm_gem_simple_kms_reset_shadow_plane - resets a shadow-buffered plane 3886dd7b6ceSThomas Zimmermann * @pipe: the simple display pipe 3896dd7b6ceSThomas Zimmermann * 3906dd7b6ceSThomas Zimmermann * This function implements struct drm_simple_display_funcs.reset_plane 3916dd7b6ceSThomas Zimmermann * for shadow-buffered planes. 3926dd7b6ceSThomas Zimmermann */ 3936dd7b6ceSThomas Zimmermann void drm_gem_simple_kms_reset_shadow_plane(struct drm_simple_display_pipe *pipe) 3946dd7b6ceSThomas Zimmermann { 3956dd7b6ceSThomas Zimmermann drm_gem_reset_shadow_plane(&pipe->plane); 3966dd7b6ceSThomas Zimmermann } 3976dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_reset_shadow_plane); 3986dd7b6ceSThomas Zimmermann 3996dd7b6ceSThomas Zimmermann /** 4006dd7b6ceSThomas Zimmermann * drm_gem_simple_kms_duplicate_shadow_plane_state - duplicates shadow-buffered plane state 4016dd7b6ceSThomas Zimmermann * @pipe: the simple display pipe 4026dd7b6ceSThomas Zimmermann * 4036dd7b6ceSThomas Zimmermann * This function implements struct drm_simple_display_funcs.duplicate_plane_state 4046dd7b6ceSThomas Zimmermann * for shadow-buffered planes. It does not duplicate existing mappings of the shadow 4056dd7b6ceSThomas Zimmermann * buffers. Mappings are maintained during the atomic commit by the plane's prepare_fb 4066dd7b6ceSThomas Zimmermann * and cleanup_fb helpers. 4076dd7b6ceSThomas Zimmermann * 4086dd7b6ceSThomas Zimmermann * Returns: 4096dd7b6ceSThomas Zimmermann * A pointer to a new plane state on success, or NULL otherwise. 4106dd7b6ceSThomas Zimmermann */ 4116dd7b6ceSThomas Zimmermann struct drm_plane_state * 4126dd7b6ceSThomas Zimmermann drm_gem_simple_kms_duplicate_shadow_plane_state(struct drm_simple_display_pipe *pipe) 4136dd7b6ceSThomas Zimmermann { 4146dd7b6ceSThomas Zimmermann return drm_gem_duplicate_shadow_plane_state(&pipe->plane); 4156dd7b6ceSThomas Zimmermann } 4166dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_duplicate_shadow_plane_state); 4176dd7b6ceSThomas Zimmermann 4186dd7b6ceSThomas Zimmermann /** 4196dd7b6ceSThomas Zimmermann * drm_gem_simple_kms_destroy_shadow_plane_state - resets shadow-buffered plane state 4206dd7b6ceSThomas Zimmermann * @pipe: the simple display pipe 4216dd7b6ceSThomas Zimmermann * @plane_state: the plane state of type struct drm_shadow_plane_state 4226dd7b6ceSThomas Zimmermann * 4236dd7b6ceSThomas Zimmermann * This function implements struct drm_simple_display_funcs.destroy_plane_state 4246dd7b6ceSThomas Zimmermann * for shadow-buffered planes. It expects that mappings of shadow buffers 4256dd7b6ceSThomas Zimmermann * have been released already. 4266dd7b6ceSThomas Zimmermann */ 4276dd7b6ceSThomas Zimmermann void drm_gem_simple_kms_destroy_shadow_plane_state(struct drm_simple_display_pipe *pipe, 4286dd7b6ceSThomas Zimmermann struct drm_plane_state *plane_state) 4296dd7b6ceSThomas Zimmermann { 4306dd7b6ceSThomas Zimmermann drm_gem_destroy_shadow_plane_state(&pipe->plane, plane_state); 4316dd7b6ceSThomas Zimmermann } 4326dd7b6ceSThomas Zimmermann EXPORT_SYMBOL(drm_gem_simple_kms_destroy_shadow_plane_state); 433