summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorBhawanpreet Lakha <bhawanpreet.lakha@amd.com>2026-07-15 14:45:41 -0400
committerAlex Deucher <alexander.deucher@amd.com>2026-08-06 09:58:58 -0400
commit5eccb2c27bde6197cea67372ec528c5791609849 (patch)
tree792f39232e922ae13a1d91733435fa04b17e6783 /drivers
parent7d52e9cf8059289e2959a4e307e58797d01d317a (diff)
downloadlinux-5eccb2c27bde6197cea67372ec528c5791609849.tar.gz
linux-5eccb2c27bde6197cea67372ec528c5791609849.zip
drm/amd/display: Add active plane count tests for crtc
Expose amdgpu_dm_crtc_count_crtc_active_planes() for KUnit and add tests covering the empty plane list and the mixed case exercising the mask filter, cursor skip, missing plane state, and framebuffer presence branches. Assisted-by: Copilot:Claude-Opus-4.8 Reviewed-by: Alex Hung <alex.hung@amd.com> Signed-off-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com> Signed-off-by: Roman Li <roman.li@amd.com> Tested-by: Dan Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c3
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h1
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c115
3 files changed, 118 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
index fd816be907c4..82a30097072e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
@@ -587,7 +587,7 @@ static void amdgpu_dm_crtc_helper_disable(struct drm_crtc *crtc)
{
}
-static int amdgpu_dm_crtc_count_crtc_active_planes(struct drm_crtc_state *new_crtc_state)
+STATIC_IFN_KUNIT int amdgpu_dm_crtc_count_crtc_active_planes(struct drm_crtc_state *new_crtc_state)
{
struct drm_atomic_commit *state = new_crtc_state->state;
struct drm_plane *plane;
@@ -618,6 +618,7 @@ static int amdgpu_dm_crtc_count_crtc_active_planes(struct drm_crtc_state *new_cr
return num_active;
}
+EXPORT_IF_KUNIT(amdgpu_dm_crtc_count_crtc_active_planes);
STATIC_IFN_KUNIT void amdgpu_dm_crtc_update_crtc_active_planes(struct drm_crtc *crtc,
struct drm_crtc_state *new_crtc_state)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h
index d1e2cb4efc54..93c6d0d8d7fd 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h
@@ -50,6 +50,7 @@ void amdgpu_dm_crtc_destroy_state(struct drm_crtc *crtc,
struct drm_crtc_state *state);
struct drm_crtc_state *amdgpu_dm_crtc_duplicate_state(struct drm_crtc *crtc);
void amdgpu_dm_crtc_reset_state(struct drm_crtc *crtc);
+int amdgpu_dm_crtc_count_crtc_active_planes(struct drm_crtc_state *new_crtc_state);
void amdgpu_dm_crtc_update_crtc_active_planes(struct drm_crtc *crtc,
struct drm_crtc_state *new_crtc_state);
void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
index f5d9424171e8..9948d1780454 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
@@ -706,6 +706,118 @@ static void dm_test_crtc_update_active_planes_no_stream(struct kunit *test)
KUNIT_EXPECT_EQ(test, dm_state->active_planes, 0);
}
+/* Tests for amdgpu_dm_crtc_count_crtc_active_planes() */
+
+static void dm_test_add_plane(struct drm_device *dev, struct drm_plane *plane,
+ unsigned int index, enum drm_plane_type type)
+{
+ INIT_LIST_HEAD(&plane->head);
+ plane->index = index;
+ plane->type = type;
+ list_add_tail(&plane->head, &dev->mode_config.plane_list);
+}
+
+/**
+ * dm_test_count_crtc_active_planes_none - Test empty plane list counts zero
+ * @test: The KUnit test context
+ *
+ * With no planes attached to the CRTC the active plane count must be zero.
+ */
+static void dm_test_count_crtc_active_planes_none(struct kunit *test)
+{
+ struct drm_crtc_state *crtc_state;
+ struct drm_atomic_commit *state;
+ struct drm_device *dev;
+
+ dev = dm_kunit_alloc_drm_with_connector_list(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+ INIT_LIST_HEAD(&dev->mode_config.plane_list);
+
+ state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+ state->dev = dev;
+
+ crtc_state = kunit_kzalloc(test, sizeof(*crtc_state), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
+ crtc_state->state = state;
+ crtc_state->plane_mask = 0;
+
+ KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_count_crtc_active_planes(crtc_state), 0);
+}
+
+/**
+ * dm_test_count_crtc_active_planes_mixed - Test counting across all plane cases
+ * @test: The KUnit test context
+ *
+ * Exercises every branch of the counting loop: a plane excluded by the mask,
+ * a cursor plane (skipped), a masked plane with no new state (counted), a
+ * masked plane with a framebuffer (counted) and a masked plane without a
+ * framebuffer (not counted). Only two planes should be reported active.
+ */
+static void dm_test_count_crtc_active_planes_mixed(struct kunit *test)
+{
+ struct drm_plane *plane_no_state;
+ struct drm_plane *plane_cursor;
+ struct drm_plane *plane_with_fb;
+ struct drm_plane *plane_no_fb;
+ struct drm_plane *plane_excluded;
+ struct drm_plane_state *ps_fb;
+ struct drm_plane_state *ps_no_fb;
+ struct drm_crtc_state *crtc_state;
+ struct drm_atomic_commit *state;
+ struct drm_framebuffer *fb;
+ struct drm_device *dev;
+
+ dev = dm_kunit_alloc_drm_with_connector_list(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+ INIT_LIST_HEAD(&dev->mode_config.plane_list);
+
+ plane_no_state = kunit_kzalloc(test, sizeof(*plane_no_state), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_no_state);
+ plane_cursor = kunit_kzalloc(test, sizeof(*plane_cursor), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cursor);
+ plane_with_fb = kunit_kzalloc(test, sizeof(*plane_with_fb), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_with_fb);
+ plane_no_fb = kunit_kzalloc(test, sizeof(*plane_no_fb), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_no_fb);
+ plane_excluded = kunit_kzalloc(test, sizeof(*plane_excluded), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_excluded);
+
+ dm_test_add_plane(dev, plane_no_state, 0, DRM_PLANE_TYPE_PRIMARY);
+ dm_test_add_plane(dev, plane_cursor, 1, DRM_PLANE_TYPE_CURSOR);
+ dm_test_add_plane(dev, plane_with_fb, 2, DRM_PLANE_TYPE_PRIMARY);
+ dm_test_add_plane(dev, plane_no_fb, 3, DRM_PLANE_TYPE_PRIMARY);
+ dm_test_add_plane(dev, plane_excluded, 4, DRM_PLANE_TYPE_PRIMARY);
+
+ fb = kunit_kzalloc(test, sizeof(*fb), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fb);
+ ps_fb = kunit_kzalloc(test, sizeof(*ps_fb), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ps_fb);
+ ps_fb->fb = fb;
+ ps_no_fb = kunit_kzalloc(test, sizeof(*ps_no_fb), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ps_no_fb);
+ ps_no_fb->fb = NULL;
+
+ state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+ state->dev = dev;
+ state->planes = kunit_kzalloc(test, sizeof(*state->planes) * 5, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state->planes);
+ state->planes[0].new_state = NULL;
+ state->planes[1].new_state = ps_fb;
+ state->planes[2].new_state = ps_fb;
+ state->planes[3].new_state = ps_no_fb;
+ state->planes[4].new_state = ps_fb;
+
+ crtc_state = kunit_kzalloc(test, sizeof(*crtc_state), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
+ crtc_state->state = state;
+ /* Exclude plane index 4 from the CRTC. */
+ crtc_state->plane_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3);
+
+ KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_count_crtc_active_planes(crtc_state), 2);
+}
+
/* Tests for amdgpu_dm_crtc_duplicate_state() */
/**
@@ -1044,6 +1156,9 @@ static struct kunit_case amdgpu_dm_crtc_tests[] = {
KUNIT_CASE(dm_test_crtc_enable_vblank_rejects_unconfigured),
/* amdgpu_dm_crtc_update_crtc_active_planes */
KUNIT_CASE(dm_test_crtc_update_active_planes_no_stream),
+ /* amdgpu_dm_crtc_count_crtc_active_planes */
+ KUNIT_CASE(dm_test_count_crtc_active_planes_none),
+ KUNIT_CASE(dm_test_count_crtc_active_planes_mixed),
/* amdgpu_dm_crtc_duplicate_state */
KUNIT_CASE(dm_test_crtc_duplicate_state_copies_fields),
/* amdgpu_dm_crtc_reset_state */