[PATCH 32/59] drm/amd/display: Test cursor commit

Alex Hung <[email protected]>
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
[WHAT]
Add KUnit tests for amdgpu_dm_commit_cursors() covering an empty commit,
a non-cursor plane, and a cursor update, and for amdgpu_dm_update_cursor()
covering missing framebuffers and removal of an active stream cursor.

[HOW]
Reuse the single-plane commit fixture. The disable path uses the real
state-only DC cursor position setter without hardware programming.

Assisted-by: Copilot:Claude-Opus-5 GPT-5.6-Sol
Reviewed-by: Bhawanpreet Lakha <[email protected]>
Signed-off-by: Alex Hung <[email protected]>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  10 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |   5 +
 .../display/amdgpu_dm/tests/amdgpu_dm_test.c  | 140 ++++++++++++++++++
 3 files changed, 151 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 9d233b18f2df..08f2cc7fec68 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3587,7 +3587,7 @@ static void remove_stream(struct amdgpu_device *adev,
 	acrtc->enabled = false;
 }
 
-static void amdgpu_dm_commit_cursors(struct drm_atomic_commit *state)
+STATIC_IFN_KUNIT void amdgpu_dm_commit_cursors(struct drm_atomic_commit *state)
 {
 	struct drm_plane *plane;
 	struct drm_plane_state *old_plane_state;
@@ -3601,6 +3601,7 @@ static void amdgpu_dm_commit_cursors(struct drm_atomic_commit *state)
 		if (plane->type == DRM_PLANE_TYPE_CURSOR)
 			amdgpu_dm_plane_handle_cursor_update(plane, old_plane_state);
 }
+EXPORT_IF_KUNIT(amdgpu_dm_commit_cursors);
 
 static inline uint32_t get_mem_type(struct drm_framebuffer *fb)
 {
@@ -3609,9 +3610,9 @@ static inline uint32_t get_mem_type(struct drm_framebuffer *fb)
 	return abo->tbo.resource ? abo->tbo.resource->mem_type : 0;
 }
 
-static void amdgpu_dm_update_cursor(struct drm_plane *plane,
-				    struct drm_plane_state *old_plane_state,
-				    struct dc_stream_update *update)
+STATIC_IFN_KUNIT void amdgpu_dm_update_cursor(struct drm_plane *plane,
+					      struct drm_plane_state *old_plane_state,
+					      struct dc_stream_update *update)
 {
 	struct amdgpu_device *adev = drm_to_adev(plane->dev);
 	struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(plane->state->fb);
@@ -3680,6 +3681,7 @@ static void amdgpu_dm_update_cursor(struct drm_plane *plane,
 		update->cursor_position = &crtc_state->stream->cursor_position;
 	}
 }
+EXPORT_IF_KUNIT(amdgpu_dm_update_cursor);
 
 static void amdgpu_dm_enable_self_refresh(struct amdgpu_display_manager *dm,
 					  struct amdgpu_crtc *acrtc_attach,
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index a48154ea62ae..ed2341b387d9 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -86,6 +86,7 @@ struct dc;
 struct amdgpu_bo;
 struct dmub_srv;
 struct dc_plane_state;
+struct dc_stream_update;
 struct dmub_notification;
 struct dmub_cmd_fused_request;
 
@@ -1171,6 +1172,10 @@ struct dm_atomic_state *dm_atomic_get_new_state(struct drm_atomic_commit *state)
 struct drm_private_state *dm_atomic_duplicate_state(struct drm_private_obj *obj);
 void dm_atomic_destroy_state(struct drm_private_obj *obj,
 			     struct drm_private_state *state);
+void amdgpu_dm_commit_cursors(struct drm_atomic_commit *state);
+void amdgpu_dm_update_cursor(struct drm_plane *plane,
+			     struct drm_plane_state *old_plane_state,
+			     struct dc_stream_update *update);
 int add_affected_mst_dsc_crtcs(struct drm_atomic_commit *state,
 			       struct drm_crtc *crtc);
 int dm_plane_layer_index_cmp(const void *a, const void *b);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
index 2afa73a07ebd..a2671ad90bfe 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
@@ -1418,6 +1418,140 @@ static void dm_test_add_affected_mst_dsc_crtcs_disabled(struct kunit *test)
 	KUNIT_EXPECT_EQ(test, add_affected_mst_dsc_crtcs(state, crtc), 0);
 }
 
+/* Tests for amdgpu_dm_commit_cursors() */
+
+/**
+ * dm_test_commit_cursors_no_planes - Test an empty plane set is a no-op
+ * @test: The KUnit test context
+ */
+static void dm_test_commit_cursors_no_planes(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+
+	amdgpu_dm_commit_cursors(dm_test_alloc_commit(test, adev));
+}
+
+/*
+ * Build a commit holding a single plane of @type with empty old and new plane
+ * states.
+ */
+static struct drm_atomic_commit *
+dm_test_commit_with_plane(struct kunit *test, struct amdgpu_device *adev,
+			  enum drm_plane_type type)
+{
+	struct drm_atomic_commit *state = dm_test_alloc_commit(test, adev);
+	struct drm_plane_state *old_state, *new_state;
+	struct drm_plane *plane;
+
+	plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, plane);
+	old_state = kunit_kzalloc(test, sizeof(*old_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, old_state);
+	new_state = kunit_kzalloc(test, sizeof(*new_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, new_state);
+	state->planes = kunit_kzalloc(test, sizeof(*state->planes), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, state->planes);
+
+	plane->type = type;
+	plane->dev = &adev->ddev;
+	plane->state = new_state;
+	adev->ddev.mode_config.num_total_plane = 1;
+	state->planes[0].ptr = plane;
+	state->planes[0].old_state = old_state;
+
+	return state;
+}
+
+/**
+ * dm_test_commit_cursors_skips_non_cursor - Test non-cursor planes are skipped
+ * @test: The KUnit test context
+ */
+static void dm_test_commit_cursors_skips_non_cursor(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+
+	amdgpu_dm_commit_cursors(dm_test_commit_with_plane(test, adev,
+							   DRM_PLANE_TYPE_PRIMARY));
+}
+
+/**
+ * dm_test_commit_cursors_updates_cursor - Test cursor planes reach the cursor update
+ * @test: The KUnit test context
+ */
+static void dm_test_commit_cursors_updates_cursor(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+
+	amdgpu_dm_commit_cursors(dm_test_commit_with_plane(test, adev,
+							   DRM_PLANE_TYPE_CURSOR));
+}
+
+/**
+ * dm_test_update_cursor_no_framebuffer - Test missing framebuffers leave the update untouched
+ * @test: The KUnit test context
+ */
+static void dm_test_update_cursor_no_framebuffer(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+	struct drm_atomic_commit *state;
+	struct dc_stream_update *update;
+	struct drm_plane *plane;
+
+	state = dm_test_commit_with_plane(test, adev, DRM_PLANE_TYPE_CURSOR);
+	plane = state->planes[0].ptr;
+	update = kunit_kzalloc(test, sizeof(*update), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, update);
+
+	update->cursor_attributes = (void *)1;
+	update->cursor_position = (void *)1;
+
+	amdgpu_dm_update_cursor(plane, state->planes[0].old_state, update);
+
+	KUNIT_EXPECT_PTR_EQ(test, update->cursor_attributes, (void *)1);
+	KUNIT_EXPECT_PTR_EQ(test, update->cursor_position, (void *)1);
+}
+
+/**
+ * dm_test_update_cursor_disables_stream - Test removing the framebuffer disables the cursor
+ * @test: The KUnit test context
+ */
+static void dm_test_update_cursor_disables_stream(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+	struct drm_atomic_commit *state;
+	struct dc_stream_update *update;
+	struct drm_plane_state *old_plane_state;
+	struct dm_crtc_state *crtc_state;
+	struct amdgpu_framebuffer *afb;
+	struct amdgpu_crtc *acrtc;
+	struct drm_plane *plane;
+
+	state = dm_test_commit_with_plane(test, adev, DRM_PLANE_TYPE_CURSOR);
+	plane = state->planes[0].ptr;
+	old_plane_state = state->planes[0].old_state;
+	crtc_state = kunit_kzalloc(test, sizeof(*crtc_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, crtc_state);
+	afb = kunit_kzalloc(test, sizeof(*afb), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, afb);
+	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, acrtc);
+	update = kunit_kzalloc(test, sizeof(*update), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, update);
+
+	old_plane_state->fb = &afb->base;
+	old_plane_state->crtc = &acrtc->base;
+	acrtc->base.state = &crtc_state->base;
+	crtc_state->stream = dm_kunit_alloc_stream(test, NULL);
+	crtc_state->stream->cursor_position.enable = true;
+
+	amdgpu_dm_update_cursor(plane, old_plane_state, update);
+
+	KUNIT_EXPECT_FALSE(test, crtc_state->stream->cursor_position.enable);
+	KUNIT_EXPECT_PTR_EQ(test, update->cursor_position,
+			    &crtc_state->stream->cursor_position);
+	KUNIT_EXPECT_NULL(test, update->cursor_attributes);
+}
+
 static struct kunit_case amdgpu_dm_tests[] = {
 	/* Simple DM callbacks */
 	KUNIT_CASE(dm_test_wait_for_idle),
@@ -1497,6 +1631,12 @@ static struct kunit_case amdgpu_dm_tests[] = {
 	KUNIT_CASE(dm_test_add_affected_mst_dsc_crtcs_not_mst),
 	KUNIT_CASE(dm_test_add_affected_mst_dsc_crtcs_other_crtc),
 	KUNIT_CASE(dm_test_add_affected_mst_dsc_crtcs_disabled),
+	/* amdgpu_dm_commit_cursors */
+	KUNIT_CASE(dm_test_commit_cursors_no_planes),
+	KUNIT_CASE(dm_test_commit_cursors_skips_non_cursor),
+	KUNIT_CASE(dm_test_commit_cursors_updates_cursor),
+	KUNIT_CASE(dm_test_update_cursor_no_framebuffer),
+	KUNIT_CASE(dm_test_update_cursor_disables_stream),
 	{}
 };
 
-- 
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.