summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/powerplay/vega20_ppt.c')
-rw-r--r--drivers/gpu/drm/amd/powerplay/vega20_ppt.c1285
1 files changed, 1088 insertions, 197 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
index 8fafcbdb1dfd..a76a22a18eb4 100644
--- a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
+++ b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
@@ -36,13 +36,29 @@
#include "vega20_pptable.h"
#include "vega20_ppsmc.h"
#include "nbio/nbio_7_4_sh_mask.h"
+#include "asic_reg/thm/thm_11_0_2_offset.h"
+#include "asic_reg/thm/thm_11_0_2_sh_mask.h"
#define smnPCIE_LC_SPEED_CNTL 0x11140290
#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288
+#define CTF_OFFSET_EDGE 5
+#define CTF_OFFSET_HOTSPOT 5
+#define CTF_OFFSET_HBM 5
+
#define MSG_MAP(msg) \
[SMU_MSG_##msg] = PPSMC_MSG_##msg
+#define SMC_DPM_FEATURE (FEATURE_DPM_PREFETCHER_MASK | \
+ FEATURE_DPM_GFXCLK_MASK | \
+ FEATURE_DPM_UCLK_MASK | \
+ FEATURE_DPM_SOCCLK_MASK | \
+ FEATURE_DPM_UVD_MASK | \
+ FEATURE_DPM_VCE_MASK | \
+ FEATURE_DPM_MP0CLK_MASK | \
+ FEATURE_DPM_LINK_MASK | \
+ FEATURE_DPM_DCEFCLK_MASK)
+
static int vega20_message_map[SMU_MSG_MAX_COUNT] = {
MSG_MAP(TestMessage),
MSG_MAP(GetSmuVersion),
@@ -129,6 +145,136 @@ static int vega20_message_map[SMU_MSG_MAX_COUNT] = {
MSG_MAP(GetAVFSVoltageByDpm),
};
+static int vega20_clk_map[SMU_CLK_COUNT] = {
+ CLK_MAP(GFXCLK, PPCLK_GFXCLK),
+ CLK_MAP(VCLK, PPCLK_VCLK),
+ CLK_MAP(DCLK, PPCLK_DCLK),
+ CLK_MAP(ECLK, PPCLK_ECLK),
+ CLK_MAP(SOCCLK, PPCLK_SOCCLK),
+ CLK_MAP(UCLK, PPCLK_UCLK),
+ CLK_MAP(DCEFCLK, PPCLK_DCEFCLK),
+ CLK_MAP(DISPCLK, PPCLK_DISPCLK),
+ CLK_MAP(PIXCLK, PPCLK_PIXCLK),
+ CLK_MAP(PHYCLK, PPCLK_PHYCLK),
+ CLK_MAP(FCLK, PPCLK_FCLK),
+};
+
+static int vega20_feature_mask_map[SMU_FEATURE_COUNT] = {
+ FEA_MAP(DPM_PREFETCHER),
+ FEA_MAP(DPM_GFXCLK),
+ FEA_MAP(DPM_UCLK),
+ FEA_MAP(DPM_SOCCLK),
+ FEA_MAP(DPM_UVD),
+ FEA_MAP(DPM_VCE),
+ FEA_MAP(ULV),
+ FEA_MAP(DPM_MP0CLK),
+ FEA_MAP(DPM_LINK),
+ FEA_MAP(DPM_DCEFCLK),
+ FEA_MAP(DS_GFXCLK),
+ FEA_MAP(DS_SOCCLK),
+ FEA_MAP(DS_LCLK),
+ FEA_MAP(PPT),
+ FEA_MAP(TDC),
+ FEA_MAP(THERMAL),
+ FEA_MAP(GFX_PER_CU_CG),
+ FEA_MAP(RM),
+ FEA_MAP(DS_DCEFCLK),
+ FEA_MAP(ACDC),
+ FEA_MAP(VR0HOT),
+ FEA_MAP(VR1HOT),
+ FEA_MAP(FW_CTF),
+ FEA_MAP(LED_DISPLAY),
+ FEA_MAP(FAN_CONTROL),
+ FEA_MAP(GFX_EDC),
+ FEA_MAP(GFXOFF),
+ FEA_MAP(CG),
+ FEA_MAP(DPM_FCLK),
+ FEA_MAP(DS_FCLK),
+ FEA_MAP(DS_MP1CLK),
+ FEA_MAP(DS_MP0CLK),
+ FEA_MAP(XGMI),
+};
+
+static int vega20_table_map[SMU_TABLE_COUNT] = {
+ TAB_MAP(PPTABLE),
+ TAB_MAP(WATERMARKS),
+ TAB_MAP(AVFS),
+ TAB_MAP(AVFS_PSM_DEBUG),
+ TAB_MAP(AVFS_FUSE_OVERRIDE),
+ TAB_MAP(PMSTATUSLOG),
+ TAB_MAP(SMU_METRICS),
+ TAB_MAP(DRIVER_SMU_CONFIG),
+ TAB_MAP(ACTIVITY_MONITOR_COEFF),
+ TAB_MAP(OVERDRIVE),
+};
+
+static int vega20_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
+ PWR_MAP(AC),
+ PWR_MAP(DC),
+};
+
+static int vega20_workload_map[] = {
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, WORKLOAD_DEFAULT_BIT),
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, WORKLOAD_PPLIB_POWER_SAVING_BIT),
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT),
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT),
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_CUSTOM_BIT),
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT),
+};
+
+static int vega20_get_smu_table_index(struct smu_context *smc, uint32_t index)
+{
+ int val;
+ if (index >= SMU_TABLE_COUNT)
+ return -EINVAL;
+
+ val = vega20_table_map[index];
+ if (val >= TABLE_COUNT)
+ return -EINVAL;
+
+ return val;
+}
+
+static int vega20_get_pwr_src_index(struct smu_context *smc, uint32_t index)
+{
+ int val;
+ if (index >= SMU_POWER_SOURCE_COUNT)
+ return -EINVAL;
+
+ val = vega20_pwr_src_map[index];
+ if (val >= POWER_SOURCE_COUNT)
+ return -EINVAL;
+
+ return val;
+}
+
+static int vega20_get_smu_feature_index(struct smu_context *smc, uint32_t index)
+{
+ int val;
+ if (index >= SMU_FEATURE_COUNT)
+ return -EINVAL;
+
+ val = vega20_feature_mask_map[index];
+ if (val > 64)
+ return -EINVAL;
+
+ return val;
+}
+
+static int vega20_get_smu_clk_index(struct smu_context *smc, uint32_t index)
+{
+ int val;
+ if (index >= SMU_CLK_COUNT)
+ return -EINVAL;
+
+ val = vega20_clk_map[index];
+ if (val >= PPCLK_COUNT)
+ return -EINVAL;
+
+ return val;
+}
+
static int vega20_get_smu_msg_index(struct smu_context *smc, uint32_t index)
{
int val;
@@ -143,6 +289,43 @@ static int vega20_get_smu_msg_index(struct smu_context *smc, uint32_t index)
return val;
}
+static int vega20_get_workload_type(struct smu_context *smu, enum PP_SMC_POWER_PROFILE profile)
+{
+ int val;
+ if (profile > PP_SMC_POWER_PROFILE_CUSTOM)
+ return -EINVAL;
+
+ val = vega20_workload_map[profile];
+
+ return val;
+}
+
+static int vega20_tables_init(struct smu_context *smu, struct smu_table *tables)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+
+ SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
+ sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM);
+
+ smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
+ if (smu_table->metrics_table)
+ return -ENOMEM;
+ smu_table->metrics_time = 0;
+
+ return 0;
+}
+
static int vega20_allocate_dpm_context(struct smu_context *smu)
{
struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
@@ -182,6 +365,7 @@ static int vega20_setup_od8_information(struct smu_context *smu)
{
ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
struct smu_table_context *table_context = &smu->smu_table;
+ struct vega20_od8_settings *od8_settings = (struct vega20_od8_settings *)smu->od_settings;
uint32_t od_feature_count, od_feature_array_size,
od_setting_count, od_setting_array_size;
@@ -202,13 +386,13 @@ static int vega20_setup_od8_information(struct smu_context *smu)
od_feature_array_size = sizeof(uint8_t) * od_feature_count;
- if (table_context->od_feature_capabilities)
+ if (od8_settings->od_feature_capabilities)
return -EINVAL;
- table_context->od_feature_capabilities = kmemdup(&powerplay_table->OverDrive8Table.ODFeatureCapabilities,
+ od8_settings->od_feature_capabilities = kmemdup(&powerplay_table->OverDrive8Table.ODFeatureCapabilities,
od_feature_array_size,
GFP_KERNEL);
- if (!table_context->od_feature_capabilities)
+ if (!od8_settings->od_feature_capabilities)
return -ENOMEM;
/* Setup correct ODSettingCount, and store ODSettingArray from
@@ -221,31 +405,31 @@ static int vega20_setup_od8_information(struct smu_context *smu)
od_setting_array_size = sizeof(uint32_t) * od_setting_count;
- if (table_context->od_settings_max)
+ if (od8_settings->od_settings_max)
return -EINVAL;
- table_context->od_settings_max = kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMax,
+ od8_settings->od_settings_max = kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMax,
od_setting_array_size,
GFP_KERNEL);
- if (!table_context->od_settings_max) {
- kfree(table_context->od_feature_capabilities);
- table_context->od_feature_capabilities = NULL;
+ if (!od8_settings->od_settings_max) {
+ kfree(od8_settings->od_feature_capabilities);
+ od8_settings->od_feature_capabilities = NULL;
return -ENOMEM;
}
- if (table_context->od_settings_min)
+ if (od8_settings->od_settings_min)
return -EINVAL;
- table_context->od_settings_min = kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMin,
+ od8_settings->od_settings_min = kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMin,
od_setting_array_size,
GFP_KERNEL);
- if (!table_context->od_settings_min) {
- kfree(table_context->od_feature_capabilities);
- table_context->od_feature_capabilities = NULL;
- kfree(table_context->od_settings_max);
- table_context->od_settings_max = NULL;
+ if (!od8_settings->od_settings_min) {
+ kfree(od8_settings->od_feature_capabilities);
+ od8_settings->od_feature_capabilities = NULL;
+ kfree(od8_settings->od_settings_max);
+ od8_settings->od_settings_max = NULL;
return -ENOMEM;
}
}
@@ -392,16 +576,42 @@ static int vega20_run_btc_afll(struct smu_context *smu)
return smu_send_smc_msg(smu, SMU_MSG_RunAfllBtc);
}
+#define FEATURE_MASK(feature) (1ULL << feature)
static int
-vega20_get_unallowed_feature_mask(struct smu_context *smu,
+vega20_get_allowed_feature_mask(struct smu_context *smu,
uint32_t *feature_mask, uint32_t num)
{
if (num > 2)
return -EINVAL;
- feature_mask[0] = 0xE0041C00;
- feature_mask[1] = 0xFFFFFFFE; /* bit32~bit63 is Unsupported */
-
+ memset(feature_mask, 0, sizeof(uint32_t) * num);
+
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT)
+ | FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT)
+ | FEATURE_MASK(FEATURE_DPM_UCLK_BIT)
+ | FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT)
+ | FEATURE_MASK(FEATURE_DPM_UVD_BIT)
+ | FEATURE_MASK(FEATURE_DPM_VCE_BIT)
+ | FEATURE_MASK(FEATURE_ULV_BIT)
+ | FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT)
+ | FEATURE_MASK(FEATURE_DPM_LINK_BIT)
+ | FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT)
+ | FEATURE_MASK(FEATURE_PPT_BIT)
+ | FEATURE_MASK(FEATURE_TDC_BIT)
+ | FEATURE_MASK(FEATURE_THERMAL_BIT)
+ | FEATURE_MASK(FEATURE_GFX_PER_CU_CG_BIT)
+ | FEATURE_MASK(FEATURE_RM_BIT)
+ | FEATURE_MASK(FEATURE_ACDC_BIT)
+ | FEATURE_MASK(FEATURE_VR0HOT_BIT)
+ | FEATURE_MASK(FEATURE_VR1HOT_BIT)
+ | FEATURE_MASK(FEATURE_FW_CTF_BIT)
+ | FEATURE_MASK(FEATURE_LED_DISPLAY_BIT)
+ | FEATURE_MASK(FEATURE_FAN_CONTROL_BIT)
+ | FEATURE_MASK(FEATURE_GFX_EDC_BIT)
+ | FEATURE_MASK(FEATURE_GFXOFF_BIT)
+ | FEATURE_MASK(FEATURE_CG_BIT)
+ | FEATURE_MASK(FEATURE_DPM_FCLK_BIT)
+ | FEATURE_MASK(FEATURE_XGMI_BIT);
return 0;
}
@@ -502,7 +712,7 @@ static int vega20_set_default_dpm_table(struct smu_context *smu)
/* socclk */
single_dpm_table = &(dpm_table->soc_table);
- if (smu_feature_is_enabled(smu, FEATURE_DPM_SOCCLK_BIT)) {
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
ret = vega20_set_single_dpm_table(smu, single_dpm_table,
PPCLK_SOCCLK);
if (ret) {
@@ -518,7 +728,7 @@ static int vega20_set_default_dpm_table(struct smu_context *smu)
/* gfxclk */
single_dpm_table = &(dpm_table->gfx_table);
- if (smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT)) {
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
ret = vega20_set_single_dpm_table(smu, single_dpm_table,
PPCLK_GFXCLK);
if (ret) {
@@ -534,7 +744,7 @@ static int vega20_set_default_dpm_table(struct smu_context *smu)
/* memclk */
single_dpm_table = &(dpm_table->mem_table);
- if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
ret = vega20_set_single_dpm_table(smu, single_dpm_table,
PPCLK_UCLK);
if (ret) {
@@ -550,7 +760,7 @@ static int vega20_set_default_dpm_table(struct smu_context *smu)
/* eclk */
single_dpm_table = &(dpm_table->eclk_table);
- if (smu_feature_is_enabled(smu, FEATURE_DPM_VCE_BIT)) {
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_VCE_BIT)) {
ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_ECLK);
if (ret) {
pr_err("[SetupDefaultDpmTable] failed to get eclk dpm levels!");
@@ -565,7 +775,7 @@ static int vega20_set_default_dpm_table(struct smu_context *smu)
/* vclk */
single_dpm_table = &(dpm_table->vclk_table);
- if (smu_feature_is_enabled(smu, FEATURE_DPM_UVD_BIT)) {
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) {
ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_VCLK);
if (ret) {
pr_err("[SetupDefaultDpmTable] failed to get vclk dpm levels!");
@@ -580,7 +790,7 @@ static int vega20_set_default_dpm_table(struct smu_context *smu)
/* dclk */
single_dpm_table = &(dpm_table->dclk_table);
- if (smu_feature_is_enabled(smu, FEATURE_DPM_UVD_BIT)) {
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) {
ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_DCLK);
if (ret) {
pr_err("[SetupDefaultDpmTable] failed to get dclk dpm levels!");
@@ -595,7 +805,7 @@ static int vega20_set_default_dpm_table(struct smu_context *smu)
/* dcefclk */
single_dpm_table = &(dpm_table->dcef_table);
- if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
ret = vega20_set_single_dpm_table(smu, single_dpm_table,
PPCLK_DCEFCLK);
if (ret) {
@@ -611,7 +821,7 @@ static int vega20_set_default_dpm_table(struct smu_context *smu)
/* pixclk */
single_dpm_table = &(dpm_table->pixel_table);
- if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
ret = vega20_set_single_dpm_table(smu, single_dpm_table,
PPCLK_PIXCLK);
if (ret) {
@@ -626,7 +836,7 @@ static int vega20_set_default_dpm_table(struct smu_context *smu)
/* dispclk */
single_dpm_table = &(dpm_table->display_table);
- if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
ret = vega20_set_single_dpm_table(smu, single_dpm_table,
PPCLK_DISPCLK);
if (ret) {
@@ -641,7 +851,7 @@ static int vega20_set_default_dpm_table(struct smu_context *smu)
/* phyclk */
single_dpm_table = &(dpm_table->phy_table);
- if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
ret = vega20_set_single_dpm_table(smu, single_dpm_table,
PPCLK_PHYCLK);
if (ret) {
@@ -719,7 +929,7 @@ static int vega20_get_clk_table(struct smu_context *smu,
}
static int vega20_print_clk_levels(struct smu_context *smu,
- enum pp_clock_type type, char *buf)
+ enum smu_clk_type type, char *buf)
{
int i, now, size = 0;
int ret = 0;
@@ -731,7 +941,7 @@ static int vega20_print_clk_levels(struct smu_context *smu,
struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
struct vega20_dpm_table *dpm_table = NULL;
struct vega20_od8_settings *od8_settings =
- (struct vega20_od8_settings *)table_context->od8_settings;
+ (struct vega20_od8_settings *)smu->od_settings;
OverDriveTable_t *od_table =
(OverDriveTable_t *)(table_context->overdrive_table);
PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable;
@@ -739,8 +949,8 @@ static int vega20_print_clk_levels(struct smu_context *smu,
dpm_table = smu_dpm->dpm_context;
switch (type) {
- case PP_SCLK:
- ret = smu_get_current_clk_freq(smu, PPCLK_GFXCLK, &now);
+ case SMU_SCLK:
+ ret = smu_get_current_clk_freq(smu, SMU_GFXCLK, &now);
if (ret) {
pr_err("Attempt to get current gfx clk Failed!");
return ret;
@@ -760,8 +970,8 @@ static int vega20_print_clk_levels(struct smu_context *smu,
? "*" : "");
break;
- case PP_MCLK:
- ret = smu_get_current_clk_freq(smu, PPCLK_UCLK, &now);
+ case SMU_MCLK:
+ ret = smu_get_current_clk_freq(smu, SMU_UCLK, &now);
if (ret) {
pr_err("Attempt to get current mclk Failed!");
return ret;
@@ -781,7 +991,7 @@ static int vega20_print_clk_levels(struct smu_context *smu,
? "*" : "");
break;
- case PP_SOCCLK:
+ case SMU_SOCCLK:
ret = smu_get_current_clk_freq(smu, PPCLK_SOCCLK, &now);
if (ret) {
pr_err("Attempt to get current socclk Failed!");
@@ -802,7 +1012,7 @@ static int vega20_print_clk_levels(struct smu_context *smu,
? "*" : "");
break;
- case PP_FCLK:
+ case SMU_FCLK:
ret = smu_get_current_clk_freq(smu, PPCLK_FCLK, &now);
if (ret) {
pr_err("Attempt to get current fclk Failed!");
@@ -817,7 +1027,7 @@ static int vega20_print_clk_levels(struct smu_context *smu,
? "*" : "");
break;
- case PP_DCEFCLK:
+ case SMU_DCEFCLK:
ret = smu_get_current_clk_freq(smu, PPCLK_DCEFCLK, &now);
if (ret) {
pr_err("Attempt to get current dcefclk Failed!");
@@ -837,7 +1047,7 @@ static int vega20_print_clk_levels(struct smu_context *smu,
(clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
break;
- case PP_PCIE:
+ case SMU_PCIE:
gen_speed = (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;
@@ -862,7 +1072,7 @@ static int vega20_print_clk_levels(struct smu_context *smu,
"*" : "");
break;
- case OD_SCLK:
+ case SMU_OD_SCLK:
if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) {
size = sprintf(buf, "%s:\n", "OD_SCLK");
@@ -874,7 +1084,7 @@ static int vega20_print_clk_levels(struct smu_context *smu,
break;
- case OD_MCLK:
+ case SMU_OD_MCLK:
if (od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
size = sprintf(buf, "%s:\n", "OD_MCLK");
size += sprintf(buf + size, "1: %10uMhz\n",
@@ -883,7 +1093,7 @@ static int vega20_print_clk_levels(struct smu_context *smu,
break;
- case OD_VDDC_CURVE:
+ case SMU_OD_VDDC_CURVE:
if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
@@ -904,7 +1114,7 @@ static int vega20_print_clk_levels(struct smu_context *smu,
break;
- case OD_RANGE:
+ case SMU_OD_RANGE:
size = sprintf(buf, "%s:\n", "OD_RANGE");
if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
@@ -971,7 +1181,7 @@ static int vega20_upload_dpm_level(struct smu_context *smu, bool max,
dpm_table = smu->smu_dpm.dpm_context;
- if (smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT) &&
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT) &&
(feature_mask & FEATURE_DPM_GFXCLK_MASK)) {
single_dpm_table = &(dpm_table->gfx_table);
freq = max ? single_dpm_table->dpm_state.soft_max_level :
@@ -986,7 +1196,7 @@ static int vega20_upload_dpm_level(struct smu_context *smu, bool max,
}
}
- if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT) &&
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT) &&
(feature_mask & FEATURE_DPM_UCLK_MASK)) {
single_dpm_table = &(dpm_table->mem_table);
freq = max ? single_dpm_table->dpm_state.soft_max_level :
@@ -1001,7 +1211,7 @@ static int vega20_upload_dpm_level(struct smu_context *smu, bool max,
}
}
- if (smu_feature_is_enabled(smu, FEATURE_DPM_SOCCLK_BIT) &&
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT) &&
(feature_mask & FEATURE_DPM_SOCCLK_MASK)) {
single_dpm_table = &(dpm_table->soc_table);
freq = max ? single_dpm_table->dpm_state.soft_max_level :
@@ -1016,7 +1226,7 @@ static int vega20_upload_dpm_level(struct smu_context *smu, bool max,
}
}
- if (smu_feature_is_enabled(smu, FEATURE_DPM_FCLK_BIT) &&
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT) &&
(feature_mask & FEATURE_DPM_FCLK_MASK)) {
single_dpm_table = &(dpm_table->fclk_table);
freq = max ? single_dpm_table->dpm_state.soft_max_level :
@@ -1031,7 +1241,7 @@ static int vega20_upload_dpm_level(struct smu_context *smu, bool max,
}
}
- if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT) &&
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
(feature_mask & FEATURE_DPM_DCEFCLK_MASK)) {
single_dpm_table = &(dpm_table->dcef_table);
freq = single_dpm_table->dpm_state.hard_min_level;
@@ -1050,7 +1260,7 @@ static int vega20_upload_dpm_level(struct smu_context *smu, bool max,
}
static int vega20_force_clk_levels(struct smu_context *smu,
- enum pp_clock_type type, uint32_t mask)
+ enum smu_clk_type clk_type, uint32_t mask)
{
struct vega20_dpm_table *dpm_table;
struct vega20_single_dpm_table *single_dpm_table;
@@ -1070,8 +1280,8 @@ static int vega20_force_clk_levels(struct smu_context *smu,
dpm_table = smu->smu_dpm.dpm_context;
- switch (type) {
- case PP_SCLK:
+ switch (clk_type) {
+ case SMU_SCLK:
single_dpm_table = &(dpm_table->gfx_table);
if (soft_max_level >= single_dpm_table->count) {
@@ -1098,7 +1308,7 @@ static int vega20_force_clk_levels(struct smu_context *smu,
break;
- case PP_MCLK:
+ case SMU_MCLK:
single_dpm_table = &(dpm_table->mem_table);
if (soft_max_level >= single_dpm_table->count) {
@@ -1125,7 +1335,7 @@ static int vega20_force_clk_levels(struct smu_context *smu,
break;
- case PP_SOCCLK:
+ case SMU_SOCCLK:
single_dpm_table = &(dpm_table->soc_table);
if (soft_max_level >= single_dpm_table->count) {
@@ -1152,7 +1362,7 @@ static int vega20_force_clk_levels(struct smu_context *smu,
break;
- case PP_FCLK:
+ case SMU_FCLK:
single_dpm_table = &(dpm_table->fclk_table);
if (soft_max_level >= single_dpm_table->count) {
@@ -1179,7 +1389,7 @@ static int vega20_force_clk_levels(struct smu_context *smu,
break;
- case PP_DCEFCLK:
+ case SMU_DCEFCLK:
hard_min_level = soft_min_level;
single_dpm_table = &(dpm_table->dcef_table);
@@ -1199,7 +1409,7 @@ static int vega20_force_clk_levels(struct smu_context *smu,
break;
- case PP_PCIE:
+ case SMU_PCIE:
if (soft_min_level >= NUM_LINK_LEVELS ||
soft_max_level >= NUM_LINK_LEVELS) {
ret = -EINVAL;
@@ -1222,7 +1432,7 @@ static int vega20_force_clk_levels(struct smu_context *smu,
}
static int vega20_get_clock_by_type_with_latency(struct smu_context *smu,
- enum amd_pp_clock_type type,
+ enum smu_clk_type clk_type,
struct pp_clock_levels_with_latency *clocks)
{
int ret;
@@ -1234,20 +1444,20 @@ static int vega20_get_clock_by_type_with_latency(struct smu_context *smu,
mutex_lock(&smu->mutex);
- switch (type) {
- case amd_pp_sys_clock:
+ switch (clk_type) {
+ case SMU_GFXCLK:
single_dpm_table = &(dpm_table->gfx_table);
ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
break;
- case amd_pp_mem_clock:
+ case SMU_MCLK:
single_dpm_table = &(dpm_table->mem_table);
ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
break;
- case amd_pp_dcef_clock:
+ case SMU_DCEFCLK:
single_dpm_table = &(dpm_table->dcef_table);
ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
break;
- case amd_pp_soc_clock:
+ case SMU_SOCCLK:
single_dpm_table = &(dpm_table->soc_table);
ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
break;
@@ -1287,23 +1497,22 @@ static int vega20_set_default_od8_setttings(struct smu_context *smu)
PPTable_t *smc_pptable = table_context->driver_pptable;
int i, ret;
- if (table_context->od8_settings)
+ if (smu->od_settings)
return -EINVAL;
- table_context->od8_settings = kzalloc(sizeof(struct vega20_od8_settings), GFP_KERNEL);
+ od8_settings = kzalloc(sizeof(struct vega20_od8_settings), GFP_KERNEL);
- if (!table_context->od8_settings)
+ if (od8_settings)
return -ENOMEM;
- memset(table_context->od8_settings, 0, sizeof(struct vega20_od8_settings));
- od8_settings = (struct vega20_od8_settings *)table_context->od8_settings;
+ smu->od_settings = (void *)od8_settings;
- if (smu_feature_is_enabled(smu, FEATURE_DPM_SOCCLK_BIT)) {
- if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] &&
- table_context->od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 &&
- table_context->od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 &&
- (table_context->od_settings_max[OD8_SETTING_GFXCLK_FMAX] >=
- table_context->od_settings_min[OD8_SETTING_GFXCLK_FMIN])) {
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
+ if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] &&
+ od8_settings->od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 &&
+ od8_settings->od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 &&
+ (od8_settings->od_settings_max[OD8_SETTING_GFXCLK_FMAX] >=
+ od8_settings->od_settings_min[OD8_SETTING_GFXCLK_FMIN])) {
od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id =
OD8_GFXCLK_LIMITS;
od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id =
@@ -1314,13 +1523,13 @@ static int vega20_set_default_od8_setttings(struct smu_context *smu)
od_table->GfxclkFmax;
}
- if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] &&
- (table_context->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >=
+ if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] &&
+ (od8_settings->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >=
smc_pptable->MinVoltageGfx / VOLTAGE_SCALE) &&
- (table_context->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <=
+ (od8_settings->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <=
smc_pptable->MaxVoltageGfx / VOLTAGE_SCALE) &&
- (table_context->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] <=
- table_context->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3])) {
+ (od8_settings->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] <=
+ od8_settings->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3])) {
od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id =
OD8_GFXCLK_CURVE;
od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id =
@@ -1371,12 +1580,12 @@ static int vega20_set_default_od8_setttings(struct smu_context *smu)
}
}
- if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
- if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] &&
- table_context->od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 &&
- table_context->od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 &&
- (table_context->od_settings_max[OD8_SETTING_UCLK_FMAX] >=
- table_context->od_settings_min[OD8_SETTING_UCLK_FMAX])) {
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
+ if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] &&
+ od8_settings->od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 &&
+ od8_settings->od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 &&
+ (od8_settings->od_settings_max[OD8_SETTING_UCLK_FMAX] >=
+ od8_settings->od_settings_min[OD8_SETTING_UCLK_FMAX])) {
od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id =
OD8_UCLK_MAX;
od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value =
@@ -1384,34 +1593,34 @@ static int vega20_set_default_od8_setttings(struct smu_context *smu)
}
}
- if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] &&
- table_context->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
- table_context->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100 &&
- table_context->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
- table_context->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100) {
+ if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] &&
+ od8_settings->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
+ od8_settings->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100 &&
+ od8_settings->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
+ od8_settings->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100) {
od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id =
OD8_POWER_LIMIT;
od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value =
od_table->OverDrivePct;
}
- if (smu_feature_is_enabled(smu, FEATURE_FAN_CONTROL_BIT)) {
- if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT] &&
- table_context->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
- table_context->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
- (table_context->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >=
- table_context->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT])) {
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT)) {
+ if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT] &&
+ od8_settings->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
+ od8_settings->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
+ (od8_settings->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >=
+ od8_settings->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT])) {
od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id =
OD8_ACOUSTIC_LIMIT_SCLK;
od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value =
od_table->FanMaximumRpm;
}
- if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] &&
- table_context->od_settings_min[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
- table_context->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
- (table_context->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >=
- table_context->od_settings_min[OD8_SETTING_FAN_MIN_SPEED])) {
+ if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] &&
+ od8_settings->od_settings_min[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
+ od8_settings->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
+ (od8_settings->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >=
+ od8_settings->od_settings_min[OD8_SETTING_FAN_MIN_SPEED])) {
od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id =
OD8_FAN_SPEED_MIN;
od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value =
@@ -1419,23 +1628,23 @@ static int vega20_set_default_od8_setttings(struct smu_context *smu)
}
}
- if (smu_feature_is_enabled(smu, FEATURE_THERMAL_BIT)) {
- if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN] &&
- table_context->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
- table_context->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
- (table_context->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >=
- table_context->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP])) {
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_THERMAL_BIT)) {
+ if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN] &&
+ od8_settings->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
+ od8_settings->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
+ (od8_settings->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >=
+ od8_settings->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP])) {
od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id =
OD8_TEMPERATURE_FAN;
od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value =
od_table->FanTargetTemperature;
}
- if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM] &&
- table_context->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
- table_context->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
- (table_context->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >=
- table_context->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX])) {
+ if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM] &&
+ od8_settings->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
+ od8_settings->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
+ (od8_settings->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >=
+ od8_settings->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX])) {
od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id =
OD8_TEMPERATURE_SYSTEM;
od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value =
@@ -1446,9 +1655,9 @@ static int vega20_set_default_od8_setttings(struct smu_context *smu)
for (i = 0; i < OD8_SETTING_COUNT; i++) {
if (od8_settings->od8_settings_array[i].feature_id) {
od8_settings->od8_settings_array[i].min_value =
- table_context->od_settings_min[i];
+ od8_settings->od_settings_min[i];
od8_settings->od8_settings_array[i].max_value =
- table_context->od_settings_max[i];
+ od8_settings->od_settings_max[i];
od8_settings->od8_settings_array[i].current_value =
od8_settings->od8_settings_array[i].default_value;
} else {
@@ -1461,8 +1670,66 @@ static int vega20_set_default_od8_setttings(struct smu_context *smu)
return 0;
}
+static int vega20_get_metrics_table(struct smu_context *smu,
+ SmuMetrics_t *metrics_table)
+{
+ struct smu_table_context *smu_table= &smu->smu_table;
+ int ret = 0;
+
+ if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + HZ / 1000)) {
+ ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS,
+ (void *)smu_table->metrics_table, false);
+ if (ret) {
+ pr_info("Failed to export SMU metrics table!\n");
+ return ret;
+ }
+ smu_table->metrics_time = jiffies;
+ }
+
+ memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t));
+
+ return ret;
+}
+
+static int vega20_set_default_od_settings(struct smu_context *smu,
+ bool initialize)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ int ret;
+
+ if (initialize) {
+ if (table_context->overdrive_table)
+ return -EINVAL;
+
+ table_context->overdrive_table = kzalloc(sizeof(OverDriveTable_t), GFP_KERNEL);
+
+ if (!table_context->overdrive_table)
+ return -ENOMEM;
+
+ ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE,
+ table_context->overdrive_table, false);
+ if (ret) {
+ pr_err("Failed to export over drive table!\n");
+ return ret;
+ }
+
+ ret = vega20_set_default_od8_setttings(smu);
+ if (ret)
+ return ret;
+ }
+
+ ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE,
+ table_context->overdrive_table, true);
+ if (ret) {
+ pr_err("Failed to import over drive table!\n");
+ return ret;
+ }
+
+ return 0;
+}
+
static int vega20_get_od_percentage(struct smu_context *smu,
- enum pp_clock_type type)
+ enum smu_clk_type clk_type)
{
struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
struct vega20_dpm_table *dpm_table = NULL;
@@ -1474,12 +1741,12 @@ static int vega20_get_od_percentage(struct smu_context *smu,
dpm_table = smu_dpm->dpm_context;
golden_table = smu_dpm->golden_dpm_context;
- switch (type) {
- case OD_SCLK:
+ switch (clk_type) {
+ case SMU_OD_SCLK:
single_dpm_table = &(dpm_table->gfx_table);
golden_dpm_table = &(golden_table->gfx_table);
break;
- case OD_MCLK:
+ case SMU_OD_MCLK:
single_dpm_table = &(dpm_table->mem_table);
golden_dpm_table = &(golden_table->mem_table);
break;
@@ -1497,6 +1764,201 @@ static int vega20_get_od_percentage(struct smu_context *smu,
return value;
}
+static int vega20_get_power_profile_mode(struct smu_context *smu, char *buf)
+{
+ DpmActivityMonitorCoeffInt_t activity_monitor;
+ uint32_t i, size = 0;
+ uint16_t workload_type = 0;
+ static const char *profile_name[] = {
+ "BOOTUP_DEFAULT",
+ "3D_FULL_SCREEN",
+ "POWER_SAVING",
+ "VIDEO",
+ "VR",
+ "COMPUTE",
+ "CUSTOM"};
+ static const char *title[] = {
+ "PROFILE_INDEX(NAME)",
+ "CLOCK_TYPE(NAME)",
+ "FPS",
+ "UseRlcBusy",
+ "MinActiveFreqType",
+ "MinActiveFreq",
+ "BoosterFreqType",
+ "BoosterFreq",
+ "PD_Data_limit_c",
+ "PD_Data_error_coeff",
+ "PD_Data_error_rate_coeff"};
+ int result = 0;
+
+ if (!smu->pm_enabled || !buf)
+ return -EINVAL;
+
+ size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
+ title[0], title[1], title[2], title[3], title[4], title[5],
+ title[6], title[7], title[8], title[9], title[10]);
+
+ for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
+ /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
+ workload_type = smu_workload_get_type(smu, i);
+ result = smu_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF | workload_type << 16,
+ (void *)(&activity_monitor), false);
+ if (result) {
+ pr_err("[%s] Failed to get activity monitor!", __func__);
+ return result;
+ }
+
+ size += sprintf(buf + size, "%2d %14s%s:\n",
+ i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
+
+ size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
+ " ",
+ 0,
+ "GFXCLK",
+ activity_monitor.Gfx_FPS,
+ activity_monitor.Gfx_UseRlcBusy,
+ activity_monitor.Gfx_MinActiveFreqType,
+ activity_monitor.Gfx_MinActiveFreq,
+ activity_monitor.Gfx_BoosterFreqType,
+ activity_monitor.Gfx_BoosterFreq,
+ activity_monitor.Gfx_PD_Data_limit_c,
+ activity_monitor.Gfx_PD_Data_error_coeff,
+ activity_monitor.Gfx_PD_Data_error_rate_coeff);
+
+ size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
+ " ",
+ 1,
+ "SOCCLK",
+ activity_monitor.Soc_FPS,
+ activity_monitor.Soc_UseRlcBusy,
+ activity_monitor.Soc_MinActiveFreqType,
+ activity_monitor.Soc_MinActiveFreq,
+ activity_monitor.Soc_BoosterFreqType,
+ activity_monitor.Soc_BoosterFreq,
+ activity_monitor.Soc_PD_Data_limit_c,
+ activity_monitor.Soc_PD_Data_error_coeff,
+ activity_monitor.Soc_PD_Data_error_rate_coeff);
+
+ size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
+ " ",
+ 2,
+ "UCLK",
+ activity_monitor.Mem_FPS,
+ activity_monitor.Mem_UseRlcBusy,
+ activity_monitor.Mem_MinActiveFreqType,
+ activity_monitor.Mem_MinActiveFreq,
+ activity_monitor.Mem_BoosterFreqType,
+ activity_monitor.Mem_BoosterFreq,
+ activity_monitor.Mem_PD_Data_limit_c,
+ activity_monitor.Mem_PD_Data_error_coeff,
+ activity_monitor.Mem_PD_Data_error_rate_coeff);
+
+ size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
+ " ",
+ 3,
+ "FCLK",
+ activity_monitor.Fclk_FPS,
+ activity_monitor.Fclk_UseRlcBusy,
+ activity_monitor.Fclk_MinActiveFreqType,
+ activity_monitor.Fclk_MinActiveFreq,
+ activity_monitor.Fclk_BoosterFreqType,
+ activity_monitor.Fclk_BoosterFreq,
+ activity_monitor.Fclk_PD_Data_limit_c,
+ activity_monitor.Fclk_PD_Data_error_coeff,
+ activity_monitor.Fclk_PD_Data_error_rate_coeff);
+ }
+
+ return size;
+}
+
+static int vega20_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
+{
+ DpmActivityMonitorCoeffInt_t activity_monitor;
+ int workload_type = 0, ret = 0;
+
+ smu->power_profile_mode = input[size];
+
+ if (!smu->pm_enabled)
+ return ret;
+ if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
+ pr_err("Invalid power profile mode %d\n", smu->power_profile_mode);
+ return -EINVAL;
+ }
+
+ if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
+ ret = smu_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF | WORKLOAD_PPLIB_CUSTOM_BIT << 16,
+ (void *)(&activity_monitor), false);
+ if (ret) {
+ pr_err("[%s] Failed to get activity monitor!", __func__);
+ return ret;
+ }
+
+ switch (input[0]) {
+ case 0: /* Gfxclk */
+ activity_monitor.Gfx_FPS = input[1];
+ activity_monitor.Gfx_UseRlcBusy = input[2];
+ activity_monitor.Gfx_MinActiveFreqType = input[3];
+ activity_monitor.Gfx_MinActiveFreq = input[4];
+ activity_monitor.Gfx_BoosterFreqType = input[5];
+ activity_monitor.Gfx_BoosterFreq = input[6];
+ activity_monitor.Gfx_PD_Data_limit_c = input[7];
+ activity_monitor.Gfx_PD_Data_error_coeff = input[8];
+ activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
+ break;
+ case 1: /* Socclk */
+ activity_monitor.Soc_FPS = input[1];
+ activity_monitor.Soc_UseRlcBusy = input[2];
+ activity_monitor.Soc_MinActiveFreqType = input[3];
+ activity_monitor.Soc_MinActiveFreq = input[4];
+ activity_monitor.Soc_BoosterFreqType = input[5];
+ activity_monitor.Soc_BoosterFreq = input[6];
+ activity_monitor.Soc_PD_Data_limit_c = input[7];
+ activity_monitor.Soc_PD_Data_error_coeff = input[8];
+ activity_monitor.Soc_PD_Data_error_rate_coeff = input[9];
+ break;
+ case 2: /* Uclk */
+ activity_monitor.Mem_FPS = input[1];
+ activity_monitor.Mem_UseRlcBusy = input[2];
+ activity_monitor.Mem_MinActiveFreqType = input[3];
+ activity_monitor.Mem_MinActiveFreq = input[4];
+ activity_monitor.Mem_BoosterFreqType = input[5];
+ activity_monitor.Mem_BoosterFreq = input[6];
+ activity_monitor.Mem_PD_Data_limit_c = input[7];
+ activity_monitor.Mem_PD_Data_error_coeff = input[8];
+ activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
+ break;
+ case 3: /* Fclk */
+ activity_monitor.Fclk_FPS = input[1];
+ activity_monitor.Fclk_UseRlcBusy = input[2];
+ activity_monitor.Fclk_MinActiveFreqType = input[3];
+ activity_monitor.Fclk_MinActiveFreq = input[4];
+ activity_monitor.Fclk_BoosterFreqType = input[5];
+ activity_monitor.Fclk_BoosterFreq = input[6];
+ activity_monitor.Fclk_PD_Data_limit_c = input[7];
+ activity_monitor.Fclk_PD_Data_error_coeff = input[8];
+ activity_monitor.Fclk_PD_Data_error_rate_coeff = input[9];
+ break;
+ }
+
+ ret = smu_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF | WORKLOAD_PPLIB_CUSTOM_BIT << 16,
+ (void *)(&activity_monitor), true);
+ if (ret) {
+ pr_err("[%s] Failed to set activity monitor!", __func__);
+ return ret;
+ }
+ }
+
+ /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
+ workload_type = smu_workload_get_type(smu, smu->power_profile_mode);
+ smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
+ 1 << workload_type);
+
+ return ret;
+}
+
static int
vega20_get_profiling_clk_mask(struct smu_context *smu,
enum amd_dpm_forced_level level,
@@ -1550,7 +2012,7 @@ vega20_set_uclk_to_highest_dpm_level(struct smu_context *smu,
if (!smu_dpm_ctx->dpm_context)
return -EINVAL;
- if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
if (dpm_table->count <= 0) {
pr_err("[%s] Dpm table has no entry!", __func__);
return -EINVAL;
@@ -1594,17 +2056,9 @@ static int vega20_display_config_changed(struct smu_context *smu)
{
int ret = 0;
- if (!smu->funcs)
- return -EINVAL;
-
- if (!smu->smu_dpm.dpm_context ||
- !smu->smu_table.tables ||
- !smu->smu_table.tables[TABLE_WATERMARKS].cpu_addr)
- return -EINVAL;
-
if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
!(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
- ret = smu->funcs->write_watermarks_table(smu);
+ ret = smu_write_watermarks_table(smu);
if (ret) {
pr_err("Failed to update WMTABLE!");
return ret;
@@ -1613,8 +2067,8 @@ static int vega20_display_config_changed(struct smu_context *smu)
}
if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
- smu_feature_is_supported(smu, FEATURE_DPM_DCEFCLK_BIT) &&
- smu_feature_is_supported(smu, FEATURE_DPM_SOCCLK_BIT)) {
+ smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
+ smu_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
smu_send_smc_msg_with_param(smu,
SMU_MSG_NumOfDisplays,
smu->display_config->num_display);
@@ -1783,11 +2237,11 @@ vega20_notify_smc_dispaly_config(struct smu_context *smu)
min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk;
min_clocks.memory_clock = smu->display_config->min_mem_set_clock;
- if (smu_feature_is_supported(smu, FEATURE_DPM_DCEFCLK_BIT)) {
+ if (smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
clock_req.clock_type = amd_pp_dcef_clock;
clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10;
if (!smu->funcs->display_clock_voltage_request(smu, &clock_req)) {
- if (smu_feature_is_supported(smu, FEATURE_DS_DCEFCLK_BIT)) {
+ if (smu_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) {
ret = smu_send_smc_msg_with_param(smu,
SMU_MSG_SetMinDeepSleepDcefclk,
min_clocks.dcef_clock_in_sr/100);
@@ -1801,7 +2255,7 @@ vega20_notify_smc_dispaly_config(struct smu_context *smu)
}
}
- if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
memtable->dpm_state.hard_min_level = min_clocks.memory_clock/100;
ret = smu_send_smc_msg_with_param(smu,
SMU_MSG_SetHardMinByFreq,
@@ -1939,13 +2393,13 @@ static int vega20_unforce_dpm_levels(struct smu_context *smu)
dpm_table->soc_table.dpm_state.soft_max_level =
dpm_table->soc_table.dpm_levels[soft_max_level].value;
- ret = smu_upload_dpm_level(smu, false, 0xFFFFFFFF);
+ ret = vega20_upload_dpm_level(smu, false, 0xFFFFFFFF);
if (ret) {
pr_err("Failed to upload DPM Bootup Levels!");
return ret;
}
- ret = smu_upload_dpm_level(smu, true, 0xFFFFFFFF);
+ ret = vega20_upload_dpm_level(smu, true, 0xFFFFFFFF);
if (ret) {
pr_err("Failed to upload DPM Max Levels!");
return ret;
@@ -1954,46 +2408,6 @@ static int vega20_unforce_dpm_levels(struct smu_context *smu)
return ret;
}
-static enum amd_dpm_forced_level vega20_get_performance_level(struct smu_context *smu)
-{
- struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
- if (!smu_dpm_ctx->dpm_context)
- return -EINVAL;
-
- if (smu_dpm_ctx->dpm_level != smu_dpm_ctx->saved_dpm_level) {
- mutex_lock(&(smu->mutex));
- smu_dpm_ctx->saved_dpm_level = smu_dpm_ctx->dpm_level;
- mutex_unlock(&(smu->mutex));
- }
- return smu_dpm_ctx->dpm_level;
-}
-
-static int
-vega20_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
-{
- int ret = 0;
- int i;
- struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
-
- if (!smu_dpm_ctx->dpm_context)
- return -EINVAL;
-
- for (i = 0; i < smu->adev->num_ip_blocks; i++) {
- if (smu->adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC)
- break;
- }
-
- mutex_lock(&smu->mutex);
-
- smu->adev->ip_blocks[i].version->funcs->enable_umd_pstate(smu, &level);
- ret = smu_handle_task(smu, level,
- AMD_PP_TASK_READJUST_POWER_STATE);
-
- mutex_unlock(&smu->mutex);
-
- return ret;
-}
-
static int vega20_update_specified_od8_value(struct smu_context *smu,
uint32_t index,
uint32_t value)
@@ -2002,7 +2416,7 @@ static int vega20_update_specified_od8_value(struct smu_context *smu,
OverDriveTable_t *od_table =
(OverDriveTable_t *)(table_context->overdrive_table);
struct vega20_od8_settings *od8_settings =
- (struct vega20_od8_settings *)table_context->od8_settings;
+ (struct vega20_od8_settings *)smu->od_settings;
switch (index) {
case OD8_SETTING_GFXCLK_FMIN:
@@ -2071,8 +2485,36 @@ static int vega20_update_specified_od8_value(struct smu_context *smu,
return 0;
}
+static int vega20_update_od8_settings(struct smu_context *smu,
+ uint32_t index,
+ uint32_t value)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ int ret;
+
+ ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE,
+ table_context->overdrive_table, false);
+ if (ret) {
+ pr_err("Failed to export over drive table!\n");
+ return ret;
+ }
+
+ ret = vega20_update_specified_od8_value(smu, index, value);
+ if (ret)
+ return ret;
+
+ ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE,
+ table_context->overdrive_table, true);
+ if (ret) {
+ pr_err("Failed to import over drive table!\n");
+ return ret;
+ }
+
+ return 0;
+}
+
static int vega20_set_od_percentage(struct smu_context *smu,
- enum pp_clock_type type,
+ enum smu_clk_type clk_type,
uint32_t value)
{
struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
@@ -2090,18 +2532,18 @@ static int vega20_set_od_percentage(struct smu_context *smu,
dpm_table = smu_dpm->dpm_context;
golden_table = smu_dpm->golden_dpm_context;
- switch (type) {
- case OD_SCLK:
+ switch (clk_type) {
+ case SMU_OD_SCLK:
single_dpm_table = &(dpm_table->gfx_table);
golden_dpm_table = &(golden_table->gfx_table);
- feature_enabled = smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT);
+ feature_enabled = smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT);
clk_id = PPCLK_GFXCLK;
index = OD8_SETTING_GFXCLK_FMAX;
break;
- case OD_MCLK:
+ case SMU_OD_MCLK:
single_dpm_table = &(dpm_table->mem_table);
golden_dpm_table = &(golden_table->mem_table);
- feature_enabled = smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT);
+ feature_enabled = smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT);
clk_id = PPCLK_UCLK;
index = OD8_SETTING_UCLK_FMAX;
break;
@@ -2117,7 +2559,7 @@ static int vega20_set_od_percentage(struct smu_context *smu,
od_clk /= 100;
od_clk += golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value;
- ret = smu_update_od8_settings(smu, index, od_clk);
+ ret = vega20_update_od8_settings(smu, index, od_clk);
if (ret) {
pr_err("[Setoverdrive] failed to set od clk!\n");
goto set_od_failed;
@@ -2155,7 +2597,7 @@ static int vega20_odn_edit_dpm_table(struct smu_context *smu,
struct vega20_dpm_table *dpm_table = NULL;
struct vega20_single_dpm_table *single_dpm_table;
struct vega20_od8_settings *od8_settings =
- (struct vega20_od8_settings *)table_context->od8_settings;
+ (struct vega20_od8_settings *)smu->od_settings;
struct pp_clock_levels_with_latency clocks;
int32_t input_index, input_clk, input_vol, i;
int od8_id;
@@ -2202,10 +2644,10 @@ static int vega20_odn_edit_dpm_table(struct smu_context *smu,
if (input_index == 0 && od_table->GfxclkFmin != input_clk) {
od_table->GfxclkFmin = input_clk;
- table_context->od_gfxclk_update = true;
+ od8_settings->od_gfxclk_update = true;
} else if (input_index == 1 && od_table->GfxclkFmax != input_clk) {
od_table->GfxclkFmax = input_clk;
- table_context->od_gfxclk_update = true;
+ od8_settings->od_gfxclk_update = true;
}
}
@@ -2250,7 +2692,7 @@ static int vega20_odn_edit_dpm_table(struct smu_context *smu,
}
if (input_index == 1 && od_table->UclkFmax != input_clk) {
- table_context->od_gfxclk_update = true;
+ od8_settings->od_gfxclk_update = true;
od_table->UclkFmax = input_clk;
}
}
@@ -2325,7 +2767,7 @@ static int vega20_odn_edit_dpm_table(struct smu_context *smu,
break;
case PP_OD_RESTORE_DEFAULT_TABLE:
- ret = smu_update_table(smu, TABLE_OVERDRIVE, table_context->overdrive_table, false);
+ ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, table_context->overdrive_table, false);
if (ret) {
pr_err("Failed to export over drive table!\n");
return ret;
@@ -2334,18 +2776,18 @@ static int vega20_odn_edit_dpm_table(struct smu_context *smu,
break;
case PP_OD_COMMIT_DPM_TABLE:
- ret = smu_update_table(smu, TABLE_OVERDRIVE, table_context->overdrive_table, true);
+ ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, table_context->overdrive_table, true);
if (ret) {
pr_err("Failed to import over drive table!\n");
return ret;
}
/* retrieve updated gfxclk table */
- if (table_context->od_gfxclk_update) {
- table_context->od_gfxclk_update = false;
+ if (od8_settings->od_gfxclk_update) {
+ od8_settings->od_gfxclk_update = false;
single_dpm_table = &(dpm_table->gfx_table);
- if (smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT)) {
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
ret = vega20_set_single_dpm_table(smu, single_dpm_table,
PPCLK_GFXCLK);
if (ret) {
@@ -2374,14 +2816,452 @@ static int vega20_odn_edit_dpm_table(struct smu_context *smu,
return ret;
}
+static int vega20_dpm_set_uvd_enable(struct smu_context *smu, bool enable)
+{
+ if (!smu_feature_is_supported(smu, SMU_FEATURE_DPM_UVD_BIT))
+ return 0;
+
+ if (enable == smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT))
+ return 0;
+
+ return smu_feature_set_enabled(smu, SMU_FEATURE_DPM_UVD_BIT, enable);
+}
+
+static int vega20_dpm_set_vce_enable(struct smu_context *smu, bool enable)
+{
+ if (!smu_feature_is_supported(smu, SMU_FEATURE_DPM_VCE_BIT))
+ return 0;
+
+ if (enable == smu_feature_is_enabled(smu, SMU_FEATURE_DPM_VCE_BIT))
+ return 0;
+
+ return smu_feature_set_enabled(smu, SMU_FEATURE_DPM_VCE_BIT, enable);
+}
+
+static int vega20_get_enabled_smc_features(struct smu_context *smu,
+ uint64_t *features_enabled)
+{
+ uint32_t feature_mask[2] = {0, 0};
+ int ret = 0;
+
+ ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
+ if (ret)
+ return ret;
+
+ *features_enabled = ((((uint64_t)feature_mask[0] << SMU_FEATURES_LOW_SHIFT) & SMU_FEATURES_LOW_MASK) |
+ (((uint64_t)feature_mask[1] << SMU_FEATURES_HIGH_SHIFT) & SMU_FEATURES_HIGH_MASK));
+
+ return ret;
+}
+
+static int vega20_enable_smc_features(struct smu_context *smu,
+ bool enable, uint64_t feature_mask)
+{
+ uint32_t smu_features_low, smu_features_high;
+ int ret = 0;
+
+ smu_features_low = (uint32_t)((feature_mask & SMU_FEATURES_LOW_MASK) >> SMU_FEATURES_LOW_SHIFT);
+ smu_features_high = (uint32_t)((feature_mask & SMU_FEATURES_HIGH_MASK) >> SMU_FEATURES_HIGH_SHIFT);
+
+ if (enable) {
+ ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnableSmuFeaturesLow,
+ smu_features_low);
+ if (ret)
+ return ret;
+ ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnableSmuFeaturesHigh,
+ smu_features_high);
+ if (ret)
+ return ret;
+ } else {
+ ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DisableSmuFeaturesLow,
+ smu_features_low);
+ if (ret)
+ return ret;
+ ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DisableSmuFeaturesHigh,
+ smu_features_high);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+
+}
+
+static int vega20_get_ppfeature_status(struct smu_context *smu, char *buf)
+{
+ static const char *ppfeature_name[] = {
+ "DPM_PREFETCHER",
+ "GFXCLK_DPM",
+ "UCLK_DPM",
+ "SOCCLK_DPM",
+ "UVD_DPM",
+ "VCE_DPM",
+ "ULV",
+ "MP0CLK_DPM",
+ "LINK_DPM",
+ "DCEFCLK_DPM",
+ "GFXCLK_DS",
+ "SOCCLK_DS",
+ "LCLK_DS",
+ "PPT",
+ "TDC",
+ "THERMAL",
+ "GFX_PER_CU_CG",
+ "RM",
+ "DCEFCLK_DS",
+ "ACDC",
+ "VR0HOT",
+ "VR1HOT",
+ "FW_CTF",
+ "LED_DISPLAY",
+ "FAN_CONTROL",
+ "GFX_EDC",
+ "GFXOFF",
+ "CG",
+ "FCLK_DPM",
+ "FCLK_DS",
+ "MP1CLK_DS",
+ "MP0CLK_DS",
+ "XGMI",
+ "ECC"};
+ static const char *output_title[] = {
+ "FEATURES",
+ "BITMASK",
+ "ENABLEMENT"};
+ uint64_t features_enabled;
+ int i;
+ int ret = 0;
+ int size = 0;
+
+ ret = vega20_get_enabled_smc_features(smu, &features_enabled);
+ if (ret)
+ return ret;
+
+ size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled);
+ size += sprintf(buf + size, "%-19s %-22s %s\n",
+ output_title[0],
+ output_title[1],
+ output_title[2]);
+ for (i = 0; i < GNLD_FEATURES_MAX; i++) {
+ size += sprintf(buf + size, "%-19s 0x%016llx %6s\n",
+ ppfeature_name[i],
+ 1ULL << i,
+ (features_enabled & (1ULL << i)) ? "Y" : "N");
+ }
+
+ return size;
+}
+
+static int vega20_set_ppfeature_status(struct smu_context *smu, uint64_t new_ppfeature_masks)
+{
+ uint64_t features_enabled;
+ uint64_t features_to_enable;
+ uint64_t features_to_disable;
+ int ret = 0;
+
+ if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX))
+ return -EINVAL;
+
+ ret = vega20_get_enabled_smc_features(smu, &features_enabled);
+ if (ret)
+ return ret;
+
+ features_to_disable =
+ features_enabled & ~new_ppfeature_masks;
+ features_to_enable =
+ ~features_enabled & new_ppfeature_masks;
+
+ pr_debug("features_to_disable 0x%llx\n", features_to_disable);
+ pr_debug("features_to_enable 0x%llx\n", features_to_enable);
+
+ if (features_to_disable) {
+ ret = vega20_enable_smc_features(smu, false, features_to_disable);
+ if (ret)
+ return ret;
+ }
+
+ if (features_to_enable) {
+ ret = vega20_enable_smc_features(smu, true, features_to_enable);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static bool vega20_is_dpm_running(struct smu_context *smu)
+{
+ int ret = 0;
+ uint32_t feature_mask[2];
+ unsigned long feature_enabled;
+ ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
+ feature_enabled = (unsigned long)((uint64_t)feature_mask[0] |
+ ((uint64_t)feature_mask[1] << 32));
+ return !!(feature_enabled & SMC_DPM_FEATURE);
+}
+
+static int vega20_set_thermal_fan_table(struct smu_context *smu)
+{
+ int ret;
+ struct smu_table_context *table_context = &smu->smu_table;
+ PPTable_t *pptable = table_context->driver_pptable;
+
+ ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetFanTemperatureTarget,
+ (uint32_t)pptable->FanTargetTemperature);
+
+ return ret;
+}
+
+static int vega20_get_fan_speed_percent(struct smu_context *smu,
+ uint32_t *speed)
+{
+ int ret = 0;
+ uint32_t current_rpm = 0, percent = 0;
+ PPTable_t *pptable = smu->smu_table.driver_pptable;
+
+ ret = smu_get_current_rpm(smu, &current_rpm);
+ if (ret)
+ return ret;
+
+ percent = current_rpm * 100 / pptable->FanMaximumRpm;
+ *speed = percent > 100 ? 100 : percent;
+
+ return 0;
+}
+
+static int vega20_get_gpu_power(struct smu_context *smu, uint32_t *value)
+{
+ int ret = 0;
+ SmuMetrics_t metrics;
+
+ if (!value)
+ return -EINVAL;
+
+ ret = vega20_get_metrics_table(smu, &metrics);
+ if (ret)
+ return ret;
+
+ *value = metrics.CurrSocketPower << 8;
+
+ return 0;
+}
+
+static int vega20_get_current_activity_percent(struct smu_context *smu,
+ enum amd_pp_sensors sensor,
+ uint32_t *value)
+{
+ int ret = 0;
+ SmuMetrics_t metrics;
+
+ if (!value)
+ return -EINVAL;
+
+ ret = vega20_get_metrics_table(smu, &metrics);
+ if (ret)
+ return ret;
+
+ switch (sensor) {
+ case AMDGPU_PP_SENSOR_GPU_LOAD:
+ *value = metrics.AverageGfxActivity;
+ break;
+ case AMDGPU_PP_SENSOR_MEM_LOAD:
+ *value = metrics.AverageUclkActivity;
+ break;
+ default:
+ pr_err("Invalid sensor for retrieving clock activity\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vega20_thermal_get_temperature(struct smu_context *smu,
+ enum amd_pp_sensors sensor,
+ uint32_t *value)
+{
+ struct amdgpu_device *adev = smu->adev;
+ SmuMetrics_t metrics;
+ uint32_t temp = 0;
+ int ret = 0;
+
+ if (!value)
+ return -EINVAL;
+
+ ret = vega20_get_metrics_table(smu, &metrics);
+ if (ret)
+ return ret;
+
+ switch (sensor) {
+ case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
+ temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS);
+ temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >>
+ CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT;
+
+ temp = temp & 0x1ff;
+ temp *= SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
+ *value = temp;
+ break;
+ case AMDGPU_PP_SENSOR_EDGE_TEMP:
+ *value = metrics.TemperatureEdge *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case AMDGPU_PP_SENSOR_MEM_TEMP:
+ *value = metrics.TemperatureHBM *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ default:
+ pr_err("Invalid sensor for retrieving temp\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+static int vega20_read_sensor(struct smu_context *smu,
+ enum amd_pp_sensors sensor,
+ void *data, uint32_t *size)
+{
+ int ret = 0;
+ struct smu_table_context *table_context = &smu->smu_table;
+ PPTable_t *pptable = table_context->driver_pptable;
+
+ switch (sensor) {
+ case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
+ *(uint32_t *)data = pptable->FanMaximumRpm;
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_MEM_LOAD:
+ case AMDGPU_PP_SENSOR_GPU_LOAD:
+ ret = vega20_get_current_activity_percent(smu,
+ sensor,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GPU_POWER:
+ ret = vega20_get_gpu_power(smu, (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
+ case AMDGPU_PP_SENSOR_EDGE_TEMP:
+ case AMDGPU_PP_SENSOR_MEM_TEMP:
+ ret = vega20_thermal_get_temperature(smu, sensor, (uint32_t *)data);
+ *size = 4;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int vega20_set_watermarks_table(struct smu_context *smu,
+ void *watermarks, struct
+ dm_pp_wm_sets_with_clock_ranges_soc15
+ *clock_ranges)
+{
+ int i;
+ Watermarks_t *table = watermarks;
+
+ if (!table || !clock_ranges)
+ return -EINVAL;
+
+ if (clock_ranges->num_wm_dmif_sets > 4 ||
+ clock_ranges->num_wm_mcif_sets > 4)
+ return -EINVAL;
+
+ for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) {
+ table->WatermarkRow[1][i].MinClock =
+ cpu_to_le16((uint16_t)
+ (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz /
+ 1000));
+ table->WatermarkRow[1][i].MaxClock =
+ cpu_to_le16((uint16_t)
+ (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz /
+ 1000));
+ table->WatermarkRow[1][i].MinUclk =
+ cpu_to_le16((uint16_t)
+ (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz /
+ 1000));
+ table->WatermarkRow[1][i].MaxUclk =
+ cpu_to_le16((uint16_t)
+ (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz /
+ 1000));
+ table->WatermarkRow[1][i].WmSetting = (uint8_t)
+ clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id;
+ }
+
+ for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) {
+ table->WatermarkRow[0][i].MinClock =
+ cpu_to_le16((uint16_t)
+ (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz /
+ 1000));
+ table->WatermarkRow[0][i].MaxClock =
+ cpu_to_le16((uint16_t)
+ (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz /
+ 1000));
+ table->WatermarkRow[0][i].MinUclk =
+ cpu_to_le16((uint16_t)
+ (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz /
+ 1000));
+ table->WatermarkRow[0][i].MaxUclk =
+ cpu_to_le16((uint16_t)
+ (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz /
+ 1000));
+ table->WatermarkRow[0][i].WmSetting = (uint8_t)
+ clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id;
+ }
+
+ return 0;
+}
+
+static const struct smu_temperature_range vega20_thermal_policy[] =
+{
+ {-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000},
+ { 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000},
+};
+
+static int vega20_get_thermal_temperature_range(struct smu_context *smu,
+ struct smu_temperature_range *range)
+{
+
+ PPTable_t *pptable = smu->smu_table.driver_pptable;
+
+ if (!range)
+ return -EINVAL;
+
+ memcpy(range, &vega20_thermal_policy[0], sizeof(struct smu_temperature_range));
+
+ range->max = pptable->TedgeLimit *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE) *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ range->hotspot_crit_max = pptable->ThotspotLimit *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ range->mem_crit_max = pptable->ThbmLimit *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ range->mem_emergency_max = (pptable->ThbmLimit + CTF_OFFSET_HBM)*
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
+
+ return 0;
+}
+
static const struct pptable_funcs vega20_ppt_funcs = {
+ .tables_init = vega20_tables_init,
.alloc_dpm_context = vega20_allocate_dpm_context,
.store_powerplay_table = vega20_store_powerplay_table,
.check_powerplay_table = vega20_check_powerplay_table,
.append_powerplay_table = vega20_append_powerplay_table,
.get_smu_msg_index = vega20_get_smu_msg_index,
+ .get_smu_clk_index = vega20_get_smu_clk_index,
+ .get_smu_feature_index = vega20_get_smu_feature_index,
+ .get_smu_table_index = vega20_get_smu_table_index,
+ .get_smu_power_index = vega20_get_pwr_src_index,
+ .get_workload_type = vega20_get_workload_type,
.run_afll_btc = vega20_run_btc_afll,
- .get_unallowed_feature_mask = vega20_get_unallowed_feature_mask,
+ .get_allowed_feature_mask = vega20_get_allowed_feature_mask,
.get_current_power_state = vega20_get_current_power_state,
.set_default_dpm_table = vega20_set_default_dpm_table,
.set_power_state = NULL,
@@ -2389,25 +3269,36 @@ static const struct pptable_funcs vega20_ppt_funcs = {
.print_clk_levels = vega20_print_clk_levels,
.force_clk_levels = vega20_force_clk_levels,
.get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency,
- .set_default_od8_settings = vega20_set_default_od8_setttings,
.get_od_percentage = vega20_get_od_percentage,
- .get_performance_level = vega20_get_performance_level,
- .force_performance_level = vega20_force_performance_level,
- .update_specified_od8_value = vega20_update_specified_od8_value,
+ .get_power_profile_mode = vega20_get_power_profile_mode,
+ .set_power_profile_mode = vega20_set_power_profile_mode,
.set_od_percentage = vega20_set_od_percentage,
+ .set_default_od_settings = vega20_set_default_od_settings,
.od_edit_dpm_table = vega20_odn_edit_dpm_table,
+ .dpm_set_uvd_enable = vega20_dpm_set_uvd_enable,
+ .dpm_set_vce_enable = vega20_dpm_set_vce_enable,
+ .read_sensor = vega20_read_sensor,
.pre_display_config_changed = vega20_pre_display_config_changed,
.display_config_changed = vega20_display_config_changed,
.apply_clocks_adjust_rules = vega20_apply_clocks_adjust_rules,
.notify_smc_dispaly_config = vega20_notify_smc_dispaly_config,
.force_dpm_limit_value = vega20_force_dpm_limit_value,
.unforce_dpm_levels = vega20_unforce_dpm_levels,
- .upload_dpm_level = vega20_upload_dpm_level,
.get_profiling_clk_mask = vega20_get_profiling_clk_mask,
+ .set_ppfeature_status = vega20_set_ppfeature_status,
+ .get_ppfeature_status = vega20_get_ppfeature_status,
+ .is_dpm_running = vega20_is_dpm_running,
+ .set_thermal_fan_table = vega20_set_thermal_fan_table,
+ .get_fan_speed_percent = vega20_get_fan_speed_percent,
+ .set_watermarks_table = vega20_set_watermarks_table,
+ .get_thermal_temperature_range = vega20_get_thermal_temperature_range
};
void vega20_set_ppt_funcs(struct smu_context *smu)
{
+ struct smu_table_context *smu_table = &smu->smu_table;
+
smu->ppt_funcs = &vega20_ppt_funcs;
smu->smc_if_version = SMU11_DRIVER_IF_VERSION;
+ smu_table->table_count = TABLE_COUNT;
}