drm/amd/display: Test cursor commit

[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 <bhawanpreet.lakha@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Alex Hung 2026-08-13 14:02:11 -06:00 committed by Alex Deucher
parent c8130c0538
commit 1903ffbca1
3 changed files with 151 additions and 4 deletions

View File

@ -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,

View File

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

View File

@ -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),
{}
};