aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/powerplay/amdgpu_smu.c')
-rw-r--r--drivers/gpu/drm/amd/powerplay/amdgpu_smu.c144
1 files changed, 134 insertions, 10 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
index 838a369c9ec3..0826625573dc 100644
--- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
@@ -133,6 +133,78 @@ int smu_get_dpm_freq_range(struct smu_context *smu,
return ret;
}
+static int smu_dpm_set_vcn_enable_locked(struct smu_context *smu,
+ bool enable)
+{
+ struct smu_power_context *smu_power = &smu->smu_power;
+ struct smu_power_gate *power_gate = &smu_power->power_gate;
+ int ret = 0;
+
+ if (!smu->ppt_funcs->dpm_set_vcn_enable)
+ return 0;
+
+ if (atomic_read(&power_gate->vcn_gated) ^ enable)
+ return 0;
+
+ ret = smu->ppt_funcs->dpm_set_vcn_enable(smu, enable);
+ if (!ret)
+ atomic_set(&power_gate->vcn_gated, !enable);
+
+ return ret;
+}
+
+static int smu_dpm_set_vcn_enable(struct smu_context *smu,
+ bool enable)
+{
+ struct smu_power_context *smu_power = &smu->smu_power;
+ struct smu_power_gate *power_gate = &smu_power->power_gate;
+ int ret = 0;
+
+ mutex_lock(&power_gate->vcn_gate_lock);
+
+ ret = smu_dpm_set_vcn_enable_locked(smu, enable);
+
+ mutex_unlock(&power_gate->vcn_gate_lock);
+
+ return ret;
+}
+
+static int smu_dpm_set_jpeg_enable_locked(struct smu_context *smu,
+ bool enable)
+{
+ struct smu_power_context *smu_power = &smu->smu_power;
+ struct smu_power_gate *power_gate = &smu_power->power_gate;
+ int ret = 0;
+
+ if (!smu->ppt_funcs->dpm_set_jpeg_enable)
+ return 0;
+
+ if (atomic_read(&power_gate->jpeg_gated) ^ enable)
+ return 0;
+
+ ret = smu->ppt_funcs->dpm_set_jpeg_enable(smu, enable);
+ if (!ret)
+ atomic_set(&power_gate->jpeg_gated, !enable);
+
+ return ret;
+}
+
+static int smu_dpm_set_jpeg_enable(struct smu_context *smu,
+ bool enable)
+{
+ struct smu_power_context *smu_power = &smu->smu_power;
+ struct smu_power_gate *power_gate = &smu_power->power_gate;
+ int ret = 0;
+
+ mutex_lock(&power_gate->jpeg_gate_lock);
+
+ ret = smu_dpm_set_jpeg_enable_locked(smu, enable);
+
+ mutex_unlock(&power_gate->jpeg_gate_lock);
+
+ return ret;
+}
+
/**
* smu_dpm_set_power_gate - power gate/ungate the specific IP block
*
@@ -353,6 +425,45 @@ static int smu_early_init(void *handle)
return smu_set_funcs(adev);
}
+static int smu_set_default_dpm_table(struct smu_context *smu)
+{
+ struct smu_power_context *smu_power = &smu->smu_power;
+ struct smu_power_gate *power_gate = &smu_power->power_gate;
+ int vcn_gate, jpeg_gate;
+ int ret = 0;
+
+ if (!smu->ppt_funcs->set_default_dpm_table)
+ return 0;
+
+ mutex_lock(&power_gate->vcn_gate_lock);
+ mutex_lock(&power_gate->jpeg_gate_lock);
+
+ vcn_gate = atomic_read(&power_gate->vcn_gated);
+ jpeg_gate = atomic_read(&power_gate->jpeg_gated);
+
+ ret = smu_dpm_set_vcn_enable_locked(smu, true);
+ if (ret)
+ goto err0_out;
+
+ ret = smu_dpm_set_jpeg_enable_locked(smu, true);
+ if (ret)
+ goto err1_out;
+
+ ret = smu->ppt_funcs->set_default_dpm_table(smu);
+ if (ret)
+ dev_err(smu->adev->dev,
+ "Failed to setup default dpm clock tables!\n");
+
+ smu_dpm_set_jpeg_enable_locked(smu, !jpeg_gate);
+err1_out:
+ smu_dpm_set_vcn_enable_locked(smu, !vcn_gate);
+err0_out:
+ mutex_unlock(&power_gate->jpeg_gate_lock);
+ mutex_unlock(&power_gate->vcn_gate_lock);
+
+ return ret;
+}
+
static int smu_late_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -579,6 +690,10 @@ static int smu_smc_table_sw_init(struct smu_context *smu)
if (ret)
return ret;
+ ret = smu_i2c_init(smu, &smu->adev->pm.smu_i2c);
+ if (ret)
+ return ret;
+
return 0;
}
@@ -586,6 +701,8 @@ static int smu_smc_table_sw_fini(struct smu_context *smu)
{
int ret;
+ smu_i2c_fini(smu, &smu->adev->pm.smu_i2c);
+
ret = smu_free_memory_pool(smu);
if (ret)
return ret;
@@ -643,6 +760,11 @@ static int smu_sw_init(void *handle)
smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+ atomic_set(&smu->smu_power.power_gate.vcn_gated, 1);
+ atomic_set(&smu->smu_power.power_gate.jpeg_gated, 1);
+ mutex_init(&smu->smu_power.power_gate.vcn_gate_lock);
+ mutex_init(&smu->smu_power.power_gate.jpeg_gate_lock);
+
smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;
smu->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;
@@ -734,7 +856,7 @@ static int smu_smc_hw_setup(struct smu_context *smu)
uint32_t pcie_gen = 0, pcie_width = 0;
int ret;
- if (smu_is_dpm_running(smu) && adev->in_suspend) {
+ if (adev->in_suspend && smu_is_dpm_running(smu)) {
dev_info(adev->dev, "dpm has been enabled\n");
return 0;
}
@@ -844,10 +966,6 @@ static int smu_smc_hw_setup(struct smu_context *smu)
return ret;
}
- ret = smu_i2c_init(smu, &adev->pm.smu_i2c);
- if (ret)
- return ret;
-
ret = smu_disable_umc_cdr_12gbps_workaround(smu);
if (ret) {
dev_err(adev->dev, "Workaround failed to disable UMC CDR feature on 12Gbps SKU!\n");
@@ -1046,8 +1164,6 @@ static int smu_smc_hw_cleanup(struct smu_context *smu)
struct amdgpu_device *adev = smu->adev;
int ret = 0;
- smu_i2c_fini(smu, &adev->pm.smu_i2c);
-
cancel_work_sync(&smu->throttling_logging_work);
ret = smu_disable_thermal_alert(smu);
@@ -1590,6 +1706,9 @@ int smu_set_mp1_state(struct smu_context *smu,
}
ret = smu_send_smc_msg(smu, msg, NULL);
+ /* some asics may not support those messages */
+ if (ret == -EINVAL)
+ ret = 0;
if (ret)
dev_err(smu->adev->dev, "[PrepareMp1] Failed!\n");
@@ -1944,6 +2063,10 @@ int smu_read_sensor(struct smu_context *smu,
mutex_lock(&smu->mutex);
+ if (smu->ppt_funcs->read_sensor)
+ if (!smu->ppt_funcs->read_sensor(smu, sensor, data, size))
+ goto unlock;
+
switch (sensor) {
case AMDGPU_PP_SENSOR_STABLE_PSTATE_SCLK:
*((uint32_t *)data) = pstate_table->gfxclk_pstate.standard * 100;
@@ -1966,7 +2089,7 @@ int smu_read_sensor(struct smu_context *smu,
*size = 4;
break;
case AMDGPU_PP_SENSOR_VCN_POWER_STATE:
- *(uint32_t *)data = smu->smu_power.power_gate.vcn_gated ? 0 : 1;
+ *(uint32_t *)data = atomic_read(&smu->smu_power.power_gate.vcn_gated) ? 0: 1;
*size = 4;
break;
case AMDGPU_PP_SENSOR_MIN_FAN_RPM:
@@ -1974,11 +2097,12 @@ int smu_read_sensor(struct smu_context *smu,
*size = 4;
break;
default:
- if (smu->ppt_funcs->read_sensor)
- ret = smu->ppt_funcs->read_sensor(smu, sensor, data, size);
+ *size = 0;
+ ret = -EOPNOTSUPP;
break;
}
+unlock:
mutex_unlock(&smu->mutex);
return ret;