Commit 4963049e authored by Ryosuke Yasuoka's avatar Ryosuke Yasuoka Committed by Jocelyn Falempe
Browse files

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: default avatarJavier Martinez Canillas <javierm@redhat.com>
Signed-off-by: default avatarRyosuke Yasuoka <ryasuoka@redhat.com>
Link: https://lore.kernel.org/r/20250427101825.812766-1-ryasuoka@redhat.com


Signed-off-by: default avatarJocelyn Falempe <jfalempe@redhat.com>
parent 9934ab18
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -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 */
+112 −60
Original line number Diff line number Diff line
@@ -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)
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,
};

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 hyperv_drm_device *hv = to_hv(pipe->crtc.dev);
	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 (fb->format->format != DRM_FORMAT_XRGB8888)
		return -EINVAL;
	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;

	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);
	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;

	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),
	ret = drm_universal_plane_init(dev, plane, 0,
				       &hyperv_plane_funcs,
				       hyperv_formats, ARRAY_SIZE(hyperv_formats),
				       hyperv_modifiers,
					   &hv->connector);
				       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);

	drm_plane_enable_fb_damage_clips(&hv->pipe.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);

	return 0;
	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;

	ret = hyperv_conn_init(hv);
	if (ret) {
		drm_err(dev, "Failed to initialized connector.\n");
		return ret;
	}

	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");