drm/hyperv: Replace simple-KMS with regular atomic helpers

Drop simple-KMS in favor of regular atomic helpers to make the code more
modular. The simple-KMS helper mix up plane and CRTC state, so it is
obsolete and should go away [1]. Since it just split the simple-pipe
functions into per-plane and per-CRTC, no functional changes is
expected.

[1] https://lore.kernel.org/lkml/dae5089d-e214-4518-b927-5c4149babad8@suse.de/

Acked-by: Javier Martinez Canillas <javierm@redhat.com>
Signed-off-by: Ryosuke Yasuoka <ryasuoka@redhat.com>
Link: https://lore.kernel.org/r/20250427101825.812766-1-ryasuoka@redhat.com
Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com>
This commit is contained in:
Ryosuke Yasuoka 2025-04-27 19:18:23 +09:00 committed by Jocelyn Falempe
parent 9934ab1805
commit 4963049ea1
2 changed files with 116 additions and 62 deletions

View File

@ -11,7 +11,9 @@
struct hyperv_drm_device {
/* drm */
struct drm_device dev;
struct drm_simple_display_pipe pipe;
struct drm_plane plane;
struct drm_crtc crtc;
struct drm_encoder encoder;
struct drm_connector connector;
/* mode */

View File

@ -5,6 +5,8 @@
#include <linux/hyperv.h>
#include <drm/drm_atomic.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
@ -15,7 +17,7 @@
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_simple_kms_helper.h>
#include <drm/drm_plane.h>
#include "hyperv_drm.h"
@ -38,18 +40,6 @@ static int hyperv_blit_to_vram_rect(struct drm_framebuffer *fb,
return 0;
}
static int hyperv_blit_to_vram_fullscreen(struct drm_framebuffer *fb,
const struct iosys_map *map)
{
struct drm_rect fullscreen = {
.x1 = 0,
.x2 = fb->width,
.y1 = 0,
.y2 = fb->height,
};
return hyperv_blit_to_vram_rect(fb, map, &fullscreen);
}
static int hyperv_connector_get_modes(struct drm_connector *connector)
{
struct hyperv_drm_device *hv = to_hv(connector->dev);
@ -98,30 +88,66 @@ static int hyperv_check_size(struct hyperv_drm_device *hv, int w, int h,
return 0;
}
static void hyperv_pipe_enable(struct drm_simple_display_pipe *pipe,
struct drm_crtc_state *crtc_state,
struct drm_plane_state *plane_state)
static const uint32_t hyperv_formats[] = {
DRM_FORMAT_XRGB8888,
};
static const uint64_t hyperv_modifiers[] = {
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_INVALID
};
static void hyperv_crtc_helper_atomic_enable(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
struct hyperv_drm_device *hv = to_hv(pipe->crtc.dev);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct hyperv_drm_device *hv = to_hv(crtc->dev);
struct drm_plane *plane = &hv->plane;
struct drm_plane_state *plane_state = plane->state;
struct drm_crtc_state *crtc_state = crtc->state;
hyperv_hide_hw_ptr(hv->hdev);
hyperv_update_situation(hv->hdev, 1, hv->screen_depth,
crtc_state->mode.hdisplay,
crtc_state->mode.vdisplay,
plane_state->fb->pitches[0]);
hyperv_blit_to_vram_fullscreen(plane_state->fb, &shadow_plane_state->data[0]);
}
static int hyperv_pipe_check(struct drm_simple_display_pipe *pipe,
struct drm_plane_state *plane_state,
struct drm_crtc_state *crtc_state)
{
struct hyperv_drm_device *hv = to_hv(pipe->crtc.dev);
struct drm_framebuffer *fb = plane_state->fb;
static const struct drm_crtc_helper_funcs hyperv_crtc_helper_funcs = {
.atomic_check = drm_crtc_helper_atomic_check,
.atomic_enable = hyperv_crtc_helper_atomic_enable,
};
if (fb->format->format != DRM_FORMAT_XRGB8888)
return -EINVAL;
static const struct drm_crtc_funcs hyperv_crtc_funcs = {
.reset = drm_atomic_helper_crtc_reset,
.destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
};
static int hyperv_plane_atomic_check(struct drm_plane *plane,
struct drm_atomic_state *state)
{
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
struct hyperv_drm_device *hv = to_hv(plane->dev);
struct drm_framebuffer *fb = plane_state->fb;
struct drm_crtc *crtc = plane_state->crtc;
struct drm_crtc_state *crtc_state = NULL;
int ret;
if (crtc)
crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state,
DRM_PLANE_NO_SCALING,
DRM_PLANE_NO_SCALING,
false, false);
if (ret)
return ret;
if (!plane_state->visible)
return 0;
if (fb->pitches[0] * fb->height > hv->fb_size) {
drm_err(&hv->dev, "fb size requested by %s for %dX%d (pitch %d) greater than %ld\n",
@ -132,53 +158,85 @@ static int hyperv_pipe_check(struct drm_simple_display_pipe *pipe,
return 0;
}
static void hyperv_pipe_update(struct drm_simple_display_pipe *pipe,
struct drm_plane_state *old_state)
static void hyperv_plane_atomic_update(struct drm_plane *plane,
struct drm_atomic_state *state)
{
struct hyperv_drm_device *hv = to_hv(pipe->crtc.dev);
struct drm_plane_state *state = pipe->plane.state;
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state);
struct drm_rect rect;
struct hyperv_drm_device *hv = to_hv(plane->dev);
struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(new_state);
struct drm_rect damage;
struct drm_rect dst_clip;
struct drm_atomic_helper_damage_iter iter;
if (drm_atomic_helper_damage_merged(old_state, state, &rect)) {
hyperv_blit_to_vram_rect(state->fb, &shadow_plane_state->data[0], &rect);
hyperv_update_dirt(hv->hdev, &rect);
drm_atomic_helper_damage_iter_init(&iter, old_state, new_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
dst_clip = new_state->dst;
if (!drm_rect_intersect(&dst_clip, &damage))
continue;
hyperv_blit_to_vram_rect(new_state->fb, &shadow_plane_state->data[0], &damage);
hyperv_update_dirt(hv->hdev, &damage);
}
}
static const struct drm_simple_display_pipe_funcs hyperv_pipe_funcs = {
.enable = hyperv_pipe_enable,
.check = hyperv_pipe_check,
.update = hyperv_pipe_update,
DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
static const struct drm_plane_helper_funcs hyperv_plane_helper_funcs = {
DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
.atomic_check = hyperv_plane_atomic_check,
.atomic_update = hyperv_plane_atomic_update,
};
static const uint32_t hyperv_formats[] = {
DRM_FORMAT_XRGB8888,
static const struct drm_plane_funcs hyperv_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = drm_plane_cleanup,
DRM_GEM_SHADOW_PLANE_FUNCS,
};
static const uint64_t hyperv_modifiers[] = {
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_INVALID
static const struct drm_encoder_funcs hyperv_drm_simple_encoder_funcs_cleanup = {
.destroy = drm_encoder_cleanup,
};
static inline int hyperv_pipe_init(struct hyperv_drm_device *hv)
{
struct drm_device *dev = &hv->dev;
struct drm_encoder *encoder = &hv->encoder;
struct drm_plane *plane = &hv->plane;
struct drm_crtc *crtc = &hv->crtc;
struct drm_connector *connector = &hv->connector;
int ret;
ret = drm_simple_display_pipe_init(&hv->dev,
&hv->pipe,
&hyperv_pipe_funcs,
hyperv_formats,
ARRAY_SIZE(hyperv_formats),
hyperv_modifiers,
&hv->connector);
ret = drm_universal_plane_init(dev, plane, 0,
&hyperv_plane_funcs,
hyperv_formats, ARRAY_SIZE(hyperv_formats),
hyperv_modifiers,
DRM_PLANE_TYPE_PRIMARY, NULL);
if (ret)
return ret;
drm_plane_helper_add(plane, &hyperv_plane_helper_funcs);
drm_plane_enable_fb_damage_clips(plane);
ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
&hyperv_crtc_funcs, NULL);
if (ret)
return ret;
drm_crtc_helper_add(crtc, &hyperv_crtc_helper_funcs);
encoder->possible_crtcs = drm_crtc_mask(crtc);
ret = drm_encoder_init(dev, encoder,
&hyperv_drm_simple_encoder_funcs_cleanup,
DRM_MODE_ENCODER_NONE, NULL);
if (ret)
return ret;
drm_plane_enable_fb_damage_clips(&hv->pipe.plane);
ret = hyperv_conn_init(hv);
if (ret) {
drm_err(dev, "Failed to initialized connector.\n");
return ret;
}
return 0;
return drm_connector_attach_encoder(connector, encoder);
}
static enum drm_mode_status
@ -221,12 +279,6 @@ int hyperv_mode_config_init(struct hyperv_drm_device *hv)
dev->mode_config.funcs = &hyperv_mode_config_funcs;
ret = hyperv_conn_init(hv);
if (ret) {
drm_err(dev, "Failed to initialized connector.\n");
return ret;
}
ret = hyperv_pipe_init(hv);
if (ret) {
drm_err(dev, "Failed to initialized pipe.\n");