blob: 0502f2f60ccebab79480cfae5876297389255f65 [file] [log] [blame]
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301/*
Zun Qiao9a2c1bc2021-08-11 08:33:36 +05302* Copyright (c) 2016-2021, 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
Zun Qiao9a2c1bc2021-08-11 08:33:36 +053083typedef int (*qahwi_create_audio_patch_v2_t)(const audio_hw_device_t *,
84 qahw_source_port_config_t *source_port_config,
85 qahw_sink_port_config_t *sink_port_config,
86 audio_patch_handle_t *);
87
88typedef int (*qahwi_in_set_param_data_t)(struct audio_stream_in *in,
89 qahw_param_id param_id,
90 qahw_param_payload *payload);
91
Manish Dewanganb8c83a42016-09-23 15:10:48 +053092typedef struct {
93 audio_hw_device_t *audio_device;
94 char module_name[MAX_MODULE_NAME_LENGTH];
95 struct listnode module_list;
96 struct listnode in_list;
97 struct listnode out_list;
98 pthread_mutex_t lock;
99 uint32_t ref_count;
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +0530100 const hw_module_t* module;
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +0530101 qahwi_get_param_data_t qahwi_get_param_data;
102 qahwi_set_param_data_t qahwi_set_param_data;
Trinath Thammishetty580f1de2018-09-28 12:43:24 +0530103 qahwi_loopback_set_param_data_t qahwi_loopback_set_param_data;
Zun Qiao9a2c1bc2021-08-11 08:33:36 +0530104 qahwi_create_audio_patch_v2_t qahwi_create_audio_patch_v2;
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530105} qahw_module_t;
106
107typedef struct {
108 qahw_module_t *module;
109 struct listnode module_list;
110 pthread_mutex_t lock;
111} qahw_module_instances_t;
112
113typedef struct {
114 audio_stream_out_t *stream;
115 qahw_module_t *module;
116 struct listnode list;
117 pthread_mutex_t lock;
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530118 qahwi_out_set_param_data_t qahwi_out_get_param_data;
119 qahwi_out_get_param_data_t qahwi_out_set_param_data;
Naresh Tanniruee3499a2017-01-05 14:05:35 +0530120 qahwi_out_write_v2_t qahwi_out_write_v2;
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530121} qahw_stream_out_t;
122
123typedef struct {
124 audio_stream_in_t *stream;
125 qahw_module_t *module;
126 struct listnode list;
127 pthread_mutex_t lock;
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +0530128 qahwi_in_read_v2_t qahwi_in_read_v2;
Manish Dewangan46e07982018-12-13 18:18:59 +0530129 qahwi_in_stop_t qahwi_in_stop;
Zun Qiao9a2c1bc2021-08-11 08:33:36 +0530130 qahwi_in_set_param_data_t qahwi_in_set_param_data;
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530131} qahw_stream_in_t;
132
133typedef enum {
134 STREAM_DIR_IN,
135 STREAM_DIR_OUT,
136} qahw_stream_direction_t;
137
138static struct listnode qahw_module_list;
139static int qahw_list_count;
140static pthread_mutex_t qahw_module_init_lock = PTHREAD_MUTEX_INITIALIZER;
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +0530141sound_trigger_hw_device_t *st_hw_device = NULL;
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530142
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +0530143
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530144/** Start of internal functions */
145/******************************************************************************/
146
147/* call this function without anylock held */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530148static bool is_valid_qahw_stream_l(void *qahw_stream,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530149 qahw_stream_direction_t dir)
150{
151
152 int is_valid = false;
153 struct listnode *module_node = NULL;
154 struct listnode *stream_node = NULL;
155 struct listnode *list_node = NULL;
156 void *stream = NULL;
157 qahw_module_t *qahw_module = NULL;
158
159 if (qahw_stream == NULL) {
160 ALOGE("%s:: Invalid stream", __func__);
161 goto exit;
162 }
163
164 if ((dir != STREAM_DIR_OUT) && (dir != STREAM_DIR_IN)) {
165 ALOGE("%s:: Invalid stream direction %d", __func__, dir);
166 goto exit;
167 }
168
169 /* go through all the modules and check for valid stream */
170 pthread_mutex_lock(&qahw_module_init_lock);
171 list_for_each(module_node, &qahw_module_list) {
172 qahw_module = node_to_item(module_node, qahw_module_t, module_list);
173 pthread_mutex_lock(&qahw_module->lock);
174 if(dir == STREAM_DIR_OUT)
175 list_node = &qahw_module->out_list;
176 else
177 list_node = &qahw_module->in_list;
178 list_for_each(stream_node, list_node) {
179 if(dir == STREAM_DIR_OUT)
180 stream = (void *)node_to_item(stream_node,
181 qahw_stream_out_t,
182 list);
183 else
184 stream = (void *)node_to_item(stream_node,
185 qahw_stream_in_t,
186 list);
187 if(stream == qahw_stream) {
188 is_valid = true;
189 break;
190 }
191 }
192 pthread_mutex_unlock(&qahw_module->lock);
193 if(is_valid)
194 break;
195 }
196 pthread_mutex_unlock(&qahw_module_init_lock);
197
198exit:
199 return is_valid;
200}
201
202/* call this fucntion with ahw_module_init_lock held*/
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530203static qahw_module_t* get_qahw_module_by_ptr_l(qahw_module_t *qahw_module)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530204{
205 struct listnode *node = NULL;
206 qahw_module_t *module = NULL, *module_temp = NULL;
207
208 if (qahw_module == NULL)
209 goto exit;
210
211 list_for_each(node, &qahw_module_list) {
212 module_temp = node_to_item(node, qahw_module_t, module_list);
213 if (module_temp == qahw_module) {
214 module = module_temp;
215 break;
216 }
217 }
218exit:
219 return module;
220}
221
222/* call this function with qahw_module_init_lock held*/
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530223static qahw_module_t* get_qahw_module_by_name_l(const char *qahw_name)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530224{
225 struct listnode *node = NULL;
226 qahw_module_t *module = NULL, *module_temp = NULL;
227
228 if (qahw_name == NULL)
229 goto exit;
230
231 list_for_each(node, &qahw_module_list) {
232 module_temp = node_to_item(node, qahw_module_t, module_list);
233 if(!strncmp(qahw_name, module_temp->module_name, MAX_MODULE_NAME_LENGTH)) {
234 module = module_temp;
235 break;
236 }
237 }
238exit:
239 return module;
240}
241/* End of of internal functions */
242
243/*
244 * Return the sampling rate in Hz - eg. 44100.
245 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530246uint32_t qahw_out_get_sample_rate_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530247{
248 uint32_t rate = 0;
249 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
250 audio_stream_out_t *out = NULL;
251
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530252 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530253 ALOGV("%s::Invalid out handle %p", __func__, out_handle);
254 goto exit;
255 }
256
257 pthread_mutex_lock(&qahw_stream_out->lock);
258 out = qahw_stream_out->stream;
259 if (out->common.get_sample_rate)
260 rate = out->common.get_sample_rate(&out->common);
261 else
262 ALOGW("%s not supported", __func__);
263 pthread_mutex_unlock(&qahw_stream_out->lock);
264
265exit:
266 return rate;
267}
268
269/*
270 * currently unused - use set_parameters with key
271 * AUDIO_PARAMETER_STREAM_SAMPLING_RATE
272 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530273int qahw_out_set_sample_rate_l(qahw_stream_handle_t *out_handle, uint32_t rate)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530274{
275 int32_t rc = -EINVAL;
276 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
277 audio_stream_out_t *out = NULL;
278
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530279 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530280 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
281 goto exit;
282 }
283 pthread_mutex_lock(&qahw_stream_out->lock);
284 out = qahw_stream_out->stream;
285 if (out->common.set_sample_rate) {
286 rc = out->common.set_sample_rate(&out->common, rate);
287 } else {
288 rc = -ENOSYS;
289 ALOGW("%s not supported", __func__);
290 }
291 pthread_mutex_unlock(&qahw_stream_out->lock);
292exit:
293 return rc;
294}
295
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530296size_t qahw_out_get_buffer_size_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530297{
298 size_t buf_size = 0;
299 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
300 audio_stream_out_t *out = NULL;
301
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530302 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530303 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
304 goto exit;
305 }
306 pthread_mutex_lock(&qahw_stream_out->lock);
307 out = qahw_stream_out->stream;
308 if (out->common.get_buffer_size) {
309 buf_size = out->common.get_buffer_size(&out->common);
310 } else {
311 ALOGW("%s not supported", __func__);
312 }
313 pthread_mutex_unlock(&qahw_stream_out->lock);
314
315exit:
316 return buf_size;
317}
318
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530319audio_channel_mask_t qahw_out_get_channels_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530320{
321 audio_channel_mask_t ch_mask = 0;
322 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
323 audio_stream_out_t *out = NULL;
324
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530325 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530326 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
327 goto exit;
328 }
329 pthread_mutex_lock(&qahw_stream_out->lock);
330 out = qahw_stream_out->stream;
331 if (out->common.get_channels) {
332 ch_mask = out->common.get_channels(&out->common);
333 } else {
334 ALOGW("%s not supported", __func__);
335 }
336 pthread_mutex_unlock(&qahw_stream_out->lock);
337
338exit:
339 return ch_mask;
340}
341
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530342audio_format_t qahw_out_get_format_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530343{
344 audio_format_t format = AUDIO_FORMAT_INVALID;
345 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
346 audio_stream_out_t *out = NULL;
347
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530348 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530349 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
350 goto exit;
351 }
352 pthread_mutex_lock(&qahw_stream_out->lock);
353 out = qahw_stream_out->stream;
354 if (out->common.get_format) {
355 format = out->common.get_format(&out->common);
356 } else {
357 ALOGW("%s not supported", __func__);
358 }
359 pthread_mutex_unlock(&qahw_stream_out->lock);
360
361exit:
362 return format;
363}
364
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530365int qahw_out_standby_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530366{
367 int32_t rc = -EINVAL;
368 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
369 audio_stream_out_t *out = NULL;
370
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530371 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530372 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
373 goto exit;
374 }
375
376 pthread_mutex_lock(&qahw_stream_out->lock);
377 out = qahw_stream_out->stream;
378 if (out->common.standby) {
379 rc = out->common.standby(&out->common);
380 } else {
381 rc = -ENOSYS;
382 ALOGW("%s not supported", __func__);
383 }
384 pthread_mutex_unlock(&qahw_stream_out->lock);
385
386exit:
387 return rc;
388}
389
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530390int qahw_out_set_parameters_l(qahw_stream_handle_t *out_handle, const char *kv_pairs)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530391{
392 int rc = NO_ERROR;
393 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
394 audio_stream_out_t *out = NULL;
395
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530396 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530397 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
398 rc = -EINVAL;
399 goto exit;
400 }
401
402 pthread_mutex_lock(&qahw_stream_out->lock);
403 out = qahw_stream_out->stream;
404 if (out->common.set_parameters) {
405 rc = out->common.set_parameters(&out->common, kv_pairs);
406 } else {
407 rc = -ENOSYS;
408 ALOGW("%s not supported", __func__);
409 }
410 pthread_mutex_unlock(&qahw_stream_out->lock);
411
412exit:
413 return rc;
414}
415
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530416char *qahw_out_get_parameters_l(const qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530417 const char *keys)
418{
419 char *str_param = NULL;
420 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
421 audio_stream_out_t *out = NULL;
422
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530423 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530424 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
425 goto exit;
426 }
427
428 pthread_mutex_lock(&qahw_stream_out->lock);
429 out = qahw_stream_out->stream;
430 if (out->common.get_parameters) {
431 str_param = out->common.get_parameters(&out->common, keys);
432 } else {
433 ALOGW("%s not supported", __func__);
434 }
435 pthread_mutex_unlock(&qahw_stream_out->lock);
436
437exit:
438 return str_param;
439}
440
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530441/* API to get playback stream specific config parameters */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530442int qahw_out_set_param_data_l(qahw_stream_handle_t *out_handle,
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530443 qahw_param_id param_id,
444 qahw_param_payload *payload)
445{
446 int rc = -EINVAL;
447 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
448 audio_stream_out_t *out = NULL;
449
450 if (!payload) {
451 ALOGE("%s::Invalid param", __func__);
452 goto exit;
453 }
454
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530455 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530456 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
457 goto exit;
458 }
459
460 pthread_mutex_lock(&qahw_stream_out->lock);
461 out = qahw_stream_out->stream;
462 if (qahw_stream_out->qahwi_out_set_param_data) {
463 rc = qahw_stream_out->qahwi_out_set_param_data(out, param_id, payload);
464 } else {
465 rc = -ENOSYS;
466 ALOGW("%s not supported", __func__);
467 }
468 pthread_mutex_unlock(&qahw_stream_out->lock);
469
470exit:
471 return rc;
472}
473
474/* API to get playback stream specific config parameters */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530475int qahw_out_get_param_data_l(qahw_stream_handle_t *out_handle,
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530476 qahw_param_id param_id,
477 qahw_param_payload *payload)
478{
479 int rc = -EINVAL;
480 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
481 audio_stream_out_t *out = NULL;
482
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530483 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530484 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
485 goto exit;
486 }
487
488 pthread_mutex_lock(&qahw_stream_out->lock);
489 out = qahw_stream_out->stream;
490 if (qahw_stream_out->qahwi_out_get_param_data) {
491 rc = qahw_stream_out->qahwi_out_get_param_data(out, param_id, payload);
492 } else {
493 rc = -ENOSYS;
494 ALOGW("%s not supported", __func__);
495 }
496 pthread_mutex_unlock(&qahw_stream_out->lock);
497
498exit:
499 return rc;
500}
501
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530502uint32_t qahw_out_get_latency_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530503{
504 uint32_t latency = 0;
505 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
506 audio_stream_out_t *out = NULL;
507
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530508 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530509 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
510 goto exit;
511 }
512
513 pthread_mutex_lock(&qahw_stream_out->lock);
514 out = qahw_stream_out->stream;
515 if (out->get_latency) {
516 latency = out->get_latency(out);
517 } else {
518 ALOGW("%s not supported", __func__);
519 }
520 pthread_mutex_unlock(&qahw_stream_out->lock);
521
522exit:
523 return latency;
524}
525
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530526int qahw_out_set_volume_l(qahw_stream_handle_t *out_handle, float left, float right)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530527{
528 int rc = -EINVAL;
529 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
530 audio_stream_out_t *out = NULL;
531
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530532 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530533 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
534 goto exit;
535 }
536
537 pthread_mutex_lock(&qahw_stream_out->lock);
538 out = qahw_stream_out->stream;
539 if (out->set_volume) {
540 rc = out->set_volume(out, left, right);
541 } else {
542 rc = -ENOSYS;
543 ALOGW("%s not supported", __func__);
544 }
545 pthread_mutex_unlock(&qahw_stream_out->lock);
546
547exit:
548 return rc;
549}
550
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530551ssize_t qahw_out_write_l(qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530552 qahw_out_buffer_t *out_buf)
553{
554 int rc = -EINVAL;
555 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
556 audio_stream_out_t *out = NULL;
557
558 if ((out_buf == NULL) || (out_buf->buffer == NULL)) {
559 ALOGE("%s::Invalid meta data %p", __func__, out_buf);
560 goto exit;
561 }
562
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530563 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530564 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
565 goto exit;
566 }
567
568 /*TBD:: validate other meta data parameters */
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530569 pthread_mutex_lock(&qahw_stream_out->lock);
570 out = qahw_stream_out->stream;
Naresh Tanniruee3499a2017-01-05 14:05:35 +0530571 if (qahw_stream_out->qahwi_out_write_v2) {
572 rc = qahw_stream_out->qahwi_out_write_v2(out, out_buf->buffer,
573 out_buf->bytes, out_buf->timestamp);
574 out_buf->offset = 0;
575 } else if (out->write) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530576 rc = out->write(out, out_buf->buffer, out_buf->bytes);
577 } else {
578 rc = -ENOSYS;
579 ALOGW("%s not supported", __func__);
580 }
581 pthread_mutex_unlock(&qahw_stream_out->lock);
582exit:
583 return rc;
584}
585
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530586int qahw_out_get_render_position_l(const qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530587 uint32_t *dsp_frames)
588{
589 int rc = -EINVAL;
590 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
591 audio_stream_out_t *out = NULL;
592
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530593 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530594 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
595 goto exit;
596 }
597
598 pthread_mutex_lock(&qahw_stream_out->lock);
599 out = qahw_stream_out->stream;
600 if (out->get_render_position) {
601 rc = out->get_render_position(out, dsp_frames);
602 } else {
603 rc = -ENOSYS;
604 ALOGW("%s not supported", __func__);
605 }
606 pthread_mutex_unlock(&qahw_stream_out->lock);
607exit:
608 return rc;
609}
610
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530611int qahw_out_set_callback_l(qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530612 qahw_stream_callback_t callback,
613 void *cookie)
614{
615 /*TBD:load hal func pointer and call */
616 int rc = -EINVAL;
617 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
618 audio_stream_out_t *out = NULL;
619
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530620 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530621 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
622 goto exit;
623 }
624
625 pthread_mutex_lock(&qahw_stream_out->lock);
626 out = qahw_stream_out->stream;
627 if (out->set_callback) {
628 rc = out->set_callback(out, (stream_callback_t)callback, cookie);
629 } else {
630 rc = -ENOSYS;
631 ALOGW("%s not supported", __func__);
632 }
633 pthread_mutex_unlock(&qahw_stream_out->lock);
634
635exit:
636 return rc;
637}
638
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530639int qahw_out_pause_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530640{
641 /*TBD:load hal func pointer and call */
642 int rc = -EINVAL;
643 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
644 audio_stream_out_t *out = NULL;
645
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530646 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530647 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
648 goto exit;
649 }
650
651 pthread_mutex_lock(&qahw_stream_out->lock);
652 out = qahw_stream_out->stream;
653 if (out->pause) {
654 rc = out->pause(out);
655 } else {
656 rc = -ENOSYS;
657 ALOGW("%s not supported", __func__);
658 }
659 pthread_mutex_unlock(&qahw_stream_out->lock);
660
661exit:
662 return rc;
663}
664
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530665int qahw_out_resume_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530666{
667 /*TBD:load hal func pointer and call */
668 int rc = -EINVAL;
669 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
670 audio_stream_out_t *out = NULL;
671
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530672 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530673 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
674 goto exit;
675 }
676
677 pthread_mutex_lock(&qahw_stream_out->lock);
678 out = qahw_stream_out->stream;
679 if (out->resume) {
680 rc = out->resume(out);
681 } else {
682 rc = -ENOSYS;
683 ALOGW("%s not supported", __func__);
684 }
685 pthread_mutex_unlock(&qahw_stream_out->lock);
686
687exit:
688 return rc;
689}
690
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530691int qahw_out_drain_l(qahw_stream_handle_t *out_handle, qahw_drain_type_t type )
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530692{
693 /*TBD:load hal func pointer and call */
694 int rc = -EINVAL;
695 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
696 audio_stream_out_t *out = NULL;
697
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530698 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530699 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
700 goto exit;
701 }
702
703 pthread_mutex_lock(&qahw_stream_out->lock);
704 out = qahw_stream_out->stream;
705 if (out->drain) {
706 rc = out->drain(out,(audio_drain_type_t)type);
707 } else {
708 rc = -ENOSYS;
709 ALOGW("%s not supported", __func__);
710 }
711 pthread_mutex_unlock(&qahw_stream_out->lock);
712
713exit:
714 return rc;
715}
716
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530717int qahw_out_flush_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530718{
719 int rc = -EINVAL;
720 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
721 audio_stream_out_t *out = NULL;
722
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530723 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530724 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
725 goto exit;
726 }
727
728 pthread_mutex_lock(&qahw_stream_out->lock);
729 out = qahw_stream_out->stream;
730 if (out->flush) {
731 rc = out->flush(out);
732 } else {
733 rc = -ENOSYS;
734 ALOGW("%s not supported", __func__);
735 }
736 pthread_mutex_unlock(&qahw_stream_out->lock);
737
738exit:
739 return rc;
740}
741
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530742int qahw_out_get_presentation_position_l(const qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530743 uint64_t *frames, struct timespec *timestamp)
744{
745 int rc = -EINVAL;
746 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
747 audio_stream_out_t *out = NULL;
748
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530749 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530750 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
751 goto exit;
752 }
753
754 pthread_mutex_lock(&qahw_stream_out->lock);
755 out = qahw_stream_out->stream;
756 if (out->get_presentation_position) {
757 rc = out->get_presentation_position(out, frames, timestamp);
758 } else {
759 rc = -ENOSYS;
760 ALOGW("%s not supported", __func__);
761 }
762 pthread_mutex_unlock(&qahw_stream_out->lock);
763
764exit:
765 return rc;
766}
767
768/* Input stream specific APIs */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530769uint32_t qahw_in_get_sample_rate_l(const qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530770{
771 uint32_t rate = 0;
772 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
773 audio_stream_in_t *in = NULL;
774
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530775 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530776 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
777 goto exit;
778 }
779
780 pthread_mutex_lock(&qahw_stream_in->lock);
781 in = qahw_stream_in->stream;
782 if (in->common.get_sample_rate) {
783 rate = in->common.get_sample_rate(&in->common);
784 } else {
785 ALOGW("%s not supported", __func__);
786 }
787 pthread_mutex_unlock(&qahw_stream_in->lock);
788
789exit:
790 return rate;
791}
792
793/*
794 * currently unused - use set_parameters with key
795 * AUDIO_PARAMETER_STREAM_SAMPLING_RATE
796 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530797int qahw_in_set_sample_rate_l(qahw_stream_handle_t *in_handle, uint32_t rate)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530798{
799 int rc = -EINVAL;
800 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
801 audio_stream_in_t *in = NULL;
802
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530803 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530804 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
805 goto exit;
806 }
807
808 pthread_mutex_lock(&qahw_stream_in->lock);
809 in = qahw_stream_in->stream;
810 if (in->common.set_sample_rate) {
811 rc = in->common.set_sample_rate(&in->common, rate);
812 } else {
813 rc = -ENOSYS;
814 ALOGW("%s not supported", __func__);
815 }
816 pthread_mutex_unlock(&qahw_stream_in->lock);
817
818exit:
819 return rc;
820}
821
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530822size_t qahw_in_get_buffer_size_l(const qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530823{
824 size_t buf_size = 0;
825 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
826 audio_stream_in_t *in = NULL;
827
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530828 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530829 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
830 goto exit;
831 }
832
833 pthread_mutex_lock(&qahw_stream_in->lock);
834 in = qahw_stream_in->stream;
835 if (in->common.get_sample_rate) {
836 buf_size = in->common.get_buffer_size(&in->common);
837 } else {
838 ALOGW("%s not supported", __func__);
839 }
840 pthread_mutex_unlock(&qahw_stream_in->lock);
841
842exit:
843 return buf_size;
844}
845
846
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530847audio_channel_mask_t qahw_in_get_channels_l(const qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530848{
849 audio_channel_mask_t ch_mask = 0;;
850 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
851 audio_stream_in_t *in = NULL;
852
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530853 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530854 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
855 goto exit;
856 }
857
858 pthread_mutex_lock(&qahw_stream_in->lock);
859 in = qahw_stream_in->stream;
860 if (in->common.get_channels) {
861 ch_mask = in->common.get_channels(&in->common);
862 } else {
863 ALOGW("%s not supported", __func__);
864 }
865 pthread_mutex_unlock(&qahw_stream_in->lock);
866
867exit:
868 return ch_mask;
869}
870
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530871audio_format_t qahw_in_get_format_l(const qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530872{
873 audio_format_t format = AUDIO_FORMAT_INVALID;
874 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
875 audio_stream_in_t *in = NULL;
876
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530877 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530878 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
879 goto exit;
880 }
881
882 pthread_mutex_lock(&qahw_stream_in->lock);
883 in = qahw_stream_in->stream;
884 if (in->common.get_format) {
885 format = in->common.get_format(&in->common);
886 } else {
887 ALOGW("%s not supported", __func__);
888 }
889 pthread_mutex_unlock(&qahw_stream_in->lock);
890
891exit:
892 return format;
893}
894
895/*
896 * currently unused - use set_parameters with key
897 * AUDIO_PARAMETER_STREAM_FORMAT
898 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530899int qahw_in_set_format_l(qahw_stream_handle_t *in_handle, audio_format_t format)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530900{
901 int rc = -EINVAL;
902 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
903 audio_stream_in_t *in = NULL;
904
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530905 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530906 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
907 goto exit;
908 }
909
910 pthread_mutex_lock(&qahw_stream_in->lock);
911 in = qahw_stream_in->stream;
912 if (in->common.set_format) {
913 rc = in->common.set_format(&in->common, format);
914 } else {
915 rc = -ENOSYS;
916 ALOGW("%s not supported", __func__);
917 }
918 pthread_mutex_unlock(&qahw_stream_in->lock);
919
920exit:
921 return rc;
922}
923
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530924int qahw_in_standby_l(qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530925{
926 int rc = -EINVAL;
927 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
928 audio_stream_in_t *in = NULL;
929
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530930 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530931 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
932 goto exit;
933 }
934
935 pthread_mutex_lock(&qahw_stream_in->lock);
936 in = qahw_stream_in->stream;
937 if (in->common.standby) {
938 rc = in->common.standby(&in->common);
939 } else {
940 rc = -ENOSYS;
941 ALOGW("%s not supported", __func__);
942 }
943 pthread_mutex_unlock(&qahw_stream_in->lock);
944
945exit:
946 return rc;
947}
948
949/*
950 * set/get audio stream parameters. The function accepts a list of
951 * parameter key value pairs in the form: key1=value1;key2=value2;...
952 *
953 * Some keys are reserved for standard parameters (See AudioParameter class)
954 *
955 * If the implementation does not accept a parameter change while
956 * the output is active but the parameter is acceptable otherwise, it must
957 * return -ENOSYS.
958 *
959 * The audio flinger will put the stream in standby and then change the
960 * parameter value.
961 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530962int qahw_in_set_parameters_l(qahw_stream_handle_t *in_handle, const char *kv_pairs)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530963{
964 int rc = -EINVAL;
965 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
966 audio_stream_in_t *in = NULL;
967
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530968 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530969 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
970 goto exit;
971 }
972
973 pthread_mutex_lock(&qahw_stream_in->lock);
974 in = qahw_stream_in->stream;
975 if (in->common.set_parameters) {
976 rc = in->common.set_parameters(&in->common, kv_pairs);
977 } else {
978 rc = -ENOSYS;
979 ALOGW("%s not supported", __func__);
980 }
981 pthread_mutex_unlock(&qahw_stream_in->lock);
982exit:
983 return rc;
984}
985
986/*
987 * Returns a pointer to a heap allocated string. The caller is responsible
988 * for freeing the memory for it using free().
989 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530990char * qahw_in_get_parameters_l(const qahw_stream_handle_t *in_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530991 const char *keys)
992{
993 char *str_param = NULL;
994 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
995 audio_stream_in_t *in = NULL;
996
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530997 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530998 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
999 goto exit;
1000 }
1001
1002 pthread_mutex_lock(&qahw_stream_in->lock);
1003 in = qahw_stream_in->stream;
1004 if (in->common.get_parameters) {
1005 str_param = in->common.get_parameters(&in->common, keys);
1006 } else {
1007 ALOGW("%s not supported", __func__);
1008 }
1009 pthread_mutex_unlock(&qahw_stream_in->lock);
1010
1011exit:
1012 return str_param;
1013}
1014
Zun Qiao9a2c1bc2021-08-11 08:33:36 +05301015/* API to get capture stream specific config parameters */
1016int qahw_in_set_param_data_l(qahw_stream_handle_t *in_handle,
1017 qahw_param_id param_id,
1018 qahw_param_payload *payload)
1019{
1020 int rc = -EINVAL;
1021 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
1022 audio_stream_in_t *in = NULL;
1023
1024 if (!payload) {
1025 ALOGE("%s::Invalid param", __func__);
1026 goto exit;
1027 }
1028
1029 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
1030 ALOGE("%s::Invalid in handle %p", __func__, in_handle);
1031 goto exit;
1032 }
1033
1034 pthread_mutex_lock(&qahw_stream_in->lock);
1035 in = qahw_stream_in->stream;
1036 if (qahw_stream_in->qahwi_in_set_param_data) {
1037 rc = qahw_stream_in->qahwi_in_set_param_data(in, param_id, payload);
1038 } else {
1039 rc = -ENOSYS;
1040 ALOGW("%s not supported", __func__);
1041 }
1042 pthread_mutex_unlock(&qahw_stream_in->lock);
1043
1044exit:
1045 return rc;
1046}
1047
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301048/*
1049 * Read audio buffer in from audio driver. Returns number of bytes read, or a
1050 * negative status_t. If at least one frame was read prior to the error,
1051 * read should return that byte count and then return an error in the subsequent call.
1052 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301053ssize_t qahw_in_read_l(qahw_stream_handle_t *in_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301054 qahw_in_buffer_t *in_buf)
1055{
1056 int rc = -EINVAL;
1057 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
1058 audio_stream_in_t *in = NULL;
1059
1060 if ((in_buf == NULL) || (in_buf->buffer == NULL)) {
1061 ALOGE("%s::Invalid meta data %p", __func__, in_buf);
1062 goto exit;
1063 }
1064
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301065 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301066 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
1067 goto exit;
1068 }
1069
1070 pthread_mutex_lock(&qahw_stream_in->lock);
1071 in = qahw_stream_in->stream;
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05301072 if (qahw_stream_in->qahwi_in_read_v2) {
1073 rc = qahw_stream_in->qahwi_in_read_v2(in, in_buf->buffer,
1074 in_buf->bytes, in_buf->timestamp);
1075 in_buf->offset = 0;
1076 } else if (in->read) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301077 rc = in->read(in, in_buf->buffer, in_buf->bytes);
1078 in_buf->offset = 0;
1079 } else {
1080 rc = -ENOSYS;
1081 ALOGW("%s not supported", __func__);
1082 }
1083 pthread_mutex_unlock(&qahw_stream_in->lock);
1084
1085exit:
1086 return rc;
1087}
1088
1089/*
Manish Dewangan46e07982018-12-13 18:18:59 +05301090 * Stop input stream. Returns zero on success.
1091 */
1092int qahw_in_stop_l(qahw_stream_handle_t *in_handle)
1093{
1094 int rc = -EINVAL;
1095 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
1096 audio_stream_in_t *in = NULL;
1097
1098 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
1099 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
1100 goto exit;
1101 }
1102 ALOGD("%s", __func__);
1103
1104 in = qahw_stream_in->stream;
1105
1106 if (qahw_stream_in->qahwi_in_stop)
1107 rc = qahw_stream_in->qahwi_in_stop(in);
1108 ALOGD("%s: exit", __func__);
1109
1110exit:
1111 return rc;
1112}
1113
1114/*
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301115 * Return the amount of input frames lost in the audio driver since the
1116 * last call of this function.
1117 * Audio driver is expected to reset the value to 0 and restart counting
1118 * upon returning the current value by this function call.
1119 * Such loss typically occurs when the user space process is blocked
1120 * longer than the capacity of audio driver buffers.
1121 *
1122 * Unit: the number of input audio frames
1123 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301124uint32_t qahw_in_get_input_frames_lost_l(qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301125{
1126 uint32_t rc = 0;
1127 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
1128 audio_stream_in_t *in = NULL;
1129
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301130 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301131 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
1132 goto exit;
1133 }
1134
1135 pthread_mutex_lock(&qahw_stream_in->lock);
1136 in = qahw_stream_in->stream;
1137 if (in->get_input_frames_lost) {
1138 rc = in->get_input_frames_lost(in);
1139 } else {
1140 rc = -ENOSYS;
1141 ALOGW("%s not supported", __func__);
1142 }
1143 pthread_mutex_unlock(&qahw_stream_in->lock);
1144
1145exit:
1146 return rc;
1147}
1148
1149/*
1150 * Return a recent count of the number of audio frames received and
1151 * the clock time associated with that frame count.
1152 *
1153 * frames is the total frame count received. This should be as early in
1154 * the capture pipeline as possible. In general,
1155 * frames should be non-negative and should not go "backwards".
1156 *
1157 * time is the clock MONOTONIC time when frames was measured. In general,
1158 * time should be a positive quantity and should not go "backwards".
1159 *
1160 * The status returned is 0 on success, -ENOSYS if the device is not
1161 * ready/available, or -EINVAL if the arguments are null or otherwise invalid.
1162 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301163int qahw_in_get_capture_position_l(const qahw_stream_handle_t *in_handle __unused,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301164 int64_t *frames __unused, int64_t *time __unused)
1165{
1166 /*TBD:: do we need this*/
1167 return -ENOSYS;
1168}
1169
1170/*
1171 * check to see if the audio hardware interface has been initialized.
1172 * returns 0 on success, -ENODEV on failure.
1173 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301174int qahw_init_check_l(const qahw_module_handle_t *hw_module)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301175{
1176 int rc = -EINVAL;
1177 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1178 qahw_module_t *qahw_module_temp;
1179
1180 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301181 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301182 pthread_mutex_unlock(&qahw_module_init_lock);
1183 if (qahw_module_temp == NULL) {
1184 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1185 goto exit;
1186 }
1187
1188 pthread_mutex_lock(&qahw_module->lock);
1189 if (qahw_module->audio_device->init_check) {
1190 rc = qahw_module->audio_device->init_check(qahw_module->audio_device);
1191 } else {
1192 rc = -ENOSYS;
1193 ALOGW("%s not supported", __func__);
1194 }
1195 pthread_mutex_unlock(&qahw_module->lock);
1196
1197exit:
1198 return rc;
1199}
1200/* set the audio volume of a voice call. Range is between 0.0 and 1.0 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301201int qahw_set_voice_volume_l(qahw_module_handle_t *hw_module, float volume)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301202{
1203 int rc = -EINVAL;
1204 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1205 qahw_module_t *qahw_module_temp;
1206
1207 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301208 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301209 pthread_mutex_unlock(&qahw_module_init_lock);
1210 if (qahw_module_temp == NULL) {
1211 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1212 goto exit;
1213 }
1214
1215 pthread_mutex_lock(&qahw_module->lock);
1216 if (qahw_module->audio_device->set_voice_volume) {
1217 rc = qahw_module->audio_device->set_voice_volume(qahw_module->audio_device,
1218 volume);
1219 } else {
1220 rc = -ENOSYS;
1221 ALOGW("%s not supported", __func__);
1222 }
1223 pthread_mutex_unlock(&qahw_module->lock);
1224
1225exit:
1226 return rc;
1227}
1228
1229/*
1230 * set_mode is called when the audio mode changes. AUDIO_MODE_NORMAL mode
1231 * is for standard audio playback, AUDIO_MODE_RINGTONE when a ringtone is
1232 * playing, and AUDIO_MODE_IN_CALL when a call is in progress.
1233 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301234int qahw_set_mode_l(qahw_module_handle_t *hw_module, audio_mode_t mode)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301235{
1236 int rc = -EINVAL;
1237 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1238 qahw_module_t *qahw_module_temp;
1239
1240 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301241 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301242 pthread_mutex_unlock(&qahw_module_init_lock);
1243 if (qahw_module_temp == NULL) {
1244 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1245 goto exit;
1246 }
1247
1248 pthread_mutex_lock(&qahw_module->lock);
1249 if (qahw_module->audio_device->set_mode) {
1250 rc = qahw_module->audio_device->set_mode(qahw_module->audio_device,
1251 mode);
1252 } else {
1253 rc = -ENOSYS;
1254 ALOGW("%s not supported", __func__);
1255 }
1256 pthread_mutex_unlock(&qahw_module->lock);
1257
1258exit:
1259 return rc;
1260}
1261
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301262int qahw_set_mic_mute_l(qahw_module_handle_t *hw_module, bool state)
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301263{
1264 int rc = -EINVAL;
1265 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1266 qahw_module_t *qahw_module_temp;
1267
1268 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301269 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301270 pthread_mutex_unlock(&qahw_module_init_lock);
1271 if (qahw_module_temp == NULL) {
1272 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1273 goto exit;
1274 }
1275
1276 pthread_mutex_lock(&qahw_module->lock);
1277 if (qahw_module->audio_device->set_mic_mute) {
1278 rc = qahw_module->audio_device->set_mic_mute(qahw_module->audio_device,
1279 state);
1280 } else {
1281 rc = -ENOSYS;
1282 ALOGW("%s not supported", __func__);
1283 }
1284 pthread_mutex_unlock(&qahw_module->lock);
1285
1286exit:
1287 return rc;
1288}
1289
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301290int qahw_get_mic_mute_l(qahw_module_handle_t *hw_module, bool *state)
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301291{
1292 size_t rc = 0;
1293 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1294 qahw_module_t *qahw_module_temp;
1295 audio_hw_device_t *audio_device;
1296
1297 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301298 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301299 pthread_mutex_unlock(&qahw_module_init_lock);
1300 if (qahw_module_temp == NULL) {
1301 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1302 goto exit;
1303 }
1304
1305 pthread_mutex_lock(&qahw_module->lock);
1306 audio_device = qahw_module->audio_device;
1307 if (qahw_module->audio_device->get_mic_mute) {
Dhananjay Kumar23a3bec2017-01-11 18:38:09 +05301308 rc = audio_device->get_mic_mute(qahw_module->audio_device, state);
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301309 } else {
1310 rc = -ENOSYS;
1311 ALOGW("%s not supported", __func__);
1312 }
1313 pthread_mutex_unlock(&qahw_module->lock);
1314
1315exit:
1316 return rc;
1317}
1318
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301319/* set/get global audio parameters */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301320int qahw_set_parameters_l(qahw_module_handle_t *hw_module, const char *kv_pairs)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301321{
1322 int rc = -EINVAL;
1323 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1324 qahw_module_t *qahw_module_temp;
1325 audio_hw_device_t *audio_device;
1326
1327 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301328 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301329 pthread_mutex_unlock(&qahw_module_init_lock);
1330 if (qahw_module_temp == NULL) {
1331 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1332 goto exit;
1333 }
1334
1335 pthread_mutex_lock(&qahw_module->lock);
1336 audio_device = qahw_module->audio_device;
1337 if (qahw_module->audio_device->set_parameters) {
1338 rc = audio_device->set_parameters(qahw_module->audio_device, kv_pairs);
1339 } else {
1340 rc = -ENOSYS;
1341 ALOGW("%s not supported", __func__);
1342 }
1343 pthread_mutex_unlock(&qahw_module->lock);
1344
1345exit:
1346 return rc;
1347}
1348
1349/*
1350 * Returns a pointer to a heap allocated string. The caller is responsible
1351 * for freeing the memory for it using free().
1352 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301353char * qahw_get_parameters_l(const qahw_module_handle_t *hw_module,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301354 const char *keys)
1355{
1356 char *str_param = NULL;
1357 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1358 qahw_module_t *qahw_module_temp;
1359 audio_hw_device_t *audio_device;
1360
1361 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301362 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301363 pthread_mutex_unlock(&qahw_module_init_lock);
1364 if (qahw_module_temp == NULL) {
1365 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1366 goto exit;
1367 }
1368
1369 pthread_mutex_lock(&qahw_module->lock);
1370 audio_device = qahw_module->audio_device;
1371 if (qahw_module->audio_device->get_parameters) {
1372 str_param = audio_device->get_parameters(qahw_module->audio_device, keys);
1373 } else {
1374 ALOGW("%s not supported", __func__);
1375 }
1376 pthread_mutex_unlock(&qahw_module->lock);
1377
1378exit:
1379 return str_param;
1380}
1381
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301382/* Api to implement get parameters based on keyword param_id
1383 * and store data in payload.
1384 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301385int qahw_get_param_data_l(const qahw_module_handle_t *hw_module,
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301386 qahw_param_id param_id,
1387 qahw_param_payload *payload)
1388{
1389 int ret = 0;
1390 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1391 qahw_module_t *qahw_module_temp;
1392
1393 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301394 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301395 pthread_mutex_unlock(&qahw_module_init_lock);
1396 if (qahw_module_temp == NULL) {
1397 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1398 goto exit;
1399 }
1400
1401 pthread_mutex_lock(&qahw_module->lock);
1402
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301403 if (qahw_module->qahwi_get_param_data){
1404 ret = qahw_module->qahwi_get_param_data (qahw_module->audio_device,
1405 param_id, payload);
1406 } else {
1407 ret = -ENOSYS;
1408 ALOGE("%s not supported\n",__func__);
1409 }
1410 pthread_mutex_unlock(&qahw_module->lock);
1411
1412exit:
1413 return ret;
1414}
1415
1416/* Api to implement set parameters based on keyword param_id
1417 * and data present in payload.
1418 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301419int qahw_set_param_data_l(const qahw_module_handle_t *hw_module,
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301420 qahw_param_id param_id,
1421 qahw_param_payload *payload)
1422{
1423 int ret = 0;
1424 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1425 qahw_module_t *qahw_module_temp;
1426
1427 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301428 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301429 pthread_mutex_unlock(&qahw_module_init_lock);
1430 if (qahw_module_temp == NULL) {
1431 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1432 goto exit;
1433 }
1434
1435 pthread_mutex_lock(&qahw_module->lock);
1436
1437 if (qahw_module->qahwi_set_param_data){
1438 ret = qahw_module->qahwi_set_param_data (qahw_module->audio_device,
1439 param_id, payload);
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301440 } else {
1441 ret = -ENOSYS;
1442 ALOGE("%s not supported\n",__func__);
1443 }
1444 pthread_mutex_unlock(&qahw_module->lock);
1445
1446exit:
1447 return ret;
1448}
1449
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301450/* Creates an audio patch between several source and sink ports.
1451 * The handle is allocated by the HAL and should be unique for this
1452 * audio HAL module.
1453 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301454int qahw_create_audio_patch_l(qahw_module_handle_t *hw_module,
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301455 unsigned int num_sources,
1456 const struct audio_port_config *sources,
1457 unsigned int num_sinks,
1458 const struct audio_port_config *sinks,
1459 audio_patch_handle_t *handle)
1460{
1461 int ret = 0;
1462 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1463 qahw_module_t *qahw_module_temp;
1464
1465 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301466 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301467 pthread_mutex_unlock(&qahw_module_init_lock);
1468 if (qahw_module_temp == NULL) {
1469 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1470 goto exit;
1471 }
1472
1473 pthread_mutex_lock(&qahw_module->lock);
1474 if (qahw_module->audio_device->create_audio_patch) {
1475 ret = qahw_module->audio_device->create_audio_patch(
1476 qahw_module->audio_device,
1477 num_sources,
1478 sources,
1479 num_sinks,
1480 sinks,
1481 handle);
1482 } else {
1483 ret = -ENOSYS;
1484 ALOGE("%s not supported\n",__func__);
1485 }
1486 pthread_mutex_unlock(&qahw_module->lock);
1487
1488exit:
1489 return ret;
1490}
1491
Zun Qiao9a2c1bc2021-08-11 08:33:36 +05301492int qahw_create_audio_patch_v2_l(qahw_module_handle_t *hw_module,
1493 qahw_source_port_config_t *source_port_config,
1494 qahw_sink_port_config_t *sink_port_config,
1495 audio_patch_handle_t *handle)
1496{
1497 int ret = 0;
1498 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1499 qahw_module_t *qahw_module_temp;
1500
1501 pthread_mutex_lock(&qahw_module_init_lock);
1502 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
1503 pthread_mutex_unlock(&qahw_module_init_lock);
1504 if (qahw_module_temp == NULL) {
1505 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1506 goto exit;
1507 }
1508
1509 pthread_mutex_lock(&qahw_module->lock);
1510
1511 if (qahw_module->qahwi_create_audio_patch_v2){
1512 ret = qahw_module->qahwi_create_audio_patch_v2(qahw_module->audio_device,
1513 source_port_config, sink_port_config, handle);
1514 } else {
1515 ret = -ENOSYS;
1516 ALOGE("%s not supported\n",__func__);
1517 }
1518 pthread_mutex_unlock(&qahw_module->lock);
1519
1520exit:
1521 return ret;
1522}
1523
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301524/* Release an audio patch */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301525int qahw_release_audio_patch_l(qahw_module_handle_t *hw_module,
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301526 audio_patch_handle_t handle)
1527{
1528 int ret = 0;
1529 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1530 qahw_module_t *qahw_module_temp;
1531
1532 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301533 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301534 pthread_mutex_unlock(&qahw_module_init_lock);
1535 if (qahw_module_temp == NULL) {
1536 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1537 goto exit;
1538 }
1539
1540 pthread_mutex_lock(&qahw_module->lock);
1541 if (qahw_module->audio_device->release_audio_patch) {
1542 ret = qahw_module->audio_device->release_audio_patch(
1543 qahw_module->audio_device,
1544 handle);
1545 } else {
1546 ret = -ENOSYS;
1547 ALOGE("%s not supported\n",__func__);
1548 }
1549 pthread_mutex_unlock(&qahw_module->lock);
1550
1551exit:
1552 return ret;
1553}
1554
Trinath Thammishetty580f1de2018-09-28 12:43:24 +05301555int qahw_loopback_set_param_data_l(qahw_module_handle_t *hw_module,
1556 audio_patch_handle_t handle,
1557 qahw_loopback_param_id param_id,
1558 qahw_loopback_param_payload *payload)
1559
1560{
1561 int ret = -EINVAL;
1562 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1563
1564 if (!payload) {
1565 ALOGE("%s:: invalid param", __func__);
1566 goto exit;
1567 }
1568
1569 if (qahw_module->qahwi_loopback_set_param_data) {
1570 ret = qahw_module->qahwi_loopback_set_param_data(handle,
1571 param_id,
Trinath Thammishetty15cd3402018-10-29 11:57:19 +05301572 payload);
Trinath Thammishetty580f1de2018-09-28 12:43:24 +05301573 } else {
1574 ret = -ENOSYS;
1575 ALOGE("%s not supported\n", __func__);
1576 }
1577
1578exit:
1579 return ret;
1580
1581}
1582
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301583/* Fills the list of supported attributes for a given audio port.
1584 * As input, "port" contains the information (type, role, address etc...)
1585 * needed by the HAL to identify the port.
1586 * As output, "port" contains possible attributes (sampling rates, formats,
1587 * channel masks, gain controllers...) for this port.
1588 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301589int qahw_get_audio_port_l(qahw_module_handle_t *hw_module,
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301590 struct audio_port *port)
1591{
1592 int ret = 0;
1593 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1594 qahw_module_t *qahw_module_temp;
1595
1596 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301597 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301598 pthread_mutex_unlock(&qahw_module_init_lock);
1599 if (qahw_module_temp == NULL) {
1600 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1601 goto exit;
1602 }
1603
1604 pthread_mutex_lock(&qahw_module->lock);
1605 if (qahw_module->audio_device->get_audio_port) {
1606 ret = qahw_module->audio_device->get_audio_port(
1607 qahw_module->audio_device,
1608 port);
1609 } else {
1610 ret = -ENOSYS;
1611 ALOGE("%s not supported\n",__func__);
1612 }
1613 pthread_mutex_unlock(&qahw_module->lock);
1614
1615exit:
1616 return ret;
1617}
1618
1619/* Set audio port configuration */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301620int qahw_set_audio_port_config_l(qahw_module_handle_t *hw_module,
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301621 const struct audio_port_config *config)
1622{
1623 int ret = 0;
1624 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1625 qahw_module_t *qahw_module_temp;
1626
1627 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301628 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301629 pthread_mutex_unlock(&qahw_module_init_lock);
1630 if (qahw_module_temp == NULL) {
1631 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1632 goto exit;
1633 }
1634
1635 pthread_mutex_lock(&qahw_module->lock);
1636 if (qahw_module->audio_device->set_audio_port_config) {
1637 ret = qahw_module->audio_device->set_audio_port_config(
1638 qahw_module->audio_device,
1639 config);
1640 } else {
1641 ret = -ENOSYS;
1642 ALOGE("%s not supported\n",__func__);
1643 }
1644 pthread_mutex_unlock(&qahw_module->lock);
1645
1646exit:
1647 return ret;
1648}
1649
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301650/* Returns audio input buffer size according to parameters passed or
1651 * 0 if one of the parameters is not supported.
1652 * See also get_buffer_size which is for a particular stream.
1653 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301654size_t qahw_get_input_buffer_size_l(const qahw_module_handle_t *hw_module,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301655 const struct audio_config *config)
1656{
1657 size_t rc = 0;
1658 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1659 qahw_module_t *qahw_module_temp;
1660 audio_hw_device_t *audio_device;
1661
1662 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301663 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301664 pthread_mutex_unlock(&qahw_module_init_lock);
1665 if (qahw_module_temp == NULL) {
1666 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1667 goto exit;
1668 }
1669
1670 pthread_mutex_lock(&qahw_module->lock);
1671 audio_device = qahw_module->audio_device;
1672 if (qahw_module->audio_device->get_input_buffer_size) {
1673 rc = audio_device->get_input_buffer_size(qahw_module->audio_device,
1674 config);
1675 } else {
1676 rc = -ENOSYS;
1677 ALOGW("%s not supported", __func__);
1678 }
1679 pthread_mutex_unlock(&qahw_module->lock);
1680
1681exit:
1682 return rc;
1683}
1684
1685/*
1686 * This method creates and opens the audio hardware output stream.
1687 * The "address" parameter qualifies the "devices" audio device type if needed.
1688 * The format format depends on the device type:
1689 * - Bluetooth devices use the MAC address of the device in the form "00:11:22:AA:BB:CC"
1690 * - USB devices use the ALSA card and device numbers in the form "card=X;device=Y"
1691 * - Other devices may use a number or any other string.
1692 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301693int qahw_open_output_stream_l(qahw_module_handle_t *hw_module,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301694 audio_io_handle_t handle,
1695 audio_devices_t devices,
1696 audio_output_flags_t flags,
1697 struct audio_config *config,
1698 qahw_stream_handle_t **out_handle,
1699 const char *address)
1700{
1701 int rc = -EINVAL;
1702 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1703 qahw_module_t *qahw_module_temp = NULL;
1704 audio_hw_device_t *audio_device = NULL;
1705 qahw_stream_out_t *qahw_stream_out = NULL;
1706
1707 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301708 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301709 pthread_mutex_unlock(&qahw_module_init_lock);
1710 if (qahw_module_temp == NULL) {
1711 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1712 return rc;
1713 }
1714
1715 pthread_mutex_lock(&qahw_module->lock);
1716 audio_device = qahw_module->audio_device;
1717 qahw_stream_out = (qahw_stream_out_t *)calloc(1, sizeof(qahw_stream_out_t));
1718 if (qahw_stream_out == NULL) {
1719 ALOGE("%s:: calloc failed for out stream_out_t",__func__);
1720 rc = -ENOMEM;
1721 goto exit;
1722 }
1723
1724 rc = audio_device->open_output_stream(audio_device,
1725 handle,
1726 devices,
1727 flags,
1728 config,
1729 &qahw_stream_out->stream,
1730 address);
1731 if (rc) {
1732 ALOGE("%s::open output stream failed %d",__func__, rc);
1733 free(qahw_stream_out);
1734 } else {
1735 qahw_stream_out->module = hw_module;
1736 *out_handle = (void *)qahw_stream_out;
1737 pthread_mutex_init(&qahw_stream_out->lock, (const pthread_mutexattr_t *)NULL);
1738 list_add_tail(&qahw_module->out_list, &qahw_stream_out->list);
Manish Dewangan3ccdea52017-02-13 19:31:54 +05301739
1740 /* clear any existing errors */
1741 const char *error;
1742 dlerror();
1743 qahw_stream_out->qahwi_out_get_param_data = (qahwi_out_get_param_data_t)
1744 dlsym(qahw_module->module->dso,
1745 "qahwi_out_get_param_data");
1746 if ((error = dlerror()) != NULL) {
1747 ALOGI("%s: dlsym error %s for qahwi_out_get_param_data",
1748 __func__, error);
1749 qahw_stream_out->qahwi_out_get_param_data = NULL;
1750 }
1751
1752 dlerror();
1753 qahw_stream_out->qahwi_out_set_param_data = (qahwi_out_set_param_data_t)
1754 dlsym(qahw_module->module->dso,
1755 "qahwi_out_set_param_data");
1756 if ((error = dlerror()) != NULL) {
1757 ALOGI("%s: dlsym error %s for qahwi_out_set_param_data",
1758 __func__, error);
1759 qahw_stream_out->qahwi_out_set_param_data = NULL;
1760 }
1761}
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301762
Naresh Tanniruee3499a2017-01-05 14:05:35 +05301763 /* dlsym qahwi_out_write_v2 */
1764 if (!rc) {
1765 const char *error;
1766
1767 /* clear any existing errors */
1768 dlerror();
1769 qahw_stream_out->qahwi_out_write_v2 = (qahwi_out_write_v2_t)dlsym(qahw_module->module->dso, "qahwi_out_write_v2");
1770 if ((error = dlerror()) != NULL) {
1771 ALOGI("%s: dlsym error %s for qahwi_out_write_v2", __func__, error);
1772 qahw_stream_out->qahwi_out_write_v2 = NULL;
1773 }
1774 }
1775
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301776exit:
1777 pthread_mutex_unlock(&qahw_module->lock);
1778 return rc;
1779}
1780
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301781int qahw_close_output_stream_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301782{
1783
1784 int rc = 0;
1785 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
1786 qahw_module_t *qahw_module = NULL;
1787 audio_hw_device_t *audio_device = NULL;
1788
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301789 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301790 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
1791 rc = -EINVAL;
1792 goto exit;
1793 }
1794
1795 ALOGV("%s::calling device close_output_stream %p", __func__, out_handle);
1796 pthread_mutex_lock(&qahw_stream_out->lock);
1797 qahw_module = qahw_stream_out->module;
1798 audio_device = qahw_module->audio_device;
1799 audio_device->close_output_stream(audio_device,
1800 qahw_stream_out->stream);
1801
1802 pthread_mutex_lock(&qahw_module->lock);
1803 list_remove(&qahw_stream_out->list);
1804 pthread_mutex_unlock(&qahw_module->lock);
1805
1806 pthread_mutex_unlock(&qahw_stream_out->lock);
1807
1808 pthread_mutex_destroy(&qahw_stream_out->lock);
1809 free(qahw_stream_out);
1810
1811exit:
1812 return rc;
1813}
1814
1815/* This method creates and opens the audio hardware input stream */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301816int qahw_open_input_stream_l(qahw_module_handle_t *hw_module,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301817 audio_io_handle_t handle,
1818 audio_devices_t devices,
1819 struct audio_config *config,
1820 qahw_stream_handle_t **in_handle,
1821 audio_input_flags_t flags,
1822 const char *address,
1823 audio_source_t source)
1824{
1825 int rc = -EINVAL;
1826 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1827 qahw_module_t *qahw_module_temp = NULL;
1828 audio_hw_device_t *audio_device = NULL;
1829 qahw_stream_in_t *qahw_stream_in = NULL;
Manish Dewangan46e07982018-12-13 18:18:59 +05301830 const char *error;
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301831
1832 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301833 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301834 pthread_mutex_unlock(&qahw_module_init_lock);
1835 if (qahw_module_temp == NULL) {
1836 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1837 return rc;
1838 }
1839
1840 pthread_mutex_lock(&qahw_module->lock);
1841 audio_device = qahw_module->audio_device;
1842 qahw_stream_in = (qahw_stream_in_t *)calloc(1, sizeof(qahw_stream_in_t));
1843 if (qahw_stream_in == NULL) {
1844 ALOGE("%s:: calloc failed for in stream_in_t",__func__);
1845 rc = -ENOMEM;
1846 goto exit;
1847 }
1848
1849 rc = audio_device->open_input_stream(audio_device,
1850 handle,
1851 devices,
1852 config,
1853 &qahw_stream_in->stream,
1854 flags,
1855 address,
1856 source);
1857 if (rc) {
1858 ALOGE("%s::open input stream failed %d",__func__, rc);
1859 free(qahw_stream_in);
Manish Dewangan46e07982018-12-13 18:18:59 +05301860 goto exit;
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301861 } else {
1862 qahw_stream_in->module = hw_module;
1863 *in_handle = (void *)qahw_stream_in;
1864 pthread_mutex_init(&qahw_stream_in->lock, (const pthread_mutexattr_t *)NULL);
1865 list_add_tail(&qahw_module->in_list, &qahw_stream_in->list);
1866 }
1867
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05301868 /* dlsym qahwi_in_read_v2 if timestamp flag is used */
Ralf Herzaec80262018-07-03 07:08:49 +02001869 if (!rc && ((flags & QAHW_INPUT_FLAG_TIMESTAMP) ||
1870 (flags & QAHW_INPUT_FLAG_PASSTHROUGH))) {
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05301871
1872 /* clear any existing errors */
1873 dlerror();
1874 qahw_stream_in->qahwi_in_read_v2 = (qahwi_in_read_v2_t)
1875 dlsym(qahw_module->module->dso, "qahwi_in_read_v2");
1876 if ((error = dlerror()) != NULL) {
1877 ALOGI("%s: dlsym error %s for qahwi_in_read_v2", __func__, error);
1878 qahw_stream_in->qahwi_in_read_v2 = NULL;
1879 }
1880 }
1881
Manish Dewangan46e07982018-12-13 18:18:59 +05301882 /* clear any existing errors */
1883 dlerror();
Zun Qiao9a2c1bc2021-08-11 08:33:36 +05301884 qahw_stream_in->qahwi_in_set_param_data = (qahwi_in_set_param_data_t)
1885 dlsym(qahw_module->module->dso,
1886 "qahwi_in_set_param_data");
1887 if ((error = dlerror()) != NULL) {
1888 ALOGI("%s: dlsym error %s for qahwi_in_set_param_data",
1889 __func__, error);
1890 qahw_stream_in->qahwi_in_set_param_data = NULL;
1891 }
1892
1893 /* clear any existing errors */
1894 dlerror();
Manish Dewangan46e07982018-12-13 18:18:59 +05301895 qahw_stream_in->qahwi_in_stop = (qahwi_in_stop_t)
1896 dlsym(qahw_module->module->dso, "qahwi_in_stop");
1897 if ((error = dlerror()) != NULL) {
1898 ALOGI("%s: dlsym error %s for qahwi_in_stop", __func__, error);
1899 qahw_stream_in->qahwi_in_stop = NULL;
1900 }
1901
1902 exit:
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301903 pthread_mutex_unlock(&qahw_module->lock);
1904 return rc;
1905}
1906
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301907int qahw_close_input_stream_l(qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301908{
1909 int rc = 0;
1910 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
1911 qahw_module_t *qahw_module = NULL;
1912 audio_hw_device_t *audio_device = NULL;
1913
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301914 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301915 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
1916 rc = -EINVAL;
1917 goto exit;
1918 }
1919
1920 ALOGV("%s:: calling device close_input_stream %p", __func__, in_handle);
1921 pthread_mutex_lock(&qahw_stream_in->lock);
1922 qahw_module = qahw_stream_in->module;
1923 audio_device = qahw_module->audio_device;
1924 audio_device->close_input_stream(audio_device,
1925 qahw_stream_in->stream);
1926
1927 pthread_mutex_lock(&qahw_module->lock);
1928 list_remove(&qahw_stream_in->list);
1929 pthread_mutex_unlock(&qahw_module->lock);
1930
1931 pthread_mutex_unlock(&qahw_stream_in->lock);
1932
1933 pthread_mutex_destroy(&qahw_stream_in->lock);
1934 free(qahw_stream_in);
1935
1936exit:
1937 return rc;
1938}
1939
1940/*returns current QTI HAL verison */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301941int qahw_get_version_l() {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301942 return QAHW_MODULE_API_VERSION_CURRENT;
1943}
1944
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +05301945/* Load AHAL module to run audio and sva concurrency */
1946static void load_st_hal()
1947{
1948#ifdef SVA_AUDIO_CONC
1949 int rc = -EINVAL;
1950 const hw_module_t* module = NULL;
1951
1952 rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, "primary", &module);
1953 if (rc) {
1954 ALOGE("%s: AHAL Loading failed %d", __func__, rc);
1955 goto error;
1956 }
1957
1958 rc = sound_trigger_hw_device_open(module, &st_hw_device);
1959 if (rc) {
1960 ALOGE("%s: AHAL Device open failed %d", __func__, rc);
1961 st_hw_device = NULL;
1962 }
1963error:
1964 return;
1965#else
1966 return;
1967#endif /*SVA_AUDIO_CONC*/
1968}
1969
1970static void unload_st_hal()
1971{
1972#ifdef SVA_AUDIO_CONC
1973 if (st_hw_device == NULL) {
1974 ALOGE("%s: audio device is NULL",__func__);
1975 return;
1976 }
1977 sound_trigger_hw_device_close(st_hw_device);
1978 st_hw_device = NULL;
1979#else
1980 return;
1981#endif /*SVA_AUDIO_CONC*/
1982}
1983
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301984/* convenience API for opening and closing an audio HAL module */
1985
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301986qahw_module_handle_t *qahw_load_module_l(const char *hw_module_id)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301987{
1988 int rc = -EINVAL;
1989 qahw_module_handle_t *qahw_mod_handle = NULL;
1990 qahw_module_t *qahw_module = NULL;
1991 char *ahal_name = NULL;
1992 const hw_module_t* module = NULL;
1993 audio_hw_device_t* audio_device = NULL;
1994
1995 if (hw_module_id == NULL) {
1996 ALOGE("%s::module id is NULL",__func__);
1997 goto exit;
1998 }
1999
2000 if (!strcmp(hw_module_id, QAHW_MODULE_ID_PRIMARY)) {
2001 ahal_name = "primary";
2002 } else if (!strcmp(hw_module_id, QAHW_MODULE_ID_A2DP)) {
2003 ahal_name = "a2dp";
2004 } else if (!strcmp(hw_module_id, QAHW_MODULE_ID_USB)) {
2005 ahal_name = "usb";
2006 } else {
2007 ALOGE("%s::Invalid Module id %s", __func__, hw_module_id);
2008 goto exit;
2009 }
2010
2011 /* return exiting module ptr if already loaded */
2012 pthread_mutex_lock(&qahw_module_init_lock);
2013 if (qahw_list_count > 0) {
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05302014 qahw_module = get_qahw_module_by_name_l(hw_module_id);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05302015 if(qahw_module != NULL) {
2016 qahw_mod_handle = (void *)qahw_module;
2017 pthread_mutex_lock(&qahw_module->lock);
2018 qahw_module->ref_count++;
2019 pthread_mutex_unlock(&qahw_module->lock);
2020 goto error_exit;
2021 }
2022 }
2023
2024 rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, ahal_name, &module);
2025 if(rc) {
2026 ALOGE("%s::HAL Loading failed %d", __func__, rc);
2027 goto error_exit;
2028 }
2029
2030 rc = audio_hw_device_open(module, &audio_device);
2031 if(rc) {
2032 ALOGE("%s::HAL Device open failed %d", __func__, rc);
2033 goto error_exit;
2034 }
2035
2036 qahw_module = (qahw_module_t *)calloc(1, sizeof(qahw_module_t));
2037 if(qahw_module == NULL) {
2038 ALOGE("%s::calloc failed", __func__);
2039 audio_hw_device_close(audio_device);
2040 goto error_exit;
2041 }
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05302042 qahw_module->module = module;
Manish Dewanganb8c83a42016-09-23 15:10:48 +05302043 ALOGD("%s::Loaded HAL %s module %p", __func__, ahal_name, qahw_module);
2044
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05302045 qahw_module->qahwi_get_param_data = (qahwi_get_param_data_t) dlsym (module->dso,
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05302046 "qahwi_get_param_data");
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05302047 if (!qahw_module->qahwi_get_param_data)
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05302048 ALOGD("%s::qahwi_get_param_data api is not defined\n",__func__);
2049
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05302050 qahw_module->qahwi_set_param_data = (qahwi_set_param_data_t) dlsym (module->dso,
2051 "qahwi_set_param_data");
2052 if (!qahw_module->qahwi_set_param_data)
2053 ALOGD("%s::qahwi_set_param_data api is not defined\n",__func__);
2054
Trinath Thammishetty580f1de2018-09-28 12:43:24 +05302055 qahw_module->qahwi_loopback_set_param_data = (qahwi_loopback_set_param_data_t)
2056 dlsym(module->dso,
2057 "qahwi_loopback_set_param_data");
2058 if (!qahw_module->qahwi_loopback_set_param_data)
2059 ALOGD("%s::qahwi_loopback_set_param_data api is not defined\n", __func__);
2060
Zun Qiao9a2c1bc2021-08-11 08:33:36 +05302061 qahw_module->qahwi_create_audio_patch_v2 = (qahwi_create_audio_patch_v2_t) dlsym (module->dso,
2062 "qahwi_create_audio_patch_v2");
2063 if (!qahw_module->qahwi_create_audio_patch_v2)
2064 ALOGD("%s::qahwi_create_audio_patch_v2 api is not defined\n",__func__);
2065
Manish Dewanganb8c83a42016-09-23 15:10:48 +05302066 if (!qahw_list_count)
2067 list_init(&qahw_module_list);
2068 qahw_list_count++;
2069
2070 pthread_mutex_init(&qahw_module->lock, (const pthread_mutexattr_t *) NULL);
2071 pthread_mutex_lock(&qahw_module->lock);
2072 qahw_module->ref_count++;
2073 pthread_mutex_unlock(&qahw_module->lock);
2074
2075 list_init(&qahw_module->out_list);
2076 list_init(&qahw_module->in_list);
2077
2078 /* update qahw_module */
2079 qahw_module->audio_device = audio_device;
2080 strlcpy(&qahw_module->module_name[0], hw_module_id, MAX_MODULE_NAME_LENGTH);
2081
2082 qahw_mod_handle = (void *)qahw_module;
2083
2084 /* Add module list to global module list */
2085 list_add_tail(&qahw_module_list, &qahw_module->module_list);
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +05302086 load_st_hal();
Manish Dewanganb8c83a42016-09-23 15:10:48 +05302087
2088error_exit:
2089 pthread_mutex_unlock(&qahw_module_init_lock);
2090
2091exit:
2092 return qahw_mod_handle;
2093}
2094
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05302095int qahw_unload_module_l(qahw_module_handle_t *hw_module)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05302096{
2097 int rc = -EINVAL;
2098 bool is_empty = false;
2099 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
2100 qahw_module_t *qahw_module_temp = NULL;
2101
2102 /* close HW device if its valid and all the streams on
2103 * it is closed
2104 */
2105 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05302106 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05302107 if (qahw_module_temp == NULL) {
2108 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
2109 goto error_exit;
2110 }
2111
2112 pthread_mutex_lock(&qahw_module->lock);
2113 qahw_module->ref_count--;
2114 if (qahw_module->ref_count > 0) {
2115 rc = 0;
2116 ALOGE("%s:: skipping module unload of %p count %d", __func__,
2117 qahw_module,
2118 qahw_module->ref_count);
2119 pthread_mutex_unlock(&qahw_module->lock);
2120 goto error_exit;
2121 }
2122
2123 is_empty = (list_empty(&qahw_module->out_list) &&
2124 list_empty(&qahw_module->in_list));
2125 if (is_empty) {
2126 rc = audio_hw_device_close(qahw_module->audio_device);
2127 if(rc) {
2128 ALOGE("%s::HAL Device close failed Error %d Module %p",__func__,
2129 rc, qahw_module);
2130 rc = 0;
2131 }
2132 qahw_list_count--;
2133 list_remove(&qahw_module->module_list);
2134 pthread_mutex_unlock(&qahw_module->lock);
2135 pthread_mutex_destroy(&qahw_module->lock);
2136 free(qahw_module);
2137 } else {
2138 pthread_mutex_unlock(&qahw_module->lock);
2139 ALOGE("%s::failed as all the streams on this module"
2140 "is not closed", __func__);
2141 rc = -EINVAL;
2142 }
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +05302143 unload_st_hal();
Manish Dewanganb8c83a42016-09-23 15:10:48 +05302144
2145error_exit:
2146 pthread_mutex_unlock(&qahw_module_init_lock);
2147
Manish Dewanganb8c83a42016-09-23 15:10:48 +05302148 return rc;
2149}
2150
2151__END_DECLS