drm/amd/smu: Update SMU13 support for SMU 13.0.0

Modify the common smu13 code and add a new smu
13.0.0 ppt file to handle the smu 13.0.0 specific
configuration.

v2: squash in typo fix in profile name

Signed-off-by: Evan Quan <evan.quan@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Evan Quan 2022-04-06 17:13:54 -04:00 committed by Alex Deucher
parent ce81151c7d
commit 276c03a054
11 changed files with 1727 additions and 50 deletions

View File

@ -1994,6 +1994,7 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_
case IP_VERSION(9, 4, 1):
case IP_VERSION(9, 4, 2):
case IP_VERSION(10, 3, 0):
case IP_VERSION(11, 0, 0):
*states = ATTR_STATE_SUPPORTED;
break;
default:

View File

@ -37,6 +37,7 @@
#include "aldebaran_ppt.h"
#include "yellow_carp_ppt.h"
#include "cyan_skillfish_ppt.h"
#include "smu_v13_0_0_ppt.h"
#include "smu_v13_0_5_ppt.h"
#include "amd_pcie.h"
@ -565,6 +566,9 @@ static int smu_set_funcs(struct amdgpu_device *adev)
/* Enable pp_od_clk_voltage node */
smu->od_enabled = true;
break;
case IP_VERSION(13, 0, 0):
smu_v13_0_0_set_ppt_funcs(smu);
break;
default:
return -EINVAL;
}

View File

@ -454,6 +454,7 @@ struct smu_umd_pstate_table {
struct pstates_clk_freq uclk_pstate;
struct pstates_clk_freq vclk_pstate;
struct pstates_clk_freq dclk_pstate;
struct pstates_clk_freq fclk_pstate;
};
struct cmn2asic_msg_mapping {
@ -1327,6 +1328,8 @@ typedef enum {
METRICS_AVERAGE_UCLK,
METRICS_AVERAGE_VCLK,
METRICS_AVERAGE_DCLK,
METRICS_AVERAGE_VCLK1,
METRICS_AVERAGE_DCLK1,
METRICS_AVERAGE_GFXACTIVITY,
METRICS_AVERAGE_MEMACTIVITY,
METRICS_AVERAGE_VCNACTIVITY,
@ -1345,6 +1348,9 @@ typedef enum {
METRICS_SS_DGPU_SHARE,
METRICS_UNIQUE_ID_UPPER32,
METRICS_UNIQUE_ID_LOWER32,
METRICS_PCIE_RATE,
METRICS_PCIE_WIDTH,
METRICS_CURR_FANPWM,
} MetricsMember_t;
enum smu_cmn2asic_mapping_type {

View File

@ -366,6 +366,8 @@ enum smu_clk_type {
__SMU_DUMMY_MAP(THM_CG), \
__SMU_DUMMY_MAP(CLK_CG), \
__SMU_DUMMY_MAP(DATA_CALCULATION), \
__SMU_DUMMY_MAP(DPM_VCLK), \
__SMU_DUMMY_MAP(DPM_DCLK), \
#undef __SMU_DUMMY_MAP
#define __SMU_DUMMY_MAP(feature) SMU_FEATURE_##feature##_BIT

View File

@ -28,9 +28,10 @@
#define SMU13_DRIVER_IF_VERSION_INV 0xFFFFFFFF
#define SMU13_DRIVER_IF_VERSION_YELLOW_CARP 0x04
#define SMU13_DRIVER_IF_VERSION_ALDE 0x08
#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_5 0x04
#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0 0x27
#define SMU13_MODE1_RESET_WAIT_TIME_IN_MS 500 //500ms
#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_5 0x04
/* MP Apertures */
#define MP0_Public 0x03800000
@ -49,7 +50,7 @@
#define SMU13_TOOL_SIZE 0x19000
#define MAX_DPM_LEVELS 16
#define MAX_PCIE_CONF 2
#define MAX_PCIE_CONF 3
#define CTF_OFFSET_EDGE 5
#define CTF_OFFSET_HOTSPOT 5
@ -73,12 +74,15 @@ struct smu_13_0_dpm_table {
uint32_t min; /* MHz */
uint32_t max; /* MHz */
uint32_t count;
bool is_fine_grained;
struct smu_13_0_dpm_clk_level dpm_levels[MAX_DPM_LEVELS];
};
struct smu_13_0_pcie_table {
uint8_t pcie_gen[MAX_PCIE_CONF];
uint8_t pcie_lane[MAX_PCIE_CONF];
uint16_t clk_freq[MAX_PCIE_CONF];
uint32_t num_of_link_levels;
};
struct smu_13_0_dpm_tables {
@ -192,8 +196,8 @@ int
smu_v13_0_set_fan_control_mode(struct smu_context *smu,
uint32_t mode);
int
smu_v13_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed);
int smu_v13_0_set_fan_speed_pwm(struct smu_context *smu,
uint32_t speed);
int smu_v13_0_set_fan_speed_rpm(struct smu_context *smu,
uint32_t speed);
@ -238,15 +242,6 @@ int smu_v13_0_set_performance_level(struct smu_context *smu,
int smu_v13_0_set_power_source(struct smu_context *smu,
enum smu_power_src_type power_src);
int smu_v13_0_get_dpm_freq_by_index(struct smu_context *smu,
enum smu_clk_type clk_type,
uint16_t level,
uint32_t *value);
int smu_v13_0_get_dpm_level_count(struct smu_context *smu,
enum smu_clk_type clk_type,
uint32_t *value);
int smu_v13_0_set_single_dpm_table(struct smu_context *smu,
enum smu_clk_type clk_type,
struct smu_13_0_dpm_table *single_dpm_table);
@ -270,5 +265,13 @@ int smu_v13_0_gfx_ulv_control(struct smu_context *smu,
int smu_v13_0_wait_for_event(struct smu_context *smu, enum smu_event_type event,
uint64_t event_arg);
int smu_v13_0_set_vcn_enable(struct smu_context *smu,
bool enable);
int smu_v13_0_set_jpeg_enable(struct smu_context *smu,
bool enable);
int smu_v13_0_init_pptable_microcode(struct smu_context *smu);
#endif
#endif

View File

@ -23,7 +23,7 @@
# Makefile for the 'smu manager' sub-component of powerplay.
# It provides the smu management services for the driver.
SMU13_MGR = smu_v13_0.o aldebaran_ppt.o yellow_carp_ppt.o smu_v13_0_5_ppt.o
SMU13_MGR = smu_v13_0.o aldebaran_ppt.o yellow_carp_ppt.o smu_v13_0_0_ppt.o smu_v13_0_5_ppt.o
AMD_SWSMU_SMU13MGR = $(addprefix $(AMD_SWSMU_PATH)/smu13/,$(SMU13_MGR))

View File

@ -28,7 +28,7 @@
#define ALDEBARAN_UMD_PSTATE_MCLK_LEVEL 0x2
#define MAX_DPM_NUMBER 16
#define MAX_PCIE_CONF 2
#define ALDEBARAN_MAX_PCIE_CONF 2
struct aldebaran_dpm_level {
bool enabled;
@ -51,9 +51,9 @@ struct aldebaran_single_dpm_table {
struct aldebaran_pcie_table {
uint16_t count;
uint8_t pcie_gen[MAX_PCIE_CONF];
uint8_t pcie_lane[MAX_PCIE_CONF];
uint32_t lclk[MAX_PCIE_CONF];
uint8_t pcie_gen[ALDEBARAN_MAX_PCIE_CONF];
uint8_t pcie_lane[ALDEBARAN_MAX_PCIE_CONF];
uint32_t lclk[ALDEBARAN_MAX_PCIE_CONF];
};
struct aldebaran_dpm_table {

View File

@ -57,6 +57,7 @@
#undef pr_debug
MODULE_FIRMWARE("amdgpu/aldebaran_smc.bin");
MODULE_FIRMWARE("amdgpu/smu_13_0_0.bin");
#define SMU13_VOLTAGE_SCALE 4
@ -73,11 +74,15 @@ MODULE_FIRMWARE("amdgpu/aldebaran_smc.bin");
static const int link_width[] = {0, 1, 2, 4, 8, 12, 16};
static const int link_speed[] = {25, 50, 80, 160};
static int smu_v13_0_get_pptable_from_firmware(struct smu_context *smu, void **table, uint32_t *size,
uint32_t pptable_id);
int smu_v13_0_init_microcode(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
const char *chip_name;
char fw_name[30];
char ucode_prefix[30];
int err = 0;
const struct smc_firmware_header_v1_0 *hdr;
const struct common_firmware_header *header;
@ -89,15 +94,14 @@ int smu_v13_0_init_microcode(struct smu_context *smu)
switch (adev->ip_versions[MP1_HWIP][0]) {
case IP_VERSION(13, 0, 2):
chip_name = "aldebaran";
chip_name = "aldebaran_smc";
break;
default:
dev_err(adev->dev, "Unsupported IP version 0x%x\n",
adev->ip_versions[MP1_HWIP][0]);
return -EINVAL;
amdgpu_ucode_ip_version_decode(adev, MP1_HWIP, ucode_prefix, sizeof(ucode_prefix));
chip_name = ucode_prefix;
}
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_smc.bin", chip_name);
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", chip_name);
err = request_firmware(&adev->pm.fw, fw_name, adev->dev);
if (err)
@ -176,6 +180,62 @@ int smu_v13_0_load_microcode(struct smu_context *smu)
if (i == adev->usec_timeout)
return -ETIME;
#endif
return 0;
}
int smu_v13_0_init_pptable_microcode(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
struct amdgpu_firmware_info *ucode = NULL;
uint32_t size = 0, pptable_id = 0;
int ret = 0;
void *table;
/* doesn't need to load smu firmware in IOV mode */
if (amdgpu_sriov_vf(adev))
return 0;
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
return 0;
if (!adev->scpm_enabled)
return 0;
/* override pptable_id from driver parameter */
if (amdgpu_smu_pptable_id >= 0) {
pptable_id = amdgpu_smu_pptable_id;
dev_info(adev->dev, "override pptable id %d\n", pptable_id);
} else {
pptable_id = smu->smu_table.boot_values.pp_table_id;
/*
* Temporary solution for SMU V13.0.0:
* - use 99991 signed pptable when SCPM enabled
* TODO: drop this when the pptable carried in vbios
* is ready.
*/
if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 0))
pptable_id = 99991;
}
/* "pptable_id == 0" means vbios carries the pptable. */
if (!pptable_id)
return 0;
ret = smu_v13_0_get_pptable_from_firmware(smu, &table, &size, pptable_id);
if (ret)
return ret;
smu->pptable_firmware.data = table;
smu->pptable_firmware.size = size;
ucode = &adev->firmware.ucode[AMDGPU_UCODE_ID_PPTABLE];
ucode->ucode_id = AMDGPU_UCODE_ID_PPTABLE;
ucode->fw = &smu->pptable_firmware;
adev->firmware.fw_size +=
ALIGN(smu->pptable_firmware.size, PAGE_SIZE);
return 0;
}
@ -216,6 +276,9 @@ int smu_v13_0_check_fw_version(struct smu_context *smu)
case IP_VERSION(13, 0, 2):
smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_ALDE;
break;
case IP_VERSION(13, 0, 0):
smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_0;
break;
case IP_VERSION(13, 0, 1):
case IP_VERSION(13, 0, 3):
case IP_VERSION(13, 0, 8):
@ -255,6 +318,21 @@ int smu_v13_0_check_fw_version(struct smu_context *smu)
return ret;
}
static int smu_v13_0_set_pptable_v2_0(struct smu_context *smu, void **table, uint32_t *size)
{
struct amdgpu_device *adev = smu->adev;
uint32_t ppt_offset_bytes;
const struct smc_firmware_header_v2_0 *v2;
v2 = (const struct smc_firmware_header_v2_0 *) adev->pm.fw->data;
ppt_offset_bytes = le32_to_cpu(v2->ppt_offset_bytes);
*size = le32_to_cpu(v2->ppt_size_bytes);
*table = (uint8_t *)v2 + ppt_offset_bytes;
return 0;
}
static int smu_v13_0_set_pptable_v2_1(struct smu_context *smu, void **table,
uint32_t *size, uint32_t pptable_id)
{
@ -327,6 +405,9 @@ static int smu_v13_0_get_pptable_from_firmware(struct smu_context *smu, void **t
}
switch (version_minor) {
case 0:
ret = smu_v13_0_set_pptable_v2_0(smu, table, size);
break;
case 1:
ret = smu_v13_0_set_pptable_v2_1(smu, table, size, pptable_id);
break;
@ -351,10 +432,19 @@ int smu_v13_0_setup_pptable(struct smu_context *smu)
dev_info(adev->dev, "override pptable id %d\n", pptable_id);
} else {
pptable_id = smu->smu_table.boot_values.pp_table_id;
/*
* Temporary solution for SMU V13.0.0:
* - use 9999 unsigned pptable when SCPM disabled
* TODO: drop this when the pptable carried in vbios
* is ready.
*/
if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 0))
pptable_id = 9999;
}
/* force using vbios pptable in sriov mode */
if (amdgpu_sriov_vf(adev) || !pptable_id)
if ((amdgpu_sriov_vf(adev) || !pptable_id) && (amdgpu_emu_mode != 1))
ret = smu_v13_0_get_pptable_from_vbios(smu, &table, &size);
else
ret = smu_v13_0_get_pptable_from_firmware(smu, &table, &size, pptable_id);
@ -407,8 +497,17 @@ int smu_v13_0_init_smc_tables(struct smu_context *smu)
}
}
smu_table->combo_pptable =
kzalloc(tables[SMU_TABLE_COMBO_PPTABLE].size, GFP_KERNEL);
if (!smu_table->combo_pptable) {
ret = -ENOMEM;
goto err4_out;
}
return 0;
err4_out:
kfree(smu_table->boot_overdrive_table);
err3_out:
kfree(smu_table->overdrive_table);
err2_out:
@ -425,11 +524,13 @@ int smu_v13_0_fini_smc_tables(struct smu_context *smu)
struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
kfree(smu_table->gpu_metrics_table);
kfree(smu_table->combo_pptable);
kfree(smu_table->boot_overdrive_table);
kfree(smu_table->overdrive_table);
kfree(smu_table->max_sustainable_clocks);
kfree(smu_table->driver_pptable);
smu_table->gpu_metrics_table = NULL;
smu_table->combo_pptable = NULL;
smu_table->boot_overdrive_table = NULL;
smu_table->overdrive_table = NULL;
smu_table->max_sustainable_clocks = NULL;
@ -568,6 +669,7 @@ int smu_v13_0_get_vbios_bootup_values(struct smu_context *smu)
smu_info);
if (!amdgpu_atombios_get_data_table(smu->adev, index, &size, &frev, &crev,
(uint8_t **)&header)) {
if ((frev == 3) && (crev == 6)) {
smu_info_v3_6 = (struct atom_smu_info_v3_6 *)header;
@ -688,7 +790,6 @@ int smu_v13_0_init_display_count(struct smu_context *smu, uint32_t count)
return ret;
}
int smu_v13_0_set_allowed_mask(struct smu_context *smu)
{
struct smu_feature *feature = &smu->smu_feature;
@ -718,6 +819,7 @@ int smu_v13_0_gfx_off_control(struct smu_context *smu, bool enable)
struct amdgpu_device *adev = smu->adev;
switch (adev->ip_versions[MP1_HWIP][0]) {
case IP_VERSION(13, 0, 0):
case IP_VERSION(13, 0, 1):
case IP_VERSION(13, 0, 3):
case IP_VERSION(13, 0, 5):
@ -1050,15 +1152,14 @@ smu_v13_0_set_fan_static_mode(struct smu_context *smu, uint32_t mode)
return 0;
}
int
smu_v13_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed)
int smu_v13_0_set_fan_speed_pwm(struct smu_context *smu,
uint32_t speed)
{
struct amdgpu_device *adev = smu->adev;
uint32_t duty100, duty;
uint64_t tmp64;
if (speed > 100)
speed = 100;
speed = MIN(speed, 255);
if (smu_v13_0_auto_fan_control(smu, 0))
return -EINVAL;
@ -1069,7 +1170,7 @@ smu_v13_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed)
return -EINVAL;
tmp64 = (uint64_t)speed * duty100;
do_div(tmp64, 100);
do_div(tmp64, 255);
duty = (uint32_t)tmp64;
WREG32_SOC15(THM, 0, regCG_FDO_CTRL0,
@ -1087,7 +1188,7 @@ smu_v13_0_set_fan_control_mode(struct smu_context *smu,
switch (mode) {
case AMD_FAN_CTRL_NONE:
ret = smu_v13_0_set_fan_speed_percent(smu, 100);
ret = smu_v13_0_set_fan_speed_pwm(smu, 255);
break;
case AMD_FAN_CTRL_MANUAL:
ret = smu_v13_0_auto_fan_control(smu, 0);
@ -1111,8 +1212,8 @@ int smu_v13_0_set_fan_speed_rpm(struct smu_context *smu,
uint32_t speed)
{
struct amdgpu_device *adev = smu->adev;
int ret;
uint32_t tach_period, crystal_clock_freq;
int ret;
if (!speed)
return -EINVAL;
@ -1128,9 +1229,7 @@ int smu_v13_0_set_fan_speed_rpm(struct smu_context *smu,
CG_TACH_CTRL, TARGET_PERIOD,
tach_period));
ret = smu_v13_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC_RPM);
return ret;
return smu_v13_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC_RPM);
}
int smu_v13_0_set_xgmi_pstate(struct smu_context *smu,
@ -1462,7 +1561,16 @@ int smu_v13_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type c
param = (clk_id & 0xffff) << 16;
if (max) {
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetMaxDpmFreq, param, max);
if (smu->adev->pm.ac_power)
ret = smu_cmn_send_smc_msg_with_param(smu,
SMU_MSG_GetMaxDpmFreq,
param,
max);
else
ret = smu_cmn_send_smc_msg_with_param(smu,
SMU_MSG_GetDcModeMaxDpmFreq,
param,
max);
if (ret)
goto failed;
}
@ -1564,24 +1672,39 @@ int smu_v13_0_set_performance_level(struct smu_context *smu,
&dpm_context->dpm_tables.uclk_table;
struct smu_13_0_dpm_table *soc_table =
&dpm_context->dpm_tables.soc_table;
struct smu_13_0_dpm_table *vclk_table =
&dpm_context->dpm_tables.vclk_table;
struct smu_13_0_dpm_table *dclk_table =
&dpm_context->dpm_tables.dclk_table;
struct smu_13_0_dpm_table *fclk_table =
&dpm_context->dpm_tables.fclk_table;
struct smu_umd_pstate_table *pstate_table =
&smu->pstate_table;
struct amdgpu_device *adev = smu->adev;
uint32_t sclk_min = 0, sclk_max = 0;
uint32_t mclk_min = 0, mclk_max = 0;
uint32_t socclk_min = 0, socclk_max = 0;
int ret = 0;
uint32_t vclk_min = 0, vclk_max = 0;
uint32_t dclk_min = 0, dclk_max = 0;
uint32_t fclk_min = 0, fclk_max = 0;
int ret = 0, i;
switch (level) {
case AMD_DPM_FORCED_LEVEL_HIGH:
sclk_min = sclk_max = gfx_table->max;
mclk_min = mclk_max = mem_table->max;
socclk_min = socclk_max = soc_table->max;
vclk_min = vclk_max = vclk_table->max;
dclk_min = dclk_max = dclk_table->max;
fclk_min = fclk_max = fclk_table->max;
break;
case AMD_DPM_FORCED_LEVEL_LOW:
sclk_min = sclk_max = gfx_table->min;
mclk_min = mclk_max = mem_table->min;
socclk_min = socclk_max = soc_table->min;
vclk_min = vclk_max = vclk_table->min;
dclk_min = dclk_max = dclk_table->min;
fclk_min = fclk_max = fclk_table->min;
break;
case AMD_DPM_FORCED_LEVEL_AUTO:
sclk_min = gfx_table->min;
@ -1590,11 +1713,20 @@ int smu_v13_0_set_performance_level(struct smu_context *smu,
mclk_max = mem_table->max;
socclk_min = soc_table->min;
socclk_max = soc_table->max;
vclk_min = vclk_table->min;
vclk_max = vclk_table->max;
dclk_min = dclk_table->min;
dclk_max = dclk_table->max;
fclk_min = fclk_table->min;
fclk_max = fclk_table->max;
break;
case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
sclk_min = sclk_max = pstate_table->gfxclk_pstate.standard;
mclk_min = mclk_max = pstate_table->uclk_pstate.standard;
socclk_min = socclk_max = pstate_table->socclk_pstate.standard;
vclk_min = vclk_max = pstate_table->vclk_pstate.standard;
dclk_min = dclk_max = pstate_table->dclk_pstate.standard;
fclk_min = fclk_max = pstate_table->fclk_pstate.standard;
break;
case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
sclk_min = sclk_max = pstate_table->gfxclk_pstate.min;
@ -1606,6 +1738,9 @@ int smu_v13_0_set_performance_level(struct smu_context *smu,
sclk_min = sclk_max = pstate_table->gfxclk_pstate.peak;
mclk_min = mclk_max = pstate_table->uclk_pstate.peak;
socclk_min = socclk_max = pstate_table->socclk_pstate.peak;
vclk_min = vclk_max = pstate_table->vclk_pstate.peak;
dclk_min = dclk_max = pstate_table->dclk_pstate.peak;
fclk_min = fclk_max = pstate_table->fclk_pstate.peak;
break;
case AMD_DPM_FORCED_LEVEL_MANUAL:
case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
@ -1615,8 +1750,17 @@ int smu_v13_0_set_performance_level(struct smu_context *smu,
return -EINVAL;
}
mclk_min = mclk_max = 0;
socclk_min = socclk_max = 0;
/*
* Unset those settings for SMU 13.0.2. As soft limits settings
* for those clock domains are not supported.
*/
if (smu->adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2)) {
mclk_min = mclk_max = 0;
socclk_min = socclk_max = 0;
vclk_min = vclk_max = 0;
dclk_min = dclk_max = 0;
fclk_min = fclk_max = 0;
}
if (sclk_min && sclk_max) {
ret = smu_v13_0_set_soft_freq_limited_range(smu,
@ -1654,6 +1798,48 @@ int smu_v13_0_set_performance_level(struct smu_context *smu,
pstate_table->socclk_pstate.curr.max = socclk_max;
}
if (vclk_min && vclk_max) {
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
if (adev->vcn.harvest_config & (1 << i))
continue;
ret = smu_v13_0_set_soft_freq_limited_range(smu,
i ? SMU_VCLK1 : SMU_VCLK,
vclk_min,
vclk_max);
if (ret)
return ret;
}
pstate_table->vclk_pstate.curr.min = vclk_min;
pstate_table->vclk_pstate.curr.max = vclk_max;
}
if (dclk_min && dclk_max) {
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
if (adev->vcn.harvest_config & (1 << i))
continue;
ret = smu_v13_0_set_soft_freq_limited_range(smu,
i ? SMU_DCLK1 : SMU_DCLK,
dclk_min,
dclk_max);
if (ret)
return ret;
}
pstate_table->dclk_pstate.curr.min = dclk_min;
pstate_table->dclk_pstate.curr.max = dclk_max;
}
if (fclk_min && fclk_max) {
ret = smu_v13_0_set_soft_freq_limited_range(smu,
SMU_FCLK,
fclk_min,
fclk_max);
if (ret)
return ret;
pstate_table->fclk_pstate.curr.min = fclk_min;
pstate_table->fclk_pstate.curr.max = fclk_max;
}
return ret;
}
@ -1674,10 +1860,10 @@ int smu_v13_0_set_power_source(struct smu_context *smu,
NULL);
}
int smu_v13_0_get_dpm_freq_by_index(struct smu_context *smu,
enum smu_clk_type clk_type,
uint16_t level,
uint32_t *value)
static int smu_v13_0_get_dpm_freq_by_index(struct smu_context *smu,
enum smu_clk_type clk_type,
uint16_t level,
uint32_t *value)
{
int ret = 0, clk_id = 0;
uint32_t param;
@ -1703,18 +1889,14 @@ int smu_v13_0_get_dpm_freq_by_index(struct smu_context *smu,
if (ret)
return ret;
/*
* BIT31: 0 - Fine grained DPM, 1 - Dicrete DPM
* now, we un-support it
*/
*value = *value & 0x7fffffff;
return ret;
}
int smu_v13_0_get_dpm_level_count(struct smu_context *smu,
enum smu_clk_type clk_type,
uint32_t *value)
static int smu_v13_0_get_dpm_level_count(struct smu_context *smu,
enum smu_clk_type clk_type,
uint32_t *value)
{
int ret;
@ -1726,6 +1908,44 @@ int smu_v13_0_get_dpm_level_count(struct smu_context *smu,
return ret;
}
static int smu_v13_0_get_fine_grained_status(struct smu_context *smu,
enum smu_clk_type clk_type,
bool *is_fine_grained_dpm)
{
int ret = 0, clk_id = 0;
uint32_t param;
uint32_t value;
if (!is_fine_grained_dpm)
return -EINVAL;
if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type))
return 0;
clk_id = smu_cmn_to_asic_specific_index(smu,
CMN2ASIC_MAPPING_CLK,
clk_type);
if (clk_id < 0)
return clk_id;
param = (uint32_t)(((clk_id & 0xffff) << 16) | 0xff);
ret = smu_cmn_send_smc_msg_with_param(smu,
SMU_MSG_GetDpmFreqByIndex,
param,
&value);
if (ret)
return ret;
/*
* BIT31: 1 - Fine grained DPM, 0 - Dicrete DPM
* now, we un-support it
*/
*is_fine_grained_dpm = value & 0x80000000;
return 0;
}
int smu_v13_0_set_single_dpm_table(struct smu_context *smu,
enum smu_clk_type clk_type,
struct smu_13_0_dpm_table *single_dpm_table)
@ -1742,6 +1962,16 @@ int smu_v13_0_set_single_dpm_table(struct smu_context *smu,
return ret;
}
if (smu->adev->ip_versions[MP1_HWIP][0] != IP_VERSION(13, 0, 2)) {
ret = smu_v13_0_get_fine_grained_status(smu,
clk_type,
&single_dpm_table->is_fine_grained);
if (ret) {
dev_err(smu->adev->dev, "[%s] failed to get fine grained status!\n", __func__);
return ret;
}
}
for (i = 0; i < single_dpm_table->count; i++) {
ret = smu_v13_0_get_dpm_freq_by_index(smu,
clk_type,
@ -1843,3 +2073,30 @@ int smu_v13_0_get_current_pcie_link_speed(struct smu_context *smu)
return link_speed[speed_level];
}
int smu_v13_0_set_vcn_enable(struct smu_context *smu,
bool enable)
{
struct amdgpu_device *adev = smu->adev;
int i, ret = 0;
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
if (adev->vcn.harvest_config & (1 << i))
continue;
ret = smu_cmn_send_smc_msg_with_param(smu, enable ?
SMU_MSG_PowerUpVcn : SMU_MSG_PowerDownVcn,
i << 16U, NULL);
if (ret)
return ret;
}
return ret;
}
int smu_v13_0_set_jpeg_enable(struct smu_context *smu,
bool enable)
{
return smu_cmn_send_smc_msg_with_param(smu, enable ?
SMU_MSG_PowerUpJpeg : SMU_MSG_PowerDownJpeg,
0, NULL);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
/*
* 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.
*
*/
#ifndef __SMU_V13_0_0_PPT_H__
#define __SMU_V13_0_0_PPT_H__
extern void smu_v13_0_0_set_ppt_funcs(struct smu_context *smu);
#endif

View File

@ -581,6 +581,17 @@ bool smu_cmn_clk_dpm_is_enabled(struct smu_context *smu,
case SMU_SOCCLK:
feature_id = SMU_FEATURE_DPM_SOCCLK_BIT;
break;
case SMU_VCLK:
case SMU_VCLK1:
feature_id = SMU_FEATURE_DPM_VCLK_BIT;
break;
case SMU_DCLK:
case SMU_DCLK1:
feature_id = SMU_FEATURE_DPM_DCLK_BIT;
break;
case SMU_FCLK:
feature_id = SMU_FEATURE_DPM_FCLK_BIT;
break;
default:
return true;
}