The current mechanism for obtaining RPM is to read tach_period from the register, and then calculate the RPM together with the frequency. But we found that on specific GPUs, such as RX 550 and RX 560D, tach_period always reads as 0 and smu7_fan_ctrl_get_fan_speed_rpm will returns -EINVAL. To solve this problem, when reading tach_period as 0, we try to estimate the current RPM using the percentage of current pwm, the maximum and minimum RPM. Signed-off-by: huangyizhi <huangyizhi@xxxxxxxxxx> --- .../drm/amd/pm/powerplay/hwmgr/smu7_thermal.c | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c index a6c3610db23e..307dd87d6882 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c @@ -81,6 +81,11 @@ int smu7_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed) { uint32_t tach_period; uint32_t crystal_clock_freq; + uint32_t duty100; + uint32_t duty; + uint32_t speed_percent; + uint64_t tmp64; + if (hwmgr->thermal_controller.fanInfo.bNoFan || !hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) @@ -89,13 +94,28 @@ int smu7_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed) tach_period = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_TACH_STATUS, TACH_PERIOD); - if (tach_period == 0) - return -EINVAL; + if (tach_period == 0) { - crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); + duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL1, FMAX_DUTY100); + duty = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_THERMAL_STATUS, FDO_PWM_DUTY); - *speed = 60 * crystal_clock_freq * 10000 / tach_period; + if (duty100 == 0) + return -EINVAL; + tmp64 = (uint64_t)duty * 100; + do_div(tmp64, duty100); + speed_percent = MIN((uint32_t)tmp64, 100); + + *speed = speed_percent * (hwmgr->thermal_controller.fanInfo.ulMaxRPM + - hwmgr->thermal_controller.fanInfo.ulMinRPM) / 100; + } else { + + crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); + + *speed = 60 * crystal_clock_freq * 10000 / tach_period; + } return 0; } -- 2.30.0