blob: 545152c16769e053aa8c11e66531ac21f6abff62 [file] [log] [blame]
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301/*
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +05302* Copyright (c) 2016-2018, 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>
38
39#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.
48 */
49#define QAHW_MODULE_API_VERSION_CURRENT QAHW_MODULE_API_VERSION_0_0
50
Naresh Tanniruee3499a2017-01-05 14:05:35 +053051
52typedef uint64_t (*qahwi_out_write_v2_t)(audio_stream_out_t *out, const void* buffer,
53 size_t bytes, int64_t* timestamp);
54
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +053055typedef int (*qahwi_get_param_data_t) (const audio_hw_device_t *,
56 qahw_param_id, qahw_param_payload *);
57
58typedef int (*qahwi_set_param_data_t) (audio_hw_device_t *,
59 qahw_param_id, qahw_param_payload *);
60
Manish Dewangan3ccdea52017-02-13 19:31:54 +053061typedef uint64_t (*qahwi_in_read_v2_t)(audio_stream_in_t *in, void* buffer,
62 size_t bytes, int64_t *timestamp);
63
Manish Dewangan46e07982018-12-13 18:18:59 +053064typedef int (*qahwi_in_stop_t)(audio_stream_in_t *in);
65
Manish Dewangan3ccdea52017-02-13 19:31:54 +053066typedef int (*qahwi_out_set_param_data_t)(struct audio_stream_out *out,
67 qahw_param_id param_id,
68 qahw_param_payload *payload);
69
70typedef int (*qahwi_out_get_param_data_t)(struct audio_stream_out *out,
71 qahw_param_id param_id,
72 qahw_param_payload *payload);
73
Trinath Thammishetty580f1de2018-09-28 12:43:24 +053074typedef int (*qahwi_loopback_set_param_data_t)(audio_patch_handle_t patch_handle,
Trinath Thammishetty15cd3402018-10-29 11:57:19 +053075 qahw_loopback_param_id param_id,
76 qahw_loopback_param_payload *payload);
Trinath Thammishetty580f1de2018-09-28 12:43:24 +053077
Manish Dewanganb8c83a42016-09-23 15:10:48 +053078typedef struct {
79 audio_hw_device_t *audio_device;
80 char module_name[MAX_MODULE_NAME_LENGTH];
81 struct listnode module_list;
82 struct listnode in_list;
83 struct listnode out_list;
84 pthread_mutex_t lock;
85 uint32_t ref_count;
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +053086 const hw_module_t* module;
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +053087 qahwi_get_param_data_t qahwi_get_param_data;
88 qahwi_set_param_data_t qahwi_set_param_data;
Trinath Thammishetty580f1de2018-09-28 12:43:24 +053089 qahwi_loopback_set_param_data_t qahwi_loopback_set_param_data;
Manish Dewanganb8c83a42016-09-23 15:10:48 +053090} qahw_module_t;
91
92typedef struct {
93 qahw_module_t *module;
94 struct listnode module_list;
95 pthread_mutex_t lock;
96} qahw_module_instances_t;
97
98typedef struct {
99 audio_stream_out_t *stream;
100 qahw_module_t *module;
101 struct listnode list;
102 pthread_mutex_t lock;
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530103 qahwi_out_set_param_data_t qahwi_out_get_param_data;
104 qahwi_out_get_param_data_t qahwi_out_set_param_data;
Naresh Tanniruee3499a2017-01-05 14:05:35 +0530105 qahwi_out_write_v2_t qahwi_out_write_v2;
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530106} qahw_stream_out_t;
107
108typedef struct {
109 audio_stream_in_t *stream;
110 qahw_module_t *module;
111 struct listnode list;
112 pthread_mutex_t lock;
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +0530113 qahwi_in_read_v2_t qahwi_in_read_v2;
Manish Dewangan46e07982018-12-13 18:18:59 +0530114 qahwi_in_stop_t qahwi_in_stop;
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530115} qahw_stream_in_t;
116
117typedef enum {
118 STREAM_DIR_IN,
119 STREAM_DIR_OUT,
120} qahw_stream_direction_t;
121
122static struct listnode qahw_module_list;
123static int qahw_list_count;
124static pthread_mutex_t qahw_module_init_lock = PTHREAD_MUTEX_INITIALIZER;
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +0530125sound_trigger_hw_device_t *st_hw_device = NULL;
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530126
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +0530127
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530128/** Start of internal functions */
129/******************************************************************************/
130
131/* call this function without anylock held */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530132static bool is_valid_qahw_stream_l(void *qahw_stream,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530133 qahw_stream_direction_t dir)
134{
135
136 int is_valid = false;
137 struct listnode *module_node = NULL;
138 struct listnode *stream_node = NULL;
139 struct listnode *list_node = NULL;
140 void *stream = NULL;
141 qahw_module_t *qahw_module = NULL;
142
143 if (qahw_stream == NULL) {
144 ALOGE("%s:: Invalid stream", __func__);
145 goto exit;
146 }
147
148 if ((dir != STREAM_DIR_OUT) && (dir != STREAM_DIR_IN)) {
149 ALOGE("%s:: Invalid stream direction %d", __func__, dir);
150 goto exit;
151 }
152
153 /* go through all the modules and check for valid stream */
154 pthread_mutex_lock(&qahw_module_init_lock);
155 list_for_each(module_node, &qahw_module_list) {
156 qahw_module = node_to_item(module_node, qahw_module_t, module_list);
157 pthread_mutex_lock(&qahw_module->lock);
158 if(dir == STREAM_DIR_OUT)
159 list_node = &qahw_module->out_list;
160 else
161 list_node = &qahw_module->in_list;
162 list_for_each(stream_node, list_node) {
163 if(dir == STREAM_DIR_OUT)
164 stream = (void *)node_to_item(stream_node,
165 qahw_stream_out_t,
166 list);
167 else
168 stream = (void *)node_to_item(stream_node,
169 qahw_stream_in_t,
170 list);
171 if(stream == qahw_stream) {
172 is_valid = true;
173 break;
174 }
175 }
176 pthread_mutex_unlock(&qahw_module->lock);
177 if(is_valid)
178 break;
179 }
180 pthread_mutex_unlock(&qahw_module_init_lock);
181
182exit:
183 return is_valid;
184}
185
186/* call this fucntion with ahw_module_init_lock held*/
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530187static qahw_module_t* get_qahw_module_by_ptr_l(qahw_module_t *qahw_module)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530188{
189 struct listnode *node = NULL;
190 qahw_module_t *module = NULL, *module_temp = NULL;
191
192 if (qahw_module == NULL)
193 goto exit;
194
195 list_for_each(node, &qahw_module_list) {
196 module_temp = node_to_item(node, qahw_module_t, module_list);
197 if (module_temp == qahw_module) {
198 module = module_temp;
199 break;
200 }
201 }
202exit:
203 return module;
204}
205
206/* call this function with qahw_module_init_lock held*/
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530207static qahw_module_t* get_qahw_module_by_name_l(const char *qahw_name)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530208{
209 struct listnode *node = NULL;
210 qahw_module_t *module = NULL, *module_temp = NULL;
211
212 if (qahw_name == NULL)
213 goto exit;
214
215 list_for_each(node, &qahw_module_list) {
216 module_temp = node_to_item(node, qahw_module_t, module_list);
217 if(!strncmp(qahw_name, module_temp->module_name, MAX_MODULE_NAME_LENGTH)) {
218 module = module_temp;
219 break;
220 }
221 }
222exit:
223 return module;
224}
225/* End of of internal functions */
226
227/*
228 * Return the sampling rate in Hz - eg. 44100.
229 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530230uint32_t qahw_out_get_sample_rate_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530231{
232 uint32_t rate = 0;
233 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
234 audio_stream_out_t *out = NULL;
235
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530236 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530237 ALOGV("%s::Invalid out handle %p", __func__, out_handle);
238 goto exit;
239 }
240
241 pthread_mutex_lock(&qahw_stream_out->lock);
242 out = qahw_stream_out->stream;
243 if (out->common.get_sample_rate)
244 rate = out->common.get_sample_rate(&out->common);
245 else
246 ALOGW("%s not supported", __func__);
247 pthread_mutex_unlock(&qahw_stream_out->lock);
248
249exit:
250 return rate;
251}
252
253/*
254 * currently unused - use set_parameters with key
255 * AUDIO_PARAMETER_STREAM_SAMPLING_RATE
256 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530257int qahw_out_set_sample_rate_l(qahw_stream_handle_t *out_handle, uint32_t rate)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530258{
259 int32_t rc = -EINVAL;
260 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
261 audio_stream_out_t *out = NULL;
262
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530263 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530264 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
265 goto exit;
266 }
267 pthread_mutex_lock(&qahw_stream_out->lock);
268 out = qahw_stream_out->stream;
269 if (out->common.set_sample_rate) {
270 rc = out->common.set_sample_rate(&out->common, rate);
271 } else {
272 rc = -ENOSYS;
273 ALOGW("%s not supported", __func__);
274 }
275 pthread_mutex_unlock(&qahw_stream_out->lock);
276exit:
277 return rc;
278}
279
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530280size_t qahw_out_get_buffer_size_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530281{
282 size_t buf_size = 0;
283 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
284 audio_stream_out_t *out = NULL;
285
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530286 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530287 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
288 goto exit;
289 }
290 pthread_mutex_lock(&qahw_stream_out->lock);
291 out = qahw_stream_out->stream;
292 if (out->common.get_buffer_size) {
293 buf_size = out->common.get_buffer_size(&out->common);
294 } else {
295 ALOGW("%s not supported", __func__);
296 }
297 pthread_mutex_unlock(&qahw_stream_out->lock);
298
299exit:
300 return buf_size;
301}
302
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530303audio_channel_mask_t qahw_out_get_channels_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530304{
305 audio_channel_mask_t ch_mask = 0;
306 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
307 audio_stream_out_t *out = NULL;
308
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530309 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530310 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
311 goto exit;
312 }
313 pthread_mutex_lock(&qahw_stream_out->lock);
314 out = qahw_stream_out->stream;
315 if (out->common.get_channels) {
316 ch_mask = out->common.get_channels(&out->common);
317 } else {
318 ALOGW("%s not supported", __func__);
319 }
320 pthread_mutex_unlock(&qahw_stream_out->lock);
321
322exit:
323 return ch_mask;
324}
325
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530326audio_format_t qahw_out_get_format_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530327{
328 audio_format_t format = AUDIO_FORMAT_INVALID;
329 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
330 audio_stream_out_t *out = NULL;
331
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530332 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530333 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
334 goto exit;
335 }
336 pthread_mutex_lock(&qahw_stream_out->lock);
337 out = qahw_stream_out->stream;
338 if (out->common.get_format) {
339 format = out->common.get_format(&out->common);
340 } else {
341 ALOGW("%s not supported", __func__);
342 }
343 pthread_mutex_unlock(&qahw_stream_out->lock);
344
345exit:
346 return format;
347}
348
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530349int qahw_out_standby_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530350{
351 int32_t rc = -EINVAL;
352 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
353 audio_stream_out_t *out = NULL;
354
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530355 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530356 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
357 goto exit;
358 }
359
360 pthread_mutex_lock(&qahw_stream_out->lock);
361 out = qahw_stream_out->stream;
362 if (out->common.standby) {
363 rc = out->common.standby(&out->common);
364 } else {
365 rc = -ENOSYS;
366 ALOGW("%s not supported", __func__);
367 }
368 pthread_mutex_unlock(&qahw_stream_out->lock);
369
370exit:
371 return rc;
372}
373
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530374int qahw_out_set_parameters_l(qahw_stream_handle_t *out_handle, const char *kv_pairs)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530375{
376 int rc = NO_ERROR;
377 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
378 audio_stream_out_t *out = NULL;
379
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530380 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530381 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
382 rc = -EINVAL;
383 goto exit;
384 }
385
386 pthread_mutex_lock(&qahw_stream_out->lock);
387 out = qahw_stream_out->stream;
388 if (out->common.set_parameters) {
389 rc = out->common.set_parameters(&out->common, kv_pairs);
390 } else {
391 rc = -ENOSYS;
392 ALOGW("%s not supported", __func__);
393 }
394 pthread_mutex_unlock(&qahw_stream_out->lock);
395
396exit:
397 return rc;
398}
399
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530400char *qahw_out_get_parameters_l(const qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530401 const char *keys)
402{
403 char *str_param = NULL;
404 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
405 audio_stream_out_t *out = NULL;
406
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530407 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530408 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
409 goto exit;
410 }
411
412 pthread_mutex_lock(&qahw_stream_out->lock);
413 out = qahw_stream_out->stream;
414 if (out->common.get_parameters) {
415 str_param = out->common.get_parameters(&out->common, keys);
416 } else {
417 ALOGW("%s not supported", __func__);
418 }
419 pthread_mutex_unlock(&qahw_stream_out->lock);
420
421exit:
422 return str_param;
423}
424
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530425/* API to get playback stream specific config parameters */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530426int qahw_out_set_param_data_l(qahw_stream_handle_t *out_handle,
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530427 qahw_param_id param_id,
428 qahw_param_payload *payload)
429{
430 int rc = -EINVAL;
431 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
432 audio_stream_out_t *out = NULL;
433
434 if (!payload) {
435 ALOGE("%s::Invalid param", __func__);
436 goto exit;
437 }
438
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530439 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530440 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
441 goto exit;
442 }
443
444 pthread_mutex_lock(&qahw_stream_out->lock);
445 out = qahw_stream_out->stream;
446 if (qahw_stream_out->qahwi_out_set_param_data) {
447 rc = qahw_stream_out->qahwi_out_set_param_data(out, param_id, payload);
448 } else {
449 rc = -ENOSYS;
450 ALOGW("%s not supported", __func__);
451 }
452 pthread_mutex_unlock(&qahw_stream_out->lock);
453
454exit:
455 return rc;
456}
457
458/* API to get playback stream specific config parameters */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530459int qahw_out_get_param_data_l(qahw_stream_handle_t *out_handle,
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530460 qahw_param_id param_id,
461 qahw_param_payload *payload)
462{
463 int rc = -EINVAL;
464 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
465 audio_stream_out_t *out = NULL;
466
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530467 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530468 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
469 goto exit;
470 }
471
472 pthread_mutex_lock(&qahw_stream_out->lock);
473 out = qahw_stream_out->stream;
474 if (qahw_stream_out->qahwi_out_get_param_data) {
475 rc = qahw_stream_out->qahwi_out_get_param_data(out, param_id, payload);
476 } else {
477 rc = -ENOSYS;
478 ALOGW("%s not supported", __func__);
479 }
480 pthread_mutex_unlock(&qahw_stream_out->lock);
481
482exit:
483 return rc;
484}
485
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530486uint32_t qahw_out_get_latency_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530487{
488 uint32_t latency = 0;
489 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
490 audio_stream_out_t *out = NULL;
491
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530492 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530493 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
494 goto exit;
495 }
496
497 pthread_mutex_lock(&qahw_stream_out->lock);
498 out = qahw_stream_out->stream;
499 if (out->get_latency) {
500 latency = out->get_latency(out);
501 } else {
502 ALOGW("%s not supported", __func__);
503 }
504 pthread_mutex_unlock(&qahw_stream_out->lock);
505
506exit:
507 return latency;
508}
509
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530510int qahw_out_set_volume_l(qahw_stream_handle_t *out_handle, float left, float right)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530511{
512 int rc = -EINVAL;
513 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
514 audio_stream_out_t *out = NULL;
515
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530516 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530517 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
518 goto exit;
519 }
520
521 pthread_mutex_lock(&qahw_stream_out->lock);
522 out = qahw_stream_out->stream;
523 if (out->set_volume) {
524 rc = out->set_volume(out, left, right);
525 } else {
526 rc = -ENOSYS;
527 ALOGW("%s not supported", __func__);
528 }
529 pthread_mutex_unlock(&qahw_stream_out->lock);
530
531exit:
532 return rc;
533}
534
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530535ssize_t qahw_out_write_l(qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530536 qahw_out_buffer_t *out_buf)
537{
538 int rc = -EINVAL;
539 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
540 audio_stream_out_t *out = NULL;
541
542 if ((out_buf == NULL) || (out_buf->buffer == NULL)) {
543 ALOGE("%s::Invalid meta data %p", __func__, out_buf);
544 goto exit;
545 }
546
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530547 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530548 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
549 goto exit;
550 }
551
552 /*TBD:: validate other meta data parameters */
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530553 pthread_mutex_lock(&qahw_stream_out->lock);
554 out = qahw_stream_out->stream;
Naresh Tanniruee3499a2017-01-05 14:05:35 +0530555 if (qahw_stream_out->qahwi_out_write_v2) {
556 rc = qahw_stream_out->qahwi_out_write_v2(out, out_buf->buffer,
557 out_buf->bytes, out_buf->timestamp);
558 out_buf->offset = 0;
559 } else if (out->write) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530560 rc = out->write(out, out_buf->buffer, out_buf->bytes);
561 } else {
562 rc = -ENOSYS;
563 ALOGW("%s not supported", __func__);
564 }
565 pthread_mutex_unlock(&qahw_stream_out->lock);
566exit:
567 return rc;
568}
569
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530570int qahw_out_get_render_position_l(const qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530571 uint32_t *dsp_frames)
572{
573 int rc = -EINVAL;
574 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
575 audio_stream_out_t *out = NULL;
576
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530577 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530578 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
579 goto exit;
580 }
581
582 pthread_mutex_lock(&qahw_stream_out->lock);
583 out = qahw_stream_out->stream;
584 if (out->get_render_position) {
585 rc = out->get_render_position(out, dsp_frames);
586 } else {
587 rc = -ENOSYS;
588 ALOGW("%s not supported", __func__);
589 }
590 pthread_mutex_unlock(&qahw_stream_out->lock);
591exit:
592 return rc;
593}
594
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530595int qahw_out_set_callback_l(qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530596 qahw_stream_callback_t callback,
597 void *cookie)
598{
599 /*TBD:load hal func pointer and call */
600 int rc = -EINVAL;
601 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
602 audio_stream_out_t *out = NULL;
603
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530604 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530605 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
606 goto exit;
607 }
608
609 pthread_mutex_lock(&qahw_stream_out->lock);
610 out = qahw_stream_out->stream;
611 if (out->set_callback) {
612 rc = out->set_callback(out, (stream_callback_t)callback, cookie);
613 } else {
614 rc = -ENOSYS;
615 ALOGW("%s not supported", __func__);
616 }
617 pthread_mutex_unlock(&qahw_stream_out->lock);
618
619exit:
620 return rc;
621}
622
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530623int qahw_out_pause_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530624{
625 /*TBD:load hal func pointer and call */
626 int rc = -EINVAL;
627 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
628 audio_stream_out_t *out = NULL;
629
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530630 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530631 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
632 goto exit;
633 }
634
635 pthread_mutex_lock(&qahw_stream_out->lock);
636 out = qahw_stream_out->stream;
637 if (out->pause) {
638 rc = out->pause(out);
639 } else {
640 rc = -ENOSYS;
641 ALOGW("%s not supported", __func__);
642 }
643 pthread_mutex_unlock(&qahw_stream_out->lock);
644
645exit:
646 return rc;
647}
648
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530649int qahw_out_resume_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530650{
651 /*TBD:load hal func pointer and call */
652 int rc = -EINVAL;
653 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
654 audio_stream_out_t *out = NULL;
655
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530656 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530657 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
658 goto exit;
659 }
660
661 pthread_mutex_lock(&qahw_stream_out->lock);
662 out = qahw_stream_out->stream;
663 if (out->resume) {
664 rc = out->resume(out);
665 } else {
666 rc = -ENOSYS;
667 ALOGW("%s not supported", __func__);
668 }
669 pthread_mutex_unlock(&qahw_stream_out->lock);
670
671exit:
672 return rc;
673}
674
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530675int qahw_out_drain_l(qahw_stream_handle_t *out_handle, qahw_drain_type_t type )
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530676{
677 /*TBD:load hal func pointer and call */
678 int rc = -EINVAL;
679 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
680 audio_stream_out_t *out = NULL;
681
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530682 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530683 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
684 goto exit;
685 }
686
687 pthread_mutex_lock(&qahw_stream_out->lock);
688 out = qahw_stream_out->stream;
689 if (out->drain) {
690 rc = out->drain(out,(audio_drain_type_t)type);
691 } else {
692 rc = -ENOSYS;
693 ALOGW("%s not supported", __func__);
694 }
695 pthread_mutex_unlock(&qahw_stream_out->lock);
696
697exit:
698 return rc;
699}
700
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530701int qahw_out_flush_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530702{
703 int rc = -EINVAL;
704 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
705 audio_stream_out_t *out = NULL;
706
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530707 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530708 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
709 goto exit;
710 }
711
712 pthread_mutex_lock(&qahw_stream_out->lock);
713 out = qahw_stream_out->stream;
714 if (out->flush) {
715 rc = out->flush(out);
716 } else {
717 rc = -ENOSYS;
718 ALOGW("%s not supported", __func__);
719 }
720 pthread_mutex_unlock(&qahw_stream_out->lock);
721
722exit:
723 return rc;
724}
725
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530726int qahw_out_get_presentation_position_l(const qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530727 uint64_t *frames, struct timespec *timestamp)
728{
729 int rc = -EINVAL;
730 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
731 audio_stream_out_t *out = NULL;
732
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530733 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530734 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
735 goto exit;
736 }
737
738 pthread_mutex_lock(&qahw_stream_out->lock);
739 out = qahw_stream_out->stream;
740 if (out->get_presentation_position) {
741 rc = out->get_presentation_position(out, frames, timestamp);
742 } else {
743 rc = -ENOSYS;
744 ALOGW("%s not supported", __func__);
745 }
746 pthread_mutex_unlock(&qahw_stream_out->lock);
747
748exit:
749 return rc;
750}
751
752/* Input stream specific APIs */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530753uint32_t qahw_in_get_sample_rate_l(const qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530754{
755 uint32_t rate = 0;
756 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
757 audio_stream_in_t *in = NULL;
758
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530759 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530760 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
761 goto exit;
762 }
763
764 pthread_mutex_lock(&qahw_stream_in->lock);
765 in = qahw_stream_in->stream;
766 if (in->common.get_sample_rate) {
767 rate = in->common.get_sample_rate(&in->common);
768 } else {
769 ALOGW("%s not supported", __func__);
770 }
771 pthread_mutex_unlock(&qahw_stream_in->lock);
772
773exit:
774 return rate;
775}
776
777/*
778 * currently unused - use set_parameters with key
779 * AUDIO_PARAMETER_STREAM_SAMPLING_RATE
780 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530781int qahw_in_set_sample_rate_l(qahw_stream_handle_t *in_handle, uint32_t rate)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530782{
783 int rc = -EINVAL;
784 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
785 audio_stream_in_t *in = NULL;
786
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530787 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530788 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
789 goto exit;
790 }
791
792 pthread_mutex_lock(&qahw_stream_in->lock);
793 in = qahw_stream_in->stream;
794 if (in->common.set_sample_rate) {
795 rc = in->common.set_sample_rate(&in->common, rate);
796 } else {
797 rc = -ENOSYS;
798 ALOGW("%s not supported", __func__);
799 }
800 pthread_mutex_unlock(&qahw_stream_in->lock);
801
802exit:
803 return rc;
804}
805
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530806size_t qahw_in_get_buffer_size_l(const qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530807{
808 size_t buf_size = 0;
809 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
810 audio_stream_in_t *in = NULL;
811
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530812 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530813 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
814 goto exit;
815 }
816
817 pthread_mutex_lock(&qahw_stream_in->lock);
818 in = qahw_stream_in->stream;
819 if (in->common.get_sample_rate) {
820 buf_size = in->common.get_buffer_size(&in->common);
821 } else {
822 ALOGW("%s not supported", __func__);
823 }
824 pthread_mutex_unlock(&qahw_stream_in->lock);
825
826exit:
827 return buf_size;
828}
829
830
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530831audio_channel_mask_t qahw_in_get_channels_l(const qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530832{
833 audio_channel_mask_t ch_mask = 0;;
834 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
835 audio_stream_in_t *in = NULL;
836
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530837 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530838 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
839 goto exit;
840 }
841
842 pthread_mutex_lock(&qahw_stream_in->lock);
843 in = qahw_stream_in->stream;
844 if (in->common.get_channels) {
845 ch_mask = in->common.get_channels(&in->common);
846 } else {
847 ALOGW("%s not supported", __func__);
848 }
849 pthread_mutex_unlock(&qahw_stream_in->lock);
850
851exit:
852 return ch_mask;
853}
854
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530855audio_format_t qahw_in_get_format_l(const qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530856{
857 audio_format_t format = AUDIO_FORMAT_INVALID;
858 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
859 audio_stream_in_t *in = NULL;
860
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530861 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530862 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
863 goto exit;
864 }
865
866 pthread_mutex_lock(&qahw_stream_in->lock);
867 in = qahw_stream_in->stream;
868 if (in->common.get_format) {
869 format = in->common.get_format(&in->common);
870 } else {
871 ALOGW("%s not supported", __func__);
872 }
873 pthread_mutex_unlock(&qahw_stream_in->lock);
874
875exit:
876 return format;
877}
878
879/*
880 * currently unused - use set_parameters with key
881 * AUDIO_PARAMETER_STREAM_FORMAT
882 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530883int qahw_in_set_format_l(qahw_stream_handle_t *in_handle, audio_format_t format)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530884{
885 int rc = -EINVAL;
886 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
887 audio_stream_in_t *in = NULL;
888
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530889 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530890 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
891 goto exit;
892 }
893
894 pthread_mutex_lock(&qahw_stream_in->lock);
895 in = qahw_stream_in->stream;
896 if (in->common.set_format) {
897 rc = in->common.set_format(&in->common, format);
898 } else {
899 rc = -ENOSYS;
900 ALOGW("%s not supported", __func__);
901 }
902 pthread_mutex_unlock(&qahw_stream_in->lock);
903
904exit:
905 return rc;
906}
907
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530908int qahw_in_standby_l(qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530909{
910 int rc = -EINVAL;
911 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
912 audio_stream_in_t *in = NULL;
913
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530914 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530915 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
916 goto exit;
917 }
918
919 pthread_mutex_lock(&qahw_stream_in->lock);
920 in = qahw_stream_in->stream;
921 if (in->common.standby) {
922 rc = in->common.standby(&in->common);
923 } else {
924 rc = -ENOSYS;
925 ALOGW("%s not supported", __func__);
926 }
927 pthread_mutex_unlock(&qahw_stream_in->lock);
928
929exit:
930 return rc;
931}
932
933/*
934 * set/get audio stream parameters. The function accepts a list of
935 * parameter key value pairs in the form: key1=value1;key2=value2;...
936 *
937 * Some keys are reserved for standard parameters (See AudioParameter class)
938 *
939 * If the implementation does not accept a parameter change while
940 * the output is active but the parameter is acceptable otherwise, it must
941 * return -ENOSYS.
942 *
943 * The audio flinger will put the stream in standby and then change the
944 * parameter value.
945 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530946int qahw_in_set_parameters_l(qahw_stream_handle_t *in_handle, const char *kv_pairs)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530947{
948 int rc = -EINVAL;
949 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
950 audio_stream_in_t *in = NULL;
951
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530952 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530953 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
954 goto exit;
955 }
956
957 pthread_mutex_lock(&qahw_stream_in->lock);
958 in = qahw_stream_in->stream;
959 if (in->common.set_parameters) {
960 rc = in->common.set_parameters(&in->common, kv_pairs);
961 } else {
962 rc = -ENOSYS;
963 ALOGW("%s not supported", __func__);
964 }
965 pthread_mutex_unlock(&qahw_stream_in->lock);
966exit:
967 return rc;
968}
969
970/*
971 * Returns a pointer to a heap allocated string. The caller is responsible
972 * for freeing the memory for it using free().
973 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530974char * qahw_in_get_parameters_l(const qahw_stream_handle_t *in_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530975 const char *keys)
976{
977 char *str_param = NULL;
978 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
979 audio_stream_in_t *in = NULL;
980
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530981 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530982 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
983 goto exit;
984 }
985
986 pthread_mutex_lock(&qahw_stream_in->lock);
987 in = qahw_stream_in->stream;
988 if (in->common.get_parameters) {
989 str_param = in->common.get_parameters(&in->common, keys);
990 } else {
991 ALOGW("%s not supported", __func__);
992 }
993 pthread_mutex_unlock(&qahw_stream_in->lock);
994
995exit:
996 return str_param;
997}
998
999/*
1000 * Read audio buffer in from audio driver. Returns number of bytes read, or a
1001 * negative status_t. If at least one frame was read prior to the error,
1002 * read should return that byte count and then return an error in the subsequent call.
1003 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301004ssize_t qahw_in_read_l(qahw_stream_handle_t *in_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301005 qahw_in_buffer_t *in_buf)
1006{
1007 int rc = -EINVAL;
1008 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
1009 audio_stream_in_t *in = NULL;
1010
1011 if ((in_buf == NULL) || (in_buf->buffer == NULL)) {
1012 ALOGE("%s::Invalid meta data %p", __func__, in_buf);
1013 goto exit;
1014 }
1015
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301016 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301017 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
1018 goto exit;
1019 }
1020
1021 pthread_mutex_lock(&qahw_stream_in->lock);
1022 in = qahw_stream_in->stream;
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05301023 if (qahw_stream_in->qahwi_in_read_v2) {
1024 rc = qahw_stream_in->qahwi_in_read_v2(in, in_buf->buffer,
1025 in_buf->bytes, in_buf->timestamp);
1026 in_buf->offset = 0;
1027 } else if (in->read) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301028 rc = in->read(in, in_buf->buffer, in_buf->bytes);
1029 in_buf->offset = 0;
1030 } else {
1031 rc = -ENOSYS;
1032 ALOGW("%s not supported", __func__);
1033 }
1034 pthread_mutex_unlock(&qahw_stream_in->lock);
1035
1036exit:
1037 return rc;
1038}
1039
1040/*
Manish Dewangan46e07982018-12-13 18:18:59 +05301041 * Stop input stream. Returns zero on success.
1042 */
1043int qahw_in_stop_l(qahw_stream_handle_t *in_handle)
1044{
1045 int rc = -EINVAL;
1046 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
1047 audio_stream_in_t *in = NULL;
1048
1049 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
1050 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
1051 goto exit;
1052 }
1053 ALOGD("%s", __func__);
1054
1055 in = qahw_stream_in->stream;
1056
1057 if (qahw_stream_in->qahwi_in_stop)
1058 rc = qahw_stream_in->qahwi_in_stop(in);
1059 ALOGD("%s: exit", __func__);
1060
1061exit:
1062 return rc;
1063}
1064
1065/*
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301066 * Return the amount of input frames lost in the audio driver since the
1067 * last call of this function.
1068 * Audio driver is expected to reset the value to 0 and restart counting
1069 * upon returning the current value by this function call.
1070 * Such loss typically occurs when the user space process is blocked
1071 * longer than the capacity of audio driver buffers.
1072 *
1073 * Unit: the number of input audio frames
1074 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301075uint32_t qahw_in_get_input_frames_lost_l(qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301076{
1077 uint32_t rc = 0;
1078 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
1079 audio_stream_in_t *in = NULL;
1080
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301081 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301082 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
1083 goto exit;
1084 }
1085
1086 pthread_mutex_lock(&qahw_stream_in->lock);
1087 in = qahw_stream_in->stream;
1088 if (in->get_input_frames_lost) {
1089 rc = in->get_input_frames_lost(in);
1090 } else {
1091 rc = -ENOSYS;
1092 ALOGW("%s not supported", __func__);
1093 }
1094 pthread_mutex_unlock(&qahw_stream_in->lock);
1095
1096exit:
1097 return rc;
1098}
1099
1100/*
1101 * Return a recent count of the number of audio frames received and
1102 * the clock time associated with that frame count.
1103 *
1104 * frames is the total frame count received. This should be as early in
1105 * the capture pipeline as possible. In general,
1106 * frames should be non-negative and should not go "backwards".
1107 *
1108 * time is the clock MONOTONIC time when frames was measured. In general,
1109 * time should be a positive quantity and should not go "backwards".
1110 *
1111 * The status returned is 0 on success, -ENOSYS if the device is not
1112 * ready/available, or -EINVAL if the arguments are null or otherwise invalid.
1113 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301114int qahw_in_get_capture_position_l(const qahw_stream_handle_t *in_handle __unused,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301115 int64_t *frames __unused, int64_t *time __unused)
1116{
1117 /*TBD:: do we need this*/
1118 return -ENOSYS;
1119}
1120
1121/*
1122 * check to see if the audio hardware interface has been initialized.
1123 * returns 0 on success, -ENODEV on failure.
1124 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301125int qahw_init_check_l(const qahw_module_handle_t *hw_module)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301126{
1127 int rc = -EINVAL;
1128 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1129 qahw_module_t *qahw_module_temp;
1130
1131 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301132 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301133 pthread_mutex_unlock(&qahw_module_init_lock);
1134 if (qahw_module_temp == NULL) {
1135 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1136 goto exit;
1137 }
1138
1139 pthread_mutex_lock(&qahw_module->lock);
1140 if (qahw_module->audio_device->init_check) {
1141 rc = qahw_module->audio_device->init_check(qahw_module->audio_device);
1142 } else {
1143 rc = -ENOSYS;
1144 ALOGW("%s not supported", __func__);
1145 }
1146 pthread_mutex_unlock(&qahw_module->lock);
1147
1148exit:
1149 return rc;
1150}
1151/* set the audio volume of a voice call. Range is between 0.0 and 1.0 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301152int qahw_set_voice_volume_l(qahw_module_handle_t *hw_module, float volume)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301153{
1154 int rc = -EINVAL;
1155 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1156 qahw_module_t *qahw_module_temp;
1157
1158 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301159 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301160 pthread_mutex_unlock(&qahw_module_init_lock);
1161 if (qahw_module_temp == NULL) {
1162 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1163 goto exit;
1164 }
1165
1166 pthread_mutex_lock(&qahw_module->lock);
1167 if (qahw_module->audio_device->set_voice_volume) {
1168 rc = qahw_module->audio_device->set_voice_volume(qahw_module->audio_device,
1169 volume);
1170 } else {
1171 rc = -ENOSYS;
1172 ALOGW("%s not supported", __func__);
1173 }
1174 pthread_mutex_unlock(&qahw_module->lock);
1175
1176exit:
1177 return rc;
1178}
1179
1180/*
1181 * set_mode is called when the audio mode changes. AUDIO_MODE_NORMAL mode
1182 * is for standard audio playback, AUDIO_MODE_RINGTONE when a ringtone is
1183 * playing, and AUDIO_MODE_IN_CALL when a call is in progress.
1184 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301185int qahw_set_mode_l(qahw_module_handle_t *hw_module, audio_mode_t mode)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301186{
1187 int rc = -EINVAL;
1188 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1189 qahw_module_t *qahw_module_temp;
1190
1191 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301192 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301193 pthread_mutex_unlock(&qahw_module_init_lock);
1194 if (qahw_module_temp == NULL) {
1195 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1196 goto exit;
1197 }
1198
1199 pthread_mutex_lock(&qahw_module->lock);
1200 if (qahw_module->audio_device->set_mode) {
1201 rc = qahw_module->audio_device->set_mode(qahw_module->audio_device,
1202 mode);
1203 } else {
1204 rc = -ENOSYS;
1205 ALOGW("%s not supported", __func__);
1206 }
1207 pthread_mutex_unlock(&qahw_module->lock);
1208
1209exit:
1210 return rc;
1211}
1212
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301213int qahw_set_mic_mute_l(qahw_module_handle_t *hw_module, bool state)
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301214{
1215 int rc = -EINVAL;
1216 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1217 qahw_module_t *qahw_module_temp;
1218
1219 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301220 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301221 pthread_mutex_unlock(&qahw_module_init_lock);
1222 if (qahw_module_temp == NULL) {
1223 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1224 goto exit;
1225 }
1226
1227 pthread_mutex_lock(&qahw_module->lock);
1228 if (qahw_module->audio_device->set_mic_mute) {
1229 rc = qahw_module->audio_device->set_mic_mute(qahw_module->audio_device,
1230 state);
1231 } else {
1232 rc = -ENOSYS;
1233 ALOGW("%s not supported", __func__);
1234 }
1235 pthread_mutex_unlock(&qahw_module->lock);
1236
1237exit:
1238 return rc;
1239}
1240
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301241int qahw_get_mic_mute_l(qahw_module_handle_t *hw_module, bool *state)
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301242{
1243 size_t rc = 0;
1244 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1245 qahw_module_t *qahw_module_temp;
1246 audio_hw_device_t *audio_device;
1247
1248 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301249 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301250 pthread_mutex_unlock(&qahw_module_init_lock);
1251 if (qahw_module_temp == NULL) {
1252 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1253 goto exit;
1254 }
1255
1256 pthread_mutex_lock(&qahw_module->lock);
1257 audio_device = qahw_module->audio_device;
1258 if (qahw_module->audio_device->get_mic_mute) {
Dhananjay Kumar23a3bec2017-01-11 18:38:09 +05301259 rc = audio_device->get_mic_mute(qahw_module->audio_device, state);
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301260 } else {
1261 rc = -ENOSYS;
1262 ALOGW("%s not supported", __func__);
1263 }
1264 pthread_mutex_unlock(&qahw_module->lock);
1265
1266exit:
1267 return rc;
1268}
1269
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301270/* set/get global audio parameters */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301271int qahw_set_parameters_l(qahw_module_handle_t *hw_module, const char *kv_pairs)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301272{
1273 int rc = -EINVAL;
1274 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1275 qahw_module_t *qahw_module_temp;
1276 audio_hw_device_t *audio_device;
1277
1278 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301279 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301280 pthread_mutex_unlock(&qahw_module_init_lock);
1281 if (qahw_module_temp == NULL) {
1282 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1283 goto exit;
1284 }
1285
1286 pthread_mutex_lock(&qahw_module->lock);
1287 audio_device = qahw_module->audio_device;
1288 if (qahw_module->audio_device->set_parameters) {
1289 rc = audio_device->set_parameters(qahw_module->audio_device, kv_pairs);
1290 } else {
1291 rc = -ENOSYS;
1292 ALOGW("%s not supported", __func__);
1293 }
1294 pthread_mutex_unlock(&qahw_module->lock);
1295
1296exit:
1297 return rc;
1298}
1299
1300/*
1301 * Returns a pointer to a heap allocated string. The caller is responsible
1302 * for freeing the memory for it using free().
1303 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301304char * qahw_get_parameters_l(const qahw_module_handle_t *hw_module,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301305 const char *keys)
1306{
1307 char *str_param = NULL;
1308 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1309 qahw_module_t *qahw_module_temp;
1310 audio_hw_device_t *audio_device;
1311
1312 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301313 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301314 pthread_mutex_unlock(&qahw_module_init_lock);
1315 if (qahw_module_temp == NULL) {
1316 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1317 goto exit;
1318 }
1319
1320 pthread_mutex_lock(&qahw_module->lock);
1321 audio_device = qahw_module->audio_device;
1322 if (qahw_module->audio_device->get_parameters) {
1323 str_param = audio_device->get_parameters(qahw_module->audio_device, keys);
1324 } else {
1325 ALOGW("%s not supported", __func__);
1326 }
1327 pthread_mutex_unlock(&qahw_module->lock);
1328
1329exit:
1330 return str_param;
1331}
1332
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301333/* Api to implement get parameters based on keyword param_id
1334 * and store data in payload.
1335 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301336int qahw_get_param_data_l(const qahw_module_handle_t *hw_module,
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301337 qahw_param_id param_id,
1338 qahw_param_payload *payload)
1339{
1340 int ret = 0;
1341 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1342 qahw_module_t *qahw_module_temp;
1343
1344 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301345 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301346 pthread_mutex_unlock(&qahw_module_init_lock);
1347 if (qahw_module_temp == NULL) {
1348 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1349 goto exit;
1350 }
1351
1352 pthread_mutex_lock(&qahw_module->lock);
1353
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301354 if (qahw_module->qahwi_get_param_data){
1355 ret = qahw_module->qahwi_get_param_data (qahw_module->audio_device,
1356 param_id, payload);
1357 } else {
1358 ret = -ENOSYS;
1359 ALOGE("%s not supported\n",__func__);
1360 }
1361 pthread_mutex_unlock(&qahw_module->lock);
1362
1363exit:
1364 return ret;
1365}
1366
1367/* Api to implement set parameters based on keyword param_id
1368 * and data present in payload.
1369 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301370int qahw_set_param_data_l(const qahw_module_handle_t *hw_module,
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301371 qahw_param_id param_id,
1372 qahw_param_payload *payload)
1373{
1374 int ret = 0;
1375 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1376 qahw_module_t *qahw_module_temp;
1377
1378 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301379 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301380 pthread_mutex_unlock(&qahw_module_init_lock);
1381 if (qahw_module_temp == NULL) {
1382 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1383 goto exit;
1384 }
1385
1386 pthread_mutex_lock(&qahw_module->lock);
1387
1388 if (qahw_module->qahwi_set_param_data){
1389 ret = qahw_module->qahwi_set_param_data (qahw_module->audio_device,
1390 param_id, payload);
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301391 } else {
1392 ret = -ENOSYS;
1393 ALOGE("%s not supported\n",__func__);
1394 }
1395 pthread_mutex_unlock(&qahw_module->lock);
1396
1397exit:
1398 return ret;
1399}
1400
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301401/* Creates an audio patch between several source and sink ports.
1402 * The handle is allocated by the HAL and should be unique for this
1403 * audio HAL module.
1404 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301405int qahw_create_audio_patch_l(qahw_module_handle_t *hw_module,
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301406 unsigned int num_sources,
1407 const struct audio_port_config *sources,
1408 unsigned int num_sinks,
1409 const struct audio_port_config *sinks,
1410 audio_patch_handle_t *handle)
1411{
1412 int ret = 0;
1413 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1414 qahw_module_t *qahw_module_temp;
1415
1416 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301417 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301418 pthread_mutex_unlock(&qahw_module_init_lock);
1419 if (qahw_module_temp == NULL) {
1420 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1421 goto exit;
1422 }
1423
1424 pthread_mutex_lock(&qahw_module->lock);
1425 if (qahw_module->audio_device->create_audio_patch) {
1426 ret = qahw_module->audio_device->create_audio_patch(
1427 qahw_module->audio_device,
1428 num_sources,
1429 sources,
1430 num_sinks,
1431 sinks,
1432 handle);
1433 } else {
1434 ret = -ENOSYS;
1435 ALOGE("%s not supported\n",__func__);
1436 }
1437 pthread_mutex_unlock(&qahw_module->lock);
1438
1439exit:
1440 return ret;
1441}
1442
1443/* Release an audio patch */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301444int qahw_release_audio_patch_l(qahw_module_handle_t *hw_module,
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301445 audio_patch_handle_t handle)
1446{
1447 int ret = 0;
1448 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1449 qahw_module_t *qahw_module_temp;
1450
1451 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301452 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301453 pthread_mutex_unlock(&qahw_module_init_lock);
1454 if (qahw_module_temp == NULL) {
1455 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1456 goto exit;
1457 }
1458
1459 pthread_mutex_lock(&qahw_module->lock);
1460 if (qahw_module->audio_device->release_audio_patch) {
1461 ret = qahw_module->audio_device->release_audio_patch(
1462 qahw_module->audio_device,
1463 handle);
1464 } else {
1465 ret = -ENOSYS;
1466 ALOGE("%s not supported\n",__func__);
1467 }
1468 pthread_mutex_unlock(&qahw_module->lock);
1469
1470exit:
1471 return ret;
1472}
1473
Trinath Thammishetty580f1de2018-09-28 12:43:24 +05301474int qahw_loopback_set_param_data_l(qahw_module_handle_t *hw_module,
1475 audio_patch_handle_t handle,
1476 qahw_loopback_param_id param_id,
1477 qahw_loopback_param_payload *payload)
1478
1479{
1480 int ret = -EINVAL;
1481 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1482
1483 if (!payload) {
1484 ALOGE("%s:: invalid param", __func__);
1485 goto exit;
1486 }
1487
1488 if (qahw_module->qahwi_loopback_set_param_data) {
1489 ret = qahw_module->qahwi_loopback_set_param_data(handle,
1490 param_id,
Trinath Thammishetty15cd3402018-10-29 11:57:19 +05301491 payload);
Trinath Thammishetty580f1de2018-09-28 12:43:24 +05301492 } else {
1493 ret = -ENOSYS;
1494 ALOGE("%s not supported\n", __func__);
1495 }
1496
1497exit:
1498 return ret;
1499
1500}
1501
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301502/* Fills the list of supported attributes for a given audio port.
1503 * As input, "port" contains the information (type, role, address etc...)
1504 * needed by the HAL to identify the port.
1505 * As output, "port" contains possible attributes (sampling rates, formats,
1506 * channel masks, gain controllers...) for this port.
1507 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301508int qahw_get_audio_port_l(qahw_module_handle_t *hw_module,
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301509 struct audio_port *port)
1510{
1511 int ret = 0;
1512 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1513 qahw_module_t *qahw_module_temp;
1514
1515 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301516 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301517 pthread_mutex_unlock(&qahw_module_init_lock);
1518 if (qahw_module_temp == NULL) {
1519 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1520 goto exit;
1521 }
1522
1523 pthread_mutex_lock(&qahw_module->lock);
1524 if (qahw_module->audio_device->get_audio_port) {
1525 ret = qahw_module->audio_device->get_audio_port(
1526 qahw_module->audio_device,
1527 port);
1528 } else {
1529 ret = -ENOSYS;
1530 ALOGE("%s not supported\n",__func__);
1531 }
1532 pthread_mutex_unlock(&qahw_module->lock);
1533
1534exit:
1535 return ret;
1536}
1537
1538/* Set audio port configuration */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301539int qahw_set_audio_port_config_l(qahw_module_handle_t *hw_module,
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301540 const struct audio_port_config *config)
1541{
1542 int ret = 0;
1543 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1544 qahw_module_t *qahw_module_temp;
1545
1546 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301547 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301548 pthread_mutex_unlock(&qahw_module_init_lock);
1549 if (qahw_module_temp == NULL) {
1550 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1551 goto exit;
1552 }
1553
1554 pthread_mutex_lock(&qahw_module->lock);
1555 if (qahw_module->audio_device->set_audio_port_config) {
1556 ret = qahw_module->audio_device->set_audio_port_config(
1557 qahw_module->audio_device,
1558 config);
1559 } else {
1560 ret = -ENOSYS;
1561 ALOGE("%s not supported\n",__func__);
1562 }
1563 pthread_mutex_unlock(&qahw_module->lock);
1564
1565exit:
1566 return ret;
1567}
1568
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301569/* Returns audio input buffer size according to parameters passed or
1570 * 0 if one of the parameters is not supported.
1571 * See also get_buffer_size which is for a particular stream.
1572 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301573size_t qahw_get_input_buffer_size_l(const qahw_module_handle_t *hw_module,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301574 const struct audio_config *config)
1575{
1576 size_t rc = 0;
1577 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1578 qahw_module_t *qahw_module_temp;
1579 audio_hw_device_t *audio_device;
1580
1581 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301582 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301583 pthread_mutex_unlock(&qahw_module_init_lock);
1584 if (qahw_module_temp == NULL) {
1585 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1586 goto exit;
1587 }
1588
1589 pthread_mutex_lock(&qahw_module->lock);
1590 audio_device = qahw_module->audio_device;
1591 if (qahw_module->audio_device->get_input_buffer_size) {
1592 rc = audio_device->get_input_buffer_size(qahw_module->audio_device,
1593 config);
1594 } else {
1595 rc = -ENOSYS;
1596 ALOGW("%s not supported", __func__);
1597 }
1598 pthread_mutex_unlock(&qahw_module->lock);
1599
1600exit:
1601 return rc;
1602}
1603
1604/*
1605 * This method creates and opens the audio hardware output stream.
1606 * The "address" parameter qualifies the "devices" audio device type if needed.
1607 * The format format depends on the device type:
1608 * - Bluetooth devices use the MAC address of the device in the form "00:11:22:AA:BB:CC"
1609 * - USB devices use the ALSA card and device numbers in the form "card=X;device=Y"
1610 * - Other devices may use a number or any other string.
1611 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301612int qahw_open_output_stream_l(qahw_module_handle_t *hw_module,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301613 audio_io_handle_t handle,
1614 audio_devices_t devices,
1615 audio_output_flags_t flags,
1616 struct audio_config *config,
1617 qahw_stream_handle_t **out_handle,
1618 const char *address)
1619{
1620 int rc = -EINVAL;
1621 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1622 qahw_module_t *qahw_module_temp = NULL;
1623 audio_hw_device_t *audio_device = NULL;
1624 qahw_stream_out_t *qahw_stream_out = NULL;
1625
1626 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301627 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301628 pthread_mutex_unlock(&qahw_module_init_lock);
1629 if (qahw_module_temp == NULL) {
1630 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1631 return rc;
1632 }
1633
1634 pthread_mutex_lock(&qahw_module->lock);
1635 audio_device = qahw_module->audio_device;
1636 qahw_stream_out = (qahw_stream_out_t *)calloc(1, sizeof(qahw_stream_out_t));
1637 if (qahw_stream_out == NULL) {
1638 ALOGE("%s:: calloc failed for out stream_out_t",__func__);
1639 rc = -ENOMEM;
1640 goto exit;
1641 }
1642
1643 rc = audio_device->open_output_stream(audio_device,
1644 handle,
1645 devices,
1646 flags,
1647 config,
1648 &qahw_stream_out->stream,
1649 address);
1650 if (rc) {
1651 ALOGE("%s::open output stream failed %d",__func__, rc);
1652 free(qahw_stream_out);
1653 } else {
1654 qahw_stream_out->module = hw_module;
1655 *out_handle = (void *)qahw_stream_out;
1656 pthread_mutex_init(&qahw_stream_out->lock, (const pthread_mutexattr_t *)NULL);
1657 list_add_tail(&qahw_module->out_list, &qahw_stream_out->list);
Manish Dewangan3ccdea52017-02-13 19:31:54 +05301658
1659 /* clear any existing errors */
1660 const char *error;
1661 dlerror();
1662 qahw_stream_out->qahwi_out_get_param_data = (qahwi_out_get_param_data_t)
1663 dlsym(qahw_module->module->dso,
1664 "qahwi_out_get_param_data");
1665 if ((error = dlerror()) != NULL) {
1666 ALOGI("%s: dlsym error %s for qahwi_out_get_param_data",
1667 __func__, error);
1668 qahw_stream_out->qahwi_out_get_param_data = NULL;
1669 }
1670
1671 dlerror();
1672 qahw_stream_out->qahwi_out_set_param_data = (qahwi_out_set_param_data_t)
1673 dlsym(qahw_module->module->dso,
1674 "qahwi_out_set_param_data");
1675 if ((error = dlerror()) != NULL) {
1676 ALOGI("%s: dlsym error %s for qahwi_out_set_param_data",
1677 __func__, error);
1678 qahw_stream_out->qahwi_out_set_param_data = NULL;
1679 }
1680}
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301681
Naresh Tanniruee3499a2017-01-05 14:05:35 +05301682 /* dlsym qahwi_out_write_v2 */
1683 if (!rc) {
1684 const char *error;
1685
1686 /* clear any existing errors */
1687 dlerror();
1688 qahw_stream_out->qahwi_out_write_v2 = (qahwi_out_write_v2_t)dlsym(qahw_module->module->dso, "qahwi_out_write_v2");
1689 if ((error = dlerror()) != NULL) {
1690 ALOGI("%s: dlsym error %s for qahwi_out_write_v2", __func__, error);
1691 qahw_stream_out->qahwi_out_write_v2 = NULL;
1692 }
1693 }
1694
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301695exit:
1696 pthread_mutex_unlock(&qahw_module->lock);
1697 return rc;
1698}
1699
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301700int qahw_close_output_stream_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301701{
1702
1703 int rc = 0;
1704 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
1705 qahw_module_t *qahw_module = NULL;
1706 audio_hw_device_t *audio_device = NULL;
1707
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301708 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301709 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
1710 rc = -EINVAL;
1711 goto exit;
1712 }
1713
1714 ALOGV("%s::calling device close_output_stream %p", __func__, out_handle);
1715 pthread_mutex_lock(&qahw_stream_out->lock);
1716 qahw_module = qahw_stream_out->module;
1717 audio_device = qahw_module->audio_device;
1718 audio_device->close_output_stream(audio_device,
1719 qahw_stream_out->stream);
1720
1721 pthread_mutex_lock(&qahw_module->lock);
1722 list_remove(&qahw_stream_out->list);
1723 pthread_mutex_unlock(&qahw_module->lock);
1724
1725 pthread_mutex_unlock(&qahw_stream_out->lock);
1726
1727 pthread_mutex_destroy(&qahw_stream_out->lock);
1728 free(qahw_stream_out);
1729
1730exit:
1731 return rc;
1732}
1733
1734/* This method creates and opens the audio hardware input stream */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301735int qahw_open_input_stream_l(qahw_module_handle_t *hw_module,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301736 audio_io_handle_t handle,
1737 audio_devices_t devices,
1738 struct audio_config *config,
1739 qahw_stream_handle_t **in_handle,
1740 audio_input_flags_t flags,
1741 const char *address,
1742 audio_source_t source)
1743{
1744 int rc = -EINVAL;
1745 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1746 qahw_module_t *qahw_module_temp = NULL;
1747 audio_hw_device_t *audio_device = NULL;
1748 qahw_stream_in_t *qahw_stream_in = NULL;
Manish Dewangan46e07982018-12-13 18:18:59 +05301749 const char *error;
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301750
1751 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301752 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301753 pthread_mutex_unlock(&qahw_module_init_lock);
1754 if (qahw_module_temp == NULL) {
1755 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1756 return rc;
1757 }
1758
1759 pthread_mutex_lock(&qahw_module->lock);
1760 audio_device = qahw_module->audio_device;
1761 qahw_stream_in = (qahw_stream_in_t *)calloc(1, sizeof(qahw_stream_in_t));
1762 if (qahw_stream_in == NULL) {
1763 ALOGE("%s:: calloc failed for in stream_in_t",__func__);
1764 rc = -ENOMEM;
1765 goto exit;
1766 }
1767
1768 rc = audio_device->open_input_stream(audio_device,
1769 handle,
1770 devices,
1771 config,
1772 &qahw_stream_in->stream,
1773 flags,
1774 address,
1775 source);
1776 if (rc) {
1777 ALOGE("%s::open input stream failed %d",__func__, rc);
1778 free(qahw_stream_in);
Manish Dewangan46e07982018-12-13 18:18:59 +05301779 goto exit;
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301780 } else {
1781 qahw_stream_in->module = hw_module;
1782 *in_handle = (void *)qahw_stream_in;
1783 pthread_mutex_init(&qahw_stream_in->lock, (const pthread_mutexattr_t *)NULL);
1784 list_add_tail(&qahw_module->in_list, &qahw_stream_in->list);
1785 }
1786
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05301787 /* dlsym qahwi_in_read_v2 if timestamp flag is used */
Ralf Herzaec80262018-07-03 07:08:49 +02001788 if (!rc && ((flags & QAHW_INPUT_FLAG_TIMESTAMP) ||
1789 (flags & QAHW_INPUT_FLAG_PASSTHROUGH))) {
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05301790
1791 /* clear any existing errors */
1792 dlerror();
1793 qahw_stream_in->qahwi_in_read_v2 = (qahwi_in_read_v2_t)
1794 dlsym(qahw_module->module->dso, "qahwi_in_read_v2");
1795 if ((error = dlerror()) != NULL) {
1796 ALOGI("%s: dlsym error %s for qahwi_in_read_v2", __func__, error);
1797 qahw_stream_in->qahwi_in_read_v2 = NULL;
1798 }
1799 }
1800
Manish Dewangan46e07982018-12-13 18:18:59 +05301801 /* clear any existing errors */
1802 dlerror();
1803 qahw_stream_in->qahwi_in_stop = (qahwi_in_stop_t)
1804 dlsym(qahw_module->module->dso, "qahwi_in_stop");
1805 if ((error = dlerror()) != NULL) {
1806 ALOGI("%s: dlsym error %s for qahwi_in_stop", __func__, error);
1807 qahw_stream_in->qahwi_in_stop = NULL;
1808 }
1809
1810 exit:
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301811 pthread_mutex_unlock(&qahw_module->lock);
1812 return rc;
1813}
1814
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301815int qahw_close_input_stream_l(qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301816{
1817 int rc = 0;
1818 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
1819 qahw_module_t *qahw_module = NULL;
1820 audio_hw_device_t *audio_device = NULL;
1821
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301822 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301823 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
1824 rc = -EINVAL;
1825 goto exit;
1826 }
1827
1828 ALOGV("%s:: calling device close_input_stream %p", __func__, in_handle);
1829 pthread_mutex_lock(&qahw_stream_in->lock);
1830 qahw_module = qahw_stream_in->module;
1831 audio_device = qahw_module->audio_device;
1832 audio_device->close_input_stream(audio_device,
1833 qahw_stream_in->stream);
1834
1835 pthread_mutex_lock(&qahw_module->lock);
1836 list_remove(&qahw_stream_in->list);
1837 pthread_mutex_unlock(&qahw_module->lock);
1838
1839 pthread_mutex_unlock(&qahw_stream_in->lock);
1840
1841 pthread_mutex_destroy(&qahw_stream_in->lock);
1842 free(qahw_stream_in);
1843
1844exit:
1845 return rc;
1846}
1847
1848/*returns current QTI HAL verison */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301849int qahw_get_version_l() {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301850 return QAHW_MODULE_API_VERSION_CURRENT;
1851}
1852
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +05301853/* Load AHAL module to run audio and sva concurrency */
1854static void load_st_hal()
1855{
1856#ifdef SVA_AUDIO_CONC
1857 int rc = -EINVAL;
1858 const hw_module_t* module = NULL;
1859
1860 rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, "primary", &module);
1861 if (rc) {
1862 ALOGE("%s: AHAL Loading failed %d", __func__, rc);
1863 goto error;
1864 }
1865
1866 rc = sound_trigger_hw_device_open(module, &st_hw_device);
1867 if (rc) {
1868 ALOGE("%s: AHAL Device open failed %d", __func__, rc);
1869 st_hw_device = NULL;
1870 }
1871error:
1872 return;
1873#else
1874 return;
1875#endif /*SVA_AUDIO_CONC*/
1876}
1877
1878static void unload_st_hal()
1879{
1880#ifdef SVA_AUDIO_CONC
1881 if (st_hw_device == NULL) {
1882 ALOGE("%s: audio device is NULL",__func__);
1883 return;
1884 }
1885 sound_trigger_hw_device_close(st_hw_device);
1886 st_hw_device = NULL;
1887#else
1888 return;
1889#endif /*SVA_AUDIO_CONC*/
1890}
1891
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301892/* convenience API for opening and closing an audio HAL module */
1893
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301894qahw_module_handle_t *qahw_load_module_l(const char *hw_module_id)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301895{
1896 int rc = -EINVAL;
1897 qahw_module_handle_t *qahw_mod_handle = NULL;
1898 qahw_module_t *qahw_module = NULL;
1899 char *ahal_name = NULL;
1900 const hw_module_t* module = NULL;
1901 audio_hw_device_t* audio_device = NULL;
1902
1903 if (hw_module_id == NULL) {
1904 ALOGE("%s::module id is NULL",__func__);
1905 goto exit;
1906 }
1907
1908 if (!strcmp(hw_module_id, QAHW_MODULE_ID_PRIMARY)) {
1909 ahal_name = "primary";
1910 } else if (!strcmp(hw_module_id, QAHW_MODULE_ID_A2DP)) {
1911 ahal_name = "a2dp";
1912 } else if (!strcmp(hw_module_id, QAHW_MODULE_ID_USB)) {
1913 ahal_name = "usb";
1914 } else {
1915 ALOGE("%s::Invalid Module id %s", __func__, hw_module_id);
1916 goto exit;
1917 }
1918
1919 /* return exiting module ptr if already loaded */
1920 pthread_mutex_lock(&qahw_module_init_lock);
1921 if (qahw_list_count > 0) {
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301922 qahw_module = get_qahw_module_by_name_l(hw_module_id);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301923 if(qahw_module != NULL) {
1924 qahw_mod_handle = (void *)qahw_module;
1925 pthread_mutex_lock(&qahw_module->lock);
1926 qahw_module->ref_count++;
1927 pthread_mutex_unlock(&qahw_module->lock);
1928 goto error_exit;
1929 }
1930 }
1931
1932 rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, ahal_name, &module);
1933 if(rc) {
1934 ALOGE("%s::HAL Loading failed %d", __func__, rc);
1935 goto error_exit;
1936 }
1937
1938 rc = audio_hw_device_open(module, &audio_device);
1939 if(rc) {
1940 ALOGE("%s::HAL Device open failed %d", __func__, rc);
1941 goto error_exit;
1942 }
1943
1944 qahw_module = (qahw_module_t *)calloc(1, sizeof(qahw_module_t));
1945 if(qahw_module == NULL) {
1946 ALOGE("%s::calloc failed", __func__);
1947 audio_hw_device_close(audio_device);
1948 goto error_exit;
1949 }
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05301950 qahw_module->module = module;
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301951 ALOGD("%s::Loaded HAL %s module %p", __func__, ahal_name, qahw_module);
1952
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301953 qahw_module->qahwi_get_param_data = (qahwi_get_param_data_t) dlsym (module->dso,
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301954 "qahwi_get_param_data");
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301955 if (!qahw_module->qahwi_get_param_data)
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301956 ALOGD("%s::qahwi_get_param_data api is not defined\n",__func__);
1957
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301958 qahw_module->qahwi_set_param_data = (qahwi_set_param_data_t) dlsym (module->dso,
1959 "qahwi_set_param_data");
1960 if (!qahw_module->qahwi_set_param_data)
1961 ALOGD("%s::qahwi_set_param_data api is not defined\n",__func__);
1962
Trinath Thammishetty580f1de2018-09-28 12:43:24 +05301963 qahw_module->qahwi_loopback_set_param_data = (qahwi_loopback_set_param_data_t)
1964 dlsym(module->dso,
1965 "qahwi_loopback_set_param_data");
1966 if (!qahw_module->qahwi_loopback_set_param_data)
1967 ALOGD("%s::qahwi_loopback_set_param_data api is not defined\n", __func__);
1968
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301969 if (!qahw_list_count)
1970 list_init(&qahw_module_list);
1971 qahw_list_count++;
1972
1973 pthread_mutex_init(&qahw_module->lock, (const pthread_mutexattr_t *) NULL);
1974 pthread_mutex_lock(&qahw_module->lock);
1975 qahw_module->ref_count++;
1976 pthread_mutex_unlock(&qahw_module->lock);
1977
1978 list_init(&qahw_module->out_list);
1979 list_init(&qahw_module->in_list);
1980
1981 /* update qahw_module */
1982 qahw_module->audio_device = audio_device;
1983 strlcpy(&qahw_module->module_name[0], hw_module_id, MAX_MODULE_NAME_LENGTH);
1984
1985 qahw_mod_handle = (void *)qahw_module;
1986
1987 /* Add module list to global module list */
1988 list_add_tail(&qahw_module_list, &qahw_module->module_list);
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +05301989 load_st_hal();
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301990
1991error_exit:
1992 pthread_mutex_unlock(&qahw_module_init_lock);
1993
1994exit:
1995 return qahw_mod_handle;
1996}
1997
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301998int qahw_unload_module_l(qahw_module_handle_t *hw_module)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301999{
2000 int rc = -EINVAL;
2001 bool is_empty = false;
2002 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
2003 qahw_module_t *qahw_module_temp = NULL;
2004
2005 /* close HW device if its valid and all the streams on
2006 * it is closed
2007 */
2008 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05302009 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05302010 if (qahw_module_temp == NULL) {
2011 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
2012 goto error_exit;
2013 }
2014
2015 pthread_mutex_lock(&qahw_module->lock);
2016 qahw_module->ref_count--;
2017 if (qahw_module->ref_count > 0) {
2018 rc = 0;
2019 ALOGE("%s:: skipping module unload of %p count %d", __func__,
2020 qahw_module,
2021 qahw_module->ref_count);
2022 pthread_mutex_unlock(&qahw_module->lock);
2023 goto error_exit;
2024 }
2025
2026 is_empty = (list_empty(&qahw_module->out_list) &&
2027 list_empty(&qahw_module->in_list));
2028 if (is_empty) {
2029 rc = audio_hw_device_close(qahw_module->audio_device);
2030 if(rc) {
2031 ALOGE("%s::HAL Device close failed Error %d Module %p",__func__,
2032 rc, qahw_module);
2033 rc = 0;
2034 }
2035 qahw_list_count--;
2036 list_remove(&qahw_module->module_list);
2037 pthread_mutex_unlock(&qahw_module->lock);
2038 pthread_mutex_destroy(&qahw_module->lock);
2039 free(qahw_module);
2040 } else {
2041 pthread_mutex_unlock(&qahw_module->lock);
2042 ALOGE("%s::failed as all the streams on this module"
2043 "is not closed", __func__);
2044 rc = -EINVAL;
2045 }
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +05302046 unload_st_hal();
Manish Dewanganb8c83a42016-09-23 15:10:48 +05302047
2048error_exit:
2049 pthread_mutex_unlock(&qahw_module_init_lock);
2050
Manish Dewanganb8c83a42016-09-23 15:10:48 +05302051 return rc;
2052}
2053
2054__END_DECLS