diff --git a/tests/kms_flip.c b/tests/kms_flip.c
index 6ec97d0a8534..5b4e27e49838 100644
--- a/tests/kms_flip.c
+++ b/tests/kms_flip.c
@@ -75,6 +75,7 @@
 #define TEST_BO_TOOBIG		(1 << 28)
 #define TEST_HANG_ONCE		(1 << 29)
 #define TEST_BASIC		(1 << 30)
+#define TEST_CRC		(1U << 31)
 
 #define EVENT_FLIP		(1 << 0)
 #define EVENT_VBLANK		(1 << 1)
@@ -151,6 +152,8 @@ static void dump_event_state(const struct event_state *es)
 		  es->seq_step);
 }
 
+#define N_FRAMES 8
+
 struct test_output {
 	int mode_valid;
 	drmModeModeInfo kmode[4];
@@ -160,14 +163,16 @@ struct test_output {
 	uint32_t _crtc[4];
 	int _pipe[4];
 	int count; /* 1:1 mapping between crtc:connector */
-	int flags;
+	unsigned int flags;
 	int pipe; /* primary pipe for vblank */
 	unsigned int current_fb_id;
 	unsigned int fb_width;
 	unsigned int fb_height;
-	unsigned int fb_ids[3];
+	unsigned int fb_ids[N_FRAMES];
 	int bpp, depth;
-	struct igt_fb fb_info[3];
+	struct igt_fb fb_info[N_FRAMES];
+	igt_pipe_crc_t *pipe_crc;
+	igt_crc_t crc[N_FRAMES];
 
 	struct event_state flip_state;
 	struct event_state vblank_state;
@@ -853,7 +858,9 @@ static unsigned int run_test_step(struct test_output *o)
 	if (o->flags & TEST_DPMS_OFF_OTHERS)
 		dpms_off_other_outputs(o);
 
-	if (!(o->flags & TEST_SINGLE_BUFFER))
+	if (o->flags & TEST_CRC)
+		o->current_fb_id = (o->current_fb_id + 1) % N_FRAMES;
+	else if (!(o->flags & TEST_SINGLE_BUFFER))
 		o->current_fb_id = !o->current_fb_id;
 
 	if (o->flags & TEST_WITH_DUMMY_BCS)
@@ -1134,7 +1141,7 @@ found:
 	drmModeFreeCrtc(config[1].crtc);
 }
 
-static void paint_flip_mode(struct igt_fb *fb, bool odd_frame)
+static void paint_flip_mode(struct igt_fb *fb, int n_phases, int phase)
 {
 	cairo_t *cr = igt_get_cairo_ctx(drm_fd, fb);
 	int width = fb->width;
@@ -1142,10 +1149,7 @@ static void paint_flip_mode(struct igt_fb *fb, bool odd_frame)
 
 	igt_paint_test_pattern(cr, width, height);
 
-	if (odd_frame)
-		cairo_rectangle(cr, width/4, height/2, width/4, height/8);
-	else
-		cairo_rectangle(cr, width/2, height/2, width/4, height/8);
+	cairo_rectangle(cr, phase * width/n_phases, height/2, width/n_phases, height/8);
 
 	cairo_set_source_rgb(cr, 1, 1, 1);
 	cairo_fill(cr);
@@ -1251,6 +1255,29 @@ static unsigned event_loop(struct test_output *o, unsigned duration_ms)
 	if (o->flags & TEST_HANG_ONCE)
 		hang = hang_gpu(drm_fd);
 
+	if (o->pipe_crc) {
+		igt_pipe_crc_stop(o->pipe_crc);
+		igt_pipe_crc_free(o->pipe_crc);
+		o->pipe_crc = NULL;
+	}
+
+	if (o->flags & TEST_CRC) {
+		o->pipe_crc = igt_pipe_crc_new_nonblock(o->pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
+
+		for (int i = 0; i <  N_FRAMES; i++) {
+			igt_assert_eq(set_mode(o, o->fb_ids[i], 0, 0), 0);
+			igt_pipe_crc_collect_crc(o->pipe_crc, &o->crc[i]);
+
+			/* We want each frame to have a unique crc */
+			for (int j = 0; j < i; j++)
+				igt_require(!igt_crc_equal(&o->crc[i], &o->crc[j]));
+		}
+		igt_assert_eq(set_mode(o, o->fb_ids[0], 0, 0), 0);
+		o->current_fb_id = 0;
+
+		igt_pipe_crc_start(o->pipe_crc);
+	}
+
 	start = gettime_us();
 
 	while (1) {
@@ -1262,6 +1289,20 @@ static unsigned event_loop(struct test_output *o, unsigned duration_ms)
 		check_all_state(o, completed_events);
 		update_all_state(o, completed_events);
 
+		if (o->flags & TEST_CRC) {
+			igt_crc_t *crcs;
+			int n_crcs;
+			int prev_fb_id = (o->current_fb_id + N_FRAMES - 1) % N_FRAMES;
+
+			n_crcs = igt_pipe_crc_get_crcs(o->pipe_crc, 2, &crcs);
+			igt_assert_eq(n_crcs, 1);
+
+			/* crc will be for the previous frame */
+			igt_assert_crc_equal(&crcs[0], &o->crc[prev_fb_id]);
+			free(crcs);
+		}
+
+
 		if (count && (gettime_us() - start) / 1000 >= duration_ms)
 			break;
 
@@ -1276,6 +1317,12 @@ static unsigned event_loop(struct test_output *o, unsigned duration_ms)
 	if (o->pending_events)
 		wait_for_events(o);
 
+	if (o->pipe_crc) {
+		igt_pipe_crc_stop(o->pipe_crc);
+		igt_pipe_crc_free(o->pipe_crc);
+		o->pipe_crc = NULL;
+	}
+
 	return end - start;
 }
 
@@ -1341,37 +1388,46 @@ static void run_test_on_crtc_set(struct test_output *o, int *crtc_idxs,
 	if (o->flags & TEST_FENCE_STRESS)
 		tiling = LOCAL_I915_FORMAT_MOD_X_TILED;
 
-	/* 256 MB is usually the maximum mappable aperture,
-	 * (make it 4x times that to ensure failure) */
-	if (o->flags & TEST_BO_TOOBIG)
-		bo_size = 4*256*1024*1024;
 
-	o->fb_ids[0] = igt_create_fb(drm_fd, o->fb_width, o->fb_height,
-					 igt_bpp_depth_to_drm_format(o->bpp, o->depth),
-					 tiling, &o->fb_info[0]);
-	o->fb_ids[1] = igt_create_fb_with_bo_size(drm_fd, o->fb_width, o->fb_height,
+	if (o->flags & TEST_CRC) {
+		for (i = 0; i < N_FRAMES; i++) {
+			o->fb_ids[i] = igt_create_fb(drm_fd, o->fb_width, o->fb_height,
+						     igt_bpp_depth_to_drm_format(o->bpp, o->depth),
+						     tiling, &o->fb_info[i]);
+			paint_flip_mode(&o->fb_info[i], N_FRAMES, i);
+		}
+	} else {
+		/* 256 MB is usually the maximum mappable aperture,
+		 * (make it 4x times that to ensure failure) */
+		if (o->flags & TEST_BO_TOOBIG)
+			bo_size = 4*256*1024*1024;
+
+		o->fb_ids[0] = igt_create_fb(drm_fd, o->fb_width, o->fb_height,
+					     igt_bpp_depth_to_drm_format(o->bpp, o->depth),
+					     tiling, &o->fb_info[0]);
+		o->fb_ids[1] = igt_create_fb_with_bo_size(drm_fd, o->fb_width, o->fb_height,
 					 igt_bpp_depth_to_drm_format(o->bpp, o->depth),
-					 tiling, &o->fb_info[1], bo_size, 0);
+							  tiling, &o->fb_info[1], bo_size, 0);
 
-	igt_assert(o->fb_ids[0]);
-	igt_assert(o->fb_ids[1]);
+		igt_assert(o->fb_ids[0]);
+		igt_assert(o->fb_ids[1]);
 
-	if (o->flags & TEST_FB_BAD_TILING) {
-		o->fb_ids[2] = igt_create_fb(drm_fd, o->fb_width, o->fb_height,
-				igt_bpp_depth_to_drm_format(o->bpp, o->depth),
-				LOCAL_I915_FORMAT_MOD_X_TILED, &o->fb_info[2]);
-		igt_require(o->fb_ids[2]);
+		if (o->flags & TEST_FB_BAD_TILING) {
+			o->fb_ids[2] = igt_create_fb(drm_fd, o->fb_width, o->fb_height,
+						     igt_bpp_depth_to_drm_format(o->bpp, o->depth),
+						     LOCAL_I915_FORMAT_MOD_X_TILED, &o->fb_info[2]);
+			igt_require(o->fb_ids[2]);
+		}
+		paint_flip_mode(&o->fb_info[0], 4, 1);
+		if (!(o->flags & TEST_BO_TOOBIG))
+			paint_flip_mode(&o->fb_info[1], 4, 2);
+		if (o->fb_ids[2])
+			paint_flip_mode(&o->fb_info[2], 4, 2);
+
+		if (o->flags & TEST_FB_BAD_TILING)
+			set_y_tiling(o, 2);
 	}
 
-	paint_flip_mode(&o->fb_info[0], false);
-	if (!(o->flags & TEST_BO_TOOBIG))
-		paint_flip_mode(&o->fb_info[1], true);
-	if (o->fb_ids[2])
-		paint_flip_mode(&o->fb_info[2], true);
-
-	if (o->flags & TEST_FB_BAD_TILING)
-		set_y_tiling(o, 2);
-
 	for (i = 0; i < o->count; i++)
 		kmstest_dump_mode(&o->kmode[i]);
 
@@ -1635,7 +1691,7 @@ int main(int argc, char **argv)
 					"blt-wf_vblank-vs-modeset" },
 		{ 60,  TEST_VBLANK | TEST_MODESET | TEST_WITH_DUMMY_RCS,
 					"rcs-wf_vblank-vs-modeset" },
-		{ 10, TEST_FLIP | TEST_BASIC, "plain-flip" },
+		{ 10, TEST_FLIP | TEST_BASIC | TEST_CRC, "plain-flip-crc" },
 		{ 30, TEST_FLIP | TEST_EBUSY , "busy-flip" },
 		{ 30, TEST_FLIP | TEST_FENCE_STRESS , "flip-vs-fences" },
 		{ 30, TEST_FLIP | TEST_CHECK_TS, "plain-flip-ts-check" },
