aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c')
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c737
1 files changed, 603 insertions, 134 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 35629140fc7a..82676c086ce4 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
@@ -49,6 +49,8 @@
#include "processpptables.h"
#include "pp_thermal.h"
#include "smu7_baco.h"
+#include "smu7_smumgr.h"
+#include "polaris10_smumgr.h"
#include "ivsrcid/ivsrcid_vislands30.h"
@@ -97,6 +99,9 @@ static struct profile_mode_setting smu7_profiling[7] =
#define PWR_SVI2_PLANE1_LOAD__PSI1__SHIFT 0x00000005
#define PWR_SVI2_PLANE1_LOAD__PSI0_EN__SHIFT 0x00000006
+#define STRAP_EVV_REVISION_MSB 2211
+#define STRAP_EVV_REVISION_LSB 2208
+
/** Values for the CG_THERMAL_CTRL::DPM_EVENT_SRC field. */
enum DPM_EVENT_SRC {
DPM_EVENT_SRC_ANALOG = 0,
@@ -106,9 +111,66 @@ enum DPM_EVENT_SRC {
DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL = 4
};
+#define ixDIDT_SQ_EDC_CTRL 0x0013
+#define ixDIDT_SQ_EDC_THRESHOLD 0x0014
+#define ixDIDT_SQ_EDC_STALL_PATTERN_1_2 0x0015
+#define ixDIDT_SQ_EDC_STALL_PATTERN_3_4 0x0016
+#define ixDIDT_SQ_EDC_STALL_PATTERN_5_6 0x0017
+#define ixDIDT_SQ_EDC_STALL_PATTERN_7 0x0018
+
+#define ixDIDT_TD_EDC_CTRL 0x0053
+#define ixDIDT_TD_EDC_THRESHOLD 0x0054
+#define ixDIDT_TD_EDC_STALL_PATTERN_1_2 0x0055
+#define ixDIDT_TD_EDC_STALL_PATTERN_3_4 0x0056
+#define ixDIDT_TD_EDC_STALL_PATTERN_5_6 0x0057
+#define ixDIDT_TD_EDC_STALL_PATTERN_7 0x0058
+
+#define ixDIDT_TCP_EDC_CTRL 0x0073
+#define ixDIDT_TCP_EDC_THRESHOLD 0x0074
+#define ixDIDT_TCP_EDC_STALL_PATTERN_1_2 0x0075
+#define ixDIDT_TCP_EDC_STALL_PATTERN_3_4 0x0076
+#define ixDIDT_TCP_EDC_STALL_PATTERN_5_6 0x0077
+#define ixDIDT_TCP_EDC_STALL_PATTERN_7 0x0078
+
+#define ixDIDT_DB_EDC_CTRL 0x0033
+#define ixDIDT_DB_EDC_THRESHOLD 0x0034
+#define ixDIDT_DB_EDC_STALL_PATTERN_1_2 0x0035
+#define ixDIDT_DB_EDC_STALL_PATTERN_3_4 0x0036
+#define ixDIDT_DB_EDC_STALL_PATTERN_5_6 0x0037
+#define ixDIDT_DB_EDC_STALL_PATTERN_7 0x0038
+
+uint32_t DIDTEDCConfig_P12[] = {
+ ixDIDT_SQ_EDC_STALL_PATTERN_1_2,
+ ixDIDT_SQ_EDC_STALL_PATTERN_3_4,
+ ixDIDT_SQ_EDC_STALL_PATTERN_5_6,
+ ixDIDT_SQ_EDC_STALL_PATTERN_7,
+ ixDIDT_SQ_EDC_THRESHOLD,
+ ixDIDT_SQ_EDC_CTRL,
+ ixDIDT_TD_EDC_STALL_PATTERN_1_2,
+ ixDIDT_TD_EDC_STALL_PATTERN_3_4,
+ ixDIDT_TD_EDC_STALL_PATTERN_5_6,
+ ixDIDT_TD_EDC_STALL_PATTERN_7,
+ ixDIDT_TD_EDC_THRESHOLD,
+ ixDIDT_TD_EDC_CTRL,
+ ixDIDT_TCP_EDC_STALL_PATTERN_1_2,
+ ixDIDT_TCP_EDC_STALL_PATTERN_3_4,
+ ixDIDT_TCP_EDC_STALL_PATTERN_5_6,
+ ixDIDT_TCP_EDC_STALL_PATTERN_7,
+ ixDIDT_TCP_EDC_THRESHOLD,
+ ixDIDT_TCP_EDC_CTRL,
+ ixDIDT_DB_EDC_STALL_PATTERN_1_2,
+ ixDIDT_DB_EDC_STALL_PATTERN_3_4,
+ ixDIDT_DB_EDC_STALL_PATTERN_5_6,
+ ixDIDT_DB_EDC_STALL_PATTERN_7,
+ ixDIDT_DB_EDC_THRESHOLD,
+ ixDIDT_DB_EDC_CTRL,
+ 0xFFFFFFFF // End of list
+};
+
static const unsigned long PhwVIslands_Magic = (unsigned long)(PHM_VIslands_Magic);
static int smu7_force_clock_level(struct pp_hwmgr *hwmgr,
enum pp_clock_type type, uint32_t mask);
+static int smu7_notify_has_display(struct pp_hwmgr *hwmgr);
static struct smu7_power_state *cast_phw_smu7_power_state(
struct pp_hw_power_state *hw_ps)
@@ -131,10 +193,10 @@ static const struct smu7_power_state *cast_const_phw_smu7_power_state(
}
/**
- * Find the MC microcode version and store it in the HwMgr struct
+ * smu7_get_mc_microcode_version - Find the MC microcode version and store it in the HwMgr struct
*
- * @param hwmgr the address of the powerplay hardware manager.
- * @return always 0
+ * @hwmgr: the address of the powerplay hardware manager.
+ * Return: always 0
*/
static int smu7_get_mc_microcode_version(struct pp_hwmgr *hwmgr)
{
@@ -171,14 +233,15 @@ static int smu7_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr)
}
/**
-* Enable voltage control
-*
-* @param pHwMgr the address of the powerplay hardware manager.
-* @return always PP_Result_OK
-*/
+ * smu7_enable_smc_voltage_controller - Enable voltage control
+ *
+ * @hwmgr the address of the powerplay hardware manager.
+ * Return: always PP_Result_OK
+ */
static int smu7_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr)
{
- if (hwmgr->chip_id == CHIP_VEGAM) {
+ if (hwmgr->chip_id >= CHIP_POLARIS10 &&
+ hwmgr->chip_id <= CHIP_VEGAM) {
PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device,
CGS_IND_REG__SMC, PWR_SVI2_PLANE1_LOAD, PSI1, 0);
PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device,
@@ -192,10 +255,10 @@ static int smu7_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr)
}
/**
-* Checks if we want to support voltage control
-*
-* @param hwmgr the address of the powerplay hardware manager.
-*/
+ * smu7_voltage_control - Checks if we want to support voltage control
+ *
+ * @hwmgr: the address of the powerplay hardware manager.
+ */
static bool smu7_voltage_control(const struct pp_hwmgr *hwmgr)
{
const struct smu7_hwmgr *data =
@@ -205,11 +268,11 @@ static bool smu7_voltage_control(const struct pp_hwmgr *hwmgr)
}
/**
-* Enable voltage control
-*
-* @param hwmgr the address of the powerplay hardware manager.
-* @return always 0
-*/
+ * smu7_enable_voltage_control - Enable voltage control
+ *
+ * @hwmgr: the address of the powerplay hardware manager.
+ * Return: always 0
+ */
static int smu7_enable_voltage_control(struct pp_hwmgr *hwmgr)
{
/* enable voltage control */
@@ -243,11 +306,11 @@ static int phm_get_svi2_voltage_table_v0(pp_atomctrl_voltage_table *voltage_tabl
/**
-* Create Voltage Tables.
-*
-* @param hwmgr the address of the powerplay hardware manager.
-* @return always 0
-*/
+ * smu7_construct_voltage_tables - Create Voltage Tables.
+ *
+ * @hwmgr: the address of the powerplay hardware manager.
+ * Return: always 0
+ */
static int smu7_construct_voltage_tables(struct pp_hwmgr *hwmgr)
{
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
@@ -355,11 +418,11 @@ static int smu7_construct_voltage_tables(struct pp_hwmgr *hwmgr)
}
/**
-* Programs static screed detection parameters
-*
-* @param hwmgr the address of the powerplay hardware manager.
-* @return always 0
-*/
+ * smu7_program_static_screen_threshold_parameters - Programs static screed detection parameters
+ *
+ * @hwmgr: the address of the powerplay hardware manager.
+ * Return: always 0
+ */
static int smu7_program_static_screen_threshold_parameters(
struct pp_hwmgr *hwmgr)
{
@@ -378,11 +441,11 @@ static int smu7_program_static_screen_threshold_parameters(
}
/**
-* Setup display gap for glitch free memory clock switching.
-*
-* @param hwmgr the address of the powerplay hardware manager.
-* @return always 0
-*/
+ * smu7_enable_display_gap - Setup display gap for glitch free memory clock switching.
+ *
+ * @hwmgr: the address of the powerplay hardware manager.
+ * Return: always 0
+ */
static int smu7_enable_display_gap(struct pp_hwmgr *hwmgr)
{
uint32_t display_gap =
@@ -402,11 +465,11 @@ static int smu7_enable_display_gap(struct pp_hwmgr *hwmgr)
}
/**
-* Programs activity state transition voting clients
-*
-* @param hwmgr the address of the powerplay hardware manager.
-* @return always 0
-*/
+ * smu7_program_voting_clients - Programs activity state transition voting clients
+ *
+ * @hwmgr: the address of the powerplay hardware manager.
+ * Return: always 0
+ */
static int smu7_program_voting_clients(struct pp_hwmgr *hwmgr)
{
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
@@ -497,12 +560,12 @@ static int smu7_reset_to_default(struct pp_hwmgr *hwmgr)
}
/**
-* Initial switch from ARB F0->F1
-*
-* @param hwmgr the address of the powerplay hardware manager.
-* @return always 0
-* This function is to be called from the SetPowerState table.
-*/
+ * smu7_initial_switch_from_arbf0_to_f1 - Initial switch from ARB F0->F1
+ *
+ * @hwmgr: the address of the powerplay hardware manager.
+ * Return: always 0
+ * This function is to be called from the SetPowerState table.
+ */
static int smu7_initial_switch_from_arbf0_to_f1(struct pp_hwmgr *hwmgr)
{
return smu7_copy_and_switch_arb_sets(hwmgr,
@@ -1088,7 +1151,8 @@ static int smu7_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
/* enable SCLK dpm */
if (!data->sclk_dpm_key_disabled) {
- if (hwmgr->chip_id == CHIP_VEGAM)
+ if (hwmgr->chip_id >= CHIP_POLARIS10 &&
+ hwmgr->chip_id <= CHIP_VEGAM)
smu7_disable_sclk_vce_handshake(hwmgr);
PP_ASSERT_WITH_CODE(
@@ -1109,7 +1173,11 @@ static int smu7_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
"Failed to enable MCLK DPM during DPM Start Function!",
return -EINVAL);
- if (hwmgr->chip_family != CHIP_VEGAM)
+ if ((hwmgr->chip_family == AMDGPU_FAMILY_CI) ||
+ (hwmgr->chip_id == CHIP_POLARIS10) ||
+ (hwmgr->chip_id == CHIP_POLARIS11) ||
+ (hwmgr->chip_id == CHIP_POLARIS12) ||
+ (hwmgr->chip_id == CHIP_TONGA))
PHM_WRITE_FIELD(hwmgr->device, MC_SEQ_CNTL_3, CAC_EN, 0x1);
@@ -1331,6 +1399,50 @@ static int smu7_pcie_performance_request(struct pp_hwmgr *hwmgr)
return 0;
}
+static int smu7_program_edc_didt_registers(struct pp_hwmgr *hwmgr,
+ uint32_t *cac_config_regs,
+ AtomCtrl_EDCLeakgeTable *edc_leakage_table)
+{
+ uint32_t data, i = 0;
+
+ while (cac_config_regs[i] != 0xFFFFFFFF) {
+ data = edc_leakage_table->DIDT_REG[i];
+ cgs_write_ind_register(hwmgr->device,
+ CGS_IND_REG__DIDT,
+ cac_config_regs[i],
+ data);
+ i++;
+ }
+
+ return 0;
+}
+
+static int smu7_populate_edc_leakage_registers(struct pp_hwmgr *hwmgr)
+{
+ struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
+ int ret = 0;
+
+ if (!data->disable_edc_leakage_controller &&
+ data->edc_hilo_leakage_offset_from_vbios.usEdcDidtLoDpm7TableOffset &&
+ data->edc_hilo_leakage_offset_from_vbios.usEdcDidtHiDpm7TableOffset) {
+ ret = smu7_program_edc_didt_registers(hwmgr,
+ DIDTEDCConfig_P12,
+ &data->edc_leakage_table);
+ if (ret)
+ return ret;
+
+ ret = smum_send_msg_to_smc(hwmgr,
+ (PPSMC_Msg)PPSMC_MSG_EnableEDCController,
+ NULL);
+ } else {
+ ret = smum_send_msg_to_smc(hwmgr,
+ (PPSMC_Msg)PPSMC_MSG_DisableEDCController,
+ NULL);
+ }
+
+ return ret;
+}
+
static int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
{
int tmp_result = 0;
@@ -1395,7 +1507,21 @@ static int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
PP_ASSERT_WITH_CODE((0 == tmp_result),
"Failed to enable VR hot GPIO interrupt!", result = tmp_result);
- smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_NoDisplay, NULL);
+ if (hwmgr->chip_id >= CHIP_POLARIS10 &&
+ hwmgr->chip_id <= CHIP_VEGAM) {
+ tmp_result = smu7_notify_has_display(hwmgr);
+ PP_ASSERT_WITH_CODE((0 == tmp_result),
+ "Failed to enable display setting!", result = tmp_result);
+ } else {
+ smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_NoDisplay, NULL);
+ }
+
+ if (hwmgr->chip_id >= CHIP_POLARIS10 &&
+ hwmgr->chip_id <= CHIP_VEGAM) {
+ tmp_result = smu7_populate_edc_leakage_registers(hwmgr);
+ PP_ASSERT_WITH_CODE((0 == tmp_result),
+ "Failed to populate edc leakage registers!", result = tmp_result);
+ }
tmp_result = smu7_enable_sclk_control(hwmgr);
PP_ASSERT_WITH_CODE((0 == tmp_result),
@@ -1558,6 +1684,8 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
struct phm_ppt_v1_information *table_info =
(struct phm_ppt_v1_information *)(hwmgr->pptable);
struct amdgpu_device *adev = hwmgr->adev;
+ uint8_t tmp1, tmp2;
+ uint16_t tmp3 = 0;
data->dll_default_on = false;
data->mclk_dpm0_activity_target = 0xa;
@@ -1612,19 +1740,6 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
- if (hwmgr->chip_id == CHIP_POLARIS12 || hwmgr->is_kicker) {
- uint8_t tmp1, tmp2;
- uint16_t tmp3 = 0;
- atomctrl_get_svi2_info(hwmgr, VOLTAGE_TYPE_VDDC, &tmp1, &tmp2,
- &tmp3);
- tmp3 = (tmp3 >> 5) & 0x3;
- data->vddc_phase_shed_control = ((tmp3 << 1) | (tmp3 >> 1)) & 0x3;
- } else if (hwmgr->chip_family == AMDGPU_FAMILY_CI) {
- data->vddc_phase_shed_control = 1;
- } else {
- data->vddc_phase_shed_control = 0;
- }
-
if (hwmgr->chip_id == CHIP_HAWAII) {
data->thermal_temp_setting.temperature_low = 94500;
data->thermal_temp_setting.temperature_high = 95000;
@@ -1683,6 +1798,22 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_ControlVDDCI);
+ data->vddc_phase_shed_control = 1;
+ if ((hwmgr->chip_id == CHIP_POLARIS12) ||
+ ASICID_IS_P20(adev->pdev->device, adev->pdev->revision) ||
+ ASICID_IS_P21(adev->pdev->device, adev->pdev->revision) ||
+ ASICID_IS_P30(adev->pdev->device, adev->pdev->revision) ||
+ ASICID_IS_P31(adev->pdev->device, adev->pdev->revision)) {
+ if (data->voltage_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) {
+ atomctrl_get_svi2_info(hwmgr, VOLTAGE_TYPE_VDDC, &tmp1, &tmp2,
+ &tmp3);
+ tmp3 = (tmp3 >> 5) & 0x3;
+ data->vddc_phase_shed_control = ((tmp3 << 1) | (tmp3 >> 1)) & 0x3;
+ }
+ } else if (hwmgr->chip_family == AMDGPU_FAMILY_CI) {
+ data->vddc_phase_shed_control = 1;
+ }
+
if ((hwmgr->pp_table_version != PP_TABLE_V0) && (hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK)
&& (table_info->cac_dtp_table->usClockStretchAmount != 0))
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
@@ -1704,14 +1835,93 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
if (adev->pg_flags & AMD_PG_SUPPORT_VCE)
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_VCEPowerGating);
+
+ data->disable_edc_leakage_controller = true;
+ if (((adev->asic_type == CHIP_POLARIS10) && hwmgr->is_kicker) ||
+ ((adev->asic_type == CHIP_POLARIS11) && hwmgr->is_kicker) ||
+ (adev->asic_type == CHIP_POLARIS12) ||
+ (adev->asic_type == CHIP_VEGAM))
+ data->disable_edc_leakage_controller = false;
+
+ if (!atomctrl_is_asic_internal_ss_supported(hwmgr)) {
+ phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+ PHM_PlatformCaps_MemorySpreadSpectrumSupport);
+ phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+ PHM_PlatformCaps_EngineSpreadSpectrumSupport);
+ }
+
+ if ((adev->pdev->device == 0x699F) &&
+ (adev->pdev->revision == 0xCF)) {
+ phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+ PHM_PlatformCaps_PowerContainment);
+ data->enable_tdc_limit_feature = false;
+ data->enable_pkg_pwr_tracking_feature = false;
+ data->disable_edc_leakage_controller = true;
+ phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+ PHM_PlatformCaps_ClockStretcher);
+ }
+}
+
+static int smu7_calculate_ro_range(struct pp_hwmgr *hwmgr)
+{
+ struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
+ struct amdgpu_device *adev = hwmgr->adev;
+ uint32_t asicrev1, evv_revision, max = 0, min = 0;
+
+ atomctrl_read_efuse(hwmgr, STRAP_EVV_REVISION_LSB, STRAP_EVV_REVISION_MSB,
+ &evv_revision);
+
+ atomctrl_read_efuse(hwmgr, 568, 579, &asicrev1);
+
+ if (ASICID_IS_P20(adev->pdev->device, adev->pdev->revision) ||
+ ASICID_IS_P30(adev->pdev->device, adev->pdev->revision)) {
+ min = 1200;
+ max = 2500;
+ } else if (ASICID_IS_P21(adev->pdev->device, adev->pdev->revision) ||
+ ASICID_IS_P31(adev->pdev->device, adev->pdev->revision)) {
+ min = 900;
+ max= 2100;
+ } else if (hwmgr->chip_id == CHIP_POLARIS10) {
+ if (adev->pdev->subsystem_vendor == 0x106B) {
+ min = 1000;
+ max = 2300;
+ } else {
+ if (evv_revision == 0) {
+ min = 1000;
+ max = 2300;
+ } else if (evv_revision == 1) {
+ if (asicrev1 == 326) {
+ min = 1200;
+ max = 2500;
+ /* TODO: PATCH RO in VBIOS */
+ } else {
+ min = 1200;
+ max = 2000;
+ }
+ } else if (evv_revision == 2) {
+ min = 1200;
+ max = 2500;
+ }
+ }
+ } else {
+ min = 1100;
+ max = 2100;
+ }
+
+ data->ro_range_minimum = min;
+ data->ro_range_maximum = max;
+
+ /* TODO: PATCH RO in VBIOS here */
+
+ return 0;
}
/**
-* Get Leakage VDDC based on leakage ID.
-*
-* @param hwmgr the address of the powerplay hardware manager.
-* @return always 0
-*/
+ * smu7_get_evv_voltages - Get Leakage VDDC based on leakage ID.
+ *
+ * @hwmgr: the address of the powerplay hardware manager.
+ * Return: always 0
+ */
static int smu7_get_evv_voltages(struct pp_hwmgr *hwmgr)
{
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
@@ -1724,6 +1934,10 @@ static int smu7_get_evv_voltages(struct pp_hwmgr *hwmgr)
(struct phm_ppt_v1_information *)hwmgr->pptable;
struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = NULL;
+ if (hwmgr->chip_id == CHIP_POLARIS10 ||
+ hwmgr->chip_id == CHIP_POLARIS11 ||
+ hwmgr->chip_id == CHIP_POLARIS12)
+ smu7_calculate_ro_range(hwmgr);
for (i = 0; i < SMU7_MAX_LEAKAGE_COUNT; i++) {
vv_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
@@ -1803,11 +2017,11 @@ static int smu7_get_evv_voltages(struct pp_hwmgr *hwmgr)
}
/**
- * Change virtual leakage voltage to actual value.
+ * smu7_patch_ppt_v1_with_vdd_leakage - Change virtual leakage voltage to actual value.
*
- * @param hwmgr the address of the powerplay hardware manager.
- * @param pointer to changing voltage
- * @param pointer to leakage table
+ * @hwmgr: the address of the powerplay hardware manager.
+ * @voltage: pointer to changing voltage
+ * @leakage_table: pointer to leakage table
*/
static void smu7_patch_ppt_v1_with_vdd_leakage(struct pp_hwmgr *hwmgr,
uint16_t *voltage, struct smu7_leakage_voltage *leakage_table)
@@ -1829,13 +2043,13 @@ static void smu7_patch_ppt_v1_with_vdd_leakage(struct pp_hwmgr *hwmgr,
}
/**
-* Patch voltage lookup table by EVV leakages.
-*
-* @param hwmgr the address of the powerplay hardware manager.
-* @param pointer to voltage lookup table
-* @param pointer to leakage table
-* @return always 0
-*/
+ * smu7_patch_lookup_table_with_leakage - Patch voltage lookup table by EVV leakages.
+ *
+ * @hwmgr: the address of the powerplay hardware manager.
+ * @lookup_table: pointer to voltage lookup table
+ * @leakage_table: pointer to leakage table
+ * Return: always 0
+ */
static int smu7_patch_lookup_table_with_leakage(struct pp_hwmgr *hwmgr,
phm_ppt_v1_voltage_lookup_table *lookup_table,
struct smu7_leakage_voltage *leakage_table)
@@ -2087,6 +2301,28 @@ static int smu7_complete_dependency_tables(struct pp_hwmgr *hwmgr)
return result;
}
+static int smu7_find_highest_vddc(struct pp_hwmgr *hwmgr)
+{
+ struct phm_ppt_v1_information *table_info =
+ (struct phm_ppt_v1_information *)(hwmgr->pptable);
+ struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table =
+ table_info->vdd_dep_on_sclk;
+ struct phm_ppt_v1_voltage_lookup_table *lookup_table =
+ table_info->vddc_lookup_table;
+ uint16_t highest_voltage;
+ uint32_t i;
+
+ highest_voltage = allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc;
+
+ for (i = 0; i < lookup_table->count; i++) {
+ if (lookup_table->entries[i].us_vdd < ATOM_VIRTUAL_VOLTAGE_ID0 &&
+ lookup_table->entries[i].us_vdd > highest_voltage)
+ highest_voltage = lookup_table->entries[i].us_vdd;
+ }
+
+ return highest_voltage;
+}
+
static int smu7_set_private_data_based_on_pptable_v1(struct pp_hwmgr *hwmgr)
{
struct phm_ppt_v1_information *table_info =
@@ -2115,8 +2351,12 @@ static int smu7_set_private_data_based_on_pptable_v1(struct pp_hwmgr *hwmgr)
allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk;
table_info->max_clock_voltage_on_ac.mclk =
allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk;
- table_info->max_clock_voltage_on_ac.vddc =
- allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc;
+ if (hwmgr->chip_id >= CHIP_POLARIS10 && hwmgr->chip_id <= CHIP_VEGAM)
+ table_info->max_clock_voltage_on_ac.vddc =
+ smu7_find_highest_vddc(hwmgr);
+ else
+ table_info->max_clock_voltage_on_ac.vddc =
+ allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc;
table_info->max_clock_voltage_on_ac.vddci =
allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci;
@@ -2148,10 +2388,17 @@ static int smu7_patch_voltage_workaround(struct pp_hwmgr *hwmgr)
sub_sys_id = adev->pdev->subsystem_device;
sub_vendor_id = adev->pdev->subsystem_vendor;
- if (hwmgr->chip_id == CHIP_POLARIS10 && hw_revision == 0xC7 &&
- ((sub_sys_id == 0xb37 && sub_vendor_id == 0x1002) ||
- (sub_sys_id == 0x4a8 && sub_vendor_id == 0x1043) ||
- (sub_sys_id == 0x9480 && sub_vendor_id == 0x1682))) {
+ if (adev->pdev->device == 0x67DF && hw_revision == 0xC7 &&
+ ((sub_sys_id == 0xb37 && sub_vendor_id == 0x1002) ||
+ (sub_sys_id == 0x4a8 && sub_vendor_id == 0x1043) ||
+ (sub_sys_id == 0x9480 && sub_vendor_id == 0x1682))) {
+
+ PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device,
+ CGS_IND_REG__SMC,
+ PWR_CKS_CNTL,
+ CKS_STRETCH_AMOUNT,
+ 0x3);
+
if (lookup_table->entries[dep_mclk_table->entries[dep_mclk_table->count-1].vddInd].us_vdd >= 1000)
return 0;
@@ -2253,11 +2500,11 @@ static int smu7_thermal_parameter_init(struct pp_hwmgr *hwmgr)
}
/**
- * Change virtual leakage voltage to actual value.
+ * smu7_patch_ppt_v0_with_vdd_leakage - Change virtual leakage voltage to actual value.
*
- * @param hwmgr the address of the powerplay hardware manager.
- * @param pointer to changing voltage
- * @param pointer to leakage table
+ * @hwmgr: the address of the powerplay hardware manager.
+ * @voltage: pointer to changing voltage
+ * @leakage_table: pointer to leakage table
*/
static void smu7_patch_ppt_v0_with_vdd_leakage(struct pp_hwmgr *hwmgr,
uint32_t *voltage, struct smu7_leakage_voltage *leakage_table)
@@ -2552,6 +2799,42 @@ static int smu7_get_elb_voltages(struct pp_hwmgr *hwmgr)
return 0;
}
+#define LEAKAGE_ID_MSB 463
+#define LEAKAGE_ID_LSB 454
+
+static int smu7_update_edc_leakage_table(struct pp_hwmgr *hwmgr)
+{
+ struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
+ uint32_t efuse;
+ uint16_t offset;
+ int ret = 0;
+
+ if (data->disable_edc_leakage_controller)
+ return 0;
+
+ ret = atomctrl_get_edc_hilo_leakage_offset_table(hwmgr,
+ &data->edc_hilo_leakage_offset_from_vbios);
+ if (ret)
+ return ret;
+
+ if (data->edc_hilo_leakage_offset_from_vbios.usEdcDidtLoDpm7TableOffset &&
+ data->edc_hilo_leakage_offset_from_vbios.usEdcDidtHiDpm7TableOffset) {
+ atomctrl_read_efuse(hwmgr, LEAKAGE_ID_LSB, LEAKAGE_ID_MSB, &efuse);
+ if (efuse < data->edc_hilo_leakage_offset_from_vbios.usHiLoLeakageThreshold)
+ offset = data->edc_hilo_leakage_offset_from_vbios.usEdcDidtLoDpm7TableOffset;
+ else
+ offset = data->edc_hilo_leakage_offset_from_vbios.usEdcDidtHiDpm7TableOffset;
+
+ ret = atomctrl_get_edc_leakage_table(hwmgr,
+ &data->edc_leakage_table,
+ offset);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
{
struct smu7_hwmgr *data;
@@ -2601,6 +2884,8 @@ static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
data->pcie_gen_cap = adev->pm.pcie_gen_mask;
if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
data->pcie_spc_cap = 20;
+ else
+ data->pcie_spc_cap = 16;
data->pcie_lane_cap = adev->pm.pcie_mlw_mask;
hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */
@@ -2613,6 +2898,10 @@ static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
smu7_hwmgr_backend_fini(hwmgr);
}
+ result = smu7_update_edc_leakage_table(hwmgr);
+ if (result)
+ return result;
+
return 0;
}
@@ -2890,7 +3179,7 @@ static int smu7_vblank_too_short(struct pp_hwmgr *hwmgr,
case CHIP_POLARIS10:
case CHIP_POLARIS11:
case CHIP_POLARIS12:
- if (hwmgr->is_kicker)
+ if (hwmgr->is_kicker || (hwmgr->chip_id == CHIP_POLARIS12))
switch_limit_us = data->is_memory_gddr5 ? 450 : 150;
else
switch_limit_us = data->is_memory_gddr5 ? 200 : 150;
@@ -2921,6 +3210,7 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
struct PP_Clocks minimum_clocks = {0};
bool disable_mclk_switching;
bool disable_mclk_switching_for_frame_lock;
+ bool disable_mclk_switching_for_display;
const struct phm_clock_and_voltage_limits *max_limits;
uint32_t i;
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
@@ -2928,9 +3218,12 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
(struct phm_ppt_v1_information *)(hwmgr->pptable);
int32_t count;
int32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0;
+ uint32_t latency;
+ bool latency_allowed = false;
data->battery_state = (PP_StateUILabel_Battery ==
request_ps->classification.ui_label);
+ data->mclk_ignore_signal = false;
PP_ASSERT_WITH_CODE(smu7_ps->performance_level_count == 2,
"VI should always have 2 performance levels",
@@ -2981,19 +3274,26 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_DisableMclkSwitchingForFrameLock);
+ disable_mclk_switching_for_display = ((1 < hwmgr->display_config->num_display) &&
+ !hwmgr->display_config->multi_monitor_in_sync) ||
+ smu7_vblank_too_short(hwmgr, hwmgr->display_config->min_vblank_time);
- if (hwmgr->display_config->num_display == 0)
- disable_mclk_switching = false;
- else
- disable_mclk_switching = ((1 < hwmgr->display_config->num_display) &&
- !hwmgr->display_config->multi_monitor_in_sync) ||
- disable_mclk_switching_for_frame_lock ||
- smu7_vblank_too_short(hwmgr, hwmgr->display_config->min_vblank_time);
+ disable_mclk_switching = disable_mclk_switching_for_frame_lock ||
+ disable_mclk_switching_for_display;
+
+ if (hwmgr->display_config->num_display == 0) {
+ if (hwmgr->chip_id >= CHIP_POLARIS10 && hwmgr->chip_id <= CHIP_VEGAM)
+ data->mclk_ignore_signal = true;
+ else
+ disable_mclk_switching = false;
+ }
sclk = smu7_ps->performance_levels[0].engine_clock;
mclk = smu7_ps->performance_levels[0].memory_clock;
- if (disable_mclk_switching)
+ if (disable_mclk_switching &&
+ (!(hwmgr->chip_id >= CHIP_POLARIS10 &&
+ hwmgr->chip_id <= CHIP_VEGAM)))
mclk = smu7_ps->performance_levels
[smu7_ps->performance_level_count - 1].memory_clock;
@@ -3018,8 +3318,41 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
if (mclk < smu7_ps->performance_levels[1].memory_clock)
mclk = smu7_ps->performance_levels[1].memory_clock;
+ if (hwmgr->chip_id >= CHIP_POLARIS10 && hwmgr->chip_id <= CHIP_VEGAM) {
+ if (disable_mclk_switching_for_display) {
+ /* Find the lowest MCLK frequency that is within
+ * the tolerable latency defined in DAL
+ */
+ latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency;
+ for (i = 0; i < data->mclk_latency_table.count; i++) {
+ if (data->mclk_latency_table.entries[i].latency <= latency) {
+ latency_allowed = true;
+
+ if ((data->mclk_latency_table.entries[i].frequency >=
+ smu7_ps->performance_levels[0].memory_clock) &&
+ (data->mclk_latency_table.entries[i].frequency <=
+ smu7_ps->performance_levels[1].memory_clock)) {
+ mclk = data->mclk_latency_table.entries[i].frequency;
+ break;
+ }
+ }
+ }
+ if ((i >= data->mclk_latency_table.count - 1) && !latency_allowed) {
+ data->mclk_ignore_signal = true;
+ } else {
+ data->mclk_ignore_signal = false;
+ }
+ }
+
+ if (disable_mclk_switching_for_frame_lock)
+ mclk = smu7_ps->performance_levels[1].memory_clock;
+ }
+
smu7_ps->performance_levels[0].memory_clock = mclk;
- smu7_ps->performance_levels[1].memory_clock = mclk;
+
+ if (!(hwmgr->chip_id >= CHIP_POLARIS10 &&
+ hwmgr->chip_id <= CHIP_VEGAM))
+ smu7_ps->performance_levels[1].memory_clock = mclk;
} else {
if (smu7_ps->performance_levels[1].memory_clock <
smu7_ps->performance_levels[0].memory_clock)
@@ -3765,6 +4098,7 @@ static int smu7_freeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
}
if ((0 == data->mclk_dpm_key_disabled) &&
+ !data->mclk_ignore_signal &&
(data->need_update_smu7_dpm_table &
DPMTABLE_OD_UPDATE_MCLK)) {
PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),
@@ -3921,6 +4255,7 @@ static int smu7_unfreeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
}
if ((0 == data->mclk_dpm_key_disabled) &&
+ !data->mclk_ignore_signal &&
(data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) {
PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),
@@ -3974,7 +4309,12 @@ static int smu7_notify_link_speed_change_after_state_change(
return 0;
}
-static int smu7_notify_smc_display(struct pp_hwmgr *hwmgr)
+static int smu7_notify_no_display(struct pp_hwmgr *hwmgr)
+{
+ return (smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_NoDisplay, NULL) == 0) ? 0 : -EINVAL;
+}
+
+static int smu7_notify_has_display(struct pp_hwmgr *hwmgr)
{
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
@@ -3987,10 +4327,25 @@ static int smu7_notify_smc_display(struct pp_hwmgr *hwmgr)
smum_send_msg_to_smc_with_parameter(hwmgr,
(PPSMC_Msg)PPSMC_MSG_SetVBITimeout, data->frame_time_x2,
NULL);
+ data->last_sent_vbi_timeout = data->frame_time_x2;
}
+
return (smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_HasDisplay, NULL) == 0) ? 0 : -EINVAL;
}
+static int smu7_notify_smc_display(struct pp_hwmgr *hwmgr)
+{
+ struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
+ int result = 0;
+
+ if (data->mclk_ignore_signal)
+ result = smu7_notify_no_display(hwmgr);
+ else
+ result = smu7_notify_has_display(hwmgr);
+
+ return result;
+}
+
static int smu7_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input)
{
int tmp_result, result = 0;
@@ -4041,11 +4396,6 @@ static int smu7_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input)
"Failed to update SCLK threshold!",
result = tmp_result);
- tmp_result = smu7_notify_smc_display(hwmgr);
- PP_ASSERT_WITH_CODE((0 == tmp_result),
- "Failed to notify smc display settings!",
- result = tmp_result);
-
tmp_result = smu7_unfreeze_sclk_mclk_dpm(hwmgr);
PP_ASSERT_WITH_CODE((0 == tmp_result),
"Failed to unfreeze SCLK MCLK DPM!",
@@ -4056,6 +4406,11 @@ static int smu7_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input)
"Failed to upload DPM level enabled mask!",
result = tmp_result);
+ tmp_result = smu7_notify_smc_display(hwmgr);
+ PP_ASSERT_WITH_CODE((0 == tmp_result),
+ "Failed to notify smc display settings!",
+ result = tmp_result);
+
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_PCIEPerformanceRequest)) {
tmp_result =
@@ -4079,29 +4434,17 @@ static int smu7_set_max_fan_pwm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_f
}
static int
-smu7_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display)
-{
- PPSMC_Msg msg = has_display ? (PPSMC_Msg)PPSMC_HasDisplay : (PPSMC_Msg)PPSMC_NoDisplay;
-
- return (smum_send_msg_to_smc(hwmgr, msg, NULL) == 0) ? 0 : -1;
-}
-
-static int
smu7_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr)
{
- if (hwmgr->display_config->num_display > 1 &&
- !hwmgr->display_config->multi_monitor_in_sync)
- smu7_notify_smc_display_change(hwmgr, false);
-
return 0;
}
/**
-* Programs the display gap
-*
-* @param hwmgr the address of the powerplay hardware manager.
-* @return always OK
-*/
+ * smu7_program_display_gap - Programs the display gap
+ *
+ * @hwmgr: the address of the powerplay hardware manager.
+ * Return: always OK
+ */
static int smu7_program_display_gap(struct pp_hwmgr *hwmgr)
{
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
@@ -4155,12 +4498,12 @@ static int smu7_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
}
/**
-* Set maximum target operating fan output RPM
-*
-* @param hwmgr: the address of the powerplay hardware manager.
-* @param usMaxFanRpm: max operating fan RPM value.
-* @return The response that came from the SMC.
-*/
+ * smu7_set_max_fan_rpm_output - Set maximum target operating fan output RPM
+ *
+ * @hwmgr: the address of the powerplay hardware manager.
+ * @usMaxFanRpm: max operating fan RPM value.
+ * Return: The response that came from the SMC.
+ */
static int smu7_set_max_fan_rpm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_rpm)
{
hwmgr->thermal_controller.
@@ -4215,6 +4558,11 @@ smu7_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
if (data->display_timing.vrefresh != hwmgr->display_config->vrefresh)
is_update_required = true;
+ if (hwmgr->chip_id >= CHIP_POLARIS10 &&
+ hwmgr->chip_id <= CHIP_VEGAM &&
+ data->last_sent_vbi_timeout != data->frame_time_x2)
+ is_update_required = true;
+
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) {
if (data->display_timing.min_clock_in_sr != hwmgr->display_config->min_core_set_clock_in_sr &&
(data->display_timing.min_clock_in_sr >= SMU7_MINIMUM_ENGINE_CLOCK ||
@@ -4350,10 +4698,10 @@ static int smu7_read_clock_registers(struct pp_hwmgr *hwmgr)
}
/**
- * Find out if memory is GDDR5.
+ * smu7_get_memory_type - Find out if memory is GDDR5.
*
- * @param hwmgr the address of the powerplay hardware manager.
- * @return always 0
+ * @hwmgr: the address of the powerplay hardware manager.
+ * Return: always 0
*/
static int smu7_get_memory_type(struct pp_hwmgr *hwmgr)
{
@@ -4366,10 +4714,10 @@ static int smu7_get_memory_type(struct pp_hwmgr *hwmgr)
}
/**
- * Enables Dynamic Power Management by SMC
+ * smu7_enable_acpi_power_management - Enables Dynamic Power Management by SMC
*
- * @param hwmgr the address of the powerplay hardware manager.
- * @return always 0
+ * @hwmgr: the address of the powerplay hardware manager.
+ * Return: always 0
*/
static int smu7_enable_acpi_power_management(struct pp_hwmgr *hwmgr)
{
@@ -4380,10 +4728,10 @@ static int smu7_enable_acpi_power_management(struct pp_hwmgr *hwmgr)
}
/**
- * Initialize PowerGating States for different engines
+ * smu7_init_power_gate_state - Initialize PowerGating States for different engines
*
- * @param hwmgr the address of the powerplay hardware manager.
- * @return always 0
+ * @hwmgr: the address of the powerplay hardware manager.
+ * Return: always 0
*/
static int smu7_init_power_gate_state(struct pp_hwmgr *hwmgr)
{
@@ -4771,6 +5119,125 @@ static int smu7_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type
return 0;
}
+static int smu7_get_sclks_with_latency(struct pp_hwmgr *hwmgr,
+ struct pp_clock_levels_with_latency *clocks)
+{
+ struct phm_ppt_v1_information *table_info =
+ (struct phm_ppt_v1_information *)hwmgr->pptable;
+ struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table =
+ table_info->vdd_dep_on_sclk;
+ int i;
+
+ clocks->num_levels = 0;
+ for (i = 0; i < dep_sclk_table->count; i++) {
+ if (dep_sclk_table->entries[i].clk) {
+ clocks->data[clocks->num_levels].clocks_in_khz =
+ dep_sclk_table->entries[i].clk * 10;
+ clocks->num_levels++;
+ }
+ }
+
+ return 0;
+}
+
+static int smu7_get_mclks_with_latency(struct pp_hwmgr *hwmgr,
+ struct pp_clock_levels_with_latency *clocks)
+{
+ struct phm_ppt_v1_information *table_info =
+ (struct phm_ppt_v1_information *)hwmgr->pptable;
+ struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
+ table_info->vdd_dep_on_mclk;
+ struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
+ int i;
+
+ clocks->num_levels = 0;
+ data->mclk_latency_table.count = 0;
+ for (i = 0; i < dep_mclk_table->count; i++) {
+ if (dep_mclk_table->entries[i].clk) {
+ clocks->data[clocks->num_levels].clocks_in_khz =
+ dep_mclk_table->entries[i].clk * 10;
+ data->mclk_latency_table.entries[data->mclk_latency_table.count].frequency =
+ dep_mclk_table->entries[i].clk;
+ clocks->data[clocks->num_levels].latency_in_us =
+ data->mclk_latency_table.entries[data->mclk_latency_table.count].latency =
+ smu7_get_mem_latency(hwmgr, dep_mclk_table->entries[i].clk);
+ clocks->num_levels++;
+ data->mclk_latency_table.count++;
+ }
+ }
+
+ return 0;
+}
+
+static int smu7_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
+ enum amd_pp_clock_type type,
+ struct pp_clock_levels_with_latency *clocks)
+{
+ if (!(hwmgr->chip_id >= CHIP_POLARIS10 &&
+ hwmgr->chip_id <= CHIP_VEGAM))
+ return -EINVAL;
+
+ switch (type) {
+ case amd_pp_sys_clock:
+ smu7_get_sclks_with_latency(hwmgr, clocks);
+ break;
+ case amd_pp_mem_clock:
+ smu7_get_mclks_with_latency(hwmgr, clocks);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int smu7_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
+ void *clock_range)
+{
+ struct phm_ppt_v1_information *table_info =
+ (struct phm_ppt_v1_information *)hwmgr->pptable;
+ struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
+ table_info->vdd_dep_on_mclk;
+ struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table =
+ table_info->vdd_dep_on_sclk;
+ struct polaris10_smumgr *smu_data =
+ (struct polaris10_smumgr *)(hwmgr->smu_backend);
+ SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table);
+ struct dm_pp_wm_sets_with_clock_ranges *watermarks =
+ (struct dm_pp_wm_sets_with_clock_ranges *)clock_range;
+ uint32_t i, j, k;
+ bool valid_entry;
+
+ if (!(hwmgr->chip_id >= CHIP_POLARIS10 &&
+ hwmgr->chip_id <= CHIP_VEGAM))
+ return -EINVAL;
+
+ for (i = 0; i < dep_mclk_table->count; i++) {
+ for (j = 0; j < dep_sclk_table->count; j++) {
+ valid_entry = false;
+ for (k = 0; k < watermarks->num_wm_sets; k++) {
+ if (dep_sclk_table->entries[i].clk / 10 >= watermarks->wm_clk_ranges[k].wm_min_eng_clk_in_khz &&
+ dep_sclk_table->entries[i].clk / 10 < watermarks->wm_clk_ranges[k].wm_max_eng_clk_in_khz &&
+ dep_mclk_table->entries[i].clk / 10 >= watermarks->wm_clk_ranges[k].wm_min_mem_clk_in_khz &&
+ dep_mclk_table->entries[i].clk / 10 < watermarks->wm_clk_ranges[k].wm_max_mem_clk_in_khz) {
+ valid_entry = true;
+ table->DisplayWatermark[i][j] = watermarks->wm_clk_ranges[k].wm_set_id;
+ break;
+ }
+ }
+ PP_ASSERT_WITH_CODE(valid_entry,
+ "Clock is not in range of specified clock range for watermark from DAL! Using highest water mark set.",
+ table->DisplayWatermark[i][j] = watermarks->wm_clk_ranges[k - 1].wm_set_id);
+ }
+ }
+
+ return smu7_copy_bytes_to_smc(hwmgr,
+ smu_data->smu7_data.dpm_table_start + offsetof(SMU74_Discrete_DpmTable, DisplayWatermark),
+ (uint8_t *)table->DisplayWatermark,
+ sizeof(uint8_t) * SMU74_MAX_LEVELS_MEMORY * SMU74_MAX_LEVELS_GRAPHICS,
+ SMC_RAM_END);
+}
+
static int smu7_notify_cac_buffer_info(struct pp_hwmgr *hwmgr,
uint32_t virtual_addr_low,
uint32_t virtual_addr_hi,
@@ -5188,6 +5655,8 @@ static const struct pp_hwmgr_func smu7_hwmgr_funcs = {
.get_mclk_od = smu7_get_mclk_od,
.set_mclk_od = smu7_set_mclk_od,
.get_clock_by_type = smu7_get_clock_by_type,
+ .get_clock_by_type_with_latency = smu7_get_clock_by_type_with_latency,
+ .set_watermarks_for_clocks_ranges = smu7_set_watermarks_for_clocks_ranges,
.read_sensor = smu7_read_sensor,
.dynamic_state_management_disable = smu7_disable_dpm_tasks,
.avfs_control = smu7_avfs_control,