diff options
Diffstat (limited to 'lib/igt_psr.c')
-rw-r--r-- | lib/igt_psr.c | 86 |
1 files changed, 85 insertions, 1 deletions
diff --git a/lib/igt_psr.c b/lib/igt_psr.c index c979b0b5..bc142632 100644 --- a/lib/igt_psr.c +++ b/lib/igt_psr.c @@ -21,7 +21,9 @@ * IN THE SOFTWARE. */ -#include "igt_psr.h" +#include "igt_psr.h" +#include "igt_sysfs.h" +#include <errno.h> bool psr_active(int fd, bool check_active) { @@ -38,3 +40,85 @@ bool psr_wait_entry(int fd) { return igt_wait(psr_active(fd, true), 500, 1); } + +static ssize_t psr_write(int fd, const char *buf) +{ + return igt_sysfs_write(fd, "i915_edp_psr_debug", buf, strlen(buf)); +} + +static int has_psr_debugfs(int fd) +{ + int ret; + + /* + * Check if new PSR debugfs api is usable by writing an invalid value. + * Legacy mode will return OK here, debugfs api will return -EINVAL. + * -ENODEV is returned when PSR is unavailable. + */ + ret = psr_write(fd, "0xf"); + if (ret == -EINVAL) + return 0; + else if (ret < 0) + return ret; + + /* legacy debugfs api, we enabled irqs by writing, disable them. */ + psr_write(fd, "0"); + return -EINVAL; +} + +static bool psr_modparam_set(int val) +{ + static int oldval = -1; + + igt_set_module_param_int("enable_psr", val); + + if (val == oldval) + return false; + + oldval = val; + return true; +} + +static int psr_restore_debugfs_fd = -1; + +static void restore_psr_debugfs(int sig) +{ + psr_write(psr_restore_debugfs_fd, "0"); +} + +static bool psr_set(int fd, bool enable) +{ + int ret; + + ret = has_psr_debugfs(fd); + if (ret == -ENODEV) { + igt_skip_on_f(enable, "PSR not available\n"); + return false; + } + + if (ret == -EINVAL) { + ret = psr_modparam_set(enable); + } else { + ret = psr_write(fd, enable ? "0x3" : "0x1"); + igt_assert(ret > 0); + } + + /* Restore original value on exit */ + if (psr_restore_debugfs_fd == -1) { + psr_restore_debugfs_fd = dup(fd); + igt_assert(psr_restore_debugfs_fd >= 0); + igt_install_exit_handler(restore_psr_debugfs); + } + + return ret; +} + +bool psr_enable(int fd) +{ + return psr_set(fd, true); +} + +bool psr_disable(int fd) +{ + return psr_set(fd, false); +} |