2 * Copyright (C) 2010-2011 thgreasi@gmail.com, jeanfi@gmail.com
3 * Copyright (C) 2010-2013 jeanfi@gmail.com
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 /* AMD id for the aticonfig */
30 #define _(str) gettext(str)
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_adapters;
61 static void __stdcall *adl_main_memory_alloc(int isize)
63 void *lpbuffer = malloc(isize);
67 static void *getprocaddress(void *plibrary, const char *name)
69 return dlsym(plibrary, name);
73 Returns the temperature (Celcius) of an AMD/Ati GPU.
75 static double get_temp(struct psensor *sensor)
77 ADLTemperature temperature;
79 temperature.iSize = sizeof(ADLTemperature);
80 temperature.iTemperature = -273;
81 if (ADL_OK != adl_overdrive5_temperature_get(sensor->amd_id,
83 return UNKNOWN_DBL_VALUE;
85 return temperature.iTemperature/1000;
88 static double get_fanspeed(struct psensor *sensor)
90 ADLFanSpeedValue fanspeedvalue;
92 fanspeedvalue.iSize = sizeof(ADLFanSpeedValue);
93 fanspeedvalue.iSpeedType = ADL_DL_FANCTRL_SPEED_TYPE_RPM;
94 fanspeedvalue.iFanSpeed = -1;
95 if (ADL_OK != adl_overdrive5_fanspeed_get(sensor->amd_id,
97 return UNKNOWN_DBL_VALUE;
99 return fanspeedvalue.iFanSpeed;
102 static struct psensor *create_sensor(int id, int values_len)
110 if (id & 1) {/* odd number ids represent fan sensors */
112 sprintf(name, "GPU%dfan", id);
113 sensor_type = SENSOR_TYPE_ATIADL
116 } else {/* even number ids represent temperature sensors */
118 sprintf(name, "GPU%dtemp", id);
119 sensor_type = SENSOR_TYPE_ATIADL
124 sid = malloc(strlen("amd") + 1 + strlen(name) + 1);
125 sprintf(sid, "amd %s", name);
127 s = psensor_create(sid, strdup(name), strdup("ATI GPU"),
128 sensor_type, values_len);
130 s->amd_id = active_adapters[id];
136 Returns the number of AMD/Ati GPU sensors (temperature and fan
139 Return 0 if no AMD/Ati gpus or cannot get information.
143 LPAdapterInfo lpadapterinfo = NULL;
144 int i, inumberadapters, inumberadaptersactive = 0;
145 int lpstatus, iadapterindex;
147 adl_main_control_done = 0;
148 active_adapters = NULL;
149 hdll = dlopen("libatiadlxx.so", RTLD_LAZY|RTLD_GLOBAL);
152 log_err(_("AMD: cannot found ADL library."));
156 adl_main_control_create = (ADL_MAIN_CONTROL_CREATE)
157 getprocaddress(hdll, "ADL_Main_Control_Create");
158 adl_main_control_destroy = (ADL_MAIN_CONTROL_DESTROY)
159 getprocaddress(hdll, "ADL_Main_Control_Destroy");
160 adl_adapter_numberofadapters_get = (ADL_ADAPTER_NUMBEROFADAPTERS_GET)
161 getprocaddress(hdll, "ADL_Adapter_NumberOfAdapters_Get");
162 adl_adapter_adapterinfo_get = (ADL_ADAPTER_ADAPTERINFO_GET)
163 getprocaddress(hdll, "ADL_Adapter_AdapterInfo_Get");
164 adl_adapter_active_get = (ADL_ADAPTER_ACTIVE_GET)
165 getprocaddress(hdll, "ADL_Adapter_Active_Get");
166 adl_overdrive5_temperature_get = (ADL_OVERDRIVE5_TEMPERATURE_GET)
167 getprocaddress(hdll, "ADL_Overdrive5_Temperature_Get");
168 adl_overdrive5_fanspeed_get = (ADL_OVERDRIVE5_FANSPEED_GET)
169 getprocaddress(hdll, "ADL_Overdrive5_FanSpeed_Get");
170 if (!adl_main_control_create ||
171 !adl_main_control_destroy ||
172 !adl_adapter_numberofadapters_get ||
173 !adl_adapter_adapterinfo_get ||
174 !adl_overdrive5_temperature_get ||
175 !adl_overdrive5_fanspeed_get) {
176 log_err(_("AMD: missing ADL's API."));
180 if (ADL_OK != adl_main_control_create(adl_main_memory_alloc, 1)) {
181 log_err(_("AMD: failed to initialize ADL."));
184 adl_main_control_done = 1;
186 if (ADL_OK != adl_adapter_numberofadapters_get(&inumberadapters)) {
187 log_err(_("AMD: cannot get the number of adapters."));
191 if (!inumberadapters)
194 lpadapterinfo = malloc(sizeof(AdapterInfo) * inumberadapters);
195 memset(lpadapterinfo, '\0', sizeof(AdapterInfo) * inumberadapters);
197 adl_adapter_adapterinfo_get(lpadapterinfo,
198 sizeof(AdapterInfo) * inumberadapters);
200 for (i = 0; i < inumberadapters; i++) {
202 iadapterindex = lpadapterinfo[i].iAdapterIndex;
204 if (ADL_OK != adl_adapter_active_get(iadapterindex, &lpstatus))
206 if (lpstatus != ADL_TRUE)
209 if (!active_adapters) {
210 active_adapters = (int *) malloc(sizeof(int));
211 inumberadaptersactive = 1;
213 ++inumberadaptersactive;
214 active_adapters = (int *)realloc
216 sizeof(int)*inumberadaptersactive);
218 if (!active_adapters)
221 active_adapters[inumberadaptersactive-1] = iadapterindex;
226 /* Each Adapter has one temperature sensor and one fan */
227 return 2*inumberadaptersactive;
230 void amd_psensor_list_update(struct psensor **sensors)
232 struct psensor **ss, *s;
238 if (s->type & SENSOR_TYPE_ATIADL) {
239 if (s->type & SENSOR_TYPE_TEMP)
240 psensor_set_current_value(s, get_temp(s));
241 else if (s->type & SENSOR_TYPE_FAN)
242 psensor_set_current_value(s, get_fanspeed(s));
250 amd_psensor_list_add(struct psensor **sensors, int values_len)
253 struct psensor **tmp, **ss, *s;
258 for (i = 0; i < n; i++) {
259 s = create_sensor(i, values_len);
261 tmp = psensor_list_add(ss, s);
275 if (adl_main_control_done)
276 adl_main_control_destroy();
280 if (active_adapters) {
281 free(active_adapters);
282 active_adapters = NULL;