--- /dev/null
+From 3b6df06f01cdbff3b610b492ad4879691afdc70d Mon Sep 17 00:00:00 2001
+From: Wesley Chalmers <Wesley.Chalmers@amd.com>
+Date: Wed, 31 May 2023 13:29:34 -0400
+Subject: drm/amd/display: Block optimize on consecutive FAMS enables
+
+From: Wesley Chalmers <Wesley.Chalmers@amd.com>
+
+commit 3b6df06f01cdbff3b610b492ad4879691afdc70d upstream.
+
+[WHY]
+It is possible to commit state multiple times in rapid succession with
+FAMS enabled; if each of these commits were to set optimized_required,
+then the user may see latency.
+
+[HOW]
+fw_based_mclk_switching is currently not used in dc->clk_mgr; use it
+to track whether the current state has FAMS enabled;
+if it has, then do not disable FAMS in prepare_bandwidth, and do not set
+optimized_required.
+
+Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Signed-off-by: Wesley Chalmers <Wesley.Chalmers@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Acked-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 3 ++
+ drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 22 ++++++++++++++++++---
+ 2 files changed, 22 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+@@ -2127,6 +2127,9 @@ void dcn20_optimize_bandwidth(
+ dc_dmub_srv_p_state_delegate(dc,
+ true, context);
+ context->bw_ctx.bw.dcn.clk.p_state_change_support = true;
++ dc->clk_mgr->clks.fw_based_mclk_switching = true;
++ } else {
++ dc->clk_mgr->clks.fw_based_mclk_switching = false;
+ }
+
+ dc->clk_mgr->funcs->update_clocks(
+--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
+@@ -949,9 +949,13 @@ void dcn30_set_disp_pattern_generator(co
+ }
+
+ void dcn30_prepare_bandwidth(struct dc *dc,
+- struct dc_state *context)
++ struct dc_state *context)
+ {
+- if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) {
++ bool p_state_change_support = context->bw_ctx.bw.dcn.clk.p_state_change_support;
++ /* Any transition into an FPO config should disable MCLK switching first to avoid
++ * driver and FW P-State synchronization issues.
++ */
++ if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching || dc->clk_mgr->clks.fw_based_mclk_switching) {
+ dc->optimized_required = true;
+ context->bw_ctx.bw.dcn.clk.p_state_change_support = false;
+ }
+@@ -962,7 +966,19 @@ void dcn30_prepare_bandwidth(struct dc *
+ dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz);
+
+ dcn20_prepare_bandwidth(dc, context);
++ /*
++ * enabled -> enabled: do not disable
++ * enabled -> disabled: disable
++ * disabled -> enabled: don't care
++ * disabled -> disabled: don't care
++ */
++ if (!context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching)
++ dc_dmub_srv_p_state_delegate(dc, false, context);
+
+- dc_dmub_srv_p_state_delegate(dc, false, context);
++ if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching || dc->clk_mgr->clks.fw_based_mclk_switching) {
++ /* After disabling P-State, restore the original value to ensure we get the correct P-State
++ * on the next optimize. */
++ context->bw_ctx.bw.dcn.clk.p_state_change_support = p_state_change_support;
++ }
+ }
+