From 37a58f691551dfdff4f1035ee119c9ebdb9eb119 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 19 Nov 2020 15:56:28 +0800 Subject: drm/amd/pm: enable Sienna Cichlid overdrive support Enable Sienna Cichlid gfxclk/uclk overdrive support. Signed-off-by: Evan Quan Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 7b6ef05a1d35..73aa78a158a6 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -730,7 +730,8 @@ static ssize_t amdgpu_set_pp_table(struct device *dev, * * - minimum and maximum engine clock labeled OD_SCLK * - * - maximum memory clock labeled OD_MCLK + * - minimum(not available for Vega20 and Navi1x) and maximum memory + * clock labeled OD_MCLK * * - three points labeled OD_VDDC_CURVE. * They can be used to calibrate the sclk voltage curve. -- cgit From a2b6df4fd6e3c0ba088b00fc00579dac263b0a64 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 19 Nov 2020 17:30:43 +0800 Subject: drm/amd/pm: support overdrive vddgfx offset setting(V2) This is supported by Sienna Cichlid, Navy Flounder and Dimgrey Cavefish. For these ASICs, the target voltage calculation can be illustrated by "voltage = voltage calculated from v/f curve + overdrive vddgfx offset". V2: limit the smu_version check for Sienna Cichlid only Here are some sample usages about this new OD setting: 1. Check current vddgfx offset setting by cat /sys/class/drm/card0/device/pp_od_clk_voltage ... ... OD_VDDGFX_OFFSET: 0mV ... ... 2. Set new vddgfx offset by echo "vo 10" > /sys/class/drm/card0/device/pp_od_clk_voltage cat /sys/class/drm/card0/device/pp_od_clk_voltage ... ... OD_VDDGFX_OFFSET: 10mV ... ... 3. Commit the new setting by echo "c" > /sys/class/drm/card0/device/pp_od_clk_voltage Signed-off-by: Evan Quan Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 73aa78a158a6..a68c8ba68c55 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -736,6 +736,12 @@ static ssize_t amdgpu_set_pp_table(struct device *dev, * - three points labeled OD_VDDC_CURVE. * They can be used to calibrate the sclk voltage curve. * + * - voltage offset(in mV) applied on target voltage calculation. + * This is available for Sienna Cichlid, Navy Flounder and Dimgrey + * Cavefish. For these ASICs, the target voltage calculation can be + * illustrated by "voltage = voltage calculated from v/f curve + + * overdrive vddgfx offset" + * * - a list of valid ranges for sclk, mclk, and voltage curve points * labeled OD_RANGE * @@ -756,6 +762,11 @@ static ssize_t amdgpu_set_pp_table(struct device *dev, * 600mV. "vc 2 1000 1000" will update point3 with clock set * as 1000Mhz and voltage 1000mV. * + * To update the voltage offset applied for gfxclk/voltage calculation, + * enter the new value by writing a string that contains "vo offset". + * This is supported by Sienna Cichlid, Navy Flounder and Dimgrey Cavefish. + * And the offset can be a positive or negative value. + * * - When you have edited all of the states as needed, write "c" (commit) * to the file to commit your changes * @@ -796,6 +807,8 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, type = PP_OD_COMMIT_DPM_TABLE; else if (!strncmp(buf, "vc", 2)) type = PP_OD_EDIT_VDDC_CURVE; + else if (!strncmp(buf, "vo", 2)) + type = PP_OD_EDIT_VDDGFX_OFFSET; else return -EINVAL; @@ -803,7 +816,8 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, tmp_str = buf_cpy; - if (type == PP_OD_EDIT_VDDC_CURVE) + if ((type == PP_OD_EDIT_VDDC_CURVE) || + (type == PP_OD_EDIT_VDDGFX_OFFSET)) tmp_str++; while (isspace(*++tmp_str)); @@ -899,6 +913,7 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, size = smu_print_clk_levels(&adev->smu, SMU_OD_SCLK, buf); size += smu_print_clk_levels(&adev->smu, SMU_OD_MCLK, buf+size); size += smu_print_clk_levels(&adev->smu, SMU_OD_VDDC_CURVE, buf+size); + size += smu_print_clk_levels(&adev->smu, SMU_OD_VDDGFX_OFFSET, buf+size); size += smu_print_clk_levels(&adev->smu, SMU_OD_RANGE, buf+size); } else if (adev->powerplay.pp_funcs->print_clock_levels) { size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf); -- cgit From 9577b0ec2be8410b94e9928f25b740b55de2c13d Mon Sep 17 00:00:00 2001 From: Xiaojian Du Date: Wed, 16 Dec 2020 14:44:10 +0800 Subject: drm/amd/pm: add two new sysfs nodes for vangogh This patch is to add two new sysfs nodes for vangogh: pp_dpm_dclk and pp_dpm_vclk. The two sysfs nodes are similar to pp_dpm_fclk/memclk/socclk. pp_dpm_dclk represents the DPM frequency of dcn unit. pp_dpm_vclk represents the DPM frequency of vcn unit. Signed-off-by: Xiaojian Du Acked-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 140 +++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index a68c8ba68c55..97c669dd4cac 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -1362,6 +1362,138 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev, return count; } +static ssize_t amdgpu_get_pp_dpm_vclk(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = drm_to_adev(ddev); + ssize_t size; + int ret; + + if (amdgpu_in_reset(adev)) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + if (is_support_sw_smu(adev)) + size = smu_print_clk_levels(&adev->smu, SMU_VCLK, buf); + else + size = snprintf(buf, PAGE_SIZE, "\n"); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return size; +} + +static ssize_t amdgpu_set_pp_dpm_vclk(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = drm_to_adev(ddev); + int ret; + uint32_t mask = 0; + + if (amdgpu_in_reset(adev)) + return -EPERM; + + ret = amdgpu_read_mask(buf, count, &mask); + if (ret) + return ret; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + if (is_support_sw_smu(adev)) + ret = smu_force_clk_levels(&adev->smu, SMU_VCLK, mask); + else + ret = 0; + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + if (ret) + return -EINVAL; + + return count; +} + +static ssize_t amdgpu_get_pp_dpm_dclk(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = drm_to_adev(ddev); + ssize_t size; + int ret; + + if (amdgpu_in_reset(adev)) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + if (is_support_sw_smu(adev)) + size = smu_print_clk_levels(&adev->smu, SMU_DCLK, buf); + else + size = snprintf(buf, PAGE_SIZE, "\n"); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return size; +} + +static ssize_t amdgpu_set_pp_dpm_dclk(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = drm_to_adev(ddev); + int ret; + uint32_t mask = 0; + + if (amdgpu_in_reset(adev)) + return -EPERM; + + ret = amdgpu_read_mask(buf, count, &mask); + if (ret) + return ret; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + if (is_support_sw_smu(adev)) + ret = smu_force_clk_levels(&adev->smu, SMU_DCLK, mask); + else + ret = 0; + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + if (ret) + return -EINVAL; + + return count; +} + static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev, struct device_attribute *attr, char *buf) @@ -2041,6 +2173,8 @@ static struct amdgpu_device_attr amdgpu_device_attrs[] = { AMDGPU_DEVICE_ATTR_RW(pp_dpm_mclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), 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_dclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), AMDGPU_DEVICE_ATTR_RW(pp_dpm_dcefclk, ATTR_FLAG_BASIC), AMDGPU_DEVICE_ATTR_RW(pp_dpm_pcie, ATTR_FLAG_BASIC), AMDGPU_DEVICE_ATTR_RW(pp_sclk_od, ATTR_FLAG_BASIC), @@ -2103,6 +2237,12 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ } else if (DEVICE_ATTR_IS(gpu_metrics)) { if (asic_type < CHIP_VEGA12) *states = ATTR_STATE_UNSUPPORTED; + } else if (DEVICE_ATTR_IS(pp_dpm_vclk)) { + if (!(asic_type == CHIP_VANGOGH)) + *states = ATTR_STATE_UNSUPPORTED; + } else if (DEVICE_ATTR_IS(pp_dpm_dclk)) { + if (!(asic_type == CHIP_VANGOGH)) + *states = ATTR_STATE_UNSUPPORTED; } if (asic_type == CHIP_ARCTURUS) { -- cgit From 08da4fcd6d98745fb1b97e37bc02e665eda8d420 Mon Sep 17 00:00:00 2001 From: Xiaojian Du Date: Tue, 29 Dec 2020 18:32:11 +0800 Subject: drm/amd/pm: modify the fine grain tuning function for Renoir This patch is to improve the fine grain tuning function for Renoir. The fine grain tuning function uses the sysfs node -- pp_od_clk_voltage to config gfxclk. Meanwhile, another sysfs node -- power_dpm_force_perfomance_level also affects the gfx clk. It will cause confusion when these two sysfs nodes works together. And the flag "od_enabled" is used to control the overdrive function for dGPU, like navi10, navi14 and navi21. APU like Renior or Vangogh uses this "od_enabled" to configure the frequency range of gfx clock, but the max value of frequency range will not be higher than the safe limit, it is not "overdrive". So this patch adds two new flags -- "fine_grain_enabled" and "fine_grain_started" to avoid this confusion, the flag will make these two sysfs nodes work separately. The flag "fine_grain_enabled" is set as "enabled" by default, so the fine grain tuning function will be enabled by default. But the flag "fine_grain_started" is set as "false" by default, so the fine grain function will not take effect until it is set as "true". Only when power_dpm_force_perfomance_level is changed to "manual" mode, the flag "fine_grain_started" will be set as "true", and the fine grain tuning function will be started. In other profile modes, including "auto", "high", "low", "profile_peak", "profile_standard", "profile_min_sclk", "profile_min_mclk", the flag "fine_grain_started" will be set as "false", and the od range of fine grain tuning function will be restored default value. Signed-off-by: Xiaojian Du Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/pm/amdgpu_pm.c') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 97c669dd4cac..f5d97b97353a 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -2217,7 +2217,8 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ } else if (DEVICE_ATTR_IS(pp_od_clk_voltage)) { *states = ATTR_STATE_UNSUPPORTED; if ((is_support_sw_smu(adev) && adev->smu.od_enabled) || - (!is_support_sw_smu(adev) && hwmgr->od_enabled)) + (is_support_sw_smu(adev) && adev->smu.fine_grain_enabled) || + (!is_support_sw_smu(adev) && hwmgr->od_enabled)) *states = ATTR_STATE_SUPPORTED; } else if (DEVICE_ATTR_IS(mem_busy_percent)) { if (adev->flags & AMD_IS_APU || asic_type == CHIP_VEGA10) -- cgit