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