Implement amd fancurve

This commit is contained in:
jussi 2019-05-07 21:23:51 +03:00
parent 192aa5403f
commit cbce4b07a8
5 changed files with 99 additions and 41 deletions

95
amd.cpp
View File

@ -2,6 +2,7 @@
#include "gputypes.h"
#include <tgmath.h>
#include <string.h>
#include "mainwindow.h"
#include <QThread>
#include <QSettings>
@ -206,6 +207,8 @@ void amd::calculateDisplayValues(int GPUIndex)
}
QString amd::applySettings(int GPUIndex)
{
currentGPUIndex = GPUIndex;
QSettings settings("tuxclocker");
settings.beginGroup("General");
//settings.setValue("latestUUID", GPUList[GPUIndex].pci_id);
@ -223,56 +226,54 @@ QString amd::applySettings(int GPUIndex)
bool hadErrors = false;
QProcess proc;
QString cmd = "pkexec /bin/sh -c \"";
/*
// Assign fan mode
switch (fanModeComboBox->currentIndex()) {
case 0:
if (!assignGPUFanCtlMode(GPUIndex, false)) {
hadErrors = true;
errStr.append("Fan mode, ");
}
break;
case 1:
if (latestFanSlider != fanSlider->value()) {
if (!assignGPUFanCtlMode(GPUIndex, true)) {
hadErrors = true;
errStr.append("Fan mode, ");
}
}
break;
}
if (GPUList[GPUIndex].manualFanCtrlAvailable && latestFanSlider != fanSlider->value()) {
if (!assignGPUFanSpeed(GPUIndex, fanSlider->value())) {
hadErrors = true;
fanSlider->setValue(latestFanSlider);
errStr.append("Fan speed, ");
}
}
if (GPUList[GPUIndex].powerLimitAvailable && latestpowerLimSlider != powerLimSlider->value()) {
if (!assignGPUPowerLimit(GPUIndex, static_cast<uint>(powerLimSlider->value()*1000000))) {
hadErrors = true;
powerLimSlider->setValue(latestpowerLimSlider);
errStr.append("Power limit, ");
}
}*/
// To avoid asking for password in pkexec multiple times, apply everything at once and query what succeeded afterwards
int cmdval = 0;
int targetValue = 0;
qDebug() << fanModeComboBox->currentIndex() << GPUList[GPUIndex].fanControlMode << "box index";
// Apply fan settings
if (fanModeComboBox->currentIndex() != GPUList[GPUIndex].fanControlMode) {
// On custom mode, the mode needs to be set again to load the new points
if (fanModeComboBox->currentIndex() == 2 || fanModeComboBox->currentIndex() != GPUList[GPUIndex].fanControlMode) {
switch (fanModeComboBox->currentIndex()) {
case 0:
cmd.append("echo '2' > "+GPUList[GPUIndex].hwmonpath+"/pwm1_enable & ");
cmd.append("echo '0' > "+GPUList[GPUIndex].hwmonpath+"/pwm1_enable & ");
// Disconnect fancurve timer
disconnect(fanUpdateTimer, SIGNAL(timeout()), this, SLOT(tempUpdater()));
break;
case 1:
cmd.append("echo '1' > "+GPUList[GPUIndex].hwmonpath+"/pwm1_enable & ");
int targetValue = fanSlider->value();
targetValue = fanSlider->value();
cmdval = static_cast<int>(ceil(targetValue*2.55));
cmd.append("echo '"+QString::number(cmdval)+"' > "+GPUList[GPUIndex].hwmonpath+"/pwm1 & ");
// Disconnect fancurve timer
disconnect(fanUpdateTimer, SIGNAL(timeout()), this, SLOT(tempUpdater()));
break;
case 2:
cmd.append("echo '1' > "+GPUList[GPUIndex].hwmonpath+"/pwm1_enable & ");
// Load the curve points from settings
QSettings settings("tuxclocker");
QString profile = settings.value("currentProfile").toString();
QString UUID = settings.value("latestUUID").toString();
settings.beginGroup(profile);
settings.beginGroup(UUID);
int size = settings.beginReadArray("curvepoints");
for (int i=0; i<size; i++) {
settings.setArrayIndex(i);
xCurvePoints.append(settings.value("xpoints").toInt());
yCurvePoints.append(settings.value("ypoints").toInt());
}
settings.endArray();
disconnect(fanUpdateTimer, SIGNAL(timeout()), this, SLOT(tempUpdater()));
// Activate the fan updater
connect(fanUpdateTimer, SIGNAL(timeout()), this, SLOT(tempUpdater()));
fanUpdateTimer->start(2000);
break;
}
}
@ -284,10 +285,11 @@ QString amd::applySettings(int GPUIndex)
}
// Apply power limit
if (powerLimSlider->value() != latestpowerLimSlider) {
cmd.append("echo '" + QString::number(powerLimSlider->value() * 1000000) +"' > " + GPUList[GPUIndex].hwmonpath + "/power1_cap & ");
if (GPUList[GPUIndex].powerLimitAvailable) {
if (powerLimSlider->value() != latestpowerLimSlider) {
cmd.append("echo '" + QString::number(powerLimSlider->value() * 1000000) +"' > " + GPUList[GPUIndex].hwmonpath + "/power1_cap & ");
}
}
// Apply voltage/core clock (highest pstate)
if (GPUList[GPUIndex].overClockAvailable) {
if ((coreClockSlider->value() != GPUList[GPUIndex].coreclocks.last()) || (voltageSlider->value() != GPUList[GPUIndex].corevolts.last())) {
@ -298,6 +300,7 @@ QString amd::applySettings(int GPUIndex)
}
cmd.append("\"");
qDebug() << "running cmd " << cmd;
proc.start(cmd);
proc.waitForFinished(-1);
QThread::msleep(200);
@ -364,6 +367,8 @@ QString amd::applySettings(int GPUIndex)
return errStr;
} else {
GPUList[GPUIndex].fanControlMode = fanModeComboBox->currentIndex();
latestFanSlider = fanSlider->value();
latestMemClkSlider = memClockSlider->value();
latestpowerLimSlider = powerLimSlider->value();
@ -466,6 +471,7 @@ void amd::queryGPUFeatures()
}*/
// If the pstate vectors are empty after searching, set the features disabled
if (!GPUList[i].corevolts.isEmpty()) GPUList[i].overVoltAvailable = true;
else GPUList[i].overVoltAvailable = false;
if (!GPUList[i].coreclocks.isEmpty()) {
GPUList[i].overClockAvailable = true;
@ -817,4 +823,13 @@ bool amd::assignGPUPowerLimit(int GPUIndex, uint targetValue)
return false;
}
void amd::tempUpdater() {
queryGPUTemp(currentGPUIndex);
if (!xCurvePoints.isEmpty()) {
int targetFanSpeed = generateFanPoint(GPUList[currentGPUIndex].temp / 1000, xCurvePoints, yCurvePoints);
qDebug() << "fancurve: setting to" << targetFanSpeed << "%";
assignGPUFanSpeed(currentGPUIndex, targetFanSpeed);
}
}
#endif

View File

@ -4,3 +4,29 @@ gputypes::gputypes()
{}
gputypes::~gputypes()
{}
int gputypes::generateFanPoint(int temp, QVector <int> xPoints, QVector <int> yPoints) {
// Calculate the value for fan speed based on temperature
// First check if the fan speed should be y[0] or y[final]
qDebug("temp: %d", temp);
int index = 0;
if (temp <= xPoints[0]) {
qDebug("ret first point");
return yPoints[0];
} else if (temp >= xPoints.last()) {
qDebug("ret last point %d", xPoints.last());
return yPoints.last();
} else {
// Get the index of the leftmost point of the interpolated interval by comparing it to temperature
for (int i=0; i<xPoints.size(); i++) {
if (temp >= xPoints[i] && temp <= xPoints[i+1]) {
index = i;
break;
}
}
// Check if the change in x is zero to avoid dividing by it
if (xPoints[index] - xPoints[index + 1] == 0) {
return yPoints[index + 1];
} else return (((yPoints[index + 1] - yPoints[index]) * (temp - xPoints[index])) / (xPoints[index + 1] - xPoints[index])) + yPoints[index];
}
}

View File

@ -147,6 +147,8 @@ public:
QLabel *memVoltageLabel;
QComboBox *fanModeComboBox;
QTimer *fanUpdateTimer;
// Variables to check if a slider has been changed
int latestFanSlider;
int latestVoltageSlider;
@ -155,6 +157,10 @@ public:
int latestCoreClkSlider;
int latestMemVoltageSlider;
// Fancurve vectors
QVector <int> xCurvePoints, yCurvePoints;
// Latest GPU index for the fancurve
int currentGPUIndex;
#ifdef NVIDIA
Display *dpy;
nvmlDevice_t *device;
@ -192,6 +198,10 @@ public:
virtual bool assignGPUMemClockOffset(int GPUIndex, int targetValue) = 0;
virtual bool assignGPUVoltageOffset(int GPUIndex, int targetValue) = 0;
virtual bool assignGPUPowerLimit(int GPUIndex, uint targetValue) = 0;
virtual void tempUpdater() = 0;
// Return the desired fan percentage
int generateFanPoint(int temp, QVector <int> xPoints, QVector <int> yPoints);
protected:
~gputypes();
@ -239,6 +249,8 @@ public slots:
bool assignGPUVoltageOffset(int GPUIndex, int targetValue);
// NVML functions know the GPU index already based on the dev object passed in setupNVML()
bool assignGPUPowerLimit(uint targetValue);
void tempUpdater();
private slots:
};
#endif
@ -285,6 +297,9 @@ public slots:
bool assignGPUVoltageOffset(int GPUIndex, int targetValue);
bool assignGPUPowerLimit(int GPUIndex, uint targetValue);
void queryPstates();
void tempUpdater();
private slots:
};
#endif

View File

@ -50,6 +50,8 @@ MainWindow::MainWindow(QWidget *parent) :
types->memClockLabel = ui->memClockLabel;
types->fanModeComboBox = ui->fanModeComboBox;
types->fanUpdateTimer = fanUpdateTimer;
// This is for libxnvctrl
types->setupGPU();
// This is for NVML

View File

@ -96,6 +96,7 @@ public:
bool isRoot = false;
public slots:
void tempUpdater();
private slots:
@ -131,7 +132,6 @@ private slots:
void getGPUDriver();
void generateFanPoint();
void checkForRoot();
void tempUpdater();
void resetChanges();
void resetTimer();