adl.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. #include "miner.h"
  2. #include "adl.h"
  3. #ifdef HAVE_ADL
  4. #if defined (__linux)
  5. #include "ADL_SDK/adl_sdk.h"
  6. #include <dlfcn.h>
  7. #include <stdlib.h>
  8. #include <unistd.h>
  9. #else
  10. #include <windows.h>
  11. #include <tchar.h>
  12. #include "ADL_SDK/adl_sdk.h"
  13. #endif
  14. #include <stdio.h>
  15. #include "adl_functions.h"
  16. // Memory allocation function
  17. static void * __stdcall ADL_Main_Memory_Alloc(int iSize)
  18. {
  19. void *lpBuffer = malloc(iSize);
  20. return lpBuffer;
  21. }
  22. // Optional Memory de-allocation function
  23. static void __stdcall ADL_Main_Memory_Free (void **lpBuffer)
  24. {
  25. if (*lpBuffer) {
  26. free (*lpBuffer);
  27. *lpBuffer = NULL;
  28. }
  29. }
  30. #if defined (LINUX)
  31. // equivalent functions in linux
  32. static void *GetProcAddress(void *pLibrary, const char *name)
  33. {
  34. return dlsym( pLibrary, name);
  35. }
  36. #endif
  37. static ADL_MAIN_CONTROL_CREATE ADL_Main_Control_Create;
  38. static ADL_MAIN_CONTROL_DESTROY ADL_Main_Control_Destroy;
  39. static ADL_ADAPTER_NUMBEROFADAPTERS_GET ADL_Adapter_NumberOfAdapters_Get;
  40. static ADL_ADAPTER_ADAPTERINFO_GET ADL_Adapter_AdapterInfo_Get;
  41. static ADL_ADAPTER_ID_GET ADL_Adapter_ID_Get;
  42. static ADL_OVERDRIVE5_TEMPERATURE_GET ADL_Overdrive5_Temperature_Get;
  43. static ADL_ADAPTER_ACTIVE_GET ADL_Adapter_Active_Get;
  44. static ADL_OVERDRIVE5_CURRENTACTIVITY_GET ADL_Overdrive5_CurrentActivity_Get;
  45. static ADL_OVERDRIVE5_ODPARAMETERS_GET ADL_Overdrive5_ODParameters_Get;
  46. static ADL_OVERDRIVE5_FANSPEEDINFO_GET ADL_Overdrive5_FanSpeedInfo_Get;
  47. static ADL_OVERDRIVE5_FANSPEED_GET ADL_Overdrive5_FanSpeed_Get;
  48. static ADL_OVERDRIVE5_FANSPEED_SET ADL_Overdrive5_FanSpeed_Set;
  49. static ADL_OVERDRIVE5_ODPERFORMANCELEVELS_GET ADL_Overdrive5_ODPerformanceLevels_Get;
  50. static ADL_OVERDRIVE5_ODPERFORMANCELEVELS_SET ADL_Overdrive5_ODPerformanceLevels_Set;
  51. static ADL_MAIN_CONTROL_REFRESH ADL_Main_Control_Refresh;
  52. bool adl_active;
  53. #if defined (LINUX)
  54. static void *hDLL; // Handle to .so library
  55. #else
  56. HINSTANCE hDLL; // Handle to DLL
  57. #endif
  58. static int iNumberAdapters;
  59. static LPAdapterInfo lpInfo = NULL;
  60. void init_adl(int nDevs)
  61. {
  62. int i, devices = 0, last_adapter = -1;
  63. #if defined (LINUX)
  64. hDLL = dlopen( "libatiadlxx.so", RTLD_LAZY|RTLD_GLOBAL);
  65. #else
  66. hDLL = LoadLibrary("atiadlxx.dll");
  67. if (hDLL == NULL)
  68. // A 32 bit calling application on 64 bit OS will fail to LoadLIbrary.
  69. // Try to load the 32 bit library (atiadlxy.dll) instead
  70. hDLL = LoadLibrary("atiadlxy.dll");
  71. #endif
  72. if (hDLL == NULL) {
  73. applog(LOG_INFO, "Unable to load ati adl library");
  74. return;
  75. }
  76. ADL_Main_Control_Create = (ADL_MAIN_CONTROL_CREATE) GetProcAddress(hDLL,"ADL_Main_Control_Create");
  77. ADL_Main_Control_Destroy = (ADL_MAIN_CONTROL_DESTROY) GetProcAddress(hDLL,"ADL_Main_Control_Destroy");
  78. ADL_Adapter_NumberOfAdapters_Get = (ADL_ADAPTER_NUMBEROFADAPTERS_GET) GetProcAddress(hDLL,"ADL_Adapter_NumberOfAdapters_Get");
  79. ADL_Adapter_AdapterInfo_Get = (ADL_ADAPTER_ADAPTERINFO_GET) GetProcAddress(hDLL,"ADL_Adapter_AdapterInfo_Get");
  80. ADL_Adapter_ID_Get = (ADL_ADAPTER_ID_GET) GetProcAddress(hDLL,"ADL_Adapter_ID_Get");
  81. ADL_Overdrive5_Temperature_Get = (ADL_OVERDRIVE5_TEMPERATURE_GET) GetProcAddress(hDLL,"ADL_Overdrive5_Temperature_Get");
  82. ADL_Adapter_Active_Get = (ADL_ADAPTER_ACTIVE_GET) GetProcAddress(hDLL, "ADL_Adapter_Active_Get");
  83. ADL_Overdrive5_CurrentActivity_Get = (ADL_OVERDRIVE5_CURRENTACTIVITY_GET) GetProcAddress(hDLL, "ADL_Overdrive5_CurrentActivity_Get");
  84. ADL_Overdrive5_ODParameters_Get = (ADL_OVERDRIVE5_ODPARAMETERS_GET) GetProcAddress(hDLL, "ADL_Overdrive5_ODParameters_Get");
  85. ADL_Overdrive5_FanSpeedInfo_Get = (ADL_OVERDRIVE5_FANSPEEDINFO_GET) GetProcAddress(hDLL, "ADL_Overdrive5_FanSpeedInfo_Get");
  86. ADL_Overdrive5_FanSpeed_Get = (ADL_OVERDRIVE5_FANSPEED_GET) GetProcAddress(hDLL, "ADL_Overdrive5_FanSpeed_Get");
  87. ADL_Overdrive5_FanSpeed_Set = (ADL_OVERDRIVE5_FANSPEED_SET) GetProcAddress(hDLL, "ADL_Overdrive5_FanSpeed_Set");
  88. ADL_Overdrive5_ODPerformanceLevels_Get = (ADL_OVERDRIVE5_ODPERFORMANCELEVELS_GET) GetProcAddress(hDLL, "ADL_Overdrive5_ODPerformanceLevels_Get");
  89. ADL_Overdrive5_ODPerformanceLevels_Set = (ADL_OVERDRIVE5_ODPERFORMANCELEVELS_SET) GetProcAddress(hDLL, "ADL_Overdrive5_ODPerformanceLevels_Set");
  90. ADL_Main_Control_Refresh = (ADL_MAIN_CONTROL_REFRESH) GetProcAddress(hDLL, "ADL_Main_Control_Refresh");
  91. if (!ADL_Main_Control_Create || !ADL_Main_Control_Destroy ||
  92. !ADL_Adapter_NumberOfAdapters_Get || !ADL_Adapter_AdapterInfo_Get ||
  93. !ADL_Adapter_ID_Get || !ADL_Overdrive5_Temperature_Get ||
  94. !ADL_Adapter_Active_Get || !ADL_Overdrive5_CurrentActivity_Get ||
  95. !ADL_Overdrive5_ODParameters_Get || !ADL_Overdrive5_FanSpeedInfo_Get ||
  96. !ADL_Overdrive5_FanSpeed_Get || !ADL_Overdrive5_FanSpeed_Set ||
  97. !ADL_Overdrive5_ODPerformanceLevels_Get || !ADL_Overdrive5_ODPerformanceLevels_Set ||
  98. !ADL_Main_Control_Refresh) {
  99. applog(LOG_INFO, "ATI ADL's API is missing");
  100. return;
  101. }
  102. // Initialise ADL. The second parameter is 1, which means:
  103. // retrieve adapter information only for adapters that are physically present and enabled in the system
  104. if (ADL_Main_Control_Create (ADL_Main_Memory_Alloc, 1) != ADL_OK) {
  105. applog(LOG_INFO, "ADL Initialisation Error!");
  106. return ;
  107. }
  108. if (ADL_Main_Control_Refresh() != ADL_OK) {
  109. applog(LOG_INFO, "ADL Refresh Error!");
  110. return ;
  111. }
  112. // Obtain the number of adapters for the system
  113. if (ADL_Adapter_NumberOfAdapters_Get ( &iNumberAdapters ) != ADL_OK) {
  114. applog(LOG_INFO, "Cannot get the number of adapters!\n");
  115. return ;
  116. }
  117. if (iNumberAdapters > 0) {
  118. lpInfo = malloc ( sizeof (AdapterInfo) * iNumberAdapters );
  119. memset ( lpInfo,'\0', sizeof (AdapterInfo) * iNumberAdapters );
  120. // Get the AdapterInfo structure for all adapters in the system
  121. if (ADL_Adapter_AdapterInfo_Get (lpInfo, sizeof (AdapterInfo) * iNumberAdapters) != ADL_OK) {
  122. applog(LOG_INFO, "ADL_Adapter_AdapterInfo_Get Error!");
  123. return ;
  124. }
  125. } else {
  126. applog(LOG_INFO, "No adapters found");
  127. return;
  128. }
  129. for ( i = 0; i < iNumberAdapters; i++ ) {
  130. struct gpu_adl *ga;
  131. int iAdapterIndex;
  132. int lpAdapterID;
  133. int lpStatus;
  134. ADLODPerformanceLevels *lpOdPerformanceLevels;
  135. int lev;
  136. iAdapterIndex = lpInfo[i].iAdapterIndex;
  137. /* Get unique identifier of the adapter */
  138. if (ADL_Adapter_ID_Get(iAdapterIndex, &lpAdapterID) != ADL_OK) {
  139. applog(LOG_INFO, "Failed to ADL_Adapter_ID_Get");
  140. continue;
  141. }
  142. if (!lpAdapterID)
  143. continue;
  144. if (lpAdapterID != last_adapter) {
  145. /* We found a truly new adapter instead of a logical
  146. * one. Now since there's no way of correlating the
  147. * opencl enumerated devices and the ADL enumerated
  148. * ones, we have to assume they're in the same order.*/
  149. if (++devices > nDevs) {
  150. applog(LOG_ERR, "ADL found more devices than opencl");
  151. return;
  152. }
  153. last_adapter = lpAdapterID;
  154. }
  155. /* See if the adapter is an AMD device with ADL active */
  156. if (ADL_Adapter_Active_Get(iAdapterIndex, &lpStatus) != ADL_OK) {
  157. applog(LOG_INFO, "Failed to ADL_Adapter_Active_Get");
  158. continue;
  159. }
  160. if (!lpStatus)
  161. continue;
  162. /* From here on we know this device is a discrete device and
  163. * should support ADL */
  164. ga = &gpus[devices - 1].adl;
  165. ga->iAdapterIndex = iAdapterIndex;
  166. ga->lpAdapterID = lpAdapterID;
  167. ga->lpStatus = lpStatus;
  168. if (ADL_Overdrive5_ODParameters_Get(iAdapterIndex, &ga->lpOdParameters) != ADL_OK) {
  169. applog(LOG_INFO, "Failed to ADL_Overdrive5_ODParameters_Get");
  170. continue;
  171. }
  172. lev = ga->lpOdParameters.iNumberOfPerformanceLevels - 1;
  173. /* We're only interested in the top performance level */
  174. lpOdPerformanceLevels = alloca(sizeof(ADLODPerformanceLevels) + (lev * sizeof(ADLODPerformanceLevel)));
  175. lpOdPerformanceLevels->iSize = sizeof(ADLODPerformanceLevels) + sizeof(ADLODPerformanceLevel) * lev;
  176. if (ADL_Overdrive5_ODPerformanceLevels_Get(iAdapterIndex, 0, lpOdPerformanceLevels) != ADL_OK) {
  177. applog(LOG_INFO, "Failed to ADL_Overdrive5_ODPerformanceLevels_Get");
  178. continue;
  179. }
  180. ga->iEngineClock = lpOdPerformanceLevels->aLevels[lev].iEngineClock;
  181. ga->iMemoryClock = lpOdPerformanceLevels->aLevels[lev].iMemoryClock;
  182. ga->iVddc = lpOdPerformanceLevels->aLevels[lev].iVddc;
  183. if (ADL_Overdrive5_FanSpeedInfo_Get(iAdapterIndex, 0, &ga->lpFanSpeedInfo) != ADL_OK) {
  184. applog(LOG_INFO, "Failed to ADL_Overdrive5_FanSpeedInfo_Get");
  185. continue;
  186. }
  187. gpus[devices - 1].has_adl = true;
  188. }
  189. adl_active = true;
  190. }
  191. float gpu_temp(int gpu)
  192. {
  193. struct gpu_adl *ga;
  194. if (!gpus[gpu].has_adl || !adl_active)
  195. return 0;
  196. ga = &gpus[gpu].adl;
  197. if (ADL_Overdrive5_Temperature_Get(ga->iAdapterIndex, 0, &ga->lpTemperature) != ADL_OK)
  198. return 0;
  199. return (float)ga->lpTemperature.iTemperature / 1000;
  200. }
  201. int gpu_engineclock(int gpu)
  202. {
  203. struct gpu_adl *ga;
  204. if (!gpus[gpu].has_adl || !adl_active)
  205. return 0;
  206. ga = &gpus[gpu].adl;
  207. if (ADL_Overdrive5_CurrentActivity_Get(ga->iAdapterIndex, &ga->lpActivity) != ADL_OK)
  208. return 0;
  209. return ga->lpActivity.iEngineClock / 100;
  210. }
  211. int gpu_memclock(int gpu)
  212. {
  213. struct gpu_adl *ga;
  214. if (!gpus[gpu].has_adl || !adl_active)
  215. return 0;
  216. ga = &gpus[gpu].adl;
  217. if (ADL_Overdrive5_CurrentActivity_Get(ga->iAdapterIndex, &ga->lpActivity) != ADL_OK)
  218. return 0;
  219. return ga->lpActivity.iMemoryClock / 100;
  220. }
  221. float gpu_vddc(int gpu)
  222. {
  223. struct gpu_adl *ga;
  224. if (!gpus[gpu].has_adl || !adl_active)
  225. return 0;
  226. ga = &gpus[gpu].adl;
  227. if (ADL_Overdrive5_CurrentActivity_Get(ga->iAdapterIndex, &ga->lpActivity) != ADL_OK)
  228. return 0;
  229. return (float)ga->lpActivity.iVddc / 1000;
  230. }
  231. int gpu_activity(int gpu)
  232. {
  233. struct gpu_adl *ga;
  234. if (!gpus[gpu].has_adl || !adl_active)
  235. return 0;
  236. ga = &gpus[gpu].adl;
  237. if (!ga->lpOdParameters.iActivityReportingSupported)
  238. return 0;
  239. if (ADL_Overdrive5_CurrentActivity_Get(ga->iAdapterIndex, &ga->lpActivity) != ADL_OK)
  240. return 0;
  241. return ga->lpActivity.iActivityPercent;
  242. }
  243. int gpu_fanspeed(int gpu)
  244. {
  245. struct gpu_adl *ga;
  246. if (!gpus[gpu].has_adl || !adl_active)
  247. return 0;
  248. ga = &gpus[gpu].adl;
  249. if (!(ga->lpFanSpeedInfo.iFlags & (ADL_DL_FANCTRL_SUPPORTS_RPM_READ | ADL_DL_FANCTRL_SUPPORTS_PERCENT_READ )))
  250. return 0;
  251. if (ADL_Overdrive5_FanSpeed_Get(ga->iAdapterIndex, 0, &ga->lpFanSpeedValue) != ADL_OK)
  252. return 0;
  253. return ga->lpFanSpeedValue.iFanSpeed;
  254. }
  255. void clear_adl(void)
  256. {
  257. if (!adl_active)
  258. return;
  259. ADL_Main_Memory_Free ( (void **)&lpInfo );
  260. ADL_Main_Control_Destroy ();
  261. #if defined (LINUX)
  262. dlclose(hDLL);
  263. #else
  264. FreeLibrary(hDLL);
  265. #endif
  266. }
  267. #endif /* HAVE_ADL */