diff mbox series

[3/3] drm/amd/display: Compensate for pre-DCE12 BTR-VRR hw limitations. (v2)

Message ID 20190426105016.12210-4-mario.kleiner.de@gmail.com (mailing list archive)
State New, archived
Headers show
Series [1/3] drm/amd/display: Fix and simplify apply_below_the_range() | expand

Commit Message

Mario Kleiner April 26, 2019, 10:50 a.m. UTC
Pre-DCE12 needs special treatment for BTR / low framerate
compensation for more stable behaviour:

According to comments in the code and some testing on DCE-8
and DCE-11, DCE-11 and earlier only apply VTOTAL_MIN/MAX
programming with a lag of one frame, so the special BTR hw
programming for intermediate fixed duration frames must be
done inside the current frame at flip submission in atomic
commit tail, ie. one vblank earlier, and the fixed refresh
intermediate frame mode must be also terminated one vblank
earlier on pre-DCE12 display engines.

To achieve proper termination on < DCE-12 shift the point
when the switch-back from fixed vblank duration to variable
vblank duration happens from the start of VBLANK (vblank irq,
as done on DCE-12+) to back-porch or end of VBLANK (handled
by vupdate irq handler). We must leave the switch-back code
inside VBLANK irq for DCE12+, as before.

Doing this, we get much better behaviour of BTR for up-sweeps,
ie. going from short to long frame durations (~high to low fps)
and for constant framerate flips, as tested on DCE-8 and
DCE-11. Behaviour is still not quite as good as on DCN-1
though.

On down-sweeps, going from long to short frame durations
(low fps to high fps) < DCE-12 is a little bit improved,
although by far not as much as for up-sweeps and constant
fps.

v2: Fix some wrong locking, as pointed out by Nicholas.
Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 45 +++++++++++++++++--
 1 file changed, 42 insertions(+), 3 deletions(-)

Comments

Kazlauskas, Nicholas April 26, 2019, 5:12 p.m. UTC | #1
On 4/26/19 6:50 AM, Mario Kleiner wrote:
> Pre-DCE12 needs special treatment for BTR / low framerate
> compensation for more stable behaviour:
> 
> According to comments in the code and some testing on DCE-8
> and DCE-11, DCE-11 and earlier only apply VTOTAL_MIN/MAX
> programming with a lag of one frame, so the special BTR hw
> programming for intermediate fixed duration frames must be
> done inside the current frame at flip submission in atomic
> commit tail, ie. one vblank earlier, and the fixed refresh
> intermediate frame mode must be also terminated one vblank
> earlier on pre-DCE12 display engines.
> 
> To achieve proper termination on < DCE-12 shift the point
> when the switch-back from fixed vblank duration to variable
> vblank duration happens from the start of VBLANK (vblank irq,
> as done on DCE-12+) to back-porch or end of VBLANK (handled
> by vupdate irq handler). We must leave the switch-back code
> inside VBLANK irq for DCE12+, as before.
> 
> Doing this, we get much better behaviour of BTR for up-sweeps,
> ie. going from short to long frame durations (~high to low fps)
> and for constant framerate flips, as tested on DCE-8 and
> DCE-11. Behaviour is still not quite as good as on DCN-1
> though.
> 
> On down-sweeps, going from long to short frame durations
> (low fps to high fps) < DCE-12 is a little bit improved,
> although by far not as much as for up-sweeps and constant
> fps.
> 
> v2: Fix some wrong locking, as pointed out by Nicholas.
> Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>

Still looks good to me, but I just noticed one other minor nitpick (sorry!)

> ---
>   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 45 +++++++++++++++++--
>   1 file changed, 42 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 76b6e621793f..7241e1f3ebec 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -364,6 +364,7 @@ static void dm_vupdate_high_irq(void *interrupt_params)
>   	struct amdgpu_device *adev = irq_params->adev;
>   	struct amdgpu_crtc *acrtc;
>   	struct dm_crtc_state *acrtc_state;
> +	unsigned long flags;
>   
>   	acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VUPDATE);
>   
> @@ -381,6 +382,22 @@ static void dm_vupdate_high_irq(void *interrupt_params)
>   		 */
>   		if (amdgpu_dm_vrr_active(acrtc_state))
>   			drm_crtc_handle_vblank(&acrtc->base);

Can't this block be merged with the one below?

With the condition also changed to just:

if (acrtc_state->stream && adev->family < AMDGPU_FAMILY_AI)
	...

I also noticed that the crtc_state itself is always accessed unlocked 
for checking whether VRR is on/off which is probably a bug... but this 
patch shouldn't be the one to fix that. At the very least though it can 
leave things in a bit better shape like you've already done. Thanks!

Nicholas Kazlauskas

> +
> +		if (acrtc_state->stream && adev->family < AMDGPU_FAMILY_AI &&
> +		    acrtc_state->vrr_params.supported &&
> +		    acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE) {
> +			spin_lock_irqsave(&adev->ddev->event_lock, flags);
> +			mod_freesync_handle_v_update(
> +			    adev->dm.freesync_module,
> +			    acrtc_state->stream,
> +			    &acrtc_state->vrr_params);
> +
> +			dc_stream_adjust_vmin_vmax(
> +			    adev->dm.dc,
> +			    acrtc_state->stream,
> +			    &acrtc_state->vrr_params.adjust);
> +			spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
> +		}
>   	}
>   }
>   
> @@ -390,6 +407,7 @@ static void dm_crtc_high_irq(void *interrupt_params)
>   	struct amdgpu_device *adev = irq_params->adev;
>   	struct amdgpu_crtc *acrtc;
>   	struct dm_crtc_state *acrtc_state;
> +	unsigned long flags;
>   
>   	acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VBLANK);
>   
> @@ -412,9 +430,10 @@ static void dm_crtc_high_irq(void *interrupt_params)
>   		 */
>   		amdgpu_dm_crtc_handle_crc_irq(&acrtc->base);
>   
> -		if (acrtc_state->stream &&
> +		if (acrtc_state->stream && adev->family >= AMDGPU_FAMILY_AI &&
>   		    acrtc_state->vrr_params.supported &&
>   		    acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE) {
> +			spin_lock_irqsave(&adev->ddev->event_lock, flags);
>   			mod_freesync_handle_v_update(
>   				adev->dm.freesync_module,
>   				acrtc_state->stream,
> @@ -424,6 +443,7 @@ static void dm_crtc_high_irq(void *interrupt_params)
>   				adev->dm.dc,
>   				acrtc_state->stream,
>   				&acrtc_state->vrr_params.adjust);
> +			spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
>   		}
>   	}
>   }
> @@ -4878,8 +4898,10 @@ static void update_freesync_state_on_stream(
>   	struct dc_plane_state *surface,
>   	u32 flip_timestamp_in_us)
>   {
> -	struct mod_vrr_params vrr_params = new_crtc_state->vrr_params;
> +	struct mod_vrr_params vrr_params;
>   	struct dc_info_packet vrr_infopacket = {0};
> +	struct amdgpu_device *adev = dm->adev;
> +	unsigned long flags;
>   
>   	if (!new_stream)
>   		return;
> @@ -4892,6 +4914,9 @@ static void update_freesync_state_on_stream(
>   	if (!new_stream->timing.h_total || !new_stream->timing.v_total)
>   		return;
>   
> +	spin_lock_irqsave(&adev->ddev->event_lock, flags);
> +	vrr_params = new_crtc_state->vrr_params;
> +
>   	if (surface) {
>   		mod_freesync_handle_preflip(
>   			dm->freesync_module,
> @@ -4899,6 +4924,12 @@ static void update_freesync_state_on_stream(
>   			new_stream,
>   			flip_timestamp_in_us,
>   			&vrr_params);
> +
> +		if (adev->family < AMDGPU_FAMILY_AI &&
> +		    amdgpu_dm_vrr_active(new_crtc_state)) {
> +			mod_freesync_handle_v_update(dm->freesync_module,
> +						     new_stream, &vrr_params);
> +		}
>   	}
>   
>   	mod_freesync_build_vrr_infopacket(
> @@ -4930,6 +4961,8 @@ static void update_freesync_state_on_stream(
>   			      new_crtc_state->base.crtc->base.id,
>   			      (int)new_crtc_state->base.vrr_enabled,
>   			      (int)vrr_params.state);
> +
> +	spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
>   }
>   
>   static void pre_update_freesync_state_on_stream(
> @@ -4937,8 +4970,10 @@ static void pre_update_freesync_state_on_stream(
>   	struct dm_crtc_state *new_crtc_state)
>   {
>   	struct dc_stream_state *new_stream = new_crtc_state->stream;
> -	struct mod_vrr_params vrr_params = new_crtc_state->vrr_params;
> +	struct mod_vrr_params vrr_params;
>   	struct mod_freesync_config config = new_crtc_state->freesync_config;
> +	struct amdgpu_device *adev = dm->adev;
> +	unsigned long flags;
>   
>   	if (!new_stream)
>   		return;
> @@ -4950,6 +4985,9 @@ static void pre_update_freesync_state_on_stream(
>   	if (!new_stream->timing.h_total || !new_stream->timing.v_total)
>   		return;
>   
> +	spin_lock_irqsave(&adev->ddev->event_lock, flags);
> +	vrr_params = new_crtc_state->vrr_params;
> +
>   	if (new_crtc_state->vrr_supported &&
>   	    config.min_refresh_in_uhz &&
>   	    config.max_refresh_in_uhz) {
> @@ -4970,6 +5008,7 @@ static void pre_update_freesync_state_on_stream(
>   			sizeof(vrr_params.adjust)) != 0);
>   
>   	new_crtc_state->vrr_params = vrr_params;
> +	spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
>   }
>   
>   static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state,
>
Mario Kleiner April 26, 2019, 9:43 p.m. UTC | #2
On Fri, Apr 26, 2019 at 7:12 PM Kazlauskas, Nicholas
<Nicholas.Kazlauskas@amd.com> wrote:
>
> On 4/26/19 6:50 AM, Mario Kleiner wrote:
> > Pre-DCE12 needs special treatment for BTR / low framerate
> > compensation for more stable behaviour:
> >
> > According to comments in the code and some testing on DCE-8
> > and DCE-11, DCE-11 and earlier only apply VTOTAL_MIN/MAX
> > programming with a lag of one frame, so the special BTR hw
> > programming for intermediate fixed duration frames must be
> > done inside the current frame at flip submission in atomic
> > commit tail, ie. one vblank earlier, and the fixed refresh
> > intermediate frame mode must be also terminated one vblank
> > earlier on pre-DCE12 display engines.
> >
> > To achieve proper termination on < DCE-12 shift the point
> > when the switch-back from fixed vblank duration to variable
> > vblank duration happens from the start of VBLANK (vblank irq,
> > as done on DCE-12+) to back-porch or end of VBLANK (handled
> > by vupdate irq handler). We must leave the switch-back code
> > inside VBLANK irq for DCE12+, as before.
> >
> > Doing this, we get much better behaviour of BTR for up-sweeps,
> > ie. going from short to long frame durations (~high to low fps)
> > and for constant framerate flips, as tested on DCE-8 and
> > DCE-11. Behaviour is still not quite as good as on DCN-1
> > though.
> >
> > On down-sweeps, going from long to short frame durations
> > (low fps to high fps) < DCE-12 is a little bit improved,
> > although by far not as much as for up-sweeps and constant
> > fps.
> >
> > v2: Fix some wrong locking, as pointed out by Nicholas.
> > Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
>
> Still looks good to me, but I just noticed one other minor nitpick (sorry!)
>
> > ---
> >   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 45 +++++++++++++++++--
> >   1 file changed, 42 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > index 76b6e621793f..7241e1f3ebec 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > @@ -364,6 +364,7 @@ static void dm_vupdate_high_irq(void *interrupt_params)
> >       struct amdgpu_device *adev = irq_params->adev;
> >       struct amdgpu_crtc *acrtc;
> >       struct dm_crtc_state *acrtc_state;
> > +     unsigned long flags;
> >
> >       acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VUPDATE);
> >
> > @@ -381,6 +382,22 @@ static void dm_vupdate_high_irq(void *interrupt_params)
> >                */
> >               if (amdgpu_dm_vrr_active(acrtc_state))
> >                       drm_crtc_handle_vblank(&acrtc->base);
>
> Can't this block be merged with the one below?
>
> With the condition also changed to just:
>
> if (acrtc_state->stream && adev->family < AMDGPU_FAMILY_AI)
>         ...

Done. New series out, retested.
-mario

>
> I also noticed that the crtc_state itself is always accessed unlocked
> for checking whether VRR is on/off which is probably a bug... but this
> patch shouldn't be the one to fix that. At the very least though it can
> leave things in a bit better shape like you've already done. Thanks!
>
> Nicholas Kazlauskas
>
> > +
> > +             if (acrtc_state->stream && adev->family < AMDGPU_FAMILY_AI &&
> > +                 acrtc_state->vrr_params.supported &&
> > +                 acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE) {
> > +                     spin_lock_irqsave(&adev->ddev->event_lock, flags);
> > +                     mod_freesync_handle_v_update(
> > +                         adev->dm.freesync_module,
> > +                         acrtc_state->stream,
> > +                         &acrtc_state->vrr_params);
> > +
> > +                     dc_stream_adjust_vmin_vmax(
> > +                         adev->dm.dc,
> > +                         acrtc_state->stream,
> > +                         &acrtc_state->vrr_params.adjust);
> > +                     spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
> > +             }
> >       }
> >   }
> >
> > @@ -390,6 +407,7 @@ static void dm_crtc_high_irq(void *interrupt_params)
> >       struct amdgpu_device *adev = irq_params->adev;
> >       struct amdgpu_crtc *acrtc;
> >       struct dm_crtc_state *acrtc_state;
> > +     unsigned long flags;
> >
> >       acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VBLANK);
> >
> > @@ -412,9 +430,10 @@ static void dm_crtc_high_irq(void *interrupt_params)
> >                */
> >               amdgpu_dm_crtc_handle_crc_irq(&acrtc->base);
> >
> > -             if (acrtc_state->stream &&
> > +             if (acrtc_state->stream && adev->family >= AMDGPU_FAMILY_AI &&
> >                   acrtc_state->vrr_params.supported &&
> >                   acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE) {
> > +                     spin_lock_irqsave(&adev->ddev->event_lock, flags);
> >                       mod_freesync_handle_v_update(
> >                               adev->dm.freesync_module,
> >                               acrtc_state->stream,
> > @@ -424,6 +443,7 @@ static void dm_crtc_high_irq(void *interrupt_params)
> >                               adev->dm.dc,
> >                               acrtc_state->stream,
> >                               &acrtc_state->vrr_params.adjust);
> > +                     spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
> >               }
> >       }
> >   }
> > @@ -4878,8 +4898,10 @@ static void update_freesync_state_on_stream(
> >       struct dc_plane_state *surface,
> >       u32 flip_timestamp_in_us)
> >   {
> > -     struct mod_vrr_params vrr_params = new_crtc_state->vrr_params;
> > +     struct mod_vrr_params vrr_params;
> >       struct dc_info_packet vrr_infopacket = {0};
> > +     struct amdgpu_device *adev = dm->adev;
> > +     unsigned long flags;
> >
> >       if (!new_stream)
> >               return;
> > @@ -4892,6 +4914,9 @@ static void update_freesync_state_on_stream(
> >       if (!new_stream->timing.h_total || !new_stream->timing.v_total)
> >               return;
> >
> > +     spin_lock_irqsave(&adev->ddev->event_lock, flags);
> > +     vrr_params = new_crtc_state->vrr_params;
> > +
> >       if (surface) {
> >               mod_freesync_handle_preflip(
> >                       dm->freesync_module,
> > @@ -4899,6 +4924,12 @@ static void update_freesync_state_on_stream(
> >                       new_stream,
> >                       flip_timestamp_in_us,
> >                       &vrr_params);
> > +
> > +             if (adev->family < AMDGPU_FAMILY_AI &&
> > +                 amdgpu_dm_vrr_active(new_crtc_state)) {
> > +                     mod_freesync_handle_v_update(dm->freesync_module,
> > +                                                  new_stream, &vrr_params);
> > +             }
> >       }
> >
> >       mod_freesync_build_vrr_infopacket(
> > @@ -4930,6 +4961,8 @@ static void update_freesync_state_on_stream(
> >                             new_crtc_state->base.crtc->base.id,
> >                             (int)new_crtc_state->base.vrr_enabled,
> >                             (int)vrr_params.state);
> > +
> > +     spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
> >   }
> >
> >   static void pre_update_freesync_state_on_stream(
> > @@ -4937,8 +4970,10 @@ static void pre_update_freesync_state_on_stream(
> >       struct dm_crtc_state *new_crtc_state)
> >   {
> >       struct dc_stream_state *new_stream = new_crtc_state->stream;
> > -     struct mod_vrr_params vrr_params = new_crtc_state->vrr_params;
> > +     struct mod_vrr_params vrr_params;
> >       struct mod_freesync_config config = new_crtc_state->freesync_config;
> > +     struct amdgpu_device *adev = dm->adev;
> > +     unsigned long flags;
> >
> >       if (!new_stream)
> >               return;
> > @@ -4950,6 +4985,9 @@ static void pre_update_freesync_state_on_stream(
> >       if (!new_stream->timing.h_total || !new_stream->timing.v_total)
> >               return;
> >
> > +     spin_lock_irqsave(&adev->ddev->event_lock, flags);
> > +     vrr_params = new_crtc_state->vrr_params;
> > +
> >       if (new_crtc_state->vrr_supported &&
> >           config.min_refresh_in_uhz &&
> >           config.max_refresh_in_uhz) {
> > @@ -4970,6 +5008,7 @@ static void pre_update_freesync_state_on_stream(
> >                       sizeof(vrr_params.adjust)) != 0);
> >
> >       new_crtc_state->vrr_params = vrr_params;
> > +     spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
> >   }
> >
> >   static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state,
> >
>
diff mbox series

Patch

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 76b6e621793f..7241e1f3ebec 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -364,6 +364,7 @@  static void dm_vupdate_high_irq(void *interrupt_params)
 	struct amdgpu_device *adev = irq_params->adev;
 	struct amdgpu_crtc *acrtc;
 	struct dm_crtc_state *acrtc_state;
+	unsigned long flags;
 
 	acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VUPDATE);
 
@@ -381,6 +382,22 @@  static void dm_vupdate_high_irq(void *interrupt_params)
 		 */
 		if (amdgpu_dm_vrr_active(acrtc_state))
 			drm_crtc_handle_vblank(&acrtc->base);
+
+		if (acrtc_state->stream && adev->family < AMDGPU_FAMILY_AI &&
+		    acrtc_state->vrr_params.supported &&
+		    acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE) {
+			spin_lock_irqsave(&adev->ddev->event_lock, flags);
+			mod_freesync_handle_v_update(
+			    adev->dm.freesync_module,
+			    acrtc_state->stream,
+			    &acrtc_state->vrr_params);
+
+			dc_stream_adjust_vmin_vmax(
+			    adev->dm.dc,
+			    acrtc_state->stream,
+			    &acrtc_state->vrr_params.adjust);
+			spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
+		}
 	}
 }
 
@@ -390,6 +407,7 @@  static void dm_crtc_high_irq(void *interrupt_params)
 	struct amdgpu_device *adev = irq_params->adev;
 	struct amdgpu_crtc *acrtc;
 	struct dm_crtc_state *acrtc_state;
+	unsigned long flags;
 
 	acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VBLANK);
 
@@ -412,9 +430,10 @@  static void dm_crtc_high_irq(void *interrupt_params)
 		 */
 		amdgpu_dm_crtc_handle_crc_irq(&acrtc->base);
 
-		if (acrtc_state->stream &&
+		if (acrtc_state->stream && adev->family >= AMDGPU_FAMILY_AI &&
 		    acrtc_state->vrr_params.supported &&
 		    acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE) {
+			spin_lock_irqsave(&adev->ddev->event_lock, flags);
 			mod_freesync_handle_v_update(
 				adev->dm.freesync_module,
 				acrtc_state->stream,
@@ -424,6 +443,7 @@  static void dm_crtc_high_irq(void *interrupt_params)
 				adev->dm.dc,
 				acrtc_state->stream,
 				&acrtc_state->vrr_params.adjust);
+			spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
 		}
 	}
 }
@@ -4878,8 +4898,10 @@  static void update_freesync_state_on_stream(
 	struct dc_plane_state *surface,
 	u32 flip_timestamp_in_us)
 {
-	struct mod_vrr_params vrr_params = new_crtc_state->vrr_params;
+	struct mod_vrr_params vrr_params;
 	struct dc_info_packet vrr_infopacket = {0};
+	struct amdgpu_device *adev = dm->adev;
+	unsigned long flags;
 
 	if (!new_stream)
 		return;
@@ -4892,6 +4914,9 @@  static void update_freesync_state_on_stream(
 	if (!new_stream->timing.h_total || !new_stream->timing.v_total)
 		return;
 
+	spin_lock_irqsave(&adev->ddev->event_lock, flags);
+	vrr_params = new_crtc_state->vrr_params;
+
 	if (surface) {
 		mod_freesync_handle_preflip(
 			dm->freesync_module,
@@ -4899,6 +4924,12 @@  static void update_freesync_state_on_stream(
 			new_stream,
 			flip_timestamp_in_us,
 			&vrr_params);
+
+		if (adev->family < AMDGPU_FAMILY_AI &&
+		    amdgpu_dm_vrr_active(new_crtc_state)) {
+			mod_freesync_handle_v_update(dm->freesync_module,
+						     new_stream, &vrr_params);
+		}
 	}
 
 	mod_freesync_build_vrr_infopacket(
@@ -4930,6 +4961,8 @@  static void update_freesync_state_on_stream(
 			      new_crtc_state->base.crtc->base.id,
 			      (int)new_crtc_state->base.vrr_enabled,
 			      (int)vrr_params.state);
+
+	spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
 }
 
 static void pre_update_freesync_state_on_stream(
@@ -4937,8 +4970,10 @@  static void pre_update_freesync_state_on_stream(
 	struct dm_crtc_state *new_crtc_state)
 {
 	struct dc_stream_state *new_stream = new_crtc_state->stream;
-	struct mod_vrr_params vrr_params = new_crtc_state->vrr_params;
+	struct mod_vrr_params vrr_params;
 	struct mod_freesync_config config = new_crtc_state->freesync_config;
+	struct amdgpu_device *adev = dm->adev;
+	unsigned long flags;
 
 	if (!new_stream)
 		return;
@@ -4950,6 +4985,9 @@  static void pre_update_freesync_state_on_stream(
 	if (!new_stream->timing.h_total || !new_stream->timing.v_total)
 		return;
 
+	spin_lock_irqsave(&adev->ddev->event_lock, flags);
+	vrr_params = new_crtc_state->vrr_params;
+
 	if (new_crtc_state->vrr_supported &&
 	    config.min_refresh_in_uhz &&
 	    config.max_refresh_in_uhz) {
@@ -4970,6 +5008,7 @@  static void pre_update_freesync_state_on_stream(
 			sizeof(vrr_params.adjust)) != 0);
 
 	new_crtc_state->vrr_params = vrr_params;
+	spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
 }
 
 static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state,