[PATCH 51/82] drm/amd/display: Test cursor update and async plane update

<[email protected]>
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
From: Alex Hung <[email protected]>

[WHAT]
Add KUnit tests for amdgpu_dm_plane_handle_cursor_update() and
amdgpu_dm_plane_atomic_async_update() covering the return taken when the
cursor plane has no framebuffer, and the copy of the new position and
size into the plane state ahead of the cursor update.

Assisted-by: Copilot:Claude-Opus-5
Reviewed-by: Bhawanpreet Lakha <[email protected]>
Signed-off-by: Alex Hung <[email protected]>
Signed-off-by: Ivan Lipski <[email protected]>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   |  6 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.h   |  1 +
 .../amdgpu_dm/tests/amdgpu_dm_plane_test.c    | 90 +++++++++++++++++++
 3 files changed, 95 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index 096e1a5e37ad0..0a5a7347238ec 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -1738,9 +1738,10 @@ void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane,
 		mutex_unlock(&adev->dm.dc_lock);
 	}
 }
+EXPORT_IF_KUNIT(amdgpu_dm_plane_handle_cursor_update);
 
-static void amdgpu_dm_plane_atomic_async_update(struct drm_plane *plane,
-						struct drm_atomic_commit *state)
+STATIC_IFN_KUNIT void amdgpu_dm_plane_atomic_async_update(struct drm_plane *plane,
+							  struct drm_atomic_commit *state)
 {
 	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
 									   plane);
@@ -1762,6 +1763,7 @@ static void amdgpu_dm_plane_atomic_async_update(struct drm_plane *plane,
 
 	amdgpu_dm_plane_handle_cursor_update(plane, old_state);
 }
+EXPORT_IF_KUNIT(amdgpu_dm_plane_atomic_async_update);
 
 STATIC_IFN_KUNIT void amdgpu_dm_plane_panic_flush(struct drm_plane *plane)
 {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.h
index d8ebe48abc9fa..18b500585bedd 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.h
@@ -136,5 +136,6 @@ bool amdgpu_dm_plane_gfx6_format_mod_supported(const struct amdgpu_device *adev,
 					       const u64 modifier);
 int amdgpu_dm_plane_helper_prepare_fb(struct drm_plane *plane, struct drm_plane_state *new_state);
 void amdgpu_dm_plane_helper_cleanup_fb(struct drm_plane *plane, struct drm_plane_state *old_state);
+void amdgpu_dm_plane_atomic_async_update(struct drm_plane *plane, struct drm_atomic_commit *state);
 #endif
 #endif
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_plane_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_plane_test.c
index 7b3f0759cc1f9..1b39f41c8414b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_plane_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_plane_test.c
@@ -3595,6 +3595,92 @@ static void dm_test_helper_cleanup_fb_no_fb(struct kunit *test)
 	amdgpu_dm_plane_helper_cleanup_fb(plane, &state);
 }
 
+/**
+ * dm_test_handle_cursor_update_no_fb() - Verify cursor update without framebuffers.
+ * @test: KUnit test context.
+ *
+ * Verify if the cursor update returns early, without touching the CRTC, when
+ * neither the new nor the old plane state has a framebuffer bound.
+ */
+static void dm_test_handle_cursor_update_no_fb(struct kunit *test)
+{
+	struct amdgpu_device *adev;
+	struct drm_plane_state old_state = {0};
+	struct drm_plane_state state = {0};
+	struct drm_plane *plane;
+
+	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
+	plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, adev);
+	KUNIT_ASSERT_NOT_NULL(test, plane);
+
+	plane->dev = &adev->ddev;
+	plane->state = &state;
+
+	amdgpu_dm_plane_handle_cursor_update(plane, &old_state);
+}
+
+/**
+ * dm_test_atomic_async_update_copies_state() - Verify async cursor state copy.
+ * @test: KUnit test context.
+ *
+ * Verify if the async update swaps the framebuffer and copies the source and
+ * CRTC rectangles from the new state into the current plane state.
+ */
+static void dm_test_atomic_async_update_copies_state(struct kunit *test)
+{
+	struct amdgpu_device *adev;
+	struct drm_atomic_commit *state;
+	struct __drm_planes_state *planes;
+	struct drm_plane_state *cur_state;
+	struct drm_plane_state *new_state;
+	struct drm_plane_state *old_state;
+	struct amdgpu_framebuffer *afb;
+	struct drm_plane *plane;
+
+	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
+	state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
+	planes = kunit_kzalloc(test, sizeof(*planes), GFP_KERNEL);
+	plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL);
+	cur_state = kunit_kzalloc(test, sizeof(*cur_state), GFP_KERNEL);
+	new_state = kunit_kzalloc(test, sizeof(*new_state), GFP_KERNEL);
+	old_state = kunit_kzalloc(test, sizeof(*old_state), GFP_KERNEL);
+	afb = kunit_kzalloc(test, sizeof(*afb), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, adev);
+	KUNIT_ASSERT_NOT_NULL(test, state);
+	KUNIT_ASSERT_NOT_NULL(test, planes);
+	KUNIT_ASSERT_NOT_NULL(test, plane);
+	KUNIT_ASSERT_NOT_NULL(test, cur_state);
+	KUNIT_ASSERT_NOT_NULL(test, new_state);
+	KUNIT_ASSERT_NOT_NULL(test, old_state);
+	KUNIT_ASSERT_NOT_NULL(test, afb);
+
+	plane->dev = &adev->ddev;
+	plane->index = 0;
+	plane->state = cur_state;
+	cur_state->fb = &afb->base;
+	new_state->src_x = 1 << 16;
+	new_state->src_y = 2 << 16;
+	new_state->src_w = 64 << 16;
+	new_state->src_h = 64 << 16;
+	new_state->crtc_x = 10;
+	new_state->crtc_y = 20;
+	new_state->crtc_w = 64;
+	new_state->crtc_h = 64;
+	state->planes = planes;
+	state->planes[0].new_state = new_state;
+	state->planes[0].old_state = old_state;
+
+	amdgpu_dm_plane_atomic_async_update(plane, state);
+
+	KUNIT_EXPECT_PTR_EQ(test, cur_state->fb, NULL);
+	KUNIT_EXPECT_PTR_EQ(test, new_state->fb, &afb->base);
+	KUNIT_EXPECT_EQ(test, cur_state->src_x, 1U << 16);
+	KUNIT_EXPECT_EQ(test, cur_state->src_h, 64U << 16);
+	KUNIT_EXPECT_EQ(test, cur_state->crtc_x, 10);
+	KUNIT_EXPECT_EQ(test, cur_state->crtc_h, 64U);
+}
+
 static struct kunit_case amdgpu_dm_plane_test_cases[] = {
 	/* amdgpu_dm_plane_is_video_format() */
 	KUNIT_CASE(dm_test_plane_is_video_format_known_video),
@@ -3664,6 +3750,10 @@ static struct kunit_case amdgpu_dm_plane_test_cases[] = {
 	KUNIT_CASE(dm_test_helper_prepare_fb_no_fb),
 	/* amdgpu_dm_plane_helper_cleanup_fb() */
 	KUNIT_CASE(dm_test_helper_cleanup_fb_no_fb),
+	/* amdgpu_dm_plane_handle_cursor_update() */
+	KUNIT_CASE(dm_test_handle_cursor_update_no_fb),
+	/* amdgpu_dm_plane_atomic_async_update() */
+	KUNIT_CASE(dm_test_atomic_async_update_copies_state),
 	/* amdgpu_dm_plane_atomic_async_check() */
 	KUNIT_CASE(dm_test_atomic_async_check_rejects),
 	KUNIT_CASE(dm_test_atomic_async_check_overlay_cursor),
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.