1 // SPDX-License-Identifier: GPL-2.0+ 2 3 #include "vkms_config.h" 4 #include <linux/iosys-map.h> 5 6 #include <drm/drm_atomic.h> 7 #include <drm/drm_atomic_helper.h> 8 #include <drm/drm_blend.h> 9 #include <drm/drm_fourcc.h> 10 #include <drm/drm_gem_atomic_helper.h> 11 #include <drm/drm_gem_framebuffer_helper.h> 12 #include <drm/drm_print.h> 13 14 #include "vkms_drv.h" 15 #include "vkms_formats.h" 16 17 static const u32 vkms_formats[] = { 18 DRM_FORMAT_ARGB8888, 19 DRM_FORMAT_ABGR8888, 20 DRM_FORMAT_BGRA8888, 21 DRM_FORMAT_RGBA8888, 22 DRM_FORMAT_XRGB8888, 23 DRM_FORMAT_XBGR8888, 24 DRM_FORMAT_RGB888, 25 DRM_FORMAT_BGR888, 26 DRM_FORMAT_XRGB16161616, 27 DRM_FORMAT_XBGR16161616, 28 DRM_FORMAT_ARGB16161616, 29 DRM_FORMAT_ABGR16161616, 30 DRM_FORMAT_RGB565, 31 DRM_FORMAT_BGR565, 32 DRM_FORMAT_NV12, 33 DRM_FORMAT_NV16, 34 DRM_FORMAT_NV24, 35 DRM_FORMAT_NV21, 36 DRM_FORMAT_NV61, 37 DRM_FORMAT_NV42, 38 DRM_FORMAT_YUV420, 39 DRM_FORMAT_YUV422, 40 DRM_FORMAT_YUV444, 41 DRM_FORMAT_YVU420, 42 DRM_FORMAT_YVU422, 43 DRM_FORMAT_YVU444, 44 DRM_FORMAT_P010, 45 DRM_FORMAT_P012, 46 DRM_FORMAT_P016, 47 DRM_FORMAT_R1, 48 DRM_FORMAT_R2, 49 DRM_FORMAT_R4, 50 DRM_FORMAT_R8, 51 }; 52 53 static struct drm_plane_state * 54 vkms_plane_duplicate_state(struct drm_plane *plane) 55 { 56 struct vkms_plane_state *vkms_state; 57 struct vkms_frame_info *frame_info; 58 59 vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL); 60 if (!vkms_state) 61 return NULL; 62 63 frame_info = kzalloc(sizeof(*frame_info), GFP_KERNEL); 64 if (!frame_info) { 65 DRM_DEBUG_KMS("Couldn't allocate frame_info\n"); 66 kfree(vkms_state); 67 return NULL; 68 } 69 70 vkms_state->frame_info = frame_info; 71 72 __drm_gem_duplicate_shadow_plane_state(plane, &vkms_state->base); 73 74 return &vkms_state->base.base; 75 } 76 77 static void vkms_plane_destroy_state(struct drm_plane *plane, 78 struct drm_plane_state *old_state) 79 { 80 struct vkms_plane_state *vkms_state = to_vkms_plane_state(old_state); 81 struct drm_crtc *crtc = vkms_state->base.base.crtc; 82 83 if (crtc && vkms_state->frame_info->fb) { 84 /* dropping the reference we acquired in 85 * vkms_primary_plane_update() 86 */ 87 if (drm_framebuffer_read_refcount(vkms_state->frame_info->fb)) 88 drm_framebuffer_put(vkms_state->frame_info->fb); 89 } 90 91 kfree(vkms_state->frame_info); 92 vkms_state->frame_info = NULL; 93 94 __drm_gem_destroy_shadow_plane_state(&vkms_state->base); 95 kfree(vkms_state); 96 } 97 98 static void vkms_plane_reset(struct drm_plane *plane) 99 { 100 struct vkms_plane_state *vkms_state; 101 102 if (plane->state) { 103 vkms_plane_destroy_state(plane, plane->state); 104 plane->state = NULL; /* must be set to NULL here */ 105 } 106 107 vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL); 108 if (!vkms_state) { 109 DRM_ERROR("Cannot allocate vkms_plane_state\n"); 110 return; 111 } 112 113 __drm_gem_reset_shadow_plane(plane, &vkms_state->base); 114 } 115 116 static const struct drm_plane_funcs vkms_plane_funcs = { 117 .update_plane = drm_atomic_helper_update_plane, 118 .disable_plane = drm_atomic_helper_disable_plane, 119 .reset = vkms_plane_reset, 120 .atomic_duplicate_state = vkms_plane_duplicate_state, 121 .atomic_destroy_state = vkms_plane_destroy_state, 122 }; 123 124 static void vkms_plane_atomic_update(struct drm_plane *plane, 125 struct drm_atomic_state *state) 126 { 127 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, 128 plane); 129 struct vkms_plane_state *vkms_plane_state; 130 struct drm_shadow_plane_state *shadow_plane_state; 131 struct drm_framebuffer *fb = new_state->fb; 132 struct vkms_frame_info *frame_info; 133 u32 fmt; 134 135 if (!new_state->crtc || !fb) 136 return; 137 138 fmt = fb->format->format; 139 vkms_plane_state = to_vkms_plane_state(new_state); 140 shadow_plane_state = &vkms_plane_state->base; 141 142 frame_info = vkms_plane_state->frame_info; 143 memcpy(&frame_info->src, &new_state->src, sizeof(struct drm_rect)); 144 memcpy(&frame_info->dst, &new_state->dst, sizeof(struct drm_rect)); 145 frame_info->fb = fb; 146 memcpy(&frame_info->map, &shadow_plane_state->data, sizeof(frame_info->map)); 147 drm_framebuffer_get(frame_info->fb); 148 frame_info->rotation = new_state->rotation; 149 150 vkms_plane_state->pixel_read_line = get_pixel_read_line_function(fmt); 151 get_conversion_matrix_to_argb_u16(fmt, new_state->color_encoding, new_state->color_range, 152 &vkms_plane_state->conversion_matrix); 153 } 154 155 static int vkms_plane_atomic_check(struct drm_plane *plane, 156 struct drm_atomic_state *state) 157 { 158 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, 159 plane); 160 struct drm_crtc_state *crtc_state; 161 int ret; 162 163 if (!new_plane_state->fb || WARN_ON(!new_plane_state->crtc)) 164 return 0; 165 166 crtc_state = drm_atomic_get_crtc_state(state, 167 new_plane_state->crtc); 168 if (IS_ERR(crtc_state)) 169 return PTR_ERR(crtc_state); 170 171 ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, 172 DRM_PLANE_NO_SCALING, 173 DRM_PLANE_NO_SCALING, 174 true, true); 175 if (ret != 0) 176 return ret; 177 178 return 0; 179 } 180 181 static int vkms_prepare_fb(struct drm_plane *plane, 182 struct drm_plane_state *state) 183 { 184 struct drm_shadow_plane_state *shadow_plane_state; 185 struct drm_framebuffer *fb = state->fb; 186 int ret; 187 188 if (!fb) 189 return 0; 190 191 shadow_plane_state = to_drm_shadow_plane_state(state); 192 193 ret = drm_gem_plane_helper_prepare_fb(plane, state); 194 if (ret) 195 return ret; 196 197 return drm_gem_fb_vmap(fb, shadow_plane_state->map, shadow_plane_state->data); 198 } 199 200 static void vkms_cleanup_fb(struct drm_plane *plane, 201 struct drm_plane_state *state) 202 { 203 struct drm_shadow_plane_state *shadow_plane_state; 204 struct drm_framebuffer *fb = state->fb; 205 206 if (!fb) 207 return; 208 209 shadow_plane_state = to_drm_shadow_plane_state(state); 210 211 drm_gem_fb_vunmap(fb, shadow_plane_state->map); 212 } 213 214 static const struct drm_plane_helper_funcs vkms_plane_helper_funcs = { 215 .atomic_update = vkms_plane_atomic_update, 216 .atomic_check = vkms_plane_atomic_check, 217 .prepare_fb = vkms_prepare_fb, 218 .cleanup_fb = vkms_cleanup_fb, 219 }; 220 221 struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev, 222 struct vkms_config_plane *plane_cfg) 223 { 224 struct drm_device *dev = &vkmsdev->drm; 225 struct vkms_plane *plane; 226 227 plane = drmm_universal_plane_alloc(dev, struct vkms_plane, base, 0, 228 &vkms_plane_funcs, 229 vkms_formats, ARRAY_SIZE(vkms_formats), 230 NULL, vkms_config_plane_get_type(plane_cfg), 231 NULL); 232 if (IS_ERR(plane)) 233 return plane; 234 235 drm_plane_helper_add(&plane->base, &vkms_plane_helper_funcs); 236 237 drm_plane_create_rotation_property(&plane->base, DRM_MODE_ROTATE_0, 238 DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK); 239 240 drm_plane_create_color_properties(&plane->base, 241 BIT(DRM_COLOR_YCBCR_BT601) | 242 BIT(DRM_COLOR_YCBCR_BT709) | 243 BIT(DRM_COLOR_YCBCR_BT2020), 244 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | 245 BIT(DRM_COLOR_YCBCR_FULL_RANGE), 246 DRM_COLOR_YCBCR_BT601, 247 DRM_COLOR_YCBCR_FULL_RANGE); 248 249 if (vkms_config_plane_get_default_pipeline(plane_cfg)) 250 vkms_initialize_colorops(&plane->base); 251 252 return plane; 253 } 254