]> git.ipfire.org Git - thirdparty/linux.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)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 10 Mar 2025 17:28:17 +0000 (13:28 -0400)
[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>
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 e71ea21401f5a4b4806e32ff54cd6ceb802935a4..5a43e4901cc07c4a072f4b96a08367a09a6357d8 100644 (file)
@@ -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;
index e0277728268a581755a3352f6549152613ea747d..52ee2225e132c209c02510e922e8c70809449d1b 100644 (file)
@@ -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,
index 9f3dd8824ed55de675f0ad96d73d507a0d164709..d562ddeca51260db98fc92ec3a4823d8164a9e53 100644 (file)
@@ -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;
 };
 
 
index 9c9947fc5d44291139a4113fda8d56eef34351d2..bfd734e1573174b4fb69d7ad252dd02842c9aee0 100644 (file)
@@ -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(
index 301ef36d3d05d957d570c075e1df9bbbadfa43ba..912f96323ed6ad3e5d3060b497e5410e608a3578 100644 (file)
@@ -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(
index a5a3e0823e21b2cac2e4b8539712b4299710c682..926c08e790c104eac189fdc18564e756f77e5d0c 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)
@@ -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
index 288e9dd9205d299999263da6b09b0c367e1315f9..f38340aa3f159db97ee697887e4de5857aca6858 100644 (file)
@@ -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
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 39668d8cc13a4050e384efce6ff29592d1ce280f..8f5da0ded85072735a663ef29ba7191acbc03806 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
@@ -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
index 2b1a2a00648adc3fcec28ade77bec43445f4da77..c8b5ed834579efeadf714e7a8e6f9e698291dab8 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;
@@ -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);