summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/powerplay/navi10_ppt.c')
-rw-r--r--drivers/gpu/drm/amd/powerplay/navi10_ppt.c346
1 files changed, 139 insertions, 207 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
index b81c7e715dc9..12c0e469bf35 100644
--- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
@@ -50,9 +50,9 @@
FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT))
#define MSG_MAP(msg, index) \
- [SMU_MSG_##msg] = index
+ [SMU_MSG_##msg] = {1, (index)}
-static int navi10_message_map[SMU_MSG_MAX_COUNT] = {
+static struct smu_11_0_cmn2aisc_mapping navi10_message_map[SMU_MSG_MAX_COUNT] = {
MSG_MAP(TestMessage, PPSMC_MSG_TestMessage),
MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion),
MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion),
@@ -119,7 +119,7 @@ static int navi10_message_map[SMU_MSG_MAX_COUNT] = {
MSG_MAP(ArmD3, PPSMC_MSG_ArmD3),
};
-static int navi10_clk_map[SMU_CLK_COUNT] = {
+static struct smu_11_0_cmn2aisc_mapping navi10_clk_map[SMU_CLK_COUNT] = {
CLK_MAP(GFXCLK, PPCLK_GFXCLK),
CLK_MAP(SCLK, PPCLK_GFXCLK),
CLK_MAP(SOCCLK, PPCLK_SOCCLK),
@@ -134,7 +134,7 @@ static int navi10_clk_map[SMU_CLK_COUNT] = {
CLK_MAP(PHYCLK, PPCLK_PHYCLK),
};
-static int navi10_feature_mask_map[SMU_FEATURE_COUNT] = {
+static struct smu_11_0_cmn2aisc_mapping navi10_feature_mask_map[SMU_FEATURE_COUNT] = {
FEA_MAP(DPM_PREFETCHER),
FEA_MAP(DPM_GFXCLK),
FEA_MAP(DPM_GFX_PACE),
@@ -179,7 +179,7 @@ static int navi10_feature_mask_map[SMU_FEATURE_COUNT] = {
FEA_MAP(ATHUB_PG),
};
-static int navi10_table_map[SMU_TABLE_COUNT] = {
+static struct smu_11_0_cmn2aisc_mapping navi10_table_map[SMU_TABLE_COUNT] = {
TAB_MAP(PPTABLE),
TAB_MAP(WATERMARKS),
TAB_MAP(AVFS),
@@ -194,12 +194,12 @@ static int navi10_table_map[SMU_TABLE_COUNT] = {
TAB_MAP(PACE),
};
-static int navi10_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
+static struct smu_11_0_cmn2aisc_mapping navi10_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
PWR_MAP(AC),
PWR_MAP(DC),
};
-static int navi10_workload_map[] = {
+static struct smu_11_0_cmn2aisc_mapping navi10_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, WORKLOAD_PPLIB_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),
@@ -211,79 +211,93 @@ static int navi10_workload_map[] = {
static int navi10_get_smu_msg_index(struct smu_context *smc, uint32_t index)
{
- int val;
- if (index > SMU_MSG_MAX_COUNT)
+ struct smu_11_0_cmn2aisc_mapping mapping;
+
+ if (index >= SMU_MSG_MAX_COUNT)
return -EINVAL;
- val = navi10_message_map[index];
- if (val > PPSMC_Message_Count)
+ mapping = navi10_message_map[index];
+ if (!(mapping.valid_mapping)) {
return -EINVAL;
+ }
- return val;
+ return mapping.map_to;
}
static int navi10_get_smu_clk_index(struct smu_context *smc, uint32_t index)
{
- int val;
+ struct smu_11_0_cmn2aisc_mapping mapping;
+
if (index >= SMU_CLK_COUNT)
return -EINVAL;
- val = navi10_clk_map[index];
- if (val >= PPCLK_COUNT)
+ mapping = navi10_clk_map[index];
+ if (!(mapping.valid_mapping)) {
return -EINVAL;
+ }
- return val;
+ return mapping.map_to;
}
static int navi10_get_smu_feature_index(struct smu_context *smc, uint32_t index)
{
- int val;
+ struct smu_11_0_cmn2aisc_mapping mapping;
+
if (index >= SMU_FEATURE_COUNT)
return -EINVAL;
- val = navi10_feature_mask_map[index];
- if (val > 64)
+ mapping = navi10_feature_mask_map[index];
+ if (!(mapping.valid_mapping)) {
return -EINVAL;
+ }
- return val;
+ return mapping.map_to;
}
static int navi10_get_smu_table_index(struct smu_context *smc, uint32_t index)
{
- int val;
+ struct smu_11_0_cmn2aisc_mapping mapping;
+
if (index >= SMU_TABLE_COUNT)
return -EINVAL;
- val = navi10_table_map[index];
- if (val >= TABLE_COUNT)
+ mapping = navi10_table_map[index];
+ if (!(mapping.valid_mapping)) {
return -EINVAL;
+ }
- return val;
+ return mapping.map_to;
}
static int navi10_get_pwr_src_index(struct smu_context *smc, uint32_t index)
{
- int val;
+ struct smu_11_0_cmn2aisc_mapping mapping;
+
if (index >= SMU_POWER_SOURCE_COUNT)
return -EINVAL;
- val = navi10_pwr_src_map[index];
- if (val >= POWER_SOURCE_COUNT)
+ mapping = navi10_pwr_src_map[index];
+ if (!(mapping.valid_mapping)) {
return -EINVAL;
+ }
- return val;
+ return mapping.map_to;
}
static int navi10_get_workload_type(struct smu_context *smu, enum PP_SMC_POWER_PROFILE profile)
{
- int val;
+ struct smu_11_0_cmn2aisc_mapping mapping;
+
if (profile > PP_SMC_POWER_PROFILE_CUSTOM)
return -EINVAL;
- val = navi10_workload_map[profile];
+ mapping = navi10_workload_map[profile];
+ if (!(mapping.valid_mapping)) {
+ return -EINVAL;
+ }
- return val;
+ return mapping.map_to;
}
static bool is_asic_secure(struct smu_context *smu)
@@ -355,7 +369,8 @@ navi10_get_allowed_feature_mask(struct smu_context *smu,
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_PG_BIT);
if (smu->adev->pg_flags & AMD_PG_SUPPORT_VCN)
- *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VCN_PG_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VCN_PG_BIT)
+ | FEATURE_MASK(FEATURE_JPEG_PG_BIT);
/* disable DPM UCLK and DS SOCCLK on navi10 A0 secure board */
if (is_asic_secure(smu)) {
@@ -927,8 +942,6 @@ static int navi10_get_gpu_power(struct smu_context *smu, uint32_t *value)
ret = navi10_get_metrics_table(smu, &metrics);
if (ret)
return ret;
- if (ret)
- return ret;
*value = metrics.AverageSocketPower << 8;
@@ -987,8 +1000,6 @@ static int navi10_get_fan_speed_rpm(struct smu_context *smu,
ret = navi10_get_metrics_table(smu, &metrics);
if (ret)
return ret;
- if (ret)
- return ret;
*speed = metrics.CurrFanSpeed;
@@ -1017,7 +1028,7 @@ static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf)
{
DpmActivityMonitorCoeffInt_t activity_monitor;
uint32_t i, size = 0;
- uint16_t workload_type = 0;
+ int16_t workload_type = 0;
static const char *profile_name[] = {
"BOOTUP_DEFAULT",
"3D_FULL_SCREEN",
@@ -1050,6 +1061,9 @@ static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf)
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);
+ if (workload_type < 0)
+ return -EINVAL;
+
result = smu_update_table(smu,
SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type,
(void *)(&activity_monitor), false);
@@ -1178,6 +1192,8 @@ static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, u
/* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
workload_type = smu_workload_get_type(smu, smu->power_profile_mode);
+ if (workload_type < 0)
+ return -EINVAL;
smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
1 << workload_type);
@@ -1367,6 +1383,9 @@ static int navi10_read_sensor(struct smu_context *smu,
struct smu_table_context *table_context = &smu->smu_table;
PPTable_t *pptable = table_context->driver_pptable;
+ if(!data || !size)
+ return -EINVAL;
+
switch (sensor) {
case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
*(uint32_t *)data = pptable->FanMaximumRpm;
@@ -1388,7 +1407,7 @@ static int navi10_read_sensor(struct smu_context *smu,
*size = 4;
break;
default:
- return -EINVAL;
+ ret = smu_smc_read_sensor(smu, sensor, data, size);
}
return ret;
@@ -1423,169 +1442,6 @@ static int navi10_get_uclk_dpm_states(struct smu_context *smu, uint32_t *clocks_
return 0;
}
-static int navi10_get_ppfeature_status(struct smu_context *smu,
- char *buf)
-{
- static const char *ppfeature_name[] = {
- "DPM_PREFETCHER",
- "DPM_GFXCLK",
- "DPM_GFX_PACE",
- "DPM_UCLK",
- "DPM_SOCCLK",
- "DPM_MP0CLK",
- "DPM_LINK",
- "DPM_DCEFCLK",
- "MEM_VDDCI_SCALING",
- "MEM_MVDD_SCALING",
- "DS_GFXCLK",
- "DS_SOCCLK",
- "DS_LCLK",
- "DS_DCEFCLK",
- "DS_UCLK",
- "GFX_ULV",
- "FW_DSTATE",
- "GFXOFF",
- "BACO",
- "VCN_PG",
- "JPEG_PG",
- "USB_PG",
- "RSMU_SMN_CG",
- "PPT",
- "TDC",
- "GFX_EDC",
- "APCC_PLUS",
- "GTHR",
- "ACDC",
- "VR0HOT",
- "VR1HOT",
- "FW_CTF",
- "FAN_CONTROL",
- "THERMAL",
- "GFX_DCS",
- "RM",
- "LED_DISPLAY",
- "GFX_SS",
- "OUT_OF_BAND_MONITOR",
- "TEMP_DEPENDENT_VMIN",
- "MMHUB_PG",
- "ATHUB_PG"};
- static const char *output_title[] = {
- "FEATURES",
- "BITMASK",
- "ENABLEMENT"};
- uint64_t features_enabled;
- uint32_t feature_mask[2];
- int i;
- int ret = 0;
- int size = 0;
-
- ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
- PP_ASSERT_WITH_CODE(!ret,
- "[GetPPfeatureStatus] Failed to get enabled smc features!",
- return ret);
- features_enabled = (uint64_t)feature_mask[0] |
- (uint64_t)feature_mask[1] << 32;
-
- 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 < (sizeof(ppfeature_name) / sizeof(ppfeature_name[0])); 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 navi10_enable_smc_features(struct smu_context *smu,
- bool enabled,
- uint64_t feature_masks)
-{
- struct smu_feature *feature = &smu->smu_feature;
- uint32_t feature_low, feature_high;
- uint32_t feature_mask[2];
- int ret = 0;
-
- feature_low = (uint32_t)(feature_masks & 0xFFFFFFFF);
- feature_high = (uint32_t)((feature_masks & 0xFFFFFFFF00000000ULL) >> 32);
-
- if (enabled) {
- ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnableSmuFeaturesLow,
- feature_low);
- if (ret)
- return ret;
- ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnableSmuFeaturesHigh,
- feature_high);
- if (ret)
- return ret;
- } else {
- ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DisableSmuFeaturesLow,
- feature_low);
- if (ret)
- return ret;
- ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DisableSmuFeaturesHigh,
- feature_high);
- if (ret)
- return ret;
- }
-
- ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
- if (ret)
- return ret;
-
- mutex_lock(&feature->mutex);
- bitmap_copy(feature->enabled, (unsigned long *)&feature_mask,
- feature->feature_num);
- mutex_unlock(&feature->mutex);
-
- return 0;
-}
-
-static int navi10_set_ppfeature_status(struct smu_context *smu,
- uint64_t new_ppfeature_masks)
-{
- uint64_t features_enabled;
- uint32_t feature_mask[2];
- uint64_t features_to_enable;
- uint64_t features_to_disable;
- int ret = 0;
-
- ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
- PP_ASSERT_WITH_CODE(!ret,
- "[SetPPfeatureStatus] Failed to get enabled smc features!",
- return ret);
- features_enabled = (uint64_t)feature_mask[0] |
- (uint64_t)feature_mask[1] << 32;
-
- 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 = navi10_enable_smc_features(smu, false, features_to_disable);
- PP_ASSERT_WITH_CODE(!ret,
- "[SetPPfeatureStatus] Failed to disable smc features!",
- return ret);
- }
-
- if (features_to_enable) {
- ret = navi10_enable_smc_features(smu, true, features_to_enable);
- PP_ASSERT_WITH_CODE(!ret,
- "[SetPPfeatureStatus] Failed to enable smc features!",
- return ret);
- }
-
- return 0;
-}
-
static int navi10_set_peak_clock_by_device(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
@@ -1627,6 +1483,10 @@ static int navi10_set_peak_clock_by_device(struct smu_context *smu)
static int navi10_set_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
{
int ret = 0;
+ struct amdgpu_device *adev = smu->adev;
+
+ if (adev->asic_type != CHIP_NAVI10)
+ return -EINVAL;
switch (level) {
case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
@@ -1649,9 +1509,82 @@ static int navi10_get_thermal_temperature_range(struct smu_context *smu,
if (!range || !powerplay_table)
return -EINVAL;
- /* The unit is temperature */
- range->min = 0;
- range->max = powerplay_table->software_shutdown_temp;
+ range->max = powerplay_table->software_shutdown_temp *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
+ return 0;
+}
+
+static int navi10_display_disable_memory_clock_switch(struct smu_context *smu,
+ bool disable_memory_clock_switch)
+{
+ int ret = 0;
+ struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks =
+ (struct smu_11_0_max_sustainable_clocks *)
+ smu->smu_table.max_sustainable_clocks;
+ uint32_t min_memory_clock = smu->hard_min_uclk_req_from_dal;
+ uint32_t max_memory_clock = max_sustainable_clocks->uclock;
+
+ if(smu->disable_uclk_switch == disable_memory_clock_switch)
+ return 0;
+
+ if(disable_memory_clock_switch)
+ ret = smu_set_hard_freq_range(smu, SMU_UCLK, max_memory_clock, 0);
+ else
+ ret = smu_set_hard_freq_range(smu, SMU_UCLK, min_memory_clock, 0);
+
+ if(!ret)
+ smu->disable_uclk_switch = disable_memory_clock_switch;
+
+ return ret;
+}
+
+static int navi10_get_power_limit(struct smu_context *smu,
+ uint32_t *limit,
+ bool asic_default)
+{
+ PPTable_t *pptable = smu->smu_table.driver_pptable;
+ uint32_t asic_default_power_limit = 0;
+ int ret = 0;
+ int power_src;
+
+ if (!smu->default_power_limit ||
+ !smu->power_limit) {
+ if (smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
+ power_src = smu_power_get_index(smu, SMU_POWER_SOURCE_AC);
+ if (power_src < 0)
+ return -EINVAL;
+
+ ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit,
+ power_src << 16);
+ if (ret) {
+ pr_err("[%s] get PPT limit failed!", __func__);
+ return ret;
+ }
+ smu_read_smc_arg(smu, &asic_default_power_limit);
+ } else {
+ /* the last hope to figure out the ppt limit */
+ if (!pptable) {
+ pr_err("Cannot get PPT limit due to pptable missing!");
+ return -EINVAL;
+ }
+ asic_default_power_limit =
+ pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
+ }
+
+ if (smu->od_enabled) {
+ asic_default_power_limit *= (100 + smu->smu_table.TDPODLimit);
+ asic_default_power_limit /= 100;
+ }
+
+ smu->default_power_limit = asic_default_power_limit;
+ smu->power_limit = asic_default_power_limit;
+ }
+
+ if (asic_default)
+ *limit = smu->default_power_limit;
+ else
+ *limit = smu->power_limit;
return 0;
}
@@ -1690,10 +1623,10 @@ static const struct pptable_funcs navi10_ppt_funcs = {
.set_watermarks_table = navi10_set_watermarks_table,
.read_sensor = navi10_read_sensor,
.get_uclk_dpm_states = navi10_get_uclk_dpm_states,
- .get_ppfeature_status = navi10_get_ppfeature_status,
- .set_ppfeature_status = navi10_set_ppfeature_status,
.set_performance_level = navi10_set_performance_level,
.get_thermal_temperature_range = navi10_get_thermal_temperature_range,
+ .display_disable_memory_clock_switch = navi10_display_disable_memory_clock_switch,
+ .get_power_limit = navi10_get_power_limit,
};
void navi10_set_ppt_funcs(struct smu_context *smu)
@@ -1701,6 +1634,5 @@ void navi10_set_ppt_funcs(struct smu_context *smu)
struct smu_table_context *smu_table = &smu->smu_table;
smu->ppt_funcs = &navi10_ppt_funcs;
- smu->smc_if_version = SMU11_DRIVER_IF_VERSION;
smu_table->table_count = TABLE_COUNT;
}