[igt-dev] [PATCH i-g-t] tests/amdgpu: Add test for Adaptive Backlight Management

Francis, David David.Francis at amd.com
Fri Dec 7 14:34:54 UTC 2018


On my machine, the gradual brightness reduction gives the following pwm measurements

pwm changed from 65535 to 64758 (-777)
pwm changed from 64758 to 63530 (-1228)
pwm changed from 63530 to 62594 (-936)
pwm changed from 62594 to 61751 (-843)
pwm changed from 61751 to 60825 (-926)
pwm changed from 60825 to 59480 (-1345)
pwm changed from 59480 to 58064 (-1416)
pwm changed from 58064 to 56967 (-1097)
pwm changed from 56967 to 55956 (-1011)
pwm changed from 55956 to 55027 (-929)


I think we can assume a change of at least 1

________________________________
From: Wentland, Harry
Sent: November 29, 2018 3:45:30 PM
To: Francis, David; igt-dev at lists.freedesktop.org
Subject: Re: [igt-dev] [PATCH i-g-t] tests/amdgpu: Add test for Adaptive Backlight Management



On 2018-11-28 3:51 p.m., David Francis wrote:
> Adaptive Backlight Management (ABM) is a power-saving
> feature on AMD ASICs that reduces backlight while increasing
> pixel contrast and luminance.  This test confirms that
> ABM is present and enabled, and that backlight performance
> is sane.  It uses AMD-specific debugfs entries to
> read the backlight PWM values.
>
> It has 5 subtests:
>
> dpms_cycle
> Sets brightness to half, then confirms that value is restored
> after dpms off and then on.
>
> backlight_monotonic_basic
> Sets brightness to ten different values, confirming that
> higher brightness values are brighter.
>
> backlight_monotonic_abm
> Same as backlight_monotonic_basic, but with abm enabled.
>
> abm_enabled
> Sets abm to its four intensity levels, confirming that
> abm reduces the backlight, and the reduction is greater
> for higher abm level.
>
> abm_gradual
> Sets abm to off and then maximum intensity, confirming
> that brightness decreases continually over the first
> second and eventually reaches the target value.
> This test takes 30s to run.
>
> Signed-off-by: David Francis <David.Francis at amd.com>
> ---
>  tests/Makefile.sources |   1 +
>  tests/amdgpu/amd_abm.c | 361 +++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 362 insertions(+)
>  create mode 100644 tests/amdgpu/amd_abm.c
>
> diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> index 5620c1d6..3d560bee 100644
> --- a/tests/Makefile.sources
> +++ b/tests/Makefile.sources
> @@ -19,6 +19,7 @@ AMDGPU_TESTS = \
>        amdgpu/amd_basic \
>        amdgpu/amd_cs_nop \
>        amdgpu/amd_prime \
> +     amdgpu/amd_abm \
>        $(NULL)
>
>  TESTS_progs = \
> diff --git a/tests/amdgpu/amd_abm.c b/tests/amdgpu/amd_abm.c
> new file mode 100644
> index 00000000..90a6f99e
> --- /dev/null
> +++ b/tests/amdgpu/amd_abm.c
> @@ -0,0 +1,361 @@
> +/*
> + * Copyright 2018 Advanced Micro Devices, Inc.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +#include "igt.h"
> +#include "drmtest.h"
> +#include "igt_kms.h"
> +#include <limits.h>
> +#include <errno.h>
> +#include <stdbool.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <fcntl.h>
> +#include <time.h>
> +
> +#define BACKLIGHT_PATH "/sys/class/backlight/amdgpu_bl0"
> +
> +static int read_current_backlight_pwm(int debugfs_dir)
> +{
> +     char buf[20];
> +
> +     igt_debugfs_simple_read(debugfs_dir, "amdgpu_current_backlight_pwm",
> +                      buf, sizeof(buf));
> +
> +     return strtol(buf, NULL, 0);
> +}
> +
> +static int read_target_backlight_pwm(int debugfs_dir)
> +{
> +     char buf[20];
> +
> +     igt_debugfs_simple_read(debugfs_dir, "amdgpu_target_backlight_pwm",
> +                      buf, sizeof(buf));
> +
> +     return strtol(buf, NULL, 0);
> +}
> +
> +static int backlight_write_brightness(int value)
> +{
> +     int fd;
> +     char full[PATH_MAX];
> +     char src[64];
> +     int len;
> +
> +     igt_assert(snprintf(full, PATH_MAX, "%s/%s", BACKLIGHT_PATH, "brightness") < PATH_MAX);
> +     fd = open(full, O_WRONLY);
> +     if (fd == -1)
> +             return -errno;
> +
> +     len = snprintf(src, sizeof(src), "%i", value);
> +     len = write(fd, src, len);
> +     close(fd);
> +
> +     if (len < 0)
> +             return len;
> +
> +     return 0;
> +}
> +
> +static void set_abm_level(igt_display_t *display, int level)
> +{
> +     int i, ret;
> +     int output_id;
> +     drmModeObjectPropertiesPtr props;
> +     uint32_t prop_id;
> +     drmModePropertyPtr prop;
> +     uint32_t type = DRM_MODE_OBJECT_CONNECTOR;
> +
> +     for (i = 0; i < display->n_outputs; i++) {
> +             output_id = display->outputs[i].id;
> +             props = drmModeObjectGetProperties(display->drm_fd, output_id, type);
> +
> +             for (i = 0; i < props->count_props; i++) {
> +                     prop_id = props->props[i];
> +                     prop = drmModeGetProperty(display->drm_fd, prop_id);
> +
> +                     igt_assert(prop);
> +
> +                     if (strcmp(prop->name, "abm level") == 0) {
> +                             ret = drmModeObjectSetProperty(display->drm_fd, output_id, type, prop_id, level);
> +
> +                             igt_assert_eq(ret, 0);
> +                     }
> +
> +                     drmModeFreeProperty(prop);
> +             }
> +     }
> +
> +}
> +
> +static int backlight_read_max_brightness(int *result)
> +{
> +     int fd;
> +     char full[PATH_MAX];
> +     char dst[64];
> +     int r, e;
> +
> +     igt_assert(snprintf(full, PATH_MAX, "%s/%s", BACKLIGHT_PATH, "max_brightness") < PATH_MAX);
> +
> +     fd = open(full, O_RDONLY);
> +     if (fd == -1)
> +             return -errno;
> +
> +     r = read(fd, dst, sizeof(dst));
> +     e = errno;
> +     close(fd);
> +
> +     if (r < 0)
> +             return -e;
> +
> +     errno = 0;
> +     *result = strtol(dst, NULL, 10);
> +     return errno;
> +}
> +
> +static void skip_if_incompatible(igt_display_t *display, int debugfs_dir)
> +{
> +     int ret, i;
> +     char buf[20];
> +     bool abm_prop_exists;
> +     int output_id;
> +     drmModeObjectPropertiesPtr props;
> +     uint32_t type = DRM_MODE_OBJECT_CONNECTOR;
> +     uint32_t prop_id;
> +     drmModePropertyPtr prop;
> +
> +     ret = igt_debugfs_simple_read(debugfs_dir, "amdgpu_current_backlight_pwm",
> +                      buf, sizeof(buf));
> +
> +     if (ret < 0)
> +             igt_skip("No current backlight debugfs entry.\n");
> +
> +     ret = igt_debugfs_simple_read(debugfs_dir, "amdgpu_target_backlight_pwm",
> +                      buf, sizeof(buf));
> +
> +     if (ret < 0)
> +             igt_skip("No target backlight debugfs entry.\n");
> +
> +     abm_prop_exists = false;
> +
> +     for (i = 0; i < display->n_outputs; i++) {
> +             output_id = display->outputs[i].id;
> +             props = drmModeObjectGetProperties(display->drm_fd, output_id, type);
> +
> +             for (i = 0; i < props->count_props; i++) {
> +                     prop_id = props->props[i];
> +                     prop = drmModeGetProperty(display->drm_fd, prop_id);
> +
> +                     if (strcmp(prop->name, "abm level") == 0)
> +                             abm_prop_exists = true;
> +
> +                     drmModeFreeProperty(prop);
> +             }
> +     }
> +
> +     if (!abm_prop_exists)
> +             igt_skip("No abm level property on any connector.\n");
> +}
> +
> +
> +static void backlight_dpms_cycle(igt_display_t *display, int debugfs, igt_output_t *output)
> +{
> +     int ret;
> +     int max_brightness;
> +     int pwm_1, pwm_2;
> +
> +     ret = backlight_read_max_brightness(&max_brightness);
> +     igt_assert_eq(ret, 0);
> +
> +     set_abm_level(display, 0);
> +     backlight_write_brightness(max_brightness / 2);
> +     usleep(100000);
> +     pwm_1 = read_target_backlight_pwm(debugfs);
> +
> +     kmstest_set_connector_dpms(display->drm_fd, output->config.connector, DRM_MODE_DPMS_OFF);
> +     kmstest_set_connector_dpms(display->drm_fd, output->config.connector, DRM_MODE_DPMS_ON);
> +     usleep(100000);
> +     pwm_2 = read_target_backlight_pwm(debugfs);
> +     igt_assert_eq(pwm_1, pwm_2);
> +}
> +
> +static void backlight_monotonic_basic(igt_display_t *display, int debugfs)
> +{
> +     int ret;
> +     int max_brightness;
> +     int prev_pwm, pwm;
> +     int brightness_step;
> +     int brightness;
> +
> +     ret = backlight_read_max_brightness(&max_brightness);
> +     igt_assert_eq(ret, 0);
> +
> +     brightness_step = max_brightness / 10;
> +
> +     set_abm_level(display, 0);
> +     backlight_write_brightness(max_brightness);
> +     usleep(100000);
> +     prev_pwm = read_target_backlight_pwm(debugfs);
> +     for (brightness = max_brightness - brightness_step;
> +          brightness > 0;
> +          brightness -= brightness_step) {
> +             backlight_write_brightness(brightness);
> +             usleep(100000);
> +             pwm = read_target_backlight_pwm(debugfs);
> +             igt_assert(pwm < prev_pwm);
> +             prev_pwm = pwm;
> +     }
> +
> +}
> +
> +static void backlight_monotonic_abm(igt_display_t *display, int debugfs)
> +{
> +     int ret, i;
> +     int max_brightness;
> +     int prev_pwm, pwm;
> +     int brightness_step;
> +     int brightness;
> +
> +     ret = backlight_read_max_brightness(&max_brightness);
> +     igt_assert_eq(ret, 0);
> +
> +     brightness_step = max_brightness / 10;
> +     for (i = 1; i < 5; i++) {
> +             set_abm_level(display, i);
> +             backlight_write_brightness(max_brightness);
> +             usleep(100000);
> +             prev_pwm = read_target_backlight_pwm(debugfs);
> +             for (brightness = max_brightness - brightness_step;
> +                  brightness > 0;
> +                  brightness -= brightness_step) {
> +                     backlight_write_brightness(brightness);
> +                     usleep(100000);
> +                     pwm = read_target_backlight_pwm(debugfs);
> +                     igt_assert(pwm < prev_pwm);
> +                     prev_pwm = pwm;
> +             }
> +     }
> +}
> +
> +static void abm_enabled(igt_display_t *display, int debugfs)
> +{
> +     int ret, i;
> +     int max_brightness;
> +     int pwm, prev_pwm, pwm_without_abm;
> +
> +     ret = backlight_read_max_brightness(&max_brightness);
> +     igt_assert_eq(ret, 0);
> +
> +     set_abm_level(display, 0);
> +     backlight_write_brightness(max_brightness);
> +     usleep(100000);
> +     prev_pwm = read_target_backlight_pwm(debugfs);
> +     pwm_without_abm = prev_pwm;
> +
> +     for (i = 1; i < 5; i++) {
> +             set_abm_level(display, i);
> +             usleep(100000);
> +             pwm = read_target_backlight_pwm(debugfs);
> +             igt_assert(pwm <= prev_pwm);
> +             igt_assert(pwm < pwm_without_abm);
> +             prev_pwm = pwm;
> +     }
> +
> +}
> +
> +static void abm_gradual(igt_display_t *display, int debugfs)
> +{
> +     int ret, i;
> +     int convergence_delay = 15;
> +     int prev_pwm, pwm, curr;
> +     int max_brightness;
> +
> +     ret = backlight_read_max_brightness(&max_brightness);
> +
> +     igt_assert_eq(ret, 0);
> +
> +     set_abm_level(display, 0);
> +     backlight_write_brightness(max_brightness);
> +
> +     sleep(convergence_delay);
> +     prev_pwm = read_target_backlight_pwm(debugfs);
> +     curr = read_current_backlight_pwm(debugfs);
> +
> +     igt_assert_eq(prev_pwm, curr);
> +     set_abm_level(display, 4);
> +     for (i = 0; i < 10; i++) {
> +             usleep(100000);
> +             pwm = read_current_backlight_pwm(debugfs);
> +             igt_assert(pwm < prev_pwm);

This seems like it very much depends on the usleep value above, the range of expected pwm reduction between no ABM and ABM level 4, as well as how quickly/slowly this executes.

Should the usleep time be a function of the convergence_delay?

Could this give us flaky test results?

How many PWM steps have you usually seen for each iteration of this function? If it's large we're probably fine.

Harry

> +             prev_pwm = pwm;
> +     }
> +
> +     sleep(convergence_delay - 1);
> +
> +     prev_pwm = read_target_backlight_pwm(debugfs);
> +     curr = read_current_backlight_pwm(debugfs);
> +
> +     igt_assert_eq(prev_pwm, curr);
> +}
> +
> +igt_main
> +{
> +     igt_display_t display;
> +     int debugfs;
> +     enum pipe pipe;
> +     igt_output_t *output;
> +
> +     igt_skip_on_simulation();
> +
> +     igt_fixture {
> +             display.drm_fd = drm_open_driver_master(DRIVER_AMDGPU);
> +
> +             if (display.drm_fd == -1)
> +                     igt_skip("Not an amdgpu driver.\n");
> +
> +             debugfs = igt_debugfs_dir(display.drm_fd);
> +
> +             kmstest_set_vt_graphics_mode();
> +
> +             igt_display_require(&display, display.drm_fd);
> +
> +             skip_if_incompatible(&display, debugfs);
> +
> +             for_each_pipe_with_valid_output(&display, pipe, output)
> +                     break;
> +     }
> +
> +     igt_subtest("dpms_cycle")
> +             backlight_dpms_cycle(&display, debugfs, output);
> +     igt_subtest("backlight_monotonic_basic")
> +             backlight_monotonic_basic(&display, debugfs);
> +     igt_subtest("backlight_monotonic_abm")
> +             backlight_monotonic_abm(&display, debugfs);
> +     igt_subtest("abm_enabled")
> +             abm_enabled(&display, debugfs);
> +     igt_subtest("abm_gradual")
> +             abm_gradual(&display, debugfs);
> +
> +     igt_fixture {
> +             igt_display_fini(&display);
> +     }
> +}
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/igt-dev/attachments/20181207/7a0e485b/attachment-0001.html>


More information about the igt-dev mailing list