LCOV - code coverage report
Current view: top level - drivers/gpu/drm - drm_gem_atomic_helper.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 74 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 15 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : 
       3             : #include <linux/dma-resv.h>
       4             : #include <linux/dma-fence-chain.h>
       5             : 
       6             : #include <drm/drm_atomic_state_helper.h>
       7             : #include <drm/drm_atomic_uapi.h>
       8             : #include <drm/drm_gem.h>
       9             : #include <drm/drm_gem_atomic_helper.h>
      10             : #include <drm/drm_gem_framebuffer_helper.h>
      11             : #include <drm/drm_simple_kms_helper.h>
      12             : 
      13             : #include "drm_internal.h"
      14             : 
      15             : /**
      16             :  * DOC: overview
      17             :  *
      18             :  * The GEM atomic helpers library implements generic atomic-commit
      19             :  * functions for drivers that use GEM objects. Currently, it provides
      20             :  * synchronization helpers, and plane state and framebuffer BO mappings
      21             :  * for planes with shadow buffers.
      22             :  *
      23             :  * Before scanout, a plane's framebuffer needs to be synchronized with
      24             :  * possible writers that draw into the framebuffer. All drivers should
      25             :  * call drm_gem_plane_helper_prepare_fb() from their implementation of
      26             :  * struct &drm_plane_helper.prepare_fb . It sets the plane's fence from
      27             :  * the framebuffer so that the DRM core can synchronize access automatically.
      28             :  *
      29             :  * drm_gem_plane_helper_prepare_fb() can also be used directly as
      30             :  * implementation of prepare_fb. For drivers based on
      31             :  * struct drm_simple_display_pipe, drm_gem_simple_display_pipe_prepare_fb()
      32             :  * provides equivalent functionality.
      33             :  *
      34             :  * .. code-block:: c
      35             :  *
      36             :  *      #include <drm/drm_gem_atomic_helper.h>
      37             :  *
      38             :  *      struct drm_plane_helper_funcs driver_plane_helper_funcs = {
      39             :  *              ...,
      40             :  *              . prepare_fb = drm_gem_plane_helper_prepare_fb,
      41             :  *      };
      42             :  *
      43             :  *      struct drm_simple_display_pipe_funcs driver_pipe_funcs = {
      44             :  *              ...,
      45             :  *              . prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
      46             :  *      };
      47             :  *
      48             :  * A driver using a shadow buffer copies the content of the shadow buffers
      49             :  * into the HW's framebuffer memory during an atomic update. This requires
      50             :  * a mapping of the shadow buffer into kernel address space. The mappings
      51             :  * cannot be established by commit-tail functions, such as atomic_update,
      52             :  * as this would violate locking rules around dma_buf_vmap().
      53             :  *
      54             :  * The helpers for shadow-buffered planes establish and release mappings,
      55             :  * and provide struct drm_shadow_plane_state, which stores the plane's mapping
      56             :  * for commit-tail functions.
      57             :  *
      58             :  * Shadow-buffered planes can easily be enabled by using the provided macros
      59             :  * %DRM_GEM_SHADOW_PLANE_FUNCS and %DRM_GEM_SHADOW_PLANE_HELPER_FUNCS.
      60             :  * These macros set up the plane and plane-helper callbacks to point to the
      61             :  * shadow-buffer helpers.
      62             :  *
      63             :  * .. code-block:: c
      64             :  *
      65             :  *      #include <drm/drm_gem_atomic_helper.h>
      66             :  *
      67             :  *      struct drm_plane_funcs driver_plane_funcs = {
      68             :  *              ...,
      69             :  *              DRM_GEM_SHADOW_PLANE_FUNCS,
      70             :  *      };
      71             :  *
      72             :  *      struct drm_plane_helper_funcs driver_plane_helper_funcs = {
      73             :  *              ...,
      74             :  *              DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
      75             :  *      };
      76             :  *
      77             :  * In the driver's atomic-update function, shadow-buffer mappings are available
      78             :  * from the plane state. Use to_drm_shadow_plane_state() to upcast from
      79             :  * struct drm_plane_state.
      80             :  *
      81             :  * .. code-block:: c
      82             :  *
      83             :  *      void driver_plane_atomic_update(struct drm_plane *plane,
      84             :  *                                      struct drm_plane_state *old_plane_state)
      85             :  *      {
      86             :  *              struct drm_plane_state *plane_state = plane->state;
      87             :  *              struct drm_shadow_plane_state *shadow_plane_state =
      88             :  *                      to_drm_shadow_plane_state(plane_state);
      89             :  *
      90             :  *              // access shadow buffer via shadow_plane_state->map
      91             :  *      }
      92             :  *
      93             :  * A mapping address for each of the framebuffer's buffer object is stored in
      94             :  * struct &drm_shadow_plane_state.map. The mappings are valid while the state
      95             :  * is being used.
      96             :  *
      97             :  * Drivers that use struct drm_simple_display_pipe can use
      98             :  * %DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS to initialize the rsp
      99             :  * callbacks. Access to shadow-buffer mappings is similar to regular
     100             :  * atomic_update.
     101             :  *
     102             :  * .. code-block:: c
     103             :  *
     104             :  *      struct drm_simple_display_pipe_funcs driver_pipe_funcs = {
     105             :  *              ...,
     106             :  *              DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
     107             :  *      };
     108             :  *
     109             :  *      void driver_pipe_enable(struct drm_simple_display_pipe *pipe,
     110             :  *                              struct drm_crtc_state *crtc_state,
     111             :  *                              struct drm_plane_state *plane_state)
     112             :  *      {
     113             :  *              struct drm_shadow_plane_state *shadow_plane_state =
     114             :  *                      to_drm_shadow_plane_state(plane_state);
     115             :  *
     116             :  *              // access shadow buffer via shadow_plane_state->map
     117             :  *      }
     118             :  */
     119             : 
     120             : /*
     121             :  * Plane Helpers
     122             :  */
     123             : 
     124             : /**
     125             :  * drm_gem_plane_helper_prepare_fb() - Prepare a GEM backed framebuffer
     126             :  * @plane: Plane
     127             :  * @state: Plane state the fence will be attached to
     128             :  *
     129             :  * This function extracts the exclusive fence from &drm_gem_object.resv and
     130             :  * attaches it to plane state for the atomic helper to wait on. This is
     131             :  * necessary to correctly implement implicit synchronization for any buffers
     132             :  * shared as a struct &dma_buf. This function can be used as the
     133             :  * &drm_plane_helper_funcs.prepare_fb callback.
     134             :  *
     135             :  * There is no need for &drm_plane_helper_funcs.cleanup_fb hook for simple
     136             :  * GEM based framebuffer drivers which have their buffers always pinned in
     137             :  * memory.
     138             :  *
     139             :  * This function is the default implementation for GEM drivers of
     140             :  * &drm_plane_helper_funcs.prepare_fb if no callback is provided.
     141             :  */
     142           0 : int drm_gem_plane_helper_prepare_fb(struct drm_plane *plane,
     143             :                                     struct drm_plane_state *state)
     144             : {
     145           0 :         struct dma_fence *fence = dma_fence_get(state->fence);
     146             :         enum dma_resv_usage usage;
     147             :         size_t i;
     148             :         int ret;
     149             : 
     150           0 :         if (!state->fb)
     151             :                 return 0;
     152             : 
     153             :         /*
     154             :          * Only add the kernel fences here if there is already a fence set via
     155             :          * explicit fencing interfaces on the atomic ioctl.
     156             :          *
     157             :          * This way explicit fencing can be used to overrule implicit fencing,
     158             :          * which is important to make explicit fencing use-cases work: One
     159             :          * example is using one buffer for 2 screens with different refresh
     160             :          * rates. Implicit fencing will clamp rendering to the refresh rate of
     161             :          * the slower screen, whereas explicit fence allows 2 independent
     162             :          * render and display loops on a single buffer. If a driver allows
     163             :          * obeys both implicit and explicit fences for plane updates, then it
     164             :          * will break all the benefits of explicit fencing.
     165             :          */
     166           0 :         usage = fence ? DMA_RESV_USAGE_KERNEL : DMA_RESV_USAGE_WRITE;
     167             : 
     168           0 :         for (i = 0; i < state->fb->format->num_planes; ++i) {
     169           0 :                 struct drm_gem_object *obj = drm_gem_fb_get_obj(state->fb, i);
     170             :                 struct dma_fence *new;
     171             : 
     172           0 :                 if (WARN_ON_ONCE(!obj))
     173           0 :                         continue;
     174             : 
     175           0 :                 ret = dma_resv_get_singleton(obj->resv, usage, &new);
     176           0 :                 if (ret)
     177             :                         goto error;
     178             : 
     179           0 :                 if (new && fence) {
     180           0 :                         struct dma_fence_chain *chain = dma_fence_chain_alloc();
     181             : 
     182           0 :                         if (!chain) {
     183             :                                 ret = -ENOMEM;
     184             :                                 goto error;
     185             :                         }
     186             : 
     187           0 :                         dma_fence_chain_init(chain, fence, new, 1);
     188           0 :                         fence = &chain->base;
     189             : 
     190           0 :                 } else if (new) {
     191           0 :                         fence = new;
     192             :                 }
     193             :         }
     194             : 
     195           0 :         dma_fence_put(state->fence);
     196           0 :         state->fence = fence;
     197           0 :         return 0;
     198             : 
     199             : error:
     200             :         dma_fence_put(fence);
     201             :         return ret;
     202             : }
     203             : EXPORT_SYMBOL_GPL(drm_gem_plane_helper_prepare_fb);
     204             : 
     205             : /**
     206             :  * drm_gem_simple_display_pipe_prepare_fb - prepare_fb helper for &drm_simple_display_pipe
     207             :  * @pipe: Simple display pipe
     208             :  * @plane_state: Plane state
     209             :  *
     210             :  * This function uses drm_gem_plane_helper_prepare_fb() to extract the fences
     211             :  * from &drm_gem_object.resv and attaches them to the plane state for the atomic
     212             :  * helper to wait on. This is necessary to correctly implement implicit
     213             :  * synchronization for any buffers shared as a struct &dma_buf. Drivers can use
     214             :  * this as their &drm_simple_display_pipe_funcs.prepare_fb callback.
     215             :  *
     216             :  * See drm_gem_plane_helper_prepare_fb() for a discussion of implicit and
     217             :  * explicit fencing in atomic modeset updates.
     218             :  */
     219           0 : int drm_gem_simple_display_pipe_prepare_fb(struct drm_simple_display_pipe *pipe,
     220             :                                            struct drm_plane_state *plane_state)
     221             : {
     222           0 :         return drm_gem_plane_helper_prepare_fb(&pipe->plane, plane_state);
     223             : }
     224             : EXPORT_SYMBOL(drm_gem_simple_display_pipe_prepare_fb);
     225             : 
     226             : /*
     227             :  * Shadow-buffered Planes
     228             :  */
     229             : 
     230             : /**
     231             :  * __drm_gem_duplicate_shadow_plane_state - duplicates shadow-buffered plane state
     232             :  * @plane: the plane
     233             :  * @new_shadow_plane_state: the new shadow-buffered plane state
     234             :  *
     235             :  * This function duplicates shadow-buffered plane state. This is helpful for drivers
     236             :  * that subclass struct drm_shadow_plane_state.
     237             :  *
     238             :  * The function does not duplicate existing mappings of the shadow buffers.
     239             :  * Mappings are maintained during the atomic commit by the plane's prepare_fb
     240             :  * and cleanup_fb helpers. See drm_gem_prepare_shadow_fb() and drm_gem_cleanup_shadow_fb()
     241             :  * for corresponding helpers.
     242             :  */
     243             : void
     244           0 : __drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane,
     245             :                                        struct drm_shadow_plane_state *new_shadow_plane_state)
     246             : {
     247           0 :         __drm_atomic_helper_plane_duplicate_state(plane, &new_shadow_plane_state->base);
     248           0 : }
     249             : EXPORT_SYMBOL(__drm_gem_duplicate_shadow_plane_state);
     250             : 
     251             : /**
     252             :  * drm_gem_duplicate_shadow_plane_state - duplicates shadow-buffered plane state
     253             :  * @plane: the plane
     254             :  *
     255             :  * This function implements struct &drm_plane_funcs.atomic_duplicate_state for
     256             :  * shadow-buffered planes. It assumes the existing state to be of type
     257             :  * struct drm_shadow_plane_state and it allocates the new state to be of this
     258             :  * type.
     259             :  *
     260             :  * The function does not duplicate existing mappings of the shadow buffers.
     261             :  * Mappings are maintained during the atomic commit by the plane's prepare_fb
     262             :  * and cleanup_fb helpers. See drm_gem_prepare_shadow_fb() and drm_gem_cleanup_shadow_fb()
     263             :  * for corresponding helpers.
     264             :  *
     265             :  * Returns:
     266             :  * A pointer to a new plane state on success, or NULL otherwise.
     267             :  */
     268             : struct drm_plane_state *
     269           0 : drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane)
     270             : {
     271           0 :         struct drm_plane_state *plane_state = plane->state;
     272             :         struct drm_shadow_plane_state *new_shadow_plane_state;
     273             : 
     274           0 :         if (!plane_state)
     275             :                 return NULL;
     276             : 
     277           0 :         new_shadow_plane_state = kzalloc(sizeof(*new_shadow_plane_state), GFP_KERNEL);
     278           0 :         if (!new_shadow_plane_state)
     279             :                 return NULL;
     280           0 :         __drm_gem_duplicate_shadow_plane_state(plane, new_shadow_plane_state);
     281             : 
     282           0 :         return &new_shadow_plane_state->base;
     283             : }
     284             : EXPORT_SYMBOL(drm_gem_duplicate_shadow_plane_state);
     285             : 
     286             : /**
     287             :  * __drm_gem_destroy_shadow_plane_state - cleans up shadow-buffered plane state
     288             :  * @shadow_plane_state: the shadow-buffered plane state
     289             :  *
     290             :  * This function cleans up shadow-buffered plane state. Helpful for drivers that
     291             :  * subclass struct drm_shadow_plane_state.
     292             :  */
     293           0 : void __drm_gem_destroy_shadow_plane_state(struct drm_shadow_plane_state *shadow_plane_state)
     294             : {
     295           0 :         __drm_atomic_helper_plane_destroy_state(&shadow_plane_state->base);
     296           0 : }
     297             : EXPORT_SYMBOL(__drm_gem_destroy_shadow_plane_state);
     298             : 
     299             : /**
     300             :  * drm_gem_destroy_shadow_plane_state - deletes shadow-buffered plane state
     301             :  * @plane: the plane
     302             :  * @plane_state: the plane state of type struct drm_shadow_plane_state
     303             :  *
     304             :  * This function implements struct &drm_plane_funcs.atomic_destroy_state
     305             :  * for shadow-buffered planes. It expects that mappings of shadow buffers
     306             :  * have been released already.
     307             :  */
     308           0 : void drm_gem_destroy_shadow_plane_state(struct drm_plane *plane,
     309             :                                         struct drm_plane_state *plane_state)
     310             : {
     311           0 :         struct drm_shadow_plane_state *shadow_plane_state =
     312             :                 to_drm_shadow_plane_state(plane_state);
     313             : 
     314           0 :         __drm_gem_destroy_shadow_plane_state(shadow_plane_state);
     315           0 :         kfree(shadow_plane_state);
     316           0 : }
     317             : EXPORT_SYMBOL(drm_gem_destroy_shadow_plane_state);
     318             : 
     319             : /**
     320             :  * __drm_gem_reset_shadow_plane - resets a shadow-buffered plane
     321             :  * @plane: the plane
     322             :  * @shadow_plane_state: the shadow-buffered plane state
     323             :  *
     324             :  * This function resets state for shadow-buffered planes. Helpful
     325             :  * for drivers that subclass struct drm_shadow_plane_state.
     326             :  */
     327           0 : void __drm_gem_reset_shadow_plane(struct drm_plane *plane,
     328             :                                   struct drm_shadow_plane_state *shadow_plane_state)
     329             : {
     330           0 :         __drm_atomic_helper_plane_reset(plane, &shadow_plane_state->base);
     331           0 : }
     332             : EXPORT_SYMBOL(__drm_gem_reset_shadow_plane);
     333             : 
     334             : /**
     335             :  * drm_gem_reset_shadow_plane - resets a shadow-buffered plane
     336             :  * @plane: the plane
     337             :  *
     338             :  * This function implements struct &drm_plane_funcs.reset_plane for
     339             :  * shadow-buffered planes. It assumes the current plane state to be
     340             :  * of type struct drm_shadow_plane and it allocates the new state of
     341             :  * this type.
     342             :  */
     343           0 : void drm_gem_reset_shadow_plane(struct drm_plane *plane)
     344             : {
     345             :         struct drm_shadow_plane_state *shadow_plane_state;
     346             : 
     347           0 :         if (plane->state) {
     348           0 :                 drm_gem_destroy_shadow_plane_state(plane, plane->state);
     349           0 :                 plane->state = NULL; /* must be set to NULL here */
     350             :         }
     351             : 
     352           0 :         shadow_plane_state = kzalloc(sizeof(*shadow_plane_state), GFP_KERNEL);
     353           0 :         if (!shadow_plane_state)
     354             :                 return;
     355             :         __drm_gem_reset_shadow_plane(plane, shadow_plane_state);
     356             : }
     357             : EXPORT_SYMBOL(drm_gem_reset_shadow_plane);
     358             : 
     359             : /**
     360             :  * drm_gem_prepare_shadow_fb - prepares shadow framebuffers
     361             :  * @plane: the plane
     362             :  * @plane_state: the plane state of type struct drm_shadow_plane_state
     363             :  *
     364             :  * This function implements struct &drm_plane_helper_funcs.prepare_fb. It
     365             :  * maps all buffer objects of the plane's framebuffer into kernel address
     366             :  * space and stores them in &struct drm_shadow_plane_state.map. The
     367             :  * framebuffer will be synchronized as part of the atomic commit.
     368             :  *
     369             :  * See drm_gem_cleanup_shadow_fb() for cleanup.
     370             :  *
     371             :  * Returns:
     372             :  * 0 on success, or a negative errno code otherwise.
     373             :  */
     374           0 : int drm_gem_prepare_shadow_fb(struct drm_plane *plane, struct drm_plane_state *plane_state)
     375             : {
     376           0 :         struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
     377           0 :         struct drm_framebuffer *fb = plane_state->fb;
     378             :         int ret;
     379             : 
     380           0 :         if (!fb)
     381             :                 return 0;
     382             : 
     383           0 :         ret = drm_gem_plane_helper_prepare_fb(plane, plane_state);
     384           0 :         if (ret)
     385             :                 return ret;
     386             : 
     387           0 :         return drm_gem_fb_vmap(fb, shadow_plane_state->map, shadow_plane_state->data);
     388             : }
     389             : EXPORT_SYMBOL(drm_gem_prepare_shadow_fb);
     390             : 
     391             : /**
     392             :  * drm_gem_cleanup_shadow_fb - releases shadow framebuffers
     393             :  * @plane: the plane
     394             :  * @plane_state: the plane state of type struct drm_shadow_plane_state
     395             :  *
     396             :  * This function implements struct &drm_plane_helper_funcs.cleanup_fb.
     397             :  * This function unmaps all buffer objects of the plane's framebuffer.
     398             :  *
     399             :  * See drm_gem_prepare_shadow_fb() for more information.
     400             :  */
     401           0 : void drm_gem_cleanup_shadow_fb(struct drm_plane *plane, struct drm_plane_state *plane_state)
     402             : {
     403           0 :         struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
     404           0 :         struct drm_framebuffer *fb = plane_state->fb;
     405             : 
     406           0 :         if (!fb)
     407             :                 return;
     408             : 
     409           0 :         drm_gem_fb_vunmap(fb, shadow_plane_state->map);
     410             : }
     411             : EXPORT_SYMBOL(drm_gem_cleanup_shadow_fb);
     412             : 
     413             : /**
     414             :  * drm_gem_simple_kms_prepare_shadow_fb - prepares shadow framebuffers
     415             :  * @pipe: the simple display pipe
     416             :  * @plane_state: the plane state of type struct drm_shadow_plane_state
     417             :  *
     418             :  * This function implements struct drm_simple_display_funcs.prepare_fb. It
     419             :  * maps all buffer objects of the plane's framebuffer into kernel address
     420             :  * space and stores them in struct drm_shadow_plane_state.map. The
     421             :  * framebuffer will be synchronized as part of the atomic commit.
     422             :  *
     423             :  * See drm_gem_simple_kms_cleanup_shadow_fb() for cleanup.
     424             :  *
     425             :  * Returns:
     426             :  * 0 on success, or a negative errno code otherwise.
     427             :  */
     428           0 : int drm_gem_simple_kms_prepare_shadow_fb(struct drm_simple_display_pipe *pipe,
     429             :                                          struct drm_plane_state *plane_state)
     430             : {
     431           0 :         return drm_gem_prepare_shadow_fb(&pipe->plane, plane_state);
     432             : }
     433             : EXPORT_SYMBOL(drm_gem_simple_kms_prepare_shadow_fb);
     434             : 
     435             : /**
     436             :  * drm_gem_simple_kms_cleanup_shadow_fb - releases shadow framebuffers
     437             :  * @pipe: the simple display pipe
     438             :  * @plane_state: the plane state of type struct drm_shadow_plane_state
     439             :  *
     440             :  * This function implements struct drm_simple_display_funcs.cleanup_fb.
     441             :  * This function unmaps all buffer objects of the plane's framebuffer.
     442             :  *
     443             :  * See drm_gem_simple_kms_prepare_shadow_fb().
     444             :  */
     445           0 : void drm_gem_simple_kms_cleanup_shadow_fb(struct drm_simple_display_pipe *pipe,
     446             :                                           struct drm_plane_state *plane_state)
     447             : {
     448           0 :         drm_gem_cleanup_shadow_fb(&pipe->plane, plane_state);
     449           0 : }
     450             : EXPORT_SYMBOL(drm_gem_simple_kms_cleanup_shadow_fb);
     451             : 
     452             : /**
     453             :  * drm_gem_simple_kms_reset_shadow_plane - resets a shadow-buffered plane
     454             :  * @pipe: the simple display pipe
     455             :  *
     456             :  * This function implements struct drm_simple_display_funcs.reset_plane
     457             :  * for shadow-buffered planes.
     458             :  */
     459           0 : void drm_gem_simple_kms_reset_shadow_plane(struct drm_simple_display_pipe *pipe)
     460             : {
     461           0 :         drm_gem_reset_shadow_plane(&pipe->plane);
     462           0 : }
     463             : EXPORT_SYMBOL(drm_gem_simple_kms_reset_shadow_plane);
     464             : 
     465             : /**
     466             :  * drm_gem_simple_kms_duplicate_shadow_plane_state - duplicates shadow-buffered plane state
     467             :  * @pipe: the simple display pipe
     468             :  *
     469             :  * This function implements struct drm_simple_display_funcs.duplicate_plane_state
     470             :  * for shadow-buffered planes. It does not duplicate existing mappings of the shadow
     471             :  * buffers. Mappings are maintained during the atomic commit by the plane's prepare_fb
     472             :  * and cleanup_fb helpers.
     473             :  *
     474             :  * Returns:
     475             :  * A pointer to a new plane state on success, or NULL otherwise.
     476             :  */
     477             : struct drm_plane_state *
     478           0 : drm_gem_simple_kms_duplicate_shadow_plane_state(struct drm_simple_display_pipe *pipe)
     479             : {
     480           0 :         return drm_gem_duplicate_shadow_plane_state(&pipe->plane);
     481             : }
     482             : EXPORT_SYMBOL(drm_gem_simple_kms_duplicate_shadow_plane_state);
     483             : 
     484             : /**
     485             :  * drm_gem_simple_kms_destroy_shadow_plane_state - resets shadow-buffered plane state
     486             :  * @pipe: the simple display pipe
     487             :  * @plane_state: the plane state of type struct drm_shadow_plane_state
     488             :  *
     489             :  * This function implements struct drm_simple_display_funcs.destroy_plane_state
     490             :  * for shadow-buffered planes. It expects that mappings of shadow buffers
     491             :  * have been released already.
     492             :  */
     493           0 : void drm_gem_simple_kms_destroy_shadow_plane_state(struct drm_simple_display_pipe *pipe,
     494             :                                                    struct drm_plane_state *plane_state)
     495             : {
     496           0 :         drm_gem_destroy_shadow_plane_state(&pipe->plane, plane_state);
     497           0 : }
     498             : EXPORT_SYMBOL(drm_gem_simple_kms_destroy_shadow_plane_state);

Generated by: LCOV version 1.14