On 2018-12-05 12:08 p.m., Nicholas Kazlauskas wrote:
> [Why]
> When the flip-rate is below the minimum supported variable refresh rate
> range for the monitor the front porch wait will timeout and be
> frequently misaligned resulting in stuttering and/or flickering.
>
> The FreeSync module can still maintain a smooth and flicker free
> image when the monitor has a refresh rate range such that the maximum
> refresh > 2 * minimum refresh by utilizing low framerate compensation,
> "below the range".
>
> [How]
> Hook up the pre-flip and post-flip handlers from the FreeSync module.
> These adjust the minimum/maximum vrr range to duplicate frames
> when appropriate by tracking flip timestamps.
>
> Cc: Harry Wentland
> Signed-off-by: Nicholas Kazlauskas
> Acked-by: Leo Li
Reviewed-by: Harry Wentland
Harry
> ---
> .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 79 ++-
> .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 +-
> 2 files changed, 62 insertions(+), 19 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 23d61570df17..e2de064426fc 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -328,12 +328,29 @@ static void dm_crtc_high_irq(void *interrupt_params)
> 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;
>
> acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src -
> IRQ_TYPE_VBLANK);
>
> if (acrtc) {
> drm_crtc_handle_vblank(&acrtc->base);
> amdgpu_dm_crtc_handle_crc_irq(&acrtc->base);
> +
> + acrtc_state = to_dm_crtc_state(acrtc->base.state);
> +
> + if (acrtc_state->stream &&
> + acrtc_state->vrr_params.supported &&
> + acrtc_state->freesync_config.state ==
> VRR_STATE_ACTIVE_VARIABLE) {
> + 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);
> + }
> }
> }
>
> @@ -3001,7 +3018,7 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc)
> dc_stream_retain(state->stream);
> }
>
> - state->adjust = cur->adjust;
> + state->vrr_params = cur->vrr_params;
> state->vrr_infopacket = cur->vrr_infopacket;
> state->abm_level = cur->abm_level;
> state->vrr_supported = cur->vrr_supported;
> @@ -4396,9 +4413,11 @@ struct dc_stream_status *dc_state_get_stream_status(
> static void update_freesync_state_on_stream(
> struct amdgpu_display_manager *dm,
> struct dm_crtc_state *new_crtc_state,
> - struct dc_stream_state *new_stream)
> + struct dc_stream_state *new_stream,
> + struct dc_plane_state *surface,
> + u32 flip_timestamp_in_us)
> {
> - struct mod_vrr_params vrr = {0};
> + struct mod_vrr_params vrr_params = new_crtc_state->vrr_params;
> struct dc_info_packet vrr_infopacket = {0};
> struct mod_freesync_config config = new_crtc_state->freesync_config;
>
> @@ -4425,43 +,52 @@ static void update_freesync_state_on_stream(
>
> mod_freesync_build_vrr_params(dm->freesync_module,
> new_stream,
> - &config, &vrr);
> + &config, &vrr_params);
> +
> + if (surface) {
> + mod_freesync_handle_preflip(
> + dm->freesync_module,
> + surface,
> + new_stream,
> + flip_timestamp_in_us,
> + &vrr_params);
> + }
>
> mod_freesync_build_vrr_infopacket(
> dm->freesync_module,
> new_stream,
> - &vrr,
> + &vrr_params,
> PACKET_TYPE_VRR,
> TRANSFER_FUNC_UNKNOWN,
> &vrr_infopacket);
>
> new_crtc_state->freesync_timing_changed =
> - (memcmp(&new_crtc_state->adjust,
> - &vrr.adjust,
> - sizeof(vrr.adjust)) != 0);
> + (memcmp(&new_crtc_state->vrr_params.adjust,
> + &vrr_params.adjust,
> + sizeof(vrr_params.adjust)) != 0);
>
> new_crtc_state->freesync_vrr_info_changed =
> (memcmp(&new_crtc_state->vrr_infopacket,
> &vrr_infopacket,
> sizeof(vrr_infopacket)) != 0);
>
> - new_crtc_state->adjust = vrr.adjust;
> +