From: Yongqiang Sun <yongqiang....@amd.com>

[Why]
In some display configuration like 1080P monitor playing a 1080P video,
if user use ALT+F4 to exit Movie and TV, there is a chance clocks are
same only water mark changed. Current clock optimization machanism will
result in water mark keeps high after exit Movie and TV app.

[How]
Return if watermark need to be optimized when doing program watermark,
perform the optimization after.

Signed-off-by: Yongqiang Sun <yongqiang....@amd.com>
Reviewed-by: Tony Cheng <tony.ch...@amd.com>
Acked-by: Rodrigo Siqueira <rodrigo.sique...@amd.com>
Acked-by: Harry Wentland <harry.wentl...@amd.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c      |  10 +-
 drivers/gpu/drm/amd/display/dc/dc.h           |   3 +-
 .../drm/amd/display/dc/dcn10/dcn10_hubbub.c   | 101 +++++++++----
 .../drm/amd/display/dc/dcn10/dcn10_hubbub.h   |   8 +-
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.c |  33 +++--
 .../drm/amd/display/dc/dcn20/dcn20_hubbub.c   |  11 +-
 .../drm/amd/display/dc/dcn20/dcn20_hwseq.c    |  26 ++--
 .../drm/amd/display/dc/dcn21/dcn21_hubbub.c   | 137 +++++++++++++-----
 .../drm/amd/display/dc/dcn21/dcn21_hubbub.h   |   8 +-
 .../gpu/drm/amd/display/dc/inc/hw/dchubbub.h  |   2 +-
 10 files changed, 237 insertions(+), 102 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c 
b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 7513aa71da38..6dece1ee30bf 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -1365,7 +1365,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc)
        int i;
        struct dc_state *context = dc->current_state;
 
-       if (!dc->optimized_required || dc->optimize_seamless_boot_streams > 0)
+       if ((!dc->clk_optimized_required && !dc->wm_optimized_required) || 
dc->optimize_seamless_boot_streams > 0)
                return true;
 
        post_surface_trace(dc);
@@ -1377,8 +1377,6 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc)
                        dc->hwss.disable_plane(dc, 
&context->res_ctx.pipe_ctx[i]);
                }
 
-       dc->optimized_required = false;
-
        dc->hwss.optimize_bandwidth(dc, context);
        return true;
 }
@@ -1826,10 +1824,10 @@ enum surface_update_type 
dc_check_update_surfaces_for_stream(
                // If there's an available clock comparator, we use that.
                if (dc->clk_mgr->funcs->are_clock_states_equal) {
                        if 
(!dc->clk_mgr->funcs->are_clock_states_equal(&dc->clk_mgr->clks, 
&dc->current_state->bw_ctx.bw.dcn.clk))
-                               dc->optimized_required = true;
+                               dc->clk_optimized_required = true;
                // Else we fallback to mem compare.
                } else if (memcmp(&dc->current_state->bw_ctx.bw.dcn.clk, 
&dc->clk_mgr->clks, offsetof(struct dc_clocks, prev_p_state_change_support)) != 
0) {
-                       dc->optimized_required = true;
+                       dc->clk_optimized_required = true;
                }
        }
 
@@ -2200,7 +2198,7 @@ static void commit_planes_for_stream(struct dc *dc,
                        dc->optimize_seamless_boot_streams--;
 
                        if (dc->optimize_seamless_boot_streams == 0)
-                               dc->optimized_required = true;
+                               dc->clk_optimized_required = true;
                }
        }
 
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h 
b/drivers/gpu/drm/amd/display/dc/dc.h
index e10d5a7d0cb8..bc1220dce3b1 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -520,7 +520,8 @@ struct dc {
        struct dce_hwseq *hwseq;
 
        /* Require to optimize clocks and bandwidth for added/removed planes */
-       bool optimized_required;
+       bool clk_optimized_required;
+       bool wm_optimized_required;
 
        /* Require to maintain clocks and bandwidth for UEFI enabled HW */
        int optimize_seamless_boot_streams;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c 
b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
index 3e851713cf8d..e441c149ff40 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
@@ -243,7 +243,7 @@ void hubbub1_wm_change_req_wa(struct hubbub *hubbub)
                        DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1);
 }
 
-void hubbub1_program_urgent_watermarks(
+bool hubbub1_program_urgent_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
@@ -251,6 +251,7 @@ void hubbub1_program_urgent_watermarks(
 {
        struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
        uint32_t prog_wm_value;
+       bool wm_pending = false;
 
        /* Repeat for water mark set A, B, C and D. */
        /* clock state A */
@@ -264,7 +265,8 @@ void hubbub1_program_urgent_watermarks(
                DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->a.urgent_ns, prog_wm_value);
-       }
+       } else if (watermarks->a.urgent_ns < hubbub1->watermarks.a.urgent_ns)
+               wm_pending = true;
 
        if (safe_to_lower || watermarks->a.pte_meta_urgent_ns > 
hubbub1->watermarks.a.pte_meta_urgent_ns) {
                hubbub1->watermarks.a.pte_meta_urgent_ns = 
watermarks->a.pte_meta_urgent_ns;
@@ -274,7 +276,8 @@ void hubbub1_program_urgent_watermarks(
                DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_A calculated 
=%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->a.pte_meta_urgent_ns, prog_wm_value);
-       }
+       } else if (watermarks->a.pte_meta_urgent_ns < 
hubbub1->watermarks.a.pte_meta_urgent_ns)
+               wm_pending = true;
 
        /* clock state B */
        if (safe_to_lower || watermarks->b.urgent_ns > 
hubbub1->watermarks.b.urgent_ns) {
@@ -287,7 +290,8 @@ void hubbub1_program_urgent_watermarks(
                DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->b.urgent_ns, prog_wm_value);
-       }
+       } else if (watermarks->b.urgent_ns < hubbub1->watermarks.b.urgent_ns)
+               wm_pending = true;
 
        if (safe_to_lower || watermarks->b.pte_meta_urgent_ns > 
hubbub1->watermarks.b.pte_meta_urgent_ns) {
                hubbub1->watermarks.b.pte_meta_urgent_ns = 
watermarks->b.pte_meta_urgent_ns;
@@ -297,7 +301,8 @@ void hubbub1_program_urgent_watermarks(
                DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_B calculated 
=%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->b.pte_meta_urgent_ns, prog_wm_value);
-       }
+       } else if (watermarks->b.pte_meta_urgent_ns < 
hubbub1->watermarks.b.pte_meta_urgent_ns)
+               wm_pending = true;
 
        /* clock state C */
        if (safe_to_lower || watermarks->c.urgent_ns > 
hubbub1->watermarks.c.urgent_ns) {
@@ -310,7 +315,8 @@ void hubbub1_program_urgent_watermarks(
                DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_C calculated =%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->c.urgent_ns, prog_wm_value);
-       }
+       } else if (watermarks->c.urgent_ns < hubbub1->watermarks.c.urgent_ns)
+               wm_pending = true;
 
        if (safe_to_lower || watermarks->c.pte_meta_urgent_ns > 
hubbub1->watermarks.c.pte_meta_urgent_ns) {
                hubbub1->watermarks.c.pte_meta_urgent_ns = 
watermarks->c.pte_meta_urgent_ns;
@@ -320,7 +326,8 @@ void hubbub1_program_urgent_watermarks(
                DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_C calculated 
=%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->c.pte_meta_urgent_ns, prog_wm_value);
-       }
+       } else if (watermarks->c.pte_meta_urgent_ns < 
hubbub1->watermarks.c.pte_meta_urgent_ns)
+               wm_pending = true;
 
        /* clock state D */
        if (safe_to_lower || watermarks->d.urgent_ns > 
hubbub1->watermarks.d.urgent_ns) {
@@ -333,7 +340,8 @@ void hubbub1_program_urgent_watermarks(
                DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_D calculated =%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->d.urgent_ns, prog_wm_value);
-       }
+       } else if (watermarks->d.urgent_ns < hubbub1->watermarks.d.urgent_ns)
+               wm_pending = true;
 
        if (safe_to_lower || watermarks->d.pte_meta_urgent_ns > 
hubbub1->watermarks.d.pte_meta_urgent_ns) {
                hubbub1->watermarks.d.pte_meta_urgent_ns = 
watermarks->d.pte_meta_urgent_ns;
@@ -343,10 +351,13 @@ void hubbub1_program_urgent_watermarks(
                DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_D calculated 
=%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->d.pte_meta_urgent_ns, prog_wm_value);
-       }
+       } else if (watermarks->d.pte_meta_urgent_ns < 
hubbub1->watermarks.d.pte_meta_urgent_ns)
+               wm_pending = true;
+
+       return wm_pending;
 }
 
-void hubbub1_program_stutter_watermarks(
+bool hubbub1_program_stutter_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
@@ -354,6 +365,7 @@ void hubbub1_program_stutter_watermarks(
 {
        struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
        uint32_t prog_wm_value;
+       bool wm_pending = false;
 
        /* clock state A */
        if (safe_to_lower || 
watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns
@@ -368,7 +380,9 @@ void hubbub1_program_stutter_watermarks(
                DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated 
=%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns
+                       < 
hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns)
+               wm_pending = true;
 
        if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_ns
                        > hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns) {
@@ -382,7 +396,9 @@ void hubbub1_program_stutter_watermarks(
                DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->a.cstate_pstate.cstate_exit_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->a.cstate_pstate.cstate_exit_ns
+                       < hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns)
+               wm_pending = true;
 
        /* clock state B */
        if (safe_to_lower || 
watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns
@@ -397,7 +413,9 @@ void hubbub1_program_stutter_watermarks(
                DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated 
=%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns
+                       < 
hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns)
+               wm_pending = true;
 
        if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_ns
                        > hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns) {
@@ -411,7 +429,9 @@ void hubbub1_program_stutter_watermarks(
                DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->b.cstate_pstate.cstate_exit_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->b.cstate_pstate.cstate_exit_ns
+                       < hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns)
+               wm_pending = true;
 
        /* clock state C */
        if (safe_to_lower || 
watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns
@@ -426,7 +446,9 @@ void hubbub1_program_stutter_watermarks(
                DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated 
=%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns
+                       < 
hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns)
+               wm_pending = true;
 
        if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_ns
                        > hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns) {
@@ -440,7 +462,9 @@ void hubbub1_program_stutter_watermarks(
                DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->c.cstate_pstate.cstate_exit_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->c.cstate_pstate.cstate_exit_ns
+                       < hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns)
+               wm_pending = true;
 
        /* clock state D */
        if (safe_to_lower || 
watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns
@@ -455,7 +479,9 @@ void hubbub1_program_stutter_watermarks(
                DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated 
=%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns
+                       < 
hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns)
+               wm_pending = true;
 
        if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_ns
                        > hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns) {
@@ -469,11 +495,14 @@ void hubbub1_program_stutter_watermarks(
                DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->d.cstate_pstate.cstate_exit_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->d.cstate_pstate.cstate_exit_ns
+                       < hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns)
+               wm_pending = true;
 
+       return wm_pending;
 }
 
-void hubbub1_program_pstate_watermarks(
+bool hubbub1_program_pstate_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
@@ -481,6 +510,7 @@ void hubbub1_program_pstate_watermarks(
 {
        struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
        uint32_t prog_wm_value;
+       bool wm_pending = false;
 
        /* clock state A */
        if (safe_to_lower || watermarks->a.cstate_pstate.pstate_change_ns
@@ -495,7 +525,9 @@ void hubbub1_program_pstate_watermarks(
                DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated 
=%d\n"
                        "HW register value = 0x%x\n\n",
                        watermarks->a.cstate_pstate.pstate_change_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->a.cstate_pstate.pstate_change_ns
+                       < hubbub1->watermarks.a.cstate_pstate.pstate_change_ns)
+               wm_pending = true;
 
        /* clock state B */
        if (safe_to_lower || watermarks->b.cstate_pstate.pstate_change_ns
@@ -510,7 +542,9 @@ void hubbub1_program_pstate_watermarks(
                DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated 
=%d\n"
                        "HW register value = 0x%x\n\n",
                        watermarks->b.cstate_pstate.pstate_change_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->b.cstate_pstate.pstate_change_ns
+                       < hubbub1->watermarks.b.cstate_pstate.pstate_change_ns)
+               wm_pending = true;
 
        /* clock state C */
        if (safe_to_lower || watermarks->c.cstate_pstate.pstate_change_ns
@@ -525,7 +559,9 @@ void hubbub1_program_pstate_watermarks(
                DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated 
=%d\n"
                        "HW register value = 0x%x\n\n",
                        watermarks->c.cstate_pstate.pstate_change_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->c.cstate_pstate.pstate_change_ns
+                       < hubbub1->watermarks.c.cstate_pstate.pstate_change_ns)
+               wm_pending = true;
 
        /* clock state D */
        if (safe_to_lower || watermarks->d.cstate_pstate.pstate_change_ns
@@ -540,23 +576,33 @@ void hubbub1_program_pstate_watermarks(
                DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated 
=%d\n"
                        "HW register value = 0x%x\n\n",
                        watermarks->d.cstate_pstate.pstate_change_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->d.cstate_pstate.pstate_change_ns
+                       < hubbub1->watermarks.d.cstate_pstate.pstate_change_ns)
+               wm_pending = true;
+
+       return wm_pending;
 }
 
-void hubbub1_program_watermarks(
+bool hubbub1_program_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
                bool safe_to_lower)
 {
        struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
+       bool wm_pending = false;
        /*
         * Need to clamp to max of the register values (i.e. no wrap)
         * for dcn1, all wm registers are 21-bit wide
         */
-       hubbub1_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, 
safe_to_lower);
-       hubbub1_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, 
safe_to_lower);
-       hubbub1_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, 
safe_to_lower);
+       if (hubbub1_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, 
safe_to_lower))
+               wm_pending = true;
+
+       if (hubbub1_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, 
safe_to_lower))
+               wm_pending = true;
+
+       if (hubbub1_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, 
safe_to_lower))
+               wm_pending = true;
 
        REG_UPDATE(DCHUBBUB_ARB_SAT_LEVEL,
                        DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
@@ -570,6 +616,7 @@ void hubbub1_program_watermarks(
                        DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, 1,
                        DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1);
 #endif
+       return wm_pending;
 }
 
 void hubbub1_update_dchub(
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h 
b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
index af57751253de..343a537172c7 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
@@ -308,7 +308,7 @@ bool hubbub1_verify_allow_pstate_change_high(
 
 void hubbub1_wm_change_req_wa(struct hubbub *hubbub);
 
-void hubbub1_program_watermarks(
+bool hubbub1_program_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
@@ -331,17 +331,17 @@ void hubbub1_construct(struct hubbub *hubbub,
        const struct dcn_hubbub_shift *hubbub_shift,
        const struct dcn_hubbub_mask *hubbub_mask);
 
-void hubbub1_program_urgent_watermarks(
+bool hubbub1_program_urgent_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
                bool safe_to_lower);
-void hubbub1_program_stutter_watermarks(
+bool hubbub1_program_stutter_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
                bool safe_to_lower);
-void hubbub1_program_pstate_watermarks(
+bool hubbub1_program_pstate_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c 
b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
index 77396a08ad29..c381d347208f 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -1048,7 +1048,7 @@ void dcn10_plane_atomic_disconnect(struct dc *dc, struct 
pipe_ctx *pipe_ctx)
        if (opp != NULL)
                opp->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = 
true;
 
-       dc->optimized_required = true;
+       dc->clk_optimized_required = true;
 
        if (hubp->funcs->hubp_disconnect)
                hubp->funcs->hubp_disconnect(hubp);
@@ -1099,7 +1099,7 @@ void dcn10_plane_atomic_disable(struct dc *dc, struct 
pipe_ctx *pipe_ctx)
                                false);
 
        hubp->power_gated = true;
-       dc->optimized_required = false; /* We're powering off, no need to 
optimize */
+       dc->clk_optimized_required = false; /* We're powering off, no need to 
optimize */
 
        hws->funcs.plane_atomic_power_down(dc,
                        pipe_ctx->plane_res.dpp,
@@ -2686,7 +2686,7 @@ void dcn10_prepare_bandwidth(
                                false);
        }
 
-       hubbub->funcs->program_watermarks(hubbub,
+       dc->wm_optimized_required = hubbub->funcs->program_watermarks(hubbub,
                        &context->bw_ctx.bw.dcn.watermarks,
                        dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
                        true);
@@ -2710,19 +2710,30 @@ void dcn10_optimize_bandwidth(
                hws->funcs.verify_allow_pstate_change_high(dc);
 
        if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
-               if (context->stream_count == 0)
+               if (context->stream_count == 0) {
                        context->bw_ctx.bw.dcn.clk.phyclk_khz = 0;
 
-               dc->clk_mgr->funcs->update_clocks(
-                               dc->clk_mgr,
-                               context,
+                       dc->clk_mgr->funcs->update_clocks(
+                                       dc->clk_mgr,
+                                       context,
+                                       true);
+               } else if (dc->clk_optimized_required || 
IS_DIAG_DC(dc->ctx->dce_environment)) {
+                       dc->clk_mgr->funcs->update_clocks(
+                                                               dc->clk_mgr,
+                                                               context,
+                                                               true);
+               }
+       }
+
+       if (dc->wm_optimized_required || IS_DIAG_DC(dc->ctx->dce_environment)) {
+               hubbub->funcs->program_watermarks(hubbub,
+                               &context->bw_ctx.bw.dcn.watermarks,
+                               dc->res_pool->ref_clocks.dchub_ref_clock_inKhz 
/ 1000,
                                true);
        }
 
-       hubbub->funcs->program_watermarks(hubbub,
-                       &context->bw_ctx.bw.dcn.watermarks,
-                       dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
-                       true);
+       dc->clk_optimized_required = false;
+       dc->wm_optimized_required = false;
        dcn10_stereo_hw_frame_pack_wa(dc, context);
 
        if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
index 9235f7d29454..c0b21d7450d4 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
@@ -562,19 +562,23 @@ void hubbub2_get_dchub_ref_freq(struct hubbub *hubbub,
        }
 }
 
-static void hubbub2_program_watermarks(
+static bool hubbub2_program_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
                bool safe_to_lower)
 {
        struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
+       bool wm_pending = false;
        /*
         * Need to clamp to max of the register values (i.e. no wrap)
         * for dcn1, all wm registers are 21-bit wide
         */
-       hubbub1_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, 
safe_to_lower);
-       hubbub1_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, 
safe_to_lower);
+       if (hubbub1_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, 
safe_to_lower))
+               wm_pending = true;
+
+       if (hubbub1_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, 
safe_to_lower))
+               wm_pending = true;
 
        /*
         * There's a special case when going from p-state support to p-state 
unsupported
@@ -592,6 +596,7 @@ static void hubbub2_program_watermarks(
        REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 
180);
 
        hubbub->funcs->allow_self_refresh_control(hubbub, 
!hubbub->ctx->dc->debug.disable_stutter);
+       return wm_pending;
 }
 
 static const struct hubbub_funcs hubbub2_funcs = {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
index b9ec40a31f5c..cf13b1db1025 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -1627,7 +1627,7 @@ void dcn20_prepare_bandwidth(
                        false);
 
        /* program dchubbub watermarks */
-       hubbub->funcs->program_watermarks(hubbub,
+       dc->wm_optimized_required = hubbub->funcs->program_watermarks(hubbub,
                                        &context->bw_ctx.bw.dcn.watermarks,
                                        
dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
                                        false);
@@ -1639,16 +1639,22 @@ void dcn20_optimize_bandwidth(
 {
        struct hubbub *hubbub = dc->res_pool->hubbub;
 
-       /* program dchubbub watermarks */
-       hubbub->funcs->program_watermarks(hubbub,
-                                       &context->bw_ctx.bw.dcn.watermarks,
-                                       
dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
-                                       true);
+       if (dc->wm_optimized_required || IS_DIAG_DC(dc->ctx->dce_environment)) {
+               /* program dchubbub watermarks */
+               hubbub->funcs->program_watermarks(hubbub,
+                                               
&context->bw_ctx.bw.dcn.watermarks,
+                                               
dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
+                                               true);
+               dc->wm_optimized_required = false;
+       }
 
-       dc->clk_mgr->funcs->update_clocks(
-                       dc->clk_mgr,
-                       context,
-                       true);
+       if (dc->clk_optimized_required || IS_DIAG_DC(dc->ctx->dce_environment)) 
{
+               dc->clk_mgr->funcs->update_clocks(
+                               dc->clk_mgr,
+                               context,
+                               true);
+               dc->wm_optimized_required = false;
+       }
 }
 
 bool dcn20_update_bandwidth(
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c 
b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c
index f546260c15b7..8440975206e0 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c
@@ -141,7 +141,7 @@ int hubbub21_init_dchub(struct hubbub *hubbub,
        return NUM_VMID;
 }
 
-void hubbub21_program_urgent_watermarks(
+bool hubbub21_program_urgent_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
@@ -149,6 +149,7 @@ void hubbub21_program_urgent_watermarks(
 {
        struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
        uint32_t prog_wm_value;
+       bool wm_pending = false;
 
        /* Repeat for water mark set A, B, C and D. */
        /* clock state A */
@@ -163,7 +164,8 @@ void hubbub21_program_urgent_watermarks(
                DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->a.urgent_ns, prog_wm_value);
-       }
+       } else if (watermarks->a.urgent_ns < hubbub1->watermarks.a.urgent_ns)
+               wm_pending = true;
 
        /* determine the transfer time for a quantity of data for a particular 
requestor.*/
        if (safe_to_lower || watermarks->a.frac_urg_bw_flip
@@ -172,7 +174,9 @@ void hubbub21_program_urgent_watermarks(
 
                REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, 0,
                                DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, 
watermarks->a.frac_urg_bw_flip);
-       }
+       } else if (watermarks->a.frac_urg_bw_flip
+                       < hubbub1->watermarks.a.frac_urg_bw_flip)
+               wm_pending = true;
 
        if (safe_to_lower || watermarks->a.frac_urg_bw_nom
                        > hubbub1->watermarks.a.frac_urg_bw_nom) {
@@ -180,14 +184,18 @@ void hubbub21_program_urgent_watermarks(
 
                REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, 0,
                                DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, 
watermarks->a.frac_urg_bw_nom);
-       }
+       } else if (watermarks->a.frac_urg_bw_nom
+                       < hubbub1->watermarks.a.frac_urg_bw_nom)
+               wm_pending = true;
+
        if (safe_to_lower || watermarks->a.urgent_latency_ns > 
hubbub1->watermarks.a.urgent_latency_ns) {
                hubbub1->watermarks.a.urgent_latency_ns = 
watermarks->a.urgent_latency_ns;
                prog_wm_value = 
convert_and_clamp(watermarks->a.urgent_latency_ns,
                                refclk_mhz, 0x1fffff);
                REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 0,
                                DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 
prog_wm_value);
-       }
+       } else if (watermarks->a.urgent_latency_ns < 
hubbub1->watermarks.a.urgent_latency_ns)
+               wm_pending = true;
 
        /* clock state B */
        if (safe_to_lower || watermarks->b.urgent_ns > 
hubbub1->watermarks.b.urgent_ns) {
@@ -201,7 +209,8 @@ void hubbub21_program_urgent_watermarks(
                DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->b.urgent_ns, prog_wm_value);
-       }
+       } else if (watermarks->b.urgent_ns < hubbub1->watermarks.b.urgent_ns)
+               wm_pending = true;
 
        /* determine the transfer time for a quantity of data for a particular 
requestor.*/
        if (safe_to_lower || watermarks->a.frac_urg_bw_flip
@@ -210,7 +219,9 @@ void hubbub21_program_urgent_watermarks(
 
                REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, 0,
                                DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, 
watermarks->a.frac_urg_bw_flip);
-       }
+       } else if (watermarks->a.frac_urg_bw_flip
+                       < hubbub1->watermarks.a.frac_urg_bw_flip)
+               wm_pending = true;
 
        if (safe_to_lower || watermarks->a.frac_urg_bw_nom
                        > hubbub1->watermarks.a.frac_urg_bw_nom) {
@@ -218,7 +229,9 @@ void hubbub21_program_urgent_watermarks(
 
                REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, 0,
                                DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, 
watermarks->a.frac_urg_bw_nom);
-       }
+       } else if (watermarks->a.frac_urg_bw_nom
+                       < hubbub1->watermarks.a.frac_urg_bw_nom)
+               wm_pending = true;
 
        if (safe_to_lower || watermarks->b.urgent_latency_ns > 
hubbub1->watermarks.b.urgent_latency_ns) {
                hubbub1->watermarks.b.urgent_latency_ns = 
watermarks->b.urgent_latency_ns;
@@ -226,7 +239,8 @@ void hubbub21_program_urgent_watermarks(
                                refclk_mhz, 0x1fffff);
                REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 0,
                                DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 
prog_wm_value);
-       }
+       } else if (watermarks->b.urgent_latency_ns < 
hubbub1->watermarks.b.urgent_latency_ns)
+               wm_pending = true;
 
        /* clock state C */
        if (safe_to_lower || watermarks->c.urgent_ns > 
hubbub1->watermarks.c.urgent_ns) {
@@ -240,7 +254,8 @@ void hubbub21_program_urgent_watermarks(
                DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_C calculated =%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->c.urgent_ns, prog_wm_value);
-       }
+       } else if (watermarks->c.urgent_ns < hubbub1->watermarks.c.urgent_ns)
+               wm_pending = true;
 
        /* determine the transfer time for a quantity of data for a particular 
requestor.*/
        if (safe_to_lower || watermarks->a.frac_urg_bw_flip
@@ -249,7 +264,9 @@ void hubbub21_program_urgent_watermarks(
 
                REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, 0,
                                DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, 
watermarks->a.frac_urg_bw_flip);
-       }
+       } else if (watermarks->a.frac_urg_bw_flip
+                       < hubbub1->watermarks.a.frac_urg_bw_flip)
+               wm_pending = true;
 
        if (safe_to_lower || watermarks->a.frac_urg_bw_nom
                        > hubbub1->watermarks.a.frac_urg_bw_nom) {
@@ -257,7 +274,9 @@ void hubbub21_program_urgent_watermarks(
 
                REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, 0,
                                DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, 
watermarks->a.frac_urg_bw_nom);
-       }
+       } else if (watermarks->a.frac_urg_bw_nom
+                       < hubbub1->watermarks.a.frac_urg_bw_nom)
+               wm_pending = true;
 
        if (safe_to_lower || watermarks->c.urgent_latency_ns > 
hubbub1->watermarks.c.urgent_latency_ns) {
                hubbub1->watermarks.c.urgent_latency_ns = 
watermarks->c.urgent_latency_ns;
@@ -265,7 +284,8 @@ void hubbub21_program_urgent_watermarks(
                                refclk_mhz, 0x1fffff);
                REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, 0,
                                DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, 
prog_wm_value);
-       }
+       } else if (watermarks->c.urgent_latency_ns < 
hubbub1->watermarks.c.urgent_latency_ns)
+               wm_pending = true;
 
        /* clock state D */
        if (safe_to_lower || watermarks->d.urgent_ns > 
hubbub1->watermarks.d.urgent_ns) {
@@ -279,7 +299,8 @@ void hubbub21_program_urgent_watermarks(
                DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_D calculated =%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->d.urgent_ns, prog_wm_value);
-       }
+       } else if (watermarks->d.urgent_ns < hubbub1->watermarks.d.urgent_ns)
+               wm_pending = true;
 
        /* determine the transfer time for a quantity of data for a particular 
requestor.*/
        if (safe_to_lower || watermarks->a.frac_urg_bw_flip
@@ -288,7 +309,9 @@ void hubbub21_program_urgent_watermarks(
 
                REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, 0,
                                DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, 
watermarks->a.frac_urg_bw_flip);
-       }
+       } else if (watermarks->a.frac_urg_bw_flip
+                       < hubbub1->watermarks.a.frac_urg_bw_flip)
+               wm_pending = true;
 
        if (safe_to_lower || watermarks->a.frac_urg_bw_nom
                        > hubbub1->watermarks.a.frac_urg_bw_nom) {
@@ -296,7 +319,9 @@ void hubbub21_program_urgent_watermarks(
 
                REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, 0,
                                DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, 
watermarks->a.frac_urg_bw_nom);
-       }
+       } else if (watermarks->a.frac_urg_bw_nom
+                       < hubbub1->watermarks.a.frac_urg_bw_nom)
+               wm_pending = true;
 
        if (safe_to_lower || watermarks->d.urgent_latency_ns > 
hubbub1->watermarks.d.urgent_latency_ns) {
                hubbub1->watermarks.d.urgent_latency_ns = 
watermarks->d.urgent_latency_ns;
@@ -304,10 +329,13 @@ void hubbub21_program_urgent_watermarks(
                                refclk_mhz, 0x1fffff);
                REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, 0,
                                DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, 
prog_wm_value);
-       }
+       } else if (watermarks->d.urgent_latency_ns < 
hubbub1->watermarks.d.urgent_latency_ns)
+               wm_pending = true;
+
+       return wm_pending;
 }
 
-void hubbub21_program_stutter_watermarks(
+bool hubbub21_program_stutter_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
@@ -315,6 +343,7 @@ void hubbub21_program_stutter_watermarks(
 {
        struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
        uint32_t prog_wm_value;
+       bool wm_pending = false;
 
        /* clock state A */
        if (safe_to_lower || 
watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns
@@ -330,7 +359,9 @@ void hubbub21_program_stutter_watermarks(
                DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated 
=%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns
+                       < 
hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns)
+               wm_pending = true;
 
        if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_ns
                        > hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns) {
@@ -345,7 +376,9 @@ void hubbub21_program_stutter_watermarks(
                DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->a.cstate_pstate.cstate_exit_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->a.cstate_pstate.cstate_exit_ns
+                       < hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns)
+               wm_pending = true;
 
        /* clock state B */
        if (safe_to_lower || 
watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns
@@ -361,7 +394,9 @@ void hubbub21_program_stutter_watermarks(
                DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated 
=%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns
+                       < 
hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns)
+               wm_pending = true;
 
        if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_ns
                        > hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns) {
@@ -376,7 +411,9 @@ void hubbub21_program_stutter_watermarks(
                DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->b.cstate_pstate.cstate_exit_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->b.cstate_pstate.cstate_exit_ns
+                       < hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns)
+               wm_pending = true;
 
        /* clock state C */
        if (safe_to_lower || 
watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns
@@ -392,7 +429,9 @@ void hubbub21_program_stutter_watermarks(
                DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated 
=%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns
+                       < 
hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns)
+               wm_pending = true;
 
        if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_ns
                        > hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns) {
@@ -407,7 +446,9 @@ void hubbub21_program_stutter_watermarks(
                DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->c.cstate_pstate.cstate_exit_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->c.cstate_pstate.cstate_exit_ns
+                       < hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns)
+               wm_pending = true;
 
        /* clock state D */
        if (safe_to_lower || 
watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns
@@ -423,7 +464,9 @@ void hubbub21_program_stutter_watermarks(
                DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated 
=%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns
+                       < 
hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns)
+               wm_pending = true;
 
        if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_ns
                        > hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns) {
@@ -438,10 +481,14 @@ void hubbub21_program_stutter_watermarks(
                DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n"
                        "HW register value = 0x%x\n",
                        watermarks->d.cstate_pstate.cstate_exit_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->d.cstate_pstate.cstate_exit_ns
+                       < hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns)
+               wm_pending = true;
+
+       return wm_pending;
 }
 
-void hubbub21_program_pstate_watermarks(
+bool hubbub21_program_pstate_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
@@ -450,6 +497,8 @@ void hubbub21_program_pstate_watermarks(
        struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
        uint32_t prog_wm_value;
 
+       bool wm_pending = false;
+
        /* clock state A */
        if (safe_to_lower || watermarks->a.cstate_pstate.pstate_change_ns
                        > hubbub1->watermarks.a.cstate_pstate.pstate_change_ns) 
{
@@ -464,7 +513,9 @@ void hubbub21_program_pstate_watermarks(
                DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated 
=%d\n"
                        "HW register value = 0x%x\n\n",
                        watermarks->a.cstate_pstate.pstate_change_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->a.cstate_pstate.pstate_change_ns
+                       < hubbub1->watermarks.a.cstate_pstate.pstate_change_ns)
+               wm_pending = true;
 
        /* clock state B */
        if (safe_to_lower || watermarks->b.cstate_pstate.pstate_change_ns
@@ -480,7 +531,9 @@ void hubbub21_program_pstate_watermarks(
                DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated 
=%d\n"
                        "HW register value = 0x%x\n\n",
                        watermarks->b.cstate_pstate.pstate_change_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->b.cstate_pstate.pstate_change_ns
+                       < hubbub1->watermarks.b.cstate_pstate.pstate_change_ns)
+               wm_pending = false;
 
        /* clock state C */
        if (safe_to_lower || watermarks->c.cstate_pstate.pstate_change_ns
@@ -496,7 +549,9 @@ void hubbub21_program_pstate_watermarks(
                DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated 
=%d\n"
                        "HW register value = 0x%x\n\n",
                        watermarks->c.cstate_pstate.pstate_change_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->c.cstate_pstate.pstate_change_ns
+                       < hubbub1->watermarks.c.cstate_pstate.pstate_change_ns)
+               wm_pending = true;
 
        /* clock state D */
        if (safe_to_lower || watermarks->d.cstate_pstate.pstate_change_ns
@@ -512,20 +567,30 @@ void hubbub21_program_pstate_watermarks(
                DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated 
=%d\n"
                        "HW register value = 0x%x\n\n",
                        watermarks->d.cstate_pstate.pstate_change_ns, 
prog_wm_value);
-       }
+       } else if (watermarks->d.cstate_pstate.pstate_change_ns
+                       < hubbub1->watermarks.d.cstate_pstate.pstate_change_ns)
+               wm_pending = true;
+
+       return wm_pending;
 }
 
-void hubbub21_program_watermarks(
+bool hubbub21_program_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
                bool safe_to_lower)
 {
        struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
+       bool wm_pending = false;
+
+       if (hubbub21_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, 
safe_to_lower))
+               wm_pending = true;
 
-       hubbub21_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, 
safe_to_lower);
-       hubbub21_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, 
safe_to_lower);
-       hubbub21_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, 
safe_to_lower);
+       if (hubbub21_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, 
safe_to_lower))
+               wm_pending = true;
+
+       if (hubbub21_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, 
safe_to_lower))
+               wm_pending = true;
 
        /*
         * The DCHub arbiter has a mechanism to dynamically rate limit the 
DCHub request stream to the fabric.
@@ -549,6 +614,8 @@ void hubbub21_program_watermarks(
                        DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, 0xF);
 
        hubbub1_allow_self_refresh_control(hubbub, 
!hubbub->ctx->dc->debug.disable_stutter);
+
+       return wm_pending;
 }
 
 void hubbub21_wm_read_state(struct hubbub *hubbub,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.h 
b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.h
index c4840dfb1fa5..ef3ef28509ed 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.h
@@ -113,22 +113,22 @@
 void dcn21_dchvm_init(struct hubbub *hubbub);
 int hubbub21_init_dchub(struct hubbub *hubbub,
                struct dcn_hubbub_phys_addr_config *pa_config);
-void hubbub21_program_watermarks(
+bool hubbub21_program_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
                bool safe_to_lower);
-void hubbub21_program_urgent_watermarks(
+bool hubbub21_program_urgent_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
                bool safe_to_lower);
-void hubbub21_program_stutter_watermarks(
+bool hubbub21_program_stutter_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
                bool safe_to_lower);
-void hubbub21_program_pstate_watermarks(
+bool hubbub21_program_pstate_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h 
b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
index c0dc1d0f5cae..f5dd0cc73c63 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
@@ -134,7 +134,7 @@ struct hubbub_funcs {
                        unsigned int dccg_ref_freq_inKhz,
                        unsigned int *dchub_ref_freq_inKhz);
 
-       void (*program_watermarks)(
+       bool (*program_watermarks)(
                        struct hubbub *hubbub,
                        struct dcn_watermark_set *watermarks,
                        unsigned int refclk_mhz,
-- 
2.25.0

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to