return 0;
 }
 
-static void drrs_status_per_crtc(struct seq_file *m,
-                                struct drm_device *dev,
-                                struct intel_crtc *crtc)
+static int i915_drrs_status(struct seq_file *m, void *unused)
 {
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct i915_drrs *drrs = &dev_priv->drrs;
-       struct intel_connector *connector;
+       struct drm_i915_private *dev_priv = node_to_i915(m->private);
        struct drm_connector_list_iter conn_iter;
+       struct intel_connector *connector;
+       struct intel_crtc *crtc;
 
-       drm_connector_list_iter_begin(dev, &conn_iter);
+       drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
        for_each_intel_connector_iter(connector, &conn_iter) {
-               if (connector->base.state->crtc != &crtc->base)
-                       continue;
-
                seq_printf(m, "[CONNECTOR:%d:%s] DRRS type: %s\n",
                           connector->base.base.id, connector->base.name,
                           intel_drrs_type_str(intel_panel_drrs_type(connector)));
 
        seq_puts(m, "\n");
 
-       if (to_intel_crtc_state(crtc->base.state)->has_drrs) {
-               mutex_lock(&drrs->mutex);
-               /* DRRS Supported */
-               seq_puts(m, "\tDRRS Enabled: Yes\n");
+       for_each_intel_crtc(&dev_priv->drm, crtc) {
+               seq_printf(m, "[CRTC:%d:%s]:\n",
+                          crtc->base.base.id, crtc->base.name);
 
-               /* disable_drrs() will make drrs->dp NULL */
-               if (!drrs->crtc) {
-                       seq_puts(m, "Idleness DRRS: Disabled\n");
-                       mutex_unlock(&drrs->mutex);
-                       return;
-               }
+               mutex_lock(&crtc->drrs.mutex);
 
-               seq_printf(m, "\t\tBusy_frontbuffer_bits: 0x%X",
-                                       drrs->busy_frontbuffer_bits);
+               /* DRRS Supported */
+               seq_printf(m, "\tDRRS Enabled: %s\n",
+                          str_yes_no(intel_drrs_is_enabled(crtc)));
 
-               seq_puts(m, "\n\t\t");
+               seq_printf(m, "\tBusy_frontbuffer_bits: 0x%X\n",
+                          crtc->drrs.busy_frontbuffer_bits);
 
                seq_printf(m, "DRRS refresh rate: %s\n",
-                          drrs->refresh_rate == DRRS_REFRESH_RATE_LOW ?
+                          crtc->drrs.refresh_rate == DRRS_REFRESH_RATE_LOW ?
                           "low" : "high");
-               seq_puts(m, "\n\t\t");
-
-               mutex_unlock(&drrs->mutex);
-       } else {
-               /* DRRS not supported. Print the VBT parameter*/
-               seq_puts(m, "\tDRRS Enabled : No");
-       }
-       seq_puts(m, "\n");
-}
 
-static int i915_drrs_status(struct seq_file *m, void *unused)
-{
-       struct drm_i915_private *dev_priv = node_to_i915(m->private);
-       struct drm_device *dev = &dev_priv->drm;
-       struct intel_crtc *crtc;
-       int active_crtc_cnt = 0;
-
-       drm_modeset_lock_all(dev);
-       for_each_intel_crtc(dev, crtc) {
-               if (crtc->base.state->active) {
-                       active_crtc_cnt++;
-                       seq_printf(m, "\nCRTC %d:  ", active_crtc_cnt);
-
-                       drrs_status_per_crtc(m, dev, crtc);
-               }
+               mutex_unlock(&crtc->drrs.mutex);
        }
-       drm_modeset_unlock_all(dev);
-
-       if (!active_crtc_cnt)
-               seq_puts(m, "No active crtc found\n");
 
        return 0;
 }
 
 }
 
 static void
-intel_drrs_set_refresh_rate_pipeconf(const struct intel_crtc_state *crtc_state,
+intel_drrs_set_refresh_rate_pipeconf(struct intel_crtc *crtc,
                                     enum drrs_refresh_rate refresh_rate)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
+       enum transcoder cpu_transcoder = crtc->drrs.cpu_transcoder;
        u32 val, bit;
 
        if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 }
 
 static void
-intel_drrs_set_refresh_rate_m_n(const struct intel_crtc_state *crtc_state,
+intel_drrs_set_refresh_rate_m_n(struct intel_crtc *crtc,
                                enum drrs_refresh_rate refresh_rate)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-
-       intel_cpu_transcoder_set_m1_n1(crtc, crtc_state->cpu_transcoder,
+       intel_cpu_transcoder_set_m1_n1(crtc, crtc->drrs.cpu_transcoder,
                                       refresh_rate == DRRS_REFRESH_RATE_LOW ?
-                                      &crtc_state->dp_m2_n2 : &crtc_state->dp_m_n);
+                                      &crtc->drrs.m2_n2 : &crtc->drrs.m_n);
 }
 
-static void intel_drrs_set_state(struct drm_i915_private *dev_priv,
-                                const struct intel_crtc_state *crtc_state,
-                                enum drrs_refresh_rate refresh_rate)
+bool intel_drrs_is_enabled(struct intel_crtc *crtc)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-
-       if (!dev_priv->drrs.crtc) {
-               drm_dbg_kms(&dev_priv->drm, "DRRS not supported.\n");
-               return;
-       }
-
-       if (!crtc) {
-               drm_dbg_kms(&dev_priv->drm,
-                           "DRRS: intel_crtc not initialized\n");
-               return;
-       }
-
-       if (dev_priv->vbt.drrs_type != DRRS_TYPE_SEAMLESS) {
-               drm_dbg_kms(&dev_priv->drm, "Only Seamless DRRS supported.\n");
-               return;
-       }
+       return crtc->drrs.cpu_transcoder != INVALID_TRANSCODER;
+}
 
-       if (refresh_rate == dev_priv->drrs.refresh_rate)
-               return;
+static void intel_drrs_set_state(struct intel_crtc *crtc,
+                                enum drrs_refresh_rate refresh_rate)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
-       if (!crtc_state->hw.active) {
-               drm_dbg_kms(&dev_priv->drm,
-                           "eDP encoder disabled. CRTC not Active\n");
+       if (refresh_rate == crtc->drrs.refresh_rate)
                return;
-       }
 
        if (DISPLAY_VER(dev_priv) >= 8 && !IS_CHERRYVIEW(dev_priv))
-               intel_drrs_set_refresh_rate_m_n(crtc_state, refresh_rate);
+               intel_drrs_set_refresh_rate_m_n(crtc, refresh_rate);
        else if (DISPLAY_VER(dev_priv) > 6)
-               intel_drrs_set_refresh_rate_pipeconf(crtc_state, refresh_rate);
-
-       dev_priv->drrs.refresh_rate = refresh_rate;
-
-       drm_dbg_kms(&dev_priv->drm, "eDP Refresh Rate set to : %s\n",
-                   refresh_rate == DRRS_REFRESH_RATE_LOW ? "low" : "high");
-}
-
-static void
-intel_drrs_enable_locked(struct intel_crtc *crtc)
-{
-       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+               intel_drrs_set_refresh_rate_pipeconf(crtc, refresh_rate);
 
-       dev_priv->drrs.busy_frontbuffer_bits = 0;
-       dev_priv->drrs.crtc = crtc;
+       crtc->drrs.refresh_rate = refresh_rate;
 }
 
 /**
        if (!crtc_state->has_drrs)
                return;
 
-       drm_dbg_kms(&dev_priv->drm, "Enabling DRRS\n");
-
-       mutex_lock(&dev_priv->drrs.mutex);
-
-       if (dev_priv->drrs.crtc) {
-               drm_warn(&dev_priv->drm, "DRRS already enabled\n");
-               goto unlock;
-       }
+       drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] Enabling DRRS\n",
+                   crtc->base.base.id, crtc->base.name);
 
-       intel_drrs_enable_locked(crtc);
+       mutex_lock(&crtc->drrs.mutex);
 
-unlock:
-       mutex_unlock(&dev_priv->drrs.mutex);
-}
-
-static void
-intel_drrs_disable_locked(const struct intel_crtc_state *crtc_state)
-{
-       struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+       crtc->drrs.cpu_transcoder = crtc_state->cpu_transcoder;
+       crtc->drrs.m_n = crtc_state->dp_m_n;
+       crtc->drrs.m2_n2 = crtc_state->dp_m2_n2;
+       crtc->drrs.busy_frontbuffer_bits = 0;
 
-       intel_drrs_set_state(dev_priv, crtc_state, DRRS_REFRESH_RATE_HIGH);
-       dev_priv->drrs.crtc = NULL;
+       mutex_unlock(&crtc->drrs.mutex);
 }
 
 /**
        if (!old_crtc_state->has_drrs)
                return;
 
-       mutex_lock(&dev_priv->drrs.mutex);
-       if (dev_priv->drrs.crtc != crtc) {
-               mutex_unlock(&dev_priv->drrs.mutex);
-               return;
-       }
+       drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] Disabling DRRS\n",
+                   crtc->base.base.id, crtc->base.name);
+
+       mutex_lock(&crtc->drrs.mutex);
+
+       if (intel_drrs_is_enabled(crtc))
+               intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_HIGH);
+
+       crtc->drrs.cpu_transcoder = INVALID_TRANSCODER;
+       crtc->drrs.busy_frontbuffer_bits = 0;
 
-       intel_drrs_disable_locked(old_crtc_state);
-       mutex_unlock(&dev_priv->drrs.mutex);
+       mutex_unlock(&crtc->drrs.mutex);
 
-       cancel_delayed_work_sync(&dev_priv->drrs.work);
+       cancel_delayed_work_sync(&crtc->drrs.work);
 }
 
 /**
- * intel_drrs_update - Update DRRS state
- * @crtc_state: new CRTC state
- *
- * This function will update DRRS states, disabling or enabling DRRS when
- * executing fastsets. For full modeset, intel_drrs_disable() and
- * intel_drrs_enable() should be called instead.
+ * intel_drrs_update - Update DRRS during fastset
+ * @state: atomic state
+ * @crtc: crtc
  */
-void
-intel_drrs_update(const struct intel_crtc_state *crtc_state)
+void intel_drrs_update(struct intel_atomic_state *state,
+                      struct intel_crtc *crtc)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       const struct intel_crtc_state *old_crtc_state =
+               intel_atomic_get_old_crtc_state(state, crtc);
+       const struct intel_crtc_state *new_crtc_state =
+               intel_atomic_get_new_crtc_state(state, crtc);
 
-       if (dev_priv->vbt.drrs_type != DRRS_TYPE_SEAMLESS)
+       if (old_crtc_state->has_drrs == new_crtc_state->has_drrs)
                return;
 
-       mutex_lock(&dev_priv->drrs.mutex);
-
-       /* New state matches current one? */
-       if (crtc_state->has_drrs == !!dev_priv->drrs.crtc)
-               goto unlock;
-
-       if (crtc_state->has_drrs)
-               intel_drrs_enable_locked(crtc);
+       if (new_crtc_state->has_drrs)
+               intel_drrs_enable(new_crtc_state);
        else
-               intel_drrs_disable_locked(crtc_state);
-
-unlock:
-       mutex_unlock(&dev_priv->drrs.mutex);
+               intel_drrs_disable(old_crtc_state);
 }
 
 static void intel_drrs_downclock_work(struct work_struct *work)
 {
-       struct drm_i915_private *dev_priv =
-               container_of(work, typeof(*dev_priv), drrs.work.work);
-       struct intel_crtc *crtc;
-
-       mutex_lock(&dev_priv->drrs.mutex);
+       struct intel_crtc *crtc = container_of(work, typeof(*crtc), drrs.work.work);
 
-       crtc = dev_priv->drrs.crtc;
-       if (!crtc)
-               goto unlock;
+       mutex_lock(&crtc->drrs.mutex);
 
-       /*
-        * The delayed work can race with an invalidate hence we need to
-        * recheck.
-        */
-
-       if (!dev_priv->drrs.busy_frontbuffer_bits) {
-               intel_drrs_set_state(dev_priv, crtc->config,
-                                    DRRS_REFRESH_RATE_LOW);
-       }
+       if (intel_drrs_is_enabled(crtc) && !crtc->drrs.busy_frontbuffer_bits)
+               intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_LOW);
 
-unlock:
-       mutex_unlock(&dev_priv->drrs.mutex);
+       mutex_unlock(&crtc->drrs.mutex);
 }
 
 static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv,
        if (dev_priv->vbt.drrs_type != DRRS_TYPE_SEAMLESS)
                return;
 
-       cancel_delayed_work(&dev_priv->drrs.work);
+       for_each_intel_crtc(&dev_priv->drm, crtc) {
+               cancel_delayed_work(&crtc->drrs.work);
 
-       mutex_lock(&dev_priv->drrs.mutex);
+               mutex_lock(&crtc->drrs.mutex);
 
-       crtc = dev_priv->drrs.crtc;
-       if (!crtc) {
-               mutex_unlock(&dev_priv->drrs.mutex);
-               return;
-       }
+               if (!intel_drrs_is_enabled(crtc)) {
+                       mutex_unlock(&crtc->drrs.mutex);
+                       continue;
+               }
 
-       frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe);
-       if (invalidate)
-               dev_priv->drrs.busy_frontbuffer_bits |= frontbuffer_bits;
-       else
-               dev_priv->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits;
+               frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe);
+               if (invalidate)
+                       crtc->drrs.busy_frontbuffer_bits |= frontbuffer_bits;
+               else
+                       crtc->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits;
 
-       /* flush/invalidate means busy screen hence upclock */
-       if (frontbuffer_bits)
-               intel_drrs_set_state(dev_priv, crtc->config,
-                                    DRRS_REFRESH_RATE_HIGH);
+               /* flush/invalidate means busy screen hence upclock */
+               if (frontbuffer_bits)
+                       intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_HIGH);
 
-       /*
-        * flush also means no more activity hence schedule downclock, if all
-        * other fbs are quiescent too
-        */
-       if (!invalidate && !dev_priv->drrs.busy_frontbuffer_bits)
-               schedule_delayed_work(&dev_priv->drrs.work,
-                                     msecs_to_jiffies(1000));
-       mutex_unlock(&dev_priv->drrs.mutex);
+               /*
+                * flush also means no more activity hence schedule downclock, if all
+                * other fbs are quiescent too
+                */
+               if (!invalidate && !crtc->drrs.busy_frontbuffer_bits)
+                       schedule_delayed_work(&crtc->drrs.work,
+                                             msecs_to_jiffies(1000));
+
+               mutex_unlock(&crtc->drrs.mutex);
+       }
 }
 
 /**
        intel_drrs_frontbuffer_update(dev_priv, frontbuffer_bits, false);
 }
 
-void intel_drrs_page_flip(struct intel_atomic_state *state,
-                         struct intel_crtc *crtc)
+void intel_drrs_page_flip(struct intel_crtc *crtc)
 {
-       struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        unsigned int frontbuffer_bits = INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe);
 
        intel_drrs_frontbuffer_update(dev_priv, frontbuffer_bits, false);
 }
 
 /**
- * intel_drrs_init - Init basic DRRS work and mutex.
+ * intel_crtc_drrs_init - Init DRRS for CRTC
+ * @crtc: crtc
+ *
+ * This function is called only once at driver load to initialize basic
+ * DRRS stuff.
+ *
+ */
+void intel_crtc_drrs_init(struct intel_crtc *crtc)
+{
+       INIT_DELAYED_WORK(&crtc->drrs.work, intel_drrs_downclock_work);
+       mutex_init(&crtc->drrs.mutex);
+       crtc->drrs.cpu_transcoder = INVALID_TRANSCODER;
+}
+
+/**
+ * intel_drrs_init - Init DRRS for eDP connector
  * @connector: eDP connector
  * @fixed_mode: preferred mode of panel
  *
- * This function is  called only once at driver load to initialize basic
- * DRRS stuff.
+ * This function is called only once at driver load to initialize
+ * DRRS support for the connector.
  *
  * Returns:
  * Downclock mode if panel supports it, else return NULL.
 {
        struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
        struct intel_encoder *encoder = connector->encoder;
-       struct drm_display_mode *downclock_mode = NULL;
-
-       INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_drrs_downclock_work);
-       mutex_init(&dev_priv->drrs.mutex);
+       struct drm_display_mode *downclock_mode;
 
        if (DISPLAY_VER(dev_priv) <= 6) {
                drm_dbg_kms(&dev_priv->drm,
                return NULL;
        }
 
-       dev_priv->drrs.refresh_rate = DRRS_REFRESH_RATE_HIGH;
        drm_dbg_kms(&dev_priv->drm,
                    "[CONNECTOR:%d:%s] %s DRRS supported\n",
                    connector->base.base.id, connector->base.name,