From: Alex Hung <[email protected]>

[WHAT]
Add KUnit coverage for the per-colorop plane helpers
__set_dm_plane_colorop_multiplier(), __set_dm_plane_colorop_3x4_matrix()
and __set_dm_plane_colorop_degamma().

A single-colorop atomic-state fixture drives each helper: the multiplier
programs hdr_mult, the 3x4 matrix enables gamut remap (and rejects a
wrong blob length), and the degamma 1D curve maps to a predefined
transfer function (and rejects an unsupported curve).

Assisted-by: Copilot:Claude-Opus-4.8 GPT-5.5
Reviewed-by: Bhawanpreet Lakha <[email protected]>
Signed-off-by: Alex Hung <[email protected]>
Signed-off-by: Wayne Lin <[email protected]>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   |   9 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_color.h   |  11 +
 .../amdgpu_dm/tests/amdgpu_dm_color_test.c    | 207 ++++++++++++++++++
 3 files changed, 224 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index 45d11990bc8e..2f46de79a47c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -1547,7 +1547,7 @@ __set_colorop_in_tf_1d_curve(struct dc_plane_state 
*dc_plane_state,
 }
 EXPORT_IF_KUNIT(__set_colorop_in_tf_1d_curve);
 
-static int
+STATIC_IFN_KUNIT int
 __set_dm_plane_colorop_degamma(struct drm_plane_state *plane_state,
                               struct dc_plane_state *dc_plane_state,
                               struct drm_colorop *colorop)
@@ -1573,8 +1573,9 @@ __set_dm_plane_colorop_degamma(struct drm_plane_state 
*plane_state,
 
        return __set_colorop_in_tf_1d_curve(dc_plane_state, colorop_state);
 }
+EXPORT_IF_KUNIT(__set_dm_plane_colorop_degamma);
 
-static int
+STATIC_IFN_KUNIT int
 __set_dm_plane_colorop_3x4_matrix(struct drm_plane_state *plane_state,
                                  struct dc_plane_state *dc_plane_state,
                                  struct drm_colorop *colorop)
@@ -1614,8 +1615,9 @@ __set_dm_plane_colorop_3x4_matrix(struct drm_plane_state 
*plane_state,
 
        return 0;
 }
+EXPORT_IF_KUNIT(__set_dm_plane_colorop_3x4_matrix);
 
-static int
+STATIC_IFN_KUNIT int
 __set_dm_plane_colorop_multiplier(struct drm_plane_state *plane_state,
                                  struct dc_plane_state *dc_plane_state,
                                  struct drm_colorop *colorop)
@@ -1643,6 +1645,7 @@ __set_dm_plane_colorop_multiplier(struct drm_plane_state 
*plane_state,
 
        return 0;
 }
+EXPORT_IF_KUNIT(__set_dm_plane_colorop_multiplier);
 
 static int
 __set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.h
index 8dbbcb3ab156..1a8b06bdaf44 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.h
@@ -113,6 +113,17 @@ int amdgpu_dm_atomic_blend_lut(const struct drm_color_lut 
*blend_lut,
                               struct dc_plane_cm *cm);
 int __set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
                                 struct drm_colorop_state *colorop_state);
+struct drm_plane_state;
+struct drm_colorop;
+int __set_dm_plane_colorop_degamma(struct drm_plane_state *plane_state,
+                                  struct dc_plane_state *dc_plane_state,
+                                  struct drm_colorop *colorop);
+int __set_dm_plane_colorop_3x4_matrix(struct drm_plane_state *plane_state,
+                                     struct dc_plane_state *dc_plane_state,
+                                     struct drm_colorop *colorop);
+int __set_dm_plane_colorop_multiplier(struct drm_plane_state *plane_state,
+                                     struct dc_plane_state *dc_plane_state,
+                                     struct drm_colorop *colorop);
 #endif
 
 #endif /* __AMDGPU_DM_COLOR_H__ */
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_color_test.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_color_test.c
index e46a8454425d..a4253e44ca7b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_color_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_color_test.c
@@ -1643,6 +1643,204 @@ static void dm_test_verify_lut3d_valid(struct kunit 
*test)
        KUNIT_EXPECT_EQ(test, amdgpu_dm_verify_lut3d_size(adev, plane_state), 
0);
 }
 
+/* ---- Tests for plane colorop helpers ---- */
+
+/**
+ * struct dm_test_colorop_fixture - shared state for plane colorop walk tests
+ * @adev: backing amdgpu device (provides a real DRM device)
+ * @state: fabricated atomic state with a single colorop slot
+ * @colorop: the colorop under test
+ * @colorop_state: the new state attached to @colorop
+ * @plane_state: plane state whose ->state points at @state
+ * @dc_plane_state: DC plane state written by the helpers
+ */
+struct dm_test_colorop_fixture {
+       struct amdgpu_device *adev;
+       struct drm_atomic_state *state;
+       struct drm_colorop *colorop;
+       struct drm_colorop_state *colorop_state;
+       struct drm_plane_state *plane_state;
+       struct dc_plane_state *dc_plane_state;
+};
+
+/**
+ * dm_test_colorop_setup - build a single-colorop atomic state fixture
+ * @test: KUnit test context
+ * @type: colorop type to assign
+ *
+ * Fabricates a minimal drm_atomic_state with one colorop slot so that
+ * for_each_new_colorop_in_state() finds exactly the colorop under test.
+ *
+ * Returns: a populated fixture (by value).
+ */
+static struct dm_test_colorop_fixture
+dm_test_colorop_setup(struct kunit *test, enum drm_colorop_type type)
+{
+       struct dm_test_colorop_fixture f = {0};
+       struct __drm_colorops_state *colorops;
+       struct dm_plane_state *dm_plane_state;
+
+       f.adev = dm_kunit_alloc_adev(test);
+       f.adev->ddev.mode_config.num_colorop = 1;
+
+       f.colorop = kunit_kzalloc(test, sizeof(*f.colorop), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, f.colorop);
+       f.colorop->dev = &f.adev->ddev;
+       f.colorop->type = type;
+
+       f.colorop_state = kunit_kzalloc(test, sizeof(*f.colorop_state), 
GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, f.colorop_state);
+       f.colorop_state->colorop = f.colorop;
+
+       colorops = kunit_kcalloc(test, 1, sizeof(*colorops), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, colorops);
+       colorops[0].ptr = f.colorop;
+       colorops[0].new_state = f.colorop_state;
+
+       f.state = kunit_kzalloc(test, sizeof(*f.state), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, f.state);
+       f.state->dev = &f.adev->ddev;
+       f.state->colorops = colorops;
+
+       dm_plane_state = kunit_kzalloc(test, sizeof(*dm_plane_state), 
GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, dm_plane_state);
+       f.plane_state = &dm_plane_state->base;
+       f.plane_state->state = f.state;
+
+       f.dc_plane_state = kunit_kzalloc(test, sizeof(*f.dc_plane_state), 
GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, f.dc_plane_state);
+
+       return f;
+}
+
+/**
+ * dm_test_colorop_multiplier_applied - Multiplier colorop programs hdr_mult
+ * @test: KUnit test context
+ */
+static void dm_test_colorop_multiplier_applied(struct kunit *test)
+{
+       struct dm_test_colorop_fixture f =
+               dm_test_colorop_setup(test, DRM_COLOROP_MULTIPLIER);
+
+       /* 1.0 in S31.32 sign-magnitude */
+       f.colorop_state->multiplier = 1ULL << 32;
+
+       KUNIT_EXPECT_EQ(test,
+               __set_dm_plane_colorop_multiplier(f.plane_state, 
f.dc_plane_state, f.colorop),
+               0);
+       KUNIT_EXPECT_EQ(test, f.dc_plane_state->hdr_mult.value, (long 
long)(1ULL << 32));
+}
+
+/**
+ * dm_test_colorop_multiplier_no_match - Non-multiplier colorop leaves 
hdr_mult untouched
+ * @test: KUnit test context
+ */
+static void dm_test_colorop_multiplier_no_match(struct kunit *test)
+{
+       struct dm_test_colorop_fixture f =
+               dm_test_colorop_setup(test, DRM_COLOROP_1D_CURVE);
+
+       f.colorop_state->multiplier = 1ULL << 32;
+
+       KUNIT_EXPECT_EQ(test,
+                       __set_dm_plane_colorop_multiplier(f.plane_state, 
f.dc_plane_state, f.colorop),
+                       0);
+       KUNIT_EXPECT_EQ(test, f.dc_plane_state->hdr_mult.value, 0LL);
+}
+
+/**
+ * dm_test_colorop_3x4_matrix_applied - CTM 3x4 colorop enables gamut remap
+ * @test: KUnit test context
+ */
+static void dm_test_colorop_3x4_matrix_applied(struct kunit *test)
+{
+       struct dm_test_colorop_fixture f =
+               dm_test_colorop_setup(test, DRM_COLOROP_CTM_3X4);
+       struct drm_property_blob *blob;
+       struct drm_color_ctm_3x4 *ctm;
+
+       ctm = kunit_kzalloc(test, sizeof(*ctm), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ctm);
+       ctm->matrix[0] = 1ULL << 32; /* identity diagonal */
+       ctm->matrix[5] = 1ULL << 32;
+       ctm->matrix[10] = 1ULL << 32;
+
+       blob = kunit_kzalloc(test, sizeof(*blob), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, blob);
+       blob->data = ctm;
+       blob->length = sizeof(struct drm_color_ctm_3x4);
+       f.colorop_state->data = blob;
+
+       KUNIT_EXPECT_EQ(test,
+                       __set_dm_plane_colorop_3x4_matrix(f.plane_state, 
f.dc_plane_state, f.colorop),
+                       0);
+       KUNIT_EXPECT_TRUE(test, 
f.dc_plane_state->gamut_remap_matrix.enable_remap);
+       KUNIT_EXPECT_FALSE(test, 
f.dc_plane_state->input_csc_color_matrix.enable_adjustment);
+}
+
+/**
+ * dm_test_colorop_3x4_matrix_bad_length - Wrong blob length: must return 
-EINVAL
+ * @test: KUnit test context
+ */
+static void dm_test_colorop_3x4_matrix_bad_length(struct kunit *test)
+{
+       struct dm_test_colorop_fixture f =
+               dm_test_colorop_setup(test, DRM_COLOROP_CTM_3X4);
+       struct drm_property_blob *blob;
+
+       blob = kunit_kzalloc(test, sizeof(*blob), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, blob);
+       blob->data = kunit_kzalloc(test, 8, GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, blob->data);
+       blob->length = 7; /* not sizeof(struct drm_color_ctm_3x4) */
+       f.colorop_state->data = blob;
+
+       KUNIT_EXPECT_EQ(test,
+                       __set_dm_plane_colorop_3x4_matrix(f.plane_state, 
f.dc_plane_state, f.colorop),
+                       -EINVAL);
+}
+
+/**
+ * dm_test_colorop_degamma_predefined - Degamma 1D curve programs predefined TF
+ * @test: KUnit test context
+ */
+static void dm_test_colorop_degamma_predefined(struct kunit *test)
+{
+       struct dm_test_colorop_fixture f =
+               dm_test_colorop_setup(test, DRM_COLOROP_1D_CURVE);
+
+       /* SRGB_EOTF is part of amdgpu_dm_supported_degam_tfs */
+       f.colorop_state->curve_1d_type = DRM_COLOROP_1D_CURVE_SRGB_EOTF;
+       f.colorop_state->bypass = false;
+
+       KUNIT_EXPECT_EQ(test,
+                       __set_dm_plane_colorop_degamma(f.plane_state, 
f.dc_plane_state, f.colorop),
+                       0);
+       KUNIT_EXPECT_EQ(test,
+                       (int)f.dc_plane_state->in_transfer_func.type,
+                       (int)TF_TYPE_PREDEFINED);
+       KUNIT_EXPECT_EQ(test,
+                       (int)f.dc_plane_state->in_transfer_func.tf,
+                       (int)TRANSFER_FUNCTION_SRGB);
+}
+
+/**
+ * dm_test_colorop_degamma_no_match - Unsupported degamma curve: must return 
-EINVAL
+ * @test: KUnit test context
+ */
+static void dm_test_colorop_degamma_no_match(struct kunit *test)
+{
+       struct dm_test_colorop_fixture f =
+               dm_test_colorop_setup(test, DRM_COLOROP_1D_CURVE);
+
+       /* SRGB_INV_EOTF is a shaper TF, not in amdgpu_dm_supported_degam_tfs */
+       f.colorop_state->curve_1d_type = DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF;
+
+       KUNIT_EXPECT_EQ(test,
+                       __set_dm_plane_colorop_degamma(f.plane_state, 
f.dc_plane_state, f.colorop),
+                       -EINVAL);
+}
+
 static struct kunit_case dm_color_test_cases[] = {
        /* amdgpu_dm_fixpt_from_s3132 */
        KUNIT_CASE(dm_test_fixpt_from_s3132_zero),
@@ -1747,6 +1945,15 @@ static struct kunit_case dm_color_test_cases[] = {
        KUNIT_CASE(dm_test_verify_lut3d_bad_shaper),
        KUNIT_CASE(dm_test_verify_lut3d_bad_lut3d),
        KUNIT_CASE(dm_test_verify_lut3d_valid),
+       /* __set_dm_plane_colorop_multiplier */
+       KUNIT_CASE(dm_test_colorop_multiplier_applied),
+       KUNIT_CASE(dm_test_colorop_multiplier_no_match),
+       /* __set_dm_plane_colorop_3x4_matrix */
+       KUNIT_CASE(dm_test_colorop_3x4_matrix_applied),
+       KUNIT_CASE(dm_test_colorop_3x4_matrix_bad_length),
+       /* __set_dm_plane_colorop_degamma */
+       KUNIT_CASE(dm_test_colorop_degamma_predefined),
+       KUNIT_CASE(dm_test_colorop_degamma_no_match),
        {}
 };
 
-- 
2.43.0

Reply via email to