root/drivers/gpu/drm/vkms/vkms_plane.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vkms_plane_duplicate_state
  2. vkms_plane_destroy_state
  3. vkms_plane_reset
  4. vkms_plane_atomic_update
  5. vkms_plane_atomic_check
  6. vkms_prepare_fb
  7. vkms_cleanup_fb
  8. vkms_plane_init

   1 // SPDX-License-Identifier: GPL-2.0+
   2 
   3 #include <drm/drm_atomic.h>
   4 #include <drm/drm_atomic_helper.h>
   5 #include <drm/drm_fourcc.h>
   6 #include <drm/drm_gem_framebuffer_helper.h>
   7 #include <drm/drm_plane_helper.h>
   8 
   9 #include "vkms_drv.h"
  10 
  11 static const u32 vkms_formats[] = {
  12         DRM_FORMAT_XRGB8888,
  13 };
  14 
  15 static const u32 vkms_cursor_formats[] = {
  16         DRM_FORMAT_ARGB8888,
  17 };
  18 
  19 static struct drm_plane_state *
  20 vkms_plane_duplicate_state(struct drm_plane *plane)
  21 {
  22         struct vkms_plane_state *vkms_state;
  23         struct vkms_composer *composer;
  24 
  25         vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL);
  26         if (!vkms_state)
  27                 return NULL;
  28 
  29         composer = kzalloc(sizeof(*composer), GFP_KERNEL);
  30         if (!composer) {
  31                 DRM_DEBUG_KMS("Couldn't allocate composer\n");
  32                 kfree(vkms_state);
  33                 return NULL;
  34         }
  35 
  36         vkms_state->composer = composer;
  37 
  38         __drm_atomic_helper_plane_duplicate_state(plane,
  39                                                   &vkms_state->base);
  40 
  41         return &vkms_state->base;
  42 }
  43 
  44 static void vkms_plane_destroy_state(struct drm_plane *plane,
  45                                      struct drm_plane_state *old_state)
  46 {
  47         struct vkms_plane_state *vkms_state = to_vkms_plane_state(old_state);
  48         struct drm_crtc *crtc = vkms_state->base.crtc;
  49 
  50         if (crtc) {
  51                 /* dropping the reference we acquired in
  52                  * vkms_primary_plane_update()
  53                  */
  54                 if (drm_framebuffer_read_refcount(&vkms_state->composer->fb))
  55                         drm_framebuffer_put(&vkms_state->composer->fb);
  56         }
  57 
  58         kfree(vkms_state->composer);
  59         vkms_state->composer = NULL;
  60 
  61         __drm_atomic_helper_plane_destroy_state(old_state);
  62         kfree(vkms_state);
  63 }
  64 
  65 static void vkms_plane_reset(struct drm_plane *plane)
  66 {
  67         struct vkms_plane_state *vkms_state;
  68 
  69         if (plane->state)
  70                 vkms_plane_destroy_state(plane, plane->state);
  71 
  72         vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL);
  73         if (!vkms_state) {
  74                 DRM_ERROR("Cannot allocate vkms_plane_state\n");
  75                 return;
  76         }
  77 
  78         plane->state = &vkms_state->base;
  79         plane->state->plane = plane;
  80 }
  81 
  82 static const struct drm_plane_funcs vkms_plane_funcs = {
  83         .update_plane           = drm_atomic_helper_update_plane,
  84         .disable_plane          = drm_atomic_helper_disable_plane,
  85         .destroy                = drm_plane_cleanup,
  86         .reset                  = vkms_plane_reset,
  87         .atomic_duplicate_state = vkms_plane_duplicate_state,
  88         .atomic_destroy_state   = vkms_plane_destroy_state,
  89 };
  90 
  91 static void vkms_plane_atomic_update(struct drm_plane *plane,
  92                                      struct drm_plane_state *old_state)
  93 {
  94         struct vkms_plane_state *vkms_plane_state;
  95         struct drm_framebuffer *fb = plane->state->fb;
  96         struct vkms_composer *composer;
  97 
  98         if (!plane->state->crtc || !fb)
  99                 return;
 100 
 101         vkms_plane_state = to_vkms_plane_state(plane->state);
 102 
 103         composer = vkms_plane_state->composer;
 104         memcpy(&composer->src, &plane->state->src, sizeof(struct drm_rect));
 105         memcpy(&composer->dst, &plane->state->dst, sizeof(struct drm_rect));
 106         memcpy(&composer->fb, fb, sizeof(struct drm_framebuffer));
 107         drm_framebuffer_get(&composer->fb);
 108         composer->offset = fb->offsets[0];
 109         composer->pitch = fb->pitches[0];
 110         composer->cpp = fb->format->cpp[0];
 111 }
 112 
 113 static int vkms_plane_atomic_check(struct drm_plane *plane,
 114                                    struct drm_plane_state *state)
 115 {
 116         struct drm_crtc_state *crtc_state;
 117         bool can_position = false;
 118         int ret;
 119 
 120         if (!state->fb | !state->crtc)
 121                 return 0;
 122 
 123         crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
 124         if (IS_ERR(crtc_state))
 125                 return PTR_ERR(crtc_state);
 126 
 127         if (plane->type == DRM_PLANE_TYPE_CURSOR)
 128                 can_position = true;
 129 
 130         ret = drm_atomic_helper_check_plane_state(state, crtc_state,
 131                                                   DRM_PLANE_HELPER_NO_SCALING,
 132                                                   DRM_PLANE_HELPER_NO_SCALING,
 133                                                   can_position, true);
 134         if (ret != 0)
 135                 return ret;
 136 
 137         /* for now primary plane must be visible and full screen */
 138         if (!state->visible && !can_position)
 139                 return -EINVAL;
 140 
 141         return 0;
 142 }
 143 
 144 static int vkms_prepare_fb(struct drm_plane *plane,
 145                            struct drm_plane_state *state)
 146 {
 147         struct drm_gem_object *gem_obj;
 148         int ret;
 149 
 150         if (!state->fb)
 151                 return 0;
 152 
 153         gem_obj = drm_gem_fb_get_obj(state->fb, 0);
 154         ret = vkms_gem_vmap(gem_obj);
 155         if (ret)
 156                 DRM_ERROR("vmap failed: %d\n", ret);
 157 
 158         return drm_gem_fb_prepare_fb(plane, state);
 159 }
 160 
 161 static void vkms_cleanup_fb(struct drm_plane *plane,
 162                             struct drm_plane_state *old_state)
 163 {
 164         struct drm_gem_object *gem_obj;
 165 
 166         if (!old_state->fb)
 167                 return;
 168 
 169         gem_obj = drm_gem_fb_get_obj(old_state->fb, 0);
 170         vkms_gem_vunmap(gem_obj);
 171 }
 172 
 173 static const struct drm_plane_helper_funcs vkms_primary_helper_funcs = {
 174         .atomic_update          = vkms_plane_atomic_update,
 175         .atomic_check           = vkms_plane_atomic_check,
 176         .prepare_fb             = vkms_prepare_fb,
 177         .cleanup_fb             = vkms_cleanup_fb,
 178 };
 179 
 180 struct drm_plane *vkms_plane_init(struct vkms_device *vkmsdev,
 181                                   enum drm_plane_type type, int index)
 182 {
 183         struct drm_device *dev = &vkmsdev->drm;
 184         const struct drm_plane_helper_funcs *funcs;
 185         struct drm_plane *plane;
 186         const u32 *formats;
 187         int ret, nformats;
 188 
 189         plane = kzalloc(sizeof(*plane), GFP_KERNEL);
 190         if (!plane)
 191                 return ERR_PTR(-ENOMEM);
 192 
 193         if (type == DRM_PLANE_TYPE_CURSOR) {
 194                 formats = vkms_cursor_formats;
 195                 nformats = ARRAY_SIZE(vkms_cursor_formats);
 196                 funcs = &vkms_primary_helper_funcs;
 197         } else {
 198                 formats = vkms_formats;
 199                 nformats = ARRAY_SIZE(vkms_formats);
 200                 funcs = &vkms_primary_helper_funcs;
 201         }
 202 
 203         ret = drm_universal_plane_init(dev, plane, 1 << index,
 204                                        &vkms_plane_funcs,
 205                                        formats, nformats,
 206                                        NULL, type, NULL);
 207         if (ret) {
 208                 kfree(plane);
 209                 return ERR_PTR(ret);
 210         }
 211 
 212         drm_plane_helper_add(plane, funcs);
 213 
 214         return plane;
 215 }

/* [<][>][^][v][top][bottom][index][help] */