diff --git a/adl.c b/adl.c index d2ca00ad..7a84dada 100644 --- a/adl.c +++ b/adl.c @@ -1,5 +1,8 @@ #include "miner.h" #include "adl.h" + +bool adl_active; + #ifdef HAVE_ADL #if defined (__linux) #include "ADL_SDK/adl_sdk.h" @@ -13,6 +16,7 @@ #endif #include +#include #include "adl_functions.h" @@ -57,7 +61,6 @@ static ADL_OVERDRIVE5_ODPERFORMANCELEVELS_GET ADL_Overdrive5_ODPerformanceLevels static ADL_OVERDRIVE5_ODPERFORMANCELEVELS_SET ADL_Overdrive5_ODPerformanceLevels_Set; static ADL_MAIN_CONTROL_REFRESH ADL_Main_Control_Refresh; -bool adl_active; #if defined (LINUX) static void *hDLL; // Handle to .so library #else @@ -297,6 +300,89 @@ int gpu_fanspeed(int gpu) return ga->lpFanSpeedValue.iFanSpeed; } +static void get_enginerange(int gpu, int *imin, int *imax) +{ + struct gpu_adl *ga; + + if (!gpus[gpu].has_adl || !adl_active) { + wlogprint("Get enginerange not supported\n"); + return; + } + ga = &gpus[gpu].adl; + *imin = ga->lpOdParameters.sEngineClock.iMin / 100; + *imax = ga->lpOdParameters.sEngineClock.iMax / 100; +} + +static int set_engineclock(int gpu, int iEngineClock) +{ + ADLODPerformanceLevels *lpOdPerformanceLevels; + struct gpu_adl *ga; + int lev; + + if (!gpus[gpu].has_adl || !adl_active) { + wlogprint("Set engineclock not supported\n"); + return 1; + } + + iEngineClock *= 100; + ga = &gpus[gpu].adl; + if (iEngineClock > ga->lpOdParameters.sEngineClock.iMax || + iEngineClock < ga->lpOdParameters.sEngineClock.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].iEngineClock = iEngineClock; + 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].iEngineClock != iEngineClock) { + /* 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; + char input; + + wlogprint("Change [E]ngine\n"); + wlogprint("Or press any other key to continue\n"); + input = getch(); + + if (!strncasecmp(&input, "e", 1)) { + get_enginerange(gpu, &imin, &imax); + wlogprint("Enter GPU engine 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_engineclock(gpu, val)) + wlogprint("Successfully modified clock speed\n"); + else + wlogprint("Failed to modify clock speed\n"); + wlogprint("Press any key to continue\n"); + input = getch(); + } +} + void clear_adl(void) { if (!adl_active) diff --git a/adl.h b/adl.h index 68dc6111..2e3fee72 100644 --- a/adl.h +++ b/adl.h @@ -1,5 +1,6 @@ #ifndef __ADL_H__ #define __ADL_H__ +bool adl_active; #ifdef HAVE_ADL void init_adl(int nDevs); float gpu_temp(int gpu); @@ -8,9 +9,11 @@ int gpu_memclock(int gpu); float gpu_vddc(int gpu); int gpu_activity(int gpu); int gpu_fanspeed(int gpu); +void change_gpusettings(int gpu); void clear_adl(void); #else /* HAVE_ADL */ void init_adl(int nDevs) {} +void change_gpusettings(int gpu) { } void clear_adl(void) {} #endif #endif diff --git a/main.c b/main.c index 04a67aec..e0d0164b 100644 --- a/main.c +++ b/main.c @@ -1610,7 +1610,7 @@ static void wlog(const char *f, ...) } /* Mandatory printing */ -static void wlogprint(const char *f, ...) +void wlogprint(const char *f, ...) { va_list ap; @@ -2372,9 +2372,7 @@ static void *stage_thread(void *userdata) return NULL; } -static char *curses_input(const char *query); - -static int curses_int(const char *query) +int curses_int(const char *query) { int ret; char *cvar; @@ -2783,7 +2781,8 @@ retry: wlog("\n"); } - wlogprint("[E]nable [D]isable [R]estart GPU\n"); + wlogprint("[E]nable [D]isable [R]estart GPU %s\n",adl_active ? "[C]hange settings" : ""); + wlogprint("Or press any other key to continue\n"); input = getch(); @@ -2826,6 +2825,13 @@ retry: } wlogprint("Attempting to restart threads of GPU %d\n", selected); reinit_device(&gpus[selected]); + } else if (adl_active && (!strncasecmp(&input, "c", 1))) { + selected = curses_int("Select GPU to change settings on"); + if (selected < 0 || selected >= nDevs) { + wlogprint("Invalid selection\n"); + goto retry; + } + change_gpusettings(selected); } clear_logwin(); @@ -4331,10 +4337,6 @@ static void *watchdog_thread(void *userdata) break; thr = &thr_info[i]; gpu = thr->cgpu->cpu_gpu; -#if 0 - applog(LOG_WARNING, "Temp %d engine %d mem %d vddc %d activity %d fanspeed %d", gpu_temp(gpu), gpu_engineclock(gpu), - gpu_memclock(gpu), gpu_vddc(gpu), gpu_activity(gpu), gpu_fanspeed(gpu)); -#endif /* Thread is waiting on getwork or disabled */ if (thr->getwork || !gpu_devices[gpu]) continue; @@ -4471,7 +4473,7 @@ void quit(int status, const char *format, ...) exit(status); } -static char *curses_input(const char *query) +char *curses_input(const char *query) { char *input; diff --git a/miner.h b/miner.h index b2aa14ec..58cf8100 100644 --- a/miner.h +++ b/miner.h @@ -443,7 +443,9 @@ enum cl_kernel { }; bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce); - +extern void wlogprint(const char *f, ...); +extern int curses_int(const char *query); +extern char *curses_input(const char *query); extern void kill_work(void); extern void log_curses(int prio, const char *f, va_list ap); extern void vapplog(int prio, const char *fmt, va_list ap);