summaryrefslogtreecommitdiff
path: root/tests/kms_psr.c
diff options
context:
space:
mode:
authorDhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>2018-07-12 01:09:43 -0700
committerRodrigo Vivi <rodrigo.vivi@intel.com>2018-07-13 15:30:25 -0700
commitd8e97e1710b27a3931a1c53d1dd88c0e709c085b (patch)
tree5d78bcc9012132cbb66770f71b68e6c6f1567383 /tests/kms_psr.c
parent20b67778f58f7f615b7fa59584b4c2aff4d54f6c (diff)
tests/psr: Rename kms_psr_sink_crc.c to kms_psr.c
We don't use sink CRC anymore in this test. Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Diffstat (limited to 'tests/kms_psr.c')
-rw-r--r--tests/kms_psr.c508
1 files changed, 508 insertions, 0 deletions
diff --git a/tests/kms_psr.c b/tests/kms_psr.c
new file mode 100644
index 00000000..4eca51da
--- /dev/null
+++ b/tests/kms_psr.c
@@ -0,0 +1,508 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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 "igt_sysfs.h"
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include "intel_bufmgr.h"
+
+enum operations {
+ PAGE_FLIP,
+ MMAP_GTT,
+ MMAP_CPU,
+ BLT,
+ RENDER,
+ PLANE_MOVE,
+ PLANE_ONOFF,
+};
+
+static const char *op_str(enum operations op)
+{
+ static const char * const name[] = {
+ [PAGE_FLIP] = "page_flip",
+ [MMAP_GTT] = "mmap_gtt",
+ [MMAP_CPU] = "mmap_cpu",
+ [BLT] = "blt",
+ [RENDER] = "render",
+ [PLANE_MOVE] = "plane_move",
+ [PLANE_ONOFF] = "plane_onoff",
+ };
+
+ return name[op];
+}
+
+typedef struct {
+ int drm_fd;
+ int debugfs_fd;
+ enum operations op;
+ uint32_t devid;
+ uint32_t crtc_id;
+ igt_display_t display;
+ drm_intel_bufmgr *bufmgr;
+ struct igt_fb fb_green, fb_white;
+ igt_plane_t *test_plane;
+ int mod_size;
+ int mod_stride;
+ drmModeModeInfo *mode;
+ igt_output_t *output;
+ bool with_psr_disabled;
+} data_t;
+
+static void create_cursor_fb(data_t *data)
+{
+ cairo_t *cr;
+ uint32_t fb_id;
+
+ fb_id = igt_create_fb(data->drm_fd, 64, 64,
+ DRM_FORMAT_ARGB8888, LOCAL_DRM_FORMAT_MOD_NONE,
+ &data->fb_white);
+ igt_assert(fb_id);
+
+ cr = igt_get_cairo_ctx(data->drm_fd, &data->fb_white);
+ igt_paint_color_alpha(cr, 0, 0, 64, 64, 1.0, 1.0, 1.0, 1.0);
+ igt_put_cairo_ctx(data->drm_fd, &data->fb_white, cr);
+}
+
+static void setup_output(data_t *data)
+{
+ igt_display_t *display = &data->display;
+ igt_output_t *output;
+ enum pipe pipe;
+
+ for_each_pipe_with_valid_output(display, pipe, output) {
+ drmModeConnectorPtr c = output->config.connector;
+
+ if (c->connector_type != DRM_MODE_CONNECTOR_eDP)
+ continue;
+
+ igt_output_set_pipe(output, pipe);
+ data->crtc_id = output->config.crtc->crtc_id;
+ data->output = output;
+ data->mode = igt_output_get_mode(output);
+
+ return;
+ }
+}
+
+static void display_init(data_t *data)
+{
+ igt_display_init(&data->display, data->drm_fd);
+ setup_output(data);
+}
+
+static void display_fini(data_t *data)
+{
+ igt_display_fini(&data->display);
+}
+
+static void fill_blt(data_t *data, uint32_t handle, unsigned char color)
+{
+ drm_intel_bo *dst = gem_handle_to_libdrm_bo(data->bufmgr,
+ data->drm_fd,
+ "", handle);
+ struct intel_batchbuffer *batch;
+
+ batch = intel_batchbuffer_alloc(data->bufmgr, data->devid);
+ igt_assert(batch);
+
+ COLOR_BLIT_COPY_BATCH_START(0);
+ OUT_BATCH((1 << 24) | (0xf0 << 16) | 0);
+ OUT_BATCH(0);
+ OUT_BATCH(0xfff << 16 | 0xfff);
+ OUT_RELOC(dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(color);
+ ADVANCE_BATCH();
+
+ intel_batchbuffer_flush(batch);
+ intel_batchbuffer_free(batch);
+
+ gem_bo_busy(data->drm_fd, handle);
+}
+
+static void scratch_buf_init(struct igt_buf *buf, drm_intel_bo *bo,
+ int size, int stride)
+{
+ memset(buf, 0, sizeof(*buf));
+
+ buf->bo = bo;
+ buf->stride = stride;
+ buf->tiling = I915_TILING_X;
+ buf->size = size;
+}
+
+static void fill_render(data_t *data, uint32_t handle, unsigned char color)
+{
+ drm_intel_bo *src, *dst;
+ struct intel_batchbuffer *batch;
+ struct igt_buf src_buf, dst_buf;
+ const uint8_t buf[4] = { color, color, color, color };
+ igt_render_copyfunc_t rendercopy = igt_get_render_copyfunc(data->devid);
+
+ igt_skip_on(!rendercopy);
+
+ dst = gem_handle_to_libdrm_bo(data->bufmgr, data->drm_fd, "", handle);
+ igt_assert(dst);
+
+ src = drm_intel_bo_alloc(data->bufmgr, "", data->mod_size, 4096);
+ igt_assert(src);
+
+ gem_write(data->drm_fd, src->handle, 0, buf, 4);
+
+ scratch_buf_init(&src_buf, src, data->mod_size, data->mod_stride);
+ scratch_buf_init(&dst_buf, dst, data->mod_size, data->mod_stride);
+
+ batch = intel_batchbuffer_alloc(data->bufmgr, data->devid);
+ igt_assert(batch);
+
+ rendercopy(batch, NULL,
+ &src_buf, 0, 0, 0xff, 0xff,
+ &dst_buf, 0, 0);
+
+ intel_batchbuffer_free(batch);
+
+ gem_bo_busy(data->drm_fd, handle);
+}
+
+static bool sink_support(data_t *data)
+{
+ char buf[512];
+
+ igt_debugfs_read(data->drm_fd, "i915_edp_psr_status", buf);
+
+ return data->with_psr_disabled ||
+ strstr(buf, "Sink_Support: yes\n");
+}
+
+static bool psr_active(data_t *data, bool check_active)
+{
+ bool active;
+ char buf[512];
+
+ igt_debugfs_read(data->drm_fd, "i915_edp_psr_status", buf);
+
+ active = strstr(buf, "HW Enabled & Active bit: yes\n") &&
+ (strstr(buf, "SRDENT") || strstr(buf, "SLEEP"));
+ return check_active ? active : !active;
+}
+
+static bool wait_psr_entry(data_t *data)
+{
+ if (data->with_psr_disabled)
+ return true;
+
+ return igt_wait((psr_active(data, true)), 500, 1);
+}
+
+static inline void manual(const char *expected)
+{
+ igt_debug_manual_check("all", expected);
+}
+
+static bool drrs_disabled(data_t *data)
+{
+ char buf[512];
+
+ igt_debugfs_read(data->drm_fd, "i915_drrs_status", buf);
+
+ return !strstr(buf, "DRRS Supported: Yes\n");
+}
+
+static void run_test(data_t *data)
+{
+ uint32_t handle = data->fb_white.gem_handle;
+ igt_plane_t *test_plane = data->test_plane;
+ void *ptr;
+ const char *expected = "";
+
+ /* Confirm that screen became Green */
+ manual("screen GREEN");
+
+ /* Confirm screen stays Green after PSR got active */
+ igt_assert(wait_psr_entry(data));
+ manual("screen GREEN");
+
+ /* Setting a secondary fb/plane */
+ igt_plane_set_fb(test_plane, &data->fb_white);
+ igt_display_commit(&data->display);
+
+ /* Confirm it is not Green anymore */
+ if (test_plane->type == DRM_PLANE_TYPE_PRIMARY)
+ manual("screen WHITE");
+ else
+ manual("GREEN background with WHITE box");
+
+ igt_assert(wait_psr_entry(data));
+ switch (data->op) {
+ case PAGE_FLIP:
+ /* Only in use when testing primary plane */
+ igt_assert(drmModePageFlip(data->drm_fd, data->crtc_id,
+ data->fb_green.fb_id, 0, NULL) == 0);
+ expected = "GREEN";
+ break;
+ case MMAP_GTT:
+ ptr = gem_mmap__gtt(data->drm_fd, handle, data->mod_size,
+ PROT_WRITE);
+ gem_set_domain(data->drm_fd, handle,
+ I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+ memset(ptr, 0xcc, data->mod_size);
+ munmap(ptr, data->mod_size);
+ expected = "BLACK or TRANSPARENT mark on top of plane in test";
+ break;
+ case MMAP_CPU:
+ ptr = gem_mmap__cpu(data->drm_fd, handle, 0, data->mod_size,
+ PROT_WRITE);
+ gem_set_domain(data->drm_fd, handle,
+ I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
+ memset(ptr, 0, data->mod_size);
+ munmap(ptr, data->mod_size);
+ gem_sw_finish(data->drm_fd, handle);
+ expected = "BLACK or TRANSPARENT mark on top of plane in test";
+ break;
+ case BLT:
+ fill_blt(data, handle, 0);
+ expected = "BLACK or TRANSPARENT mark on top of plane in test";
+ break;
+ case RENDER:
+ fill_render(data, handle, 0);
+ expected = "BLACK or TRANSPARENT mark on top of plane in test";
+ break;
+ case PLANE_MOVE:
+ /* Only in use when testing Sprite and Cursor */
+ igt_plane_set_position(test_plane, 500, 500);
+ igt_display_commit(&data->display);
+ expected = "White box moved to 500x500";
+ break;
+ case PLANE_ONOFF:
+ /* Only in use when testing Sprite and Cursor */
+ igt_plane_set_fb(test_plane, NULL);
+ igt_display_commit(&data->display);
+ expected = "screen GREEN";
+ break;
+ }
+ igt_assert(psr_active(data, false));
+ manual(expected);
+}
+
+static void test_cleanup(data_t *data) {
+ igt_plane_t *primary;
+
+ primary = igt_output_get_plane_type(data->output,
+ DRM_PLANE_TYPE_PRIMARY);
+ igt_plane_set_fb(primary, NULL);
+ igt_plane_set_fb(data->test_plane, NULL);
+ igt_display_commit(&data->display);
+
+ igt_remove_fb(data->drm_fd, &data->fb_green);
+ igt_remove_fb(data->drm_fd, &data->fb_white);
+}
+
+static void setup_test_plane(data_t *data, int test_plane)
+{
+ uint32_t white_h, white_v;
+ igt_plane_t *primary, *sprite, *cursor;
+
+ igt_create_color_fb(data->drm_fd,
+ data->mode->hdisplay, data->mode->vdisplay,
+ DRM_FORMAT_XRGB8888,
+ LOCAL_I915_FORMAT_MOD_X_TILED,
+ 0.0, 1.0, 0.0,
+ &data->fb_green);
+
+ primary = igt_output_get_plane_type(data->output,
+ DRM_PLANE_TYPE_PRIMARY);
+ igt_plane_set_fb(primary, NULL);
+ data->test_plane = primary;
+
+ white_h = data->mode->hdisplay;
+ white_v = data->mode->vdisplay;
+
+ /* Ignoring pitch and bpp to avoid changing full screen */
+ data->mod_size = white_h * white_v;
+ data->mod_stride = white_h * 4;
+
+ switch (test_plane) {
+ case DRM_PLANE_TYPE_OVERLAY:
+ sprite = igt_output_get_plane_type(data->output,
+ DRM_PLANE_TYPE_OVERLAY);
+ igt_plane_set_fb(sprite, NULL);
+ white_h = white_h/2;
+ white_v = white_v/2;
+ data->test_plane = sprite;
+ case DRM_PLANE_TYPE_PRIMARY:
+ igt_create_color_fb(data->drm_fd,
+ white_h, white_v,
+ DRM_FORMAT_XRGB8888,
+ LOCAL_I915_FORMAT_MOD_X_TILED,
+ 1.0, 1.0, 1.0,
+ &data->fb_white);
+ break;
+ case DRM_PLANE_TYPE_CURSOR:
+ cursor = igt_output_get_plane_type(data->output,
+ DRM_PLANE_TYPE_CURSOR);
+ igt_plane_set_fb(cursor, NULL);
+ create_cursor_fb(data);
+ igt_plane_set_position(cursor, 0, 0);
+
+ /* Cursor is 64 x 64, ignoring pitch and bbp again */
+ data->mod_size = 64 * 64;
+ data->test_plane = cursor;
+ break;
+ }
+
+ igt_display_commit(&data->display);
+
+ igt_plane_set_fb(primary, &data->fb_green);
+ igt_display_commit(&data->display);
+}
+
+static void dpms_off_on(data_t *data)
+{
+ kmstest_set_connector_dpms(data->drm_fd, data->output->config.connector,
+ DRM_MODE_DPMS_OFF);
+ kmstest_set_connector_dpms(data->drm_fd, data->output->config.connector,
+ DRM_MODE_DPMS_ON);
+}
+
+static int opt_handler(int opt, int opt_index, void *_data)
+{
+ data_t *data = _data;
+
+ switch (opt) {
+ case 'n':
+ data->with_psr_disabled = true;
+ break;
+ default:
+ igt_assert(0);
+ }
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ const char *help_str =
+ " --no-psr\tRun test without PSR.";
+ static struct option long_options[] = {
+ {"no-psr", 0, 0, 'n'},
+ { 0, 0, 0, 0 }
+ };
+ data_t data = {};
+ enum operations op;
+
+ igt_subtest_init_parse_opts(&argc, argv, "", long_options,
+ help_str, opt_handler, &data);
+ igt_skip_on_simulation();
+
+ igt_fixture {
+ data.drm_fd = drm_open_driver_master(DRIVER_INTEL);
+ data.debugfs_fd = igt_debugfs_dir(data.drm_fd);
+ kmstest_set_vt_graphics_mode();
+ data.devid = intel_get_drm_devid(data.drm_fd);
+
+ igt_set_module_param_int("enable_psr", data.with_psr_disabled ?
+ 0 : 1);
+ igt_require_f(sink_support(&data),
+ "Sink does not support PSR\n");
+
+ data.bufmgr = drm_intel_bufmgr_gem_init(data.drm_fd, 4096);
+ igt_assert(data.bufmgr);
+ drm_intel_bufmgr_gem_enable_reuse(data.bufmgr);
+
+ display_init(&data);
+ }
+
+ igt_subtest("basic") {
+ setup_test_plane(&data, DRM_PLANE_TYPE_PRIMARY);
+ igt_assert(wait_psr_entry(&data));
+ test_cleanup(&data);
+ }
+
+ igt_subtest("no_drrs") {
+ setup_test_plane(&data, DRM_PLANE_TYPE_PRIMARY);
+ igt_assert(wait_psr_entry(&data));
+ igt_assert(drrs_disabled(&data));
+ test_cleanup(&data);
+ }
+
+ for (op = PAGE_FLIP; op <= RENDER; op++) {
+ igt_subtest_f("primary_%s", op_str(op)) {
+ data.op = op;
+ setup_test_plane(&data, DRM_PLANE_TYPE_PRIMARY);
+ igt_assert(wait_psr_entry(&data));
+ run_test(&data);
+ test_cleanup(&data);
+ }
+ }
+
+ for (op = MMAP_GTT; op <= PLANE_ONOFF; op++) {
+ igt_subtest_f("sprite_%s", op_str(op)) {
+ data.op = op;
+ setup_test_plane(&data, DRM_PLANE_TYPE_OVERLAY);
+ igt_assert(wait_psr_entry(&data));
+ run_test(&data);
+ test_cleanup(&data);
+ }
+ }
+
+ for (op = MMAP_GTT; op <= PLANE_ONOFF; op++) {
+ igt_subtest_f("cursor_%s", op_str(op)) {
+ data.op = op;
+ setup_test_plane(&data, DRM_PLANE_TYPE_CURSOR);
+ igt_assert(wait_psr_entry(&data));
+ run_test(&data);
+ test_cleanup(&data);
+ }
+ }
+
+ igt_subtest_f("dpms") {
+ data.op = RENDER;
+ setup_test_plane(&data, DRM_PLANE_TYPE_PRIMARY);
+ igt_assert(wait_psr_entry(&data));
+ dpms_off_on(&data);
+ run_test(&data);
+ test_cleanup(&data);
+ }
+
+ igt_subtest_f("suspend") {
+ data.op = PLANE_ONOFF;
+ setup_test_plane(&data, DRM_PLANE_TYPE_CURSOR);
+ igt_assert(wait_psr_entry(&data));
+ igt_system_suspend_autoresume(SUSPEND_STATE_MEM,
+ SUSPEND_TEST_NONE);
+ igt_assert(wait_psr_entry(&data));
+ run_test(&data);
+ test_cleanup(&data);
+ }
+
+ igt_fixture {
+ close(data.debugfs_fd);
+ drm_intel_bufmgr_destroy(data.bufmgr);
+ display_fini(&data);
+ }
+
+ igt_exit();
+}