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

Submitted by Francis, David on Nov. 28, 2018, 8:51 p.m.

Details

Message ID 20181128205107.16315-1-David.Francis@amd.com
State New
Series "tests/amdgpu: Add test for Adaptive Backlight Management"
Headers show

Commit Message

Francis, David Nov. 28, 2018, 8:51 p.m.
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@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

Patch hide | download patch | download mbox

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);
+		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);
+	}
+}

Comments

Wentland, Harry Nov. 29, 2018, 8:45 p.m.
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@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);

> +	}

> +}

>
Francis, David Dec. 7, 2018, 2:34 p.m.
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