]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/amd/display: Do not enable replay when vtotal update is pending.
authorDanny Wang <danny.wang@amd.com>
Thu, 13 Feb 2025 08:18:34 +0000 (16:18 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 29 May 2025 09:12:16 +0000 (11:12 +0200)
[ Upstream commit bd00b29b5f236dce677089319176dee5872b5a7a ]

[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.koo@amd.com>
Reviewed-by: Robin Chen <robin.chen@amd.com>
Signed-off-by: Danny Wang <danny.wang@amd.com>
Signed-off-by: Zhongwei Zhang <Zhongwei.Zhang@amd.com>
Signed-off-by: Tom Chung <chiahsuan.chung@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Stable-dep-of: 874697e12793 ("drm/amd/display: Defer BW-optimization-blocked DRR adjustments")
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dc_hw_types.h
drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h

index 4683c7ef4507f58cffc8f010003b98aaa7aae265..a444fe1e0838a1d1d267d1fc9a26dbdb2c690e82 100644 (file)
@@ -452,6 +452,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
@@ -465,7 +466,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;
                }
        }
@@ -3127,8 +3128,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;
index 6eb9bae3af9127b85eef7f5be0de7a1730a4ec8f..a49604b7701f71f84670377542b3eaf3f9884fef 100644 (file)
@@ -609,6 +609,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,
index 5ac55601a6da1798ff83c7949403e727a5d1a74c..37e381fc7f02a40973f7bc293fcf47811d6224a5 100644 (file)
@@ -1015,6 +1015,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;
 };
 
 
index 81f4c386c287517eddef9a6801bbfc1589401d49..fc4fb4055ab004d96494deee7b3f8f4784daa811 100644 (file)
@@ -1654,9 +1654,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)
@@ -2104,8 +2102,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(
index 13f9e9b439f6a5f79265261e0cf888eecb9eb58f..4c89bf6725b3b8f1e815b8dc6379f82baf07164b 100644 (file)
@@ -1112,9 +1112,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;
        }
@@ -3217,8 +3215,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(
index b78096a7690eeba147052a04a48eb10a493ee6f4..f7e31aec32058d509b0dd8d750ead8b96cac1190 100644 (file)
@@ -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)
@@ -2849,9 +2847,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
index 03ba01f4ace18a40c25bb650fbe6c4ddf23a8fb3..38f8898266971c534db138da5d63aa70ff13adde 100644 (file)
@@ -538,9 +538,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
index b907ad1acedd9e7f52ddfba19aa62086e4a2185a..922b8d71cf1aa56abc2c9e1114c581809d6197b0 100644 (file)
@@ -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(
index 0d39d193dacfa0fdf04682199fad3ad645656cd5..284f011f5643df2e7b25959421f747407d1ab048 100644 (file)
@@ -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
@@ -1866,9 +1863,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
index a7d66cfd93c9116bdc75ad1918a8a90e7e01e4fd..16ef5250a02e13dfe954ea38fe5a13543fa6ab2f 100644 (file)
@@ -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;
@@ -521,6 +522,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);