]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amd/display: Disable stutter when programming watermarks on dcn32
authorDillon Varone <Dillon.Varone@amd.com>
Mon, 15 Sep 2025 15:22:52 +0000 (11:22 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 23 Sep 2025 14:26:10 +0000 (10:26 -0400)
[WHY&HOW]
Reprogramming watermarks with stutter allowed can cause instability on
some ASICs. Disable it prior to raising watermarks (prepare bandwidth),
then re-enable after lowering (optimize bandwidth).

Reviewed-by: Alvin Lee <Alvin.Lee2@amd.com>
Signed-off-by: Dillon Varone <Dillon.Varone@amd.com>
Signed-off-by: Ivan Lipski <ivan.lipski@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/hubbub/dcn32/dcn32_hubbub.c
drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h

index 9d15ba5917720dc53560a8ec5bbb90a325cc85c3..62d132bf3028f686dbf9687bc3b38f5becb48225 100644 (file)
@@ -1163,6 +1163,7 @@ struct dc_debug_options {
        unsigned int auxless_alpm_lfps_silence_ns;
        unsigned int auxless_alpm_lfps_t1t2_us;
        short auxless_alpm_lfps_t1t2_offset_us;
+       bool disable_stutter_for_wm_program;
 };
 
 
index 92957398ac0a6b1392da034c794b1c825b2eb090..3b71bfaca29140ee16115a447a7084b8da07a655 100644 (file)
@@ -28,6 +28,7 @@
 #include "dcn32_hubbub.h"
 #include "dm_services.h"
 #include "reg_helper.h"
+#include "dal_asic_id.h"
 
 
 #define CTX \
@@ -72,6 +73,14 @@ static void dcn32_init_crb(struct hubbub *hubbub)
        REG_UPDATE(DCHUBBUB_DEBUG_CTRL_0, DET_DEPTH, 0x47F);
 }
 
+static void hubbub32_set_sdp_control(struct hubbub *hubbub, bool dc_control)
+{
+       struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+
+       REG_UPDATE(DCHUBBUB_SDPIF_CFG0,
+                       SDPIF_PORT_CONTROL, dc_control);
+}
+
 void hubbub32_set_request_limit(struct hubbub *hubbub, int memory_channel_count, int words_per_channel)
 {
        struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
@@ -754,8 +763,17 @@ static bool hubbub32_program_watermarks(
                unsigned int refclk_mhz,
                bool safe_to_lower)
 {
+       struct dc *dc = hubbub->ctx->dc;
        bool wm_pending = false;
 
+       if (!safe_to_lower && dc->debug.disable_stutter_for_wm_program &&
+                       (ASICREV_IS_GC_11_0_0(dc->ctx->asic_id.hw_internal_rev) ||
+                       ASICREV_IS_GC_11_0_3(dc->ctx->asic_id.hw_internal_rev))) {
+               /* before raising watermarks, SDP control give to DF, stutter must be disabled */
+               hubbub32_set_sdp_control(hubbub, false);
+               hubbub1_allow_self_refresh_control(hubbub, false);
+       }
+
        if (hubbub32_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
                wm_pending = true;
 
@@ -786,10 +804,20 @@ static bool hubbub32_program_watermarks(
        REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND,
                        DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0x1FF);*/
 
-       if (safe_to_lower || hubbub->ctx->dc->debug.disable_stutter)
-               hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);
+       if (safe_to_lower) {
+               /* after lowering watermarks, stutter setting is restored, SDP control given to DC */
+               hubbub1_allow_self_refresh_control(hubbub, !dc->debug.disable_stutter);
+
+               if (dc->debug.disable_stutter_for_wm_program &&
+                               (ASICREV_IS_GC_11_0_0(dc->ctx->asic_id.hw_internal_rev) ||
+                               ASICREV_IS_GC_11_0_3(dc->ctx->asic_id.hw_internal_rev))) {
+                       hubbub32_set_sdp_control(hubbub, true);
+               }
+       } else if (dc->debug.disable_stutter) {
+               hubbub1_allow_self_refresh_control(hubbub, !dc->debug.disable_stutter);
+       }
 
-       hubbub32_force_usr_retraining_allow(hubbub, hubbub->ctx->dc->debug.force_usr_allow);
+       hubbub32_force_usr_retraining_allow(hubbub, dc->debug.force_usr_allow);
 
        return wm_pending;
 }
@@ -974,8 +1002,7 @@ void hubbub32_init(struct hubbub *hubbub)
        ignore the "df_pre_cstate_req" from the SDP port control.
        only the DCN will determine when to connect the SDP port
        */
-       REG_UPDATE(DCHUBBUB_SDPIF_CFG0,
-                       SDPIF_PORT_CONTROL, 1);
+       hubbub32_set_sdp_control(hubbub, true);
        /*Set SDP's max outstanding request to 512
        must set the register back to 0 (max outstanding = 256) in zero frame buffer mode*/
        REG_UPDATE(DCHUBBUB_SDPIF_CFG1,
index 8f80ccb846d76ca197dcbfaf2122af81bd888e29..3965a7f1b64b7d0b2d2d08b38fb56b6e8434889e 100644 (file)
@@ -739,6 +739,7 @@ static const struct dc_debug_options debug_defaults_drv = {
        .fpo_vactive_min_active_margin_us = 200,
        .fpo_vactive_max_blank_us = 1000,
        .enable_legacy_fast_update = false,
+       .disable_stutter_for_wm_program = true
 };
 
 static struct dce_aux *dcn32_aux_engine_create(
index 20d71459602126a00a9e1516ced4a48e5710725e..99f0432288b448fa19f67169a07024243818e65b 100644 (file)
@@ -1230,7 +1230,8 @@ unsigned int dcn32_get_max_hw_cursor_size(const struct dc *dc,
       SR(DCHUBBUB_ARB_MALL_CNTL),                                              \
       SR(DCN_VM_FAULT_ADDR_MSB), SR(DCN_VM_FAULT_ADDR_LSB),                    \
       SR(DCN_VM_FAULT_CNTL), SR(DCN_VM_FAULT_STATUS),                          \
-      SR(SDPIF_REQUEST_RATE_LIMIT)
+      SR(SDPIF_REQUEST_RATE_LIMIT),                                            \
+      SR(DCHUBBUB_SDPIF_CFG0)
 
 /* DCCG */