Implement changing memory speed and voltage on the fly.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
diff --git a/adl.c b/adl.c
index 7a84dad..2b79ac4 100644
--- a/adl.c
+++ b/adl.c
@@ -355,12 +355,134 @@ static int set_engineclock(int gpu, int iEngineClock)
return 0;
}
+static void get_memoryrange(int gpu, int *imin, int *imax)
+{
+ struct gpu_adl *ga;
+
+ if (!gpus[gpu].has_adl || !adl_active) {
+ wlogprint("Get memoryrange not supported\n");
+ return;
+ }
+ ga = &gpus[gpu].adl;
+ *imin = ga->lpOdParameters.sMemoryClock.iMin / 100;
+ *imax = ga->lpOdParameters.sMemoryClock.iMax / 100;
+}
+
+static int set_memoryclock(int gpu, int iMemoryClock)
+{
+ ADLODPerformanceLevels *lpOdPerformanceLevels;
+ struct gpu_adl *ga;
+ int lev;
+
+ if (!gpus[gpu].has_adl || !adl_active) {
+ wlogprint("Set memoryclock not supported\n");
+ return 1;
+ }
+
+ iMemoryClock *= 100;
+ ga = &gpus[gpu].adl;
+ if (iMemoryClock > ga->lpOdParameters.sMemoryClock.iMax ||
+ iMemoryClock < ga->lpOdParameters.sMemoryClock.iMin)
+ return 1;
+
+ lev = ga->lpOdParameters.iNumberOfPerformanceLevels - 1;
+ lpOdPerformanceLevels = alloca(sizeof(ADLODPerformanceLevels) + (lev * sizeof(ADLODPerformanceLevel)));
+ lpOdPerformanceLevels->iSize = sizeof(ADLODPerformanceLevels) + sizeof(ADLODPerformanceLevel) * lev;
+ if (ADL_Overdrive5_ODPerformanceLevels_Get(ga->iAdapterIndex, 0, lpOdPerformanceLevels) != ADL_OK)
+ return 1;
+ lpOdPerformanceLevels->aLevels[lev].iMemoryClock = iMemoryClock;
+ if (ADL_Overdrive5_ODPerformanceLevels_Set(ga->iAdapterIndex, lpOdPerformanceLevels) != ADL_OK)
+ return 1;
+ ADL_Overdrive5_ODPerformanceLevels_Get(ga->iAdapterIndex, 0, lpOdPerformanceLevels);
+ /* Reset to old value if it fails! */
+ if (lpOdPerformanceLevels->aLevels[lev].iMemoryClock != iMemoryClock) {
+ /* Set all the parameters in case they're linked somehow */
+ lpOdPerformanceLevels->aLevels[lev].iMemoryClock = ga->iEngineClock;
+ lpOdPerformanceLevels->aLevels[lev].iMemoryClock = ga->iMemoryClock;
+ lpOdPerformanceLevels->aLevels[lev].iVddc = ga->iVddc;
+ ADL_Overdrive5_ODPerformanceLevels_Set(ga->iAdapterIndex, lpOdPerformanceLevels);
+ ADL_Overdrive5_ODPerformanceLevels_Get(ga->iAdapterIndex, 0, lpOdPerformanceLevels);
+ return 1;
+ }
+ ga->iEngineClock = lpOdPerformanceLevels->aLevels[lev].iEngineClock;
+ ga->iMemoryClock = lpOdPerformanceLevels->aLevels[lev].iMemoryClock;
+ ga->iVddc = lpOdPerformanceLevels->aLevels[lev].iVddc;
+ return 0;
+}
+
+static void get_vddcrange(int gpu, float *imin, float *imax)
+{
+ struct gpu_adl *ga;
+
+ if (!gpus[gpu].has_adl || !adl_active) {
+ wlogprint("Get vddcrange not supported\n");
+ return;
+ }
+ ga = &gpus[gpu].adl;
+ *imin = (float)ga->lpOdParameters.sVddc.iMin / 1000;
+ *imax = (float)ga->lpOdParameters.sVddc.iMax / 1000;
+}
+
+static float curses_float(const char *query)
+{
+ float ret;
+ char *cvar;
+
+ cvar = curses_input(query);
+ ret = atof(cvar);
+ free(cvar);
+ return ret;
+}
+
+static int set_vddc(int gpu, float fVddc)
+{
+ ADLODPerformanceLevels *lpOdPerformanceLevels;
+ struct gpu_adl *ga;
+ int iVddc, lev;
+
+ if (!gpus[gpu].has_adl || !adl_active) {
+ wlogprint("Set vddc not supported\n");
+ return 1;
+ }
+
+ iVddc = 1000 * fVddc;
+ ga = &gpus[gpu].adl;
+ if (iVddc > ga->lpOdParameters.sVddc.iMax ||
+ iVddc < ga->lpOdParameters.sVddc.iMin)
+ return 1;
+
+ lev = ga->lpOdParameters.iNumberOfPerformanceLevels - 1;
+ lpOdPerformanceLevels = alloca(sizeof(ADLODPerformanceLevels) + (lev * sizeof(ADLODPerformanceLevel)));
+ lpOdPerformanceLevels->iSize = sizeof(ADLODPerformanceLevels) + sizeof(ADLODPerformanceLevel) * lev;
+ if (ADL_Overdrive5_ODPerformanceLevels_Get(ga->iAdapterIndex, 0, lpOdPerformanceLevels) != ADL_OK)
+ return 1;
+ lpOdPerformanceLevels->aLevels[lev].iVddc = iVddc;
+ if (ADL_Overdrive5_ODPerformanceLevels_Set(ga->iAdapterIndex, lpOdPerformanceLevels) != ADL_OK)
+ return 1;
+ ADL_Overdrive5_ODPerformanceLevels_Get(ga->iAdapterIndex, 0, lpOdPerformanceLevels);
+ /* Reset to old value if it fails! */
+ if (lpOdPerformanceLevels->aLevels[lev].iVddc != iVddc) {
+ /* Set all the parameters in case they're linked somehow */
+ lpOdPerformanceLevels->aLevels[lev].iEngineClock = ga->iEngineClock;
+ lpOdPerformanceLevels->aLevels[lev].iMemoryClock = ga->iMemoryClock;
+ lpOdPerformanceLevels->aLevels[lev].iVddc = ga->iVddc;
+ ADL_Overdrive5_ODPerformanceLevels_Set(ga->iAdapterIndex, lpOdPerformanceLevels);
+ ADL_Overdrive5_ODPerformanceLevels_Get(ga->iAdapterIndex, 0, lpOdPerformanceLevels);
+ return 1;
+ }
+ ga->iEngineClock = lpOdPerformanceLevels->aLevels[lev].iEngineClock;
+ ga->iMemoryClock = lpOdPerformanceLevels->aLevels[lev].iMemoryClock;
+ ga->iVddc = lpOdPerformanceLevels->aLevels[lev].iVddc;
+ return 0;
+}
+
void change_gpusettings(int gpu)
{
int val, imin = 0, imax = 0;
+ float fval, fmin = 0, fmax = 0;
char input;
- wlogprint("Change [E]ngine\n");
+ wlogprint("Change [E]ngine [M]emory [V]oltage\n");
wlogprint("Or press any other key to continue\n");
input = getch();
@@ -375,12 +497,40 @@ void change_gpusettings(int gpu)
return;
}
if (!set_engineclock(gpu, val))
- wlogprint("Successfully modified clock speed\n");
+ wlogprint("Successfully modified engine clock speed\n");
+ else
+ wlogprint("Failed to modify engine clock speed\n");
+ } else if (!strncasecmp(&input, "m", 1)) {
+ get_memoryrange(gpu, &imin, &imax);
+ wlogprint("Enter GPU memory clock speed (%d - %d Mhz):", imin, imax);
+ val = curses_int("");
+ if (val < imin || val > imax) {
+ wlogprint("Value is outside safe range, are you sure?\n");
+ input = getch();
+ if (strncasecmp(&input, "y", 1))
+ return;
+ }
+ if (!set_memoryclock(gpu, val))
+ wlogprint("Successfully modified memory clock speed\n");
else
- wlogprint("Failed to modify clock speed\n");
- wlogprint("Press any key to continue\n");
- input = getch();
+ wlogprint("Failed to modify memory clock speed\n");
+ } else if (!strncasecmp(&input, "v", 1)) {
+ get_vddcrange(gpu, &fmin, &fmax);
+ wlogprint("Enter GPU voltage (%.3f - %.3f Mhz):", fmin, fmax);
+ fval = curses_float("");
+ if (fval < fmin || fval > fmax) {
+ wlogprint("Value is outside safe range, are you sure?\n");
+ input = getch();
+ if (strncasecmp(&input, "y", 1))
+ return;
+ }
+ if (!set_vddc(gpu, fval))
+ wlogprint("Successfully modified voltage\n");
+ else
+ wlogprint("Failed to modify voltage\n");
}
+ wlogprint("Press any key to continue\n");
+ input = getch();
}
void clear_adl(void)