blob: 7f82a8ad20e4a9cbeb6e31eba5eefb64c3d2a6ce [file] [log] [blame]
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001/*
Aditya Bavanari29bcea22017-10-03 20:10:35 +05302 * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#define LOG_TAG "audio_hw_generic_effect"
31//#define LOG_NDEBUG 0
32#define LOG_NDDEBUG 0
33
34#include <errno.h>
35#include <math.h>
36#include <cutils/log.h>
37#include <fcntl.h>
38#include <dirent.h>
39#include "audio_hw.h"
40#include "platform.h"
41#include "platform_api.h"
42#include <sys/stat.h>
43#include <stdlib.h>
44#include <dlfcn.h>
45#include <math.h>
46#include <cutils/properties.h>
47#include "audio_extn.h"
48#include "audio_hw.h"
49
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053050#ifdef DYNAMIC_LOG_ENABLED
51#include <log_xml_parser.h>
52#define LOG_MASK HAL_MOD_FILE_GEF
53#include <log_utils.h>
54#endif
55
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080056#ifdef AUDIO_GENERIC_EFFECT_FRAMEWORK_ENABLED
57
Weiyin Jiang82e40942017-01-10 16:07:34 +080058#if LINUX_ENABLED
Manish Dewangan6a36d002017-10-09 14:11:00 +053059#define GEF_LIBRARY "libqtigef.so"
Weiyin Jiang82e40942017-01-10 16:07:34 +080060#else
David Ng06ccd872017-03-15 11:39:33 -070061#define GEF_LIBRARY "/vendor/lib/libqtigef.so"
Weiyin Jiang82e40942017-01-10 16:07:34 +080062#endif
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080063
64typedef void* (*gef_init_t)(void*);
Dhananjay Kumara427f142017-07-10 13:49:13 +053065typedef void (*gef_deinit_t)(void*);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080066typedef void (*gef_device_config_cb_t)(void*, audio_devices_t,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +080067 audio_channel_mask_t, int, int);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080068
69typedef struct {
70 void* handle;
71 void* gef_ptr;
72 gef_init_t init;
Dhananjay Kumara427f142017-07-10 13:49:13 +053073 gef_deinit_t deinit;
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080074 gef_device_config_cb_t device_config_cb;
75} gef_data;
76
77static gef_data gef_hal_handle;
78
79typedef enum {
80 ASM = 0,
81 ADM
82} gef_calibration_type;
83
84typedef enum {
85 AUDIO_DEVICE_CAL_TYPE = 0,
86 AUDIO_STREAM_CAL_TYPE,
87} acdb_device_type;
88
89
90static acdb_device_type make_acdb_device_type_from_gef_cal_type
91 (gef_calibration_type gef_cal_type)
92{
93 int acdb_device_type = 0;
94
95 switch (gef_cal_type) {
96 case ASM:
97 acdb_device_type = AUDIO_STREAM_CAL_TYPE;
98 break;
99 case ADM:
100 acdb_device_type = AUDIO_DEVICE_CAL_TYPE;
101 break;
102 default:
103 acdb_device_type = -1;
104 break;
105 }
106
107 return ((int)acdb_device_type);
108}
109
110void audio_extn_gef_init(struct audio_device *adev)
111{
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800112 const char* error = NULL;
113
114 ALOGV("%s: Enter with error", __func__);
115
116 memset(&gef_hal_handle, 0, sizeof(gef_data));
117
Satish Babu Patakokila38230962017-10-18 20:34:56 +0530118 //: check error for dlopen
119 gef_hal_handle.handle = dlopen(GEF_LIBRARY, RTLD_LAZY);
120 if (gef_hal_handle.handle == NULL) {
121 ALOGE("%s: DLOPEN failed for %s with error %s",
122 __func__, GEF_LIBRARY, dlerror());
123 goto ERROR_RETURN;
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800124 } else {
Satish Babu Patakokila38230962017-10-18 20:34:56 +0530125 ALOGV("%s: DLOPEN successful for %s", __func__, GEF_LIBRARY);
126
127 //call dlerror to clear the error
128 dlerror();
129 gef_hal_handle.init =
130 (gef_init_t)dlsym(gef_hal_handle.handle, "gef_init");
131 error = dlerror();
132
133 if(error != NULL) {
134 ALOGE("%s: dlsym of %s failed with error %s",
135 __func__, "gef_init", error);
136 goto ERROR_RETURN;
137 }
138
139 //call dlerror to clear the error
140 dlerror();
141 gef_hal_handle.deinit =
142 (gef_deinit_t)dlsym(gef_hal_handle.handle, "gef_deinit");
143 error = dlerror();
144
145 if(error != NULL) {
146 ALOGE("%s: dlsym of %s failed with error %s",
147 __func__, "gef_deinit", error);
148 goto ERROR_RETURN;
149 }
150
151 //call dlerror to clear the error
152 error = dlerror();
153 gef_hal_handle.device_config_cb =
154 (gef_device_config_cb_t)dlsym(gef_hal_handle.handle,
155 "gef_device_config_cb");
156 error = dlerror();
157
158 if(error != NULL) {
159 ALOGE("%s: dlsym of %s failed with error %s",
160 __func__, "gef_device_config_cb", error);
161 goto ERROR_RETURN;
162 }
163
164 gef_hal_handle.gef_ptr = gef_hal_handle.init((void*)adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800165 }
166
167ERROR_RETURN:
Satish Babu Patakokila38230962017-10-18 20:34:56 +0530168 ALOGV("%s: Exit with error ", __func__);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800169 return;
170}
171
172
Aditya Bavanari29bcea22017-10-03 20:10:35 +0530173#ifdef INSTANCE_ID_ENABLED
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800174//this will be called from GEF to exchange calibration using acdb
175int audio_extn_gef_send_audio_cal(void* dev, int acdb_dev_id,
176 int gef_cal_type, int app_type, int topology_id, int sample_rate,
Aditya Bavanari29bcea22017-10-03 20:10:35 +0530177 uint32_t module_id, uint16_t instance_id, uint32_t param_id,
178 void* data, int length, bool persist)
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800179{
180 int ret = 0;
181 struct audio_device *adev = (struct audio_device*)dev;
Aditya Bavanari29bcea22017-10-03 20:10:35 +0530182 acdb_audio_cal_cfg_t cal;
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800183 int acdb_device_type =
184 make_acdb_device_type_from_gef_cal_type(gef_cal_type);
185
186 ALOGV("%s: Enter", __func__);
Aditya Bavanari29bcea22017-10-03 20:10:35 +0530187 memset(&cal, 0, sizeof(acdb_audio_cal_cfg_t));
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800188
189 //lock adev
190 pthread_mutex_lock(&adev->lock);
191
Aditya Bavanari29bcea22017-10-03 20:10:35 +0530192 //pack cal
193 platform_make_cal_cfg(&cal, acdb_dev_id,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800194 acdb_device_type, app_type, topology_id, sample_rate,
Aditya Bavanari29bcea22017-10-03 20:10:35 +0530195 module_id, instance_id, param_id, true);
196
197 ret = platform_send_audio_cal(adev->platform, &cal, data, length, persist);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800198
199 pthread_mutex_unlock(&adev->lock);
200
201 ALOGV("%s: Exit with error %d", __func__, ret);
202
203 return ret;
204}
205
206//this will be called from GEF to exchange calibration using acdb
207int audio_extn_gef_get_audio_cal(void* dev, int acdb_dev_id,
208 int gef_cal_type, int app_type, int topology_id, int sample_rate,
Aditya Bavanari29bcea22017-10-03 20:10:35 +0530209 uint32_t module_id, uint16_t instance_id, uint32_t param_id,
210 void* data, int* length, bool persist)
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800211{
212 int ret = 0;
213 struct audio_device *adev = (struct audio_device*)dev;
Aditya Bavanari29bcea22017-10-03 20:10:35 +0530214 acdb_audio_cal_cfg_t cal;
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800215 int acdb_device_type =
216 make_acdb_device_type_from_gef_cal_type(gef_cal_type);
217
218 ALOGV("%s: Enter", __func__);
Aditya Bavanari29bcea22017-10-03 20:10:35 +0530219 memset(&cal, 0, sizeof(acdb_audio_cal_cfg_t));
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800220
221 //lock adev
222 pthread_mutex_lock(&adev->lock);
223
Aditya Bavanari29bcea22017-10-03 20:10:35 +0530224 //pack cal
225 platform_make_cal_cfg(&cal, acdb_dev_id,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800226 acdb_device_type, app_type, topology_id, sample_rate,
Aditya Bavanari29bcea22017-10-03 20:10:35 +0530227 module_id, instance_id, param_id, false);
228
229 ret = platform_get_audio_cal(adev->platform, &cal, data, length, persist);
230
231 pthread_mutex_unlock(&adev->lock);
232
233 ALOGV("%s: Exit with error %d", __func__, ret);
234
235 return ret;
236}
237
238//this will be called from GEF to store into acdb
239int audio_extn_gef_store_audio_cal(void* dev, int acdb_dev_id,
240 int gef_cal_type, int app_type, int topology_id, int sample_rate,
241 uint32_t module_id, uint16_t instance_id,
242 uint32_t param_id, void* data, int length)
243{
244 int ret = 0;
245 struct audio_device *adev = (struct audio_device*)dev;
246 acdb_audio_cal_cfg_t cal;
247 int acdb_device_type =
248 make_acdb_device_type_from_gef_cal_type(gef_cal_type);
249
250 ALOGV("%s: Enter", __func__);
251 memset(&cal, 0, sizeof(acdb_audio_cal_cfg_t));
252
253 //lock adev
254 pthread_mutex_lock(&adev->lock);
255
256 //pack cal
257 platform_make_cal_cfg(&cal, acdb_dev_id,
258 acdb_device_type, app_type, topology_id, sample_rate,
259 module_id, instance_id, param_id, true);
260
261 ret = platform_store_audio_cal(adev->platform, &cal, data, length);
262
263 pthread_mutex_unlock(&adev->lock);
264
265 ALOGV("%s: Exit with error %d", __func__, ret);
266
267 return ret;
268}
269
270//this will be called from GEF to retrieve calibration using acdb
271int audio_extn_gef_retrieve_audio_cal(void* dev, int acdb_dev_id,
272 int gef_cal_type, int app_type, int topology_id, int sample_rate,
273 uint32_t module_id, uint16_t instance_id, uint32_t param_id, void* data, int* length)
274{
275 int ret = 0;
276 struct audio_device *adev = (struct audio_device*)dev;
277 acdb_audio_cal_cfg_t cal;
278 int acdb_device_type =
279 make_acdb_device_type_from_gef_cal_type(gef_cal_type);
280
281 ALOGV("%s: Enter", __func__);
282 memset(&cal, 0, sizeof(acdb_audio_cal_cfg_t));
283
284 //lock adev
285 pthread_mutex_lock(&adev->lock);
286
287 //pack cal
288 platform_make_cal_cfg(&cal, acdb_dev_id,
289 acdb_device_type, app_type, topology_id, sample_rate,
290 module_id, instance_id, param_id, true);
291
292 ret = platform_retrieve_audio_cal(adev->platform, &cal, data, length);
293
294 pthread_mutex_unlock(&adev->lock);
295
296 ALOGV("%s: Exit with error %d", __func__, ret);
297
298 return ret;
299}
300#else
301//this will be called from GEF to exchange calibration using acdb
302int audio_extn_gef_send_audio_cal(void* dev, int acdb_dev_id,
303 int gef_cal_type, int app_type, int topology_id, int sample_rate,
304 uint32_t module_id, uint32_t param_id, void* data, int length,
305 bool persist)
306{
307 int ret = 0;
308 struct audio_device *adev = (struct audio_device*)dev;
309 acdb_audio_cal_cfg_t cal;
310 int acdb_device_type =
311 make_acdb_device_type_from_gef_cal_type(gef_cal_type);
312
313 ALOGV("%s: Enter", __func__);
314 memset(&cal, 0, sizeof(acdb_audio_cal_cfg_t));
315
316 //lock adev
317 pthread_mutex_lock(&adev->lock);
318
319 //pack cal
320 platform_make_cal_cfg(&cal, acdb_dev_id,
321 acdb_device_type, app_type, topology_id, sample_rate,
322 module_id, param_id, true);
323
324 ret = platform_send_audio_cal(adev->platform, &cal, data, length, persist);
325
326 pthread_mutex_unlock(&adev->lock);
327
328 ALOGV("%s: Exit with error %d", __func__, ret);
329
330 return ret;
331}
332
333//this will be called from GEF to exchange calibration using acdb
334int audio_extn_gef_get_audio_cal(void* dev, int acdb_dev_id,
335 int gef_cal_type, int app_type, int topology_id, int sample_rate,
336 uint32_t module_id, uint32_t param_id, void* data, int* length,
337 bool persist)
338{
339 int ret = 0;
340 struct audio_device *adev = (struct audio_device*)dev;
341 acdb_audio_cal_cfg_t cal;
342 int acdb_device_type =
343 make_acdb_device_type_from_gef_cal_type(gef_cal_type);
344
345 ALOGV("%s: Enter", __func__);
346 memset(&cal, 0, sizeof(acdb_audio_cal_cfg_t));
347
348 //lock adev
349 pthread_mutex_lock(&adev->lock);
350
351 //pack cal
352 platform_make_cal_cfg(&cal, acdb_dev_id,
353 acdb_device_type, app_type, topology_id, sample_rate,
354 module_id, param_id, false);
355
356 ret = platform_get_audio_cal(adev->platform, &cal, data, length, persist);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800357
358 pthread_mutex_unlock(&adev->lock);
359
360 ALOGV("%s: Exit with error %d", __func__, ret);
361
362 return ret;
363}
364
365//this will be called from GEF to store into acdb
366int audio_extn_gef_store_audio_cal(void* dev, int acdb_dev_id,
367 int gef_cal_type, int app_type, int topology_id, int sample_rate,
368 uint32_t module_id, uint32_t param_id, void* data, int length)
369{
370 int ret = 0;
371 struct audio_device *adev = (struct audio_device*)dev;
Aditya Bavanari29bcea22017-10-03 20:10:35 +0530372 acdb_audio_cal_cfg_t cal;
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800373 int acdb_device_type =
374 make_acdb_device_type_from_gef_cal_type(gef_cal_type);
375
376 ALOGV("%s: Enter", __func__);
Aditya Bavanari29bcea22017-10-03 20:10:35 +0530377 memset(&cal, 0, sizeof(acdb_audio_cal_cfg_t));
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800378
379 //lock adev
380 pthread_mutex_lock(&adev->lock);
381
Aditya Bavanari29bcea22017-10-03 20:10:35 +0530382 //pack cal
383 platform_make_cal_cfg(&cal, acdb_dev_id,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800384 acdb_device_type, app_type, topology_id, sample_rate,
Aditya Bavanari29bcea22017-10-03 20:10:35 +0530385 module_id, param_id, true);
386
387 ret = platform_store_audio_cal(adev->platform, &cal, data, length);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800388
389 pthread_mutex_unlock(&adev->lock);
390
391 ALOGV("%s: Exit with error %d", __func__, ret);
392
393 return ret;
394}
395
396//this will be called from GEF to retrieve calibration using acdb
397int audio_extn_gef_retrieve_audio_cal(void* dev, int acdb_dev_id,
398 int gef_cal_type, int app_type, int topology_id, int sample_rate,
399 uint32_t module_id, uint32_t param_id, void* data, int* length)
400{
401 int ret = 0;
402 struct audio_device *adev = (struct audio_device*)dev;
Aditya Bavanari29bcea22017-10-03 20:10:35 +0530403 acdb_audio_cal_cfg_t cal;
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800404 int acdb_device_type =
405 make_acdb_device_type_from_gef_cal_type(gef_cal_type);
406
407 ALOGV("%s: Enter", __func__);
Aditya Bavanari29bcea22017-10-03 20:10:35 +0530408 memset(&cal, 0, sizeof(acdb_audio_cal_cfg_t));
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800409
410 //lock adev
411 pthread_mutex_lock(&adev->lock);
412
Aditya Bavanari29bcea22017-10-03 20:10:35 +0530413 //pack cal
414 platform_make_cal_cfg(&cal, acdb_dev_id,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800415 acdb_device_type, app_type, topology_id, sample_rate,
Aditya Bavanari29bcea22017-10-03 20:10:35 +0530416 module_id, param_id, true);
417
418 ret = platform_retrieve_audio_cal(adev->platform, &cal, data, length);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800419
420 pthread_mutex_unlock(&adev->lock);
421
422 ALOGV("%s: Exit with error %d", __func__, ret);
423
424 return ret;
425}
Aditya Bavanari29bcea22017-10-03 20:10:35 +0530426#endif
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800427
428//this will be called from HAL to notify GEF of new device configuration
429void audio_extn_gef_notify_device_config(audio_devices_t audio_device,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +0800430 audio_channel_mask_t channel_mask, int sample_rate, int acdb_id)
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800431{
432 ALOGV("%s: Enter", __func__);
433
434 //call into GEF to share channel mask and device info
435 if (gef_hal_handle.handle && gef_hal_handle.device_config_cb) {
436 gef_hal_handle.device_config_cb(gef_hal_handle.gef_ptr, audio_device, channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +0800437 sample_rate, acdb_id);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800438 }
439
440 ALOGV("%s: Exit", __func__);
441
442 return;
443}
444
445void audio_extn_gef_deinit()
446{
447 ALOGV("%s: Enter", __func__);
448
449 if (gef_hal_handle.handle) {
Dhananjay Kumara427f142017-07-10 13:49:13 +0530450 if (gef_hal_handle.handle && gef_hal_handle.deinit)
451 gef_hal_handle.deinit(gef_hal_handle.gef_ptr);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800452 dlclose(gef_hal_handle.handle);
453 }
454
455 memset(&gef_hal_handle, 0, sizeof(gef_data));
456
457 ALOGV("%s: Exit", __func__);
458}
459
460#endif