blob: 19f9dfb42454a38fd13e15c15420f23220e66c35 [file] [log] [blame]
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001/*
Weiyin Jiang82e40942017-01-10 16:07:34 +08002 * Copyright (c) 2016-2017, 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
59#define GEF_LIBRARY "/usr/lib/libqtigef.so"
60#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*);
65typedef void (*gef_device_config_cb_t)(void*, audio_devices_t,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +080066 audio_channel_mask_t, int, int);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080067
68typedef struct {
69 void* handle;
70 void* gef_ptr;
71 gef_init_t init;
72 gef_device_config_cb_t device_config_cb;
73} gef_data;
74
75static gef_data gef_hal_handle;
76
77typedef enum {
78 ASM = 0,
79 ADM
80} gef_calibration_type;
81
82typedef enum {
83 AUDIO_DEVICE_CAL_TYPE = 0,
84 AUDIO_STREAM_CAL_TYPE,
85} acdb_device_type;
86
87
88static acdb_device_type make_acdb_device_type_from_gef_cal_type
89 (gef_calibration_type gef_cal_type)
90{
91 int acdb_device_type = 0;
92
93 switch (gef_cal_type) {
94 case ASM:
95 acdb_device_type = AUDIO_STREAM_CAL_TYPE;
96 break;
97 case ADM:
98 acdb_device_type = AUDIO_DEVICE_CAL_TYPE;
99 break;
100 default:
101 acdb_device_type = -1;
102 break;
103 }
104
105 return ((int)acdb_device_type);
106}
107
108void audio_extn_gef_init(struct audio_device *adev)
109{
110 int ret = 0;
111 const char* error = NULL;
112
113 ALOGV("%s: Enter with error", __func__);
114
115 memset(&gef_hal_handle, 0, sizeof(gef_data));
116
117 ret = access(GEF_LIBRARY, R_OK);
118 if (ret == 0) {
119 //: check error for dlopen
120 gef_hal_handle.handle = dlopen(GEF_LIBRARY, RTLD_LAZY);
121 if (gef_hal_handle.handle == NULL) {
122 ALOGE("%s: DLOPEN failed for %s with error %s",
123 __func__, GEF_LIBRARY, dlerror());
124 goto ERROR_RETURN;
125 } else {
126 ALOGV("%s: DLOPEN successful for %s", __func__, GEF_LIBRARY);
127
128 //call dlerror to clear the error
129 dlerror();
130 gef_hal_handle.init =
131 (gef_init_t)dlsym(gef_hal_handle.handle, "gef_init");
132 error = dlerror();
133
134 if(error != NULL) {
135 ALOGE("%s: dlsym of %s failed with error %s",
136 __func__, "gef_init", error);
137 goto ERROR_RETURN;
138 }
139
140 //call dlerror to clear the error
141 error = dlerror();
142 gef_hal_handle.device_config_cb =
143 (gef_device_config_cb_t)dlsym(gef_hal_handle.handle,
144 "gef_device_config_cb");
145 error = dlerror();
146
147 if(error != NULL) {
148 ALOGE("%s: dlsym of %s failed with error %s",
149 __func__, "gef_device_config_cb", error);
150 goto ERROR_RETURN;
151 }
152
153 gef_hal_handle.gef_ptr = gef_hal_handle.init((void*)adev);
154 }
155 } else {
156 ALOGE("%s: %s access failed", __func__, GEF_LIBRARY);
157 }
158
159ERROR_RETURN:
160 ALOGV("%s: Exit with error %d", __func__, ret);
161 return;
162}
163
164
165//this will be called from GEF to exchange calibration using acdb
166int audio_extn_gef_send_audio_cal(void* dev, int acdb_dev_id,
167 int gef_cal_type, int app_type, int topology_id, int sample_rate,
168 uint32_t module_id, uint32_t param_id, void* data, int length, bool persist)
169{
170 int ret = 0;
171 struct audio_device *adev = (struct audio_device*)dev;
172 int acdb_device_type =
173 make_acdb_device_type_from_gef_cal_type(gef_cal_type);
174
175 ALOGV("%s: Enter", __func__);
176
177 //lock adev
178 pthread_mutex_lock(&adev->lock);
179
180 //send cal
181 ret = platform_send_audio_cal(adev->platform, acdb_dev_id,
182 acdb_device_type, app_type, topology_id, sample_rate,
183 module_id, param_id, data, length, persist);
184
185 pthread_mutex_unlock(&adev->lock);
186
187 ALOGV("%s: Exit with error %d", __func__, ret);
188
189 return ret;
190}
191
192//this will be called from GEF to exchange calibration using acdb
193int audio_extn_gef_get_audio_cal(void* dev, int acdb_dev_id,
194 int gef_cal_type, int app_type, int topology_id, int sample_rate,
195 uint32_t module_id, uint32_t param_id, void* data, int* length, bool persist)
196{
197 int ret = 0;
198 struct audio_device *adev = (struct audio_device*)dev;
199 int acdb_device_type =
200 make_acdb_device_type_from_gef_cal_type(gef_cal_type);
201
202 ALOGV("%s: Enter", __func__);
203
204 //lock adev
205 pthread_mutex_lock(&adev->lock);
206
207 ret = platform_get_audio_cal(adev->platform, acdb_dev_id,
208 acdb_device_type, app_type, topology_id, sample_rate,
209 module_id, param_id, data, length, persist);
210
211 pthread_mutex_unlock(&adev->lock);
212
213 ALOGV("%s: Exit with error %d", __func__, ret);
214
215 return ret;
216}
217
218//this will be called from GEF to store into acdb
219int audio_extn_gef_store_audio_cal(void* dev, int acdb_dev_id,
220 int gef_cal_type, int app_type, int topology_id, int sample_rate,
221 uint32_t module_id, uint32_t param_id, void* data, int length)
222{
223 int ret = 0;
224 struct audio_device *adev = (struct audio_device*)dev;
225 int acdb_device_type =
226 make_acdb_device_type_from_gef_cal_type(gef_cal_type);
227
228 ALOGV("%s: Enter", __func__);
229
230 //lock adev
231 pthread_mutex_lock(&adev->lock);
232
233 ret = platform_store_audio_cal(adev->platform, acdb_dev_id,
234 acdb_device_type, app_type, topology_id, sample_rate,
235 module_id, param_id, data, length);
236
237 pthread_mutex_unlock(&adev->lock);
238
239 ALOGV("%s: Exit with error %d", __func__, ret);
240
241 return ret;
242}
243
244//this will be called from GEF to retrieve calibration using acdb
245int audio_extn_gef_retrieve_audio_cal(void* dev, int acdb_dev_id,
246 int gef_cal_type, int app_type, int topology_id, int sample_rate,
247 uint32_t module_id, uint32_t param_id, void* data, int* length)
248{
249 int ret = 0;
250 struct audio_device *adev = (struct audio_device*)dev;
251 int acdb_device_type =
252 make_acdb_device_type_from_gef_cal_type(gef_cal_type);
253
254 ALOGV("%s: Enter", __func__);
255
256 //lock adev
257 pthread_mutex_lock(&adev->lock);
258
259 ret = platform_retrieve_audio_cal(adev->platform, acdb_dev_id,
260 acdb_device_type, app_type, topology_id, sample_rate,
261 module_id, param_id, 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 HAL to notify GEF of new device configuration
271void audio_extn_gef_notify_device_config(audio_devices_t audio_device,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +0800272 audio_channel_mask_t channel_mask, int sample_rate, int acdb_id)
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800273{
274 ALOGV("%s: Enter", __func__);
275
276 //call into GEF to share channel mask and device info
277 if (gef_hal_handle.handle && gef_hal_handle.device_config_cb) {
278 gef_hal_handle.device_config_cb(gef_hal_handle.gef_ptr, audio_device, channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +0800279 sample_rate, acdb_id);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +0800280 }
281
282 ALOGV("%s: Exit", __func__);
283
284 return;
285}
286
287void audio_extn_gef_deinit()
288{
289 ALOGV("%s: Enter", __func__);
290
291 if (gef_hal_handle.handle) {
292 dlclose(gef_hal_handle.handle);
293 }
294
295 memset(&gef_hal_handle, 0, sizeof(gef_data));
296
297 ALOGV("%s: Exit", __func__);
298}
299
300#endif