mirror of
https://github.com/Lurkki14/tuxclocker.git
synced 2025-02-25 18:55:24 -06:00
add AMD memory pstate editing
This commit is contained in:
@@ -96,6 +96,10 @@ std::optional<Assignable> vfPointClockAssignable(
|
|||||||
if (!vfPoint.has_value())
|
if (!vfPoint.has_value())
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
|
// Memory clock -> controller clock for memory clocks
|
||||||
|
if (vfType == MemoryPState)
|
||||||
|
return toMemoryClock(vfPoint->clock, data);
|
||||||
|
|
||||||
return vfPoint->clock;
|
return vfPoint->clock;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,6 +118,10 @@ std::optional<Assignable> vfPointClockAssignable(
|
|||||||
if (!vfPoint.has_value())
|
if (!vfPoint.has_value())
|
||||||
return AssignmentError::UnknownError;
|
return AssignmentError::UnknownError;
|
||||||
|
|
||||||
|
// Memory clock -> controller clock for memory clocks
|
||||||
|
if (vfType == MemoryPState)
|
||||||
|
target = toControllerClock(target, data);
|
||||||
|
|
||||||
std::ofstream file{data.hwmonPath + "/pp_od_clk_voltage"};
|
std::ofstream file{data.hwmonPath + "/pp_od_clk_voltage"};
|
||||||
char cmdString[32];
|
char cmdString[32];
|
||||||
snprintf(
|
snprintf(
|
||||||
@@ -653,6 +661,78 @@ std::vector<TreeNode<DeviceNode>> getCorePStateVolt(AMDGPUData data) {
|
|||||||
.hash = md5(data.pciId + "CorePStateVolt" + std::to_string(id)),
|
.hash = md5(data.pciId + "CorePStateVolt" + std::to_string(id)),
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<TreeNode<DeviceNode>> getMemoryPStateFreq(AMDGPUData data) {
|
||||||
|
static amdgpu_device_handle latestDev = nullptr;
|
||||||
|
static int pointId = 0;
|
||||||
|
std::vector<TreeNode<DeviceNode>> retval = {};
|
||||||
|
|
||||||
|
if (data.devHandle != latestDev)
|
||||||
|
// Start from zero for new device
|
||||||
|
pointId = 0;
|
||||||
|
|
||||||
|
latestDev = data.devHandle;
|
||||||
|
|
||||||
|
auto rangeController = parsePstateRangeLineWithRead("MCLK", data);
|
||||||
|
if (!rangeController.has_value()) {
|
||||||
|
pointId++;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Controller clock -> effective clock
|
||||||
|
Range<int> range{
|
||||||
|
toMemoryClock(rangeController->min, data), toMemoryClock(rangeController->max, data)};
|
||||||
|
|
||||||
|
// Make a copy so the lambda keeps using the right id
|
||||||
|
auto id = pointId;
|
||||||
|
// Conversion back to controller clock is handled there
|
||||||
|
auto assignable = vfPointClockAssignable(MemoryPState, id, range, data);
|
||||||
|
|
||||||
|
pointId++;
|
||||||
|
|
||||||
|
if (!assignable.has_value())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return {DeviceNode{
|
||||||
|
.name = _("Memory Clock"),
|
||||||
|
.interface = *assignable,
|
||||||
|
.hash = md5(data.pciId + "MemoryPStateFreq" + std::to_string(id)),
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<TreeNode<DeviceNode>> getMemoryPStateVolt(AMDGPUData data) {
|
||||||
|
static amdgpu_device_handle latestDev = nullptr;
|
||||||
|
static int pointId = 0;
|
||||||
|
std::vector<TreeNode<DeviceNode>> retval = {};
|
||||||
|
|
||||||
|
if (data.devHandle != latestDev)
|
||||||
|
// Start from zero for new device
|
||||||
|
pointId = 0;
|
||||||
|
|
||||||
|
latestDev = data.devHandle;
|
||||||
|
|
||||||
|
auto range = parsePstateRangeLineWithRead("VDDC", data);
|
||||||
|
if (!range.has_value()) {
|
||||||
|
pointId++;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a copy so the lambda keeps using the right id
|
||||||
|
auto id = pointId;
|
||||||
|
auto assignable = vfPointVoltageAssignable(MemoryPState, id, *range, data);
|
||||||
|
|
||||||
|
pointId++;
|
||||||
|
|
||||||
|
if (!assignable.has_value())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return {DeviceNode{
|
||||||
|
.name = _("Memory Voltage"),
|
||||||
|
.interface = *assignable,
|
||||||
|
.hash = md5(data.pciId + "MemoryPStateVolt" + std::to_string(id)),
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<TreeNode<DeviceNode>> getVoltFreqNodes(AMDGPUData data) {
|
std::vector<TreeNode<DeviceNode>> getVoltFreqNodes(AMDGPUData data) {
|
||||||
// Root item for voltage and frequency of a point
|
// Root item for voltage and frequency of a point
|
||||||
std::vector<TreeNode<DeviceNode>> retval;
|
std::vector<TreeNode<DeviceNode>> retval;
|
||||||
@@ -706,6 +786,32 @@ std::vector<TreeNode<DeviceNode>> getCorePStateNodes(AMDGPUData data) {
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<TreeNode<DeviceNode>> getMemoryPStateNodes(AMDGPUData data) {
|
||||||
|
// Root item for voltage and frequency of a pstate
|
||||||
|
std::vector<TreeNode<DeviceNode>> retval;
|
||||||
|
if (!data.ppTableType.has_value() || *data.ppTableType != Vega10)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
auto path = data.hwmonPath + "/pp_od_clk_voltage";
|
||||||
|
auto tableContents = fileContents(path);
|
||||||
|
if (!tableContents.has_value())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
auto lines = pstateSectionLines("OD_MCLK", *tableContents);
|
||||||
|
char name[32];
|
||||||
|
for (int i = 0; i < lines.size(); i++) {
|
||||||
|
snprintf(name, 32, "%s %i", _("State"), i);
|
||||||
|
|
||||||
|
DeviceNode node{
|
||||||
|
.name = name,
|
||||||
|
.interface = std::nullopt,
|
||||||
|
.hash = md5(data.pciId + "MemoryPState" + std::to_string(i)),
|
||||||
|
};
|
||||||
|
retval.push_back(node);
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<TreeNode<DeviceNode>> getVoltageRead(AMDGPUData data) {
|
std::vector<TreeNode<DeviceNode>> getVoltageRead(AMDGPUData data) {
|
||||||
auto func = [=](int sensorType) -> ReadResult {
|
auto func = [=](int sensorType) -> ReadResult {
|
||||||
uint volt;
|
uint volt;
|
||||||
@@ -819,6 +925,17 @@ std::vector<TreeNode<DeviceNode>> getCorePStateRoot(AMDGPUData data) {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<TreeNode<DeviceNode>> getMemoryPStateRoot(AMDGPUData data) {
|
||||||
|
if (!data.ppTableType.has_value() || *data.ppTableType != Vega10)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return {DeviceNode{
|
||||||
|
.name = _("Memory Performance States"),
|
||||||
|
.interface = std::nullopt,
|
||||||
|
.hash = md5(data.pciId + "Memory Performance States"),
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<TreeNode<DeviceNode>> getGPUName(AMDGPUData data) {
|
std::vector<TreeNode<DeviceNode>> getGPUName(AMDGPUData data) {
|
||||||
auto name = amdgpu_get_marketing_name(data.devHandle);
|
auto name = amdgpu_get_marketing_name(data.devHandle);
|
||||||
if (name) {
|
if (name) {
|
||||||
@@ -862,6 +979,12 @@ auto gpuTree = TreeConstructor<AMDGPUData, DeviceNode>{
|
|||||||
{getCorePStateFreq, {}},
|
{getCorePStateFreq, {}},
|
||||||
{getCorePStateVolt, {}}
|
{getCorePStateVolt, {}}
|
||||||
}}
|
}}
|
||||||
|
}},
|
||||||
|
{getMemoryPStateRoot, {
|
||||||
|
{getMemoryPStateNodes, {
|
||||||
|
{getMemoryPStateFreq, {}},
|
||||||
|
{getMemoryPStateVolt, {}}
|
||||||
|
}}
|
||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -195,3 +195,26 @@ std::vector<AMDGPUData> fromFilesystem() {
|
|||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int toMemoryClock(int controllerClock, AMDGPUData data) {
|
||||||
|
drm_amdgpu_info_device info;
|
||||||
|
if (amdgpu_query_info(data.devHandle, AMDGPU_INFO_DEV_INFO, sizeof(info), &info) != 0)
|
||||||
|
return controllerClock;
|
||||||
|
|
||||||
|
// For GDDR 6 (?) memory clock is 2x controller clock, for rest it's the same
|
||||||
|
if (info.vram_type == AMDGPU_VRAM_TYPE_GDDR6)
|
||||||
|
return controllerClock * 2;
|
||||||
|
|
||||||
|
return controllerClock;
|
||||||
|
}
|
||||||
|
|
||||||
|
int toControllerClock(int memoryClock, AMDGPUData data) {
|
||||||
|
drm_amdgpu_info_device info;
|
||||||
|
if (amdgpu_query_info(data.devHandle, AMDGPU_INFO_DEV_INFO, sizeof(info), &info) != 0)
|
||||||
|
return memoryClock;
|
||||||
|
|
||||||
|
if (info.vram_type == AMDGPU_VRAM_TYPE_GDDR6)
|
||||||
|
return memoryClock / 2;
|
||||||
|
|
||||||
|
return memoryClock;
|
||||||
|
}
|
||||||
|
|||||||
@@ -51,3 +51,7 @@ std::optional<PPTableType> fromPPTableContents(const std::string &contents);
|
|||||||
std::optional<AMDGPUData> fromRenderDFile(const fs::directory_entry &entry);
|
std::optional<AMDGPUData> fromRenderDFile(const fs::directory_entry &entry);
|
||||||
|
|
||||||
std::vector<AMDGPUData> fromFilesystem();
|
std::vector<AMDGPUData> fromFilesystem();
|
||||||
|
|
||||||
|
// https://docs.kernel.org/gpu/amdgpu/thermal.html#pp-od-clk-voltage
|
||||||
|
int toMemoryClock(int controllerClock, AMDGPUData data);
|
||||||
|
int toControllerClock(int memoryClock, AMDGPUData data);
|
||||||
|
|||||||
Reference in New Issue
Block a user