From: Alvin Lee <[email protected]>

[Description]
- For FPO + Vactive cases, we rely on the Vactive display to be at
  it's nominal refresh rate because the Vactive pipe may not necessarily
  assert P-State allow while it's in VBLANK
- For cases where the Vactive display has a stretched VBLANK due to
  VRR, we could underflow when trying to complete an FPO + Vactive
  MCLK switch because the FPO display has limited VBLANK time in
  waiting for the Vactive display to assert P-State allow naturally
- Block FPO + Vactive if the Vactive display has VRR active (variable
  or fixed)

Reviewed-by: Jun Lei <[email protected]>
Acked-by: Alex Hung <[email protected]>
Signed-off-by: Alvin Lee <[email protected]>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c             | 5 ++++-
 drivers/gpu/drm/amd/display/dc/dc_stream.h           | 2 ++
 drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 7 ++++++-
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c 
b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 7b68ff0f9c4a..9be18ebb1c17 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -2604,7 +2604,7 @@ static enum surface_update_type 
check_update_surfaces_for_stream(
 
                if (stream_update->stream && 
stream_update->stream->freesync_on_desktop &&
                        (stream_update->vrr_infopacket || 
stream_update->allow_freesync ||
-                               stream_update->vrr_active_variable))
+                               stream_update->vrr_active_variable || 
stream_update->vrr_active_fixed))
                        su_flags->bits.fams_changed = 1;
 
                if (su_flags->raw != 0)
@@ -2964,6 +2964,9 @@ static void copy_stream_update_to_stream(struct dc *dc,
        if (update->vrr_active_variable)
                stream->vrr_active_variable = *update->vrr_active_variable;
 
+       if (update->vrr_active_fixed)
+               stream->vrr_active_fixed = *update->vrr_active_fixed;
+
        if (update->crtc_timing_adjust)
                stream->adjust = *update->crtc_timing_adjust;
 
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h 
b/drivers/gpu/drm/amd/display/dc/dc_stream.h
index 0add5ecc895f..d5b3e3a32cc6 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
@@ -233,6 +233,7 @@ struct dc_stream_state {
         */
        bool vrr_active_variable;
        bool freesync_on_desktop;
+       bool vrr_active_fixed;
 
        bool converter_disable_audio;
        uint8_t qs_bit;
@@ -326,6 +327,7 @@ struct dc_stream_update {
        bool integer_scaling_update;
        bool *allow_freesync;
        bool *vrr_active_variable;
+       bool *vrr_active_fixed;
 
        struct colorspace_transform *gamut_remap;
        enum dc_color_space *output_color_space;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c 
b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
index 826059d5b367..46fd7b68857c 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
@@ -35,6 +35,7 @@
 
 #define DC_LOGGER_INIT(logger)
 
+static const unsigned int MAX_FPO_VACTIVE_BLANK_US = 600;
 static const struct subvp_high_refresh_list subvp_high_refresh_list = {
                        .min_refresh = 120,
                        .max_refresh = 165,
@@ -2924,6 +2925,7 @@ bool dcn32_find_vactive_pipe(struct dc *dc, const struct 
dc_state *context, uint
        unsigned int i, pipe_idx;
        const struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
        bool vactive_found = false;
+       unsigned int blank_us = 0;
 
        for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
                const struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
@@ -2931,7 +2933,10 @@ bool dcn32_find_vactive_pipe(struct dc *dc, const struct 
dc_state *context, uint
                if (!pipe->stream)
                        continue;
 
-               if 
(vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]]
 >= vactive_margin_req_us) {
+               blank_us = ((pipe->stream->timing.v_total - 
pipe->stream->timing.v_addressable) * pipe->stream->timing.h_total /
+                               (double)(pipe->stream->timing.pix_clk_100hz * 
100)) * 1000000;
+               if 
(vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]]
 >= vactive_margin_req_us &&
+                               !(pipe->stream->vrr_active_variable || 
pipe->stream->vrr_active_fixed) && blank_us < MAX_FPO_VACTIVE_BLANK_US) {
                        vactive_found = true;
                        break;
                }
-- 
2.40.0

Reply via email to