From bb7c3e9ce2d43a37b699ca379876089e03a756e3 Mon Sep 17 00:00:00 2001 From: Lijo Lazar <lijo.lazar@amd.com> Date: Thu, 3 Mar 2022 09:13:22 +0530 Subject: [PATCH 01/65] drm/amdgpu: Disable baco dummy mode On aldebaran, BACO dummy mode may be enabled during reset. Disable it during resume. Signed-off-by: Lijo Lazar <lijo.lazar@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c index b31df4db01fb3..c2357e83a8c41 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c @@ -362,9 +362,24 @@ const struct nbio_hdp_flush_reg nbio_v7_4_hdp_flush_reg_ald = { static void nbio_v7_4_init_registers(struct amdgpu_device *adev) { + uint32_t baco_cntl; + if (amdgpu_sriov_vf(adev)) adev->rmmio_remap.reg_offset = SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_DEV0_EPF0_VF0_HDP_MEM_COHERENCY_FLUSH_CNTL) << 2; + + if (adev->ip_versions[NBIO_HWIP][0] == IP_VERSION(7, 4, 4) && + !amdgpu_sriov_vf(adev)) { + baco_cntl = RREG32_SOC15(NBIO, 0, mmBACO_CNTL); + if (baco_cntl & + (BACO_CNTL__BACO_DUMMY_EN_MASK | BACO_CNTL__BACO_EN_MASK)) { + baco_cntl &= ~(BACO_CNTL__BACO_DUMMY_EN_MASK | + BACO_CNTL__BACO_EN_MASK); + dev_dbg(adev->dev, "Unsetting baco dummy mode %x", + baco_cntl); + WREG32_SOC15(NBIO, 0, mmBACO_CNTL, baco_cntl); + } + } } static void nbio_v7_4_handle_ras_controller_intr_no_bifring(struct amdgpu_device *adev) From 7c916f95f58df401fef4f8c7549aa80a5739b0dd Mon Sep 17 00:00:00 2001 From: Yifan Zhang <yifan1.zhang@amd.com> Date: Mon, 7 Mar 2022 13:54:21 +0800 Subject: [PATCH 02/65] drm/amdgpu: change registers in error checking for smu 13.0.5 smu 13.0.5 use new registers for smu msg and param. Signed-off-by: Yifan Zhang <yifan1.zhang@amd.com> Reviewed-by: Huang Rui <ray.huang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index 590a6ed12d540..89b22b2610668 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -160,11 +160,17 @@ static void __smu_cmn_reg_print_error(struct smu_context *smu, { struct amdgpu_device *adev = smu->adev; const char *message = smu_get_message_name(smu, msg); + u32 msg_idx, prm; switch (reg_c2pmsg_90) { case SMU_RESP_NONE: { - u32 msg_idx = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66); - u32 prm = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82); + if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 5)) { + msg_idx = RREG32_SOC15(MP1, 0, mmMP1_C2PMSG_2); + prm = RREG32_SOC15(MP1, 0, mmMP1_C2PMSG_34); + } else { + msg_idx = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66); + prm = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82); + } dev_err_ratelimited(adev->dev, "SMU: I'm not done with your previous command: SMN_C2PMSG_66:0x%08X SMN_C2PMSG_82:0x%08X", msg_idx, prm); From 3b8b44a431b76be2645806cfa0494399c3dbbd85 Mon Sep 17 00:00:00 2001 From: Charlene Liu <Charlene.Liu@amd.com> Date: Fri, 11 Feb 2022 20:55:25 -0500 Subject: [PATCH 03/65] drm/amd/display: add debug option to bypass ssinfo from bios for dcn315 [Why & How] Add debug option to bypass ssinfo from BIOS for dcn315. Reviewed-by: Park, Chris <Chris.Park@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Charlene Liu <Charlene.Liu@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../dc/clk_mgr/dcn315/dcn315_clk_mgr.c | 5 +++- .../display/dc/clk_mgr/dcn315/dcn315_smu.c | 24 +++++++++++++++++++ .../display/dc/clk_mgr/dcn315/dcn315_smu.h | 2 ++ .../gpu/drm/amd/display/dc/dce/dce_clk_mgr.c | 2 ++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c index 357f89b4a8e09..48fab0a0c08ba 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c @@ -526,6 +526,7 @@ void dcn315_clk_mgr_construct( struct dccg *dccg) { struct dcn315_smu_dpm_clks smu_dpm_clks = { 0 }; + struct clk_mgr *clk_mgr_base = ctx->dc->clk_mgr; clk_mgr->base.base.ctx = ctx; clk_mgr->base.base.funcs = &dcn315_funcs; @@ -586,8 +587,10 @@ void dcn315_clk_mgr_construct( } clk_mgr->base.base.dprefclk_khz = 600000; - clk_mgr->base.dccg->ref_dtbclk_khz = 600000; + clk_mgr->base.base.dprefclk_khz = dcn315_smu_get_dpref_clk(&clk_mgr->base); + clk_mgr->base.dccg->ref_dtbclk_khz = clk_mgr->base.base.dprefclk_khz; dce_clock_read_ss_info(&clk_mgr->base); + clk_mgr->base.dccg->ref_dtbclk_khz = dce_adjust_dp_ref_freq_for_ss(&clk_mgr->base, clk_mgr->base.base.dprefclk_khz); clk_mgr->base.base.bw_params = &dcn315_bw_params; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_smu.c index 1420eb5097d3b..880ffea2afc6a 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_smu.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_smu.c @@ -312,3 +312,27 @@ void dcn315_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr) VBIOSSMC_MSG_TransferTableDram2Smu, TABLE_WATERMARKS); } +int dcn315_smu_get_dpref_clk(struct clk_mgr_internal *clk_mgr) +{ + int dprefclk_get_mhz = -1; + if (clk_mgr->smu_present) { + dprefclk_get_mhz = dcn315_smu_send_msg_with_param( + clk_mgr, + VBIOSSMC_MSG_GetDprefclkFreq, + 0); + } + return (dprefclk_get_mhz * 1000); +} + +int dcn315_smu_get_smu_fclk(struct clk_mgr_internal *clk_mgr) +{ + int fclk_get_mhz = -1; + + if (clk_mgr->smu_present) { + fclk_get_mhz = dcn315_smu_send_msg_with_param( + clk_mgr, + VBIOSSMC_MSG_GetFclkFrequency, + 0); + } + return (fclk_get_mhz * 1000); +} diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_smu.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_smu.h index 96ec6bfcad22e..66fa42f8dd189 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_smu.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_smu.h @@ -123,4 +123,6 @@ void dcn315_smu_transfer_dpm_table_smu_2_dram(struct clk_mgr_internal *clk_mgr); void dcn315_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr); void dcn315_smu_request_voltage_via_phyclk(struct clk_mgr_internal *clk_mgr, int requested_phyclk_khz); void dcn315_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr); +int dcn315_smu_get_dpref_clk(struct clk_mgr_internal *clk_mgr); +int dcn315_smu_get_smu_fclk(struct clk_mgr_internal *clk_mgr); #endif /* DAL_DC_315_SMU_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c index 1435d7bc1f215..07359eb89efc9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c @@ -450,6 +450,8 @@ void dce_clock_read_ss_info(struct dce_clk_mgr *clk_mgr_dce) clk_mgr_dce->dprefclk_ss_percentage = info.spread_spectrum_percentage; } + if (clk_mgr_dce->base.ctx->dc->debug.ignore_dpref_ss) + clk_mgr_dce->dprefclk_ss_percentage = 0; } } } From df5a07c45c68fd85cd4d1a4ad7892d3a717a4ccf Mon Sep 17 00:00:00 2001 From: Hansen Dsouza <Hansen.Dsouza@amd.com> Date: Fri, 18 Feb 2022 19:53:50 -0500 Subject: [PATCH 04/65] drm/amd/display: fix deep color ratio Fix enum mapping for deep color ratio Reviewed-by: Charlene Liu <Charlene.Liu@amd.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Signed-off-by: Hansen Dsouza <Hansen.Dsouza@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/dce/dce_clock_source.c | 100 ++++++++++++++++++ .../drm/amd/display/dc/dce/dce_clock_source.h | 9 ++ .../drm/amd/display/dc/dcn31/dcn31_resource.c | 2 +- .../amd/display/dc/dcn316/dcn316_resource.c | 2 +- 4 files changed, 111 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 2c7eb982eabca..9285bdeca2702 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -971,6 +971,81 @@ static bool dce112_program_pix_clk( return true; } +#if defined(CONFIG_DRM_AMD_DC_DCN) +static bool dcn31_program_pix_clk( + struct clock_source *clock_source, + struct pixel_clk_params *pix_clk_params, + struct pll_settings *pll_settings) +{ + struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source); + struct bp_pixel_clock_parameters bp_pc_params = {0}; + enum transmitter_color_depth bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_24; + + if (IS_FPGA_MAXIMUS_DC(clock_source->ctx->dce_environment)) { + unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; + unsigned dp_dto_ref_100hz = 7000000; + unsigned clock_100hz = pll_settings->actual_pix_clk_100hz; + + /* Set DTO values: phase = target clock, modulo = reference clock */ + REG_WRITE(PHASE[inst], clock_100hz); + REG_WRITE(MODULO[inst], dp_dto_ref_100hz); + + /* Enable DTO */ + REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 1); + return true; + } + + /*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/ + bp_pc_params.controller_id = pix_clk_params->controller_id; + bp_pc_params.pll_id = clock_source->id; + bp_pc_params.target_pixel_clock_100hz = pll_settings->actual_pix_clk_100hz; + bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id; + bp_pc_params.signal_type = pix_clk_params->signal_type; + + // Make sure we send the correct color depth to DMUB for HDMI + if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) { + switch (pix_clk_params->color_depth) { + case COLOR_DEPTH_888: + bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_24; + break; + case COLOR_DEPTH_101010: + bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_30; + break; + case COLOR_DEPTH_121212: + bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_36; + break; + case COLOR_DEPTH_161616: + bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_48; + break; + default: + bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_24; + break; + } + bp_pc_params.color_depth = bp_pc_colour_depth; + } + + if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { + bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC = + pll_settings->use_external_clk; + bp_pc_params.flags.SET_XTALIN_REF_SRC = + !pll_settings->use_external_clk; + if (pix_clk_params->flags.SUPPORT_YCBCR420) { + bp_pc_params.flags.SUPPORT_YUV_420 = 1; + } + } + if (clk_src->bios->funcs->set_pixel_clock( + clk_src->bios, &bp_pc_params) != BP_RESULT_OK) + return false; + /* Resync deep color DTO */ + if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) + dce112_program_pixel_clk_resync(clk_src, + pix_clk_params->signal_type, + pix_clk_params->color_depth, + pix_clk_params->flags.SUPPORT_YCBCR420); + + return true; +} +#endif static bool dce110_clock_source_power_down( struct clock_source *clk_src) @@ -1205,6 +1280,13 @@ static const struct clock_source_funcs dcn3_clk_src_funcs = { .get_pix_clk_dividers = dcn3_get_pix_clk_dividers, .get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz }; + +static const struct clock_source_funcs dcn31_clk_src_funcs = { + .cs_power_down = dce110_clock_source_power_down, + .program_pix_clk = dcn31_program_pix_clk, + .get_pix_clk_dividers = dcn3_get_pix_clk_dividers, + .get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz +}; #endif /*****************************************/ /* Constructor */ @@ -1609,6 +1691,24 @@ bool dcn3_clk_src_construct( } #endif +#if defined(CONFIG_DRM_AMD_DC_DCN) +bool dcn31_clk_src_construct( + struct dce110_clk_src *clk_src, + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + const struct dce110_clk_src_shift *cs_shift, + const struct dce110_clk_src_mask *cs_mask) +{ + bool ret = dce112_clk_src_construct(clk_src, ctx, bios, id, regs, cs_shift, cs_mask); + + clk_src->base.funcs = &dcn31_clk_src_funcs; + + return ret; +} +#endif + #if defined(CONFIG_DRM_AMD_DC_DCN) bool dcn301_clk_src_construct( struct dce110_clk_src *clk_src, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h index 692fa23ca02b7..069de7649c8c3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h @@ -292,6 +292,15 @@ bool dcn301_clk_src_construct( const struct dce110_clk_src_regs *regs, const struct dce110_clk_src_shift *cs_shift, const struct dce110_clk_src_mask *cs_mask); + +bool dcn31_clk_src_construct( + struct dce110_clk_src *clk_src, + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + const struct dce110_clk_src_shift *cs_shift, + const struct dce110_clk_src_mask *cs_mask); #endif /* this table is use to find *1.001 and /1.001 pixel rates from non-precise pixel rate */ 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 2ecd7bbfa0d4b..3c5efa61dff97 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -2177,7 +2177,7 @@ static struct clock_source *dcn30_clock_source_create( if (!clk_src) return NULL; - if (dcn3_clk_src_construct(clk_src, ctx, bios, id, + if (dcn31_clk_src_construct(clk_src, ctx, bios, id, regs, &cs_shift, &cs_mask)) { clk_src->base.dp_clk_src = dp_clk_src; return &clk_src->base; diff --git a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c index 72d581c6092fd..2e378d9cd00dd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c @@ -1759,7 +1759,7 @@ static struct clock_source *dcn31_clock_source_create( if (!clk_src) return NULL; - if (dcn3_clk_src_construct(clk_src, ctx, bios, id, + if (dcn31_clk_src_construct(clk_src, ctx, bios, id, regs, &cs_shift, &cs_mask)) { clk_src->base.dp_clk_src = dp_clk_src; return &clk_src->base; From 4984e3aae6fa4f42fc24f2745b74509bf2cb0b03 Mon Sep 17 00:00:00 2001 From: "Leung, Martin" <Martin.Leung@amd.com> Date: Sun, 20 Feb 2022 21:44:26 -0500 Subject: [PATCH 05/65] drm/amd/display: cleaning up smu_if to add future flexibility why and how: need to hook in new smu interfaces cleaning up code that used old variables Reviewed-by: Nevenko Stupar <Nevenko.Stupar@amd.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Signed-off-by: Leung, Martin <Martin.Leung@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c | 13 +--- .../dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c | 9 ++- .../dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.h | 67 +---------------- .../dc/clk_mgr/dcn30/dcn30_smu11_driver_if.h | 74 +++++++++++++++++++ .../display/include/grph_object_ctrl_defs.h | 22 ------ 5 files changed, 86 insertions(+), 99 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_smu11_driver_if.h 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 220682e45b8dc..5ed6a93d1708c 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 @@ -25,30 +25,23 @@ #include "dccg.h" #include "clk_mgr_internal.h" - #include "dcn30_clk_mgr_smu_msg.h" #include "dcn20/dcn20_clk_mgr.h" #include "dce100/dce_clk_mgr.h" +#include "dcn30/dcn30_clk_mgr.h" #include "reg_helper.h" #include "core_types.h" #include "dm_helpers.h" - #include "atomfirmware.h" - - #include "sienna_cichlid_ip_offset.h" #include "dcn/dcn_3_0_0_offset.h" #include "dcn/dcn_3_0_0_sh_mask.h" - #include "nbio/nbio_7_4_offset.h" - #include "dpcs/dpcs_3_0_0_offset.h" #include "dpcs/dpcs_3_0_0_sh_mask.h" - #include "mmhub/mmhub_2_0_0_offset.h" #include "mmhub/mmhub_2_0_0_sh_mask.h" -/*we don't have clk folder yet*/ -#include "dcn30/dcn30_clk_mgr.h" +#include "dcn30_smu11_driver_if.h" #undef FN #define FN(reg_name, field_name) \ @@ -83,7 +76,7 @@ static const struct clk_mgr_mask clk_mgr_mask = { /* Query SMU for all clock states for a particular clock */ -static void dcn3_init_single_clock(struct clk_mgr_internal *clk_mgr, PPCLK_e clk, unsigned int *entry_0, unsigned int *num_levels) +static void dcn3_init_single_clock(struct clk_mgr_internal *clk_mgr, uint32_t clk, unsigned int *entry_0, unsigned int *num_levels) { unsigned int i; char *entry_i = (char *)entry_0; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c index 8ecc708bcd9ec..bfc960579760c 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c @@ -29,6 +29,7 @@ #include "clk_mgr_internal.h" #include "reg_helper.h" #include "dalsmc.h" +#include "dcn30_smu11_driver_if.h" #define mmDAL_MSG_REG 0x1628A #define mmDAL_ARG_REG 0x16273 @@ -197,7 +198,7 @@ void dcn30_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr) } /* Returns the actual frequency that was set in MHz, 0 on failure */ -unsigned int dcn30_smu_set_hard_min_by_freq(struct clk_mgr_internal *clk_mgr, PPCLK_e clk, uint16_t freq_mhz) +unsigned int dcn30_smu_set_hard_min_by_freq(struct clk_mgr_internal *clk_mgr, uint32_t clk, uint16_t freq_mhz) { uint32_t response = 0; @@ -215,7 +216,7 @@ unsigned int dcn30_smu_set_hard_min_by_freq(struct clk_mgr_internal *clk_mgr, PP } /* Returns the actual frequency that was set in MHz, 0 on failure */ -unsigned int dcn30_smu_set_hard_max_by_freq(struct clk_mgr_internal *clk_mgr, PPCLK_e clk, uint16_t freq_mhz) +unsigned int dcn30_smu_set_hard_max_by_freq(struct clk_mgr_internal *clk_mgr, uint32_t clk, uint16_t freq_mhz) { uint32_t response = 0; @@ -246,7 +247,7 @@ unsigned int dcn30_smu_set_hard_max_by_freq(struct clk_mgr_internal *clk_mgr, PP * * Returns 0 on failure */ -unsigned int dcn30_smu_get_dpm_freq_by_index(struct clk_mgr_internal *clk_mgr, PPCLK_e clk, uint8_t dpm_level) +unsigned int dcn30_smu_get_dpm_freq_by_index(struct clk_mgr_internal *clk_mgr, uint32_t clk, uint8_t dpm_level) { uint32_t response = 0; @@ -264,7 +265,7 @@ unsigned int dcn30_smu_get_dpm_freq_by_index(struct clk_mgr_internal *clk_mgr, P } /* Returns the max DPM frequency in DC mode in MHz, 0 on failure */ -unsigned int dcn30_smu_get_dc_mode_max_dpm_freq(struct clk_mgr_internal *clk_mgr, PPCLK_e clk) +unsigned int dcn30_smu_get_dc_mode_max_dpm_freq(struct clk_mgr_internal *clk_mgr, uint32_t clk) { uint32_t response = 0; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.h index dd2640a3ce5d1..ca9f5296be94a 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.h @@ -28,65 +28,6 @@ #include "core_types.h" -#define SMU11_DRIVER_IF_VERSION 0x1F - -typedef enum { - PPCLK_GFXCLK = 0, - PPCLK_SOCCLK, - PPCLK_UCLK, - PPCLK_FCLK, - PPCLK_DCLK_0, - PPCLK_VCLK_0, - PPCLK_DCLK_1, - PPCLK_VCLK_1, - PPCLK_DCEFCLK, - PPCLK_DISPCLK, - PPCLK_PIXCLK, - PPCLK_PHYCLK, - PPCLK_DTBCLK, - PPCLK_COUNT, -} PPCLK_e; - -typedef struct { - uint16_t MinClock; // This is either DCEFCLK or SOCCLK (in MHz) - uint16_t MaxClock; // This is either DCEFCLK or SOCCLK (in MHz) - uint16_t MinUclk; - uint16_t MaxUclk; - - uint8_t WmSetting; - uint8_t Flags; - uint8_t Padding[2]; - -} WatermarkRowGeneric_t; - -#define NUM_WM_RANGES 4 - -typedef enum { - WM_SOCCLK = 0, - WM_DCEFCLK, - WM_COUNT, -} WM_CLOCK_e; - -typedef enum { - WATERMARKS_CLOCK_RANGE = 0, - WATERMARKS_DUMMY_PSTATE, - WATERMARKS_MALL, - WATERMARKS_COUNT, -} WATERMARKS_FLAGS_e; - -typedef struct { - // Watermarks - WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES]; -} Watermarks_t; - -typedef struct { - Watermarks_t Watermarks; - - uint32_t MmHubPadding[8]; // SMU internal use -} WatermarksExternal_t; - -#define TABLE_WATERMARKS 1 - struct clk_mgr_internal; bool dcn30_smu_test_message(struct clk_mgr_internal *clk_mgr, uint32_t input); @@ -97,10 +38,10 @@ void dcn30_smu_set_dram_addr_high(struct clk_mgr_internal *clk_mgr, uint void dcn30_smu_set_dram_addr_low(struct clk_mgr_internal *clk_mgr, uint32_t addr_low); void dcn30_smu_transfer_wm_table_smu_2_dram(struct clk_mgr_internal *clk_mgr); void dcn30_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr); -unsigned int dcn30_smu_set_hard_min_by_freq(struct clk_mgr_internal *clk_mgr, PPCLK_e clk, uint16_t freq_mhz); -unsigned int dcn30_smu_set_hard_max_by_freq(struct clk_mgr_internal *clk_mgr, PPCLK_e clk, uint16_t freq_mhz); -unsigned int dcn30_smu_get_dpm_freq_by_index(struct clk_mgr_internal *clk_mgr, PPCLK_e clk, uint8_t dpm_level); -unsigned int dcn30_smu_get_dc_mode_max_dpm_freq(struct clk_mgr_internal *clk_mgr, PPCLK_e clk); +unsigned int dcn30_smu_set_hard_min_by_freq(struct clk_mgr_internal *clk_mgr, uint32_t clk, uint16_t freq_mhz); +unsigned int dcn30_smu_set_hard_max_by_freq(struct clk_mgr_internal *clk_mgr, uint32_t clk, uint16_t freq_mhz); +unsigned int dcn30_smu_get_dpm_freq_by_index(struct clk_mgr_internal *clk_mgr, uint32_t clk, uint8_t dpm_level); +unsigned int dcn30_smu_get_dc_mode_max_dpm_freq(struct clk_mgr_internal *clk_mgr, uint32_t clk); void dcn30_smu_set_min_deep_sleep_dcef_clk(struct clk_mgr_internal *clk_mgr, uint32_t freq_mhz); void dcn30_smu_set_num_of_displays(struct clk_mgr_internal *clk_mgr, uint32_t num_displays); void dcn30_smu_set_display_refresh_from_mall(struct clk_mgr_internal *clk_mgr, bool enable, uint8_t cache_timer_delay, uint8_t cache_timer_scale); diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_smu11_driver_if.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_smu11_driver_if.h new file mode 100644 index 0000000000000..8ea8ee57b39f5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_smu11_driver_if.h @@ -0,0 +1,74 @@ +// This is a stripped-down version of the smu11_driver_if.h file for the relevant DAL interfaces. + +#define SMU11_DRIVER_IF_VERSION 0x40 + +//Only Clks that have DPM descriptors are listed here +typedef enum { + PPCLK_GFXCLK = 0, + PPCLK_SOCCLK, + PPCLK_UCLK, + PPCLK_FCLK, + PPCLK_DCLK_0, + PPCLK_VCLK_0, + PPCLK_DCLK_1, + PPCLK_VCLK_1, + PPCLK_DCEFCLK, + PPCLK_DISPCLK, + PPCLK_PIXCLK, + PPCLK_PHYCLK, + PPCLK_DTBCLK, + PPCLK_COUNT, +} PPCLK_e; + +typedef struct { + uint16_t MinClock; // This is either DCEFCLK or SOCCLK (in MHz) + uint16_t MaxClock; // This is either DCEFCLK or SOCCLK (in MHz) + uint16_t MinUclk; + uint16_t MaxUclk; + + uint8_t WmSetting; + uint8_t Flags; + uint8_t Padding[2]; + +} WatermarkRowGeneric_t; + +#define NUM_WM_RANGES 4 + +typedef enum { + WM_SOCCLK = 0, + WM_DCEFCLK, + WM_COUNT, +} WM_CLOCK_e; + +typedef enum { + WATERMARKS_CLOCK_RANGE = 0, + WATERMARKS_DUMMY_PSTATE, + WATERMARKS_MALL, + WATERMARKS_COUNT, +} WATERMARKS_FLAGS_e; + +typedef struct { + // Watermarks + WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES]; +} Watermarks_t; + +typedef struct { + Watermarks_t Watermarks; + + uint32_t MmHubPadding[8]; // SMU internal use +} WatermarksExternal_t; + +// Table types +#define TABLE_PPTABLE 0 +#define TABLE_WATERMARKS 1 +#define TABLE_AVFS_PSM_DEBUG 2 +#define TABLE_AVFS_FUSE_OVERRIDE 3 +#define TABLE_PMSTATUSLOG 4 +#define TABLE_SMU_METRICS 5 +#define TABLE_DRIVER_SMU_CONFIG 6 +#define TABLE_ACTIVITY_MONITOR_COEFF 7 +#define TABLE_OVERDRIVE 8 +#define TABLE_I2C_COMMANDS 9 +#define TABLE_PACE 10 +#define TABLE_ECCINFO 11 +#define TABLE_COUNT 12 diff --git a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h index dd974c428d23d..bc96d02113608 100644 --- a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h +++ b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h @@ -419,28 +419,6 @@ struct integrated_info { struct edp_info edp2_info; }; -/** -* Power source ids. -*/ -enum power_source { - POWER_SOURCE_AC = 0, - POWER_SOURCE_DC, - POWER_SOURCE_LIMITED_POWER, - POWER_SOURCE_LIMITED_POWER_2, - POWER_SOURCE_MAX -}; - -struct bios_event_info { - uint32_t thermal_state; - uint32_t backlight_level; - enum power_source powerSource; - bool has_thermal_state_changed; - bool has_power_source_changed; - bool has_forced_mode_changed; - bool forced_mode; - bool backlight_changed; -}; - /* * DFS-bypass flag */ From 4189f2938d49d4d6b2e2191c86000c2e04ca7305 Mon Sep 17 00:00:00 2001 From: Charlene Liu <charlene.liu@amd.com> Date: Wed, 23 Feb 2022 00:11:33 -0500 Subject: [PATCH 06/65] drm/amd/display: fix the clock source contruct for dcn315 [why] Driver sends invalid deep color ratio to DMUB. Update it to the right one by using another clock source construct. Reviewed-by: Hansen Dsouza <hansen.dsouza@amd.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Signed-off-by: Charlene Liu <charlene.liu@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c index 9a035e517ca90..d161b81976313 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c @@ -1760,7 +1760,7 @@ static struct clock_source *dcn31_clock_source_create( if (!clk_src) return NULL; - if (dcn3_clk_src_construct(clk_src, ctx, bios, id, + if (dcn31_clk_src_construct(clk_src, ctx, bios, id, regs, &cs_shift, &cs_mask)) { clk_src->base.dp_clk_src = dp_clk_src; return &clk_src->base; From dbede77ce38df760bcdcbc53287e8673fa65982a Mon Sep 17 00:00:00 2001 From: George Shen <george.shen@amd.com> Date: Sun, 20 Feb 2022 15:57:00 -0500 Subject: [PATCH 07/65] drm/amd/display: Clean up fixed VS PHY test w/a function [Why] Unify naming for fixed VS workarounds. [How] Rename function to match naming convention. Refactor code to remove unused function. Reviewed-by: Wenjing Liu <Wenjing.Liu@amd.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Signed-off-by: George Shen <george.shen@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 55 ++----------------- 1 file changed, 5 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 1895252765dc5..6a213467c97ce 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -347,29 +347,6 @@ static void vendor_specific_lttpr_wa_one_start(struct dc_link *link) sizeof(vendor_lttpr_write_data)); } -static void vendor_specific_lttpr_wa_one_end( - struct dc_link *link, - uint8_t retry_count) -{ - const uint8_t vendor_lttpr_write_data[4] = {0x1, 0x50, 0x63, 0x0}; - const uint8_t offset = dp_convert_to_count( - link->dpcd_caps.lttpr_caps.phy_repeater_cnt); - uint32_t vendor_lttpr_write_address = 0xF004F; - - if (!retry_count) { - if (offset != 0xFF) - vendor_lttpr_write_address += - ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1)); - - /* W/A for certain LTTPR to reset their lane settings, part two of two */ - core_link_write_dpcd( - link, - vendor_lttpr_write_address, - &vendor_lttpr_write_data[0], - sizeof(vendor_lttpr_write_data)); - } -} - static void vendor_specific_lttpr_wa_one_two( struct dc_link *link, const uint8_t rate) @@ -396,9 +373,9 @@ static void vendor_specific_lttpr_wa_one_two( } } -static void vendor_specific_lttpr_wa_three( +static void dp_fixed_vs_pe_read_lane_adjust( struct dc_link *link, - union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX]) + union dpcd_training_lane dpcd_lane_adjust[LANE_COUNT_DP_MAX]) { const uint8_t vendor_lttpr_write_data_vs[3] = {0x0, 0x53, 0x63}; const uint8_t vendor_lttpr_write_data_pe[3] = {0x0, 0x54, 0x63}; @@ -440,23 +417,8 @@ static void vendor_specific_lttpr_wa_three( 1); for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) { - dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_LANE = (dprx_vs >> (2 * lane)) & 0x3; - dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_LANE = (dprx_pe >> (2 * lane)) & 0x3; - } -} - -static void vendor_specific_lttpr_wa_three_dpcd( - struct dc_link *link, - union dpcd_training_lane dpcd_lane_adjust[LANE_COUNT_DP_MAX]) -{ - union lane_adjust lane_adjust[LANE_COUNT_DP_MAX]; - uint8_t lane = 0; - - vendor_specific_lttpr_wa_three(link, lane_adjust); - - for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) { - dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_SET = lane_adjust[lane].bits.VOLTAGE_SWING_LANE; - dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_SET = lane_adjust[lane].bits.PRE_EMPHASIS_LANE; + dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_SET = (dprx_vs >> (2 * lane)) & 0x3; + dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_SET = (dprx_pe >> (2 * lane)) & 0x3; } } @@ -1463,13 +1425,6 @@ static enum link_training_result perform_clock_recovery_sequence( dpcd_lane_adjust, offset); - if (link->dc->debug.apply_vendor_specific_lttpr_wa && - (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && - link->lttpr_mode == LTTPR_MODE_TRANSPARENT) { - vendor_specific_lttpr_wa_one_end(link, retry_count); - vendor_specific_lttpr_wa_three(link, dpcd_lane_adjust); - } - /* 5. check CR done*/ if (dp_is_cr_done(lane_count, dpcd_lane_status)) return LINK_TRAINING_SUCCESS; @@ -4136,7 +4091,7 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) if (link->dc->debug.apply_vendor_specific_lttpr_wa && (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && link->lttpr_mode == LTTPR_MODE_TRANSPARENT) - vendor_specific_lttpr_wa_three_dpcd( + dp_fixed_vs_pe_read_lane_adjust( link, link_training_settings.dpcd_lane_settings); From 3741584519dcb780c38df502dd5e4cf7cea4d9f2 Mon Sep 17 00:00:00 2001 From: Dillon Varone <dillon.varone@amd.com> Date: Thu, 17 Feb 2022 15:33:03 -0500 Subject: [PATCH 08/65] drm/amd/display: Add minimal pipe split transition state [WHY?] When adding/removng a plane to some configurations, unsupported pipe programming can occur when moving to a new plane. [HOW?] Add a safe transistion state before programming new configuration. Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Signed-off-by: Dillon Varone <dillon.varone@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 61e3bb99375fa..01b5996fa3aab 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1082,7 +1082,8 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context) break; } } - if (!should_disable && pipe_split_change) + if (!should_disable && pipe_split_change && + dc->current_state->stream_count != context->stream_count) should_disable = true; if (should_disable && old_stream) { @@ -1690,6 +1691,7 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c struct pipe_ctx *pipe; int i, k, l; struct dc_stream_state *dc_streams[MAX_STREAMS] = {0}; + struct dc_state *old_state; #if defined(CONFIG_DRM_AMD_DC_DCN) dc_z10_restore(dc); @@ -1808,10 +1810,11 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c for (i = 0; i < context->stream_count; i++) context->streams[i]->mode_changed = false; - dc_release_state(dc->current_state); - + old_state = dc->current_state; dc->current_state = context; + dc_release_state(old_state); + dc_retain_state(dc->current_state); return result; From d8ff38d8fcd0a7bb66d17ec689135239aca78532 Mon Sep 17 00:00:00 2001 From: Wyatt Wood <wyatt.wood@amd.com> Date: Wed, 23 Feb 2022 11:22:30 -0500 Subject: [PATCH 09/65] drm/amd/display: Release AUX engine after failed acquire [Why] There is a sequence in which aux arbitration doesn't work correctly. Driver is left with aux access after it times out waiting for access. In future dmub fw is never granted aux access and is stuck in a while loop. [How] Cancel aux request from driver after timing out. Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Signed-off-by: Wyatt Wood <wyatt.wood@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dce/dce_aux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c index 74b05b3aef087..b8d6f42024130 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c @@ -413,7 +413,7 @@ static bool acquire( return false; if (!acquire_engine(engine)) { - dal_ddc_close(ddc); + release_engine(engine); return false; } From 53923e62afad6f52b2b931a74d2ee10274051b28 Mon Sep 17 00:00:00 2001 From: Jasdeep Dhillon <jasdeep.dhillon@amd.com> Date: Thu, 24 Feb 2022 10:56:07 -0500 Subject: [PATCH 10/65] drm/amd/display: move FPU associated DCN303 code to DML folder [Why & How] As part of the FPU isolation work documented in https://patchwork.freedesktop.org/series/93042/, isolate code that uses FPU in DCN303 to DML, where all FPU code should locate. Co-authored-by: Jasdeep Dhillon <jasdeep.dhillon@amd.com> Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Signed-off-by: Jasdeep Dhillon <jasdeep.dhillon@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/dcn303/Makefile | 26 -- .../amd/display/dc/dcn303/dcn303_resource.c | 327 +--------------- .../amd/display/dc/dcn303/dcn303_resource.h | 3 + drivers/gpu/drm/amd/display/dc/dml/Makefile | 2 + .../amd/display/dc/dml/dcn303/dcn303_fpu.c | 362 ++++++++++++++++++ .../amd/display/dc/dml/dcn303/dcn303_fpu.h | 32 ++ 6 files changed, 409 insertions(+), 343 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dcn303/dcn303_fpu.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dcn303/dcn303_fpu.h diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/Makefile b/drivers/gpu/drm/amd/display/dc/dcn303/Makefile index 6f7a1f2b49f03..8702e0b7fda3b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn303/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn303/Makefile @@ -8,32 +8,6 @@ DCN3_03 = dcn303_init.o dcn303_hwseq.o dcn303_resource.o -ifdef CONFIG_X86 -CFLAGS_$(AMDDALPATH)/dc/dcn303/dcn303_resource.o := -msse -endif - -ifdef CONFIG_PPC64 -CFLAGS_$(AMDDALPATH)/dc/dcn303/dcn303_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/dcn303/dcn303_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/dcn303/dcn303_resource.o += -mpreferred-stack-boundary=4 -else -CFLAGS_$(AMDDALPATH)/dc/dcn303/dcn303_resource.o += -msse2 -endif -endif - AMD_DAL_DCN3_03 = $(addprefix $(AMDDALPATH)/dc/dcn303/,$(DCN3_03)) AMD_DISPLAY_FILES += $(AMD_DAL_DCN3_03) diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c index 36649716e9919..4fcbc05028087 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c @@ -52,140 +52,10 @@ #include "dpcs/dpcs_3_0_3_sh_mask.h" #include "nbio/nbio_2_3_offset.h" -#define DC_LOGGER_INIT(logger) +#include "dml/dcn303/dcn303_fpu.h" -struct _vcs_dpi_ip_params_st dcn3_03_ip = { - .use_min_dcfclk = 0, - .clamp_min_dcfclk = 0, - .odm_capable = 1, - .gpuvm_enable = 1, - .hostvm_enable = 0, - .gpuvm_max_page_table_levels = 4, - .hostvm_max_page_table_levels = 4, - .hostvm_cached_page_table_levels = 0, - .pte_group_size_bytes = 2048, - .num_dsc = 2, - .rob_buffer_size_kbytes = 184, - .det_buffer_size_kbytes = 184, - .dpte_buffer_size_in_pte_reqs_luma = 64, - .dpte_buffer_size_in_pte_reqs_chroma = 34, - .pde_proc_buffer_size_64k_reqs = 48, - .dpp_output_buffer_pixels = 2560, - .opp_output_buffer_lines = 1, - .pixel_chunk_size_kbytes = 8, - .pte_enable = 1, - .max_page_table_levels = 2, - .pte_chunk_size_kbytes = 2, // ? - .meta_chunk_size_kbytes = 2, - .writeback_chunk_size_kbytes = 8, - .line_buffer_size_bits = 789504, - .is_line_buffer_bpp_fixed = 0, // ? - .line_buffer_fixed_bpp = 0, // ? - .dcc_supported = true, - .writeback_interface_buffer_size_kbytes = 90, - .writeback_line_buffer_buffer_size = 0, - .max_line_buffer_lines = 12, - .writeback_luma_buffer_size_kbytes = 12, // writeback_line_buffer_buffer_size = 656640 - .writeback_chroma_buffer_size_kbytes = 8, - .writeback_chroma_line_buffer_width_pixels = 4, - .writeback_max_hscl_ratio = 1, - .writeback_max_vscl_ratio = 1, - .writeback_min_hscl_ratio = 1, - .writeback_min_vscl_ratio = 1, - .writeback_max_hscl_taps = 1, - .writeback_max_vscl_taps = 1, - .writeback_line_buffer_luma_buffer_size = 0, - .writeback_line_buffer_chroma_buffer_size = 14643, - .cursor_buffer_size = 8, - .cursor_chunk_size = 2, - .max_num_otg = 2, - .max_num_dpp = 2, - .max_num_wb = 1, - .max_dchub_pscl_bw_pix_per_clk = 4, - .max_pscl_lb_bw_pix_per_clk = 2, - .max_lb_vscl_bw_pix_per_clk = 4, - .max_vscl_hscl_bw_pix_per_clk = 4, - .max_hscl_ratio = 6, - .max_vscl_ratio = 6, - .hscl_mults = 4, - .vscl_mults = 4, - .max_hscl_taps = 8, - .max_vscl_taps = 8, - .dispclk_ramp_margin_percent = 1, - .underscan_factor = 1.11, - .min_vblank_lines = 32, - .dppclk_delay_subtotal = 46, - .dynamic_metadata_vm_enabled = true, - .dppclk_delay_scl_lb_only = 16, - .dppclk_delay_scl = 50, - .dppclk_delay_cnvc_formatter = 27, - .dppclk_delay_cnvc_cursor = 6, - .dispclk_delay_subtotal = 119, - .dcfclk_cstate_latency = 5.2, // SRExitTime - .max_inter_dcn_tile_repeaters = 8, - .max_num_hdmi_frl_outputs = 1, - .odm_combine_4to1_supported = false, - .xfc_supported = false, - .xfc_fill_bw_overhead_percent = 10.0, - .xfc_fill_constant_bytes = 0, - .gfx7_compat_tiling_supported = 0, - .number_of_cursors = 1, -}; - -struct _vcs_dpi_soc_bounding_box_st dcn3_03_soc = { - .clock_limits = { - { - .state = 0, - .dispclk_mhz = 1217.0, - .dppclk_mhz = 1217.0, - .phyclk_mhz = 810.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 405.6, - }, - }, +#define DC_LOGGER_INIT(logger) - .min_dcfclk = 500.0, /* TODO: set this to actual min DCFCLK */ - .num_states = 1, - .sr_exit_time_us = 35.5, - .sr_enter_plus_exit_time_us = 40, - .urgent_latency_us = 4.0, - .urgent_latency_pixel_data_only_us = 4.0, - .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, - .urgent_latency_vm_data_only_us = 4.0, - .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, - .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, - .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, - .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 80.0, - .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 60.0, - .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0, - .max_avg_sdp_bw_use_normal_percent = 60.0, - .max_avg_dram_bw_use_normal_percent = 40.0, - .writeback_latency_us = 12.0, - .max_request_size_bytes = 256, - .fabric_datapath_to_dcn_data_return_bytes = 64, - .dcn_downspread_percent = 0.5, - .downspread_percent = 0.38, - .dram_page_open_time_ns = 50.0, - .dram_rw_turnaround_time_ns = 17.5, - .dram_return_buffer_per_channel_bytes = 8192, - .round_trip_ping_latency_dcfclk_cycles = 156, - .urgent_out_of_order_return_per_channel_bytes = 4096, - .channel_interleave_bytes = 256, - .num_banks = 8, - .gpuvm_min_page_size_bytes = 4096, - .hostvm_min_page_size_bytes = 4096, - .dram_clock_change_latency_us = 404, - .dummy_pstate_latency_us = 5, - .writeback_dram_clock_change_latency_us = 23.0, - .return_bus_width_bytes = 64, - .dispclk_dppclk_vco_speed_mhz = 3650, - .xfc_bus_transport_time_us = 20, // ? - .xfc_xbuf_latency_tolerance_us = 4, // ? - .use_urgent_burst_bw = 1, // ? - .do_urgent_latency_adjustment = true, - .urgent_latency_adjustment_fabric_clock_component_us = 1.0, - .urgent_latency_adjustment_fabric_clock_reference_mhz = 1000, -}; static const struct dc_debug_options debug_defaults_drv = { .disable_dmcu = true, @@ -1031,24 +901,18 @@ static bool init_soc_bounding_box(struct dc *dc, struct resource_pool *pool) loaded_ip->max_num_otg = pool->pipe_count; loaded_ip->max_num_dpp = pool->pipe_count; loaded_ip->clamp_min_dcfclk = dc->config.clamp_min_dcfclk; + DC_FP_START(); dcn20_patch_bounding_box(dc, loaded_bb); + 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_03_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_03_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_03_soc.sr_exit_time_us = - bb_info.dram_sr_exit_latency_100ns * 10; + DC_FP_START(); + dcn303_fpu_init_soc_bounding_box(bb_info); + DC_FP_END(); } } @@ -1186,183 +1050,12 @@ static void dcn303_destroy_resource_pool(struct resource_pool **pool) *pool = NULL; } -static void dcn303_get_optimal_dcfclk_fclk_for_uclk(unsigned int uclk_mts, - unsigned int *optimal_dcfclk, - unsigned int *optimal_fclk) -{ - double bw_from_dram, bw_from_dram1, bw_from_dram2; - - bw_from_dram1 = uclk_mts * dcn3_03_soc.num_chans * - dcn3_03_soc.dram_channel_width_bytes * (dcn3_03_soc.max_avg_dram_bw_use_normal_percent / 100); - bw_from_dram2 = uclk_mts * dcn3_03_soc.num_chans * - dcn3_03_soc.dram_channel_width_bytes * (dcn3_03_soc.max_avg_sdp_bw_use_normal_percent / 100); - - bw_from_dram = (bw_from_dram1 < bw_from_dram2) ? bw_from_dram1 : bw_from_dram2; - - if (optimal_fclk) - *optimal_fclk = bw_from_dram / - (dcn3_03_soc.fabric_datapath_to_dcn_data_return_bytes * - (dcn3_03_soc.max_avg_sdp_bw_use_normal_percent / 100)); - - if (optimal_dcfclk) - *optimal_dcfclk = bw_from_dram / - (dcn3_03_soc.return_bus_width_bytes * (dcn3_03_soc.max_avg_sdp_bw_use_normal_percent / 100)); -} void dcn303_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) { - unsigned int i, j; - unsigned int num_states = 0; - - unsigned int dcfclk_mhz[DC__VOLTAGE_STATES] = {0}; - unsigned int dram_speed_mts[DC__VOLTAGE_STATES] = {0}; - unsigned int optimal_uclk_for_dcfclk_sta_targets[DC__VOLTAGE_STATES] = {0}; - unsigned int optimal_dcfclk_for_uclk[DC__VOLTAGE_STATES] = {0}; - - unsigned int dcfclk_sta_targets[DC__VOLTAGE_STATES] = {694, 875, 1000, 1200}; - unsigned int num_dcfclk_sta_targets = 4; - unsigned int num_uclk_states; - - - if (dc->ctx->dc_bios->vram_info.num_chans) - dcn3_03_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans; - - if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes) - dcn3_03_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes; - - dcn3_03_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; - dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; - - if (bw_params->clk_table.entries[0].memclk_mhz) { - int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0, max_phyclk_mhz = 0; - - for (i = 0; i < MAX_NUM_DPM_LVL; i++) { - if (bw_params->clk_table.entries[i].dcfclk_mhz > max_dcfclk_mhz) - max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz; - if (bw_params->clk_table.entries[i].dispclk_mhz > max_dispclk_mhz) - max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz; - if (bw_params->clk_table.entries[i].dppclk_mhz > max_dppclk_mhz) - max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz; - if (bw_params->clk_table.entries[i].phyclk_mhz > max_phyclk_mhz) - max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz; - } - if (!max_dcfclk_mhz) - max_dcfclk_mhz = dcn3_03_soc.clock_limits[0].dcfclk_mhz; - if (!max_dispclk_mhz) - max_dispclk_mhz = dcn3_03_soc.clock_limits[0].dispclk_mhz; - if (!max_dppclk_mhz) - max_dppclk_mhz = dcn3_03_soc.clock_limits[0].dppclk_mhz; - if (!max_phyclk_mhz) - max_phyclk_mhz = dcn3_03_soc.clock_limits[0].phyclk_mhz; - - if (max_dcfclk_mhz > dcfclk_sta_targets[num_dcfclk_sta_targets-1]) { - dcfclk_sta_targets[num_dcfclk_sta_targets] = max_dcfclk_mhz; - num_dcfclk_sta_targets++; - } else if (max_dcfclk_mhz < dcfclk_sta_targets[num_dcfclk_sta_targets-1]) { - for (i = 0; i < num_dcfclk_sta_targets; i++) { - if (dcfclk_sta_targets[i] > max_dcfclk_mhz) { - dcfclk_sta_targets[i] = max_dcfclk_mhz; - break; - } - } - /* Update size of array since we "removed" duplicates */ - num_dcfclk_sta_targets = i + 1; - } - - num_uclk_states = bw_params->clk_table.num_entries; - - /* Calculate optimal dcfclk for each uclk */ - for (i = 0; i < num_uclk_states; i++) { - dcn303_get_optimal_dcfclk_fclk_for_uclk(bw_params->clk_table.entries[i].memclk_mhz * 16, - &optimal_dcfclk_for_uclk[i], NULL); - if (optimal_dcfclk_for_uclk[i] < bw_params->clk_table.entries[0].dcfclk_mhz) - optimal_dcfclk_for_uclk[i] = bw_params->clk_table.entries[0].dcfclk_mhz; - } - - /* Calculate optimal uclk for each dcfclk sta target */ - for (i = 0; i < num_dcfclk_sta_targets; i++) { - for (j = 0; j < num_uclk_states; j++) { - if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j]) { - optimal_uclk_for_dcfclk_sta_targets[i] = - bw_params->clk_table.entries[j].memclk_mhz * 16; - break; - } - } - } - - i = 0; - j = 0; - /* create the final dcfclk and uclk table */ - while (i < num_dcfclk_sta_targets && j < num_uclk_states && num_states < DC__VOLTAGE_STATES) { - if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j] && i < num_dcfclk_sta_targets) { - dcfclk_mhz[num_states] = dcfclk_sta_targets[i]; - dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++]; - } else { - if (j < num_uclk_states && optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) { - dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j]; - dram_speed_mts[num_states++] = - bw_params->clk_table.entries[j++].memclk_mhz * 16; - } else { - j = num_uclk_states; - } - } - } - - while (i < num_dcfclk_sta_targets && num_states < DC__VOLTAGE_STATES) { - dcfclk_mhz[num_states] = dcfclk_sta_targets[i]; - dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++]; - } - - while (j < num_uclk_states && num_states < DC__VOLTAGE_STATES && - optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) { - dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j]; - dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16; - } - - dcn3_03_soc.num_states = num_states; - for (i = 0; i < dcn3_03_soc.num_states; i++) { - dcn3_03_soc.clock_limits[i].state = i; - dcn3_03_soc.clock_limits[i].dcfclk_mhz = dcfclk_mhz[i]; - dcn3_03_soc.clock_limits[i].fabricclk_mhz = dcfclk_mhz[i]; - dcn3_03_soc.clock_limits[i].dram_speed_mts = dram_speed_mts[i]; - - /* Fill all states with max values of all other clocks */ - dcn3_03_soc.clock_limits[i].dispclk_mhz = max_dispclk_mhz; - dcn3_03_soc.clock_limits[i].dppclk_mhz = max_dppclk_mhz; - dcn3_03_soc.clock_limits[i].phyclk_mhz = max_phyclk_mhz; - /* Populate from bw_params for DTBCLK, SOCCLK */ - if (!bw_params->clk_table.entries[i].dtbclk_mhz && i > 0) - dcn3_03_soc.clock_limits[i].dtbclk_mhz = dcn3_03_soc.clock_limits[i-1].dtbclk_mhz; - else - dcn3_03_soc.clock_limits[i].dtbclk_mhz = bw_params->clk_table.entries[i].dtbclk_mhz; - if (!bw_params->clk_table.entries[i].socclk_mhz && i > 0) - dcn3_03_soc.clock_limits[i].socclk_mhz = dcn3_03_soc.clock_limits[i-1].socclk_mhz; - else - dcn3_03_soc.clock_limits[i].socclk_mhz = bw_params->clk_table.entries[i].socclk_mhz; - /* These clocks cannot come from bw_params, always fill from dcn3_03_soc[1] */ - /* FCLK, PHYCLK_D18, DSCCLK */ - dcn3_03_soc.clock_limits[i].phyclk_d18_mhz = dcn3_03_soc.clock_limits[0].phyclk_d18_mhz; - dcn3_03_soc.clock_limits[i].dscclk_mhz = dcn3_03_soc.clock_limits[0].dscclk_mhz; - } - - // WA: patch strobe modes to compensate for DCN303 BW issue - if (dcn3_03_soc.num_chans <= 4) { - for (i = 0; i < dcn3_03_soc.num_states; i++) { - if (dcn3_03_soc.clock_limits[i].dram_speed_mts > 1700) - break; - - if (dcn3_03_soc.clock_limits[i].dram_speed_mts >= 1500) { - dcn3_03_soc.clock_limits[i].dcfclk_mhz = 100; - dcn3_03_soc.clock_limits[i].fabricclk_mhz = 100; - } - } - } - - /* re-init DML with updated bb */ - dml_init_instance(&dc->dml, &dcn3_03_soc, &dcn3_03_ip, DML_PROJECT_DCN30); - if (dc->current_state) - dml_init_instance(&dc->current_state->bw_ctx.dml, &dcn3_03_soc, &dcn3_03_ip, DML_PROJECT_DCN30); - } + DC_FP_START(); + dcn303_fpu_update_bw_bounding_box(dc, bw_params); + DC_FP_END(); } static struct resource_funcs dcn303_res_pool_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.h b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.h index 5b590c169763a..9c7d795409006 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.h @@ -10,6 +10,9 @@ #include "core_types.h" +extern struct _vcs_dpi_ip_params_st dcn3_03_ip; +extern struct _vcs_dpi_soc_bounding_box_st dcn3_03_soc; + struct resource_pool *dcn303_create_resource_pool(const struct dc_init_data *init_data, struct dc *dc); void dcn303_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index b16c492593e23..6ab83c3e9c5cd 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -72,6 +72,7 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_ccflags) $(fram CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn301/dcn301_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn302/dcn302_fpu.o := $(dml_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml/dcn303/dcn303_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dsc/rc_calc_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/calcs/dcn_calcs.o := $(dml_ccflags) @@ -113,6 +114,7 @@ DML += dcn30/display_mode_vba_30.o dcn30/display_rq_dlg_calc_30.o DML += dcn31/display_mode_vba_31.o dcn31/display_rq_dlg_calc_31.o DML += dcn301/dcn301_fpu.o DML += dcn302/dcn302_fpu.o +DML += dcn303/dcn303_fpu.o DML += dsc/rc_calc_fpu.o DML += calcs/dcn_calcs.o calcs/dcn_calc_math.o calcs/dcn_calc_auto.o endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn303/dcn303_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn303/dcn303_fpu.c new file mode 100644 index 0000000000000..8fb14baed208b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn303/dcn303_fpu.c @@ -0,0 +1,362 @@ +/* + * Copyright 2019-2021 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 "resource.h" +#include "clk_mgr.h" +#include "dcn20/dcn20_resource.h" +#include "dcn303/dcn303_resource.h" + +#include "dml/dcn20/dcn20_fpu.h" +#include "dcn303_fpu.h" + +struct _vcs_dpi_ip_params_st dcn3_03_ip = { + .use_min_dcfclk = 0, + .clamp_min_dcfclk = 0, + .odm_capable = 1, + .gpuvm_enable = 1, + .hostvm_enable = 0, + .gpuvm_max_page_table_levels = 4, + .hostvm_max_page_table_levels = 4, + .hostvm_cached_page_table_levels = 0, + .pte_group_size_bytes = 2048, + .num_dsc = 2, + .rob_buffer_size_kbytes = 184, + .det_buffer_size_kbytes = 184, + .dpte_buffer_size_in_pte_reqs_luma = 64, + .dpte_buffer_size_in_pte_reqs_chroma = 34, + .pde_proc_buffer_size_64k_reqs = 48, + .dpp_output_buffer_pixels = 2560, + .opp_output_buffer_lines = 1, + .pixel_chunk_size_kbytes = 8, + .pte_enable = 1, + .max_page_table_levels = 2, + .pte_chunk_size_kbytes = 2, // ? + .meta_chunk_size_kbytes = 2, + .writeback_chunk_size_kbytes = 8, + .line_buffer_size_bits = 789504, + .is_line_buffer_bpp_fixed = 0, // ? + .line_buffer_fixed_bpp = 0, // ? + .dcc_supported = true, + .writeback_interface_buffer_size_kbytes = 90, + .writeback_line_buffer_buffer_size = 0, + .max_line_buffer_lines = 12, + .writeback_luma_buffer_size_kbytes = 12, // writeback_line_buffer_buffer_size = 656640 + .writeback_chroma_buffer_size_kbytes = 8, + .writeback_chroma_line_buffer_width_pixels = 4, + .writeback_max_hscl_ratio = 1, + .writeback_max_vscl_ratio = 1, + .writeback_min_hscl_ratio = 1, + .writeback_min_vscl_ratio = 1, + .writeback_max_hscl_taps = 1, + .writeback_max_vscl_taps = 1, + .writeback_line_buffer_luma_buffer_size = 0, + .writeback_line_buffer_chroma_buffer_size = 14643, + .cursor_buffer_size = 8, + .cursor_chunk_size = 2, + .max_num_otg = 2, + .max_num_dpp = 2, + .max_num_wb = 1, + .max_dchub_pscl_bw_pix_per_clk = 4, + .max_pscl_lb_bw_pix_per_clk = 2, + .max_lb_vscl_bw_pix_per_clk = 4, + .max_vscl_hscl_bw_pix_per_clk = 4, + .max_hscl_ratio = 6, + .max_vscl_ratio = 6, + .hscl_mults = 4, + .vscl_mults = 4, + .max_hscl_taps = 8, + .max_vscl_taps = 8, + .dispclk_ramp_margin_percent = 1, + .underscan_factor = 1.11, + .min_vblank_lines = 32, + .dppclk_delay_subtotal = 46, + .dynamic_metadata_vm_enabled = true, + .dppclk_delay_scl_lb_only = 16, + .dppclk_delay_scl = 50, + .dppclk_delay_cnvc_formatter = 27, + .dppclk_delay_cnvc_cursor = 6, + .dispclk_delay_subtotal = 119, + .dcfclk_cstate_latency = 5.2, // SRExitTime + .max_inter_dcn_tile_repeaters = 8, + .max_num_hdmi_frl_outputs = 1, + .odm_combine_4to1_supported = false, + + .xfc_supported = false, + .xfc_fill_bw_overhead_percent = 10.0, + .xfc_fill_constant_bytes = 0, + .gfx7_compat_tiling_supported = 0, + .number_of_cursors = 1, +}; + +struct _vcs_dpi_soc_bounding_box_st dcn3_03_soc = { + .clock_limits = { + { + .state = 0, + .dispclk_mhz = 562.0, + .dppclk_mhz = 300.0, + .phyclk_mhz = 300.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 405.6, + }, + }, + + .min_dcfclk = 500.0, /* TODO: set this to actual min DCFCLK */ + .num_states = 1, + .sr_exit_time_us = 35.5, + .sr_enter_plus_exit_time_us = 40, + .urgent_latency_us = 4.0, + .urgent_latency_pixel_data_only_us = 4.0, + .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, + .urgent_latency_vm_data_only_us = 4.0, + .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, + .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, + .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 80.0, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 60.0, + .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0, + .max_avg_sdp_bw_use_normal_percent = 60.0, + .max_avg_dram_bw_use_normal_percent = 40.0, + .writeback_latency_us = 12.0, + .max_request_size_bytes = 256, + .fabric_datapath_to_dcn_data_return_bytes = 64, + .dcn_downspread_percent = 0.5, + .downspread_percent = 0.38, + .dram_page_open_time_ns = 50.0, + .dram_rw_turnaround_time_ns = 17.5, + .dram_return_buffer_per_channel_bytes = 8192, + .round_trip_ping_latency_dcfclk_cycles = 156, + .urgent_out_of_order_return_per_channel_bytes = 4096, + .channel_interleave_bytes = 256, + .num_banks = 8, + .gpuvm_min_page_size_bytes = 4096, + .hostvm_min_page_size_bytes = 4096, + .dram_clock_change_latency_us = 404, + .dummy_pstate_latency_us = 5, + .writeback_dram_clock_change_latency_us = 23.0, + .return_bus_width_bytes = 64, + .dispclk_dppclk_vco_speed_mhz = 3650, + .xfc_bus_transport_time_us = 20, // ? + .xfc_xbuf_latency_tolerance_us = 4, // ? + .use_urgent_burst_bw = 1, // ? + .do_urgent_latency_adjustment = true, + .urgent_latency_adjustment_fabric_clock_component_us = 1.0, + .urgent_latency_adjustment_fabric_clock_reference_mhz = 1000, +}; + +static void dcn303_get_optimal_dcfclk_fclk_for_uclk(unsigned int uclk_mts, + unsigned int *optimal_dcfclk, + unsigned int *optimal_fclk) +{ + double bw_from_dram, bw_from_dram1, bw_from_dram2; + + bw_from_dram1 = uclk_mts * dcn3_03_soc.num_chans * + dcn3_03_soc.dram_channel_width_bytes * (dcn3_03_soc.max_avg_dram_bw_use_normal_percent / 100); + bw_from_dram2 = uclk_mts * dcn3_03_soc.num_chans * + dcn3_03_soc.dram_channel_width_bytes * (dcn3_03_soc.max_avg_sdp_bw_use_normal_percent / 100); + + bw_from_dram = (bw_from_dram1 < bw_from_dram2) ? bw_from_dram1 : bw_from_dram2; + + if (optimal_fclk) + *optimal_fclk = bw_from_dram / + (dcn3_03_soc.fabric_datapath_to_dcn_data_return_bytes * + (dcn3_03_soc.max_avg_sdp_bw_use_normal_percent / 100)); + + if (optimal_dcfclk) + *optimal_dcfclk = bw_from_dram / + (dcn3_03_soc.return_bus_width_bytes * (dcn3_03_soc.max_avg_sdp_bw_use_normal_percent / 100)); +} + + +void dcn303_fpu_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +{ + unsigned int i, j; + unsigned int num_states = 0; + + unsigned int dcfclk_mhz[DC__VOLTAGE_STATES] = {0}; + unsigned int dram_speed_mts[DC__VOLTAGE_STATES] = {0}; + unsigned int optimal_uclk_for_dcfclk_sta_targets[DC__VOLTAGE_STATES] = {0}; + unsigned int optimal_dcfclk_for_uclk[DC__VOLTAGE_STATES] = {0}; + + unsigned int dcfclk_sta_targets[DC__VOLTAGE_STATES] = {694, 875, 1000, 1200}; + unsigned int num_dcfclk_sta_targets = 4; + unsigned int num_uclk_states; + + dc_assert_fp_enabled(); + + if (dc->ctx->dc_bios->vram_info.num_chans) + dcn3_03_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans; + + if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes) + dcn3_03_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes; + + dcn3_03_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; + dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; + + if (bw_params->clk_table.entries[0].memclk_mhz) { + int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0, max_phyclk_mhz = 0; + + for (i = 0; i < MAX_NUM_DPM_LVL; i++) { + if (bw_params->clk_table.entries[i].dcfclk_mhz > max_dcfclk_mhz) + max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz; + if (bw_params->clk_table.entries[i].dispclk_mhz > max_dispclk_mhz) + max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz; + if (bw_params->clk_table.entries[i].dppclk_mhz > max_dppclk_mhz) + max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz; + if (bw_params->clk_table.entries[i].phyclk_mhz > max_phyclk_mhz) + max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz; + } + if (!max_dcfclk_mhz) + max_dcfclk_mhz = dcn3_03_soc.clock_limits[0].dcfclk_mhz; + if (!max_dispclk_mhz) + max_dispclk_mhz = dcn3_03_soc.clock_limits[0].dispclk_mhz; + if (!max_dppclk_mhz) + max_dppclk_mhz = dcn3_03_soc.clock_limits[0].dppclk_mhz; + if (!max_phyclk_mhz) + max_phyclk_mhz = dcn3_03_soc.clock_limits[0].phyclk_mhz; + + if (max_dcfclk_mhz > dcfclk_sta_targets[num_dcfclk_sta_targets-1]) { + dcfclk_sta_targets[num_dcfclk_sta_targets] = max_dcfclk_mhz; + num_dcfclk_sta_targets++; + } else if (max_dcfclk_mhz < dcfclk_sta_targets[num_dcfclk_sta_targets-1]) { + for (i = 0; i < num_dcfclk_sta_targets; i++) { + if (dcfclk_sta_targets[i] > max_dcfclk_mhz) { + dcfclk_sta_targets[i] = max_dcfclk_mhz; + break; + } + } + /* Update size of array since we "removed" duplicates */ + num_dcfclk_sta_targets = i + 1; + } + + num_uclk_states = bw_params->clk_table.num_entries; + + /* Calculate optimal dcfclk for each uclk */ + for (i = 0; i < num_uclk_states; i++) { + dcn303_get_optimal_dcfclk_fclk_for_uclk(bw_params->clk_table.entries[i].memclk_mhz * 16, + &optimal_dcfclk_for_uclk[i], NULL); + if (optimal_dcfclk_for_uclk[i] < bw_params->clk_table.entries[0].dcfclk_mhz) + optimal_dcfclk_for_uclk[i] = bw_params->clk_table.entries[0].dcfclk_mhz; + } + + /* Calculate optimal uclk for each dcfclk sta target */ + for (i = 0; i < num_dcfclk_sta_targets; i++) { + for (j = 0; j < num_uclk_states; j++) { + if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j]) { + optimal_uclk_for_dcfclk_sta_targets[i] = + bw_params->clk_table.entries[j].memclk_mhz * 16; + break; + } + } + } + + i = 0; + j = 0; + /* create the final dcfclk and uclk table */ + while (i < num_dcfclk_sta_targets && j < num_uclk_states && num_states < DC__VOLTAGE_STATES) { + if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j] && i < num_dcfclk_sta_targets) { + dcfclk_mhz[num_states] = dcfclk_sta_targets[i]; + dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++]; + } else { + if (j < num_uclk_states && optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) { + dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j]; + dram_speed_mts[num_states++] = + bw_params->clk_table.entries[j++].memclk_mhz * 16; + } else { + j = num_uclk_states; + } + } + } + + while (i < num_dcfclk_sta_targets && num_states < DC__VOLTAGE_STATES) { + dcfclk_mhz[num_states] = dcfclk_sta_targets[i]; + dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++]; + } + + while (j < num_uclk_states && num_states < DC__VOLTAGE_STATES && + optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) { + dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j]; + dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16; + } + + dcn3_03_soc.num_states = num_states; + for (i = 0; i < dcn3_03_soc.num_states; i++) { + dcn3_03_soc.clock_limits[i].state = i; + dcn3_03_soc.clock_limits[i].dcfclk_mhz = dcfclk_mhz[i]; + dcn3_03_soc.clock_limits[i].fabricclk_mhz = dcfclk_mhz[i]; + dcn3_03_soc.clock_limits[i].dram_speed_mts = dram_speed_mts[i]; + + /* Fill all states with max values of all other clocks */ + dcn3_03_soc.clock_limits[i].dispclk_mhz = max_dispclk_mhz; + dcn3_03_soc.clock_limits[i].dppclk_mhz = max_dppclk_mhz; + dcn3_03_soc.clock_limits[i].phyclk_mhz = max_phyclk_mhz; + /* Populate from bw_params for DTBCLK, SOCCLK */ + if (!bw_params->clk_table.entries[i].dtbclk_mhz && i > 0) + dcn3_03_soc.clock_limits[i].dtbclk_mhz = dcn3_03_soc.clock_limits[i-1].dtbclk_mhz; + else + dcn3_03_soc.clock_limits[i].dtbclk_mhz = bw_params->clk_table.entries[i].dtbclk_mhz; + if (!bw_params->clk_table.entries[i].socclk_mhz && i > 0) + dcn3_03_soc.clock_limits[i].socclk_mhz = dcn3_03_soc.clock_limits[i-1].socclk_mhz; + else + dcn3_03_soc.clock_limits[i].socclk_mhz = bw_params->clk_table.entries[i].socclk_mhz; + /* These clocks cannot come from bw_params, always fill from dcn3_03_soc[1] */ + /* FCLK, PHYCLK_D18, DSCCLK */ + dcn3_03_soc.clock_limits[i].phyclk_d18_mhz = dcn3_03_soc.clock_limits[0].phyclk_d18_mhz; + dcn3_03_soc.clock_limits[i].dscclk_mhz = dcn3_03_soc.clock_limits[0].dscclk_mhz; + } + + if (dcn3_03_soc.num_chans <= 4) { + for (i = 0; i < dcn3_03_soc.num_states; i++) { + if (dcn3_03_soc.clock_limits[i].dram_speed_mts > 1700) + break; + + if (dcn3_03_soc.clock_limits[i].dram_speed_mts >= 1500) { + dcn3_03_soc.clock_limits[i].dcfclk_mhz = 100; + dcn3_03_soc.clock_limits[i].fabricclk_mhz = 100; + } + } + } + + /* re-init DML with updated bb */ + dml_init_instance(&dc->dml, &dcn3_03_soc, &dcn3_03_ip, DML_PROJECT_DCN30); + if (dc->current_state) + dml_init_instance(&dc->current_state->bw_ctx.dml, &dcn3_03_soc, &dcn3_03_ip, DML_PROJECT_DCN30); + } +} + +void dcn303_fpu_init_soc_bounding_box(struct bp_soc_bb_info bb_info) +{ + dc_assert_fp_enabled(); + + if (bb_info.dram_clock_change_latency_100ns > 0) + dcn3_03_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_03_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_03_soc.sr_exit_time_us = + bb_info.dram_sr_exit_latency_100ns * 10; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn303/dcn303_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn303/dcn303_fpu.h new file mode 100644 index 0000000000000..92ec833fa528e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn303/dcn303_fpu.h @@ -0,0 +1,32 @@ +/* + * Copyright 2019-2021 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 + * + */ + +#ifndef __DCN303_FPU_H__ +#define __DCN303_FPU_H__ + +void dcn303_fpu_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); +void dcn303_fpu_init_soc_bounding_box(struct bp_soc_bb_info bb_info); + +#endif /* __DCN303_FPU_H__*/ From 5fed53c7983654b1658c49a030ac86bba7965fde Mon Sep 17 00:00:00 2001 From: "Leo (Hanghong) Ma" <hanghong.ma@amd.com> Date: Fri, 11 Feb 2022 09:44:05 -0500 Subject: [PATCH 11/65] drm/amd/display: Add link dp trace support [Why] It is nice to have link training and link loss status logging in our trace, and this patch add the all necessary accessors in dc side. [How] 1. Define dp_trace struct and create new file link_dp_trace.c and link_dp_trace.h; 2. Add dp link training status update in dc_link_dp.c; Reviewed-by: Wenjing Liu <Wenjing.Liu@amd.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Signed-off-by: Leo (Hanghong) Ma <hanghong.ma@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 5 + .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 24 ++- drivers/gpu/drm/amd/display/dc/dc_link.h | 36 +++++ drivers/gpu/drm/amd/display/dc/link/Makefile | 2 +- .../drm/amd/display/dc/link/link_dp_trace.c | 146 ++++++++++++++++++ .../drm/amd/display/dc/link/link_dp_trace.h | 57 +++++++ 6 files changed, 268 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/link/link_dp_trace.c create mode 100644 drivers/gpu/drm/amd/display/dc/link/link_dp_trace.h diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index b2ed2b683ba55..1951a92e34173 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -50,6 +50,7 @@ #include "inc/hw/panel_cntl.h" #include "inc/link_enc_cfg.h" #include "inc/link_dpcd.h" +#include "link/link_dp_trace.h" #include "dc/dcn30/dcn30_vpg.h" @@ -1255,6 +1256,9 @@ static bool detect_link_and_local_sink(struct dc_link *link, !sink->edid_caps.edid_hdmi) sink->sink_signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + if (link->local_sink && dc_is_dp_signal(sink_caps.signal)) + dp_trace_init(link); + /* Connectivity log: detection */ for (i = 0; i < sink->dc_edid.length / DC_EDID_BLOCK_SIZE; i++) { CONN_DATA_DETECT(link, @@ -1307,6 +1311,7 @@ static bool detect_link_and_local_sink(struct dc_link *link, link->dongle_max_pix_clk = 0; dc_link_clear_dprx_states(link); + dp_trace_reset(link); } LINK_INFO("link=%d, dc_sink_in=%p is now %s prev_sink=%p edid same=%d\n", diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 6a213467c97ce..0e84c54dc67ea 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -39,6 +39,7 @@ #include "dce/dmub_hw_lock_mgr.h" #include "inc/dc_link_dpia.h" #include "inc/link_enc_cfg.h" +#include "link/link_dp_trace.h" /*Travis*/ static const uint8_t DP_VGA_LVDS_CONVERTER_ID_2[] = "sivarT"; @@ -2776,6 +2777,10 @@ bool perform_link_training_with_retries( enum link_training_result status = LINK_TRAINING_CR_FAIL_LANE0; struct dc_link_settings current_setting = *link_setting; const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); + int fail_count = 0; + + dp_trace_commit_lt_init(link); + if (dp_get_link_encoding_format(¤t_setting) == DP_8b_10b_ENCODING) /* We need to do this before the link training to ensure the idle @@ -2783,6 +2788,7 @@ bool perform_link_training_with_retries( */ link_hwss->setup_stream_encoder(pipe_ctx); + dp_trace_set_lt_start_timestamp(link, false); for (j = 0; j < attempts; ++j) { DC_LOG_HW_LINK_TRAINING("%s: Beginning link training attempt %u of %d\n", @@ -2838,10 +2844,15 @@ bool perform_link_training_with_retries( skip_video_pattern); } + dp_trace_lt_total_count_increment(link, false); + dp_trace_lt_result_update(link, status, false); + dp_trace_set_lt_end_timestamp(link, false); if (status == LINK_TRAINING_SUCCESS) return true; } + fail_count++; + dp_trace_lt_fail_count_update(link, fail_count, false); /* latest link training still fail, skip delay and keep PHY on */ if (j == (attempts - 1) && link->ep_type == DISPLAY_ENDPOINT_PHY) @@ -3309,6 +3320,8 @@ static bool dp_verify_link_cap( } else { (*fail_count)++; } + dp_trace_lt_total_count_increment(link, true); + dp_trace_lt_result_update(link, status, true); dp_disable_link_phy(link, &link_res, link->connector_signal); } while (!success && decide_fallback_link_setting(link, initial_link_settings, &cur_link_settings, status)); @@ -3340,13 +3353,16 @@ bool dp_verify_link_cap_with_retries( { int i = 0; bool success = false; + int fail_count = 0; + + dp_trace_detect_lt_init(link); if (link->link_enc && link->link_enc->features.flags.bits.DP_IS_USB_C && link->dc->debug.usbc_combo_phy_reset_wa) apply_usbc_combo_phy_reset_wa(link, known_limit_link_setting); + dp_trace_set_lt_start_timestamp(link, false); for (i = 0; i < attempts; i++) { - int fail_count = 0; enum dc_connection_type type = dc_connection_none; memset(&link->verified_link_cap, 0, @@ -3361,6 +3377,10 @@ bool dp_verify_link_cap_with_retries( } msleep(10); } + + dp_trace_lt_fail_count_update(link, fail_count, true); + dp_trace_set_lt_end_timestamp(link, true); + return success; } @@ -4627,6 +4647,8 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd status = false; if (out_link_loss) *out_link_loss = true; + + dp_trace_link_loss_increment(link); } if (link->type == dc_connection_sst_branch && diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index ce6e8d013459a..78e66e4bab5a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -76,6 +76,28 @@ struct link_trace { struct time_stamp time_stamp; }; +struct dp_trace_lt_counts { + unsigned int total; + unsigned int fail; +}; + +struct dp_trace_lt { + struct dp_trace_lt_counts counts; + struct dp_trace_timestamps { + unsigned long long start; + unsigned long long end; + } timestamps; + enum link_training_result result; + bool is_logged; +}; + +struct dp_trace { + struct dp_trace_lt detect_lt_trace; + struct dp_trace_lt commit_lt_trace; + unsigned int link_loss_count; + bool is_initialized; +}; + /* PSR feature flags */ struct psr_settings { bool psr_feature_enabled; // PSR is supported by sink @@ -121,6 +143,8 @@ struct dc_link { bool edp_sink_present; + struct dp_trace dp_trace; + /* caps is the same as reported_link_cap. link_traing use * reported_link_cap. Will clean up. TODO */ @@ -470,4 +494,16 @@ void dc_link_clear_dprx_states(struct dc_link *link); struct gpio *get_hpd_gpio(struct dc_bios *dcb, struct graphics_object_id link_id, struct gpio_service *gpio_service); +void dp_trace_reset(struct dc_link *link); +bool dc_dp_trace_is_initialized(struct dc_link *link); +unsigned long long dc_dp_trace_get_lt_end_timestamp(struct dc_link *link, + bool in_detection); +void dc_dp_trace_set_is_logged_flag(struct dc_link *link, + bool in_detection, + bool is_logged); +bool dc_dp_trace_is_logged(struct dc_link *link, + bool in_detection); +struct dp_trace_lt_counts *dc_dp_trace_get_lt_counts(struct dc_link *link, + bool in_detection); +unsigned int dc_dp_trace_get_link_loss_count(struct dc_link *link); #endif /* DC_LINK_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/Makefile b/drivers/gpu/drm/amd/display/dc/link/Makefile index c4a69ba7cb62f..054c2a727eb22 100644 --- a/drivers/gpu/drm/amd/display/dc/link/Makefile +++ b/drivers/gpu/drm/amd/display/dc/link/Makefile @@ -23,7 +23,7 @@ # It abstracts the control and status of back end pipe such as DIO, HPO, DPIA, # PHY, HPD, DDC and etc). -LINK = link_hwss_dio.o link_hwss_dpia.o link_hwss_hpo_dp.o +LINK = link_hwss_dio.o link_hwss_dpia.o link_hwss_hpo_dp.o link_dp_trace.o AMD_DAL_LINK = $(addprefix $(AMDDALPATH)/dc/link/,$(LINK)) diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_trace.c b/drivers/gpu/drm/amd/display/dc/link/link_dp_trace.c new file mode 100644 index 0000000000000..e7047391934bc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/link_dp_trace.c @@ -0,0 +1,146 @@ +/* + * 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 "dc_link.h" +#include "link_dp_trace.h" + +void dp_trace_init(struct dc_link *link) +{ + memset(&link->dp_trace, 0, sizeof(link->dp_trace)); + link->dp_trace.is_initialized = true; +} + +void dp_trace_reset(struct dc_link *link) +{ + memset(&link->dp_trace, 0, sizeof(link->dp_trace)); +} + +bool dc_dp_trace_is_initialized(struct dc_link *link) +{ + return link->dp_trace.is_initialized; +} + +void dp_trace_detect_lt_init(struct dc_link *link) +{ + memset(&link->dp_trace.detect_lt_trace, 0, sizeof(link->dp_trace.detect_lt_trace)); +} + +void dp_trace_commit_lt_init(struct dc_link *link) +{ + memset(&link->dp_trace.commit_lt_trace, 0, sizeof(link->dp_trace.commit_lt_trace)); +} + +void dp_trace_link_loss_increment(struct dc_link *link) +{ + link->dp_trace.link_loss_count++; +} + +void dp_trace_lt_fail_count_update(struct dc_link *link, + unsigned int fail_count, + bool in_detection) +{ + if (in_detection) + link->dp_trace.detect_lt_trace.counts.fail = fail_count; + else + link->dp_trace.commit_lt_trace.counts.fail = fail_count; +} + +void dp_trace_lt_total_count_increment(struct dc_link *link, + bool in_detection) +{ + if (in_detection) + link->dp_trace.detect_lt_trace.counts.total++; + else + link->dp_trace.commit_lt_trace.counts.total++; +} + +void dc_dp_trace_set_is_logged_flag(struct dc_link *link, + bool in_detection, + bool is_logged) +{ + if (in_detection) + link->dp_trace.detect_lt_trace.is_logged = is_logged; + else + link->dp_trace.commit_lt_trace.is_logged = is_logged; +} + +bool dc_dp_trace_is_logged(struct dc_link *link, + bool in_detection) +{ + if (in_detection) + return link->dp_trace.detect_lt_trace.is_logged; + else + return link->dp_trace.commit_lt_trace.is_logged; +} + +void dp_trace_lt_result_update(struct dc_link *link, + enum link_training_result result, + bool in_detection) +{ + if (in_detection) + link->dp_trace.detect_lt_trace.result = result; + else + link->dp_trace.commit_lt_trace.result = result; +} + +void dp_trace_set_lt_start_timestamp(struct dc_link *link, + bool in_detection) +{ + if (in_detection) + link->dp_trace.detect_lt_trace.timestamps.start = dm_get_timestamp(link->dc->ctx); + else + link->dp_trace.commit_lt_trace.timestamps.start = dm_get_timestamp(link->dc->ctx); +} + +void dp_trace_set_lt_end_timestamp(struct dc_link *link, + bool in_detection) +{ + if (in_detection) + link->dp_trace.detect_lt_trace.timestamps.end = dm_get_timestamp(link->dc->ctx); + else + link->dp_trace.commit_lt_trace.timestamps.end = dm_get_timestamp(link->dc->ctx); +} + +unsigned long long dc_dp_trace_get_lt_end_timestamp(struct dc_link *link, + bool in_detection) +{ + if (in_detection) + return link->dp_trace.detect_lt_trace.timestamps.end; + else + return link->dp_trace.commit_lt_trace.timestamps.end; +} + +struct dp_trace_lt_counts *dc_dp_trace_get_lt_counts(struct dc_link *link, + bool in_detection) +{ + if (in_detection) + return &link->dp_trace.detect_lt_trace.counts; + else + return &link->dp_trace.commit_lt_trace.counts; +} + +unsigned int dc_dp_trace_get_link_loss_count(struct dc_link *link) +{ + return link->dp_trace.link_loss_count; +} diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_trace.h b/drivers/gpu/drm/amd/display/dc/link/link_dp_trace.h new file mode 100644 index 0000000000000..702f97c6ead02 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/link_dp_trace.h @@ -0,0 +1,57 @@ +/* + * 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 + * + */ +#ifndef __LINK_DP_TRACE_H__ +#define __LINK_DP_TRACE_H__ + +void dp_trace_init(struct dc_link *link); +void dp_trace_reset(struct dc_link *link); +bool dc_dp_trace_is_initialized(struct dc_link *link); +void dp_trace_detect_lt_init(struct dc_link *link); +void dp_trace_commit_lt_init(struct dc_link *link); +void dp_trace_link_loss_increment(struct dc_link *link); +void dp_trace_lt_fail_count_update(struct dc_link *link, + unsigned int fail_count, + bool in_detection); +void dp_trace_lt_total_count_increment(struct dc_link *link, + bool in_detection); +void dc_dp_trace_set_is_logged_flag(struct dc_link *link, + bool in_detection, + bool is_logged); +bool dc_dp_trace_is_logged(struct dc_link *link, + bool in_detection); +void dp_trace_lt_result_update(struct dc_link *link, + enum link_training_result result, + bool in_detection); +void dp_trace_set_lt_start_timestamp(struct dc_link *link, + bool in_detection); +void dp_trace_set_lt_end_timestamp(struct dc_link *link, + bool in_detection); +unsigned long long dc_dp_trace_get_lt_end_timestamp(struct dc_link *link, + bool in_detection); +struct dp_trace_lt_counts *dc_dp_trace_get_lt_counts(struct dc_link *link, + bool in_detection); +unsigned int dc_dp_trace_get_link_loss_count(struct dc_link *link); + +#endif /* __LINK_DP_TRACE_H__ */ From 305f098020920f9ea6ff9162ee46392f4d67e67f Mon Sep 17 00:00:00 2001 From: Charlene Liu <Charlene.Liu@amd.com> Date: Thu, 24 Feb 2022 12:57:23 -0500 Subject: [PATCH 12/65] drm/amd/display: merge two duplicated clock_source_create [why] dcn31x could use dcn31 sepcific which contains deep_color_ratio for dmub Reviewed-by: Nevenko Stupar <Nevenko.Stupar@amd.com> Reviewed-by: Hansen Dsouza <hansen.dsouza@amd.com> Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Signed-off-by: Charlene Liu <Charlene.Liu@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/dce/dce_clock_source.c | 127 ++++++++++-------- .../amd/display/dc/dcn315/dcn315_resource.c | 33 +---- .../amd/display/dc/dcn316/dcn316_resource.c | 33 +---- 3 files changed, 82 insertions(+), 111 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 9285bdeca2702..cc5128e67daff 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -978,70 +978,87 @@ static bool dcn31_program_pix_clk( struct pll_settings *pll_settings) { struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source); + unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; + unsigned int dp_dto_ref_khz = clock_source->ctx->dc->clk_mgr->dprefclk_khz; + const struct pixel_rate_range_table_entry *e = + look_up_in_video_optimized_rate_tlb(pix_clk_params->requested_pix_clk_100hz / 10); struct bp_pixel_clock_parameters bp_pc_params = {0}; enum transmitter_color_depth bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_24; - - if (IS_FPGA_MAXIMUS_DC(clock_source->ctx->dce_environment)) { - unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; - unsigned dp_dto_ref_100hz = 7000000; - unsigned clock_100hz = pll_settings->actual_pix_clk_100hz; - - /* Set DTO values: phase = target clock, modulo = reference clock */ - REG_WRITE(PHASE[inst], clock_100hz); - REG_WRITE(MODULO[inst], dp_dto_ref_100hz); - - /* Enable DTO */ + // For these signal types Driver to program DP_DTO without calling VBIOS Command table + if (dc_is_dp_signal(pix_clk_params->signal_type)) { + if (e) { + /* Set DTO values: phase = target clock, modulo = reference clock*/ + REG_WRITE(PHASE[inst], e->target_pixel_rate_khz * e->mult_factor); + REG_WRITE(MODULO[inst], dp_dto_ref_khz * e->div_factor); + } else { + /* Set DTO values: phase = target clock, modulo = reference clock*/ + REG_WRITE(PHASE[inst], pll_settings->actual_pix_clk_100hz * 100); + REG_WRITE(MODULO[inst], dp_dto_ref_khz * 1000); + } REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 1); - return true; - } + } else { + if (IS_FPGA_MAXIMUS_DC(clock_source->ctx->dce_environment)) { + unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; + unsigned dp_dto_ref_100hz = 7000000; + unsigned clock_100hz = pll_settings->actual_pix_clk_100hz; + + /* Set DTO values: phase = target clock, modulo = reference clock */ + REG_WRITE(PHASE[inst], clock_100hz); + REG_WRITE(MODULO[inst], dp_dto_ref_100hz); + + /* Enable DTO */ + REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 1); + return true; + } - /*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/ - bp_pc_params.controller_id = pix_clk_params->controller_id; - bp_pc_params.pll_id = clock_source->id; - bp_pc_params.target_pixel_clock_100hz = pll_settings->actual_pix_clk_100hz; - bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id; - bp_pc_params.signal_type = pix_clk_params->signal_type; + /*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/ + bp_pc_params.controller_id = pix_clk_params->controller_id; + bp_pc_params.pll_id = clock_source->id; + bp_pc_params.target_pixel_clock_100hz = pll_settings->actual_pix_clk_100hz; + bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id; + bp_pc_params.signal_type = pix_clk_params->signal_type; - // Make sure we send the correct color depth to DMUB for HDMI - if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) { - switch (pix_clk_params->color_depth) { - case COLOR_DEPTH_888: - bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_24; - break; - case COLOR_DEPTH_101010: - bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_30; - break; - case COLOR_DEPTH_121212: - bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_36; - break; - case COLOR_DEPTH_161616: - bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_48; - break; - default: - bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_24; - break; + // Make sure we send the correct color depth to DMUB for HDMI + if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) { + switch (pix_clk_params->color_depth) { + case COLOR_DEPTH_888: + bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_24; + break; + case COLOR_DEPTH_101010: + bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_30; + break; + case COLOR_DEPTH_121212: + bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_36; + break; + case COLOR_DEPTH_161616: + bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_48; + break; + default: + bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_24; + break; + } + bp_pc_params.color_depth = bp_pc_colour_depth; } - bp_pc_params.color_depth = bp_pc_colour_depth; - } - if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { - bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC = - pll_settings->use_external_clk; - bp_pc_params.flags.SET_XTALIN_REF_SRC = - !pll_settings->use_external_clk; - if (pix_clk_params->flags.SUPPORT_YCBCR420) { - bp_pc_params.flags.SUPPORT_YUV_420 = 1; + if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { + bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC = + pll_settings->use_external_clk; + bp_pc_params.flags.SET_XTALIN_REF_SRC = + !pll_settings->use_external_clk; + if (pix_clk_params->flags.SUPPORT_YCBCR420) { + bp_pc_params.flags.SUPPORT_YUV_420 = 1; + } } + if (clk_src->bios->funcs->set_pixel_clock( + clk_src->bios, &bp_pc_params) != BP_RESULT_OK) + return false; + /* Resync deep color DTO */ + if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) + dce112_program_pixel_clk_resync(clk_src, + pix_clk_params->signal_type, + pix_clk_params->color_depth, + pix_clk_params->flags.SUPPORT_YCBCR420); } - if (clk_src->bios->funcs->set_pixel_clock( - clk_src->bios, &bp_pc_params) != BP_RESULT_OK) - return false; - /* Resync deep color DTO */ - if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) - dce112_program_pixel_clk_resync(clk_src, - pix_clk_params->signal_type, - pix_clk_params->color_depth, - pix_clk_params->flags.SUPPORT_YCBCR420); return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c index d161b81976313..a9dc84b652608 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c @@ -1963,29 +1963,6 @@ static struct resource_funcs dcn315_res_pool_funcs = { .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, }; -static struct clock_source *dcn30_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dcn3_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - BREAK_TO_DEBUGGER(); - return NULL; -} - static bool dcn315_resource_construct( uint8_t num_virtual_links, struct dc *dc, @@ -2091,23 +2068,23 @@ static bool dcn315_resource_construct( /* Clock Sources for Pixel Clock*/ pool->base.clock_sources[DCN31_CLK_SRC_PLL0] = - dcn30_clock_source_create(ctx, ctx->dc_bios, + dcn31_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL0, &clk_src_regs[0], false); pool->base.clock_sources[DCN31_CLK_SRC_PLL1] = - dcn30_clock_source_create(ctx, ctx->dc_bios, + dcn31_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL1, &clk_src_regs[1], false); pool->base.clock_sources[DCN31_CLK_SRC_PLL2] = - dcn30_clock_source_create(ctx, ctx->dc_bios, + dcn31_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL2, &clk_src_regs[2], false); pool->base.clock_sources[DCN31_CLK_SRC_PLL3] = - dcn30_clock_source_create(ctx, ctx->dc_bios, + dcn31_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL3, &clk_src_regs[3], false); pool->base.clock_sources[DCN31_CLK_SRC_PLL4] = - dcn30_clock_source_create(ctx, ctx->dc_bios, + dcn31_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL4, &clk_src_regs[4], false); diff --git a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c index 2e378d9cd00dd..936803721cc3c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c @@ -1964,29 +1964,6 @@ static struct resource_funcs dcn316_res_pool_funcs = { .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, }; -static struct clock_source *dcn30_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dcn3_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - BREAK_TO_DEBUGGER(); - return NULL; -} - static bool dcn316_resource_construct( uint8_t num_virtual_links, struct dc *dc, @@ -2092,23 +2069,23 @@ static bool dcn316_resource_construct( /* Clock Sources for Pixel Clock*/ pool->base.clock_sources[DCN31_CLK_SRC_PLL0] = - dcn30_clock_source_create(ctx, ctx->dc_bios, + dcn31_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL0, &clk_src_regs[0], false); pool->base.clock_sources[DCN31_CLK_SRC_PLL1] = - dcn30_clock_source_create(ctx, ctx->dc_bios, + dcn31_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL1, &clk_src_regs[1], false); pool->base.clock_sources[DCN31_CLK_SRC_PLL2] = - dcn30_clock_source_create(ctx, ctx->dc_bios, + dcn31_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL2, &clk_src_regs[2], false); pool->base.clock_sources[DCN31_CLK_SRC_PLL3] = - dcn30_clock_source_create(ctx, ctx->dc_bios, + dcn31_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL3, &clk_src_regs[3], false); pool->base.clock_sources[DCN31_CLK_SRC_PLL4] = - dcn30_clock_source_create(ctx, ctx->dc_bios, + dcn31_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL4, &clk_src_regs[4], false); From 76a52f36b636cdff6b5b18f13daf05005e4b0b57 Mon Sep 17 00:00:00 2001 From: Jingwen Zhu <jingwen.zhu@amd.com> Date: Fri, 25 Feb 2022 16:55:59 +0800 Subject: [PATCH 13/65] drm/amd/display: add gamut coefficient set A and B [Why] Screen shake on DCN3 night light SDR BR3. [How] Change the logic to use double buffer reisgter on gamut settings. Reviewed-by: Krunoslav Kovac <Krunoslav.Kovac@amd.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Signed-off-by: Jingwen Zhu <jingwen.zhu@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp_cm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp_cm.c index 387eec6161629..87dbeca189847 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp_cm.c @@ -408,6 +408,6 @@ void dpp3_cm_set_gamut_remap( gamut_mode = 1; //follow dcn2 approach for now - using only coefficient set A - program_gamut_remap(dpp, arr_reg_val, GAMUT_REMAP_COEFF); + program_gamut_remap(dpp, arr_reg_val, gamut_mode); } } From 4a897de1d607c15ebb9aa11a424ec3f3243304a3 Mon Sep 17 00:00:00 2001 From: Sung Joon Kim <sungjoon.kim@amd.com> Date: Thu, 24 Feb 2022 14:58:52 -0500 Subject: [PATCH 14/65] drm/amd/display: disable HPD SW timer for passive dongle type 1 only [why] Need to provide this workaround only for type 1 passive dongle [how] Detect if dongle is type 1 or 2. And use it to determine if w/a is needed. Reviewed-by: Charlene Liu <Charlene.Liu@amd.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Signed-off-by: Sung Joon Kim <sungjoon.kim@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 1 + drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 2 ++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/include/ddc_service_types.h | 1 + 4 files changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 1951a92e34173..b3ca3307d39d0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -731,6 +731,7 @@ static bool detect_dp(struct dc_link *link, sink_caps, audio_support); link->dpcd_caps.dongle_type = sink_caps->dongle_type; + link->dpcd_caps.is_dongle_type_one = sink_caps->is_dongle_type_one; link->dpcd_caps.dpcd_rev.raw = 0; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index f1bbd918de357..1d4863763df9c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -493,6 +493,7 @@ void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( sink_cap->max_hdmi_pixel_clock = max_tmds_clk * 1000; } + sink_cap->is_dongle_type_one = false; } else { if (is_valid_hdmi_signature == true) { @@ -510,6 +511,7 @@ void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( "Type 1 DP-HDMI passive dongle (no signature) %dMhz: ", sink_cap->max_hdmi_pixel_clock / 1000); } + sink_cap->is_dongle_type_one = true; } return; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 333f4a49cacbb..a57ac086f2bd6 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1206,6 +1206,7 @@ struct dpcd_caps { /* dongle type (DP converter, CV smart dongle) */ enum display_dongle_type dongle_type; + bool is_dongle_type_one; /* branch device or sink device */ bool is_branch_dev; /* Dongle's downstream count. */ diff --git a/drivers/gpu/drm/amd/display/include/ddc_service_types.h b/drivers/gpu/drm/amd/display/include/ddc_service_types.h index f561e213bf989..f883d87791fe5 100644 --- a/drivers/gpu/drm/amd/display/include/ddc_service_types.h +++ b/drivers/gpu/drm/amd/display/include/ddc_service_types.h @@ -64,6 +64,7 @@ enum ddc_service_type { struct display_sink_capability { /* dongle type (DP converter, CV smart dongle) */ enum display_dongle_type dongle_type; + bool is_dongle_type_one; /********************************************************** capabilities going INTO SINK DEVICE (stream capabilities) From 4185f99094d50a2f402153ff8922bc694f5f6d96 Mon Sep 17 00:00:00 2001 From: Wenjing Liu <wenjing.liu@amd.com> Date: Tue, 15 Feb 2022 18:34:08 -0500 Subject: [PATCH 15/65] drm/amd/display: handle DP2.0 RX with UHBR20 but not UHBR13.5 support [why] DP2.0 defines DP2.0 RX capability using bit maps. This means there is a corner case the DP2.0 RX can declare UHBR20 capability but not UHBR13.5 support. In this case we should skip UHBR13.5 selection and continue to our next option in decide liink settings. Reviewed-by: George Shen <George.Shen@amd.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Signed-off-by: Wenjing Liu <wenjing.liu@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 49 ++++++++++++++----- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 0e84c54dc67ea..7d88165e8fa2b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -3470,7 +3470,8 @@ static enum dc_lane_count increase_lane_count(enum dc_lane_count lane_count) } } -static enum dc_link_rate increase_link_rate(enum dc_link_rate link_rate) +static enum dc_link_rate increase_link_rate(struct dc_link *link, + enum dc_link_rate link_rate) { switch (link_rate) { case LINK_RATE_LOW: @@ -3482,7 +3483,15 @@ static enum dc_link_rate increase_link_rate(enum dc_link_rate link_rate) case LINK_RATE_HIGH3: return LINK_RATE_UHBR10; case LINK_RATE_UHBR10: - return LINK_RATE_UHBR13_5; + /* upto DP2.x specs UHBR13.5 is the only link rate that could be + * not supported by DPRX when higher link rate is supported. + * so we treat it as a special case for code simplicity. When we + * have new specs with more link rates like this, we should + * consider a more generic solution to handle discrete link + * rate capabilities. + */ + return link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR13_5 ? + LINK_RATE_UHBR13_5 : LINK_RATE_UHBR20; case LINK_RATE_UHBR13_5: return LINK_RATE_UHBR20; default: @@ -3491,12 +3500,17 @@ static enum dc_link_rate increase_link_rate(enum dc_link_rate link_rate) } static bool decide_fallback_link_setting_max_bw_policy( + struct dc_link *link, const struct dc_link_settings *max, - struct dc_link_settings *cur) + struct dc_link_settings *cur, + enum link_training_result training_result) { uint8_t cur_idx = 0, next_idx; bool found = false; + if (training_result == LINK_TRAINING_ABORT) + return false; + while (cur_idx < ARRAY_SIZE(dp_lt_fallbacks)) /* find current index */ if (dp_lt_fallbacks[cur_idx].lane_count == cur->lane_count && @@ -3509,11 +3523,22 @@ static bool decide_fallback_link_setting_max_bw_policy( while (next_idx < ARRAY_SIZE(dp_lt_fallbacks)) /* find next index */ - if (dp_lt_fallbacks[next_idx].lane_count <= max->lane_count && - dp_lt_fallbacks[next_idx].link_rate <= max->link_rate) - break; - else + if (dp_lt_fallbacks[next_idx].lane_count > max->lane_count || + dp_lt_fallbacks[next_idx].link_rate > max->link_rate) + next_idx++; + else if (dp_lt_fallbacks[next_idx].link_rate == LINK_RATE_UHBR13_5 && + link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR13_5 == 0) + /* upto DP2.x specs UHBR13.5 is the only link rate that + * could be not supported by DPRX when higher link rate + * is supported. so we treat it as a special case for + * code simplicity. When we have new specs with more + * link rates like this, we should consider a more + * generic solution to handle discrete link rate + * capabilities. + */ next_idx++; + else + break; if (next_idx < ARRAY_SIZE(dp_lt_fallbacks)) { cur->lane_count = dp_lt_fallbacks[next_idx].lane_count; @@ -3542,8 +3567,8 @@ static bool decide_fallback_link_setting( return false; if (dp_get_link_encoding_format(&initial_link_settings) == DP_128b_132b_ENCODING || link->dc->debug.force_dp2_lt_fallback_method) - return decide_fallback_link_setting_max_bw_policy(&initial_link_settings, - current_link_setting); + return decide_fallback_link_setting_max_bw_policy(link, &initial_link_settings, + current_link_setting, training_result); switch (training_result) { case LINK_TRAINING_CR_FAIL_LANE0: @@ -3698,7 +3723,7 @@ static bool decide_dp_link_settings(struct dc_link *link, struct dc_link_setting current_link_setting.lane_count); } else { current_link_setting.link_rate = - increase_link_rate( + increase_link_rate(link, current_link_setting.link_rate); current_link_setting.lane_count = initial_link_setting.lane_count; @@ -3813,7 +3838,7 @@ static bool decide_edp_link_settings_with_dsc(struct dc_link *link, /* minimize lane */ if (current_link_setting.link_rate < max_link_rate) { current_link_setting.link_rate = - increase_link_rate( + increase_link_rate(link, current_link_setting.link_rate); } else { if (current_link_setting.lane_count < @@ -3834,7 +3859,7 @@ static bool decide_edp_link_settings_with_dsc(struct dc_link *link, current_link_setting.lane_count); } else { current_link_setting.link_rate = - increase_link_rate( + increase_link_rate(link, current_link_setting.link_rate); current_link_setting.lane_count = initial_link_setting.lane_count; From e7145aaedd55b19ae4e8bd25cbd4ef8f415b6b89 Mon Sep 17 00:00:00 2001 From: Charlene Liu <Charlene.Liu@amd.com> Date: Fri, 25 Feb 2022 20:50:14 -0500 Subject: [PATCH 16/65] drm/amd/display: enable dcn315/316 s0i2 support [why] enable the support in driver, let the control by CMOS Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Signed-off-by: Charlene Liu <Charlene.Liu@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c | 2 +- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c index 48fab0a0c08ba..edda572dc5701 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c @@ -131,6 +131,7 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base, union display_idle_optimization_u idle_info = { 0 }; idle_info.idle_info.df_request_disabled = 1; idle_info.idle_info.phy_ref_clk_off = 1; + idle_info.idle_info.s0i2_rdy = 1; dcn315_smu_set_display_idle_optimization(clk_mgr, idle_info.data); /* update power state */ clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER; @@ -526,7 +527,6 @@ void dcn315_clk_mgr_construct( struct dccg *dccg) { struct dcn315_smu_dpm_clks smu_dpm_clks = { 0 }; - struct clk_mgr *clk_mgr_base = ctx->dc->clk_mgr; clk_mgr->base.base.ctx = ctx; clk_mgr->base.base.funcs = &dcn315_funcs; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c index c940635b7a743..43120a8f83052 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c @@ -172,8 +172,7 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base, union display_idle_optimization_u idle_info = { 0 }; idle_info.idle_info.df_request_disabled = 1; idle_info.idle_info.phy_ref_clk_off = 1; - // Todo DCN316 set this to 1 if any no issue - idle_info.idle_info.s0i2_rdy = 0; + idle_info.idle_info.s0i2_rdy = 1; dcn316_smu_set_display_idle_optimization(clk_mgr, idle_info.data); /* update power state */ clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER; From 6e899860f557fc60135506242cc3fb705e64b718 Mon Sep 17 00:00:00 2001 From: Anthony Koo <Anthony.Koo@amd.com> Date: Sat, 26 Feb 2022 21:25:22 -0500 Subject: [PATCH 17/65] drm/amd/display: [FW Promotion] Release 0.0.107.0 Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Signed-off-by: Anthony Koo <Anthony.Koo@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 01b597d021fda..8521508af7557 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -46,10 +46,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0x082bd4c8 +#define DMUB_FW_VERSION_GIT_HASH 0xb6b77696 #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 106 +#define DMUB_FW_VERSION_REVISION 107 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 From 9c1e260e97606330518a78422ae28d9d56ac87d6 Mon Sep 17 00:00:00 2001 From: Aric Cyr <aric.cyr@amd.com> Date: Mon, 28 Feb 2022 10:00:09 -0500 Subject: [PATCH 18/65] drm/amd/display: 3.2.176 drm/amd/display: 3.2.176 This version brings along following fixes: - move FPU operations from dcn21 to dml/dcn20 folder - move FPU-related code from dcn20 to dml folder - Fix compile error from TO_CLK_MGR_INTERNAL - Fix double free during GPU reset on DC streams - Add NULL check - [FW Promotion] Release 0.0.107.0 - enable dcn315/316 s0i2 support - handle DP2.0 RX with UHBR20 but not UHBR13.5 support - disable HPD SW timer for passive dongle type 1 only - add gamut coefficient set A and B - merge two duplicated clock_source_create - Add link dp trace support - move FPU associated DCN303 code to DML folder - Release AUX engine after failed acquire - Add minimal pipe split transition state - Clean up fixed VS PHY test w/a function - fix the clock source contruct for dcn315 - cleaning up smu_if to add future flexibility - fix deep color ratio - add debug option to bypass ssinfo from bios for dcn315 Acked-by: Alan Liu <HaoPing.Liu@amd.com> Signed-off-by: Aric Cyr <aric.cyr@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index a57ac086f2bd6..bd5f718a9eb2d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.175" +#define DC_VER "3.2.176" #define MAX_SURFACES 3 #define MAX_PLANES 6 From 84ce38c7bf7a19fb1f9cc61181e830b7e04dd51d Mon Sep 17 00:00:00 2001 From: Chris Park <Chris.Park@amd.com> Date: Mon, 28 Feb 2022 10:23:00 -0500 Subject: [PATCH 19/65] drm/amd/display: Add NULL check [Why] Virtualization enters blue screen of death (BSoD) due to NULL res_pool object when accessing DSC encoder capability. [How] Add NULL check to avoid blue screen of death. Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Signed-off-by: Chris Park <Chris.Park@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index bc2150f3d79be..7af153434e9e4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2335,6 +2335,9 @@ void dc_resource_state_construct( bool dc_resource_is_dsc_encoding_supported(const struct dc *dc) { + if (dc->res_pool == NULL) + return false; + return dc->res_pool->res_cap->num_dsc > 0; } From 32685b32d825ca08c5dec826477332df886c4743 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Date: Mon, 28 Feb 2022 10:48:56 -0500 Subject: [PATCH 20/65] drm/amd/display: Fix double free during GPU reset on DC streams [Why] The issue only occurs during the GPU reset code path. We first backup the current state prior to commiting 0 streams internally from DM to DC. This state backup contains valid link encoder assignments. DC will clear the link encoder assignments as part of current state (but not the backup, since it was a copied before the commit) and free the extra stream reference it held. DC requires that the link encoder assignments remain cleared/invalid prior to commiting. Since the backup still has valid assignments we call the interface post reset to clear them. This routine also releases the extra reference that the link encoder interface held - resulting in a double free (and eventually a NULL pointer dereference). [How] We'll have to do a full DC commit anyway after GPU reset because the stream count previously went to 0. We don't need to retain the assignment that we had backed up, so just copy off of the now clean current state assignment after the reset has occcurred with the new link_enc_cfg_copy() interface. Fixes: 6d63fcc2a334 ("drm/amd/display: Reset link encoder assignments for GPU reset") Reviewed-by: Jimmy Kizito <Jimmy.Kizito@amd.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 ++++++--- drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c | 7 +++++++ drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h | 5 +++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index e1d3db3fe8deb..a473700580888 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2633,10 +2633,13 @@ static int dm_resume(void *handle) * before the 0 streams commit. * * DC expects that link encoder assignments are *not* valid - * when committing a state, so as a workaround it needs to be - * cleared here. + * when committing a state, so as a workaround we can copy + * off of the current state. + * + * We lose the previous assignments, but we had already + * commit 0 streams anyway. */ - link_enc_cfg_init(dm->dc, dc_state); + link_enc_cfg_copy(adev->dm.dc->current_state, dc_state); if (dc_enable_dmub_notifications(adev->dm.dc)) amdgpu_dm_outbox_init(adev); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c index 047c626a4a340..42da7f4301132 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c @@ -272,6 +272,13 @@ void link_enc_cfg_init( state->res_ctx.link_enc_cfg_ctx.mode = LINK_ENC_CFG_STEADY; } +void link_enc_cfg_copy(const struct dc_state *src_ctx, struct dc_state *dst_ctx) +{ + memcpy(&dst_ctx->res_ctx.link_enc_cfg_ctx, + &src_ctx->res_ctx.link_enc_cfg_ctx, + sizeof(dst_ctx->res_ctx.link_enc_cfg_ctx)); +} + void link_enc_cfg_link_encs_assign( struct dc *dc, struct dc_state *state, diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h b/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h index c2f08514a1d9f..c6f6baa6e6774 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h @@ -39,6 +39,11 @@ void link_enc_cfg_init( const struct dc *dc, struct dc_state *state); +/* + * Copies a link encoder assignment from another state. + */ +void link_enc_cfg_copy(const struct dc_state *src_ctx, struct dc_state *dst_ctx); + /* * Algorithm for assigning available DIG link encoders to streams. * From 44ca49f046f89a97ad319372b4fdbde67da1b6b3 Mon Sep 17 00:00:00 2001 From: Leo Li <sunpeng.li@amd.com> Date: Thu, 24 Feb 2022 16:30:41 -0500 Subject: [PATCH 21/65] drm/amd/display: Fix compile error from TO_CLK_MGR_INTERNAL [Why] On LNX, TO_CLK_MGR_INTERNAL() only works to get clk_mgr_internal from a given clk_mgr. In clk_mgr_dcn316 struct, the clk_mgr_internal is already a memeber by the alias 'base' [How] Use &clk_mgr->base instead. Reviewed-by: Harry Wentland <Harry.Wentland@amd.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Signed-off-by: Leo Li <sunpeng.li@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../dc/clk_mgr/dcn316/dcn316_clk_mgr.c | 5 +++- .../display/dc/clk_mgr/dcn316/dcn316_smu.c | 26 +++++++++++++++++++ .../display/dc/clk_mgr/dcn316/dcn316_smu.h | 2 ++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c index 43120a8f83052..702d00ce7da4c 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c @@ -683,8 +683,11 @@ void dcn316_clk_mgr_construct( } clk_mgr->base.base.dprefclk_khz = 600000; - clk_mgr->base.dccg->ref_dtbclk_khz = 600000; + clk_mgr->base.base.dprefclk_khz = dcn316_smu_get_dpref_clk(&clk_mgr->base); + clk_mgr->base.dccg->ref_dtbclk_khz = clk_mgr->base.base.dprefclk_khz; dce_clock_read_ss_info(&clk_mgr->base); + clk_mgr->base.dccg->ref_dtbclk_khz = + dce_adjust_dp_ref_freq_for_ss(&clk_mgr->base, clk_mgr->base.base.dprefclk_khz); clk_mgr->base.base.bw_params = &dcn316_bw_params; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_smu.c index 128614dff1089..dceec4b960527 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_smu.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_smu.c @@ -310,3 +310,29 @@ void dcn316_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable) VBIOSSMC_MSG_SetDtbclkFreq, enable); } + +int dcn316_smu_get_dpref_clk(struct clk_mgr_internal *clk_mgr) +{ + int dprefclk_get_mhz = -1; + + if (clk_mgr->smu_present) { + dprefclk_get_mhz = dcn316_smu_send_msg_with_param( + clk_mgr, + VBIOSSMC_MSG_GetDprefclkFreq, + 0); + } + return (dprefclk_get_mhz * 1000); +} + +int dcn316_smu_get_smu_fclk(struct clk_mgr_internal *clk_mgr) +{ + int fclk_get_mhz = -1; + + if (clk_mgr->smu_present) { + fclk_get_mhz = dcn316_smu_send_msg_with_param( + clk_mgr, + VBIOSSMC_MSG_GetFclkFrequency, + 0); + } + return (fclk_get_mhz * 1000); +} diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_smu.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_smu.h index 658b36d0e107b..2a7293f665152 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_smu.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_smu.h @@ -133,5 +133,7 @@ void dcn316_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr); void dcn316_smu_request_voltage_via_phyclk(struct clk_mgr_internal *clk_mgr, int requested_phyclk_khz); void dcn316_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr); void dcn316_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable); +int dcn316_smu_get_dpref_clk(struct clk_mgr_internal *clk_mgr); +int dcn316_smu_get_smu_fclk(struct clk_mgr_internal *clk_mgr); #endif /* DAL_DC_316_SMU_H_ */ From cf689e869cf0339c387397c7a6805e387594656d Mon Sep 17 00:00:00 2001 From: Melissa Wen <mwen@igalia.com> Date: Wed, 23 Feb 2022 23:27:25 +0000 Subject: [PATCH 22/65] drm/amd/display: move FPU-related code from dcn20 to dml folder Move parts of dcn20 code that uses FPU to dml folder. It aims to isolate FPU operations as described by series: drm/amd/display: Introduce FPU directory inside DC https://patchwork.freedesktop.org/series/93042/ This patch moves the following functions from dcn20_resource to dml/dcn20_fpu and calls of public functions in dcn20_resource are wrapped by DC_FP_START/END(): - void dcn20_populate_dml_writeback_from_context - static bool is_dtbclk_required() - static enum dcn_zstate_support_state() - void dcn20_calculate_dlg_params() - static void swizzle_to_dml_params() - int dcn20_populate_dml_pipes_from_context() - void dcn20_calculate_wm() - void dcn20_cap_soc_clocks() - void dcn20_update_bounding_box() - void dcn20_patch_bounding_box() - bool dcn20_validate_bandwidth_fp() This movement also affects dcn21/30/31, as dcn20_calculate_dlg_params() is used by them. For this reason, I included dcn20_fpu headers in dcn20_resource headers to make dcn20_calculate_dlg_params() visible to dcn21/30/31. Three new functions are created to isolate well-delimited FPU operations: - void dcn20_fpu_set_wb_arb_params(): set cli_watermark, pstate_watermark and time_per_pixel from wb_arb_params (struct mcif_arb_params), since those uses FPU operations on double types: WritebackUrgentWatermark, WritebackDRAMClockChangeWatermark, '16.0'. - void dcn20_fpu_set_wm_ranges(): set min_fill_clk_mhz and max_fill_clk_mhz involves FPU calcs on dram_speed_mts (double type); - void dcn20_fpu_adjust_dppclk(): adjust operation on RequiredDPPCLK that is a double. Signed-off-by: Melissa Wen <mwen@igalia.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn20/Makefile | 25 - .../drm/amd/display/dc/dcn20/dcn20_resource.c | 1369 +--------------- .../drm/amd/display/dc/dcn20/dcn20_resource.h | 31 +- .../drm/amd/display/dc/dcn21/dcn21_resource.c | 8 +- .../drm/amd/display/dc/dcn30/dcn30_resource.c | 7 + .../drm/amd/display/dc/dcn31/dcn31_resource.c | 4 + .../amd/display/dc/dcn315/dcn315_resource.c | 2 + .../amd/display/dc/dcn316/dcn316_resource.c | 2 + .../drm/amd/display/dc/dml/dcn20/dcn20_fpu.c | 1386 +++++++++++++++++ .../drm/amd/display/dc/dml/dcn20/dcn20_fpu.h | 42 + 10 files changed, 1476 insertions(+), 1400 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile index 5fcaf78334ff9..abaed2121febf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile @@ -9,31 +9,6 @@ DCN20 = dcn20_resource.o dcn20_init.o dcn20_hwseq.o dcn20_dpp.o dcn20_dpp_cm.o d DCN20 += dcn20_dsc.o -ifdef CONFIG_X86 -CFLAGS_$(AMDDALPATH)/dc/dcn20/dcn20_resource.o := -mhard-float -msse -endif - -ifdef CONFIG_PPC64 -CFLAGS_$(AMDDALPATH)/dc/dcn20/dcn20_resource.o := -mhard-float -maltivec -endif - -ifdef CONFIG_CC_IS_GCC -ifeq ($(call cc-ifversion, -lt, 0701, y), y) -IS_OLD_GCC = 1 -endif -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/dcn20/dcn20_resource.o += -mpreferred-stack-boundary=4 -else -CFLAGS_$(AMDDALPATH)/dc/dcn20/dcn20_resource.o += -msse2 -endif -endif - AMD_DAL_DCN20 = $(addprefix $(AMDDALPATH)/dc/dcn20/,$(DCN20)) AMD_DISPLAY_FILES += $(AMD_DAL_DCN20) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index dfe2e1c25a26e..d473708d53999 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -63,7 +63,6 @@ #include "dcn20_dccg.h" #include "dcn20_vmid.h" #include "dc_link_ddc.h" -#include "dc_link_dp.h" #include "dce/dce_panel_cntl.h" #include "navi10_ip_offset.h" @@ -93,367 +92,6 @@ #define DC_LOGGER_INIT(logger) -struct _vcs_dpi_ip_params_st dcn2_0_ip = { - .odm_capable = 1, - .gpuvm_enable = 0, - .hostvm_enable = 0, - .gpuvm_max_page_table_levels = 4, - .hostvm_max_page_table_levels = 4, - .hostvm_cached_page_table_levels = 0, - .pte_group_size_bytes = 2048, - .num_dsc = 6, - .rob_buffer_size_kbytes = 168, - .det_buffer_size_kbytes = 164, - .dpte_buffer_size_in_pte_reqs_luma = 84, - .pde_proc_buffer_size_64k_reqs = 48, - .dpp_output_buffer_pixels = 2560, - .opp_output_buffer_lines = 1, - .pixel_chunk_size_kbytes = 8, - .pte_chunk_size_kbytes = 2, - .meta_chunk_size_kbytes = 2, - .writeback_chunk_size_kbytes = 2, - .line_buffer_size_bits = 789504, - .is_line_buffer_bpp_fixed = 0, - .line_buffer_fixed_bpp = 0, - .dcc_supported = true, - .max_line_buffer_lines = 12, - .writeback_luma_buffer_size_kbytes = 12, - .writeback_chroma_buffer_size_kbytes = 8, - .writeback_chroma_line_buffer_width_pixels = 4, - .writeback_max_hscl_ratio = 1, - .writeback_max_vscl_ratio = 1, - .writeback_min_hscl_ratio = 1, - .writeback_min_vscl_ratio = 1, - .writeback_max_hscl_taps = 12, - .writeback_max_vscl_taps = 12, - .writeback_line_buffer_luma_buffer_size = 0, - .writeback_line_buffer_chroma_buffer_size = 14643, - .cursor_buffer_size = 8, - .cursor_chunk_size = 2, - .max_num_otg = 6, - .max_num_dpp = 6, - .max_num_wb = 1, - .max_dchub_pscl_bw_pix_per_clk = 4, - .max_pscl_lb_bw_pix_per_clk = 2, - .max_lb_vscl_bw_pix_per_clk = 4, - .max_vscl_hscl_bw_pix_per_clk = 4, - .max_hscl_ratio = 8, - .max_vscl_ratio = 8, - .hscl_mults = 4, - .vscl_mults = 4, - .max_hscl_taps = 8, - .max_vscl_taps = 8, - .dispclk_ramp_margin_percent = 1, - .underscan_factor = 1.10, - .min_vblank_lines = 32, // - .dppclk_delay_subtotal = 77, // - .dppclk_delay_scl_lb_only = 16, - .dppclk_delay_scl = 50, - .dppclk_delay_cnvc_formatter = 8, - .dppclk_delay_cnvc_cursor = 6, - .dispclk_delay_subtotal = 87, // - .dcfclk_cstate_latency = 10, // SRExitTime - .max_inter_dcn_tile_repeaters = 8, - .xfc_supported = true, - .xfc_fill_bw_overhead_percent = 10.0, - .xfc_fill_constant_bytes = 0, - .number_of_cursors = 1, -}; - -static struct _vcs_dpi_ip_params_st dcn2_0_nv14_ip = { - .odm_capable = 1, - .gpuvm_enable = 0, - .hostvm_enable = 0, - .gpuvm_max_page_table_levels = 4, - .hostvm_max_page_table_levels = 4, - .hostvm_cached_page_table_levels = 0, - .num_dsc = 5, - .rob_buffer_size_kbytes = 168, - .det_buffer_size_kbytes = 164, - .dpte_buffer_size_in_pte_reqs_luma = 84, - .dpte_buffer_size_in_pte_reqs_chroma = 42,//todo - .dpp_output_buffer_pixels = 2560, - .opp_output_buffer_lines = 1, - .pixel_chunk_size_kbytes = 8, - .pte_enable = 1, - .max_page_table_levels = 4, - .pte_chunk_size_kbytes = 2, - .meta_chunk_size_kbytes = 2, - .writeback_chunk_size_kbytes = 2, - .line_buffer_size_bits = 789504, - .is_line_buffer_bpp_fixed = 0, - .line_buffer_fixed_bpp = 0, - .dcc_supported = true, - .max_line_buffer_lines = 12, - .writeback_luma_buffer_size_kbytes = 12, - .writeback_chroma_buffer_size_kbytes = 8, - .writeback_chroma_line_buffer_width_pixels = 4, - .writeback_max_hscl_ratio = 1, - .writeback_max_vscl_ratio = 1, - .writeback_min_hscl_ratio = 1, - .writeback_min_vscl_ratio = 1, - .writeback_max_hscl_taps = 12, - .writeback_max_vscl_taps = 12, - .writeback_line_buffer_luma_buffer_size = 0, - .writeback_line_buffer_chroma_buffer_size = 14643, - .cursor_buffer_size = 8, - .cursor_chunk_size = 2, - .max_num_otg = 5, - .max_num_dpp = 5, - .max_num_wb = 1, - .max_dchub_pscl_bw_pix_per_clk = 4, - .max_pscl_lb_bw_pix_per_clk = 2, - .max_lb_vscl_bw_pix_per_clk = 4, - .max_vscl_hscl_bw_pix_per_clk = 4, - .max_hscl_ratio = 8, - .max_vscl_ratio = 8, - .hscl_mults = 4, - .vscl_mults = 4, - .max_hscl_taps = 8, - .max_vscl_taps = 8, - .dispclk_ramp_margin_percent = 1, - .underscan_factor = 1.10, - .min_vblank_lines = 32, // - .dppclk_delay_subtotal = 77, // - .dppclk_delay_scl_lb_only = 16, - .dppclk_delay_scl = 50, - .dppclk_delay_cnvc_formatter = 8, - .dppclk_delay_cnvc_cursor = 6, - .dispclk_delay_subtotal = 87, // - .dcfclk_cstate_latency = 10, // SRExitTime - .max_inter_dcn_tile_repeaters = 8, - .xfc_supported = true, - .xfc_fill_bw_overhead_percent = 10.0, - .xfc_fill_constant_bytes = 0, - .ptoi_supported = 0, - .number_of_cursors = 1, -}; - -static struct _vcs_dpi_soc_bounding_box_st dcn2_0_soc = { - /* Defaults that get patched on driver load from firmware. */ - .clock_limits = { - { - .state = 0, - .dcfclk_mhz = 560.0, - .fabricclk_mhz = 560.0, - .dispclk_mhz = 513.0, - .dppclk_mhz = 513.0, - .phyclk_mhz = 540.0, - .socclk_mhz = 560.0, - .dscclk_mhz = 171.0, - .dram_speed_mts = 8960.0, - }, - { - .state = 1, - .dcfclk_mhz = 694.0, - .fabricclk_mhz = 694.0, - .dispclk_mhz = 642.0, - .dppclk_mhz = 642.0, - .phyclk_mhz = 600.0, - .socclk_mhz = 694.0, - .dscclk_mhz = 214.0, - .dram_speed_mts = 11104.0, - }, - { - .state = 2, - .dcfclk_mhz = 875.0, - .fabricclk_mhz = 875.0, - .dispclk_mhz = 734.0, - .dppclk_mhz = 734.0, - .phyclk_mhz = 810.0, - .socclk_mhz = 875.0, - .dscclk_mhz = 245.0, - .dram_speed_mts = 14000.0, - }, - { - .state = 3, - .dcfclk_mhz = 1000.0, - .fabricclk_mhz = 1000.0, - .dispclk_mhz = 1100.0, - .dppclk_mhz = 1100.0, - .phyclk_mhz = 810.0, - .socclk_mhz = 1000.0, - .dscclk_mhz = 367.0, - .dram_speed_mts = 16000.0, - }, - { - .state = 4, - .dcfclk_mhz = 1200.0, - .fabricclk_mhz = 1200.0, - .dispclk_mhz = 1284.0, - .dppclk_mhz = 1284.0, - .phyclk_mhz = 810.0, - .socclk_mhz = 1200.0, - .dscclk_mhz = 428.0, - .dram_speed_mts = 16000.0, - }, - /*Extra state, no dispclk ramping*/ - { - .state = 5, - .dcfclk_mhz = 1200.0, - .fabricclk_mhz = 1200.0, - .dispclk_mhz = 1284.0, - .dppclk_mhz = 1284.0, - .phyclk_mhz = 810.0, - .socclk_mhz = 1200.0, - .dscclk_mhz = 428.0, - .dram_speed_mts = 16000.0, - }, - }, - .num_states = 5, - .sr_exit_time_us = 8.6, - .sr_enter_plus_exit_time_us = 10.9, - .urgent_latency_us = 4.0, - .urgent_latency_pixel_data_only_us = 4.0, - .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, - .urgent_latency_vm_data_only_us = 4.0, - .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, - .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, - .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, - .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 40.0, - .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 40.0, - .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0, - .max_avg_sdp_bw_use_normal_percent = 40.0, - .max_avg_dram_bw_use_normal_percent = 40.0, - .writeback_latency_us = 12.0, - .ideal_dram_bw_after_urgent_percent = 40.0, - .max_request_size_bytes = 256, - .dram_channel_width_bytes = 2, - .fabric_datapath_to_dcn_data_return_bytes = 64, - .dcn_downspread_percent = 0.5, - .downspread_percent = 0.38, - .dram_page_open_time_ns = 50.0, - .dram_rw_turnaround_time_ns = 17.5, - .dram_return_buffer_per_channel_bytes = 8192, - .round_trip_ping_latency_dcfclk_cycles = 131, - .urgent_out_of_order_return_per_channel_bytes = 256, - .channel_interleave_bytes = 256, - .num_banks = 8, - .num_chans = 16, - .vmm_page_size_bytes = 4096, - .dram_clock_change_latency_us = 404.0, - .dummy_pstate_latency_us = 5.0, - .writeback_dram_clock_change_latency_us = 23.0, - .return_bus_width_bytes = 64, - .dispclk_dppclk_vco_speed_mhz = 3850, - .xfc_bus_transport_time_us = 20, - .xfc_xbuf_latency_tolerance_us = 4, - .use_urgent_burst_bw = 0 -}; - -static struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv14_soc = { - .clock_limits = { - { - .state = 0, - .dcfclk_mhz = 560.0, - .fabricclk_mhz = 560.0, - .dispclk_mhz = 513.0, - .dppclk_mhz = 513.0, - .phyclk_mhz = 540.0, - .socclk_mhz = 560.0, - .dscclk_mhz = 171.0, - .dram_speed_mts = 8960.0, - }, - { - .state = 1, - .dcfclk_mhz = 694.0, - .fabricclk_mhz = 694.0, - .dispclk_mhz = 642.0, - .dppclk_mhz = 642.0, - .phyclk_mhz = 600.0, - .socclk_mhz = 694.0, - .dscclk_mhz = 214.0, - .dram_speed_mts = 11104.0, - }, - { - .state = 2, - .dcfclk_mhz = 875.0, - .fabricclk_mhz = 875.0, - .dispclk_mhz = 734.0, - .dppclk_mhz = 734.0, - .phyclk_mhz = 810.0, - .socclk_mhz = 875.0, - .dscclk_mhz = 245.0, - .dram_speed_mts = 14000.0, - }, - { - .state = 3, - .dcfclk_mhz = 1000.0, - .fabricclk_mhz = 1000.0, - .dispclk_mhz = 1100.0, - .dppclk_mhz = 1100.0, - .phyclk_mhz = 810.0, - .socclk_mhz = 1000.0, - .dscclk_mhz = 367.0, - .dram_speed_mts = 16000.0, - }, - { - .state = 4, - .dcfclk_mhz = 1200.0, - .fabricclk_mhz = 1200.0, - .dispclk_mhz = 1284.0, - .dppclk_mhz = 1284.0, - .phyclk_mhz = 810.0, - .socclk_mhz = 1200.0, - .dscclk_mhz = 428.0, - .dram_speed_mts = 16000.0, - }, - /*Extra state, no dispclk ramping*/ - { - .state = 5, - .dcfclk_mhz = 1200.0, - .fabricclk_mhz = 1200.0, - .dispclk_mhz = 1284.0, - .dppclk_mhz = 1284.0, - .phyclk_mhz = 810.0, - .socclk_mhz = 1200.0, - .dscclk_mhz = 428.0, - .dram_speed_mts = 16000.0, - }, - }, - .num_states = 5, - .sr_exit_time_us = 11.6, - .sr_enter_plus_exit_time_us = 13.9, - .urgent_latency_us = 4.0, - .urgent_latency_pixel_data_only_us = 4.0, - .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, - .urgent_latency_vm_data_only_us = 4.0, - .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, - .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, - .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, - .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 40.0, - .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 40.0, - .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0, - .max_avg_sdp_bw_use_normal_percent = 40.0, - .max_avg_dram_bw_use_normal_percent = 40.0, - .writeback_latency_us = 12.0, - .ideal_dram_bw_after_urgent_percent = 40.0, - .max_request_size_bytes = 256, - .dram_channel_width_bytes = 2, - .fabric_datapath_to_dcn_data_return_bytes = 64, - .dcn_downspread_percent = 0.5, - .downspread_percent = 0.38, - .dram_page_open_time_ns = 50.0, - .dram_rw_turnaround_time_ns = 17.5, - .dram_return_buffer_per_channel_bytes = 8192, - .round_trip_ping_latency_dcfclk_cycles = 131, - .urgent_out_of_order_return_per_channel_bytes = 256, - .channel_interleave_bytes = 256, - .num_banks = 8, - .num_chans = 8, - .vmm_page_size_bytes = 4096, - .dram_clock_change_latency_us = 404.0, - .dummy_pstate_latency_us = 5.0, - .writeback_dram_clock_change_latency_us = 23.0, - .return_bus_width_bytes = 64, - .dispclk_dppclk_vco_speed_mhz = 3850, - .xfc_bus_transport_time_us = 20, - .xfc_xbuf_latency_tolerance_us = 4, - .use_urgent_burst_bw = 0 -}; - -static struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv12_soc = { 0 }; - #ifndef mmDP0_DP_DPHY_INTERNAL_CTRL #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f #define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 @@ -1810,69 +1448,6 @@ enum dc_status dcn20_remove_stream_from_ctx(struct dc *dc, struct dc_state *new_ return result; } - -static void swizzle_to_dml_params( - enum swizzle_mode_values swizzle, - unsigned int *sw_mode) -{ - switch (swizzle) { - case DC_SW_LINEAR: - *sw_mode = dm_sw_linear; - break; - case DC_SW_4KB_S: - *sw_mode = dm_sw_4kb_s; - break; - case DC_SW_4KB_S_X: - *sw_mode = dm_sw_4kb_s_x; - break; - case DC_SW_4KB_D: - *sw_mode = dm_sw_4kb_d; - break; - case DC_SW_4KB_D_X: - *sw_mode = dm_sw_4kb_d_x; - break; - case DC_SW_64KB_S: - *sw_mode = dm_sw_64kb_s; - break; - case DC_SW_64KB_S_X: - *sw_mode = dm_sw_64kb_s_x; - break; - case DC_SW_64KB_S_T: - *sw_mode = dm_sw_64kb_s_t; - break; - case DC_SW_64KB_D: - *sw_mode = dm_sw_64kb_d; - break; - case DC_SW_64KB_D_X: - *sw_mode = dm_sw_64kb_d_x; - break; - case DC_SW_64KB_D_T: - *sw_mode = dm_sw_64kb_d_t; - break; - case DC_SW_64KB_R_X: - *sw_mode = dm_sw_64kb_r_x; - break; - case DC_SW_VAR_S: - *sw_mode = dm_sw_var_s; - break; - case DC_SW_VAR_S_X: - *sw_mode = dm_sw_var_s_x; - break; - case DC_SW_VAR_D: - *sw_mode = dm_sw_var_d; - break; - case DC_SW_VAR_D_X: - *sw_mode = dm_sw_var_d_x; - break; - case DC_SW_VAR_R_X: - *sw_mode = dm_sw_var_r_x; - break; - default: - ASSERT(0); /* Not supported */ - break; - } -} - bool dcn20_split_stream_for_odm( const struct dc *dc, struct resource_context *res_ctx, @@ -1988,394 +1563,6 @@ void dcn20_split_stream_for_mpc( ASSERT(primary_pipe->plane_state); } -int dcn20_populate_dml_pipes_from_context( - struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - bool fast_validate) -{ - int pipe_cnt, i; - bool synchronized_vblank = true; - struct resource_context *res_ctx = &context->res_ctx; - - for (i = 0, pipe_cnt = -1; i < dc->res_pool->pipe_count; i++) { - if (!res_ctx->pipe_ctx[i].stream) - continue; - - if (pipe_cnt < 0) { - pipe_cnt = i; - continue; - } - - if (res_ctx->pipe_ctx[pipe_cnt].stream == res_ctx->pipe_ctx[i].stream) - continue; - - if (dc->debug.disable_timing_sync || - (!resource_are_streams_timing_synchronizable( - res_ctx->pipe_ctx[pipe_cnt].stream, - res_ctx->pipe_ctx[i].stream) && - !resource_are_vblanks_synchronizable( - res_ctx->pipe_ctx[pipe_cnt].stream, - res_ctx->pipe_ctx[i].stream))) { - synchronized_vblank = false; - break; - } - } - - for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { - struct dc_crtc_timing *timing = &res_ctx->pipe_ctx[i].stream->timing; - unsigned int v_total; - unsigned int front_porch; - int output_bpc; - struct audio_check aud_check = {0}; - - if (!res_ctx->pipe_ctx[i].stream) - continue; - - v_total = timing->v_total; - front_porch = timing->v_front_porch; - - /* todo: - pipes[pipe_cnt].pipe.src.dynamic_metadata_enable = 0; - pipes[pipe_cnt].pipe.src.dcc = 0; - pipes[pipe_cnt].pipe.src.vm = 0;*/ - - pipes[pipe_cnt].clks_cfg.refclk_mhz = dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000.0; - - pipes[pipe_cnt].dout.dsc_enable = res_ctx->pipe_ctx[i].stream->timing.flags.DSC; - /* todo: rotation?*/ - pipes[pipe_cnt].dout.dsc_slices = res_ctx->pipe_ctx[i].stream->timing.dsc_cfg.num_slices_h; - if (res_ctx->pipe_ctx[i].stream->use_dynamic_meta) { - pipes[pipe_cnt].pipe.src.dynamic_metadata_enable = true; - /* 1/2 vblank */ - pipes[pipe_cnt].pipe.src.dynamic_metadata_lines_before_active = - (v_total - timing->v_addressable - - timing->v_border_top - timing->v_border_bottom) / 2; - /* 36 bytes dp, 32 hdmi */ - pipes[pipe_cnt].pipe.src.dynamic_metadata_xmit_bytes = - dc_is_dp_signal(res_ctx->pipe_ctx[i].stream->signal) ? 36 : 32; - } - pipes[pipe_cnt].pipe.src.dcc = false; - pipes[pipe_cnt].pipe.src.dcc_rate = 1; - pipes[pipe_cnt].pipe.dest.synchronized_vblank_all_planes = synchronized_vblank; - pipes[pipe_cnt].pipe.dest.hblank_start = timing->h_total - timing->h_front_porch; - pipes[pipe_cnt].pipe.dest.hblank_end = pipes[pipe_cnt].pipe.dest.hblank_start - - timing->h_addressable - - timing->h_border_left - - timing->h_border_right; - pipes[pipe_cnt].pipe.dest.vblank_start = v_total - front_porch; - pipes[pipe_cnt].pipe.dest.vblank_end = pipes[pipe_cnt].pipe.dest.vblank_start - - timing->v_addressable - - timing->v_border_top - - timing->v_border_bottom; - pipes[pipe_cnt].pipe.dest.htotal = timing->h_total; - pipes[pipe_cnt].pipe.dest.vtotal = v_total; - pipes[pipe_cnt].pipe.dest.hactive = - timing->h_addressable + timing->h_border_left + timing->h_border_right; - pipes[pipe_cnt].pipe.dest.vactive = - timing->v_addressable + timing->v_border_top + timing->v_border_bottom; - pipes[pipe_cnt].pipe.dest.interlaced = timing->flags.INTERLACE; - pipes[pipe_cnt].pipe.dest.pixel_rate_mhz = timing->pix_clk_100hz/10000.0; - if (timing->timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) - pipes[pipe_cnt].pipe.dest.pixel_rate_mhz *= 2; - pipes[pipe_cnt].pipe.dest.otg_inst = res_ctx->pipe_ctx[i].stream_res.tg->inst; - pipes[pipe_cnt].dout.dp_lanes = 4; - pipes[pipe_cnt].dout.is_virtual = 0; - pipes[pipe_cnt].pipe.dest.vtotal_min = res_ctx->pipe_ctx[i].stream->adjust.v_total_min; - pipes[pipe_cnt].pipe.dest.vtotal_max = res_ctx->pipe_ctx[i].stream->adjust.v_total_max; - switch (get_num_odm_splits(&res_ctx->pipe_ctx[i])) { - case 1: - pipes[pipe_cnt].pipe.dest.odm_combine = dm_odm_combine_mode_2to1; - break; - case 3: - pipes[pipe_cnt].pipe.dest.odm_combine = dm_odm_combine_mode_4to1; - break; - default: - pipes[pipe_cnt].pipe.dest.odm_combine = dm_odm_combine_mode_disabled; - } - pipes[pipe_cnt].pipe.src.hsplit_grp = res_ctx->pipe_ctx[i].pipe_idx; - if (res_ctx->pipe_ctx[i].top_pipe && res_ctx->pipe_ctx[i].top_pipe->plane_state - == res_ctx->pipe_ctx[i].plane_state) { - struct pipe_ctx *first_pipe = res_ctx->pipe_ctx[i].top_pipe; - int split_idx = 0; - - while (first_pipe->top_pipe && first_pipe->top_pipe->plane_state - == res_ctx->pipe_ctx[i].plane_state) { - first_pipe = first_pipe->top_pipe; - split_idx++; - } - /* Treat 4to1 mpc combine as an mpo of 2 2-to-1 combines */ - if (split_idx == 0) - pipes[pipe_cnt].pipe.src.hsplit_grp = first_pipe->pipe_idx; - else if (split_idx == 1) - pipes[pipe_cnt].pipe.src.hsplit_grp = res_ctx->pipe_ctx[i].pipe_idx; - else if (split_idx == 2) - pipes[pipe_cnt].pipe.src.hsplit_grp = res_ctx->pipe_ctx[i].top_pipe->pipe_idx; - } else if (res_ctx->pipe_ctx[i].prev_odm_pipe) { - struct pipe_ctx *first_pipe = res_ctx->pipe_ctx[i].prev_odm_pipe; - - while (first_pipe->prev_odm_pipe) - first_pipe = first_pipe->prev_odm_pipe; - pipes[pipe_cnt].pipe.src.hsplit_grp = first_pipe->pipe_idx; - } - - switch (res_ctx->pipe_ctx[i].stream->signal) { - case SIGNAL_TYPE_DISPLAY_PORT_MST: - case SIGNAL_TYPE_DISPLAY_PORT: - pipes[pipe_cnt].dout.output_type = dm_dp; - break; - case SIGNAL_TYPE_EDP: - pipes[pipe_cnt].dout.output_type = dm_edp; - break; - case SIGNAL_TYPE_HDMI_TYPE_A: - case SIGNAL_TYPE_DVI_SINGLE_LINK: - case SIGNAL_TYPE_DVI_DUAL_LINK: - pipes[pipe_cnt].dout.output_type = dm_hdmi; - break; - default: - /* In case there is no signal, set dp with 4 lanes to allow max config */ - pipes[pipe_cnt].dout.is_virtual = 1; - pipes[pipe_cnt].dout.output_type = dm_dp; - pipes[pipe_cnt].dout.dp_lanes = 4; - } - - switch (res_ctx->pipe_ctx[i].stream->timing.display_color_depth) { - case COLOR_DEPTH_666: - output_bpc = 6; - break; - case COLOR_DEPTH_888: - output_bpc = 8; - break; - case COLOR_DEPTH_101010: - output_bpc = 10; - break; - case COLOR_DEPTH_121212: - output_bpc = 12; - break; - case COLOR_DEPTH_141414: - output_bpc = 14; - break; - case COLOR_DEPTH_161616: - output_bpc = 16; - break; - case COLOR_DEPTH_999: - output_bpc = 9; - break; - case COLOR_DEPTH_111111: - output_bpc = 11; - break; - default: - output_bpc = 8; - break; - } - - switch (res_ctx->pipe_ctx[i].stream->timing.pixel_encoding) { - case PIXEL_ENCODING_RGB: - case PIXEL_ENCODING_YCBCR444: - pipes[pipe_cnt].dout.output_format = dm_444; - pipes[pipe_cnt].dout.output_bpp = output_bpc * 3; - break; - case PIXEL_ENCODING_YCBCR420: - pipes[pipe_cnt].dout.output_format = dm_420; - pipes[pipe_cnt].dout.output_bpp = (output_bpc * 3.0) / 2; - break; - case PIXEL_ENCODING_YCBCR422: - if (res_ctx->pipe_ctx[i].stream->timing.flags.DSC && - !res_ctx->pipe_ctx[i].stream->timing.dsc_cfg.ycbcr422_simple) - pipes[pipe_cnt].dout.output_format = dm_n422; - else - pipes[pipe_cnt].dout.output_format = dm_s422; - pipes[pipe_cnt].dout.output_bpp = output_bpc * 2; - break; - default: - pipes[pipe_cnt].dout.output_format = dm_444; - pipes[pipe_cnt].dout.output_bpp = output_bpc * 3; - } - - if (res_ctx->pipe_ctx[i].stream->timing.flags.DSC) - pipes[pipe_cnt].dout.output_bpp = res_ctx->pipe_ctx[i].stream->timing.dsc_cfg.bits_per_pixel / 16.0; - - /* todo: default max for now, until there is logic reflecting this in dc*/ - pipes[pipe_cnt].dout.dsc_input_bpc = 12; - /*fill up the audio sample rate (unit in kHz)*/ - get_audio_check(&res_ctx->pipe_ctx[i].stream->audio_info, &aud_check); - pipes[pipe_cnt].dout.max_audio_sample_rate = aud_check.max_audiosample_rate / 1000; - /* - * For graphic plane, cursor number is 1, nv12 is 0 - * bw calculations due to cursor on/off - */ - if (res_ctx->pipe_ctx[i].plane_state && - res_ctx->pipe_ctx[i].plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) - pipes[pipe_cnt].pipe.src.num_cursors = 0; - else - pipes[pipe_cnt].pipe.src.num_cursors = dc->dml.ip.number_of_cursors; - - pipes[pipe_cnt].pipe.src.cur0_src_width = 256; - pipes[pipe_cnt].pipe.src.cur0_bpp = dm_cur_32bit; - - if (!res_ctx->pipe_ctx[i].plane_state) { - pipes[pipe_cnt].pipe.src.is_hsplit = pipes[pipe_cnt].pipe.dest.odm_combine != dm_odm_combine_mode_disabled; - pipes[pipe_cnt].pipe.src.source_scan = dm_horz; - pipes[pipe_cnt].pipe.src.sw_mode = dm_sw_4kb_s; - pipes[pipe_cnt].pipe.src.macro_tile_size = dm_64k_tile; - pipes[pipe_cnt].pipe.src.viewport_width = timing->h_addressable; - if (pipes[pipe_cnt].pipe.src.viewport_width > 1920) - pipes[pipe_cnt].pipe.src.viewport_width = 1920; - pipes[pipe_cnt].pipe.src.viewport_height = timing->v_addressable; - if (pipes[pipe_cnt].pipe.src.viewport_height > 1080) - pipes[pipe_cnt].pipe.src.viewport_height = 1080; - pipes[pipe_cnt].pipe.src.surface_height_y = pipes[pipe_cnt].pipe.src.viewport_height; - pipes[pipe_cnt].pipe.src.surface_width_y = pipes[pipe_cnt].pipe.src.viewport_width; - pipes[pipe_cnt].pipe.src.surface_height_c = pipes[pipe_cnt].pipe.src.viewport_height; - pipes[pipe_cnt].pipe.src.surface_width_c = pipes[pipe_cnt].pipe.src.viewport_width; - pipes[pipe_cnt].pipe.src.data_pitch = ((pipes[pipe_cnt].pipe.src.viewport_width + 255) / 256) * 256; - pipes[pipe_cnt].pipe.src.source_format = dm_444_32; - pipes[pipe_cnt].pipe.dest.recout_width = pipes[pipe_cnt].pipe.src.viewport_width; /*vp_width/hratio*/ - pipes[pipe_cnt].pipe.dest.recout_height = pipes[pipe_cnt].pipe.src.viewport_height; /*vp_height/vratio*/ - pipes[pipe_cnt].pipe.dest.full_recout_width = pipes[pipe_cnt].pipe.dest.recout_width; /*when is_hsplit != 1*/ - pipes[pipe_cnt].pipe.dest.full_recout_height = pipes[pipe_cnt].pipe.dest.recout_height; /*when is_hsplit != 1*/ - pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_16; - pipes[pipe_cnt].pipe.scale_ratio_depth.hscl_ratio = 1.0; - pipes[pipe_cnt].pipe.scale_ratio_depth.vscl_ratio = 1.0; - pipes[pipe_cnt].pipe.scale_ratio_depth.scl_enable = 0; /*Lb only or Full scl*/ - pipes[pipe_cnt].pipe.scale_taps.htaps = 1; - pipes[pipe_cnt].pipe.scale_taps.vtaps = 1; - pipes[pipe_cnt].pipe.dest.vtotal_min = v_total; - pipes[pipe_cnt].pipe.dest.vtotal_max = v_total; - - if (pipes[pipe_cnt].pipe.dest.odm_combine == dm_odm_combine_mode_2to1) { - pipes[pipe_cnt].pipe.src.viewport_width /= 2; - pipes[pipe_cnt].pipe.dest.recout_width /= 2; - } else if (pipes[pipe_cnt].pipe.dest.odm_combine == dm_odm_combine_mode_4to1) { - pipes[pipe_cnt].pipe.src.viewport_width /= 4; - pipes[pipe_cnt].pipe.dest.recout_width /= 4; - } - } else { - struct dc_plane_state *pln = res_ctx->pipe_ctx[i].plane_state; - struct scaler_data *scl = &res_ctx->pipe_ctx[i].plane_res.scl_data; - - pipes[pipe_cnt].pipe.src.immediate_flip = pln->flip_immediate; - pipes[pipe_cnt].pipe.src.is_hsplit = (res_ctx->pipe_ctx[i].bottom_pipe && res_ctx->pipe_ctx[i].bottom_pipe->plane_state == pln) - || (res_ctx->pipe_ctx[i].top_pipe && res_ctx->pipe_ctx[i].top_pipe->plane_state == pln) - || pipes[pipe_cnt].pipe.dest.odm_combine != dm_odm_combine_mode_disabled; - - /* stereo is not split */ - if (pln->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE || - pln->stereo_format == PLANE_STEREO_FORMAT_TOP_AND_BOTTOM) { - pipes[pipe_cnt].pipe.src.is_hsplit = false; - pipes[pipe_cnt].pipe.src.hsplit_grp = res_ctx->pipe_ctx[i].pipe_idx; - } - - pipes[pipe_cnt].pipe.src.source_scan = pln->rotation == ROTATION_ANGLE_90 - || pln->rotation == ROTATION_ANGLE_270 ? dm_vert : dm_horz; - pipes[pipe_cnt].pipe.src.viewport_y_y = scl->viewport.y; - pipes[pipe_cnt].pipe.src.viewport_y_c = scl->viewport_c.y; - pipes[pipe_cnt].pipe.src.viewport_width = scl->viewport.width; - pipes[pipe_cnt].pipe.src.viewport_width_c = scl->viewport_c.width; - pipes[pipe_cnt].pipe.src.viewport_height = scl->viewport.height; - pipes[pipe_cnt].pipe.src.viewport_height_c = scl->viewport_c.height; - pipes[pipe_cnt].pipe.src.viewport_width_max = pln->src_rect.width; - pipes[pipe_cnt].pipe.src.viewport_height_max = pln->src_rect.height; - pipes[pipe_cnt].pipe.src.surface_width_y = pln->plane_size.surface_size.width; - pipes[pipe_cnt].pipe.src.surface_height_y = pln->plane_size.surface_size.height; - pipes[pipe_cnt].pipe.src.surface_width_c = pln->plane_size.chroma_size.width; - pipes[pipe_cnt].pipe.src.surface_height_c = pln->plane_size.chroma_size.height; - if (pln->format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA - || pln->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { - pipes[pipe_cnt].pipe.src.data_pitch = pln->plane_size.surface_pitch; - pipes[pipe_cnt].pipe.src.data_pitch_c = pln->plane_size.chroma_pitch; - pipes[pipe_cnt].pipe.src.meta_pitch = pln->dcc.meta_pitch; - pipes[pipe_cnt].pipe.src.meta_pitch_c = pln->dcc.meta_pitch_c; - } else { - pipes[pipe_cnt].pipe.src.data_pitch = pln->plane_size.surface_pitch; - pipes[pipe_cnt].pipe.src.meta_pitch = pln->dcc.meta_pitch; - } - pipes[pipe_cnt].pipe.src.dcc = pln->dcc.enable; - pipes[pipe_cnt].pipe.dest.recout_width = scl->recout.width; - pipes[pipe_cnt].pipe.dest.recout_height = scl->recout.height; - pipes[pipe_cnt].pipe.dest.full_recout_height = scl->recout.height; - pipes[pipe_cnt].pipe.dest.full_recout_width = scl->recout.width; - if (pipes[pipe_cnt].pipe.dest.odm_combine == dm_odm_combine_mode_2to1) - pipes[pipe_cnt].pipe.dest.full_recout_width *= 2; - else if (pipes[pipe_cnt].pipe.dest.odm_combine == dm_odm_combine_mode_4to1) - pipes[pipe_cnt].pipe.dest.full_recout_width *= 4; - else { - struct pipe_ctx *split_pipe = res_ctx->pipe_ctx[i].bottom_pipe; - - while (split_pipe && split_pipe->plane_state == pln) { - pipes[pipe_cnt].pipe.dest.full_recout_width += split_pipe->plane_res.scl_data.recout.width; - split_pipe = split_pipe->bottom_pipe; - } - split_pipe = res_ctx->pipe_ctx[i].top_pipe; - while (split_pipe && split_pipe->plane_state == pln) { - pipes[pipe_cnt].pipe.dest.full_recout_width += split_pipe->plane_res.scl_data.recout.width; - split_pipe = split_pipe->top_pipe; - } - } - - pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_16; - pipes[pipe_cnt].pipe.scale_ratio_depth.hscl_ratio = (double) scl->ratios.horz.value / (1ULL<<32); - pipes[pipe_cnt].pipe.scale_ratio_depth.hscl_ratio_c = (double) scl->ratios.horz_c.value / (1ULL<<32); - pipes[pipe_cnt].pipe.scale_ratio_depth.vscl_ratio = (double) scl->ratios.vert.value / (1ULL<<32); - pipes[pipe_cnt].pipe.scale_ratio_depth.vscl_ratio_c = (double) scl->ratios.vert_c.value / (1ULL<<32); - pipes[pipe_cnt].pipe.scale_ratio_depth.scl_enable = - scl->ratios.vert.value != dc_fixpt_one.value - || scl->ratios.horz.value != dc_fixpt_one.value - || scl->ratios.vert_c.value != dc_fixpt_one.value - || scl->ratios.horz_c.value != dc_fixpt_one.value /*Lb only or Full scl*/ - || dc->debug.always_scale; /*support always scale*/ - pipes[pipe_cnt].pipe.scale_taps.htaps = scl->taps.h_taps; - pipes[pipe_cnt].pipe.scale_taps.htaps_c = scl->taps.h_taps_c; - pipes[pipe_cnt].pipe.scale_taps.vtaps = scl->taps.v_taps; - pipes[pipe_cnt].pipe.scale_taps.vtaps_c = scl->taps.v_taps_c; - - pipes[pipe_cnt].pipe.src.macro_tile_size = - swizzle_mode_to_macro_tile_size(pln->tiling_info.gfx9.swizzle); - swizzle_to_dml_params(pln->tiling_info.gfx9.swizzle, - &pipes[pipe_cnt].pipe.src.sw_mode); - - switch (pln->format) { - case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: - case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: - pipes[pipe_cnt].pipe.src.source_format = dm_420_8; - break; - case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: - case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: - pipes[pipe_cnt].pipe.src.source_format = dm_420_10; - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: - case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: - pipes[pipe_cnt].pipe.src.source_format = dm_444_64; - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: - case SURFACE_PIXEL_FORMAT_GRPH_RGB565: - pipes[pipe_cnt].pipe.src.source_format = dm_444_16; - break; - case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: - pipes[pipe_cnt].pipe.src.source_format = dm_444_8; - break; - case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA: - pipes[pipe_cnt].pipe.src.source_format = dm_rgbe_alpha; - break; - default: - pipes[pipe_cnt].pipe.src.source_format = dm_444_32; - break; - } - } - - pipe_cnt++; - } - - /* populate writeback information */ - DC_FP_START(); - dc->res_pool->funcs->populate_dml_writeback_from_context(dc, res_ctx, pipes); - DC_FP_END(); - - return pipe_cnt; -} - unsigned int dcn20_calc_max_scaled_time( unsigned int time_per_pixel, enum mmhubbub_wbif_mode mode, @@ -2413,7 +1600,7 @@ void dcn20_set_mcif_arb_params( { enum mmhubbub_wbif_mode wbif_mode; struct mcif_arb_params *wb_arb_params; - int i, j, k, dwb_pipe; + int i, j, dwb_pipe; /* Writeback MCIF_WB arbitration parameters */ dwb_pipe = 0; @@ -2437,11 +1624,10 @@ void dcn20_set_mcif_arb_params( } else wbif_mode = PACKED_444; - for (k = 0; k < sizeof(wb_arb_params->cli_watermark)/sizeof(wb_arb_params->cli_watermark[0]); k++) { - wb_arb_params->cli_watermark[k] = get_wm_writeback_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - wb_arb_params->pstate_watermark[k] = get_wm_writeback_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - } - wb_arb_params->time_per_pixel = 16.0 * 1000 / (context->res_ctx.pipe_ctx[i].stream->phy_pix_clk / 1000); /* 4 bit fraction, ms */ + DC_FP_START(); + dcn20_fpu_set_wb_arb_params(wb_arb_params, context, pipes, pipe_cnt, i); + DC_FP_END(); + wb_arb_params->slice_lines = 32; wb_arb_params->arbitration_slice = 2; wb_arb_params->max_scaled_time = dcn20_calc_max_scaled_time(wb_arb_params->time_per_pixel, @@ -2808,8 +1994,11 @@ int dcn20_validate_apply_pipe_split_flags( } /* Adjust dppclk when split is forced, do not bother with dispclk */ - if (split[i] != 0 && v->NoOfDPP[vlevel][max_mpc_comb][pipe_idx] == 1) - v->RequiredDPPCLK[vlevel][max_mpc_comb][pipe_idx] /= 2; + if (split[i] != 0 && v->NoOfDPP[vlevel][max_mpc_comb][pipe_idx] == 1) { + DC_FP_START(); + dcn20_fpu_adjust_dppclk(v, vlevel, max_mpc_comb, pipe_idx, false); + DC_FP_END(); + } pipe_idx++; } @@ -2835,7 +2024,9 @@ bool dcn20_fast_validate_bw( dcn20_merge_pipes_for_validate(dc, context); + DC_FP_START(); pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); + DC_FP_END(); *pipe_cnt_out = pipe_cnt; @@ -2892,7 +2083,9 @@ bool dcn20_fast_validate_bw( hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe); ASSERT(hsplit_pipe); if (!hsplit_pipe) { - context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx] *= 2; + DC_FP_START(); + dcn20_fpu_adjust_dppclk(&context->bw_ctx.dml.vba, vlevel, context->bw_ctx.dml.vba.maxMpcComb, pipe_idx, true); + DC_FP_END(); continue; } if (context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) { @@ -2934,369 +2127,6 @@ bool dcn20_fast_validate_bw( return out; } -static void dcn20_calculate_wm( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int *out_pipe_cnt, - int *pipe_split_from, - int vlevel, - bool fast_validate) -{ - int pipe_cnt, i, pipe_idx; - - for (i = 0, pipe_idx = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { - if (!context->res_ctx.pipe_ctx[i].stream) - continue; - - pipes[pipe_cnt].clks_cfg.refclk_mhz = dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000.0; - pipes[pipe_cnt].clks_cfg.dispclk_mhz = context->bw_ctx.dml.vba.RequiredDISPCLK[vlevel][context->bw_ctx.dml.vba.maxMpcComb]; - - if (pipe_split_from[i] < 0) { - pipes[pipe_cnt].clks_cfg.dppclk_mhz = - context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx]; - if (context->bw_ctx.dml.vba.BlendingAndTiming[pipe_idx] == pipe_idx) - pipes[pipe_cnt].pipe.dest.odm_combine = - context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]; - else - pipes[pipe_cnt].pipe.dest.odm_combine = 0; - pipe_idx++; - } else { - pipes[pipe_cnt].clks_cfg.dppclk_mhz = - context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_split_from[i]]; - if (context->bw_ctx.dml.vba.BlendingAndTiming[pipe_split_from[i]] == pipe_split_from[i]) - pipes[pipe_cnt].pipe.dest.odm_combine = - context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_split_from[i]]; - else - pipes[pipe_cnt].pipe.dest.odm_combine = 0; - } - - if (dc->config.forced_clocks) { - pipes[pipe_cnt].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz; - pipes[pipe_cnt].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz; - } - if (dc->debug.min_disp_clk_khz > pipes[pipe_cnt].clks_cfg.dispclk_mhz * 1000) - pipes[pipe_cnt].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0; - if (dc->debug.min_dpp_clk_khz > pipes[pipe_cnt].clks_cfg.dppclk_mhz * 1000) - pipes[pipe_cnt].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0; - - pipe_cnt++; - } - - if (pipe_cnt != pipe_idx) { - if (dc->res_pool->funcs->populate_dml_pipes) - pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, - context, pipes, fast_validate); - else - pipe_cnt = dcn20_populate_dml_pipes_from_context(dc, - context, pipes, fast_validate); - } - - *out_pipe_cnt = pipe_cnt; - - pipes[0].clks_cfg.voltage = vlevel; - pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].dcfclk_mhz; - pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].socclk_mhz; - - /* only pipe 0 is read for voltage and dcf/soc clocks */ - if (vlevel < 1) { - pipes[0].clks_cfg.voltage = 1; - pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[1].dcfclk_mhz; - pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[1].socclk_mhz; - } - context->bw_ctx.bw.dcn.watermarks.b.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - - if (vlevel < 2) { - pipes[0].clks_cfg.voltage = 2; - pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[2].dcfclk_mhz; - pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[2].socclk_mhz; - } - context->bw_ctx.bw.dcn.watermarks.c.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - - if (vlevel < 3) { - pipes[0].clks_cfg.voltage = 3; - pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[2].dcfclk_mhz; - pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[2].socclk_mhz; - } - context->bw_ctx.bw.dcn.watermarks.d.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - - pipes[0].clks_cfg.voltage = vlevel; - pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].dcfclk_mhz; - pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].socclk_mhz; - context->bw_ctx.bw.dcn.watermarks.a.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; -} - -static bool is_dtbclk_required(struct dc *dc, struct dc_state *context) -{ - int i; - for (i = 0; i < dc->res_pool->pipe_count; i++) { - if (!context->res_ctx.pipe_ctx[i].stream) - continue; - if (is_dp_128b_132b_signal(&context->res_ctx.pipe_ctx[i])) - return true; - } - return false; -} - -static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struct dc_state *context) -{ - int plane_count; - int i; - - plane_count = 0; - for (i = 0; i < dc->res_pool->pipe_count; i++) { - if (context->res_ctx.pipe_ctx[i].plane_state) - plane_count++; - } - - /* - * Zstate is allowed in following scenarios: - * 1. Single eDP with PSR enabled - * 2. 0 planes (No memory requests) - * 3. Single eDP without PSR but > 5ms stutter period - */ - if (plane_count == 0) - return DCN_ZSTATE_SUPPORT_ALLOW; - else if (context->stream_count == 1 && context->streams[0]->signal == SIGNAL_TYPE_EDP) { - struct dc_link *link = context->streams[0]->sink->link; - - /* zstate only supported on PWRSEQ0 */ - if (link->link_index != 0) - return DCN_ZSTATE_SUPPORT_DISALLOW; - - if (context->bw_ctx.dml.vba.StutterPeriod > 5000.0) - return DCN_ZSTATE_SUPPORT_ALLOW; - else if (link->psr_settings.psr_version == DC_PSR_VERSION_1 && !dc->debug.disable_psr) - return DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY; - else - return DCN_ZSTATE_SUPPORT_DISALLOW; - } else - return DCN_ZSTATE_SUPPORT_DISALLOW; -} - -void dcn20_calculate_dlg_params( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int pipe_cnt, - int vlevel) -{ - int i, pipe_idx; - - /* Writeback MCIF_WB arbitration parameters */ - dc->res_pool->funcs->set_mcif_arb_params(dc, context, pipes, pipe_cnt); - - context->bw_ctx.bw.dcn.clk.dispclk_khz = context->bw_ctx.dml.vba.DISPCLK * 1000; - context->bw_ctx.bw.dcn.clk.dcfclk_khz = context->bw_ctx.dml.vba.DCFCLK * 1000; - context->bw_ctx.bw.dcn.clk.socclk_khz = context->bw_ctx.dml.vba.SOCCLK * 1000; - context->bw_ctx.bw.dcn.clk.dramclk_khz = context->bw_ctx.dml.vba.DRAMSpeed * 1000 / 16; - - if (dc->debug.min_dram_clk_khz > context->bw_ctx.bw.dcn.clk.dramclk_khz) - context->bw_ctx.bw.dcn.clk.dramclk_khz = dc->debug.min_dram_clk_khz; - - context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = context->bw_ctx.dml.vba.DCFCLKDeepSleep * 1000; - context->bw_ctx.bw.dcn.clk.fclk_khz = context->bw_ctx.dml.vba.FabricClock * 1000; - context->bw_ctx.bw.dcn.clk.p_state_change_support = - context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] - != dm_dram_clock_change_unsupported; - context->bw_ctx.bw.dcn.clk.dppclk_khz = 0; - - context->bw_ctx.bw.dcn.clk.zstate_support = decide_zstate_support(dc, context); - - context->bw_ctx.bw.dcn.clk.dtbclk_en = is_dtbclk_required(dc, context); - - if (context->bw_ctx.bw.dcn.clk.dispclk_khz < dc->debug.min_disp_clk_khz) - context->bw_ctx.bw.dcn.clk.dispclk_khz = dc->debug.min_disp_clk_khz; - - for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { - if (!context->res_ctx.pipe_ctx[i].stream) - continue; - pipes[pipe_idx].pipe.dest.vstartup_start = get_vstartup(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); - pipes[pipe_idx].pipe.dest.vupdate_offset = get_vupdate_offset(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); - pipes[pipe_idx].pipe.dest.vupdate_width = get_vupdate_width(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); - pipes[pipe_idx].pipe.dest.vready_offset = get_vready_offset(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); - context->res_ctx.pipe_ctx[i].det_buffer_size_kb = context->bw_ctx.dml.ip.det_buffer_size_kbytes; - context->res_ctx.pipe_ctx[i].unbounded_req = pipes[pipe_idx].pipe.src.unbounded_req_mode; - - if (context->bw_ctx.bw.dcn.clk.dppclk_khz < pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000) - context->bw_ctx.bw.dcn.clk.dppclk_khz = pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000; - context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz = - pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000; - context->res_ctx.pipe_ctx[i].pipe_dlg_param = pipes[pipe_idx].pipe.dest; - pipe_idx++; - } - /*save a original dppclock copy*/ - context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz; - context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz; - context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = context->bw_ctx.dml.soc.clock_limits[vlevel].dppclk_mhz * 1000; - context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = context->bw_ctx.dml.soc.clock_limits[vlevel].dispclk_mhz * 1000; - - context->bw_ctx.bw.dcn.compbuf_size_kb = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes - - context->bw_ctx.dml.ip.det_buffer_size_kbytes * pipe_idx; - - for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { - bool cstate_en = context->bw_ctx.dml.vba.PrefetchMode[vlevel][context->bw_ctx.dml.vba.maxMpcComb] != 2; - - if (!context->res_ctx.pipe_ctx[i].stream) - continue; - - if (dc->ctx->dce_version == DCN_VERSION_2_01) - cstate_en = false; - - context->bw_ctx.dml.funcs.rq_dlg_get_dlg_reg(&context->bw_ctx.dml, - &context->res_ctx.pipe_ctx[i].dlg_regs, - &context->res_ctx.pipe_ctx[i].ttu_regs, - pipes, - pipe_cnt, - pipe_idx, - cstate_en, - context->bw_ctx.bw.dcn.clk.p_state_change_support, - false, false, true); - - context->bw_ctx.dml.funcs.rq_dlg_get_rq_reg(&context->bw_ctx.dml, - &context->res_ctx.pipe_ctx[i].rq_regs, - &pipes[pipe_idx].pipe); - pipe_idx++; - } -} - -static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *context, - bool fast_validate) -{ - bool out = false; - - BW_VAL_TRACE_SETUP(); - - int vlevel = 0; - int pipe_split_from[MAX_PIPES]; - int pipe_cnt = 0; - display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_ATOMIC); - DC_LOGGER_INIT(dc->ctx->logger); - - BW_VAL_TRACE_COUNT(); - - out = dcn20_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel, fast_validate); - - if (pipe_cnt == 0) - goto validate_out; - - if (!out) - goto validate_fail; - - BW_VAL_TRACE_END_VOLTAGE_LEVEL(); - - if (fast_validate) { - BW_VAL_TRACE_SKIP(fast); - goto validate_out; - } - - dcn20_calculate_wm(dc, context, pipes, &pipe_cnt, pipe_split_from, vlevel, fast_validate); - dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); - - BW_VAL_TRACE_END_WATERMARKS(); - - goto validate_out; - -validate_fail: - DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n", - dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states])); - - BW_VAL_TRACE_SKIP(fail); - out = false; - -validate_out: - kfree(pipes); - - BW_VAL_TRACE_FINISH(); - - return out; -} - -/* - * This must be noinline to ensure anything that deals with FP registers - * is contained within this call; previously our compiling with hard-float - * would result in fp instructions being emitted outside of the boundaries - * of the DC_FP_START/END macros, which makes sense as the compiler has no - * idea about what is wrapped and what is not - * - * This is largely just a workaround to avoid breakage introduced with 5.6, - * ideally all fp-using code should be moved into its own file, only that - * should be compiled with hard-float, and all code exported from there - * should be strictly wrapped with DC_FP_START/END - */ -static noinline bool dcn20_validate_bandwidth_fp(struct dc *dc, - struct dc_state *context, bool fast_validate) -{ - bool voltage_supported = false; - bool full_pstate_supported = false; - bool dummy_pstate_supported = false; - double p_state_latency_us; - - p_state_latency_us = context->bw_ctx.dml.soc.dram_clock_change_latency_us; - context->bw_ctx.dml.soc.disable_dram_clock_change_vactive_support = - dc->debug.disable_dram_clock_change_vactive_support; - context->bw_ctx.dml.soc.allow_dram_clock_one_display_vactive = - dc->debug.enable_dram_clock_change_one_display_vactive; - - /*Unsafe due to current pipe merge and split logic*/ - ASSERT(context != dc->current_state); - - if (fast_validate) { - return dcn20_validate_bandwidth_internal(dc, context, true); - } - - // Best case, we support full UCLK switch latency - voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false); - full_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support; - - if (context->bw_ctx.dml.soc.dummy_pstate_latency_us == 0 || - (voltage_supported && full_pstate_supported)) { - context->bw_ctx.bw.dcn.clk.p_state_change_support = full_pstate_supported; - goto restore_dml_state; - } - - // Fallback: Try to only support G6 temperature read latency - context->bw_ctx.dml.soc.dram_clock_change_latency_us = context->bw_ctx.dml.soc.dummy_pstate_latency_us; - - voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false); - dummy_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support; - - if (voltage_supported && (dummy_pstate_supported || !(context->stream_count))) { - context->bw_ctx.bw.dcn.clk.p_state_change_support = false; - goto restore_dml_state; - } - - // ERROR: fallback is supposed to always work. - ASSERT(false); - -restore_dml_state: - context->bw_ctx.dml.soc.dram_clock_change_latency_us = p_state_latency_us; - return voltage_supported; -} - bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, bool fast_validate) { @@ -3464,170 +2294,6 @@ static void dcn20_pp_smu_destroy(struct pp_smu_funcs **pp_smu) } } -void dcn20_cap_soc_clocks( - struct _vcs_dpi_soc_bounding_box_st *bb, - struct pp_smu_nv_clock_table max_clocks) -{ - int i; - - // First pass - cap all clocks higher than the reported max - for (i = 0; i < bb->num_states; i++) { - if ((bb->clock_limits[i].dcfclk_mhz > (max_clocks.dcfClockInKhz / 1000)) - && max_clocks.dcfClockInKhz != 0) - bb->clock_limits[i].dcfclk_mhz = (max_clocks.dcfClockInKhz / 1000); - - if ((bb->clock_limits[i].dram_speed_mts > (max_clocks.uClockInKhz / 1000) * 16) - && max_clocks.uClockInKhz != 0) - bb->clock_limits[i].dram_speed_mts = (max_clocks.uClockInKhz / 1000) * 16; - - if ((bb->clock_limits[i].fabricclk_mhz > (max_clocks.fabricClockInKhz / 1000)) - && max_clocks.fabricClockInKhz != 0) - bb->clock_limits[i].fabricclk_mhz = (max_clocks.fabricClockInKhz / 1000); - - if ((bb->clock_limits[i].dispclk_mhz > (max_clocks.displayClockInKhz / 1000)) - && max_clocks.displayClockInKhz != 0) - bb->clock_limits[i].dispclk_mhz = (max_clocks.displayClockInKhz / 1000); - - if ((bb->clock_limits[i].dppclk_mhz > (max_clocks.dppClockInKhz / 1000)) - && max_clocks.dppClockInKhz != 0) - bb->clock_limits[i].dppclk_mhz = (max_clocks.dppClockInKhz / 1000); - - if ((bb->clock_limits[i].phyclk_mhz > (max_clocks.phyClockInKhz / 1000)) - && max_clocks.phyClockInKhz != 0) - bb->clock_limits[i].phyclk_mhz = (max_clocks.phyClockInKhz / 1000); - - if ((bb->clock_limits[i].socclk_mhz > (max_clocks.socClockInKhz / 1000)) - && max_clocks.socClockInKhz != 0) - bb->clock_limits[i].socclk_mhz = (max_clocks.socClockInKhz / 1000); - - if ((bb->clock_limits[i].dscclk_mhz > (max_clocks.dscClockInKhz / 1000)) - && max_clocks.dscClockInKhz != 0) - bb->clock_limits[i].dscclk_mhz = (max_clocks.dscClockInKhz / 1000); - } - - // Second pass - remove all duplicate clock states - for (i = bb->num_states - 1; i > 1; i--) { - bool duplicate = true; - - if (bb->clock_limits[i-1].dcfclk_mhz != bb->clock_limits[i].dcfclk_mhz) - duplicate = false; - if (bb->clock_limits[i-1].dispclk_mhz != bb->clock_limits[i].dispclk_mhz) - duplicate = false; - if (bb->clock_limits[i-1].dppclk_mhz != bb->clock_limits[i].dppclk_mhz) - duplicate = false; - if (bb->clock_limits[i-1].dram_speed_mts != bb->clock_limits[i].dram_speed_mts) - duplicate = false; - if (bb->clock_limits[i-1].dscclk_mhz != bb->clock_limits[i].dscclk_mhz) - duplicate = false; - if (bb->clock_limits[i-1].fabricclk_mhz != bb->clock_limits[i].fabricclk_mhz) - duplicate = false; - if (bb->clock_limits[i-1].phyclk_mhz != bb->clock_limits[i].phyclk_mhz) - duplicate = false; - if (bb->clock_limits[i-1].socclk_mhz != bb->clock_limits[i].socclk_mhz) - duplicate = false; - - if (duplicate) - bb->num_states--; - } -} - -void dcn20_update_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb, - struct pp_smu_nv_clock_table *max_clocks, unsigned int *uclk_states, unsigned int num_states) -{ - struct _vcs_dpi_voltage_scaling_st calculated_states[DC__VOLTAGE_STATES]; - int i; - int num_calculated_states = 0; - int min_dcfclk = 0; - - if (num_states == 0) - return; - - memset(calculated_states, 0, sizeof(calculated_states)); - - if (dc->bb_overrides.min_dcfclk_mhz > 0) - min_dcfclk = dc->bb_overrides.min_dcfclk_mhz; - else { - if (ASICREV_IS_NAVI12_P(dc->ctx->asic_id.hw_internal_rev)) - min_dcfclk = 310; - else - // Accounting for SOC/DCF relationship, we can go as high as - // 506Mhz in Vmin. - min_dcfclk = 506; - } - - for (i = 0; i < num_states; i++) { - int min_fclk_required_by_uclk; - calculated_states[i].state = i; - calculated_states[i].dram_speed_mts = uclk_states[i] * 16 / 1000; - - // FCLK:UCLK ratio is 1.08 - min_fclk_required_by_uclk = div_u64(((unsigned long long)uclk_states[i]) * 1080, - 1000000); - - calculated_states[i].fabricclk_mhz = (min_fclk_required_by_uclk < min_dcfclk) ? - min_dcfclk : min_fclk_required_by_uclk; - - calculated_states[i].socclk_mhz = (calculated_states[i].fabricclk_mhz > max_clocks->socClockInKhz / 1000) ? - max_clocks->socClockInKhz / 1000 : calculated_states[i].fabricclk_mhz; - - calculated_states[i].dcfclk_mhz = (calculated_states[i].fabricclk_mhz > max_clocks->dcfClockInKhz / 1000) ? - max_clocks->dcfClockInKhz / 1000 : calculated_states[i].fabricclk_mhz; - - calculated_states[i].dispclk_mhz = max_clocks->displayClockInKhz / 1000; - calculated_states[i].dppclk_mhz = max_clocks->displayClockInKhz / 1000; - calculated_states[i].dscclk_mhz = max_clocks->displayClockInKhz / (1000 * 3); - - calculated_states[i].phyclk_mhz = max_clocks->phyClockInKhz / 1000; - - num_calculated_states++; - } - - calculated_states[num_calculated_states - 1].socclk_mhz = max_clocks->socClockInKhz / 1000; - calculated_states[num_calculated_states - 1].fabricclk_mhz = max_clocks->socClockInKhz / 1000; - calculated_states[num_calculated_states - 1].dcfclk_mhz = max_clocks->dcfClockInKhz / 1000; - - memcpy(bb->clock_limits, calculated_states, sizeof(bb->clock_limits)); - bb->num_states = num_calculated_states; - - // Duplicate the last state, DML always an extra state identical to max state to work - memcpy(&bb->clock_limits[num_calculated_states], &bb->clock_limits[num_calculated_states - 1], sizeof(struct _vcs_dpi_voltage_scaling_st)); - bb->clock_limits[num_calculated_states].state = bb->num_states; -} - -void dcn20_patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb) -{ - if ((int)(bb->sr_exit_time_us * 1000) != dc->bb_overrides.sr_exit_time_ns - && dc->bb_overrides.sr_exit_time_ns) { - bb->sr_exit_time_us = dc->bb_overrides.sr_exit_time_ns / 1000.0; - } - - if ((int)(bb->sr_enter_plus_exit_time_us * 1000) - != dc->bb_overrides.sr_enter_plus_exit_time_ns - && dc->bb_overrides.sr_enter_plus_exit_time_ns) { - bb->sr_enter_plus_exit_time_us = - dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0; - } - - if ((int)(bb->urgent_latency_us * 1000) != dc->bb_overrides.urgent_latency_ns - && dc->bb_overrides.urgent_latency_ns) { - bb->urgent_latency_us = dc->bb_overrides.urgent_latency_ns / 1000.0; - } - - if ((int)(bb->dram_clock_change_latency_us * 1000) - != dc->bb_overrides.dram_clock_change_latency_ns - && dc->bb_overrides.dram_clock_change_latency_ns) { - bb->dram_clock_change_latency_us = - dc->bb_overrides.dram_clock_change_latency_ns / 1000.0; - } - - if ((int)(bb->dummy_pstate_latency_us * 1000) - != dc->bb_overrides.dummy_clock_change_latency_ns - && dc->bb_overrides.dummy_clock_change_latency_ns) { - bb->dummy_pstate_latency_us = - dc->bb_overrides.dummy_clock_change_latency_ns / 1000.0; - } -} - static struct _vcs_dpi_soc_bounding_box_st *get_asic_rev_soc_bb( uint32_t hw_internal_rev) { @@ -3910,8 +2576,9 @@ static bool dcn20_resource_construct( ranges.reader_wm_sets[i].wm_inst = i; ranges.reader_wm_sets[i].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; ranges.reader_wm_sets[i].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; - ranges.reader_wm_sets[i].min_fill_clk_mhz = (i > 0) ? (loaded_bb->clock_limits[i - 1].dram_speed_mts / 16) + 1 : 0; - ranges.reader_wm_sets[i].max_fill_clk_mhz = loaded_bb->clock_limits[i].dram_speed_mts / 16; + DC_FP_START(); + dcn20_fpu_set_wm_ranges(i, &ranges, loaded_bb); + DC_FP_END(); ranges.num_reader_wm_sets = i + 1; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h index 6ec8ff45f0f79..7cbe1e9daa36e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h @@ -27,6 +27,7 @@ #define __DC_RESOURCE_DCN20_H__ #include "core_types.h" +#include "dml/dcn20/dcn20_fpu.h" #define TO_DCN20_RES_POOL(pool)\ container_of(pool, struct dcn20_resource_pool, base) @@ -35,6 +36,12 @@ struct dc; struct resource_pool; struct _vcs_dpi_display_pipe_params_st; +extern struct _vcs_dpi_ip_params_st dcn2_0_ip; +extern struct _vcs_dpi_ip_params_st dcn2_0_nv14_ip; +extern struct _vcs_dpi_soc_bounding_box_st dcn2_0_soc; +extern struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv14_soc; +extern struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv12_soc; + struct dcn20_resource_pool { struct resource_pool base; }; @@ -49,11 +56,7 @@ unsigned int dcn20_calc_max_scaled_time( unsigned int time_per_pixel, enum mmhubbub_wbif_mode mode, unsigned int urgent_watermark); -int dcn20_populate_dml_pipes_from_context( - struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - bool fast_validate); + struct pipe_ctx *dcn20_acquire_idle_pipe_for_layer( struct dc_state *state, const struct resource_pool *pool, @@ -79,7 +82,6 @@ struct dpp *dcn20_dpp_create( struct input_pixel_processor *dcn20_ipp_create( struct dc_context *ctx, uint32_t inst); - struct output_pixel_processor *dcn20_opp_create( struct dc_context *ctx, uint32_t inst); @@ -96,11 +98,6 @@ struct display_stream_compressor *dcn20_dsc_create( struct dc_context *ctx, uint32_t inst); void dcn20_dsc_destroy(struct display_stream_compressor **dsc); -void dcn20_cap_soc_clocks( - struct _vcs_dpi_soc_bounding_box_st *bb, - struct pp_smu_nv_clock_table max_clocks); -void dcn20_update_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb, - struct pp_smu_nv_clock_table *max_clocks, unsigned int *uclk_states, unsigned int num_states); struct hubp *dcn20_hubp_create( struct dc_context *ctx, uint32_t inst); @@ -158,11 +155,6 @@ bool dcn20_fast_validate_bw( int *pipe_split_from, int *vlevel_out, bool fast_validate); -void dcn20_calculate_dlg_params( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int pipe_cnt, - int vlevel); enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state *context, struct dc_stream_state *stream); enum dc_status dcn20_add_stream_to_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream); @@ -170,12 +162,5 @@ enum dc_status dcn20_add_dsc_to_stream_resource(struct dc *dc, struct dc_state * enum dc_status dcn20_remove_stream_from_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream); enum dc_status dcn20_patch_unknown_plane_state(struct dc_plane_state *plane_state); -void dcn20_patch_bounding_box( - struct dc *dc, - struct _vcs_dpi_soc_bounding_box_st *bb); -void dcn20_cap_soc_clocks( - struct _vcs_dpi_soc_bounding_box_st *bb, - struct pp_smu_nv_clock_table max_clocks); - #endif /* __DC_RESOURCE_DCN20_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index e5cc6bf45743a..116a8ccf6c938 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -1363,7 +1363,9 @@ static noinline bool dcn21_validate_bandwidth_fp(struct dc *dc, } dcn21_calculate_wm(dc, context, pipes, &pipe_cnt, pipe_split_from, vlevel, fast_validate); + DC_FP_START(); dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); + DC_FP_END(); BW_VAL_TRACE_END_WATERMARKS(); @@ -1902,9 +1904,13 @@ static int dcn21_populate_dml_pipes_from_context( display_e2e_pipe_params_st *pipes, bool fast_validate) { - uint32_t pipe_cnt = dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + uint32_t pipe_cnt; int i; + DC_FP_START(); + pipe_cnt = dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + DC_FP_END(); + for (i = 0; i < pipe_cnt; i++) { pipes[i].pipe.src.hostvm = dc->res_pool->hubbub->riommu_active; 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 f10f7a0ca02a0..e6a62cc75139b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -1462,7 +1462,9 @@ int dcn30_populate_dml_pipes_from_context( int i, pipe_cnt; struct resource_context *res_ctx = &context->res_ctx; + DC_FP_START(); dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + DC_FP_END(); for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { if (!res_ctx->pipe_ctx[i].stream) @@ -1731,7 +1733,10 @@ 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_END(); if (dc->ctx->dc_bios->funcs->get_soc_bb_info) { struct bp_soc_bb_info bb_info = {0}; @@ -2261,7 +2266,9 @@ static noinline void dcn30_calculate_wm_and_dlg_fp( pipe_idx++; } + DC_FP_START(); dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); + DC_FP_END(); if (!pstate_en) /* Restore full p-state latency */ 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 3c5efa61dff97..7dbe301a994a4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -1787,7 +1787,9 @@ int dcn31_populate_dml_pipes_from_context( struct pipe_ctx *pipe; bool upscaled = false; + DC_FP_START(); dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + DC_FP_END(); for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { struct dc_crtc_timing *timing; @@ -1999,7 +2001,9 @@ static void dcn31_calculate_wm_and_dlg_fp( pipe_idx++; } + DC_FP_START(); dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); + DC_FP_END(); } void dcn31_calculate_wm_and_dlg( diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c index a9dc84b652608..06adb77c206ba 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c @@ -1785,7 +1785,9 @@ static int dcn315_populate_dml_pipes_from_context( struct pipe_ctx *pipe; const int max_usable_det = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes - DCN3_15_MIN_COMPBUF_SIZE_KB; + DC_FP_START(); dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + DC_FP_END(); for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { struct dc_crtc_timing *timing; diff --git a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c index 936803721cc3c..8decc3ccf8cac 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c @@ -1786,7 +1786,9 @@ static int dcn316_populate_dml_pipes_from_context( struct pipe_ctx *pipe; const int max_usable_det = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes - DCN3_16_MIN_COMPBUF_SIZE_KB; + DC_FP_START(); dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + DC_FP_END(); for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { struct dc_crtc_timing *timing; 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 d590dc9173637..f321e6a82d128 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 @@ -25,6 +25,9 @@ */ #include "resource.h" +#include "clk_mgr.h" +#include "dc_link_dp.h" +#include "dcn20/dcn20_resource.h" #include "dcn20_fpu.h" @@ -61,6 +64,369 @@ * warning. */ +struct _vcs_dpi_ip_params_st dcn2_0_ip = { + .odm_capable = 1, + .gpuvm_enable = 0, + .hostvm_enable = 0, + .gpuvm_max_page_table_levels = 4, + .hostvm_max_page_table_levels = 4, + .hostvm_cached_page_table_levels = 0, + .pte_group_size_bytes = 2048, + .num_dsc = 6, + .rob_buffer_size_kbytes = 168, + .det_buffer_size_kbytes = 164, + .dpte_buffer_size_in_pte_reqs_luma = 84, + .pde_proc_buffer_size_64k_reqs = 48, + .dpp_output_buffer_pixels = 2560, + .opp_output_buffer_lines = 1, + .pixel_chunk_size_kbytes = 8, + .pte_chunk_size_kbytes = 2, + .meta_chunk_size_kbytes = 2, + .writeback_chunk_size_kbytes = 2, + .line_buffer_size_bits = 789504, + .is_line_buffer_bpp_fixed = 0, + .line_buffer_fixed_bpp = 0, + .dcc_supported = true, + .max_line_buffer_lines = 12, + .writeback_luma_buffer_size_kbytes = 12, + .writeback_chroma_buffer_size_kbytes = 8, + .writeback_chroma_line_buffer_width_pixels = 4, + .writeback_max_hscl_ratio = 1, + .writeback_max_vscl_ratio = 1, + .writeback_min_hscl_ratio = 1, + .writeback_min_vscl_ratio = 1, + .writeback_max_hscl_taps = 12, + .writeback_max_vscl_taps = 12, + .writeback_line_buffer_luma_buffer_size = 0, + .writeback_line_buffer_chroma_buffer_size = 14643, + .cursor_buffer_size = 8, + .cursor_chunk_size = 2, + .max_num_otg = 6, + .max_num_dpp = 6, + .max_num_wb = 1, + .max_dchub_pscl_bw_pix_per_clk = 4, + .max_pscl_lb_bw_pix_per_clk = 2, + .max_lb_vscl_bw_pix_per_clk = 4, + .max_vscl_hscl_bw_pix_per_clk = 4, + .max_hscl_ratio = 8, + .max_vscl_ratio = 8, + .hscl_mults = 4, + .vscl_mults = 4, + .max_hscl_taps = 8, + .max_vscl_taps = 8, + .dispclk_ramp_margin_percent = 1, + .underscan_factor = 1.10, + .min_vblank_lines = 32, // + .dppclk_delay_subtotal = 77, // + .dppclk_delay_scl_lb_only = 16, + .dppclk_delay_scl = 50, + .dppclk_delay_cnvc_formatter = 8, + .dppclk_delay_cnvc_cursor = 6, + .dispclk_delay_subtotal = 87, // + .dcfclk_cstate_latency = 10, // SRExitTime + .max_inter_dcn_tile_repeaters = 8, + .xfc_supported = true, + .xfc_fill_bw_overhead_percent = 10.0, + .xfc_fill_constant_bytes = 0, + .number_of_cursors = 1, +}; + +struct _vcs_dpi_ip_params_st dcn2_0_nv14_ip = { + .odm_capable = 1, + .gpuvm_enable = 0, + .hostvm_enable = 0, + .gpuvm_max_page_table_levels = 4, + .hostvm_max_page_table_levels = 4, + .hostvm_cached_page_table_levels = 0, + .num_dsc = 5, + .rob_buffer_size_kbytes = 168, + .det_buffer_size_kbytes = 164, + .dpte_buffer_size_in_pte_reqs_luma = 84, + .dpte_buffer_size_in_pte_reqs_chroma = 42,//todo + .dpp_output_buffer_pixels = 2560, + .opp_output_buffer_lines = 1, + .pixel_chunk_size_kbytes = 8, + .pte_enable = 1, + .max_page_table_levels = 4, + .pte_chunk_size_kbytes = 2, + .meta_chunk_size_kbytes = 2, + .writeback_chunk_size_kbytes = 2, + .line_buffer_size_bits = 789504, + .is_line_buffer_bpp_fixed = 0, + .line_buffer_fixed_bpp = 0, + .dcc_supported = true, + .max_line_buffer_lines = 12, + .writeback_luma_buffer_size_kbytes = 12, + .writeback_chroma_buffer_size_kbytes = 8, + .writeback_chroma_line_buffer_width_pixels = 4, + .writeback_max_hscl_ratio = 1, + .writeback_max_vscl_ratio = 1, + .writeback_min_hscl_ratio = 1, + .writeback_min_vscl_ratio = 1, + .writeback_max_hscl_taps = 12, + .writeback_max_vscl_taps = 12, + .writeback_line_buffer_luma_buffer_size = 0, + .writeback_line_buffer_chroma_buffer_size = 14643, + .cursor_buffer_size = 8, + .cursor_chunk_size = 2, + .max_num_otg = 5, + .max_num_dpp = 5, + .max_num_wb = 1, + .max_dchub_pscl_bw_pix_per_clk = 4, + .max_pscl_lb_bw_pix_per_clk = 2, + .max_lb_vscl_bw_pix_per_clk = 4, + .max_vscl_hscl_bw_pix_per_clk = 4, + .max_hscl_ratio = 8, + .max_vscl_ratio = 8, + .hscl_mults = 4, + .vscl_mults = 4, + .max_hscl_taps = 8, + .max_vscl_taps = 8, + .dispclk_ramp_margin_percent = 1, + .underscan_factor = 1.10, + .min_vblank_lines = 32, // + .dppclk_delay_subtotal = 77, // + .dppclk_delay_scl_lb_only = 16, + .dppclk_delay_scl = 50, + .dppclk_delay_cnvc_formatter = 8, + .dppclk_delay_cnvc_cursor = 6, + .dispclk_delay_subtotal = 87, // + .dcfclk_cstate_latency = 10, // SRExitTime + .max_inter_dcn_tile_repeaters = 8, + .xfc_supported = true, + .xfc_fill_bw_overhead_percent = 10.0, + .xfc_fill_constant_bytes = 0, + .ptoi_supported = 0, + .number_of_cursors = 1, +}; + +struct _vcs_dpi_soc_bounding_box_st dcn2_0_soc = { + /* Defaults that get patched on driver load from firmware. */ + .clock_limits = { + { + .state = 0, + .dcfclk_mhz = 560.0, + .fabricclk_mhz = 560.0, + .dispclk_mhz = 513.0, + .dppclk_mhz = 513.0, + .phyclk_mhz = 540.0, + .socclk_mhz = 560.0, + .dscclk_mhz = 171.0, + .dram_speed_mts = 8960.0, + }, + { + .state = 1, + .dcfclk_mhz = 694.0, + .fabricclk_mhz = 694.0, + .dispclk_mhz = 642.0, + .dppclk_mhz = 642.0, + .phyclk_mhz = 600.0, + .socclk_mhz = 694.0, + .dscclk_mhz = 214.0, + .dram_speed_mts = 11104.0, + }, + { + .state = 2, + .dcfclk_mhz = 875.0, + .fabricclk_mhz = 875.0, + .dispclk_mhz = 734.0, + .dppclk_mhz = 734.0, + .phyclk_mhz = 810.0, + .socclk_mhz = 875.0, + .dscclk_mhz = 245.0, + .dram_speed_mts = 14000.0, + }, + { + .state = 3, + .dcfclk_mhz = 1000.0, + .fabricclk_mhz = 1000.0, + .dispclk_mhz = 1100.0, + .dppclk_mhz = 1100.0, + .phyclk_mhz = 810.0, + .socclk_mhz = 1000.0, + .dscclk_mhz = 367.0, + .dram_speed_mts = 16000.0, + }, + { + .state = 4, + .dcfclk_mhz = 1200.0, + .fabricclk_mhz = 1200.0, + .dispclk_mhz = 1284.0, + .dppclk_mhz = 1284.0, + .phyclk_mhz = 810.0, + .socclk_mhz = 1200.0, + .dscclk_mhz = 428.0, + .dram_speed_mts = 16000.0, + }, + /*Extra state, no dispclk ramping*/ + { + .state = 5, + .dcfclk_mhz = 1200.0, + .fabricclk_mhz = 1200.0, + .dispclk_mhz = 1284.0, + .dppclk_mhz = 1284.0, + .phyclk_mhz = 810.0, + .socclk_mhz = 1200.0, + .dscclk_mhz = 428.0, + .dram_speed_mts = 16000.0, + }, + }, + .num_states = 5, + .sr_exit_time_us = 8.6, + .sr_enter_plus_exit_time_us = 10.9, + .urgent_latency_us = 4.0, + .urgent_latency_pixel_data_only_us = 4.0, + .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, + .urgent_latency_vm_data_only_us = 4.0, + .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, + .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, + .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 40.0, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 40.0, + .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0, + .max_avg_sdp_bw_use_normal_percent = 40.0, + .max_avg_dram_bw_use_normal_percent = 40.0, + .writeback_latency_us = 12.0, + .ideal_dram_bw_after_urgent_percent = 40.0, + .max_request_size_bytes = 256, + .dram_channel_width_bytes = 2, + .fabric_datapath_to_dcn_data_return_bytes = 64, + .dcn_downspread_percent = 0.5, + .downspread_percent = 0.38, + .dram_page_open_time_ns = 50.0, + .dram_rw_turnaround_time_ns = 17.5, + .dram_return_buffer_per_channel_bytes = 8192, + .round_trip_ping_latency_dcfclk_cycles = 131, + .urgent_out_of_order_return_per_channel_bytes = 256, + .channel_interleave_bytes = 256, + .num_banks = 8, + .num_chans = 16, + .vmm_page_size_bytes = 4096, + .dram_clock_change_latency_us = 404.0, + .dummy_pstate_latency_us = 5.0, + .writeback_dram_clock_change_latency_us = 23.0, + .return_bus_width_bytes = 64, + .dispclk_dppclk_vco_speed_mhz = 3850, + .xfc_bus_transport_time_us = 20, + .xfc_xbuf_latency_tolerance_us = 4, + .use_urgent_burst_bw = 0 +}; + +struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv14_soc = { + .clock_limits = { + { + .state = 0, + .dcfclk_mhz = 560.0, + .fabricclk_mhz = 560.0, + .dispclk_mhz = 513.0, + .dppclk_mhz = 513.0, + .phyclk_mhz = 540.0, + .socclk_mhz = 560.0, + .dscclk_mhz = 171.0, + .dram_speed_mts = 8960.0, + }, + { + .state = 1, + .dcfclk_mhz = 694.0, + .fabricclk_mhz = 694.0, + .dispclk_mhz = 642.0, + .dppclk_mhz = 642.0, + .phyclk_mhz = 600.0, + .socclk_mhz = 694.0, + .dscclk_mhz = 214.0, + .dram_speed_mts = 11104.0, + }, + { + .state = 2, + .dcfclk_mhz = 875.0, + .fabricclk_mhz = 875.0, + .dispclk_mhz = 734.0, + .dppclk_mhz = 734.0, + .phyclk_mhz = 810.0, + .socclk_mhz = 875.0, + .dscclk_mhz = 245.0, + .dram_speed_mts = 14000.0, + }, + { + .state = 3, + .dcfclk_mhz = 1000.0, + .fabricclk_mhz = 1000.0, + .dispclk_mhz = 1100.0, + .dppclk_mhz = 1100.0, + .phyclk_mhz = 810.0, + .socclk_mhz = 1000.0, + .dscclk_mhz = 367.0, + .dram_speed_mts = 16000.0, + }, + { + .state = 4, + .dcfclk_mhz = 1200.0, + .fabricclk_mhz = 1200.0, + .dispclk_mhz = 1284.0, + .dppclk_mhz = 1284.0, + .phyclk_mhz = 810.0, + .socclk_mhz = 1200.0, + .dscclk_mhz = 428.0, + .dram_speed_mts = 16000.0, + }, + /*Extra state, no dispclk ramping*/ + { + .state = 5, + .dcfclk_mhz = 1200.0, + .fabricclk_mhz = 1200.0, + .dispclk_mhz = 1284.0, + .dppclk_mhz = 1284.0, + .phyclk_mhz = 810.0, + .socclk_mhz = 1200.0, + .dscclk_mhz = 428.0, + .dram_speed_mts = 16000.0, + }, + }, + .num_states = 5, + .sr_exit_time_us = 11.6, + .sr_enter_plus_exit_time_us = 13.9, + .urgent_latency_us = 4.0, + .urgent_latency_pixel_data_only_us = 4.0, + .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, + .urgent_latency_vm_data_only_us = 4.0, + .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, + .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, + .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 40.0, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 40.0, + .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0, + .max_avg_sdp_bw_use_normal_percent = 40.0, + .max_avg_dram_bw_use_normal_percent = 40.0, + .writeback_latency_us = 12.0, + .ideal_dram_bw_after_urgent_percent = 40.0, + .max_request_size_bytes = 256, + .dram_channel_width_bytes = 2, + .fabric_datapath_to_dcn_data_return_bytes = 64, + .dcn_downspread_percent = 0.5, + .downspread_percent = 0.38, + .dram_page_open_time_ns = 50.0, + .dram_rw_turnaround_time_ns = 17.5, + .dram_return_buffer_per_channel_bytes = 8192, + .round_trip_ping_latency_dcfclk_cycles = 131, + .urgent_out_of_order_return_per_channel_bytes = 256, + .channel_interleave_bytes = 256, + .num_banks = 8, + .num_chans = 8, + .vmm_page_size_bytes = 4096, + .dram_clock_change_latency_us = 404.0, + .dummy_pstate_latency_us = 5.0, + .writeback_dram_clock_change_latency_us = 23.0, + .return_bus_width_bytes = 64, + .dispclk_dppclk_vco_speed_mhz = 3850, + .xfc_bus_transport_time_us = 20, + .xfc_xbuf_latency_tolerance_us = 4, + .use_urgent_burst_bw = 0 +}; + +struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv12_soc = { 0 }; + +#define DC_LOGGER_INIT(logger) + void dcn20_populate_dml_writeback_from_context(struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes) @@ -100,3 +466,1023 @@ void dcn20_populate_dml_writeback_from_context(struct dc *dc, pipe_cnt++; } } + +void dcn20_fpu_set_wb_arb_params(struct mcif_arb_params *wb_arb_params, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt, int i) +{ + int k; + + dc_assert_fp_enabled(); + + for (k = 0; k < sizeof(wb_arb_params->cli_watermark)/sizeof(wb_arb_params->cli_watermark[0]); k++) { + wb_arb_params->cli_watermark[k] = get_wm_writeback_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + wb_arb_params->pstate_watermark[k] = get_wm_writeback_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + } + wb_arb_params->time_per_pixel = 16.0 * 1000 / (context->res_ctx.pipe_ctx[i].stream->phy_pix_clk / 1000); /* 4 bit fraction, ms */ +} + +static bool is_dtbclk_required(struct dc *dc, struct dc_state *context) +{ + int i; + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (!context->res_ctx.pipe_ctx[i].stream) + continue; + if (is_dp_128b_132b_signal(&context->res_ctx.pipe_ctx[i])) + return true; + } + return false; +} + +static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struct dc_state *context) +{ + int plane_count; + int i; + + plane_count = 0; + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (context->res_ctx.pipe_ctx[i].plane_state) + plane_count++; + } + + /* + * Zstate is allowed in following scenarios: + * 1. Single eDP with PSR enabled + * 2. 0 planes (No memory requests) + * 3. Single eDP without PSR but > 5ms stutter period + */ + if (plane_count == 0) + return DCN_ZSTATE_SUPPORT_ALLOW; + else if (context->stream_count == 1 && context->streams[0]->signal == SIGNAL_TYPE_EDP) { + struct dc_link *link = context->streams[0]->sink->link; + + /* zstate only supported on PWRSEQ0 */ + if (link->link_index != 0) + return DCN_ZSTATE_SUPPORT_DISALLOW; + + if (context->bw_ctx.dml.vba.StutterPeriod > 5000.0) + return DCN_ZSTATE_SUPPORT_ALLOW; + else if (link->psr_settings.psr_version == DC_PSR_VERSION_1 && !dc->debug.disable_psr) + return DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY; + else + return DCN_ZSTATE_SUPPORT_DISALLOW; + } else + return DCN_ZSTATE_SUPPORT_DISALLOW; +} + +void dcn20_calculate_dlg_params( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt, + int vlevel) +{ + int i, pipe_idx; + + dc_assert_fp_enabled(); + + /* Writeback MCIF_WB arbitration parameters */ + dc->res_pool->funcs->set_mcif_arb_params(dc, context, pipes, pipe_cnt); + + context->bw_ctx.bw.dcn.clk.dispclk_khz = context->bw_ctx.dml.vba.DISPCLK * 1000; + context->bw_ctx.bw.dcn.clk.dcfclk_khz = context->bw_ctx.dml.vba.DCFCLK * 1000; + context->bw_ctx.bw.dcn.clk.socclk_khz = context->bw_ctx.dml.vba.SOCCLK * 1000; + context->bw_ctx.bw.dcn.clk.dramclk_khz = context->bw_ctx.dml.vba.DRAMSpeed * 1000 / 16; + + if (dc->debug.min_dram_clk_khz > context->bw_ctx.bw.dcn.clk.dramclk_khz) + context->bw_ctx.bw.dcn.clk.dramclk_khz = dc->debug.min_dram_clk_khz; + + context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = context->bw_ctx.dml.vba.DCFCLKDeepSleep * 1000; + context->bw_ctx.bw.dcn.clk.fclk_khz = context->bw_ctx.dml.vba.FabricClock * 1000; + context->bw_ctx.bw.dcn.clk.p_state_change_support = + context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] + != dm_dram_clock_change_unsupported; + context->bw_ctx.bw.dcn.clk.dppclk_khz = 0; + + context->bw_ctx.bw.dcn.clk.zstate_support = decide_zstate_support(dc, context); + + context->bw_ctx.bw.dcn.clk.dtbclk_en = is_dtbclk_required(dc, context); + + if (context->bw_ctx.bw.dcn.clk.dispclk_khz < dc->debug.min_disp_clk_khz) + context->bw_ctx.bw.dcn.clk.dispclk_khz = dc->debug.min_disp_clk_khz; + + for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { + if (!context->res_ctx.pipe_ctx[i].stream) + continue; + pipes[pipe_idx].pipe.dest.vstartup_start = get_vstartup(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); + pipes[pipe_idx].pipe.dest.vupdate_offset = get_vupdate_offset(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); + pipes[pipe_idx].pipe.dest.vupdate_width = get_vupdate_width(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); + pipes[pipe_idx].pipe.dest.vready_offset = get_vready_offset(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); + context->res_ctx.pipe_ctx[i].det_buffer_size_kb = context->bw_ctx.dml.ip.det_buffer_size_kbytes; + context->res_ctx.pipe_ctx[i].unbounded_req = pipes[pipe_idx].pipe.src.unbounded_req_mode; + + if (context->bw_ctx.bw.dcn.clk.dppclk_khz < pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000) + context->bw_ctx.bw.dcn.clk.dppclk_khz = pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000; + context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz = + pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000; + context->res_ctx.pipe_ctx[i].pipe_dlg_param = pipes[pipe_idx].pipe.dest; + pipe_idx++; + } + /*save a original dppclock copy*/ + context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz; + context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz; + context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = context->bw_ctx.dml.soc.clock_limits[vlevel].dppclk_mhz * 1000; + context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = context->bw_ctx.dml.soc.clock_limits[vlevel].dispclk_mhz * 1000; + + context->bw_ctx.bw.dcn.compbuf_size_kb = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes + - context->bw_ctx.dml.ip.det_buffer_size_kbytes * pipe_idx; + + for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { + bool cstate_en = context->bw_ctx.dml.vba.PrefetchMode[vlevel][context->bw_ctx.dml.vba.maxMpcComb] != 2; + + if (!context->res_ctx.pipe_ctx[i].stream) + continue; + + if (dc->ctx->dce_version == DCN_VERSION_2_01) + cstate_en = false; + + context->bw_ctx.dml.funcs.rq_dlg_get_dlg_reg(&context->bw_ctx.dml, + &context->res_ctx.pipe_ctx[i].dlg_regs, + &context->res_ctx.pipe_ctx[i].ttu_regs, + pipes, + pipe_cnt, + pipe_idx, + cstate_en, + context->bw_ctx.bw.dcn.clk.p_state_change_support, + false, false, true); + + context->bw_ctx.dml.funcs.rq_dlg_get_rq_reg(&context->bw_ctx.dml, + &context->res_ctx.pipe_ctx[i].rq_regs, + &pipes[pipe_idx].pipe); + pipe_idx++; + } +} + +static void swizzle_to_dml_params( + enum swizzle_mode_values swizzle, + unsigned int *sw_mode) +{ + switch (swizzle) { + case DC_SW_LINEAR: + *sw_mode = dm_sw_linear; + break; + case DC_SW_4KB_S: + *sw_mode = dm_sw_4kb_s; + break; + case DC_SW_4KB_S_X: + *sw_mode = dm_sw_4kb_s_x; + break; + case DC_SW_4KB_D: + *sw_mode = dm_sw_4kb_d; + break; + case DC_SW_4KB_D_X: + *sw_mode = dm_sw_4kb_d_x; + break; + case DC_SW_64KB_S: + *sw_mode = dm_sw_64kb_s; + break; + case DC_SW_64KB_S_X: + *sw_mode = dm_sw_64kb_s_x; + break; + case DC_SW_64KB_S_T: + *sw_mode = dm_sw_64kb_s_t; + break; + case DC_SW_64KB_D: + *sw_mode = dm_sw_64kb_d; + break; + case DC_SW_64KB_D_X: + *sw_mode = dm_sw_64kb_d_x; + break; + case DC_SW_64KB_D_T: + *sw_mode = dm_sw_64kb_d_t; + break; + case DC_SW_64KB_R_X: + *sw_mode = dm_sw_64kb_r_x; + break; + case DC_SW_VAR_S: + *sw_mode = dm_sw_var_s; + break; + case DC_SW_VAR_S_X: + *sw_mode = dm_sw_var_s_x; + break; + case DC_SW_VAR_D: + *sw_mode = dm_sw_var_d; + break; + case DC_SW_VAR_D_X: + *sw_mode = dm_sw_var_d_x; + break; + case DC_SW_VAR_R_X: + *sw_mode = dm_sw_var_r_x; + break; + default: + ASSERT(0); /* Not supported */ + break; + } +} + +int dcn20_populate_dml_pipes_from_context( + struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate) +{ + int pipe_cnt, i; + bool synchronized_vblank = true; + struct resource_context *res_ctx = &context->res_ctx; + + dc_assert_fp_enabled(); + + for (i = 0, pipe_cnt = -1; i < dc->res_pool->pipe_count; i++) { + if (!res_ctx->pipe_ctx[i].stream) + continue; + + if (pipe_cnt < 0) { + pipe_cnt = i; + continue; + } + + if (res_ctx->pipe_ctx[pipe_cnt].stream == res_ctx->pipe_ctx[i].stream) + continue; + + if (dc->debug.disable_timing_sync || + (!resource_are_streams_timing_synchronizable( + res_ctx->pipe_ctx[pipe_cnt].stream, + res_ctx->pipe_ctx[i].stream) && + !resource_are_vblanks_synchronizable( + res_ctx->pipe_ctx[pipe_cnt].stream, + res_ctx->pipe_ctx[i].stream))) { + synchronized_vblank = false; + break; + } + } + + for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { + struct dc_crtc_timing *timing = &res_ctx->pipe_ctx[i].stream->timing; + unsigned int v_total; + unsigned int front_porch; + int output_bpc; + struct audio_check aud_check = {0}; + + if (!res_ctx->pipe_ctx[i].stream) + continue; + + v_total = timing->v_total; + front_porch = timing->v_front_porch; + + /* todo: + pipes[pipe_cnt].pipe.src.dynamic_metadata_enable = 0; + pipes[pipe_cnt].pipe.src.dcc = 0; + pipes[pipe_cnt].pipe.src.vm = 0;*/ + + pipes[pipe_cnt].clks_cfg.refclk_mhz = dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000.0; + + pipes[pipe_cnt].dout.dsc_enable = res_ctx->pipe_ctx[i].stream->timing.flags.DSC; + /* todo: rotation?*/ + pipes[pipe_cnt].dout.dsc_slices = res_ctx->pipe_ctx[i].stream->timing.dsc_cfg.num_slices_h; + if (res_ctx->pipe_ctx[i].stream->use_dynamic_meta) { + pipes[pipe_cnt].pipe.src.dynamic_metadata_enable = true; + /* 1/2 vblank */ + pipes[pipe_cnt].pipe.src.dynamic_metadata_lines_before_active = + (v_total - timing->v_addressable + - timing->v_border_top - timing->v_border_bottom) / 2; + /* 36 bytes dp, 32 hdmi */ + pipes[pipe_cnt].pipe.src.dynamic_metadata_xmit_bytes = + dc_is_dp_signal(res_ctx->pipe_ctx[i].stream->signal) ? 36 : 32; + } + pipes[pipe_cnt].pipe.src.dcc = false; + pipes[pipe_cnt].pipe.src.dcc_rate = 1; + pipes[pipe_cnt].pipe.dest.synchronized_vblank_all_planes = synchronized_vblank; + pipes[pipe_cnt].pipe.dest.hblank_start = timing->h_total - timing->h_front_porch; + pipes[pipe_cnt].pipe.dest.hblank_end = pipes[pipe_cnt].pipe.dest.hblank_start + - timing->h_addressable + - timing->h_border_left + - timing->h_border_right; + pipes[pipe_cnt].pipe.dest.vblank_start = v_total - front_porch; + pipes[pipe_cnt].pipe.dest.vblank_end = pipes[pipe_cnt].pipe.dest.vblank_start + - timing->v_addressable + - timing->v_border_top + - timing->v_border_bottom; + pipes[pipe_cnt].pipe.dest.htotal = timing->h_total; + pipes[pipe_cnt].pipe.dest.vtotal = v_total; + pipes[pipe_cnt].pipe.dest.hactive = + timing->h_addressable + timing->h_border_left + timing->h_border_right; + pipes[pipe_cnt].pipe.dest.vactive = + timing->v_addressable + timing->v_border_top + timing->v_border_bottom; + pipes[pipe_cnt].pipe.dest.interlaced = timing->flags.INTERLACE; + pipes[pipe_cnt].pipe.dest.pixel_rate_mhz = timing->pix_clk_100hz/10000.0; + if (timing->timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) + pipes[pipe_cnt].pipe.dest.pixel_rate_mhz *= 2; + pipes[pipe_cnt].pipe.dest.otg_inst = res_ctx->pipe_ctx[i].stream_res.tg->inst; + pipes[pipe_cnt].dout.dp_lanes = 4; + pipes[pipe_cnt].dout.is_virtual = 0; + pipes[pipe_cnt].pipe.dest.vtotal_min = res_ctx->pipe_ctx[i].stream->adjust.v_total_min; + pipes[pipe_cnt].pipe.dest.vtotal_max = res_ctx->pipe_ctx[i].stream->adjust.v_total_max; + switch (get_num_odm_splits(&res_ctx->pipe_ctx[i])) { + case 1: + pipes[pipe_cnt].pipe.dest.odm_combine = dm_odm_combine_mode_2to1; + break; + case 3: + pipes[pipe_cnt].pipe.dest.odm_combine = dm_odm_combine_mode_4to1; + break; + default: + pipes[pipe_cnt].pipe.dest.odm_combine = dm_odm_combine_mode_disabled; + } + pipes[pipe_cnt].pipe.src.hsplit_grp = res_ctx->pipe_ctx[i].pipe_idx; + if (res_ctx->pipe_ctx[i].top_pipe && res_ctx->pipe_ctx[i].top_pipe->plane_state + == res_ctx->pipe_ctx[i].plane_state) { + struct pipe_ctx *first_pipe = res_ctx->pipe_ctx[i].top_pipe; + int split_idx = 0; + + while (first_pipe->top_pipe && first_pipe->top_pipe->plane_state + == res_ctx->pipe_ctx[i].plane_state) { + first_pipe = first_pipe->top_pipe; + split_idx++; + } + /* Treat 4to1 mpc combine as an mpo of 2 2-to-1 combines */ + if (split_idx == 0) + pipes[pipe_cnt].pipe.src.hsplit_grp = first_pipe->pipe_idx; + else if (split_idx == 1) + pipes[pipe_cnt].pipe.src.hsplit_grp = res_ctx->pipe_ctx[i].pipe_idx; + else if (split_idx == 2) + pipes[pipe_cnt].pipe.src.hsplit_grp = res_ctx->pipe_ctx[i].top_pipe->pipe_idx; + } else if (res_ctx->pipe_ctx[i].prev_odm_pipe) { + struct pipe_ctx *first_pipe = res_ctx->pipe_ctx[i].prev_odm_pipe; + + while (first_pipe->prev_odm_pipe) + first_pipe = first_pipe->prev_odm_pipe; + pipes[pipe_cnt].pipe.src.hsplit_grp = first_pipe->pipe_idx; + } + + switch (res_ctx->pipe_ctx[i].stream->signal) { + case SIGNAL_TYPE_DISPLAY_PORT_MST: + case SIGNAL_TYPE_DISPLAY_PORT: + pipes[pipe_cnt].dout.output_type = dm_dp; + break; + case SIGNAL_TYPE_EDP: + pipes[pipe_cnt].dout.output_type = dm_edp; + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + pipes[pipe_cnt].dout.output_type = dm_hdmi; + break; + default: + /* In case there is no signal, set dp with 4 lanes to allow max config */ + pipes[pipe_cnt].dout.is_virtual = 1; + pipes[pipe_cnt].dout.output_type = dm_dp; + pipes[pipe_cnt].dout.dp_lanes = 4; + } + + switch (res_ctx->pipe_ctx[i].stream->timing.display_color_depth) { + case COLOR_DEPTH_666: + output_bpc = 6; + break; + case COLOR_DEPTH_888: + output_bpc = 8; + break; + case COLOR_DEPTH_101010: + output_bpc = 10; + break; + case COLOR_DEPTH_121212: + output_bpc = 12; + break; + case COLOR_DEPTH_141414: + output_bpc = 14; + break; + case COLOR_DEPTH_161616: + output_bpc = 16; + break; + case COLOR_DEPTH_999: + output_bpc = 9; + break; + case COLOR_DEPTH_111111: + output_bpc = 11; + break; + default: + output_bpc = 8; + break; + } + + switch (res_ctx->pipe_ctx[i].stream->timing.pixel_encoding) { + case PIXEL_ENCODING_RGB: + case PIXEL_ENCODING_YCBCR444: + pipes[pipe_cnt].dout.output_format = dm_444; + pipes[pipe_cnt].dout.output_bpp = output_bpc * 3; + break; + case PIXEL_ENCODING_YCBCR420: + pipes[pipe_cnt].dout.output_format = dm_420; + pipes[pipe_cnt].dout.output_bpp = (output_bpc * 3.0) / 2; + break; + case PIXEL_ENCODING_YCBCR422: + if (res_ctx->pipe_ctx[i].stream->timing.flags.DSC && + !res_ctx->pipe_ctx[i].stream->timing.dsc_cfg.ycbcr422_simple) + pipes[pipe_cnt].dout.output_format = dm_n422; + else + pipes[pipe_cnt].dout.output_format = dm_s422; + pipes[pipe_cnt].dout.output_bpp = output_bpc * 2; + break; + default: + pipes[pipe_cnt].dout.output_format = dm_444; + pipes[pipe_cnt].dout.output_bpp = output_bpc * 3; + } + + if (res_ctx->pipe_ctx[i].stream->timing.flags.DSC) + pipes[pipe_cnt].dout.output_bpp = res_ctx->pipe_ctx[i].stream->timing.dsc_cfg.bits_per_pixel / 16.0; + + /* todo: default max for now, until there is logic reflecting this in dc*/ + pipes[pipe_cnt].dout.dsc_input_bpc = 12; + /*fill up the audio sample rate (unit in kHz)*/ + get_audio_check(&res_ctx->pipe_ctx[i].stream->audio_info, &aud_check); + pipes[pipe_cnt].dout.max_audio_sample_rate = aud_check.max_audiosample_rate / 1000; + /* + * For graphic plane, cursor number is 1, nv12 is 0 + * bw calculations due to cursor on/off + */ + if (res_ctx->pipe_ctx[i].plane_state && + res_ctx->pipe_ctx[i].plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) + pipes[pipe_cnt].pipe.src.num_cursors = 0; + else + pipes[pipe_cnt].pipe.src.num_cursors = dc->dml.ip.number_of_cursors; + + pipes[pipe_cnt].pipe.src.cur0_src_width = 256; + pipes[pipe_cnt].pipe.src.cur0_bpp = dm_cur_32bit; + + if (!res_ctx->pipe_ctx[i].plane_state) { + pipes[pipe_cnt].pipe.src.is_hsplit = pipes[pipe_cnt].pipe.dest.odm_combine != dm_odm_combine_mode_disabled; + pipes[pipe_cnt].pipe.src.source_scan = dm_horz; + pipes[pipe_cnt].pipe.src.sw_mode = dm_sw_4kb_s; + pipes[pipe_cnt].pipe.src.macro_tile_size = dm_64k_tile; + pipes[pipe_cnt].pipe.src.viewport_width = timing->h_addressable; + if (pipes[pipe_cnt].pipe.src.viewport_width > 1920) + pipes[pipe_cnt].pipe.src.viewport_width = 1920; + pipes[pipe_cnt].pipe.src.viewport_height = timing->v_addressable; + if (pipes[pipe_cnt].pipe.src.viewport_height > 1080) + pipes[pipe_cnt].pipe.src.viewport_height = 1080; + pipes[pipe_cnt].pipe.src.surface_height_y = pipes[pipe_cnt].pipe.src.viewport_height; + pipes[pipe_cnt].pipe.src.surface_width_y = pipes[pipe_cnt].pipe.src.viewport_width; + pipes[pipe_cnt].pipe.src.surface_height_c = pipes[pipe_cnt].pipe.src.viewport_height; + pipes[pipe_cnt].pipe.src.surface_width_c = pipes[pipe_cnt].pipe.src.viewport_width; + pipes[pipe_cnt].pipe.src.data_pitch = ((pipes[pipe_cnt].pipe.src.viewport_width + 255) / 256) * 256; + pipes[pipe_cnt].pipe.src.source_format = dm_444_32; + pipes[pipe_cnt].pipe.dest.recout_width = pipes[pipe_cnt].pipe.src.viewport_width; /*vp_width/hratio*/ + pipes[pipe_cnt].pipe.dest.recout_height = pipes[pipe_cnt].pipe.src.viewport_height; /*vp_height/vratio*/ + pipes[pipe_cnt].pipe.dest.full_recout_width = pipes[pipe_cnt].pipe.dest.recout_width; /*when is_hsplit != 1*/ + pipes[pipe_cnt].pipe.dest.full_recout_height = pipes[pipe_cnt].pipe.dest.recout_height; /*when is_hsplit != 1*/ + pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_16; + pipes[pipe_cnt].pipe.scale_ratio_depth.hscl_ratio = 1.0; + pipes[pipe_cnt].pipe.scale_ratio_depth.vscl_ratio = 1.0; + pipes[pipe_cnt].pipe.scale_ratio_depth.scl_enable = 0; /*Lb only or Full scl*/ + pipes[pipe_cnt].pipe.scale_taps.htaps = 1; + pipes[pipe_cnt].pipe.scale_taps.vtaps = 1; + pipes[pipe_cnt].pipe.dest.vtotal_min = v_total; + pipes[pipe_cnt].pipe.dest.vtotal_max = v_total; + + if (pipes[pipe_cnt].pipe.dest.odm_combine == dm_odm_combine_mode_2to1) { + pipes[pipe_cnt].pipe.src.viewport_width /= 2; + pipes[pipe_cnt].pipe.dest.recout_width /= 2; + } else if (pipes[pipe_cnt].pipe.dest.odm_combine == dm_odm_combine_mode_4to1) { + pipes[pipe_cnt].pipe.src.viewport_width /= 4; + pipes[pipe_cnt].pipe.dest.recout_width /= 4; + } + } else { + struct dc_plane_state *pln = res_ctx->pipe_ctx[i].plane_state; + struct scaler_data *scl = &res_ctx->pipe_ctx[i].plane_res.scl_data; + + pipes[pipe_cnt].pipe.src.immediate_flip = pln->flip_immediate; + pipes[pipe_cnt].pipe.src.is_hsplit = (res_ctx->pipe_ctx[i].bottom_pipe && res_ctx->pipe_ctx[i].bottom_pipe->plane_state == pln) + || (res_ctx->pipe_ctx[i].top_pipe && res_ctx->pipe_ctx[i].top_pipe->plane_state == pln) + || pipes[pipe_cnt].pipe.dest.odm_combine != dm_odm_combine_mode_disabled; + + /* stereo is not split */ + if (pln->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE || + pln->stereo_format == PLANE_STEREO_FORMAT_TOP_AND_BOTTOM) { + pipes[pipe_cnt].pipe.src.is_hsplit = false; + pipes[pipe_cnt].pipe.src.hsplit_grp = res_ctx->pipe_ctx[i].pipe_idx; + } + + pipes[pipe_cnt].pipe.src.source_scan = pln->rotation == ROTATION_ANGLE_90 + || pln->rotation == ROTATION_ANGLE_270 ? dm_vert : dm_horz; + pipes[pipe_cnt].pipe.src.viewport_y_y = scl->viewport.y; + pipes[pipe_cnt].pipe.src.viewport_y_c = scl->viewport_c.y; + pipes[pipe_cnt].pipe.src.viewport_width = scl->viewport.width; + pipes[pipe_cnt].pipe.src.viewport_width_c = scl->viewport_c.width; + pipes[pipe_cnt].pipe.src.viewport_height = scl->viewport.height; + pipes[pipe_cnt].pipe.src.viewport_height_c = scl->viewport_c.height; + pipes[pipe_cnt].pipe.src.viewport_width_max = pln->src_rect.width; + pipes[pipe_cnt].pipe.src.viewport_height_max = pln->src_rect.height; + pipes[pipe_cnt].pipe.src.surface_width_y = pln->plane_size.surface_size.width; + pipes[pipe_cnt].pipe.src.surface_height_y = pln->plane_size.surface_size.height; + pipes[pipe_cnt].pipe.src.surface_width_c = pln->plane_size.chroma_size.width; + pipes[pipe_cnt].pipe.src.surface_height_c = pln->plane_size.chroma_size.height; + if (pln->format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA + || pln->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + pipes[pipe_cnt].pipe.src.data_pitch = pln->plane_size.surface_pitch; + pipes[pipe_cnt].pipe.src.data_pitch_c = pln->plane_size.chroma_pitch; + pipes[pipe_cnt].pipe.src.meta_pitch = pln->dcc.meta_pitch; + pipes[pipe_cnt].pipe.src.meta_pitch_c = pln->dcc.meta_pitch_c; + } else { + pipes[pipe_cnt].pipe.src.data_pitch = pln->plane_size.surface_pitch; + pipes[pipe_cnt].pipe.src.meta_pitch = pln->dcc.meta_pitch; + } + pipes[pipe_cnt].pipe.src.dcc = pln->dcc.enable; + pipes[pipe_cnt].pipe.dest.recout_width = scl->recout.width; + pipes[pipe_cnt].pipe.dest.recout_height = scl->recout.height; + pipes[pipe_cnt].pipe.dest.full_recout_height = scl->recout.height; + pipes[pipe_cnt].pipe.dest.full_recout_width = scl->recout.width; + if (pipes[pipe_cnt].pipe.dest.odm_combine == dm_odm_combine_mode_2to1) + pipes[pipe_cnt].pipe.dest.full_recout_width *= 2; + else if (pipes[pipe_cnt].pipe.dest.odm_combine == dm_odm_combine_mode_4to1) + pipes[pipe_cnt].pipe.dest.full_recout_width *= 4; + else { + struct pipe_ctx *split_pipe = res_ctx->pipe_ctx[i].bottom_pipe; + + while (split_pipe && split_pipe->plane_state == pln) { + pipes[pipe_cnt].pipe.dest.full_recout_width += split_pipe->plane_res.scl_data.recout.width; + split_pipe = split_pipe->bottom_pipe; + } + split_pipe = res_ctx->pipe_ctx[i].top_pipe; + while (split_pipe && split_pipe->plane_state == pln) { + pipes[pipe_cnt].pipe.dest.full_recout_width += split_pipe->plane_res.scl_data.recout.width; + split_pipe = split_pipe->top_pipe; + } + } + + pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_16; + pipes[pipe_cnt].pipe.scale_ratio_depth.hscl_ratio = (double) scl->ratios.horz.value / (1ULL<<32); + pipes[pipe_cnt].pipe.scale_ratio_depth.hscl_ratio_c = (double) scl->ratios.horz_c.value / (1ULL<<32); + pipes[pipe_cnt].pipe.scale_ratio_depth.vscl_ratio = (double) scl->ratios.vert.value / (1ULL<<32); + pipes[pipe_cnt].pipe.scale_ratio_depth.vscl_ratio_c = (double) scl->ratios.vert_c.value / (1ULL<<32); + pipes[pipe_cnt].pipe.scale_ratio_depth.scl_enable = + scl->ratios.vert.value != dc_fixpt_one.value + || scl->ratios.horz.value != dc_fixpt_one.value + || scl->ratios.vert_c.value != dc_fixpt_one.value + || scl->ratios.horz_c.value != dc_fixpt_one.value /*Lb only or Full scl*/ + || dc->debug.always_scale; /*support always scale*/ + pipes[pipe_cnt].pipe.scale_taps.htaps = scl->taps.h_taps; + pipes[pipe_cnt].pipe.scale_taps.htaps_c = scl->taps.h_taps_c; + pipes[pipe_cnt].pipe.scale_taps.vtaps = scl->taps.v_taps; + pipes[pipe_cnt].pipe.scale_taps.vtaps_c = scl->taps.v_taps_c; + + pipes[pipe_cnt].pipe.src.macro_tile_size = + swizzle_mode_to_macro_tile_size(pln->tiling_info.gfx9.swizzle); + swizzle_to_dml_params(pln->tiling_info.gfx9.swizzle, + &pipes[pipe_cnt].pipe.src.sw_mode); + + switch (pln->format) { + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + pipes[pipe_cnt].pipe.src.source_format = dm_420_8; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + pipes[pipe_cnt].pipe.src.source_format = dm_420_10; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + pipes[pipe_cnt].pipe.src.source_format = dm_444_64; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + pipes[pipe_cnt].pipe.src.source_format = dm_444_16; + break; + case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: + pipes[pipe_cnt].pipe.src.source_format = dm_444_8; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA: + pipes[pipe_cnt].pipe.src.source_format = dm_rgbe_alpha; + break; + default: + pipes[pipe_cnt].pipe.src.source_format = dm_444_32; + break; + } + } + + pipe_cnt++; + } + + /* populate writeback information */ + DC_FP_START(); + dc->res_pool->funcs->populate_dml_writeback_from_context(dc, res_ctx, pipes); + DC_FP_END(); + + return pipe_cnt; +} + +void dcn20_calculate_wm( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int *out_pipe_cnt, + int *pipe_split_from, + int vlevel, + bool fast_validate) +{ + int pipe_cnt, i, pipe_idx; + + dc_assert_fp_enabled(); + + for (i = 0, pipe_idx = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { + if (!context->res_ctx.pipe_ctx[i].stream) + continue; + + pipes[pipe_cnt].clks_cfg.refclk_mhz = dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000.0; + pipes[pipe_cnt].clks_cfg.dispclk_mhz = context->bw_ctx.dml.vba.RequiredDISPCLK[vlevel][context->bw_ctx.dml.vba.maxMpcComb]; + + if (pipe_split_from[i] < 0) { + pipes[pipe_cnt].clks_cfg.dppclk_mhz = + context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx]; + if (context->bw_ctx.dml.vba.BlendingAndTiming[pipe_idx] == pipe_idx) + pipes[pipe_cnt].pipe.dest.odm_combine = + context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]; + else + pipes[pipe_cnt].pipe.dest.odm_combine = 0; + pipe_idx++; + } else { + pipes[pipe_cnt].clks_cfg.dppclk_mhz = + context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_split_from[i]]; + if (context->bw_ctx.dml.vba.BlendingAndTiming[pipe_split_from[i]] == pipe_split_from[i]) + pipes[pipe_cnt].pipe.dest.odm_combine = + context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_split_from[i]]; + else + pipes[pipe_cnt].pipe.dest.odm_combine = 0; + } + + if (dc->config.forced_clocks) { + pipes[pipe_cnt].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz; + pipes[pipe_cnt].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz; + } + if (dc->debug.min_disp_clk_khz > pipes[pipe_cnt].clks_cfg.dispclk_mhz * 1000) + pipes[pipe_cnt].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0; + if (dc->debug.min_dpp_clk_khz > pipes[pipe_cnt].clks_cfg.dppclk_mhz * 1000) + pipes[pipe_cnt].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0; + + pipe_cnt++; + } + + if (pipe_cnt != pipe_idx) { + if (dc->res_pool->funcs->populate_dml_pipes) + pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, + context, pipes, fast_validate); + else + pipe_cnt = dcn20_populate_dml_pipes_from_context(dc, + context, pipes, fast_validate); + } + + *out_pipe_cnt = pipe_cnt; + + pipes[0].clks_cfg.voltage = vlevel; + pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].dcfclk_mhz; + pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].socclk_mhz; + + /* only pipe 0 is read for voltage and dcf/soc clocks */ + if (vlevel < 1) { + pipes[0].clks_cfg.voltage = 1; + pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[1].dcfclk_mhz; + pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[1].socclk_mhz; + } + context->bw_ctx.bw.dcn.watermarks.b.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.b.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.b.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + + if (vlevel < 2) { + pipes[0].clks_cfg.voltage = 2; + pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[2].dcfclk_mhz; + pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[2].socclk_mhz; + } + context->bw_ctx.bw.dcn.watermarks.c.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + + if (vlevel < 3) { + pipes[0].clks_cfg.voltage = 3; + pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[2].dcfclk_mhz; + pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[2].socclk_mhz; + } + context->bw_ctx.bw.dcn.watermarks.d.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.d.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + + pipes[0].clks_cfg.voltage = vlevel; + pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].dcfclk_mhz; + pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].socclk_mhz; + context->bw_ctx.bw.dcn.watermarks.a.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; +} + +void dcn20_update_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb, + struct pp_smu_nv_clock_table *max_clocks, unsigned int *uclk_states, unsigned int num_states) +{ + struct _vcs_dpi_voltage_scaling_st calculated_states[DC__VOLTAGE_STATES]; + int i; + int num_calculated_states = 0; + int min_dcfclk = 0; + + dc_assert_fp_enabled(); + + if (num_states == 0) + return; + + memset(calculated_states, 0, sizeof(calculated_states)); + + if (dc->bb_overrides.min_dcfclk_mhz > 0) + min_dcfclk = dc->bb_overrides.min_dcfclk_mhz; + else { + if (ASICREV_IS_NAVI12_P(dc->ctx->asic_id.hw_internal_rev)) + min_dcfclk = 310; + else + // Accounting for SOC/DCF relationship, we can go as high as + // 506Mhz in Vmin. + min_dcfclk = 506; + } + + for (i = 0; i < num_states; i++) { + int min_fclk_required_by_uclk; + calculated_states[i].state = i; + calculated_states[i].dram_speed_mts = uclk_states[i] * 16 / 1000; + + // FCLK:UCLK ratio is 1.08 + min_fclk_required_by_uclk = div_u64(((unsigned long long)uclk_states[i]) * 1080, + 1000000); + + calculated_states[i].fabricclk_mhz = (min_fclk_required_by_uclk < min_dcfclk) ? + min_dcfclk : min_fclk_required_by_uclk; + + calculated_states[i].socclk_mhz = (calculated_states[i].fabricclk_mhz > max_clocks->socClockInKhz / 1000) ? + max_clocks->socClockInKhz / 1000 : calculated_states[i].fabricclk_mhz; + + calculated_states[i].dcfclk_mhz = (calculated_states[i].fabricclk_mhz > max_clocks->dcfClockInKhz / 1000) ? + max_clocks->dcfClockInKhz / 1000 : calculated_states[i].fabricclk_mhz; + + calculated_states[i].dispclk_mhz = max_clocks->displayClockInKhz / 1000; + calculated_states[i].dppclk_mhz = max_clocks->displayClockInKhz / 1000; + calculated_states[i].dscclk_mhz = max_clocks->displayClockInKhz / (1000 * 3); + + calculated_states[i].phyclk_mhz = max_clocks->phyClockInKhz / 1000; + + num_calculated_states++; + } + + calculated_states[num_calculated_states - 1].socclk_mhz = max_clocks->socClockInKhz / 1000; + calculated_states[num_calculated_states - 1].fabricclk_mhz = max_clocks->socClockInKhz / 1000; + calculated_states[num_calculated_states - 1].dcfclk_mhz = max_clocks->dcfClockInKhz / 1000; + + memcpy(bb->clock_limits, calculated_states, sizeof(bb->clock_limits)); + bb->num_states = num_calculated_states; + + // Duplicate the last state, DML always an extra state identical to max state to work + memcpy(&bb->clock_limits[num_calculated_states], &bb->clock_limits[num_calculated_states - 1], sizeof(struct _vcs_dpi_voltage_scaling_st)); + bb->clock_limits[num_calculated_states].state = bb->num_states; +} + +void dcn20_cap_soc_clocks( + struct _vcs_dpi_soc_bounding_box_st *bb, + struct pp_smu_nv_clock_table max_clocks) +{ + int i; + + dc_assert_fp_enabled(); + + // First pass - cap all clocks higher than the reported max + for (i = 0; i < bb->num_states; i++) { + if ((bb->clock_limits[i].dcfclk_mhz > (max_clocks.dcfClockInKhz / 1000)) + && max_clocks.dcfClockInKhz != 0) + bb->clock_limits[i].dcfclk_mhz = (max_clocks.dcfClockInKhz / 1000); + + if ((bb->clock_limits[i].dram_speed_mts > (max_clocks.uClockInKhz / 1000) * 16) + && max_clocks.uClockInKhz != 0) + bb->clock_limits[i].dram_speed_mts = (max_clocks.uClockInKhz / 1000) * 16; + + if ((bb->clock_limits[i].fabricclk_mhz > (max_clocks.fabricClockInKhz / 1000)) + && max_clocks.fabricClockInKhz != 0) + bb->clock_limits[i].fabricclk_mhz = (max_clocks.fabricClockInKhz / 1000); + + if ((bb->clock_limits[i].dispclk_mhz > (max_clocks.displayClockInKhz / 1000)) + && max_clocks.displayClockInKhz != 0) + bb->clock_limits[i].dispclk_mhz = (max_clocks.displayClockInKhz / 1000); + + if ((bb->clock_limits[i].dppclk_mhz > (max_clocks.dppClockInKhz / 1000)) + && max_clocks.dppClockInKhz != 0) + bb->clock_limits[i].dppclk_mhz = (max_clocks.dppClockInKhz / 1000); + + if ((bb->clock_limits[i].phyclk_mhz > (max_clocks.phyClockInKhz / 1000)) + && max_clocks.phyClockInKhz != 0) + bb->clock_limits[i].phyclk_mhz = (max_clocks.phyClockInKhz / 1000); + + if ((bb->clock_limits[i].socclk_mhz > (max_clocks.socClockInKhz / 1000)) + && max_clocks.socClockInKhz != 0) + bb->clock_limits[i].socclk_mhz = (max_clocks.socClockInKhz / 1000); + + if ((bb->clock_limits[i].dscclk_mhz > (max_clocks.dscClockInKhz / 1000)) + && max_clocks.dscClockInKhz != 0) + bb->clock_limits[i].dscclk_mhz = (max_clocks.dscClockInKhz / 1000); + } + + // Second pass - remove all duplicate clock states + for (i = bb->num_states - 1; i > 1; i--) { + bool duplicate = true; + + if (bb->clock_limits[i-1].dcfclk_mhz != bb->clock_limits[i].dcfclk_mhz) + duplicate = false; + if (bb->clock_limits[i-1].dispclk_mhz != bb->clock_limits[i].dispclk_mhz) + duplicate = false; + if (bb->clock_limits[i-1].dppclk_mhz != bb->clock_limits[i].dppclk_mhz) + duplicate = false; + if (bb->clock_limits[i-1].dram_speed_mts != bb->clock_limits[i].dram_speed_mts) + duplicate = false; + if (bb->clock_limits[i-1].dscclk_mhz != bb->clock_limits[i].dscclk_mhz) + duplicate = false; + if (bb->clock_limits[i-1].fabricclk_mhz != bb->clock_limits[i].fabricclk_mhz) + duplicate = false; + if (bb->clock_limits[i-1].phyclk_mhz != bb->clock_limits[i].phyclk_mhz) + duplicate = false; + if (bb->clock_limits[i-1].socclk_mhz != bb->clock_limits[i].socclk_mhz) + duplicate = false; + + if (duplicate) + bb->num_states--; + } +} + +void dcn20_patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb) +{ + dc_assert_fp_enabled(); + + if ((int)(bb->sr_exit_time_us * 1000) != dc->bb_overrides.sr_exit_time_ns + && dc->bb_overrides.sr_exit_time_ns) { + bb->sr_exit_time_us = dc->bb_overrides.sr_exit_time_ns / 1000.0; + } + + if ((int)(bb->sr_enter_plus_exit_time_us * 1000) + != dc->bb_overrides.sr_enter_plus_exit_time_ns + && dc->bb_overrides.sr_enter_plus_exit_time_ns) { + bb->sr_enter_plus_exit_time_us = + dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0; + } + + if ((int)(bb->urgent_latency_us * 1000) != dc->bb_overrides.urgent_latency_ns + && dc->bb_overrides.urgent_latency_ns) { + bb->urgent_latency_us = dc->bb_overrides.urgent_latency_ns / 1000.0; + } + + if ((int)(bb->dram_clock_change_latency_us * 1000) + != dc->bb_overrides.dram_clock_change_latency_ns + && dc->bb_overrides.dram_clock_change_latency_ns) { + bb->dram_clock_change_latency_us = + dc->bb_overrides.dram_clock_change_latency_ns / 1000.0; + } + + if ((int)(bb->dummy_pstate_latency_us * 1000) + != dc->bb_overrides.dummy_clock_change_latency_ns + && dc->bb_overrides.dummy_clock_change_latency_ns) { + bb->dummy_pstate_latency_us = + dc->bb_overrides.dummy_clock_change_latency_ns / 1000.0; + } +} + +static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *context, + bool fast_validate) +{ + bool out = false; + + BW_VAL_TRACE_SETUP(); + + int vlevel = 0; + int pipe_split_from[MAX_PIPES]; + int pipe_cnt = 0; + display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_ATOMIC); + DC_LOGGER_INIT(dc->ctx->logger); + + BW_VAL_TRACE_COUNT(); + + out = dcn20_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel, fast_validate); + + if (pipe_cnt == 0) + goto validate_out; + + if (!out) + goto validate_fail; + + BW_VAL_TRACE_END_VOLTAGE_LEVEL(); + + if (fast_validate) { + BW_VAL_TRACE_SKIP(fast); + goto validate_out; + } + + dcn20_calculate_wm(dc, context, pipes, &pipe_cnt, pipe_split_from, vlevel, fast_validate); + dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); + + BW_VAL_TRACE_END_WATERMARKS(); + + goto validate_out; + +validate_fail: + DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n", + dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states])); + + BW_VAL_TRACE_SKIP(fail); + out = false; + +validate_out: + kfree(pipes); + + BW_VAL_TRACE_FINISH(); + + return out; +} + +bool dcn20_validate_bandwidth_fp(struct dc *dc, + struct dc_state *context, + bool fast_validate) +{ + bool voltage_supported = false; + bool full_pstate_supported = false; + bool dummy_pstate_supported = false; + double p_state_latency_us; + + dc_assert_fp_enabled(); + + p_state_latency_us = context->bw_ctx.dml.soc.dram_clock_change_latency_us; + context->bw_ctx.dml.soc.disable_dram_clock_change_vactive_support = + dc->debug.disable_dram_clock_change_vactive_support; + context->bw_ctx.dml.soc.allow_dram_clock_one_display_vactive = + dc->debug.enable_dram_clock_change_one_display_vactive; + + /*Unsafe due to current pipe merge and split logic*/ + ASSERT(context != dc->current_state); + + if (fast_validate) { + return dcn20_validate_bandwidth_internal(dc, context, true); + } + + // Best case, we support full UCLK switch latency + voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false); + full_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support; + + if (context->bw_ctx.dml.soc.dummy_pstate_latency_us == 0 || + (voltage_supported && full_pstate_supported)) { + context->bw_ctx.bw.dcn.clk.p_state_change_support = full_pstate_supported; + goto restore_dml_state; + } + + // Fallback: Try to only support G6 temperature read latency + context->bw_ctx.dml.soc.dram_clock_change_latency_us = context->bw_ctx.dml.soc.dummy_pstate_latency_us; + + voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false); + dummy_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support; + + if (voltage_supported && (dummy_pstate_supported || !(context->stream_count))) { + context->bw_ctx.bw.dcn.clk.p_state_change_support = false; + goto restore_dml_state; + } + + // ERROR: fallback is supposed to always work. + ASSERT(false); + +restore_dml_state: + context->bw_ctx.dml.soc.dram_clock_change_latency_us = p_state_latency_us; + return voltage_supported; +} + +void dcn20_fpu_set_wm_ranges(int i, + struct pp_smu_wm_range_sets *ranges, + struct _vcs_dpi_soc_bounding_box_st *loaded_bb) +{ + dc_assert_fp_enabled(); + + ranges->reader_wm_sets[i].min_fill_clk_mhz = (i > 0) ? (loaded_bb->clock_limits[i - 1].dram_speed_mts / 16) + 1 : 0; + ranges->reader_wm_sets[i].max_fill_clk_mhz = loaded_bb->clock_limits[i].dram_speed_mts / 16; +} + +void dcn20_fpu_adjust_dppclk(struct vba_vars_st *v, + int vlevel, + int max_mpc_comb, + int pipe_idx, + bool is_validating_bw) +{ + dc_assert_fp_enabled(); + + if (is_validating_bw) + v->RequiredDPPCLK[vlevel][max_mpc_comb][pipe_idx] *= 2; + else + v->RequiredDPPCLK[vlevel][max_mpc_comb][pipe_idx] /= 2; +} 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 36f26126d574b..c59f1ad1b0e0e 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 @@ -23,6 +23,7 @@ * Authors: AMD * */ +#include "core_types.h" #ifndef __DCN20_FPU_H__ #define __DCN20_FPU_H__ @@ -31,4 +32,45 @@ void dcn20_populate_dml_writeback_from_context(struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes); +void dcn20_fpu_set_wb_arb_params(struct mcif_arb_params *wb_arb_params, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt, int i); +void dcn20_calculate_dlg_params(struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt, + int vlevel); +int dcn20_populate_dml_pipes_from_context(struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate); +void dcn20_calculate_wm(struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int *out_pipe_cnt, + int *pipe_split_from, + int vlevel, + bool fast_validate); +void dcn20_cap_soc_clocks(struct _vcs_dpi_soc_bounding_box_st *bb, + struct pp_smu_nv_clock_table max_clocks); +void dcn20_update_bounding_box(struct dc *dc, + struct _vcs_dpi_soc_bounding_box_st *bb, + struct pp_smu_nv_clock_table *max_clocks, + unsigned int *uclk_states, + unsigned int num_states); +void dcn20_patch_bounding_box(struct dc *dc, + struct _vcs_dpi_soc_bounding_box_st *bb); +bool dcn20_validate_bandwidth_fp(struct dc *dc, + struct dc_state *context, + bool fast_validate); +void dcn20_fpu_set_wm_ranges(int i, + struct pp_smu_wm_range_sets *ranges, + struct _vcs_dpi_soc_bounding_box_st *loaded_bb); +void dcn20_fpu_adjust_dppclk(struct vba_vars_st *v, + int vlevel, + int max_mpc_comb, + int pipe_idx, + bool is_validating_bw); + #endif /* __DCN20_FPU_H__ */ From 22f87d99832650d9389b0b3d08f3c970afc53f10 Mon Sep 17 00:00:00 2001 From: Melissa Wen <mwen@igalia.com> Date: Mon, 28 Feb 2022 20:10:46 -0100 Subject: [PATCH 23/65] drm/amd/display: move FPU operations from dcn21 to dml/dcn20 folder dml/dcn20_fpu file centralizes all DCN2x functions that require FPU access. Therefore, this patch moves FPU-related code from dcn21 to dcn20_fpu. These include: - dcn21_populate_dml_pipes_from_context() - dcn21_validate_bandwidth_fp() and related: - dcn21_calculate_wm(), - patch_bounding_box(), - calculate_wm_set_for_vlevel() - renaming update_bw_bounding_box() to dcn21_update_bw_bounding_box(), move to dcn20_fpu with related static function construct_low_pstate_lvl() Also, make dcn21_fast_validate_bw() public in dcn21_resource as it is called by dcn21_validate_bandwidth_fp() now in dcn20_fpu. Reuse dcn20_fpu_adjust_dppclk() in dcn21_fast_validate_bw() as it isolates the same FPU operation. Include dchubbub.h as it is required in dcn21_populate_dml_pipes_from_context() Signed-off-by: Melissa Wen <mwen@igalia.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn21/Makefile | 25 - .../drm/amd/display/dc/dcn21/dcn21_resource.c | 570 +----------------- .../drm/amd/display/dc/dcn21/dcn21_resource.h | 11 + .../drm/amd/display/dc/dml/dcn20/dcn20_fpu.c | 538 ++++++++++++++++- .../drm/amd/display/dc/dml/dcn20/dcn20_fpu.h | 9 + 5 files changed, 571 insertions(+), 582 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/Makefile b/drivers/gpu/drm/amd/display/dc/dcn21/Makefile index bb8c951410822..0dc06e4289993 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn21/Makefile @@ -5,31 +5,6 @@ DCN21 = dcn21_init.o dcn21_hubp.o dcn21_hubbub.o dcn21_resource.o \ dcn21_hwseq.o dcn21_link_encoder.o dcn21_dccg.o -ifdef CONFIG_X86 -CFLAGS_$(AMDDALPATH)/dc/dcn21/dcn21_resource.o := -mhard-float -msse -endif - -ifdef CONFIG_PPC64 -CFLAGS_$(AMDDALPATH)/dc/dcn21/dcn21_resource.o := -mhard-float -maltivec -endif - -ifdef CONFIG_CC_IS_GCC -ifeq ($(call cc-ifversion, -lt, 0701, y), y) -IS_OLD_GCC = 1 -endif -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/dcn21/dcn21_resource.o += -mpreferred-stack-boundary=4 -else -CFLAGS_$(AMDDALPATH)/dc/dcn21/dcn21_resource.o += -msse2 -endif -endif - AMD_DAL_DCN21 = $(addprefix $(AMDDALPATH)/dc/dcn21/,$(DCN21)) AMD_DISPLAY_FILES += $(AMD_DAL_DCN21) diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index 116a8ccf6c938..6127326567722 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -34,6 +34,7 @@ #include "resource.h" #include "include/irq_service_interface.h" #include "dcn20/dcn20_resource.h" +#include "dcn21/dcn21_resource.h" #include "dml/dcn20/dcn20_fpu.h" @@ -89,230 +90,6 @@ #include "dce/dmub_psr.h" #include "dce/dmub_abm.h" -#define DC_LOGGER_INIT(logger) - - -struct _vcs_dpi_ip_params_st dcn2_1_ip = { - .odm_capable = 1, - .gpuvm_enable = 1, - .hostvm_enable = 1, - .gpuvm_max_page_table_levels = 1, - .hostvm_max_page_table_levels = 4, - .hostvm_cached_page_table_levels = 2, - .num_dsc = 3, - .rob_buffer_size_kbytes = 168, - .det_buffer_size_kbytes = 164, - .dpte_buffer_size_in_pte_reqs_luma = 44, - .dpte_buffer_size_in_pte_reqs_chroma = 42,//todo - .dpp_output_buffer_pixels = 2560, - .opp_output_buffer_lines = 1, - .pixel_chunk_size_kbytes = 8, - .pte_enable = 1, - .max_page_table_levels = 4, - .pte_chunk_size_kbytes = 2, - .meta_chunk_size_kbytes = 2, - .min_meta_chunk_size_bytes = 256, - .writeback_chunk_size_kbytes = 2, - .line_buffer_size_bits = 789504, - .is_line_buffer_bpp_fixed = 0, - .line_buffer_fixed_bpp = 0, - .dcc_supported = true, - .max_line_buffer_lines = 12, - .writeback_luma_buffer_size_kbytes = 12, - .writeback_chroma_buffer_size_kbytes = 8, - .writeback_chroma_line_buffer_width_pixels = 4, - .writeback_max_hscl_ratio = 1, - .writeback_max_vscl_ratio = 1, - .writeback_min_hscl_ratio = 1, - .writeback_min_vscl_ratio = 1, - .writeback_max_hscl_taps = 12, - .writeback_max_vscl_taps = 12, - .writeback_line_buffer_luma_buffer_size = 0, - .writeback_line_buffer_chroma_buffer_size = 14643, - .cursor_buffer_size = 8, - .cursor_chunk_size = 2, - .max_num_otg = 4, - .max_num_dpp = 4, - .max_num_wb = 1, - .max_dchub_pscl_bw_pix_per_clk = 4, - .max_pscl_lb_bw_pix_per_clk = 2, - .max_lb_vscl_bw_pix_per_clk = 4, - .max_vscl_hscl_bw_pix_per_clk = 4, - .max_hscl_ratio = 4, - .max_vscl_ratio = 4, - .hscl_mults = 4, - .vscl_mults = 4, - .max_hscl_taps = 8, - .max_vscl_taps = 8, - .dispclk_ramp_margin_percent = 1, - .underscan_factor = 1.10, - .min_vblank_lines = 32, // - .dppclk_delay_subtotal = 77, // - .dppclk_delay_scl_lb_only = 16, - .dppclk_delay_scl = 50, - .dppclk_delay_cnvc_formatter = 8, - .dppclk_delay_cnvc_cursor = 6, - .dispclk_delay_subtotal = 87, // - .dcfclk_cstate_latency = 10, // SRExitTime - .max_inter_dcn_tile_repeaters = 8, - - .xfc_supported = false, - .xfc_fill_bw_overhead_percent = 10.0, - .xfc_fill_constant_bytes = 0, - .ptoi_supported = 0, - .number_of_cursors = 1, -}; - -struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = { - .clock_limits = { - { - .state = 0, - .dcfclk_mhz = 400.0, - .fabricclk_mhz = 400.0, - .dispclk_mhz = 600.0, - .dppclk_mhz = 400.00, - .phyclk_mhz = 600.0, - .socclk_mhz = 278.0, - .dscclk_mhz = 205.67, - .dram_speed_mts = 1600.0, - }, - { - .state = 1, - .dcfclk_mhz = 464.52, - .fabricclk_mhz = 800.0, - .dispclk_mhz = 654.55, - .dppclk_mhz = 626.09, - .phyclk_mhz = 600.0, - .socclk_mhz = 278.0, - .dscclk_mhz = 205.67, - .dram_speed_mts = 1600.0, - }, - { - .state = 2, - .dcfclk_mhz = 514.29, - .fabricclk_mhz = 933.0, - .dispclk_mhz = 757.89, - .dppclk_mhz = 685.71, - .phyclk_mhz = 600.0, - .socclk_mhz = 278.0, - .dscclk_mhz = 287.67, - .dram_speed_mts = 1866.0, - }, - { - .state = 3, - .dcfclk_mhz = 576.00, - .fabricclk_mhz = 1067.0, - .dispclk_mhz = 847.06, - .dppclk_mhz = 757.89, - .phyclk_mhz = 600.0, - .socclk_mhz = 715.0, - .dscclk_mhz = 318.334, - .dram_speed_mts = 2134.0, - }, - { - .state = 4, - .dcfclk_mhz = 626.09, - .fabricclk_mhz = 1200.0, - .dispclk_mhz = 900.00, - .dppclk_mhz = 847.06, - .phyclk_mhz = 810.0, - .socclk_mhz = 953.0, - .dscclk_mhz = 489.0, - .dram_speed_mts = 2400.0, - }, - { - .state = 5, - .dcfclk_mhz = 685.71, - .fabricclk_mhz = 1333.0, - .dispclk_mhz = 1028.57, - .dppclk_mhz = 960.00, - .phyclk_mhz = 810.0, - .socclk_mhz = 278.0, - .dscclk_mhz = 287.67, - .dram_speed_mts = 2666.0, - }, - { - .state = 6, - .dcfclk_mhz = 757.89, - .fabricclk_mhz = 1467.0, - .dispclk_mhz = 1107.69, - .dppclk_mhz = 1028.57, - .phyclk_mhz = 810.0, - .socclk_mhz = 715.0, - .dscclk_mhz = 318.334, - .dram_speed_mts = 3200.0, - }, - { - .state = 7, - .dcfclk_mhz = 847.06, - .fabricclk_mhz = 1600.0, - .dispclk_mhz = 1395.0, - .dppclk_mhz = 1285.00, - .phyclk_mhz = 1325.0, - .socclk_mhz = 953.0, - .dscclk_mhz = 489.0, - .dram_speed_mts = 4266.0, - }, - /*Extra state, no dispclk ramping*/ - { - .state = 8, - .dcfclk_mhz = 847.06, - .fabricclk_mhz = 1600.0, - .dispclk_mhz = 1395.0, - .dppclk_mhz = 1285.0, - .phyclk_mhz = 1325.0, - .socclk_mhz = 953.0, - .dscclk_mhz = 489.0, - .dram_speed_mts = 4266.0, - }, - - }, - - .sr_exit_time_us = 12.5, - .sr_enter_plus_exit_time_us = 17.0, - .urgent_latency_us = 4.0, - .urgent_latency_pixel_data_only_us = 4.0, - .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, - .urgent_latency_vm_data_only_us = 4.0, - .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, - .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, - .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, - .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 80.0, - .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 75.0, - .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0, - .max_avg_sdp_bw_use_normal_percent = 60.0, - .max_avg_dram_bw_use_normal_percent = 100.0, - .writeback_latency_us = 12.0, - .max_request_size_bytes = 256, - .dram_channel_width_bytes = 4, - .fabric_datapath_to_dcn_data_return_bytes = 32, - .dcn_downspread_percent = 0.5, - .downspread_percent = 0.38, - .dram_page_open_time_ns = 50.0, - .dram_rw_turnaround_time_ns = 17.5, - .dram_return_buffer_per_channel_bytes = 8192, - .round_trip_ping_latency_dcfclk_cycles = 128, - .urgent_out_of_order_return_per_channel_bytes = 4096, - .channel_interleave_bytes = 256, - .num_banks = 8, - .num_chans = 4, - .vmm_page_size_bytes = 4096, - .dram_clock_change_latency_us = 23.84, - .return_bus_width_bytes = 64, - .dispclk_dppclk_vco_speed_mhz = 3600, - .xfc_bus_transport_time_us = 4, - .xfc_xbuf_latency_tolerance_us = 4, - .use_urgent_burst_bw = 1, - .num_states = 8 -}; - -#ifndef MAX -#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) -#endif -#ifndef MIN -#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) -#endif - /* begin ********************* * macros to expend register list macro defined in HW object header file */ @@ -705,12 +482,6 @@ static const struct dcn10_stream_encoder_mask se_mask = { static void dcn21_pp_smu_destroy(struct pp_smu_funcs **pp_smu); -static int dcn21_populate_dml_pipes_from_context( - struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - bool fast_validate); - static struct input_pixel_processor *dcn21_ipp_create( struct dc_context *ctx, uint32_t inst) { @@ -1029,163 +800,13 @@ static void dcn21_resource_destruct(struct dcn21_resource_pool *pool) dcn21_pp_smu_destroy(&pool->base.pp_smu); } - -static void calculate_wm_set_for_vlevel( - int vlevel, - struct wm_range_table_entry *table_entry, - struct dcn_watermarks *wm_set, - struct display_mode_lib *dml, - display_e2e_pipe_params_st *pipes, - int pipe_cnt) -{ - double dram_clock_change_latency_cached = dml->soc.dram_clock_change_latency_us; - - ASSERT(vlevel < dml->soc.num_states); - /* only pipe 0 is read for voltage and dcf/soc clocks */ - pipes[0].clks_cfg.voltage = vlevel; - pipes[0].clks_cfg.dcfclk_mhz = dml->soc.clock_limits[vlevel].dcfclk_mhz; - pipes[0].clks_cfg.socclk_mhz = dml->soc.clock_limits[vlevel].socclk_mhz; - - dml->soc.dram_clock_change_latency_us = table_entry->pstate_latency_us; - dml->soc.sr_exit_time_us = table_entry->sr_exit_time_us; - dml->soc.sr_enter_plus_exit_time_us = table_entry->sr_enter_plus_exit_time_us; - - wm_set->urgent_ns = get_wm_urgent(dml, pipes, pipe_cnt) * 1000; - wm_set->cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(dml, pipes, pipe_cnt) * 1000; - wm_set->cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(dml, pipes, pipe_cnt) * 1000; - wm_set->cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(dml, pipes, pipe_cnt) * 1000; - wm_set->pte_meta_urgent_ns = get_wm_memory_trip(dml, pipes, pipe_cnt) * 1000; - wm_set->frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(dml, pipes, pipe_cnt) * 1000; - wm_set->frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(dml, pipes, pipe_cnt) * 1000; - wm_set->urgent_latency_ns = get_urgent_latency(dml, pipes, pipe_cnt) * 1000; - dml->soc.dram_clock_change_latency_us = dram_clock_change_latency_cached; - -} - -static void patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb) -{ - int i; - - if (dc->bb_overrides.sr_exit_time_ns) { - for (i = 0; i < WM_SET_COUNT; i++) { - dc->clk_mgr->bw_params->wm_table.entries[i].sr_exit_time_us = - dc->bb_overrides.sr_exit_time_ns / 1000.0; - } - } - - if (dc->bb_overrides.sr_enter_plus_exit_time_ns) { - for (i = 0; i < WM_SET_COUNT; i++) { - dc->clk_mgr->bw_params->wm_table.entries[i].sr_enter_plus_exit_time_us = - dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0; - } - } - - if (dc->bb_overrides.urgent_latency_ns) { - bb->urgent_latency_us = dc->bb_overrides.urgent_latency_ns / 1000.0; - } - - if (dc->bb_overrides.dram_clock_change_latency_ns) { - for (i = 0; i < WM_SET_COUNT; i++) { - dc->clk_mgr->bw_params->wm_table.entries[i].pstate_latency_us = - dc->bb_overrides.dram_clock_change_latency_ns / 1000.0; - } - } -} - -static void dcn21_calculate_wm( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int *out_pipe_cnt, - int *pipe_split_from, - int vlevel_req, - bool fast_validate) -{ - int pipe_cnt, i, pipe_idx; - int vlevel, vlevel_max; - struct wm_range_table_entry *table_entry; - struct clk_bw_params *bw_params = dc->clk_mgr->bw_params; - - ASSERT(bw_params); - - patch_bounding_box(dc, &context->bw_ctx.dml.soc); - - for (i = 0, pipe_idx = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { - if (!context->res_ctx.pipe_ctx[i].stream) - continue; - - pipes[pipe_cnt].clks_cfg.refclk_mhz = dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000.0; - pipes[pipe_cnt].clks_cfg.dispclk_mhz = context->bw_ctx.dml.vba.RequiredDISPCLK[vlevel_req][context->bw_ctx.dml.vba.maxMpcComb]; - - if (pipe_split_from[i] < 0) { - pipes[pipe_cnt].clks_cfg.dppclk_mhz = - context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel_req][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx]; - if (context->bw_ctx.dml.vba.BlendingAndTiming[pipe_idx] == pipe_idx) - pipes[pipe_cnt].pipe.dest.odm_combine = - context->bw_ctx.dml.vba.ODMCombineEnablePerState[vlevel_req][pipe_idx]; - else - pipes[pipe_cnt].pipe.dest.odm_combine = 0; - pipe_idx++; - } else { - pipes[pipe_cnt].clks_cfg.dppclk_mhz = - context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel_req][context->bw_ctx.dml.vba.maxMpcComb][pipe_split_from[i]]; - if (context->bw_ctx.dml.vba.BlendingAndTiming[pipe_split_from[i]] == pipe_split_from[i]) - pipes[pipe_cnt].pipe.dest.odm_combine = - context->bw_ctx.dml.vba.ODMCombineEnablePerState[vlevel_req][pipe_split_from[i]]; - else - pipes[pipe_cnt].pipe.dest.odm_combine = 0; - } - pipe_cnt++; - } - - if (pipe_cnt != pipe_idx) { - if (dc->res_pool->funcs->populate_dml_pipes) - pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, - context, pipes, fast_validate); - else - pipe_cnt = dcn21_populate_dml_pipes_from_context(dc, - context, pipes, fast_validate); - } - - *out_pipe_cnt = pipe_cnt; - - vlevel_max = bw_params->clk_table.num_entries - 1; - - - /* WM Set D */ - table_entry = &bw_params->wm_table.entries[WM_D]; - if (table_entry->wm_type == WM_TYPE_RETRAINING) - vlevel = 0; - else - vlevel = vlevel_max; - calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.d, - &context->bw_ctx.dml, pipes, pipe_cnt); - /* WM Set C */ - table_entry = &bw_params->wm_table.entries[WM_C]; - vlevel = MIN(MAX(vlevel_req, 3), vlevel_max); - calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.c, - &context->bw_ctx.dml, pipes, pipe_cnt); - /* WM Set B */ - table_entry = &bw_params->wm_table.entries[WM_B]; - vlevel = MIN(MAX(vlevel_req, 2), vlevel_max); - calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.b, - &context->bw_ctx.dml, pipes, pipe_cnt); - - /* WM Set A */ - table_entry = &bw_params->wm_table.entries[WM_A]; - vlevel = MIN(vlevel_req, vlevel_max); - calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.a, - &context->bw_ctx.dml, pipes, pipe_cnt); -} - - -static bool dcn21_fast_validate_bw( - struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int *pipe_cnt_out, - int *pipe_split_from, - int *vlevel_out, - bool fast_validate) +bool dcn21_fast_validate_bw(struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int *pipe_cnt_out, + int *pipe_split_from, + int *vlevel_out, + bool fast_validate) { bool out = false; int split[MAX_PIPES] = { 0 }; @@ -1197,7 +818,9 @@ static bool dcn21_fast_validate_bw( dcn20_merge_pipes_for_validate(dc, context); + DC_FP_START(); pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); + DC_FP_END(); *pipe_cnt_out = pipe_cnt; @@ -1287,7 +910,9 @@ static bool dcn21_fast_validate_bw( hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe); ASSERT(hsplit_pipe); if (!hsplit_pipe) { - context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx] *= 2; + DC_FP_START(); + dcn20_fpu_adjust_dppclk(&context->bw_ctx.dml.vba, vlevel, context->bw_ctx.dml.vba.maxMpcComb, pipe_idx, true); + DC_FP_END(); continue; } if (context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) { @@ -1329,63 +954,6 @@ static bool dcn21_fast_validate_bw( return out; } -static noinline bool dcn21_validate_bandwidth_fp(struct dc *dc, - struct dc_state *context, bool fast_validate) -{ - bool out = false; - - BW_VAL_TRACE_SETUP(); - - int vlevel = 0; - int pipe_split_from[MAX_PIPES]; - int pipe_cnt = 0; - display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_ATOMIC); - DC_LOGGER_INIT(dc->ctx->logger); - - BW_VAL_TRACE_COUNT(); - - /*Unsafe due to current pipe merge and split logic*/ - ASSERT(context != dc->current_state); - - out = dcn21_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel, fast_validate); - - if (pipe_cnt == 0) - goto validate_out; - - if (!out) - goto validate_fail; - - BW_VAL_TRACE_END_VOLTAGE_LEVEL(); - - if (fast_validate) { - BW_VAL_TRACE_SKIP(fast); - goto validate_out; - } - - dcn21_calculate_wm(dc, context, pipes, &pipe_cnt, pipe_split_from, vlevel, fast_validate); - DC_FP_START(); - dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); - DC_FP_END(); - - BW_VAL_TRACE_END_WATERMARKS(); - - goto validate_out; - -validate_fail: - DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n", - dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states])); - - BW_VAL_TRACE_SKIP(fail); - out = false; - -validate_out: - kfree(pipes); - - BW_VAL_TRACE_FINISH(); - - return out; -} - /* * Some of the functions further below use the FPU, so we need to wrap this * with DC_FP_START()/DC_FP_END(). Use the same approach as for @@ -1560,94 +1128,6 @@ static struct display_stream_compressor *dcn21_dsc_create(struct dc_context *ctx return &dsc->base; } -static struct _vcs_dpi_voltage_scaling_st construct_low_pstate_lvl(struct clk_limit_table *clk_table, unsigned int high_voltage_lvl) -{ - struct _vcs_dpi_voltage_scaling_st low_pstate_lvl; - int i; - - low_pstate_lvl.state = 1; - low_pstate_lvl.dcfclk_mhz = clk_table->entries[0].dcfclk_mhz; - low_pstate_lvl.fabricclk_mhz = clk_table->entries[0].fclk_mhz; - low_pstate_lvl.socclk_mhz = clk_table->entries[0].socclk_mhz; - low_pstate_lvl.dram_speed_mts = clk_table->entries[0].memclk_mhz * 2; - - low_pstate_lvl.dispclk_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].dispclk_mhz; - low_pstate_lvl.dppclk_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].dppclk_mhz; - low_pstate_lvl.dram_bw_per_chan_gbps = dcn2_1_soc.clock_limits[high_voltage_lvl].dram_bw_per_chan_gbps; - low_pstate_lvl.dscclk_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].dscclk_mhz; - low_pstate_lvl.dtbclk_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].dtbclk_mhz; - low_pstate_lvl.phyclk_d18_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].phyclk_d18_mhz; - low_pstate_lvl.phyclk_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].phyclk_mhz; - - for (i = clk_table->num_entries; i > 1; i--) - clk_table->entries[i] = clk_table->entries[i-1]; - clk_table->entries[1] = clk_table->entries[0]; - clk_table->num_entries++; - - return low_pstate_lvl; -} - -static void update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) -{ - struct dcn21_resource_pool *pool = TO_DCN21_RES_POOL(dc->res_pool); - struct clk_limit_table *clk_table = &bw_params->clk_table; - struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES]; - unsigned int i, closest_clk_lvl = 0, k = 0; - int j; - - dcn2_1_ip.max_num_otg = pool->base.res_cap->num_timing_generator; - dcn2_1_ip.max_num_dpp = pool->base.pipe_count; - dcn2_1_soc.num_chans = bw_params->num_channels; - - ASSERT(clk_table->num_entries); - /* Copy dcn2_1_soc.clock_limits to clock_limits to avoid copying over null states later */ - for (i = 0; i < dcn2_1_soc.num_states + 1; i++) { - clock_limits[i] = dcn2_1_soc.clock_limits[i]; - } - - for (i = 0; i < clk_table->num_entries; i++) { - /* loop backwards*/ - for (closest_clk_lvl = 0, j = dcn2_1_soc.num_states - 1; j >= 0; j--) { - if ((unsigned int) dcn2_1_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) { - closest_clk_lvl = j; - break; - } - } - - /* clk_table[1] is reserved for min DF PState. skip here to fill in later. */ - if (i == 1) - k++; - - clock_limits[k].state = k; - clock_limits[k].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; - clock_limits[k].fabricclk_mhz = clk_table->entries[i].fclk_mhz; - clock_limits[k].socclk_mhz = clk_table->entries[i].socclk_mhz; - clock_limits[k].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2; - - clock_limits[k].dispclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dispclk_mhz; - clock_limits[k].dppclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dppclk_mhz; - clock_limits[k].dram_bw_per_chan_gbps = dcn2_1_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; - clock_limits[k].dscclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dscclk_mhz; - clock_limits[k].dtbclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; - clock_limits[k].phyclk_d18_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; - clock_limits[k].phyclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_mhz; - - k++; - } - for (i = 0; i < clk_table->num_entries + 1; i++) - dcn2_1_soc.clock_limits[i] = clock_limits[i]; - if (clk_table->num_entries) { - dcn2_1_soc.num_states = clk_table->num_entries + 1; - /* fill in min DF PState */ - dcn2_1_soc.clock_limits[1] = construct_low_pstate_lvl(clk_table, closest_clk_lvl); - /* duplicate last level */ - dcn2_1_soc.clock_limits[dcn2_1_soc.num_states] = dcn2_1_soc.clock_limits[dcn2_1_soc.num_states - 1]; - dcn2_1_soc.clock_limits[dcn2_1_soc.num_states].state = dcn2_1_soc.num_states; - } - - dml_init_instance(&dc->dml, &dcn2_1_soc, &dcn2_1_ip, DML_PROJECT_DCN21); -} - static struct pp_smu_funcs *dcn21_pp_smu_create(struct dc_context *ctx) { struct pp_smu_funcs *pp_smu = kzalloc(sizeof(*pp_smu), GFP_KERNEL); @@ -1898,28 +1378,6 @@ static uint32_t read_pipe_fuses(struct dc_context *ctx) return value; } -static int dcn21_populate_dml_pipes_from_context( - struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - bool fast_validate) -{ - uint32_t pipe_cnt; - int i; - - DC_FP_START(); - pipe_cnt = dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); - DC_FP_END(); - - for (i = 0; i < pipe_cnt; i++) { - - pipes[i].pipe.src.hostvm = dc->res_pool->hubbub->riommu_active; - pipes[i].pipe.src.gpuvm = 1; - } - - return pipe_cnt; -} - static enum dc_status dcn21_patch_unknown_plane_state(struct dc_plane_state *plane_state) { enum dc_status result = DC_OK; @@ -1947,7 +1405,7 @@ static const struct resource_funcs dcn21_res_pool_funcs = { .patch_unknown_plane_state = dcn21_patch_unknown_plane_state, .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, - .update_bw_bounding_box = update_bw_bounding_box + .update_bw_bounding_box = dcn21_update_bw_bounding_box, }; static bool dcn21_resource_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.h b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.h index a27355171bca5..f7ecc002c2f7f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.h @@ -35,11 +35,22 @@ struct dc; struct resource_pool; struct _vcs_dpi_display_pipe_params_st; +extern struct _vcs_dpi_ip_params_st dcn2_1_ip; +extern struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc; + struct dcn21_resource_pool { struct resource_pool base; }; struct resource_pool *dcn21_create_resource_pool( const struct dc_init_data *init_data, struct dc *dc); +bool dcn21_fast_validate_bw( + struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int *pipe_cnt_out, + int *pipe_split_from, + int *vlevel_out, + bool fast_validate); #endif /* _DCN21_RESOURCE_H_ */ 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 f321e6a82d128..7cc8c78cb1637 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 @@ -27,10 +27,21 @@ #include "resource.h" #include "clk_mgr.h" #include "dc_link_dp.h" +#include "dchubbub.h" #include "dcn20/dcn20_resource.h" +#include "dcn21/dcn21_resource.h" #include "dcn20_fpu.h" +#define DC_LOGGER_INIT(logger) + +#ifndef MAX +#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) +#endif +#ifndef MIN +#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) +#endif + /** * DOC: DCN2x FPU manipulation Overview * @@ -425,7 +436,219 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv14_soc = { struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv12_soc = { 0 }; -#define DC_LOGGER_INIT(logger) +struct _vcs_dpi_ip_params_st dcn2_1_ip = { + .odm_capable = 1, + .gpuvm_enable = 1, + .hostvm_enable = 1, + .gpuvm_max_page_table_levels = 1, + .hostvm_max_page_table_levels = 4, + .hostvm_cached_page_table_levels = 2, + .num_dsc = 3, + .rob_buffer_size_kbytes = 168, + .det_buffer_size_kbytes = 164, + .dpte_buffer_size_in_pte_reqs_luma = 44, + .dpte_buffer_size_in_pte_reqs_chroma = 42,//todo + .dpp_output_buffer_pixels = 2560, + .opp_output_buffer_lines = 1, + .pixel_chunk_size_kbytes = 8, + .pte_enable = 1, + .max_page_table_levels = 4, + .pte_chunk_size_kbytes = 2, + .meta_chunk_size_kbytes = 2, + .min_meta_chunk_size_bytes = 256, + .writeback_chunk_size_kbytes = 2, + .line_buffer_size_bits = 789504, + .is_line_buffer_bpp_fixed = 0, + .line_buffer_fixed_bpp = 0, + .dcc_supported = true, + .max_line_buffer_lines = 12, + .writeback_luma_buffer_size_kbytes = 12, + .writeback_chroma_buffer_size_kbytes = 8, + .writeback_chroma_line_buffer_width_pixels = 4, + .writeback_max_hscl_ratio = 1, + .writeback_max_vscl_ratio = 1, + .writeback_min_hscl_ratio = 1, + .writeback_min_vscl_ratio = 1, + .writeback_max_hscl_taps = 12, + .writeback_max_vscl_taps = 12, + .writeback_line_buffer_luma_buffer_size = 0, + .writeback_line_buffer_chroma_buffer_size = 14643, + .cursor_buffer_size = 8, + .cursor_chunk_size = 2, + .max_num_otg = 4, + .max_num_dpp = 4, + .max_num_wb = 1, + .max_dchub_pscl_bw_pix_per_clk = 4, + .max_pscl_lb_bw_pix_per_clk = 2, + .max_lb_vscl_bw_pix_per_clk = 4, + .max_vscl_hscl_bw_pix_per_clk = 4, + .max_hscl_ratio = 4, + .max_vscl_ratio = 4, + .hscl_mults = 4, + .vscl_mults = 4, + .max_hscl_taps = 8, + .max_vscl_taps = 8, + .dispclk_ramp_margin_percent = 1, + .underscan_factor = 1.10, + .min_vblank_lines = 32, // + .dppclk_delay_subtotal = 77, // + .dppclk_delay_scl_lb_only = 16, + .dppclk_delay_scl = 50, + .dppclk_delay_cnvc_formatter = 8, + .dppclk_delay_cnvc_cursor = 6, + .dispclk_delay_subtotal = 87, // + .dcfclk_cstate_latency = 10, // SRExitTime + .max_inter_dcn_tile_repeaters = 8, + + .xfc_supported = false, + .xfc_fill_bw_overhead_percent = 10.0, + .xfc_fill_constant_bytes = 0, + .ptoi_supported = 0, + .number_of_cursors = 1, +}; + +struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = { + .clock_limits = { + { + .state = 0, + .dcfclk_mhz = 400.0, + .fabricclk_mhz = 400.0, + .dispclk_mhz = 600.0, + .dppclk_mhz = 400.00, + .phyclk_mhz = 600.0, + .socclk_mhz = 278.0, + .dscclk_mhz = 205.67, + .dram_speed_mts = 1600.0, + }, + { + .state = 1, + .dcfclk_mhz = 464.52, + .fabricclk_mhz = 800.0, + .dispclk_mhz = 654.55, + .dppclk_mhz = 626.09, + .phyclk_mhz = 600.0, + .socclk_mhz = 278.0, + .dscclk_mhz = 205.67, + .dram_speed_mts = 1600.0, + }, + { + .state = 2, + .dcfclk_mhz = 514.29, + .fabricclk_mhz = 933.0, + .dispclk_mhz = 757.89, + .dppclk_mhz = 685.71, + .phyclk_mhz = 600.0, + .socclk_mhz = 278.0, + .dscclk_mhz = 287.67, + .dram_speed_mts = 1866.0, + }, + { + .state = 3, + .dcfclk_mhz = 576.00, + .fabricclk_mhz = 1067.0, + .dispclk_mhz = 847.06, + .dppclk_mhz = 757.89, + .phyclk_mhz = 600.0, + .socclk_mhz = 715.0, + .dscclk_mhz = 318.334, + .dram_speed_mts = 2134.0, + }, + { + .state = 4, + .dcfclk_mhz = 626.09, + .fabricclk_mhz = 1200.0, + .dispclk_mhz = 900.00, + .dppclk_mhz = 847.06, + .phyclk_mhz = 810.0, + .socclk_mhz = 953.0, + .dscclk_mhz = 489.0, + .dram_speed_mts = 2400.0, + }, + { + .state = 5, + .dcfclk_mhz = 685.71, + .fabricclk_mhz = 1333.0, + .dispclk_mhz = 1028.57, + .dppclk_mhz = 960.00, + .phyclk_mhz = 810.0, + .socclk_mhz = 278.0, + .dscclk_mhz = 287.67, + .dram_speed_mts = 2666.0, + }, + { + .state = 6, + .dcfclk_mhz = 757.89, + .fabricclk_mhz = 1467.0, + .dispclk_mhz = 1107.69, + .dppclk_mhz = 1028.57, + .phyclk_mhz = 810.0, + .socclk_mhz = 715.0, + .dscclk_mhz = 318.334, + .dram_speed_mts = 3200.0, + }, + { + .state = 7, + .dcfclk_mhz = 847.06, + .fabricclk_mhz = 1600.0, + .dispclk_mhz = 1395.0, + .dppclk_mhz = 1285.00, + .phyclk_mhz = 1325.0, + .socclk_mhz = 953.0, + .dscclk_mhz = 489.0, + .dram_speed_mts = 4266.0, + }, + /*Extra state, no dispclk ramping*/ + { + .state = 8, + .dcfclk_mhz = 847.06, + .fabricclk_mhz = 1600.0, + .dispclk_mhz = 1395.0, + .dppclk_mhz = 1285.0, + .phyclk_mhz = 1325.0, + .socclk_mhz = 953.0, + .dscclk_mhz = 489.0, + .dram_speed_mts = 4266.0, + }, + + }, + + .sr_exit_time_us = 12.5, + .sr_enter_plus_exit_time_us = 17.0, + .urgent_latency_us = 4.0, + .urgent_latency_pixel_data_only_us = 4.0, + .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, + .urgent_latency_vm_data_only_us = 4.0, + .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, + .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, + .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 80.0, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 75.0, + .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0, + .max_avg_sdp_bw_use_normal_percent = 60.0, + .max_avg_dram_bw_use_normal_percent = 100.0, + .writeback_latency_us = 12.0, + .max_request_size_bytes = 256, + .dram_channel_width_bytes = 4, + .fabric_datapath_to_dcn_data_return_bytes = 32, + .dcn_downspread_percent = 0.5, + .downspread_percent = 0.38, + .dram_page_open_time_ns = 50.0, + .dram_rw_turnaround_time_ns = 17.5, + .dram_return_buffer_per_channel_bytes = 8192, + .round_trip_ping_latency_dcfclk_cycles = 128, + .urgent_out_of_order_return_per_channel_bytes = 4096, + .channel_interleave_bytes = 256, + .num_banks = 8, + .num_chans = 4, + .vmm_page_size_bytes = 4096, + .dram_clock_change_latency_us = 23.84, + .return_bus_width_bytes = 64, + .dispclk_dppclk_vco_speed_mhz = 3600, + .xfc_bus_transport_time_us = 4, + .xfc_xbuf_latency_tolerance_us = 4, + .use_urgent_burst_bw = 1, + .num_states = 8 +}; void dcn20_populate_dml_writeback_from_context(struct dc *dc, struct resource_context *res_ctx, @@ -1486,3 +1709,316 @@ void dcn20_fpu_adjust_dppclk(struct vba_vars_st *v, else v->RequiredDPPCLK[vlevel][max_mpc_comb][pipe_idx] /= 2; } + +int dcn21_populate_dml_pipes_from_context(struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate) +{ + uint32_t pipe_cnt; + int i; + + dc_assert_fp_enabled(); + + pipe_cnt = dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + + for (i = 0; i < pipe_cnt; i++) { + + pipes[i].pipe.src.hostvm = dc->res_pool->hubbub->riommu_active; + pipes[i].pipe.src.gpuvm = 1; + } + + return pipe_cnt; +} + +static void patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb) +{ + int i; + + if (dc->bb_overrides.sr_exit_time_ns) { + for (i = 0; i < WM_SET_COUNT; i++) { + dc->clk_mgr->bw_params->wm_table.entries[i].sr_exit_time_us = + dc->bb_overrides.sr_exit_time_ns / 1000.0; + } + } + + if (dc->bb_overrides.sr_enter_plus_exit_time_ns) { + for (i = 0; i < WM_SET_COUNT; i++) { + dc->clk_mgr->bw_params->wm_table.entries[i].sr_enter_plus_exit_time_us = + dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0; + } + } + + if (dc->bb_overrides.urgent_latency_ns) { + bb->urgent_latency_us = dc->bb_overrides.urgent_latency_ns / 1000.0; + } + + if (dc->bb_overrides.dram_clock_change_latency_ns) { + for (i = 0; i < WM_SET_COUNT; i++) { + dc->clk_mgr->bw_params->wm_table.entries[i].pstate_latency_us = + dc->bb_overrides.dram_clock_change_latency_ns / 1000.0; + } + } +} + +static void calculate_wm_set_for_vlevel(int vlevel, + struct wm_range_table_entry *table_entry, + struct dcn_watermarks *wm_set, + struct display_mode_lib *dml, + display_e2e_pipe_params_st *pipes, + int pipe_cnt) +{ + double dram_clock_change_latency_cached = dml->soc.dram_clock_change_latency_us; + + ASSERT(vlevel < dml->soc.num_states); + /* only pipe 0 is read for voltage and dcf/soc clocks */ + pipes[0].clks_cfg.voltage = vlevel; + pipes[0].clks_cfg.dcfclk_mhz = dml->soc.clock_limits[vlevel].dcfclk_mhz; + pipes[0].clks_cfg.socclk_mhz = dml->soc.clock_limits[vlevel].socclk_mhz; + + dml->soc.dram_clock_change_latency_us = table_entry->pstate_latency_us; + dml->soc.sr_exit_time_us = table_entry->sr_exit_time_us; + dml->soc.sr_enter_plus_exit_time_us = table_entry->sr_enter_plus_exit_time_us; + + wm_set->urgent_ns = get_wm_urgent(dml, pipes, pipe_cnt) * 1000; + wm_set->cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(dml, pipes, pipe_cnt) * 1000; + wm_set->cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(dml, pipes, pipe_cnt) * 1000; + wm_set->cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(dml, pipes, pipe_cnt) * 1000; + wm_set->pte_meta_urgent_ns = get_wm_memory_trip(dml, pipes, pipe_cnt) * 1000; + wm_set->frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(dml, pipes, pipe_cnt) * 1000; + wm_set->frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(dml, pipes, pipe_cnt) * 1000; + wm_set->urgent_latency_ns = get_urgent_latency(dml, pipes, pipe_cnt) * 1000; + dml->soc.dram_clock_change_latency_us = dram_clock_change_latency_cached; +} + +static void dcn21_calculate_wm(struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int *out_pipe_cnt, + int *pipe_split_from, + int vlevel_req, + bool fast_validate) +{ + int pipe_cnt, i, pipe_idx; + int vlevel, vlevel_max; + struct wm_range_table_entry *table_entry; + struct clk_bw_params *bw_params = dc->clk_mgr->bw_params; + + ASSERT(bw_params); + + patch_bounding_box(dc, &context->bw_ctx.dml.soc); + + for (i = 0, pipe_idx = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { + if (!context->res_ctx.pipe_ctx[i].stream) + continue; + + pipes[pipe_cnt].clks_cfg.refclk_mhz = dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000.0; + pipes[pipe_cnt].clks_cfg.dispclk_mhz = context->bw_ctx.dml.vba.RequiredDISPCLK[vlevel_req][context->bw_ctx.dml.vba.maxMpcComb]; + + if (pipe_split_from[i] < 0) { + pipes[pipe_cnt].clks_cfg.dppclk_mhz = + context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel_req][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx]; + if (context->bw_ctx.dml.vba.BlendingAndTiming[pipe_idx] == pipe_idx) + pipes[pipe_cnt].pipe.dest.odm_combine = + context->bw_ctx.dml.vba.ODMCombineEnablePerState[vlevel_req][pipe_idx]; + else + pipes[pipe_cnt].pipe.dest.odm_combine = 0; + pipe_idx++; + } else { + pipes[pipe_cnt].clks_cfg.dppclk_mhz = + context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel_req][context->bw_ctx.dml.vba.maxMpcComb][pipe_split_from[i]]; + if (context->bw_ctx.dml.vba.BlendingAndTiming[pipe_split_from[i]] == pipe_split_from[i]) + pipes[pipe_cnt].pipe.dest.odm_combine = + context->bw_ctx.dml.vba.ODMCombineEnablePerState[vlevel_req][pipe_split_from[i]]; + else + pipes[pipe_cnt].pipe.dest.odm_combine = 0; + } + pipe_cnt++; + } + + if (pipe_cnt != pipe_idx) { + if (dc->res_pool->funcs->populate_dml_pipes) + pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, + context, pipes, fast_validate); + else + pipe_cnt = dcn21_populate_dml_pipes_from_context(dc, + context, pipes, fast_validate); + } + + *out_pipe_cnt = pipe_cnt; + + vlevel_max = bw_params->clk_table.num_entries - 1; + + + /* WM Set D */ + table_entry = &bw_params->wm_table.entries[WM_D]; + if (table_entry->wm_type == WM_TYPE_RETRAINING) + vlevel = 0; + else + vlevel = vlevel_max; + calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.d, + &context->bw_ctx.dml, pipes, pipe_cnt); + /* WM Set C */ + table_entry = &bw_params->wm_table.entries[WM_C]; + vlevel = MIN(MAX(vlevel_req, 3), vlevel_max); + calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.c, + &context->bw_ctx.dml, pipes, pipe_cnt); + /* WM Set B */ + table_entry = &bw_params->wm_table.entries[WM_B]; + vlevel = MIN(MAX(vlevel_req, 2), vlevel_max); + calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.b, + &context->bw_ctx.dml, pipes, pipe_cnt); + + /* WM Set A */ + table_entry = &bw_params->wm_table.entries[WM_A]; + vlevel = MIN(vlevel_req, vlevel_max); + calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.a, + &context->bw_ctx.dml, pipes, pipe_cnt); +} + +bool dcn21_validate_bandwidth_fp(struct dc *dc, + struct dc_state *context, + bool fast_validate) +{ + bool out = false; + + BW_VAL_TRACE_SETUP(); + + int vlevel = 0; + int pipe_split_from[MAX_PIPES]; + int pipe_cnt = 0; + display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_ATOMIC); + DC_LOGGER_INIT(dc->ctx->logger); + + BW_VAL_TRACE_COUNT(); + + dc_assert_fp_enabled(); + + /*Unsafe due to current pipe merge and split logic*/ + ASSERT(context != dc->current_state); + + out = dcn21_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel, fast_validate); + + if (pipe_cnt == 0) + goto validate_out; + + if (!out) + goto validate_fail; + + BW_VAL_TRACE_END_VOLTAGE_LEVEL(); + + if (fast_validate) { + BW_VAL_TRACE_SKIP(fast); + goto validate_out; + } + + dcn21_calculate_wm(dc, context, pipes, &pipe_cnt, pipe_split_from, vlevel, fast_validate); + dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); + + BW_VAL_TRACE_END_WATERMARKS(); + + goto validate_out; + +validate_fail: + DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n", + dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states])); + + BW_VAL_TRACE_SKIP(fail); + out = false; + +validate_out: + kfree(pipes); + + BW_VAL_TRACE_FINISH(); + + return out; +} + +static struct _vcs_dpi_voltage_scaling_st construct_low_pstate_lvl(struct clk_limit_table *clk_table, unsigned int high_voltage_lvl) +{ + struct _vcs_dpi_voltage_scaling_st low_pstate_lvl; + int i; + + low_pstate_lvl.state = 1; + low_pstate_lvl.dcfclk_mhz = clk_table->entries[0].dcfclk_mhz; + low_pstate_lvl.fabricclk_mhz = clk_table->entries[0].fclk_mhz; + low_pstate_lvl.socclk_mhz = clk_table->entries[0].socclk_mhz; + low_pstate_lvl.dram_speed_mts = clk_table->entries[0].memclk_mhz * 2; + + low_pstate_lvl.dispclk_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].dispclk_mhz; + low_pstate_lvl.dppclk_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].dppclk_mhz; + low_pstate_lvl.dram_bw_per_chan_gbps = dcn2_1_soc.clock_limits[high_voltage_lvl].dram_bw_per_chan_gbps; + low_pstate_lvl.dscclk_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].dscclk_mhz; + low_pstate_lvl.dtbclk_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].dtbclk_mhz; + low_pstate_lvl.phyclk_d18_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].phyclk_d18_mhz; + low_pstate_lvl.phyclk_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].phyclk_mhz; + + for (i = clk_table->num_entries; i > 1; i--) + clk_table->entries[i] = clk_table->entries[i-1]; + clk_table->entries[1] = clk_table->entries[0]; + clk_table->num_entries++; + + return low_pstate_lvl; +} + +void dcn21_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +{ + struct dcn21_resource_pool *pool = TO_DCN21_RES_POOL(dc->res_pool); + struct clk_limit_table *clk_table = &bw_params->clk_table; + struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES]; + unsigned int i, closest_clk_lvl = 0, k = 0; + int j; + + dc_assert_fp_enabled(); + + dcn2_1_ip.max_num_otg = pool->base.res_cap->num_timing_generator; + dcn2_1_ip.max_num_dpp = pool->base.pipe_count; + dcn2_1_soc.num_chans = bw_params->num_channels; + + ASSERT(clk_table->num_entries); + /* Copy dcn2_1_soc.clock_limits to clock_limits to avoid copying over null states later */ + for (i = 0; i < dcn2_1_soc.num_states + 1; i++) { + clock_limits[i] = dcn2_1_soc.clock_limits[i]; + } + + for (i = 0; i < clk_table->num_entries; i++) { + /* loop backwards*/ + for (closest_clk_lvl = 0, j = dcn2_1_soc.num_states - 1; j >= 0; j--) { + if ((unsigned int) dcn2_1_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) { + closest_clk_lvl = j; + break; + } + } + + /* clk_table[1] is reserved for min DF PState. skip here to fill in later. */ + if (i == 1) + k++; + + clock_limits[k].state = k; + clock_limits[k].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; + clock_limits[k].fabricclk_mhz = clk_table->entries[i].fclk_mhz; + clock_limits[k].socclk_mhz = clk_table->entries[i].socclk_mhz; + clock_limits[k].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2; + + clock_limits[k].dispclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dispclk_mhz; + clock_limits[k].dppclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dppclk_mhz; + clock_limits[k].dram_bw_per_chan_gbps = dcn2_1_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; + clock_limits[k].dscclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dscclk_mhz; + clock_limits[k].dtbclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; + clock_limits[k].phyclk_d18_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; + clock_limits[k].phyclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_mhz; + + k++; + } + for (i = 0; i < clk_table->num_entries + 1; i++) + dcn2_1_soc.clock_limits[i] = clock_limits[i]; + if (clk_table->num_entries) { + dcn2_1_soc.num_states = clk_table->num_entries + 1; + /* fill in min DF PState */ + dcn2_1_soc.clock_limits[1] = construct_low_pstate_lvl(clk_table, closest_clk_lvl); + /* duplicate last level */ + dcn2_1_soc.clock_limits[dcn2_1_soc.num_states] = dcn2_1_soc.clock_limits[dcn2_1_soc.num_states - 1]; + dcn2_1_soc.clock_limits[dcn2_1_soc.num_states].state = dcn2_1_soc.num_states; + } + + dml_init_instance(&dc->dml, &dcn2_1_soc, &dcn2_1_ip, DML_PROJECT_DCN21); +} 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 c59f1ad1b0e0e..aa892193e4854 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 @@ -73,4 +73,13 @@ void dcn20_fpu_adjust_dppclk(struct vba_vars_st *v, int pipe_idx, bool is_validating_bw); +int dcn21_populate_dml_pipes_from_context(struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate); +bool dcn21_validate_bandwidth_fp(struct dc *dc, + struct dc_state *context, + bool fast_validate); +void dcn21_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); + #endif /* __DCN20_FPU_H__ */ From 6e6faf7a8364c77f4021f44043a5a5cee91f7025 Mon Sep 17 00:00:00 2001 From: Melissa Wen <mwen@igalia.com> Date: Mon, 28 Feb 2022 20:10:47 -0100 Subject: [PATCH 24/65] drm/amd/display: move FPU code from dcn10 to dml/dcn10 folder FPU operations in dcn10 was already moved to dml folder via calcs code. However, dcn1_0_ip and dcn_1_0_soc with FPU componentd remains on dcn10. Following previous changes to isolate FPU, this patch creates dcn10_fpu files to isolate FPU-specific code and moves those structs to it. Signed-off-by: Melissa Wen <mwen@igalia.com> Acked-by: Alan Liu <HaoPing.Liu@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 62 --------- .../drm/amd/display/dc/dcn10/dcn10_resource.h | 4 + drivers/gpu/drm/amd/display/dc/dml/Makefile | 2 + .../drm/amd/display/dc/dml/dcn10/dcn10_fpu.c | 123 ++++++++++++++++++ .../drm/amd/display/dc/dml/dcn10/dcn10_fpu.h | 30 +++++ 5 files changed, 159 insertions(+), 62 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.h diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 858b721498971..ac96242cc4747 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -70,68 +70,6 @@ #include "dce/dce_aux.h" #include "dce/dce_i2c.h" -const struct _vcs_dpi_ip_params_st dcn1_0_ip = { - .rob_buffer_size_kbytes = 64, - .det_buffer_size_kbytes = 164, - .dpte_buffer_size_in_pte_reqs_luma = 42, - .dpp_output_buffer_pixels = 2560, - .opp_output_buffer_lines = 1, - .pixel_chunk_size_kbytes = 8, - .pte_enable = 1, - .pte_chunk_size_kbytes = 2, - .meta_chunk_size_kbytes = 2, - .writeback_chunk_size_kbytes = 2, - .line_buffer_size_bits = 589824, - .max_line_buffer_lines = 12, - .IsLineBufferBppFixed = 0, - .LineBufferFixedBpp = -1, - .writeback_luma_buffer_size_kbytes = 12, - .writeback_chroma_buffer_size_kbytes = 8, - .max_num_dpp = 4, - .max_num_wb = 2, - .max_dchub_pscl_bw_pix_per_clk = 4, - .max_pscl_lb_bw_pix_per_clk = 2, - .max_lb_vscl_bw_pix_per_clk = 4, - .max_vscl_hscl_bw_pix_per_clk = 4, - .max_hscl_ratio = 4, - .max_vscl_ratio = 4, - .hscl_mults = 4, - .vscl_mults = 4, - .max_hscl_taps = 8, - .max_vscl_taps = 8, - .dispclk_ramp_margin_percent = 1, - .underscan_factor = 1.10, - .min_vblank_lines = 14, - .dppclk_delay_subtotal = 90, - .dispclk_delay_subtotal = 42, - .dcfclk_cstate_latency = 10, - .max_inter_dcn_tile_repeaters = 8, - .can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one = 0, - .bug_forcing_LC_req_same_size_fixed = 0, -}; - -const struct _vcs_dpi_soc_bounding_box_st dcn1_0_soc = { - .sr_exit_time_us = 9.0, - .sr_enter_plus_exit_time_us = 11.0, - .urgent_latency_us = 4.0, - .writeback_latency_us = 12.0, - .ideal_dram_bw_after_urgent_percent = 80.0, - .max_request_size_bytes = 256, - .downspread_percent = 0.5, - .dram_page_open_time_ns = 50.0, - .dram_rw_turnaround_time_ns = 17.5, - .dram_return_buffer_per_channel_bytes = 8192, - .round_trip_ping_latency_dcfclk_cycles = 128, - .urgent_out_of_order_return_per_channel_bytes = 256, - .channel_interleave_bytes = 256, - .num_banks = 8, - .num_chans = 2, - .vmm_page_size_bytes = 4096, - .dram_clock_change_latency_us = 17.0, - .writeback_dram_clock_change_latency_us = 23.0, - .return_bus_width_bytes = 64, -}; - #ifndef mmDP0_DP_DPHY_INTERNAL_CTRL #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f #define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h index 633025ccb8700..bf8e33cd8147c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h @@ -27,6 +27,7 @@ #define __DC_RESOURCE_DCN10_H__ #include "core_types.h" +#include "dml/dcn10/dcn10_fpu.h" #define TO_DCN10_RES_POOL(pool)\ container_of(pool, struct dcn10_resource_pool, base) @@ -35,6 +36,9 @@ struct dc; struct resource_pool; struct _vcs_dpi_display_pipe_params_st; +extern struct _vcs_dpi_ip_params_st dcn1_0_ip; +extern struct _vcs_dpi_soc_bounding_box_st dcn1_0_soc; + struct dcn10_resource_pool { struct resource_pool base; }; diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index 6ab83c3e9c5cd..28978ce62f87d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -58,6 +58,7 @@ CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags) ifdef CONFIG_DRM_AMD_DC_DCN CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml/dcn10/dcn10_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/dcn20_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_ccflags) @@ -106,6 +107,7 @@ DML = calcs/dce_calcs.o calcs/custom_float.o calcs/bw_fixed.o ifdef CONFIG_DRM_AMD_DC_DCN DML += display_mode_lib.o display_rq_dlg_helpers.o dml1_display_rq_dlg_calc.o +DML += dcn10/dcn10_fpu.o DML += dcn20/dcn20_fpu.o DML += display_mode_vba.o dcn20/display_rq_dlg_calc_20.o dcn20/display_mode_vba_20.o DML += dcn20/display_rq_dlg_calc_20v2.o dcn20/display_mode_vba_20v2.o diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c new file mode 100644 index 0000000000000..99644d8962221 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2021 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 "dcn10/dcn10_resource.h" + +#include "dcn10_fpu.h" + +/** + * DOC: DCN10 FPU manipulation Overview + * + * The DCN architecture relies on FPU operations, which require special + * compilation flags and the use of kernel_fpu_begin/end functions; ideally, we + * want to avoid spreading FPU access across multiple files. With this idea in + * mind, this file aims to centralize DCN10 functions that require FPU access + * in a single place. Code in this file follows the following code pattern: + * + * 1. Functions that use FPU operations should be isolated in static functions. + * 2. The FPU functions should have the noinline attribute to ensure anything + * that deals with FP register is contained within this call. + * 3. All function that needs to be accessed outside this file requires a + * public interface that not uses any FPU reference. + * 4. Developers **must not** use DC_FP_START/END in this file, but they need + * to ensure that the caller invokes it before access any function available + * in this file. For this reason, public functions in this file must invoke + * dc_assert_fp_enabled(); + * + * Let's expand a little bit more the idea in the code pattern. To fully + * isolate FPU operations in a single place, we must avoid situations where + * compilers spill FP values to registers due to FP enable in a specific C + * file. Note that even if we isolate all FPU functions in a single file and + * call its interface from other files, the compiler might enable the use of + * FPU before we call DC_FP_START. Nevertheless, it is the programmer's + * responsibility to invoke DC_FP_START/END in the correct place. To highlight + * situations where developers forgot to use the FP protection before calling + * the DC FPU interface functions, we introduce a helper that checks if the + * function is invoked under FP protection. If not, it will trigger a kernel + * warning. + */ + +struct _vcs_dpi_ip_params_st dcn1_0_ip = { + .rob_buffer_size_kbytes = 64, + .det_buffer_size_kbytes = 164, + .dpte_buffer_size_in_pte_reqs_luma = 42, + .dpp_output_buffer_pixels = 2560, + .opp_output_buffer_lines = 1, + .pixel_chunk_size_kbytes = 8, + .pte_enable = 1, + .pte_chunk_size_kbytes = 2, + .meta_chunk_size_kbytes = 2, + .writeback_chunk_size_kbytes = 2, + .line_buffer_size_bits = 589824, + .max_line_buffer_lines = 12, + .IsLineBufferBppFixed = 0, + .LineBufferFixedBpp = -1, + .writeback_luma_buffer_size_kbytes = 12, + .writeback_chroma_buffer_size_kbytes = 8, + .max_num_dpp = 4, + .max_num_wb = 2, + .max_dchub_pscl_bw_pix_per_clk = 4, + .max_pscl_lb_bw_pix_per_clk = 2, + .max_lb_vscl_bw_pix_per_clk = 4, + .max_vscl_hscl_bw_pix_per_clk = 4, + .max_hscl_ratio = 4, + .max_vscl_ratio = 4, + .hscl_mults = 4, + .vscl_mults = 4, + .max_hscl_taps = 8, + .max_vscl_taps = 8, + .dispclk_ramp_margin_percent = 1, + .underscan_factor = 1.10, + .min_vblank_lines = 14, + .dppclk_delay_subtotal = 90, + .dispclk_delay_subtotal = 42, + .dcfclk_cstate_latency = 10, + .max_inter_dcn_tile_repeaters = 8, + .can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one = 0, + .bug_forcing_LC_req_same_size_fixed = 0, +}; + +struct _vcs_dpi_soc_bounding_box_st dcn1_0_soc = { + .sr_exit_time_us = 9.0, + .sr_enter_plus_exit_time_us = 11.0, + .urgent_latency_us = 4.0, + .writeback_latency_us = 12.0, + .ideal_dram_bw_after_urgent_percent = 80.0, + .max_request_size_bytes = 256, + .downspread_percent = 0.5, + .dram_page_open_time_ns = 50.0, + .dram_rw_turnaround_time_ns = 17.5, + .dram_return_buffer_per_channel_bytes = 8192, + .round_trip_ping_latency_dcfclk_cycles = 128, + .urgent_out_of_order_return_per_channel_bytes = 256, + .channel_interleave_bytes = 256, + .num_banks = 8, + .num_chans = 2, + .vmm_page_size_bytes = 4096, + .dram_clock_change_latency_us = 17.0, + .writeback_dram_clock_change_latency_us = 23.0, + .return_bus_width_bytes = 64, +}; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.h new file mode 100644 index 0000000000000..e74ed4b4ce5b8 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2021 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 + * + */ + +#ifndef __DCN10_FPU_H__ +#define __DCN10_FPU_H__ + +#endif /* __DCN20_FPU_H__ */ From d510eccfa51e09f5e65621a2e8d41f58a8dbd3ba Mon Sep 17 00:00:00 2001 From: "Stanley.Yang" <Stanley.Yang@amd.com> Date: Thu, 3 Mar 2022 17:51:24 +0800 Subject: [PATCH 25/65] drm/amd/pm: add send bad channel info function support message SMU update bad channel info to update HBM bad channel info in OOB table Signed-off-by: Stanley.Yang <Stanley.Yang@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 12 ++++++ drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 1 + drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 10 +++++ drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 7 +++ .../pm/swsmu/inc/pmfw_if/aldebaran_ppsmc.h | 3 +- drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h | 3 +- .../drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 43 +++++++++++++++++++ 7 files changed, 77 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 1d63f1e8884c3..9a892d6d1d7af 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -507,6 +507,18 @@ int amdgpu_dpm_send_hbm_bad_pages_num(struct amdgpu_device *adev, uint32_t size) return ret; } +int amdgpu_dpm_send_hbm_bad_channel_flag(struct amdgpu_device *adev, uint32_t size) +{ + struct smu_context *smu = adev->powerplay.pp_handle; + int ret = 0; + + mutex_lock(&adev->pm.mutex); + ret = smu_send_hbm_bad_channel_flag(smu, size); + mutex_unlock(&adev->pm.mutex); + + return ret; +} + int amdgpu_dpm_get_dpm_freq_range(struct amdgpu_device *adev, enum pp_clock_type type, uint32_t *min, diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index ddfa55b59d021..3e78b3057277d 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -412,6 +412,7 @@ void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable); int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version); int amdgpu_dpm_handle_passthrough_sbr(struct amdgpu_device *adev, bool enable); int amdgpu_dpm_send_hbm_bad_pages_num(struct amdgpu_device *adev, uint32_t size); +int amdgpu_dpm_send_hbm_bad_channel_flag(struct amdgpu_device *adev, uint32_t size); int amdgpu_dpm_get_dpm_freq_range(struct amdgpu_device *adev, enum pp_clock_type type, uint32_t *min, diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 7e79a67bb8ef0..f1544755d8b46 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -3052,3 +3052,13 @@ int smu_send_hbm_bad_pages_num(struct smu_context *smu, uint32_t size) return ret; } + +int smu_send_hbm_bad_channel_flag(struct smu_context *smu, uint32_t size) +{ + int ret = 0; + + if (smu->ppt_funcs && smu->ppt_funcs->send_hbm_bad_channel_flag) + ret = smu->ppt_funcs->send_hbm_bad_channel_flag(smu, size); + + return ret; +} diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index fbef3ab8d4875..ef57b6089c697 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -1292,6 +1292,12 @@ struct pptable_funcs { * @set_config_table: Apply the input DriverSmuConfig table settings. */ int (*set_config_table)(struct smu_context *smu, struct config_table_setting *table); + + /** + * @sned_hbm_bad_channel_flag: message SMU to update bad channel info + * of SMUBUS table. + */ + int (*send_hbm_bad_channel_flag)(struct smu_context *smu, uint32_t size); }; typedef enum { @@ -1428,5 +1434,6 @@ int smu_get_ecc_info(struct smu_context *smu, void *umc_ecc); int smu_stb_collect_info(struct smu_context *smu, void *buff, uint32_t size); void amdgpu_smu_stb_debug_fs_init(struct amdgpu_device *adev); int smu_send_hbm_bad_pages_num(struct smu_context *smu, uint32_t size); +int smu_send_hbm_bad_channel_flag(struct smu_context *smu, uint32_t size); #endif #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/aldebaran_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/aldebaran_ppsmc.h index ab66a4b9e4381..0f498baf68385 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/aldebaran_ppsmc.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/aldebaran_ppsmc.h @@ -103,7 +103,8 @@ #define PPSMC_MSG_GfxDriverResetRecovery 0x42 #define PPSMC_MSG_BoardPowerCalibration 0x43 #define PPSMC_MSG_HeavySBR 0x45 -#define PPSMC_Message_Count 0x46 +#define PPSMC_MSG_SetBadHBMPagesRetiredFlagsPerChannel 0x46 +#define PPSMC_Message_Count 0x47 //PPSMC Reset Types diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h index d787c3b9fc523..9f6f306eeca03 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h @@ -232,7 +232,8 @@ __SMU_DUMMY_MAP(ForceGfxVid), \ __SMU_DUMMY_MAP(Spare0), \ __SMU_DUMMY_MAP(UnforceGfxVid), \ - __SMU_DUMMY_MAP(HeavySBR), + __SMU_DUMMY_MAP(HeavySBR), \ + __SMU_DUMMY_MAP(SetBadHBMPagesRetiredFlagsPerChannel), #undef __SMU_DUMMY_MAP #define __SMU_DUMMY_MAP(type) SMU_MSG_##type diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index 890acc4e2cb8f..cd81f848d45ab 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -82,6 +82,12 @@ */ #define SUPPORT_ECCTABLE_SMU_VERSION 0x00442a00 +/* + * SMU support BAD CHENNEL info MSG since version 68.51.00, + * use this to check ECCTALE feature whether support + */ +#define SUPPORT_BAD_CHANNEL_INFO_MSG_VERSION 0x00443300 + static const struct smu_temperature_range smu13_thermal_policy[] = { {-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000}, @@ -140,6 +146,7 @@ static const struct cmn2asic_msg_mapping aldebaran_message_map[SMU_MSG_MAX_COUNT MSG_MAP(GfxDriverResetRecovery, PPSMC_MSG_GfxDriverResetRecovery, 0), MSG_MAP(BoardPowerCalibration, PPSMC_MSG_BoardPowerCalibration, 0), MSG_MAP(HeavySBR, PPSMC_MSG_HeavySBR, 0), + MSG_MAP(SetBadHBMPagesRetiredFlagsPerChannel, PPSMC_MSG_SetBadHBMPagesRetiredFlagsPerChannel, 0), }; static const struct cmn2asic_mapping aldebaran_clk_map[SMU_CLK_COUNT] = { @@ -1997,6 +2004,41 @@ static int aldebaran_smu_send_hbm_bad_page_num(struct smu_context *smu, return ret; } +static int aldebaran_check_bad_channel_info_support(struct smu_context *smu) +{ + uint32_t if_version = 0xff, smu_version = 0xff; + int ret = 0; + + ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version); + if (ret) { + /* return not support if failed get smu_version */ + ret = -EOPNOTSUPP; + } + + if (smu_version < SUPPORT_BAD_CHANNEL_INFO_MSG_VERSION) + ret = -EOPNOTSUPP; + + return ret; +} + +static int aldebaran_send_hbm_bad_channel_flag(struct smu_context *smu, + uint32_t size) +{ + int ret = 0; + + ret = aldebaran_check_bad_channel_info_support(smu); + if (ret) + return ret; + + /* message SMU to update the bad channel info on SMUBUS */ + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetBadHBMPagesRetiredFlagsPerChannel, size, NULL); + if (ret) + dev_err(smu->adev->dev, "[%s] failed to message SMU to update HBM bad channel info\n", + __func__); + + return ret; +} + static const struct pptable_funcs aldebaran_ppt_funcs = { /* init dpm */ .get_allowed_feature_mask = aldebaran_get_allowed_feature_mask, @@ -2062,6 +2104,7 @@ static const struct pptable_funcs aldebaran_ppt_funcs = { .i2c_fini = aldebaran_i2c_control_fini, .send_hbm_bad_pages_num = aldebaran_smu_send_hbm_bad_page_num, .get_ecc_info = aldebaran_get_ecc_info, + .send_hbm_bad_channel_flag = aldebaran_send_hbm_bad_channel_flag, }; void aldebaran_set_ppt_funcs(struct smu_context *smu) From 69691c823531c36c7283ecaa040e99e9c12ece07 Mon Sep 17 00:00:00 2001 From: "Stanley.Yang" <Stanley.Yang@amd.com> Date: Thu, 3 Mar 2022 17:56:33 +0800 Subject: [PATCH 26/65] drm/amdgpu: message smu to update bad channel info It should notice SMU to update bad channel info when detected uncorrectable error in UMC block Signed-off-by: Stanley.Yang <Stanley.Yang@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 7 ++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 3 +++ .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 25 +++++++++++++++++-- .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h | 4 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c | 5 ++++ 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index d78c2970e5585..424c22a841f40 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2068,6 +2068,7 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) mutex_init(&con->recovery_lock); INIT_WORK(&con->recovery_work, amdgpu_ras_do_recovery); atomic_set(&con->in_recovery, 0); + con->eeprom_control.bad_channel_bitmap = 0; max_eeprom_records_count = amdgpu_ras_eeprom_max_record_count(); amdgpu_ras_validate_threshold(adev, max_eeprom_records_count); @@ -2092,6 +2093,11 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) goto free; amdgpu_dpm_send_hbm_bad_pages_num(adev, con->eeprom_control.ras_num_recs); + + if (con->update_channel_flag == true) { + amdgpu_dpm_send_hbm_bad_channel_flag(adev, con->eeprom_control.bad_channel_bitmap); + con->update_channel_flag = false; + } } #ifdef CONFIG_X86_MCE_AMD @@ -2285,6 +2291,7 @@ int amdgpu_ras_init(struct amdgpu_device *adev) goto release_con; } + con->update_channel_flag = false; con->features = 0; INIT_LIST_HEAD(&con->head); /* Might need get this flag from vbios. */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index 7cddaad90d6d9..9314fde81e68f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -374,6 +374,9 @@ struct amdgpu_ras { /* record umc error info queried from smu */ struct umc_ecc_info umc_ecc; + + /* Indicates smu whether need update bad channel info */ + bool update_channel_flag; }; struct ras_fs_data { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index a44f2eeed6ef7..c4283987bb1e8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -267,6 +267,7 @@ int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control) { struct amdgpu_device *adev = to_amdgpu_device(control); struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr; + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); u8 csum; int res; @@ -287,6 +288,10 @@ int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control) amdgpu_dpm_send_hbm_bad_pages_num(adev, control->ras_num_recs); + control->bad_channel_bitmap = 0; + amdgpu_dpm_send_hbm_bad_channel_flag(adev, control->bad_channel_bitmap); + con->update_channel_flag = false; + amdgpu_ras_debugfs_set_ret_size(control); mutex_unlock(&control->ras_tbl_mutex); @@ -420,6 +425,7 @@ amdgpu_ras_eeprom_append_table(struct amdgpu_ras_eeprom_control *control, struct eeprom_table_record *record, const u32 num) { + struct amdgpu_ras *con = amdgpu_ras_get_context(to_amdgpu_device(control)); u32 a, b, i; u8 *buf, *pp; int res; @@ -431,9 +437,16 @@ amdgpu_ras_eeprom_append_table(struct amdgpu_ras_eeprom_control *control, /* Encode all of them in one go. */ pp = buf; - for (i = 0; i < num; i++, pp += RAS_TABLE_RECORD_SIZE) + for (i = 0; i < num; i++, pp += RAS_TABLE_RECORD_SIZE) { __encode_table_record_to_buf(control, &record[i], pp); + /* update bad channel bitmap */ + if (!(control->bad_channel_bitmap & (1 << record[i].mem_channel))) { + control->bad_channel_bitmap |= 1 << record[i].mem_channel; + con->update_channel_flag = true; + } + } + /* a, first record index to write into. * b, last record index to write into. * a = first index to read (fri) + number of records in the table, @@ -686,6 +699,7 @@ int amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control, const u32 num) { struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); int i, res; u8 *buf, *pp; u32 g0, g1; @@ -753,8 +767,15 @@ int amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control, /* Read up everything? Then transform. */ pp = buf; - for (i = 0; i < num; i++, pp += RAS_TABLE_RECORD_SIZE) + for (i = 0; i < num; i++, pp += RAS_TABLE_RECORD_SIZE) { __decode_table_record_from_buf(control, &record[i], pp); + + /* update bad channel bitmap */ + if (!(control->bad_channel_bitmap & (1 << record[i].mem_channel))) { + control->bad_channel_bitmap |= 1 << record[i].mem_channel; + con->update_channel_flag = true; + } + } Out: kfree(buf); mutex_unlock(&control->ras_tbl_mutex); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h index 6bb00578bfbbc..54d9bfe0881d9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h @@ -80,6 +80,10 @@ struct amdgpu_ras_eeprom_control { /* Protect table access via this mutex. */ struct mutex ras_tbl_mutex; + + /* Record channel info which occurred bad pages + */ + u32 bad_channel_bitmap; }; /* diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c index 85da6cbaf3b7c..aad3c8b4c8102 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c @@ -97,6 +97,11 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev, amdgpu_ras_save_bad_pages(adev); amdgpu_dpm_send_hbm_bad_pages_num(adev, con->eeprom_control.ras_num_recs); + + if (con->update_channel_flag == true) { + amdgpu_dpm_send_hbm_bad_channel_flag(adev, con->eeprom_control.bad_channel_bitmap); + con->update_channel_flag = false; + } } if (reset) From 8718ca1dbf497c302df989afaeb82f05f5a3d961 Mon Sep 17 00:00:00 2001 From: Lijo Lazar <lijo.lazar@amd.com> Date: Fri, 25 Feb 2022 09:43:49 +0530 Subject: [PATCH 27/65] drm/amd/pm: Send message when resp status is 0xFC When PMFW is really busy, it will respond with 0xFC. However, it doesn't change the response register state when it becomes free. Driver should retry and proceed to send message if the response status is 0xFC. Signed-off-by: Lijo Lazar <lijo.lazar@amd.com> Reviewed-by: Evan Quan <evan.quan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index 89b22b2610668..ae64d1980f106 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -303,7 +303,6 @@ int smu_cmn_send_msg_without_waiting(struct smu_context *smu, reg = __smu_cmn_poll_stat(smu); res = __smu_cmn_reg2errno(smu, reg); if (reg == SMU_RESP_NONE || - reg == SMU_RESP_BUSY_OTHER || res == -EREMOTEIO) goto Out; __smu_cmn_send_msg(smu, msg_index, param); @@ -397,7 +396,6 @@ int smu_cmn_send_smc_msg_with_param(struct smu_context *smu, reg = __smu_cmn_poll_stat(smu); res = __smu_cmn_reg2errno(smu, reg); if (reg == SMU_RESP_NONE || - reg == SMU_RESP_BUSY_OTHER || res == -EREMOTEIO) { __smu_cmn_reg_print_error(smu, reg, index, param, msg); goto Out; From 2e9fda82c98b1e417b90ff5a2f8b8b96cac06fc5 Mon Sep 17 00:00:00 2001 From: "Tianci.Yin" <tianci.yin@amd.com> Date: Tue, 8 Mar 2022 13:45:45 +0800 Subject: [PATCH 28/65] drm/amd/display: fix dp kvm can't light up [why] The DP KVM failed to light up, since the lttpr_mode is not reset to default value when failed to read LTTPR capabilities, and the variable max_link_rate retains a initial value zero, this cause variable link_rate be assigned to an error value zero, consquently pixel_clock get wrong value zero, and kvm can't light up. [how] Reset lttpr_mode to default value when failed to read LTTPR capabilities, so that the link_rate fallbacks to the minimum rate that supported by link encoder and sink. Reviewed-by: Harry Wentland <harry.wentland@amd.com> Signed-off-by: Tianci.Yin <tianci.yin@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 7d88165e8fa2b..c35d55fe41aba 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -5110,6 +5110,7 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link) sizeof(lttpr_dpcd_data)); if (status != DC_OK) { DC_LOG_DP2("%s: Read LTTPR caps data failed.\n", __func__); + link->lttpr_mode = LTTPR_MODE_NON_LTTPR; return false; } From 67a359d85ec2679cc8e11b16844df960e3b27c24 Mon Sep 17 00:00:00 2001 From: David Yat Sin <david.yatsin@amd.com> Date: Tue, 8 Mar 2022 09:08:18 -0500 Subject: [PATCH 29/65] drm/amdkfd: CRIU remove sync and TLB flush on restore When the process is getting restored, the queues are not mapped yet, so there is no VMID assigned for this process and no TLBs to flush. Signed-off-by: David Yat Sin <david.yatsin@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 30 +----------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 59d3fe269e7c1..789bdfbd3f9b7 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -2102,7 +2102,6 @@ static int criu_restore_bos(struct kfd_process *p, struct kfd_criu_bo_bucket *bo_buckets = NULL; struct kfd_criu_bo_priv_data *bo_privs = NULL; const bool criu_resume = true; - bool flush_tlbs = false; int ret = 0, j = 0; uint32_t i = 0; @@ -2248,7 +2247,6 @@ static int criu_restore_bos(struct kfd_process *p, for (j = 0; j < p->n_pdds; j++) { struct kfd_dev *peer; struct kfd_process_device *peer_pdd; - bool table_freed = false; if (!bo_priv->mapped_gpuids[j]) break; @@ -2268,20 +2266,11 @@ static int criu_restore_bos(struct kfd_process *p, pr_debug("map mem in restore ioctl -> 0x%llx\n", ((struct kgd_mem *)mem)->va); ret = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(peer->adev, - (struct kgd_mem *)mem, peer_pdd->drm_priv, &table_freed); + (struct kgd_mem *)mem, peer_pdd->drm_priv, NULL); if (ret) { pr_err("Failed to map to gpu %d/%d\n", j, p->n_pdds); goto exit; } - if (table_freed) - flush_tlbs = true; - } - - ret = amdgpu_amdkfd_gpuvm_sync_memory(dev->adev, - (struct kgd_mem *) mem, true); - if (ret) { - pr_debug("Sync memory failed, wait interrupted by user signal\n"); - goto exit; } pr_debug("map memory was successful for the BO\n"); @@ -2296,23 +2285,6 @@ static int criu_restore_bos(struct kfd_process *p, } } /* done */ - if (flush_tlbs) { - /* Flush TLBs after waiting for the page table updates to complete */ - for (j = 0; j < p->n_pdds; j++) { - struct kfd_dev *peer; - struct kfd_process_device *pdd = p->pdds[j]; - struct kfd_process_device *peer_pdd; - - peer = kfd_device_by_id(pdd->dev->id); - if (WARN_ON_ONCE(!peer)) - continue; - peer_pdd = kfd_get_process_device_data(peer, p); - if (WARN_ON_ONCE(!peer_pdd)) - continue; - kfd_flush_tlb(peer_pdd, TLB_FLUSH_LEGACY); - } - } - /* Copy only the buckets back so user can read bo_buckets[N].restored_offset */ ret = copy_to_user((void __user *)args->bos, bo_buckets, From b38c074b2b07349097d824e3c6c49b5ac8d98910 Mon Sep 17 00:00:00 2001 From: David Yat Sin <david.yatsin@amd.com> Date: Tue, 8 Mar 2022 09:35:41 -0500 Subject: [PATCH 30/65] drm/amdkfd: CRIU Refactor restore BO function Refactor CRIU restore BO to reduce identation. Signed-off-by: David Yat Sin <david.yatsin@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 271 +++++++++++------------ 1 file changed, 129 insertions(+), 142 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 789bdfbd3f9b7..2c7d76e67ddbe 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -2094,6 +2094,132 @@ static int criu_restore_devices(struct kfd_process *p, return ret; } +static int criu_restore_memory_of_gpu(struct kfd_process_device *pdd, + struct kfd_criu_bo_bucket *bo_bucket, + struct kfd_criu_bo_priv_data *bo_priv, + struct kgd_mem **kgd_mem) +{ + int idr_handle; + int ret; + const bool criu_resume = true; + u64 offset; + + if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) { + if (bo_bucket->size != kfd_doorbell_process_slice(pdd->dev)) + return -EINVAL; + + offset = kfd_get_process_doorbells(pdd); + } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) { + /* MMIO BOs need remapped bus address */ + if (bo_bucket->size != PAGE_SIZE) { + pr_err("Invalid page size\n"); + return -EINVAL; + } + offset = pdd->dev->adev->rmmio_remap.bus_addr; + if (!offset) { + pr_err("amdgpu_amdkfd_get_mmio_remap_phys_addr failed\n"); + return -ENOMEM; + } + } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) { + offset = bo_priv->user_addr; + } + /* Create the BO */ + ret = amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(pdd->dev->adev, bo_bucket->addr, + bo_bucket->size, pdd->drm_priv, kgd_mem, + &offset, bo_bucket->alloc_flags, criu_resume); + if (ret) { + pr_err("Could not create the BO\n"); + return ret; + } + pr_debug("New BO created: size:0x%llx addr:0x%llx offset:0x%llx\n", + bo_bucket->size, bo_bucket->addr, offset); + + /* Restore previous IDR handle */ + pr_debug("Restoring old IDR handle for the BO"); + idr_handle = idr_alloc(&pdd->alloc_idr, *kgd_mem, bo_priv->idr_handle, + bo_priv->idr_handle + 1, GFP_KERNEL); + + if (idr_handle < 0) { + pr_err("Could not allocate idr\n"); + amdgpu_amdkfd_gpuvm_free_memory_of_gpu(pdd->dev->adev, *kgd_mem, pdd->drm_priv, + NULL); + return -ENOMEM; + } + + if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) + bo_bucket->restored_offset = KFD_MMAP_TYPE_DOORBELL | KFD_MMAP_GPU_ID(pdd->dev->id); + if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) { + bo_bucket->restored_offset = KFD_MMAP_TYPE_MMIO | KFD_MMAP_GPU_ID(pdd->dev->id); + } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_GTT) { + bo_bucket->restored_offset = offset; + } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) { + bo_bucket->restored_offset = offset; + /* Update the VRAM usage count */ + WRITE_ONCE(pdd->vram_usage, pdd->vram_usage + bo_bucket->size); + } + return 0; +} + +static int criu_restore_bo(struct kfd_process *p, + struct kfd_criu_bo_bucket *bo_bucket, + struct kfd_criu_bo_priv_data *bo_priv) +{ + struct kfd_process_device *pdd; + struct kgd_mem *kgd_mem; + int ret; + int j; + + pr_debug("Restoring BO size:0x%llx addr:0x%llx gpu_id:0x%x flags:0x%x idr_handle:0x%x\n", + bo_bucket->size, bo_bucket->addr, bo_bucket->gpu_id, bo_bucket->alloc_flags, + bo_priv->idr_handle); + + pdd = kfd_process_device_data_by_id(p, bo_bucket->gpu_id); + if (!pdd) { + pr_err("Failed to get pdd\n"); + return -ENODEV; + } + + ret = criu_restore_memory_of_gpu(pdd, bo_bucket, bo_priv, &kgd_mem); + if (ret) + return ret; + + /* now map these BOs to GPU/s */ + for (j = 0; j < p->n_pdds; j++) { + struct kfd_dev *peer; + struct kfd_process_device *peer_pdd; + + if (!bo_priv->mapped_gpuids[j]) + break; + + peer_pdd = kfd_process_device_data_by_id(p, bo_priv->mapped_gpuids[j]); + if (!peer_pdd) + return -EINVAL; + + peer = peer_pdd->dev; + + peer_pdd = kfd_bind_process_to_device(peer, p); + if (IS_ERR(peer_pdd)) + return PTR_ERR(peer_pdd); + + ret = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(peer->adev, kgd_mem, peer_pdd->drm_priv, + NULL); + if (ret) { + pr_err("Failed to map to gpu %d/%d\n", j, p->n_pdds); + return ret; + } + } + + pr_debug("map memory was successful for the BO\n"); + /* create the dmabuf object and export the bo */ + if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) { + ret = criu_get_prime_handle(&kgd_mem->bo->tbo.base, DRM_RDWR, + &bo_bucket->dmabuf_fd); + if (ret) + return ret; + } + return 0; +} + static int criu_restore_bos(struct kfd_process *p, struct kfd_ioctl_criu_args *args, uint64_t *priv_offset, @@ -2101,8 +2227,7 @@ static int criu_restore_bos(struct kfd_process *p, { struct kfd_criu_bo_bucket *bo_buckets = NULL; struct kfd_criu_bo_priv_data *bo_privs = NULL; - const bool criu_resume = true; - int ret = 0, j = 0; + int ret = 0; uint32_t i = 0; if (*priv_offset + (args->num_bos * sizeof(*bo_privs)) > max_priv_data_size) @@ -2140,149 +2265,11 @@ static int criu_restore_bos(struct kfd_process *p, /* Create and map new BOs */ for (; i < args->num_bos; i++) { - struct kfd_criu_bo_bucket *bo_bucket; - struct kfd_criu_bo_priv_data *bo_priv; - struct kfd_dev *dev; - struct kfd_process_device *pdd; - struct kgd_mem *kgd_mem; - void *mem; - u64 offset; - int idr_handle; - - bo_bucket = &bo_buckets[i]; - bo_priv = &bo_privs[i]; - - pr_debug("kfd restore ioctl - bo_bucket[%d]:\n", i); - pr_debug("size = 0x%llx, bo_addr = 0x%llx bo_offset = 0x%llx\n" - "gpu_id = 0x%x alloc_flags = 0x%x\n" - "idr_handle = 0x%x\n", - bo_bucket->size, - bo_bucket->addr, - bo_bucket->offset, - bo_bucket->gpu_id, - bo_bucket->alloc_flags, - bo_priv->idr_handle); - - pdd = kfd_process_device_data_by_id(p, bo_bucket->gpu_id); - if (!pdd) { - pr_err("Failed to get pdd\n"); - ret = -ENODEV; - goto exit; - } - dev = pdd->dev; - - if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) { - pr_debug("restore ioctl: KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL\n"); - if (bo_bucket->size != kfd_doorbell_process_slice(dev)) { - ret = -EINVAL; - goto exit; - } - offset = kfd_get_process_doorbells(pdd); - } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) { - /* MMIO BOs need remapped bus address */ - pr_debug("restore ioctl :KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP\n"); - if (bo_bucket->size != PAGE_SIZE) { - pr_err("Invalid page size\n"); - ret = -EINVAL; - goto exit; - } - offset = dev->adev->rmmio_remap.bus_addr; - if (!offset) { - pr_err("amdgpu_amdkfd_get_mmio_remap_phys_addr failed\n"); - ret = -ENOMEM; - goto exit; - } - } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) { - offset = bo_priv->user_addr; - } - /* Create the BO */ - ret = amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(dev->adev, - bo_bucket->addr, - bo_bucket->size, - pdd->drm_priv, - (struct kgd_mem **) &mem, - &offset, - bo_bucket->alloc_flags, - criu_resume); + ret = criu_restore_bo(p, &bo_buckets[i], &bo_privs[i]); if (ret) { - pr_err("Could not create the BO\n"); - ret = -ENOMEM; - goto exit; - } - pr_debug("New BO created: size = 0x%llx, bo_addr = 0x%llx bo_offset = 0x%llx\n", - bo_bucket->size, bo_bucket->addr, offset); - - /* Restore previuos IDR handle */ - pr_debug("Restoring old IDR handle for the BO"); - idr_handle = idr_alloc(&pdd->alloc_idr, mem, - bo_priv->idr_handle, - bo_priv->idr_handle + 1, GFP_KERNEL); - - if (idr_handle < 0) { - pr_err("Could not allocate idr\n"); - amdgpu_amdkfd_gpuvm_free_memory_of_gpu(dev->adev, - (struct kgd_mem *)mem, - pdd->drm_priv, NULL); - ret = -ENOMEM; + pr_debug("Failed to restore BO[%d] ret%d\n", i, ret); goto exit; } - - if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) - bo_bucket->restored_offset = KFD_MMAP_TYPE_DOORBELL | - KFD_MMAP_GPU_ID(pdd->dev->id); - if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) { - bo_bucket->restored_offset = KFD_MMAP_TYPE_MMIO | - KFD_MMAP_GPU_ID(pdd->dev->id); - } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_GTT) { - bo_bucket->restored_offset = offset; - pr_debug("updating offset for GTT\n"); - } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) { - bo_bucket->restored_offset = offset; - /* Update the VRAM usage count */ - WRITE_ONCE(pdd->vram_usage, pdd->vram_usage + bo_bucket->size); - pr_debug("updating offset for VRAM\n"); - } - - /* now map these BOs to GPU/s */ - for (j = 0; j < p->n_pdds; j++) { - struct kfd_dev *peer; - struct kfd_process_device *peer_pdd; - - if (!bo_priv->mapped_gpuids[j]) - break; - - peer_pdd = kfd_process_device_data_by_id(p, bo_priv->mapped_gpuids[j]); - if (!peer_pdd) { - ret = -EINVAL; - goto exit; - } - peer = peer_pdd->dev; - - peer_pdd = kfd_bind_process_to_device(peer, p); - if (IS_ERR(peer_pdd)) { - ret = PTR_ERR(peer_pdd); - goto exit; - } - pr_debug("map mem in restore ioctl -> 0x%llx\n", - ((struct kgd_mem *)mem)->va); - ret = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(peer->adev, - (struct kgd_mem *)mem, peer_pdd->drm_priv, NULL); - if (ret) { - pr_err("Failed to map to gpu %d/%d\n", j, p->n_pdds); - goto exit; - } - } - - pr_debug("map memory was successful for the BO\n"); - /* create the dmabuf object and export the bo */ - kgd_mem = (struct kgd_mem *)mem; - if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) { - ret = criu_get_prime_handle(&kgd_mem->bo->tbo.base, - DRM_RDWR, - &bo_bucket->dmabuf_fd); - if (ret) - goto exit; - } } /* done */ /* Copy only the buckets back so user can read bo_buckets[N].restored_offset */ From 65722ff6181aa52c3d5b0929004af22a3a63e148 Mon Sep 17 00:00:00 2001 From: David Yat Sin <david.yatsin@amd.com> Date: Tue, 8 Mar 2022 14:00:50 -0500 Subject: [PATCH 31/65] drm/amdkfd: CRIU export dmabuf handles for GTT BOs Export dmabuf handles for GTT BOs so that their contents can be accessed using SDMA during checkpoint/restore. v2: Squash in fix from David to set dmabuf handle to invalid for BOs that cannot be accessed using SDMA during checkpoint/restore. Signed-off-by: David Yat Sin <david.yatsin@amd.com> Reviewed-by : Rajneesh Bhardwaj <rajneesh.bhardwaj@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 18 ++++++++++++++---- include/uapi/linux/kfd_ioctl.h | 5 ++++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 2c7d76e67ddbe..607f65ab39ac8 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1759,14 +1759,18 @@ static int criu_checkpoint_bos(struct kfd_process *p, goto exit; } } - if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) { + if (bo_bucket->alloc_flags + & (KFD_IOC_ALLOC_MEM_FLAGS_VRAM | KFD_IOC_ALLOC_MEM_FLAGS_GTT)) { ret = criu_get_prime_handle(&dumper_bo->tbo.base, bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_WRITABLE ? DRM_RDWR : 0, &bo_bucket->dmabuf_fd); if (ret) goto exit; + } else { + bo_bucket->dmabuf_fd = KFD_INVALID_FD; } + if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) bo_bucket->offset = KFD_MMAP_TYPE_DOORBELL | KFD_MMAP_GPU_ID(pdd->dev->id); @@ -1812,7 +1816,8 @@ static int criu_checkpoint_bos(struct kfd_process *p, exit: while (ret && bo_index--) { - if (bo_buckets[bo_index].alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) + if (bo_buckets[bo_index].alloc_flags + & (KFD_IOC_ALLOC_MEM_FLAGS_VRAM | KFD_IOC_ALLOC_MEM_FLAGS_GTT)) close_fd(bo_buckets[bo_index].dmabuf_fd); } @@ -2211,12 +2216,16 @@ static int criu_restore_bo(struct kfd_process *p, pr_debug("map memory was successful for the BO\n"); /* create the dmabuf object and export the bo */ - if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) { + if (bo_bucket->alloc_flags + & (KFD_IOC_ALLOC_MEM_FLAGS_VRAM | KFD_IOC_ALLOC_MEM_FLAGS_GTT)) { ret = criu_get_prime_handle(&kgd_mem->bo->tbo.base, DRM_RDWR, &bo_bucket->dmabuf_fd); if (ret) return ret; + } else { + bo_bucket->dmabuf_fd = KFD_INVALID_FD; } + return 0; } @@ -2281,7 +2290,8 @@ static int criu_restore_bos(struct kfd_process *p, exit: while (ret && i--) { - if (bo_buckets[i].alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) + if (bo_buckets[i].alloc_flags + & (KFD_IOC_ALLOC_MEM_FLAGS_VRAM | KFD_IOC_ALLOC_MEM_FLAGS_GTT)) close_fd(bo_buckets[i].dmabuf_fd); } kvfree(bo_buckets); diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h index b40687bf10144..42975e940758d 100644 --- a/include/uapi/linux/kfd_ioctl.h +++ b/include/uapi/linux/kfd_ioctl.h @@ -33,9 +33,10 @@ * - 1.5 - Add SVM API * - 1.6 - Query clear flags in SVM get_attr API * - 1.7 - Checkpoint Restore (CRIU) API + * - 1.8 - CRIU - Support for SDMA transfers with GTT BOs */ #define KFD_IOCTL_MAJOR_VERSION 1 -#define KFD_IOCTL_MINOR_VERSION 7 +#define KFD_IOCTL_MINOR_VERSION 8 struct kfd_ioctl_get_version_args { __u32 major_version; /* from KFD */ @@ -195,6 +196,8 @@ struct kfd_ioctl_dbg_wave_control_args { __u32 buf_size_in_bytes; /*including gpu_id and buf_size */ }; +#define KFD_INVALID_FD 0xffffffff + /* Matching HSA_EVENTTYPE */ #define KFD_IOC_EVENT_SIGNAL 0 #define KFD_IOC_EVENT_NODECHANGE 1 From e7031d8258f1b4d6d50e5e5b5d92ba16f66eb8b4 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Date: Fri, 17 Dec 2021 09:55:54 -0500 Subject: [PATCH 32/65] drm/amd/display: Add pstate verification and recovery for DCN31 [Why] To debug when p-state is being blocked and avoid PMFW hangs when it does occur. [How] Re-use the DCN10 hardware sequencer by adding a new interface for verifying p-state high on the hubbub. The interface is mostly the same as the DCN10 interface, but the bit definitions have changed for the debug bus. Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Reviewed-by: Eric Yang <Eric.Yang2@amd.com> Reviewed-by: Harry Wentland <harry.wentland@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/dcn10/dcn10_hubbub.c | 1 + .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 10 +++- .../drm/amd/display/dc/dcn30/dcn30_hubbub.c | 1 + .../drm/amd/display/dc/dcn301/dcn301_hubbub.c | 1 + .../drm/amd/display/dc/dcn31/dcn31_hubbub.c | 60 +++++++++++++++++++ .../drm/amd/display/dc/dcn31/dcn31_resource.c | 2 +- .../gpu/drm/amd/display/dc/inc/hw/dchubbub.h | 2 + 7 files changed, 73 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c index f4f423d0b8c3f..80595d7f060c3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c @@ -940,6 +940,7 @@ static const struct hubbub_funcs hubbub1_funcs = { .program_watermarks = hubbub1_program_watermarks, .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled, .allow_self_refresh_control = hubbub1_allow_self_refresh_control, + .verify_allow_pstate_change_high = hubbub1_verify_allow_pstate_change_high, }; void hubbub1_construct(struct hubbub *hubbub, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index bc9dd48258e32..c3e141c19a77e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1112,9 +1112,13 @@ static bool dcn10_hw_wa_force_recovery(struct dc *dc) void dcn10_verify_allow_pstate_change_high(struct dc *dc) { + struct hubbub *hubbub = dc->res_pool->hubbub; static bool should_log_hw_state; /* prevent hw state log by default */ - if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub)) { + if (!hubbub->funcs->verify_allow_pstate_change_high) + return; + + if (!hubbub->funcs->verify_allow_pstate_change_high(hubbub)) { int i = 0; if (should_log_hw_state) @@ -1123,8 +1127,8 @@ void dcn10_verify_allow_pstate_change_high(struct dc *dc) TRACE_DC_PIPE_STATE(pipe_ctx, i, MAX_PIPES); BREAK_TO_DEBUGGER(); if (dcn10_hw_wa_force_recovery(dc)) { - /*check again*/ - if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub)) + /*check again*/ + if (!hubbub->funcs->verify_allow_pstate_change_high(hubbub)) BREAK_TO_DEBUGGER(); } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c index f4414de96acc5..152c9c5733f1c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c @@ -448,6 +448,7 @@ static const struct hubbub_funcs hubbub30_funcs = { .program_watermarks = hubbub3_program_watermarks, .allow_self_refresh_control = hubbub1_allow_self_refresh_control, .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled, + .verify_allow_pstate_change_high = hubbub1_verify_allow_pstate_change_high, .force_wm_propagate_to_pipes = hubbub3_force_wm_propagate_to_pipes, .force_pstate_change_control = hubbub3_force_pstate_change_control, .init_watermarks = hubbub3_init_watermarks, diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c index 1e3bd2e9cdcc4..a046664e20316 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c @@ -60,6 +60,7 @@ static const struct hubbub_funcs hubbub301_funcs = { .program_watermarks = hubbub3_program_watermarks, .allow_self_refresh_control = hubbub1_allow_self_refresh_control, .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled, + .verify_allow_pstate_change_high = hubbub1_verify_allow_pstate_change_high, .force_wm_propagate_to_pipes = hubbub3_force_wm_propagate_to_pipes, .force_pstate_change_control = hubbub3_force_pstate_change_control, .hubbub_read_state = hubbub2_read_state, diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c index 5e3bcaf12cac4..3e6d6ebd199ee 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c @@ -949,6 +949,65 @@ static void hubbub31_get_dchub_ref_freq(struct hubbub *hubbub, } } +static bool hubbub31_verify_allow_pstate_change_high(struct hubbub *hubbub) +{ + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); + + /* + * Pstate latency is ~20us so if we wait over 40us and pstate allow + * still not asserted, we are probably stuck and going to hang + */ + const unsigned int pstate_wait_timeout_us = 100; + const unsigned int pstate_wait_expected_timeout_us = 40; + + static unsigned int max_sampled_pstate_wait_us; /* data collection */ + static bool forced_pstate_allow; /* help with revert wa */ + + unsigned int debug_data = 0; + unsigned int i; + + if (forced_pstate_allow) { + /* we hacked to force pstate allow to prevent hang last time + * we verify_allow_pstate_change_high. so disable force + * here so we can check status + */ + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 0, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 0); + forced_pstate_allow = false; + } + + REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, hubbub2->debug_test_index_pstate); + + for (i = 0; i < pstate_wait_timeout_us; i++) { + debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA); + + /* Debug bit is specific to ASIC. */ + if (debug_data & (1 << 26)) { + if (i > pstate_wait_expected_timeout_us) + DC_LOG_WARNING("pstate took longer than expected ~%dus\n", i); + return true; + } + if (max_sampled_pstate_wait_us < i) + max_sampled_pstate_wait_us = i; + + udelay(1); + } + + /* force pstate allow to prevent system hang + * and break to debugger to investigate + */ + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 1, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 1); + forced_pstate_allow = true; + + DC_LOG_WARNING("pstate TEST_DEBUG_DATA: 0x%X\n", + debug_data); + + return false; +} + static const struct hubbub_funcs hubbub31_funcs = { .update_dchub = hubbub2_update_dchub, .init_dchub_sys_ctx = hubbub31_init_dchub_sys_ctx, @@ -961,6 +1020,7 @@ static const struct hubbub_funcs hubbub31_funcs = { .program_watermarks = hubbub31_program_watermarks, .allow_self_refresh_control = hubbub1_allow_self_refresh_control, .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled, + .verify_allow_pstate_change_high = hubbub31_verify_allow_pstate_change_high, .program_det_size = dcn31_program_det_size, .program_compbuf_size = dcn31_program_compbuf_size, .init_crb = dcn31_init_crb, 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 7dbe301a994a4..89b7b6b7254ac 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -1011,7 +1011,7 @@ static const struct dc_debug_options debug_defaults_drv = { .max_downscale_src_width = 4096,/*upto true 4K*/ .disable_pplib_wm_range = false, .scl_reset_length10 = true, - .sanity_checks = false, + .sanity_checks = true, .underflow_assert_delay_us = 0xFFFFFFFF, .dwb_fi_phase = -1, // -1 = disable, .dmub_command_table = true, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h index 713f5558f5e17..9195dec294c2d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h @@ -154,6 +154,8 @@ struct hubbub_funcs { bool (*is_allow_self_refresh_enabled)(struct hubbub *hubbub); void (*allow_self_refresh_control)(struct hubbub *hubbub, bool allow); + bool (*verify_allow_pstate_change_high)(struct hubbub *hubbub); + void (*apply_DEDCN21_147_wa)(struct hubbub *hubbub); void (*force_wm_propagate_to_pipes)(struct hubbub *hubbub); From 0fe382fb82dc6cc6eaba6534d038dc381e2b17b9 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Wed, 9 Mar 2022 13:55:50 -0500 Subject: [PATCH 33/65] drm/amdgpu/display: enable scatter/gather display for DCN 3.1.6 Enable scatter/gather display for DCN 3.1.6. Reviewed-by: Harry Wentland <harry.wentland@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index a473700580888..da9628a0212ed 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1481,6 +1481,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) case IP_VERSION(3, 1, 2): case IP_VERSION(3, 1, 3): case IP_VERSION(3, 1, 5): + case IP_VERSION(3, 1, 6): init_data.flags.gpu_vm_support = true; break; default: From 6f172ae59a7577dbb73e2a8da18697ba8dc56341 Mon Sep 17 00:00:00 2001 From: Jonathan Kim <jonathan.kim@amd.com> Date: Wed, 9 Mar 2022 16:55:57 -0500 Subject: [PATCH 34/65] drm/amdgpu: fix aldebaran xgmi topology for vf VFs must also distinguish whether or not the TA supports full duplex or half duplex link records in order to report the correct xGMI topology. Signed-off-by: Jonathan Kim <jonathan.kim@amd.com> Reviewed-by: Shaoyun Liu <shaoyun.liu@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 3ce1d38a7822b..a6acec1a6155d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -310,6 +310,10 @@ static int psp_sw_init(void *handle) return ret; } + adev->psp.xgmi_context.supports_extended_data = + !adev->gmc.xgmi.connected_to_cpu && + adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 2); + memset(&boot_cfg_entry, 0, sizeof(boot_cfg_entry)); if (psp_get_runtime_db_entry(adev, PSP_RUNTIME_ENTRY_TYPE_BOOT_CONFIG, @@ -3008,7 +3012,6 @@ static int psp_init_sos_base_fw(struct amdgpu_device *adev) adev->psp.sos.size_bytes = le32_to_cpu(sos_hdr->sos.size_bytes); adev->psp.sos.start_addr = ucode_array_start_addr + le32_to_cpu(sos_hdr->sos.offset_bytes); - adev->psp.xgmi_context.supports_extended_data = false; } else { /* Load alternate PSP SOS FW */ sos_hdr_v1_3 = (const struct psp_firmware_header_v1_3 *)adev->psp.sos_fw->data; @@ -3023,7 +3026,6 @@ static int psp_init_sos_base_fw(struct amdgpu_device *adev) adev->psp.sos.size_bytes = le32_to_cpu(sos_hdr_v1_3->sos_aux.size_bytes); adev->psp.sos.start_addr = ucode_array_start_addr + le32_to_cpu(sos_hdr_v1_3->sos_aux.offset_bytes); - adev->psp.xgmi_context.supports_extended_data = true; } if ((adev->psp.sys.size_bytes == 0) || (adev->psp.sos.size_bytes == 0)) { From a03b288650abf2a92d5ecdaa737e3d04a2a77984 Mon Sep 17 00:00:00 2001 From: Hawking Zhang <Hawking.Zhang@amd.com> Date: Thu, 10 Mar 2022 15:53:04 +0800 Subject: [PATCH 35/65] drm/amdgpu: drop xmgi23 error query/reset support xgmi_ras is only initialized when host to GPU interface is PCIE. in such case, xgmi23 is disabled and protected by security firmware. Host access will results to security violation Signed-off-by: Hawking Zhang <Hawking.Zhang@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index 05c0d6e2c75ca..1b108d03e7859 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -34,7 +34,6 @@ #include "amdgpu_reset.h" -#define smnPCS_XGMI23_PCS_ERROR_STATUS 0x11a01210 #define smnPCS_XGMI3X16_PCS_ERROR_STATUS 0x11a0020c #define smnPCS_GOPX1_PCS_ERROR_STATUS 0x12200210 @@ -69,17 +68,6 @@ static const int wafl_pcs_err_status_reg_arct[] = { smnPCS_GOPX1_0_PCS_GOPX1_PCS_ERROR_STATUS + 0x100000, }; -static const int xgmi23_pcs_err_status_reg_aldebaran[] = { - smnPCS_XGMI23_PCS_ERROR_STATUS, - smnPCS_XGMI23_PCS_ERROR_STATUS + 0x100000, - smnPCS_XGMI23_PCS_ERROR_STATUS + 0x200000, - smnPCS_XGMI23_PCS_ERROR_STATUS + 0x300000, - smnPCS_XGMI23_PCS_ERROR_STATUS + 0x400000, - smnPCS_XGMI23_PCS_ERROR_STATUS + 0x500000, - smnPCS_XGMI23_PCS_ERROR_STATUS + 0x600000, - smnPCS_XGMI23_PCS_ERROR_STATUS + 0x700000 -}; - static const int xgmi3x16_pcs_err_status_reg_aldebaran[] = { smnPCS_XGMI3X16_PCS_ERROR_STATUS, smnPCS_XGMI3X16_PCS_ERROR_STATUS + 0x100000, @@ -797,9 +785,6 @@ static void amdgpu_xgmi_reset_ras_error_count(struct amdgpu_device *adev) xgmi_pcs_err_status_reg_vg20[i]); break; case CHIP_ALDEBARAN: - for (i = 0; i < ARRAY_SIZE(xgmi23_pcs_err_status_reg_aldebaran); i++) - pcs_clear_status(adev, - xgmi23_pcs_err_status_reg_aldebaran[i]); for (i = 0; i < ARRAY_SIZE(xgmi3x16_pcs_err_status_reg_aldebaran); i++) pcs_clear_status(adev, xgmi3x16_pcs_err_status_reg_aldebaran[i]); @@ -900,13 +885,6 @@ static void amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev, } break; case CHIP_ALDEBARAN: - /* check xgmi23 pcs error */ - for (i = 0; i < ARRAY_SIZE(xgmi23_pcs_err_status_reg_aldebaran); i++) { - data = RREG32_PCIE(xgmi23_pcs_err_status_reg_aldebaran[i]); - if (data) - amdgpu_xgmi_query_pcs_error_status(adev, - data, &ue_cnt, &ce_cnt, true); - } /* check xgmi3x16 pcs error */ for (i = 0; i < ARRAY_SIZE(xgmi3x16_pcs_err_status_reg_aldebaran); i++) { data = RREG32_PCIE(xgmi3x16_pcs_err_status_reg_aldebaran[i]); From a29d44aea1aef0bc58d4951f2ddbe5b22d9a2e94 Mon Sep 17 00:00:00 2001 From: "Stanley.Yang" <Stanley.Yang@amd.com> Date: Thu, 10 Mar 2022 21:55:09 +0800 Subject: [PATCH 36/65] drm/amd/pm: use pm mutex to protect ecc info table Signed-off-by: Stanley.Yang <Stanley.Yang@amd.com> Reviewed-by: Evan Quan <evan.quan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 9a892d6d1d7af..89fbee568be4a 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -643,11 +643,16 @@ int amdgpu_dpm_get_ecc_info(struct amdgpu_device *adev, void *umc_ecc) { struct smu_context *smu = adev->powerplay.pp_handle; + int ret = 0; if (!is_support_sw_smu(adev)) return -EOPNOTSUPP; - return smu_get_ecc_info(smu, umc_ecc); + mutex_lock(&adev->pm.mutex); + ret = smu_get_ecc_info(smu, umc_ecc); + mutex_unlock(&adev->pm.mutex); + + return ret; } struct amd_vce_state *amdgpu_dpm_get_vce_clock_state(struct amdgpu_device *adev, From 85ac2021fe3ace59cc0afd6edf005abad35625b0 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 25 Jan 2022 15:04:54 -0500 Subject: [PATCH 37/65] drm/amdgpu: only check for _PR3 on dGPUs We don't support runtime pm on APUs. They support more dynamic power savings using clock and powergating. Reviewed-by: Mario Limonciello <mario.limonciello@amd.com> Tested-by: Mario Limonciello <mario.limonciello@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index ddc5cd61af587..1b313a95c7e55 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2159,8 +2159,10 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev) !pci_is_thunderbolt_attached(to_pci_dev(dev->dev))) adev->flags |= AMD_IS_PX; - parent = pci_upstream_bridge(adev->pdev); - adev->has_pr3 = parent ? pci_pr3_present(parent) : false; + if (!(adev->flags & AMD_IS_APU)) { + parent = pci_upstream_bridge(adev->pdev); + adev->has_pr3 = parent ? pci_pr3_present(parent) : false; + } amdgpu_amdkfd_device_probe(adev); From 72a98763b473890e6605604bfcaf71fc212b4720 Mon Sep 17 00:00:00 2001 From: "Tianci.Yin" <tianci.yin@amd.com> Date: Thu, 10 Mar 2022 21:12:49 +0800 Subject: [PATCH 38/65] drm/amd: fix gfx hang on renoir in IGT reload test [why] CP hangs in igt reloading test on renoir, more precisely, hangs on the second time insmod. [how] mode2 reset can make it recover, and mode2 reset only effects gfx core, dcn and the screen will not be impacted. Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Tianci.Yin <tianci.yin@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/soc15.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 496c4a6e23ac8..3d0251ef8d79a 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -853,6 +853,10 @@ static bool soc15_need_reset_on_init(struct amdgpu_device *adev) { u32 sol_reg; + /* CP hangs in IGT reloading test on RN, reset to WA */ + if (adev->asic_type == CHIP_RENOIR) + return true; + /* Just return false for soc15 GPUs. Reset does not seem to * be necessary. */ From 436afdfa35dc8aaf43959593f6c433d0ad29abc3 Mon Sep 17 00:00:00 2001 From: Philip Yang <Philip.Yang@amd.com> Date: Tue, 15 Mar 2022 14:38:51 -0400 Subject: [PATCH 39/65] drm/amdgpu: Move reset domain init before calling RREG32 amdgpu_detect_virtualization reads register, amdgpu_device_rreg access adev->reset_domain->sem if kernel defined CONFIG_LOCKDEP, below is the random boot hang backtrace on Vega10. It may get random NULL pointer access backtrace if amdgpu_sriov_runtime is true too. Move amdgpu_reset_create_reset_domain before calling to RREG32. BUG: kernel NULL pointer dereference, address: #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: 0000 [#1] PREEMPT SMP NOPTI Workqueue: events work_for_cpu_fn RIP: 0010:down_read_trylock+0x13/0xf0 Call Trace: <TASK> amdgpu_device_skip_hw_access+0x38/0x80 [amdgpu] amdgpu_device_rreg+0x1b/0x170 [amdgpu] amdgpu_detect_virtualization+0x73/0x100 [amdgpu] amdgpu_device_init.cold.60+0xbe/0x16b1 [amdgpu] ? pci_bus_read_config_word+0x43/0x70 amdgpu_driver_load_kms+0x15/0x120 [amdgpu] amdgpu_pci_probe+0x1a1/0x3a0 [amdgpu] Fixes: d0fb18b535679a ("drm/amdgpu: Move reset sem into reset_domain") Signed-off-by: Philip Yang <Philip.Yang@amd.com> Reviewed-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 1b313a95c7e55..3987ecb24ef4f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3666,6 +3666,15 @@ int amdgpu_device_init(struct amdgpu_device *adev, if (amdgpu_mes && adev->asic_type >= CHIP_NAVI10) adev->enable_mes = true; + /* + * Reset domain needs to be present early, before XGMI hive discovered + * (if any) and intitialized to use reset sem and in_gpu reset flag + * early on during init and before calling to RREG32. + */ + adev->reset_domain = amdgpu_reset_create_reset_domain(SINGLE_DEVICE, "amdgpu-reset-dev"); + if (!adev->reset_domain) + return -ENOMEM; + /* detect hw virtualization here */ amdgpu_detect_virtualization(adev); @@ -3675,15 +3684,6 @@ int amdgpu_device_init(struct amdgpu_device *adev, return r; } - /* - * Reset domain needs to be present early, before XGMI hive discovered - * (if any) and intitialized to use reset sem and in_gpu reset flag - * early on during init. - */ - adev->reset_domain = amdgpu_reset_create_reset_domain(SINGLE_DEVICE ,"amdgpu-reset-dev"); - if (!adev->reset_domain) - return -ENOMEM; - /* early init functions */ r = amdgpu_device_ip_early_init(adev); if (r) From a0248d543bbf2a977e7e6d9966ce8d96f6e5c358 Mon Sep 17 00:00:00 2001 From: "JinZe.Xu" <JinZe.Xu@amd.com> Date: Thu, 10 Mar 2022 17:20:34 -0500 Subject: [PATCH 40/65] drm/amd/display: Add I2C escape to support query device exist. [How] 1. Search OEM I2C info from BIOS and compare with input parameter. 2. If BIOS doesn't record it, just try to read one byte. Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Agustin Gutierrez <agustin.gutierrez@amd.com> Signed-off-by: JinZe.Xu <JinZe.Xu@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 13 ++++++++++ drivers/gpu/drm/amd/display/dc/dc_link.h | 5 ++++ drivers/gpu/drm/amd/display/dc/dce/dce_i2c.c | 26 ++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_i2c.h | 6 +++++ 4 files changed, 50 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 01b5996fa3aab..f6e19efea7568 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -3363,6 +3363,19 @@ bool dc_is_dmcu_initialized(struct dc *dc) return false; } +bool dc_is_oem_i2c_device_present( + struct dc *dc, + size_t slave_address) +{ + if (dc->res_pool->oem_device) + return dce_i2c_oem_device_present( + dc->res_pool, + dc->res_pool->oem_device, + slave_address); + + return false; +} + bool dc_submit_i2c( struct dc *dc, uint32_t link_index, diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index 78e66e4bab5a3..aa818bf840ebb 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -466,6 +466,11 @@ const struct dc_link_settings *dc_link_get_link_cap( void dc_link_overwrite_extended_receiver_cap( struct dc_link *link); +bool dc_is_oem_i2c_device_present( + struct dc *dc, + size_t slave_address +); + bool dc_submit_i2c( struct dc *dc, uint32_t link_index, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c.c b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c.c index dd41736bb5c49..f5cd2392fc5f7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c.c @@ -25,6 +25,32 @@ #include "dce_i2c.h" #include "reg_helper.h" +bool dce_i2c_oem_device_present( + struct resource_pool *pool, + struct ddc_service *ddc, + size_t slave_address +) +{ + struct dc *dc = ddc->ctx->dc; + struct dc_bios *dcb = dc->ctx->dc_bios; + struct graphics_object_id id = {0}; + struct graphics_object_i2c_info i2c_info; + + if (!dc->ctx->dc_bios->fw_info.oem_i2c_present) + return false; + + id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id; + id.enum_id = 0; + id.type = OBJECT_TYPE_GENERIC; + if (dcb->funcs->get_i2c_info(dcb, id, &i2c_info) != BP_RESULT_OK) + return false; + + if (i2c_info.i2c_slave_address != slave_address) + return false; + + return true; +} + bool dce_i2c_submit_command( struct resource_pool *pool, struct ddc *ddc, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c.h b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c.h index a171c5cd8439a..535fd58de4502 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c.h @@ -30,6 +30,12 @@ #include "dce_i2c_hw.h" #include "dce_i2c_sw.h" +bool dce_i2c_oem_device_present( + struct resource_pool *pool, + struct ddc_service *ddc, + size_t slave_address +); + bool dce_i2c_submit_command( struct resource_pool *pool, struct ddc *ddc, From 10499e4055949e4682d2e7c428365175e99e0800 Mon Sep 17 00:00:00 2001 From: "Leo (Hanghong) Ma" <hanghong.ma@amd.com> Date: Thu, 10 Mar 2022 17:20:35 -0500 Subject: [PATCH 41/65] drm/amd/display: Add function to get the pipe from the stream context [Why] We need a helper function in dc to grab the pipe from the stream context. [How] Add it. Reviewed-by: Martin Leung <Martin.Leung@amd.com> Acked-by: Agustin Gutierrez <agustin.gutierrez@amd.com> Signed-off-by: Leo (Hanghong) Ma <hanghong.ma@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 14 ++++++++++++++ drivers/gpu/drm/amd/display/dc/dc_stream.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index dc5fd27b031a0..c4e871f358abc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -718,6 +718,20 @@ enum dc_status dc_stream_add_dsc_to_resource(struct dc *dc, } } +struct pipe_ctx *dc_stream_get_pipe_ctx(struct dc_stream_state *stream) +{ + int i = 0; + + for (i = 0; i < MAX_PIPES; i++) { + struct pipe_ctx *pipe = &stream->ctx->dc->current_state->res_ctx.pipe_ctx[i]; + + if (pipe->stream == stream) + return pipe; + } + + return NULL; +} + void dc_stream_log(const struct dc *dc, const struct dc_stream_state *stream) { DC_LOG_DC( diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index f631b61abedd4..99a750f561f81 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -524,4 +524,6 @@ bool dc_stream_get_crtc_position(struct dc *dc, unsigned int *v_pos, unsigned int *nom_v_pos); +struct pipe_ctx *dc_stream_get_pipe_ctx(struct dc_stream_state *stream); + #endif /* DC_STREAM_H_ */ From a18112ae72d693bd4eb79f2ec09b536eeacb902b Mon Sep 17 00:00:00 2001 From: Wayne Lin <Wayne.Lin@amd.com> Date: Thu, 10 Mar 2022 17:20:36 -0500 Subject: [PATCH 42/65] drm/amd/display: Fix a few parts in debugfs entry [Why & How] 1. To leverage and simplify the igt tool. Change the value of retrain when calling preferred training settings. Now, writing value to link settings triggers link training immediately. 2. Add dc lock when triggering link training in edp_ilr_write() Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Acked-by: Agustin Gutierrez <agustin.gutierrez@amd.com> Signed-off-by: Wayne Lin <Wayne.Lin@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 777210811311e..da17ece1a2c50 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -243,6 +243,7 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf, { struct amdgpu_dm_connector *connector = file_inode(f)->i_private; struct dc_link *link = connector->dc_link; + struct amdgpu_device *adev = drm_to_adev(connector->base.dev); struct dc *dc = (struct dc *)link->dc; struct dc_link_settings prefer_link_settings; char *wr_buf = NULL; @@ -302,6 +303,9 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf, if (!valid_input) { kfree(wr_buf); DRM_DEBUG_DRIVER("Invalid Input value No HW will be programmed\n"); + mutex_lock(&adev->dm.dc_lock); + dc_link_set_preferred_training_settings(dc, NULL, NULL, link, false); + mutex_unlock(&adev->dm.dc_lock); return size; } @@ -313,7 +317,9 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf, prefer_link_settings.lane_count = param[0]; prefer_link_settings.link_rate = param[1]; - dc_link_set_preferred_training_settings(dc, &prefer_link_settings, NULL, link, true); + mutex_lock(&adev->dm.dc_lock); + dc_link_set_preferred_training_settings(dc, &prefer_link_settings, NULL, link, false); + mutex_unlock(&adev->dm.dc_lock); kfree(wr_buf); return size; @@ -2883,7 +2889,9 @@ static ssize_t edp_ilr_write(struct file *f, const char __user *buf, kfree(wr_buf); DRM_DEBUG_DRIVER("Invalid Input value. No HW will be programmed\n"); prefer_link_settings.use_link_rate_set = false; + mutex_lock(&adev->dm.dc_lock); dc_link_set_preferred_training_settings(dc, NULL, NULL, link, false); + mutex_unlock(&adev->dm.dc_lock); return size; } From d853419f5fcce39553ce0f6837fa122f113b15b6 Mon Sep 17 00:00:00 2001 From: Jing Zhou <Jing.Zhou@amd.com> Date: Thu, 10 Mar 2022 17:20:37 -0500 Subject: [PATCH 43/65] drm/amd/display: Update engine ddc [Why] Crash caused by a ddc update failure [How] Update engine ddc before release engine. Reviewed-by: Wyatt Wood <Wyatt.Wood@amd.com> Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Agustin Gutierrez <agustin.gutierrez@amd.com> Signed-off-by: Jing Zhou <Jing.Zhou@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dce/dce_aux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c index b8d6f42024130..8e814000db62d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c @@ -413,6 +413,7 @@ static bool acquire( return false; if (!acquire_engine(engine)) { + engine->ddc = ddc; release_engine(engine); return false; } From c791d75a64f5c628a9c9a7d9b9ec01ef0357e6a3 Mon Sep 17 00:00:00 2001 From: Eric Yang <Eric.Yang2@amd.com> Date: Thu, 10 Mar 2022 17:20:38 -0500 Subject: [PATCH 44/65] drm/amd/display: Block zstate when more than one plane enabled [Why] Currently Z10 save/restore only covers 1 plane case. If we enter Z10 with 2 planes enabled, 1 of the 2 planes will not be restored. causing black screen. [How] Disable Zstate when more than 1 plane is enabled. Right now Z9 enable but Z10 disable is not a supported config, so we disable both. Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Reviewed-by: Nevenko Stupar <Nevenko.Stupar@amd.com> Acked-by: Agustin Gutierrez <agustin.gutierrez@amd.com> Signed-off-by: Eric Yang <Eric.Yang2@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) 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 7cc8c78cb1637..2f6122153bdb5 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 @@ -730,18 +730,22 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc } /* - * Zstate is allowed in following scenarios: - * 1. Single eDP with PSR enabled - * 2. 0 planes (No memory requests) - * 3. Single eDP without PSR but > 5ms stutter period + * Z9 and Z10 allowed cases: + * 1. 0 Planes enabled + * 2. single eDP, on link 0, 1 plane and stutter period > 5ms + * Z10 only cases: + * 1. single eDP, on link 0, 1 plane and stutter period >= 5ms + * Zstate not allowed cases: + * 1. Everything else */ if (plane_count == 0) return DCN_ZSTATE_SUPPORT_ALLOW; else if (context->stream_count == 1 && context->streams[0]->signal == SIGNAL_TYPE_EDP) { struct dc_link *link = context->streams[0]->sink->link; + struct dc_stream_status *stream_status = &context->stream_status[0]; - /* zstate only supported on PWRSEQ0 */ - if (link->link_index != 0) + /* zstate only supported on PWRSEQ0 and when there's <2 planes*/ + if (link->link_index != 0 || stream_status->plane_count > 1) return DCN_ZSTATE_SUPPORT_DISALLOW; if (context->bw_ctx.dml.vba.StutterPeriod > 5000.0) From 906fbba2c9d48678fd182d0de4dd193d9dd0cc9c Mon Sep 17 00:00:00 2001 From: Dale Zhao <dale.zhao@amd.com> Date: Thu, 10 Mar 2022 17:20:39 -0500 Subject: [PATCH 45/65] drm/amd/display: Add new enum for EDID status [Why] We must support a new type of partial edid return in the future [How] Add interface and case hander for partial edid Reviewed-by: Charlene Liu <Charlene.Liu@amd.com> Acked-by: Agustin Gutierrez <agustin.gutierrez@amd.com> Signed-off-by: Dale Zhao <dale.zhao@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 3 +++ drivers/gpu/drm/amd/display/dc/dc_types.h | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index b3ca3307d39d0..cb87dd6431808 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1183,6 +1183,9 @@ static bool detect_link_and_local_sink(struct dc_link *link, case EDID_BAD_CHECKSUM: DC_LOG_ERROR("EDID checksum invalid.\n"); break; + case EDID_PARTIAL_VALID: + DC_LOG_ERROR("Partial EDID valid, abandon invalid blocks.\n"); + break; case EDID_NO_RESPONSE: DC_LOG_ERROR("No EDID read.\n"); /* diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 48859d5fc1725..2ba9f528c0fe7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -138,6 +138,7 @@ enum dc_edid_status { EDID_BAD_CHECKSUM, EDID_THE_SAME, EDID_FALL_BACK, + EDID_PARTIAL_VALID, }; enum act_return_status { From 3a0625813bacf12bf188f8242b42b508af28baa0 Mon Sep 17 00:00:00 2001 From: Wayne Lin <Wayne.Lin@amd.com> Date: Thu, 10 Mar 2022 17:20:40 -0500 Subject: [PATCH 46/65] drm/amd/display: Retry when fail reading lane status during LT [Why] In dp_get_lane_status_and_lane_adjust(), we call core_link_read_dpcd() to get lane status but we ignore the return value of the function. If there is problem with AUX and we eventually can only get partial data from monitor, we might misuse the data to jude the link training result. Which could have us trapped in the dc_link_dp_perform_link_training() since we thought that we can still give a try on another link setting. [How] In dp_get_lane_status_and_lane_adjust(), take return value of core_link_read_dpcd() into account. If we fail to read all requested data, we treat lanes status as previous one and repeat LT steps again. Reviewed-by: Wenjing Liu <Wenjing.Liu@amd.com> Acked-by: Agustin Gutierrez <agustin.gutierrez@amd.com> Signed-off-by: Wayne Lin <Wayne.Lin@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index c35d55fe41aba..351081f574cb7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -984,6 +984,14 @@ enum dc_status dp_get_lane_status_and_lane_adjust( (uint8_t *)(dpcd_buf), sizeof(dpcd_buf)); + if (status != DC_OK) { + DC_LOG_HW_LINK_TRAINING("%s:\n Failed to read from address 0x%X," + " keep current lane status and lane adjust unchanged", + __func__, + lane01_status_address); + return status; + } + for (lane = 0; lane < (uint32_t)(link_training_setting->link_settings.lane_count); lane++) { @@ -1124,6 +1132,9 @@ static bool perform_post_lt_adj_req_sequence( uint32_t adj_req_timer; bool req_drv_setting_changed; uint32_t lane; + union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0}; + union lane_align_status_updated dpcd_lane_status_updated = {0}; + union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0}; req_drv_setting_changed = false; for (adj_req_count = 0; adj_req_count < POST_LT_ADJ_REQ_LIMIT; @@ -1135,11 +1146,6 @@ static bool perform_post_lt_adj_req_sequence( adj_req_timer < POST_LT_ADJ_REQ_TIMEOUT; adj_req_timer++) { - union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX]; - union lane_align_status_updated - dpcd_lane_status_updated; - union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } }; - dp_get_lane_status_and_lane_adjust( link, lt_settings, @@ -1366,6 +1372,10 @@ static enum link_training_result perform_clock_recovery_sequence( retries_cr = 0; retry_count = 0; + memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status)); + memset(&dpcd_lane_status_updated, '\0', + sizeof(dpcd_lane_status_updated)); + if (!link->ctx->dc->work_arounds.lt_early_cr_pattern) dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_cr, offset); @@ -1377,9 +1387,6 @@ static enum link_training_result perform_clock_recovery_sequence( while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) && (retry_count < LINK_TRAINING_MAX_CR_RETRY)) { - memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status)); - memset(&dpcd_lane_status_updated, '\0', - sizeof(dpcd_lane_status_updated)); /* 1. call HWSS to set lane settings*/ dp_set_hw_lane_settings( @@ -2475,12 +2482,13 @@ static enum link_training_result dp_perform_fixed_vs_pe_training_sequence( retries_cr = 0; retry_count = 0; + memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status)); + memset(&dpcd_lane_status_updated, '\0', + sizeof(dpcd_lane_status_updated)); + while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) && (retry_count < LINK_TRAINING_MAX_CR_RETRY)) { - memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status)); - memset(&dpcd_lane_status_updated, '\0', - sizeof(dpcd_lane_status_updated)); /* 1. call HWSS to set lane settings */ dp_set_hw_lane_settings( From 2716bc822e2325efed0731d6a6a7dff755dc34d7 Mon Sep 17 00:00:00 2001 From: Jing Zhou <Jing.Zhou@amd.com> Date: Thu, 10 Mar 2022 17:20:41 -0500 Subject: [PATCH 47/65] drm/amd/display: Add null pointer filter [Why & How] Add null pointer filter for logical integrity. Reviewed-by: Charlene Liu <Charlene.Liu@amd.com> Acked-by: Agustin Gutierrez <agustin.gutierrez@amd.com> Signed-off-by: Jing Zhou <Jing.Zhou@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c index dae8e489c8cf4..778c206f754d3 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c @@ -647,7 +647,9 @@ enum gpio_result dal_ddc_set_config( void dal_ddc_close( struct ddc *ddc) { - dal_gpio_close(ddc->pin_clock); - dal_gpio_close(ddc->pin_data); + if (ddc != NULL) { + dal_gpio_close(ddc->pin_clock); + dal_gpio_close(ddc->pin_data); + } } From dd15640bcee5a5fa74fc52557dd6220f48b01116 Mon Sep 17 00:00:00 2001 From: Becle Lee <becle.lee@amd.com> Date: Thu, 10 Mar 2022 17:20:42 -0500 Subject: [PATCH 48/65] drm/amd/display: Wait for hubp read line for Pollock [Why] Underflow occurred while hubp ret pipe read is idle and the second pipe is powered up and added. Flickering and underflow are only observed on Pollock. [How] Check the hubp ret pipe read prior to unlock pipes. Reviewed-by: Hersen Wu <hersenxs.wu@amd.com> Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Agustin Gutierrez <agustin.gutierrez@amd.com> Signed-off-by: Becle Lee <becle.lee@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c | 15 +++++++++++++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h | 4 ++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 15 +++++++++++++++ .../gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 10 ++++++++++ drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h | 1 + .../drm/amd/display/dc/inc/hw_sequencer_private.h | 1 + 6 files changed, 46 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c index ea185c8773232..fbff6beb78be8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c @@ -1311,6 +1311,20 @@ void hubp1_set_flip_int(struct hubp *hubp) return; } +/** + * hubp1_wait_pipe_read_start - wait for hubp ret path starting read. + * + * @hubp: hubp struct reference. + */ +void hubp1_wait_pipe_read_start(struct hubp *hubp) +{ + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + + REG_WAIT(HUBPRET_READ_LINE_STATUS, + PIPE_READ_VBLANK, 0, + 1, 1000); +} + void hubp1_init(struct hubp *hubp) { //do nothing @@ -1345,6 +1359,7 @@ static const struct hubp_funcs dcn10_hubp_funcs = { .hubp_soft_reset = hubp1_soft_reset, .hubp_in_blank = hubp1_in_blank, .hubp_set_flip_int = hubp1_set_flip_int, + .hubp_wait_pipe_read_start = hubp1_wait_pipe_read_start, }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h index 9cb8c383d673c..0b17c2993ca5b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h @@ -76,6 +76,7 @@ SRI(DCSURF_SURFACE_CONTROL, HUBPREQ, id),\ SRI(DCSURF_SURFACE_FLIP_INTERRUPT, HUBPREQ, id),\ SRI(HUBPRET_CONTROL, HUBPRET, id),\ + SRI(HUBPRET_READ_LINE_STATUS, HUBPRET, id),\ SRI(DCN_EXPANSION_MODE, HUBPREQ, id),\ SRI(DCHUBP_REQ_SIZE_CONFIG, HUBP, id),\ SRI(DCHUBP_REQ_SIZE_CONFIG_C, HUBP, id),\ @@ -186,6 +187,7 @@ uint32_t DCSURF_SURFACE_CONTROL; \ uint32_t DCSURF_SURFACE_FLIP_INTERRUPT; \ uint32_t HUBPRET_CONTROL; \ + uint32_t HUBPRET_READ_LINE_STATUS; \ uint32_t DCN_EXPANSION_MODE; \ uint32_t DCHUBP_REQ_SIZE_CONFIG; \ uint32_t DCHUBP_REQ_SIZE_CONFIG_C; \ @@ -338,6 +340,7 @@ HUBP_SF(HUBPRET0_HUBPRET_CONTROL, DET_BUF_PLANE1_BASE_ADDRESS, mask_sh),\ HUBP_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CB_B, mask_sh),\ HUBP_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CR_R, mask_sh),\ + HUBP_SF(HUBPRET0_HUBPRET_READ_LINE_STATUS, PIPE_READ_VBLANK, mask_sh),\ HUBP_SF(HUBPREQ0_DCN_EXPANSION_MODE, DRQ_EXPANSION_MODE, mask_sh),\ HUBP_SF(HUBPREQ0_DCN_EXPANSION_MODE, PRQ_EXPANSION_MODE, mask_sh),\ HUBP_SF(HUBPREQ0_DCN_EXPANSION_MODE, MRQ_EXPANSION_MODE, mask_sh),\ @@ -538,6 +541,7 @@ type DET_BUF_PLANE1_BASE_ADDRESS;\ type CROSSBAR_SRC_CB_B;\ type CROSSBAR_SRC_CR_R;\ + type PIPE_READ_VBLANK;\ type DRQ_EXPANSION_MODE;\ type PRQ_EXPANSION_MODE;\ type MRQ_EXPANSION_MODE;\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index ac96242cc4747..4048908dd2659 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -863,6 +863,21 @@ static struct dce_hwseq *dcn10_hwseq_create( hws->wa.DEGVIDCN10_253 = true; hws->wa.false_optc_underflow = true; hws->wa.DEGVIDCN10_254 = true; + + if ((ctx->asic_id.chip_family == FAMILY_RV) && + ASICREV_IS_RAVEN2(ctx->asic_id.hw_internal_rev)) + switch (ctx->asic_id.pci_revision_id) { + case PRID_POLLOCK_94: + case PRID_POLLOCK_95: + case PRID_POLLOCK_E9: + case PRID_POLLOCK_EA: + case PRID_POLLOCK_EB: + hws->wa.wait_hubpret_read_start_during_mpo_transition = true; + break; + default: + hws->wa.wait_hubpret_read_start_during_mpo_transition = false; + break; + } } return hws; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 1ef880fed7766..ab910deed4812 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1739,6 +1739,16 @@ void dcn20_program_front_end_for_ctx( || pipe->stream->update_flags.raw) && hws->funcs.program_all_writeback_pipes_in_tree) hws->funcs.program_all_writeback_pipes_in_tree(dc, pipe->stream, context); + + /* Avoid underflow by check of pipe line read when adding 2nd plane. */ + if (hws->wa.wait_hubpret_read_start_during_mpo_transition && + !pipe->top_pipe && + pipe->stream && + pipe->plane_res.hubp->funcs->hubp_wait_pipe_read_start && + dc->current_state->stream_status[0].plane_count == 1 && + context->stream_status[0].plane_count > 1) { + pipe->plane_res.hubp->funcs->hubp_wait_pipe_read_start(pipe->plane_res.hubp); + } } } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h index 2c031586f4e64..e45b7993c5c57 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h @@ -195,6 +195,7 @@ struct hubp_funcs { void (*hubp_set_flip_int)(struct hubp *hubp); + void (*hubp_wait_pipe_read_start)(struct hubp *hubp); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h index 280c8764b6369..8c2f190c47124 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h @@ -42,6 +42,7 @@ struct dce_hwseq_wa { bool DEGVIDCN21; bool disallow_self_refresh_during_multi_plane_transition; bool dp_hpo_and_otg_sequence; + bool wait_hubpret_read_start_during_mpo_transition; }; struct hwseq_wa_state { From a91b402d50072e4801b231925f33574f90e562ce Mon Sep 17 00:00:00 2001 From: Charlene Liu <Charlene.Liu@amd.com> Date: Thu, 10 Mar 2022 17:20:43 -0500 Subject: [PATCH 49/65] drm/amd/display: Add save/restore PANEL_PWRSEQ_REF_DIV2 [why] DCN31 has this in zstate save/restore sequence. need for non_zstate supported ASIC [how] add this PANEL_PWRSEQ_REF_DIV2 to existing panel_cntl_hw_init structure. Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Acked-by: Agustin Gutierrez <agustin.gutierrez@amd.com> Signed-off-by: Charlene Liu <Charlene.Liu@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../amd/display/dc/dcn31/dcn31_panel_cntl.c | 5 +- .../drm/amd/display/dc/inc/hw/panel_cntl.h | 1 + .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 88 ++++++++++++++++++- 3 files changed, 91 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c index 83ece02380a8f..11ea9d13e3128 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c @@ -83,7 +83,8 @@ static uint32_t dcn31_panel_cntl_hw_init(struct panel_cntl *panel_cntl) cmd.panel_cntl.data.bl_pwm_period_cntl = panel_cntl->stored_backlight_registers.BL_PWM_PERIOD_CNTL; cmd.panel_cntl.data.bl_pwm_ref_div1 = panel_cntl->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV; - + cmd.panel_cntl.data.bl_pwm_ref_div2 = + panel_cntl->stored_backlight_registers.PANEL_PWRSEQ_REF_DIV2; if (!dc_dmub_srv_cmd_with_reply_data(dc_dmub_srv, &cmd)) return 0; @@ -92,6 +93,8 @@ static uint32_t dcn31_panel_cntl_hw_init(struct panel_cntl *panel_cntl) panel_cntl->stored_backlight_registers.BL_PWM_PERIOD_CNTL = cmd.panel_cntl.data.bl_pwm_period_cntl; panel_cntl->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV = cmd.panel_cntl.data.bl_pwm_ref_div1; + panel_cntl->stored_backlight_registers.PANEL_PWRSEQ_REF_DIV2 = + cmd.panel_cntl.data.bl_pwm_ref_div2; return cmd.panel_cntl.data.current_backlight; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h b/drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h index 48eac622c6a0f..24af9d80b9373 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h @@ -39,6 +39,7 @@ struct panel_cntl_backlight_registers { unsigned int BL_PWM_CNTL2; unsigned int BL_PWM_PERIOD_CNTL; unsigned int LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV; + unsigned int PANEL_PWRSEQ_REF_DIV2; }; struct panel_cntl_funcs { diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 8521508af7557..294717e09abfc 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -1450,6 +1450,80 @@ enum dmub_cmd_mall_type { DMUB_CMD__MALL_ACTION_NO_DF_REQ = 3, }; +/** + * PHY Link rate for DP. + */ +enum phy_link_rate { + /** + * not supported. + */ + PHY_RATE_UNKNOWN = 0, + /** + * Rate_1 (RBR) - 1.62 Gbps/Lane + */ + PHY_RATE_162 = 1, + /** + * Rate_2 - 2.16 Gbps/Lane + */ + PHY_RATE_216 = 2, + /** + * Rate_3 - 2.43 Gbps/Lane + */ + PHY_RATE_243 = 3, + /** + * Rate_4 (HBR) - 2.70 Gbps/Lane + */ + PHY_RATE_270 = 4, + /** + * Rate_5 (RBR2)- 3.24 Gbps/Lane + */ + PHY_RATE_324 = 5, + /** + * Rate_6 - 4.32 Gbps/Lane + */ + PHY_RATE_432 = 6, + /** + * Rate_7 (HBR2)- 5.40 Gbps/Lane + */ + PHY_RATE_540 = 7, + /** + * Rate_8 (HBR3)- 8.10 Gbps/Lane + */ + PHY_RATE_810 = 8, + /** + * UHBR10 - 10.0 Gbps/Lane + */ + PHY_RATE_1000 = 9, + /** + * UHBR13.5 - 13.5 Gbps/Lane + */ + PHY_RATE_1350 = 10, + /** + * UHBR10 - 20.0 Gbps/Lane + */ + PHY_RATE_2000 = 11, +}; + +/** + * enum dmub_phy_fsm_state - PHY FSM states. + * PHY FSM state to transit to during PSR enable/disable. + */ +enum dmub_phy_fsm_state { + DMUB_PHY_FSM_POWER_UP_DEFAULT = 0, + DMUB_PHY_FSM_RESET, + DMUB_PHY_FSM_RESET_RELEASED, + DMUB_PHY_FSM_SRAM_LOAD_DONE, + DMUB_PHY_FSM_INITIALIZED, + DMUB_PHY_FSM_CALIBRATED, + DMUB_PHY_FSM_CALIBRATED_LP, + DMUB_PHY_FSM_CALIBRATED_PG, + DMUB_PHY_FSM_POWER_DOWN, + DMUB_PHY_FSM_PLL_EN, + DMUB_PHY_FSM_TX_EN, + DMUB_PHY_FSM_FAST_LP, +}; + + /** * Data passed from driver to FW in a DMUB_CMD__PSR_COPY_SETTINGS command. @@ -1698,9 +1772,16 @@ struct dmub_cmd_psr_force_static_data { */ uint8_t panel_inst; /** - * Explicit padding to 4 byte boundary. + * Phy state to enter. + * Values to use are defined in dmub_phy_fsm_state */ - uint8_t pad[2]; + uint8_t phy_fsm_state; + /** + * Phy rate for DP - RBR/HBR/HBR2/HBR3. + * Set this using enum phy_link_rate. + * This does not support HDMI/DP2 for now. + */ + uint8_t phy_rate; }; /** @@ -2377,6 +2458,9 @@ struct dmub_cmd_panel_cntl_data { uint32_t bl_pwm_ref_div1; /* in/out */ uint8_t is_backlight_on : 1; /* in/out */ uint8_t is_powered_on : 1; /* in/out */ + uint8_t padding[3]; + uint32_t bl_pwm_ref_div2; /* in/out */ + uint8_t reserved[4]; }; /** From cfe7c679412f14811cb3c4119c8025cb97564c48 Mon Sep 17 00:00:00 2001 From: Anthony Koo <Anthony.Koo@amd.com> Date: Thu, 10 Mar 2022 17:20:44 -0500 Subject: [PATCH 50/65] drm/amd/display: [FW Promotion] Release 0.0.108.0 Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Agustin Gutierrez <agustin.gutierrez@amd.com> Signed-off-by: Anthony Koo <Anthony.Koo@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 294717e09abfc..71214c7a60fce 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -46,10 +46,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0xb6b77696 +#define DMUB_FW_VERSION_GIT_HASH 0x929554ba #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 107 +#define DMUB_FW_VERSION_REVISION 108 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 From fdf0ece6309d90dc0f9388001239cb2d12671af3 Mon Sep 17 00:00:00 2001 From: Aric Cyr <aric.cyr@amd.com> Date: Thu, 10 Mar 2022 17:20:45 -0500 Subject: [PATCH 51/65] drm/amd/display: 3.2.177 This version brings along following fixes: - Added I2C escape to support query exist - Functionality to get pipe from stream context - debugfs entry fixes - Block zstate when more than one plane enabled - Update to engine ddc - Reading lante status during LT fixes - Null point filters - [FW Promotion] Release 0.0.108.0 Acked-by: Agustin Gutierrez <agustin.gutierrez@amd.com> Signed-off-by: Aric Cyr <aric.cyr@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index bd5f718a9eb2d..4ffab7bb1098b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.176" +#define DC_VER "3.2.177" #define MAX_SURFACES 3 #define MAX_PLANES 6 From 8476269f758221863c01a0a6cccb0d75ec5d60c3 Mon Sep 17 00:00:00 2001 From: yipechai <YiPeng.Chai@amd.com> Date: Fri, 11 Mar 2022 16:54:20 +0800 Subject: [PATCH 52/65] drm/amdgpu: fixed the warnings reported by kernel test robot The reported warnings are as follows: 1.warning:no-previous-prototype-for-amdgpu_hdp_ras_fini. 2.warning:no-previous-prototype-for-amdgpu_mmhub_ras_fini. Amdgpu_hdp_ras_fini and amdgpu_mmhub_ras_fini are unused in the code, they are the only functions in amdgpu_hdp.c and amdgpu_mmhub.c. After removing these two functions, both amdgpu_hdp.c and amdgpu_mmhub.c are empty, so these two files can be deleted to fix the warning. Signed-off-by: yipechai <YiPeng.Chai@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/Makefile | 4 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.c | 30 ----------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.c | 30 ----------------------- 3 files changed, 2 insertions(+), 62 deletions(-) delete mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.c delete mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.c diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 5dfe08cb045eb..40e2c6e2df797 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -53,11 +53,11 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o \ amdgpu_gtt_mgr.o amdgpu_preempt_mgr.o amdgpu_vram_mgr.o amdgpu_virt.o \ amdgpu_atomfirmware.o amdgpu_vf_error.o amdgpu_sched.o \ - amdgpu_debugfs.o amdgpu_ids.o amdgpu_gmc.o amdgpu_mmhub.o \ + amdgpu_debugfs.o amdgpu_ids.o amdgpu_gmc.o \ amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \ amdgpu_vm_sdma.o amdgpu_discovery.o amdgpu_ras_eeprom.o amdgpu_nbio.o \ amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o \ - amdgpu_fw_attestation.o amdgpu_securedisplay.o amdgpu_hdp.o \ + amdgpu_fw_attestation.o amdgpu_securedisplay.o \ amdgpu_eeprom.o amdgpu_mca.o amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.c deleted file mode 100644 index 3f3d92e16c2e3..0000000000000 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2021 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. - * - */ - -#include "amdgpu.h" -#include "amdgpu_ras.h" - -void amdgpu_hdp_ras_fini(struct amdgpu_device *adev, struct ras_common_if *ras_block) -{ - -} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.c deleted file mode 100644 index 8f2fa247d6059..0000000000000 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2019 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. - * - */ - -#include "amdgpu.h" -#include "amdgpu_ras.h" - -void amdgpu_mmhub_ras_fini(struct amdgpu_device *adev, struct ras_common_if *ras_block) -{ - -} From 8c0f11ff3895ec96c9523ac607dd51f812ab69a8 Mon Sep 17 00:00:00 2001 From: Lang Yu <Lang.Yu@amd.com> Date: Tue, 15 Mar 2022 13:17:55 +0800 Subject: [PATCH 53/65] drm/amdgpu: only allow secure submission on rings which support that MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only GFX ring, SDMA ring and VCN decode ring support secure submission at the moment. Suggested-by: Christian König <christian.koenig@amd.com> Signed-off-by: Lang Yu <Lang.Yu@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 1 + drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 1 + drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 1 + drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 1 + drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 1 + drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 4 ++++ drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 1 + drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 1 + drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 1 + drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 1 + drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 2 ++ drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 2 ++ 13 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index bc1297dcdf976..d583766ea3922 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -166,8 +166,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, } if ((ib->flags & AMDGPU_IB_FLAGS_SECURE) && - (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE)) { - dev_err(adev->dev, "secure submissions not supported on compute rings\n"); + (!ring->funcs->secure_submission_supported)) { + dev_err(adev->dev, "secure submissions not supported on ring <%s>\n", ring->name); return -EINVAL; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h index a8bed1b478996..5320bb0883d85 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h @@ -155,6 +155,7 @@ struct amdgpu_ring_funcs { u32 nop; bool support_64bit_ptrs; bool no_user_fence; + bool secure_submission_supported; unsigned vmhub; unsigned extra_dw; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 713d39d89e304..f4c6accd32263 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -9377,6 +9377,7 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_gfx = { .align_mask = 0xff, .nop = PACKET3(PACKET3_NOP, 0x3FFF), .support_64bit_ptrs = true, + .secure_submission_supported = true, .vmhub = AMDGPU_GFXHUB_0, .get_rptr = gfx_v10_0_ring_get_rptr_gfx, .get_wptr = gfx_v10_0_ring_get_wptr_gfx, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 8def7f630d4c2..46d4bf27ebbbb 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -6865,6 +6865,7 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_gfx = { .align_mask = 0xff, .nop = PACKET3(PACKET3_NOP, 0x3FFF), .support_64bit_ptrs = true, + .secure_submission_supported = true, .vmhub = AMDGPU_GFXHUB_0, .get_rptr = gfx_v9_0_ring_get_rptr_gfx, .get_wptr = gfx_v9_0_ring_get_wptr_gfx, diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c index 4509bd4cce2d6..1d8bbcbd7a37b 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c @@ -1142,6 +1142,7 @@ static const struct amdgpu_ring_funcs sdma_v2_4_ring_funcs = { .align_mask = 0xf, .nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), .support_64bit_ptrs = false, + .secure_submission_supported = true, .get_rptr = sdma_v2_4_ring_get_rptr, .get_wptr = sdma_v2_4_ring_get_wptr, .set_wptr = sdma_v2_4_ring_set_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index 135727b59c41e..4ef4feff5649a 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -1580,6 +1580,7 @@ static const struct amdgpu_ring_funcs sdma_v3_0_ring_funcs = { .align_mask = 0xf, .nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), .support_64bit_ptrs = false, + .secure_submission_supported = true, .get_rptr = sdma_v3_0_ring_get_rptr, .get_wptr = sdma_v3_0_ring_get_wptr, .set_wptr = sdma_v3_0_ring_set_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index 01b385568c14d..d7e8f72323641 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -2414,6 +2414,7 @@ static const struct amdgpu_ring_funcs sdma_v4_0_ring_funcs = { .align_mask = 0xf, .nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), .support_64bit_ptrs = true, + .secure_submission_supported = true, .vmhub = AMDGPU_MMHUB_0, .get_rptr = sdma_v4_0_ring_get_rptr, .get_wptr = sdma_v4_0_ring_get_wptr, @@ -2450,6 +2451,7 @@ static const struct amdgpu_ring_funcs sdma_v4_0_ring_funcs_2nd_mmhub = { .align_mask = 0xf, .nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), .support_64bit_ptrs = true, + .secure_submission_supported = true, .vmhub = AMDGPU_MMHUB_1, .get_rptr = sdma_v4_0_ring_get_rptr, .get_wptr = sdma_v4_0_ring_get_wptr, @@ -2482,6 +2484,7 @@ static const struct amdgpu_ring_funcs sdma_v4_0_page_ring_funcs = { .align_mask = 0xf, .nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), .support_64bit_ptrs = true, + .secure_submission_supported = true, .vmhub = AMDGPU_MMHUB_0, .get_rptr = sdma_v4_0_ring_get_rptr, .get_wptr = sdma_v4_0_page_ring_get_wptr, @@ -2514,6 +2517,7 @@ static const struct amdgpu_ring_funcs sdma_v4_0_page_ring_funcs_2nd_mmhub = { .align_mask = 0xf, .nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), .support_64bit_ptrs = true, + .secure_submission_supported = true, .vmhub = AMDGPU_MMHUB_1, .get_rptr = sdma_v4_0_ring_get_rptr, .get_wptr = sdma_v4_0_page_ring_get_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c index 53a8df4b030e2..a8d49c005f73d 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c @@ -1690,6 +1690,7 @@ static const struct amdgpu_ring_funcs sdma_v5_0_ring_funcs = { .align_mask = 0xf, .nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), .support_64bit_ptrs = true, + .secure_submission_supported = true, .vmhub = AMDGPU_GFXHUB_0, .get_rptr = sdma_v5_0_ring_get_rptr, .get_wptr = sdma_v5_0_ring_get_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c index dcc622e18d451..824eace698842 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c @@ -1687,6 +1687,7 @@ static const struct amdgpu_ring_funcs sdma_v5_2_ring_funcs = { .align_mask = 0xf, .nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), .support_64bit_ptrs = true, + .secure_submission_supported = true, .vmhub = AMDGPU_GFXHUB_0, .get_rptr = sdma_v5_2_ring_get_rptr, .get_wptr = sdma_v5_2_ring_get_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c index 7bbb9ba6b80b4..6c9d5cde61c40 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c @@ -1910,6 +1910,7 @@ static const struct amdgpu_ring_funcs vcn_v1_0_dec_ring_vm_funcs = { .align_mask = 0xf, .support_64bit_ptrs = false, .no_user_fence = true, + .secure_submission_supported = true, .vmhub = AMDGPU_MMHUB_0, .get_rptr = vcn_v1_0_dec_ring_get_rptr, .get_wptr = vcn_v1_0_dec_ring_get_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c index 319ac8ea434bf..8cb2124405f6c 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c @@ -2007,6 +2007,7 @@ static const struct amd_ip_funcs vcn_v2_0_ip_funcs = { static const struct amdgpu_ring_funcs vcn_v2_0_dec_ring_vm_funcs = { .type = AMDGPU_RING_TYPE_VCN_DEC, .align_mask = 0xf, + .secure_submission_supported = true, .vmhub = AMDGPU_MMHUB_0, .get_rptr = vcn_v2_0_dec_ring_get_rptr, .get_wptr = vcn_v2_0_dec_ring_get_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index 1869bae4104bd..1bf672966a622 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -1515,6 +1515,7 @@ static void vcn_v2_5_dec_ring_set_wptr(struct amdgpu_ring *ring) static const struct amdgpu_ring_funcs vcn_v2_5_dec_ring_vm_funcs = { .type = AMDGPU_RING_TYPE_VCN_DEC, .align_mask = 0xf, + .secure_submission_supported = true, .vmhub = AMDGPU_MMHUB_1, .get_rptr = vcn_v2_5_dec_ring_get_rptr, .get_wptr = vcn_v2_5_dec_ring_get_wptr, @@ -1545,6 +1546,7 @@ static const struct amdgpu_ring_funcs vcn_v2_5_dec_ring_vm_funcs = { static const struct amdgpu_ring_funcs vcn_v2_6_dec_ring_vm_funcs = { .type = AMDGPU_RING_TYPE_VCN_DEC, .align_mask = 0xf, + .secure_submission_supported = true, .vmhub = AMDGPU_MMHUB_0, .get_rptr = vcn_v2_5_dec_ring_get_rptr, .get_wptr = vcn_v2_5_dec_ring_get_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 5dbf5ba7d62db..c87263ed20ecb 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -1786,6 +1786,7 @@ static const struct amdgpu_ring_funcs vcn_v3_0_dec_sw_ring_vm_funcs = { .type = AMDGPU_RING_TYPE_VCN_DEC, .align_mask = 0x3f, .nop = VCN_DEC_SW_CMD_NO_OP, + .secure_submission_supported = true, .vmhub = AMDGPU_MMHUB_0, .get_rptr = vcn_v3_0_dec_ring_get_rptr, .get_wptr = vcn_v3_0_dec_ring_get_wptr, @@ -1944,6 +1945,7 @@ static int vcn_v3_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p, static const struct amdgpu_ring_funcs vcn_v3_0_dec_ring_vm_funcs = { .type = AMDGPU_RING_TYPE_VCN_DEC, .align_mask = 0xf, + .secure_submission_supported = true, .vmhub = AMDGPU_MMHUB_0, .get_rptr = vcn_v3_0_dec_ring_get_rptr, .get_wptr = vcn_v3_0_dec_ring_get_wptr, From 4e2f50e2306fdd0e5fc7db3d9a452ba1327b787e Mon Sep 17 00:00:00 2001 From: Tianci Yin <tianci.yin@amd.com> Date: Tue, 15 Mar 2022 09:58:09 +0800 Subject: [PATCH 54/65] drm/amdgpu/vcn: fix vcn ring test failure in igt reload test [why] On Renoir, vcn ring test failed on the second time insmod in the reload test. After investigation, it proves that vcn only can disable dpg under dpg unpause mode (dpg unpause mode is default for dec only, dpg pause mode is for dec/enc). [how] unpause dpg in dpg stopping procedure. Reviewed-by: James Zhu <James.Zhu@amd.com> Signed-off-by: Tianci Yin <tianci.yin@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c index 8cb2124405f6c..7a7f35e83dd5c 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c @@ -1098,8 +1098,10 @@ static int vcn_v2_0_start(struct amdgpu_device *adev) static int vcn_v2_0_stop_dpg_mode(struct amdgpu_device *adev) { + struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE}; uint32_t tmp; + vcn_v2_0_pause_dpg_mode(adev, 0, &state); /* Wait for power status to be 1 */ SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_POWER_STATUS, 1, UVD_POWER_STATUS__UVD_POWER_STATUS_MASK); From 9527b9caf82b040e794fba2667f6d8a85a793bb7 Mon Sep 17 00:00:00 2001 From: Philip Yang <Philip.Yang@amd.com> Date: Fri, 11 Mar 2022 15:22:15 -0500 Subject: [PATCH 55/65] drm/amdkfd: evict svm bo worker handle error Migrate vram to ram may fail to find the vma if process is exiting and vma is removed, evict svm bo worker sets prange->svm_bo to NULL and warn svm_bo ref count != 1 only if migrating vram to ram successfully. Signed-off-by: Philip Yang <Philip.Yang@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 29 +++++++++++++++++++----- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 21 ++++++++++------- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c index 7f689094be5ac..3a29d857640b1 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c @@ -638,6 +638,22 @@ svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct svm_range *prange, return r; } +/** + * svm_migrate_vma_to_ram - migrate range inside one vma from device to system + * + * @adev: amdgpu device to migrate from + * @prange: svm range structure + * @vma: vm_area_struct that range [start, end] belongs to + * @start: range start virtual address in pages + * @end: range end virtual address in pages + * + * Context: Process context, caller hold mmap read lock, prange->migrate_mutex + * + * Return: + * 0 - success with all pages migrated + * negative values - indicate error + * positive values - partial migration, number of pages not migrated + */ static long svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange, struct vm_area_struct *vma, uint64_t start, uint64_t end) @@ -709,8 +725,6 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange, pdd = svm_range_get_pdd_by_adev(prange, adev); if (pdd) WRITE_ONCE(pdd->page_out, pdd->page_out + cpages); - - return upages; } return r ? r : upages; } @@ -720,7 +734,7 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange, * @prange: range structure * @mm: process mm, use current->mm if NULL * - * Context: Process context, caller hold mmap read lock, svms lock, prange lock + * Context: Process context, caller hold mmap read lock, prange->migrate_mutex * * Return: * 0 - OK, otherwise error code @@ -759,13 +773,16 @@ int svm_migrate_vram_to_ram(struct svm_range *prange, struct mm_struct *mm) unsigned long next; vma = find_vma(mm, addr); - if (!vma || addr < vma->vm_start) + if (!vma || addr < vma->vm_start) { + pr_debug("failed to find vma for prange %p\n", prange); + r = -EFAULT; break; + } next = min(vma->vm_end, end); r = svm_migrate_vma_to_ram(adev, prange, vma, addr, next); if (r < 0) { - pr_debug("failed %ld to migrate\n", r); + pr_debug("failed %ld to migrate prange %p\n", r, prange); break; } else { upages += r; @@ -773,7 +790,7 @@ int svm_migrate_vram_to_ram(struct svm_range *prange, struct mm_struct *mm) addr = next; } - if (!upages) { + if (r >= 0 && !upages) { svm_range_vram_node_free(prange); prange->actual_loc = 0; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 509d915cbe696..3b8856b4cece8 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -3155,6 +3155,7 @@ static void svm_range_evict_svm_bo_worker(struct work_struct *work) struct svm_range_bo *svm_bo; struct kfd_process *p; struct mm_struct *mm; + int r = 0; svm_bo = container_of(work, struct svm_range_bo, eviction_work); if (!svm_bo_ref_unless_zero(svm_bo)) @@ -3170,7 +3171,7 @@ static void svm_range_evict_svm_bo_worker(struct work_struct *work) mmap_read_lock(mm); spin_lock(&svm_bo->list_lock); - while (!list_empty(&svm_bo->range_list)) { + while (!list_empty(&svm_bo->range_list) && !r) { struct svm_range *prange = list_first_entry(&svm_bo->range_list, struct svm_range, svm_bo_list); @@ -3184,15 +3185,18 @@ static void svm_range_evict_svm_bo_worker(struct work_struct *work) mutex_lock(&prange->migrate_mutex); do { - svm_migrate_vram_to_ram(prange, + r = svm_migrate_vram_to_ram(prange, svm_bo->eviction_fence->mm); - } while (prange->actual_loc && --retries); - WARN(prange->actual_loc, "Migration failed during eviction"); + } while (!r && prange->actual_loc && --retries); - mutex_lock(&prange->lock); - prange->svm_bo = NULL; - mutex_unlock(&prange->lock); + if (!r && prange->actual_loc) + pr_info_once("Migration failed during eviction"); + if (!prange->actual_loc) { + mutex_lock(&prange->lock); + prange->svm_bo = NULL; + mutex_unlock(&prange->lock); + } mutex_unlock(&prange->migrate_mutex); spin_lock(&svm_bo->list_lock); @@ -3201,10 +3205,11 @@ static void svm_range_evict_svm_bo_worker(struct work_struct *work) mmap_read_unlock(mm); dma_fence_signal(&svm_bo->eviction_fence->base); + /* This is the last reference to svm_bo, after svm_range_vram_node_free * has been called in svm_migrate_vram_to_ram */ - WARN_ONCE(kref_read(&svm_bo->kref) != 1, "This was not the last reference\n"); + WARN_ONCE(!r && kref_read(&svm_bo->kref) != 1, "This was not the last reference\n"); svm_range_bo_unref(svm_bo); } From 3f543552846b9ae47c8442af1c506207bdcc00d2 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun <yongqiang.sun@amd.com> Date: Mon, 14 Mar 2022 14:17:08 -0400 Subject: [PATCH 56/65] drm/amdgpu: Merge get_reserved_allocation to get_vbios_allocations. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some ASICs need reserved memory for firmware or other components, which is not allowed to be used by driver. amdgpu_gmc_get_reserved_allocation is to handle additional areas. To avoid any missing calling, merged amdgpu_gmc_get_reserved_allocation to amdgpu_gmc_get_vbios_allocations. Acked-by: Christian König <christian.koenig@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Yongqiang Sun <yongqiang.sun@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 32 ++++++++++--------------- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 1 - drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 1 - 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 58fd2729f577e..a25ae3b512564 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -622,6 +622,13 @@ void amdgpu_gmc_get_vbios_allocations(struct amdgpu_device *adev) { unsigned size; + /* + * Some ASICs need to reserve a region of video memory to avoid access + * from driver + */ + adev->mman.stolen_reserved_offset = 0; + adev->mman.stolen_reserved_size = 0; + /* * TODO: * Currently there is a bug where some memory client outside @@ -636,6 +643,12 @@ void amdgpu_gmc_get_vbios_allocations(struct amdgpu_device *adev) case CHIP_RENOIR: adev->mman.keep_stolen_vga_memory = true; break; + case CHIP_YELLOW_CARP: + if (amdgpu_discovery == 0) { + adev->mman.stolen_reserved_offset = 0x1ffb0000; + adev->mman.stolen_reserved_size = 64 * PAGE_SIZE; + } + break; default: adev->mman.keep_stolen_vga_memory = false; break; @@ -756,25 +769,6 @@ uint64_t amdgpu_gmc_vram_cpu_pa(struct amdgpu_device *adev, struct amdgpu_bo *bo return amdgpu_bo_gpu_offset(bo) - adev->gmc.vram_start + adev->gmc.aper_base; } -void amdgpu_gmc_get_reserved_allocation(struct amdgpu_device *adev) -{ - /* Some ASICs need to reserve a region of video memory to avoid access - * from driver */ - adev->mman.stolen_reserved_offset = 0; - adev->mman.stolen_reserved_size = 0; - - switch (adev->asic_type) { - case CHIP_YELLOW_CARP: - if (amdgpu_discovery == 0) { - adev->mman.stolen_reserved_offset = 0x1ffb0000; - adev->mman.stolen_reserved_size = 64 * PAGE_SIZE; - } - break; - default: - break; - } -} - int amdgpu_gmc_vram_checking(struct amdgpu_device *adev) { struct amdgpu_bo *vram_bo = NULL; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index 93505bb0a36c3..032b0313f2777 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -331,7 +331,6 @@ amdgpu_gmc_set_vm_fault_masks(struct amdgpu_device *adev, int hub_type, bool enable); void amdgpu_gmc_get_vbios_allocations(struct amdgpu_device *adev); -void amdgpu_gmc_get_reserved_allocation(struct amdgpu_device *adev); void amdgpu_gmc_init_pdb0(struct amdgpu_device *adev); uint64_t amdgpu_gmc_vram_mc2pa(struct amdgpu_device *adev, uint64_t mc_addr); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index f60b7bd4dbf58..3c1d440824a73 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -948,7 +948,6 @@ static int gmc_v10_0_sw_init(void *handle) return r; amdgpu_gmc_get_vbios_allocations(adev); - amdgpu_gmc_get_reserved_allocation(adev); /* Memory manager */ r = amdgpu_bo_init(adev); From faad5ccac1eaae584f9ac2ea66278bd137edcbe3 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun <yongqiang.sun@amd.com> Date: Tue, 15 Mar 2022 09:43:41 -0400 Subject: [PATCH 57/65] drm/amdgpu: Add stolen reserved memory for MI25 SRIOV. MI25 SRIOV guest driver loading failed due to allocated memory overlaps with firmware reserved area. Allocate stolen reserved memory for MI25 SRIOV specifically to avoid the memory overlap. Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Yongqiang Sun <yongqiang.sun@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index a25ae3b512564..ca2cfb65f9763 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -639,6 +639,15 @@ void amdgpu_gmc_get_vbios_allocations(struct amdgpu_device *adev) */ switch (adev->asic_type) { case CHIP_VEGA10: + adev->mman.keep_stolen_vga_memory = true; + /* + * VEGA10 SRIOV VF needs some firmware reserved area. + */ + if (amdgpu_sriov_vf(adev)) { + adev->mman.stolen_reserved_offset = 0x100000; + adev->mman.stolen_reserved_size = 0x600000; + } + break; case CHIP_RAVEN: case CHIP_RENOIR: adev->mman.keep_stolen_vga_memory = true; From bd4b9bb77956639e6d9618ed306cb2264c69ba49 Mon Sep 17 00:00:00 2001 From: Julia Lawall <Julia.Lawall@inria.fr> Date: Mon, 14 Mar 2022 12:53:25 +0100 Subject: [PATCH 58/65] drm/amd/pm: fix typos in comments Various spelling mistakes in comments. Detected with the help of Coccinelle. Signed-off-by: Julia Lawall <Julia.Lawall@inria.fr> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index cbbbd4079249e..5cd67ddf84956 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -1870,7 +1870,7 @@ static ssize_t amdgpu_set_smartshift_bias(struct device *dev, amdgpu_smartshift_bias = bias; r = count; - /* TODO: upadte bias level with SMU message */ + /* TODO: update bias level with SMU message */ out: pm_runtime_mark_last_busy(ddev->dev); From 58398727e6f4955f2781e93517b8f0a3e8f22e75 Mon Sep 17 00:00:00 2001 From: Julia Lawall <Julia.Lawall@inria.fr> Date: Mon, 14 Mar 2022 12:53:53 +0100 Subject: [PATCH 59/65] drm/amdgpu: fix typos in comments Various spelling mistakes in comments. Detected with the help of Coccinelle. Signed-off-by: Julia Lawall <Julia.Lawall@inria.fr> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index fe660a8e150f8..970b065e9a6b1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -340,7 +340,7 @@ static void amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev, if (free_vram >= 128 * 1024 * 1024 || free_vram >= total_vram / 8) { s64 min_us; - /* Be more aggresive on dGPUs. Try to fill a portion of free + /* Be more aggressive on dGPUs. Try to fill a portion of free * VRAM now. */ if (!(adev->flags & AMD_IS_APU)) @@ -1280,7 +1280,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, continue; /* - * Work around dma_resv shortcommings by wrapping up the + * Work around dma_resv shortcomings by wrapping up the * submission in a dma_fence_chain and add it as exclusive * fence. */ From 28b7382621f0a83f1db795f36ee0fee6f66c10e9 Mon Sep 17 00:00:00 2001 From: Julia Lawall <Julia.Lawall@inria.fr> Date: Mon, 14 Mar 2022 12:53:47 +0100 Subject: [PATCH 60/65] drm/amdgpu/dc: fix typos in comments Various spelling mistakes in comments. Detected with the help of Coccinelle. Signed-off-by: Julia Lawall <Julia.Lawall@inria.fr> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/bios/command_table.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c index ad13e4e36d779..0e36cd800fc90 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c @@ -456,7 +456,7 @@ static enum bp_result transmitter_control_v2( if ((CONNECTOR_ID_DUAL_LINK_DVII == connector_id) || (CONNECTOR_ID_DUAL_LINK_DVID == connector_id)) /* on INIT this bit should be set according to the - * phisycal connector + * physical connector * Bit0: dual link connector flag * =0 connector is single link connector * =1 connector is dual link connector @@ -468,7 +468,7 @@ static enum bp_result transmitter_control_v2( cpu_to_le16((uint8_t)cntl->connector_obj_id.id); break; case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS: - /* votage swing and pre-emphsis */ + /* voltage swing and pre-emphsis */ params.asMode.ucLaneSel = (uint8_t)cntl->lane_select; params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings; break; @@ -2120,7 +2120,7 @@ static enum bp_result program_clock_v5( memset(¶ms, 0, sizeof(params)); if (!bp->cmd_helper->clock_source_id_to_atom( bp_params->pll_id, &atom_pll_id)) { - BREAK_TO_DEBUGGER(); /* Invalid Inpute!! */ + BREAK_TO_DEBUGGER(); /* Invalid Input!! */ return BP_RESULT_BADINPUT; } From 508a47d434bffde45ca3cdb8ece186f28f9d84bf Mon Sep 17 00:00:00 2001 From: Dan Carpenter <dan.carpenter@oracle.com> Date: Mon, 14 Mar 2022 17:04:05 +0300 Subject: [PATCH 61/65] drm/amd/pm: fix indenting in __smu_cmn_reg_print_error() Smatch complains that the dev_err_ratelimited() is indented one tab more than the surrounding lines. drivers/gpu/drm/amd/amdgpu/../pm/swsmu/smu_cmn.c:174 __smu_cmn_reg_print_error() warn: inconsistent indenting It looks like it's not a bug, just that the indenting needs to be cleaned up. Reviewed-by: Luben Tuikov <luben.tuikov@amd.com> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index ae64d1980f106..b8d0c70ff668c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -164,17 +164,17 @@ static void __smu_cmn_reg_print_error(struct smu_context *smu, switch (reg_c2pmsg_90) { case SMU_RESP_NONE: { - if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 5)) { - msg_idx = RREG32_SOC15(MP1, 0, mmMP1_C2PMSG_2); - prm = RREG32_SOC15(MP1, 0, mmMP1_C2PMSG_34); - } else { - msg_idx = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66); - prm = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82); - } + if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 5)) { + msg_idx = RREG32_SOC15(MP1, 0, mmMP1_C2PMSG_2); + prm = RREG32_SOC15(MP1, 0, mmMP1_C2PMSG_34); + } else { + msg_idx = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66); + prm = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82); + } dev_err_ratelimited(adev->dev, "SMU: I'm not done with your previous command: SMN_C2PMSG_66:0x%08X SMN_C2PMSG_82:0x%08X", msg_idx, prm); - } + } break; case SMU_RESP_OK: /* The SMU executed the command. It completed with a From 1cbd78879b5f889355b2a6343ea5db7e633438b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 18 Feb 2022 12:03:43 +0200 Subject: [PATCH 62/65] drm/amdgpu: Remove pointless on stack mode copies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These on stack copies of the modes appear to be pointless. Just look at the originals directly. Cc: Harry Wentland <harry.wentland@amd.com> Cc: Leo Li <sunpeng.li@amd.com> Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Cc: Alex Deucher <alexander.deucher@amd.com> Cc: amd-gfx@lists.freedesktop.org Cc: Nikola Cornij <nikola.cornij@amd.com> Cc: Aurabindo Pillai <aurabindo.pillai@amd.com> Reviewed-by: Harry Wentland <harry.wentland@amd.com> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index da9628a0212ed..234af77915aa6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -10181,27 +10181,27 @@ static bool is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state, struct drm_crtc_state *new_crtc_state) { - struct drm_display_mode old_mode, new_mode; + const struct drm_display_mode *old_mode, *new_mode; if (!old_crtc_state || !new_crtc_state) return false; - old_mode = old_crtc_state->mode; - new_mode = new_crtc_state->mode; - - if (old_mode.clock == new_mode.clock && - old_mode.hdisplay == new_mode.hdisplay && - old_mode.vdisplay == new_mode.vdisplay && - old_mode.htotal == new_mode.htotal && - old_mode.vtotal != new_mode.vtotal && - old_mode.hsync_start == new_mode.hsync_start && - old_mode.vsync_start != new_mode.vsync_start && - old_mode.hsync_end == new_mode.hsync_end && - old_mode.vsync_end != new_mode.vsync_end && - old_mode.hskew == new_mode.hskew && - old_mode.vscan == new_mode.vscan && - (old_mode.vsync_end - old_mode.vsync_start) == - (new_mode.vsync_end - new_mode.vsync_start)) + old_mode = &old_crtc_state->mode; + new_mode = &new_crtc_state->mode; + + if (old_mode->clock == new_mode->clock && + old_mode->hdisplay == new_mode->hdisplay && + old_mode->vdisplay == new_mode->vdisplay && + old_mode->htotal == new_mode->htotal && + old_mode->vtotal != new_mode->vtotal && + old_mode->hsync_start == new_mode->hsync_start && + old_mode->vsync_start != new_mode->vsync_start && + old_mode->hsync_end == new_mode->hsync_end && + old_mode->vsync_end != new_mode->vsync_end && + old_mode->hskew == new_mode->hskew && + old_mode->vscan == new_mode->vscan && + (old_mode->vsync_end - old_mode->vsync_start) == + (new_mode->vsync_end - new_mode->vsync_start)) return true; return false; From 07d01469325c87aef4ab02ad4ec31d73321665ee Mon Sep 17 00:00:00 2001 From: Paul Menzel <pmenzel@molgen.mpg.de> Date: Tue, 15 Mar 2022 10:29:36 +0100 Subject: [PATCH 63/65] drm/amdgpu: Use ternary operator in `vcn_v1_0_start()` Remove the boilerplate of declaring a variable and using an if else statement by using the ternary operator. Reviewed-by: James Zhu <James.Zhu@amd.com> Signed-off-by: Paul Menzel <pmenzel@molgen.mpg.de> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c index 6c9d5cde61c40..dff54190b96c7 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c @@ -1102,13 +1102,8 @@ static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev) static int vcn_v1_0_start(struct amdgpu_device *adev) { - int r; - - if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) - r = vcn_v1_0_start_dpg_mode(adev); - else - r = vcn_v1_0_start_spg_mode(adev); - return r; + return (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ? + vcn_v1_0_start_dpg_mode(adev) : vcn_v1_0_start_spg_mode(adev); } /** From 606d5877592b0a6f945a68399c870ba9d2a9ff7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 18 Feb 2022 12:03:46 +0200 Subject: [PATCH 64/65] drm/radeon: Use drm_mode_copy() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit struct drm_display_mode embeds a list head, so overwriting the full struct with another one will corrupt the list (if the destination mode is on a list). Use drm_mode_copy() instead which explicitly preserves the list head of the destination mode. Even if we know the destination mode is not on any list using drm_mode_copy() seems decent as it sets a good example. Bad examples of not using it might eventually get copied into code where preserving the list head actually matters. Obviously one case not covered here is when the mode itself is embedded in a larger structure and the whole structure is copied. But if we are careful when copying into modes embedded in structures I think we can be a little more reassured that bogus list heads haven't been propagated in. @is_mode_copy@ @@ drm_mode_copy(...) { ... } @depends on !is_mode_copy@ struct drm_display_mode *mode; expression E, S; @@ ( - *mode = E + drm_mode_copy(mode, &E) | - memcpy(mode, E, S) + drm_mode_copy(mode, E) ) @depends on !is_mode_copy@ struct drm_display_mode mode; expression E; @@ ( - mode = E + drm_mode_copy(&mode, &E) | - memcpy(&mode, E, S) + drm_mode_copy(&mode, E) ) @@ struct drm_display_mode *mode; @@ - &*mode + mode Cc: Alex Deucher <alexander.deucher@amd.com> Cc: amd-gfx@lists.freedesktop.org Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/radeon/radeon_connectors.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index a7925a8290b2f..0cb1345c6ba40 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -777,7 +777,7 @@ static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder, if (mode->type & DRM_MODE_TYPE_PREFERRED) { if (mode->hdisplay != native_mode->hdisplay || mode->vdisplay != native_mode->vdisplay) - memcpy(native_mode, mode, sizeof(*mode)); + drm_mode_copy(native_mode, mode); } } @@ -786,7 +786,7 @@ static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder, list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { if (mode->hdisplay == native_mode->hdisplay && mode->vdisplay == native_mode->vdisplay) { - *native_mode = *mode; + drm_mode_copy(native_mode, mode); drm_mode_set_crtcinfo(native_mode, CRTC_INTERLACE_HALVE_V); DRM_DEBUG_KMS("Determined LVDS native mode details from EDID\n"); break; From 426c89aa203bcec9d9cf6eea36735eafa1b1f099 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 18 Feb 2022 12:03:45 +0200 Subject: [PATCH 65/65] drm/amdgpu: Use drm_mode_copy() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit struct drm_display_mode embeds a list head, so overwriting the full struct with another one will corrupt the list (if the destination mode is on a list). Use drm_mode_copy() instead which explicitly preserves the list head of the destination mode. Even if we know the destination mode is not on any list using drm_mode_copy() seems decent as it sets a good example. Bad examples of not using it might eventually get copied into code where preserving the list head actually matters. Obviously one case not covered here is when the mode itself is embedded in a larger structure and the whole structure is copied. But if we are careful when copying into modes embedded in structures I think we can be a little more reassured that bogus list heads haven't been propagated in. @is_mode_copy@ @@ drm_mode_copy(...) { ... } @depends on !is_mode_copy@ struct drm_display_mode *mode; expression E, S; @@ ( - *mode = E + drm_mode_copy(mode, &E) | - memcpy(mode, E, S) + drm_mode_copy(mode, E) ) @depends on !is_mode_copy@ struct drm_display_mode mode; expression E; @@ ( - mode = E + drm_mode_copy(&mode, &E) | - memcpy(&mode, E, S) + drm_mode_copy(&mode, E) ) @@ struct drm_display_mode *mode; @@ - &*mode + mode Cc: Alex Deucher <alexander.deucher@amd.com> Cc: Harry Wentland <harry.wentland@amd.com> Cc: Leo Li <sunpeng.li@amd.com> Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Cc: amd-gfx@lists.freedesktop.org Reviewed-by: Harry Wentland <harry.wentland@amd.com> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 4 ++-- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index fa20261aa9285..673078faa27a7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -626,7 +626,7 @@ amdgpu_connector_fixup_lcd_native_mode(struct drm_encoder *encoder, if (mode->type & DRM_MODE_TYPE_PREFERRED) { if (mode->hdisplay != native_mode->hdisplay || mode->vdisplay != native_mode->vdisplay) - memcpy(native_mode, mode, sizeof(*mode)); + drm_mode_copy(native_mode, mode); } } @@ -635,7 +635,7 @@ amdgpu_connector_fixup_lcd_native_mode(struct drm_encoder *encoder, list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { if (mode->hdisplay == native_mode->hdisplay && mode->vdisplay == native_mode->vdisplay) { - *native_mode = *mode; + drm_mode_copy(native_mode, mode); drm_mode_set_crtcinfo(native_mode, CRTC_INTERLACE_HALVE_V); DRM_DEBUG_KMS("Determined LVDS native mode details from EDID\n"); break; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 234af77915aa6..b30656959fd86 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -6360,7 +6360,7 @@ get_highest_refresh_rate_mode(struct amdgpu_dm_connector *aconnector, } } - aconnector->freesync_vid_base = *m_pref; + drm_mode_copy(&aconnector->freesync_vid_base, m_pref); return m_pref; } @@ -6473,8 +6473,8 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, recalculate_timing = is_freesync_video_mode(&mode, aconnector); if (recalculate_timing) { freesync_mode = get_highest_refresh_rate_mode(aconnector, false); - saved_mode = mode; - mode = *freesync_mode; + drm_mode_copy(&saved_mode, &mode); + drm_mode_copy(&mode, freesync_mode); } else { decide_crtc_timing_for_drm_display_mode( &mode, preferred_mode, scale);