summaryrefslogtreecommitdiff
path: root/tests/amdgpu/amd_abm.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/amdgpu/amd_abm.c')
-rw-r--r--tests/amdgpu/amd_abm.c363
1 files changed, 363 insertions, 0 deletions
diff --git a/tests/amdgpu/amd_abm.c b/tests/amdgpu/amd_abm.c
new file mode 100644
index 00000000..363b1e90
--- /dev/null
+++ b/tests/amdgpu/amd_abm.c
@@ -0,0 +1,363 @@
+/*
+ * 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) {
+ if (output->config.connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+ 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);
+ }
+}