From: Ray Wu <ray.wu@amd.com>
To: Hugo Sales <hugo@hsal.es>,
harry.wentland@amd.com, siqueira@igalia.com,
amd-gfx@lists.freedesktop.org, sunpeng.li@amd.com,
alexander.deucher@amd.com
Cc: mario.limonciello@amd.com, christian.koenig@amd.com,
linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
simona@ffwll.ch, alex.hung@amd.com, airlied@gmail.com
Subject: Re: [PATCH RFC 2/3] drm/amd/display: Add KUnit tests for the ATIF backlight curve check
Date: Wed, 11 Nov 2026 17:39:38 +0800 [thread overview]
Message-ID: <7e02d6ff-4278-4d57-90fc-97d7fd665b02@amd.com> (raw)
In-Reply-To: <20261104-backlight-curve-validate-v1-2-10c688880e85@hsal.es>
Hi Hugo,
Thanks for this.
With the backlight update in the other thread, amdgpu_dm no longer maps
brightness through the ATIF curve; only the power module uses it, and it
validates the curve itself. So 1/3 and 2/3 are no longer needed. I have
replied to 3/3 with my Reviewed-by.
Thanks,
Ray
On 11/4/2026 6:31 PM, Hugo Sales wrote:
> Test the curve check in amdgpu_dm_validate_backlight_caps():
>
> - the GV301QH curve stays as it is
> - a luminance over 100% becomes 100%
> - a falling luminance rises to the point before
> - a curve whose signals fall gets dropped
> - a repeated signal stays
> - a curve with more points than luminance_data holds is cut to fit
>
> Also check the brightness the PWM and AUX paths give on the checked
> curves
>
> Signed-off-by: Hugo Sales <hugo@hsal.es>
> ---
> KUnit: dm_test_validate_custom_curve_unsorted and the luminance checks
> in the falling test fail without patch 1
> ---
> .../amdgpu_dm/tests/amdgpu_dm_backlight_test.c | 184 +++++++++++++++++++++
> 1 file changed, 184 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c
> index b3e6a96320164..d76527e49acf2 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c
> @@ -1696,6 +1696,185 @@ static void dm_test_brightness_curve_pwm_luminance_over_100(struct kunit *test)
> KUNIT_EXPECT_EQ(test, convert_brightness_from_user(&caps, 225000), 255000U);
> }
>
> +/* Tests for the custom curve check in amdgpu_dm_validate_backlight_caps() */
> +
> +static struct amdgpu_display_manager *alloc_validate_dm(struct kunit *test)
> +{
> + struct amdgpu_display_manager *dm = dm_kunit_alloc_dm(test);
> +
> + dm->adev = dm_kunit_alloc_adev(test);
> + /* drm_warn() prints the curve warnings against this device */
> + KUNIT_ASSERT_NOT_NULL(test, adev_to_drm(dm->adev)->dev);
> +
> + return dm;
> +}
> +
> +static struct amdgpu_dm_backlight_caps *
> +validate_custom_curve(struct amdgpu_display_manager *dm,
> + const struct amdgpu_dm_luminance_data *points, int n)
> +{
> + struct amdgpu_dm_backlight_caps *caps = &dm->backlight_caps[0];
> +
> + set_custom_curve_caps(caps, points, n);
> + caps->caps_valid = true;
> + amdgpu_dm_validate_backlight_caps(dm, 0);
> +
> + return caps;
> +}
> +
> +/**
> + * dm_test_validate_custom_curve_gv301qh - Test a good ATIF curve is left alone
> + * @test: The KUnit test context
> + *
> + * The GV301QH curve rises and stays within 100%, so the check must keep
> + * every point as it is
> + */
> +static void dm_test_validate_custom_curve_gv301qh(struct kunit *test)
> +{
> + struct amdgpu_display_manager *dm = alloc_validate_dm(test);
> + struct amdgpu_dm_backlight_caps *caps = &dm->backlight_caps[0];
> +
> + set_gv301qh_caps(caps, false);
> + caps->caps_valid = true;
> + amdgpu_dm_validate_backlight_caps(dm, 0);
> +
> + KUNIT_EXPECT_TRUE(test, caps->caps_valid);
> + KUNIT_ASSERT_EQ(test, caps->data_points, ARRAY_SIZE(gv301qh_curve));
> + KUNIT_EXPECT_MEMEQ(test, caps->luminance_data, gv301qh_curve, sizeof(gv301qh_curve));
> +}
> +
> +/**
> + * dm_test_validate_custom_curve_luminance_over_100 - Test ATIF luminance over 100% becomes 100%
> + * @test: The KUnit test context
> + *
> + * Points (100, 50), (200, 150) and (250, 120) become (100, 50), (200, 100)
> + * and (250, 100). Level 150 is then 50 + 50 * 50 / 100 = 75% and level 200
> + * is full brightness. Over AUX, 301176 of 512000 is just below signal 150,
> + * so it lands one below 75% of 1000..512000, at 384249
> + */
> +static void dm_test_validate_custom_curve_luminance_over_100(struct kunit *test)
> +{
> + static const struct amdgpu_dm_luminance_data points[] = {
> + { .input_signal = 100, .luminance = 50 },
> + { .input_signal = 200, .luminance = 150 },
> + { .input_signal = 250, .luminance = 120 },
> + };
> + struct amdgpu_display_manager *dm = alloc_validate_dm(test);
> + struct amdgpu_dm_backlight_caps *caps;
> +
> + dm_test_enable_custom_curve(test);
> + caps = validate_custom_curve(dm, points, ARRAY_SIZE(points));
> +
> + KUNIT_ASSERT_EQ(test, caps->data_points, 3);
> + KUNIT_EXPECT_EQ(test, caps->luminance_data[0].luminance, 50);
> + KUNIT_EXPECT_EQ(test, caps->luminance_data[1].luminance, 100);
> + KUNIT_EXPECT_EQ(test, caps->luminance_data[2].luminance, 100);
> +
> + KUNIT_EXPECT_EQ(test, convert_brightness_from_user(caps, 150 * 0x101), 49151U);
> + KUNIT_EXPECT_EQ(test, convert_brightness_from_user(caps, 200 * 0x101), 65535U);
> + KUNIT_EXPECT_EQ(test, convert_brightness_to_millipercent(caps, 150 * 0x101), 75000U);
> + KUNIT_EXPECT_EQ(test, convert_brightness_to_millipercent(caps, 200 * 0x101), 100000U);
> +
> + caps->aux_support = true;
> + caps->aux_min_input_signal = 1;
> + caps->aux_max_input_signal = 512;
> + KUNIT_EXPECT_EQ(test, convert_brightness_from_user(caps, 301176), 384249U);
> +}
> +
> +/**
> + * dm_test_validate_custom_curve_falling - Test a falling ATIF point is raised
> + * @test: The KUnit test context
> + *
> + * In (50, 30), (100, 60), (150, 40) and (200, 80), the point at 150 is
> + * raised to 60%, so the curve is flat from 100 to 150. Level 125 is 60% on
> + * both paths, which over AUX is 307600 in 1000..512000
> + */
> +static void dm_test_validate_custom_curve_falling(struct kunit *test)
> +{
> + static const struct amdgpu_dm_luminance_data points[] = {
> + { .input_signal = 50, .luminance = 30 },
> + { .input_signal = 100, .luminance = 60 },
> + { .input_signal = 150, .luminance = 40 },
> + { .input_signal = 200, .luminance = 80 },
> + };
> + struct amdgpu_display_manager *dm = alloc_validate_dm(test);
> + struct amdgpu_dm_backlight_caps *caps;
> +
> + dm_test_enable_custom_curve(test);
> + caps = validate_custom_curve(dm, points, ARRAY_SIZE(points));
> +
> + KUNIT_ASSERT_EQ(test, caps->data_points, 4);
> + KUNIT_EXPECT_EQ(test, caps->luminance_data[1].luminance, 60);
> + KUNIT_EXPECT_EQ(test, caps->luminance_data[2].luminance, 60);
> + KUNIT_EXPECT_EQ(test, caps->luminance_data[3].luminance, 80);
> +
> + KUNIT_EXPECT_EQ(test, convert_brightness_from_user(caps, 125 * 0x101), 39321U);
> + KUNIT_EXPECT_EQ(test, convert_brightness_to_millipercent(caps, 125 * 0x101), 60000U);
> +
> + caps->aux_support = true;
> + caps->aux_min_input_signal = 1;
> + caps->aux_max_input_signal = 512;
> + KUNIT_EXPECT_EQ(test, convert_brightness_from_user(caps, 250980), 307600U);
> +}
> +
> +/**
> + * dm_test_validate_custom_curve_unsorted - Test a curve whose signals fall is dropped
> + * @test: The KUnit test context
> + *
> + * A signal below the one before leaves no curve, so the mapping is
> + * linear. A repeated signal is a step: the curve stays, and level 100 is
> + * at the later point's 60%
> + */
> +static void dm_test_validate_custom_curve_unsorted(struct kunit *test)
> +{
> + static const struct amdgpu_dm_luminance_data falling[] = {
> + { .input_signal = 100, .luminance = 40 },
> + { .input_signal = 80, .luminance = 60 },
> + };
> + static const struct amdgpu_dm_luminance_data repeated[] = {
> + { .input_signal = 50, .luminance = 20 },
> + { .input_signal = 100, .luminance = 40 },
> + { .input_signal = 100, .luminance = 60 },
> + };
> + struct amdgpu_display_manager *dm = alloc_validate_dm(test);
> + struct amdgpu_dm_backlight_caps *caps;
> +
> + dm_test_enable_custom_curve(test);
> +
> + caps = validate_custom_curve(dm, falling, ARRAY_SIZE(falling));
> + KUNIT_EXPECT_EQ(test, caps->data_points, 0);
> + KUNIT_EXPECT_EQ(test, convert_brightness_from_user(caps, 32768), 32768U);
> +
> + caps = validate_custom_curve(dm, repeated, ARRAY_SIZE(repeated));
> + KUNIT_EXPECT_EQ(test, caps->data_points, 3);
> + KUNIT_EXPECT_EQ(test, convert_brightness_to_millipercent(caps, 100 * 0x101), 60000U);
> +}
> +
> +/**
> + * dm_test_validate_custom_curve_too_many_points - Test data_points is cut to the array
> + * @test: The KUnit test context
> + *
> + * data_points is a u8 from firmware, so it can claim more points than
> + * luminance_data holds. The check keeps the points that fit
> + */
> +static void dm_test_validate_custom_curve_too_many_points(struct kunit *test)
> +{
> + struct amdgpu_display_manager *dm = alloc_validate_dm(test);
> + struct amdgpu_dm_backlight_caps *caps = &dm->backlight_caps[0];
> + int i;
> +
> + set_gv301qh_caps(caps, false);
> + for (i = 0; i < ARRAY_SIZE(caps->luminance_data); i++) {
> + caps->luminance_data[i].input_signal = 2 * i;
> + caps->luminance_data[i].luminance = i;
> + }
> + caps->data_points = 255;
> + caps->caps_valid = true;
> + amdgpu_dm_validate_backlight_caps(dm, 0);
> +
> + KUNIT_EXPECT_EQ(test, caps->data_points, ARRAY_SIZE(caps->luminance_data));
> +}
> +
> /**
> * dm_test_brightness_range_zero_signals - Test Brightness range with zero min and max signals
> * @test: The KUnit test context
> @@ -2365,6 +2544,11 @@ static struct kunit_case dm_backlight_test_cases[] = {
> KUNIT_CASE(dm_test_backlight_caps_aux_support_noop),
> /* amdgpu_dm_validate_backlight_caps */
> KUNIT_CASE_PARAM(dm_test_validate_backlight_caps, dm_validate_caps_gen_params),
> + KUNIT_CASE(dm_test_validate_custom_curve_gv301qh),
> + KUNIT_CASE(dm_test_validate_custom_curve_luminance_over_100),
> + KUNIT_CASE(dm_test_validate_custom_curve_falling),
> + KUNIT_CASE(dm_test_validate_custom_curve_unsorted),
> + KUNIT_CASE(dm_test_validate_custom_curve_too_many_points),
> /* get_brightness_range */
> KUNIT_CASE(dm_test_brightness_range_null_caps),
> KUNIT_CASE(dm_test_brightness_range_pwm),
>
next prev parent reply other threads:[~2026-11-11 9:41 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-04 10:31 [PATCH RFC 0/3] drm/amd/display: Check the ATIF backlight curve Hugo Sales
2026-11-04 10:31 ` [PATCH RFC 1/3] drm/amd/display: Repair or drop a bad " Hugo Sales
2026-11-04 10:31 ` [PATCH RFC 2/3] drm/amd/display: Add KUnit tests for the ATIF backlight curve check Hugo Sales
2026-11-11 9:39 ` Ray Wu [this message]
2026-11-04 10:31 ` [PATCH RFC 3/3] drm/amd/display: Warn about an invalid ATIF backlight signal range Hugo Sales
2026-11-11 9:35 ` Ray Wu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=7e02d6ff-4278-4d57-90fc-97d7fd665b02@amd.com \
--to=ray.wu@amd.com \
--cc=airlied@gmail.com \
--cc=alex.hung@amd.com \
--cc=alexander.deucher@amd.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=christian.koenig@amd.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=harry.wentland@amd.com \
--cc=hugo@hsal.es \
--cc=linux-kernel@vger.kernel.org \
--cc=mario.limonciello@amd.com \
--cc=simona@ffwll.ch \
--cc=siqueira@igalia.com \
--cc=sunpeng.li@amd.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®