diff mbox series

[SRU,Kinetic,PULL] Fix AMDGPU: kernel: RIP: 0010:kernel_fpu_begin_mask+0xa4/0xb0 Edit

Message ID 20230303043404.205928-1-koba.ko@canonical.com
State New
Headers show
Series [SRU,Kinetic,PULL] Fix AMDGPU: kernel: RIP: 0010:kernel_fpu_begin_mask+0xa4/0xb0 Edit | expand

Commit Message

Koba Ko March 3, 2023, 4:34 a.m. UTC
BugLink: https://bugs.launchpad.net/bugs/2009044

[Impact]
With AMD W6800, call trace will be printed during system boot
kernel: RIP: 0010:kernel_fpu_begin_mask+0xa4/0xb0

[Fix]
move FPU codes from dcn folder to dml folder.
also clean up the FPU codes on dcn folder.

[Test Case]
1. boot a machine with the AMD W6800.
2. get into desktop and check the dmesg

[Where problems could occur]
Medium, code refactoring so may occur some codes are left in original folder.

[Misc Info]
all patches have been landed on Unstable/Lunar so SRU only for Kinetic.

----------------------------------------------------------------
The following changes since commit 1073c741148b00ad908fd5b335d6566fc4f6c23d:

  UBUNTU: Ubuntu-5.19.0-37.38 (2023-03-01 09:03:08 -0800)

are available in the Git repository at:

  https://git.launchpad.net/~kobako/+git/kinetic_nxt lp2009044

for you to fetch changes up to 0543b19cac04f7edf5587cea6bd31801b0237b64:

  drm/amd/display: make variables static (2023-03-03 02:41:55 +0000)

----------------------------------------------------------------
Magali Lemes (2):
      drm/amd/display: include missing headers
      drm/amd/display: make variables static

Melissa Wen (4):
      drm/amd/display: remove useless FPU protection wrapper from dcn31_resource file
      drm/amd/display: move FPU code on dcn21 clk_mgr
      drm/amd/display: move FPU code from dcn30 clk mgr to DML folder
      drm/amd/display: move FPU code from dcn301 clk mgr to DML folder

Rodrigo Siqueira (5):
      drm/amd/display: Drop unnecessary FPU flags on dcn302 files
      drm/amd/display: Remove FPU operations from dcn201 resources
      drm/amd/display: Create patch bounding box function for isolate FPU
      drm/amd/display: Remove FPU flags from DCN30 Makefile
      drm/amd/display: Fix a compilation failure on PowerPC caused by FPU code

 drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile    |  18 --
 .../drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c  | 234 +--------------
 .../drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.h  |   7 +
 .../amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c   |  55 +---
 .../drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c |  85 +-----
 .../drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.h |   3 +
 drivers/gpu/drm/amd/display/dc/dcn201/Makefile     |  25 --
 .../drm/amd/display/dc/dcn201/dcn201_resource.c    |  10 +-
 drivers/gpu/drm/amd/display/dc/dcn30/Makefile      |  32 --
 drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c  |   8 -
 drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h  |   3 -
 .../gpu/drm/amd/display/dc/dcn30/dcn30_resource.c  |  19 +-
 drivers/gpu/drm/amd/display/dc/dcn302/Makefile     |  19 --
 .../gpu/drm/amd/display/dc/dcn31/dcn31_resource.c  |   6 -
 .../gpu/drm/amd/display/dc/dcn31/dcn31_resource.h  |   1 -
 .../drm/amd/display/dc/dcn315/dcn315_resource.h    |   1 -
 .../drm/amd/display/dc/dcn316/dcn316_resource.h    |   1 -
 drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c  | 328 +++++++++++++++++++++
 .../gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c   | 323 ++++++++++++++++++++
 .../gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h   |   6 +
 .../gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c   |  83 +++++-
 .../gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.h   |   3 +
 .../gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c |  75 +++++
 .../gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c   |   9 +-
 .../drm/amd/display/dc/inc/hw/timing_generator.h   |   2 -
 25 files changed, 859 insertions(+), 497 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c

Comments

Stefan Bader April 12, 2023, 9:09 a.m. UTC | #1
On 03.03.23 05:34, Koba Ko wrote:
> BugLink: https://bugs.launchpad.net/bugs/2009044
> 
> [Impact]
> With AMD W6800, call trace will be printed during system boot
> kernel: RIP: 0010:kernel_fpu_begin_mask+0xa4/0xb0
> 
> [Fix]
> move FPU codes from dcn folder to dml folder.
> also clean up the FPU codes on dcn folder.
> 
> [Test Case]
> 1. boot a machine with the AMD W6800.
> 2. get into desktop and check the dmesg
> 
> [Where problems could occur]
> Medium, code refactoring so may occur some codes are left in original folder.
> 
> [Misc Info]
> all patches have been landed on Unstable/Lunar so SRU only for Kinetic.

Rejected for the following reasons:
- none of the patches has a BugLink
- patch #3 "drm/amd/display: move FPU code from dcn30 clk mgr to DML 
folder"
   claims to be a cherry pick but hunk #2 to dcn30_clk_mgr.c does not 
apply. The
   upstream patch is replacing 65 lines while the backport only replaces 57.
- patch #5 is neither a cherry pick. It adjusts removal by 6 lines which 
have
   already been dropped.
- and this continues with patch #6 , #8, and #9. I did not bother to 
check what
   was changed there.

While the changes I did look at were straight forward in the sense that 
things which were already missing were worked around when removing the 
rest. But this must be documented as backport notes.

-Stefan

> 
> ----------------------------------------------------------------
> The following changes since commit 1073c741148b00ad908fd5b335d6566fc4f6c23d:
> 
>    UBUNTU: Ubuntu-5.19.0-37.38 (2023-03-01 09:03:08 -0800)
> 
> are available in the Git repository at:
> 
>    https://git.launchpad.net/~kobako/+git/kinetic_nxt lp2009044
> 
> for you to fetch changes up to 0543b19cac04f7edf5587cea6bd31801b0237b64:
> 
>    drm/amd/display: make variables static (2023-03-03 02:41:55 +0000)
> 
> ----------------------------------------------------------------
> Magali Lemes (2):
>        drm/amd/display: include missing headers
>        drm/amd/display: make variables static
> 
> Melissa Wen (4):
>        drm/amd/display: remove useless FPU protection wrapper from dcn31_resource file
>        drm/amd/display: move FPU code on dcn21 clk_mgr
>        drm/amd/display: move FPU code from dcn30 clk mgr to DML folder
>        drm/amd/display: move FPU code from dcn301 clk mgr to DML folder
> 
> Rodrigo Siqueira (5):
>        drm/amd/display: Drop unnecessary FPU flags on dcn302 files
>        drm/amd/display: Remove FPU operations from dcn201 resources
>        drm/amd/display: Create patch bounding box function for isolate FPU
>        drm/amd/display: Remove FPU flags from DCN30 Makefile
>        drm/amd/display: Fix a compilation failure on PowerPC caused by FPU code
> 
>   drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile    |  18 --
>   .../drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c  | 234 +--------------
>   .../drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.h  |   7 +
>   .../amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c   |  55 +---
>   .../drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c |  85 +-----
>   .../drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.h |   3 +
>   drivers/gpu/drm/amd/display/dc/dcn201/Makefile     |  25 --
>   .../drm/amd/display/dc/dcn201/dcn201_resource.c    |  10 +-
>   drivers/gpu/drm/amd/display/dc/dcn30/Makefile      |  32 --
>   drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c  |   8 -
>   drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h  |   3 -
>   .../gpu/drm/amd/display/dc/dcn30/dcn30_resource.c  |  19 +-
>   drivers/gpu/drm/amd/display/dc/dcn302/Makefile     |  19 --
>   .../gpu/drm/amd/display/dc/dcn31/dcn31_resource.c  |   6 -
>   .../gpu/drm/amd/display/dc/dcn31/dcn31_resource.h  |   1 -
>   .../drm/amd/display/dc/dcn315/dcn315_resource.h    |   1 -
>   .../drm/amd/display/dc/dcn316/dcn316_resource.h    |   1 -
>   drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c  | 328 +++++++++++++++++++++
>   .../gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c   | 323 ++++++++++++++++++++
>   .../gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h   |   6 +
>   .../gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c   |  83 +++++-
>   .../gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.h   |   3 +
>   .../gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c |  75 +++++
>   .../gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c   |   9 +-
>   .../drm/amd/display/dc/inc/hw/timing_generator.h   |   2 -
>   25 files changed, 859 insertions(+), 497 deletions(-)
>   create mode 100644 drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c
> 
> diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
> index 8178719176329..ffd005c460fcd 100644
> --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
> +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
> @@ -107,12 +107,6 @@ AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN201)
>   ###############################################################################
>   CLK_MGR_DCN21 = rn_clk_mgr.o rn_clk_mgr_vbios_smu.o
>   
> -# prevent build errors regarding soft-float vs hard-float FP ABI tags
> -# this code is currently unused on ppc64, as it applies to Renoir APUs only
> -ifdef CONFIG_PPC64
> -CFLAGS_$(AMDDALPATH)/dc/clk_mgr/dcn21/rn_clk_mgr.o := $(call cc-option,-mno-gnu-attribute)
> -endif
> -
>   AMD_DAL_CLK_MGR_DCN21 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn21/,$(CLK_MGR_DCN21))
>   
>   AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN21)
> @@ -121,12 +115,6 @@ AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN21)
>   ###############################################################################
>   CLK_MGR_DCN30 = dcn30_clk_mgr.o dcn30_clk_mgr_smu_msg.o
>   
> -# prevent build errors regarding soft-float vs hard-float FP ABI tags
> -# this code is currently unused on ppc64, as it applies to VanGogh APUs only
> -ifdef CONFIG_PPC64
> -CFLAGS_$(AMDDALPATH)/dc/clk_mgr/dcn30/dcn30_clk_mgr.o := $(call cc-option,-mno-gnu-attribute)
> -endif
> -
>   AMD_DAL_CLK_MGR_DCN30 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn30/,$(CLK_MGR_DCN30))
>   
>   AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN30)
> @@ -135,12 +123,6 @@ AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN30)
>   ###############################################################################
>   CLK_MGR_DCN301 = vg_clk_mgr.o dcn301_smu.o
>   
> -# prevent build errors regarding soft-float vs hard-float FP ABI tags
> -# this code is currently unused on ppc64, as it applies to VanGogh APUs only
> -ifdef CONFIG_PPC64
> -CFLAGS_$(AMDDALPATH)/dc/clk_mgr/dcn301/vg_clk_mgr.o := $(call cc-option,-mno-gnu-attribute)
> -endif
> -
>   AMD_DAL_CLK_MGR_DCN301 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn301/,$(CLK_MGR_DCN301))
>   
>   AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN301)
> diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
> index cf1b5f354ae99..0202dc682682b 100644
> --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
> +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
> @@ -26,10 +26,9 @@
>   #include "dccg.h"
>   #include "clk_mgr_internal.h"
>   
> -
>   #include "dcn20/dcn20_clk_mgr.h"
>   #include "rn_clk_mgr.h"
> -
> +#include "dml/dcn20/dcn20_fpu.h"
>   
>   #include "dce100/dce_clk_mgr.h"
>   #include "rn_clk_mgr_vbios_smu.h"
> @@ -45,7 +44,6 @@
>   
>   /* Constants */
>   
> -#define LPDDR_MEM_RETRAIN_LATENCY 4.977 /* Number obtained from LPDDR4 Training Counter Requirement doc */
>   #define SMU_VER_55_51_0 0x373300 /* SMU Version that is able to set DISPCLK below 100MHz */
>   
>   /* Macros */
> @@ -613,228 +611,6 @@ static struct clk_bw_params rn_bw_params = {
>   
>   };
>   
> -static struct wm_table ddr4_wm_table_gs = {
> -	.entries = {
> -		{
> -			.wm_inst = WM_A,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.72,
> -			.sr_exit_time_us = 7.09,
> -			.sr_enter_plus_exit_time_us = 8.14,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_B,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.72,
> -			.sr_exit_time_us = 10.12,
> -			.sr_enter_plus_exit_time_us = 11.48,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_C,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.72,
> -			.sr_exit_time_us = 10.12,
> -			.sr_enter_plus_exit_time_us = 11.48,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_D,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.72,
> -			.sr_exit_time_us = 10.12,
> -			.sr_enter_plus_exit_time_us = 11.48,
> -			.valid = true,
> -		},
> -	}
> -};
> -
> -static struct wm_table lpddr4_wm_table_gs = {
> -	.entries = {
> -		{
> -			.wm_inst = WM_A,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.65333,
> -			.sr_exit_time_us = 5.32,
> -			.sr_enter_plus_exit_time_us = 6.38,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_B,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.65333,
> -			.sr_exit_time_us = 9.82,
> -			.sr_enter_plus_exit_time_us = 11.196,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_C,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.65333,
> -			.sr_exit_time_us = 9.89,
> -			.sr_enter_plus_exit_time_us = 11.24,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_D,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.65333,
> -			.sr_exit_time_us = 9.748,
> -			.sr_enter_plus_exit_time_us = 11.102,
> -			.valid = true,
> -		},
> -	}
> -};
> -
> -static struct wm_table lpddr4_wm_table_with_disabled_ppt = {
> -	.entries = {
> -		{
> -			.wm_inst = WM_A,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.65333,
> -			.sr_exit_time_us = 8.32,
> -			.sr_enter_plus_exit_time_us = 9.38,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_B,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.65333,
> -			.sr_exit_time_us = 9.82,
> -			.sr_enter_plus_exit_time_us = 11.196,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_C,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.65333,
> -			.sr_exit_time_us = 9.89,
> -			.sr_enter_plus_exit_time_us = 11.24,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_D,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.65333,
> -			.sr_exit_time_us = 9.748,
> -			.sr_enter_plus_exit_time_us = 11.102,
> -			.valid = true,
> -		},
> -	}
> -};
> -
> -static struct wm_table ddr4_wm_table_rn = {
> -	.entries = {
> -		{
> -			.wm_inst = WM_A,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.72,
> -			.sr_exit_time_us = 11.90,
> -			.sr_enter_plus_exit_time_us = 12.80,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_B,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.72,
> -			.sr_exit_time_us = 13.18,
> -			.sr_enter_plus_exit_time_us = 14.30,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_C,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.72,
> -			.sr_exit_time_us = 13.18,
> -			.sr_enter_plus_exit_time_us = 14.30,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_D,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.72,
> -			.sr_exit_time_us = 13.18,
> -			.sr_enter_plus_exit_time_us = 14.30,
> -			.valid = true,
> -		},
> -	}
> -};
> -
> -static struct wm_table ddr4_1R_wm_table_rn = {
> -	.entries = {
> -		{
> -			.wm_inst = WM_A,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.72,
> -			.sr_exit_time_us = 13.90,
> -			.sr_enter_plus_exit_time_us = 14.80,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_B,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.72,
> -			.sr_exit_time_us = 13.90,
> -			.sr_enter_plus_exit_time_us = 14.80,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_C,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.72,
> -			.sr_exit_time_us = 13.90,
> -			.sr_enter_plus_exit_time_us = 14.80,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_D,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.72,
> -			.sr_exit_time_us = 13.90,
> -			.sr_enter_plus_exit_time_us = 14.80,
> -			.valid = true,
> -		},
> -	}
> -};
> -
> -static struct wm_table lpddr4_wm_table_rn = {
> -	.entries = {
> -		{
> -			.wm_inst = WM_A,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.65333,
> -			.sr_exit_time_us = 7.32,
> -			.sr_enter_plus_exit_time_us = 8.38,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_B,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.65333,
> -			.sr_exit_time_us = 9.82,
> -			.sr_enter_plus_exit_time_us = 11.196,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_C,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.65333,
> -			.sr_exit_time_us = 9.89,
> -			.sr_enter_plus_exit_time_us = 11.24,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_D,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.65333,
> -			.sr_exit_time_us = 9.748,
> -			.sr_enter_plus_exit_time_us = 11.102,
> -			.valid = true,
> -		},
> -	}
> -};
> -
>   static unsigned int find_socclk_for_voltage(struct dpm_clocks *clock_table, unsigned int voltage)
>   {
>   	int i;
> @@ -914,12 +690,10 @@ static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params
>   		/*
>   		 * WM set D will be re-purposed for memory retraining
>   		 */
> -		bw_params->wm_table.entries[WM_D].pstate_latency_us = LPDDR_MEM_RETRAIN_LATENCY;
> -		bw_params->wm_table.entries[WM_D].wm_inst = WM_D;
> -		bw_params->wm_table.entries[WM_D].wm_type = WM_TYPE_RETRAINING;
> -		bw_params->wm_table.entries[WM_D].valid = true;
> +		DC_FP_START();
> +		dcn21_clk_mgr_set_bw_params_wm_table(bw_params);
> +		DC_FP_END();
>   	}
> -
>   }
>   
>   void rn_clk_mgr_construct(
> diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.h
> index e4322fa5475b6..2e088c5171b28 100644
> --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.h
> +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.h
> @@ -29,6 +29,13 @@
>   #include "clk_mgr.h"
>   #include "dm_pp_smu.h"
>   
> +extern struct wm_table ddr4_wm_table_gs;
> +extern struct wm_table lpddr4_wm_table_gs;
> +extern struct wm_table lpddr4_wm_table_with_disabled_ppt;
> +extern struct wm_table ddr4_wm_table_rn;
> +extern struct wm_table ddr4_1R_wm_table_rn;
> +extern struct wm_table lpddr4_wm_table_rn;
> +
>   struct rn_clk_registers {
>   	uint32_t CLK1_CLK0_CURRENT_CNT; /* DPREFCLK */
>   };
> diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
> index 5ed6a93d1708c..e34a0e81facb6 100644
> --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
> +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
> @@ -29,6 +29,7 @@
>   #include "dcn20/dcn20_clk_mgr.h"
>   #include "dce100/dce_clk_mgr.h"
>   #include "dcn30/dcn30_clk_mgr.h"
> +#include "dml/dcn30/dcn30_fpu.h"
>   #include "reg_helper.h"
>   #include "core_types.h"
>   #include "dm_helpers.h"
> @@ -97,57 +98,11 @@ static void dcn3_init_single_clock(struct clk_mgr_internal *clk_mgr, uint32_t cl
>   	}
>   }
>   
> -static noinline void dcn3_build_wm_range_table(struct clk_mgr_internal *clk_mgr)
> +static void dcn3_build_wm_range_table(struct clk_mgr_internal *clk_mgr)
>   {
> -	/* defaults */
> -	double pstate_latency_us = clk_mgr->base.ctx->dc->dml.soc.dram_clock_change_latency_us;
> -	double sr_exit_time_us = clk_mgr->base.ctx->dc->dml.soc.sr_exit_time_us;
> -	double sr_enter_plus_exit_time_us = clk_mgr->base.ctx->dc->dml.soc.sr_enter_plus_exit_time_us;
> -	uint16_t min_uclk_mhz = clk_mgr->base.bw_params->clk_table.entries[0].memclk_mhz;
> -
> -	/* Set A - Normal - default values*/
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].valid = true;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us = pstate_latency_us;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].dml_input.sr_exit_time_us = sr_exit_time_us;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.wm_type = WATERMARKS_CLOCK_RANGE;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.min_dcfclk = 0;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.max_dcfclk = 0xFFFF;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.min_uclk = min_uclk_mhz;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.max_uclk = 0xFFFF;
> -
> -	/* Set B - Performance - higher minimum clocks */
> -//	clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].valid = true;
> -//	clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].dml_input.pstate_latency_us = pstate_latency_us;
> -//	clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].dml_input.sr_exit_time_us = sr_exit_time_us;
> -//	clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;
> -//	clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.wm_type = WATERMARKS_CLOCK_RANGE;
> -//	clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.min_dcfclk = TUNED VALUE;
> -//	clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.max_dcfclk = 0xFFFF;
> -//	clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.min_uclk = TUNED VALUE;
> -//	clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.max_uclk = 0xFFFF;
> -
> -	/* Set C - Dummy P-State - P-State latency set to "dummy p-state" value */
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].valid = true;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].dml_input.pstate_latency_us = clk_mgr->base.ctx->dc->dml.soc.dummy_pstate_latency_us;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].dml_input.sr_exit_time_us = sr_exit_time_us;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.wm_type = WATERMARKS_DUMMY_PSTATE;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.min_dcfclk = 0;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.max_dcfclk = 0xFFFF;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.min_uclk = min_uclk_mhz;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.max_uclk = 0xFFFF;
> -
> -	/* Set D - MALL - SR enter and exit times adjusted for MALL */
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].valid = true;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.pstate_latency_us = pstate_latency_us;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.sr_exit_time_us = 2;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.sr_enter_plus_exit_time_us = 4;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.wm_type = WATERMARKS_MALL;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_dcfclk = 0;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_dcfclk = 0xFFFF;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_uclk = min_uclk_mhz;
> -	clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_uclk = 0xFFFF;
> +	DC_FP_START();
> +	dcn3_fpu_build_wm_range_table(&clk_mgr->base);
> +	DC_FP_END();
>   }
>   
>   void dcn3_init_clocks(struct clk_mgr *clk_mgr_base)
> diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
> index f310b0d25a076..24715ca2fa944 100644
> --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
> +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
> @@ -32,6 +32,9 @@
>   // For dcn20_update_clocks_update_dpp_dto
>   #include "dcn20/dcn20_clk_mgr.h"
>   
> +// For DML FPU code
> +#include "dml/dcn20/dcn20_fpu.h"
> +
>   #include "vg_clk_mgr.h"
>   #include "dcn301_smu.h"
>   #include "reg_helper.h"
> @@ -526,81 +529,6 @@ static struct clk_bw_params vg_bw_params = {
>   
>   };
>   
> -static struct wm_table ddr4_wm_table = {
> -	.entries = {
> -		{
> -			.wm_inst = WM_A,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.72,
> -			.sr_exit_time_us = 6.09,
> -			.sr_enter_plus_exit_time_us = 7.14,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_B,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.72,
> -			.sr_exit_time_us = 10.12,
> -			.sr_enter_plus_exit_time_us = 11.48,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_C,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.72,
> -			.sr_exit_time_us = 10.12,
> -			.sr_enter_plus_exit_time_us = 11.48,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_D,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.72,
> -			.sr_exit_time_us = 10.12,
> -			.sr_enter_plus_exit_time_us = 11.48,
> -			.valid = true,
> -		},
> -	}
> -};
> -
> -static struct wm_table lpddr5_wm_table = {
> -	.entries = {
> -		{
> -			.wm_inst = WM_A,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.65333,
> -			.sr_exit_time_us = 13.5,
> -			.sr_enter_plus_exit_time_us = 16.5,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_B,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.65333,
> -			.sr_exit_time_us = 13.5,
> -			.sr_enter_plus_exit_time_us = 16.5,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_C,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.65333,
> -			.sr_exit_time_us = 13.5,
> -			.sr_enter_plus_exit_time_us = 16.5,
> -			.valid = true,
> -		},
> -		{
> -			.wm_inst = WM_D,
> -			.wm_type = WM_TYPE_PSTATE_CHG,
> -			.pstate_latency_us = 11.65333,
> -			.sr_exit_time_us = 13.5,
> -			.sr_enter_plus_exit_time_us = 16.5,
> -			.valid = true,
> -		},
> -	}
> -};
> -
> -
>   static unsigned int find_dcfclk_for_voltage(const struct vg_dpm_clocks *clock_table,
>   		unsigned int voltage)
>   {
> @@ -670,10 +598,9 @@ static void vg_clk_mgr_helper_populate_bw_params(
>   		/*
>   		 * WM set D will be re-purposed for memory retraining
>   		 */
> -		bw_params->wm_table.entries[WM_D].pstate_latency_us = LPDDR_MEM_RETRAIN_LATENCY;
> -		bw_params->wm_table.entries[WM_D].wm_inst = WM_D;
> -		bw_params->wm_table.entries[WM_D].wm_type = WM_TYPE_RETRAINING;
> -		bw_params->wm_table.entries[WM_D].valid = true;
> +		DC_FP_START();
> +		dcn21_clk_mgr_set_bw_params_wm_table(bw_params);
> +		DC_FP_END();
>   	}
>   
>   }
> diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.h
> index 7255477307f13..75884f5729891 100644
> --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.h
> +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.h
> @@ -29,6 +29,9 @@
>   
>   struct watermarks;
>   
> +extern struct wm_table ddr4_wm_table;
> +extern struct wm_table lpddr5_wm_table;
> +
>   struct smu_watermark_set {
>   	struct watermarks *wm_set;
>   	union large_integer mc_address;
> diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/Makefile b/drivers/gpu/drm/amd/display/dc/dcn201/Makefile
> index f68038ceb1b15..5c9ce2cebb0f6 100644
> --- a/drivers/gpu/drm/amd/display/dc/dcn201/Makefile
> +++ b/drivers/gpu/drm/amd/display/dc/dcn201/Makefile
> @@ -6,31 +6,6 @@ DCN201 = dcn201_init.o dcn201_resource.o dcn201_hwseq.o \
>   	dcn201_mpc.o dcn201_hubp.o dcn201_opp.o dcn201_optc.o dcn201_dpp.o \
>   	dcn201_dccg.o dcn201_link_encoder.o
>   
> -ifdef CONFIG_X86
> -CFLAGS_$(AMDDALPATH)/dc/dcn201/dcn201_resource.o := -mhard-float -msse
> -endif
> -
> -ifdef CONFIG_PPC64
> -CFLAGS_$(AMDDALPATH)/dc/dcn201/dcn201_resource.o := -mhard-float -maltivec
> -endif
> -
> -ifdef CONFIG_CC_IS_GCC
> -ifeq ($(call cc-ifversion, -lt, 0701, y), y)
> -IS_OLD_GCC = 1
> -endif
> -CFLAGS_$(AMDDALPATH)/dc/dcn201/dcn201_resource.o += -mhard-float
> -endif
> -
> -ifdef CONFIG_X86
> -ifdef IS_OLD_GCC
> -# Stack alignment mismatch, proceed with caution.
> -# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
> -# (8B stack alignment).
> -CFLAGS_$(AMDDALPATH)/dc/dcn201/dcn201_resource.o += -mpreferred-stack-boundary=4
> -else
> -CFLAGS_$(AMDDALPATH)/dc/dcn201/dcn201_resource.o += -msse2
> -endif
> -endif
>   AMD_DAL_DCN201 = $(addprefix $(AMDDALPATH)/dc/dcn201/,$(DCN201))
>   
>   AMD_DISPLAY_FILES += $(AMD_DAL_DCN201)
> diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c
> index 0bb7d3dd53fa4..e549a79f3fe1a 100644
> --- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c
> +++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c
> @@ -1036,6 +1036,14 @@ static bool dcn201_get_dcc_compression_cap(const struct dc *dc,
>   			output);
>   }
>   
> +static void dcn201_populate_dml_writeback_from_context(struct dc *dc,
> +						       struct resource_context *res_ctx,
> +						       display_e2e_pipe_params_st *pipes)
> +{
> +	DC_FP_START();
> +	dcn201_populate_dml_writeback_from_context_fpu(dc, res_ctx, pipes);
> +	DC_FP_END();
> +}
>   
>   static void dcn201_destroy_resource_pool(struct resource_pool **pool)
>   {
> @@ -1067,8 +1075,8 @@ static struct resource_funcs dcn201_res_pool_funcs = {
>   	.add_dsc_to_stream_resource = NULL,
>   	.remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
>   	.acquire_idle_pipe_for_layer = dcn201_acquire_idle_pipe_for_layer,
> +	.populate_dml_writeback_from_context = dcn201_populate_dml_writeback_from_context,
>   	.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
> -	.populate_dml_writeback_from_context = dcn20_populate_dml_writeback_from_context,
>   	.set_mcif_arb_params = dcn20_set_mcif_arb_params,
>   	.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link
>   };
> diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
> index dfd77b3cc84d8..b7c2ae9ddfda3 100644
> --- a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
> +++ b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
> @@ -30,38 +30,6 @@ DCN30 = dcn30_init.o dcn30_hubbub.o dcn30_hubp.o dcn30_dpp.o dcn30_optc.o \
>   	dcn30_dpp_cm.o dcn30_dwb_cm.o dcn30_cm_common.o dcn30_mmhubbub.o \
>   	dcn30_dio_link_encoder.o dcn30_resource.o
>   
> -
> -ifdef CONFIG_X86
> -CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o := -msse
> -CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o := -msse
> -endif
> -
> -ifdef CONFIG_PPC64
> -CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o := -mhard-float -maltivec
> -CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o := -mhard-float -maltivec
> -endif
> -
> -ifdef CONFIG_CC_IS_GCC
> -ifeq ($(call cc-ifversion, -lt, 0701, y), y)
> -IS_OLD_GCC = 1
> -endif
> -CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o += -mhard-float
> -CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o += -mhard-float
> -endif
> -
> -ifdef CONFIG_X86
> -ifdef IS_OLD_GCC
> -# Stack alignment mismatch, proceed with caution.
> -# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
> -# (8B stack alignment).
> -CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o += -mpreferred-stack-boundary=4
> -CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o += -mpreferred-stack-boundary=4
> -else
> -CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o += -msse2
> -CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o += -msse2
> -endif
> -endif
> -
>   AMD_DAL_DCN30 = $(addprefix $(AMDDALPATH)/dc/dcn30/,$(DCN30))
>   
>   AMD_DISPLAY_FILES += $(AMD_DAL_DCN30)
> diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
> index b604fb26f288d..4c57c001fd23b 100644
> --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
> +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
> @@ -186,14 +186,6 @@ void optc3_set_dsc_config(struct timing_generator *optc,
>   
>   }
>   
> -void optc3_set_vrr_m_const(struct timing_generator *optc,
> -		double vtotal_avg)
> -{
> -	DC_FP_START();
> -	optc3_fpu_set_vrr_m_const(optc, vtotal_avg);
> -	DC_FP_END();
> -}
> -
>   void optc3_set_odm_bypass(struct timing_generator *optc,
>   		const struct dc_crtc_timing *dc_crtc_timing)
>   {
> diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h
> index 97f11ef6e9f02..bd5743b73fa5b 100644
> --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h
> +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h
> @@ -320,9 +320,6 @@ void optc3_lock_doublebuffer_enable(struct timing_generator *optc);
>   
>   void optc3_lock_doublebuffer_disable(struct timing_generator *optc);
>   
> -void optc3_set_vrr_m_const(struct timing_generator *optc,
> -		double vtotal_avg);
> -
>   void optc3_set_drr_trigger_window(struct timing_generator *optc,
>   		uint32_t window_start, uint32_t window_end);
>   
> diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
> index 1c1a67c4cec1c..19ef63b13fe43 100644
> --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
> +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
> @@ -1520,26 +1520,11 @@ static bool init_soc_bounding_box(struct dc *dc,
>   	loaded_ip->max_num_otg = pool->base.res_cap->num_timing_generator;
>   	loaded_ip->max_num_dpp = pool->base.pipe_count;
>   	loaded_ip->clamp_min_dcfclk = dc->config.clamp_min_dcfclk;
> -
> -	DC_FP_START();
>   	dcn20_patch_bounding_box(dc, loaded_bb);
> +	DC_FP_START();
> +	patch_dcn30_soc_bounding_box(dc, &dcn3_0_soc);
>   	DC_FP_END();
>   
> -	if (dc->ctx->dc_bios->funcs->get_soc_bb_info) {
> -		struct bp_soc_bb_info bb_info = {0};
> -
> -		if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) {
> -			if (bb_info.dram_clock_change_latency_100ns > 0)
> -				dcn3_0_soc.dram_clock_change_latency_us = bb_info.dram_clock_change_latency_100ns * 10;
> -
> -			if (bb_info.dram_sr_enter_exit_latency_100ns > 0)
> -				dcn3_0_soc.sr_enter_plus_exit_time_us = bb_info.dram_sr_enter_exit_latency_100ns * 10;
> -
> -			if (bb_info.dram_sr_exit_latency_100ns > 0)
> -				dcn3_0_soc.sr_exit_time_us = bb_info.dram_sr_exit_latency_100ns * 10;
> -		}
> -	}
> -
>   	return true;
>   }
>   
> diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/Makefile b/drivers/gpu/drm/amd/display/dc/dcn302/Makefile
> index f9561d7f97a1d..ebd01cb467b79 100644
> --- a/drivers/gpu/drm/amd/display/dc/dcn302/Makefile
> +++ b/drivers/gpu/drm/amd/display/dc/dcn302/Makefile
> @@ -7,25 +7,6 @@
>   
>   DCN3_02 = dcn302_init.o dcn302_hwseq.o dcn302_resource.o
>   
> -ifdef CONFIG_X86
> -CFLAGS_$(AMDDALPATH)/dc/dcn302/dcn302_resource.o := -msse
> -endif
> -
> -ifdef CONFIG_PPC64
> -CFLAGS_$(AMDDALPATH)/dc/dcn302/dcn302_resource.o := -mhard-float -maltivec
> -endif
> -
> -ifdef CONFIG_X86
> -ifdef IS_OLD_GCC
> -# Stack alignment mismatch, proceed with caution.
> -# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
> -# (8B stack alignment).
> -CFLAGS_$(AMDDALPATH)/dc/dcn302/dcn302_resource.o += -mpreferred-stack-boundary=4
> -else
> -CFLAGS_$(AMDDALPATH)/dc/dcn302/dcn302_resource.o += -msse2
> -endif
> -endif
> -
>   AMD_DAL_DCN3_02 = $(addprefix $(AMDDALPATH)/dc/dcn302/,$(DCN3_02))
>   
>   AMD_DISPLAY_FILES += $(AMD_DAL_DCN3_02)
> diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
> index 3d9f07d4770bf..fe21d33111729 100644
> --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
> +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
> @@ -1873,8 +1873,6 @@ static bool dcn31_resource_construct(
>   	struct dc_context *ctx = dc->ctx;
>   	struct irq_service_init_data init_data;
>   
> -	DC_FP_START();
> -
>   	ctx->dc_bios->regs = &bios_regs;
>   
>   	pool->base.res_cap = &res_cap_dcn31;
> @@ -2182,13 +2180,9 @@ static bool dcn31_resource_construct(
>   
>   	dc->dcn_ip->max_num_dpp = dcn3_1_ip.max_num_dpp;
>   
> -	DC_FP_END();
> -
>   	return true;
>   
>   create_fail:
> -
> -	DC_FP_END();
>   	dcn31_resource_destruct(pool);
>   
>   	return false;
> diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h
> index 393458015d6a4..98ae95f378659 100644
> --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h
> +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h
> @@ -32,7 +32,6 @@
>   	container_of(pool, struct dcn31_resource_pool, base)
>   
>   extern struct _vcs_dpi_ip_params_st dcn3_1_ip;
> -extern struct _vcs_dpi_soc_bounding_box_st dcn3_1_soc;
>   
>   struct dcn31_resource_pool {
>   	struct resource_pool base;
> diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h
> index 39929fa67a510..22849eaa6f243 100644
> --- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h
> +++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h
> @@ -32,7 +32,6 @@
>   	container_of(pool, struct dcn315_resource_pool, base)
>   
>   extern struct _vcs_dpi_ip_params_st dcn3_15_ip;
> -extern struct _vcs_dpi_ip_params_st dcn3_15_soc;
>   
>   struct dcn315_resource_pool {
>   	struct resource_pool base;
> diff --git a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h
> index 0dc5a6c13ae7d..aba6d634131b4 100644
> --- a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h
> +++ b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h
> @@ -32,7 +32,6 @@
>   	container_of(pool, struct dcn316_resource_pool, base)
>   
>   extern struct _vcs_dpi_ip_params_st dcn3_16_ip;
> -extern struct _vcs_dpi_ip_params_st dcn3_16_soc;
>   
>   struct dcn316_resource_pool {
>   	struct resource_pool base;
> diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c
> new file mode 100644
> index 0000000000000..eff1f4e17689c
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c
> @@ -0,0 +1,328 @@
> +/*
> + * Copyright 2022 Advanced Micro Devices, Inc.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + *
> + * Authors: AMD
> + *
> + */
> +
> +#include "dcn32_optc.h"
> +
> +#include "dcn30/dcn30_optc.h"
> +#include "dcn31/dcn31_optc.h"
> +#include "reg_helper.h"
> +#include "dc.h"
> +#include "dcn_calc_math.h"
> +#include "dc_dmub_srv.h"
> +
> +#define REG(reg)\
> +	optc1->tg_regs->reg
> +
> +#define CTX \
> +	optc1->base.ctx
> +
> +#undef FN
> +#define FN(reg_name, field_name) \
> +	optc1->tg_shift->field_name, optc1->tg_mask->field_name
> +
> +static void optc32_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
> +		struct dc_crtc_timing *timing)
> +{
> +	struct optc *optc1 = DCN10TG_FROM_TG(optc);
> +	uint32_t memory_mask = 0;
> +	int h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right;
> +	int mpcc_hactive = h_active / opp_cnt;
> +	/* Each memory instance is 2048x(32x2) bits to support half line of 4096 */
> +	int odm_mem_count = (h_active + 2047) / 2048;
> +
> +	/*
> +	 * display <= 4k : 2 memories + 2 pipes
> +	 * 4k < display <= 8k : 4 memories + 2 pipes
> +	 * 8k < display <= 12k : 6 memories + 4 pipes
> +	 */
> +	if (opp_cnt == 4) {
> +		if (odm_mem_count <= 2)
> +			memory_mask = 0x3;
> +		else if (odm_mem_count <= 4)
> +			memory_mask = 0xf;
> +		else
> +			memory_mask = 0x3f;
> +	} else {
> +		if (odm_mem_count <= 2)
> +			memory_mask = 0x1 << (opp_id[0] * 2) | 0x1 << (opp_id[1] * 2);
> +		else if (odm_mem_count <= 4)
> +			memory_mask = 0x3 << (opp_id[0] * 2) | 0x3 << (opp_id[1] * 2);
> +		else
> +			memory_mask = 0x77;
> +	}
> +
> +	REG_SET(OPTC_MEMORY_CONFIG, 0,
> +		OPTC_MEM_SEL, memory_mask);
> +
> +	if (opp_cnt == 2) {
> +		REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0,
> +				OPTC_NUM_OF_INPUT_SEGMENT, 1,
> +				OPTC_SEG0_SRC_SEL, opp_id[0],
> +				OPTC_SEG1_SRC_SEL, opp_id[1]);
> +	} else if (opp_cnt == 4) {
> +		REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0,
> +				OPTC_NUM_OF_INPUT_SEGMENT, 3,
> +				OPTC_SEG0_SRC_SEL, opp_id[0],
> +				OPTC_SEG1_SRC_SEL, opp_id[1],
> +				OPTC_SEG2_SRC_SEL, opp_id[2],
> +				OPTC_SEG3_SRC_SEL, opp_id[3]);
> +	}
> +
> +	REG_UPDATE(OPTC_WIDTH_CONTROL,
> +			OPTC_SEGMENT_WIDTH, mpcc_hactive);
> +
> +	REG_UPDATE(OTG_H_TIMING_CNTL,
> +			OTG_H_TIMING_DIV_MODE, opp_cnt - 1);
> +	optc1->opp_count = opp_cnt;
> +}
> +
> +static void optc32_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode)
> +{
> +	struct optc *optc1 = DCN10TG_FROM_TG(optc);
> +
> +	REG_UPDATE(OTG_H_TIMING_CNTL,
> +			OTG_H_TIMING_DIV_MODE_MANUAL, manual_mode ? 1 : 0);
> +}
> +/**
> + * Enable CRTC
> + * Enable CRTC - call ASIC Control Object to enable Timing generator.
> + */
> +static bool optc32_enable_crtc(struct timing_generator *optc)
> +{
> +	struct optc *optc1 = DCN10TG_FROM_TG(optc);
> +
> +	/* opp instance for OTG, 1 to 1 mapping and odm will adjust */
> +	REG_UPDATE(OPTC_DATA_SOURCE_SELECT,
> +			OPTC_SEG0_SRC_SEL, optc->inst);
> +
> +	/* VTG enable first is for HW workaround */
> +	REG_UPDATE(CONTROL,
> +			VTG0_ENABLE, 1);
> +
> +	REG_SEQ_START();
> +
> +	/* Enable CRTC */
> +	REG_UPDATE_2(OTG_CONTROL,
> +			OTG_DISABLE_POINT_CNTL, 2,
> +			OTG_MASTER_EN, 1);
> +
> +	REG_SEQ_SUBMIT();
> +	REG_SEQ_WAIT_DONE();
> +
> +	return true;
> +}
> +
> +/* disable_crtc */
> +static bool optc32_disable_crtc(struct timing_generator *optc)
> +{
> +	struct optc *optc1 = DCN10TG_FROM_TG(optc);
> +
> +	/* disable otg request until end of the first line
> +	 * in the vertical blank region
> +	 */
> +	REG_UPDATE(OTG_CONTROL,
> +			OTG_MASTER_EN, 0);
> +
> +	REG_UPDATE(CONTROL,
> +			VTG0_ENABLE, 0);
> +
> +	/* CRTC disabled, so disable  clock. */
> +	REG_WAIT(OTG_CLOCK_CONTROL,
> +			OTG_BUSY, 0,
> +			1, 100000);
> +
> +	return true;
> +}
> +
> +void optc32_phantom_crtc_post_enable(struct timing_generator *optc)
> +{
> +	struct optc *optc1 = DCN10TG_FROM_TG(optc);
> +
> +	/* Disable immediately. */
> +	REG_UPDATE_2(OTG_CONTROL, OTG_DISABLE_POINT_CNTL, 0, OTG_MASTER_EN, 0);
> +
> +	/* CRTC disabled, so disable  clock. */
> +	REG_WAIT(OTG_CLOCK_CONTROL, OTG_BUSY, 0, 1, 100000);
> +}
> +
> +static void optc32_set_odm_bypass(struct timing_generator *optc,
> +		const struct dc_crtc_timing *dc_crtc_timing)
> +{
> +	struct optc *optc1 = DCN10TG_FROM_TG(optc);
> +	enum h_timing_div_mode h_div = H_TIMING_NO_DIV;
> +
> +	REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0,
> +			OPTC_NUM_OF_INPUT_SEGMENT, 0,
> +			OPTC_SEG0_SRC_SEL, optc->inst,
> +			OPTC_SEG1_SRC_SEL, 0xf,
> +			OPTC_SEG2_SRC_SEL, 0xf,
> +			OPTC_SEG3_SRC_SEL, 0xf
> +			);
> +
> +	h_div = optc1_is_two_pixels_per_containter(dc_crtc_timing);
> +	REG_UPDATE(OTG_H_TIMING_CNTL,
> +			OTG_H_TIMING_DIV_MODE, h_div);
> +
> +	REG_SET(OPTC_MEMORY_CONFIG, 0,
> +			OPTC_MEM_SEL, 0);
> +	optc1->opp_count = 1;
> +}
> +
> +void optc32_setup_manual_trigger(struct timing_generator *optc)
> +{
> +	struct optc *optc1 = DCN10TG_FROM_TG(optc);
> +	struct dc *dc = optc->ctx->dc;
> +
> +	if (dc->caps.dmub_caps.mclk_sw && !dc->debug.disable_fams)
> +		dc_dmub_srv_set_drr_manual_trigger_cmd(dc, optc->inst);
> +	else {
> +		/*
> +		 * MIN_MASK_EN is gone and MASK is now always enabled.
> +		 *
> +		 * To get it to it work with manual trigger we need to make sure
> +		 * we program the correct bit.
> +		 */
> +		REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
> +				OTG_V_TOTAL_MIN_SEL, 1,
> +				OTG_V_TOTAL_MAX_SEL, 1,
> +				OTG_FORCE_LOCK_ON_EVENT, 0,
> +				OTG_SET_V_TOTAL_MIN_MASK, (1 << 1)); /* TRIGA */
> +
> +		// Setup manual flow control for EOF via TRIG_A
> +		optc->funcs->setup_manual_trigger(optc);
> +	}
> +}
> +
> +void optc32_set_drr(
> +	struct timing_generator *optc,
> +	const struct drr_params *params)
> +{
> +	struct optc *optc1 = DCN10TG_FROM_TG(optc);
> +
> +	if (params != NULL &&
> +		params->vertical_total_max > 0 &&
> +		params->vertical_total_min > 0) {
> +
> +		if (params->vertical_total_mid != 0) {
> +
> +			REG_SET(OTG_V_TOTAL_MID, 0,
> +				OTG_V_TOTAL_MID, params->vertical_total_mid - 1);
> +
> +			REG_UPDATE_2(OTG_V_TOTAL_CONTROL,
> +					OTG_VTOTAL_MID_REPLACING_MAX_EN, 1,
> +					OTG_VTOTAL_MID_FRAME_NUM,
> +					(uint8_t)params->vertical_total_mid_frame_num);
> +
> +		}
> +
> +		optc->funcs->set_vtotal_min_max(optc, params->vertical_total_min - 1, params->vertical_total_max - 1);
> +		optc32_setup_manual_trigger(optc);
> +	} else {
> +		REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
> +				OTG_SET_V_TOTAL_MIN_MASK, 0,
> +				OTG_V_TOTAL_MIN_SEL, 0,
> +				OTG_V_TOTAL_MAX_SEL, 0,
> +				OTG_FORCE_LOCK_ON_EVENT, 0);
> +
> +		optc->funcs->set_vtotal_min_max(optc, 0, 0);
> +	}
> +}
> +
> +static struct timing_generator_funcs dcn32_tg_funcs = {
> +		.validate_timing = optc1_validate_timing,
> +		.program_timing = optc1_program_timing,
> +		.setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0,
> +		.setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1,
> +		.setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2,
> +		.program_global_sync = optc1_program_global_sync,
> +		.enable_crtc = optc32_enable_crtc,
> +		.disable_crtc = optc32_disable_crtc,
> +		.phantom_crtc_post_enable = optc32_phantom_crtc_post_enable,
> +		/* used by enable_timing_synchronization. Not need for FPGA */
> +		.is_counter_moving = optc1_is_counter_moving,
> +		.get_position = optc1_get_position,
> +		.get_frame_count = optc1_get_vblank_counter,
> +		.get_scanoutpos = optc1_get_crtc_scanoutpos,
> +		.get_otg_active_size = optc1_get_otg_active_size,
> +		.set_early_control = optc1_set_early_control,
> +		/* used by enable_timing_synchronization. Not need for FPGA */
> +		.wait_for_state = optc1_wait_for_state,
> +		.set_blank_color = optc3_program_blank_color,
> +		.did_triggered_reset_occur = optc1_did_triggered_reset_occur,
> +		.triplebuffer_lock = optc3_triplebuffer_lock,
> +		.triplebuffer_unlock = optc2_triplebuffer_unlock,
> +		.enable_reset_trigger = optc1_enable_reset_trigger,
> +		.enable_crtc_reset = optc1_enable_crtc_reset,
> +		.disable_reset_trigger = optc1_disable_reset_trigger,
> +		.lock = optc3_lock,
> +		.unlock = optc1_unlock,
> +		.lock_doublebuffer_enable = optc3_lock_doublebuffer_enable,
> +		.lock_doublebuffer_disable = optc3_lock_doublebuffer_disable,
> +		.enable_optc_clock = optc1_enable_optc_clock,
> +		.set_drr = optc31_set_drr, // TODO: Update to optc32_set_drr once FW headers are promoted
> +		.get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal,
> +		.set_vtotal_min_max = optc3_set_vtotal_min_max,
> +		.set_static_screen_control = optc1_set_static_screen_control,
> +		.program_stereo = optc1_program_stereo,
> +		.is_stereo_left_eye = optc1_is_stereo_left_eye,
> +		.tg_init = optc3_tg_init,
> +		.is_tg_enabled = optc1_is_tg_enabled,
> +		.is_optc_underflow_occurred = optc1_is_optc_underflow_occurred,
> +		.clear_optc_underflow = optc1_clear_optc_underflow,
> +		.setup_global_swap_lock = NULL,
> +		.get_crc = optc1_get_crc,
> +		.configure_crc = optc1_configure_crc,
> +		.set_dsc_config = optc3_set_dsc_config,
> +		.get_dsc_status = optc2_get_dsc_status,
> +		.set_dwb_source = NULL,
> +		.set_odm_bypass = optc32_set_odm_bypass,
> +		.set_odm_combine = optc32_set_odm_combine,
> +		.set_h_timing_div_manual_mode = optc32_set_h_timing_div_manual_mode,
> +		.get_optc_source = optc2_get_optc_source,
> +		.set_out_mux = optc3_set_out_mux,
> +		.set_drr_trigger_window = optc3_set_drr_trigger_window,
> +		.set_vtotal_change_limit = optc3_set_vtotal_change_limit,
> +		.set_gsl = optc2_set_gsl,
> +		.set_gsl_source_select = optc2_set_gsl_source_select,
> +		.set_vtg_params = optc1_set_vtg_params,
> +		.program_manual_trigger = optc2_program_manual_trigger,
> +		.setup_manual_trigger = optc2_setup_manual_trigger,
> +		.get_hw_timing = optc1_get_hw_timing,
> +};
> +
> +void dcn32_timing_generator_init(struct optc *optc1)
> +{
> +	optc1->base.funcs = &dcn32_tg_funcs;
> +
> +	optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1;
> +	optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1;
> +
> +	optc1->min_h_blank = 32;
> +	optc1->min_v_blank = 3;
> +	optc1->min_v_blank_interlace = 5;
> +	optc1->min_h_sync_width = 4;
> +	optc1->min_v_sync_width = 1;
> +}
> +
> diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
> index f79dd40f8d811..b196b1f38c185 100644
> --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
> +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
> @@ -30,6 +30,7 @@
>   #include "dchubbub.h"
>   #include "dcn20/dcn20_resource.h"
>   #include "dcn21/dcn21_resource.h"
> +#include "clk_mgr/dcn21/rn_clk_mgr.h"
>   
>   #include "dcn20_fpu.h"
>   
> @@ -42,6 +43,9 @@
>   #define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
>   #endif
>   
> +/* Constant */
> +#define LPDDR_MEM_RETRAIN_LATENCY 4.977 /* Number obtained from LPDDR4 Training Counter Requirement doc */
> +
>   /**
>    * DOC: DCN2x FPU manipulation Overview
>    *
> @@ -650,6 +654,228 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = {
>   	.num_states = 8
>   };
>   
> +struct wm_table ddr4_wm_table_gs = {
> +	.entries = {
> +		{
> +			.wm_inst = WM_A,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.72,
> +			.sr_exit_time_us = 7.09,
> +			.sr_enter_plus_exit_time_us = 8.14,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_B,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.72,
> +			.sr_exit_time_us = 10.12,
> +			.sr_enter_plus_exit_time_us = 11.48,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_C,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.72,
> +			.sr_exit_time_us = 10.12,
> +			.sr_enter_plus_exit_time_us = 11.48,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_D,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.72,
> +			.sr_exit_time_us = 10.12,
> +			.sr_enter_plus_exit_time_us = 11.48,
> +			.valid = true,
> +		},
> +	}
> +};
> +
> +struct wm_table lpddr4_wm_table_gs = {
> +	.entries = {
> +		{
> +			.wm_inst = WM_A,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.65333,
> +			.sr_exit_time_us = 5.32,
> +			.sr_enter_plus_exit_time_us = 6.38,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_B,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.65333,
> +			.sr_exit_time_us = 9.82,
> +			.sr_enter_plus_exit_time_us = 11.196,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_C,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.65333,
> +			.sr_exit_time_us = 9.89,
> +			.sr_enter_plus_exit_time_us = 11.24,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_D,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.65333,
> +			.sr_exit_time_us = 9.748,
> +			.sr_enter_plus_exit_time_us = 11.102,
> +			.valid = true,
> +		},
> +	}
> +};
> +
> +struct wm_table lpddr4_wm_table_with_disabled_ppt = {
> +	.entries = {
> +		{
> +			.wm_inst = WM_A,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.65333,
> +			.sr_exit_time_us = 8.32,
> +			.sr_enter_plus_exit_time_us = 9.38,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_B,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.65333,
> +			.sr_exit_time_us = 9.82,
> +			.sr_enter_plus_exit_time_us = 11.196,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_C,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.65333,
> +			.sr_exit_time_us = 9.89,
> +			.sr_enter_plus_exit_time_us = 11.24,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_D,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.65333,
> +			.sr_exit_time_us = 9.748,
> +			.sr_enter_plus_exit_time_us = 11.102,
> +			.valid = true,
> +		},
> +	}
> +};
> +
> +struct wm_table ddr4_wm_table_rn = {
> +	.entries = {
> +		{
> +			.wm_inst = WM_A,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.72,
> +			.sr_exit_time_us = 11.90,
> +			.sr_enter_plus_exit_time_us = 12.80,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_B,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.72,
> +			.sr_exit_time_us = 13.18,
> +			.sr_enter_plus_exit_time_us = 14.30,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_C,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.72,
> +			.sr_exit_time_us = 13.18,
> +			.sr_enter_plus_exit_time_us = 14.30,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_D,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.72,
> +			.sr_exit_time_us = 13.18,
> +			.sr_enter_plus_exit_time_us = 14.30,
> +			.valid = true,
> +		},
> +	}
> +};
> +
> +struct wm_table ddr4_1R_wm_table_rn = {
> +	.entries = {
> +		{
> +			.wm_inst = WM_A,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.72,
> +			.sr_exit_time_us = 13.90,
> +			.sr_enter_plus_exit_time_us = 14.80,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_B,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.72,
> +			.sr_exit_time_us = 13.90,
> +			.sr_enter_plus_exit_time_us = 14.80,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_C,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.72,
> +			.sr_exit_time_us = 13.90,
> +			.sr_enter_plus_exit_time_us = 14.80,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_D,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.72,
> +			.sr_exit_time_us = 13.90,
> +			.sr_enter_plus_exit_time_us = 14.80,
> +			.valid = true,
> +		},
> +	}
> +};
> +
> +struct wm_table lpddr4_wm_table_rn = {
> +	.entries = {
> +		{
> +			.wm_inst = WM_A,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.65333,
> +			.sr_exit_time_us = 7.32,
> +			.sr_enter_plus_exit_time_us = 8.38,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_B,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.65333,
> +			.sr_exit_time_us = 9.82,
> +			.sr_enter_plus_exit_time_us = 11.196,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_C,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.65333,
> +			.sr_exit_time_us = 9.89,
> +			.sr_enter_plus_exit_time_us = 11.24,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_D,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.65333,
> +			.sr_exit_time_us = 9.748,
> +			.sr_enter_plus_exit_time_us = 11.102,
> +			.valid = true,
> +		},
> +	}
> +};
> +
>   void dcn20_populate_dml_writeback_from_context(struct dc *dc,
>   					       struct resource_context *res_ctx,
>   					       display_e2e_pipe_params_st *pipes)
> @@ -2036,3 +2262,100 @@ void dcn21_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params
>   
>   	dml_init_instance(&dc->dml, &dcn2_1_soc, &dcn2_1_ip, DML_PROJECT_DCN21);
>   }
> +
> +void dcn21_clk_mgr_set_bw_params_wm_table(struct clk_bw_params *bw_params)
> +{
> +	dc_assert_fp_enabled();
> +
> +	bw_params->wm_table.entries[WM_D].pstate_latency_us = LPDDR_MEM_RETRAIN_LATENCY;
> +	bw_params->wm_table.entries[WM_D].wm_inst = WM_D;
> +	bw_params->wm_table.entries[WM_D].wm_type = WM_TYPE_RETRAINING;
> +	bw_params->wm_table.entries[WM_D].valid = true;
> +}
> +
> +void dcn201_populate_dml_writeback_from_context_fpu(struct dc *dc,
> +						    struct resource_context *res_ctx,
> +						    display_e2e_pipe_params_st *pipes)
> +{
> +	int pipe_cnt, i, j;
> +	double max_calc_writeback_dispclk;
> +	double writeback_dispclk;
> +	struct writeback_st dout_wb;
> +
> +	dc_assert_fp_enabled();
> +
> +	for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
> +		struct dc_stream_state *stream = res_ctx->pipe_ctx[i].stream;
> +
> +		if (!stream)
> +			continue;
> +		max_calc_writeback_dispclk = 0;
> +
> +		/* Set writeback information */
> +		pipes[pipe_cnt].dout.wb_enable = 0;
> +		pipes[pipe_cnt].dout.num_active_wb = 0;
> +		for (j = 0; j < stream->num_wb_info; j++) {
> +			struct dc_writeback_info *wb_info = &stream->writeback_info[j];
> +
> +			if (wb_info->wb_enabled && wb_info->writeback_source_plane &&
> +					(wb_info->writeback_source_plane == res_ctx->pipe_ctx[i].plane_state)) {
> +				pipes[pipe_cnt].dout.wb_enable = 1;
> +				pipes[pipe_cnt].dout.num_active_wb++;
> +				dout_wb.wb_src_height = wb_info->dwb_params.cnv_params.crop_en ?
> +					wb_info->dwb_params.cnv_params.crop_height :
> +					wb_info->dwb_params.cnv_params.src_height;
> +				dout_wb.wb_src_width = wb_info->dwb_params.cnv_params.crop_en ?
> +					wb_info->dwb_params.cnv_params.crop_width :
> +					wb_info->dwb_params.cnv_params.src_width;
> +				dout_wb.wb_dst_width = wb_info->dwb_params.dest_width;
> +				dout_wb.wb_dst_height = wb_info->dwb_params.dest_height;
> +				dout_wb.wb_htaps_luma = wb_info->dwb_params.scaler_taps.h_taps;
> +				dout_wb.wb_vtaps_luma = wb_info->dwb_params.scaler_taps.v_taps;;
> +				dout_wb.wb_htaps_chroma = wb_info->dwb_params.scaler_taps.h_taps_c;
> +				dout_wb.wb_vtaps_chroma = wb_info->dwb_params.scaler_taps.v_taps_c;
> +				dout_wb.wb_hratio = wb_info->dwb_params.cnv_params.crop_en ?
> +					(double)wb_info->dwb_params.cnv_params.crop_width /
> +						(double)wb_info->dwb_params.dest_width :
> +					(double)wb_info->dwb_params.cnv_params.src_width /
> +						(double)wb_info->dwb_params.dest_width;
> +				dout_wb.wb_vratio = wb_info->dwb_params.cnv_params.crop_en ?
> +					(double)wb_info->dwb_params.cnv_params.crop_height /
> +						(double)wb_info->dwb_params.dest_height :
> +					(double)wb_info->dwb_params.cnv_params.src_height /
> +						(double)wb_info->dwb_params.dest_height;
> +				if (wb_info->dwb_params.out_format == dwb_scaler_mode_yuv420) {
> +					if (wb_info->dwb_params.output_depth == DWB_OUTPUT_PIXEL_DEPTH_8BPC)
> +						dout_wb.wb_pixel_format = dm_420_8;
> +					else
> +						dout_wb.wb_pixel_format = dm_420_10;
> +				} else
> +					dout_wb.wb_pixel_format = dm_444_32;
> +
> +				/* Workaround for cases where multiple writebacks are connected to same plane
> +				 * In which case, need to compute worst case and set the associated writeback parameters
> +				 * This workaround is necessary due to DML computation assuming only 1 set of writeback
> +				 * parameters per pipe */
> +				writeback_dispclk = CalculateWriteBackDISPCLK(
> +						dout_wb.wb_pixel_format,
> +						pipes[pipe_cnt].pipe.dest.pixel_rate_mhz,
> +						dout_wb.wb_hratio,
> +						dout_wb.wb_vratio,
> +						dout_wb.wb_htaps_luma,
> +						dout_wb.wb_vtaps_luma,
> +						dout_wb.wb_htaps_chroma,
> +						dout_wb.wb_vtaps_chroma,
> +						dout_wb.wb_dst_width,
> +						pipes[pipe_cnt].pipe.dest.htotal,
> +						2);
> +
> +				if (writeback_dispclk > max_calc_writeback_dispclk) {
> +					max_calc_writeback_dispclk = writeback_dispclk;
> +					pipes[pipe_cnt].dout.wb = dout_wb;
> +				}
> +			}
> +		}
> +
> +		pipe_cnt++;
> +	}
> +
> +}
> diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h
> index aa892193e4854..c51badf7b68a9 100644
> --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h
> +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h
> @@ -82,4 +82,10 @@ bool dcn21_validate_bandwidth_fp(struct dc *dc,
>   				 bool fast_validate);
>   void dcn21_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params);
>   
> +void dcn21_clk_mgr_set_bw_params_wm_table(struct clk_bw_params *bw_params);
> +
> +void dcn201_populate_dml_writeback_from_context_fpu(struct dc *dc,
> +						struct resource_context *res_ctx,
> +						display_e2e_pipe_params_st *pipes);
> +
>   #endif /* __DCN20_FPU_H__ */
> diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c
> index 574676a0711ae..8bc1bc55e6352 100644
> --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c
> +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c
> @@ -29,7 +29,7 @@
>   #include "dcn20/dcn20_resource.h"
>   #include "dcn30/dcn30_resource.h"
>   
> -
> +#include "clk_mgr/dcn30/dcn30_smu11_driver_if.h"
>   #include "display_mode_vba_30.h"
>   #include "dcn30_fpu.h"
>   
> @@ -614,4 +614,85 @@ void dcn30_fpu_update_bw_bounding_box(struct dc *dc,
>   
>   }
>   
> +void dcn3_fpu_build_wm_range_table(struct clk_mgr *base)
> +{
> +	/* defaults */
> +	double pstate_latency_us = base->ctx->dc->dml.soc.dram_clock_change_latency_us;
> +	double sr_exit_time_us = base->ctx->dc->dml.soc.sr_exit_time_us;
> +	double sr_enter_plus_exit_time_us = base->ctx->dc->dml.soc.sr_enter_plus_exit_time_us;
> +	uint16_t min_uclk_mhz = base->bw_params->clk_table.entries[0].memclk_mhz;
> +
> +	dc_assert_fp_enabled();
> +
> +	/* Set A - Normal - default values*/
> +	base->bw_params->wm_table.nv_entries[WM_A].valid = true;
> +	base->bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us = pstate_latency_us;
> +	base->bw_params->wm_table.nv_entries[WM_A].dml_input.sr_exit_time_us = sr_exit_time_us;
> +	base->bw_params->wm_table.nv_entries[WM_A].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;
> +	base->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.wm_type = WATERMARKS_CLOCK_RANGE;
> +	base->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.min_dcfclk = 0;
> +	base->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.max_dcfclk = 0xFFFF;
> +	base->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.min_uclk = min_uclk_mhz;
> +	base->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.max_uclk = 0xFFFF;
> +
> +	/* Set B - Performance - higher minimum clocks */
> +//	base->bw_params->wm_table.nv_entries[WM_B].valid = true;
> +//	base->bw_params->wm_table.nv_entries[WM_B].dml_input.pstate_latency_us = pstate_latency_us;
> +//	base->bw_params->wm_table.nv_entries[WM_B].dml_input.sr_exit_time_us = sr_exit_time_us;
> +//	base->bw_params->wm_table.nv_entries[WM_B].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;
> +//	base->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.wm_type = WATERMARKS_CLOCK_RANGE;
> +//	base->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.min_dcfclk = TUNED VALUE;
> +//	base->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.max_dcfclk = 0xFFFF;
> +//	base->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.min_uclk = TUNED VALUE;
> +//	base->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.max_uclk = 0xFFFF;
> +
> +	/* Set C - Dummy P-State - P-State latency set to "dummy p-state" value */
> +	base->bw_params->wm_table.nv_entries[WM_C].valid = true;
> +	base->bw_params->wm_table.nv_entries[WM_C].dml_input.pstate_latency_us = 0;
> +	base->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_exit_time_us = sr_exit_time_us;
> +	base->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;
> +	base->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.wm_type = WATERMARKS_DUMMY_PSTATE;
> +	base->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.min_dcfclk = 0;
> +	base->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.max_dcfclk = 0xFFFF;
> +	base->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.min_uclk = min_uclk_mhz;
> +	base->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.max_uclk = 0xFFFF;
> +	base->bw_params->dummy_pstate_table[0].dram_speed_mts = 1600;
> +	base->bw_params->dummy_pstate_table[0].dummy_pstate_latency_us = 38;
> +	base->bw_params->dummy_pstate_table[1].dram_speed_mts = 8000;
> +	base->bw_params->dummy_pstate_table[1].dummy_pstate_latency_us = 9;
> +	base->bw_params->dummy_pstate_table[2].dram_speed_mts = 10000;
> +	base->bw_params->dummy_pstate_table[2].dummy_pstate_latency_us = 8;
> +	base->bw_params->dummy_pstate_table[3].dram_speed_mts = 16000;
> +	base->bw_params->dummy_pstate_table[3].dummy_pstate_latency_us = 5;
> +
> +	/* Set D - MALL - SR enter and exit times adjusted for MALL */
> +	base->bw_params->wm_table.nv_entries[WM_D].valid = true;
> +	base->bw_params->wm_table.nv_entries[WM_D].dml_input.pstate_latency_us = pstate_latency_us;
> +	base->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_exit_time_us = 2;
> +	base->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_enter_plus_exit_time_us = 4;
> +	base->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.wm_type = WATERMARKS_MALL;
> +	base->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_dcfclk = 0;
> +	base->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_dcfclk = 0xFFFF;
> +	base->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_uclk = min_uclk_mhz;
> +	base->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_uclk = 0xFFFF;
> +}
>   
> +void patch_dcn30_soc_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *dcn3_0_ip)
> +{
> +	dc_assert_fp_enabled();
> +
> +	if (dc->ctx->dc_bios->funcs->get_soc_bb_info) {
> +		struct bp_soc_bb_info bb_info = {0};
> +
> +		if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) {
> +			if (bb_info.dram_clock_change_latency_100ns > 0)
> +				dcn3_0_soc.dram_clock_change_latency_us = bb_info.dram_clock_change_latency_100ns * 10;
> +
> +			if (bb_info.dram_sr_enter_exit_latency_100ns > 0)
> +				dcn3_0_soc.sr_enter_plus_exit_time_us = bb_info.dram_sr_enter_exit_latency_100ns * 10;
> +
> +			if (bb_info.dram_sr_exit_latency_100ns > 0)
> +				dcn3_0_soc.sr_exit_time_us = bb_info.dram_sr_exit_latency_100ns * 10;
> +		}
> +	}
> +}
> diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.h
> index dedfe7b5f1731..595ce88cfa69a 100644
> --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.h
> +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.h
> @@ -63,5 +63,8 @@ void dcn30_fpu_update_bw_bounding_box(struct dc *dc,
>   	unsigned int *dcfclk_mhz,
>   	unsigned int *dram_speed_mts);
>   
> +void dcn3_fpu_build_wm_range_table(struct clk_mgr *base);
> +
> +void patch_dcn30_soc_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *dcn3_0_ip);
>   
>   #endif /* __DCN30_FPU_H__*/
> diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c
> index 0a7a338649731..e391e4e26d610 100644
> --- a/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c
> +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c
> @@ -26,6 +26,7 @@
>   #include "clk_mgr.h"
>   #include "dcn20/dcn20_resource.h"
>   #include "dcn301/dcn301_resource.h"
> +#include "clk_mgr/dcn301/vg_clk_mgr.h"
>   
>   #include "dml/dcn20/dcn20_fpu.h"
>   #include "dcn301_fpu.h"
> @@ -214,6 +215,80 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_01_soc = {
>   	.urgent_latency_adjustment_fabric_clock_reference_mhz = 0,
>   };
>   
> +struct wm_table ddr4_wm_table = {
> +	.entries = {
> +		{
> +			.wm_inst = WM_A,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.72,
> +			.sr_exit_time_us = 6.09,
> +			.sr_enter_plus_exit_time_us = 7.14,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_B,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.72,
> +			.sr_exit_time_us = 10.12,
> +			.sr_enter_plus_exit_time_us = 11.48,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_C,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.72,
> +			.sr_exit_time_us = 10.12,
> +			.sr_enter_plus_exit_time_us = 11.48,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_D,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.72,
> +			.sr_exit_time_us = 10.12,
> +			.sr_enter_plus_exit_time_us = 11.48,
> +			.valid = true,
> +		},
> +	}
> +};
> +
> +struct wm_table lpddr5_wm_table = {
> +	.entries = {
> +		{
> +			.wm_inst = WM_A,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.65333,
> +			.sr_exit_time_us = 13.5,
> +			.sr_enter_plus_exit_time_us = 16.5,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_B,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.65333,
> +			.sr_exit_time_us = 13.5,
> +			.sr_enter_plus_exit_time_us = 16.5,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_C,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.65333,
> +			.sr_exit_time_us = 13.5,
> +			.sr_enter_plus_exit_time_us = 16.5,
> +			.valid = true,
> +		},
> +		{
> +			.wm_inst = WM_D,
> +			.wm_type = WM_TYPE_PSTATE_CHG,
> +			.pstate_latency_us = 11.65333,
> +			.sr_exit_time_us = 13.5,
> +			.sr_enter_plus_exit_time_us = 16.5,
> +			.valid = true,
> +		},
> +	}
> +};
> +
>   static void calculate_wm_set_for_vlevel(int vlevel,
>   		struct wm_range_table_entry *table_entry,
>   		struct dcn_watermarks *wm_set,
> diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c
> index 54db2eca9e6b7..47e6bc934bad4 100644
> --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c
> +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c
> @@ -25,6 +25,9 @@
>   
>   #include "resource.h"
>   #include "clk_mgr.h"
> +#include "dcn31/dcn31_resource.h"
> +#include "dcn315/dcn315_resource.h"
> +#include "dcn316/dcn316_resource.h"
>   
>   #include "dml/dcn20/dcn20_fpu.h"
>   #include "dcn31_fpu.h"
> @@ -114,7 +117,7 @@ struct _vcs_dpi_ip_params_st dcn3_1_ip = {
>   	.dcc_supported = true,
>   };
>   
> -struct _vcs_dpi_soc_bounding_box_st dcn3_1_soc = {
> +static struct _vcs_dpi_soc_bounding_box_st dcn3_1_soc = {
>   		/*TODO: correct dispclk/dppclk voltage level determination*/
>   	.clock_limits = {
>   		{
> @@ -259,7 +262,7 @@ struct _vcs_dpi_ip_params_st dcn3_15_ip = {
>   	.dcc_supported = true,
>   };
>   
> -struct _vcs_dpi_soc_bounding_box_st dcn3_15_soc = {
> +static struct _vcs_dpi_soc_bounding_box_st dcn3_15_soc = {
>   	.sr_exit_time_us = 9.0,
>   	.sr_enter_plus_exit_time_us = 11.0,
>   	.sr_exit_z8_time_us = 50.0,
> @@ -354,7 +357,7 @@ struct _vcs_dpi_ip_params_st dcn3_16_ip = {
>   	.dcc_supported = true,
>   };
>   
> -struct _vcs_dpi_soc_bounding_box_st dcn3_16_soc = {
> +static struct _vcs_dpi_soc_bounding_box_st dcn3_16_soc = {
>   		/*TODO: correct dispclk/dppclk voltage level determination*/
>   	.clock_limits = {
>   		{
> diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
> index 554d2e33bd7f1..56f34dba3cb2a 100644
> --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
> +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
> @@ -298,8 +298,6 @@ struct timing_generator_funcs {
>   			int group_idx,
>   			uint32_t gsl_ready_signal);
>   	void (*set_out_mux)(struct timing_generator *tg, enum otg_out_mux_dest dest);
> -	void (*set_vrr_m_const)(struct timing_generator *optc,
> -			double vtotal_avg);
>   	void (*set_drr_trigger_window)(struct timing_generator *optc,
>   			uint32_t window_start, uint32_t window_end);
>   	void (*set_vtotal_change_limit)(struct timing_generator *optc,
>
diff mbox series

Patch

diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
index 8178719176329..ffd005c460fcd 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
@@ -107,12 +107,6 @@  AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN201)
 ###############################################################################
 CLK_MGR_DCN21 = rn_clk_mgr.o rn_clk_mgr_vbios_smu.o
 
-# prevent build errors regarding soft-float vs hard-float FP ABI tags
-# this code is currently unused on ppc64, as it applies to Renoir APUs only
-ifdef CONFIG_PPC64
-CFLAGS_$(AMDDALPATH)/dc/clk_mgr/dcn21/rn_clk_mgr.o := $(call cc-option,-mno-gnu-attribute)
-endif
-
 AMD_DAL_CLK_MGR_DCN21 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn21/,$(CLK_MGR_DCN21))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN21)
@@ -121,12 +115,6 @@  AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN21)
 ###############################################################################
 CLK_MGR_DCN30 = dcn30_clk_mgr.o dcn30_clk_mgr_smu_msg.o
 
-# prevent build errors regarding soft-float vs hard-float FP ABI tags
-# this code is currently unused on ppc64, as it applies to VanGogh APUs only
-ifdef CONFIG_PPC64
-CFLAGS_$(AMDDALPATH)/dc/clk_mgr/dcn30/dcn30_clk_mgr.o := $(call cc-option,-mno-gnu-attribute)
-endif
-
 AMD_DAL_CLK_MGR_DCN30 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn30/,$(CLK_MGR_DCN30))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN30)
@@ -135,12 +123,6 @@  AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN30)
 ###############################################################################
 CLK_MGR_DCN301 = vg_clk_mgr.o dcn301_smu.o
 
-# prevent build errors regarding soft-float vs hard-float FP ABI tags
-# this code is currently unused on ppc64, as it applies to VanGogh APUs only
-ifdef CONFIG_PPC64
-CFLAGS_$(AMDDALPATH)/dc/clk_mgr/dcn301/vg_clk_mgr.o := $(call cc-option,-mno-gnu-attribute)
-endif
-
 AMD_DAL_CLK_MGR_DCN301 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn301/,$(CLK_MGR_DCN301))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN301)
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
index cf1b5f354ae99..0202dc682682b 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
@@ -26,10 +26,9 @@ 
 #include "dccg.h"
 #include "clk_mgr_internal.h"
 
-
 #include "dcn20/dcn20_clk_mgr.h"
 #include "rn_clk_mgr.h"
-
+#include "dml/dcn20/dcn20_fpu.h"
 
 #include "dce100/dce_clk_mgr.h"
 #include "rn_clk_mgr_vbios_smu.h"
@@ -45,7 +44,6 @@ 
 
 /* Constants */
 
-#define LPDDR_MEM_RETRAIN_LATENCY 4.977 /* Number obtained from LPDDR4 Training Counter Requirement doc */
 #define SMU_VER_55_51_0 0x373300 /* SMU Version that is able to set DISPCLK below 100MHz */
 
 /* Macros */
@@ -613,228 +611,6 @@  static struct clk_bw_params rn_bw_params = {
 
 };
 
-static struct wm_table ddr4_wm_table_gs = {
-	.entries = {
-		{
-			.wm_inst = WM_A,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.72,
-			.sr_exit_time_us = 7.09,
-			.sr_enter_plus_exit_time_us = 8.14,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_B,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.72,
-			.sr_exit_time_us = 10.12,
-			.sr_enter_plus_exit_time_us = 11.48,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_C,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.72,
-			.sr_exit_time_us = 10.12,
-			.sr_enter_plus_exit_time_us = 11.48,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_D,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.72,
-			.sr_exit_time_us = 10.12,
-			.sr_enter_plus_exit_time_us = 11.48,
-			.valid = true,
-		},
-	}
-};
-
-static struct wm_table lpddr4_wm_table_gs = {
-	.entries = {
-		{
-			.wm_inst = WM_A,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.65333,
-			.sr_exit_time_us = 5.32,
-			.sr_enter_plus_exit_time_us = 6.38,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_B,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.65333,
-			.sr_exit_time_us = 9.82,
-			.sr_enter_plus_exit_time_us = 11.196,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_C,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.65333,
-			.sr_exit_time_us = 9.89,
-			.sr_enter_plus_exit_time_us = 11.24,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_D,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.65333,
-			.sr_exit_time_us = 9.748,
-			.sr_enter_plus_exit_time_us = 11.102,
-			.valid = true,
-		},
-	}
-};
-
-static struct wm_table lpddr4_wm_table_with_disabled_ppt = {
-	.entries = {
-		{
-			.wm_inst = WM_A,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.65333,
-			.sr_exit_time_us = 8.32,
-			.sr_enter_plus_exit_time_us = 9.38,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_B,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.65333,
-			.sr_exit_time_us = 9.82,
-			.sr_enter_plus_exit_time_us = 11.196,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_C,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.65333,
-			.sr_exit_time_us = 9.89,
-			.sr_enter_plus_exit_time_us = 11.24,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_D,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.65333,
-			.sr_exit_time_us = 9.748,
-			.sr_enter_plus_exit_time_us = 11.102,
-			.valid = true,
-		},
-	}
-};
-
-static struct wm_table ddr4_wm_table_rn = {
-	.entries = {
-		{
-			.wm_inst = WM_A,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.72,
-			.sr_exit_time_us = 11.90,
-			.sr_enter_plus_exit_time_us = 12.80,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_B,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.72,
-			.sr_exit_time_us = 13.18,
-			.sr_enter_plus_exit_time_us = 14.30,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_C,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.72,
-			.sr_exit_time_us = 13.18,
-			.sr_enter_plus_exit_time_us = 14.30,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_D,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.72,
-			.sr_exit_time_us = 13.18,
-			.sr_enter_plus_exit_time_us = 14.30,
-			.valid = true,
-		},
-	}
-};
-
-static struct wm_table ddr4_1R_wm_table_rn = {
-	.entries = {
-		{
-			.wm_inst = WM_A,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.72,
-			.sr_exit_time_us = 13.90,
-			.sr_enter_plus_exit_time_us = 14.80,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_B,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.72,
-			.sr_exit_time_us = 13.90,
-			.sr_enter_plus_exit_time_us = 14.80,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_C,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.72,
-			.sr_exit_time_us = 13.90,
-			.sr_enter_plus_exit_time_us = 14.80,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_D,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.72,
-			.sr_exit_time_us = 13.90,
-			.sr_enter_plus_exit_time_us = 14.80,
-			.valid = true,
-		},
-	}
-};
-
-static struct wm_table lpddr4_wm_table_rn = {
-	.entries = {
-		{
-			.wm_inst = WM_A,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.65333,
-			.sr_exit_time_us = 7.32,
-			.sr_enter_plus_exit_time_us = 8.38,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_B,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.65333,
-			.sr_exit_time_us = 9.82,
-			.sr_enter_plus_exit_time_us = 11.196,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_C,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.65333,
-			.sr_exit_time_us = 9.89,
-			.sr_enter_plus_exit_time_us = 11.24,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_D,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.65333,
-			.sr_exit_time_us = 9.748,
-			.sr_enter_plus_exit_time_us = 11.102,
-			.valid = true,
-		},
-	}
-};
-
 static unsigned int find_socclk_for_voltage(struct dpm_clocks *clock_table, unsigned int voltage)
 {
 	int i;
@@ -914,12 +690,10 @@  static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params
 		/*
 		 * WM set D will be re-purposed for memory retraining
 		 */
-		bw_params->wm_table.entries[WM_D].pstate_latency_us = LPDDR_MEM_RETRAIN_LATENCY;
-		bw_params->wm_table.entries[WM_D].wm_inst = WM_D;
-		bw_params->wm_table.entries[WM_D].wm_type = WM_TYPE_RETRAINING;
-		bw_params->wm_table.entries[WM_D].valid = true;
+		DC_FP_START();
+		dcn21_clk_mgr_set_bw_params_wm_table(bw_params);
+		DC_FP_END();
 	}
-
 }
 
 void rn_clk_mgr_construct(
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.h
index e4322fa5475b6..2e088c5171b28 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.h
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.h
@@ -29,6 +29,13 @@ 
 #include "clk_mgr.h"
 #include "dm_pp_smu.h"
 
+extern struct wm_table ddr4_wm_table_gs;
+extern struct wm_table lpddr4_wm_table_gs;
+extern struct wm_table lpddr4_wm_table_with_disabled_ppt;
+extern struct wm_table ddr4_wm_table_rn;
+extern struct wm_table ddr4_1R_wm_table_rn;
+extern struct wm_table lpddr4_wm_table_rn;
+
 struct rn_clk_registers {
 	uint32_t CLK1_CLK0_CURRENT_CNT; /* DPREFCLK */
 };
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
index 5ed6a93d1708c..e34a0e81facb6 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
@@ -29,6 +29,7 @@ 
 #include "dcn20/dcn20_clk_mgr.h"
 #include "dce100/dce_clk_mgr.h"
 #include "dcn30/dcn30_clk_mgr.h"
+#include "dml/dcn30/dcn30_fpu.h"
 #include "reg_helper.h"
 #include "core_types.h"
 #include "dm_helpers.h"
@@ -97,57 +98,11 @@  static void dcn3_init_single_clock(struct clk_mgr_internal *clk_mgr, uint32_t cl
 	}
 }
 
-static noinline void dcn3_build_wm_range_table(struct clk_mgr_internal *clk_mgr)
+static void dcn3_build_wm_range_table(struct clk_mgr_internal *clk_mgr)
 {
-	/* defaults */
-	double pstate_latency_us = clk_mgr->base.ctx->dc->dml.soc.dram_clock_change_latency_us;
-	double sr_exit_time_us = clk_mgr->base.ctx->dc->dml.soc.sr_exit_time_us;
-	double sr_enter_plus_exit_time_us = clk_mgr->base.ctx->dc->dml.soc.sr_enter_plus_exit_time_us;
-	uint16_t min_uclk_mhz = clk_mgr->base.bw_params->clk_table.entries[0].memclk_mhz;
-
-	/* Set A - Normal - default values*/
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].valid = true;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us = pstate_latency_us;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].dml_input.sr_exit_time_us = sr_exit_time_us;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.wm_type = WATERMARKS_CLOCK_RANGE;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.min_dcfclk = 0;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.max_dcfclk = 0xFFFF;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.min_uclk = min_uclk_mhz;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.max_uclk = 0xFFFF;
-
-	/* Set B - Performance - higher minimum clocks */
-//	clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].valid = true;
-//	clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].dml_input.pstate_latency_us = pstate_latency_us;
-//	clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].dml_input.sr_exit_time_us = sr_exit_time_us;
-//	clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;
-//	clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.wm_type = WATERMARKS_CLOCK_RANGE;
-//	clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.min_dcfclk = TUNED VALUE;
-//	clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.max_dcfclk = 0xFFFF;
-//	clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.min_uclk = TUNED VALUE;
-//	clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.max_uclk = 0xFFFF;
-
-	/* Set C - Dummy P-State - P-State latency set to "dummy p-state" value */
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].valid = true;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].dml_input.pstate_latency_us = clk_mgr->base.ctx->dc->dml.soc.dummy_pstate_latency_us;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].dml_input.sr_exit_time_us = sr_exit_time_us;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.wm_type = WATERMARKS_DUMMY_PSTATE;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.min_dcfclk = 0;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.max_dcfclk = 0xFFFF;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.min_uclk = min_uclk_mhz;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.max_uclk = 0xFFFF;
-
-	/* Set D - MALL - SR enter and exit times adjusted for MALL */
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].valid = true;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.pstate_latency_us = pstate_latency_us;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.sr_exit_time_us = 2;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.sr_enter_plus_exit_time_us = 4;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.wm_type = WATERMARKS_MALL;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_dcfclk = 0;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_dcfclk = 0xFFFF;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_uclk = min_uclk_mhz;
-	clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_uclk = 0xFFFF;
+	DC_FP_START();
+	dcn3_fpu_build_wm_range_table(&clk_mgr->base);
+	DC_FP_END();
 }
 
 void dcn3_init_clocks(struct clk_mgr *clk_mgr_base)
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
index f310b0d25a076..24715ca2fa944 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
@@ -32,6 +32,9 @@ 
 // For dcn20_update_clocks_update_dpp_dto
 #include "dcn20/dcn20_clk_mgr.h"
 
+// For DML FPU code
+#include "dml/dcn20/dcn20_fpu.h"
+
 #include "vg_clk_mgr.h"
 #include "dcn301_smu.h"
 #include "reg_helper.h"
@@ -526,81 +529,6 @@  static struct clk_bw_params vg_bw_params = {
 
 };
 
-static struct wm_table ddr4_wm_table = {
-	.entries = {
-		{
-			.wm_inst = WM_A,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.72,
-			.sr_exit_time_us = 6.09,
-			.sr_enter_plus_exit_time_us = 7.14,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_B,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.72,
-			.sr_exit_time_us = 10.12,
-			.sr_enter_plus_exit_time_us = 11.48,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_C,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.72,
-			.sr_exit_time_us = 10.12,
-			.sr_enter_plus_exit_time_us = 11.48,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_D,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.72,
-			.sr_exit_time_us = 10.12,
-			.sr_enter_plus_exit_time_us = 11.48,
-			.valid = true,
-		},
-	}
-};
-
-static struct wm_table lpddr5_wm_table = {
-	.entries = {
-		{
-			.wm_inst = WM_A,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.65333,
-			.sr_exit_time_us = 13.5,
-			.sr_enter_plus_exit_time_us = 16.5,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_B,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.65333,
-			.sr_exit_time_us = 13.5,
-			.sr_enter_plus_exit_time_us = 16.5,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_C,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.65333,
-			.sr_exit_time_us = 13.5,
-			.sr_enter_plus_exit_time_us = 16.5,
-			.valid = true,
-		},
-		{
-			.wm_inst = WM_D,
-			.wm_type = WM_TYPE_PSTATE_CHG,
-			.pstate_latency_us = 11.65333,
-			.sr_exit_time_us = 13.5,
-			.sr_enter_plus_exit_time_us = 16.5,
-			.valid = true,
-		},
-	}
-};
-
-
 static unsigned int find_dcfclk_for_voltage(const struct vg_dpm_clocks *clock_table,
 		unsigned int voltage)
 {
@@ -670,10 +598,9 @@  static void vg_clk_mgr_helper_populate_bw_params(
 		/*
 		 * WM set D will be re-purposed for memory retraining
 		 */
-		bw_params->wm_table.entries[WM_D].pstate_latency_us = LPDDR_MEM_RETRAIN_LATENCY;
-		bw_params->wm_table.entries[WM_D].wm_inst = WM_D;
-		bw_params->wm_table.entries[WM_D].wm_type = WM_TYPE_RETRAINING;
-		bw_params->wm_table.entries[WM_D].valid = true;
+		DC_FP_START();
+		dcn21_clk_mgr_set_bw_params_wm_table(bw_params);
+		DC_FP_END();
 	}
 
 }
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.h
index 7255477307f13..75884f5729891 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.h
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.h
@@ -29,6 +29,9 @@ 
 
 struct watermarks;
 
+extern struct wm_table ddr4_wm_table;
+extern struct wm_table lpddr5_wm_table;
+
 struct smu_watermark_set {
 	struct watermarks *wm_set;
 	union large_integer mc_address;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/Makefile b/drivers/gpu/drm/amd/display/dc/dcn201/Makefile
index f68038ceb1b15..5c9ce2cebb0f6 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn201/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn201/Makefile
@@ -6,31 +6,6 @@  DCN201 = dcn201_init.o dcn201_resource.o dcn201_hwseq.o \
 	dcn201_mpc.o dcn201_hubp.o dcn201_opp.o dcn201_optc.o dcn201_dpp.o \
 	dcn201_dccg.o dcn201_link_encoder.o
 
-ifdef CONFIG_X86
-CFLAGS_$(AMDDALPATH)/dc/dcn201/dcn201_resource.o := -mhard-float -msse
-endif
-
-ifdef CONFIG_PPC64
-CFLAGS_$(AMDDALPATH)/dc/dcn201/dcn201_resource.o := -mhard-float -maltivec
-endif
-
-ifdef CONFIG_CC_IS_GCC
-ifeq ($(call cc-ifversion, -lt, 0701, y), y)
-IS_OLD_GCC = 1
-endif
-CFLAGS_$(AMDDALPATH)/dc/dcn201/dcn201_resource.o += -mhard-float
-endif
-
-ifdef CONFIG_X86
-ifdef IS_OLD_GCC
-# Stack alignment mismatch, proceed with caution.
-# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
-# (8B stack alignment).
-CFLAGS_$(AMDDALPATH)/dc/dcn201/dcn201_resource.o += -mpreferred-stack-boundary=4
-else
-CFLAGS_$(AMDDALPATH)/dc/dcn201/dcn201_resource.o += -msse2
-endif
-endif
 AMD_DAL_DCN201 = $(addprefix $(AMDDALPATH)/dc/dcn201/,$(DCN201))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_DCN201)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c
index 0bb7d3dd53fa4..e549a79f3fe1a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c
@@ -1036,6 +1036,14 @@  static bool dcn201_get_dcc_compression_cap(const struct dc *dc,
 			output);
 }
 
+static void dcn201_populate_dml_writeback_from_context(struct dc *dc,
+						       struct resource_context *res_ctx,
+						       display_e2e_pipe_params_st *pipes)
+{
+	DC_FP_START();
+	dcn201_populate_dml_writeback_from_context_fpu(dc, res_ctx, pipes);
+	DC_FP_END();
+}
 
 static void dcn201_destroy_resource_pool(struct resource_pool **pool)
 {
@@ -1067,8 +1075,8 @@  static struct resource_funcs dcn201_res_pool_funcs = {
 	.add_dsc_to_stream_resource = NULL,
 	.remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
 	.acquire_idle_pipe_for_layer = dcn201_acquire_idle_pipe_for_layer,
+	.populate_dml_writeback_from_context = dcn201_populate_dml_writeback_from_context,
 	.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
-	.populate_dml_writeback_from_context = dcn20_populate_dml_writeback_from_context,
 	.set_mcif_arb_params = dcn20_set_mcif_arb_params,
 	.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link
 };
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
index dfd77b3cc84d8..b7c2ae9ddfda3 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
@@ -30,38 +30,6 @@  DCN30 = dcn30_init.o dcn30_hubbub.o dcn30_hubp.o dcn30_dpp.o dcn30_optc.o \
 	dcn30_dpp_cm.o dcn30_dwb_cm.o dcn30_cm_common.o dcn30_mmhubbub.o \
 	dcn30_dio_link_encoder.o dcn30_resource.o
 
-
-ifdef CONFIG_X86
-CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o := -msse
-CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o := -msse
-endif
-
-ifdef CONFIG_PPC64
-CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o := -mhard-float -maltivec
-CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o := -mhard-float -maltivec
-endif
-
-ifdef CONFIG_CC_IS_GCC
-ifeq ($(call cc-ifversion, -lt, 0701, y), y)
-IS_OLD_GCC = 1
-endif
-CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o += -mhard-float
-CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o += -mhard-float
-endif
-
-ifdef CONFIG_X86
-ifdef IS_OLD_GCC
-# Stack alignment mismatch, proceed with caution.
-# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
-# (8B stack alignment).
-CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o += -mpreferred-stack-boundary=4
-CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o += -mpreferred-stack-boundary=4
-else
-CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o += -msse2
-CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o += -msse2
-endif
-endif
-
 AMD_DAL_DCN30 = $(addprefix $(AMDDALPATH)/dc/dcn30/,$(DCN30))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_DCN30)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
index b604fb26f288d..4c57c001fd23b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
@@ -186,14 +186,6 @@  void optc3_set_dsc_config(struct timing_generator *optc,
 
 }
 
-void optc3_set_vrr_m_const(struct timing_generator *optc,
-		double vtotal_avg)
-{
-	DC_FP_START();
-	optc3_fpu_set_vrr_m_const(optc, vtotal_avg);
-	DC_FP_END();
-}
-
 void optc3_set_odm_bypass(struct timing_generator *optc,
 		const struct dc_crtc_timing *dc_crtc_timing)
 {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h
index 97f11ef6e9f02..bd5743b73fa5b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h
@@ -320,9 +320,6 @@  void optc3_lock_doublebuffer_enable(struct timing_generator *optc);
 
 void optc3_lock_doublebuffer_disable(struct timing_generator *optc);
 
-void optc3_set_vrr_m_const(struct timing_generator *optc,
-		double vtotal_avg);
-
 void optc3_set_drr_trigger_window(struct timing_generator *optc,
 		uint32_t window_start, uint32_t window_end);
 
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
index 1c1a67c4cec1c..19ef63b13fe43 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
@@ -1520,26 +1520,11 @@  static bool init_soc_bounding_box(struct dc *dc,
 	loaded_ip->max_num_otg = pool->base.res_cap->num_timing_generator;
 	loaded_ip->max_num_dpp = pool->base.pipe_count;
 	loaded_ip->clamp_min_dcfclk = dc->config.clamp_min_dcfclk;
-
-	DC_FP_START();
 	dcn20_patch_bounding_box(dc, loaded_bb);
+	DC_FP_START();
+	patch_dcn30_soc_bounding_box(dc, &dcn3_0_soc);
 	DC_FP_END();
 
-	if (dc->ctx->dc_bios->funcs->get_soc_bb_info) {
-		struct bp_soc_bb_info bb_info = {0};
-
-		if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) {
-			if (bb_info.dram_clock_change_latency_100ns > 0)
-				dcn3_0_soc.dram_clock_change_latency_us = bb_info.dram_clock_change_latency_100ns * 10;
-
-			if (bb_info.dram_sr_enter_exit_latency_100ns > 0)
-				dcn3_0_soc.sr_enter_plus_exit_time_us = bb_info.dram_sr_enter_exit_latency_100ns * 10;
-
-			if (bb_info.dram_sr_exit_latency_100ns > 0)
-				dcn3_0_soc.sr_exit_time_us = bb_info.dram_sr_exit_latency_100ns * 10;
-		}
-	}
-
 	return true;
 }
 
diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/Makefile b/drivers/gpu/drm/amd/display/dc/dcn302/Makefile
index f9561d7f97a1d..ebd01cb467b79 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn302/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn302/Makefile
@@ -7,25 +7,6 @@ 
 
 DCN3_02 = dcn302_init.o dcn302_hwseq.o dcn302_resource.o
 
-ifdef CONFIG_X86
-CFLAGS_$(AMDDALPATH)/dc/dcn302/dcn302_resource.o := -msse
-endif
-
-ifdef CONFIG_PPC64
-CFLAGS_$(AMDDALPATH)/dc/dcn302/dcn302_resource.o := -mhard-float -maltivec
-endif
-
-ifdef CONFIG_X86
-ifdef IS_OLD_GCC
-# Stack alignment mismatch, proceed with caution.
-# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
-# (8B stack alignment).
-CFLAGS_$(AMDDALPATH)/dc/dcn302/dcn302_resource.o += -mpreferred-stack-boundary=4
-else
-CFLAGS_$(AMDDALPATH)/dc/dcn302/dcn302_resource.o += -msse2
-endif
-endif
-
 AMD_DAL_DCN3_02 = $(addprefix $(AMDDALPATH)/dc/dcn302/,$(DCN3_02))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_DCN3_02)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
index 3d9f07d4770bf..fe21d33111729 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
@@ -1873,8 +1873,6 @@  static bool dcn31_resource_construct(
 	struct dc_context *ctx = dc->ctx;
 	struct irq_service_init_data init_data;
 
-	DC_FP_START();
-
 	ctx->dc_bios->regs = &bios_regs;
 
 	pool->base.res_cap = &res_cap_dcn31;
@@ -2182,13 +2180,9 @@  static bool dcn31_resource_construct(
 
 	dc->dcn_ip->max_num_dpp = dcn3_1_ip.max_num_dpp;
 
-	DC_FP_END();
-
 	return true;
 
 create_fail:
-
-	DC_FP_END();
 	dcn31_resource_destruct(pool);
 
 	return false;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h
index 393458015d6a4..98ae95f378659 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h
@@ -32,7 +32,6 @@ 
 	container_of(pool, struct dcn31_resource_pool, base)
 
 extern struct _vcs_dpi_ip_params_st dcn3_1_ip;
-extern struct _vcs_dpi_soc_bounding_box_st dcn3_1_soc;
 
 struct dcn31_resource_pool {
 	struct resource_pool base;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h
index 39929fa67a510..22849eaa6f243 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h
@@ -32,7 +32,6 @@ 
 	container_of(pool, struct dcn315_resource_pool, base)
 
 extern struct _vcs_dpi_ip_params_st dcn3_15_ip;
-extern struct _vcs_dpi_ip_params_st dcn3_15_soc;
 
 struct dcn315_resource_pool {
 	struct resource_pool base;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h
index 0dc5a6c13ae7d..aba6d634131b4 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h
@@ -32,7 +32,6 @@ 
 	container_of(pool, struct dcn316_resource_pool, base)
 
 extern struct _vcs_dpi_ip_params_st dcn3_16_ip;
-extern struct _vcs_dpi_ip_params_st dcn3_16_soc;
 
 struct dcn316_resource_pool {
 	struct resource_pool base;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c
new file mode 100644
index 0000000000000..eff1f4e17689c
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c
@@ -0,0 +1,328 @@ 
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dcn32_optc.h"
+
+#include "dcn30/dcn30_optc.h"
+#include "dcn31/dcn31_optc.h"
+#include "reg_helper.h"
+#include "dc.h"
+#include "dcn_calc_math.h"
+#include "dc_dmub_srv.h"
+
+#define REG(reg)\
+	optc1->tg_regs->reg
+
+#define CTX \
+	optc1->base.ctx
+
+#undef FN
+#define FN(reg_name, field_name) \
+	optc1->tg_shift->field_name, optc1->tg_mask->field_name
+
+static void optc32_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
+		struct dc_crtc_timing *timing)
+{
+	struct optc *optc1 = DCN10TG_FROM_TG(optc);
+	uint32_t memory_mask = 0;
+	int h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right;
+	int mpcc_hactive = h_active / opp_cnt;
+	/* Each memory instance is 2048x(32x2) bits to support half line of 4096 */
+	int odm_mem_count = (h_active + 2047) / 2048;
+
+	/*
+	 * display <= 4k : 2 memories + 2 pipes
+	 * 4k < display <= 8k : 4 memories + 2 pipes
+	 * 8k < display <= 12k : 6 memories + 4 pipes
+	 */
+	if (opp_cnt == 4) {
+		if (odm_mem_count <= 2)
+			memory_mask = 0x3;
+		else if (odm_mem_count <= 4)
+			memory_mask = 0xf;
+		else
+			memory_mask = 0x3f;
+	} else {
+		if (odm_mem_count <= 2)
+			memory_mask = 0x1 << (opp_id[0] * 2) | 0x1 << (opp_id[1] * 2);
+		else if (odm_mem_count <= 4)
+			memory_mask = 0x3 << (opp_id[0] * 2) | 0x3 << (opp_id[1] * 2);
+		else
+			memory_mask = 0x77;
+	}
+
+	REG_SET(OPTC_MEMORY_CONFIG, 0,
+		OPTC_MEM_SEL, memory_mask);
+
+	if (opp_cnt == 2) {
+		REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0,
+				OPTC_NUM_OF_INPUT_SEGMENT, 1,
+				OPTC_SEG0_SRC_SEL, opp_id[0],
+				OPTC_SEG1_SRC_SEL, opp_id[1]);
+	} else if (opp_cnt == 4) {
+		REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0,
+				OPTC_NUM_OF_INPUT_SEGMENT, 3,
+				OPTC_SEG0_SRC_SEL, opp_id[0],
+				OPTC_SEG1_SRC_SEL, opp_id[1],
+				OPTC_SEG2_SRC_SEL, opp_id[2],
+				OPTC_SEG3_SRC_SEL, opp_id[3]);
+	}
+
+	REG_UPDATE(OPTC_WIDTH_CONTROL,
+			OPTC_SEGMENT_WIDTH, mpcc_hactive);
+
+	REG_UPDATE(OTG_H_TIMING_CNTL,
+			OTG_H_TIMING_DIV_MODE, opp_cnt - 1);
+	optc1->opp_count = opp_cnt;
+}
+
+static void optc32_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode)
+{
+	struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+	REG_UPDATE(OTG_H_TIMING_CNTL,
+			OTG_H_TIMING_DIV_MODE_MANUAL, manual_mode ? 1 : 0);
+}
+/**
+ * Enable CRTC
+ * Enable CRTC - call ASIC Control Object to enable Timing generator.
+ */
+static bool optc32_enable_crtc(struct timing_generator *optc)
+{
+	struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+	/* opp instance for OTG, 1 to 1 mapping and odm will adjust */
+	REG_UPDATE(OPTC_DATA_SOURCE_SELECT,
+			OPTC_SEG0_SRC_SEL, optc->inst);
+
+	/* VTG enable first is for HW workaround */
+	REG_UPDATE(CONTROL,
+			VTG0_ENABLE, 1);
+
+	REG_SEQ_START();
+
+	/* Enable CRTC */
+	REG_UPDATE_2(OTG_CONTROL,
+			OTG_DISABLE_POINT_CNTL, 2,
+			OTG_MASTER_EN, 1);
+
+	REG_SEQ_SUBMIT();
+	REG_SEQ_WAIT_DONE();
+
+	return true;
+}
+
+/* disable_crtc */
+static bool optc32_disable_crtc(struct timing_generator *optc)
+{
+	struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+	/* disable otg request until end of the first line
+	 * in the vertical blank region
+	 */
+	REG_UPDATE(OTG_CONTROL,
+			OTG_MASTER_EN, 0);
+
+	REG_UPDATE(CONTROL,
+			VTG0_ENABLE, 0);
+
+	/* CRTC disabled, so disable  clock. */
+	REG_WAIT(OTG_CLOCK_CONTROL,
+			OTG_BUSY, 0,
+			1, 100000);
+
+	return true;
+}
+
+void optc32_phantom_crtc_post_enable(struct timing_generator *optc)
+{
+	struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+	/* Disable immediately. */
+	REG_UPDATE_2(OTG_CONTROL, OTG_DISABLE_POINT_CNTL, 0, OTG_MASTER_EN, 0);
+
+	/* CRTC disabled, so disable  clock. */
+	REG_WAIT(OTG_CLOCK_CONTROL, OTG_BUSY, 0, 1, 100000);
+}
+
+static void optc32_set_odm_bypass(struct timing_generator *optc,
+		const struct dc_crtc_timing *dc_crtc_timing)
+{
+	struct optc *optc1 = DCN10TG_FROM_TG(optc);
+	enum h_timing_div_mode h_div = H_TIMING_NO_DIV;
+
+	REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0,
+			OPTC_NUM_OF_INPUT_SEGMENT, 0,
+			OPTC_SEG0_SRC_SEL, optc->inst,
+			OPTC_SEG1_SRC_SEL, 0xf,
+			OPTC_SEG2_SRC_SEL, 0xf,
+			OPTC_SEG3_SRC_SEL, 0xf
+			);
+
+	h_div = optc1_is_two_pixels_per_containter(dc_crtc_timing);
+	REG_UPDATE(OTG_H_TIMING_CNTL,
+			OTG_H_TIMING_DIV_MODE, h_div);
+
+	REG_SET(OPTC_MEMORY_CONFIG, 0,
+			OPTC_MEM_SEL, 0);
+	optc1->opp_count = 1;
+}
+
+void optc32_setup_manual_trigger(struct timing_generator *optc)
+{
+	struct optc *optc1 = DCN10TG_FROM_TG(optc);
+	struct dc *dc = optc->ctx->dc;
+
+	if (dc->caps.dmub_caps.mclk_sw && !dc->debug.disable_fams)
+		dc_dmub_srv_set_drr_manual_trigger_cmd(dc, optc->inst);
+	else {
+		/*
+		 * MIN_MASK_EN is gone and MASK is now always enabled.
+		 *
+		 * To get it to it work with manual trigger we need to make sure
+		 * we program the correct bit.
+		 */
+		REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
+				OTG_V_TOTAL_MIN_SEL, 1,
+				OTG_V_TOTAL_MAX_SEL, 1,
+				OTG_FORCE_LOCK_ON_EVENT, 0,
+				OTG_SET_V_TOTAL_MIN_MASK, (1 << 1)); /* TRIGA */
+
+		// Setup manual flow control for EOF via TRIG_A
+		optc->funcs->setup_manual_trigger(optc);
+	}
+}
+
+void optc32_set_drr(
+	struct timing_generator *optc,
+	const struct drr_params *params)
+{
+	struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+	if (params != NULL &&
+		params->vertical_total_max > 0 &&
+		params->vertical_total_min > 0) {
+
+		if (params->vertical_total_mid != 0) {
+
+			REG_SET(OTG_V_TOTAL_MID, 0,
+				OTG_V_TOTAL_MID, params->vertical_total_mid - 1);
+
+			REG_UPDATE_2(OTG_V_TOTAL_CONTROL,
+					OTG_VTOTAL_MID_REPLACING_MAX_EN, 1,
+					OTG_VTOTAL_MID_FRAME_NUM,
+					(uint8_t)params->vertical_total_mid_frame_num);
+
+		}
+
+		optc->funcs->set_vtotal_min_max(optc, params->vertical_total_min - 1, params->vertical_total_max - 1);
+		optc32_setup_manual_trigger(optc);
+	} else {
+		REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
+				OTG_SET_V_TOTAL_MIN_MASK, 0,
+				OTG_V_TOTAL_MIN_SEL, 0,
+				OTG_V_TOTAL_MAX_SEL, 0,
+				OTG_FORCE_LOCK_ON_EVENT, 0);
+
+		optc->funcs->set_vtotal_min_max(optc, 0, 0);
+	}
+}
+
+static struct timing_generator_funcs dcn32_tg_funcs = {
+		.validate_timing = optc1_validate_timing,
+		.program_timing = optc1_program_timing,
+		.setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0,
+		.setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1,
+		.setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2,
+		.program_global_sync = optc1_program_global_sync,
+		.enable_crtc = optc32_enable_crtc,
+		.disable_crtc = optc32_disable_crtc,
+		.phantom_crtc_post_enable = optc32_phantom_crtc_post_enable,
+		/* used by enable_timing_synchronization. Not need for FPGA */
+		.is_counter_moving = optc1_is_counter_moving,
+		.get_position = optc1_get_position,
+		.get_frame_count = optc1_get_vblank_counter,
+		.get_scanoutpos = optc1_get_crtc_scanoutpos,
+		.get_otg_active_size = optc1_get_otg_active_size,
+		.set_early_control = optc1_set_early_control,
+		/* used by enable_timing_synchronization. Not need for FPGA */
+		.wait_for_state = optc1_wait_for_state,
+		.set_blank_color = optc3_program_blank_color,
+		.did_triggered_reset_occur = optc1_did_triggered_reset_occur,
+		.triplebuffer_lock = optc3_triplebuffer_lock,
+		.triplebuffer_unlock = optc2_triplebuffer_unlock,
+		.enable_reset_trigger = optc1_enable_reset_trigger,
+		.enable_crtc_reset = optc1_enable_crtc_reset,
+		.disable_reset_trigger = optc1_disable_reset_trigger,
+		.lock = optc3_lock,
+		.unlock = optc1_unlock,
+		.lock_doublebuffer_enable = optc3_lock_doublebuffer_enable,
+		.lock_doublebuffer_disable = optc3_lock_doublebuffer_disable,
+		.enable_optc_clock = optc1_enable_optc_clock,
+		.set_drr = optc31_set_drr, // TODO: Update to optc32_set_drr once FW headers are promoted
+		.get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal,
+		.set_vtotal_min_max = optc3_set_vtotal_min_max,
+		.set_static_screen_control = optc1_set_static_screen_control,
+		.program_stereo = optc1_program_stereo,
+		.is_stereo_left_eye = optc1_is_stereo_left_eye,
+		.tg_init = optc3_tg_init,
+		.is_tg_enabled = optc1_is_tg_enabled,
+		.is_optc_underflow_occurred = optc1_is_optc_underflow_occurred,
+		.clear_optc_underflow = optc1_clear_optc_underflow,
+		.setup_global_swap_lock = NULL,
+		.get_crc = optc1_get_crc,
+		.configure_crc = optc1_configure_crc,
+		.set_dsc_config = optc3_set_dsc_config,
+		.get_dsc_status = optc2_get_dsc_status,
+		.set_dwb_source = NULL,
+		.set_odm_bypass = optc32_set_odm_bypass,
+		.set_odm_combine = optc32_set_odm_combine,
+		.set_h_timing_div_manual_mode = optc32_set_h_timing_div_manual_mode,
+		.get_optc_source = optc2_get_optc_source,
+		.set_out_mux = optc3_set_out_mux,
+		.set_drr_trigger_window = optc3_set_drr_trigger_window,
+		.set_vtotal_change_limit = optc3_set_vtotal_change_limit,
+		.set_gsl = optc2_set_gsl,
+		.set_gsl_source_select = optc2_set_gsl_source_select,
+		.set_vtg_params = optc1_set_vtg_params,
+		.program_manual_trigger = optc2_program_manual_trigger,
+		.setup_manual_trigger = optc2_setup_manual_trigger,
+		.get_hw_timing = optc1_get_hw_timing,
+};
+
+void dcn32_timing_generator_init(struct optc *optc1)
+{
+	optc1->base.funcs = &dcn32_tg_funcs;
+
+	optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1;
+	optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1;
+
+	optc1->min_h_blank = 32;
+	optc1->min_v_blank = 3;
+	optc1->min_v_blank_interlace = 5;
+	optc1->min_h_sync_width = 4;
+	optc1->min_v_sync_width = 1;
+}
+
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
index f79dd40f8d811..b196b1f38c185 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
@@ -30,6 +30,7 @@ 
 #include "dchubbub.h"
 #include "dcn20/dcn20_resource.h"
 #include "dcn21/dcn21_resource.h"
+#include "clk_mgr/dcn21/rn_clk_mgr.h"
 
 #include "dcn20_fpu.h"
 
@@ -42,6 +43,9 @@ 
 #define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
 #endif
 
+/* Constant */
+#define LPDDR_MEM_RETRAIN_LATENCY 4.977 /* Number obtained from LPDDR4 Training Counter Requirement doc */
+
 /**
  * DOC: DCN2x FPU manipulation Overview
  *
@@ -650,6 +654,228 @@  struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = {
 	.num_states = 8
 };
 
+struct wm_table ddr4_wm_table_gs = {
+	.entries = {
+		{
+			.wm_inst = WM_A,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.72,
+			.sr_exit_time_us = 7.09,
+			.sr_enter_plus_exit_time_us = 8.14,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_B,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.72,
+			.sr_exit_time_us = 10.12,
+			.sr_enter_plus_exit_time_us = 11.48,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_C,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.72,
+			.sr_exit_time_us = 10.12,
+			.sr_enter_plus_exit_time_us = 11.48,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_D,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.72,
+			.sr_exit_time_us = 10.12,
+			.sr_enter_plus_exit_time_us = 11.48,
+			.valid = true,
+		},
+	}
+};
+
+struct wm_table lpddr4_wm_table_gs = {
+	.entries = {
+		{
+			.wm_inst = WM_A,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.65333,
+			.sr_exit_time_us = 5.32,
+			.sr_enter_plus_exit_time_us = 6.38,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_B,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.65333,
+			.sr_exit_time_us = 9.82,
+			.sr_enter_plus_exit_time_us = 11.196,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_C,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.65333,
+			.sr_exit_time_us = 9.89,
+			.sr_enter_plus_exit_time_us = 11.24,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_D,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.65333,
+			.sr_exit_time_us = 9.748,
+			.sr_enter_plus_exit_time_us = 11.102,
+			.valid = true,
+		},
+	}
+};
+
+struct wm_table lpddr4_wm_table_with_disabled_ppt = {
+	.entries = {
+		{
+			.wm_inst = WM_A,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.65333,
+			.sr_exit_time_us = 8.32,
+			.sr_enter_plus_exit_time_us = 9.38,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_B,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.65333,
+			.sr_exit_time_us = 9.82,
+			.sr_enter_plus_exit_time_us = 11.196,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_C,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.65333,
+			.sr_exit_time_us = 9.89,
+			.sr_enter_plus_exit_time_us = 11.24,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_D,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.65333,
+			.sr_exit_time_us = 9.748,
+			.sr_enter_plus_exit_time_us = 11.102,
+			.valid = true,
+		},
+	}
+};
+
+struct wm_table ddr4_wm_table_rn = {
+	.entries = {
+		{
+			.wm_inst = WM_A,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.72,
+			.sr_exit_time_us = 11.90,
+			.sr_enter_plus_exit_time_us = 12.80,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_B,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.72,
+			.sr_exit_time_us = 13.18,
+			.sr_enter_plus_exit_time_us = 14.30,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_C,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.72,
+			.sr_exit_time_us = 13.18,
+			.sr_enter_plus_exit_time_us = 14.30,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_D,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.72,
+			.sr_exit_time_us = 13.18,
+			.sr_enter_plus_exit_time_us = 14.30,
+			.valid = true,
+		},
+	}
+};
+
+struct wm_table ddr4_1R_wm_table_rn = {
+	.entries = {
+		{
+			.wm_inst = WM_A,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.72,
+			.sr_exit_time_us = 13.90,
+			.sr_enter_plus_exit_time_us = 14.80,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_B,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.72,
+			.sr_exit_time_us = 13.90,
+			.sr_enter_plus_exit_time_us = 14.80,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_C,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.72,
+			.sr_exit_time_us = 13.90,
+			.sr_enter_plus_exit_time_us = 14.80,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_D,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.72,
+			.sr_exit_time_us = 13.90,
+			.sr_enter_plus_exit_time_us = 14.80,
+			.valid = true,
+		},
+	}
+};
+
+struct wm_table lpddr4_wm_table_rn = {
+	.entries = {
+		{
+			.wm_inst = WM_A,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.65333,
+			.sr_exit_time_us = 7.32,
+			.sr_enter_plus_exit_time_us = 8.38,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_B,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.65333,
+			.sr_exit_time_us = 9.82,
+			.sr_enter_plus_exit_time_us = 11.196,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_C,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.65333,
+			.sr_exit_time_us = 9.89,
+			.sr_enter_plus_exit_time_us = 11.24,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_D,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.65333,
+			.sr_exit_time_us = 9.748,
+			.sr_enter_plus_exit_time_us = 11.102,
+			.valid = true,
+		},
+	}
+};
+
 void dcn20_populate_dml_writeback_from_context(struct dc *dc,
 					       struct resource_context *res_ctx,
 					       display_e2e_pipe_params_st *pipes)
@@ -2036,3 +2262,100 @@  void dcn21_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params
 
 	dml_init_instance(&dc->dml, &dcn2_1_soc, &dcn2_1_ip, DML_PROJECT_DCN21);
 }
+
+void dcn21_clk_mgr_set_bw_params_wm_table(struct clk_bw_params *bw_params)
+{
+	dc_assert_fp_enabled();
+
+	bw_params->wm_table.entries[WM_D].pstate_latency_us = LPDDR_MEM_RETRAIN_LATENCY;
+	bw_params->wm_table.entries[WM_D].wm_inst = WM_D;
+	bw_params->wm_table.entries[WM_D].wm_type = WM_TYPE_RETRAINING;
+	bw_params->wm_table.entries[WM_D].valid = true;
+}
+
+void dcn201_populate_dml_writeback_from_context_fpu(struct dc *dc,
+						    struct resource_context *res_ctx,
+						    display_e2e_pipe_params_st *pipes)
+{
+	int pipe_cnt, i, j;
+	double max_calc_writeback_dispclk;
+	double writeback_dispclk;
+	struct writeback_st dout_wb;
+
+	dc_assert_fp_enabled();
+
+	for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
+		struct dc_stream_state *stream = res_ctx->pipe_ctx[i].stream;
+
+		if (!stream)
+			continue;
+		max_calc_writeback_dispclk = 0;
+
+		/* Set writeback information */
+		pipes[pipe_cnt].dout.wb_enable = 0;
+		pipes[pipe_cnt].dout.num_active_wb = 0;
+		for (j = 0; j < stream->num_wb_info; j++) {
+			struct dc_writeback_info *wb_info = &stream->writeback_info[j];
+
+			if (wb_info->wb_enabled && wb_info->writeback_source_plane &&
+					(wb_info->writeback_source_plane == res_ctx->pipe_ctx[i].plane_state)) {
+				pipes[pipe_cnt].dout.wb_enable = 1;
+				pipes[pipe_cnt].dout.num_active_wb++;
+				dout_wb.wb_src_height = wb_info->dwb_params.cnv_params.crop_en ?
+					wb_info->dwb_params.cnv_params.crop_height :
+					wb_info->dwb_params.cnv_params.src_height;
+				dout_wb.wb_src_width = wb_info->dwb_params.cnv_params.crop_en ?
+					wb_info->dwb_params.cnv_params.crop_width :
+					wb_info->dwb_params.cnv_params.src_width;
+				dout_wb.wb_dst_width = wb_info->dwb_params.dest_width;
+				dout_wb.wb_dst_height = wb_info->dwb_params.dest_height;
+				dout_wb.wb_htaps_luma = wb_info->dwb_params.scaler_taps.h_taps;
+				dout_wb.wb_vtaps_luma = wb_info->dwb_params.scaler_taps.v_taps;;
+				dout_wb.wb_htaps_chroma = wb_info->dwb_params.scaler_taps.h_taps_c;
+				dout_wb.wb_vtaps_chroma = wb_info->dwb_params.scaler_taps.v_taps_c;
+				dout_wb.wb_hratio = wb_info->dwb_params.cnv_params.crop_en ?
+					(double)wb_info->dwb_params.cnv_params.crop_width /
+						(double)wb_info->dwb_params.dest_width :
+					(double)wb_info->dwb_params.cnv_params.src_width /
+						(double)wb_info->dwb_params.dest_width;
+				dout_wb.wb_vratio = wb_info->dwb_params.cnv_params.crop_en ?
+					(double)wb_info->dwb_params.cnv_params.crop_height /
+						(double)wb_info->dwb_params.dest_height :
+					(double)wb_info->dwb_params.cnv_params.src_height /
+						(double)wb_info->dwb_params.dest_height;
+				if (wb_info->dwb_params.out_format == dwb_scaler_mode_yuv420) {
+					if (wb_info->dwb_params.output_depth == DWB_OUTPUT_PIXEL_DEPTH_8BPC)
+						dout_wb.wb_pixel_format = dm_420_8;
+					else
+						dout_wb.wb_pixel_format = dm_420_10;
+				} else
+					dout_wb.wb_pixel_format = dm_444_32;
+
+				/* Workaround for cases where multiple writebacks are connected to same plane
+				 * In which case, need to compute worst case and set the associated writeback parameters
+				 * This workaround is necessary due to DML computation assuming only 1 set of writeback
+				 * parameters per pipe */
+				writeback_dispclk = CalculateWriteBackDISPCLK(
+						dout_wb.wb_pixel_format,
+						pipes[pipe_cnt].pipe.dest.pixel_rate_mhz,
+						dout_wb.wb_hratio,
+						dout_wb.wb_vratio,
+						dout_wb.wb_htaps_luma,
+						dout_wb.wb_vtaps_luma,
+						dout_wb.wb_htaps_chroma,
+						dout_wb.wb_vtaps_chroma,
+						dout_wb.wb_dst_width,
+						pipes[pipe_cnt].pipe.dest.htotal,
+						2);
+
+				if (writeback_dispclk > max_calc_writeback_dispclk) {
+					max_calc_writeback_dispclk = writeback_dispclk;
+					pipes[pipe_cnt].dout.wb = dout_wb;
+				}
+			}
+		}
+
+		pipe_cnt++;
+	}
+
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h
index aa892193e4854..c51badf7b68a9 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h
@@ -82,4 +82,10 @@  bool dcn21_validate_bandwidth_fp(struct dc *dc,
 				 bool fast_validate);
 void dcn21_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params);
 
+void dcn21_clk_mgr_set_bw_params_wm_table(struct clk_bw_params *bw_params);
+
+void dcn201_populate_dml_writeback_from_context_fpu(struct dc *dc,
+						struct resource_context *res_ctx,
+						display_e2e_pipe_params_st *pipes);
+
 #endif /* __DCN20_FPU_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c
index 574676a0711ae..8bc1bc55e6352 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c
@@ -29,7 +29,7 @@ 
 #include "dcn20/dcn20_resource.h"
 #include "dcn30/dcn30_resource.h"
 
-
+#include "clk_mgr/dcn30/dcn30_smu11_driver_if.h"
 #include "display_mode_vba_30.h"
 #include "dcn30_fpu.h"
 
@@ -614,4 +614,85 @@  void dcn30_fpu_update_bw_bounding_box(struct dc *dc,
 
 }
 
+void dcn3_fpu_build_wm_range_table(struct clk_mgr *base)
+{
+	/* defaults */
+	double pstate_latency_us = base->ctx->dc->dml.soc.dram_clock_change_latency_us;
+	double sr_exit_time_us = base->ctx->dc->dml.soc.sr_exit_time_us;
+	double sr_enter_plus_exit_time_us = base->ctx->dc->dml.soc.sr_enter_plus_exit_time_us;
+	uint16_t min_uclk_mhz = base->bw_params->clk_table.entries[0].memclk_mhz;
+
+	dc_assert_fp_enabled();
+
+	/* Set A - Normal - default values*/
+	base->bw_params->wm_table.nv_entries[WM_A].valid = true;
+	base->bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us = pstate_latency_us;
+	base->bw_params->wm_table.nv_entries[WM_A].dml_input.sr_exit_time_us = sr_exit_time_us;
+	base->bw_params->wm_table.nv_entries[WM_A].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;
+	base->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.wm_type = WATERMARKS_CLOCK_RANGE;
+	base->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.min_dcfclk = 0;
+	base->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.max_dcfclk = 0xFFFF;
+	base->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.min_uclk = min_uclk_mhz;
+	base->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.max_uclk = 0xFFFF;
+
+	/* Set B - Performance - higher minimum clocks */
+//	base->bw_params->wm_table.nv_entries[WM_B].valid = true;
+//	base->bw_params->wm_table.nv_entries[WM_B].dml_input.pstate_latency_us = pstate_latency_us;
+//	base->bw_params->wm_table.nv_entries[WM_B].dml_input.sr_exit_time_us = sr_exit_time_us;
+//	base->bw_params->wm_table.nv_entries[WM_B].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;
+//	base->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.wm_type = WATERMARKS_CLOCK_RANGE;
+//	base->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.min_dcfclk = TUNED VALUE;
+//	base->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.max_dcfclk = 0xFFFF;
+//	base->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.min_uclk = TUNED VALUE;
+//	base->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.max_uclk = 0xFFFF;
+
+	/* Set C - Dummy P-State - P-State latency set to "dummy p-state" value */
+	base->bw_params->wm_table.nv_entries[WM_C].valid = true;
+	base->bw_params->wm_table.nv_entries[WM_C].dml_input.pstate_latency_us = 0;
+	base->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_exit_time_us = sr_exit_time_us;
+	base->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;
+	base->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.wm_type = WATERMARKS_DUMMY_PSTATE;
+	base->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.min_dcfclk = 0;
+	base->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.max_dcfclk = 0xFFFF;
+	base->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.min_uclk = min_uclk_mhz;
+	base->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.max_uclk = 0xFFFF;
+	base->bw_params->dummy_pstate_table[0].dram_speed_mts = 1600;
+	base->bw_params->dummy_pstate_table[0].dummy_pstate_latency_us = 38;
+	base->bw_params->dummy_pstate_table[1].dram_speed_mts = 8000;
+	base->bw_params->dummy_pstate_table[1].dummy_pstate_latency_us = 9;
+	base->bw_params->dummy_pstate_table[2].dram_speed_mts = 10000;
+	base->bw_params->dummy_pstate_table[2].dummy_pstate_latency_us = 8;
+	base->bw_params->dummy_pstate_table[3].dram_speed_mts = 16000;
+	base->bw_params->dummy_pstate_table[3].dummy_pstate_latency_us = 5;
+
+	/* Set D - MALL - SR enter and exit times adjusted for MALL */
+	base->bw_params->wm_table.nv_entries[WM_D].valid = true;
+	base->bw_params->wm_table.nv_entries[WM_D].dml_input.pstate_latency_us = pstate_latency_us;
+	base->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_exit_time_us = 2;
+	base->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_enter_plus_exit_time_us = 4;
+	base->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.wm_type = WATERMARKS_MALL;
+	base->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_dcfclk = 0;
+	base->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_dcfclk = 0xFFFF;
+	base->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_uclk = min_uclk_mhz;
+	base->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_uclk = 0xFFFF;
+}
 
+void patch_dcn30_soc_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *dcn3_0_ip)
+{
+	dc_assert_fp_enabled();
+
+	if (dc->ctx->dc_bios->funcs->get_soc_bb_info) {
+		struct bp_soc_bb_info bb_info = {0};
+
+		if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) {
+			if (bb_info.dram_clock_change_latency_100ns > 0)
+				dcn3_0_soc.dram_clock_change_latency_us = bb_info.dram_clock_change_latency_100ns * 10;
+
+			if (bb_info.dram_sr_enter_exit_latency_100ns > 0)
+				dcn3_0_soc.sr_enter_plus_exit_time_us = bb_info.dram_sr_enter_exit_latency_100ns * 10;
+
+			if (bb_info.dram_sr_exit_latency_100ns > 0)
+				dcn3_0_soc.sr_exit_time_us = bb_info.dram_sr_exit_latency_100ns * 10;
+		}
+	}
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.h
index dedfe7b5f1731..595ce88cfa69a 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.h
@@ -63,5 +63,8 @@  void dcn30_fpu_update_bw_bounding_box(struct dc *dc,
 	unsigned int *dcfclk_mhz,
 	unsigned int *dram_speed_mts);
 
+void dcn3_fpu_build_wm_range_table(struct clk_mgr *base);
+
+void patch_dcn30_soc_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *dcn3_0_ip);
 
 #endif /* __DCN30_FPU_H__*/
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c
index 0a7a338649731..e391e4e26d610 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c
@@ -26,6 +26,7 @@ 
 #include "clk_mgr.h"
 #include "dcn20/dcn20_resource.h"
 #include "dcn301/dcn301_resource.h"
+#include "clk_mgr/dcn301/vg_clk_mgr.h"
 
 #include "dml/dcn20/dcn20_fpu.h"
 #include "dcn301_fpu.h"
@@ -214,6 +215,80 @@  struct _vcs_dpi_soc_bounding_box_st dcn3_01_soc = {
 	.urgent_latency_adjustment_fabric_clock_reference_mhz = 0,
 };
 
+struct wm_table ddr4_wm_table = {
+	.entries = {
+		{
+			.wm_inst = WM_A,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.72,
+			.sr_exit_time_us = 6.09,
+			.sr_enter_plus_exit_time_us = 7.14,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_B,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.72,
+			.sr_exit_time_us = 10.12,
+			.sr_enter_plus_exit_time_us = 11.48,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_C,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.72,
+			.sr_exit_time_us = 10.12,
+			.sr_enter_plus_exit_time_us = 11.48,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_D,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.72,
+			.sr_exit_time_us = 10.12,
+			.sr_enter_plus_exit_time_us = 11.48,
+			.valid = true,
+		},
+	}
+};
+
+struct wm_table lpddr5_wm_table = {
+	.entries = {
+		{
+			.wm_inst = WM_A,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.65333,
+			.sr_exit_time_us = 13.5,
+			.sr_enter_plus_exit_time_us = 16.5,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_B,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.65333,
+			.sr_exit_time_us = 13.5,
+			.sr_enter_plus_exit_time_us = 16.5,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_C,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.65333,
+			.sr_exit_time_us = 13.5,
+			.sr_enter_plus_exit_time_us = 16.5,
+			.valid = true,
+		},
+		{
+			.wm_inst = WM_D,
+			.wm_type = WM_TYPE_PSTATE_CHG,
+			.pstate_latency_us = 11.65333,
+			.sr_exit_time_us = 13.5,
+			.sr_enter_plus_exit_time_us = 16.5,
+			.valid = true,
+		},
+	}
+};
+
 static void calculate_wm_set_for_vlevel(int vlevel,
 		struct wm_range_table_entry *table_entry,
 		struct dcn_watermarks *wm_set,
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c
index 54db2eca9e6b7..47e6bc934bad4 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c
@@ -25,6 +25,9 @@ 
 
 #include "resource.h"
 #include "clk_mgr.h"
+#include "dcn31/dcn31_resource.h"
+#include "dcn315/dcn315_resource.h"
+#include "dcn316/dcn316_resource.h"
 
 #include "dml/dcn20/dcn20_fpu.h"
 #include "dcn31_fpu.h"
@@ -114,7 +117,7 @@  struct _vcs_dpi_ip_params_st dcn3_1_ip = {
 	.dcc_supported = true,
 };
 
-struct _vcs_dpi_soc_bounding_box_st dcn3_1_soc = {
+static struct _vcs_dpi_soc_bounding_box_st dcn3_1_soc = {
 		/*TODO: correct dispclk/dppclk voltage level determination*/
 	.clock_limits = {
 		{
@@ -259,7 +262,7 @@  struct _vcs_dpi_ip_params_st dcn3_15_ip = {
 	.dcc_supported = true,
 };
 
-struct _vcs_dpi_soc_bounding_box_st dcn3_15_soc = {
+static struct _vcs_dpi_soc_bounding_box_st dcn3_15_soc = {
 	.sr_exit_time_us = 9.0,
 	.sr_enter_plus_exit_time_us = 11.0,
 	.sr_exit_z8_time_us = 50.0,
@@ -354,7 +357,7 @@  struct _vcs_dpi_ip_params_st dcn3_16_ip = {
 	.dcc_supported = true,
 };
 
-struct _vcs_dpi_soc_bounding_box_st dcn3_16_soc = {
+static struct _vcs_dpi_soc_bounding_box_st dcn3_16_soc = {
 		/*TODO: correct dispclk/dppclk voltage level determination*/
 	.clock_limits = {
 		{
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
index 554d2e33bd7f1..56f34dba3cb2a 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
@@ -298,8 +298,6 @@  struct timing_generator_funcs {
 			int group_idx,
 			uint32_t gsl_ready_signal);
 	void (*set_out_mux)(struct timing_generator *tg, enum otg_out_mux_dest dest);
-	void (*set_vrr_m_const)(struct timing_generator *optc,
-			double vtotal_avg);
 	void (*set_drr_trigger_window)(struct timing_generator *optc,
 			uint32_t window_start, uint32_t window_end);
 	void (*set_vtotal_change_limit)(struct timing_generator *optc,