]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/amd/display: Add more color KUnit tests
authorAlex Hung <alex.hung@amd.com>
Thu, 14 May 2026 20:29:52 +0000 (14:29 -0600)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 3 Jun 2026 17:40:23 +0000 (13:40 -0400)
[Why & How]
Add KUnit tests for __set_tf_bypass(), __set_tf_distributed_points(),
the bypass paths of amdgpu_dm_set_atomic_regamma(),
amdgpu_dm_atomic_shaper_lut(), and amdgpu_dm_atomic_blend_lut(), and
all three input branches of __set_colorop_in_tf_1d_curve().

Export the three shaper/blend/regamma helpers and
__set_colorop_in_tf_1d_curve with STATIC_IFN_KUNIT and EXPORT_IF_KUNIT
to make their branches reachable from tests.
Add the following test cases in amdgpu_dm_color_test.c:
- dm_test_set_tf_bypass: verify bypass TF setup
- dm_test_set_tf_distributed_points_srgb: validate sRGB gamma
- dm_test_set_tf_distributed_points_pq: validate PQ gamma
- dm_test_set_atomic_regamma_bypass: verify regamma bypass path
- dm_test_atomic_shaper_lut_bypass: verify shaper LUT bypass path
- dm_test_atomic_blend_lut_bypass: verify blend LUT bypass path
- dm_test_set_colorop_in_tf_1d_curve_invalid_type: verify invalid
  colorop type returns -EINVAL
- dm_test_set_colorop_in_tf_1d_curve_unsupported_curve: verify
  unsupported curve type returns -EINVAL
- dm_test_set_colorop_in_tf_1d_curve_bypass: verify bypass path sets
  TF_TYPE_BYPASS and TRANSFER_FUNCTION_LINEAR

Assisted-by: Copilot:Claude-Sonnet-4.6
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Ray Wu <ray.wu@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.h
drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_color_test.c

index 56bf9384c3298e6dadc064429dc70c2bd72157c0..86086d10c5435a733b526deff4107667951bd38c 100644 (file)
@@ -759,21 +759,23 @@ static int __set_output_tf_32(struct dc_transfer_func *func,
        return res ? 0 : -ENOMEM;
 }
 
-static void __set_tf_bypass(struct dc_transfer_func *tf)
+STATIC_IFN_KUNIT void __set_tf_bypass(struct dc_transfer_func *tf)
 {
        tf->type = TF_TYPE_BYPASS;
        tf->tf = TRANSFER_FUNCTION_LINEAR;
 }
+EXPORT_IF_KUNIT(__set_tf_bypass);
 
-static void __set_tf_distributed_points(struct dc_transfer_func *tf,
+STATIC_IFN_KUNIT void __set_tf_distributed_points(struct dc_transfer_func *tf,
                                        enum dc_transfer_func_predefined predefined_tf)
 {
        tf->type = TF_TYPE_DISTRIBUTED_POINTS;
        tf->tf = predefined_tf;
        tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
 }
+EXPORT_IF_KUNIT(__set_tf_distributed_points);
 
-static int amdgpu_dm_set_atomic_regamma(struct dc_transfer_func *out_tf,
+STATIC_IFN_KUNIT int amdgpu_dm_set_atomic_regamma(struct dc_transfer_func *out_tf,
                                        const struct drm_color_lut *regamma_lut,
                                        uint32_t regamma_size, bool has_rom,
                                        enum dc_transfer_func_predefined tf)
@@ -804,6 +806,7 @@ static int amdgpu_dm_set_atomic_regamma(struct dc_transfer_func *out_tf,
 
        return ret;
 }
+EXPORT_IF_KUNIT(amdgpu_dm_set_atomic_regamma);
 
 /**
  * __set_input_tf - calculates the input transfer function based on expected
@@ -1073,7 +1076,7 @@ STATIC_IFN_KUNIT void amdgpu_dm_atomic_lut3d(const struct drm_color_lut *drm_lut
 }
 EXPORT_IF_KUNIT(amdgpu_dm_atomic_lut3d);
 
-static int amdgpu_dm_atomic_shaper_lut(const struct drm_color_lut *shaper_lut,
+STATIC_IFN_KUNIT int amdgpu_dm_atomic_shaper_lut(const struct drm_color_lut *shaper_lut,
                                       bool has_rom,
                                       enum dc_transfer_func_predefined tf,
                                       uint32_t shaper_size,
@@ -1094,8 +1097,9 @@ static int amdgpu_dm_atomic_shaper_lut(const struct drm_color_lut *shaper_lut,
 
        return ret;
 }
+EXPORT_IF_KUNIT(amdgpu_dm_atomic_shaper_lut);
 
-static int amdgpu_dm_atomic_blend_lut(const struct drm_color_lut *blend_lut,
+STATIC_IFN_KUNIT int amdgpu_dm_atomic_blend_lut(const struct drm_color_lut *blend_lut,
                                       bool has_rom,
                                       enum dc_transfer_func_predefined tf,
                                       uint32_t blend_size,
@@ -1119,6 +1123,7 @@ static int amdgpu_dm_atomic_blend_lut(const struct drm_color_lut *blend_lut,
 
        return ret;
 }
+EXPORT_IF_KUNIT(amdgpu_dm_atomic_blend_lut);
 
 /**
  * amdgpu_dm_verify_lut3d_size - verifies if 3D LUT is supported and if user
@@ -1496,7 +1501,7 @@ __set_dm_plane_degamma(struct drm_plane_state *plane_state,
        return 0;
 }
 
-static int
+STATIC_IFN_KUNIT int
 __set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
                             struct drm_colorop_state *colorop_state)
 {
@@ -1522,6 +1527,7 @@ __set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
 
        return 0;
 }
+EXPORT_IF_KUNIT(__set_colorop_in_tf_1d_curve);
 
 static int
 __set_dm_plane_colorop_degamma(struct drm_plane_state *plane_state,
index 6f4e97fe6694a997b8560c60c834aa1b0f7435bf..e4f53b7bc7539c2750cee0dea2a17838bca69cac 100644 (file)
@@ -36,11 +36,14 @@ struct drm_color_lut;
 struct drm_color_lut32;
 struct drm_color_ctm;
 struct drm_color_ctm_3x4;
+struct drm_colorop_state;
 struct drm_property_blob;
 struct dc_gamma;
 struct dc_rgb;
+struct dc_plane_state;
 struct fixed31_32;
 struct tetrahedral_params;
+struct dc_transfer_func;
 
 #if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
 /*
@@ -91,6 +94,25 @@ void amdgpu_dm_atomic_lut3d(const struct drm_color_lut *drm_lut3d,
 int __set_colorop_3dlut(const struct drm_color_lut32 *drm_lut3d,
                        uint32_t drm_lut3d_size,
                        struct dc_3dlut *lut);
+void __set_tf_bypass(struct dc_transfer_func *tf);
+void __set_tf_distributed_points(struct dc_transfer_func *tf,
+                                enum dc_transfer_func_predefined predefined_tf);
+int amdgpu_dm_set_atomic_regamma(struct dc_transfer_func *out_tf,
+                                const struct drm_color_lut *regamma_lut,
+                                uint32_t regamma_size, bool has_rom,
+                                enum dc_transfer_func_predefined tf);
+int amdgpu_dm_atomic_shaper_lut(const struct drm_color_lut *shaper_lut,
+                               bool has_rom,
+                               enum dc_transfer_func_predefined tf,
+                               uint32_t shaper_size,
+                               struct dc_transfer_func *func_shaper);
+int amdgpu_dm_atomic_blend_lut(const struct drm_color_lut *blend_lut,
+                              bool has_rom,
+                              enum dc_transfer_func_predefined tf,
+                              uint32_t blend_size,
+                              struct dc_transfer_func *func_blend);
+int __set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
+                                struct drm_colorop_state *colorop_state);
 #endif
 
 #endif /* __AMDGPU_DM_COLOR_H__ */
index 56eea0f5a75d6e8cb47cadead1108d9c3f5e389d..f943361b70e821b3d54323f90717591eaf4f69da 100644 (file)
@@ -1316,6 +1316,217 @@ static void dm_test_set_colorop_3dlut_data_forwarded(struct kunit *test)
                        drm_color_lut32_extract(0x40000000, 12));
 }
 
+/**
+ * dm_test_set_tf_bypass - __set_tf_bypass: sets TF_TYPE_BYPASS and TRANSFER_FUNCTION_LINEAR
+ * @test: KUnit test context
+ */
+static void dm_test_set_tf_bypass(struct kunit *test)
+{
+       struct dc_transfer_func *tf;
+
+       tf = kunit_kzalloc(test, sizeof(*tf), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, tf);
+
+       tf->type = TF_TYPE_DISTRIBUTED_POINTS;
+       tf->tf = TRANSFER_FUNCTION_SRGB;
+
+       __set_tf_bypass(tf);
+
+       KUNIT_EXPECT_EQ(test, (int)tf->type, (int)TF_TYPE_BYPASS);
+       KUNIT_EXPECT_EQ(test, (int)tf->tf, (int)TRANSFER_FUNCTION_LINEAR);
+}
+
+/**
+ * dm_test_set_tf_distributed_points_srgb - __set_tf_distributed_points: sRGB predefined TF
+ * @test: KUnit test context
+ */
+static void dm_test_set_tf_distributed_points_srgb(struct kunit *test)
+{
+       struct dc_transfer_func *tf;
+
+       tf = kunit_kzalloc(test, sizeof(*tf), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, tf);
+
+       __set_tf_distributed_points(tf, TRANSFER_FUNCTION_SRGB);
+
+       KUNIT_EXPECT_EQ(test, (int)tf->type, (int)TF_TYPE_DISTRIBUTED_POINTS);
+       KUNIT_EXPECT_EQ(test, (int)tf->tf, (int)TRANSFER_FUNCTION_SRGB);
+       KUNIT_EXPECT_EQ(test, tf->sdr_ref_white_level, 80U);
+}
+
+/**
+ * dm_test_set_tf_distributed_points_pq - __set_tf_distributed_points: PQ predefined TF
+ * @test: KUnit test context
+ */
+static void dm_test_set_tf_distributed_points_pq(struct kunit *test)
+{
+       struct dc_transfer_func *tf;
+
+       tf = kunit_kzalloc(test, sizeof(*tf), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, tf);
+
+       __set_tf_distributed_points(tf, TRANSFER_FUNCTION_PQ);
+
+       KUNIT_EXPECT_EQ(test, (int)tf->type, (int)TF_TYPE_DISTRIBUTED_POINTS);
+       KUNIT_EXPECT_EQ(test, (int)tf->tf, (int)TRANSFER_FUNCTION_PQ);
+       KUNIT_EXPECT_EQ(test, tf->sdr_ref_white_level, 80U);
+}
+
+/**
+ * dm_test_set_atomic_regamma_bypass - No LUT and linear TF: must take bypass path
+ * @test: KUnit test context
+ */
+static void dm_test_set_atomic_regamma_bypass(struct kunit *test)
+{
+       struct dc_transfer_func *out_tf;
+
+       out_tf = kunit_kzalloc(test, sizeof(*out_tf), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, out_tf);
+
+       /* size=0 and tf=LINEAR: must take the bypass branch */
+       KUNIT_EXPECT_EQ(test,
+               amdgpu_dm_set_atomic_regamma(out_tf, NULL, 0, false,
+                                            TRANSFER_FUNCTION_LINEAR),
+               0);
+       KUNIT_EXPECT_EQ(test, (int)out_tf->type, (int)TF_TYPE_BYPASS);
+       KUNIT_EXPECT_EQ(test, (int)out_tf->tf, (int)TRANSFER_FUNCTION_LINEAR);
+}
+
+/**
+ * dm_test_atomic_shaper_lut_bypass - No LUT and linear TF: must take bypass path
+ * @test: KUnit test context
+ */
+static void dm_test_atomic_shaper_lut_bypass(struct kunit *test)
+{
+       struct dc_transfer_func *func_shaper;
+
+       func_shaper = kunit_kzalloc(test, sizeof(*func_shaper), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, func_shaper);
+
+       /* size=0 and tf=LINEAR: must take the bypass branch */
+       KUNIT_EXPECT_EQ(test,
+               amdgpu_dm_atomic_shaper_lut(NULL, false,
+                                           TRANSFER_FUNCTION_LINEAR,
+                                           0, func_shaper),
+               0);
+       KUNIT_EXPECT_EQ(test, (int)func_shaper->type, (int)TF_TYPE_BYPASS);
+       KUNIT_EXPECT_EQ(test, (int)func_shaper->tf, (int)TRANSFER_FUNCTION_LINEAR);
+}
+
+/**
+ * dm_test_atomic_blend_lut_bypass - amdgpu_dm_atomic_blend_lut bypass: no LUT, linear TF -> bypass
+ * @test: KUnit test context
+ */
+static void dm_test_atomic_blend_lut_bypass(struct kunit *test)
+{
+       struct dc_transfer_func *func_blend;
+
+       func_blend = kunit_kzalloc(test, sizeof(*func_blend), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, func_blend);
+
+       /* size=0 and tf=LINEAR: must take the bypass branch */
+       KUNIT_EXPECT_EQ(test,
+               amdgpu_dm_atomic_blend_lut(NULL, false,
+                                          TRANSFER_FUNCTION_LINEAR,
+                                          0, func_blend),
+               0);
+       KUNIT_EXPECT_EQ(test, (int)func_blend->type, (int)TF_TYPE_BYPASS);
+       KUNIT_EXPECT_EQ(test, (int)func_blend->tf, (int)TRANSFER_FUNCTION_LINEAR);
+}
+
+/* ---- Tests for __set_colorop_in_tf_1d_curve ---- */
+
+/**
+ * dm_test_set_colorop_in_tf_1d_curve_invalid_type - Non-1D colorop type must be rejected
+ * @test: KUnit test context
+ */
+static void dm_test_set_colorop_in_tf_1d_curve_invalid_type(struct kunit *test)
+{
+       struct dc_plane_state *dc_plane_state;
+       struct drm_colorop *colorop;
+       struct drm_colorop_state *colorop_state;
+
+       dc_plane_state = kunit_kzalloc(test, sizeof(*dc_plane_state), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, dc_plane_state);
+
+       colorop = kunit_kzalloc(test, sizeof(*colorop), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, colorop);
+
+       colorop_state = kunit_kzalloc(test, sizeof(*colorop_state), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, colorop_state);
+
+       colorop->type = DRM_COLOROP_3D_LUT;
+       colorop_state->colorop = colorop;
+       colorop_state->curve_1d_type = DRM_COLOROP_1D_CURVE_SRGB_EOTF;
+
+       KUNIT_EXPECT_EQ(test,
+               __set_colorop_in_tf_1d_curve(dc_plane_state, colorop_state),
+               -EINVAL);
+}
+
+/**
+ * dm_test_set_colorop_in_tf_1d_curve_unsupported_curve - Unsupported 1D curve type must be rejected
+ * @test: KUnit test context
+ */
+static void dm_test_set_colorop_in_tf_1d_curve_unsupported_curve(struct kunit *test)
+{
+       struct dc_plane_state *dc_plane_state;
+       struct drm_colorop *colorop;
+       struct drm_colorop_state *colorop_state;
+
+       dc_plane_state = kunit_kzalloc(test, sizeof(*dc_plane_state), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, dc_plane_state);
+
+       colorop = kunit_kzalloc(test, sizeof(*colorop), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, colorop);
+
+       colorop_state = kunit_kzalloc(test, sizeof(*colorop_state), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, colorop_state);
+
+       colorop->type = DRM_COLOROP_1D_CURVE;
+       colorop_state->colorop = colorop;
+       colorop_state->curve_1d_type = DRM_COLOROP_1D_CURVE_COUNT;
+
+       KUNIT_EXPECT_EQ(test,
+               __set_colorop_in_tf_1d_curve(dc_plane_state, colorop_state),
+               -EINVAL);
+}
+
+/**
+ * dm_test_set_colorop_in_tf_1d_curve_bypass - Bypass mode forces linear bypass transfer function
+ * @test: KUnit test context
+ */
+static void dm_test_set_colorop_in_tf_1d_curve_bypass(struct kunit *test)
+{
+       struct dc_plane_state *dc_plane_state;
+       struct drm_colorop *colorop;
+       struct drm_colorop_state *colorop_state;
+
+       dc_plane_state = kunit_kzalloc(test, sizeof(*dc_plane_state), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, dc_plane_state);
+
+       colorop = kunit_kzalloc(test, sizeof(*colorop), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, colorop);
+
+       colorop_state = kunit_kzalloc(test, sizeof(*colorop_state), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, colorop_state);
+
+       colorop->type = DRM_COLOROP_1D_CURVE;
+       colorop_state->colorop = colorop;
+       colorop_state->curve_1d_type = DRM_COLOROP_1D_CURVE_SRGB_EOTF;
+       colorop_state->bypass = true;
+
+       KUNIT_EXPECT_EQ(test,
+               __set_colorop_in_tf_1d_curve(dc_plane_state, colorop_state),
+               0);
+       KUNIT_EXPECT_EQ(test,
+               (int)dc_plane_state->in_transfer_func.type,
+               (int)TF_TYPE_BYPASS);
+       KUNIT_EXPECT_EQ(test,
+               (int)dc_plane_state->in_transfer_func.tf,
+               (int)TRANSFER_FUNCTION_LINEAR);
+}
+
 static struct kunit_case dm_color_test_cases[] = {
        /* amdgpu_dm_fixpt_from_s3132 */
        KUNIT_CASE(dm_test_fixpt_from_s3132_zero),
@@ -1398,6 +1609,21 @@ static struct kunit_case dm_color_test_cases[] = {
        KUNIT_CASE(dm_test_set_colorop_3dlut_zero_size),
        KUNIT_CASE(dm_test_set_colorop_3dlut_nonzero_state_bits),
        KUNIT_CASE(dm_test_set_colorop_3dlut_data_forwarded),
+       /* __set_tf_bypass */
+       KUNIT_CASE(dm_test_set_tf_bypass),
+       /* __set_tf_distributed_points */
+       KUNIT_CASE(dm_test_set_tf_distributed_points_srgb),
+       KUNIT_CASE(dm_test_set_tf_distributed_points_pq),
+       /* amdgpu_dm_set_atomic_regamma */
+       KUNIT_CASE(dm_test_set_atomic_regamma_bypass),
+       /* amdgpu_dm_atomic_shaper_lut */
+       KUNIT_CASE(dm_test_atomic_shaper_lut_bypass),
+       /* amdgpu_dm_atomic_blend_lut */
+       KUNIT_CASE(dm_test_atomic_blend_lut_bypass),
+       /* __set_colorop_in_tf_1d_curve */
+       KUNIT_CASE(dm_test_set_colorop_in_tf_1d_curve_invalid_type),
+       KUNIT_CASE(dm_test_set_colorop_in_tf_1d_curve_unsupported_curve),
+       KUNIT_CASE(dm_test_set_colorop_in_tf_1d_curve_bypass),
        {}
 };