aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/powerplay/smu_v11_0.c')
-rw-r--r--drivers/gpu/drm/amd/powerplay/smu_v11_0.c329
1 files changed, 182 insertions, 147 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
index 5fde5cf65b42..c5257ae3188a 100644
--- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
@@ -33,6 +33,7 @@
#include "soc15_common.h"
#include "atom.h"
#include "vega20_ppt.h"
+#include "arcturus_ppt.h"
#include "navi10_ppt.h"
#include "asic_reg/thm/thm_11_0_2_offset.h"
@@ -45,7 +46,10 @@
#include "asic_reg/smuio/smuio_11_0_0_sh_mask.h"
MODULE_FIRMWARE("amdgpu/vega20_smc.bin");
+MODULE_FIRMWARE("amdgpu/arcturus_smc.bin");
MODULE_FIRMWARE("amdgpu/navi10_smc.bin");
+MODULE_FIRMWARE("amdgpu/navi14_smc.bin");
+MODULE_FIRMWARE("amdgpu/navi12_smc.bin");
#define SMU11_VOLTAGE_SCALE 4
@@ -102,8 +106,8 @@ static int smu_v11_0_send_msg(struct smu_context *smu, uint16_t msg)
ret = smu_v11_0_wait_for_response(smu);
if (ret)
- pr_err("Failed to send message 0x%x, response 0x%x\n", index,
- ret);
+ pr_err("failed send message: %10s (%d) response %#x\n",
+ smu_get_message_name(smu, msg), index, ret);
return ret;
@@ -123,8 +127,8 @@ smu_v11_0_send_msg_with_param(struct smu_context *smu, uint16_t msg,
ret = smu_v11_0_wait_for_response(smu);
if (ret)
- pr_err("Failed to send message 0x%x, response 0x%x, param 0x%x\n",
- index, ret, param);
+ pr_err("failed send message: %10s (%d) \tparam: 0x%08x response %#x\n",
+ smu_get_message_name(smu, msg), index, param, ret);
WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0);
@@ -134,8 +138,8 @@ smu_v11_0_send_msg_with_param(struct smu_context *smu, uint16_t msg,
ret = smu_v11_0_wait_for_response(smu);
if (ret)
- pr_err("Failed to send message 0x%x, response 0x%x param 0x%x\n",
- index, ret, param);
+ pr_err("failed send message: %10s (%d) \tparam: 0x%08x response %#x\n",
+ smu_get_message_name(smu, msg), index, param, ret);
return ret;
}
@@ -154,9 +158,18 @@ static int smu_v11_0_init_microcode(struct smu_context *smu)
case CHIP_VEGA20:
chip_name = "vega20";
break;
+ case CHIP_ARCTURUS:
+ chip_name = "arcturus";
+ break;
case CHIP_NAVI10:
chip_name = "navi10";
break;
+ case CHIP_NAVI14:
+ chip_name = "navi14";
+ break;
+ case CHIP_NAVI12:
+ chip_name = "navi12";
+ break;
default:
BUG();
}
@@ -202,7 +215,7 @@ static int smu_v11_0_load_microcode(struct smu_context *smu)
uint32_t i;
uint32_t mp1_fw_flags;
- hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data;
+ hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data;
src = (const uint32_t *)(adev->pm.fw->data +
le32_to_cpu(hdr->header.ucode_array_offset_bytes));
@@ -261,6 +274,25 @@ static int smu_v11_0_check_fw_version(struct smu_context *smu)
smu_minor = (smu_version >> 8) & 0xff;
smu_debug = (smu_version >> 0) & 0xff;
+ switch (smu->adev->asic_type) {
+ case CHIP_VEGA20:
+ smu->smc_if_version = SMU11_DRIVER_IF_VERSION_VG20;
+ break;
+ case CHIP_ARCTURUS:
+ smu->smc_if_version = SMU11_DRIVER_IF_VERSION_ARCT;
+ break;
+ case CHIP_NAVI10:
+ smu->smc_if_version = SMU11_DRIVER_IF_VERSION_NV10;
+ break;
+ case CHIP_NAVI14:
+ smu->smc_if_version = SMU11_DRIVER_IF_VERSION_NV14;
+ break;
+ default:
+ pr_err("smu unsupported asic type:%d.\n", smu->adev->asic_type);
+ smu->smc_if_version = SMU11_DRIVER_IF_VERSION_INV;
+ break;
+ }
+
/*
* 1. if_version mismatch is not critical as our fw is designed
* to be backward compatible.
@@ -295,7 +327,8 @@ static int smu_v11_0_set_pptable_v2_0(struct smu_context *smu, void **table, uin
return 0;
}
-static int smu_v11_0_set_pptable_v2_1(struct smu_context *smu, void **table, uint32_t *size, uint32_t pptable_id)
+static int smu_v11_0_set_pptable_v2_1(struct smu_context *smu, void **table,
+ uint32_t *size, uint32_t pptable_id)
{
struct amdgpu_device *adev = smu->adev;
const struct smc_firmware_header_v2_1 *v2_1;
@@ -326,7 +359,8 @@ static int smu_v11_0_setup_pptable(struct smu_context *smu)
struct amdgpu_device *adev = smu->adev;
const struct smc_firmware_header_v1_0 *hdr;
int ret, index;
- uint32_t size;
+ uint32_t size = 0;
+ uint16_t atom_table_size;
uint8_t frev, crev;
void *table;
uint16_t version_major, version_minor;
@@ -354,10 +388,11 @@ static int smu_v11_0_setup_pptable(struct smu_context *smu)
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
powerplayinfo);
- ret = smu_get_atom_data_table(smu, index, (uint16_t *)&size, &frev, &crev,
+ ret = smu_get_atom_data_table(smu, index, &atom_table_size, &frev, &crev,
(uint8_t **)&table);
if (ret)
return ret;
+ size = atom_table_size;
}
if (!smu->smu_table.power_play_table)
@@ -535,6 +570,9 @@ int smu_v11_0_get_vbios_bootup_values(struct smu_context *smu)
smu->smu_table.boot_values.pp_table_id = v_3_3->pplib_pptable_id;
}
+ smu->smu_table.boot_values.format_revision = header->format_revision;
+ smu->smu_table.boot_values.content_revision = header->content_revision;
+
return 0;
}
@@ -614,6 +652,24 @@ static int smu_v11_0_get_clk_info_from_vbios(struct smu_context *smu)
output = (struct atom_get_smu_clock_info_output_parameters_v3_1 *)&input;
smu->smu_table.boot_values.dclk = le32_to_cpu(output->atom_smu_outputclkfreq.smu_clock_freq_hz) / 10000;
+ if ((smu->smu_table.boot_values.format_revision == 3) &&
+ (smu->smu_table.boot_values.content_revision >= 2)) {
+ memset(&input, 0, sizeof(input));
+ input.clk_id = SMU11_SYSPLL1_0_FCLK_ID;
+ input.syspll_id = SMU11_SYSPLL1_2_ID;
+ input.command = GET_SMU_CLOCK_INFO_V3_1_GET_CLOCK_FREQ;
+ index = get_index_into_master_table(atom_master_list_of_command_functions_v2_1,
+ getsmuclockinfo);
+
+ ret = amdgpu_atom_execute_table(adev->mode_info.atom_context, index,
+ (uint32_t *)&input);
+ if (ret)
+ return -EINVAL;
+
+ output = (struct atom_get_smu_clock_info_output_parameters_v3_1 *)&input;
+ smu->smu_table.boot_values.fclk = le32_to_cpu(output->atom_smu_outputclkfreq.smu_clock_freq_hz) / 10000;
+ }
+
return 0;
}
@@ -722,8 +778,6 @@ static int smu_v11_0_write_watermarks_table(struct smu_context *smu)
struct smu_table *table = NULL;
table = &smu_table->tables[SMU_TABLE_WATERMARKS];
- if (!table)
- return -EINVAL;
if (!table->cpu_addr)
return -EINVAL;
@@ -788,44 +842,6 @@ static int smu_v11_0_init_display_count(struct smu_context *smu, uint32_t count)
return ret;
}
-static int smu_v11_0_update_feature_enable_state(struct smu_context *smu, uint32_t feature_id, bool enabled)
-{
- uint32_t feature_low = 0, feature_high = 0;
- int ret = 0;
-
- if (!smu->pm_enabled)
- return ret;
- if (feature_id >= 0 && feature_id < 31)
- feature_low = (1 << feature_id);
- else if (feature_id > 31 && feature_id < 63)
- feature_high = (1 << feature_id);
- else
- return -EINVAL;
-
- 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;
-
- }
-
- return ret;
-}
static int smu_v11_0_set_allowed_mask(struct smu_context *smu)
{
@@ -927,11 +943,21 @@ smu_v11_0_get_max_sustainable_clock(struct smu_context *smu, uint32_t *clock,
enum smu_clk_type clock_select)
{
int ret = 0;
+ int clk_id;
if (!smu->pm_enabled)
return ret;
+
+ if ((smu_msg_get_index(smu, SMU_MSG_GetDcModeMaxDpmFreq) < 0) ||
+ (smu_msg_get_index(smu, SMU_MSG_GetMaxDpmFreq) < 0))
+ return 0;
+
+ clk_id = smu_clk_get_index(smu, clock_select);
+ if (clk_id < 0)
+ return -EINVAL;
+
ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetDcModeMaxDpmFreq,
- smu_clk_get_index(smu, clock_select) << 16);
+ clk_id << 16);
if (ret) {
pr_err("[GetMaxSustainableClock] Failed to get max DC clock from SMC!");
return ret;
@@ -946,7 +972,7 @@ smu_v11_0_get_max_sustainable_clock(struct smu_context *smu, uint32_t *clock,
/* if DC limit is zero, return AC limit */
ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetMaxDpmFreq,
- smu_clk_get_index(smu, clock_select) << 16);
+ clk_id << 16);
if (ret) {
pr_err("[GetMaxSustainableClock] failed to get max AC clock from SMC!");
return ret;
@@ -1037,57 +1063,32 @@ static int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu)
return 0;
}
-static int smu_v11_0_get_power_limit(struct smu_context *smu,
- uint32_t *limit,
- bool get_default)
+static int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n)
{
int ret = 0;
- if (get_default) {
- mutex_lock(&smu->mutex);
- *limit = smu->default_power_limit;
- if (smu->od_enabled) {
- *limit *= (100 + smu->smu_table.TDPODLimit);
- *limit /= 100;
- }
- mutex_unlock(&smu->mutex);
- } else {
- ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit,
- smu_power_get_index(smu, SMU_POWER_SOURCE_AC) << 16);
- if (ret) {
- pr_err("[%s] get PPT limit failed!", __func__);
- return ret;
- }
- smu_read_smc_arg(smu, limit);
- smu->power_limit = *limit;
+ if (n > smu->default_power_limit) {
+ pr_err("New power limit is over the max allowed %d\n",
+ smu->default_power_limit);
+ return -EINVAL;
}
- return ret;
-}
-
-static int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n)
-{
- uint32_t max_power_limit;
- int ret = 0;
-
if (n == 0)
n = smu->default_power_limit;
- max_power_limit = smu->default_power_limit;
-
- if (smu->od_enabled) {
- max_power_limit *= (100 + smu->smu_table.TDPODLimit);
- max_power_limit /= 100;
+ if (!smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
+ pr_err("Setting new power limit is not supported!\n");
+ return -EOPNOTSUPP;
}
- if (smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT))
- ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, n);
+ ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, n);
if (ret) {
- pr_err("[%s] Set power limit Failed!", __func__);
+ pr_err("[%s] Set power limit Failed!\n", __func__);
return ret;
}
+ smu->power_limit = n;
- return ret;
+ return 0;
}
static int smu_v11_0_get_current_clk_freq(struct smu_context *smu,
@@ -1096,16 +1097,21 @@ static int smu_v11_0_get_current_clk_freq(struct smu_context *smu,
{
int ret = 0;
uint32_t freq = 0;
+ int asic_clk_id;
if (clk_id >= SMU_CLK_COUNT || !value)
return -EINVAL;
+ asic_clk_id = smu_clk_get_index(smu, clk_id);
+ if (asic_clk_id < 0)
+ return -EINVAL;
+
/* if don't has GetDpmClockFreq Message, try get current clock by SmuMetrics_t */
- if (smu_msg_get_index(smu, SMU_MSG_GetDpmClockFreq) == 0)
+ if (smu_msg_get_index(smu, SMU_MSG_GetDpmClockFreq) < 0)
ret = smu_get_current_clk_freq_by_table(smu, clk_id, &freq);
else {
ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetDpmClockFreq,
- (smu_clk_get_index(smu, clk_id) << 16));
+ (asic_clk_id << 16));
if (ret)
return ret;
@@ -1121,23 +1127,17 @@ static int smu_v11_0_get_current_clk_freq(struct smu_context *smu,
}
static int smu_v11_0_set_thermal_range(struct smu_context *smu,
- struct smu_temperature_range *range)
+ struct smu_temperature_range range)
{
struct amdgpu_device *adev = smu->adev;
int low = SMU_THERMAL_MINIMUM_ALERT_TEMP;
int high = SMU_THERMAL_MAXIMUM_ALERT_TEMP;
uint32_t val;
- if (!range)
- return -EINVAL;
-
- if (low < range->min)
- low = range->min;
- if (high > range->max)
- high = range->max;
-
- low = max(SMU_THERMAL_MINIMUM_ALERT_TEMP, range->min);
- high = min(SMU_THERMAL_MAXIMUM_ALERT_TEMP, range->max);
+ low = max(SMU_THERMAL_MINIMUM_ALERT_TEMP,
+ range.min / SMU_TEMPERATURE_UNITS_PER_CENTIGRADES);
+ high = min(SMU_THERMAL_MAXIMUM_ALERT_TEMP,
+ range.max / SMU_TEMPERATURE_UNITS_PER_CENTIGRADES);
if (low > high)
return -EINVAL;
@@ -1173,27 +1173,20 @@ static int smu_v11_0_enable_thermal_alert(struct smu_context *smu)
static int smu_v11_0_start_thermal_control(struct smu_context *smu)
{
int ret = 0;
- struct smu_temperature_range range = {
- TEMP_RANGE_MIN,
- TEMP_RANGE_MAX,
- TEMP_RANGE_MAX,
- TEMP_RANGE_MIN,
- TEMP_RANGE_MAX,
- TEMP_RANGE_MAX,
- TEMP_RANGE_MIN,
- TEMP_RANGE_MAX,
- TEMP_RANGE_MAX};
+ struct smu_temperature_range range;
struct amdgpu_device *adev = smu->adev;
if (!smu->pm_enabled)
return ret;
+ memcpy(&range, &smu11_thermal_policy[0], sizeof(struct smu_temperature_range));
+
ret = smu_get_thermal_temperature_range(smu, &range);
if (ret)
return ret;
if (smu->smu_table.thermal_controller_type) {
- ret = smu_v11_0_set_thermal_range(smu, &range);
+ ret = smu_v11_0_set_thermal_range(smu, range);
if (ret)
return ret;
@@ -1206,17 +1199,15 @@ static int smu_v11_0_start_thermal_control(struct smu_context *smu)
return ret;
}
- adev->pm.dpm.thermal.min_temp = range.min * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
- adev->pm.dpm.thermal.max_temp = range.max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
- adev->pm.dpm.thermal.max_edge_emergency_temp = range.edge_emergency_max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
- adev->pm.dpm.thermal.min_hotspot_temp = range.hotspot_min * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
- adev->pm.dpm.thermal.max_hotspot_crit_temp = range.hotspot_crit_max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
- adev->pm.dpm.thermal.max_hotspot_emergency_temp = range.hotspot_emergency_max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
- adev->pm.dpm.thermal.min_mem_temp = range.mem_min * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
- adev->pm.dpm.thermal.max_mem_crit_temp = range.mem_crit_max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
- adev->pm.dpm.thermal.max_mem_emergency_temp = range.mem_emergency_max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
- adev->pm.dpm.thermal.min_temp = range.min * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
- adev->pm.dpm.thermal.max_temp = range.max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ adev->pm.dpm.thermal.min_temp = range.min;
+ adev->pm.dpm.thermal.max_temp = range.max;
+ adev->pm.dpm.thermal.max_edge_emergency_temp = range.edge_emergency_max;
+ adev->pm.dpm.thermal.min_hotspot_temp = range.hotspot_min;
+ adev->pm.dpm.thermal.max_hotspot_crit_temp = range.hotspot_crit_max;
+ adev->pm.dpm.thermal.max_hotspot_emergency_temp = range.hotspot_emergency_max;
+ adev->pm.dpm.thermal.min_mem_temp = range.mem_min;
+ adev->pm.dpm.thermal.max_mem_crit_temp = range.mem_crit_max;
+ adev->pm.dpm.thermal.max_mem_emergency_temp = range.mem_emergency_max;
return ret;
}
@@ -1250,6 +1241,10 @@ static int smu_v11_0_read_sensor(struct smu_context *smu,
void *data, uint32_t *size)
{
int ret = 0;
+
+ if(!data || !size)
+ return -EINVAL;
+
switch (sensor) {
case AMDGPU_PP_SENSOR_GFX_MCLK:
ret = smu_get_current_clk_freq(smu, SMU_UCLK, (uint32_t *)data);
@@ -1272,10 +1267,6 @@ static int smu_v11_0_read_sensor(struct smu_context *smu,
break;
}
- /* try get sensor data by asic */
- if (ret)
- ret = smu_asic_read_sensor(smu, sensor, data, size);
-
if (ret)
*size = 0;
@@ -1322,10 +1313,15 @@ smu_v11_0_display_clock_voltage_request(struct smu_context *smu,
if (ret)
goto failed;
+ if (clk_select == SMU_UCLK && smu->disable_uclk_switch)
+ return 0;
+
mutex_lock(&smu->mutex);
- ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinByFreq,
- (smu_clk_get_index(smu, clk_select) << 16) | clk_freq);
+ ret = smu_set_hard_freq_range(smu, clk_select, clk_freq, 0);
mutex_unlock(&smu->mutex);
+
+ if(clk_select == SMU_UCLK)
+ smu->hard_min_uclk_req_from_dal = clk_freq;
}
failed:
@@ -1361,6 +1357,8 @@ static int smu_v11_0_gfx_off_control(struct smu_context *smu, bool enable)
case CHIP_VEGA20:
break;
case CHIP_NAVI10:
+ case CHIP_NAVI14:
+ case CHIP_NAVI12:
if (!(adev->pm.pp_feature & PP_GFXOFF_MASK))
return 0;
mutex_lock(&smu->mutex);
@@ -1387,17 +1385,17 @@ smu_v11_0_get_fan_control_mode(struct smu_context *smu)
}
static int
-smu_v11_0_smc_fan_control(struct smu_context *smu, bool start)
+smu_v11_0_auto_fan_control(struct smu_context *smu, bool auto_fan_control)
{
int ret = 0;
if (!smu_feature_is_supported(smu, SMU_FEATURE_FAN_CONTROL_BIT))
return 0;
- ret = smu_feature_set_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT, start);
+ ret = smu_feature_set_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT, auto_fan_control);
if (ret)
pr_err("[%s]%s smc FAN CONTROL feature failed!",
- __func__, (start ? "Start" : "Stop"));
+ __func__, (auto_fan_control ? "Start" : "Stop"));
return ret;
}
@@ -1421,16 +1419,15 @@ static int
smu_v11_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed)
{
struct amdgpu_device *adev = smu->adev;
- uint32_t duty100;
- uint32_t duty;
+ uint32_t duty100, duty;
uint64_t tmp64;
- bool stop = 0;
if (speed > 100)
speed = 100;
- if (smu_v11_0_smc_fan_control(smu, stop))
+ if (smu_v11_0_auto_fan_control(smu, 0))
return -EINVAL;
+
duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1),
CG_FDO_CTRL1, FMAX_DUTY100);
if (!duty100)
@@ -1452,18 +1449,16 @@ smu_v11_0_set_fan_control_mode(struct smu_context *smu,
uint32_t mode)
{
int ret = 0;
- bool start = 1;
- bool stop = 0;
switch (mode) {
case AMD_FAN_CTRL_NONE:
ret = smu_v11_0_set_fan_speed_percent(smu, 100);
break;
case AMD_FAN_CTRL_MANUAL:
- ret = smu_v11_0_smc_fan_control(smu, stop);
+ ret = smu_v11_0_auto_fan_control(smu, 0);
break;
case AMD_FAN_CTRL_AUTO:
- ret = smu_v11_0_smc_fan_control(smu, start);
+ ret = smu_v11_0_auto_fan_control(smu, 1);
break;
default:
break;
@@ -1483,13 +1478,12 @@ static int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu,
struct amdgpu_device *adev = smu->adev;
int ret;
uint32_t tach_period, crystal_clock_freq;
- bool stop = 0;
if (!speed)
return -EINVAL;
mutex_lock(&(smu->mutex));
- ret = smu_v11_0_smc_fan_control(smu, stop);
+ ret = smu_v11_0_auto_fan_control(smu, 0);
if (ret)
goto set_fan_speed_rpm_failed;
@@ -1670,7 +1664,7 @@ static bool smu_v11_0_baco_is_support(struct smu_context *smu)
static enum smu_baco_state smu_v11_0_baco_get_state(struct smu_context *smu)
{
struct smu_baco_context *smu_baco = &smu->smu_baco;
- enum smu_baco_state baco_state = SMU_BACO_STATE_EXIT;
+ enum smu_baco_state baco_state;
mutex_lock(&smu_baco->mutex);
baco_state = smu_baco->state;
@@ -1724,6 +1718,43 @@ static int smu_v11_0_baco_reset(struct smu_context *smu)
return ret;
}
+static int smu_v11_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type clk_type,
+ uint32_t *min, uint32_t *max)
+{
+ int ret = 0, clk_id = 0;
+ uint32_t param = 0;
+
+ mutex_lock(&smu->mutex);
+ clk_id = smu_clk_get_index(smu, clk_type);
+ if (clk_id < 0) {
+ ret = -EINVAL;
+ goto failed;
+ }
+ param = (clk_id & 0xffff) << 16;
+
+ if (max) {
+ ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetMaxDpmFreq, param);
+ if (ret)
+ goto failed;
+ ret = smu_read_smc_arg(smu, max);
+ if (ret)
+ goto failed;
+ }
+
+ if (min) {
+ ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetMinDpmFreq, param);
+ if (ret)
+ goto failed;
+ ret = smu_read_smc_arg(smu, min);
+ if (ret)
+ goto failed;
+ }
+
+failed:
+ mutex_unlock(&smu->mutex);
+ return ret;
+}
+
static const struct smu_funcs smu_v11_0_funcs = {
.init_microcode = smu_v11_0_init_microcode,
.load_microcode = smu_v11_0_load_microcode,
@@ -1742,7 +1773,7 @@ static const struct smu_funcs smu_v11_0_funcs = {
.notify_memory_pool_location = smu_v11_0_notify_memory_pool_location,
.check_pptable = smu_v11_0_check_pptable,
.parse_pptable = smu_v11_0_parse_pptable,
- .populate_smc_pptable = smu_v11_0_populate_smc_pptable,
+ .populate_smc_tables = smu_v11_0_populate_smc_pptable,
.write_pptable = smu_v11_0_write_pptable,
.write_watermarks_table = smu_v11_0_write_watermarks_table,
.set_min_dcef_deep_sleep = smu_v11_0_set_min_dcef_deep_sleep,
@@ -1751,9 +1782,7 @@ static const struct smu_funcs smu_v11_0_funcs = {
.set_allowed_mask = smu_v11_0_set_allowed_mask,
.get_enabled_mask = smu_v11_0_get_enabled_mask,
.system_features_control = smu_v11_0_system_features_control,
- .update_feature_enable_state = smu_v11_0_update_feature_enable_state,
.notify_display_change = smu_v11_0_notify_display_change,
- .get_power_limit = smu_v11_0_get_power_limit,
.set_power_limit = smu_v11_0_set_power_limit,
.get_current_clk_freq = smu_v11_0_get_current_clk_freq,
.init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks,
@@ -1775,6 +1804,7 @@ static const struct smu_funcs smu_v11_0_funcs = {
.baco_get_state = smu_v11_0_baco_get_state,
.baco_set_state = smu_v11_0_baco_set_state,
.baco_reset = smu_v11_0_baco_reset,
+ .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq,
};
void smu_v11_0_set_smu_funcs(struct smu_context *smu)
@@ -1786,7 +1816,12 @@ void smu_v11_0_set_smu_funcs(struct smu_context *smu)
case CHIP_VEGA20:
vega20_set_ppt_funcs(smu);
break;
+ case CHIP_ARCTURUS:
+ arcturus_set_ppt_funcs(smu);
+ break;
case CHIP_NAVI10:
+ case CHIP_NAVI14:
+ case CHIP_NAVI12:
navi10_set_ppt_funcs(smu);
break;
default: