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)) |