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:
parent
ce81151c7d
commit
276c03a054
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
1365
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
Normal file
1365
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
Normal file
File diff suppressed because it is too large
Load Diff
28
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.h
Normal file
28
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.h
Normal 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
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user