mirror of
https://github.com/Lurkki14/tuxclocker.git
synced 2024-11-24 09:10:16 -06:00
add RX 7000-series fan speed control
This commit is contained in:
parent
62424998e0
commit
4f96ee1628
9
doc/amd-pptables/rx7000-fancurve
Normal file
9
doc/amd-pptables/rx7000-fancurve
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
OD_FAN_CURVE:
|
||||||
|
0: 0C 0%
|
||||||
|
1: 45C 15%
|
||||||
|
2: 50C 30%
|
||||||
|
3: 55C 70%
|
||||||
|
4: 65C 100%
|
||||||
|
OD_RANGE:
|
||||||
|
FAN_CURVE(hotspot temp): 25C 100C
|
||||||
|
FAN_CURVE(fan speed): 15% 100%
|
@ -368,6 +368,13 @@ std::vector<TreeNode<DeviceNode>> getFanMode(AMDGPUData data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<TreeNode<DeviceNode>> getFanSpeedWrite(AMDGPUData data) {
|
std::vector<TreeNode<DeviceNode>> getFanSpeedWrite(AMDGPUData data) {
|
||||||
|
// Don't try to use pre-6.7 interface on RX 7000
|
||||||
|
// TODO: potential regression, if this exists on older cards, but doesn't function
|
||||||
|
char fanCurvePath[128];
|
||||||
|
snprintf(fanCurvePath, 128, "%s/gpu_od/fan_ctrl/fan_curve", data.devPath.c_str());
|
||||||
|
if (std::ifstream{fanCurvePath}.good())
|
||||||
|
return {};
|
||||||
|
|
||||||
char path[96];
|
char path[96];
|
||||||
snprintf(path, 96, "%s/pwm1", data.hwmonPath.c_str());
|
snprintf(path, 96, "%s/pwm1", data.hwmonPath.c_str());
|
||||||
if (!std::ifstream{path}.good())
|
if (!std::ifstream{path}.good())
|
||||||
@ -410,6 +417,71 @@ std::vector<TreeNode<DeviceNode>> getFanSpeedWrite(AMDGPUData data) {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<TreeNode<DeviceNode>> getFanSpeedWriteRX7000(AMDGPUData data) {
|
||||||
|
char fanCurvePath[128];
|
||||||
|
snprintf(fanCurvePath, 128, "%s/gpu_od/fan_ctrl/fan_curve", data.devPath.c_str());
|
||||||
|
if (!std::ifstream{fanCurvePath}.good())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
auto contentsRaw = fileContents(fanCurvePath);
|
||||||
|
if (!contentsRaw.has_value())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
// Replace the space in 'fan speed' with underscore, see doc/amd-pptables/rx7000-fancurve
|
||||||
|
// to fit the format parsePstateRangeLine expects
|
||||||
|
// Little cursed, but this allows us to use the same algorithm
|
||||||
|
auto contents =
|
||||||
|
fplus::replace_tokens(std::string{"fan speed"}, std::string{"fan_speed"}, *contentsRaw);
|
||||||
|
|
||||||
|
// We don't care acout the temps, since we set all points to desired speed
|
||||||
|
auto speedRange = parsePstateRangeLine("FAN_CURVE(fan_speed)", contents);
|
||||||
|
if (!speedRange.has_value())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
// Doesn't make sense with what we do
|
||||||
|
auto getFunc = [] { return std::nullopt; };
|
||||||
|
|
||||||
|
auto setFunc = [=](AssignmentArgument a) -> std::optional<AssignmentError> {
|
||||||
|
if (!std::holds_alternative<int>(a))
|
||||||
|
return AssignmentError::InvalidType;
|
||||||
|
|
||||||
|
auto target = std::get<int>(a);
|
||||||
|
if (speedRange->min > target || speedRange->max < target)
|
||||||
|
return AssignmentError::OutOfRange;
|
||||||
|
|
||||||
|
// TODO: do we even need to care about setting same temperature?
|
||||||
|
// Might be slow to do this every assignment
|
||||||
|
auto lines = pstateSectionLines("OD_FAN_CURVE", contents);
|
||||||
|
std::ofstream file{fanCurvePath};
|
||||||
|
if (lines.empty() || !file.good())
|
||||||
|
return AssignmentError::UnknownError;
|
||||||
|
|
||||||
|
for (int i = 0; i < lines.size(); i++) {
|
||||||
|
// Write all curve points to same value
|
||||||
|
auto words = fplus::split_one_of(std::string{" "}, false, lines[i]);
|
||||||
|
if (words.size() < 3)
|
||||||
|
return AssignmentError::UnknownError;
|
||||||
|
|
||||||
|
// Essentially cut off the 'C' in '65C'
|
||||||
|
auto temp = std::atoi(words[1].c_str());
|
||||||
|
char cmdString[32];
|
||||||
|
// TODO: docs say PWM but internet says percentage
|
||||||
|
snprintf(cmdString, 32, "%i %i %i", i, temp, target);
|
||||||
|
if (!(file << cmdString))
|
||||||
|
return AssignmentError::UnknownError;
|
||||||
|
}
|
||||||
|
if (file << "c")
|
||||||
|
return std::nullopt;
|
||||||
|
return AssignmentError::UnknownError;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {DeviceNode{
|
||||||
|
.name = _("Fan Speed"),
|
||||||
|
.interface = Assignable{setFunc, *speedRange, getFunc, _("%")},
|
||||||
|
.hash = md5(data.identifier + "RX7000 Fan Speed"),
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<TreeNode<DeviceNode>> getFanSpeedRead(AMDGPUData data) {
|
std::vector<TreeNode<DeviceNode>> getFanSpeedRead(AMDGPUData data) {
|
||||||
char path[96];
|
char path[96];
|
||||||
|
|
||||||
@ -1330,6 +1402,7 @@ auto gpuTree = TreeConstructor<AMDGPUData, DeviceNode>{
|
|||||||
{getFanRoot, {
|
{getFanRoot, {
|
||||||
{getFanMode, {}},
|
{getFanMode, {}},
|
||||||
{getFanSpeedWrite, {}},
|
{getFanSpeedWrite, {}},
|
||||||
|
{getFanSpeedWriteRX7000, {}},
|
||||||
{getFanSpeedRead, {}}
|
{getFanSpeedRead, {}}
|
||||||
}},
|
}},
|
||||||
{getPowerRoot, {
|
{getPowerRoot, {
|
||||||
|
Loading…
Reference in New Issue
Block a user