/* The stream has changed so CRC capture needs to re-enabled. */
                source = dm_new_crtc_state->crc_src;
                if (amdgpu_dm_is_valid_crc_source(source)) {
-                       dm_new_crtc_state->crc_src = AMDGPU_DM_PIPE_CRC_SOURCE_NONE;
-                       if (source == AMDGPU_DM_PIPE_CRC_SOURCE_CRTC)
-                               amdgpu_dm_crtc_set_crc_source(crtc, "crtc");
-                       else if (source == AMDGPU_DM_PIPE_CRC_SOURCE_DPRX)
-                               amdgpu_dm_crtc_set_crc_source(crtc, "dprx");
+                       amdgpu_dm_crtc_configure_crc_source(
+                               crtc, dm_new_crtc_state,
+                               dm_new_crtc_state->crc_src);
                }
 #endif
        }
 
                if (dm_old_crtc_state->interrupts_enabled &&
                    (!dm_new_crtc_state->interrupts_enabled ||
-                    drm_atomic_crtc_needs_modeset(new_crtc_state))) {
-                       /*
-                        * Drop the extra vblank reference added by CRC
-                        * capture if applicable.
-                        */
-                       if (amdgpu_dm_is_valid_crc_source(dm_new_crtc_state->crc_src))
-                               drm_crtc_vblank_put(crtc);
-
-                       /*
-                        * Only keep CRC capture enabled if there's
-                        * still a stream for the CRTC.
-                        */
-                       if (!dm_new_crtc_state->stream)
-                               dm_new_crtc_state->crc_src = AMDGPU_DM_PIPE_CRC_SOURCE_NONE;
-
+                    drm_atomic_crtc_needs_modeset(new_crtc_state)))
                        manage_dm_interrupts(adev, acrtc, false);
-               }
        }
        /*
         * Add check here for SoC's that support hardware cursor plane, to
 
        return 0;
 }
 
-int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
+int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
+                                       struct dm_crtc_state *dm_crtc_state,
+                                       enum amdgpu_dm_pipe_crc_source source)
 {
        struct amdgpu_device *adev = crtc->dev->dev_private;
+       struct dc_stream_state *stream_state = dm_crtc_state->stream;
+       bool enable = amdgpu_dm_is_valid_crc_source(source);
+       int ret = 0;
+
+       /* Configuration will be deferred to stream enable. */
+       if (!stream_state)
+               return 0;
+
+       mutex_lock(&adev->dm.dc_lock);
+
+       /* Enable CRTC CRC generation if necessary. */
+       if (dm_is_crc_source_crtc(source)) {
+               if (!dc_stream_configure_crc(stream_state->ctx->dc,
+                                            stream_state, enable, enable)) {
+                       ret = -EINVAL;
+                       goto unlock;
+               }
+       }
+
+       /* Configure dithering */
+       if (!dm_need_crc_dither(source))
+               dc_stream_set_dither_option(stream_state, DITHER_OPTION_TRUN8);
+       else
+               dc_stream_set_dither_option(stream_state,
+                                           DITHER_OPTION_DEFAULT);
+
+unlock:
+       mutex_unlock(&adev->dm.dc_lock);
+
+       return ret;
+}
+
+int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
+{
        struct dm_crtc_state *crtc_state = to_dm_crtc_state(crtc->state);
-       struct dc_stream_state *stream_state = crtc_state->stream;
        struct drm_dp_aux *aux = NULL;
        bool enable = false;
        bool enabled = false;
                return -EINVAL;
        }
 
-       if (!stream_state) {
-               DRM_ERROR("No stream state for CRTC%d\n", crtc->index);
-               return -EINVAL;
-       }
-
        enable = amdgpu_dm_is_valid_crc_source(source);
 
-       mutex_lock(&adev->dm.dc_lock);
        /*
         * USER REQ SRC | CURRENT SRC | BEHAVIOR
         * -----------------------------
 
                if (!aconn) {
                        DRM_DEBUG_DRIVER("No amd connector matching CRTC-%d\n", crtc->index);
-                       mutex_unlock(&adev->dm.dc_lock);
                        return -EINVAL;
                }
 
 
                if (!aux) {
                        DRM_DEBUG_DRIVER("No dp aux for amd connector\n");
-                       mutex_unlock(&adev->dm.dc_lock);
-                       return -EINVAL;
-               }
-       } else if (dm_is_crc_source_crtc(source)) {
-               if (!dc_stream_configure_crc(stream_state->ctx->dc, stream_state,
-                                            enable, enable)) {
-                       mutex_unlock(&adev->dm.dc_lock);
                        return -EINVAL;
                }
        }
 
-       /* configure dithering */
-       if (!dm_need_crc_dither(source))
-               dc_stream_set_dither_option(stream_state, DITHER_OPTION_TRUN8);
-       else if (!dm_need_crc_dither(crtc_state->crc_src))
-               dc_stream_set_dither_option(stream_state, DITHER_OPTION_DEFAULT);
-
-       mutex_unlock(&adev->dm.dc_lock);
+       if (amdgpu_dm_crtc_configure_crc_source(crtc, crtc_state, source))
+               return -EINVAL;
 
        /*
         * Reading the CRC requires the vblank interrupt handler to be
 
 #ifndef AMD_DAL_DEV_AMDGPU_DM_AMDGPU_DM_CRC_H_
 #define AMD_DAL_DEV_AMDGPU_DM_AMDGPU_DM_CRC_H_
 
+struct drm_crtc;
+struct dm_crtc_state;
+
 enum amdgpu_dm_pipe_crc_source {
        AMDGPU_DM_PIPE_CRC_SOURCE_NONE = 0,
        AMDGPU_DM_PIPE_CRC_SOURCE_CRTC,
 
 /* amdgpu_dm_crc.c */
 #ifdef CONFIG_DEBUG_FS
+int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
+                                       struct dm_crtc_state *dm_crtc_state,
+                                       enum amdgpu_dm_pipe_crc_source source);
 int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name);
 int amdgpu_dm_crtc_verify_crc_source(struct drm_crtc *crtc,
                                     const char *src_name,