return 0;
        else {
                struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc];
-               struct dm_crtc_state *acrtc_state = to_dm_crtc_state(
-                               acrtc->base.state);
 
-
-               if (acrtc_state->stream == NULL) {
+               if (acrtc->dm_irq_params.stream == NULL) {
                        DRM_ERROR("dc_stream_state is NULL for crtc '%d'!\n",
                                  crtc);
                        return 0;
                }
 
-               return dc_stream_get_vblank_counter(acrtc_state->stream);
+               return dc_stream_get_vblank_counter(acrtc->dm_irq_params.stream);
        }
 }
 
                return -EINVAL;
        else {
                struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc];
-               struct dm_crtc_state *acrtc_state = to_dm_crtc_state(
-                                               acrtc->base.state);
 
-               if (acrtc_state->stream ==  NULL) {
+               if (acrtc->dm_irq_params.stream ==  NULL) {
                        DRM_ERROR("dc_stream_state is NULL for crtc '%d'!\n",
                                  crtc);
                        return 0;
                 * TODO rework base driver to use values directly.
                 * for now parse it back into reg-format
                 */
-               dc_stream_get_scanoutpos(acrtc_state->stream,
+               dc_stream_get_scanoutpos(acrtc->dm_irq_params.stream,
                                         &v_blank_start,
                                         &v_blank_end,
                                         &h_position,
        return NULL;
 }
 
+static inline bool amdgpu_dm_vrr_active_irq(struct amdgpu_crtc *acrtc)
+{
+       return acrtc->dm_irq_params.freesync_config.state ==
+                      VRR_STATE_ACTIVE_VARIABLE ||
+              acrtc->dm_irq_params.freesync_config.state ==
+                      VRR_STATE_ACTIVE_FIXED;
+}
+
 static inline bool amdgpu_dm_vrr_active(struct dm_crtc_state *dm_state)
 {
        return dm_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE ||
        struct amdgpu_device *adev = irq_params->adev;
        unsigned long flags;
        struct drm_pending_vblank_event *e;
-       struct dm_crtc_state *acrtc_state;
        uint32_t vpos, hpos, v_blank_start, v_blank_end;
        bool vrr_active;
 
        if (!e)
                WARN_ON(1);
 
-       acrtc_state = to_dm_crtc_state(amdgpu_crtc->base.state);
-       vrr_active = amdgpu_dm_vrr_active(acrtc_state);
+       vrr_active = amdgpu_dm_vrr_active_irq(amdgpu_crtc);
 
        /* Fixed refresh rate, or VRR scanout position outside front-porch? */
        if (!vrr_active ||
-           !dc_stream_get_scanoutpos(acrtc_state->stream, &v_blank_start,
+           !dc_stream_get_scanoutpos(amdgpu_crtc->dm_irq_params.stream, &v_blank_start,
                                      &v_blank_end, &hpos, &vpos) ||
            (vpos < v_blank_start)) {
                /* Update to correct count and vblank timestamp if racing with
        struct common_irq_params *irq_params = interrupt_params;
        struct amdgpu_device *adev = irq_params->adev;
        struct amdgpu_crtc *acrtc;
-       struct dm_crtc_state *acrtc_state;
        unsigned long flags;
+       int vrr_active;
 
        acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VUPDATE);
 
        if (acrtc) {
-               acrtc_state = to_dm_crtc_state(acrtc->base.state);
+               vrr_active = amdgpu_dm_vrr_active_irq(acrtc);
 
                DRM_DEBUG_VBL("crtc:%d, vupdate-vrr:%d\n",
                              acrtc->crtc_id,
-                             amdgpu_dm_vrr_active(acrtc_state));
+                             vrr_active);
 
                /* Core vblank handling is done here after end of front-porch in
                 * vrr mode, as vblank timestamping will give valid results
                 * page-flip completion events that have been queued to us
                 * if a pageflip happened inside front-porch.
                 */
-               if (amdgpu_dm_vrr_active(acrtc_state)) {
+               if (vrr_active) {
                        drm_crtc_handle_vblank(&acrtc->base);
 
                        /* BTR processing for pre-DCE12 ASICs */
-                       if (acrtc_state->stream &&
+                       if (acrtc->dm_irq_params.stream &&
                            adev->family < AMDGPU_FAMILY_AI) {
                                spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
                                mod_freesync_handle_v_update(
                                    adev->dm.freesync_module,
-                                   acrtc_state->stream,
-                                   &acrtc_state->vrr_params);
+                                   acrtc->dm_irq_params.stream,
+                                   &acrtc->dm_irq_params.vrr_params);
 
                                dc_stream_adjust_vmin_vmax(
                                    adev->dm.dc,
-                                   acrtc_state->stream,
-                                   &acrtc_state->vrr_params.adjust);
+                                   acrtc->dm_irq_params.stream,
+                                   &acrtc->dm_irq_params.vrr_params.adjust);
                                spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
                        }
                }
        struct common_irq_params *irq_params = interrupt_params;
        struct amdgpu_device *adev = irq_params->adev;
        struct amdgpu_crtc *acrtc;
-       struct dm_crtc_state *acrtc_state;
        unsigned long flags;
+       int vrr_active;
 
        acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VBLANK);
        if (!acrtc)
                return;
 
-       acrtc_state = to_dm_crtc_state(acrtc->base.state);
+       vrr_active = amdgpu_dm_vrr_active_irq(acrtc);
 
        DRM_DEBUG_VBL("crtc:%d, vupdate-vrr:%d, planes:%d\n", acrtc->crtc_id,
-                        amdgpu_dm_vrr_active(acrtc_state),
-                        acrtc_state->active_planes);
+                     vrr_active, acrtc->dm_irq_params.active_planes);
 
        /**
         * Core vblank handling at start of front-porch is only possible
         * valid results while done in front-porch. Otherwise defer it
         * to dm_vupdate_high_irq after end of front-porch.
         */
-       if (!amdgpu_dm_vrr_active(acrtc_state))
+       if (!vrr_active)
                drm_crtc_handle_vblank(&acrtc->base);
 
        /**
 
        spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
 
-       if (acrtc_state->stream && acrtc_state->vrr_params.supported &&
-           acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE) {
+       if (acrtc->dm_irq_params.stream &&
+           acrtc->dm_irq_params.vrr_params.supported &&
+           acrtc->dm_irq_params.freesync_config.state ==
+                   VRR_STATE_ACTIVE_VARIABLE) {
                mod_freesync_handle_v_update(adev->dm.freesync_module,
-                                            acrtc_state->stream,
-                                            &acrtc_state->vrr_params);
+                                            acrtc->dm_irq_params.stream,
+                                            &acrtc->dm_irq_params.vrr_params);
 
-               dc_stream_adjust_vmin_vmax(adev->dm.dc, acrtc_state->stream,
-                                          &acrtc_state->vrr_params.adjust);
+               dc_stream_adjust_vmin_vmax(adev->dm.dc, acrtc->dm_irq_params.stream,
+                                          &acrtc->dm_irq_params.vrr_params.adjust);
        }
 
        /*
         */
        if (adev->family >= AMDGPU_FAMILY_RV &&
            acrtc->pflip_status == AMDGPU_FLIP_SUBMITTED &&
-           acrtc_state->active_planes == 0) {
+           acrtc->dm_irq_params.active_planes == 0) {
                if (acrtc->event) {
                        drm_crtc_send_vblank_event(&acrtc->base, acrtc->event);
                        acrtc->event = NULL;
        }
 
        state->active_planes = cur->active_planes;
-       state->vrr_params = cur->vrr_params;
        state->vrr_infopacket = cur->vrr_infopacket;
        state->abm_level = cur->abm_level;
        state->vrr_supported = cur->vrr_supported;
        struct mod_vrr_params vrr_params;
        struct dc_info_packet vrr_infopacket = {0};
        struct amdgpu_device *adev = dm->adev;
+       struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_crtc_state->base.crtc);
        unsigned long flags;
 
        if (!new_stream)
                return;
 
        spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
-       vrr_params = new_crtc_state->vrr_params;
+        vrr_params = acrtc->dm_irq_params.vrr_params;
 
        if (surface) {
                mod_freesync_handle_preflip(
                &vrr_infopacket);
 
        new_crtc_state->freesync_timing_changed |=
-               (memcmp(&new_crtc_state->vrr_params.adjust,
+               (memcmp(&acrtc->dm_irq_params.vrr_params.adjust,
                        &vrr_params.adjust,
                        sizeof(vrr_params.adjust)) != 0);
 
                        &vrr_infopacket,
                        sizeof(vrr_infopacket)) != 0);
 
-       new_crtc_state->vrr_params = vrr_params;
+       acrtc->dm_irq_params.vrr_params = vrr_params;
        new_crtc_state->vrr_infopacket = vrr_infopacket;
 
-       new_stream->adjust = new_crtc_state->vrr_params.adjust;
+       new_stream->adjust = acrtc->dm_irq_params.vrr_params.adjust;
        new_stream->vrr_infopacket = vrr_infopacket;
 
        if (new_crtc_state->freesync_vrr_info_changed)
        spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
 }
 
-static void pre_update_freesync_state_on_stream(
+static void update_stream_irq_parameters(
        struct amdgpu_display_manager *dm,
        struct dm_crtc_state *new_crtc_state)
 {
        struct mod_vrr_params vrr_params;
        struct mod_freesync_config config = new_crtc_state->freesync_config;
        struct amdgpu_device *adev = dm->adev;
+       struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_crtc_state->base.crtc);
        unsigned long flags;
 
        if (!new_stream)
                return;
 
        spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
-       vrr_params = new_crtc_state->vrr_params;
+       vrr_params = acrtc->dm_irq_params.vrr_params;
 
        if (new_crtc_state->vrr_supported &&
            config.min_refresh_in_uhz &&
                                      &config, &vrr_params);
 
        new_crtc_state->freesync_timing_changed |=
-               (memcmp(&new_crtc_state->vrr_params.adjust,
-                       &vrr_params.adjust,
-                       sizeof(vrr_params.adjust)) != 0);
+               (memcmp(&acrtc->dm_irq_params.vrr_params.adjust,
+                       &vrr_params.adjust, sizeof(vrr_params.adjust)) != 0);
 
-       new_crtc_state->vrr_params = vrr_params;
+       new_crtc_state->freesync_config = config;
+       /* Copy state for access from DM IRQ handler */
+       acrtc->dm_irq_params.freesync_config = config;
+       acrtc->dm_irq_params.active_planes = new_crtc_state->active_planes;
+       acrtc->dm_irq_params.vrr_params = vrr_params;
        spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
 }
 
                        spin_lock_irqsave(&pcrtc->dev->event_lock, flags);
                        dc_stream_adjust_vmin_vmax(
                                dm->dc, acrtc_state->stream,
-                               &acrtc_state->vrr_params.adjust);
+                               &acrtc_attach->dm_irq_params.vrr_params.adjust);
                        spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags);
                }
                mutex_lock(&dm->dc_lock);
 {
        struct drm_crtc *crtc;
        struct drm_crtc_state *old_crtc_state, *new_crtc_state;
+       struct dm_crtc_state *dm_old_crtc_state;
        struct amdgpu_device *adev = drm_to_adev(dev);
        int i;
 
        for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
                struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
 
+               dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
+
                if (old_crtc_state->active &&
                    (!new_crtc_state->active ||
-                    drm_atomic_crtc_needs_modeset(new_crtc_state)))
+                    drm_atomic_crtc_needs_modeset(new_crtc_state))) {
                        manage_dm_interrupts(adev, acrtc, false);
+                       dc_stream_release(dm_old_crtc_state->stream);
+               }
        }
        /*
         * Add check here for SoC's that support hardware cursor plane, to
                        if (!status)
                                status = dc_stream_get_status_from_state(dc_state,
                                                                         dm_new_crtc_state->stream);
-
                        if (!status)
                                DC_ERR("got no status for stream %p on acrtc%p\n", dm_new_crtc_state->stream, acrtc);
                        else
                dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
                dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
 
-               /* Update freesync active state. */
-               pre_update_freesync_state_on_stream(dm, dm_new_crtc_state);
+               /* For freesync config update on crtc state and params for irq */
+               update_stream_irq_parameters(dm, dm_new_crtc_state);
 
                /* Handle vrr on->off / off->on transitions */
                amdgpu_dm_handle_vrr_transition(dm_old_crtc_state,
        for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
                struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
 
+               dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
+
                if (new_crtc_state->active &&
                    (!old_crtc_state->active ||
                     drm_atomic_crtc_needs_modeset(new_crtc_state))) {
+                       dc_stream_retain(dm_new_crtc_state->stream);
+                       acrtc->dm_irq_params.stream = dm_new_crtc_state->stream;
                        manage_dm_interrupts(adev, acrtc, true);
+
 #ifdef CONFIG_DEBUG_FS
                        /**
                         * Frontend may have changed so reapply the CRC capture
 {
        new_crtc_state->vrr_supported = false;
 
-       memset(&new_crtc_state->vrr_params, 0,
-              sizeof(new_crtc_state->vrr_params));
        memset(&new_crtc_state->vrr_infopacket, 0,
               sizeof(new_crtc_state->vrr_infopacket));
 }