diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 5fd100b..4f77fb2 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -55,6 +55,7 @@ i915-y += intel_audio.o \
 	  intel_overlay.o \
 	  intel_psr.o \
 	  intel_drrs.o \
+	  intel_dsi_drrs.o \
 	  intel_sideband.o \
 	  intel_sprite.o
 i915-$(CONFIG_ACPI)		+= intel_acpi.o intel_opregion.o
diff --git a/drivers/gpu/drm/i915/intel_drrs.c b/drivers/gpu/drm/i915/intel_drrs.c
index eb67909..2a776d2 100644
--- a/drivers/gpu/drm/i915/intel_drrs.c
+++ b/drivers/gpu/drm/i915/intel_drrs.c
@@ -19,6 +19,7 @@
 
 #include "i915_drv.h"
 #include "intel_drv.h"
+#include "intel_dsi.h"
 #include "intel_drrs.h"
 
 int get_drrs_struct_index_for_pipe(struct drm_i915_private *dev_priv, int pipe)
@@ -354,6 +355,7 @@ int intel_drrs_init(struct drm_device *dev,
 					struct drm_display_mode *fixed_mode)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_encoder *intel_encoder = intel_connector->encoder;
 	struct i915_drrs *drrs;
 	int ret = 0, index;
 
@@ -384,6 +386,14 @@ int intel_drrs_init(struct drm_device *dev,
 	drrs = dev_priv->drrs[index];
 	drrs->connector = intel_connector;
 
+	if (intel_encoder->type == INTEL_OUTPUT_DSI) {
+		drrs->encoder_ops = get_intel_dsi_drrs_ops();
+	} else {
+		DRM_ERROR("DRRS: Unsupported Encoder\n");
+		ret = -EINVAL;
+		goto err_out;
+	}
+
 	if (!drrs->encoder_ops) {
 		DRM_ERROR("Encoder ops not initialized\n");
 		ret = -EINVAL;
diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h
index 2784ac4..129f68e 100644
--- a/drivers/gpu/drm/i915/intel_dsi.h
+++ b/drivers/gpu/drm/i915/intel_dsi.h
@@ -28,6 +28,7 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_mipi_dsi.h>
 #include "intel_drv.h"
+#include "intel_dsi_drrs.h"
 
 /* Dual Link support */
 #define DSI_DUAL_LINK_NONE		0
@@ -47,6 +48,8 @@ struct intel_dsi {
 	/* bit mask of ports being driven */
 	u16 ports;
 
+	struct dsi_drrs dsi_drrs;
+
 	/* if true, use HS mode, otherwise LP */
 	bool hs;
 
diff --git a/drivers/gpu/drm/i915/intel_dsi_drrs.c b/drivers/gpu/drm/i915/intel_dsi_drrs.c
new file mode 100644
index 0000000..6ab0e9e
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_dsi_drrs.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2015, Intel Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Author:
+ * Ramalingam C <ramalingam.c@intel.com>
+ */
+
+#include <drm/i915_drm.h>
+#include <linux/delay.h>
+
+#include "intel_drv.h"
+#include "intel_dsi.h"
+
+/* Work function for DSI deferred work */
+static void intel_mipi_drrs_work_fn(struct work_struct *__work)
+{
+	struct intel_mipi_drrs_work *work =
+				container_of(to_delayed_work(__work),
+					struct intel_mipi_drrs_work, work);
+	struct i915_drrs *drrs = work->drrs;
+	struct intel_encoder *intel_encoder = drrs->connector->encoder;
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&intel_encoder->base);
+	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
+	struct dsi_mnp *dsi_mnp;
+	struct drm_display_mode *prev_mode = NULL;
+	bool fallback_attempt = false;
+	int ret, retry_cnt = 3;
+
+init:
+	dsi_mnp = &dsi_drrs->mnp[work->target_rr_type];
+	DRM_DEBUG("Refresh rate Type: %d-->%d\n",
+					drrs->drrs_state.current_rr_type,
+						work->target_rr_type);
+	DRM_DEBUG("Target RR: %d\n", work->target_mode->vrefresh);
+
+retry:
+	if (!intel_crtc || !intel_crtc->active)
+		goto out;
+
+	ret = dsi_drrs->ops->configure_dsi_pll(intel_encoder, dsi_mnp);
+	if (ret == 0) {
+
+		/* PLL Programming is successful */
+		mutex_lock(&drrs->drrs_mutex);
+		drrs->drrs_state.current_rr_type = work->target_rr_type;
+		mutex_unlock(&drrs->drrs_mutex);
+		DRM_INFO("Refresh Rate set to : %dHz\n",
+						work->target_mode->vrefresh);
+
+		/* TODO: Update crtc mode and drain ladency with watermark */
+
+	} else if (ret == -ETIMEDOUT && retry_cnt) {
+
+		/* Timed out. But still attempts are allowed */
+		retry_cnt--;
+		DRM_DEBUG("Retry left ... <%d>\n", retry_cnt);
+		goto retry;
+	} else if (ret == -EACCES && !fallback_attempt) {
+
+		/*
+		 * PLL Didn't lock for the programmed value
+		 * fall back to prev mode
+		 */
+		DRM_ERROR("Falling back to the previous DRRS state. %d->%d\n",
+					work->target_rr_type,
+					drrs->drrs_state.current_rr_type);
+
+		mutex_lock(&drrs->drrs_mutex);
+		drrs->drrs_state.target_rr_type =
+					drrs->drrs_state.current_rr_type;
+		mutex_unlock(&drrs->drrs_mutex);
+
+		work->target_rr_type = drrs->drrs_state.target_rr_type;
+		drm_mode_destroy(intel_encoder->base.dev, work->target_mode);
+
+		if (work->target_rr_type == DRRS_HIGH_RR)
+			prev_mode = drrs->connector->panel.fixed_mode;
+		else if (work->target_rr_type == DRRS_LOW_RR)
+			prev_mode = drrs->connector->panel.downclock_mode;
+
+		work->target_mode = drm_mode_duplicate(intel_encoder->base.dev,
+								prev_mode);
+		fallback_attempt = true;
+		goto init;
+	} else {
+
+		/*
+		 * All attempts are failed or Fall back
+		 * mode all didn't go through.
+		 */
+		if (fallback_attempt)
+			DRM_ERROR("DRRS State Fallback attempt failed\n");
+		if (ret == -ETIMEDOUT)
+			DRM_ERROR("TIMEDOUT in all retry attempt\n");
+	}
+
+out:
+	drm_mode_destroy(intel_encoder->base.dev, work->target_mode);
+	work->work_completed = true;
+}
+
+/* Whether DRRS_HR_STATE is pending in the dsi deferred work */
+bool intel_dsi_is_drrs_hr_state_pending(struct i915_drrs *drrs)
+{
+	struct intel_dsi *intel_dsi =
+			enc_to_intel_dsi(&drrs->connector->encoder->base);
+	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
+	struct intel_mipi_drrs_work *work = dsi_drrs->mipi_drrs_work;
+
+	if (work_busy(&work->work.work) && work->target_rr_type == DRRS_HIGH_RR)
+		return true;
+	return false;
+}
+
+void intel_dsi_set_drrs_state(struct i915_drrs *drrs)
+{
+	struct intel_encoder *intel_encoder = drrs->connector->encoder;
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&intel_encoder->base);
+	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
+	struct drm_display_mode *target_mode =
+				drrs->connector->panel.target_mode;
+	struct intel_mipi_drrs_work *work = dsi_drrs->mipi_drrs_work;
+	unsigned int ret;
+
+	ret = work_busy(&work->work.work);
+	if (ret) {
+		if (work->target_mode)
+			if (work->target_mode->vrefresh ==
+						target_mode->vrefresh) {
+				DRM_INFO("Repeated request for %dHz\n",
+							target_mode->vrefresh);
+				return;
+			}
+		DRM_DEBUG("Cancelling an queued/executing work\n");
+		atomic_set(&work->abort_wait_loop, 1);
+		cancel_delayed_work_sync(&work->work);
+		atomic_set(&work->abort_wait_loop, 0);
+		if ((ret & WORK_BUSY_PENDING) && !work->work_completed)
+			drm_mode_destroy(intel_encoder->base.dev,
+							work->target_mode);
+	}
+
+	work->work_completed = false;
+	work->drrs = drrs;
+	work->target_rr_type = drrs->drrs_state.target_rr_type;
+	work->target_mode = drm_mode_duplicate(intel_encoder->base.dev,
+								target_mode);
+	schedule_delayed_work(&work->work, 0);
+}
+
+/* DSI deferred function init*/
+int intel_dsi_drrs_deferred_work_init(struct i915_drrs *drrs)
+{
+	struct intel_encoder *intel_encoder = drrs->connector->encoder;
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&intel_encoder->base);
+	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
+	struct intel_mipi_drrs_work *work;
+
+	work = kzalloc(sizeof(struct intel_mipi_drrs_work), GFP_KERNEL);
+	if (!work) {
+		DRM_ERROR("Failed to allocate mipi DRRS work structure\n");
+		return -ENOMEM;
+	}
+
+	atomic_set(&work->abort_wait_loop, 0);
+	INIT_DELAYED_WORK(&work->work, intel_mipi_drrs_work_fn);
+	work->target_mode = NULL;
+	work->work_completed = true;
+
+	dsi_drrs->mipi_drrs_work = work;
+	return 0;
+}
+
+/* Based on the VBT's min supported vrefresh, downclock mode will be created */
+struct drm_display_mode *
+intel_dsi_calc_panel_downclock(struct i915_drrs *drrs,
+			struct drm_display_mode *fixed_mode)
+{
+	struct intel_encoder *intel_encoder = drrs->connector->encoder;
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&intel_encoder->base);
+	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
+	struct drm_display_mode *downclock_mode = NULL;
+
+	if (dsi_drrs->min_vrefresh == 0 ||
+			dsi_drrs->min_vrefresh >= fixed_mode->vrefresh) {
+		DRM_ERROR("Invalid min Vrefresh. %d\n", dsi_drrs->min_vrefresh);
+		return NULL;
+	}
+
+	/* Allocate */
+	downclock_mode =
+			drm_mode_duplicate(intel_encoder->base.dev, fixed_mode);
+	if (!downclock_mode) {
+		DRM_ERROR("Downclock mode allocation failed. No memory\n");
+		return NULL;
+	}
+
+	downclock_mode->vrefresh = dsi_drrs->min_vrefresh;
+	DRM_DEBUG("drrs_min_vrefresh = %u\n", downclock_mode->vrefresh);
+	downclock_mode->clock = downclock_mode->vrefresh *
+		downclock_mode->vtotal * downclock_mode->htotal / 1000;
+
+	return downclock_mode;
+}
+
+/* Main init Enrty for DSI DRRS module */
+int intel_dsi_drrs_init(struct i915_drrs *drrs,
+					struct drm_display_mode *fixed_mode)
+{
+	struct intel_encoder *intel_encoder = drrs->connector->encoder;
+	struct drm_i915_private *dev_priv =
+					intel_encoder->base.dev->dev_private;
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&intel_encoder->base);
+	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
+	struct intel_panel *panel = &drrs->connector->panel;
+	struct drm_display_mode *downclock_mode;
+	int ret = 0;
+
+	dsi_drrs->min_vrefresh = dev_priv->vbt.drrs_min_vrefresh;
+
+	if (fixed_mode->vrefresh == 0)
+		fixed_mode->vrefresh = drm_mode_vrefresh(fixed_mode);
+
+	/* Modes Initialization */
+	downclock_mode = intel_dsi_calc_panel_downclock(drrs, fixed_mode);
+	if (!downclock_mode) {
+		DRM_ERROR("Downclock mode not Found\n");
+		ret = -ENOMEM;
+		goto out_err_1;
+	}
+
+	DRM_DEBUG("downclock_mode :\n");
+	drm_mode_debug_printmodeline(downclock_mode);
+
+	panel->target_mode = NULL;
+
+	if (!dsi_drrs->ops || !dsi_drrs->ops->mnp_calculate_for_mode ||
+					!dsi_drrs->ops->configure_dsi_pll) {
+		DRM_ERROR("DSI platform ops not initialized\n");
+		ret = -EINVAL;
+		goto out_err_2;
+	}
+
+	/* Calculate mnp for fixed and downclock modes */
+	ret = dsi_drrs->ops->mnp_calculate_for_mode(
+			intel_encoder, &dsi_drrs->mnp[DRRS_HIGH_RR],
+			fixed_mode);
+	if (ret < 0)
+		goto out_err_2;
+
+	ret = dsi_drrs->ops->mnp_calculate_for_mode(
+			intel_encoder, &dsi_drrs->mnp[DRRS_LOW_RR],
+			downclock_mode);
+	if (ret < 0)
+		goto out_err_2;
+
+	ret = intel_dsi_drrs_deferred_work_init(drrs);
+	if (ret < 0)
+		goto out_err_2;
+
+	/* In DSI SEAMLESS DRRS is a SW driven feature */
+	drrs->drrs_state.type = SEAMLESS_DRRS_SUPPORT_SW;
+	intel_panel_init(panel, fixed_mode, downclock_mode);
+
+	return ret;
+
+out_err_2:
+	drm_mode_destroy(intel_encoder->base.dev, downclock_mode);
+out_err_1:
+	return ret;
+}
+
+void intel_dsi_drrs_exit(struct i915_drrs *drrs)
+{
+	struct intel_encoder *intel_encoder = drrs->connector->encoder;
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&intel_encoder->base);
+	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
+	struct intel_mipi_drrs_work *work = dsi_drrs->mipi_drrs_work;
+	unsigned int ret;
+
+	ret = work_busy(&work->work.work);
+	if (ret) {
+		DRM_DEBUG("Cancelling an queued/executing work\n");
+		atomic_set(&work->abort_wait_loop, 1);
+		cancel_delayed_work_sync(&work->work);
+		atomic_set(&work->abort_wait_loop, 0);
+		if ((ret & WORK_BUSY_PENDING) && !work->work_completed)
+			drm_mode_destroy(intel_encoder->base.dev,
+							work->target_mode);
+	}
+
+	drm_mode_destroy(intel_encoder->base.dev,
+				drrs->connector->panel.downclock_mode);
+	drrs->connector->panel.downclock_mode = NULL;
+
+	kfree(dsi_drrs->mipi_drrs_work);
+	drrs->drrs_state.type = DRRS_NOT_SUPPORTED;
+}
+
+struct drrs_encoder_ops drrs_dsi_ops = {
+	.init = intel_dsi_drrs_init,
+	.exit = intel_dsi_drrs_exit,
+	.set_drrs_state = intel_dsi_set_drrs_state,
+	.is_drrs_hr_state_pending = intel_dsi_is_drrs_hr_state_pending,
+};
+
+/* Call back Function for Intel_drrs module to get the dsi func ptr */
+inline struct drrs_encoder_ops *get_intel_dsi_drrs_ops(void)
+{
+	return &drrs_dsi_ops;
+}
diff --git a/drivers/gpu/drm/i915/intel_dsi_drrs.h b/drivers/gpu/drm/i915/intel_dsi_drrs.h
new file mode 100644
index 0000000..27736a0
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_dsi_drrs.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015, Intel Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Author:
+ * Ramalingam C <ramalingam.c@intel.com>
+ */
+
+#ifndef INTEL_DSI_DRRS_H
+#define INTEL_DSI_DRRS_H
+
+struct dsi_mnp {
+	u32 dsi_pll_ctrl;
+	u32 dsi_pll_div;
+};
+
+struct drrs_dsi_platform_ops {
+	int (*configure_dsi_pll)(struct intel_encoder *encoder,
+						struct dsi_mnp *dsi_mnp);
+	int (*mnp_calculate_for_mode)(struct intel_encoder *encoder,
+				struct dsi_mnp *dsi_mnp,
+				struct drm_display_mode *mode);
+};
+
+/**
+ * MIPI PLL register dont have a option to perform a seamless
+ * PLL divider change. To simulate that operation in SW we are using
+ * this deferred work
+ */
+struct intel_mipi_drrs_work {
+	struct delayed_work work;
+	struct i915_drrs *drrs;
+
+	/* Target Refresh rate type and the target mode */
+	enum drrs_refresh_rate_type target_rr_type;
+	struct drm_display_mode *target_mode;
+
+	/* Atomic variable to terminate any executing deferred work */
+	atomic_t abort_wait_loop;
+
+	/* To indicate the scheduled work completion */
+	bool work_completed;
+};
+
+struct dsi_drrs {
+	struct intel_mipi_drrs_work *mipi_drrs_work;
+	struct dsi_mnp mnp[DRRS_MAX_RR];
+	int min_vrefresh;
+	struct drrs_dsi_platform_ops *ops;
+};
+
+extern inline struct drrs_encoder_ops *get_intel_dsi_drrs_ops(void);
+#endif /* INTEL_DSI_DRRS_H */
diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c
index d20cf37..c58eb02 100644
--- a/drivers/gpu/drm/i915/intel_dsi_pll.c
+++ b/drivers/gpu/drm/i915/intel_dsi_pll.c
@@ -38,11 +38,6 @@
 #define DSI_HFP_PACKET_EXTRA_SIZE	6
 #define DSI_EOTP_PACKET_SIZE		4
 
-struct dsi_mnp {
-	u32 dsi_pll_ctrl;
-	u32 dsi_pll_div;
-};
-
 static const u32 lfsr_converts[] = {
 	426, 469, 234, 373, 442, 221, 110, 311, 411,		/* 62 - 70 */
 	461, 486, 243, 377, 188, 350, 175, 343, 427, 213,	/* 71 - 80 */
