From: Boyuan Zhang <boyuan.zhang@xxxxxxx> Add a new function to set powergating_by_smu for the given instance Signed-off-by: Boyuan Zhang <boyuan.zhang@xxxxxxx> --- .../gpu/drm/amd/include/kgd_pp_interface.h | 2 + drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 67 +++++++++++++++++++ drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 4 ++ drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 1 + 4 files changed, 74 insertions(+) diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index 2fa71f68205e..cdd891f51422 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -406,6 +406,8 @@ struct amd_pm_funcs { int (*wait_for_fw_loading_complete)(void *handle); int (*set_powergating_by_smu)(void *handle, uint32_t block_type, bool gate); + int (*set_powergating_by_smu_instance)(void *handle, + uint32_t block_type, bool gate, int inst); int (*set_clockgating_by_smu)(void *handle, uint32_t msg_id); int (*set_power_limit)(void *handle, uint32_t n); int (*get_power_limit)(void *handle, uint32_t *limit, diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 9dc82f4d7c93..f2d2f85476dc 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -110,6 +110,49 @@ int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block return ret; } +int amdgpu_dpm_set_powergating_by_smu_instance(struct amdgpu_device *adev, uint32_t block_type, bool gate, int inst) +{ + int ret = 0; + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + enum ip_power_state pwr_state = gate ? POWER_STATE_OFF : POWER_STATE_ON; + bool is_vcn = (block_type == AMD_IP_BLOCK_TYPE_UVD || block_type == AMD_IP_BLOCK_TYPE_VCN); + + if (atomic_read(&adev->pm.pwr_state[block_type]) == pwr_state && + (!is_vcn || adev->vcn.num_vcn_inst == 1)) { + dev_dbg(adev->dev, "IP block%d already in the target %s state!", + block_type, gate ? "gate" : "ungate"); + return 0; + } + + mutex_lock(&adev->pm.mutex); + + switch (block_type) { + case AMD_IP_BLOCK_TYPE_UVD: + case AMD_IP_BLOCK_TYPE_VCE: + case AMD_IP_BLOCK_TYPE_GFX: + case AMD_IP_BLOCK_TYPE_VCN: + case AMD_IP_BLOCK_TYPE_SDMA: + case AMD_IP_BLOCK_TYPE_JPEG: + case AMD_IP_BLOCK_TYPE_GMC: + case AMD_IP_BLOCK_TYPE_ACP: + case AMD_IP_BLOCK_TYPE_VPE: + if (pp_funcs && pp_funcs->set_powergating_by_smu_instance) { + ret = (pp_funcs->set_powergating_by_smu_instance( + (adev)->powerplay.pp_handle, block_type, gate, inst)); + } + break; + default: + break; + } + + if (!ret) + atomic_set(&adev->pm.pwr_state[block_type], pwr_state); + + mutex_unlock(&adev->pm.mutex); + + return ret; +} + int amdgpu_dpm_set_gfx_power_up_by_imu(struct amdgpu_device *adev) { struct smu_context *smu = adev->powerplay.pp_handle; @@ -572,6 +615,30 @@ void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) enable ? "enable" : "disable", ret); } +void amdgpu_dpm_enable_vcn(struct amdgpu_device *adev, bool enable, int inst) +{ + int ret = 0; + + if (adev->family == AMDGPU_FAMILY_SI) { + mutex_lock(&adev->pm.mutex); + if (enable) { + adev->pm.dpm.uvd_active = true; + adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD; + } else { + adev->pm.dpm.uvd_active = false; + } + mutex_unlock(&adev->pm.mutex); + + amdgpu_dpm_compute_clocks(adev); + return; + } + + ret = amdgpu_dpm_set_powergating_by_smu_instance(adev, AMD_IP_BLOCK_TYPE_UVD, !enable, inst); + if (ret) + DRM_ERROR("Dpm %s uvd failed, ret = %d. \n", + enable ? "enable" : "disable", ret); +} + void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) { int ret = 0; diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index f5bf41f21c41..f4cd60ffba47 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -395,6 +395,9 @@ int amdgpu_dpm_set_apu_thermal_limit(struct amdgpu_device *adev, uint32_t limit) int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block_type, bool gate); +int amdgpu_dpm_set_powergating_by_smu_instance(struct amdgpu_device *adev, + uint32_t block_type, bool gate, int inst); + extern int amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low); extern int amdgpu_dpm_get_mclk(struct amdgpu_device *adev, bool low); @@ -442,6 +445,7 @@ void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev); void amdgpu_dpm_compute_clocks(struct amdgpu_device *adev); void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable); +void amdgpu_dpm_enable_vcn(struct amdgpu_device *adev, bool enable, int inst); void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable); void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable); void amdgpu_dpm_enable_vpe(struct amdgpu_device *adev, bool enable); diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index ddfed7189708..449925105889 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -3744,6 +3744,7 @@ static const struct amd_pm_funcs swsmu_pm_funcs = { .dispatch_tasks = smu_handle_dpm_task, .load_firmware = smu_load_microcode, .set_powergating_by_smu = smu_dpm_set_power_gate, + .set_powergating_by_smu_instance = smu_dpm_set_power_gate_instance, .set_power_limit = smu_set_power_limit, .get_power_limit = smu_get_power_limit, .get_power_profile_mode = smu_get_power_profile_mode, -- 2.34.1