[WHAT]
Add KUnit tests for fill_dc_plane_attributes(), covering the copy of the
plane info into the DC plane state and the scaling, pixel format and 3D
LUT rejection paths.

[HOW]
Reuse the plane info fixture and add a CRTC state complete enough for
the colour management update. A scaling factor of 1 in the plane caps
means no scaling, which matches the 1:1 geometry of the fixture.

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 |   9 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |   3 +
 .../display/amdgpu_dm/tests/amdgpu_dm_test.c  | 126 ++++++++++++++++++
 3 files changed, 134 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 8a87677b46b8..a97caf7e1d33 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3074,10 +3074,10 @@ fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
 }
 EXPORT_IF_KUNIT(fill_dc_plane_info_and_addr);
 
-static int fill_dc_plane_attributes(struct amdgpu_device *adev,
-                                   struct dc_plane_state *dc_plane_state,
-                                   struct drm_plane_state *plane_state,
-                                   struct drm_crtc_state *crtc_state)
+STATIC_IFN_KUNIT int fill_dc_plane_attributes(struct amdgpu_device *adev,
+                                             struct dc_plane_state 
*dc_plane_state,
+                                             struct drm_plane_state 
*plane_state,
+                                             struct drm_crtc_state *crtc_state)
 {
        struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state);
        struct amdgpu_framebuffer *afb = (struct amdgpu_framebuffer 
*)plane_state->fb;
@@ -3130,6 +3130,7 @@ static int fill_dc_plane_attributes(struct amdgpu_device 
*adev,
 
        return 0;
 }
+EXPORT_IF_KUNIT(fill_dc_plane_attributes);
 
 static inline void fill_dc_dirty_rect(struct drm_plane *plane,
                                      struct rect *dirty_rect, int32_t x,
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 09ecca519b3b..b1db78e79015 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -1268,6 +1268,9 @@ int amdgpu_dm_mode_config_init(struct amdgpu_device 
*adev);
 int initialize_plane(struct amdgpu_display_manager *dm, struct 
amdgpu_mode_info *mode_info,
                     int plane_id, enum drm_plane_type plane_type,
                     const struct dc_plane_cap *plane_cap);
+int fill_dc_plane_attributes(struct amdgpu_device *adev, struct dc_plane_state 
*dc_plane_state,
+                            struct drm_plane_state *plane_state,
+                            struct drm_crtc_state *crtc_state);
 #endif
 
 #endif /* __AMDGPU_DM_H__ */
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 0fe19a66e6f9..f8c540a6cdee 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
@@ -3964,6 +3964,127 @@ static void 
dm_test_early_init_unsupported_version(struct kunit *test)
        KUNIT_EXPECT_FALSE(test, adev->dc_enabled);
 }
 
+/* Tests for fill_dc_plane_attributes() */
+
+struct dm_test_plane_attr_ctx {
+       struct amdgpu_device *adev;
+       struct dm_crtc_state *crtc_state;
+       struct dm_test_plane_info_ctx *plane;
+       struct dc_plane_state *dc_plane;
+};
+
+/*
+ * A DC plane, plus a CRTC state complete enough for the colour management
+ * update at the end of fill_dc_plane_attributes(). A scaling factor of 1 in 
the
+ * plane caps means "no scaling", which is what the 1:1 geometry of the plane
+ * info context needs.
+ */
+static struct dm_test_plane_attr_ctx *
+dm_test_plane_attr_ctx_alloc(struct kunit *test, u32 drm_format)
+{
+       struct dm_test_plane_attr_ctx *ctx;
+
+       ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+       ctx->crtc_state = kunit_kzalloc(test, sizeof(*ctx->crtc_state), 
GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ctx->crtc_state);
+       ctx->dc_plane = kunit_kzalloc(test, sizeof(*ctx->dc_plane), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ctx->dc_plane);
+
+       ctx->adev = dm_kunit_alloc_adev(test);
+       ctx->adev->dm.dc = dm_kunit_alloc_dc_with_ctx(test);
+       ctx->adev->dm.dc->caps.planes[0].max_upscale_factor.argb8888 = 1;
+       ctx->adev->dm.dc->caps.planes[0].max_downscale_factor.argb8888 = 1;
+
+       ctx->crtc_state->stream = dm_kunit_alloc_stream(test, NULL);
+       /* Colour management resolves the device through the commit 
backpointer. */
+       ctx->crtc_state->base.state = dm_test_alloc_commit(test, ctx->adev);
+       ctx->plane = dm_test_plane_info_ctx_alloc(test, ctx->adev, drm_format);
+
+       return ctx;
+}
+
+static int dm_test_fill_plane_attr(struct dm_test_plane_attr_ctx *ctx)
+{
+       return fill_dc_plane_attributes(ctx->adev, ctx->dc_plane,
+                                       ctx->plane->plane_state, 
&ctx->crtc_state->base);
+}
+
+/**
+ * dm_test_plane_attributes_success - Test plane info is copied into the DC 
plane
+ * @test: The KUnit test context
+ */
+static void dm_test_plane_attributes_success(struct kunit *test)
+{
+       struct dm_test_plane_attr_ctx *ctx;
+
+       ctx = dm_test_plane_attr_ctx_alloc(test, DRM_FORMAT_ARGB8888);
+       ctx->plane->plane_state->normalized_zpos = 2;
+
+       KUNIT_EXPECT_EQ(test, dm_test_fill_plane_attr(ctx), 0);
+       KUNIT_EXPECT_EQ(test, (int)ctx->dc_plane->format,
+                       (int)SURFACE_PIXEL_FORMAT_GRPH_ARGB8888);
+       KUNIT_EXPECT_EQ(test, (int)ctx->dc_plane->color_space, 
(int)COLOR_SPACE_SRGB);
+       KUNIT_EXPECT_EQ(test, (int)ctx->dc_plane->rotation, 
(int)ROTATION_ANGLE_0);
+       KUNIT_EXPECT_EQ(test, ctx->dc_plane->src_rect.width, 1920U);
+       KUNIT_EXPECT_EQ(test, ctx->dc_plane->dst_rect.width, 1920U);
+       KUNIT_EXPECT_EQ(test, ctx->dc_plane->layer_index, 2);
+       KUNIT_EXPECT_TRUE(test, ctx->dc_plane->visible);
+       KUNIT_EXPECT_TRUE(test, ctx->dc_plane->flip_int_enabled);
+}
+
+/**
+ * dm_test_plane_attributes_bad_scaling - Test an empty source rectangle is 
rejected
+ * @test: The KUnit test context
+ */
+static void dm_test_plane_attributes_bad_scaling(struct kunit *test)
+{
+       struct dm_test_plane_attr_ctx *ctx;
+
+       ctx = dm_test_plane_attr_ctx_alloc(test, DRM_FORMAT_ARGB8888);
+       ctx->plane->plane_state->src_w = 0;
+
+       KUNIT_EXPECT_EQ(test, dm_test_fill_plane_attr(ctx), -EINVAL);
+}
+
+/**
+ * dm_test_plane_attributes_bad_format - Test an unsupported format is rejected
+ * @test: The KUnit test context
+ */
+static void dm_test_plane_attributes_bad_format(struct kunit *test)
+{
+       struct dm_test_plane_attr_ctx *ctx;
+
+       ctx = dm_test_plane_attr_ctx_alloc(test, DRM_FORMAT_YUYV);
+
+       KUNIT_EXPECT_EQ(test, dm_test_fill_plane_attr(ctx), -EINVAL);
+}
+
+/**
+ * dm_test_plane_attributes_bad_color_mgmt - Test a bad 3D LUT is rejected
+ * @test: The KUnit test context
+ */
+static void dm_test_plane_attributes_bad_color_mgmt(struct kunit *test)
+{
+       struct dm_test_plane_attr_ctx *ctx;
+       struct drm_property_blob *blob;
+       struct drm_color_lut *lut;
+
+       ctx = dm_test_plane_attr_ctx_alloc(test, DRM_FORMAT_ARGB8888);
+       blob = kunit_kzalloc(test, sizeof(*blob), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, blob);
+       lut = kunit_kcalloc(test, 16, sizeof(*lut), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, lut);
+
+       /* A 3D LUT that is not a perfect cube fails validation. */
+       blob->data = lut;
+       blob->length = 16 * sizeof(*lut);
+       ctx->adev->dm.dc->caps.color.dpp.hw_3d_lut = true;
+       ctx->plane->dm_plane_state->lut3d = blob;
+
+       KUNIT_EXPECT_EQ(test, dm_test_fill_plane_attr(ctx), -EINVAL);
+}
+
 /* Tests for load_dmcu_fw() */
 
 /**
@@ -4505,6 +4626,11 @@ static struct kunit_case amdgpu_dm_tests[] = {
        KUNIT_CASE(dm_test_early_init_legacy_asics),
        KUNIT_CASE(dm_test_early_init_dcn_versions),
        KUNIT_CASE(dm_test_early_init_unsupported_version),
+       /* fill_dc_plane_attributes */
+       KUNIT_CASE(dm_test_plane_attributes_success),
+       KUNIT_CASE(dm_test_plane_attributes_bad_scaling),
+       KUNIT_CASE(dm_test_plane_attributes_bad_format),
+       KUNIT_CASE(dm_test_plane_attributes_bad_color_mgmt),
        /* load_dmcu_fw */
        KUNIT_CASE(dm_test_load_dmcu_fw_no_dmcu),
        KUNIT_CASE(dm_test_load_dmcu_fw_dcn),
-- 
2.43.0

Reply via email to