1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2020 VeriSilicon Holdings Co., Ltd.
6 #include <drm/drm_atomic.h>
7 #include <drm/drm_atomic_helper.h>
8 #include <drm/drm_plane_helper.h>
9 #include <drm/drm_fb_cma_helper.h>
10 #include <drm/drm_gem_cma_helper.h>
11 #include <drm/vs_drm.h>
12 #include <soc/starfive/vic7100.h>
20 void vs_plane_destory(struct drm_plane *plane)
22 struct vs_plane *vs_plane = to_vs_plane(plane);
24 drm_plane_cleanup(plane);
28 static void vs_plane_reset(struct drm_plane *plane)
30 struct vs_plane_state *state;
31 struct vs_plane *vs_plane = to_vs_plane(plane);
34 __drm_atomic_helper_plane_destroy_state(plane->state);
36 state = to_vs_plane_state(plane->state);
41 state = kzalloc(sizeof(*state), GFP_KERNEL);
45 __drm_atomic_helper_plane_reset(plane, &state->base);
47 state->degamma = VS_DEGAMMA_DISABLE;
48 state->degamma_changed = false;
49 state->base.zpos = vs_plane->id;
51 memset(&state->status, 0, sizeof(state->status));
54 static void _vs_plane_duplicate_blob(struct vs_plane_state *state,
55 struct vs_plane_state *ori_state)
57 state->watermark = ori_state->watermark;
58 state->color_mgmt = ori_state->color_mgmt;
59 state->roi = ori_state->roi;
62 drm_property_blob_get(state->watermark);
63 if (state->color_mgmt)
64 drm_property_blob_get(state->color_mgmt);
66 drm_property_blob_get(state->roi);
70 _vs_plane_set_property_blob_from_id(struct drm_device *dev,
71 struct drm_property_blob **blob,
75 struct drm_property_blob *new_blob = NULL;
78 new_blob = drm_property_lookup_blob(dev, blob_id);
82 if (new_blob->length != expected_size) {
83 drm_property_blob_put(new_blob);
88 drm_property_replace_blob(blob, new_blob);
89 drm_property_blob_put(new_blob);
94 static struct drm_plane_state *
95 vs_plane_atomic_duplicate_state(struct drm_plane *plane)
97 struct vs_plane_state *ori_state;
98 struct vs_plane_state *state;
100 if (WARN_ON(!plane->state))
103 ori_state = to_vs_plane_state(plane->state);
104 state = kzalloc(sizeof(*state), GFP_KERNEL);
108 __drm_atomic_helper_plane_duplicate_state(plane, &state->base);
110 state->degamma = ori_state->degamma;
111 state->degamma_changed = ori_state->degamma_changed;
113 _vs_plane_duplicate_blob(state, ori_state);
114 memcpy(&state->status, &ori_state->status, sizeof(ori_state->status));
119 static void vs_plane_atomic_destroy_state(struct drm_plane *plane,
120 struct drm_plane_state *state)
122 struct vs_plane_state *vs_plane_state = to_vs_plane_state(state);
124 __drm_atomic_helper_plane_destroy_state(state);
126 drm_property_blob_put(vs_plane_state->watermark);
127 drm_property_blob_put(vs_plane_state->color_mgmt);
128 drm_property_blob_put(vs_plane_state->roi);
129 kfree(vs_plane_state);
132 static int vs_plane_atomic_set_property(struct drm_plane *plane,
133 struct drm_plane_state *state,
134 struct drm_property *property,
137 struct drm_device *dev = plane->dev;
138 struct vs_plane *vs_plane = to_vs_plane(plane);
139 struct vs_plane_state *vs_plane_state = to_vs_plane_state(state);
142 if (property == vs_plane->degamma_mode) {
143 if (vs_plane_state->degamma != val) {
144 vs_plane_state->degamma = val;
145 vs_plane_state->degamma_changed = true;
147 vs_plane_state->degamma_changed = false;
149 } else if (property == vs_plane->watermark_prop) {
150 ret = _vs_plane_set_property_blob_from_id(dev,
151 &vs_plane_state->watermark,
152 val, sizeof(struct drm_vs_watermark));
154 } else if (property == vs_plane->color_mgmt_prop) {
155 ret = _vs_plane_set_property_blob_from_id(dev,
156 &vs_plane_state->color_mgmt,
157 val, sizeof(struct drm_vs_color_mgmt));
159 } else if (property == vs_plane->roi_prop) {
160 ret = _vs_plane_set_property_blob_from_id(dev,
161 &vs_plane_state->roi,
162 val, sizeof(struct drm_vs_roi));
171 static int vs_plane_atomic_get_property(struct drm_plane *plane,
172 const struct drm_plane_state *state,
173 struct drm_property *property,
176 struct vs_plane *vs_plane = to_vs_plane(plane);
177 const struct vs_plane_state *vs_plane_state =
178 container_of(state, const struct vs_plane_state, base);
180 if (property == vs_plane->degamma_mode)
181 *val = vs_plane_state->degamma;
182 else if (property == vs_plane->watermark_prop)
183 *val = (vs_plane_state->watermark) ?
184 vs_plane_state->watermark->base.id : 0;
185 else if (property == vs_plane->color_mgmt_prop)
186 *val = (vs_plane_state->color_mgmt) ?
187 vs_plane_state->color_mgmt->base.id : 0;
188 else if (property == vs_plane->roi_prop)
189 *val = (vs_plane_state->roi) ?
190 vs_plane_state->roi->base.id : 0;
197 static bool vs_format_mod_supported(struct drm_plane *plane,
204 * We always have to allow these modifiers:
205 * 1. Core DRM checks for LINEAR support if userspace does not provide modifiers.
206 * 2. Not passing any modifiers is the same as explicitly passing INVALID.
208 if (modifier == DRM_FORMAT_MOD_LINEAR) {
212 /* Check that the modifier is on the list of the plane's supported modifiers. */
213 for (i = 0; i < plane->modifier_count; i++) {
214 if (modifier == plane->modifiers[i])
217 if (i == plane->modifier_count)
224 const struct drm_plane_funcs vs_plane_funcs = {
225 .update_plane = drm_atomic_helper_update_plane,
226 .disable_plane = drm_atomic_helper_disable_plane,
227 .destroy = vs_plane_destory,
228 .reset = vs_plane_reset,
229 .atomic_duplicate_state = vs_plane_atomic_duplicate_state,
230 .atomic_destroy_state = vs_plane_atomic_destroy_state,
231 .atomic_set_property = vs_plane_atomic_set_property,
232 .atomic_get_property = vs_plane_atomic_get_property,
233 .format_mod_supported = vs_format_mod_supported,
236 static unsigned char vs_get_plane_number(struct drm_framebuffer *fb)
238 const struct drm_format_info *info;
243 info = drm_format_info(fb->format->format);
244 if (!info || info->num_planes > MAX_NUM_PLANES)
247 return info->num_planes;
251 static int vs_plane_atomic_check(struct drm_plane *plane,
252 struct drm_atomic_state *state)
254 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
256 struct vs_plane *vs_plane = to_vs_plane(plane);
257 struct drm_framebuffer *fb = new_plane_state->fb;
258 struct drm_crtc *crtc = new_plane_state->crtc;
259 struct vs_crtc *vs_crtc = to_vs_crtc(crtc);
264 //return vs_plane->funcs->check(vs_crtc->dev, vs_plane, new_plane_state);
265 return vs_plane->funcs->check(vs_crtc->dev, plane, state);
268 static void vs_plane_atomic_update(struct drm_plane *plane,
269 struct drm_atomic_state *state)
271 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
273 unsigned char i, num_planes;
274 struct drm_framebuffer *fb;
275 struct vs_plane *vs_plane = to_vs_plane(plane);
276 //struct drm_plane_state *state = plane->state;
277 struct vs_crtc *vs_crtc = to_vs_crtc(new_state->crtc);
278 struct vs_plane_state *plane_state = to_vs_plane_state(new_state);
279 //struct drm_format_name_buf *name = &plane_state->status.format_name;
281 if (!new_state->fb || !new_state->crtc)
286 num_planes = vs_get_plane_number(fb);
288 for (i = 0; i < num_planes; i++) {
289 struct vs_gem_object *vs_obj;
291 vs_obj = vs_fb_get_gem_obj(fb, i);
292 vs_plane->dma_addr[i] = vs_obj->iova + fb->offsets[i];
293 starfive_flush_dcache(vs_plane->dma_addr[i], vs_obj->size);
296 plane_state->status.src = drm_plane_state_src(new_state);
297 plane_state->status.dest = drm_plane_state_dest(new_state);
298 //drm_get_format_name(fb->format->format, name);
300 vs_plane->funcs->update(vs_crtc->dev, vs_plane, plane, state);
303 static void vs_plane_atomic_disable(struct drm_plane *plane,
304 struct drm_atomic_state *state)
306 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
308 struct vs_plane *vs_plane = to_vs_plane(plane);
309 struct vs_crtc *vs_crtc = to_vs_crtc(old_state->crtc);
311 vs_plane->funcs->disable(vs_crtc->dev, vs_plane, old_state);
314 const struct drm_plane_helper_funcs vs_plane_helper_funcs = {
315 .atomic_check = vs_plane_atomic_check,
316 .atomic_update = vs_plane_atomic_update,
317 .atomic_disable = vs_plane_atomic_disable,
320 static const struct drm_prop_enum_list vs_degamma_mode_enum_list[] = {
321 { VS_DEGAMMA_DISABLE, "disabled" },
322 { VS_DEGAMMA_BT709, "preset degamma for BT709" },
323 { VS_DEGAMMA_BT2020, "preset degamma for BT2020" },
326 struct vs_plane *vs_plane_create(struct drm_device *drm_dev,
327 struct vs_plane_info *info,
328 unsigned int layer_num,
329 unsigned int possible_crtcs)
331 struct vs_plane *plane;
337 plane = kzalloc(sizeof(struct vs_plane), GFP_KERNEL);
341 ret = drm_universal_plane_init(drm_dev, &plane->base, possible_crtcs,
342 &vs_plane_funcs, info->formats,
343 info->num_formats, info->modifiers, info->type,
344 info->name ? info->name : NULL);
348 drm_plane_helper_add(&plane->base, &vs_plane_helper_funcs);
350 /* Set up the plane properties */
351 if (info->degamma_size) {
352 plane->degamma_mode = drm_property_create_enum(drm_dev, 0,
354 vs_degamma_mode_enum_list,
355 ARRAY_SIZE(vs_degamma_mode_enum_list));
357 if (!plane->degamma_mode)
358 goto error_cleanup_plane;
360 drm_object_attach_property(&plane->base.base,
365 if (info->rotation) {
366 ret = drm_plane_create_rotation_property(&plane->base,
370 goto error_cleanup_plane;
373 if (info->blend_mode) {
374 ret = drm_plane_create_blend_mode_property(&plane->base,
377 goto error_cleanup_plane;
378 ret = drm_plane_create_alpha_property(&plane->base);
380 goto error_cleanup_plane;
383 if (info->color_encoding) {
384 ret = drm_plane_create_color_properties(&plane->base,
385 info->color_encoding,
386 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
387 DRM_COLOR_YCBCR_BT709,
388 DRM_COLOR_YCBCR_LIMITED_RANGE);
390 goto error_cleanup_plane;
393 if (info->zpos != 255) {
394 ret = drm_plane_create_zpos_property(&plane->base, info->zpos, 0, layer_num - 1);
396 goto error_cleanup_plane;
398 #if KERNEL_VERSION(5, 8, 0) <= LINUX_VERSION_CODE
400 ret = drm_plane_create_zpos_immutable_property(&plane->base,
403 goto error_cleanup_plane;
407 if (info->watermark) {
408 plane->watermark_prop = drm_property_create(drm_dev, DRM_MODE_PROP_BLOB,
410 if (!plane->watermark_prop)
411 goto error_cleanup_plane;
413 drm_object_attach_property(&plane->base.base, plane->watermark_prop, 0);
416 if (info->color_mgmt) {
417 plane->color_mgmt_prop = drm_property_create(drm_dev, DRM_MODE_PROP_BLOB,
419 if (!plane->color_mgmt_prop)
420 goto error_cleanup_plane;
422 drm_object_attach_property(&plane->base.base, plane->color_mgmt_prop, 0);
426 plane->roi_prop = drm_property_create(drm_dev, DRM_MODE_PROP_BLOB,
428 if (!plane->roi_prop)
429 goto error_cleanup_plane;
431 drm_object_attach_property(&plane->base.base, plane->roi_prop, 0);
437 drm_plane_cleanup(&plane->base);