mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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),
>

  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®