diff --git a/tests/kms_frontbuffer_tracking.c b/tests/kms_frontbuffer_tracking.c
index c24e4a8..4d46e1e 100644
--- a/tests/kms_frontbuffer_tracking.c
+++ b/tests/kms_frontbuffer_tracking.c
@@ -32,9 +32,18 @@
 #include <poll.h>
 #include <pthread.h>
 
+#include "drmtest.h"
+#include "igt_debugfs.h"
+#include "igt_kms.h"
+#include "intel_chipset.h"
+#include "intel_batchbuffer.h"
+#include "ioctl_wrappers.h"
+#include <time.h>
+#include <stdlib.h>
+#include <sys/time.h>
 
 IGT_TEST_DESCRIPTION("Test the Kernel's frontbuffer tracking mechanism and "
-		     "its related features: FBC and PSR");
+		     "its related features: DRRS, FBC and PSR");
 
 /*
  * One of the aspects of this test is that, for every subtest, we try different
@@ -327,6 +336,41 @@ drmModeModeInfo std_1024_mode = {
 	.name = "Custom 1024x768",
 };
 
+#define DRRS_TOLERANCE_THRESHOLD 2
+#define DRRS_POLL_TIMEOUT_PERIOD_MS 5000
+#define DRRS_STATUS_BYTES_CNT 1000
+#define DRRS_MAX_ITERATION 3
+
+/*
+ * Struct to hold drrs test related data
+ */
+typedef struct {
+	uint32_t devid;
+	uint32_t handle[2];
+	igt_display_t display;
+	igt_output_t *output;
+	enum pipe pipe;
+	igt_plane_t *primary;
+	struct igt_fb fb[2];
+	uint32_t fb_id[2];
+} drrs_data_t;
+
+/*
+ * Structure to count vblank and note the starting time of the counter
+ */
+typedef struct {
+	unsigned int vbl_count;
+	struct timeval start;
+} vbl_info;
+
+/*
+ * Structure for refresh rate type
+ */
+typedef struct{
+	int rate;
+	const char *name;
+} refresh_rate_t;
+
 static drmModeModeInfoPtr get_connector_smallest_mode(drmModeConnectorPtr c)
 {
 	int i;
@@ -3415,6 +3459,410 @@ static const char *flip_str(enum flip_type flip)
 
 #define TEST_MODE_ITER_END } } } } } }
 
+static inline uint32_t pipe_select(int pipe)
+{
+	if (pipe > 1)
+		return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
+	else if (pipe > 0)
+		return DRM_VBLANK_SECONDARY;
+	else
+		return DRM_VBLANK_ABSOLUTE;
+}
+
+/*
+ * Calculates the total no. of millisec elapsed since timeval start
+ */
+static double igt_millisec_elapsed(const struct timeval *start)
+{
+	struct timeval curr;
+
+	gettimeofday(&curr, NULL);
+	return (1e3*(curr.tv_sec - start->tv_sec) +
+				(curr.tv_usec - start->tv_usec)/1000.00);
+}
+
+/*
+ * Func to read the DRRS status from debugfs
+ */
+static bool read_drrs_status(char *str)
+{
+	FILE *fp;
+	int fd;
+	int cnt;
+
+	fd = igt_debugfs_open(drm.fd, "i915_drrs_status", O_RDONLY);
+	igt_assert(fd);
+	fp = fdopen(fd, "r");
+	igt_require(fp);
+	cnt = fread(str, DRRS_STATUS_BYTES_CNT - 1, 1, fp);
+
+	if (!cnt) {
+		if (!feof(fp)) {
+			igt_critical("Failed to read i915_drrs_status:%d \n",
+				ferror(fp));
+			return false;
+		}
+		clearerr(fp);
+	}
+	fclose(fp);
+
+	return true;
+}
+
+/*
+ * Func to check for DRRS support
+ */
+static bool is_drrs_supported(void)
+{
+	char str[DRRS_STATUS_BYTES_CNT] = {};
+
+	if (!read_drrs_status(str))
+		return false;
+
+	return strstr(str, "DRRS Supported: Yes") != NULL;
+}
+
+/*
+ * Func to check if DRRS is enabled by driver.
+ */
+static bool is_drrs_enabled(void)
+{
+	char str[DRRS_STATUS_BYTES_CNT] = {};
+
+	if (!read_drrs_status(str))
+		return false;
+
+	return strstr(str, "Idleness DRRS: Disabled") == NULL;
+}
+
+
+/*
+ * vbl_rate = vbl_count/time taken
+ */
+static double vbl_rate(const union drm_wait_vblank *start,
+				const union drm_wait_vblank *end)
+{
+	double s, e;
+
+	s = start->reply.tval_sec + 1e-6 * start->reply.tval_usec;
+	e = end->reply.tval_sec + 1e-6 * end->reply.tval_usec;
+	return ((end->reply.sequence - start->reply.sequence) / (e - s));
+}
+
+/*
+ * refresh_rate = (20 vblanks) /(time for 20vblanks)
+ */
+int calculate_refresh_rate(drrs_data_t *data)
+{
+	union drm_wait_vblank start, end;
+	struct timeval start_tv;
+	int refresh_rate;
+
+	memset(&start, 0, sizeof(start));
+	start.request.type = DRM_VBLANK_RELATIVE | pipe_select(data->pipe);
+
+	if (drmWaitVBlank(drm.fd, &start) != 0) {
+		igt_critical("drmWaitVBlank Failed!\n");
+		return -1;
+	}
+	gettimeofday(&start_tv, NULL);
+	memset(&end, 0, sizeof(end));
+	end.request.type = DRM_VBLANK_RELATIVE | pipe_select(data->pipe);
+
+	/* Configured to wait for 20 vblank events*/
+	end.request.sequence = 20;
+
+	if (drmWaitVBlank(drm.fd, &end) != 0) {
+		igt_critical("drmWaitVBlank Failed!\n");
+		return -1;
+	}
+	refresh_rate = vbl_rate(&start, &end);
+
+	return refresh_rate;
+}
+
+/*
+ * Poll for DRRS transition from high to low with 5 seconds time out.
+ */
+int wait_for_drrs_switch_to_low(drrs_data_t *data)
+{
+	char drrs_status[DRRS_STATUS_BYTES_CNT] = {};
+	const char *drrs_low_name = "DRRS_LOW_RR";
+	int status = 1;
+	struct timeval start_tv;
+
+	gettimeofday(&start_tv, NULL);
+
+	while (igt_millisec_elapsed(&start_tv) < DRRS_POLL_TIMEOUT_PERIOD_MS) {
+
+		if (!read_drrs_status(drrs_status)) {
+			status = -1;
+			break;
+		}
+
+		if (strstr(drrs_status, drrs_low_name) != NULL)
+			break;
+	}
+
+	if (igt_millisec_elapsed(&start_tv) > DRRS_POLL_TIMEOUT_PERIOD_MS) {
+
+		igt_critical("DRRS failed to switch refresh rate from "
+			"higher to lower\n");
+
+		status = -1;
+	}
+
+	return status;
+}
+
+/*
+ * Check if calulated refresh rate is same as expected refresh rate
+ * Returns 0 in case of pass , 1 in case of failure, and -1 for error.
+ */
+static int check_refresh_rate(drrs_data_t *data, refresh_rate_t *expected_rr)
+{
+	int refresh_rate = -1;
+	char drrs_status[DRRS_STATUS_BYTES_CNT] = {};
+
+	/* Get the DRRS Status from the debugfs entry */
+	if (!read_drrs_status(drrs_status))
+		return -1;
+
+	refresh_rate = calculate_refresh_rate(data);
+
+	if (refresh_rate < 0) {
+		igt_critical("Refresh rate calculation FAILED\n");
+		return -1;
+	}
+
+	/* Compare with Expected Refresh Rate */
+	if (strstr(drrs_status, expected_rr->name) != NULL
+	&& abs(refresh_rate - expected_rr->rate) <= DRRS_TOLERANCE_THRESHOLD) {
+		return 0;
+	}
+	igt_critical("Expected %s : FAILED.\n", expected_rr->name);
+
+	return 1;
+}
+
+/*
+ * This function
+ * 1. Creates framebuffers
+ * 2. Apply framebuffers alternatively and count the vblank refresh rate
+ *    which should be equal to highest refresh rate supported.
+ * 3. Poll for DRRS to toggle from DRRS_HIGH_RR -> DRRS_LOW_RR with 5sec
+ *    timeout using kernel debugfs entry(i915_drrs_status).
+ * 4. Once DRRS switches to LOW we count the vblank refresh rate which
+ *    should be equal to lowest refresh rate supported.
+ * 5. The above calculated vblank refresh rates can have a tolerance of 2.
+ */
+static int execute_test(drrs_data_t *data)
+{
+	igt_display_t *display = &data->display;
+	igt_output_t *output = data->output;
+	drmModeModeInfo *mode, *supported_modes;
+	int test_failed = 0;
+	int ret, i, i_mod, count_modes;
+	refresh_rate_t high_rr, low_rr;
+
+	high_rr.name = "DRRS_HIGH_RR";
+	high_rr.rate = 0;
+	low_rr.name = "DRRS_LOW_RR";
+	low_rr.rate = 0;
+
+	/* get the max and min supported refresh rates for the display */
+	supported_modes = output->config.connector->modes;
+	count_modes = output->config.connector->count_modes;
+
+	/* minimum 2 modes are required for DRRS */
+	igt_assert_f(count_modes >= 2, "Minimum 2 modes required for DRRS\n");
+
+	for (i = 0; i < count_modes; i++) {
+		int rr = supported_modes[i].vrefresh;
+
+		if (i == 0) {
+			high_rr.rate = low_rr.rate = rr;
+			continue;
+		}
+
+		if (high_rr.rate < rr)
+			high_rr.rate = rr;
+
+		if (low_rr.rate > rr)
+			low_rr.rate = rr;
+	}
+
+	igt_output_set_pipe(output, data->pipe);
+	data->primary = igt_output_get_plane(data->output,
+				DRM_PLANE_TYPE_OVERLAY);
+	mode = igt_output_get_mode(data->output);
+	data->fb_id[0] = igt_create_color_fb(drm.fd, mode->hdisplay,
+						mode->vdisplay,
+						DRM_FORMAT_XRGB8888,
+						LOCAL_DRM_FORMAT_MOD_NONE,
+						0.0, 100.1, 0.0, &data->fb[0]);
+
+	igt_assert(data->fb_id[0]);
+	data->fb_id[1] = igt_create_color_fb(drm.fd, mode->hdisplay,
+						mode->vdisplay,
+						DRM_FORMAT_XRGB8888,
+						LOCAL_DRM_FORMAT_MOD_NONE,
+						100.1, 0.0, 0.0,
+						&data->fb[1]);
+
+	igt_assert(data->fb_id[1]);
+	data->handle[0] = data->fb[0].gem_handle;
+	data->handle[1] = data->fb[1].gem_handle;
+
+	for (i = 1; i <= DRRS_MAX_ITERATION; i++) {
+		i_mod = i % 2;
+		igt_plane_set_fb(data->primary, &data->fb[i_mod]);
+		igt_display_commit(display);
+
+		if (!is_drrs_enabled()) {
+			igt_critical("DRRS not enabled\n");
+			igt_plane_set_fb(data->primary, NULL);
+			igt_output_set_pipe(output, PIPE_ANY);
+			igt_display_commit(display);
+			igt_remove_fb(drm.fd, &data->fb[0]);
+			igt_remove_fb(drm.fd, &data->fb[1]);
+			return -1;
+		}
+
+		/* expecting High RR */
+		ret =  check_refresh_rate(data, &high_rr);
+
+		if (ret == -1)
+			return -1;
+
+		if (ret == 1)
+			test_failed = 1;
+
+		/*
+		 * Poll kernel debugfs entry for DRRS
+		 * transition from High to Low
+		 */
+		ret = wait_for_drrs_switch_to_low(data);
+
+		if (ret == -1)
+			return 1;
+
+		/* expecting Low RR */
+		ret = check_refresh_rate(data, &low_rr);
+
+		if (ret == -1)
+			return -1;
+
+		if (ret == 1)
+			test_failed = 1;
+	}
+
+	return test_failed;
+}
+
+/*
+ * Func to free the framebuffers after the test completion.
+ */
+static void finish_crtc(drrs_data_t *data)
+{
+	igt_plane_set_fb(data->primary, NULL);
+	igt_output_set_pipe(data->output, PIPE_ANY);
+	igt_display_commit(&data->display);
+
+	igt_remove_fb(drm.fd, &data->fb[0]);
+	igt_remove_fb(drm.fd, &data->fb[1]);
+}
+
+/*
+ * Func to reset the display structures after the test completion.
+ */
+static void reset_display(drrs_data_t *data)
+{
+	igt_display_t *display = &data->display;
+	enum pipe pipe_id;
+
+	for_each_pipe(display, pipe_id) {
+		igt_pipe_t *pipe = &display->pipes[pipe_id];
+		igt_plane_t *plane = igt_pipe_get_plane_type(pipe,
+					DRM_PLANE_TYPE_PRIMARY);
+
+		if (plane->fb)
+			igt_plane_set_fb(plane, NULL);
+	}
+
+	for_each_connected_output(display, data->output)
+		igt_output_set_pipe(data->output, PIPE_ANY);
+}
+
+/*
+ * Func to run the drrs test for the eDP display.
+ */
+static void run_test(drrs_data_t *data)
+{
+	int ret;
+	igt_display_t *display = &data->display;
+
+	reset_display(data);
+
+	for_each_pipe_with_valid_output(display, data->pipe, data->output) {
+		drmModeConnectorPtr c = data->output->config.connector;
+
+		if (c->connector_type != DRM_MODE_CONNECTOR_eDP ||
+			c->connection != DRM_MODE_CONNECTED)
+			continue;
+
+		ret = execute_test(data);
+
+		igt_skip_on_f(ret == -1,
+				"%s on pipe %s, connector %s:SKIPPED\n",
+					igt_subtest_name(),
+					kmstest_pipe_name(data->pipe),
+					igt_output_name(data->output));
+
+		igt_fail_on_f(ret == 1,
+				"%s on pipe %s, connector %s:FAILED\n",
+					igt_subtest_name(),
+					kmstest_pipe_name(data->pipe),
+					igt_output_name(data->output));
+
+		igt_assert_f(ret == 0,
+				"%s on pipe %s, connector %s: PASSED\n",
+					igt_subtest_name(),
+					kmstest_pipe_name(data->pipe),
+					igt_output_name(data->output));
+
+		finish_crtc(data);
+	}
+}
+
+/*
+ * Function to test edp-DRRS feature.Exits from the function if PSR is enabled
+ */
+void edp_drrs_test(void)
+{
+	drrs_data_t data = {};
+
+	igt_assert_f(!psr.can_test,
+			"DRRS cannot be tested as PSR is enabled\n");
+	igt_skip_on_simulation();
+
+	/*
+	 * Using the same drm.fd which was opened during setup_environment
+	 */
+	igt_assert_f(drm.fd != -1, "Invalid fd\n");
+	data.devid = intel_get_drm_devid(drm.fd);
+	igt_assert_f(data.devid >= 0, "Invalid dev id\n");
+
+	/*
+	 * Check if the DRRS is supported.If yes call the Idleness DRRS test
+	 */
+	igt_require_f(is_drrs_supported(),
+			"DRRS not supported:check VBT/panel caps\n");
+	igt_display_init(&data.display, drm.fd);
+	run_test(&data);
+	igt_display_fini(&data.display);
+}
+
 int main(int argc, char *argv[])
 {
 	struct test_mode t;
@@ -3628,6 +4076,9 @@ int main(int argc, char *argv[])
 			suspend_subtest(&t);
 	TEST_MODE_ITER_END
 
+	igt_subtest_f("edp-DRRS")
+		edp_drrs_test();
+
 	t.pipes = PIPE_SINGLE;
 	t.screen = SCREEN_PRIM;
 	t.plane = PLANE_PRI;
