blob: 2ae690624af5d1d106733b5663556b895ec63750 [file] [log] [blame]
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301/*
Josh Kirschc03f31d2019-01-15 11:50:53 -08002* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
Manish Dewanganb8c83a42016-09-23 15:10:48 +05303*
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 "qahw"
31/*#define LOG_NDEBUG 0*/
32#define LOG_NDDEBUG 0
33
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +053034#include <dlfcn.h>
Manish Dewanganb8c83a42016-09-23 15:10:48 +053035#include <utils/Log.h>
36#include <stdlib.h>
37#include <cutils/list.h>
Samyak Jain5deda9e2018-12-24 12:49:31 +053038#include <pthread.h>
Manish Dewanganb8c83a42016-09-23 15:10:48 +053039#include <hardware/audio.h>
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +053040#include <hardware/sound_trigger.h>
Sidipotu Ashok404f26d2017-10-10 22:27:51 +053041#include "qahw.h"
Manish Dewanganb8c83a42016-09-23 15:10:48 +053042
43#define NO_ERROR 0
44#define MAX_MODULE_NAME_LENGTH 100
45
46/*
47 * The current HAL API version.
Josh Kirschc03f31d2019-01-15 11:50:53 -080048 * version 1.0 has support for voice only in new stream based APIS
Manish Dewanganb8c83a42016-09-23 15:10:48 +053049 */
Josh Kirschc03f31d2019-01-15 11:50:53 -080050#ifdef QAHW_MODULE_API_VERSION_1_0
51#define QAHW_MODULE_API_VERSION_CURRENT QAHW_MODULE_API_VERSION_1_0
52#else
Manish Dewanganb8c83a42016-09-23 15:10:48 +053053#define QAHW_MODULE_API_VERSION_CURRENT QAHW_MODULE_API_VERSION_0_0
Josh Kirschc03f31d2019-01-15 11:50:53 -080054#endif
Manish Dewanganb8c83a42016-09-23 15:10:48 +053055
Naresh Tanniruee3499a2017-01-05 14:05:35 +053056
57typedef uint64_t (*qahwi_out_write_v2_t)(audio_stream_out_t *out, const void* buffer,
58 size_t bytes, int64_t* timestamp);
59
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +053060typedef int (*qahwi_get_param_data_t) (const audio_hw_device_t *,
61 qahw_param_id, qahw_param_payload *);
62
63typedef int (*qahwi_set_param_data_t) (audio_hw_device_t *,
64 qahw_param_id, qahw_param_payload *);
65
Manish Dewangan3ccdea52017-02-13 19:31:54 +053066typedef uint64_t (*qahwi_in_read_v2_t)(audio_stream_in_t *in, void* buffer,
67 size_t bytes, int64_t *timestamp);
68
Manish Dewangan46e07982018-12-13 18:18:59 +053069typedef int (*qahwi_in_stop_t)(audio_stream_in_t *in);
70
Manish Dewangan3ccdea52017-02-13 19:31:54 +053071typedef int (*qahwi_out_set_param_data_t)(struct audio_stream_out *out,
72 qahw_param_id param_id,
73 qahw_param_payload *payload);
74
75typedef int (*qahwi_out_get_param_data_t)(struct audio_stream_out *out,
76 qahw_param_id param_id,
77 qahw_param_payload *payload);
78
Trinath Thammishetty580f1de2018-09-28 12:43:24 +053079typedef int (*qahwi_loopback_set_param_data_t)(audio_patch_handle_t patch_handle,
Trinath Thammishetty15cd3402018-10-29 11:57:19 +053080 qahw_loopback_param_id param_id,
81 qahw_loopback_param_payload *payload);
Trinath Thammishetty580f1de2018-09-28 12:43:24 +053082
Manish Dewanganb8c83a42016-09-23 15:10:48 +053083typedef struct {
84 audio_hw_device_t *audio_device;
85 char module_name[MAX_MODULE_NAME_LENGTH];
86 struct listnode module_list;
87 struct listnode in_list;
88 struct listnode out_list;
89 pthread_mutex_t lock;
90 uint32_t ref_count;
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +053091 const hw_module_t* module;
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +053092 qahwi_get_param_data_t qahwi_get_param_data;
93 qahwi_set_param_data_t qahwi_set_param_data;
Trinath Thammishetty580f1de2018-09-28 12:43:24 +053094 qahwi_loopback_set_param_data_t qahwi_loopback_set_param_data;
Manish Dewanganb8c83a42016-09-23 15:10:48 +053095} qahw_module_t;
96
97typedef struct {
98 qahw_module_t *module;
99 struct listnode module_list;
100 pthread_mutex_t lock;
101} qahw_module_instances_t;
102
103typedef struct {
104 audio_stream_out_t *stream;
105 qahw_module_t *module;
106 struct listnode list;
107 pthread_mutex_t lock;
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530108 qahwi_out_set_param_data_t qahwi_out_get_param_data;
109 qahwi_out_get_param_data_t qahwi_out_set_param_data;
Naresh Tanniruee3499a2017-01-05 14:05:35 +0530110 qahwi_out_write_v2_t qahwi_out_write_v2;
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530111} qahw_stream_out_t;
112
113typedef struct {
114 audio_stream_in_t *stream;
115 qahw_module_t *module;
116 struct listnode list;
117 pthread_mutex_t lock;
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +0530118 qahwi_in_read_v2_t qahwi_in_read_v2;
Manish Dewangan46e07982018-12-13 18:18:59 +0530119 qahwi_in_stop_t qahwi_in_stop;
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530120} qahw_stream_in_t;
121
122typedef enum {
123 STREAM_DIR_IN,
124 STREAM_DIR_OUT,
125} qahw_stream_direction_t;
126
127static struct listnode qahw_module_list;
128static int qahw_list_count;
129static pthread_mutex_t qahw_module_init_lock = PTHREAD_MUTEX_INITIALIZER;
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +0530130sound_trigger_hw_device_t *st_hw_device = NULL;
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530131
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +0530132
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530133/** Start of internal functions */
134/******************************************************************************/
135
136/* call this function without anylock held */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530137static bool is_valid_qahw_stream_l(void *qahw_stream,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530138 qahw_stream_direction_t dir)
139{
140
141 int is_valid = false;
142 struct listnode *module_node = NULL;
143 struct listnode *stream_node = NULL;
144 struct listnode *list_node = NULL;
145 void *stream = NULL;
146 qahw_module_t *qahw_module = NULL;
147
148 if (qahw_stream == NULL) {
149 ALOGE("%s:: Invalid stream", __func__);
150 goto exit;
151 }
152
153 if ((dir != STREAM_DIR_OUT) && (dir != STREAM_DIR_IN)) {
154 ALOGE("%s:: Invalid stream direction %d", __func__, dir);
155 goto exit;
156 }
157
158 /* go through all the modules and check for valid stream */
159 pthread_mutex_lock(&qahw_module_init_lock);
160 list_for_each(module_node, &qahw_module_list) {
161 qahw_module = node_to_item(module_node, qahw_module_t, module_list);
162 pthread_mutex_lock(&qahw_module->lock);
163 if(dir == STREAM_DIR_OUT)
164 list_node = &qahw_module->out_list;
165 else
166 list_node = &qahw_module->in_list;
167 list_for_each(stream_node, list_node) {
168 if(dir == STREAM_DIR_OUT)
169 stream = (void *)node_to_item(stream_node,
170 qahw_stream_out_t,
171 list);
172 else
173 stream = (void *)node_to_item(stream_node,
174 qahw_stream_in_t,
175 list);
176 if(stream == qahw_stream) {
177 is_valid = true;
178 break;
179 }
180 }
181 pthread_mutex_unlock(&qahw_module->lock);
182 if(is_valid)
183 break;
184 }
185 pthread_mutex_unlock(&qahw_module_init_lock);
186
187exit:
188 return is_valid;
189}
190
191/* call this fucntion with ahw_module_init_lock held*/
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530192static qahw_module_t* get_qahw_module_by_ptr_l(qahw_module_t *qahw_module)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530193{
194 struct listnode *node = NULL;
195 qahw_module_t *module = NULL, *module_temp = NULL;
196
197 if (qahw_module == NULL)
198 goto exit;
199
200 list_for_each(node, &qahw_module_list) {
201 module_temp = node_to_item(node, qahw_module_t, module_list);
202 if (module_temp == qahw_module) {
203 module = module_temp;
204 break;
205 }
206 }
207exit:
208 return module;
209}
210
211/* call this function with qahw_module_init_lock held*/
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530212static qahw_module_t* get_qahw_module_by_name_l(const char *qahw_name)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530213{
214 struct listnode *node = NULL;
215 qahw_module_t *module = NULL, *module_temp = NULL;
216
217 if (qahw_name == NULL)
218 goto exit;
219
220 list_for_each(node, &qahw_module_list) {
221 module_temp = node_to_item(node, qahw_module_t, module_list);
222 if(!strncmp(qahw_name, module_temp->module_name, MAX_MODULE_NAME_LENGTH)) {
223 module = module_temp;
224 break;
225 }
226 }
227exit:
228 return module;
229}
230/* End of of internal functions */
231
232/*
233 * Return the sampling rate in Hz - eg. 44100.
234 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530235uint32_t qahw_out_get_sample_rate_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530236{
237 uint32_t rate = 0;
238 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
239 audio_stream_out_t *out = NULL;
240
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530241 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530242 ALOGV("%s::Invalid out handle %p", __func__, out_handle);
243 goto exit;
244 }
245
246 pthread_mutex_lock(&qahw_stream_out->lock);
247 out = qahw_stream_out->stream;
248 if (out->common.get_sample_rate)
249 rate = out->common.get_sample_rate(&out->common);
250 else
251 ALOGW("%s not supported", __func__);
252 pthread_mutex_unlock(&qahw_stream_out->lock);
253
254exit:
255 return rate;
256}
257
258/*
259 * currently unused - use set_parameters with key
260 * AUDIO_PARAMETER_STREAM_SAMPLING_RATE
261 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530262int qahw_out_set_sample_rate_l(qahw_stream_handle_t *out_handle, uint32_t rate)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530263{
264 int32_t rc = -EINVAL;
265 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
266 audio_stream_out_t *out = NULL;
267
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530268 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530269 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
270 goto exit;
271 }
272 pthread_mutex_lock(&qahw_stream_out->lock);
273 out = qahw_stream_out->stream;
274 if (out->common.set_sample_rate) {
275 rc = out->common.set_sample_rate(&out->common, rate);
276 } else {
277 rc = -ENOSYS;
278 ALOGW("%s not supported", __func__);
279 }
280 pthread_mutex_unlock(&qahw_stream_out->lock);
281exit:
282 return rc;
283}
284
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530285size_t qahw_out_get_buffer_size_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530286{
287 size_t buf_size = 0;
288 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
289 audio_stream_out_t *out = NULL;
290
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530291 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530292 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
293 goto exit;
294 }
295 pthread_mutex_lock(&qahw_stream_out->lock);
296 out = qahw_stream_out->stream;
297 if (out->common.get_buffer_size) {
298 buf_size = out->common.get_buffer_size(&out->common);
299 } else {
300 ALOGW("%s not supported", __func__);
301 }
302 pthread_mutex_unlock(&qahw_stream_out->lock);
303
304exit:
305 return buf_size;
306}
307
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530308audio_channel_mask_t qahw_out_get_channels_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530309{
310 audio_channel_mask_t ch_mask = 0;
311 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
312 audio_stream_out_t *out = NULL;
313
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530314 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530315 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
316 goto exit;
317 }
318 pthread_mutex_lock(&qahw_stream_out->lock);
319 out = qahw_stream_out->stream;
320 if (out->common.get_channels) {
321 ch_mask = out->common.get_channels(&out->common);
322 } else {
323 ALOGW("%s not supported", __func__);
324 }
325 pthread_mutex_unlock(&qahw_stream_out->lock);
326
327exit:
328 return ch_mask;
329}
330
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530331audio_format_t qahw_out_get_format_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530332{
333 audio_format_t format = AUDIO_FORMAT_INVALID;
334 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
335 audio_stream_out_t *out = NULL;
336
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530337 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530338 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
339 goto exit;
340 }
341 pthread_mutex_lock(&qahw_stream_out->lock);
342 out = qahw_stream_out->stream;
343 if (out->common.get_format) {
344 format = out->common.get_format(&out->common);
345 } else {
346 ALOGW("%s not supported", __func__);
347 }
348 pthread_mutex_unlock(&qahw_stream_out->lock);
349
350exit:
351 return format;
352}
353
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530354int qahw_out_standby_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530355{
356 int32_t rc = -EINVAL;
357 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
358 audio_stream_out_t *out = NULL;
359
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530360 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530361 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
362 goto exit;
363 }
364
365 pthread_mutex_lock(&qahw_stream_out->lock);
366 out = qahw_stream_out->stream;
367 if (out->common.standby) {
368 rc = out->common.standby(&out->common);
369 } else {
370 rc = -ENOSYS;
371 ALOGW("%s not supported", __func__);
372 }
373 pthread_mutex_unlock(&qahw_stream_out->lock);
374
375exit:
376 return rc;
377}
378
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530379int qahw_out_set_parameters_l(qahw_stream_handle_t *out_handle, const char *kv_pairs)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530380{
381 int rc = NO_ERROR;
382 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
383 audio_stream_out_t *out = NULL;
384
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530385 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530386 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
387 rc = -EINVAL;
388 goto exit;
389 }
390
391 pthread_mutex_lock(&qahw_stream_out->lock);
392 out = qahw_stream_out->stream;
393 if (out->common.set_parameters) {
394 rc = out->common.set_parameters(&out->common, kv_pairs);
395 } else {
396 rc = -ENOSYS;
397 ALOGW("%s not supported", __func__);
398 }
399 pthread_mutex_unlock(&qahw_stream_out->lock);
400
401exit:
402 return rc;
403}
404
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530405char *qahw_out_get_parameters_l(const qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530406 const char *keys)
407{
408 char *str_param = NULL;
409 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
410 audio_stream_out_t *out = NULL;
411
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530412 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530413 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
414 goto exit;
415 }
416
417 pthread_mutex_lock(&qahw_stream_out->lock);
418 out = qahw_stream_out->stream;
419 if (out->common.get_parameters) {
420 str_param = out->common.get_parameters(&out->common, keys);
421 } else {
422 ALOGW("%s not supported", __func__);
423 }
424 pthread_mutex_unlock(&qahw_stream_out->lock);
425
426exit:
427 return str_param;
428}
429
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530430/* API to get playback stream specific config parameters */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530431int qahw_out_set_param_data_l(qahw_stream_handle_t *out_handle,
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530432 qahw_param_id param_id,
433 qahw_param_payload *payload)
434{
435 int rc = -EINVAL;
436 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
437 audio_stream_out_t *out = NULL;
438
439 if (!payload) {
440 ALOGE("%s::Invalid param", __func__);
441 goto exit;
442 }
443
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530444 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530445 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
446 goto exit;
447 }
448
449 pthread_mutex_lock(&qahw_stream_out->lock);
450 out = qahw_stream_out->stream;
451 if (qahw_stream_out->qahwi_out_set_param_data) {
452 rc = qahw_stream_out->qahwi_out_set_param_data(out, param_id, payload);
453 } else {
454 rc = -ENOSYS;
455 ALOGW("%s not supported", __func__);
456 }
457 pthread_mutex_unlock(&qahw_stream_out->lock);
458
459exit:
460 return rc;
461}
462
463/* API to get playback stream specific config parameters */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530464int qahw_out_get_param_data_l(qahw_stream_handle_t *out_handle,
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530465 qahw_param_id param_id,
466 qahw_param_payload *payload)
467{
468 int rc = -EINVAL;
469 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
470 audio_stream_out_t *out = NULL;
471
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530472 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530473 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
474 goto exit;
475 }
476
477 pthread_mutex_lock(&qahw_stream_out->lock);
478 out = qahw_stream_out->stream;
479 if (qahw_stream_out->qahwi_out_get_param_data) {
480 rc = qahw_stream_out->qahwi_out_get_param_data(out, param_id, payload);
481 } else {
482 rc = -ENOSYS;
483 ALOGW("%s not supported", __func__);
484 }
485 pthread_mutex_unlock(&qahw_stream_out->lock);
486
487exit:
488 return rc;
489}
490
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530491uint32_t qahw_out_get_latency_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530492{
493 uint32_t latency = 0;
494 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
495 audio_stream_out_t *out = NULL;
496
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530497 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530498 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
499 goto exit;
500 }
501
502 pthread_mutex_lock(&qahw_stream_out->lock);
503 out = qahw_stream_out->stream;
504 if (out->get_latency) {
505 latency = out->get_latency(out);
506 } else {
507 ALOGW("%s not supported", __func__);
508 }
509 pthread_mutex_unlock(&qahw_stream_out->lock);
510
511exit:
512 return latency;
513}
514
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530515int qahw_out_set_volume_l(qahw_stream_handle_t *out_handle, float left, float right)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530516{
517 int rc = -EINVAL;
518 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
519 audio_stream_out_t *out = NULL;
520
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530521 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530522 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
523 goto exit;
524 }
525
526 pthread_mutex_lock(&qahw_stream_out->lock);
527 out = qahw_stream_out->stream;
528 if (out->set_volume) {
529 rc = out->set_volume(out, left, right);
530 } else {
531 rc = -ENOSYS;
532 ALOGW("%s not supported", __func__);
533 }
534 pthread_mutex_unlock(&qahw_stream_out->lock);
535
536exit:
537 return rc;
538}
539
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530540ssize_t qahw_out_write_l(qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530541 qahw_out_buffer_t *out_buf)
542{
543 int rc = -EINVAL;
544 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
545 audio_stream_out_t *out = NULL;
546
547 if ((out_buf == NULL) || (out_buf->buffer == NULL)) {
548 ALOGE("%s::Invalid meta data %p", __func__, out_buf);
549 goto exit;
550 }
551
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530552 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530553 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
554 goto exit;
555 }
556
557 /*TBD:: validate other meta data parameters */
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530558 pthread_mutex_lock(&qahw_stream_out->lock);
559 out = qahw_stream_out->stream;
Naresh Tanniruee3499a2017-01-05 14:05:35 +0530560 if (qahw_stream_out->qahwi_out_write_v2) {
561 rc = qahw_stream_out->qahwi_out_write_v2(out, out_buf->buffer,
562 out_buf->bytes, out_buf->timestamp);
563 out_buf->offset = 0;
564 } else if (out->write) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530565 rc = out->write(out, out_buf->buffer, out_buf->bytes);
566 } else {
567 rc = -ENOSYS;
568 ALOGW("%s not supported", __func__);
569 }
570 pthread_mutex_unlock(&qahw_stream_out->lock);
571exit:
572 return rc;
573}
574
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530575int qahw_out_get_render_position_l(const qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530576 uint32_t *dsp_frames)
577{
578 int rc = -EINVAL;
579 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
580 audio_stream_out_t *out = NULL;
581
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530582 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530583 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
584 goto exit;
585 }
586
587 pthread_mutex_lock(&qahw_stream_out->lock);
588 out = qahw_stream_out->stream;
589 if (out->get_render_position) {
590 rc = out->get_render_position(out, dsp_frames);
591 } else {
592 rc = -ENOSYS;
593 ALOGW("%s not supported", __func__);
594 }
595 pthread_mutex_unlock(&qahw_stream_out->lock);
596exit:
597 return rc;
598}
599
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530600int qahw_out_set_callback_l(qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530601 qahw_stream_callback_t callback,
602 void *cookie)
603{
604 /*TBD:load hal func pointer and call */
605 int rc = -EINVAL;
606 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
607 audio_stream_out_t *out = NULL;
608
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530609 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530610 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
611 goto exit;
612 }
613
614 pthread_mutex_lock(&qahw_stream_out->lock);
615 out = qahw_stream_out->stream;
616 if (out->set_callback) {
617 rc = out->set_callback(out, (stream_callback_t)callback, cookie);
618 } else {
619 rc = -ENOSYS;
620 ALOGW("%s not supported", __func__);
621 }
622 pthread_mutex_unlock(&qahw_stream_out->lock);
623
624exit:
625 return rc;
626}
627
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530628int qahw_out_pause_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530629{
630 /*TBD:load hal func pointer and call */
631 int rc = -EINVAL;
632 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
633 audio_stream_out_t *out = NULL;
634
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530635 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530636 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
637 goto exit;
638 }
639
640 pthread_mutex_lock(&qahw_stream_out->lock);
641 out = qahw_stream_out->stream;
642 if (out->pause) {
643 rc = out->pause(out);
644 } else {
645 rc = -ENOSYS;
646 ALOGW("%s not supported", __func__);
647 }
648 pthread_mutex_unlock(&qahw_stream_out->lock);
649
650exit:
651 return rc;
652}
653
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530654int qahw_out_resume_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530655{
656 /*TBD:load hal func pointer and call */
657 int rc = -EINVAL;
658 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
659 audio_stream_out_t *out = NULL;
660
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530661 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530662 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
663 goto exit;
664 }
665
666 pthread_mutex_lock(&qahw_stream_out->lock);
667 out = qahw_stream_out->stream;
668 if (out->resume) {
669 rc = out->resume(out);
670 } else {
671 rc = -ENOSYS;
672 ALOGW("%s not supported", __func__);
673 }
674 pthread_mutex_unlock(&qahw_stream_out->lock);
675
676exit:
677 return rc;
678}
679
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530680int qahw_out_drain_l(qahw_stream_handle_t *out_handle, qahw_drain_type_t type )
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530681{
682 /*TBD:load hal func pointer and call */
683 int rc = -EINVAL;
684 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
685 audio_stream_out_t *out = NULL;
686
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530687 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530688 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
689 goto exit;
690 }
691
692 pthread_mutex_lock(&qahw_stream_out->lock);
693 out = qahw_stream_out->stream;
694 if (out->drain) {
695 rc = out->drain(out,(audio_drain_type_t)type);
696 } else {
697 rc = -ENOSYS;
698 ALOGW("%s not supported", __func__);
699 }
700 pthread_mutex_unlock(&qahw_stream_out->lock);
701
702exit:
703 return rc;
704}
705
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530706int qahw_out_flush_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530707{
708 int rc = -EINVAL;
709 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
710 audio_stream_out_t *out = NULL;
711
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530712 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530713 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
714 goto exit;
715 }
716
717 pthread_mutex_lock(&qahw_stream_out->lock);
718 out = qahw_stream_out->stream;
719 if (out->flush) {
720 rc = out->flush(out);
721 } else {
722 rc = -ENOSYS;
723 ALOGW("%s not supported", __func__);
724 }
725 pthread_mutex_unlock(&qahw_stream_out->lock);
726
727exit:
728 return rc;
729}
730
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530731int qahw_out_get_presentation_position_l(const qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530732 uint64_t *frames, struct timespec *timestamp)
733{
734 int rc = -EINVAL;
735 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
736 audio_stream_out_t *out = NULL;
737
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530738 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530739 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
740 goto exit;
741 }
742
743 pthread_mutex_lock(&qahw_stream_out->lock);
744 out = qahw_stream_out->stream;
745 if (out->get_presentation_position) {
746 rc = out->get_presentation_position(out, frames, timestamp);
747 } else {
748 rc = -ENOSYS;
749 ALOGW("%s not supported", __func__);
750 }
751 pthread_mutex_unlock(&qahw_stream_out->lock);
752
753exit:
754 return rc;
755}
756
757/* Input stream specific APIs */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530758uint32_t qahw_in_get_sample_rate_l(const qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530759{
760 uint32_t rate = 0;
761 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
762 audio_stream_in_t *in = NULL;
763
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530764 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530765 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
766 goto exit;
767 }
768
769 pthread_mutex_lock(&qahw_stream_in->lock);
770 in = qahw_stream_in->stream;
771 if (in->common.get_sample_rate) {
772 rate = in->common.get_sample_rate(&in->common);
773 } else {
774 ALOGW("%s not supported", __func__);
775 }
776 pthread_mutex_unlock(&qahw_stream_in->lock);
777
778exit:
779 return rate;
780}
781
782/*
783 * currently unused - use set_parameters with key
784 * AUDIO_PARAMETER_STREAM_SAMPLING_RATE
785 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530786int qahw_in_set_sample_rate_l(qahw_stream_handle_t *in_handle, uint32_t rate)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530787{
788 int rc = -EINVAL;
789 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
790 audio_stream_in_t *in = NULL;
791
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530792 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530793 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
794 goto exit;
795 }
796
797 pthread_mutex_lock(&qahw_stream_in->lock);
798 in = qahw_stream_in->stream;
799 if (in->common.set_sample_rate) {
800 rc = in->common.set_sample_rate(&in->common, rate);
801 } else {
802 rc = -ENOSYS;
803 ALOGW("%s not supported", __func__);
804 }
805 pthread_mutex_unlock(&qahw_stream_in->lock);
806
807exit:
808 return rc;
809}
810
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530811size_t qahw_in_get_buffer_size_l(const qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530812{
813 size_t buf_size = 0;
814 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
815 audio_stream_in_t *in = NULL;
816
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530817 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530818 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
819 goto exit;
820 }
821
822 pthread_mutex_lock(&qahw_stream_in->lock);
823 in = qahw_stream_in->stream;
824 if (in->common.get_sample_rate) {
825 buf_size = in->common.get_buffer_size(&in->common);
826 } else {
827 ALOGW("%s not supported", __func__);
828 }
829 pthread_mutex_unlock(&qahw_stream_in->lock);
830
831exit:
832 return buf_size;
833}
834
835
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530836audio_channel_mask_t qahw_in_get_channels_l(const qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530837{
838 audio_channel_mask_t ch_mask = 0;;
839 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
840 audio_stream_in_t *in = NULL;
841
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530842 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530843 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
844 goto exit;
845 }
846
847 pthread_mutex_lock(&qahw_stream_in->lock);
848 in = qahw_stream_in->stream;
849 if (in->common.get_channels) {
850 ch_mask = in->common.get_channels(&in->common);
851 } else {
852 ALOGW("%s not supported", __func__);
853 }
854 pthread_mutex_unlock(&qahw_stream_in->lock);
855
856exit:
857 return ch_mask;
858}
859
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530860audio_format_t qahw_in_get_format_l(const qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530861{
862 audio_format_t format = AUDIO_FORMAT_INVALID;
863 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
864 audio_stream_in_t *in = NULL;
865
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530866 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530867 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
868 goto exit;
869 }
870
871 pthread_mutex_lock(&qahw_stream_in->lock);
872 in = qahw_stream_in->stream;
873 if (in->common.get_format) {
874 format = in->common.get_format(&in->common);
875 } else {
876 ALOGW("%s not supported", __func__);
877 }
878 pthread_mutex_unlock(&qahw_stream_in->lock);
879
880exit:
881 return format;
882}
883
884/*
885 * currently unused - use set_parameters with key
886 * AUDIO_PARAMETER_STREAM_FORMAT
887 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530888int qahw_in_set_format_l(qahw_stream_handle_t *in_handle, audio_format_t format)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530889{
890 int rc = -EINVAL;
891 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
892 audio_stream_in_t *in = NULL;
893
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530894 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530895 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
896 goto exit;
897 }
898
899 pthread_mutex_lock(&qahw_stream_in->lock);
900 in = qahw_stream_in->stream;
901 if (in->common.set_format) {
902 rc = in->common.set_format(&in->common, format);
903 } else {
904 rc = -ENOSYS;
905 ALOGW("%s not supported", __func__);
906 }
907 pthread_mutex_unlock(&qahw_stream_in->lock);
908
909exit:
910 return rc;
911}
912
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530913int qahw_in_standby_l(qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530914{
915 int rc = -EINVAL;
916 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
917 audio_stream_in_t *in = NULL;
918
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530919 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530920 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
921 goto exit;
922 }
923
924 pthread_mutex_lock(&qahw_stream_in->lock);
925 in = qahw_stream_in->stream;
926 if (in->common.standby) {
927 rc = in->common.standby(&in->common);
928 } else {
929 rc = -ENOSYS;
930 ALOGW("%s not supported", __func__);
931 }
932 pthread_mutex_unlock(&qahw_stream_in->lock);
933
934exit:
935 return rc;
936}
937
938/*
939 * set/get audio stream parameters. The function accepts a list of
940 * parameter key value pairs in the form: key1=value1;key2=value2;...
941 *
942 * Some keys are reserved for standard parameters (See AudioParameter class)
943 *
944 * If the implementation does not accept a parameter change while
945 * the output is active but the parameter is acceptable otherwise, it must
946 * return -ENOSYS.
947 *
948 * The audio flinger will put the stream in standby and then change the
949 * parameter value.
950 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530951int qahw_in_set_parameters_l(qahw_stream_handle_t *in_handle, const char *kv_pairs)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530952{
953 int rc = -EINVAL;
954 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
955 audio_stream_in_t *in = NULL;
956
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530957 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530958 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
959 goto exit;
960 }
961
962 pthread_mutex_lock(&qahw_stream_in->lock);
963 in = qahw_stream_in->stream;
964 if (in->common.set_parameters) {
965 rc = in->common.set_parameters(&in->common, kv_pairs);
966 } else {
967 rc = -ENOSYS;
968 ALOGW("%s not supported", __func__);
969 }
970 pthread_mutex_unlock(&qahw_stream_in->lock);
971exit:
972 return rc;
973}
974
975/*
976 * Returns a pointer to a heap allocated string. The caller is responsible
977 * for freeing the memory for it using free().
978 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530979char * qahw_in_get_parameters_l(const qahw_stream_handle_t *in_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530980 const char *keys)
981{
982 char *str_param = NULL;
983 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
984 audio_stream_in_t *in = NULL;
985
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530986 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530987 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
988 goto exit;
989 }
990
991 pthread_mutex_lock(&qahw_stream_in->lock);
992 in = qahw_stream_in->stream;
993 if (in->common.get_parameters) {
994 str_param = in->common.get_parameters(&in->common, keys);
995 } else {
996 ALOGW("%s not supported", __func__);
997 }
998 pthread_mutex_unlock(&qahw_stream_in->lock);
999
1000exit:
1001 return str_param;
1002}
1003
1004/*
1005 * Read audio buffer in from audio driver. Returns number of bytes read, or a
1006 * negative status_t. If at least one frame was read prior to the error,
1007 * read should return that byte count and then return an error in the subsequent call.
1008 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301009ssize_t qahw_in_read_l(qahw_stream_handle_t *in_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301010 qahw_in_buffer_t *in_buf)
1011{
1012 int rc = -EINVAL;
1013 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
1014 audio_stream_in_t *in = NULL;
1015
1016 if ((in_buf == NULL) || (in_buf->buffer == NULL)) {
1017 ALOGE("%s::Invalid meta data %p", __func__, in_buf);
1018 goto exit;
1019 }
1020
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301021 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301022 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
1023 goto exit;
1024 }
1025
1026 pthread_mutex_lock(&qahw_stream_in->lock);
1027 in = qahw_stream_in->stream;
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05301028 if (qahw_stream_in->qahwi_in_read_v2) {
1029 rc = qahw_stream_in->qahwi_in_read_v2(in, in_buf->buffer,
1030 in_buf->bytes, in_buf->timestamp);
1031 in_buf->offset = 0;
1032 } else if (in->read) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301033 rc = in->read(in, in_buf->buffer, in_buf->bytes);
1034 in_buf->offset = 0;
1035 } else {
1036 rc = -ENOSYS;
1037 ALOGW("%s not supported", __func__);
1038 }
1039 pthread_mutex_unlock(&qahw_stream_in->lock);
1040
1041exit:
1042 return rc;
1043}
1044
1045/*
Manish Dewangan46e07982018-12-13 18:18:59 +05301046 * Stop input stream. Returns zero on success.
1047 */
1048int qahw_in_stop_l(qahw_stream_handle_t *in_handle)
1049{
1050 int rc = -EINVAL;
1051 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
1052 audio_stream_in_t *in = NULL;
1053
1054 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
1055 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
1056 goto exit;
1057 }
1058 ALOGD("%s", __func__);
1059
1060 in = qahw_stream_in->stream;
1061
1062 if (qahw_stream_in->qahwi_in_stop)
1063 rc = qahw_stream_in->qahwi_in_stop(in);
1064 ALOGD("%s: exit", __func__);
1065
1066exit:
1067 return rc;
1068}
1069
1070/*
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301071 * Return the amount of input frames lost in the audio driver since the
1072 * last call of this function.
1073 * Audio driver is expected to reset the value to 0 and restart counting
1074 * upon returning the current value by this function call.
1075 * Such loss typically occurs when the user space process is blocked
1076 * longer than the capacity of audio driver buffers.
1077 *
1078 * Unit: the number of input audio frames
1079 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301080uint32_t qahw_in_get_input_frames_lost_l(qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301081{
1082 uint32_t rc = 0;
1083 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
1084 audio_stream_in_t *in = NULL;
1085
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301086 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301087 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
1088 goto exit;
1089 }
1090
1091 pthread_mutex_lock(&qahw_stream_in->lock);
1092 in = qahw_stream_in->stream;
1093 if (in->get_input_frames_lost) {
1094 rc = in->get_input_frames_lost(in);
1095 } else {
1096 rc = -ENOSYS;
1097 ALOGW("%s not supported", __func__);
1098 }
1099 pthread_mutex_unlock(&qahw_stream_in->lock);
1100
1101exit:
1102 return rc;
1103}
1104
1105/*
1106 * Return a recent count of the number of audio frames received and
1107 * the clock time associated with that frame count.
1108 *
1109 * frames is the total frame count received. This should be as early in
1110 * the capture pipeline as possible. In general,
1111 * frames should be non-negative and should not go "backwards".
1112 *
1113 * time is the clock MONOTONIC time when frames was measured. In general,
1114 * time should be a positive quantity and should not go "backwards".
1115 *
1116 * The status returned is 0 on success, -ENOSYS if the device is not
1117 * ready/available, or -EINVAL if the arguments are null or otherwise invalid.
1118 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301119int qahw_in_get_capture_position_l(const qahw_stream_handle_t *in_handle __unused,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301120 int64_t *frames __unused, int64_t *time __unused)
1121{
1122 /*TBD:: do we need this*/
1123 return -ENOSYS;
1124}
1125
1126/*
1127 * check to see if the audio hardware interface has been initialized.
1128 * returns 0 on success, -ENODEV on failure.
1129 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301130int qahw_init_check_l(const qahw_module_handle_t *hw_module)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301131{
1132 int rc = -EINVAL;
1133 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1134 qahw_module_t *qahw_module_temp;
1135
1136 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301137 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301138 pthread_mutex_unlock(&qahw_module_init_lock);
1139 if (qahw_module_temp == NULL) {
1140 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1141 goto exit;
1142 }
1143
1144 pthread_mutex_lock(&qahw_module->lock);
1145 if (qahw_module->audio_device->init_check) {
1146 rc = qahw_module->audio_device->init_check(qahw_module->audio_device);
1147 } else {
1148 rc = -ENOSYS;
1149 ALOGW("%s not supported", __func__);
1150 }
1151 pthread_mutex_unlock(&qahw_module->lock);
1152
1153exit:
1154 return rc;
1155}
1156/* set the audio volume of a voice call. Range is between 0.0 and 1.0 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301157int qahw_set_voice_volume_l(qahw_module_handle_t *hw_module, float volume)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301158{
1159 int rc = -EINVAL;
1160 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1161 qahw_module_t *qahw_module_temp;
1162
1163 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301164 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301165 pthread_mutex_unlock(&qahw_module_init_lock);
1166 if (qahw_module_temp == NULL) {
1167 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1168 goto exit;
1169 }
1170
1171 pthread_mutex_lock(&qahw_module->lock);
1172 if (qahw_module->audio_device->set_voice_volume) {
1173 rc = qahw_module->audio_device->set_voice_volume(qahw_module->audio_device,
1174 volume);
1175 } else {
1176 rc = -ENOSYS;
1177 ALOGW("%s not supported", __func__);
1178 }
1179 pthread_mutex_unlock(&qahw_module->lock);
1180
1181exit:
1182 return rc;
1183}
1184
1185/*
1186 * set_mode is called when the audio mode changes. AUDIO_MODE_NORMAL mode
1187 * is for standard audio playback, AUDIO_MODE_RINGTONE when a ringtone is
1188 * playing, and AUDIO_MODE_IN_CALL when a call is in progress.
1189 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301190int qahw_set_mode_l(qahw_module_handle_t *hw_module, audio_mode_t mode)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301191{
1192 int rc = -EINVAL;
1193 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1194 qahw_module_t *qahw_module_temp;
1195
1196 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301197 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301198 pthread_mutex_unlock(&qahw_module_init_lock);
1199 if (qahw_module_temp == NULL) {
1200 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1201 goto exit;
1202 }
1203
1204 pthread_mutex_lock(&qahw_module->lock);
1205 if (qahw_module->audio_device->set_mode) {
1206 rc = qahw_module->audio_device->set_mode(qahw_module->audio_device,
1207 mode);
1208 } else {
1209 rc = -ENOSYS;
1210 ALOGW("%s not supported", __func__);
1211 }
1212 pthread_mutex_unlock(&qahw_module->lock);
1213
1214exit:
1215 return rc;
1216}
1217
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301218int qahw_set_mic_mute_l(qahw_module_handle_t *hw_module, bool state)
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301219{
1220 int rc = -EINVAL;
1221 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1222 qahw_module_t *qahw_module_temp;
1223
1224 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301225 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301226 pthread_mutex_unlock(&qahw_module_init_lock);
1227 if (qahw_module_temp == NULL) {
1228 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1229 goto exit;
1230 }
1231
1232 pthread_mutex_lock(&qahw_module->lock);
1233 if (qahw_module->audio_device->set_mic_mute) {
1234 rc = qahw_module->audio_device->set_mic_mute(qahw_module->audio_device,
1235 state);
1236 } else {
1237 rc = -ENOSYS;
1238 ALOGW("%s not supported", __func__);
1239 }
1240 pthread_mutex_unlock(&qahw_module->lock);
1241
1242exit:
1243 return rc;
1244}
1245
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301246int qahw_get_mic_mute_l(qahw_module_handle_t *hw_module, bool *state)
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301247{
1248 size_t rc = 0;
1249 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1250 qahw_module_t *qahw_module_temp;
1251 audio_hw_device_t *audio_device;
1252
1253 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301254 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301255 pthread_mutex_unlock(&qahw_module_init_lock);
1256 if (qahw_module_temp == NULL) {
1257 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1258 goto exit;
1259 }
1260
1261 pthread_mutex_lock(&qahw_module->lock);
1262 audio_device = qahw_module->audio_device;
1263 if (qahw_module->audio_device->get_mic_mute) {
Dhananjay Kumar23a3bec2017-01-11 18:38:09 +05301264 rc = audio_device->get_mic_mute(qahw_module->audio_device, state);
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301265 } else {
1266 rc = -ENOSYS;
1267 ALOGW("%s not supported", __func__);
1268 }
1269 pthread_mutex_unlock(&qahw_module->lock);
1270
1271exit:
1272 return rc;
1273}
1274
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301275/* set/get global audio parameters */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301276int qahw_set_parameters_l(qahw_module_handle_t *hw_module, const char *kv_pairs)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301277{
1278 int rc = -EINVAL;
1279 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1280 qahw_module_t *qahw_module_temp;
1281 audio_hw_device_t *audio_device;
1282
1283 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301284 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301285 pthread_mutex_unlock(&qahw_module_init_lock);
1286 if (qahw_module_temp == NULL) {
1287 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1288 goto exit;
1289 }
1290
1291 pthread_mutex_lock(&qahw_module->lock);
1292 audio_device = qahw_module->audio_device;
1293 if (qahw_module->audio_device->set_parameters) {
1294 rc = audio_device->set_parameters(qahw_module->audio_device, kv_pairs);
1295 } else {
1296 rc = -ENOSYS;
1297 ALOGW("%s not supported", __func__);
1298 }
1299 pthread_mutex_unlock(&qahw_module->lock);
1300
1301exit:
1302 return rc;
1303}
1304
1305/*
1306 * Returns a pointer to a heap allocated string. The caller is responsible
1307 * for freeing the memory for it using free().
1308 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301309char * qahw_get_parameters_l(const qahw_module_handle_t *hw_module,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301310 const char *keys)
1311{
1312 char *str_param = NULL;
1313 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1314 qahw_module_t *qahw_module_temp;
1315 audio_hw_device_t *audio_device;
1316
1317 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301318 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301319 pthread_mutex_unlock(&qahw_module_init_lock);
1320 if (qahw_module_temp == NULL) {
1321 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1322 goto exit;
1323 }
1324
1325 pthread_mutex_lock(&qahw_module->lock);
1326 audio_device = qahw_module->audio_device;
1327 if (qahw_module->audio_device->get_parameters) {
1328 str_param = audio_device->get_parameters(qahw_module->audio_device, keys);
1329 } else {
1330 ALOGW("%s not supported", __func__);
1331 }
1332 pthread_mutex_unlock(&qahw_module->lock);
1333
1334exit:
1335 return str_param;
1336}
1337
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301338/* Api to implement get parameters based on keyword param_id
1339 * and store data in payload.
1340 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301341int qahw_get_param_data_l(const qahw_module_handle_t *hw_module,
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301342 qahw_param_id param_id,
1343 qahw_param_payload *payload)
1344{
1345 int ret = 0;
1346 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1347 qahw_module_t *qahw_module_temp;
1348
1349 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301350 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301351 pthread_mutex_unlock(&qahw_module_init_lock);
1352 if (qahw_module_temp == NULL) {
1353 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1354 goto exit;
1355 }
1356
1357 pthread_mutex_lock(&qahw_module->lock);
1358
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301359 if (qahw_module->qahwi_get_param_data){
1360 ret = qahw_module->qahwi_get_param_data (qahw_module->audio_device,
1361 param_id, payload);
1362 } else {
1363 ret = -ENOSYS;
1364 ALOGE("%s not supported\n",__func__);
1365 }
1366 pthread_mutex_unlock(&qahw_module->lock);
1367
1368exit:
1369 return ret;
1370}
1371
1372/* Api to implement set parameters based on keyword param_id
1373 * and data present in payload.
1374 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301375int qahw_set_param_data_l(const qahw_module_handle_t *hw_module,
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301376 qahw_param_id param_id,
1377 qahw_param_payload *payload)
1378{
1379 int ret = 0;
1380 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1381 qahw_module_t *qahw_module_temp;
1382
1383 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301384 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301385 pthread_mutex_unlock(&qahw_module_init_lock);
1386 if (qahw_module_temp == NULL) {
1387 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1388 goto exit;
1389 }
1390
1391 pthread_mutex_lock(&qahw_module->lock);
1392
1393 if (qahw_module->qahwi_set_param_data){
1394 ret = qahw_module->qahwi_set_param_data (qahw_module->audio_device,
1395 param_id, payload);
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301396 } else {
1397 ret = -ENOSYS;
1398 ALOGE("%s not supported\n",__func__);
1399 }
1400 pthread_mutex_unlock(&qahw_module->lock);
1401
1402exit:
1403 return ret;
1404}
1405
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301406/* Creates an audio patch between several source and sink ports.
1407 * The handle is allocated by the HAL and should be unique for this
1408 * audio HAL module.
1409 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301410int qahw_create_audio_patch_l(qahw_module_handle_t *hw_module,
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301411 unsigned int num_sources,
1412 const struct audio_port_config *sources,
1413 unsigned int num_sinks,
1414 const struct audio_port_config *sinks,
1415 audio_patch_handle_t *handle)
1416{
1417 int ret = 0;
1418 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1419 qahw_module_t *qahw_module_temp;
1420
1421 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301422 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301423 pthread_mutex_unlock(&qahw_module_init_lock);
1424 if (qahw_module_temp == NULL) {
1425 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1426 goto exit;
1427 }
1428
1429 pthread_mutex_lock(&qahw_module->lock);
1430 if (qahw_module->audio_device->create_audio_patch) {
1431 ret = qahw_module->audio_device->create_audio_patch(
1432 qahw_module->audio_device,
1433 num_sources,
1434 sources,
1435 num_sinks,
1436 sinks,
1437 handle);
1438 } else {
1439 ret = -ENOSYS;
1440 ALOGE("%s not supported\n",__func__);
1441 }
1442 pthread_mutex_unlock(&qahw_module->lock);
1443
1444exit:
1445 return ret;
1446}
1447
1448/* Release an audio patch */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301449int qahw_release_audio_patch_l(qahw_module_handle_t *hw_module,
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301450 audio_patch_handle_t handle)
1451{
1452 int ret = 0;
1453 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1454 qahw_module_t *qahw_module_temp;
1455
1456 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301457 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301458 pthread_mutex_unlock(&qahw_module_init_lock);
1459 if (qahw_module_temp == NULL) {
1460 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1461 goto exit;
1462 }
1463
1464 pthread_mutex_lock(&qahw_module->lock);
1465 if (qahw_module->audio_device->release_audio_patch) {
1466 ret = qahw_module->audio_device->release_audio_patch(
1467 qahw_module->audio_device,
1468 handle);
1469 } else {
1470 ret = -ENOSYS;
1471 ALOGE("%s not supported\n",__func__);
1472 }
1473 pthread_mutex_unlock(&qahw_module->lock);
1474
1475exit:
1476 return ret;
1477}
1478
Trinath Thammishetty580f1de2018-09-28 12:43:24 +05301479int qahw_loopback_set_param_data_l(qahw_module_handle_t *hw_module,
1480 audio_patch_handle_t handle,
1481 qahw_loopback_param_id param_id,
1482 qahw_loopback_param_payload *payload)
1483
1484{
1485 int ret = -EINVAL;
1486 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1487
1488 if (!payload) {
1489 ALOGE("%s:: invalid param", __func__);
1490 goto exit;
1491 }
1492
1493 if (qahw_module->qahwi_loopback_set_param_data) {
1494 ret = qahw_module->qahwi_loopback_set_param_data(handle,
1495 param_id,
Trinath Thammishetty15cd3402018-10-29 11:57:19 +05301496 payload);
Trinath Thammishetty580f1de2018-09-28 12:43:24 +05301497 } else {
1498 ret = -ENOSYS;
1499 ALOGE("%s not supported\n", __func__);
1500 }
1501
1502exit:
1503 return ret;
1504
1505}
1506
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301507/* Fills the list of supported attributes for a given audio port.
1508 * As input, "port" contains the information (type, role, address etc...)
1509 * needed by the HAL to identify the port.
1510 * As output, "port" contains possible attributes (sampling rates, formats,
1511 * channel masks, gain controllers...) for this port.
1512 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301513int qahw_get_audio_port_l(qahw_module_handle_t *hw_module,
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301514 struct audio_port *port)
1515{
1516 int ret = 0;
1517 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1518 qahw_module_t *qahw_module_temp;
1519
1520 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301521 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301522 pthread_mutex_unlock(&qahw_module_init_lock);
1523 if (qahw_module_temp == NULL) {
1524 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1525 goto exit;
1526 }
1527
1528 pthread_mutex_lock(&qahw_module->lock);
1529 if (qahw_module->audio_device->get_audio_port) {
1530 ret = qahw_module->audio_device->get_audio_port(
1531 qahw_module->audio_device,
1532 port);
1533 } else {
1534 ret = -ENOSYS;
1535 ALOGE("%s not supported\n",__func__);
1536 }
1537 pthread_mutex_unlock(&qahw_module->lock);
1538
1539exit:
1540 return ret;
1541}
1542
1543/* Set audio port configuration */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301544int qahw_set_audio_port_config_l(qahw_module_handle_t *hw_module,
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301545 const struct audio_port_config *config)
1546{
1547 int ret = 0;
1548 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1549 qahw_module_t *qahw_module_temp;
1550
1551 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301552 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301553 pthread_mutex_unlock(&qahw_module_init_lock);
1554 if (qahw_module_temp == NULL) {
1555 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1556 goto exit;
1557 }
1558
1559 pthread_mutex_lock(&qahw_module->lock);
1560 if (qahw_module->audio_device->set_audio_port_config) {
1561 ret = qahw_module->audio_device->set_audio_port_config(
1562 qahw_module->audio_device,
1563 config);
1564 } else {
1565 ret = -ENOSYS;
1566 ALOGE("%s not supported\n",__func__);
1567 }
1568 pthread_mutex_unlock(&qahw_module->lock);
1569
1570exit:
1571 return ret;
1572}
1573
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301574/* Returns audio input buffer size according to parameters passed or
1575 * 0 if one of the parameters is not supported.
1576 * See also get_buffer_size which is for a particular stream.
1577 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301578size_t qahw_get_input_buffer_size_l(const qahw_module_handle_t *hw_module,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301579 const struct audio_config *config)
1580{
1581 size_t rc = 0;
1582 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1583 qahw_module_t *qahw_module_temp;
1584 audio_hw_device_t *audio_device;
1585
1586 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301587 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301588 pthread_mutex_unlock(&qahw_module_init_lock);
1589 if (qahw_module_temp == NULL) {
1590 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1591 goto exit;
1592 }
1593
1594 pthread_mutex_lock(&qahw_module->lock);
1595 audio_device = qahw_module->audio_device;
1596 if (qahw_module->audio_device->get_input_buffer_size) {
1597 rc = audio_device->get_input_buffer_size(qahw_module->audio_device,
1598 config);
1599 } else {
1600 rc = -ENOSYS;
1601 ALOGW("%s not supported", __func__);
1602 }
1603 pthread_mutex_unlock(&qahw_module->lock);
1604
1605exit:
1606 return rc;
1607}
1608
1609/*
1610 * This method creates and opens the audio hardware output stream.
1611 * The "address" parameter qualifies the "devices" audio device type if needed.
1612 * The format format depends on the device type:
1613 * - Bluetooth devices use the MAC address of the device in the form "00:11:22:AA:BB:CC"
1614 * - USB devices use the ALSA card and device numbers in the form "card=X;device=Y"
1615 * - Other devices may use a number or any other string.
1616 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301617int qahw_open_output_stream_l(qahw_module_handle_t *hw_module,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301618 audio_io_handle_t handle,
1619 audio_devices_t devices,
1620 audio_output_flags_t flags,
1621 struct audio_config *config,
1622 qahw_stream_handle_t **out_handle,
1623 const char *address)
1624{
1625 int rc = -EINVAL;
1626 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1627 qahw_module_t *qahw_module_temp = NULL;
1628 audio_hw_device_t *audio_device = NULL;
1629 qahw_stream_out_t *qahw_stream_out = NULL;
1630
1631 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301632 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301633 pthread_mutex_unlock(&qahw_module_init_lock);
1634 if (qahw_module_temp == NULL) {
1635 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1636 return rc;
1637 }
1638
1639 pthread_mutex_lock(&qahw_module->lock);
1640 audio_device = qahw_module->audio_device;
1641 qahw_stream_out = (qahw_stream_out_t *)calloc(1, sizeof(qahw_stream_out_t));
1642 if (qahw_stream_out == NULL) {
1643 ALOGE("%s:: calloc failed for out stream_out_t",__func__);
1644 rc = -ENOMEM;
1645 goto exit;
1646 }
1647
1648 rc = audio_device->open_output_stream(audio_device,
1649 handle,
1650 devices,
1651 flags,
1652 config,
1653 &qahw_stream_out->stream,
1654 address);
1655 if (rc) {
1656 ALOGE("%s::open output stream failed %d",__func__, rc);
1657 free(qahw_stream_out);
1658 } else {
1659 qahw_stream_out->module = hw_module;
1660 *out_handle = (void *)qahw_stream_out;
1661 pthread_mutex_init(&qahw_stream_out->lock, (const pthread_mutexattr_t *)NULL);
1662 list_add_tail(&qahw_module->out_list, &qahw_stream_out->list);
Manish Dewangan3ccdea52017-02-13 19:31:54 +05301663
1664 /* clear any existing errors */
1665 const char *error;
1666 dlerror();
1667 qahw_stream_out->qahwi_out_get_param_data = (qahwi_out_get_param_data_t)
1668 dlsym(qahw_module->module->dso,
1669 "qahwi_out_get_param_data");
1670 if ((error = dlerror()) != NULL) {
1671 ALOGI("%s: dlsym error %s for qahwi_out_get_param_data",
1672 __func__, error);
1673 qahw_stream_out->qahwi_out_get_param_data = NULL;
1674 }
1675
1676 dlerror();
1677 qahw_stream_out->qahwi_out_set_param_data = (qahwi_out_set_param_data_t)
1678 dlsym(qahw_module->module->dso,
1679 "qahwi_out_set_param_data");
1680 if ((error = dlerror()) != NULL) {
1681 ALOGI("%s: dlsym error %s for qahwi_out_set_param_data",
1682 __func__, error);
1683 qahw_stream_out->qahwi_out_set_param_data = NULL;
1684 }
1685}
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301686
Naresh Tanniruee3499a2017-01-05 14:05:35 +05301687 /* dlsym qahwi_out_write_v2 */
1688 if (!rc) {
1689 const char *error;
1690
1691 /* clear any existing errors */
1692 dlerror();
1693 qahw_stream_out->qahwi_out_write_v2 = (qahwi_out_write_v2_t)dlsym(qahw_module->module->dso, "qahwi_out_write_v2");
1694 if ((error = dlerror()) != NULL) {
1695 ALOGI("%s: dlsym error %s for qahwi_out_write_v2", __func__, error);
1696 qahw_stream_out->qahwi_out_write_v2 = NULL;
1697 }
1698 }
1699
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301700exit:
1701 pthread_mutex_unlock(&qahw_module->lock);
1702 return rc;
1703}
1704
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301705int qahw_close_output_stream_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301706{
1707
1708 int rc = 0;
1709 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
1710 qahw_module_t *qahw_module = NULL;
1711 audio_hw_device_t *audio_device = NULL;
1712
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301713 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301714 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
1715 rc = -EINVAL;
1716 goto exit;
1717 }
1718
1719 ALOGV("%s::calling device close_output_stream %p", __func__, out_handle);
1720 pthread_mutex_lock(&qahw_stream_out->lock);
1721 qahw_module = qahw_stream_out->module;
1722 audio_device = qahw_module->audio_device;
1723 audio_device->close_output_stream(audio_device,
1724 qahw_stream_out->stream);
1725
1726 pthread_mutex_lock(&qahw_module->lock);
1727 list_remove(&qahw_stream_out->list);
1728 pthread_mutex_unlock(&qahw_module->lock);
1729
1730 pthread_mutex_unlock(&qahw_stream_out->lock);
1731
1732 pthread_mutex_destroy(&qahw_stream_out->lock);
1733 free(qahw_stream_out);
1734
1735exit:
1736 return rc;
1737}
1738
1739/* This method creates and opens the audio hardware input stream */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301740int qahw_open_input_stream_l(qahw_module_handle_t *hw_module,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301741 audio_io_handle_t handle,
1742 audio_devices_t devices,
1743 struct audio_config *config,
1744 qahw_stream_handle_t **in_handle,
1745 audio_input_flags_t flags,
1746 const char *address,
1747 audio_source_t source)
1748{
1749 int rc = -EINVAL;
1750 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1751 qahw_module_t *qahw_module_temp = NULL;
1752 audio_hw_device_t *audio_device = NULL;
1753 qahw_stream_in_t *qahw_stream_in = NULL;
Manish Dewangan46e07982018-12-13 18:18:59 +05301754 const char *error;
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301755
1756 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301757 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301758 pthread_mutex_unlock(&qahw_module_init_lock);
1759 if (qahw_module_temp == NULL) {
1760 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1761 return rc;
1762 }
1763
1764 pthread_mutex_lock(&qahw_module->lock);
1765 audio_device = qahw_module->audio_device;
1766 qahw_stream_in = (qahw_stream_in_t *)calloc(1, sizeof(qahw_stream_in_t));
1767 if (qahw_stream_in == NULL) {
1768 ALOGE("%s:: calloc failed for in stream_in_t",__func__);
1769 rc = -ENOMEM;
1770 goto exit;
1771 }
1772
1773 rc = audio_device->open_input_stream(audio_device,
1774 handle,
1775 devices,
1776 config,
1777 &qahw_stream_in->stream,
1778 flags,
1779 address,
1780 source);
1781 if (rc) {
1782 ALOGE("%s::open input stream failed %d",__func__, rc);
1783 free(qahw_stream_in);
Manish Dewangan46e07982018-12-13 18:18:59 +05301784 goto exit;
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301785 } else {
1786 qahw_stream_in->module = hw_module;
1787 *in_handle = (void *)qahw_stream_in;
1788 pthread_mutex_init(&qahw_stream_in->lock, (const pthread_mutexattr_t *)NULL);
1789 list_add_tail(&qahw_module->in_list, &qahw_stream_in->list);
1790 }
1791
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05301792 /* dlsym qahwi_in_read_v2 if timestamp flag is used */
Ralf Herzaec80262018-07-03 07:08:49 +02001793 if (!rc && ((flags & QAHW_INPUT_FLAG_TIMESTAMP) ||
1794 (flags & QAHW_INPUT_FLAG_PASSTHROUGH))) {
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05301795
1796 /* clear any existing errors */
1797 dlerror();
1798 qahw_stream_in->qahwi_in_read_v2 = (qahwi_in_read_v2_t)
1799 dlsym(qahw_module->module->dso, "qahwi_in_read_v2");
1800 if ((error = dlerror()) != NULL) {
1801 ALOGI("%s: dlsym error %s for qahwi_in_read_v2", __func__, error);
1802 qahw_stream_in->qahwi_in_read_v2 = NULL;
1803 }
1804 }
1805
Manish Dewangan46e07982018-12-13 18:18:59 +05301806 /* clear any existing errors */
1807 dlerror();
1808 qahw_stream_in->qahwi_in_stop = (qahwi_in_stop_t)
1809 dlsym(qahw_module->module->dso, "qahwi_in_stop");
1810 if ((error = dlerror()) != NULL) {
1811 ALOGI("%s: dlsym error %s for qahwi_in_stop", __func__, error);
1812 qahw_stream_in->qahwi_in_stop = NULL;
1813 }
1814
1815 exit:
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301816 pthread_mutex_unlock(&qahw_module->lock);
1817 return rc;
1818}
1819
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301820int qahw_close_input_stream_l(qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301821{
1822 int rc = 0;
1823 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
1824 qahw_module_t *qahw_module = NULL;
1825 audio_hw_device_t *audio_device = NULL;
1826
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301827 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301828 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
1829 rc = -EINVAL;
1830 goto exit;
1831 }
1832
1833 ALOGV("%s:: calling device close_input_stream %p", __func__, in_handle);
1834 pthread_mutex_lock(&qahw_stream_in->lock);
1835 qahw_module = qahw_stream_in->module;
1836 audio_device = qahw_module->audio_device;
1837 audio_device->close_input_stream(audio_device,
1838 qahw_stream_in->stream);
1839
1840 pthread_mutex_lock(&qahw_module->lock);
1841 list_remove(&qahw_stream_in->list);
1842 pthread_mutex_unlock(&qahw_module->lock);
1843
1844 pthread_mutex_unlock(&qahw_stream_in->lock);
1845
1846 pthread_mutex_destroy(&qahw_stream_in->lock);
1847 free(qahw_stream_in);
1848
1849exit:
1850 return rc;
1851}
1852
1853/*returns current QTI HAL verison */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301854int qahw_get_version_l() {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301855 return QAHW_MODULE_API_VERSION_CURRENT;
1856}
1857
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +05301858/* Load AHAL module to run audio and sva concurrency */
1859static void load_st_hal()
1860{
1861#ifdef SVA_AUDIO_CONC
1862 int rc = -EINVAL;
1863 const hw_module_t* module = NULL;
1864
1865 rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, "primary", &module);
1866 if (rc) {
1867 ALOGE("%s: AHAL Loading failed %d", __func__, rc);
1868 goto error;
1869 }
1870
1871 rc = sound_trigger_hw_device_open(module, &st_hw_device);
1872 if (rc) {
1873 ALOGE("%s: AHAL Device open failed %d", __func__, rc);
1874 st_hw_device = NULL;
1875 }
1876error:
1877 return;
1878#else
1879 return;
1880#endif /*SVA_AUDIO_CONC*/
1881}
1882
1883static void unload_st_hal()
1884{
1885#ifdef SVA_AUDIO_CONC
1886 if (st_hw_device == NULL) {
1887 ALOGE("%s: audio device is NULL",__func__);
1888 return;
1889 }
1890 sound_trigger_hw_device_close(st_hw_device);
1891 st_hw_device = NULL;
1892#else
1893 return;
1894#endif /*SVA_AUDIO_CONC*/
1895}
1896
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301897/* convenience API for opening and closing an audio HAL module */
1898
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301899qahw_module_handle_t *qahw_load_module_l(const char *hw_module_id)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301900{
1901 int rc = -EINVAL;
1902 qahw_module_handle_t *qahw_mod_handle = NULL;
1903 qahw_module_t *qahw_module = NULL;
1904 char *ahal_name = NULL;
1905 const hw_module_t* module = NULL;
1906 audio_hw_device_t* audio_device = NULL;
1907
1908 if (hw_module_id == NULL) {
1909 ALOGE("%s::module id is NULL",__func__);
1910 goto exit;
1911 }
1912
1913 if (!strcmp(hw_module_id, QAHW_MODULE_ID_PRIMARY)) {
1914 ahal_name = "primary";
1915 } else if (!strcmp(hw_module_id, QAHW_MODULE_ID_A2DP)) {
1916 ahal_name = "a2dp";
1917 } else if (!strcmp(hw_module_id, QAHW_MODULE_ID_USB)) {
1918 ahal_name = "usb";
1919 } else {
1920 ALOGE("%s::Invalid Module id %s", __func__, hw_module_id);
1921 goto exit;
1922 }
1923
1924 /* return exiting module ptr if already loaded */
1925 pthread_mutex_lock(&qahw_module_init_lock);
1926 if (qahw_list_count > 0) {
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301927 qahw_module = get_qahw_module_by_name_l(hw_module_id);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301928 if(qahw_module != NULL) {
1929 qahw_mod_handle = (void *)qahw_module;
1930 pthread_mutex_lock(&qahw_module->lock);
1931 qahw_module->ref_count++;
1932 pthread_mutex_unlock(&qahw_module->lock);
1933 goto error_exit;
1934 }
1935 }
1936
1937 rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, ahal_name, &module);
1938 if(rc) {
1939 ALOGE("%s::HAL Loading failed %d", __func__, rc);
1940 goto error_exit;
1941 }
1942
1943 rc = audio_hw_device_open(module, &audio_device);
1944 if(rc) {
1945 ALOGE("%s::HAL Device open failed %d", __func__, rc);
1946 goto error_exit;
1947 }
1948
1949 qahw_module = (qahw_module_t *)calloc(1, sizeof(qahw_module_t));
1950 if(qahw_module == NULL) {
1951 ALOGE("%s::calloc failed", __func__);
1952 audio_hw_device_close(audio_device);
1953 goto error_exit;
1954 }
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05301955 qahw_module->module = module;
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301956 ALOGD("%s::Loaded HAL %s module %p", __func__, ahal_name, qahw_module);
1957
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301958 qahw_module->qahwi_get_param_data = (qahwi_get_param_data_t) dlsym (module->dso,
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301959 "qahwi_get_param_data");
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301960 if (!qahw_module->qahwi_get_param_data)
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301961 ALOGD("%s::qahwi_get_param_data api is not defined\n",__func__);
1962
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301963 qahw_module->qahwi_set_param_data = (qahwi_set_param_data_t) dlsym (module->dso,
1964 "qahwi_set_param_data");
1965 if (!qahw_module->qahwi_set_param_data)
1966 ALOGD("%s::qahwi_set_param_data api is not defined\n",__func__);
1967
Trinath Thammishetty580f1de2018-09-28 12:43:24 +05301968 qahw_module->qahwi_loopback_set_param_data = (qahwi_loopback_set_param_data_t)
1969 dlsym(module->dso,
1970 "qahwi_loopback_set_param_data");
1971 if (!qahw_module->qahwi_loopback_set_param_data)
1972 ALOGD("%s::qahwi_loopback_set_param_data api is not defined\n", __func__);
1973
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301974 if (!qahw_list_count)
1975 list_init(&qahw_module_list);
1976 qahw_list_count++;
1977
1978 pthread_mutex_init(&qahw_module->lock, (const pthread_mutexattr_t *) NULL);
1979 pthread_mutex_lock(&qahw_module->lock);
1980 qahw_module->ref_count++;
1981 pthread_mutex_unlock(&qahw_module->lock);
1982
1983 list_init(&qahw_module->out_list);
1984 list_init(&qahw_module->in_list);
1985
1986 /* update qahw_module */
1987 qahw_module->audio_device = audio_device;
1988 strlcpy(&qahw_module->module_name[0], hw_module_id, MAX_MODULE_NAME_LENGTH);
1989
1990 qahw_mod_handle = (void *)qahw_module;
1991
1992 /* Add module list to global module list */
1993 list_add_tail(&qahw_module_list, &qahw_module->module_list);
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +05301994 load_st_hal();
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301995
1996error_exit:
1997 pthread_mutex_unlock(&qahw_module_init_lock);
1998
1999exit:
2000 return qahw_mod_handle;
2001}
2002
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05302003int qahw_unload_module_l(qahw_module_handle_t *hw_module)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05302004{
2005 int rc = -EINVAL;
2006 bool is_empty = false;
2007 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
2008 qahw_module_t *qahw_module_temp = NULL;
2009
2010 /* close HW device if its valid and all the streams on
2011 * it is closed
2012 */
2013 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05302014 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05302015 if (qahw_module_temp == NULL) {
2016 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
2017 goto error_exit;
2018 }
2019
2020 pthread_mutex_lock(&qahw_module->lock);
2021 qahw_module->ref_count--;
2022 if (qahw_module->ref_count > 0) {
2023 rc = 0;
2024 ALOGE("%s:: skipping module unload of %p count %d", __func__,
2025 qahw_module,
2026 qahw_module->ref_count);
2027 pthread_mutex_unlock(&qahw_module->lock);
2028 goto error_exit;
2029 }
2030
2031 is_empty = (list_empty(&qahw_module->out_list) &&
2032 list_empty(&qahw_module->in_list));
2033 if (is_empty) {
2034 rc = audio_hw_device_close(qahw_module->audio_device);
2035 if(rc) {
2036 ALOGE("%s::HAL Device close failed Error %d Module %p",__func__,
2037 rc, qahw_module);
2038 rc = 0;
2039 }
2040 qahw_list_count--;
2041 list_remove(&qahw_module->module_list);
2042 pthread_mutex_unlock(&qahw_module->lock);
2043 pthread_mutex_destroy(&qahw_module->lock);
2044 free(qahw_module);
2045 } else {
2046 pthread_mutex_unlock(&qahw_module->lock);
2047 ALOGE("%s::failed as all the streams on this module"
2048 "is not closed", __func__);
2049 rc = -EINVAL;
2050 }
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +05302051 unload_st_hal();
Manish Dewanganb8c83a42016-09-23 15:10:48 +05302052
2053error_exit:
2054 pthread_mutex_unlock(&qahw_module_init_lock);
2055
Manish Dewanganb8c83a42016-09-23 15:10:48 +05302056 return rc;
2057}
2058
2059__END_DECLS