[PATCH 25/34] drm/amd/display: test amdgpu_dm_crtc_get_cursor_mode
Tom Chung <[email protected]> Wed, 5 Aug 2026 14:36:37 +0800
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
From: Alex Hung <[email protected]> [WHAT] Add KUnit tests for amdgpu_dm_crtc_get_cursor_mode() with a synthetic two-plane atomic-state fixture, an invocation helper, and a colorop helper, covering: - new hardware defaulting to overlay mode, - an unchanged state keeping native mode, - a disabled cursor keeping native mode, - a YUV underlying plane forcing overlay, - a plane scale mismatch forcing overlay, - full cursor coverage allowing native mode, - a coverage hole forcing overlay, - an unrelated update leaving the cursor untouched, - a cursor scale change forcing recomputation, - a cursor position change forcing recomputation, - a color pipeline activation forcing recomputation. Assisted-by: Copilot:GPT-5.6-Sol Reviewed-by: Bhawanpreet Lakha <[email protected]> Signed-off-by: Alex Hung <[email protected]> Signed-off-by: Tom Chung <[email protected]> --- .../amd/display/amdgpu_dm/amdgpu_dm_cursor.c | 1 + .../amdgpu_dm/tests/amdgpu_dm_cursor_test.c | 336 ++++++++++++++++++ 2 files changed, 337 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_cursor.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_cursor.c index 34b5f2b28e91..046ffc0bd5dc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_cursor.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_cursor.c @@ -444,3 +444,4 @@ int amdgpu_dm_crtc_get_cursor_mode(struct amdgpu_device *adev, return 0; } +EXPORT_IF_KUNIT(amdgpu_dm_crtc_get_cursor_mode); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_cursor_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_cursor_test.c index e093420bb2fd..f085eb1a616d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_cursor_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_cursor_test.c @@ -54,6 +54,144 @@ static struct dm_cursor_fb_fixture dm_test_alloc_cursor_fb_fixture(struct kunit return fixture; } +struct dm_cursor_mode_fixture { + struct amdgpu_device *adev; + struct drm_atomic_commit *state; + struct dm_crtc_state *dm_crtc_state; + struct drm_crtc *crtc; + struct drm_plane *cursor; + struct drm_plane *primary; + struct drm_plane_state *old_cursor_state; + struct drm_plane_state *cursor_state; + struct drm_plane_state *old_primary_state; + struct drm_plane_state *primary_state; + struct drm_framebuffer *cursor_fb; + struct drm_framebuffer *primary_fb; +}; + +static struct dm_cursor_mode_fixture dm_test_alloc_cursor_mode_fixture(struct kunit *test) +{ + struct dm_cursor_mode_fixture fixture = { 0 }; + + fixture.adev = dm_kunit_alloc_adev(test); + fixture.state = kunit_kzalloc(test, sizeof(*fixture.state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fixture.state); + fixture.dm_crtc_state = kunit_kzalloc(test, sizeof(*fixture.dm_crtc_state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fixture.dm_crtc_state); + fixture.crtc = kunit_kzalloc(test, sizeof(*fixture.crtc), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fixture.crtc); + fixture.cursor = kunit_kzalloc(test, sizeof(*fixture.cursor), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fixture.cursor); + fixture.primary = kunit_kzalloc(test, sizeof(*fixture.primary), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fixture.primary); + fixture.old_cursor_state = + kunit_kzalloc(test, sizeof(*fixture.old_cursor_state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fixture.old_cursor_state); + fixture.cursor_state = kunit_kzalloc(test, sizeof(*fixture.cursor_state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fixture.cursor_state); + fixture.old_primary_state = + kunit_kzalloc(test, sizeof(*fixture.old_primary_state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fixture.old_primary_state); + fixture.primary_state = kunit_kzalloc(test, sizeof(*fixture.primary_state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fixture.primary_state); + fixture.cursor_fb = kunit_kzalloc(test, sizeof(*fixture.cursor_fb), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fixture.cursor_fb); + fixture.primary_fb = kunit_kzalloc(test, sizeof(*fixture.primary_fb), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fixture.primary_fb); + fixture.state->planes = kunit_kcalloc(test, 2, sizeof(*fixture.state->planes), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fixture.state->planes); + fixture.state->acquire_ctx = + kunit_kzalloc(test, sizeof(*fixture.state->acquire_ctx), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fixture.state->acquire_ctx); + + fixture.adev->ddev.mode_config.num_total_plane = 2; + fixture.state->dev = &fixture.adev->ddev; + fixture.crtc->dev = &fixture.adev->ddev; + fixture.crtc->cursor = fixture.cursor; + fixture.cursor->dev = &fixture.adev->ddev; + fixture.cursor->index = 0; + fixture.cursor->type = DRM_PLANE_TYPE_CURSOR; + fixture.cursor->base.id = 2; + fixture.primary->dev = &fixture.adev->ddev; + fixture.primary->index = 1; + fixture.primary->type = DRM_PLANE_TYPE_PRIMARY; + fixture.primary->base.id = 1; + + fixture.cursor_fb->format = drm_format_info(DRM_FORMAT_ARGB8888); + fixture.primary_fb->format = drm_format_info(DRM_FORMAT_XRGB8888); + fixture.old_cursor_state->plane = fixture.cursor; + fixture.old_cursor_state->crtc = fixture.crtc; + fixture.old_cursor_state->fb = fixture.cursor_fb; + fixture.old_cursor_state->src_w = 64 << 16; + fixture.old_cursor_state->src_h = 64 << 16; + fixture.old_cursor_state->crtc_w = 64; + fixture.old_cursor_state->crtc_h = 64; + fixture.old_cursor_state->zpos = 1; + *fixture.cursor_state = *fixture.old_cursor_state; + fixture.cursor_state->state = fixture.state; + fixture.old_primary_state->plane = fixture.primary; + fixture.old_primary_state->crtc = fixture.crtc; + fixture.old_primary_state->fb = fixture.primary_fb; + fixture.old_primary_state->src_w = 1920 << 16; + fixture.old_primary_state->src_h = 1080 << 16; + fixture.old_primary_state->crtc_w = 1920; + fixture.old_primary_state->crtc_h = 1080; + fixture.old_primary_state->zpos = 0; + *fixture.primary_state = *fixture.old_primary_state; + fixture.primary_state->state = fixture.state; + + fixture.state->planes[0].ptr = fixture.cursor; + fixture.state->planes[0].old_state = fixture.old_cursor_state; + fixture.state->planes[0].new_state = fixture.cursor_state; + fixture.state->planes[1].ptr = fixture.primary; + fixture.state->planes[1].old_state = fixture.old_primary_state; + fixture.state->planes[1].new_state = fixture.primary_state; + fixture.dm_crtc_state->base.crtc = fixture.crtc; + fixture.dm_crtc_state->base.plane_mask = drm_plane_mask(fixture.cursor) | + drm_plane_mask(fixture.primary); + fixture.dm_crtc_state->base.zpos_changed = true; + fixture.dm_crtc_state->base.mode.hdisplay = 1920; + fixture.dm_crtc_state->base.mode.vdisplay = 1080; + + return fixture; +} + +static void dm_test_add_cursor_mode_colorop(struct kunit *test, + struct dm_cursor_mode_fixture *fixture, + bool old_bypass, bool new_bypass) +{ + struct drm_colorop_state *old_colorop_state; + struct drm_colorop_state *new_colorop_state; + struct drm_colorop *colorop; + + colorop = kunit_kzalloc(test, sizeof(*colorop), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, colorop); + old_colorop_state = kunit_kzalloc(test, sizeof(*old_colorop_state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, old_colorop_state); + new_colorop_state = kunit_kzalloc(test, sizeof(*new_colorop_state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, new_colorop_state); + fixture->state->colorops = + kunit_kzalloc(test, sizeof(*fixture->state->colorops), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fixture->state->colorops); + + fixture->adev->ddev.mode_config.num_colorop = 1; + fixture->state->colorops[0].ptr = colorop; + fixture->state->colorops[0].old_state = old_colorop_state; + fixture->state->colorops[0].new_state = new_colorop_state; + colorop->plane = fixture->primary; + old_colorop_state->colorop = colorop; + old_colorop_state->bypass = old_bypass; + new_colorop_state->colorop = colorop; + new_colorop_state->bypass = new_bypass; +} + +static int dm_test_get_cursor_mode(struct dm_cursor_mode_fixture *fixture, + enum amdgpu_dm_cursor_mode *cursor_mode) +{ + return amdgpu_dm_crtc_get_cursor_mode(fixture->adev, fixture->state, + fixture->dm_crtc_state, cursor_mode); +} + /* Tests for dm_check_cursor_fb() */ /** @@ -358,6 +496,192 @@ static void dm_test_plane_color_pipeline_ignores_other_plane(struct kunit *test) KUNIT_EXPECT_FALSE(test, dm_plane_color_pipeline_active(state, other_plane, false)); } +/* Tests for amdgpu_dm_crtc_get_cursor_mode() */ + +/** + * dm_test_crtc_get_cursor_mode_new_hardware - Test new hardware always uses native mode + * @test: The KUnit test context + */ +static void dm_test_crtc_get_cursor_mode_new_hardware(struct kunit *test) +{ + struct amdgpu_device *adev = dm_kunit_alloc_adev(test); + struct dm_crtc_state *dm_crtc_state; + enum amdgpu_dm_cursor_mode cursor_mode = DM_CURSOR_OVERLAY_MODE; + int ret; + + dm_crtc_state = kunit_kzalloc(test, sizeof(*dm_crtc_state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, dm_crtc_state); + adev->ip_versions[DCE_HWIP][0] = IP_VERSION(4, 2, 0); + + ret = amdgpu_dm_crtc_get_cursor_mode(adev, NULL, dm_crtc_state, &cursor_mode); + KUNIT_EXPECT_EQ(test, ret, 0); + KUNIT_EXPECT_EQ(test, cursor_mode, DM_CURSOR_NATIVE_MODE); +} + +/** + * dm_test_crtc_get_cursor_mode_no_change - Test unchanged atomic state preserves cursor mode + * @test: The KUnit test context + */ +static void dm_test_crtc_get_cursor_mode_no_change(struct kunit *test) +{ + struct amdgpu_device *adev = dm_kunit_alloc_adev(test); + struct drm_atomic_commit *state; + struct dm_crtc_state *dm_crtc_state; + enum amdgpu_dm_cursor_mode cursor_mode = DM_CURSOR_NATIVE_MODE; + int ret; + + state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, state); + dm_crtc_state = kunit_kzalloc(test, sizeof(*dm_crtc_state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, dm_crtc_state); + state->dev = &adev->ddev; + dm_crtc_state->cursor_mode = DM_CURSOR_OVERLAY_MODE; + + ret = amdgpu_dm_crtc_get_cursor_mode(adev, state, dm_crtc_state, &cursor_mode); + KUNIT_EXPECT_EQ(test, ret, 0); + KUNIT_EXPECT_EQ(test, cursor_mode, DM_CURSOR_OVERLAY_MODE); +} + +/** + * dm_test_crtc_get_cursor_mode_disabled_cursor - Test disabled cursor preserves mode + * @test: The KUnit test context + */ +static void dm_test_crtc_get_cursor_mode_disabled_cursor(struct kunit *test) +{ + struct dm_cursor_mode_fixture fixture = dm_test_alloc_cursor_mode_fixture(test); + enum amdgpu_dm_cursor_mode cursor_mode = DM_CURSOR_NATIVE_MODE; + + fixture.cursor_state->crtc = NULL; + fixture.cursor_state->fb = NULL; + + KUNIT_EXPECT_EQ(test, dm_test_get_cursor_mode(&fixture, &cursor_mode), 0); + KUNIT_EXPECT_EQ(test, cursor_mode, DM_CURSOR_NATIVE_MODE); +} + +/** + * dm_test_crtc_get_cursor_mode_yuv_plane - Test YUV plane requires overlay cursor + * @test: The KUnit test context + */ +static void dm_test_crtc_get_cursor_mode_yuv_plane(struct kunit *test) +{ + struct dm_cursor_mode_fixture fixture = dm_test_alloc_cursor_mode_fixture(test); + enum amdgpu_dm_cursor_mode cursor_mode = DM_CURSOR_NATIVE_MODE; + + fixture.primary_fb->format = drm_format_info(DRM_FORMAT_NV12); + + KUNIT_EXPECT_EQ(test, dm_test_get_cursor_mode(&fixture, &cursor_mode), 0); + KUNIT_EXPECT_EQ(test, cursor_mode, DM_CURSOR_OVERLAY_MODE); +} + +/** + * dm_test_crtc_get_cursor_mode_scale_mismatch - Test different scaling requires overlay + * @test: The KUnit test context + */ +static void dm_test_crtc_get_cursor_mode_scale_mismatch(struct kunit *test) +{ + struct dm_cursor_mode_fixture fixture = dm_test_alloc_cursor_mode_fixture(test); + enum amdgpu_dm_cursor_mode cursor_mode = DM_CURSOR_NATIVE_MODE; + + fixture.old_primary_state->src_w = 960 << 16; + fixture.old_primary_state->src_h = 540 << 16; + fixture.primary_state->src_w = 960 << 16; + fixture.primary_state->src_h = 540 << 16; + + KUNIT_EXPECT_EQ(test, dm_test_get_cursor_mode(&fixture, &cursor_mode), 0); + KUNIT_EXPECT_EQ(test, cursor_mode, DM_CURSOR_OVERLAY_MODE); +} + +/** + * dm_test_crtc_get_cursor_mode_full_coverage - Test full RGB coverage uses native cursor + * @test: The KUnit test context + */ +static void dm_test_crtc_get_cursor_mode_full_coverage(struct kunit *test) +{ + struct dm_cursor_mode_fixture fixture = dm_test_alloc_cursor_mode_fixture(test); + enum amdgpu_dm_cursor_mode cursor_mode = DM_CURSOR_OVERLAY_MODE; + + KUNIT_EXPECT_EQ(test, dm_test_get_cursor_mode(&fixture, &cursor_mode), 0); + KUNIT_EXPECT_EQ(test, cursor_mode, DM_CURSOR_NATIVE_MODE); +} + +/** + * dm_test_crtc_get_cursor_mode_hole - Test incomplete plane coverage uses overlay cursor + * @test: The KUnit test context + */ +static void dm_test_crtc_get_cursor_mode_hole(struct kunit *test) +{ + struct dm_cursor_mode_fixture fixture = dm_test_alloc_cursor_mode_fixture(test); + enum amdgpu_dm_cursor_mode cursor_mode = DM_CURSOR_NATIVE_MODE; + + fixture.old_primary_state->crtc_w = 1280; + fixture.primary_state->crtc_w = 1280; + + KUNIT_EXPECT_EQ(test, dm_test_get_cursor_mode(&fixture, &cursor_mode), 0); + KUNIT_EXPECT_EQ(test, cursor_mode, DM_CURSOR_OVERLAY_MODE); +} + +/** + * dm_test_crtc_get_cursor_mode_without_cursor - Test unrelated update avoids cursor state + * @test: The KUnit test context + */ +static void dm_test_crtc_get_cursor_mode_without_cursor(struct kunit *test) +{ + struct dm_cursor_mode_fixture fixture = dm_test_alloc_cursor_mode_fixture(test); + enum amdgpu_dm_cursor_mode cursor_mode = DM_CURSOR_NATIVE_MODE; + + fixture.state->planes[0].ptr = NULL; + fixture.dm_crtc_state->base.plane_mask = drm_plane_mask(fixture.primary); + + KUNIT_EXPECT_EQ(test, dm_test_get_cursor_mode(&fixture, &cursor_mode), 0); + KUNIT_EXPECT_EQ(test, cursor_mode, DM_CURSOR_NATIVE_MODE); +} + +/** + * dm_test_crtc_get_cursor_mode_scale_changed - Test scale change triggers reevaluation + * @test: The KUnit test context + */ +static void dm_test_crtc_get_cursor_mode_scale_changed(struct kunit *test) +{ + struct dm_cursor_mode_fixture fixture = dm_test_alloc_cursor_mode_fixture(test); + enum amdgpu_dm_cursor_mode cursor_mode = DM_CURSOR_NATIVE_MODE; + + fixture.primary_state->src_w = 960 << 16; + fixture.primary_state->src_h = 540 << 16; + + KUNIT_EXPECT_EQ(test, dm_test_get_cursor_mode(&fixture, &cursor_mode), 0); + KUNIT_EXPECT_EQ(test, cursor_mode, DM_CURSOR_OVERLAY_MODE); +} + +/** + * dm_test_crtc_get_cursor_mode_position_changed - Test destination move triggers reevaluation + * @test: The KUnit test context + */ +static void dm_test_crtc_get_cursor_mode_position_changed(struct kunit *test) +{ + struct dm_cursor_mode_fixture fixture = dm_test_alloc_cursor_mode_fixture(test); + enum amdgpu_dm_cursor_mode cursor_mode = DM_CURSOR_NATIVE_MODE; + + fixture.primary_state->crtc_x = 1; + + KUNIT_EXPECT_EQ(test, dm_test_get_cursor_mode(&fixture, &cursor_mode), 0); + KUNIT_EXPECT_EQ(test, cursor_mode, DM_CURSOR_OVERLAY_MODE); +} + +/** + * dm_test_crtc_get_cursor_mode_color_pipeline - Test active color pipeline requires overlay + * @test: The KUnit test context + */ +static void dm_test_crtc_get_cursor_mode_color_pipeline(struct kunit *test) +{ + struct dm_cursor_mode_fixture fixture = dm_test_alloc_cursor_mode_fixture(test); + enum amdgpu_dm_cursor_mode cursor_mode = DM_CURSOR_NATIVE_MODE; + + dm_test_add_cursor_mode_colorop(test, &fixture, true, false); + + KUNIT_EXPECT_EQ(test, dm_test_get_cursor_mode(&fixture, &cursor_mode), 0); + KUNIT_EXPECT_EQ(test, cursor_mode, DM_CURSOR_OVERLAY_MODE); +} + /* Tests for amdgpu_dm_should_update_native_cursor() */ /** @@ -598,6 +922,18 @@ static struct kunit_case amdgpu_dm_cursor_tests[] = { /* dm_plane_color_pipeline_active */ KUNIT_CASE(dm_test_plane_color_pipeline_active), KUNIT_CASE(dm_test_plane_color_pipeline_ignores_other_plane), + /* amdgpu_dm_crtc_get_cursor_mode */ + KUNIT_CASE(dm_test_crtc_get_cursor_mode_new_hardware), + KUNIT_CASE(dm_test_crtc_get_cursor_mode_no_change), + KUNIT_CASE(dm_test_crtc_get_cursor_mode_disabled_cursor), + KUNIT_CASE(dm_test_crtc_get_cursor_mode_yuv_plane), + KUNIT_CASE(dm_test_crtc_get_cursor_mode_scale_mismatch), + KUNIT_CASE(dm_test_crtc_get_cursor_mode_full_coverage), + KUNIT_CASE(dm_test_crtc_get_cursor_mode_hole), + KUNIT_CASE(dm_test_crtc_get_cursor_mode_without_cursor), + KUNIT_CASE(dm_test_crtc_get_cursor_mode_scale_changed), + KUNIT_CASE(dm_test_crtc_get_cursor_mode_position_changed), + KUNIT_CASE(dm_test_crtc_get_cursor_mode_color_pipeline), /* amdgpu_dm_should_update_native_cursor */ KUNIT_CASE(dm_test_should_update_native_cursor_without_crtc), KUNIT_CASE(dm_test_should_update_native_cursor_disable_native), -- 2.43.0