Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/pm: add fan minimum pwm OD setting support for SMU13

Add SMU13 fan minimum pwm OD setting support.

Signed-off-by: Evan Quan <evan.quan@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Evan Quan and committed by
Alex Deucher
9df5d008 eedd5a34

+177 -2
+6
Documentation/gpu/amdgpu/thermal.rst
··· 88 88 .. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c 89 89 :doc: fan_target_temperature 90 90 91 + fan_minimum_pwm 92 + --------------- 93 + 94 + .. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c 95 + :doc: fan_minimum_pwm 96 + 91 97 GFXOFF 92 98 ====== 93 99
+2
drivers/gpu/drm/amd/include/kgd_pp_interface.h
··· 117 117 OD_ACOUSTIC_LIMIT, 118 118 OD_ACOUSTIC_TARGET, 119 119 OD_FAN_TARGET_TEMPERATURE, 120 + OD_FAN_MINIMUM_PWM, 120 121 }; 121 122 122 123 enum amd_pp_sensors { ··· 196 195 PP_OD_EDIT_ACOUSTIC_LIMIT, 197 196 PP_OD_EDIT_ACOUSTIC_TARGET, 198 197 PP_OD_EDIT_FAN_TARGET_TEMPERATURE, 198 + PP_OD_EDIT_FAN_MINIMUM_PWM, 199 199 }; 200 200 201 201 struct pp_states_info {
+64
drivers/gpu/drm/amd/pm/amdgpu_pm.c
··· 3745 3745 return umode; 3746 3746 } 3747 3747 3748 + /** 3749 + * DOC: fan_minimum_pwm 3750 + * 3751 + * The amdgpu driver provides a sysfs API for checking and adjusting the 3752 + * minimum fan speed in PWM. 3753 + * 3754 + * Reading back the file shows you the current setting and the permitted 3755 + * ranges if changable. 3756 + * 3757 + * Writing an integer to the file, change the setting accordingly. 3758 + * 3759 + * When you have finished the editing, write "c" (commit) to the file to commit 3760 + * your changes. 3761 + * 3762 + * This setting works under auto fan control mode only. It can co-exist with 3763 + * other settings which can work also under auto mode. It adjusts the PMFW's 3764 + * behavior about the minimum fan speed in PWM the fan should spin. Setting 3765 + * via this interface will switch the fan control to auto mode implicitly. 3766 + */ 3767 + static ssize_t fan_minimum_pwm_show(struct kobject *kobj, 3768 + struct kobj_attribute *attr, 3769 + char *buf) 3770 + { 3771 + struct od_kobj *container = container_of(kobj, struct od_kobj, kobj); 3772 + struct amdgpu_device *adev = (struct amdgpu_device *)container->priv; 3773 + 3774 + return (ssize_t)amdgpu_retrieve_od_settings(adev, OD_FAN_MINIMUM_PWM, buf); 3775 + } 3776 + 3777 + static ssize_t fan_minimum_pwm_store(struct kobject *kobj, 3778 + struct kobj_attribute *attr, 3779 + const char *buf, 3780 + size_t count) 3781 + { 3782 + struct od_kobj *container = container_of(kobj, struct od_kobj, kobj); 3783 + struct amdgpu_device *adev = (struct amdgpu_device *)container->priv; 3784 + 3785 + return (ssize_t)amdgpu_distribute_custom_od_settings(adev, 3786 + PP_OD_EDIT_FAN_MINIMUM_PWM, 3787 + buf, 3788 + count); 3789 + } 3790 + 3791 + static umode_t fan_minimum_pwm_visible(struct amdgpu_device *adev) 3792 + { 3793 + umode_t umode = 0000; 3794 + 3795 + if (adev->pm.od_feature_mask & OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE) 3796 + umode |= S_IRUSR | S_IRGRP | S_IROTH; 3797 + 3798 + if (adev->pm.od_feature_mask & OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET) 3799 + umode |= S_IWUSR; 3800 + 3801 + return umode; 3802 + } 3803 + 3748 3804 static struct od_feature_set amdgpu_od_set = { 3749 3805 .containers = { 3750 3806 [0] = { ··· 3836 3780 .is_visible = fan_target_temperature_visible, 3837 3781 .show = fan_target_temperature_show, 3838 3782 .store = fan_target_temperature_store, 3783 + }, 3784 + }, 3785 + [4] = { 3786 + .name = "fan_minimum_pwm", 3787 + .ops = { 3788 + .is_visible = fan_minimum_pwm_visible, 3789 + .show = fan_minimum_pwm_show, 3790 + .store = fan_minimum_pwm_store, 3839 3791 }, 3840 3792 }, 3841 3793 },
+2
drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
··· 322 322 #define OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET BIT(5) 323 323 #define OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE BIT(6) 324 324 #define OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET BIT(7) 325 + #define OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE BIT(8) 326 + #define OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET BIT(9) 325 327 326 328 struct amdgpu_pm { 327 329 struct mutex mutex;
+2
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
··· 2489 2489 clk_type = SMU_OD_ACOUSTIC_TARGET; break; 2490 2490 case OD_FAN_TARGET_TEMPERATURE: 2491 2491 clk_type = SMU_OD_FAN_TARGET_TEMPERATURE; break; 2492 + case OD_FAN_MINIMUM_PWM: 2493 + clk_type = SMU_OD_FAN_MINIMUM_PWM; break; 2492 2494 default: 2493 2495 clk_type = SMU_CLK_COUNT; break; 2494 2496 }
+1
drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
··· 284 284 SMU_OD_ACOUSTIC_LIMIT, 285 285 SMU_OD_ACOUSTIC_TARGET, 286 286 SMU_OD_FAN_TARGET_TEMPERATURE, 287 + SMU_OD_FAN_MINIMUM_PWM, 287 288 SMU_CLK_COUNT, 288 289 }; 289 290
+50 -1
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
··· 106 106 #define PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT 7 107 107 #define PP_OD_FEATURE_FAN_ACOUSTIC_TARGET 8 108 108 #define PP_OD_FEATURE_FAN_TARGET_TEMPERATURE 9 109 + #define PP_OD_FEATURE_FAN_MINIMUM_PWM 10 109 110 110 111 #define LINK_SPEED_MAX 3 111 112 ··· 1148 1147 od_min_setting = overdrive_lowerlimits->FanTargetTemperature; 1149 1148 od_max_setting = overdrive_upperlimits->FanTargetTemperature; 1150 1149 break; 1150 + case PP_OD_FEATURE_FAN_MINIMUM_PWM: 1151 + od_min_setting = overdrive_lowerlimits->FanMinimumPwm; 1152 + od_max_setting = overdrive_upperlimits->FanMinimumPwm; 1153 + break; 1151 1154 default: 1152 1155 od_min_setting = od_max_setting = INT_MAX; 1153 1156 break; ··· 1451 1446 &min_value, 1452 1447 &max_value); 1453 1448 size += sysfs_emit_at(buf, size, "TARGET_TEMPERATURE: %u %u\n", 1449 + min_value, max_value); 1450 + break; 1451 + 1452 + case SMU_OD_FAN_MINIMUM_PWM: 1453 + if (!smu_v13_0_0_is_od_feature_supported(smu, 1454 + PP_OD_FEATURE_FAN_CURVE_BIT)) 1455 + break; 1456 + 1457 + size += sysfs_emit_at(buf, size, "FAN_MINIMUM_PWM:\n"); 1458 + size += sysfs_emit_at(buf, size, "%d\n", 1459 + (int)od_table->OverDriveTable.FanMinimumPwm); 1460 + 1461 + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); 1462 + smu_v13_0_0_get_od_setting_limits(smu, 1463 + PP_OD_FEATURE_FAN_MINIMUM_PWM, 1464 + &min_value, 1465 + &max_value); 1466 + size += sysfs_emit_at(buf, size, "MINIMUM_PWM: %u %u\n", 1454 1467 min_value, max_value); 1455 1468 break; 1456 1469 ··· 1786 1763 od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); 1787 1764 break; 1788 1765 1766 + case PP_OD_EDIT_FAN_MINIMUM_PWM: 1767 + if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) { 1768 + dev_warn(adev->dev, "Fan curve setting not supported!\n"); 1769 + return -ENOTSUPP; 1770 + } 1771 + 1772 + smu_v13_0_0_get_od_setting_limits(smu, 1773 + PP_OD_FEATURE_FAN_MINIMUM_PWM, 1774 + &minimum, 1775 + &maximum); 1776 + if (input[0] < minimum || 1777 + input[0] > maximum) { 1778 + dev_info(adev->dev, "fan minimum pwm setting(%ld) must be within [%d, %d]!\n", 1779 + input[0], minimum, maximum); 1780 + return -EINVAL; 1781 + } 1782 + 1783 + od_table->OverDriveTable.FanMinimumPwm = input[0]; 1784 + od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; 1785 + od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); 1786 + break; 1787 + 1789 1788 case PP_OD_RESTORE_DEFAULT_TABLE: 1790 1789 feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask; 1791 1790 memcpy(od_table, ··· 2071 2026 OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_RETRIEVE | 2072 2027 OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET | 2073 2028 OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE | 2074 - OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET; 2029 + OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET | 2030 + OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE | 2031 + OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET; 2075 2032 } 2076 2033 2077 2034 static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu) ··· 2137 2090 user_od_table_bak.OverDriveTable.AcousticTargetRpmThreshold; 2138 2091 user_od_table->OverDriveTable.FanTargetTemperature = 2139 2092 user_od_table_bak.OverDriveTable.FanTargetTemperature; 2093 + user_od_table->OverDriveTable.FanMinimumPwm = 2094 + user_od_table_bak.OverDriveTable.FanMinimumPwm; 2140 2095 } 2141 2096 2142 2097 smu_v13_0_0_set_supported_od_feature_mask(smu);
+50 -1
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
··· 82 82 #define PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT 7 83 83 #define PP_OD_FEATURE_FAN_ACOUSTIC_TARGET 8 84 84 #define PP_OD_FEATURE_FAN_TARGET_TEMPERATURE 9 85 + #define PP_OD_FEATURE_FAN_MINIMUM_PWM 10 85 86 86 87 #define LINK_SPEED_MAX 3 87 88 ··· 1128 1127 od_min_setting = overdrive_lowerlimits->FanTargetTemperature; 1129 1128 od_max_setting = overdrive_upperlimits->FanTargetTemperature; 1130 1129 break; 1130 + case PP_OD_FEATURE_FAN_MINIMUM_PWM: 1131 + od_min_setting = overdrive_lowerlimits->FanMinimumPwm; 1132 + od_max_setting = overdrive_upperlimits->FanMinimumPwm; 1133 + break; 1131 1134 default: 1132 1135 od_min_setting = od_max_setting = INT_MAX; 1133 1136 break; ··· 1431 1426 &min_value, 1432 1427 &max_value); 1433 1428 size += sysfs_emit_at(buf, size, "TARGET_TEMPERATURE: %u %u\n", 1429 + min_value, max_value); 1430 + break; 1431 + 1432 + case SMU_OD_FAN_MINIMUM_PWM: 1433 + if (!smu_v13_0_7_is_od_feature_supported(smu, 1434 + PP_OD_FEATURE_FAN_CURVE_BIT)) 1435 + break; 1436 + 1437 + size += sysfs_emit_at(buf, size, "FAN_MINIMUM_PWM:\n"); 1438 + size += sysfs_emit_at(buf, size, "%d\n", 1439 + (int)od_table->OverDriveTable.FanMinimumPwm); 1440 + 1441 + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); 1442 + smu_v13_0_7_get_od_setting_limits(smu, 1443 + PP_OD_FEATURE_FAN_MINIMUM_PWM, 1444 + &min_value, 1445 + &max_value); 1446 + size += sysfs_emit_at(buf, size, "MINIMUM_PWM: %u %u\n", 1434 1447 min_value, max_value); 1435 1448 break; 1436 1449 ··· 1766 1743 od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); 1767 1744 break; 1768 1745 1746 + case PP_OD_EDIT_FAN_MINIMUM_PWM: 1747 + if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) { 1748 + dev_warn(adev->dev, "Fan curve setting not supported!\n"); 1749 + return -ENOTSUPP; 1750 + } 1751 + 1752 + smu_v13_0_7_get_od_setting_limits(smu, 1753 + PP_OD_FEATURE_FAN_MINIMUM_PWM, 1754 + &minimum, 1755 + &maximum); 1756 + if (input[0] < minimum || 1757 + input[0] > maximum) { 1758 + dev_info(adev->dev, "fan minimum pwm setting(%ld) must be within [%d, %d]!\n", 1759 + input[0], minimum, maximum); 1760 + return -EINVAL; 1761 + } 1762 + 1763 + od_table->OverDriveTable.FanMinimumPwm = input[0]; 1764 + od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; 1765 + od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); 1766 + break; 1767 + 1769 1768 case PP_OD_RESTORE_DEFAULT_TABLE: 1770 1769 feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask; 1771 1770 memcpy(od_table, ··· 2046 2001 OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_RETRIEVE | 2047 2002 OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET | 2048 2003 OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE | 2049 - OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET; 2004 + OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET | 2005 + OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE | 2006 + OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET; 2050 2007 } 2051 2008 2052 2009 static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu) ··· 2112 2065 user_od_table_bak.OverDriveTable.AcousticTargetRpmThreshold; 2113 2066 user_od_table->OverDriveTable.FanTargetTemperature = 2114 2067 user_od_table_bak.OverDriveTable.FanTargetTemperature; 2068 + user_od_table->OverDriveTable.FanMinimumPwm = 2069 + user_od_table_bak.OverDriveTable.FanMinimumPwm; 2115 2070 } 2116 2071 2117 2072 smu_v13_0_7_set_supported_od_feature_mask(smu);