From: Alex Hung <[email protected]> [WHY] The color transfer-function calculation helpers were not covered by the amdgpu_dm_color KUnit suite. They rely on DAL fixed-point math and run under the KUnit UML build without native floating point.
[HOW] Expose the five static helpers to KUnit and add direct coverage for the legacy, 16-bit, and 32-bit input and output transfer-function paths, including sRGB, linear, and ROM-backed variants. Assisted-by: Copilot:GPT-5.6-Sol Reviewed-by: Bhawanpreet Lakha <[email protected]> Signed-off-by: Alex Hung <[email protected]> Signed-off-by: Fangzhi Zuo <[email protected]> Tested-by: Dan Wheeler <[email protected]> --- .../amd/display/amdgpu_dm/amdgpu_dm_color.c | 36 +++-- .../amd/display/amdgpu_dm/amdgpu_dm_color.h | 14 ++ .../amdgpu_dm/tests/amdgpu_dm_color_test.c | 147 ++++++++++++++++++ 3 files changed, 184 insertions(+), 13 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 658dfc37d4d4..7b68c6846039 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 @@ -618,9 +618,10 @@ EXPORT_IF_KUNIT(__drm_ctm_3x4_to_dc_matrix); * Returns: * 0 in case of success, -ENOMEM if fails */ -static int __set_legacy_tf(struct dc_transfer_func *func, - const struct drm_color_lut *lut, uint32_t lut_size, - bool has_rom) +STATIC_IFN_KUNIT int +__set_legacy_tf(struct dc_transfer_func *func, + const struct drm_color_lut *lut, uint32_t lut_size, + bool has_rom) { struct dc_gamma *gamma = NULL; struct calculate_buffer cal_buffer = {0}; @@ -645,6 +646,7 @@ static int __set_legacy_tf(struct dc_transfer_func *func, return res ? 0 : -ENOMEM; } +EXPORT_IF_KUNIT(__set_legacy_tf); /** * __set_output_tf - calculates the output transfer function based on expected input space. @@ -656,9 +658,10 @@ static int __set_legacy_tf(struct dc_transfer_func *func, * Returns: * 0 in case of success. -ENOMEM if fails. */ -static int __set_output_tf(struct dc_transfer_func *func, - const struct drm_color_lut *lut, uint32_t lut_size, - bool has_rom) +STATIC_IFN_KUNIT int +__set_output_tf(struct dc_transfer_func *func, + const struct drm_color_lut *lut, uint32_t lut_size, + bool has_rom) { struct dc_gamma *gamma = NULL; struct calculate_buffer cal_buffer = {0}; @@ -703,6 +706,7 @@ static int __set_output_tf(struct dc_transfer_func *func, return res ? 0 : -ENOMEM; } +EXPORT_IF_KUNIT(__set_output_tf); /** * __set_output_tf_32 - calculates the output transfer function based on expected input space. @@ -714,9 +718,10 @@ static int __set_output_tf(struct dc_transfer_func *func, * Returns: * 0 in case of success. -ENOMEM if fails. */ -static int __set_output_tf_32(struct dc_transfer_func *func, - const struct drm_color_lut32 *lut, uint32_t lut_size, - bool has_rom) +STATIC_IFN_KUNIT int +__set_output_tf_32(struct dc_transfer_func *func, + const struct drm_color_lut32 *lut, uint32_t lut_size, + bool has_rom) { struct dc_gamma *gamma = NULL; struct calculate_buffer cal_buffer = {0}; @@ -759,6 +764,7 @@ static int __set_output_tf_32(struct dc_transfer_func *func, return res ? 0 : -ENOMEM; } +EXPORT_IF_KUNIT(__set_output_tf_32); STATIC_IFN_KUNIT void __set_tf_bypass(struct dc_transfer_func *tf) { @@ -820,8 +826,9 @@ EXPORT_IF_KUNIT(amdgpu_dm_set_atomic_regamma); * Returns: * 0 in case of success. -ENOMEM if fails. */ -static int __set_input_tf(struct dc_color_caps *caps, struct dc_transfer_func *func, - const struct drm_color_lut *lut, uint32_t lut_size) +STATIC_IFN_KUNIT int __set_input_tf(struct dc_color_caps *caps, + struct dc_transfer_func *func, + const struct drm_color_lut *lut, uint32_t lut_size) { struct dc_gamma *gamma = NULL; bool res; @@ -844,6 +851,7 @@ static int __set_input_tf(struct dc_color_caps *caps, struct dc_transfer_func *f return res ? 0 : -ENOMEM; } +EXPORT_IF_KUNIT(__set_input_tf); /** * __set_input_tf_32 - calculates the input transfer function based on expected @@ -856,8 +864,9 @@ static int __set_input_tf(struct dc_color_caps *caps, struct dc_transfer_func *f * Returns: * 0 in case of success. -ENOMEM if fails. */ -static int __set_input_tf_32(struct dc_color_caps *caps, struct dc_transfer_func *func, - const struct drm_color_lut32 *lut, uint32_t lut_size) +STATIC_IFN_KUNIT int __set_input_tf_32(struct dc_color_caps *caps, + struct dc_transfer_func *func, + const struct drm_color_lut32 *lut, uint32_t lut_size) { struct dc_gamma *gamma = NULL; bool res; @@ -880,6 +889,7 @@ static int __set_input_tf_32(struct dc_color_caps *caps, struct dc_transfer_func return res ? 0 : -ENOMEM; } +EXPORT_IF_KUNIT(__set_input_tf_32); STATIC_IFN_KUNIT enum dc_transfer_func_predefined 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 cec23a020c3d..3e8a3d3fc855 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 @@ -64,6 +64,20 @@ void __drm_ctm_to_dc_matrix(const struct drm_color_ctm *ctm, struct fixed31_32 *matrix); void __drm_ctm_3x4_to_dc_matrix(const struct drm_color_ctm_3x4 *ctm, struct fixed31_32 *matrix); +int __set_legacy_tf(struct dc_transfer_func *func, + const struct drm_color_lut *lut, uint32_t lut_size, + bool has_rom); +int __set_output_tf(struct dc_transfer_func *func, + const struct drm_color_lut *lut, uint32_t lut_size, + bool has_rom); +int __set_output_tf_32(struct dc_transfer_func *func, + const struct drm_color_lut32 *lut, uint32_t lut_size, + bool has_rom); +struct dc_color_caps; +int __set_input_tf(struct dc_color_caps *caps, struct dc_transfer_func *func, + const struct drm_color_lut *lut, uint32_t lut_size); +int __set_input_tf_32(struct dc_color_caps *caps, struct dc_transfer_func *func, + const struct drm_color_lut32 *lut, uint32_t lut_size); enum dc_transfer_func_predefined amdgpu_tf_to_dc_tf(enum amdgpu_transfer_function tf); enum dc_transfer_func_predefined 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 e76e533a8323..de11a606a88c 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 @@ -1375,6 +1375,146 @@ static void dm_test_set_tf_distributed_points_pq(struct kunit *test) KUNIT_EXPECT_EQ(test, tf->sdr_ref_white_level, 80U); } +/** + * dm_test_set_legacy_tf_identity - Legacy identity LUT uses the sRGB ROM path + * @test: KUnit test context + */ +static void dm_test_set_legacy_tf_identity(struct kunit *test) +{ + struct drm_color_lut *lut; + struct dc_transfer_func *tf; + int i; + + tf = kunit_kzalloc(test, sizeof(*tf), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, tf); + lut = kunit_kcalloc(test, MAX_COLOR_LEGACY_LUT_ENTRIES, sizeof(*lut), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, lut); + + for (i = 0; i < MAX_COLOR_LEGACY_LUT_ENTRIES; i++) { + u16 value = i * MAX_DRM_LUT_VALUE / (MAX_COLOR_LEGACY_LUT_ENTRIES - 1); + + lut[i].red = value; + lut[i].green = value; + lut[i].blue = value; + } + + tf->type = TF_TYPE_PREDEFINED; + tf->tf = TRANSFER_FUNCTION_SRGB; + + KUNIT_EXPECT_EQ(test, + __set_legacy_tf(tf, lut, MAX_COLOR_LEGACY_LUT_ENTRIES, true), + 0); +} + +/** + * dm_test_set_output_tf_linear - Linear output without a LUT calculates degamma + * @test: KUnit test context + */ +static void dm_test_set_output_tf_linear(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_PREDEFINED; + tf->tf = TRANSFER_FUNCTION_LINEAR; + + KUNIT_EXPECT_EQ(test, __set_output_tf(tf, NULL, 0, false), 0); +} + +/** + * dm_test_set_output_tf_32_srgb_rom - sRGB output uses the no-LUT ROM path + * @test: KUnit test context + */ +static void dm_test_set_output_tf_32_srgb_rom(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_PREDEFINED; + tf->tf = TRANSFER_FUNCTION_SRGB; + + KUNIT_EXPECT_EQ(test, __set_output_tf_32(tf, NULL, 0, true), 0); +} + +/** + * dm_test_set_input_tf_srgb - Predefined sRGB input needs no generated curve + * @test: KUnit test context + */ +static void dm_test_set_input_tf_srgb(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_PREDEFINED; + tf->tf = TRANSFER_FUNCTION_SRGB; + + KUNIT_EXPECT_EQ(test, __set_input_tf(NULL, tf, NULL, 0), 0); +} + +/** + * dm_test_set_input_tf_32_srgb - 32-bit input wrapper accepts predefined sRGB + * @test: KUnit test context + */ +static void dm_test_set_input_tf_32_srgb(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_PREDEFINED; + tf->tf = TRANSFER_FUNCTION_SRGB; + + KUNIT_EXPECT_EQ(test, __set_input_tf_32(NULL, tf, NULL, 0), 0); +} + +/** + * dm_test_set_transfer_funcs_with_luts - LUT-backed transfer functions succeed + * @test: KUnit test context + */ +static void dm_test_set_transfer_funcs_with_luts(struct kunit *test) +{ + struct drm_color_lut32 *lut32; + struct drm_color_lut *lut; + struct dc_transfer_func *tf; + + lut = kunit_kcalloc(test, MAX_COLOR_LUT_ENTRIES, sizeof(*lut), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, lut); + lut32 = kunit_kcalloc(test, MAX_COLOR_LUT_ENTRIES, sizeof(*lut32), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, lut32); + tf = kunit_kzalloc(test, sizeof(*tf), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, tf); + + tf->type = TF_TYPE_DISTRIBUTED_POINTS; + tf->tf = TRANSFER_FUNCTION_LINEAR; + KUNIT_EXPECT_EQ(test, + __set_output_tf(tf, lut, MAX_COLOR_LUT_ENTRIES, false), + 0); + + memset(tf, 0, sizeof(*tf)); + tf->type = TF_TYPE_DISTRIBUTED_POINTS; + tf->tf = TRANSFER_FUNCTION_LINEAR; + KUNIT_EXPECT_EQ(test, + __set_output_tf_32(tf, lut32, MAX_COLOR_LUT_ENTRIES, false), + 0); + + memset(tf, 0, sizeof(*tf)); + tf->type = TF_TYPE_DISTRIBUTED_POINTS; + tf->tf = TRANSFER_FUNCTION_SRGB; + KUNIT_EXPECT_EQ(test, + __set_input_tf(NULL, tf, lut, MAX_COLOR_LUT_ENTRIES), + 0); + + memset(tf, 0, sizeof(*tf)); + tf->type = TF_TYPE_DISTRIBUTED_POINTS; + tf->tf = TRANSFER_FUNCTION_SRGB; + KUNIT_EXPECT_EQ(test, + __set_input_tf_32(NULL, tf, lut32, MAX_COLOR_LUT_ENTRIES), + 0); +} + /** * dm_test_set_atomic_regamma_bypass - No LUT and linear TF: must take bypass path * @test: KUnit test context @@ -2384,6 +2524,13 @@ static struct kunit_case dm_color_test_cases[] = { /* __set_tf_distributed_points */ KUNIT_CASE(dm_test_set_tf_distributed_points_srgb), KUNIT_CASE(dm_test_set_tf_distributed_points_pq), + /* Transfer-function calculation helpers */ + KUNIT_CASE(dm_test_set_legacy_tf_identity), + KUNIT_CASE(dm_test_set_output_tf_linear), + KUNIT_CASE(dm_test_set_output_tf_32_srgb_rom), + KUNIT_CASE(dm_test_set_input_tf_srgb), + KUNIT_CASE(dm_test_set_input_tf_32_srgb), + KUNIT_CASE(dm_test_set_transfer_funcs_with_luts), /* amdgpu_dm_set_atomic_regamma */ KUNIT_CASE(dm_test_set_atomic_regamma_bypass), /* amdgpu_dm_atomic_shaper_lut */ -- 2.53.0
