diff options
Diffstat (limited to 'drivers/gpu/drm/amd/pm/amdgpu_dpm.c')
| -rw-r--r-- | drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 108 | 
1 files changed, 77 insertions, 31 deletions
| diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 9dc82f4d7c93..6a9e26905edf 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -70,13 +70,18 @@ int amdgpu_dpm_get_mclk(struct amdgpu_device *adev, bool low)  	return ret;  } -int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block_type, bool gate) +int amdgpu_dpm_set_powergating_by_smu(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) { +	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; @@ -88,7 +93,6 @@ int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block  	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: @@ -96,7 +100,12 @@ int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block  	case AMD_IP_BLOCK_TYPE_VPE:  		if (pp_funcs && pp_funcs->set_powergating_by_smu)  			ret = (pp_funcs->set_powergating_by_smu( -				(adev)->powerplay.pp_handle, block_type, gate)); +				(adev)->powerplay.pp_handle, block_type, gate, 0)); +		break; +	case AMD_IP_BLOCK_TYPE_VCN: +		if (pp_funcs && pp_funcs->set_powergating_by_smu) +			ret = (pp_funcs->set_powergating_by_smu( +				(adev)->powerplay.pp_handle, block_type, gate, inst));  		break;  	default:  		break; @@ -566,7 +575,17 @@ void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable)  		return;  	} -	ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable); +	ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable, 0); +	if (ret) +		DRM_ERROR("Dpm %s uvd failed, ret = %d. \n", +			  enable ? "enable" : "disable", ret); +} + +void amdgpu_dpm_enable_vcn(struct amdgpu_device *adev, bool enable, int inst) +{ +	int ret = 0; + +	ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCN, !enable, inst);  	if (ret)  		DRM_ERROR("Dpm %s uvd failed, ret = %d. \n",  			  enable ? "enable" : "disable", ret); @@ -591,7 +610,7 @@ void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable)  		return;  	} -	ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable); +	ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable, 0);  	if (ret)  		DRM_ERROR("Dpm %s vce failed, ret = %d. \n",  			  enable ? "enable" : "disable", ret); @@ -601,7 +620,7 @@ void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable)  {  	int ret = 0; -	ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_JPEG, !enable); +	ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_JPEG, !enable, 0);  	if (ret)  		DRM_ERROR("Dpm %s jpeg failed, ret = %d. \n",  			  enable ? "enable" : "disable", ret); @@ -611,7 +630,7 @@ void amdgpu_dpm_enable_vpe(struct amdgpu_device *adev, bool enable)  {  	int ret = 0; -	ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VPE, !enable); +	ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VPE, !enable, 0);  	if (ret)  		DRM_ERROR("Dpm %s vpe failed, ret = %d.\n",  			  enable ? "enable" : "disable", ret); @@ -700,6 +719,21 @@ int amdgpu_dpm_send_rma_reason(struct amdgpu_device *adev)  	return ret;  } +int amdgpu_dpm_reset_sdma(struct amdgpu_device *adev, uint32_t inst_mask) +{ +	struct smu_context *smu = adev->powerplay.pp_handle; +	int ret; + +	if (!is_support_sw_smu(adev)) +		return -EOPNOTSUPP; + +	mutex_lock(&adev->pm.mutex); +	ret = smu_reset_sdma(smu, inst_mask); +	mutex_unlock(&adev->pm.mutex); + +	return ret; +} +  int amdgpu_dpm_get_dpm_freq_range(struct amdgpu_device *adev,  				  enum pp_clock_type type,  				  uint32_t *min, @@ -953,6 +987,24 @@ enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device  	return level;  } +static void amdgpu_dpm_enter_umd_state(struct amdgpu_device *adev) +{ +	/* enter UMD Pstate */ +	amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_GFX, +					       AMD_PG_STATE_UNGATE); +	amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_GFX, +					       AMD_CG_STATE_UNGATE); +} + +static void amdgpu_dpm_exit_umd_state(struct amdgpu_device *adev) +{ +	/* exit UMD Pstate */ +	amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_GFX, +					       AMD_CG_STATE_GATE); +	amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_GFX, +					       AMD_PG_STATE_GATE); +} +  int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev,  				       enum amd_dpm_forced_level level)  { @@ -973,6 +1025,10 @@ int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev,  	if (current_level == level)  		return 0; +	if (!(current_level & profile_mode_mask) && +	    (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) +		return -EINVAL; +  	if (adev->asic_type == CHIP_RAVEN) {  		if (!(adev->apu_flags & AMD_APU_IS_RAVEN2)) {  			if (current_level != AMD_DPM_FORCED_LEVEL_MANUAL && @@ -984,35 +1040,25 @@ int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev,  		}  	} -	if (!(current_level & profile_mode_mask) && -	    (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) -		return -EINVAL; - -	if (!(current_level & profile_mode_mask) && -	      (level & profile_mode_mask)) { -		/* enter UMD Pstate */ -		amdgpu_device_ip_set_powergating_state(adev, -						       AMD_IP_BLOCK_TYPE_GFX, -						       AMD_PG_STATE_UNGATE); -		amdgpu_device_ip_set_clockgating_state(adev, -						       AMD_IP_BLOCK_TYPE_GFX, -						       AMD_CG_STATE_UNGATE); -	} else if ((current_level & profile_mode_mask) && -		    !(level & profile_mode_mask)) { -		/* exit UMD Pstate */ -		amdgpu_device_ip_set_clockgating_state(adev, -						       AMD_IP_BLOCK_TYPE_GFX, -						       AMD_CG_STATE_GATE); -		amdgpu_device_ip_set_powergating_state(adev, -						       AMD_IP_BLOCK_TYPE_GFX, -						       AMD_PG_STATE_GATE); -	} +	if (!(current_level & profile_mode_mask) && (level & profile_mode_mask)) +		amdgpu_dpm_enter_umd_state(adev); +	else if ((current_level & profile_mode_mask) && +		 !(level & profile_mode_mask)) +		amdgpu_dpm_exit_umd_state(adev);  	mutex_lock(&adev->pm.mutex);  	if (pp_funcs->force_performance_level(adev->powerplay.pp_handle,  					      level)) {  		mutex_unlock(&adev->pm.mutex); +		/* If new level failed, retain the umd state as before */ +		if (!(current_level & profile_mode_mask) && +		    (level & profile_mode_mask)) +			amdgpu_dpm_exit_umd_state(adev); +		else if ((current_level & profile_mode_mask) && +			 !(level & profile_mode_mask)) +			amdgpu_dpm_enter_umd_state(adev); +  		return -EINVAL;  	} | 
