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