[PATCH] drm/amd/pm: workaround for audio noise issue

Alex Deucher alexdeucher at gmail.com
Thu Mar 11 04:43:32 UTC 2021


On Wed, Mar 10, 2021 at 11:27 PM Kenneth Feng <kenneth.feng at amd.com> wrote:
>
> On some Intel platforms, audio noise can be detected due to
> high pcie speed switch latency.
> This patch leaverages ppfeaturemask to fix to the highest pcie
> speed then disable pcie switching.

You may want a follow up patch to check the vendor of the pcie root
port in amdgpu_device_get_pcie_info() and change the ppfeaturemask in
that case.

Alex

>
> Signed-off-by: Kenneth Feng <kenneth.feng at amd.com>
> ---
>  .../drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c   | 54 ++++++++++++++
>  .../drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c | 74 ++++++++++++++++---
>  .../drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c | 25 +++++++
>  .../drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c | 26 +++++++
>  4 files changed, 168 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
> index a58f92249c53..54bbee310e57 100644
> --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
> +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
> @@ -587,6 +587,48 @@ static int smu7_force_switch_to_arbf0(struct pp_hwmgr *hwmgr)
>                         tmp, MC_CG_ARB_FREQ_F0);
>  }
>
> +static uint16_t smu7_override_pcie_speed(struct pp_hwmgr *hwmgr)
> +{
> +       struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
> +       uint16_t pcie_gen = 0;
> +
> +       if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4 &&
> +           adev->pm.pcie_gen_mask & CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN4)
> +               pcie_gen = 3;
> +       else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3 &&
> +               adev->pm.pcie_gen_mask & CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3)
> +               pcie_gen = 2;
> +       else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 &&
> +               adev->pm.pcie_gen_mask & CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2)
> +               pcie_gen = 1;
> +       else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 &&
> +               adev->pm.pcie_gen_mask & CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1)
> +               pcie_gen = 0;
> +
> +       return pcie_gen;
> +}
> +
> +static uint16_t smu7_override_pcie_width(struct pp_hwmgr *hwmgr)
> +{
> +       struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
> +       uint16_t pcie_width = 0;
> +
> +       if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16)
> +               pcie_width = 16;
> +       else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12)
> +               pcie_width = 12;
> +       else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8)
> +               pcie_width = 8;
> +       else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4)
> +               pcie_width = 4;
> +       else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2)
> +               pcie_width = 2;
> +       else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1)
> +               pcie_width = 1;
> +
> +       return pcie_width;
> +}
> +
>  static int smu7_setup_default_pcie_table(struct pp_hwmgr *hwmgr)
>  {
>         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
> @@ -683,6 +725,11 @@ static int smu7_setup_default_pcie_table(struct pp_hwmgr *hwmgr)
>                                         PP_Min_PCIEGen),
>                         get_pcie_lane_support(data->pcie_lane_cap,
>                                         PP_Max_PCIELane));
> +
> +               if (data->pcie_dpm_key_disabled)
> +                       phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table,
> +                               data->dpm_table.pcie_speed_table.count,
> +                               smu7_override_pcie_speed(hwmgr), smu7_override_pcie_width(hwmgr));
>         }
>         return 0;
>  }
> @@ -1248,6 +1295,13 @@ static int smu7_start_dpm(struct pp_hwmgr *hwmgr)
>                                                 NULL)),
>                                 "Failed to enable pcie DPM during DPM Start Function!",
>                                 return -EINVAL);
> +       } else {
> +               PP_ASSERT_WITH_CODE(
> +                               (0 == smum_send_msg_to_smc(hwmgr,
> +                                               PPSMC_MSG_PCIeDPM_Disable,
> +                                               NULL)),
> +                               "Failed to disble pcie DPM during DPM Start Function!",
> +                               return -EINVAL);
>         }
>
>         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
> diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
> index 408b35866704..f5a32654cde7 100644
> --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
> +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
> @@ -54,6 +54,9 @@
>  #include "smuio/smuio_9_0_offset.h"
>  #include "smuio/smuio_9_0_sh_mask.h"
>
> +#define smnPCIE_LC_SPEED_CNTL                  0x11140290
> +#define smnPCIE_LC_LINK_WIDTH_CNTL             0x11140288
> +
>  #define HBM_MEMORY_CHANNEL_WIDTH    128
>
>  static const uint32_t channel_number[] = {1, 2, 0, 4, 0, 8, 0, 16, 2};
> @@ -443,8 +446,7 @@ static void vega10_init_dpm_defaults(struct pp_hwmgr *hwmgr)
>         if (PP_CAP(PHM_PlatformCaps_VCEDPM))
>                 data->smu_features[GNLD_DPM_VCE].supported = true;
>
> -       if (!data->registry_data.pcie_dpm_key_disabled)
> -               data->smu_features[GNLD_DPM_LINK].supported = true;
> +       data->smu_features[GNLD_DPM_LINK].supported = true;
>
>         if (!data->registry_data.dcefclk_dpm_key_disabled)
>                 data->smu_features[GNLD_DPM_DCEFCLK].supported = true;
> @@ -1544,6 +1546,13 @@ static int vega10_override_pcie_parameters(struct pp_hwmgr *hwmgr)
>                         pp_table->PcieLaneCount[i] = pcie_width;
>         }
>
> +       if (data->registry_data.pcie_dpm_key_disabled) {
> +               for (i = 0; i < NUM_LINK_LEVELS; i++) {
> +                       pp_table->PcieGenSpeed[i] = pcie_gen;
> +                       pp_table->PcieLaneCount[i] = pcie_width;
> +               }
> +       }
> +
>         return 0;
>  }
>
> @@ -2966,6 +2975,14 @@ static int vega10_start_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap)
>                 }
>         }
>
> +       if (data->registry_data.pcie_dpm_key_disabled) {
> +               PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
> +                               false, data->smu_features[GNLD_DPM_LINK].smu_feature_bitmap),
> +               "Attempt to Disable Link DPM feature Failed!", return -EINVAL);
> +               data->smu_features[GNLD_DPM_LINK].enabled = false;
> +               data->smu_features[GNLD_DPM_LINK].supported = false;
> +       }
> +
>         return 0;
>  }
>
> @@ -4584,6 +4601,24 @@ static int vega10_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfe
>         return 0;
>  }
>
> +static int vega10_get_current_pcie_link_width_level(struct pp_hwmgr *hwmgr)
> +{
> +       struct amdgpu_device *adev = hwmgr->adev;
> +
> +       return (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) &
> +               PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK)
> +               >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT;
> +}
> +
> +static int vega10_get_current_pcie_link_speed_level(struct pp_hwmgr *hwmgr)
> +{
> +       struct amdgpu_device *adev = hwmgr->adev;
> +
> +       return (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
> +               PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
> +               >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT;
> +}
> +
>  static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
>                 enum pp_clock_type type, char *buf)
>  {
> @@ -4592,8 +4627,9 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
>         struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
>         struct vega10_single_dpm_table *soc_table = &(data->dpm_table.soc_table);
>         struct vega10_single_dpm_table *dcef_table = &(data->dpm_table.dcef_table);
> -       struct vega10_pcie_table *pcie_table = &(data->dpm_table.pcie_table);
>         struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep = NULL;
> +       uint32_t gen_speed, lane_width, current_gen_speed, current_lane_width;
> +       PPTable_t *pptable = &(data->smc_state_table.pp_table);
>
>         int i, now, size = 0, count = 0;
>
> @@ -4650,15 +4686,31 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
>                                         "*" : "");
>                 break;
>         case PP_PCIE:
> -               smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentLinkIndex, &now);
> -
> -               for (i = 0; i < pcie_table->count; i++)
> -                       size += sprintf(buf + size, "%d: %s %s\n", i,
> -                                       (pcie_table->pcie_gen[i] == 0) ? "2.5GT/s, x1" :
> -                                       (pcie_table->pcie_gen[i] == 1) ? "5.0GT/s, x16" :
> -                                       (pcie_table->pcie_gen[i] == 2) ? "8.0GT/s, x16" : "",
> -                                       (i == now) ? "*" : "");
> +               current_gen_speed =
> +                       vega10_get_current_pcie_link_speed_level(hwmgr);
> +               current_lane_width =
> +                       vega10_get_current_pcie_link_width_level(hwmgr);
> +               for (i = 0; i < NUM_LINK_LEVELS; i++) {
> +                       gen_speed = pptable->PcieGenSpeed[i];
> +                       lane_width = pptable->PcieLaneCount[i];
> +
> +                       size += sprintf(buf + size, "%d: %s %s %s\n", i,
> +                                       (gen_speed == 0) ? "2.5GT/s," :
> +                                       (gen_speed == 1) ? "5.0GT/s," :
> +                                       (gen_speed == 2) ? "8.0GT/s," :
> +                                       (gen_speed == 3) ? "16.0GT/s," : "",
> +                                       (lane_width == 1) ? "x1" :
> +                                       (lane_width == 2) ? "x2" :
> +                                       (lane_width == 3) ? "x4" :
> +                                       (lane_width == 4) ? "x8" :
> +                                       (lane_width == 5) ? "x12" :
> +                                       (lane_width == 6) ? "x16" : "",
> +                                       (current_gen_speed == gen_speed) &&
> +                                       (current_lane_width == lane_width) ?
> +                                       "*" : "");
> +               }
>                 break;
> +
>         case OD_SCLK:
>                 if (hwmgr->od_enabled) {
>                         size = sprintf(buf, "%s:\n", "OD_SCLK");
> diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c
> index 196ac2a4d145..f3d37acbf663 100644
> --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c
> +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c
> @@ -133,6 +133,8 @@ static void vega12_set_default_registry_data(struct pp_hwmgr *hwmgr)
>         data->registry_data.auto_wattman_debug = 0;
>         data->registry_data.auto_wattman_sample_period = 100;
>         data->registry_data.auto_wattman_threshold = 50;
> +       data->registry_data.pcie_dpm_key_disabled =
> +                       hwmgr->feature_mask & PP_PCIE_DPM_MASK ? false : true;

You don't need the false : true.  You can just do:
data->registry_data.pcie_dpm_key_disabled = !(hwmgr->feature_mask &
PP_PCIE_DPM_MASK);
Same comment on the other cases of this.


>  }
>
>  static int vega12_set_features_platform_caps(struct pp_hwmgr *hwmgr)
> @@ -539,6 +541,29 @@ static int vega12_override_pcie_parameters(struct pp_hwmgr *hwmgr)
>                 pp_table->PcieLaneCount[i] = pcie_width_arg;
>         }
>
> +       /* override to the highest if it's disabled from ppfeaturmask */
> +       if (data->registry_data.pcie_dpm_key_disabled) {
> +               for (i = 0; i < NUM_LINK_LEVELS; i++) {
> +                       smu_pcie_arg = (i << 16) | (pcie_gen << 8) | pcie_width;
> +                       ret = smum_send_msg_to_smc_with_parameter(hwmgr,
> +                               PPSMC_MSG_OverridePcieParameters, smu_pcie_arg,
> +                               NULL);
> +                       PP_ASSERT_WITH_CODE(!ret,
> +                               "[OverridePcieParameters] Attempt to override pcie params failed!",
> +                               return ret);
> +
> +                       pp_table->PcieGenSpeed[i] = pcie_gen;
> +                       pp_table->PcieLaneCount[i] = pcie_width;
> +               }
> +               ret = vega12_enable_smc_features(hwmgr,
> +                               false,
> +                               data->smu_features[GNLD_DPM_LINK].smu_feature_bitmap);
> +               PP_ASSERT_WITH_CODE(!ret,
> +                               "Attempt to Disable DPM LINK Failed!",
> +                               return ret);
> +               data->smu_features[GNLD_DPM_LINK].enabled = false;
> +               data->smu_features[GNLD_DPM_LINK].supported = false;
> +       }
>         return 0;
>  }
>
> diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c
> index 78bbd4d666f2..2df637727d1b 100644
> --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c
> +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c
> @@ -171,6 +171,8 @@ static void vega20_set_default_registry_data(struct pp_hwmgr *hwmgr)
>         data->registry_data.gfxoff_controlled_by_driver = 1;
>         data->gfxoff_allowed = false;
>         data->counter_gfxoff = 0;
> +       data->registry_data.pcie_dpm_key_disabled =
> +                       hwmgr->feature_mask & PP_PCIE_DPM_MASK ? false : true;
>  }
>
>  static int vega20_set_features_platform_caps(struct pp_hwmgr *hwmgr)
> @@ -884,6 +886,30 @@ static int vega20_override_pcie_parameters(struct pp_hwmgr *hwmgr)
>                 pp_table->PcieLaneCount[i] = pcie_width_arg;
>         }
>
> +       /* override to the highest if it's disabled from ppfeaturmask */
> +       if (data->registry_data.pcie_dpm_key_disabled) {
> +               for (i = 0; i < NUM_LINK_LEVELS; i++) {
> +                       smu_pcie_arg = (i << 16) | (pcie_gen << 8) | pcie_width;
> +                       ret = smum_send_msg_to_smc_with_parameter(hwmgr,
> +                               PPSMC_MSG_OverridePcieParameters, smu_pcie_arg,
> +                               NULL);
> +                       PP_ASSERT_WITH_CODE(!ret,
> +                               "[OverridePcieParameters] Attempt to override pcie params failed!",
> +                               return ret);
> +
> +                       pp_table->PcieGenSpeed[i] = pcie_gen;
> +                       pp_table->PcieLaneCount[i] = pcie_width;
> +               }
> +               ret = vega20_enable_smc_features(hwmgr,
> +                               false,
> +                               data->smu_features[GNLD_DPM_LINK].smu_feature_bitmap);
> +               PP_ASSERT_WITH_CODE(!ret,
> +                               "Attempt to Disable DPM LINK Failed!",
> +                               return ret);
> +               data->smu_features[GNLD_DPM_LINK].enabled = false;
> +               data->smu_features[GNLD_DPM_LINK].supported = false;
> +       }
> +
>         return 0;
>  }
>
> --
> 2.17.1
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx


More information about the amd-gfx mailing list