2 Copyright (C) 2010-2011 thgreasi@gmail.com
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 /* AMD id for the aticonfig */
29 #define _(str) gettext(str)
32 #include <dlfcn.h> /* dyopen, dlsym, dlclose */
35 #include <string.h> /* memeset */
39 /* Definitions of the used function pointers.
40 Add more if you use other ADL APIs */
41 typedef int (*ADL_MAIN_CONTROL_CREATE)(ADL_MAIN_MALLOC_CALLBACK, int);
42 typedef int (*ADL_MAIN_CONTROL_DESTROY)();
43 typedef int (*ADL_ADAPTER_NUMBEROFADAPTERS_GET) (int *);
44 typedef int (*ADL_ADAPTER_ADAPTERINFO_GET) (LPAdapterInfo, int);
45 typedef int (*ADL_ADAPTER_ACTIVE_GET) (int, int*);
46 typedef int (*ADL_OVERDRIVE5_TEMPERATURE_GET) (int, int, ADLTemperature*);
47 typedef int (*ADL_OVERDRIVE5_FANSPEED_GET) (int, int, ADLFanSpeedValue*);
49 static ADL_MAIN_CONTROL_CREATE adl_main_control_create;
50 static ADL_MAIN_CONTROL_DESTROY adl_main_control_destroy;
51 static ADL_ADAPTER_NUMBEROFADAPTERS_GET adl_adapter_numberofadapters_get;
52 static ADL_ADAPTER_ADAPTERINFO_GET adl_adapter_adapterinfo_get;
53 static ADL_ADAPTER_ACTIVE_GET adl_adapter_active_get;
54 static ADL_OVERDRIVE5_TEMPERATURE_GET adl_overdrive5_temperature_get;
55 static ADL_OVERDRIVE5_FANSPEED_GET adl_overdrive5_fanspeed_get;
58 static int adl_main_control_done;
59 static int *active_amd_adapters;
61 /* Memory allocation function */
62 static void __stdcall *adl_main_memory_alloc(int isize)
64 void *lpbuffer = malloc(isize);
68 /* Optional Memory de-allocation function */
69 static void __stdcall adl_main_memory_free(void** lpbuffer)
77 static void *getprocaddress(void * plibrary, const char * name)
79 return dlsym(plibrary, name);
83 Returns the temperature (Celcius) of an AMD/Ati GPU.
85 static int get_temp(struct psensor *sensor)
87 ADLTemperature temperature;
89 temperature.iSize = sizeof(ADLTemperature);
90 temperature.iTemperature = -273;
91 if (ADL_OK != adl_overdrive5_temperature_get(sensor->amd_id,
95 return temperature.iTemperature/1000;
98 static int get_fanspeed(struct psensor *sensor)
100 ADLFanSpeedValue fanspeedvalue;
102 fanspeedvalue.iSize = sizeof(ADLFanSpeedValue);
103 fanspeedvalue.iSpeedType = ADL_DL_FANCTRL_SPEED_TYPE_RPM;
104 fanspeedvalue.iFanSpeed = -1;
105 if (ADL_OK != adl_overdrive5_fanspeed_get(sensor->amd_id,
109 return fanspeedvalue.iFanSpeed;
112 static struct psensor *create_sensor(int id, int values_len)
120 if (id & 1) {/* odd number ids represent fan sensors */
122 sprintf(name, "GPU%dfan", id);
123 sensor_type = SENSOR_TYPE_AMD_FAN;
124 } else {/* even number ids represent temperature sensors */
126 sprintf(name, "GPU%dtemp", id);
127 sensor_type = SENSOR_TYPE_AMD_TEMP;
130 sid = malloc(strlen("AMD") + 1 + strlen(name) + 1);
131 sprintf(sid, "AMD %s", name);
133 s = psensor_create(sid, strdup(name),
134 sensor_type, values_len);
136 s->amd_id = active_amd_adapters[id];
142 Returns the number of AMD/Ati GPU sensors (temperature and fan speed).
144 Return 0 if no AMD/Ati gpus or cannot get information.
148 LPAdapterInfo lpadapterinfo = NULL;
149 int i, inumberadapters, inumberadaptersactive = 0;
150 int lpstatus, iadapterindex;
153 adl_main_control_done = 0;
154 active_amd_adapters = NULL;
155 hdll = dlopen("libatiadlxx.so", RTLD_LAZY|RTLD_GLOBAL);
160 _("ERROR: ADL library not found!\n"));
164 adl_main_control_create = (ADL_MAIN_CONTROL_CREATE)
165 getprocaddress(hdll, "ADL_Main_Control_Create");
166 adl_main_control_destroy = (ADL_MAIN_CONTROL_DESTROY)
167 getprocaddress(hdll, "ADL_Main_Control_Destroy");
168 adl_adapter_numberofadapters_get = (ADL_ADAPTER_NUMBEROFADAPTERS_GET)
169 getprocaddress(hdll, "ADL_Adapter_NumberOfAdapters_Get");
170 adl_adapter_adapterinfo_get = (ADL_ADAPTER_ADAPTERINFO_GET)
171 getprocaddress(hdll, "ADL_Adapter_AdapterInfo_Get");
172 adl_adapter_active_get = (ADL_ADAPTER_ACTIVE_GET)
173 getprocaddress(hdll, "ADL_Adapter_Active_Get");
174 adl_overdrive5_temperature_get = (ADL_OVERDRIVE5_TEMPERATURE_GET)
175 getprocaddress(hdll, "ADL_Overdrive5_Temperature_Get");
176 adl_overdrive5_fanspeed_get = (ADL_OVERDRIVE5_FANSPEED_GET)
177 getprocaddress(hdll, "ADL_Overdrive5_FanSpeed_Get");
178 if (!adl_main_control_create ||
179 !adl_main_control_destroy ||
180 !adl_adapter_numberofadapters_get ||
181 !adl_adapter_adapterinfo_get ||
182 !adl_overdrive5_temperature_get ||
183 !adl_overdrive5_fanspeed_get) {
185 _("ERROR: ADL's API is missing!\n"));
189 /* Initialize ADL. The second parameter is 1, which means:
190 retrieve adapter information only for adapters that
191 are physically present and enabled in the system */
192 if (ADL_OK != adl_main_control_create(adl_main_memory_alloc, 1)) {
194 _("ERROR: ADL Initialization Error!\n"));
197 adl_main_control_done = 1;
199 /* Obtain the number of adapters for the system */
200 if (ADL_OK != adl_adapter_numberofadapters_get(&inumberadapters)) {
202 _("ERROR: Cannot get the number of adapters!\n"));
206 if (!inumberadapters)
209 lpadapterinfo = malloc(sizeof(AdapterInfo) * inumberadapters);
210 memset(lpadapterinfo, '\0', sizeof(AdapterInfo) * inumberadapters);
212 /* Get the AdapterInfo structure for all adapters in the system */
213 adl_adapter_adapterinfo_get(lpadapterinfo,
214 sizeof(AdapterInfo) * inumberadapters);
216 /* Repeat for all available adapters in the system */
217 for (i = 0; i < inumberadapters; i++) {
218 iadapterindex = lpadapterinfo[i].iAdapterIndex;
219 if (ADL_OK != adl_adapter_active_get(iadapterindex, &lpstatus))
221 if (lpstatus != ADL_TRUE)
222 /* count only if the adapter is active */
225 if (!active_amd_adapters) {
226 active_amd_adapters = (int *) malloc(sizeof(int));
227 inumberadaptersactive = 1;
229 ++inumberadaptersactive;
230 active_amd_adapters =
231 (int *) realloc(active_amd_adapters,
232 sizeof(int)*inumberadaptersactive);
234 active_amd_adapters[inumberadaptersactive-1] = iadapterindex;
237 adl_main_memory_free((void **) &lpadapterinfo);
239 /* Each Adapter has one GPU temperature
240 sensor and one fan control sensor */
241 return 2*inumberadaptersactive;
244 void amd_psensor_list_update(struct psensor **sensors)
246 struct psensor **ss, *s;
252 if (s->type == SENSOR_TYPE_AMD_TEMP)
253 psensor_set_current_value(s, get_temp(s));
254 else if (s->type == SENSOR_TYPE_AMD_FAN)
255 psensor_set_current_value(s, get_fanspeed(s));
262 amd_psensor_list_add(struct psensor **sensors, int values_len)
265 struct psensor **tmp, **ss, *s;
270 for (i = 0; i < n; i++) {
271 s = create_sensor(i, values_len);
273 tmp = psensor_list_add(ss, s);
281 if (active_amd_adapters) {
282 free(active_amd_adapters);
283 active_amd_adapters = NULL;
292 if (adl_main_control_done)
293 adl_main_control_destroy();
296 if (active_amd_adapters) {
297 free(active_amd_adapters);
298 active_amd_adapters = NULL;