[i-g-t V3] Add IGT support for Bigjoiner

Bhanuprakash Modem bhanuprakash.modem at intel.com
Tue Aug 16 04:48:32 UTC 2022


Signed-off-by: Bhanuprakash Modem <bhanuprakash.modem at intel.com>
---
 lib/igt_kms.c                         |  32 ++++
 lib/igt_kms.h                         |   1 +
 tests/chamelium/kms_color_chamelium.c |   9 ++
 tests/i915/kms_big_fb.c               |  13 ++
 tests/i915/kms_big_joiner.c           | 118 +++++++++++---
 tests/i915/kms_busy.c                 | 104 ++++++++----
 tests/i915/kms_ccs.c                  |  17 +-
 tests/i915/kms_cdclk.c                |  93 ++++++-----
 tests/i915/kms_fence_pin_leak.c       |   9 ++
 tests/i915/kms_flip_scaled_crc.c      |  13 +-
 tests/i915/kms_flip_tiling.c          |   7 +
 tests/i915/kms_frontbuffer_tracking.c |  16 +-
 tests/i915/kms_mmap_write_crc.c       |   6 +
 tests/i915/kms_psr.c                  |   4 +
 tests/i915/kms_psr2_sf.c              |   7 +
 tests/i915/kms_psr2_su.c              |   7 +
 tests/i915/kms_psr_stress_test.c      |   8 +-
 tests/i915/kms_pwrite_crc.c           |   7 +
 tests/kms_async_flips.c               |  14 +-
 tests/kms_atomic.c                    |  28 +++-
 tests/kms_atomic_interruptible.c      |  39 +++++
 tests/kms_atomic_transition.c         | 131 ++++++++++++++--
 tests/kms_color.c                     |   9 +-
 tests/kms_color_helper.c              |  12 ++
 tests/kms_color_helper.h              |   1 +
 tests/kms_concurrent.c                |  10 +-
 tests/kms_content_protection.c        |  17 ++
 tests/kms_cursor_crc.c                |  49 ++++--
 tests/kms_cursor_edge_walk.c          |   6 +
 tests/kms_cursor_legacy.c             | 202 +++++++++++++++---------
 tests/kms_display_modes.c             | 104 +++++++-----
 tests/kms_dp_tiled_display.c          |   1 +
 tests/kms_flip_event_leak.c           |  10 ++
 tests/kms_invalid_mode.c              |   6 +
 tests/kms_lease.c                     |   6 +
 tests/kms_multipipe_modeset.c         |   9 ++
 tests/kms_pipe_crc_basic.c            |  24 +++
 tests/kms_plane.c                     |  30 ++--
 tests/kms_plane_alpha_blend.c         |   7 +
 tests/kms_plane_cursor.c              |   8 +-
 tests/kms_plane_lowres.c              |   3 +
 tests/kms_plane_multiple.c            |  11 +-
 tests/kms_plane_scaling.c             | 217 +++++++++++++++++---------
 tests/kms_prime.c                     |  11 +-
 tests/kms_properties.c                |  18 +++
 tests/kms_rmfb.c                      |  10 +-
 tests/kms_rotation_crc.c              |  25 ++-
 tests/kms_scaling_modes.c             |   8 +-
 tests/kms_sequence.c                  |   6 +
 tests/kms_universal_plane.c           |  93 +++++++++--
 tests/kms_vblank.c                    |  54 ++++++-
 tests/kms_vrr.c                       |   6 +
 52 files changed, 1286 insertions(+), 370 deletions(-)

diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index 1ba3bd2a..182e4820 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -5692,6 +5692,11 @@ bool igt_max_bpc_constraint(igt_display_t *display, enum pipe pipe,
 
 	for_each_connector_mode(output) {
 		igt_output_override_mode(output, &connector->modes[j__]);
+
+		if (is_i915_device(display->drm_fd) &&
+		    !igt_check_bigjoiner_support(display))
+			continue;
+
 		igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
 
 		if (!igt_check_output_bpc_equal(display->drm_fd, pipe,
@@ -5803,3 +5808,30 @@ bool igt_parse_mode_string(const char *mode_string, drmModeModeInfo *mode)
 
 	return true;
 }
+
+/*
+ * igt_test_constraint:
+ * @display: a pointer to an #igt_display_t structure
+ *
+ * Get all active pipes from connected outputs (i.e. pending_pipe != PIPE_NONE)
+ * and check those pipes supports the selected mode(s).
+ *
+ * This is a super set of all test constraints.
+ *
+ * Example:
+ *  * Pipe-D can't support mode > 5K
+ *  * To use 8K mode on a pipe then consecutive pipe must be free.
+ *  * MSO is supported only on PIPE_A/PIPE_B.
+ *
+ * Returns: true if a valid crtc/connector mode combo found, else false
+ */
+bool igt_test_constraint(igt_display_t *display)
+{
+	bool result = true;
+
+	/* TODO: Add all possible test constraints here. */
+	if (is_i915_device(display->drm_fd))
+		result &= igt_check_bigjoiner_support(display);
+
+	return result;
+}
diff --git a/lib/igt_kms.h b/lib/igt_kms.h
index a2cf0937..82186cfe 100644
--- a/lib/igt_kms.h
+++ b/lib/igt_kms.h
@@ -975,5 +975,6 @@ bool igt_max_bpc_constraint(igt_display_t *display, enum pipe pipe,
 		igt_output_t *output, int bpc);
 bool igt_check_bigjoiner_support(igt_display_t *display);
 bool igt_parse_mode_string(const char *mode_string, drmModeModeInfo *mode);
+bool igt_test_constraint(igt_display_t *display);
 
 #endif /* __IGT_KMS_H__ */
diff --git a/tests/chamelium/kms_color_chamelium.c b/tests/chamelium/kms_color_chamelium.c
index 678931aa..42289e91 100644
--- a/tests/chamelium/kms_color_chamelium.c
+++ b/tests/chamelium/kms_color_chamelium.c
@@ -458,6 +458,9 @@ run_gamma_degamma_tests_for_pipe(data_t *data, enum pipe p,
 	data->drm_format = DRM_FORMAT_XRGB8888;
 	data->mode = igt_output_get_mode(data->output);
 
+	if (!test_constraint(data, p))
+		return;
+
 	igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(p), data->output->name)
 		igt_assert(test_t(data, data->primary, data->ports[port_idx]));
 }
@@ -493,6 +496,9 @@ run_ctm_tests_for_pipe(data_t *data, enum pipe p,
 	data->drm_format = DRM_FORMAT_XRGB8888;
 	data->mode = igt_output_get_mode(data->output);
 
+	if (!test_constraint(data, p))
+		return;
+
 	igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(p), data->output->name) {
 		bool success = false;
 		int i;
@@ -538,6 +544,9 @@ run_limited_range_ctm_test_for_pipe(data_t *data, enum pipe p,
 	data->drm_format = DRM_FORMAT_XRGB8888;
 	data->mode = igt_output_get_mode(data->output);
 
+	if (!test_constraint(data, p))
+		return;
+
 	igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(p), data->output->name)
 		igt_assert(test_t(data, data->primary, data->ports[port_idx]));
 }
diff --git a/tests/i915/kms_big_fb.c b/tests/i915/kms_big_fb.c
index d50fde45..6f12c59d 100644
--- a/tests/i915/kms_big_fb.c
+++ b/tests/i915/kms_big_fb.c
@@ -397,6 +397,9 @@ static bool test_pipe(data_t *data)
 	igt_plane_t *primary;
 	bool ret = false;
 
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(data->pipe), igt_output_name(data->output));
+
 	if (data->format == DRM_FORMAT_C8 &&
 	    !igt_pipe_obj_has_prop(&data->display.pipes[data->pipe],
 				   IGT_CRTC_GAMMA_LUT))
@@ -472,6 +475,10 @@ max_hw_stride_async_flip_test(data_t *data)
 	igt_crc_t compare_crc, async_crc;
 
 	igt_require(data->display.is_atomic);
+
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(data->pipe), igt_output_name(data->output));
+
 	igt_output_set_pipe(data->output, data->pipe);
 
 	primary = igt_output_get_plane_type(data->output, DRM_PLANE_TYPE_PRIMARY);
@@ -582,6 +589,12 @@ static void test_scanout(data_t *data)
 		    data->format, data->modifier);
 
 	for_each_pipe_with_valid_output(&data->display, data->pipe, data->output) {
+		igt_display_reset(&data->display);
+
+		igt_output_set_pipe(data->output, data->pipe);
+		if (!igt_test_constraint(&data->display))
+			continue;
+
 		if (data->async_flip_test) {
 			if (max_hw_stride_async_flip_test(data))
 				return;
diff --git a/tests/i915/kms_big_joiner.c b/tests/i915/kms_big_joiner.c
index 7d400616..2e189fc8 100644
--- a/tests/i915/kms_big_joiner.c
+++ b/tests/i915/kms_big_joiner.c
@@ -43,6 +43,44 @@ typedef struct {
 	} big_joiner_output[2];
 } data_t;
 
+static void test_invalid(data_t *data)
+{
+	igt_output_t *output;
+	igt_display_t *display = &data->display;
+	int ret;
+
+	igt_info("Bigjoiner test on ");
+	for_each_connected_output(display, output){
+		enum pipe p = output->pending_pipe;
+		drmModeModeInfo *mode;
+		igt_pipe_t *pipe;
+		igt_plane_t *plane;
+
+		if (p == PIPE_NONE)
+			continue;
+
+		mode = igt_output_get_mode(output);
+		igt_info("pipe:%s, output:%s, mode:", kmstest_pipe_name(p), igt_output_name(output));
+		kmstest_dump_mode(mode);
+
+		pipe = &display->pipes[p];
+		plane = igt_pipe_get_plane_type(pipe, DRM_PLANE_TYPE_PRIMARY);
+
+		igt_plane_set_fb(plane, &data->fb);
+		igt_fb_set_size(&data->fb, plane, mode->hdisplay, mode->vdisplay);
+		igt_plane_set_size(plane, mode->hdisplay, mode->vdisplay);
+	}
+
+	/* This commit is expectd to fail as this pipe is being used for big joiner */
+	ret = igt_display_try_commit_atomic(display, DRM_MODE_ATOMIC_TEST_ONLY |
+					    DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+
+	igt_display_reset(&data->display);
+	igt_display_commit2(display, COMMIT_ATOMIC);
+
+	igt_assert_lt(ret, 0);
+}
+
 static void test_invalid_modeset(data_t *data)
 {
 	drmModeModeInfo *mode;
@@ -261,19 +299,17 @@ igt_main
 		igt_require(data.display.is_atomic);
 
 		for_each_connected_output(&data.display, output) {
-			if (count < 2) {
-				for (i = 0; i < output->config.connector->count_modes; i++) {
-					mode = &output->config.connector->modes[i];
-					if (mode->hdisplay > MAX_HDISPLAY_PER_PIPE) {
-						data.big_joiner_output[count].mode_number = i;
-						data.big_joiner_output[count].id = output->id;
-						count++;
-
-						width = max(width, mode->hdisplay);
-						height = max(height, mode->vdisplay);
-						break;
-					}
-				}
+			igt_sort_connector_modes(output->config.connector,
+						 sort_drm_modes_by_res_dsc);
+
+			mode = &output->config.connector->modes[0];
+			if (mode->hdisplay > MAX_HDISPLAY_PER_PIPE) {
+				data.big_joiner_output[count].mode_number = i;
+				data.big_joiner_output[count].id = output->id;
+				count++;
+
+				width = max(width, mode->hdisplay);
+				height = max(height, mode->vdisplay);
 			}
 			valid_output++;
 		}
@@ -303,13 +339,55 @@ igt_main
 	igt_describe("Verify if the modeset on the adjoining pipe is rejected "
 		     "when the pipe is active with a big joiner modeset");
 	igt_subtest_with_dynamic("invalid-modeset") {
-		igt_require_f(valid_output > 1, "No valid Second output found\n");
-		for (i = 0; i < data.n_pipes - 1; i++) {
-			data.pipe1 = pipe_seq[i];
-			data.pipe2 = pipe_seq[i + 1];
-			igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe_seq[i]),
-						    kmstest_pipe_name(pipe_seq[i + 1]))
-				test_invalid_modeset(&data);
+		enum pipe pipe;
+
+		for_each_pipe_with_valid_output(&data.display, pipe, output) {
+			igt_display_reset(&data.display);
+
+			igt_sort_connector_modes(output->config.connector,
+						 sort_drm_modes_by_res_dsc);
+
+			igt_output_set_pipe(output, pipe);
+			igt_output_override_mode(output,
+						 &output->config.connector->modes[0]);
+			if (!igt_check_bigjoiner_support(&data.display)) {
+				igt_dynamic("single-connector") {
+					test_invalid(&data);
+				}
+			}
+		}
+
+		igt_display_reset(&data.display);
+		for_each_pipe(&data.display, pipe) {
+			for_each_valid_output_on_pipe(&data.display, pipe, output) {
+				if (output->pending_pipe != PIPE_NONE)
+					continue;
+
+				igt_sort_connector_modes(output->config.connector,
+							 sort_drm_modes_by_res_dsc);
+
+				igt_output_set_pipe(output, pipe);
+				igt_output_override_mode(output,
+							 &output->config.connector->modes[0]);
+
+				break;
+			}
+		}
+		if (valid_output > 1 &&
+		    !igt_check_bigjoiner_support(&data.display)) {
+			igt_dynamic("multi-connector") {
+				test_invalid(&data);
+			}
+		}
+
+		if(valid_output > 1) {
+			for (i = 0; i < data.n_pipes - 1; i++) {
+				data.pipe1 = pipe_seq[i];
+				data.pipe2 = pipe_seq[i + 1];
+				igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe_seq[i]),
+							    kmstest_pipe_name(pipe_seq[i + 1]))
+					test_invalid_modeset(&data);
+			}
 		}
 	}
 
diff --git a/tests/i915/kms_busy.c b/tests/i915/kms_busy.c
index 99a07c2a..15642b99 100644
--- a/tests/i915/kms_busy.c
+++ b/tests/i915/kms_busy.c
@@ -32,15 +32,12 @@ IGT_TEST_DESCRIPTION("Basic check of KMS ABI with busy framebuffers.");
 
 static bool all_pipes = false;
 
-static igt_output_t *
-set_fb_on_crtc(igt_display_t *dpy, int pipe, struct igt_fb *fb)
+static void
+set_fb_on_crtc(igt_display_t *dpy, int pipe,
+	       igt_output_t *output, struct igt_fb *fb)
 {
 	drmModeModeInfoPtr mode;
 	igt_plane_t *primary;
-	igt_output_t *output;
-
-	output = igt_get_single_output_for_pipe(dpy, pipe);
-	igt_require(output);
 
 	igt_output_set_pipe(output, pipe);
 	mode = igt_output_get_mode(output);
@@ -51,8 +48,6 @@ set_fb_on_crtc(igt_display_t *dpy, int pipe, struct igt_fb *fb)
 
 	primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
 	igt_plane_set_fb(primary, fb);
-
-	return output;
 }
 
 static void do_cleanup_display(igt_display_t *dpy)
@@ -136,18 +131,23 @@ static void flip_to_fb(igt_display_t *dpy, int pipe,
 	put_ahnd(ahnd);
 }
 
-static void test_flip(igt_display_t *dpy, int pipe, bool modeset)
+static void test_flip(igt_display_t *dpy, int pipe,
+		      igt_output_t *output, bool modeset)
 {
 	struct igt_fb fb[2];
 	int warmup[] = { 0, 1, 0, -1 };
 	struct timespec tv = {};
-	igt_output_t *output;
 	int timeout;
 
 	if (modeset)
 		igt_require(dpy->is_atomic);
 
-	output = set_fb_on_crtc(dpy, pipe, &fb[0]);
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
+	igt_display_reset(dpy);
+
+	set_fb_on_crtc(dpy, pipe, output, &fb[0]);
 	igt_display_commit2(dpy, COMMIT_LEGACY);
 
 	igt_create_pattern_fb(dpy->drm_fd,
@@ -224,13 +224,18 @@ static void test_atomic_commit_hang(igt_display_t *dpy, igt_plane_t *primary,
 }
 
 static void test_hang(igt_display_t *dpy,
-		      enum pipe pipe, bool modeset, bool hang_newfb)
+		      enum pipe pipe, igt_output_t *output,
+		      bool modeset, bool hang_newfb)
 {
 	struct igt_fb fb[2];
-	igt_output_t *output;
 	igt_plane_t *primary;
 
-	output = set_fb_on_crtc(dpy, pipe, &fb[0]);
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
+	igt_display_reset(dpy);
+
+	set_fb_on_crtc(dpy, pipe, output, &fb[0]);
 	igt_display_commit2(dpy, COMMIT_ATOMIC);
 	primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
 
@@ -265,16 +270,22 @@ static void test_hang(igt_display_t *dpy,
 	igt_remove_fb(dpy->drm_fd, &fb[0]);
 }
 
-static void test_pageflip_modeset_hang(igt_display_t *dpy, enum pipe pipe)
+static void
+test_pageflip_modeset_hang(igt_display_t *dpy,
+			   igt_output_t *output, enum pipe pipe)
 {
 	struct igt_fb fb;
 	struct drm_event_vblank ev;
-	igt_output_t *output;
 	igt_plane_t *primary;
 	igt_spin_t *t;
 	uint64_t ahnd = get_reloc_ahnd(dpy->drm_fd, 0);
 
-	output = set_fb_on_crtc(dpy, pipe, &fb);
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
+	igt_display_reset(dpy);
+
+	set_fb_on_crtc(dpy, pipe, output, &fb);
 	primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
 
 	igt_display_commit2(dpy, dpy->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
@@ -299,6 +310,21 @@ static void test_pageflip_modeset_hang(igt_display_t *dpy, enum pipe pipe)
 	igt_remove_fb(dpy->drm_fd, &fb);
 }
 
+static bool
+is_valid_combo(igt_display_t *dpy, igt_output_t *output, enum pipe pipe)
+{
+	bool ret = true;
+
+	igt_display_reset(dpy);
+
+	igt_output_set_pipe(output, pipe);
+	if (!igt_test_constraint(dpy))
+		ret = false;
+	igt_output_set_pipe(output, PIPE_NONE);
+
+	return ret;
+}
+
 static int opt_handler(int opt, int opt_index, void *data)
 {
 	switch (opt) {
@@ -319,7 +345,8 @@ igt_main_args("e", NULL, help_str, opt_handler, NULL)
 {
 	igt_display_t display = { .drm_fd = -1, .n_pipes = IGT_MAX_PIPES };
 
-	enum pipe active_pipes[IGT_MAX_PIPES];
+	enum pipe pipe, active_pipes[IGT_MAX_PIPES];
+	igt_output_t *output;
 	uint32_t last_pipe = 0;
 	int i;
 	struct {
@@ -338,7 +365,6 @@ igt_main_args("e", NULL, help_str, opt_handler, NULL)
 
 	igt_fixture {
 		int fd = drm_open_driver_master(DRIVER_INTEL);
-		enum pipe pipe;
 
 		igt_require_gem(fd);
 		gem_require_mmap_device_coherent(fd);
@@ -358,63 +384,72 @@ igt_main_args("e", NULL, help_str, opt_handler, NULL)
 
 	igt_describe("Test for basic check of KMS ABI with busy framebuffers.");
 	igt_subtest_with_dynamic("basic") { /* just run on the first pipe */
-		enum pipe pipe;
+		for_each_pipe_with_single_output(&display, pipe, output) {
+			if (!is_valid_combo(&display, output, pipe))
+				continue;
 
-		for_each_pipe(&display, pipe) {
 			igt_dynamic("flip")
-				test_flip(&display, pipe, false);
+				test_flip(&display, pipe, output, false);
 			igt_dynamic("modeset")
-				test_flip(&display, pipe, true);
+				test_flip(&display, pipe, output, true);
 			break;
 		}
 	}
 
 	igt_subtest_with_dynamic("basic-hang") {
-		enum pipe pipe;
 		igt_hang_t hang = igt_allow_hang(display.drm_fd, 0, 0);
 		errno = 0;
 
-		for_each_pipe(&display, pipe) {
+		for_each_pipe_with_single_output(&display, pipe, output) {
+			if (!is_valid_combo(&display, output, pipe))
+				continue;
+
 			if (!all_pipes && pipe != active_pipes[0] &&
 					  pipe != active_pipes[last_pipe])
 				continue;
 
 			igt_dynamic_f("flip-pipe-%s", kmstest_pipe_name(pipe))
-				test_flip(&display, pipe, false);
+				test_flip(&display, pipe, output, false);
 			igt_dynamic_f("modeset-pipe-%s", kmstest_pipe_name(pipe))
-				test_flip(&display, pipe, true);
+				test_flip(&display, pipe, output, true);
 		}
 
 		igt_disallow_hang(display.drm_fd, hang);
 	}
 
 	igt_subtest_with_dynamic("extended-pageflip-modeset-hang-oldfb") {
-		enum pipe pipe;
 		igt_hang_t hang = igt_allow_hang(display.drm_fd, 0, 0);
 		errno = 0;
 
-		for_each_pipe(&display, pipe) {
+		for_each_pipe_with_single_output(&display, pipe, output) {
+			if (!is_valid_combo(&display, output, pipe))
+				continue;
+
 			if (!all_pipes && pipe != active_pipes[0] &&
 					  pipe != active_pipes[last_pipe])
 				continue;
 
 			igt_dynamic_f("pipe-%s", kmstest_pipe_name(pipe))
-				test_pageflip_modeset_hang(&display, pipe);
+				test_pageflip_modeset_hang(&display, output, pipe);
 		}
 
 		igt_disallow_hang(display.drm_fd, hang);
 	}
 
 	for (i = 0; i < sizeof(tests) / sizeof (tests[0]); i++) {
+		igt_fixture
+			igt_require(display.is_atomic);
+
 		igt_subtest_with_dynamic(tests[i].name) {
-			enum pipe pipe;
 			igt_hang_t hang;
 			errno = 0;
 
-			igt_require(display.is_atomic);
 			hang = igt_allow_hang(display.drm_fd, 0, 0);
 
-			for_each_pipe(&display, pipe) {
+			for_each_pipe_with_single_output(&display, pipe, output) {
+				if (!is_valid_combo(&display, output, pipe))
+					continue;
+
 				if (!all_pipes && pipe != active_pipes[0] &&
 						  pipe != active_pipes[last_pipe])
 					continue;
@@ -423,7 +458,8 @@ igt_main_args("e", NULL, help_str, opt_handler, NULL)
 					if (tests[i].reset)
 						igt_set_module_param_int(display.drm_fd, "force_reset_modeset_test", 1);
 
-					test_hang(&display, pipe, tests[i].modeset, tests[i].hang_newfb);
+					test_hang(&display, pipe, output,
+						  tests[i].modeset, tests[i].hang_newfb);
 
 					if (tests[i].reset)
 						igt_set_module_param_int(display.drm_fd, "force_reset_modeset_test", 0);
diff --git a/tests/i915/kms_ccs.c b/tests/i915/kms_ccs.c
index 4df611f7..1d55cd2d 100644
--- a/tests/i915/kms_ccs.c
+++ b/tests/i915/kms_ccs.c
@@ -589,12 +589,20 @@ static int test_ccs(data_t *data)
 static void test_output(data_t *data, const int testnum)
 {
 	igt_fixture {
+		bool found = false;
 		data->flags = tests[testnum].flags;
 
-		data->output = igt_get_single_output_for_pipe(&data->display,
-							      data->pipe);
-		igt_require(data->output);
-		igt_output_set_pipe(data->output, data->pipe);
+		for_each_valid_output_on_pipe(&data->display, data->pipe, data->output) {
+			igt_display_reset(&data->display);
+
+			igt_output_set_pipe(data->output, data->pipe);
+			if (igt_test_constraint(&data->display)) {
+				found = true;
+				break;
+			}
+
+		}
+		igt_require_f(found, "No valid pipe/output combo found.\n");
 	}
 
 	for (int i = 0; i < ARRAY_SIZE(ccs_modifiers); i++) {
@@ -610,7 +618,6 @@ static void test_output(data_t *data, const int testnum)
 		igt_subtest_f("pipe-%s-%s-%s", kmstest_pipe_name(data->pipe),
 			      tests[testnum].testname, ccs_modifiers[i].str) {
 			int valid_tests = 0;
-			igt_require(data->output);
 
 			if (data->flags == TEST_RANDOM)
 				igt_info("Testing with seed %d\n", data->seed);
diff --git a/tests/i915/kms_cdclk.c b/tests/i915/kms_cdclk.c
index 002b631c..78abfedd 100644
--- a/tests/i915/kms_cdclk.c
+++ b/tests/i915/kms_cdclk.c
@@ -243,20 +243,17 @@ static void test_mode_transition_on_all_outputs(data_t *data)
 	int debugfs_fd = data->debugfs_fd;
 	drmModeModeInfo *mode, *mode_hi, *mode_lo;
 	igt_output_t *output;
-	int valid_outputs = 0;
 	int cdclk_ref, cdclk_new;
 	uint16_t width = 0, height = 0;
 	struct igt_fb fb;
 	igt_pipe_t *pipe;
 	igt_plane_t *plane;
-	int i = 0, j = 0;
+	enum pipe p, active_pipes[IGT_MAX_PIPES];
+	int i = 0, active_pipe_count = 0;
 
 	do_cleanup_display(display);
 	igt_display_reset(display);
 
-	for_each_connected_output(&data->display, output)
-		valid_outputs++;
-
 	for_each_connected_output(display, output) {
 		mode = igt_output_get_mode(output);
 		igt_assert(mode);
@@ -269,52 +266,59 @@ static void test_mode_transition_on_all_outputs(data_t *data)
 
 	igt_create_pattern_fb(data->drm_fd, width, height, DRM_FORMAT_XRGB8888,
 			      DRM_FORMAT_MOD_LINEAR, &fb);
-	i = 0;
+
 	for_each_connected_output(display, output) {
-		pipe = &display->pipes[i];
-		plane = igt_pipe_get_plane_type(pipe, DRM_PLANE_TYPE_PRIMARY);
+		for_each_pipe(display, p) {
+			mode = NULL;
 
-		mode = NULL;
+			igt_output_set_pipe(output, p);
+			mode = igt_output_get_mode(output);
+			igt_assert(mode);
 
-		igt_output_set_pipe(output, i);
-		mode = igt_output_get_mode(output);
-		igt_assert(mode);
+			mode_hi = get_highres_mode(output);
+			igt_require(mode_hi != NULL);
+
+			igt_output_override_mode(output, mode_hi);
+			if (!igt_test_constraint(display)) {
+				igt_output_set_pipe(output, PIPE_NONE);
+				continue;
+			}
 
-		mode_lo = get_lowres_mode(output);
+			active_pipes[active_pipe_count++] = p;
+			pipe = &display->pipes[p];
+			plane = igt_pipe_get_plane_type(pipe, DRM_PLANE_TYPE_PRIMARY);
+			igt_plane_set_fb(plane, &fb);
+			igt_fb_set_size(&fb, plane, mode_hi->hdisplay, mode_hi->vdisplay);
+			igt_plane_set_size(plane, mode_hi->hdisplay, mode_hi->vdisplay);
 
-		igt_output_override_mode(output, mode_lo);
-		igt_plane_set_fb(plane, &fb);
-		igt_fb_set_size(&fb, plane, mode_lo->hdisplay, mode_lo->vdisplay);
-		igt_plane_set_size(plane, mode_lo->hdisplay, mode_lo->vdisplay);
-		i++;
+			break;
+		}
 	}
 
 	igt_display_commit2(display, COMMIT_ATOMIC);
-	cdclk_ref = get_current_cdclk_freq(debugfs_fd);
+	cdclk_new = get_current_cdclk_freq(debugfs_fd);
 
-	j = 0;
 	for_each_connected_output(display, output) {
-		pipe = &display->pipes[j];
-		plane = igt_pipe_get_plane_type(pipe, DRM_PLANE_TYPE_PRIMARY);
+		for (i = 0; i < active_pipe_count; i++) {
+			pipe = &display->pipes[active_pipes[i]];
+			plane = igt_pipe_get_plane_type(pipe, DRM_PLANE_TYPE_PRIMARY);
 
-		mode = NULL;
+			mode = NULL;
+			igt_output_set_pipe(output, i);
+			mode = igt_output_get_mode(output);
+			igt_assert(mode);
 
-		igt_output_set_pipe(output, j);
-		mode = igt_output_get_mode(output);
-		igt_assert(mode);
-
-		mode_hi = get_highres_mode(output);
-		igt_require(mode_hi != NULL);
+			mode_lo = get_lowres_mode(output);
 
-		igt_output_override_mode(output, mode_hi);
-		igt_plane_set_fb(plane, &fb);
-		igt_fb_set_size(&fb, plane, mode_hi->hdisplay, mode_hi->vdisplay);
-		igt_plane_set_size(plane, mode_hi->hdisplay, mode_hi->vdisplay);
-		j++;
+			igt_output_override_mode(output, mode_lo);
+			igt_plane_set_fb(plane, &fb);
+			igt_fb_set_size(&fb, plane, mode_lo->hdisplay, mode_lo->vdisplay);
+			igt_plane_set_size(plane, mode_lo->hdisplay, mode_lo->vdisplay);
+		}
 	}
 
 	igt_display_commit2(display, COMMIT_ATOMIC);
-	cdclk_new = get_current_cdclk_freq(debugfs_fd);
+	cdclk_ref = get_current_cdclk_freq(debugfs_fd);
 	igt_info("CD clock frequency %d -> %d\n", cdclk_ref, cdclk_new);
 
 	/* cdclk should bump */
@@ -332,13 +336,18 @@ static void run_cdclk_test(data_t *data, uint32_t flags)
 	enum pipe pipe;
 
 	for_each_pipe_with_valid_output(display, pipe, output) {
-		igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), output->name)
-			if (igt_pipe_connector_valid(pipe, output)) {
-				if (flags & TEST_PLANESCALING)
-					test_plane_scaling(data, pipe, output);
-				if (flags & TEST_MODETRANSITION)
-					test_mode_transition(data, pipe, output);
-			}
+		igt_output_set_pipe(output, pipe);
+		if (!igt_test_constraint(display)) {
+			igt_output_set_pipe(output, PIPE_NONE);
+			continue;
+		}
+
+		igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), output->name) {
+			if (flags & TEST_PLANESCALING)
+				test_plane_scaling(data, pipe, output);
+			if (flags & TEST_MODETRANSITION)
+				test_mode_transition(data, pipe, output);
+		}
 	}
 }
 
diff --git a/tests/i915/kms_fence_pin_leak.c b/tests/i915/kms_fence_pin_leak.c
index 16eb595f..461ddfbc 100644
--- a/tests/i915/kms_fence_pin_leak.c
+++ b/tests/i915/kms_fence_pin_leak.c
@@ -124,6 +124,9 @@ static void run_single_test(data_t *data, enum pipe pipe, igt_output_t *output)
 	struct igt_fb fb[2];
 	int i;
 
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
 	igt_output_set_pipe(output, pipe);
 
 	mode = igt_output_get_mode(output);
@@ -196,6 +199,12 @@ static void run_test(data_t *data)
 	enum pipe p;
 
 	for_each_pipe_with_valid_output(display, p, output) {
+		igt_display_reset(display);
+
+		igt_output_set_pipe(output, p);
+		if (!igt_test_constraint(display))
+			continue;
+
 		run_single_test(data, p, output);
 
 		return; /* one time ought to be enough */
diff --git a/tests/i915/kms_flip_scaled_crc.c b/tests/i915/kms_flip_scaled_crc.c
index 764eb70f..bc9d8cb4 100644
--- a/tests/i915/kms_flip_scaled_crc.c
+++ b/tests/i915/kms_flip_scaled_crc.c
@@ -648,8 +648,13 @@ igt_main
 			for_each_pipe(&data.display, pipe) {
 				bool found = false;
 				for_each_valid_output_on_pipe(&data.display, pipe, output) {
+					igt_display_reset(&data.display);
+
 					modetoset = find_mode(&data, output);
-					if (modetoset) {
+					igt_output_set_pipe(output, pipe);
+					igt_output_override_mode(output, modetoset);
+
+					if (modetoset && igt_test_constraint(&data.display)) {
 						found = true;
 						igt_dynamic_f("pipe-%s-valid-mode", kmstest_pipe_name(pipe))
 							run_tests(&data, index, pipe, output, modetoset);
@@ -658,6 +663,12 @@ igt_main
 				}
 				if (!found) {
 					for_each_valid_output_on_pipe(&data.display, pipe, output) {
+						igt_display_reset(&data.display);
+
+						igt_output_set_pipe(output, pipe);
+						if (!igt_test_constraint(&data.display))
+							continue;
+
 						igt_dynamic_f("pipe-%s-default-mode", kmstest_pipe_name(pipe))
 							run_tests(&data, index, pipe, output, modetoset);
 					}
diff --git a/tests/i915/kms_flip_tiling.c b/tests/i915/kms_flip_tiling.c
index ba9ff46e..8831245f 100644
--- a/tests/i915/kms_flip_tiling.c
+++ b/tests/i915/kms_flip_tiling.c
@@ -78,6 +78,9 @@ test_flip_tiling(data_t *data, enum pipe pipe, igt_output_t *output, uint64_t mo
 	igt_crc_t reference_crc, crc;
 	int fb_id, ret;
 
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
 	memcpy(&data->old_fb, &data->fb, sizeof(data->fb));
 
 	mode = igt_output_get_mode(output);
@@ -194,8 +197,12 @@ igt_main
 		for_each_pipe_with_valid_output(&data.display, pipe, output) {
 			igt_plane_t *plane;
 
+			igt_display_reset(&data.display);
 			pipe_crc_free(&data);
+
 			igt_output_set_pipe(output, pipe);
+			if (!igt_test_constraint(&data.display))
+				continue;
 
 			plane = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
 
diff --git a/tests/i915/kms_frontbuffer_tracking.c b/tests/i915/kms_frontbuffer_tracking.c
index 9518c706..ff5fb90d 100644
--- a/tests/i915/kms_frontbuffer_tracking.c
+++ b/tests/i915/kms_frontbuffer_tracking.c
@@ -403,15 +403,23 @@ static bool find_connector(bool edp_only, bool pipe_a,
 		if (pipe_a && pipe != PIPE_A)
 			continue;
 
-		if (output == forbidden_output || pipe == forbidden_pipe)
+		if (output == forbidden_output || pipe == forbidden_pipe) {
+			igt_output_set_pipe(output, pipe);
+			igt_output_override_mode(output, connector_get_mode(output));
+
 			continue;
+		}
 
 		if (c->connector_type == DRM_MODE_CONNECTOR_eDP && opt.no_edp)
 			continue;
 
-		*ret_output = output;
-		*ret_pipe = pipe;
-		return true;
+		igt_output_set_pipe(output, pipe);
+		igt_output_override_mode(output, connector_get_mode(output));
+		if (igt_test_constraint(&drm.display)) {
+			*ret_output = output;
+			*ret_pipe = pipe;
+			return true;
+		}
 	}
 
 	return false;
diff --git a/tests/i915/kms_mmap_write_crc.c b/tests/i915/kms_mmap_write_crc.c
index a57938b5..1bc249b9 100644
--- a/tests/i915/kms_mmap_write_crc.c
+++ b/tests/i915/kms_mmap_write_crc.c
@@ -276,6 +276,12 @@ igt_main_args("n", NULL, NULL, opt_handler, NULL)
 
 	igt_subtest_with_dynamic("main") {
 		for_each_pipe_with_valid_output(&data.display, pipe, output) {
+			igt_display_reset(&data.display);
+
+			igt_output_set_pipe(output, pipe);
+			if (!igt_test_constraint(&data.display))
+				continue;
+
 			igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe),
 				      igt_output_name(output)) {
 				data.output = output;
diff --git a/tests/i915/kms_psr.c b/tests/i915/kms_psr.c
index 480e2cc7..82148e2f 100644
--- a/tests/i915/kms_psr.c
+++ b/tests/i915/kms_psr.c
@@ -102,7 +102,11 @@ static void setup_output(data_t *data)
 		if (c->connector_type != DRM_MODE_CONNECTOR_eDP)
 			continue;
 
+		igt_display_reset(display);
 		igt_output_set_pipe(output, pipe);
+		if (!igt_test_constraint(display))
+			continue;
+
 		data->crtc_id = output->config.crtc->crtc_id;
 		data->output = output;
 		data->mode = igt_output_get_mode(output);
diff --git a/tests/i915/kms_psr2_sf.c b/tests/i915/kms_psr2_sf.c
index 6612587c..920e5a4e 100644
--- a/tests/i915/kms_psr2_sf.c
+++ b/tests/i915/kms_psr2_sf.c
@@ -115,7 +115,11 @@ static void setup_output(data_t *data)
 		if (c->connector_type != DRM_MODE_CONNECTOR_eDP)
 			continue;
 
+		igt_display_reset(display);
 		igt_output_set_pipe(output, pipe);
+		if (!igt_test_constraint(display))
+			continue;
+
 		data->output = output;
 		data->mode = igt_output_get_mode(output);
 
@@ -127,6 +131,9 @@ static void display_init(data_t *data)
 {
 	igt_display_require(&data->display, data->drm_fd);
 	setup_output(data);
+
+	igt_require_f(data->output, "No available output found\n");
+	igt_require_f(data->mode, "No available mode found on %s\n", data->output->name);
 }
 
 static void display_fini(data_t *data)
diff --git a/tests/i915/kms_psr2_su.c b/tests/i915/kms_psr2_su.c
index caccf713..b8247e25 100644
--- a/tests/i915/kms_psr2_su.c
+++ b/tests/i915/kms_psr2_su.c
@@ -104,7 +104,11 @@ static void setup_output(data_t *data)
 		if (c->connector_type != DRM_MODE_CONNECTOR_eDP)
 			continue;
 
+		igt_display_reset(display);
 		igt_output_set_pipe(output, pipe);
+		if (!igt_test_constraint(display))
+			continue;
+
 		data->output = output;
 		data->mode = igt_output_get_mode(output);
 
@@ -116,6 +120,9 @@ static void display_init(data_t *data)
 {
 	igt_display_require(&data->display, data->drm_fd);
 	setup_output(data);
+
+	igt_require_f(data->output, "No available output found\n");
+	igt_require_f(data->mode, "No available mode found on %s\n", data->output->name);
 }
 
 static void display_fini(data_t *data)
diff --git a/tests/i915/kms_psr_stress_test.c b/tests/i915/kms_psr_stress_test.c
index daac41d4..c2ebaac5 100644
--- a/tests/i915/kms_psr_stress_test.c
+++ b/tests/i915/kms_psr_stress_test.c
@@ -72,7 +72,13 @@ static void setup_output(data_t *data)
 		if (c->connector_type != DRM_MODE_CONNECTOR_eDP)
 			continue;
 
+		igt_display_reset(display);
 		igt_output_set_pipe(output, pipe);
+		if (!igt_test_constraint(display)) {
+			igt_output_set_pipe(output, PIPE_NONE);
+			continue;
+		}
+
 		data->output = output;
 		data->mode = igt_output_get_mode(output);
 
@@ -374,4 +380,4 @@ igt_main
 		close(data.debugfs_fd);
 		close(data.drm_fd);
 	}
-}
\ No newline at end of file
+}
diff --git a/tests/i915/kms_pwrite_crc.c b/tests/i915/kms_pwrite_crc.c
index 584e6a19..cc24efbf 100644
--- a/tests/i915/kms_pwrite_crc.c
+++ b/tests/i915/kms_pwrite_crc.c
@@ -110,6 +110,7 @@ static void prepare_crtc(data_t *data)
 	igt_output_t *output = data->output;
 	drmModeModeInfo *mode;
 
+	igt_display_reset(display);
 	/* select the pipe we want to use */
 	igt_output_set_pipe(output, data->pipe);
 
@@ -160,6 +161,12 @@ static void run_test(data_t *data)
 	enum pipe pipe;
 
 	for_each_pipe_with_valid_output(display, pipe, output) {
+		igt_display_reset(display);
+
+		igt_output_set_pipe(output, data->pipe);
+		if (!igt_test_constraint(display))
+			continue;
+
 		data->output = output;
 		data->pipe = pipe;
 
diff --git a/tests/kms_async_flips.c b/tests/kms_async_flips.c
index 695aea74..c2410f4c 100644
--- a/tests/kms_async_flips.c
+++ b/tests/kms_async_flips.c
@@ -542,9 +542,19 @@ static void run_test(data_t *data, void (*test)(data_t *))
 {
 	igt_output_t *output;
 	enum pipe pipe;
+	igt_display_t *display = &data->display;
 
-	for_each_pipe(&data->display, pipe) {
-		for_each_valid_output_on_pipe(&data->display, pipe, output) {
+	igt_display_reset(display);
+
+	for_each_pipe(display, pipe) {
+		for_each_valid_output_on_pipe(display, pipe, output) {
+			igt_output_set_pipe(output, pipe);
+			if (!igt_test_constraint(display)) {
+				igt_output_set_pipe(output, PIPE_NONE);
+				continue;
+			}
+
+			igt_output_set_pipe(output, PIPE_NONE);
 			igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), output->name) {
 				data->output = output;
 				data->pipe = pipe;
diff --git a/tests/kms_atomic.c b/tests/kms_atomic.c
index 253829f2..fd20b91f 100644
--- a/tests/kms_atomic.c
+++ b/tests/kms_atomic.c
@@ -1265,6 +1265,9 @@ static void atomic_plane_damage(igt_pipe_t *pipe, igt_plane_t *plane, struct igt
 
 static void atomic_setup(igt_display_t *display, enum pipe pipe, igt_output_t *output, igt_plane_t *primary, struct igt_fb *fb)
 {
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
 	igt_output_set_pipe(output, pipe);
 	igt_plane_set_fb(primary, fb);
 
@@ -1293,6 +1296,7 @@ igt_main
 	igt_plane_t *primary = NULL;
 	drmModeModeInfo *mode;
 	struct igt_fb fb;
+	bool valid_config = false;
 
 	igt_fixture {
 		display.drm_fd = drm_open_driver_master(DRIVER_ANY);
@@ -1303,8 +1307,15 @@ igt_main
 		igt_require(display.is_atomic);
 		igt_display_require_output(&display);
 
-		for_each_pipe_with_valid_output(&display, pipe, output)
-			break;
+		for_each_pipe_with_valid_output(&display, pipe, output) {
+			igt_output_set_pipe(output, pipe);
+			if (igt_test_constraint(&display)) {
+				valid_config = true;
+				break;
+			}
+			igt_output_set_pipe(output, PIPE_NONE);
+		}
+		igt_require(valid_config);
 
 		pipe_obj = &display.pipes[pipe];
 		primary = igt_pipe_get_plane_type(pipe_obj, DRM_PLANE_TYPE_PRIMARY);
@@ -1342,9 +1353,12 @@ igt_main
 	igt_subtest("plane-primary-overlay-mutable-zpos") {
 		uint32_t format_primary = DRM_FORMAT_ARGB8888;
 		uint32_t format_overlay = DRM_FORMAT_ARGB1555;
+		igt_plane_t *overlay;
 
-		igt_plane_t *overlay =
-			igt_pipe_get_plane_type(pipe_obj, DRM_PLANE_TYPE_OVERLAY);
+		igt_info("Using (pipe %s + %s) to run the subtest.\n",
+			 kmstest_pipe_name(pipe), igt_output_name(output));
+
+		overlay = igt_pipe_get_plane_type(pipe_obj, DRM_PLANE_TYPE_OVERLAY);
 		igt_require(overlay);
 
 		igt_require(igt_plane_has_prop(primary, IGT_PLANE_ZPOS));
@@ -1361,6 +1375,9 @@ igt_main
 	igt_describe("Verify the reported zpos property of planes by making sure "\
 		     "only higher zpos planes cover the lower zpos ones.");
 	igt_subtest("plane-immutable-zpos") {
+		igt_info("Using (pipe %s + %s) to run the subtest.\n",
+			 kmstest_pipe_name(pipe), igt_output_name(output));
+
 		igt_output_set_pipe(output, pipe);
 		plane_immutable_zpos(&display, pipe_obj, output);
 	}
@@ -1370,6 +1387,9 @@ igt_main
 	igt_subtest("test-only") {
 		atomic_clear(&display, pipe, primary, output);
 
+		igt_info("Using (pipe %s + %s) to run the subtest.\n",
+			 kmstest_pipe_name(pipe), igt_output_name(output));
+
 		test_only(pipe_obj, primary, output);
 	}
 
diff --git a/tests/kms_atomic_interruptible.c b/tests/kms_atomic_interruptible.c
index 038cb286..c7259bc2 100644
--- a/tests/kms_atomic_interruptible.c
+++ b/tests/kms_atomic_interruptible.c
@@ -82,6 +82,9 @@ static void run_plane_test(igt_display_t *display, enum pipe pipe, igt_output_t
 	igt_plane_t *primary, *plane;
 	int block;
 
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
 	/*
 	 * Make sure we start with everything disabled to force a real modeset.
 	 * igt_display_require only sets sw state, and assumes the first test
@@ -265,6 +268,21 @@ static void run_plane_test(igt_display_t *display, enum pipe pipe, igt_output_t
 	igt_remove_fb(display->drm_fd, &fb);
 }
 
+static bool is_valid_combo(igt_display_t *display,
+			   enum pipe pipe, igt_output_t *output)
+{
+	bool ret = true;
+
+	igt_display_reset(display);
+
+	igt_output_set_pipe(output, pipe);
+	if (!igt_test_constraint(display))
+		ret = false;
+	igt_output_set_pipe(output, PIPE_NONE);
+
+	return ret;
+}
+
 igt_main
 {
 	igt_display_t display;
@@ -286,6 +304,9 @@ igt_main
 	igt_describe("Tests the interrupt properties of legacy modeset");
 	igt_subtest_with_dynamic("legacy-setmode") {
 		for_each_pipe_with_valid_output(&display, pipe, output) {
+			if (!is_valid_combo(&display, pipe, output))
+				continue;
+
 			igt_dynamic_f("%s-pipe-%s", igt_output_name(output), kmstest_pipe_name(pipe))
 				run_plane_test(&display, pipe, output, test_legacy_modeset, DRM_PLANE_TYPE_PRIMARY);
 			break;
@@ -295,6 +316,9 @@ igt_main
 	igt_describe("Tests the interrupt properties of atomic modeset");
 	igt_subtest_with_dynamic("atomic-setmode") {
 		for_each_pipe_with_valid_output(&display, pipe, output) {
+			if (!is_valid_combo(&display, pipe, output))
+				continue;
+
 			igt_dynamic_f("%s-pipe-%s", igt_output_name(output), kmstest_pipe_name(pipe))
 				run_plane_test(&display, pipe, output, test_atomic_modeset, DRM_PLANE_TYPE_PRIMARY);
 			break;
@@ -304,6 +328,9 @@ igt_main
 	igt_describe("Tests the interrupt properties for DPMS");
 	igt_subtest_with_dynamic("legacy-dpms") {
 		for_each_pipe_with_valid_output(&display, pipe, output) {
+			if (!is_valid_combo(&display, pipe, output))
+				continue;
+
 			igt_dynamic_f("%s-pipe-%s", igt_output_name(output), kmstest_pipe_name(pipe))
 				run_plane_test(&display, pipe, output, test_legacy_dpms, DRM_PLANE_TYPE_PRIMARY);
 			break;
@@ -313,6 +340,9 @@ igt_main
 	igt_describe("Tests the interrupt properties for pageflip");
 	igt_subtest_with_dynamic("legacy-pageflip") {
 		for_each_pipe_with_valid_output(&display, pipe, output) {
+			if (!is_valid_combo(&display, pipe, output))
+				continue;
+
 			igt_dynamic_f("%s-pipe-%s", igt_output_name(output), kmstest_pipe_name(pipe))
 				run_plane_test(&display, pipe, output, test_pageflip, DRM_PLANE_TYPE_PRIMARY);
 			break;
@@ -322,6 +352,9 @@ igt_main
 	igt_describe("Tests the interrupt properties for cursor");
 	igt_subtest_with_dynamic("legacy-cursor") {
 		for_each_pipe_with_valid_output(&display, pipe, output) {
+			if (!is_valid_combo(&display, pipe, output))
+				continue;
+
 			igt_dynamic_f("%s-pipe-%s", igt_output_name(output), kmstest_pipe_name(pipe))
 				run_plane_test(&display, pipe, output, test_setcursor, DRM_PLANE_TYPE_CURSOR);
 			break;
@@ -331,6 +364,9 @@ igt_main
 	igt_describe("Tests the interrupt properties for primary plane");
 	igt_subtest_with_dynamic("universal-setplane-primary") {
 		for_each_pipe_with_valid_output(&display, pipe, output) {
+			if (!is_valid_combo(&display, pipe, output))
+				continue;
+
 			igt_dynamic_f("%s-pipe-%s", igt_output_name(output), kmstest_pipe_name(pipe))
 				run_plane_test(&display, pipe, output, test_setplane, DRM_PLANE_TYPE_PRIMARY);
 			break;
@@ -340,6 +376,9 @@ igt_main
 	igt_describe("Tests the interrupt properties for cursor plane");
 	igt_subtest_with_dynamic("universal-setplane-cursor") {
 		for_each_pipe_with_valid_output(&display, pipe, output) {
+			if (!is_valid_combo(&display, pipe, output))
+				continue;
+
 			igt_dynamic_f("%s-pipe-%s", igt_output_name(output), kmstest_pipe_name(pipe))
 				run_plane_test(&display, pipe, output, test_setplane, DRM_PLANE_TYPE_CURSOR);
 			break;
diff --git a/tests/kms_atomic_transition.c b/tests/kms_atomic_transition.c
index 10b21c92..55b8d0e3 100644
--- a/tests/kms_atomic_transition.c
+++ b/tests/kms_atomic_transition.c
@@ -66,6 +66,9 @@ run_primary_test(data_t *data, enum pipe pipe, igt_output_t *output)
 	int i, ret;
 	unsigned flags = DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET;
 
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
 	igt_output_set_pipe(output, pipe);
 	primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
 
@@ -490,6 +493,9 @@ run_transition_test(data_t *data, enum pipe pipe, igt_output_t *output,
 	unsigned flags = 0;
 	int ret;
 
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
 	if (fencing)
 		prepare_fencing(data, pipe);
 	else
@@ -755,8 +761,13 @@ static unsigned set_combinations(data_t *data, unsigned mask, struct igt_fb *fb)
 			if (output->pending_pipe != PIPE_NONE)
 				continue;
 
-			mode = igt_output_get_mode(output);
-			break;
+			igt_output_set_pipe(output, pipe);
+			if (igt_test_constraint(&data->display)) {
+				mode = igt_output_get_mode(output);
+				break;
+			} else {
+				igt_output_set_pipe(output, PIPE_NONE);
+			}
 		}
 
 		if (!mode)
@@ -843,8 +854,17 @@ retry:
 				continue;
 
 			igt_output_set_pipe(output, i);
-			mode = igt_output_get_mode(output);
-			break;
+			if (igt_test_constraint(&data->display)) {
+				mode = igt_output_get_mode(output);
+
+				igt_info("(pipe %s + %s), mode:",
+					 kmstest_pipe_name(i), igt_output_name(output));
+				kmstest_dump_mode(mode);
+
+				break;
+			} else {
+				igt_output_set_pipe(output, PIPE_NONE);
+			}
 		}
 
 		if (mode) {
@@ -979,6 +999,21 @@ static void run_modeset_transition(data_t *data, int requested_outputs, bool non
 	run_modeset_tests(data, requested_outputs, nonblocking, fencing);
 }
 
+static bool is_valid_combo(igt_display_t *display,
+			   enum pipe pipe, igt_output_t *output)
+{
+	bool ret = true;
+
+	igt_display_reset(display);
+
+	igt_output_set_pipe(output, pipe);
+	if (!igt_test_constraint(display))
+		ret = false;
+	igt_output_set_pipe(output, PIPE_NONE);
+
+	return ret;
+}
+
 static int opt_handler(int opt, int opt_index, void *_data)
 {
 	data_t *data = _data;
@@ -1025,94 +1060,131 @@ igt_main_args("", long_opts, help_str, opt_handler, &data)
 
 	igt_describe("Check toggling of primary plane with vblank");
 	igt_subtest("plane-primary-toggle-with-vblank-wait") {
+		bool found = false;
+
+		pipe_count = 0;
 		for_each_pipe_with_valid_output(&data.display, pipe, output) {
 			if (pipe_count == 2 * count && !data.extended)
 				break;
 			pipe_count++;
-			run_primary_test(&data, pipe, output);
 
+			if (!is_valid_combo(&data.display, pipe, output))
+				continue;
+
+			found = true;
+			run_primary_test(&data, pipe, output);
 		}
-		pipe_count = 0;
+		igt_require(found);
 	}
 
 	igt_describe("Transition test for all plane combinations");
 	igt_subtest_with_dynamic("plane-all-transition") {
+		pipe_count = 0;
+
 		for_each_pipe_with_valid_output(&data.display, pipe, output) {
 			if (pipe_count == 2 * count && !data.extended)
 				break;
 			pipe_count++;
+
+			if (!is_valid_combo(&data.display, pipe, output))
+				continue;
+
 			igt_dynamic_f("%s-pipe-%s", igt_output_name(output), kmstest_pipe_name(pipe))
 				run_transition_test(&data, pipe, output, TRANSITION_PLANES, false, false);
 			test_cleanup(&data, pipe, output, false);
 		}
-		pipe_count = 0;
 	}
 
 	igt_describe("Transition test for all plane combinations with fencing commit");
 	igt_subtest_with_dynamic("plane-all-transition-fencing") {
+		pipe_count = 0;
+
 		for_each_pipe_with_valid_output(&data.display, pipe, output) {
 			if (pipe_count == 2 * count && !data.extended)
 				break;
 			pipe_count++;
+
+			if (!is_valid_combo(&data.display, pipe, output))
+				continue;
+
 			igt_dynamic_f("%s-pipe-%s", igt_output_name(output), kmstest_pipe_name(pipe))
 				run_transition_test(&data, pipe, output, TRANSITION_PLANES, false, true);
 			test_cleanup(&data, pipe, output, true);
 		}
-		pipe_count = 0;
 	}
 
 	igt_describe("Transition test for all plane combinations with nonblocking commit");
 	igt_subtest_with_dynamic("plane-all-transition-nonblocking") {
+		pipe_count = 0;
+
 		for_each_pipe_with_valid_output(&data.display, pipe, output) {
 			if (pipe_count == 2 * count && !data.extended)
 				break;
 			pipe_count++;
+
+			if (!is_valid_combo(&data.display, pipe, output))
+				continue;
+
 			igt_dynamic_f("%s-pipe-%s", igt_output_name(output), kmstest_pipe_name(pipe))
 				run_transition_test(&data, pipe, output, TRANSITION_PLANES, true, false);
 			test_cleanup(&data, pipe, output, false);
 		}
-		pipe_count = 0;
 	}
 
 	igt_describe("Transition test for all plane combinations with nonblocking and fencing commit");
 	igt_subtest_with_dynamic("plane-all-transition-nonblocking-fencing") {
+		pipe_count = 0;
+
 		for_each_pipe_with_valid_output(&data.display, pipe, output) {
 			if (pipe_count == 2 * count && !data.extended)
 				break;
 			pipe_count++;
+
+			if (!is_valid_combo(&data.display, pipe, output))
+				continue;
+
 			igt_dynamic_f("%s-pipe-%s", igt_output_name(output), kmstest_pipe_name(pipe))
 				run_transition_test(&data, pipe, output, TRANSITION_PLANES, true, true);
 			test_cleanup(&data, pipe, output, true);
 		}
-		pipe_count = 0;
 	}
 
 	igt_describe("Transition test with non blocking commit and make sure commit of disabled plane has "
 		       "to complete before atomic commit on that plane");
 	igt_subtest_with_dynamic("plane-use-after-nonblocking-unbind") {
+		pipe_count = 0;
+
 		for_each_pipe_with_valid_output(&data.display, pipe, output) {
 			if (pipe_count == 2 * count && !data.extended)
 				break;
 			pipe_count++;
+
+			if (!is_valid_combo(&data.display, pipe, output))
+				continue;
+
 			igt_dynamic_f("%s-pipe-%s", igt_output_name(output), kmstest_pipe_name(pipe))
 				run_transition_test(&data, pipe, output, TRANSITION_AFTER_FREE, true, false);
 			test_cleanup(&data, pipe, output, false);
 		}
-		pipe_count = 0;
 	}
 
 	igt_describe("Transition test with non blocking and fencing commit and make sure commit of "
 		       "disabled plane has to complete before atomic commit on that plane");
 	igt_subtest_with_dynamic("plane-use-after-nonblocking-unbind-fencing") {
+		pipe_count = 0;
+
 		for_each_pipe_with_valid_output(&data.display, pipe, output) {
 			if (pipe_count == 2 * count && !data.extended)
 				break;
 			pipe_count++;
+
+			if (!is_valid_combo(&data.display, pipe, output))
+				continue;
+
 			igt_dynamic_f("%s-pipe-%s", igt_output_name(output), kmstest_pipe_name(pipe))
 				run_transition_test(&data, pipe, output, TRANSITION_AFTER_FREE, true, true);
 			test_cleanup(&data, pipe, output, true);
 		}
-		pipe_count = 0;
 	}
 
 	/*
@@ -1122,78 +1194,103 @@ igt_main_args("", long_opts, help_str, opt_handler, &data)
 	 */
 	igt_describe("Modeset test for all plane combinations");
 	igt_subtest_with_dynamic("plane-all-modeset-transition") {
+		pipe_count = 0;
+
 		for_each_pipe_with_valid_output(&data.display, pipe, output) {
 			if (pipe_count == 2 * count && !data.extended)
 				break;
 			pipe_count++;
+
 			if (output_is_internal_panel(output))
 				continue;
 
+			if (!is_valid_combo(&data.display, pipe, output))
+				continue;
+
 			igt_dynamic_f("%s-pipe-%s", igt_output_name(output), kmstest_pipe_name(pipe))
 				run_transition_test(&data, pipe, output, TRANSITION_MODESET, false, false);
 			test_cleanup(&data, pipe, output, false);
 		}
-		pipe_count = 0;
 	}
 
 	igt_describe("Modeset test for all plane combinations with fencing commit");
 	igt_subtest_with_dynamic("plane-all-modeset-transition-fencing") {
+		pipe_count = 0;
+
 		for_each_pipe_with_valid_output(&data.display, pipe, output) {
 			if (pipe_count == 2 * count && !data.extended)
 				break;
 			pipe_count++;
+
 			if (output_is_internal_panel(output))
 				continue;
 
+			if (!is_valid_combo(&data.display, pipe, output))
+				continue;
+
 			igt_dynamic_f("%s-pipe-%s", igt_output_name(output), kmstest_pipe_name(pipe))
 				run_transition_test(&data, pipe, output, TRANSITION_MODESET, false, true);
 			test_cleanup(&data, pipe, output, true);
 		}
-		pipe_count = 0;
 	}
 
 	igt_describe("Modeset test for all plane combinations on internal panels");
 	igt_subtest_with_dynamic("plane-all-modeset-transition-internal-panels") {
+		pipe_count = 0;
+
 		for_each_pipe_with_valid_output(&data.display, pipe, output) {
 			if (pipe_count == 2 * count && !data.extended)
 				break;
 			pipe_count++;
+
 			if (!output_is_internal_panel(output))
 				continue;
 
+			if (!is_valid_combo(&data.display, pipe, output))
+				continue;
+
 			igt_dynamic_f("%s-pipe-%s", igt_output_name(output), kmstest_pipe_name(pipe))
 				run_transition_test(&data, pipe, output, TRANSITION_MODESET_FAST, false, false);
 			test_cleanup(&data, pipe, output, false);
 		}
-		pipe_count = 0;
 	}
 
 	igt_describe("Modeset test for all plane combinations on internal panels with fencing commit");
 	igt_subtest_with_dynamic("plane-all-modeset-transition-fencing-internal-panels") {
+		pipe_count = 0;
+
 		for_each_pipe_with_valid_output(&data.display, pipe, output) {
 			if (pipe_count == 2 * count && !data.extended)
 				break;
 			pipe_count++;
+
 			if (!output_is_internal_panel(output))
 				continue;
 
+			if (!is_valid_combo(&data.display, pipe, output))
+				continue;
+
 			igt_dynamic_f("%s-pipe-%s", igt_output_name(output), kmstest_pipe_name(pipe))
 				run_transition_test(&data, pipe, output, TRANSITION_MODESET_FAST, false, true);
 			test_cleanup(&data, pipe, output, true);
 		}
-		pipe_count = 0;
 	}
 
 	igt_describe("Check toggling and modeset transition on plane");
 	igt_subtest("plane-toggle-modeset-transition") {
+		pipe_count = 0;
+
 		for_each_pipe_with_valid_output(&data.display, pipe, output) {
 			if (pipe_count == 2 * count && !data.extended)
 				break;
 			pipe_count++;
+
+			if (!is_valid_combo(&data.display, pipe, output))
+				continue;
+
 			run_transition_test(&data, pipe, output, TRANSITION_MODESET_DISABLE, false, false);
 			test_cleanup(&data, pipe, output, false);
 		}
-		pipe_count = 0;
 	}
 
 	igt_describe("Modeset transition tests for combinations of crtc enabled");
diff --git a/tests/kms_color.c b/tests/kms_color.c
index c202547e..9b60f1e8 100644
--- a/tests/kms_color.c
+++ b/tests/kms_color.c
@@ -722,9 +722,13 @@ run_gamma_degamma_tests_for_pipe(data_t *data, enum pipe p,
 	data->drm_format = DRM_FORMAT_XRGB8888;
 	data->mode = igt_output_get_mode(data->output);
 
+	if (!test_constraint(data, p))
+		goto out;
+
 	igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(p), data->output->name)
 		igt_assert(test_t(data, data->primary));
 
+out:
 	test_cleanup(data);
 }
 
@@ -752,6 +756,9 @@ run_ctm_tests_for_pipe(data_t *data, enum pipe p,
 	data->drm_format = DRM_FORMAT_XRGB8888;
 	data->mode = igt_output_get_mode(data->output);
 
+	if (!test_constraint(data, p))
+		goto out;
+
 	igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(p), data->output->name) {
 		bool success = false;
 		int i;
@@ -780,6 +787,7 @@ run_ctm_tests_for_pipe(data_t *data, enum pipe p,
 		igt_assert(success);
 	}
 
+out:
 	test_cleanup(data);
 }
 
@@ -820,7 +828,6 @@ run_deep_color_tests_for_pipe(data_t *data, enum pipe p)
 		igt_display_reset(&data->display);
 		igt_output_set_prop_value(output, IGT_CONNECTOR_MAX_BPC, 10);
 		igt_output_set_pipe(output, p);
-		igt_display_commit_atomic(&data->display, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
 
 		if (is_i915_device(data->drm_fd) &&
 		    !igt_max_bpc_constraint(&data->display, p, output, 10))
diff --git a/tests/kms_color_helper.c b/tests/kms_color_helper.c
index 55f3e409..a5b45c80 100644
--- a/tests/kms_color_helper.c
+++ b/tests/kms_color_helper.c
@@ -24,6 +24,18 @@
 
 #include "kms_color_helper.h"
 
+bool test_constraint(data_t *data, enum pipe pipe)
+{
+	bool ret = true;
+
+	igt_output_set_pipe(data->output, pipe);
+	if (!igt_test_constraint(&data->display))
+		ret = false;
+	igt_output_set_pipe(data->output, PIPE_NONE);
+
+	return ret;
+}
+
 bool
 panel_supports_deep_color(int drm_fd, char *output_name)
 {
diff --git a/tests/kms_color_helper.h b/tests/kms_color_helper.h
index f0ae30e3..576c2416 100644
--- a/tests/kms_color_helper.h
+++ b/tests/kms_color_helper.h
@@ -69,6 +69,7 @@ typedef struct {
 	color_t coeffs[];
 } gamma_lut_t;
 
+bool test_constraint(data_t *data, enum pipe pipe);
 bool panel_supports_deep_color(int fd, char *output_name);
 uint64_t get_max_bpc(igt_output_t *output);
 void paint_gradient_rectangles(data_t *data,
diff --git a/tests/kms_concurrent.c b/tests/kms_concurrent.c
index 6f8ffd4a..a6b9189e 100644
--- a/tests/kms_concurrent.c
+++ b/tests/kms_concurrent.c
@@ -330,9 +330,17 @@ run_tests_for_pipe(data_t *data, enum pipe pipe)
 	igt_describe("Test atomic mode setting concurrently with multiple planes and screen "
 		     "resolution.");
 	igt_subtest_with_dynamic_f("pipe-%s", kmstest_pipe_name(pipe)) {
-		for_each_valid_output_on_pipe(&data->display, pipe, output)
+		for_each_valid_output_on_pipe(&data->display, pipe, output) {
+			igt_display_reset(&data->display);
+
+			igt_output_set_pipe(output, pipe);
+			if (!igt_test_constraint(&data->display))
+				continue;
+
+			igt_output_set_pipe(output, PIPE_NONE);
 			igt_dynamic_f("%s", igt_output_name(output))
 				run_test(data, pipe, output);
+		}
 	}
 }
 
diff --git a/tests/kms_content_protection.c b/tests/kms_content_protection.c
index 3041f1cd..9134e1ca 100644
--- a/tests/kms_content_protection.c
+++ b/tests/kms_content_protection.c
@@ -338,6 +338,15 @@ static void test_content_protection_on_output(igt_output_t *output,
 		if (!igt_pipe_is_free(display, pipe))
 			continue;
 
+		igt_output_set_pipe(output, pipe);
+		if (!igt_test_constraint(display)) {
+			igt_output_set_pipe(output, PIPE_NONE);
+			continue;
+		}
+
+		igt_info("Using (pipe %s + %s) to run the subtest.\n",
+			 kmstest_pipe_name(pipe), igt_output_name(output));
+
 		modeset_with_fb(pipe, output, s);
 		test_cp_enable_with_retry(output, s, 3, content_type, false,
 					  false);
@@ -610,6 +619,14 @@ test_content_protection_mst(int content_type)
 		igt_assert_f(igt_pipe_connector_valid(pipe, output), "Output-pipe combination invalid\n");
 
 		igt_output_set_pipe(output, pipe);
+		if (!igt_test_constraint(display)){
+			igt_output_set_pipe(output, PIPE_NONE);
+			continue;
+		}
+
+		igt_info("Using (pipe %s + %s) to run the subtest.\n",
+			 kmstest_pipe_name(pipe), igt_output_name(output));
+
 		prepare_modeset_on_mst_output(output);
 		mst_output[dp_mst_outputs++] = output;
 
diff --git a/tests/kms_cursor_crc.c b/tests/kms_cursor_crc.c
index 14d4c4ca..65004a84 100644
--- a/tests/kms_cursor_crc.c
+++ b/tests/kms_cursor_crc.c
@@ -687,6 +687,21 @@ static void test_rapid_movement(data_t *data)
 	igt_assert_lt(usec, 0.9 * 400 * 1000000 / data->refresh);
 }
 
+static bool is_valid_combo(data_t *data, enum pipe pipe)
+{
+	bool ret = true;
+	igt_display_t *display = &data->display;
+
+	igt_display_reset(display);
+
+	igt_output_set_pipe(data->output, pipe);
+	if (!igt_test_constraint(display))
+		ret = false;
+	igt_output_set_pipe(data->output, PIPE_NONE);
+
+	return ret;
+}
+
 static void run_size_tests(data_t *data, void (*testfunc)(data_t *),
 			   int w, int h)
 {
@@ -695,22 +710,21 @@ static void run_size_tests(data_t *data, void (*testfunc)(data_t *),
 
 	snprintf(name, sizeof(name), "%dx%d", w, h);
 
-	create_cursor_fb(data, w, h);
-	if (require_cursor_size(data, w, h)) {
-		igt_debug("Cursor size %dx%d not supported by driver\n", w, h);
-
-		igt_remove_fb(data->drm_fd, &data->fb);
-		return;
-	}
-
 	for_each_pipe(&data->display, pipe) {
 		data->pipe = pipe;
+
+		if (!is_valid_combo(data, pipe))
+			continue;
+
+		if (require_cursor_size(data, w, h)) {
+			igt_debug("Cursor size %dx%d not supported by driver\n", w, h);
+			continue;
+		}
+
 		igt_dynamic_f("pipe-%s-%s-%s",
 			      kmstest_pipe_name(pipe), data->output->name, name)
 			run_test(data, testfunc, w, h);
 	}
-
-	igt_remove_fb(data->drm_fd, &data->fb);
 }
 
 static void run_tests_on_pipe(data_t *data)
@@ -749,6 +763,9 @@ static void run_tests_on_pipe(data_t *data)
 		for_each_pipe(&data->display, pipe) {
 			data->pipe = pipe;
 
+			if (!is_valid_combo(data, pipe))
+				continue;
+
 			igt_dynamic_f("pipe-%s-%s",
 				      kmstest_pipe_name(pipe),
 				      data->output->name)
@@ -763,6 +780,9 @@ static void run_tests_on_pipe(data_t *data)
 		for_each_pipe(&data->display, pipe) {
 			data->pipe = pipe;
 
+			if (!is_valid_combo(data, pipe))
+				continue;
+
 			igt_dynamic_f("pipe-%s-%s",
 				      kmstest_pipe_name(pipe),
 				      data->output->name)
@@ -777,6 +797,9 @@ static void run_tests_on_pipe(data_t *data)
 		for_each_pipe(&data->display, pipe) {
 			data->pipe = pipe;
 
+			if (!is_valid_combo(data, pipe))
+				continue;
+
 			igt_dynamic_f("pipe-%s-%s",
 				      kmstest_pipe_name(pipe),
 				      data->output->name)
@@ -795,6 +818,9 @@ static void run_tests_on_pipe(data_t *data)
 			data->pipe = pipe;
 			data->flags = TEST_DPMS;
 
+			if (!is_valid_combo(data, pipe))
+				continue;
+
 			if (require_cursor_size(data, data->cursor_max_w, data->cursor_max_h)) {
 				igt_debug("Cursor size %dx%d not supported by driver\n",
 					  data->cursor_max_w, data->cursor_max_h);
@@ -816,6 +842,9 @@ static void run_tests_on_pipe(data_t *data)
 			data->pipe = pipe;
 			data->flags = TEST_SUSPEND;
 
+			if (!is_valid_combo(data, pipe))
+				continue;
+
 			if (require_cursor_size(data, data->cursor_max_w, data->cursor_max_h)) {
 				igt_debug("Cursor size %dx%d not supported by driver\n",
 					  data->cursor_max_w, data->cursor_max_h);
diff --git a/tests/kms_cursor_edge_walk.c b/tests/kms_cursor_edge_walk.c
index b75fc216..3e5832a9 100644
--- a/tests/kms_cursor_edge_walk.c
+++ b/tests/kms_cursor_edge_walk.c
@@ -351,6 +351,12 @@ igt_main_args("", long_opts, help_str, opt_handler, &data)
 						data.curh = data.curw;
 						igt_require(data.curw <= max_curw && data.curh <= max_curh);
 
+						igt_display_reset(&data.display);
+						igt_output_set_pipe(data.output, data.pipe);
+						if (!igt_test_constraint(&data.display))
+							continue;
+
+						igt_output_set_pipe(data.output, PIPE_NONE);
 						igt_dynamic_f("pipe-%s-%s-%dx%d",
 							      kmstest_pipe_name(data.pipe),
 							      data.output->name,
diff --git a/tests/kms_cursor_legacy.c b/tests/kms_cursor_legacy.c
index 1b697667..e8361170 100644
--- a/tests/kms_cursor_legacy.c
+++ b/tests/kms_cursor_legacy.c
@@ -177,31 +177,21 @@ static void stress(igt_display_t *display,
 	munmap(results, PAGE_SIZE);
 }
 
-static igt_output_t *set_fb_on_crtc(igt_display_t *display, enum pipe pipe, struct igt_fb *fb_info)
+static void set_fb_on_crtc(igt_display_t *display, enum pipe pipe,
+			   igt_output_t *output, struct igt_fb *fb_info)
 {
-	igt_output_t *output;
-
-	for_each_valid_output_on_pipe(display, pipe, output) {
-		drmModeModeInfoPtr mode;
-		igt_plane_t *primary;
-
-		if (output->pending_pipe != PIPE_NONE)
-			continue;
-
-		igt_output_set_pipe(output, pipe);
-		mode = igt_output_get_mode(output);
+	drmModeModeInfoPtr mode;
+	igt_plane_t *primary;
 
-		igt_create_pattern_fb(display->drm_fd,
-			      mode->hdisplay, mode->vdisplay,
-			      DRM_FORMAT_XRGB8888, I915_TILING_NONE, fb_info);
+	igt_output_set_pipe(output, pipe);
+	mode = igt_output_get_mode(output);
 
-		primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
-		igt_plane_set_fb(primary, fb_info);
+	igt_create_pattern_fb(display->drm_fd,
+		      mode->hdisplay, mode->vdisplay,
+		      DRM_FORMAT_XRGB8888, I915_TILING_NONE, fb_info);
 
-		return output;
-	}
-
-	return NULL;
+	primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
+	igt_plane_set_fb(primary, fb_info);
 }
 
 static	igt_plane_t
@@ -236,36 +226,44 @@ static void populate_cursor_args(igt_display_t *display, enum pipe pipe,
 	arg[1] = *arg;
 }
 
-static enum pipe find_connected_pipe(igt_display_t *display, bool second)
+static enum pipe
+find_connected_pipe(igt_display_t *display, bool second, igt_output_t **output)
 {
-	enum pipe pipe, first = PIPE_NONE;
-	igt_output_t *output;
-	igt_output_t *first_output = NULL;
+	enum pipe pipe;
+	bool first_output = false;
 	bool found = false;
 
 	if (!second) {
 		igt_pipe_crc_free(pipe_crc);
 		pipe_crc = NULL;
-
-		/* Clear display, events will be eaten by commit.. */
-		igt_display_reset(display);
 	}
 
-	for_each_pipe_with_valid_output(display, pipe, output) {
-		if (first == pipe || output == first_output)
-			continue;
+	/* Clear display, events will be eaten by commit.. */
+	igt_display_reset(display);
 
-		if (second) {
-			first = pipe;
-			first_output = output;
-			second = false;
-			continue;
-		}
+	for_each_pipe(display, pipe) {
+		for_each_valid_output_on_pipe(display, pipe, *output) {
+			if((*output)->pending_pipe != PIPE_NONE)
+				continue;
 
-		found = true;
-		break;
+			igt_output_set_pipe(*output, pipe);
+			if (igt_test_constraint(display)) {
+				found = true;
+
+				if (second) {
+					first_output = true;
+					second = false;
+					found = false;
+				}
+				break;
+			}
+			igt_output_set_pipe(*output, PIPE_NONE);
+		}
+		if (found)
+			break;
 	}
 
+	igt_display_reset(display);
 	if (first_output)
 		igt_require_f(found, "No second valid output found\n");
 	else
@@ -429,10 +427,9 @@ static void flip(igt_display_t *display,
 	results = mmap(NULL, PAGE_SIZE, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
 	igt_assert(results != MAP_FAILED);
 
-	igt_display_reset(display);
-
-	flip_pipe = find_connected_pipe(display, !!flip_pipe);
-	cursor_pipe = find_connected_pipe(display, !!cursor_pipe);
+	flip_pipe = find_connected_pipe(display, !!flip_pipe, &output);
+	cursor_pipe = find_connected_pipe(display, !!cursor_pipe, &output2);
+	igt_skip_on(!output || !output2);
 
 	igt_info("Using pipe %s for page flip, pipe %s for cursor\n",
 		  kmstest_pipe_name(flip_pipe), kmstest_pipe_name(cursor_pipe));
@@ -446,15 +443,15 @@ static void flip(igt_display_t *display,
 					DRM_PLANE_TYPE_OVERLAY));
 	}
 
-	igt_require((output = set_fb_on_crtc(display, flip_pipe, &fb_info)));
+	set_fb_on_crtc(display, flip_pipe, output, &fb_info);
 	if (flip_pipe != cursor_pipe) {
-		igt_require((output2 = set_fb_on_crtc(display, cursor_pipe, &fb_info2)));
+		set_fb_on_crtc(display, cursor_pipe, output2, &fb_info2);
 
 		if (try_commit(display)) {
 			override_output_modes(display, output, output2);
 
-			igt_require((output = set_fb_on_crtc(display, flip_pipe, &fb_info)));
-			igt_require((output2 = set_fb_on_crtc(display, cursor_pipe, &fb_info2)));
+			set_fb_on_crtc(display, flip_pipe, output, &fb_info);
+			set_fb_on_crtc(display, cursor_pipe, output2, &fb_info2);
 		}
 	}
 
@@ -546,7 +543,7 @@ static void basic_flip_cursor(igt_display_t *display,
 	struct drm_event_vblank vbl;
 	struct igt_fb fb_info, cursor_fb, cursor_fb2, argb_fb;
 	unsigned vblank_start;
-	enum pipe pipe = find_connected_pipe(display, false);
+	enum pipe pipe;
 	uint64_t ahnd = 0;
 	igt_spin_t *spin;
 	int i, miss1 = 0, miss2 = 0, delta;
@@ -562,7 +559,13 @@ static void basic_flip_cursor(igt_display_t *display,
 	if (mode >= flip_test_atomic)
 		igt_require(display->is_atomic);
 
-	igt_require((output = set_fb_on_crtc(display, pipe, &fb_info)));
+	pipe = find_connected_pipe(display, false, &output);
+	igt_require(output);
+
+	igt_info("Using pipe %s & %s\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
+	set_fb_on_crtc(display, pipe, output, &fb_info);
 
 	igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
 	cursor = set_cursor_on_pipe(display, pipe, &cursor_fb);
@@ -717,7 +720,7 @@ static void flip_vs_cursor(igt_display_t *display, enum flip_test mode, int nloo
 	struct igt_fb fb_info, cursor_fb, cursor_fb2, argb_fb;
 	unsigned vblank_start;
 	int target, cpu;
-	enum pipe pipe = find_connected_pipe(display, false);
+	enum pipe pipe;
 	volatile unsigned long *shared;
 	cpu_set_t mask, oldmask;
 	igt_output_t *output;
@@ -726,7 +729,13 @@ static void flip_vs_cursor(igt_display_t *display, enum flip_test mode, int nloo
 	if (mode >= flip_test_atomic)
 		igt_require(display->is_atomic);
 
-	igt_require((output = set_fb_on_crtc(display, pipe, &fb_info)));
+	pipe = find_connected_pipe(display, false, &output);
+	igt_require(output);
+
+	igt_info("Using pipe %s & %s\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
+	set_fb_on_crtc(display, pipe, output, &fb_info);
 
 	igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
 	cursor = set_cursor_on_pipe(display, pipe, &cursor_fb);
@@ -843,12 +852,18 @@ static void nonblocking_modeset_vs_cursor(igt_display_t *display, int loops)
 {
 	struct igt_fb fb_info, cursor_fb;
 	igt_output_t *output;
-	enum pipe pipe = find_connected_pipe(display, false);
+	enum pipe pipe;
 	struct drm_mode_cursor arg[2];
 	igt_plane_t *primary, *cursor = NULL;
 
 	igt_require(display->is_atomic);
-	igt_require((output = set_fb_on_crtc(display, pipe, &fb_info)));
+	pipe = find_connected_pipe(display, false, &output);
+	igt_require(output);
+
+	igt_info("Using pipe %s & %s\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
+	set_fb_on_crtc(display, pipe, output, &fb_info);
 	primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
 	igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
 	cursor = set_cursor_on_pipe(display, pipe, &cursor_fb);
@@ -935,8 +950,7 @@ static void two_screens_flip_vs_cursor(igt_display_t *display, int nloops, bool
 {
 	struct drm_mode_cursor arg1[2], arg2[2];
 	struct igt_fb fb_info, fb2_info, cursor_fb;
-	enum pipe pipe = find_connected_pipe(display, false);
-	enum pipe pipe2 = find_connected_pipe(display, true);
+	enum pipe pipe, pipe2;
 	igt_output_t *output, *output2;
 	bool enabled = false;
 	volatile unsigned long *shared;
@@ -952,22 +966,28 @@ static void two_screens_flip_vs_cursor(igt_display_t *display, int nloops, bool
 		igt_require(drmGetCap(display->drm_fd, DRM_CAP_CRTC_IN_VBLANK_EVENT, &val) == 0);
 	}
 
+	if (atomic)
+		igt_require(display->is_atomic);
+
 	shared = mmap(NULL, PAGE_SIZE, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
 	igt_assert(shared != MAP_FAILED);
 
-	igt_fail_on(modeset && !atomic);
+	pipe = find_connected_pipe(display, false, &output);
+	pipe2 = find_connected_pipe(display, true, &output2);
+	igt_skip_on(!output || !output2);
 
-	if (atomic)
-		igt_require(display->is_atomic);
+	igt_info("Using pipe %s & %s and pipe %s & %s\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output),
+		 kmstest_pipe_name(pipe2), igt_output_name(output2));
 
-	igt_require((output = set_fb_on_crtc(display, pipe, &fb_info)));
-	igt_require((output2 = set_fb_on_crtc(display, pipe2, &fb2_info)));
+	set_fb_on_crtc(display, pipe, output, &fb_info);
+	set_fb_on_crtc(display, pipe2, output2, &fb2_info);
 
 	if (try_commit(display)) {
 		override_output_modes(display, output, output2);
 
-		igt_require((output = set_fb_on_crtc(display, pipe, &fb_info)));
-		igt_require((output2 = set_fb_on_crtc(display, pipe2, &fb2_info)));
+		set_fb_on_crtc(display, pipe, output, &fb_info);
+		set_fb_on_crtc(display, pipe2, output2, &fb2_info);
 	}
 
 	igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
@@ -1120,7 +1140,7 @@ static void cursor_vs_flip(igt_display_t *display, enum flip_test mode, int nloo
 	unsigned vblank_start, vblank_last;
 	volatile unsigned long *shared;
 	long target;
-	enum pipe pipe = find_connected_pipe(display, false);
+	enum pipe pipe;
 	igt_output_t *output;
 	uint32_t vrefresh;
 	int fail_count;
@@ -1132,7 +1152,13 @@ static void cursor_vs_flip(igt_display_t *display, enum flip_test mode, int nloo
 	shared = mmap(NULL, PAGE_SIZE, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
 	igt_assert(shared != MAP_FAILED);
 
-	igt_require((output = set_fb_on_crtc(display, pipe, &fb_info)));
+	pipe = find_connected_pipe(display, false, &output);
+	igt_require(output);
+
+	igt_info("Using pipe %s & %s\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
+	set_fb_on_crtc(display, pipe, output, &fb_info);
 	vrefresh = igt_output_get_mode(output)->vrefresh;
 
 	igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
@@ -1224,10 +1250,7 @@ static void two_screens_cursor_vs_flip(igt_display_t *display, int nloops, bool
 	struct igt_fb fb_info[2], cursor_fb;
 	volatile unsigned long *shared;
 	int target[2];
-	enum pipe pipe[2] = {
-		find_connected_pipe(display, false),
-		find_connected_pipe(display, true)
-	};
+	enum pipe pipe[2];
 	igt_output_t *outputs[2];
 	igt_plane_t *cursors[2];
 
@@ -1237,14 +1260,22 @@ static void two_screens_cursor_vs_flip(igt_display_t *display, int nloops, bool
 	if (atomic)
 		igt_require(display->is_atomic);
 
-	igt_require((outputs[0] = set_fb_on_crtc(display, pipe[0], &fb_info[0])));
-	igt_require((outputs[1] = set_fb_on_crtc(display, pipe[1], &fb_info[1])));
+	pipe[0] = find_connected_pipe(display, false, &outputs[0]);
+	pipe[1] = find_connected_pipe(display, true, &outputs[1]);
+	igt_skip_on(!outputs[0] || !outputs[1]);
+
+	igt_info("Using pipe %s & %s and pipe %s & %s\n",
+		 kmstest_pipe_name(pipe[0]), igt_output_name(outputs[0]),
+		 kmstest_pipe_name(pipe[1]), igt_output_name(outputs[1]));
+
+	set_fb_on_crtc(display, pipe[0], outputs[0], &fb_info[0]);
+	set_fb_on_crtc(display, pipe[1], outputs[1], &fb_info[1]);
 
 	if (try_commit(display)) {
 		override_output_modes(display, outputs[0], outputs[1]);
 
-		igt_require((outputs[0] = set_fb_on_crtc(display, pipe[0], &fb_info[0])));
-		igt_require((outputs[1] = set_fb_on_crtc(display, pipe[1], &fb_info[1])));
+		set_fb_on_crtc(display, pipe[0], outputs[0], &fb_info[0]);
+		set_fb_on_crtc(display, pipe[1], outputs[1], &fb_info[1]);
 	}
 
 	igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
@@ -1345,7 +1376,7 @@ static void flip_vs_cursor_crc(igt_display_t *display, bool atomic)
 	struct drm_event_vblank vbl;
 	struct igt_fb fb_info, cursor_fb;
 	unsigned vblank_start;
-	enum pipe pipe = find_connected_pipe(display, false);
+	enum pipe pipe;
 	igt_crc_t crcs[3];
 	igt_output_t *output;
 	igt_plane_t *cursor;
@@ -1353,7 +1384,13 @@ static void flip_vs_cursor_crc(igt_display_t *display, bool atomic)
 	if (atomic)
 		igt_require(display->is_atomic);
 
-	igt_require((output = set_fb_on_crtc(display, pipe, &fb_info)));
+	pipe = find_connected_pipe(display, false, &output);
+	igt_require(output);
+
+	igt_info("Using pipe %s & %s\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
+	set_fb_on_crtc(display, pipe, output, &fb_info);
 
 	igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
 	populate_cursor_args(display, pipe, arg, &cursor_fb);
@@ -1409,9 +1446,9 @@ static void flip_vs_cursor_busy_crc(igt_display_t *display, bool atomic)
 	struct drm_event_vblank vbl;
 	struct igt_fb fb_info[2], cursor_fb;
 	unsigned vblank_start;
-	enum pipe pipe = find_connected_pipe(display, false);
-	igt_pipe_t *pipe_connected = &display->pipes[pipe];
-	igt_plane_t *plane_primary = igt_pipe_get_plane_type(pipe_connected, DRM_PLANE_TYPE_PRIMARY);
+	enum pipe pipe;
+	igt_pipe_t *pipe_connected;
+	igt_plane_t *plane_primary;
 	igt_crc_t crcs[2], test_crc;
 	uint64_t ahnd;
 	igt_output_t *output;
@@ -1423,7 +1460,16 @@ static void flip_vs_cursor_busy_crc(igt_display_t *display, bool atomic)
 	if (atomic)
 		igt_require(display->is_atomic);
 
-	igt_require((output = set_fb_on_crtc(display, pipe, &fb_info[0])));
+	pipe = find_connected_pipe(display, false, &output);
+	igt_require(output);
+
+	igt_info("Using pipe %s & %s\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
+	pipe_connected = &display->pipes[pipe];
+	plane_primary = igt_pipe_get_plane_type(pipe_connected, DRM_PLANE_TYPE_PRIMARY);
+
+	set_fb_on_crtc(display, pipe, output, &fb_info[0]);
 	igt_create_color_pattern_fb(display->drm_fd, fb_info[0].width, fb_info[0].height,
 				    DRM_FORMAT_XRGB8888, I915_FORMAT_MOD_X_TILED, .1, .1, .1, &fb_info[1]);
 
diff --git a/tests/kms_display_modes.c b/tests/kms_display_modes.c
index eff30cbb..816efcf8 100644
--- a/tests/kms_display_modes.c
+++ b/tests/kms_display_modes.c
@@ -34,31 +34,26 @@ typedef struct {
 	int n_pipes;
 } data_t;
 
-static void run_extendedmode_basic(data_t *data, int pipe1, int pipe2)
+static void run_extendedmode_basic(data_t *data,
+				   enum pipe pipe1, igt_output_t *output1,
+				   enum pipe pipe2, igt_output_t *output2)
 {
 	struct igt_fb fb, fbs[2];
 	drmModeModeInfo *mode[2];
-	igt_output_t *output, *extended_output[2];
 	igt_display_t *display = &data->display;
 	igt_plane_t *plane[2];
 	igt_pipe_crc_t *pipe_crc[2] = { 0 };
 	igt_crc_t ref_crc[2], crc[2];
-	int count = 0, width, height;
+	int width, height;
 	cairo_t *cr;
 
-	for_each_connected_output(display, output) {
-		extended_output[count] = output;
-		count++;
+	igt_display_reset(display);
 
-		if (count > 1)
-			break;
-	}
-
-	igt_output_set_pipe(extended_output[0], pipe1);
-	igt_output_set_pipe(extended_output[1], pipe2);
+	igt_output_set_pipe(output1, pipe1);
+	igt_output_set_pipe(output2, pipe2);
 
-	mode[0] = igt_output_get_mode(extended_output[0]);
-	mode[1] = igt_output_get_mode(extended_output[1]);
+	mode[0] = igt_output_get_mode(output1);
+	mode[1] = igt_output_get_mode(output2);
 
 	pipe_crc[0] = igt_pipe_crc_new(data->drm_fd, pipe1, INTEL_PIPE_CRC_SOURCE_AUTO);
 	pipe_crc[1] = igt_pipe_crc_new(data->drm_fd, pipe2, INTEL_PIPE_CRC_SOURCE_AUTO);
@@ -115,8 +110,8 @@ static void run_extendedmode_basic(data_t *data, int pipe1, int pipe2)
 	igt_pipe_crc_free(pipe_crc[0]);
 	igt_pipe_crc_free(pipe_crc[1]);
 
-	igt_output_set_pipe(extended_output[0], PIPE_NONE);
-	igt_output_set_pipe(extended_output[1], PIPE_NONE);
+	igt_output_set_pipe(output1, PIPE_NONE);
+	igt_output_set_pipe(output2, PIPE_NONE);
 
 	igt_plane_set_fb(igt_pipe_get_plane_type(&display->pipes[pipe1],
 			  DRM_PLANE_TYPE_PRIMARY), NULL);
@@ -129,43 +124,68 @@ static void run_extendedmode_basic(data_t *data, int pipe1, int pipe2)
 	igt_assert_crc_equal(&crc[1], &ref_crc[1]);
 }
 
+#define for_each_connected_output_local(display, output)		\
+	for (int j__ = 0;  assert(igt_can_fail()), j__ < (display)->n_outputs; j__++)	\
+		for_each_if ((((output) = &(display)->outputs[j__]), \
+			      igt_output_is_connected((output))))
+
+#define for_each_valid_output_on_pipe_local(display, pipe, output) \
+	for_each_connected_output_local((display), (output)) \
+		for_each_if (igt_pipe_connector_valid((pipe), (output)))
+
+static void run_extendedmode_test(data_t *data) {
+	enum pipe pipe1, pipe2;
+	igt_output_t *output1, *output2;
+	igt_display_t *display = &data->display;
+
+	igt_display_reset(display);
+
+	for_each_pipe(display, pipe1) {
+		for_each_valid_output_on_pipe(display, pipe1, output1) {
+			for_each_pipe(display, pipe2) {
+				if (pipe1 == pipe2)
+					continue;
+
+				for_each_valid_output_on_pipe_local(display, pipe2, output2) {
+					if (output1 == output2)
+						continue;
+
+					igt_display_reset(display);
+
+					igt_output_set_pipe(output1, pipe1);
+					igt_output_set_pipe(output2, pipe2);
+
+					if (!igt_test_constraint(display))
+						continue;
+
+					igt_dynamic_f("pipe-%s-%s-pipe-%s-%s",
+						      kmstest_pipe_name(pipe1),
+						      igt_output_name(output1),
+						      kmstest_pipe_name(pipe2),
+						      igt_output_name(output2))
+						run_extendedmode_basic(data,
+								pipe1, output1,
+								pipe2, output2);
+				}
+			}
+		}
+	}
+}
+
 igt_main
 {
 	data_t data;
-	int valid_output = 0, i, j = 0;
-	igt_output_t *output;
-	int pipe[IGT_MAX_PIPES];
 
 	igt_fixture {
 		data.drm_fd = drm_open_driver_master(DRIVER_ANY);
 		kmstest_set_vt_graphics_mode();
 		igt_display_require(&data.display, data.drm_fd);
-
-		for_each_connected_output(&data.display, output) {
-			valid_output++;
-
-			if (valid_output > 1)
-				break;
-		}
-
-		data.n_pipes = 0;
-		for_each_pipe(&data.display, i) {
-			data.n_pipes++;
-			pipe[j] = i;
-			j++;
-		}
-
-		igt_require_f(valid_output > 1, "No valid second output found\n");
+		igt_display_require_output(&data.display);
 	}
 
 	igt_describe("Test for validating display extended mode with a pair of connected displays");
-	igt_subtest_with_dynamic("extended-mode-basic") {
-		for (i = 0; i < data.n_pipes - 1; i++) {
-			igt_dynamic_f("pipe-%s%s", kmstest_pipe_name(pipe[i]),
-					kmstest_pipe_name(pipe[i+1]));
-			run_extendedmode_basic(&data, pipe[i], pipe[i+1]);
-		}
-	}
+	igt_subtest_with_dynamic("extended-mode-basic")
+		run_extendedmode_test(&data);
 
 	igt_fixture {
 		igt_display_fini(&data.display);
diff --git a/tests/kms_dp_tiled_display.c b/tests/kms_dp_tiled_display.c
index 8f503e40..1ef815a0 100644
--- a/tests/kms_dp_tiled_display.c
+++ b/tests/kms_dp_tiled_display.c
@@ -271,6 +271,7 @@ static void setup_mode(data_t *data)
 		igt_require(found);
 		igt_output_override_mode(output, mode);
 	}
+	igt_require(igt_test_constraint(data->display));
 	igt_display_commit_atomic(data->display, DRM_MODE_ATOMIC_ALLOW_MODESET,
 				  NULL);
 }
diff --git a/tests/kms_flip_event_leak.c b/tests/kms_flip_event_leak.c
index ac201293..1df2474c 100644
--- a/tests/kms_flip_event_leak.c
+++ b/tests/kms_flip_event_leak.c
@@ -48,6 +48,9 @@ static void test(data_t *data, enum pipe pipe, igt_output_t *output)
 	struct igt_fb fb[2];
 	int fd, ret;
 
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
 	/* select the pipe we want to use */
 	igt_output_set_pipe(output, pipe);
 
@@ -102,6 +105,13 @@ igt_simple_main
 	igt_display_require(&data.display, data.drm_fd);
 
 	for_each_pipe_with_valid_output(&data.display, pipe, output) {
+		igt_display_reset(&data.display);
+
+		igt_output_set_pipe(output, pipe);
+		if (!igt_test_constraint(&data.display))
+			continue;
+
+		igt_output_set_pipe(output, PIPE_NONE);
 		test(&data, pipe, output);
 		valid_tests++;
 	}
diff --git a/tests/kms_invalid_mode.c b/tests/kms_invalid_mode.c
index 0ae98a31..7c3866d8 100644
--- a/tests/kms_invalid_mode.c
+++ b/tests/kms_invalid_mode.c
@@ -293,6 +293,12 @@ igt_main
 	for (int i = 0; i < ARRAY_SIZE(subtests); i++) {
 		igt_subtest_with_dynamic(subtests[i].name) {
 			for_each_pipe_with_valid_output(&data.display, pipe, output) {
+				igt_display_reset(&data.display);
+
+				igt_output_set_pipe(output, pipe);
+				if (!igt_test_constraint(&data.display))
+					continue;
+
 				igt_dynamic_f("%s-pipe-%s", igt_output_name(output), kmstest_pipe_name(pipe)) {
 					data.output = output;
 					data.pipe = pipe;
diff --git a/tests/kms_lease.c b/tests/kms_lease.c
index 0bf102a6..512d2fc3 100644
--- a/tests/kms_lease.c
+++ b/tests/kms_lease.c
@@ -823,6 +823,12 @@ static void run_test(data_t *data, void (*testfunc)(data_t *))
 			 kmstest_pipe_name(p),
 			 igt_output_name(output));
 
+		igt_display_reset(display);
+
+		igt_output_set_pipe(output, p);
+		if (!igt_test_constraint(display))
+			continue;
+
 		data->pipe = p;
 		data->crtc_id = pipe_to_crtc_id(display, p);
 		data->connector_id = output->id;
diff --git a/tests/kms_multipipe_modeset.c b/tests/kms_multipipe_modeset.c
index 6358d930..6ba6943e 100644
--- a/tests/kms_multipipe_modeset.c
+++ b/tests/kms_multipipe_modeset.c
@@ -46,6 +46,15 @@ static void run_test(data_t *data, int valid_outputs)
 	drmModeModeInfo *mode;
 	int i = 0;
 
+	/* Find suitable mode/resolution combo */
+	for_each_connected_output(display, output) {
+		pipe = &display->pipes[i];
+		igt_output_set_pipe(output, i);
+
+		i++;
+	}
+	igt_require(igt_override_all_active_output_modes_to_fit_bw(display));
+
 	for_each_connected_output(display, output) {
 		mode = igt_output_get_mode(output);
 		igt_assert(mode);
diff --git a/tests/kms_pipe_crc_basic.c b/tests/kms_pipe_crc_basic.c
index 2ff40f72..176fb702 100644
--- a/tests/kms_pipe_crc_basic.c
+++ b/tests/kms_pipe_crc_basic.c
@@ -271,6 +271,21 @@ static void test_disable_crc_after_crtc(data_t *data, enum pipe pipe,
 	igt_remove_fb(data->drm_fd, &data->fb);
 }
 
+static bool is_valid_combo(igt_display_t *display,
+			   enum pipe pipe, igt_output_t *output)
+{
+	bool ret = true;
+
+	igt_display_reset(display);
+
+	igt_output_set_pipe(output, pipe);
+	if (!igt_test_constraint(display))
+		ret = false;
+	igt_output_set_pipe(output, pipe);
+
+	return ret;
+}
+
 data_t data = {0, };
 
 igt_main
@@ -319,6 +334,9 @@ igt_main
 		igt_describe(tests[i].desc);
 		igt_subtest_with_dynamic(tests[i].name) {
 			for_each_pipe_with_single_output(&data.display, pipe, output) {
+				if(!is_valid_combo(&data.display, pipe, output))
+					continue;
+
 				igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), output->name) {
 					if (tests[i].flags & TEST_SUSPEND) {
 						test_read_crc(&data, pipe, output, 0);
@@ -347,6 +365,9 @@ igt_main
 		     "does not cause issues.");
 	igt_subtest_with_dynamic("disable-crc-after-crtc") {
 		for_each_pipe_with_single_output(&data.display, pipe, output) {
+			if(!is_valid_combo(&data.display, pipe, output))
+				continue;
+
 			igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), output->name)
 				test_disable_crc_after_crtc(&data, pipe, output);
 		}
@@ -355,6 +376,9 @@ igt_main
 	igt_describe("Basic sanity check for CRC mismatches");
 	igt_subtest_with_dynamic("compare-crc-sanitycheck") {
 		for_each_pipe_with_single_output(&data.display, pipe, output) {
+			if(!is_valid_combo(&data.display, pipe, output))
+				continue;
+
 			igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), output->name)
 				test_compare_crc(&data, pipe, output);
 		}
diff --git a/tests/kms_plane.c b/tests/kms_plane.c
index 3cf3cfd3..62dc9af6 100644
--- a/tests/kms_plane.c
+++ b/tests/kms_plane.c
@@ -56,6 +56,7 @@ typedef struct {
 typedef struct {
 	int drm_fd;
 	igt_display_t display;
+	igt_output_t *output;
 	igt_pipe_crc_t *pipe_crc;
 	const color_t *colors;
 	int num_colors;
@@ -273,11 +274,11 @@ static void
 test_plane_position(data_t *data, enum pipe pipe)
 {
 	int n_planes = data->display.pipes[pipe].n_planes;
-	igt_output_t *output;
+	igt_output_t *output = data->output;
 	igt_crc_t reference_crc;
 
-	output = igt_get_single_output_for_pipe(&data->display, pipe);
-	igt_require(output);
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
 
 	test_init(data, pipe);
 	test_grab_crc(data, output, pipe, &green, data->flags, &reference_crc);
@@ -380,11 +381,11 @@ test_plane_panning_with_output(data_t *data,
 static void
 test_plane_panning(data_t *data, enum pipe pipe)
 {
-	igt_output_t *output;
+	igt_output_t *output = data->output;
 	igt_crc_t ref_crc;
 
-	output = igt_get_single_output_for_pipe(&data->display, pipe);
-	igt_require(output);
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
 
 	test_init(data, pipe);
 
@@ -1050,7 +1051,7 @@ test_pixel_formats(data_t *data, enum pipe pipe)
 	igt_plane_t *primary;
 	drmModeModeInfo *mode;
 	bool result;
-	igt_output_t *output;
+	igt_output_t *output = data->output;
 	igt_plane_t *plane;
 
 	if (data->extended) {
@@ -1061,10 +1062,10 @@ test_pixel_formats(data_t *data, enum pipe pipe)
 		data->num_colors = ARRAY_SIZE(colors_reduced);
 	}
 
-	test_init(data, pipe);
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
 
-	output = igt_get_single_output_for_pipe(&data->display, pipe);
-	igt_require(output);
+	test_init(data, pipe);
 
 	mode = igt_output_get_mode(output);
 
@@ -1108,7 +1109,14 @@ static void run_test(data_t *data, void (*test)(data_t *, enum pipe))
 	enum pipe pipe;
 	int count = 0;
 
-	for_each_pipe(&data->display, pipe) {
+	for_each_pipe_with_single_output(&data->display, pipe, data->output) {
+		igt_display_reset(&data->display);
+
+		igt_output_set_pipe(data->output, pipe);
+		if (!igt_test_constraint(&data->display))
+			continue;
+
+		igt_output_set_pipe(data->output, PIPE_NONE);
 		igt_dynamic_f("pipe-%s-planes", kmstest_pipe_name(pipe))
 			test(data, pipe);
 
diff --git a/tests/kms_plane_alpha_blend.c b/tests/kms_plane_alpha_blend.c
index bd064d1e..41cdb99e 100644
--- a/tests/kms_plane_alpha_blend.c
+++ b/tests/kms_plane_alpha_blend.c
@@ -476,6 +476,13 @@ static void run_test_on_pipe_planes(data_t *data, enum pipe pipe, bool blend,
 	bool found = false;
 	bool multiply = false;
 
+	igt_display_reset(display);
+	igt_output_set_pipe(output, pipe);
+	igt_require(igt_test_constraint(display));
+
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
 	for_each_plane_on_pipe(display, pipe, plane) {
 		if (!igt_plane_has_prop(plane, IGT_PLANE_ALPHA))
 			continue;
diff --git a/tests/kms_plane_cursor.c b/tests/kms_plane_cursor.c
index 73085cc8..ab246508 100644
--- a/tests/kms_plane_cursor.c
+++ b/tests/kms_plane_cursor.c
@@ -76,12 +76,16 @@ static void test_init(data_t *data, enum pipe pipe_id)
 	data->overlay = igt_pipe_get_plane_type(data->pipe, DRM_PLANE_TYPE_OVERLAY);
 	data->cursor = igt_pipe_get_plane_type(data->pipe, DRM_PLANE_TYPE_CURSOR);
 
+	igt_output_set_pipe(data->output, data->pipe_id);
+	igt_require(igt_test_constraint(display));
+
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(data->pipe_id), igt_output_name(data->output));
+
 	igt_require_pipe_crc(data->drm_fd);
 	data->pipe_crc = igt_pipe_crc_new(data->drm_fd, data->pipe_id,
 					  INTEL_PIPE_CRC_SOURCE_AUTO);
 
-	igt_output_set_pipe(data->output, data->pipe_id);
-
 	/* Overlay rectangle for a rect in the center of the screen */
 	data->or.x = data->mode->hdisplay / 4;
 	data->or.y = data->mode->vdisplay / 4;
diff --git a/tests/kms_plane_lowres.c b/tests/kms_plane_lowres.c
index f37dbd16..ca6b0eae 100644
--- a/tests/kms_plane_lowres.c
+++ b/tests/kms_plane_lowres.c
@@ -277,6 +277,9 @@ static void run_test(data_t *data, uint64_t modifier)
 			igt_display_reset(&data->display);
 			igt_output_set_pipe(data->output, data->pipe);
 
+			if (!igt_test_constraint(&data->display))
+				continue;
+
 			data->pipe_crc = igt_pipe_crc_new(data->drm_fd, data->pipe,
 							  INTEL_PIPE_CRC_SOURCE_AUTO);
 
diff --git a/tests/kms_plane_multiple.c b/tests/kms_plane_multiple.c
index 1679f7ce..c59fd4df 100644
--- a/tests/kms_plane_multiple.c
+++ b/tests/kms_plane_multiple.c
@@ -296,6 +296,9 @@ test_plane_position_with_output(data_t *data, enum pipe pipe,
 	bool loop_forever;
 	char info[256];
 
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
 	if (opt.iterations == LOOP_FOREVER) {
 		loop_forever = true;
 		sprintf(info, "forever");
@@ -366,12 +369,18 @@ static void
 test_plane_position(data_t *data, enum pipe pipe, uint64_t modifier)
 {
 	igt_output_t *output;
+	igt_display_t *display = &data->display;
 	int n_planes = opt.all_planes ?
 			data->display.pipes[pipe].n_planes : DEFAULT_N_PLANES;
 
-	output = igt_get_single_output_for_pipe(&data->display, pipe);
+	output = igt_get_single_output_for_pipe(display, pipe);
 	igt_require(output);
 
+	igt_display_reset(display);
+
+	igt_output_set_pipe(output, pipe);
+	igt_require(igt_test_constraint(display));
+
 	if (!opt.user_seed)
 		opt.seed = time(NULL);
 
diff --git a/tests/kms_plane_scaling.c b/tests/kms_plane_scaling.c
index fc8250b5..2ab7a80f 100644
--- a/tests/kms_plane_scaling.c
+++ b/tests/kms_plane_scaling.c
@@ -546,30 +546,45 @@ static void test_scaler_with_pixel_format_pipe(data_t *d, int width, int height,
 	}
 }
 
-static void find_connected_pipe(igt_display_t *display, bool second, enum pipe *pipe, igt_output_t **output)
+static enum pipe
+find_connected_pipe(igt_display_t *display, bool second, igt_output_t **output)
 {
-	enum pipe first = PIPE_NONE;
-	igt_output_t *first_output = NULL;
+	enum pipe pipe;
+	bool first_output = false;
 	bool found = false;
 
-	for_each_pipe_with_valid_output(display, *pipe, *output) {
-		if (first == *pipe || *output == first_output)
-			continue;
+	igt_display_reset(display);
 
-		if (second) {
-			first = *pipe;
-			first_output = *output;
-			second = false;
-			continue;
-		}
+	for_each_pipe(display, pipe) {
+		for_each_valid_output_on_pipe(display, pipe, *output) {
+			if((*output)->pending_pipe != PIPE_NONE)
+				continue;
 
-		return;
+			igt_output_set_pipe(*output, pipe);
+			if (igt_test_constraint(display)) {
+				found = true;
+
+				if (second) {
+					first_output = true;
+					second = false;
+					found = false;
+				}
+				break;
+			}
+			igt_output_set_pipe(*output, PIPE_NONE);
+		}
+		if (found)
+			break;
 	}
 
+	igt_display_reset(display);
+
 	if (first_output)
 		igt_require_f(found, "No second valid output found\n");
 	else
 		igt_require_f(found, "No valid outputs found\n");
+
+	return pipe;
 }
 
 static void
@@ -749,13 +764,16 @@ static void test_scaler_with_multi_pipe_plane(data_t *d)
 	enum pipe pipe1, pipe2;
 	int ret1, ret2;
 
-	cleanup_crtc(d);
-
-	find_connected_pipe(display, false, &pipe1, &output1);
-	find_connected_pipe(display, true, &pipe2, &output2);
+	cleanup_fbs(d);
 
+	pipe1 = find_connected_pipe(display, false, &output1);
+	pipe2 = find_connected_pipe(display, true, &output2);
 	igt_skip_on(!output1 || !output2);
 
+	igt_info("Using (pipe %s + %s) and (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe1), igt_output_name(output1),
+		 kmstest_pipe_name(pipe2), igt_output_name(output2));
+
 	igt_output_set_pipe(output1, pipe1);
 	igt_output_set_pipe(output2, pipe2);
 
@@ -820,6 +838,21 @@ static void test_scaler_with_multi_pipe_plane(data_t *d)
 	igt_assert_eq(ret1 && ret2, 0);
 }
 
+static bool
+is_valid_combo(igt_display_t *display, enum pipe pipe, igt_output_t *output)
+{
+	bool ret = true;
+
+	igt_display_reset(display);
+
+	igt_output_set_pipe(output, pipe);
+	if (!igt_test_constraint(display))
+		ret = false;
+	igt_output_set_pipe(output, PIPE_NONE);
+
+	return ret;
+}
+
 static int opt_handler(int opt, int opt_index, void *_data)
 {
 	data_t *data = _data;
@@ -861,17 +894,22 @@ igt_main_args("", long_opts, help_str, opt_handler, &data)
 		for (int index = 0; index < ARRAY_SIZE(scaler_with_pixel_format_tests); index++) {
 			igt_describe(scaler_with_pixel_format_tests[index].describe);
 			igt_subtest_with_dynamic(scaler_with_pixel_format_tests[index].name) {
-			for_each_pipe_with_single_output(&data.display, pipe, output)
-				igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), igt_output_name(output)) {
-					drmModeModeInfo *mode;
-
-					mode = igt_output_get_mode(output);
-
-					test_scaler_with_pixel_format_pipe(&data,
-							get_width(mode, scaler_with_pixel_format_tests[index].sf),
-							get_height(mode, scaler_with_pixel_format_tests[index].sf),
-							scaler_with_pixel_format_tests[index].is_upscale,
-							pipe, output);
+				for_each_pipe(&data.display, pipe) {
+					for_each_valid_output_on_pipe(&data.display, pipe, output) {
+						if (!is_valid_combo(&data.display, pipe, output))
+							continue;
+
+						igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), igt_output_name(output)) {
+							drmModeModeInfo *mode = igt_output_get_mode(output);
+
+							test_scaler_with_pixel_format_pipe(&data,
+								get_width(mode, scaler_with_pixel_format_tests[index].sf),
+								get_height(mode, scaler_with_pixel_format_tests[index].sf),
+								scaler_with_pixel_format_tests[index].is_upscale,
+								pipe, output);
+						}
+						break;
+					}
 				}
 			}
 		}
@@ -879,17 +917,22 @@ igt_main_args("", long_opts, help_str, opt_handler, &data)
 		for (int index = 0; index < ARRAY_SIZE(scaler_with_rotation_tests); index++) {
 			igt_describe(scaler_with_rotation_tests[index].describe);
 			igt_subtest_with_dynamic(scaler_with_rotation_tests[index].name) {
-			for_each_pipe_with_single_output(&data.display, pipe, output)
-				igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), igt_output_name(output)) {
-					drmModeModeInfo *mode;
-
-					mode = igt_output_get_mode(output);
-
-					test_scaler_with_rotation_pipe(&data,
-							get_width(mode, scaler_with_rotation_tests[index].sf),
-							get_height(mode, scaler_with_rotation_tests[index].sf),
-							scaler_with_rotation_tests[index].is_upscale,
-							pipe, output);
+				for_each_pipe(&data.display, pipe) {
+					for_each_valid_output_on_pipe(&data.display, pipe, output) {
+						if (!is_valid_combo(&data.display, pipe, output))
+							continue;
+
+						igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), igt_output_name(output)) {
+							drmModeModeInfo *mode = igt_output_get_mode(output);
+
+							test_scaler_with_rotation_pipe(&data,
+								get_width(mode, scaler_with_rotation_tests[index].sf),
+								get_height(mode, scaler_with_rotation_tests[index].sf),
+								scaler_with_rotation_tests[index].is_upscale,
+								pipe, output);
+						}
+						break;
+					}
 				}
 			}
 		}
@@ -897,85 +940,113 @@ igt_main_args("", long_opts, help_str, opt_handler, &data)
 		for (int index = 0; index < ARRAY_SIZE(scaler_with_modifiers_tests); index++) {
 			igt_describe(scaler_with_modifiers_tests[index].describe);
 			igt_subtest_with_dynamic(scaler_with_modifiers_tests[index].name) {
-			for_each_pipe_with_single_output(&data.display, pipe, output)
-				igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), igt_output_name(output)) {
-					drmModeModeInfo *mode;
-
-					mode = igt_output_get_mode(output);
-
-					test_scaler_with_modifier_pipe(&data,
-							get_width(mode, scaler_with_rotation_tests[index].sf),
-							get_height(mode, scaler_with_rotation_tests[index].sf),
-							scaler_with_rotation_tests[index].is_upscale,
-							pipe, output);
+				for_each_pipe(&data.display, pipe) {
+					for_each_valid_output_on_pipe(&data.display, pipe, output) {
+						if (!is_valid_combo(&data.display, pipe, output))
+							continue;
+
+						igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), igt_output_name(output)) {
+							drmModeModeInfo *mode = igt_output_get_mode(output);
+
+							test_scaler_with_modifier_pipe(&data,
+								get_width(mode, scaler_with_rotation_tests[index].sf),
+								get_height(mode, scaler_with_rotation_tests[index].sf),
+								scaler_with_rotation_tests[index].is_upscale,
+								pipe, output);
+						}
+						break;
+					}
 				}
 			}
 		}
 
 		igt_describe("Tests scaling with clipping and clamping, pixel formats.");
 		igt_subtest_with_dynamic("plane-scaler-with-clipping-clamping-pixel-formats") {
-			for_each_pipe_with_single_output(&data.display, pipe, output) {
-				drmModeModeInfo *mode;
+			for_each_pipe(&data.display, pipe) {
+				for_each_valid_output_on_pipe(&data.display, pipe, output) {
+					if (!is_valid_combo(&data.display, pipe, output))
+						continue;
 
-				mode = igt_output_get_mode(output);
+					igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), igt_output_name(output)) {
+						drmModeModeInfo *mode = igt_output_get_mode(output);
 
-				igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), igt_output_name(output))
-					test_scaler_with_pixel_format_pipe(&data, mode->hdisplay + 100,
+						test_scaler_with_pixel_format_pipe(&data, mode->hdisplay + 100,
 							mode->vdisplay + 100, false, pipe, output);
+					}
+					break;
+				}
 			}
 		}
 
 		igt_describe("Tests scaling with clipping and clamping, rotation.");
 		igt_subtest_with_dynamic("plane-scaler-with-clipping-clamping-rotation") {
-			for_each_pipe_with_single_output(&data.display, pipe, output) {
-				drmModeModeInfo *mode;
+			for_each_pipe(&data.display, pipe) {
+				for_each_valid_output_on_pipe(&data.display, pipe, output) {
+					if (!is_valid_combo(&data.display, pipe, output))
+						continue;
 
-				mode = igt_output_get_mode(output);
+					igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), igt_output_name(output)) {
+						drmModeModeInfo *mode = igt_output_get_mode(output);
 
-				igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), igt_output_name(output))
-					test_scaler_with_rotation_pipe(&data, mode->hdisplay + 100,
+						test_scaler_with_rotation_pipe(&data, mode->hdisplay + 100,
 							mode->vdisplay + 100, false, pipe, output);
+					}
+					break;
+				}
 			}
 		}
 
 		igt_describe("Tests scaling with clipping and clamping, modifiers.");
 		igt_subtest_with_dynamic("plane-scaler-with-clipping-clamping-modifiers") {
-			for_each_pipe_with_single_output(&data.display, pipe, output) {
-				drmModeModeInfo *mode;
-
-				mode = igt_output_get_mode(output);
-
-				igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), igt_output_name(output))
-					test_scaler_with_modifier_pipe(&data, mode->hdisplay + 100,
+			for_each_pipe(&data.display, pipe) {
+				for_each_valid_output_on_pipe(&data.display, pipe, output) {
+					if (!is_valid_combo(&data.display, pipe, output))
+						continue;
+
+					igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), igt_output_name(output)) {
+						drmModeModeInfo *mode = igt_output_get_mode(output);
+						test_scaler_with_modifier_pipe(&data, mode->hdisplay + 100,
 							mode->vdisplay + 100, false, pipe, output);
+					}
+					break;
+				}
 			}
 		}
 
 		for (int index = 0; index < ARRAY_SIZE(scaler_with_2_planes_tests); index++) {
 			igt_describe(scaler_with_2_planes_tests[index].describe);
 			igt_subtest_with_dynamic(scaler_with_2_planes_tests[index].name) {
-			for_each_pipe_with_single_output(&data.display, pipe, output)
-				igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), igt_output_name(output)) {
-					drmModeModeInfo *mode;
+			for_each_pipe(&data.display, pipe) {
+				for_each_valid_output_on_pipe(&data.display, pipe, output) {
+					if (!is_valid_combo(&data.display, pipe, output))
+						continue;
 
-					mode = igt_output_get_mode(output);
+					igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), igt_output_name(output)) {
+						drmModeModeInfo *mode = igt_output_get_mode(output);
 
-					test_planes_scaling_combo(&data,
+						test_planes_scaling_combo(&data,
 							get_width(mode, scaler_with_2_planes_tests[index].sf_plane1),
 							get_height(mode, scaler_with_2_planes_tests[index].sf_plane1),
 							get_width(mode, scaler_with_2_planes_tests[index].sf_plane2),
 							get_height(mode, scaler_with_2_planes_tests[index].sf_plane2),
 							pipe, output, scaler_with_2_planes_tests[index].test_type);
+					}
+					break;
 				}
 			}
+			}
 		}
 
 		igt_describe("Negative test for number of scalers per pipe.");
 		igt_subtest_with_dynamic("invalid-num-scalers") {
-			for_each_pipe_with_valid_output(&data.display, pipe, output)
+			for_each_pipe_with_valid_output(&data.display, pipe, output) {
+				if (!is_valid_combo(&data.display, pipe, output))
+					continue;
+
 				igt_dynamic_f("pipe-%s-%s-invalid-num-scalers",
 					       kmstest_pipe_name(pipe), igt_output_name(output))
 					test_invalid_num_scalers(&data, pipe, output);
+			}
 		}
 	}
 
diff --git a/tests/kms_prime.c b/tests/kms_prime.c
index 3df690e0..a2a7ce1f 100644
--- a/tests/kms_prime.c
+++ b/tests/kms_prime.c
@@ -89,14 +89,17 @@ static igt_output_t *setup_display(int importer_fd, igt_display_t *display,
 	bool found = false;
 
 	for_each_pipe_with_valid_output(display, *pipe, output) {
-		found = true;
-		break;
+		igt_display_reset(display);
+
+		igt_output_set_pipe(output, *pipe);
+		if (igt_test_constraint(display)) {
+			found = true;
+			break;
+		}
 	}
 
 	igt_require_f(found, "No valid connector/pipe found\n");
 
-	igt_display_reset(display);
-	igt_output_set_pipe(output, *pipe);
 	return output;
 }
 
diff --git a/tests/kms_properties.c b/tests/kms_properties.c
index dd5a93aa..a9c2b7df 100644
--- a/tests/kms_properties.c
+++ b/tests/kms_properties.c
@@ -241,6 +241,12 @@ static void plane_properties(igt_display_t *display, bool atomic)
 		found = false;
 
 		for_each_valid_output_on_pipe(display, pipe, output) {
+			igt_display_reset(display);
+
+			igt_output_set_pipe(output, pipe);
+			if (!igt_test_constraint(display))
+				continue;
+
 			found_any = found = true;
 
 			run_plane_property_tests(display, pipe, output, atomic);
@@ -264,6 +270,12 @@ static void crtc_properties(igt_display_t *display, bool atomic)
 		found = false;
 
 		for_each_valid_output_on_pipe(display, pipe, output) {
+			igt_display_reset(display);
+
+			igt_output_set_pipe(output, pipe);
+			if (!igt_test_constraint(display))
+				continue;
+
 			found_any_valid_pipe = found = true;
 
 			run_crtc_property_tests(display, pipe, output, atomic);
@@ -290,6 +302,12 @@ static void connector_properties(igt_display_t *display, bool atomic)
 			if (!igt_pipe_connector_valid(pipe, output))
 				continue;
 
+			igt_display_reset(display);
+
+			igt_output_set_pipe(output, pipe);
+			if (!igt_test_constraint(display))
+				continue;
+
 			found = true;
 			run_connector_property_tests(display, pipe, output, atomic);
 			break;
diff --git a/tests/kms_rmfb.c b/tests/kms_rmfb.c
index 7e43e1bd..2bf4968b 100644
--- a/tests/kms_rmfb.c
+++ b/tests/kms_rmfb.c
@@ -155,8 +155,15 @@ run_rmfb_test(struct rmfb_data *data, bool reopen)
 {
 	igt_output_t *output;
 	enum pipe pipe;
+	igt_display_t *display = &data->display;
+
+	for_each_pipe_with_single_output(display, pipe, output) {
+		igt_display_reset(display);
+
+		igt_output_set_pipe(output, pipe);
+		if (!igt_test_constraint(display))
+			continue;
 
-	for_each_pipe_with_single_output(&data->display, pipe, output) {
 		igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe),
 			      igt_output_name(output))
 			test_rmfb(data, output, pipe, reopen);
@@ -192,7 +199,6 @@ igt_main
 		igt_describe(tests[i].description);
 		igt_subtest_with_dynamic(tests[i].name) {
 			run_rmfb_test(&data, tests[i].reopen);
-
 		}
 	}
 
diff --git a/tests/kms_rotation_crc.c b/tests/kms_rotation_crc.c
index 50869a08..52551c06 100644
--- a/tests/kms_rotation_crc.c
+++ b/tests/kms_rotation_crc.c
@@ -198,6 +198,8 @@ static void prepare_crtc(data_t *data, igt_output_t *output, enum pipe pipe,
 	cleanup_crtc(data);
 
 	igt_output_set_pipe(output, pipe);
+	igt_require(igt_test_constraint(display));
+
 	igt_plane_set_rotation(plane, IGT_ROTATION_0);
 
 	/* create the pipe_crc object for this pipe */
@@ -461,6 +463,7 @@ static void test_plane_rotation(data_t *data, int plane_type, bool test_bad_form
 	igt_output_t *output;
 	enum pipe pipe;
 	int pipe_count = 0, connected_outputs = 0;
+	bool found = false;
 
 	if (is_amdgpu_device(data->gfx_fd))
 		igt_require(plane_type != DRM_PLANE_TYPE_OVERLAY &&
@@ -478,6 +481,13 @@ static void test_plane_rotation(data_t *data, int plane_type, bool test_bad_form
 		igt_plane_t *plane;
 		int i, j, c;
 
+		igt_display_reset(display);
+
+		igt_output_set_pipe(output, pipe);
+		if (!igt_test_constraint(display))
+			continue;
+
+		found = true;
 		mode = igt_output_get_mode(output);
 
 		/*
@@ -568,6 +578,7 @@ static void test_plane_rotation(data_t *data, int plane_type, bool test_bad_form
 			igt_pipe_crc_stop(data->pipe_crc);
 		}
 	}
+	igt_require_f(found, "No valid pipe/output combo found.\n");
 }
 
 typedef struct {
@@ -677,6 +688,7 @@ static void test_multi_plane_rotation(data_t *data, enum pipe pipe)
 	bool have_crc; // flag if can use previously logged crc for comparison
 	igt_crc_t crclog[16] = {}; //4 * 4 rotation crc storage for packed formats
 	char *str1, *str2; // for debug printouts
+	bool found = false;
 
 	/*
 	 * These are those modes which are tested. For testing feel interesting
@@ -706,11 +718,20 @@ static void test_multi_plane_rotation(data_t *data, enum pipe pipe)
 	{IGT_ROTATION_270, .2f, .4f, I915_FORMAT_MOD_Yf_TILED },
 	};
 
+	igt_display_require_output(display);
+
 	for_each_valid_output_on_pipe(display, pipe, output) {
 		int i, j, k, l, flipsw, fliphw;
+
+		igt_display_reset(display);
+
 		igt_output_set_pipe(output, pipe);
+		if (!igt_test_constraint(display))
+			continue;
+
+		found = true;
+
 		mode = igt_output_get_mode(output);
-		igt_display_require_output(display);
 		igt_display_commit2(display, COMMIT_ATOMIC);
 
 		used_w = TEST_WIDTH(mode);
@@ -890,6 +911,8 @@ static void test_multi_plane_rotation(data_t *data, enum pipe pipe)
 			igt_remove_fb(data->gfx_fd, &planeconfigs[c].fbs[d][MULTIPLANE_ROTATED]);
 		}
 	}
+
+	igt_require_f(found, "No valid pipe/output combo found.\n");
 }
 
 static void test_plane_rotation_exhaust_fences(data_t *data,
diff --git a/tests/kms_scaling_modes.c b/tests/kms_scaling_modes.c
index 8e80189a..a0b268ae 100644
--- a/tests/kms_scaling_modes.c
+++ b/tests/kms_scaling_modes.c
@@ -93,13 +93,17 @@ static void test_scaling_mode(data_t *data, uint32_t flags)
 	enum pipe pipe;
 
 	for_each_pipe_with_valid_output(display, pipe, output) {
+		igt_display_reset(display);
+
 		if (!has_scaling_mode(output))
 			continue;
 
+		igt_output_set_pipe(output, pipe);
+		if (!igt_test_constraint(display))
+			continue;
+
 		igt_dynamic_f("%s-pipe-%s", output->name, kmstest_pipe_name(pipe))
 			test_scaling_mode_on_output(display, pipe, output, flags);
-
-		igt_display_reset(display);
 	}
 }
 
diff --git a/tests/kms_sequence.c b/tests/kms_sequence.c
index 1655d7d1..e6442e8e 100644
--- a/tests/kms_sequence.c
+++ b/tests/kms_sequence.c
@@ -285,6 +285,12 @@ igt_main
 				     "drmCrtcQueueSequence");
 			igt_subtest_with_dynamic_f("%s-%s", f->name, m->name) {
 				for_each_pipe_with_valid_output(&data.display, p, output) {
+					igt_display_reset(&data.display);
+
+					igt_output_set_pipe(output, p);
+					if (!igt_test_constraint(&data.display))
+						continue;
+
 					igt_dynamic_f("%s-pipe-%s", igt_output_name(output), kmstest_pipe_name(p)) {
 						data.pipe = p;
 						data.output = output;
diff --git a/tests/kms_universal_plane.c b/tests/kms_universal_plane.c
index 3cb6d704..52f7c107 100644
--- a/tests/kms_universal_plane.c
+++ b/tests/kms_universal_plane.c
@@ -366,6 +366,9 @@ sanity_test_pipe(data_t *data, enum pipe pipe, igt_output_t *output)
 
 	igt_require_pipe(&data->display, pipe);
 
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
 	igt_output_set_pipe(output, pipe);
 	mode = igt_output_get_mode(output);
 
@@ -479,6 +482,9 @@ pageflip_test_pipe(data_t *data, enum pipe pipe, igt_output_t *output)
 
 	igt_require_pipe(&data->display, pipe);
 
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
 	igt_output_set_pipe(output, pipe);
 
 	pageflip_test_init(&test, output, pipe);
@@ -582,6 +588,9 @@ cursor_leak_test_pipe(data_t *data, enum pipe pipe, igt_output_t *output)
 	igt_require(display->has_cursor_plane);
 	igt_require_intel(data->drm_fd);
 
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
 	igt_output_set_pipe(output, pipe);
 	mode = igt_output_get_mode(output);
 
@@ -710,6 +719,9 @@ gen9_test_pipe(data_t *data, enum pipe pipe, igt_output_t *output)
 	igt_skip_on(data->display_ver < 9);
 	igt_require_pipe(&data->display, pipe);
 
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
 	igt_output_set_pipe(output, pipe);
 
 	gen9_test_init(&test, output, pipe);
@@ -745,6 +757,21 @@ gen9_test_pipe(data_t *data, enum pipe pipe, igt_output_t *output)
 	gen9_test_fini(&test, output);
 }
 
+static bool
+is_valid_combo(igt_display_t *display, enum pipe pipe, igt_output_t *output)
+{
+	bool ret = true;
+
+	igt_display_reset(display);
+
+	igt_output_set_pipe(output, pipe);
+	if (!igt_test_constraint(display))
+		ret = false;
+	igt_output_set_pipe(output, PIPE_NONE);
+
+	return ret;
+}
+
 static void
 run_tests_for_pipe(data_t *data, enum pipe pipe)
 {
@@ -763,34 +790,79 @@ run_tests_for_pipe(data_t *data, enum pipe pipe)
 
 	igt_describe("Check the switching between different primary plane fbs with CRTC off");
 	igt_subtest_f("universal-plane-pipe-%s-functional",
-		      kmstest_pipe_name(pipe))
-		for_each_valid_output_on_pipe(&data->display, pipe, output)
+		      kmstest_pipe_name(pipe)) {
+		bool found = false;
+
+		for_each_valid_output_on_pipe(&data->display, pipe, output) {
+			if (!is_valid_combo(&data->display, pipe, output))
+				continue;
+
+			found = true;
 			functional_test_pipe(data, pipe, output);
+		}
+		igt_require_f(found, "No valid pipe/output combo found.\n");
+	}
 
 	igt_describe("Test for scale-up or scale-down using universal plane API without covering CRTC");
 	igt_subtest_f("universal-plane-pipe-%s-sanity",
-		      kmstest_pipe_name(pipe))
-		for_each_valid_output_on_pipe(&data->display, pipe, output)
+		      kmstest_pipe_name(pipe)) {
+		bool found = false;
+
+		for_each_valid_output_on_pipe(&data->display, pipe, output) {
+			if (!is_valid_combo(&data->display, pipe, output))
+				continue;
+
+			found = true;
 			sanity_test_pipe(data, pipe, output);
+		}
+		igt_require_f(found, "No valid pipe/output combo found.\n");
+	}
 
 	igt_describe("Check pageflips while primary plane is disabled before IOCTL or between IOCTL"
 			" and pageflip execution");
 	igt_subtest_f("disable-primary-vs-flip-pipe-%s",
-		      kmstest_pipe_name(pipe))
-		for_each_valid_output_on_pipe(&data->display, pipe, output)
+		      kmstest_pipe_name(pipe)) {
+		bool found = false;
+
+		for_each_valid_output_on_pipe(&data->display, pipe, output) {
+			if (!is_valid_combo(&data->display, pipe, output))
+				continue;
+
+			found = true;
 			pageflip_test_pipe(data, pipe, output);
+		}
+		igt_require_f(found, "No valid pipe/output combo found.\n");
+	}
 
 	igt_describe("Check for cursor leaks after performing cursor operations");
 	igt_subtest_f("cursor-fb-leak-pipe-%s",
-		      kmstest_pipe_name(pipe))
-		for_each_valid_output_on_pipe(&data->display, pipe, output)
+		      kmstest_pipe_name(pipe)) {
+		bool found = false;
+
+		for_each_valid_output_on_pipe(&data->display, pipe, output) {
+			if (!is_valid_combo(&data->display, pipe, output))
+				continue;
+
+			found = true;
 			cursor_leak_test_pipe(data, pipe, output);
+		}
+		igt_require_f(found, "No valid pipe/output combo found.\n");
+	}
 
 	igt_describe("Check if pageflip succeeds in windowed setting");
 	igt_subtest_f("universal-plane-gen9-features-pipe-%s",
-		      kmstest_pipe_name(pipe))
-		for_each_valid_output_on_pipe(&data->display, pipe, output)
+		      kmstest_pipe_name(pipe)) {
+		bool found = false;
+
+		for_each_valid_output_on_pipe(&data->display, pipe, output) {
+			if (!is_valid_combo(&data->display, pipe, output))
+				continue;
+
+			found = true;
 			gen9_test_pipe(data, pipe, output);
+		}
+		igt_require_f(found, "No valid pipe/output combo found.\n");
+	}
 }
 
 static data_t data;
@@ -808,6 +880,7 @@ igt_main
 
 		igt_require_pipe_crc(data.drm_fd);
 		igt_display_require(&data.display, data.drm_fd);
+		igt_display_require_output(&data.display);
 	}
 
 	for_each_pipe_static(pipe) {
diff --git a/tests/kms_vblank.c b/tests/kms_vblank.c
index e65e8522..811ba6d0 100644
--- a/tests/kms_vblank.c
+++ b/tests/kms_vblank.c
@@ -175,6 +175,21 @@ static void run_test(data_t *data, void (*testfunc)(data_t *, int, int))
 	cleanup_crtc(data, fd, output);
 }
 
+static bool
+is_valid_combo(igt_display_t *display, enum pipe pipe, igt_output_t *output)
+{
+	bool ret = true;
+
+	igt_display_reset(display);
+
+	igt_output_set_pipe(output, pipe);
+	if (!igt_test_constraint(display))
+		ret = false;
+	igt_output_set_pipe(output, PIPE_NONE);
+
+	return ret;
+}
+
 static void crtc_id_subtest(data_t *data, int fd)
 {
 	igt_display_t *display = &data->display;
@@ -188,6 +203,15 @@ static void crtc_id_subtest(data_t *data, int fd)
 		uint64_t val;
 		union drm_wait_vblank vbl;
 
+		igt_display_reset(display);
+
+		igt_output_set_pipe(output, p);
+		if (!igt_test_constraint(display))
+			continue;
+
+		igt_info("Using (pipe %s + %s) to run the subtest.\n",
+			 kmstest_pipe_name(p), igt_output_name(output));
+
 		crtc_id = display->pipes[p].crtc_id;
 		if (drmGetCap(display->drm_fd, DRM_CAP_CRTC_IN_VBLANK_EVENT, &val) == 0)
 			expected_crtc_id = crtc_id;
@@ -449,10 +473,18 @@ static void run_subtests_for_pipe(data_t *data)
 			igt_subtest_f("pipe-%s-%s-%s",
 				      kmstest_pipe_name(data->pipe),
 				      f->name, m->name) {
+				int found = 0;
+
 				for_each_valid_output_on_pipe(&data->display, data->pipe, data->output) {
+					if (!is_valid_combo(&data->display, data->pipe, data->output))
+						continue;
+
 					data->flags = m->flags | NOHANG;
 					run_test(data, f->func);
+
+					found++;
 				}
+				igt_require_f(found, "No valid pipe/output combo found.\n");
 			}
 
 			/* Skip the -hang version if NOHANG flag is set */
@@ -464,13 +496,20 @@ static void run_subtests_for_pipe(data_t *data)
 				      kmstest_pipe_name(data->pipe),
 				      f->name, m->name) {
 				igt_hang_t hang;
+				int found = 0;
 
 				hang = igt_allow_hang(data->display.drm_fd, 0, 0);
 				for_each_valid_output_on_pipe(&data->display, data->pipe, data->output) {
+					if (!is_valid_combo(&data->display, data->pipe, data->output))
+						continue;
+
 					data->flags = m->flags;
 					run_test(data, f->func);
+
+					found++;
 				}
 				igt_disallow_hang(data->display.drm_fd, hang);
+				igt_require_f(found, "No valid pipe/output combo found.\n");
 			}
 		}
 	}
@@ -482,12 +521,23 @@ static void invalid_subtest(data_t *data, int fd)
 	unsigned long valid_flags;
 	igt_display_t* display = &data->display;
 	enum pipe pipe = 0;
-	igt_output_t* output = igt_get_single_output_for_pipe(display, pipe);
+	igt_output_t *output;
+
+	igt_display_reset(display);
+	igt_display_require_output_on_pipe(display, pipe);
+
+	output = igt_get_single_output_for_pipe(display, pipe);
+	igt_require(output);
 
 	data->pipe = pipe;
 	data->output = output;
+
 	igt_output_set_pipe(output, pipe);
-	igt_display_require_output_on_pipe(display, pipe);
+	igt_require(igt_test_constraint(display));
+
+	igt_info("Using (pipe %s + %s) to run the subtest.\n",
+		 kmstest_pipe_name(pipe), igt_output_name(output));
+
 	prepare_crtc(data, fd, output);
 
 	/* First check all is well with a simple query */
diff --git a/tests/kms_vrr.c b/tests/kms_vrr.c
index 8976d4a6..4d7c771d 100644
--- a/tests/kms_vrr.c
+++ b/tests/kms_vrr.c
@@ -444,6 +444,12 @@ run_vrr_test(data_t *data, test_t test, uint32_t flags)
 
 		for_each_pipe(&data->display, pipe) {
 			if (igt_pipe_connector_valid(pipe, output)) {
+				igt_display_reset(&data->display);
+
+				igt_output_set_pipe(output, pipe);
+				if (!igt_test_constraint(&data->display))
+					continue;
+
 				igt_dynamic_f("pipe-%s-%s",
 					      kmstest_pipe_name(pipe), output->name)
 					test(data, pipe, output, flags);
-- 
2.35.1



More information about the Intel-gfx-trybot mailing list