From: Alex Hung Date: Thu, 14 May 2026 20:29:52 +0000 (-0600) Subject: drm/amd/display: Add more color KUnit tests X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b640830f1a6f1b5705c2865ef48e066f36fed419;p=thirdparty%2Flinux.git drm/amd/display: Add more color KUnit tests [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 Signed-off-by: Alex Hung Signed-off-by: Ray Wu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- 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 56bf9384c3298..86086d10c5435 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 @@ -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, 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 6f4e97fe6694a..e4f53b7bc7539 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 @@ -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__ */ 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 56eea0f5a75d6..f943361b70e82 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 @@ -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), {} };