From: Danny Wang <danny.w...@amd.com>

[Why&How]
Vtotal is not applied to HW when handling vsync interrupt.
Make sure vtotal is aligned before enable replay.

Reviewed-by: Anthony Koo <anthony....@amd.com>
Reviewed-by: Robin Chen <robin.c...@amd.com>
Signed-off-by: Danny Wang <danny.w...@amd.com>
Signed-off-by: Zhongwei Zhang <zhongwei.zh...@amd.com>
Signed-off-by: Tom Chung <chiahsuan.ch...@amd.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c          |  9 +++++++--
 .../gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 15 +++++++++++++++
 drivers/gpu/drm/amd/display/dc/dc_hw_types.h      |  1 +
 .../drm/amd/display/dc/hwss/dce110/dce110_hwseq.c |  7 ++-----
 .../drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c   |  7 ++-----
 .../drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c   |  8 ++------
 .../drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c   |  4 +---
 .../drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c   |  3 +--
 .../drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 10 +++-------
 .../gpu/drm/amd/display/dc/hwss/hw_sequencer.h    |  6 ++++++
 10 files changed, 40 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c 
b/drivers/gpu/drm/amd/display/dc/core/dc.c
index e71ea21401f5..5a43e4901cc0 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -453,6 +453,7 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
 
        if (dc->caps.max_v_total != 0 &&
                (adjust->v_total_max > dc->caps.max_v_total || 
adjust->v_total_min > dc->caps.max_v_total)) {
+               stream->adjust.timing_adjust_pending = false;
                if (adjust->allow_otg_v_count_halt)
                        return set_long_vtotal(dc, stream, adjust);
                else
@@ -466,7 +467,7 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
                        dc->hwss.set_drr(&pipe,
                                        1,
                                        *adjust);
-
+                       stream->adjust.timing_adjust_pending = false;
                        return true;
                }
        }
@@ -3165,8 +3166,12 @@ static void copy_stream_update_to_stream(struct dc *dc,
        if (update->vrr_active_fixed)
                stream->vrr_active_fixed = *update->vrr_active_fixed;
 
-       if (update->crtc_timing_adjust)
+       if (update->crtc_timing_adjust) {
+               if (stream->adjust.v_total_min != 
update->crtc_timing_adjust->v_total_min ||
+                       stream->adjust.v_total_max != 
update->crtc_timing_adjust->v_total_max)
+                       stream->adjust.timing_adjust_pending = true;
                stream->adjust = *update->crtc_timing_adjust;
+       }
 
        if (update->dpms_off)
                stream->dpms_off = *update->dpms_off;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index e0277728268a..52ee2225e132 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -659,6 +659,21 @@ void set_p_state_switch_method(
        }
 }
 
+void set_drr_and_clear_adjust_pending(
+               struct pipe_ctx *pipe_ctx,
+               struct dc_stream_state *stream,
+               struct drr_params *params)
+{
+       /* params can be null.*/
+       if (pipe_ctx && pipe_ctx->stream_res.tg &&
+                       pipe_ctx->stream_res.tg->funcs->set_drr)
+               pipe_ctx->stream_res.tg->funcs->set_drr(
+                               pipe_ctx->stream_res.tg, params);
+
+       if (stream)
+               stream->adjust.timing_adjust_pending = false;
+}
+
 void get_fams2_visual_confirm_color(
                struct dc *dc,
                struct dc_state *context,
diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h 
b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
index 9f3dd8824ed5..d562ddeca512 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
@@ -1017,6 +1017,7 @@ struct dc_crtc_timing_adjust {
        uint32_t v_total_mid;
        uint32_t v_total_mid_frame_num;
        uint32_t allow_otg_v_count_halt;
+       uint8_t timing_adjust_pending;
 };
 
 
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
index 9c9947fc5d44..bfd734e15731 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
@@ -1658,9 +1658,7 @@ enum dc_status dce110_apply_single_controller_ctx_to_hw(
 
        params.vertical_total_min = stream->adjust.v_total_min;
        params.vertical_total_max = stream->adjust.v_total_max;
-       if (pipe_ctx->stream_res.tg->funcs->set_drr)
-               pipe_ctx->stream_res.tg->funcs->set_drr(
-                       pipe_ctx->stream_res.tg, &params);
+       set_drr_and_clear_adjust_pending(pipe_ctx, stream, &params);
 
        // DRR should set trigger event to monitor surface update event
        if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0)
@@ -2109,8 +2107,7 @@ static void set_drr(struct pipe_ctx **pipe_ctx,
                struct timing_generator *tg = pipe_ctx[i]->stream_res.tg;
 
                if ((tg != NULL) && tg->funcs) {
-                       if (tg->funcs->set_drr)
-                               tg->funcs->set_drr(tg, &params);
+                       set_drr_and_clear_adjust_pending(pipe_ctx[i], 
pipe_ctx[i]->stream, &params);
                        if (adjust.v_total_max != 0 && adjust.v_total_min != 0)
                                if (tg->funcs->set_static_screen_control)
                                        tg->funcs->set_static_screen_control(
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
index 301ef36d3d05..912f96323ed6 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
@@ -1113,9 +1113,7 @@ static void dcn10_reset_back_end_for_pipe(
                
pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
 
                
pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, 
false);
-               if (pipe_ctx->stream_res.tg->funcs->set_drr)
-                       pipe_ctx->stream_res.tg->funcs->set_drr(
-                                       pipe_ctx->stream_res.tg, NULL);
+               set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, 
NULL);
                if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
                        pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 
0;
        }
@@ -3218,8 +3216,7 @@ void dcn10_set_drr(struct pipe_ctx **pipe_ctx,
                struct timing_generator *tg = pipe_ctx[i]->stream_res.tg;
 
                if ((tg != NULL) && tg->funcs) {
-                       if (tg->funcs->set_drr)
-                               tg->funcs->set_drr(tg, &params);
+                       set_drr_and_clear_adjust_pending(pipe_ctx[i], 
pipe_ctx[i]->stream, &params);
                        if (adjust.v_total_max != 0 && adjust.v_total_min != 0)
                                if (tg->funcs->set_static_screen_control)
                                        tg->funcs->set_static_screen_control(
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
index a5a3e0823e21..926c08e790c1 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
@@ -952,9 +952,7 @@ enum dc_status dcn20_enable_stream_timing(
        params.vertical_total_max = stream->adjust.v_total_max;
        params.vertical_total_mid = stream->adjust.v_total_mid;
        params.vertical_total_mid_frame_num = 
stream->adjust.v_total_mid_frame_num;
-       if (pipe_ctx->stream_res.tg->funcs->set_drr)
-               pipe_ctx->stream_res.tg->funcs->set_drr(
-                       pipe_ctx->stream_res.tg, &params);
+       set_drr_and_clear_adjust_pending(pipe_ctx, stream, &params);
 
        // DRR should set trigger event to monitor surface update event
        if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0)
@@ -2856,9 +2854,7 @@ void dcn20_reset_back_end_for_pipe(
                        pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
                                        pipe_ctx->stream_res.tg, 
&pipe_ctx->stream->timing);
 
-               if (pipe_ctx->stream_res.tg->funcs->set_drr)
-                       pipe_ctx->stream_res.tg->funcs->set_drr(
-                                       pipe_ctx->stream_res.tg, NULL);
+               set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, 
NULL);
                /* TODO - convert symclk_ref_cnts for otg to a bit map to solve
                 * the case where the same symclk is shared across multiple otg
                 * instances
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
index 288e9dd9205d..f38340aa3f15 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
@@ -543,9 +543,7 @@ static void dcn31_reset_back_end_for_pipe(
        if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
                pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0;
 
-       if (pipe_ctx->stream_res.tg->funcs->set_drr)
-               pipe_ctx->stream_res.tg->funcs->set_drr(
-                               pipe_ctx->stream_res.tg, NULL);
+       set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, NULL);
 
        /* DPMS may already disable or */
        /* dpms_off status is incorrect due to fastboot
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
index b907ad1acedd..922b8d71cf1a 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
@@ -1473,8 +1473,7 @@ void dcn35_set_drr(struct pipe_ctx **pipe_ctx,
                                        num_frames = 2 * (frame_rate % 60);
                                }
                        }
-                       if (tg->funcs->set_drr)
-                               tg->funcs->set_drr(tg, &params);
+                       set_drr_and_clear_adjust_pending(pipe_ctx[i], 
pipe_ctx[i]->stream, &params);
                        if (adjust.v_total_max != 0 && adjust.v_total_min != 0)
                                if (tg->funcs->set_static_screen_control)
                                        tg->funcs->set_static_screen_control(
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index 39668d8cc13a..8f5da0ded850 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -830,10 +830,7 @@ enum dc_status dcn401_enable_stream_timing(
        }
 
        hws->funcs.wait_for_blank_complete(pipe_ctx->stream_res.opp);
-
-       if (pipe_ctx->stream_res.tg->funcs->set_drr)
-               pipe_ctx->stream_res.tg->funcs->set_drr(
-                       pipe_ctx->stream_res.tg, &params);
+       set_drr_and_clear_adjust_pending(pipe_ctx, stream, &params);
 
        /* Event triggers and num frames initialized for DRR, but can be
         * later updated for PSR use. Note DRR trigger events are generated
@@ -1820,9 +1817,8 @@ void dcn401_reset_back_end_for_pipe(
                        pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
                                        pipe_ctx->stream_res.tg, 
&pipe_ctx->stream->timing);
 
-               if (pipe_ctx->stream_res.tg->funcs->set_drr)
-                       pipe_ctx->stream_res.tg->funcs->set_drr(
-                                       pipe_ctx->stream_res.tg, NULL);
+               set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, 
NULL);
+
                /* TODO - convert symclk_ref_cnts for otg to a bit map to solve
                 * the case where the same symclk is shared across multiple otg
                 * instances
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h 
b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
index 2b1a2a00648a..c8b5ed834579 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
@@ -46,6 +46,7 @@ struct dce_hwseq;
 struct link_resource;
 struct dc_dmub_cmd;
 struct pg_block_update;
+struct drr_params;
 
 struct subvp_pipe_control_lock_fast_params {
        struct dc *dc;
@@ -527,6 +528,11 @@ void set_p_state_switch_method(
                struct dc_state *context,
                struct pipe_ctx *pipe_ctx);
 
+void set_drr_and_clear_adjust_pending(
+               struct pipe_ctx *pipe_ctx,
+               struct dc_stream_state *stream,
+               struct drr_params *params);
+
 void hwss_execute_sequence(struct dc *dc,
                struct block_sequence block_sequence[],
                int num_steps);
-- 
2.34.1

Reply via email to