summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/vkms/vkms_plane.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/vkms/vkms_plane.c')
-rw-r--r--drivers/gpu/drm/vkms/vkms_plane.c242
1 files changed, 142 insertions, 100 deletions
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
index 418817600ad1..19fe6acad306 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -1,60 +1,97 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
+
+#include "vkms_config.h"
+#include <linux/iosys-map.h>
-#include "vkms_drv.h"
-#include <drm/drm_plane_helper.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_blend.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_print.h>
+
+#include "vkms_drv.h"
+#include "vkms_formats.h"
+
+static const u32 vkms_formats[] = {
+ DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_ABGR8888,
+ DRM_FORMAT_BGRA8888,
+ DRM_FORMAT_RGBA8888,
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_RGB888,
+ DRM_FORMAT_BGR888,
+ DRM_FORMAT_XRGB16161616,
+ DRM_FORMAT_XBGR16161616,
+ DRM_FORMAT_ARGB16161616,
+ DRM_FORMAT_ABGR16161616,
+ DRM_FORMAT_RGB565,
+ DRM_FORMAT_BGR565,
+ DRM_FORMAT_NV12,
+ DRM_FORMAT_NV16,
+ DRM_FORMAT_NV24,
+ DRM_FORMAT_NV21,
+ DRM_FORMAT_NV61,
+ DRM_FORMAT_NV42,
+ DRM_FORMAT_YUV420,
+ DRM_FORMAT_YUV422,
+ DRM_FORMAT_YUV444,
+ DRM_FORMAT_YVU420,
+ DRM_FORMAT_YVU422,
+ DRM_FORMAT_YVU444,
+ DRM_FORMAT_P010,
+ DRM_FORMAT_P012,
+ DRM_FORMAT_P016,
+ DRM_FORMAT_R1,
+ DRM_FORMAT_R2,
+ DRM_FORMAT_R4,
+ DRM_FORMAT_R8,
+};
static struct drm_plane_state *
vkms_plane_duplicate_state(struct drm_plane *plane)
{
struct vkms_plane_state *vkms_state;
- struct vkms_crc_data *crc_data;
+ struct vkms_frame_info *frame_info;
vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL);
if (!vkms_state)
return NULL;
- crc_data = kzalloc(sizeof(*crc_data), GFP_KERNEL);
- if (!crc_data) {
- DRM_DEBUG_KMS("Couldn't allocate crc_data\n");
+ frame_info = kzalloc(sizeof(*frame_info), GFP_KERNEL);
+ if (!frame_info) {
+ DRM_DEBUG_KMS("Couldn't allocate frame_info\n");
kfree(vkms_state);
return NULL;
}
- vkms_state->crc_data = crc_data;
+ vkms_state->frame_info = frame_info;
- __drm_atomic_helper_plane_duplicate_state(plane,
- &vkms_state->base);
+ __drm_gem_duplicate_shadow_plane_state(plane, &vkms_state->base);
- return &vkms_state->base;
+ return &vkms_state->base.base;
}
static void vkms_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct vkms_plane_state *vkms_state = to_vkms_plane_state(old_state);
- struct drm_crtc *crtc = vkms_state->base.crtc;
+ struct drm_crtc *crtc = vkms_state->base.base.crtc;
- if (crtc) {
+ if (crtc && vkms_state->frame_info->fb) {
/* dropping the reference we acquired in
* vkms_primary_plane_update()
*/
- if (drm_framebuffer_read_refcount(&vkms_state->crc_data->fb))
- drm_framebuffer_put(&vkms_state->crc_data->fb);
+ if (drm_framebuffer_read_refcount(vkms_state->frame_info->fb))
+ drm_framebuffer_put(vkms_state->frame_info->fb);
}
- kfree(vkms_state->crc_data);
- vkms_state->crc_data = NULL;
+ kfree(vkms_state->frame_info);
+ vkms_state->frame_info = NULL;
- __drm_atomic_helper_plane_destroy_state(old_state);
+ __drm_gem_destroy_shadow_plane_state(&vkms_state->base);
kfree(vkms_state);
}
@@ -62,8 +99,10 @@ static void vkms_plane_reset(struct drm_plane *plane)
{
struct vkms_plane_state *vkms_state;
- if (plane->state)
+ if (plane->state) {
vkms_plane_destroy_state(plane, plane->state);
+ plane->state = NULL; /* must be set to NULL here */
+ }
vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL);
if (!vkms_state) {
@@ -71,141 +110,144 @@ static void vkms_plane_reset(struct drm_plane *plane)
return;
}
- plane->state = &vkms_state->base;
- plane->state->plane = plane;
+ __drm_gem_reset_shadow_plane(plane, &vkms_state->base);
}
static const struct drm_plane_funcs vkms_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
- .destroy = drm_plane_cleanup,
.reset = vkms_plane_reset,
.atomic_duplicate_state = vkms_plane_duplicate_state,
.atomic_destroy_state = vkms_plane_destroy_state,
};
static void vkms_plane_atomic_update(struct drm_plane *plane,
- struct drm_plane_state *old_state)
+ struct drm_atomic_state *state)
{
+ struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
+ plane);
struct vkms_plane_state *vkms_plane_state;
- struct drm_framebuffer *fb = plane->state->fb;
- struct vkms_crc_data *crc_data;
+ struct drm_shadow_plane_state *shadow_plane_state;
+ struct drm_framebuffer *fb = new_state->fb;
+ struct vkms_frame_info *frame_info;
+ u32 fmt;
- if (!plane->state->crtc || !fb)
+ if (!new_state->crtc || !fb)
return;
- vkms_plane_state = to_vkms_plane_state(plane->state);
-
- crc_data = vkms_plane_state->crc_data;
- memcpy(&crc_data->src, &plane->state->src, sizeof(struct drm_rect));
- memcpy(&crc_data->dst, &plane->state->dst, sizeof(struct drm_rect));
- memcpy(&crc_data->fb, fb, sizeof(struct drm_framebuffer));
- drm_framebuffer_get(&crc_data->fb);
- crc_data->offset = fb->offsets[0];
- crc_data->pitch = fb->pitches[0];
- crc_data->cpp = fb->format->cpp[0];
+ fmt = fb->format->format;
+ vkms_plane_state = to_vkms_plane_state(new_state);
+ shadow_plane_state = &vkms_plane_state->base;
+
+ frame_info = vkms_plane_state->frame_info;
+ memcpy(&frame_info->src, &new_state->src, sizeof(struct drm_rect));
+ memcpy(&frame_info->dst, &new_state->dst, sizeof(struct drm_rect));
+ frame_info->fb = fb;
+ memcpy(&frame_info->map, &shadow_plane_state->data, sizeof(frame_info->map));
+ drm_framebuffer_get(frame_info->fb);
+ frame_info->rotation = new_state->rotation;
+
+ vkms_plane_state->pixel_read_line = get_pixel_read_line_function(fmt);
+ get_conversion_matrix_to_argb_u16(fmt, new_state->color_encoding, new_state->color_range,
+ &vkms_plane_state->conversion_matrix);
}
static int vkms_plane_atomic_check(struct drm_plane *plane,
- struct drm_plane_state *state)
+ struct drm_atomic_state *state)
{
+ struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
+ plane);
struct drm_crtc_state *crtc_state;
- bool can_position = false;
int ret;
- if (!state->fb | !state->crtc)
+ if (!new_plane_state->fb || WARN_ON(!new_plane_state->crtc))
return 0;
- crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
+ crtc_state = drm_atomic_get_crtc_state(state,
+ new_plane_state->crtc);
if (IS_ERR(crtc_state))
return PTR_ERR(crtc_state);
- if (plane->type == DRM_PLANE_TYPE_CURSOR)
- can_position = true;
-
- ret = drm_atomic_helper_check_plane_state(state, crtc_state,
- DRM_PLANE_HELPER_NO_SCALING,
- DRM_PLANE_HELPER_NO_SCALING,
- can_position, true);
+ ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
+ DRM_PLANE_NO_SCALING,
+ DRM_PLANE_NO_SCALING,
+ true, true);
if (ret != 0)
return ret;
- /* for now primary plane must be visible and full screen */
- if (!state->visible && !can_position)
- return -EINVAL;
-
return 0;
}
static int vkms_prepare_fb(struct drm_plane *plane,
struct drm_plane_state *state)
{
- struct drm_gem_object *gem_obj;
+ struct drm_shadow_plane_state *shadow_plane_state;
+ struct drm_framebuffer *fb = state->fb;
int ret;
- if (!state->fb)
+ if (!fb)
return 0;
- gem_obj = drm_gem_fb_get_obj(state->fb, 0);
- ret = vkms_gem_vmap(gem_obj);
+ shadow_plane_state = to_drm_shadow_plane_state(state);
+
+ ret = drm_gem_plane_helper_prepare_fb(plane, state);
if (ret)
- DRM_ERROR("vmap failed: %d\n", ret);
+ return ret;
- return drm_gem_fb_prepare_fb(plane, state);
+ return drm_gem_fb_vmap(fb, shadow_plane_state->map, shadow_plane_state->data);
}
static void vkms_cleanup_fb(struct drm_plane *plane,
- struct drm_plane_state *old_state)
+ struct drm_plane_state *state)
{
- struct drm_gem_object *gem_obj;
+ struct drm_shadow_plane_state *shadow_plane_state;
+ struct drm_framebuffer *fb = state->fb;
- if (!old_state->fb)
+ if (!fb)
return;
- gem_obj = drm_gem_fb_get_obj(old_state->fb, 0);
- vkms_gem_vunmap(gem_obj);
+ shadow_plane_state = to_drm_shadow_plane_state(state);
+
+ drm_gem_fb_vunmap(fb, shadow_plane_state->map);
}
-static const struct drm_plane_helper_funcs vkms_primary_helper_funcs = {
+static const struct drm_plane_helper_funcs vkms_plane_helper_funcs = {
.atomic_update = vkms_plane_atomic_update,
.atomic_check = vkms_plane_atomic_check,
.prepare_fb = vkms_prepare_fb,
.cleanup_fb = vkms_cleanup_fb,
};
-struct drm_plane *vkms_plane_init(struct vkms_device *vkmsdev,
- enum drm_plane_type type)
+struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
+ struct vkms_config_plane *plane_cfg)
{
struct drm_device *dev = &vkmsdev->drm;
- const struct drm_plane_helper_funcs *funcs;
- struct drm_plane *plane;
- const u32 *formats;
- int ret, nformats;
-
- plane = kzalloc(sizeof(*plane), GFP_KERNEL);
- if (!plane)
- return ERR_PTR(-ENOMEM);
-
- if (type == DRM_PLANE_TYPE_CURSOR) {
- formats = vkms_cursor_formats;
- nformats = ARRAY_SIZE(vkms_cursor_formats);
- funcs = &vkms_primary_helper_funcs;
- } else {
- formats = vkms_formats;
- nformats = ARRAY_SIZE(vkms_formats);
- funcs = &vkms_primary_helper_funcs;
- }
-
- ret = drm_universal_plane_init(dev, plane, 0,
- &vkms_plane_funcs,
- formats, nformats,
- NULL, type, NULL);
- if (ret) {
- kfree(plane);
- return ERR_PTR(ret);
- }
-
- drm_plane_helper_add(plane, funcs);
+ struct vkms_plane *plane;
+
+ plane = drmm_universal_plane_alloc(dev, struct vkms_plane, base, 0,
+ &vkms_plane_funcs,
+ vkms_formats, ARRAY_SIZE(vkms_formats),
+ NULL, vkms_config_plane_get_type(plane_cfg),
+ NULL);
+ if (IS_ERR(plane))
+ return plane;
+
+ drm_plane_helper_add(&plane->base, &vkms_plane_helper_funcs);
+
+ drm_plane_create_rotation_property(&plane->base, DRM_MODE_ROTATE_0,
+ DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK);
+
+ drm_plane_create_color_properties(&plane->base,
+ BIT(DRM_COLOR_YCBCR_BT601) |
+ BIT(DRM_COLOR_YCBCR_BT709) |
+ BIT(DRM_COLOR_YCBCR_BT2020),
+ BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
+ BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+ DRM_COLOR_YCBCR_BT601,
+ DRM_COLOR_YCBCR_FULL_RANGE);
+
+ if (vkms_config_plane_get_default_pipeline(plane_cfg))
+ vkms_initialize_colorops(&plane->base);
return plane;
}