summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/pm/swsmu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/pm/swsmu')
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c28
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c101
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c302
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c120
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c69
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c310
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c216
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c3
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_internal.h1
10 files changed, 485 insertions, 667 deletions
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 39990790ed67..cf999b7a2164 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -405,6 +405,8 @@ static int smu_set_funcs(struct amdgpu_device *adev)
break;
case CHIP_VANGOGH:
vangogh_set_ppt_funcs(smu);
+ /* enable the OD by default to allow the fine grain tuning function */
+ smu->od_enabled = true;
break;
default:
return -EINVAL;
@@ -474,6 +476,8 @@ static int smu_late_init(void *handle)
struct smu_context *smu = &adev->smu;
int ret = 0;
+ smu_set_fine_grain_gfx_freq_parameters(smu);
+
if (adev->asic_type == CHIP_VANGOGH)
return 0;
@@ -843,7 +847,7 @@ static int smu_sw_init(void *handle)
smu->smu_dpm.dpm_level = AMD_DPM_FORCED_LEVEL_AUTO;
smu->smu_dpm.requested_dpm_level = AMD_DPM_FORCED_LEVEL_AUTO;
- if (!amdgpu_sriov_vf(adev)) {
+ if (!amdgpu_sriov_vf(adev) || (adev->asic_type != CHIP_NAVI12)) {
ret = smu_init_microcode(smu);
if (ret) {
dev_err(adev->dev, "Failed to load smu firmware!\n");
@@ -914,11 +918,15 @@ static int smu_smc_hw_setup(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
uint32_t pcie_gen = 0, pcie_width = 0;
- int ret;
+ int ret = 0;
if (adev->in_suspend && smu_is_dpm_running(smu)) {
dev_info(adev->dev, "dpm has been enabled\n");
- return 0;
+ /* this is needed specifically */
+ if ((adev->asic_type >= CHIP_SIENNA_CICHLID) &&
+ (adev->asic_type <= CHIP_DIMGREY_CAVEFISH))
+ ret = smu_system_features_control(smu, true);
+ return ret;
}
ret = smu_init_display_count(smu, 0);
@@ -1179,7 +1187,7 @@ static int smu_disable_dpms(struct smu_context *smu)
*/
if (smu->uploading_custom_pp_table &&
(adev->asic_type >= CHIP_NAVI10) &&
- (adev->asic_type <= CHIP_NAVY_FLOUNDER))
+ (adev->asic_type <= CHIP_DIMGREY_CAVEFISH))
return 0;
/*
@@ -2529,3 +2537,15 @@ int smu_enable_mgpu_fan_boost(struct smu_context *smu)
return ret;
}
+
+int smu_gfx_state_change_set(struct smu_context *smu, uint32_t state)
+{
+ int ret = 0;
+
+ mutex_lock(&smu->mutex);
+ if (smu->ppt_funcs->gfx_state_change_set)
+ ret = smu->ppt_funcs->gfx_state_change_set(smu, state);
+ mutex_unlock(&smu->mutex);
+
+ return ret;
+}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index 4fd850e58004..cd7b411457ff 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -1000,77 +1000,6 @@ static int arcturus_get_thermal_temperature_range(struct smu_context *smu,
return 0;
}
-static int arcturus_get_current_activity_percent(struct smu_context *smu,
- enum amd_pp_sensors sensor,
- uint32_t *value)
-{
- int ret = 0;
-
- if (!value)
- return -EINVAL;
-
- switch (sensor) {
- case AMDGPU_PP_SENSOR_GPU_LOAD:
- ret = arcturus_get_smu_metrics_data(smu,
- METRICS_AVERAGE_GFXACTIVITY,
- value);
- break;
- case AMDGPU_PP_SENSOR_MEM_LOAD:
- ret = arcturus_get_smu_metrics_data(smu,
- METRICS_AVERAGE_MEMACTIVITY,
- value);
- break;
- default:
- dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n");
- return -EINVAL;
- }
-
- return ret;
-}
-
-static int arcturus_get_gpu_power(struct smu_context *smu, uint32_t *value)
-{
- if (!value)
- return -EINVAL;
-
- return arcturus_get_smu_metrics_data(smu,
- METRICS_AVERAGE_SOCKETPOWER,
- value);
-}
-
-static int arcturus_thermal_get_temperature(struct smu_context *smu,
- enum amd_pp_sensors sensor,
- uint32_t *value)
-{
- int ret = 0;
-
- if (!value)
- return -EINVAL;
-
- switch (sensor) {
- case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
- ret = arcturus_get_smu_metrics_data(smu,
- METRICS_TEMPERATURE_HOTSPOT,
- value);
- break;
- case AMDGPU_PP_SENSOR_EDGE_TEMP:
- ret = arcturus_get_smu_metrics_data(smu,
- METRICS_TEMPERATURE_EDGE,
- value);
- break;
- case AMDGPU_PP_SENSOR_MEM_TEMP:
- ret = arcturus_get_smu_metrics_data(smu,
- METRICS_TEMPERATURE_MEM,
- value);
- break;
- default:
- dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n");
- return -EINVAL;
- }
-
- return ret;
-}
-
static int arcturus_read_sensor(struct smu_context *smu,
enum amd_pp_sensors sensor,
void *data, uint32_t *size)
@@ -1092,21 +1021,39 @@ static int arcturus_read_sensor(struct smu_context *smu,
*size = 4;
break;
case AMDGPU_PP_SENSOR_MEM_LOAD:
+ ret = arcturus_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_MEMACTIVITY,
+ (uint32_t *)data);
+ *size = 4;
+ break;
case AMDGPU_PP_SENSOR_GPU_LOAD:
- ret = arcturus_get_current_activity_percent(smu,
- sensor,
- (uint32_t *)data);
+ ret = arcturus_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXACTIVITY,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GPU_POWER:
- ret = arcturus_get_gpu_power(smu, (uint32_t *)data);
+ ret = arcturus_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_SOCKETPOWER,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
+ ret = arcturus_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_HOTSPOT,
+ (uint32_t *)data);
+ *size = 4;
+ break;
case AMDGPU_PP_SENSOR_EDGE_TEMP:
+ ret = arcturus_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_EDGE,
+ (uint32_t *)data);
+ *size = 4;
+ break;
case AMDGPU_PP_SENSOR_MEM_TEMP:
- ret = arcturus_thermal_get_temperature(smu, sensor,
- (uint32_t *)data);
+ ret = arcturus_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_MEM,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GFX_MCLK:
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index ef1a62e86a0e..51e83123f72a 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -1302,44 +1302,6 @@ static int navi10_display_config_changed(struct smu_context *smu)
return ret;
}
-static int navi10_get_gpu_power(struct smu_context *smu, uint32_t *value)
-{
- if (!value)
- return -EINVAL;
-
- return navi10_get_smu_metrics_data(smu,
- METRICS_AVERAGE_SOCKETPOWER,
- value);
-}
-
-static int navi10_get_current_activity_percent(struct smu_context *smu,
- enum amd_pp_sensors sensor,
- uint32_t *value)
-{
- int ret = 0;
-
- if (!value)
- return -EINVAL;
-
- switch (sensor) {
- case AMDGPU_PP_SENSOR_GPU_LOAD:
- ret = navi10_get_smu_metrics_data(smu,
- METRICS_AVERAGE_GFXACTIVITY,
- value);
- break;
- case AMDGPU_PP_SENSOR_MEM_LOAD:
- ret = navi10_get_smu_metrics_data(smu,
- METRICS_AVERAGE_MEMACTIVITY,
- value);
- break;
- default:
- dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n");
- return -EINVAL;
- }
-
- return ret;
-}
-
static bool navi10_is_dpm_running(struct smu_context *smu)
{
int ret = 0;
@@ -1652,39 +1614,6 @@ static int navi10_set_watermarks_table(struct smu_context *smu,
return 0;
}
-static int navi10_thermal_get_temperature(struct smu_context *smu,
- enum amd_pp_sensors sensor,
- uint32_t *value)
-{
- int ret = 0;
-
- if (!value)
- return -EINVAL;
-
- switch (sensor) {
- case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
- ret = navi10_get_smu_metrics_data(smu,
- METRICS_TEMPERATURE_HOTSPOT,
- value);
- break;
- case AMDGPU_PP_SENSOR_EDGE_TEMP:
- ret = navi10_get_smu_metrics_data(smu,
- METRICS_TEMPERATURE_EDGE,
- value);
- break;
- case AMDGPU_PP_SENSOR_MEM_TEMP:
- ret = navi10_get_smu_metrics_data(smu,
- METRICS_TEMPERATURE_MEM,
- value);
- break;
- default:
- dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n");
- return -EINVAL;
- }
-
- return ret;
-}
-
static int navi10_read_sensor(struct smu_context *smu,
enum amd_pp_sensors sensor,
void *data, uint32_t *size)
@@ -1703,18 +1632,39 @@ static int navi10_read_sensor(struct smu_context *smu,
*size = 4;
break;
case AMDGPU_PP_SENSOR_MEM_LOAD:
+ ret = navi10_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_MEMACTIVITY,
+ (uint32_t *)data);
+ *size = 4;
+ break;
case AMDGPU_PP_SENSOR_GPU_LOAD:
- ret = navi10_get_current_activity_percent(smu, sensor, (uint32_t *)data);
+ ret = navi10_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXACTIVITY,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GPU_POWER:
- ret = navi10_get_gpu_power(smu, (uint32_t *)data);
+ ret = navi10_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_SOCKETPOWER,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
+ ret = navi10_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_HOTSPOT,
+ (uint32_t *)data);
+ *size = 4;
+ break;
case AMDGPU_PP_SENSOR_EDGE_TEMP:
+ ret = navi10_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_EDGE,
+ (uint32_t *)data);
+ *size = 4;
+ break;
case AMDGPU_PP_SENSOR_MEM_TEMP:
- ret = navi10_thermal_get_temperature(smu, sensor, (uint32_t *)data);
+ ret = navi10_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_MEM,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GFX_MCLK:
@@ -2325,210 +2275,6 @@ static int navi10_run_umc_cdr_workaround(struct smu_context *smu)
return 0;
}
-static void navi10_fill_i2c_req(SwI2cRequest_t *req, bool write,
- uint8_t address, uint32_t numbytes,
- uint8_t *data)
-{
- int i;
-
- req->I2CcontrollerPort = 0;
- req->I2CSpeed = 2;
- req->SlaveAddress = address;
- req->NumCmds = numbytes;
-
- for (i = 0; i < numbytes; i++) {
- SwI2cCmd_t *cmd = &req->SwI2cCmds[i];
-
- /* First 2 bytes are always write for lower 2b EEPROM address */
- if (i < 2)
- cmd->Cmd = 1;
- else
- cmd->Cmd = write;
-
-
- /* Add RESTART for read after address filled */
- cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0;
-
- /* Add STOP in the end */
- cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0;
-
- /* Fill with data regardless if read or write to simplify code */
- cmd->RegisterAddr = data[i];
- }
-}
-
-static int navi10_i2c_read_data(struct i2c_adapter *control,
- uint8_t address,
- uint8_t *data,
- uint32_t numbytes)
-{
- uint32_t i, ret = 0;
- SwI2cRequest_t req;
- struct amdgpu_device *adev = to_amdgpu_device(control);
- struct smu_table_context *smu_table = &adev->smu.smu_table;
- struct smu_table *table = &smu_table->driver_table;
-
- if (numbytes > MAX_SW_I2C_COMMANDS) {
- dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
- numbytes, MAX_SW_I2C_COMMANDS);
- return -EINVAL;
- }
-
- memset(&req, 0, sizeof(req));
- navi10_fill_i2c_req(&req, false, address, numbytes, data);
-
- mutex_lock(&adev->smu.mutex);
- /* Now read data starting with that address */
- ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req,
- true);
- mutex_unlock(&adev->smu.mutex);
-
- if (!ret) {
- SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr;
-
- /* Assume SMU fills res.SwI2cCmds[i].Data with read bytes */
- for (i = 0; i < numbytes; i++)
- data[i] = res->SwI2cCmds[i].Data;
-
- dev_dbg(adev->dev, "navi10_i2c_read_data, address = %x, bytes = %d, data :",
- (uint16_t)address, numbytes);
-
- print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
- 8, 1, data, numbytes, false);
- } else
- dev_err(adev->dev, "navi10_i2c_read_data - error occurred :%x", ret);
-
- return ret;
-}
-
-static int navi10_i2c_write_data(struct i2c_adapter *control,
- uint8_t address,
- uint8_t *data,
- uint32_t numbytes)
-{
- uint32_t ret;
- SwI2cRequest_t req;
- struct amdgpu_device *adev = to_amdgpu_device(control);
-
- if (numbytes > MAX_SW_I2C_COMMANDS) {
- dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
- numbytes, MAX_SW_I2C_COMMANDS);
- return -EINVAL;
- }
-
- memset(&req, 0, sizeof(req));
- navi10_fill_i2c_req(&req, true, address, numbytes, data);
-
- mutex_lock(&adev->smu.mutex);
- ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true);
- mutex_unlock(&adev->smu.mutex);
-
- if (!ret) {
- dev_dbg(adev->dev, "navi10_i2c_write(), address = %x, bytes = %d , data: ",
- (uint16_t)address, numbytes);
-
- print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
- 8, 1, data, numbytes, false);
- /*
- * According to EEPROM spec there is a MAX of 10 ms required for
- * EEPROM to flush internal RX buffer after STOP was issued at the
- * end of write transaction. During this time the EEPROM will not be
- * responsive to any more commands - so wait a bit more.
- */
- msleep(10);
-
- } else
- dev_err(adev->dev, "navi10_i2c_write- error occurred :%x", ret);
-
- return ret;
-}
-
-static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap,
- struct i2c_msg *msgs, int num)
-{
- uint32_t i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0;
- uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 };
-
- for (i = 0; i < num; i++) {
- /*
- * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at
- * once and hence the data needs to be spliced into chunks and sent each
- * chunk separately
- */
- data_size = msgs[i].len - 2;
- data_chunk_size = MAX_SW_I2C_COMMANDS - 2;
- next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff);
- data_ptr = msgs[i].buf + 2;
-
- for (j = 0; j < data_size / data_chunk_size; j++) {
- /* Insert the EEPROM dest addess, bits 0-15 */
- data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
- data_chunk[1] = (next_eeprom_addr & 0xff);
-
- if (msgs[i].flags & I2C_M_RD) {
- ret = navi10_i2c_read_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- data_chunk, MAX_SW_I2C_COMMANDS);
-
- memcpy(data_ptr, data_chunk + 2, data_chunk_size);
- } else {
-
- memcpy(data_chunk + 2, data_ptr, data_chunk_size);
-
- ret = navi10_i2c_write_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- data_chunk, MAX_SW_I2C_COMMANDS);
- }
-
- if (ret) {
- num = -EIO;
- goto fail;
- }
-
- next_eeprom_addr += data_chunk_size;
- data_ptr += data_chunk_size;
- }
-
- if (data_size % data_chunk_size) {
- data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
- data_chunk[1] = (next_eeprom_addr & 0xff);
-
- if (msgs[i].flags & I2C_M_RD) {
- ret = navi10_i2c_read_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- data_chunk, (data_size % data_chunk_size) + 2);
-
- memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size);
- } else {
- memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size);
-
- ret = navi10_i2c_write_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- data_chunk, (data_size % data_chunk_size) + 2);
- }
-
- if (ret) {
- num = -EIO;
- goto fail;
- }
- }
- }
-
-fail:
- return num;
-}
-
-static u32 navi10_i2c_func(struct i2c_adapter *adap)
-{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
-}
-
-
-static const struct i2c_algorithm navi10_i2c_algo = {
- .master_xfer = navi10_i2c_xfer,
- .functionality = navi10_i2c_func,
-};
-
static ssize_t navi10_get_gpu_metrics(struct smu_context *smu,
void **table)
{
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index 0600befc6e4c..db0f2a476c23 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -1119,44 +1119,6 @@ static int sienna_cichlid_display_config_changed(struct smu_context *smu)
return ret;
}
-static int sienna_cichlid_get_gpu_power(struct smu_context *smu, uint32_t *value)
-{
- if (!value)
- return -EINVAL;
-
- return sienna_cichlid_get_smu_metrics_data(smu,
- METRICS_AVERAGE_SOCKETPOWER,
- value);
-}
-
-static int sienna_cichlid_get_current_activity_percent(struct smu_context *smu,
- enum amd_pp_sensors sensor,
- uint32_t *value)
-{
- int ret = 0;
-
- if (!value)
- return -EINVAL;
-
- switch (sensor) {
- case AMDGPU_PP_SENSOR_GPU_LOAD:
- ret = sienna_cichlid_get_smu_metrics_data(smu,
- METRICS_AVERAGE_GFXACTIVITY,
- value);
- break;
- case AMDGPU_PP_SENSOR_MEM_LOAD:
- ret = sienna_cichlid_get_smu_metrics_data(smu,
- METRICS_AVERAGE_MEMACTIVITY,
- value);
- break;
- default:
- dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n");
- return -EINVAL;
- }
-
- return ret;
-}
-
static bool sienna_cichlid_is_dpm_running(struct smu_context *smu)
{
int ret = 0;
@@ -1468,39 +1430,6 @@ static int sienna_cichlid_set_watermarks_table(struct smu_context *smu,
return 0;
}
-static int sienna_cichlid_thermal_get_temperature(struct smu_context *smu,
- enum amd_pp_sensors sensor,
- uint32_t *value)
-{
- int ret = 0;
-
- if (!value)
- return -EINVAL;
-
- switch (sensor) {
- case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
- ret = sienna_cichlid_get_smu_metrics_data(smu,
- METRICS_TEMPERATURE_HOTSPOT,
- value);
- break;
- case AMDGPU_PP_SENSOR_EDGE_TEMP:
- ret = sienna_cichlid_get_smu_metrics_data(smu,
- METRICS_TEMPERATURE_EDGE,
- value);
- break;
- case AMDGPU_PP_SENSOR_MEM_TEMP:
- ret = sienna_cichlid_get_smu_metrics_data(smu,
- METRICS_TEMPERATURE_MEM,
- value);
- break;
- default:
- dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n");
- return -EINVAL;
- }
-
- return ret;
-}
-
static int sienna_cichlid_read_sensor(struct smu_context *smu,
enum amd_pp_sensors sensor,
void *data, uint32_t *size)
@@ -1519,18 +1448,39 @@ static int sienna_cichlid_read_sensor(struct smu_context *smu,
*size = 4;
break;
case AMDGPU_PP_SENSOR_MEM_LOAD:
+ ret = sienna_cichlid_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_MEMACTIVITY,
+ (uint32_t *)data);
+ *size = 4;
+ break;
case AMDGPU_PP_SENSOR_GPU_LOAD:
- ret = sienna_cichlid_get_current_activity_percent(smu, sensor, (uint32_t *)data);
+ ret = sienna_cichlid_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXACTIVITY,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GPU_POWER:
- ret = sienna_cichlid_get_gpu_power(smu, (uint32_t *)data);
+ ret = sienna_cichlid_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_SOCKETPOWER,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
+ ret = sienna_cichlid_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_HOTSPOT,
+ (uint32_t *)data);
+ *size = 4;
+ break;
case AMDGPU_PP_SENSOR_EDGE_TEMP:
+ ret = sienna_cichlid_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_EDGE,
+ (uint32_t *)data);
+ *size = 4;
+ break;
case AMDGPU_PP_SENSOR_MEM_TEMP:
- ret = sienna_cichlid_thermal_get_temperature(smu, sensor, (uint32_t *)data);
+ ret = sienna_cichlid_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_MEM,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GFX_MCLK:
@@ -1805,11 +1755,6 @@ static void sienna_cichlid_dump_pptable(struct smu_context *smu)
dev_info(smu->adev->dev, "SmnclkDpmFreq[%d] = 0x%x\n", i, pptable->SmnclkDpmFreq[i]);
dev_info(smu->adev->dev, "SmnclkDpmVoltage[%d] = 0x%x\n", i, pptable->SmnclkDpmVoltage[i]);
}
- dev_info(smu->adev->dev, "PaddingAPCC[0] = 0x%x\n", pptable->PaddingAPCC[0]);
- dev_info(smu->adev->dev, "PaddingAPCC[1] = 0x%x\n", pptable->PaddingAPCC[1]);
- dev_info(smu->adev->dev, "PaddingAPCC[2] = 0x%x\n", pptable->PaddingAPCC[2]);
- dev_info(smu->adev->dev, "PaddingAPCC[3] = 0x%x\n", pptable->PaddingAPCC[3]);
-
dev_info(smu->adev->dev, "ThrottlerControlMask = 0x%x\n", pptable->ThrottlerControlMask);
dev_info(smu->adev->dev, "FwDStateMask = 0x%x\n", pptable->FwDStateMask);
@@ -2036,23 +1981,6 @@ static void sienna_cichlid_dump_pptable(struct smu_context *smu)
for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++)
dev_info(smu->adev->dev, " .[%02d] = 0x%x\n", i, pptable->FreqTableFclk[i]);
- dev_info(smu->adev->dev, "Paddingclks[0] = 0x%x\n", pptable->Paddingclks[0]);
- dev_info(smu->adev->dev, "Paddingclks[1] = 0x%x\n", pptable->Paddingclks[1]);
- dev_info(smu->adev->dev, "Paddingclks[2] = 0x%x\n", pptable->Paddingclks[2]);
- dev_info(smu->adev->dev, "Paddingclks[3] = 0x%x\n", pptable->Paddingclks[3]);
- dev_info(smu->adev->dev, "Paddingclks[4] = 0x%x\n", pptable->Paddingclks[4]);
- dev_info(smu->adev->dev, "Paddingclks[5] = 0x%x\n", pptable->Paddingclks[5]);
- dev_info(smu->adev->dev, "Paddingclks[6] = 0x%x\n", pptable->Paddingclks[6]);
- dev_info(smu->adev->dev, "Paddingclks[7] = 0x%x\n", pptable->Paddingclks[7]);
- dev_info(smu->adev->dev, "Paddingclks[8] = 0x%x\n", pptable->Paddingclks[8]);
- dev_info(smu->adev->dev, "Paddingclks[9] = 0x%x\n", pptable->Paddingclks[9]);
- dev_info(smu->adev->dev, "Paddingclks[10] = 0x%x\n", pptable->Paddingclks[10]);
- dev_info(smu->adev->dev, "Paddingclks[11] = 0x%x\n", pptable->Paddingclks[11]);
- dev_info(smu->adev->dev, "Paddingclks[12] = 0x%x\n", pptable->Paddingclks[12]);
- dev_info(smu->adev->dev, "Paddingclks[13] = 0x%x\n", pptable->Paddingclks[13]);
- dev_info(smu->adev->dev, "Paddingclks[14] = 0x%x\n", pptable->Paddingclks[14]);
- dev_info(smu->adev->dev, "Paddingclks[15] = 0x%x\n", pptable->Paddingclks[15]);
-
dev_info(smu->adev->dev, "DcModeMaxFreq\n");
dev_info(smu->adev->dev, " .PPCLK_GFXCLK = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_GFXCLK]);
dev_info(smu->adev->dev, " .PPCLK_SOCCLK = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_SOCCLK]);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
index b6453ee6f8e6..624065d3c079 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
@@ -216,6 +216,7 @@ int smu_v11_0_check_fw_status(struct smu_context *smu)
int smu_v11_0_check_fw_version(struct smu_context *smu)
{
+ struct amdgpu_device *adev = smu->adev;
uint32_t if_version = 0xff, smu_version = 0xff;
uint16_t smu_major;
uint8_t smu_minor, smu_debug;
@@ -228,6 +229,8 @@ int smu_v11_0_check_fw_version(struct smu_context *smu)
smu_major = (smu_version >> 16) & 0xffff;
smu_minor = (smu_version >> 8) & 0xff;
smu_debug = (smu_version >> 0) & 0xff;
+ if (smu->is_apu)
+ adev->pm.fw_version = smu_version;
switch (smu->adev->asic_type) {
case CHIP_ARCTURUS:
@@ -336,8 +339,7 @@ int smu_v11_0_setup_pptable(struct smu_context *smu)
hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data;
version_major = le16_to_cpu(hdr->header.header_version_major);
version_minor = le16_to_cpu(hdr->header.header_version_minor);
- if ((version_major == 2 && smu->smu_table.boot_values.pp_table_id > 0) ||
- adev->asic_type == CHIP_DIMGREY_CAVEFISH) {
+ if (version_major == 2 && smu->smu_table.boot_values.pp_table_id > 0) {
dev_info(adev->dev, "use driver provided pptable %d\n", smu->smu_table.boot_values.pp_table_id);
switch (version_minor) {
case 0:
@@ -435,11 +437,13 @@ int smu_v11_0_fini_smc_tables(struct smu_context *smu)
kfree(smu_table->overdrive_table);
kfree(smu_table->max_sustainable_clocks);
kfree(smu_table->driver_pptable);
+ kfree(smu_table->clocks_table);
smu_table->gpu_metrics_table = NULL;
smu_table->boot_overdrive_table = NULL;
smu_table->overdrive_table = NULL;
smu_table->max_sustainable_clocks = NULL;
smu_table->driver_pptable = NULL;
+ smu_table->clocks_table = NULL;
kfree(smu_table->hardcode_pptable);
smu_table->hardcode_pptable = NULL;
@@ -466,11 +470,11 @@ int smu_v11_0_init_power(struct smu_context *smu)
{
struct smu_power_context *smu_power = &smu->smu_power;
- smu_power->power_context = kzalloc(sizeof(struct smu_11_0_dpm_context),
+ smu_power->power_context = kzalloc(sizeof(struct smu_11_0_power_context),
GFP_KERNEL);
if (!smu_power->power_context)
return -ENOMEM;
- smu_power->power_context_size = sizeof(struct smu_11_0_dpm_context);
+ smu_power->power_context_size = sizeof(struct smu_11_0_power_context);
return 0;
}
@@ -1183,7 +1187,12 @@ int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu,
if (ret)
return ret;
- crystal_clock_freq = amdgpu_asic_get_xclk(adev);
+ /*
+ * crystal_clock_freq div by 4 is required since the fan control
+ * module refers to 25MHz
+ */
+
+ crystal_clock_freq = amdgpu_asic_get_xclk(adev) / 4;
tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
@@ -1481,6 +1490,9 @@ enum smu_baco_state smu_v11_0_baco_get_state(struct smu_context *smu)
return baco_state;
}
+#define D3HOT_BACO_SEQUENCE 0
+#define D3HOT_BAMACO_SEQUENCE 2
+
int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state)
{
struct smu_baco_context *smu_baco = &smu->smu_baco;
@@ -1495,15 +1507,34 @@ int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state)
mutex_lock(&smu_baco->mutex);
if (state == SMU_BACO_STATE_ENTER) {
- if (!ras || !ras->supported) {
- data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL);
- data |= 0x80000000;
- WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data);
-
- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 0, NULL);
- } else {
- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 1, NULL);
+ switch (adev->asic_type) {
+ case CHIP_SIENNA_CICHLID:
+ case CHIP_NAVY_FLOUNDER:
+ case CHIP_DIMGREY_CAVEFISH:
+ if (amdgpu_runtime_pm == 2)
+ ret = smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_EnterBaco,
+ D3HOT_BAMACO_SEQUENCE,
+ NULL);
+ else
+ ret = smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_EnterBaco,
+ D3HOT_BACO_SEQUENCE,
+ NULL);
+ break;
+ default:
+ if (!ras || !ras->supported) {
+ data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL);
+ data |= 0x80000000;
+ WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data);
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 0, NULL);
+ } else {
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 1, NULL);
+ }
+ break;
}
+
} else {
ret = smu_cmn_send_smc_msg(smu, SMU_MSG_ExitBaco, NULL);
if (ret)
@@ -1996,6 +2027,18 @@ void smu_v11_0_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics)
gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
}
+void smu_v11_0_init_gpu_metrics_v2_0(struct gpu_metrics_v2_0 *gpu_metrics)
+{
+ memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v2_0));
+
+ gpu_metrics->common_header.structure_size =
+ sizeof(struct gpu_metrics_v2_0);
+ gpu_metrics->common_header.format_revision = 2;
+ gpu_metrics->common_header.content_revision = 0;
+
+ gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
+}
+
int smu_v11_0_gfx_ulv_control(struct smu_context *smu,
bool enablement)
{
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
index 83a1b0a04eb1..a81e5c823211 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
@@ -200,8 +200,14 @@ static int vangogh_tables_init(struct smu_context *smu)
if (!smu_table->watermarks_table)
goto err2_out;
+ smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL);
+ if (!smu_table->clocks_table)
+ goto err3_out;
+
return 0;
+err3_out:
+ kfree(smu_table->clocks_table);
err2_out:
kfree(smu_table->gpu_metrics_table);
err1_out:
@@ -259,6 +265,12 @@ static int vangogh_get_smu_metrics_data(struct smu_context *smu,
case METRICS_THROTTLER_STATUS:
*value = metrics->ThrottlerStatus;
break;
+ case METRICS_VOLTAGE_VDDGFX:
+ *value = metrics->Voltage[2];
+ break;
+ case METRICS_VOLTAGE_VDDSOC:
+ *value = metrics->Voltage[1];
+ break;
default:
*value = UINT_MAX;
break;
@@ -390,91 +402,33 @@ static bool vangogh_is_dpm_running(struct smu_context *smu)
return !!(feature_enabled & SMC_DPM_FEATURE);
}
-static int vangogh_get_current_activity_percent(struct smu_context *smu,
- enum amd_pp_sensors sensor,
- uint32_t *value)
-{
- int ret = 0;
-
- if (!value)
- return -EINVAL;
-
- switch (sensor) {
- case AMDGPU_PP_SENSOR_GPU_LOAD:
- ret = vangogh_get_smu_metrics_data(smu,
- METRICS_AVERAGE_GFXACTIVITY,
- value);
- break;
- default:
- dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int vangogh_get_gpu_power(struct smu_context *smu, uint32_t *value)
-{
- if (!value)
- return -EINVAL;
-
- return vangogh_get_smu_metrics_data(smu,
- METRICS_AVERAGE_SOCKETPOWER,
- value);
-}
-
-static int vangogh_thermal_get_temperature(struct smu_context *smu,
- enum amd_pp_sensors sensor,
- uint32_t *value)
-{
- int ret = 0;
-
- if (!value)
- return -EINVAL;
-
- switch (sensor) {
- case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
- ret = vangogh_get_smu_metrics_data(smu,
- METRICS_TEMPERATURE_HOTSPOT,
- value);
- break;
- case AMDGPU_PP_SENSOR_EDGE_TEMP:
- ret = vangogh_get_smu_metrics_data(smu,
- METRICS_TEMPERATURE_EDGE,
- value);
- break;
- default:
- dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n");
- return -EINVAL;
- }
-
- return ret;
-}
-
-static int vangogh_get_current_clk_freq_by_table(struct smu_context *smu,
- enum smu_clk_type clk_type,
- uint32_t *value)
+static int vangogh_print_fine_grain_clk(struct smu_context *smu,
+ enum smu_clk_type clk_type, char *buf)
{
- MetricsMember_t member_type;
+ int size = 0;
switch (clk_type) {
- case SMU_GFXCLK:
- member_type = METRICS_AVERAGE_GFXCLK;
- break;
- case SMU_MCLK:
- case SMU_UCLK:
- member_type = METRICS_AVERAGE_UCLK;
+ case SMU_OD_SCLK:
+ if (smu->od_enabled) {
+ size = sprintf(buf, "%s:\n", "OD_SCLK");
+ size += sprintf(buf + size, "0: %10uMhz\n",
+ (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq);
+ size += sprintf(buf + size, "1: %10uMhz\n",
+ (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq);
+ }
break;
- case SMU_SOCCLK:
- member_type = METRICS_AVERAGE_SOCCLK;
+ case SMU_OD_RANGE:
+ if (smu->od_enabled) {
+ size = sprintf(buf, "%s:\n", "OD_RANGE");
+ size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
+ smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq);
+ }
break;
default:
- return -EINVAL;
+ break;
}
- return vangogh_get_smu_metrics_data(smu,
- member_type,
- value);
+ return size;
}
static int vangogh_read_sensor(struct smu_context *smu,
@@ -489,30 +443,53 @@ static int vangogh_read_sensor(struct smu_context *smu,
mutex_lock(&smu->sensor_lock);
switch (sensor) {
case AMDGPU_PP_SENSOR_GPU_LOAD:
- ret = vangogh_get_current_activity_percent(smu, sensor, (uint32_t *)data);
+ ret = vangogh_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXACTIVITY,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GPU_POWER:
- ret = vangogh_get_gpu_power(smu, (uint32_t *)data);
+ ret = vangogh_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_SOCKETPOWER,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_EDGE_TEMP:
+ ret = vangogh_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_EDGE,
+ (uint32_t *)data);
+ *size = 4;
+ break;
case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
- ret = vangogh_thermal_get_temperature(smu, sensor, (uint32_t *)data);
+ ret = vangogh_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_HOTSPOT,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GFX_MCLK:
- ret = vangogh_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data);
+ ret = vangogh_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_UCLK,
+ (uint32_t *)data);
*(uint32_t *)data *= 100;
*size = 4;
break;
case AMDGPU_PP_SENSOR_GFX_SCLK:
- ret = vangogh_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data);
+ ret = vangogh_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXCLK,
+ (uint32_t *)data);
*(uint32_t *)data *= 100;
*size = 4;
break;
case AMDGPU_PP_SENSOR_VDDGFX:
- ret = smu_v11_0_get_gfx_vdd(smu, (uint32_t *)data);
+ ret = vangogh_get_smu_metrics_data(smu,
+ METRICS_VOLTAGE_VDDGFX,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_VDDNB:
+ ret = vangogh_get_smu_metrics_data(smu,
+ METRICS_VOLTAGE_VDDSOC,
+ (uint32_t *)data);
*size = 4;
break;
default:
@@ -584,6 +561,167 @@ static int vangogh_set_watermarks_table(struct smu_context *smu,
return 0;
}
+static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu,
+ void **table)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct gpu_metrics_v2_0 *gpu_metrics =
+ (struct gpu_metrics_v2_0 *)smu_table->gpu_metrics_table;
+ SmuMetrics_t metrics;
+ int ret = 0;
+
+ ret = smu_cmn_get_metrics_table(smu, &metrics, true);
+ if (ret)
+ return ret;
+
+ smu_v11_0_init_gpu_metrics_v2_0(gpu_metrics);
+
+ gpu_metrics->temperature_gfx = metrics.GfxTemperature;
+ gpu_metrics->temperature_soc = metrics.SocTemperature;
+ memcpy(&gpu_metrics->temperature_core[0],
+ &metrics.CoreTemperature[0],
+ sizeof(uint16_t) * 8);
+ gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0];
+ gpu_metrics->temperature_l3[1] = metrics.L3Temperature[1];
+
+ gpu_metrics->average_gfx_activity = metrics.GfxActivity;
+ gpu_metrics->average_mm_activity = metrics.UvdActivity;
+
+ gpu_metrics->average_socket_power = metrics.CurrentSocketPower;
+ gpu_metrics->average_cpu_power = metrics.Power[0];
+ gpu_metrics->average_soc_power = metrics.Power[1];
+ memcpy(&gpu_metrics->average_core_power[0],
+ &metrics.CorePower[0],
+ sizeof(uint16_t) * 8);
+
+ gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency;
+ gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency;
+ gpu_metrics->average_fclk_frequency = metrics.MemclkFrequency;
+ gpu_metrics->average_vclk_frequency = metrics.VclkFrequency;
+
+ memcpy(&gpu_metrics->current_coreclk[0],
+ &metrics.CoreFrequency[0],
+ sizeof(uint16_t) * 8);
+ gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0];
+ gpu_metrics->current_l3clk[1] = metrics.L3Frequency[1];
+
+ gpu_metrics->throttle_status = metrics.ThrottlerStatus;
+
+ *table = (void *)gpu_metrics;
+
+ return sizeof(struct gpu_metrics_v2_0);
+}
+
+static int vangogh_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type,
+ long input[], uint32_t size)
+{
+ int ret = 0;
+
+ if (!smu->od_enabled) {
+ dev_warn(smu->adev->dev, "Fine grain is not enabled!\n");
+ return -EINVAL;
+ }
+
+ switch (type) {
+ case PP_OD_EDIT_SCLK_VDDC_TABLE:
+ if (size != 2) {
+ dev_err(smu->adev->dev, "Input parameter number not correct\n");
+ return -EINVAL;
+ }
+
+ if (input[0] == 0) {
+ if (input[1] < smu->gfx_default_hard_min_freq) {
+ dev_warn(smu->adev->dev, "Fine grain setting minimum sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n",
+ input[1], smu->gfx_default_hard_min_freq);
+ return -EINVAL;
+ }
+ smu->gfx_actual_hard_min_freq = input[1];
+ } else if (input[0] == 1) {
+ if (input[1] > smu->gfx_default_soft_max_freq) {
+ dev_warn(smu->adev->dev, "Fine grain setting maximum sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n",
+ input[1], smu->gfx_default_soft_max_freq);
+ return -EINVAL;
+ }
+ smu->gfx_actual_soft_max_freq = input[1];
+ } else {
+ return -EINVAL;
+ }
+ break;
+ case PP_OD_RESTORE_DEFAULT_TABLE:
+ if (size != 0) {
+ dev_err(smu->adev->dev, "Input parameter number not correct\n");
+ return -EINVAL;
+ } else {
+ smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
+ smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
+ smu->gfx_actual_hard_min_freq, NULL);
+ if (ret) {
+ dev_err(smu->adev->dev, "Restore the default hard min sclk failed!");
+ return ret;
+ }
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
+ smu->gfx_actual_soft_max_freq, NULL);
+ if (ret) {
+ dev_err(smu->adev->dev, "Restore the default soft max sclk failed!");
+ return ret;
+ }
+ }
+ break;
+ case PP_OD_COMMIT_DPM_TABLE:
+ if (size != 0) {
+ dev_err(smu->adev->dev, "Input parameter number not correct\n");
+ return -EINVAL;
+ } else {
+ if (smu->gfx_actual_hard_min_freq > smu->gfx_actual_soft_max_freq) {
+ dev_err(smu->adev->dev, "The setting minimun sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n",
+ smu->gfx_actual_hard_min_freq, smu->gfx_actual_soft_max_freq);
+ return -EINVAL;
+ }
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
+ smu->gfx_actual_hard_min_freq, NULL);
+ if (ret) {
+ dev_err(smu->adev->dev, "Set hard min sclk failed!");
+ return ret;
+ }
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
+ smu->gfx_actual_soft_max_freq, NULL);
+ if (ret) {
+ dev_err(smu->adev->dev, "Set soft max sclk failed!");
+ return ret;
+ }
+ }
+ break;
+ default:
+ return -ENOSYS;
+ }
+
+ return ret;
+}
+
+static int vangogh_set_default_dpm_tables(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+
+ return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0, smu_table->clocks_table, false);
+}
+
+static int vangogh_set_fine_grain_gfx_freq_parameters(struct smu_context *smu)
+{
+ DpmClocks_t *clk_table = smu->smu_table.clocks_table;
+
+ smu->gfx_default_hard_min_freq = clk_table->MinGfxClk;
+ smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk;
+ smu->gfx_actual_hard_min_freq = 0;
+ smu->gfx_actual_soft_max_freq = 0;
+
+ return 0;
+}
+
static const struct pptable_funcs vangogh_ppt_funcs = {
.check_fw_status = smu_v11_0_check_fw_status,
@@ -605,8 +743,12 @@ static const struct pptable_funcs vangogh_ppt_funcs = {
.get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
.set_watermarks_table = vangogh_set_watermarks_table,
.set_driver_table_location = smu_v11_0_set_driver_table_location,
- .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception,
.interrupt_work = smu_v11_0_interrupt_work,
+ .get_gpu_metrics = vangogh_get_gpu_metrics,
+ .od_edit_dpm_table = vangogh_od_edit_dpm_table,
+ .print_clk_levels = vangogh_print_fine_grain_clk,
+ .set_default_dpm_table = vangogh_set_default_dpm_tables,
+ .set_fine_grain_gfx_freq_parameters = vangogh_set_fine_grain_gfx_freq_parameters,
};
void vangogh_set_ppt_funcs(struct smu_context *smu)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
index 66c1026489be..dc75db8af371 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
@@ -170,7 +170,7 @@ err0_out:
return -ENOMEM;
}
-/**
+/*
* This interface just for getting uclk ultimate freq and should't introduce
* other likewise function result in overmuch callback.
*/
@@ -492,28 +492,6 @@ static int renoir_dpm_set_jpeg_enable(struct smu_context *smu, bool enable)
return ret;
}
-static int renoir_get_current_clk_freq_by_table(struct smu_context *smu,
- enum smu_clk_type clk_type,
- uint32_t *value)
-{
- int ret = 0, clk_id = 0;
- SmuMetrics_t metrics;
-
- ret = smu_cmn_get_metrics_table(smu, &metrics, false);
- if (ret)
- return ret;
-
- clk_id = smu_cmn_to_asic_specific_index(smu,
- CMN2ASIC_MAPPING_CLK,
- clk_type);
- if (clk_id < 0)
- return clk_id;
-
- *value = metrics.ClockFrequency[clk_id];
-
- return ret;
-}
-
static int renoir_force_dpm_limit_value(struct smu_context *smu, bool highest)
{
int ret = 0, i = 0;
@@ -574,89 +552,7 @@ static int renoir_unforce_dpm_levels(struct smu_context *smu) {
return ret;
}
-static int renoir_get_gpu_temperature(struct smu_context *smu, uint32_t *value)
-{
- int ret = 0;
- SmuMetrics_t metrics;
-
- if (!value)
- return -EINVAL;
-
- ret = smu_cmn_get_metrics_table(smu, &metrics, false);
- if (ret)
- return ret;
-
- *value = (metrics.GfxTemperature / 100) *
- SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
-
- return 0;
-}
-
-static int renoir_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 = smu_cmn_get_metrics_table(smu, &metrics, false);
- if (ret)
- return ret;
-
- switch (sensor) {
- case AMDGPU_PP_SENSOR_GPU_LOAD:
- *value = metrics.AverageGfxActivity / 100;
- break;
- default:
- dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int renoir_get_vddc(struct smu_context *smu, uint32_t *value,
- unsigned int index)
-{
- int ret = 0;
- SmuMetrics_t metrics;
-
- if (index >= 2)
- return -EINVAL;
-
- if (!value)
- return -EINVAL;
-
- ret = smu_cmn_get_metrics_table(smu, &metrics, false);
- if (ret)
- return ret;
-
- *value = metrics.Voltage[index];
-
- return 0;
-}
-
-static int renoir_get_power(struct smu_context *smu, uint32_t *value)
-{
- int ret = 0;
- SmuMetrics_t metrics;
-
- if (!value)
- return -EINVAL;
-
- ret = smu_cmn_get_metrics_table(smu, &metrics, false);
- if (ret)
- return ret;
-
- *value = metrics.CurrentSocketPower << 8;
-
- return 0;
-}
-
-/**
+/*
* This interface get dpm clock table for dc
*/
static int renoir_get_dpm_clock_table(struct smu_context *smu, struct dpm_clocks *clock_table)
@@ -1011,6 +907,71 @@ static int renoir_get_power_profile_mode(struct smu_context *smu,
return size;
}
+static int renoir_get_smu_metrics_data(struct smu_context *smu,
+ MetricsMember_t member,
+ uint32_t *value)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+
+ SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
+ int ret = 0;
+
+ mutex_lock(&smu->metrics_lock);
+
+ ret = smu_cmn_get_metrics_table_locked(smu,
+ NULL,
+ false);
+ if (ret) {
+ mutex_unlock(&smu->metrics_lock);
+ return ret;
+ }
+
+ switch (member) {
+ case METRICS_AVERAGE_GFXCLK:
+ *value = metrics->ClockFrequency[CLOCK_GFXCLK];
+ break;
+ case METRICS_AVERAGE_SOCCLK:
+ *value = metrics->ClockFrequency[CLOCK_SOCCLK];
+ break;
+ case METRICS_AVERAGE_UCLK:
+ *value = metrics->ClockFrequency[CLOCK_FCLK];
+ break;
+ case METRICS_AVERAGE_GFXACTIVITY:
+ *value = metrics->AverageGfxActivity / 100;
+ break;
+ case METRICS_AVERAGE_VCNACTIVITY:
+ *value = metrics->AverageUvdActivity / 100;
+ break;
+ case METRICS_AVERAGE_SOCKETPOWER:
+ *value = metrics->CurrentSocketPower << 8;
+ break;
+ case METRICS_TEMPERATURE_EDGE:
+ *value = (metrics->GfxTemperature / 100) *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case METRICS_TEMPERATURE_HOTSPOT:
+ *value = (metrics->SocTemperature / 100) *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case METRICS_THROTTLER_STATUS:
+ *value = metrics->ThrottlerStatus;
+ break;
+ case METRICS_VOLTAGE_VDDGFX:
+ *value = metrics->Voltage[0];
+ break;
+ case METRICS_VOLTAGE_VDDSOC:
+ *value = metrics->Voltage[1];
+ break;
+ default:
+ *value = UINT_MAX;
+ break;
+ }
+
+ mutex_unlock(&smu->metrics_lock);
+
+ return ret;
+}
+
static int renoir_read_sensor(struct smu_context *smu,
enum amd_pp_sensors sensor,
void *data, uint32_t *size)
@@ -1023,33 +984,53 @@ static int renoir_read_sensor(struct smu_context *smu,
mutex_lock(&smu->sensor_lock);
switch (sensor) {
case AMDGPU_PP_SENSOR_GPU_LOAD:
- ret = renoir_get_current_activity_percent(smu, sensor, (uint32_t *)data);
+ ret = renoir_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXACTIVITY,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_EDGE_TEMP:
+ ret = renoir_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_EDGE,
+ (uint32_t *)data);
*size = 4;
break;
- case AMDGPU_PP_SENSOR_GPU_TEMP:
- ret = renoir_get_gpu_temperature(smu, (uint32_t *)data);
+ case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
+ ret = renoir_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_HOTSPOT,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GFX_MCLK:
- ret = renoir_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data);
+ ret = renoir_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_UCLK,
+ (uint32_t *)data);
*(uint32_t *)data *= 100;
*size = 4;
break;
case AMDGPU_PP_SENSOR_GFX_SCLK:
- ret = renoir_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data);
+ ret = renoir_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXCLK,
+ (uint32_t *)data);
*(uint32_t *)data *= 100;
*size = 4;
break;
case AMDGPU_PP_SENSOR_VDDGFX:
- ret = renoir_get_vddc(smu, (uint32_t *)data, 0);
+ ret = renoir_get_smu_metrics_data(smu,
+ METRICS_VOLTAGE_VDDGFX,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_VDDNB:
- ret = renoir_get_vddc(smu, (uint32_t *)data, 1);
+ ret = renoir_get_smu_metrics_data(smu,
+ METRICS_VOLTAGE_VDDSOC,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GPU_POWER:
- ret = renoir_get_power(smu, (uint32_t *)data);
+ ret = renoir_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_SOCKETPOWER,
+ (uint32_t *)data);
*size = 4;
break;
default:
@@ -1136,6 +1117,12 @@ static ssize_t renoir_get_gpu_metrics(struct smu_context *smu,
return sizeof(struct gpu_metrics_v2_0);
}
+static int renoir_gfx_state_change_set(struct smu_context *smu, uint32_t state)
+{
+
+ return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GpuChangeState, state, NULL);
+}
+
static const struct pptable_funcs renoir_ppt_funcs = {
.set_power_state = NULL,
.print_clk_levels = renoir_print_clk_levels,
@@ -1171,6 +1158,7 @@ static const struct pptable_funcs renoir_ppt_funcs = {
.get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
.set_pp_feature_mask = smu_cmn_set_pp_feature_mask,
.get_gpu_metrics = renoir_get_gpu_metrics,
+ .gfx_state_change_set = renoir_gfx_state_change_set,
};
void renoir_set_ppt_funcs(struct smu_context *smu)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c
index 660f403d5770..522d55004655 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c
@@ -71,6 +71,7 @@ int smu_v12_0_check_fw_status(struct smu_context *smu)
int smu_v12_0_check_fw_version(struct smu_context *smu)
{
+ struct amdgpu_device *adev = smu->adev;
uint32_t if_version = 0xff, smu_version = 0xff;
uint16_t smu_major;
uint8_t smu_minor, smu_debug;
@@ -83,6 +84,8 @@ int smu_v12_0_check_fw_version(struct smu_context *smu)
smu_major = (smu_version >> 16) & 0xffff;
smu_minor = (smu_version >> 8) & 0xff;
smu_debug = (smu_version >> 0) & 0xff;
+ if (smu->is_apu)
+ adev->pm.fw_version = smu_version;
/*
* 1. if_version mismatch is not critical as our fw is designed
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
index dc28f22aeb38..f8260769061c 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
@@ -655,7 +655,7 @@ int smu_cmn_update_table(struct smu_context *smu,
return ret;
if (!drv2smu) {
- amdgpu_asic_flush_hdp(adev, NULL);
+ amdgpu_asic_invalidate_hdp(adev, NULL);
memcpy(table_data, table->cpu_addr, table_size);
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
index f7be2d1a0ff2..68d9464ababc 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
@@ -90,6 +90,7 @@
#define smu_get_fan_parameters(smu) smu_ppt_funcs(get_fan_parameters, 0, smu)
#define smu_post_init(smu) smu_ppt_funcs(post_init, 0, smu)
#define smu_gpo_control(smu, enablement) smu_ppt_funcs(gpo_control, 0, smu, enablement)
+#define smu_set_fine_grain_gfx_freq_parameters(smu) smu_ppt_funcs(set_fine_grain_gfx_freq_parameters, 0, smu)
#endif
#endif