diff options
Diffstat (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c')
| -rw-r--r-- | drivers/gpu/drm/amd/pm/amdgpu_pm.c | 127 | 
1 files changed, 125 insertions, 2 deletions
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index bf6d63673b5a..58c2246918fd 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -91,6 +91,8 @@ const char * const amdgpu_pp_profile_name[] = {  	"COMPUTE",  	"CUSTOM",  	"WINDOW_3D", +	"CAPPED", +	"UNCAPPED",  };  /** @@ -1178,6 +1180,21 @@ static ssize_t amdgpu_set_pp_dpm_vclk(struct device *dev,  	return amdgpu_set_pp_dpm_clock(dev, PP_VCLK, buf, count);  } +static ssize_t amdgpu_get_pp_dpm_vclk1(struct device *dev, +		struct device_attribute *attr, +		char *buf) +{ +	return amdgpu_get_pp_dpm_clock(dev, PP_VCLK1, buf); +} + +static ssize_t amdgpu_set_pp_dpm_vclk1(struct device *dev, +		struct device_attribute *attr, +		const char *buf, +		size_t count) +{ +	return amdgpu_set_pp_dpm_clock(dev, PP_VCLK1, buf, count); +} +  static ssize_t amdgpu_get_pp_dpm_dclk(struct device *dev,  		struct device_attribute *attr,  		char *buf) @@ -1193,6 +1210,21 @@ static ssize_t amdgpu_set_pp_dpm_dclk(struct device *dev,  	return amdgpu_set_pp_dpm_clock(dev, PP_DCLK, buf, count);  } +static ssize_t amdgpu_get_pp_dpm_dclk1(struct device *dev, +		struct device_attribute *attr, +		char *buf) +{ +	return amdgpu_get_pp_dpm_clock(dev, PP_DCLK1, buf); +} + +static ssize_t amdgpu_set_pp_dpm_dclk1(struct device *dev, +		struct device_attribute *attr, +		const char *buf, +		size_t count) +{ +	return amdgpu_set_pp_dpm_clock(dev, PP_DCLK1, buf, count); +} +  static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev,  		struct device_attribute *attr,  		char *buf) @@ -1686,6 +1718,82 @@ static ssize_t amdgpu_set_thermal_throttling_logging(struct device *dev,  }  /** + * DOC: apu_thermal_cap + * + * The amdgpu driver provides a sysfs API for retrieving/updating thermal + * limit temperature in millidegrees Celsius + * + * Reading back the file shows you core limit value + * + * Writing an integer to the file, sets a new thermal limit. The value + * should be between 0 and 100. If the value is less than 0 or greater + * than 100, then the write request will be ignored. + */ +static ssize_t amdgpu_get_apu_thermal_cap(struct device *dev, +					 struct device_attribute *attr, +					 char *buf) +{ +	int ret, size; +	u32 limit; +	struct drm_device *ddev = dev_get_drvdata(dev); +	struct amdgpu_device *adev = drm_to_adev(ddev); + +	ret = pm_runtime_get_sync(ddev->dev); +	if (ret < 0) { +		pm_runtime_put_autosuspend(ddev->dev); +		return ret; +	} + +	ret = amdgpu_dpm_get_apu_thermal_limit(adev, &limit); +	if (!ret) +		size = sysfs_emit(buf, "%u\n", limit); +	else +		size = sysfs_emit(buf, "failed to get thermal limit\n"); + +	pm_runtime_mark_last_busy(ddev->dev); +	pm_runtime_put_autosuspend(ddev->dev); + +	return size; +} + +static ssize_t amdgpu_set_apu_thermal_cap(struct device *dev, +					 struct device_attribute *attr, +					 const char *buf, +					 size_t count) +{ +	int ret; +	u32 value; +	struct drm_device *ddev = dev_get_drvdata(dev); +	struct amdgpu_device *adev = drm_to_adev(ddev); + +	ret = kstrtou32(buf, 10, &value); +	if (ret) +		return ret; + +	if (value > 100) { +		dev_err(dev, "Invalid argument !\n"); +		return -EINVAL; +	} + +	ret = pm_runtime_get_sync(ddev->dev); +	if (ret < 0) { +		pm_runtime_put_autosuspend(ddev->dev); +		return ret; +	} + +	ret = amdgpu_dpm_set_apu_thermal_limit(adev, value); +	if (ret) { +		dev_err(dev, "failed to update thermal limit\n"); +		return ret; +	} + +	pm_runtime_mark_last_busy(ddev->dev); +	pm_runtime_put_autosuspend(ddev->dev); + +	return count; +} + +/**   * DOC: gpu_metrics   *   * The amdgpu driver provides a sysfs API for retrieving current gpu @@ -1924,7 +2032,9 @@ static struct amdgpu_device_attr amdgpu_device_attrs[] = {  	AMDGPU_DEVICE_ATTR_RW(pp_dpm_socclk,				ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF),  	AMDGPU_DEVICE_ATTR_RW(pp_dpm_fclk,				ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF),  	AMDGPU_DEVICE_ATTR_RW(pp_dpm_vclk,				ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), +	AMDGPU_DEVICE_ATTR_RW(pp_dpm_vclk1,				ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF),  	AMDGPU_DEVICE_ATTR_RW(pp_dpm_dclk,				ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), +	AMDGPU_DEVICE_ATTR_RW(pp_dpm_dclk1,				ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF),  	AMDGPU_DEVICE_ATTR_RW(pp_dpm_dcefclk,				ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF),  	AMDGPU_DEVICE_ATTR_RW(pp_dpm_pcie,				ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF),  	AMDGPU_DEVICE_ATTR_RW(pp_sclk_od,				ATTR_FLAG_BASIC), @@ -1937,6 +2047,7 @@ static struct amdgpu_device_attr amdgpu_device_attrs[] = {  	AMDGPU_DEVICE_ATTR_RW(pp_features,				ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF),  	AMDGPU_DEVICE_ATTR_RO(unique_id,				ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF),  	AMDGPU_DEVICE_ATTR_RW(thermal_throttling_logging,		ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), +	AMDGPU_DEVICE_ATTR_RW(apu_thermal_cap,				ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF),  	AMDGPU_DEVICE_ATTR_RO(gpu_metrics,				ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF),  	AMDGPU_DEVICE_ATTR_RO(smartshift_apu_power,			ATTR_FLAG_BASIC,  			      .attr_update = ss_power_attr_update), @@ -2012,6 +2123,12 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_  		      gc_ver == IP_VERSION(11, 0, 2) ||  		      gc_ver == IP_VERSION(11, 0, 3)))  			*states = ATTR_STATE_UNSUPPORTED; +	} else if (DEVICE_ATTR_IS(pp_dpm_vclk1)) { +		if (!((gc_ver == IP_VERSION(10, 3, 1) || +			   gc_ver == IP_VERSION(10, 3, 0) || +			   gc_ver == IP_VERSION(11, 0, 2) || +			   gc_ver == IP_VERSION(11, 0, 3)) && adev->vcn.num_vcn_inst >= 2)) +			*states = ATTR_STATE_UNSUPPORTED;  	} else if (DEVICE_ATTR_IS(pp_dpm_dclk)) {  		if (!(gc_ver == IP_VERSION(10, 3, 1) ||  		      gc_ver == IP_VERSION(10, 3, 0) || @@ -2020,6 +2137,12 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_  		      gc_ver == IP_VERSION(11, 0, 2) ||  		      gc_ver == IP_VERSION(11, 0, 3)))  			*states = ATTR_STATE_UNSUPPORTED; +	} else if (DEVICE_ATTR_IS(pp_dpm_dclk1)) { +		if (!((gc_ver == IP_VERSION(10, 3, 1) || +			   gc_ver == IP_VERSION(10, 3, 0) || +			   gc_ver == IP_VERSION(11, 0, 2) || +			   gc_ver == IP_VERSION(11, 0, 3)) && adev->vcn.num_vcn_inst >= 2)) +			*states = ATTR_STATE_UNSUPPORTED;  	} else if (DEVICE_ATTR_IS(pp_power_profile_mode)) {  		if (amdgpu_dpm_get_power_profile_mode(adev, NULL) == -EOPNOTSUPP)  			*states = ATTR_STATE_UNSUPPORTED; @@ -3272,7 +3395,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,  	      attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't manage state */  		effective_mode &= ~S_IWUSR; -	/* not implemented yet for GC 10.3.1 APUs */ +	/* In the case of APUs, this is only implemented on Vangogh */  	if (((adev->family == AMDGPU_FAMILY_SI) ||  	     ((adev->flags & AMD_IS_APU) && (gc_ver != IP_VERSION(10, 3, 1)))) &&  	    (attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr || @@ -3281,7 +3404,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,  	     attr == &sensor_dev_attr_power1_cap_default.dev_attr.attr))  		return 0; -	/* not implemented yet for APUs having <= GC 9.3.0 */ +	/* not implemented yet for APUs having < GC 9.3.0 (Renoir) */  	if (((adev->family == AMDGPU_FAMILY_SI) ||  	     ((adev->flags & AMD_IS_APU) && (gc_ver < IP_VERSION(9, 3, 0)))) &&  	    (attr == &sensor_dev_attr_power1_average.dev_attr.attr))  | 
