blob: 3390c26900081186c76ce097df91a0ba4e2df06b [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
64typedef int (*qahwi_out_set_param_data_t)(struct audio_stream_out *out,
65 qahw_param_id param_id,
66 qahw_param_payload *payload);
67
68typedef int (*qahwi_out_get_param_data_t)(struct audio_stream_out *out,
69 qahw_param_id param_id,
70 qahw_param_payload *payload);
71
Trinath Thammishetty580f1de2018-09-28 12:43:24 +053072typedef int (*qahwi_loopback_set_param_data_t)(audio_patch_handle_t patch_handle,
Trinath Thammishetty15cd3402018-10-29 11:57:19 +053073 qahw_loopback_param_id param_id,
74 qahw_loopback_param_payload *payload);
Trinath Thammishetty580f1de2018-09-28 12:43:24 +053075
Manish Dewanganb8c83a42016-09-23 15:10:48 +053076typedef struct {
77 audio_hw_device_t *audio_device;
78 char module_name[MAX_MODULE_NAME_LENGTH];
79 struct listnode module_list;
80 struct listnode in_list;
81 struct listnode out_list;
82 pthread_mutex_t lock;
83 uint32_t ref_count;
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +053084 const hw_module_t* module;
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +053085 qahwi_get_param_data_t qahwi_get_param_data;
86 qahwi_set_param_data_t qahwi_set_param_data;
Trinath Thammishetty580f1de2018-09-28 12:43:24 +053087 qahwi_loopback_set_param_data_t qahwi_loopback_set_param_data;
Manish Dewanganb8c83a42016-09-23 15:10:48 +053088} qahw_module_t;
89
90typedef struct {
91 qahw_module_t *module;
92 struct listnode module_list;
93 pthread_mutex_t lock;
94} qahw_module_instances_t;
95
96typedef struct {
97 audio_stream_out_t *stream;
98 qahw_module_t *module;
99 struct listnode list;
100 pthread_mutex_t lock;
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530101 qahwi_out_set_param_data_t qahwi_out_get_param_data;
102 qahwi_out_get_param_data_t qahwi_out_set_param_data;
Naresh Tanniruee3499a2017-01-05 14:05:35 +0530103 qahwi_out_write_v2_t qahwi_out_write_v2;
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530104} qahw_stream_out_t;
105
106typedef struct {
107 audio_stream_in_t *stream;
108 qahw_module_t *module;
109 struct listnode list;
110 pthread_mutex_t lock;
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +0530111 qahwi_in_read_v2_t qahwi_in_read_v2;
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530112} qahw_stream_in_t;
113
114typedef enum {
115 STREAM_DIR_IN,
116 STREAM_DIR_OUT,
117} qahw_stream_direction_t;
118
119static struct listnode qahw_module_list;
120static int qahw_list_count;
121static pthread_mutex_t qahw_module_init_lock = PTHREAD_MUTEX_INITIALIZER;
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +0530122sound_trigger_hw_device_t *st_hw_device = NULL;
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530123
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +0530124
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530125/** Start of internal functions */
126/******************************************************************************/
127
128/* call this function without anylock held */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530129static bool is_valid_qahw_stream_l(void *qahw_stream,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530130 qahw_stream_direction_t dir)
131{
132
133 int is_valid = false;
134 struct listnode *module_node = NULL;
135 struct listnode *stream_node = NULL;
136 struct listnode *list_node = NULL;
137 void *stream = NULL;
138 qahw_module_t *qahw_module = NULL;
139
140 if (qahw_stream == NULL) {
141 ALOGE("%s:: Invalid stream", __func__);
142 goto exit;
143 }
144
145 if ((dir != STREAM_DIR_OUT) && (dir != STREAM_DIR_IN)) {
146 ALOGE("%s:: Invalid stream direction %d", __func__, dir);
147 goto exit;
148 }
149
150 /* go through all the modules and check for valid stream */
151 pthread_mutex_lock(&qahw_module_init_lock);
152 list_for_each(module_node, &qahw_module_list) {
153 qahw_module = node_to_item(module_node, qahw_module_t, module_list);
154 pthread_mutex_lock(&qahw_module->lock);
155 if(dir == STREAM_DIR_OUT)
156 list_node = &qahw_module->out_list;
157 else
158 list_node = &qahw_module->in_list;
159 list_for_each(stream_node, list_node) {
160 if(dir == STREAM_DIR_OUT)
161 stream = (void *)node_to_item(stream_node,
162 qahw_stream_out_t,
163 list);
164 else
165 stream = (void *)node_to_item(stream_node,
166 qahw_stream_in_t,
167 list);
168 if(stream == qahw_stream) {
169 is_valid = true;
170 break;
171 }
172 }
173 pthread_mutex_unlock(&qahw_module->lock);
174 if(is_valid)
175 break;
176 }
177 pthread_mutex_unlock(&qahw_module_init_lock);
178
179exit:
180 return is_valid;
181}
182
183/* call this fucntion with ahw_module_init_lock held*/
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530184static qahw_module_t* get_qahw_module_by_ptr_l(qahw_module_t *qahw_module)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530185{
186 struct listnode *node = NULL;
187 qahw_module_t *module = NULL, *module_temp = NULL;
188
189 if (qahw_module == NULL)
190 goto exit;
191
192 list_for_each(node, &qahw_module_list) {
193 module_temp = node_to_item(node, qahw_module_t, module_list);
194 if (module_temp == qahw_module) {
195 module = module_temp;
196 break;
197 }
198 }
199exit:
200 return module;
201}
202
203/* call this function with qahw_module_init_lock held*/
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530204static qahw_module_t* get_qahw_module_by_name_l(const char *qahw_name)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530205{
206 struct listnode *node = NULL;
207 qahw_module_t *module = NULL, *module_temp = NULL;
208
209 if (qahw_name == NULL)
210 goto exit;
211
212 list_for_each(node, &qahw_module_list) {
213 module_temp = node_to_item(node, qahw_module_t, module_list);
214 if(!strncmp(qahw_name, module_temp->module_name, MAX_MODULE_NAME_LENGTH)) {
215 module = module_temp;
216 break;
217 }
218 }
219exit:
220 return module;
221}
222/* End of of internal functions */
223
224/*
225 * Return the sampling rate in Hz - eg. 44100.
226 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530227uint32_t qahw_out_get_sample_rate_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530228{
229 uint32_t rate = 0;
230 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
231 audio_stream_out_t *out = NULL;
232
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530233 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530234 ALOGV("%s::Invalid out handle %p", __func__, out_handle);
235 goto exit;
236 }
237
238 pthread_mutex_lock(&qahw_stream_out->lock);
239 out = qahw_stream_out->stream;
240 if (out->common.get_sample_rate)
241 rate = out->common.get_sample_rate(&out->common);
242 else
243 ALOGW("%s not supported", __func__);
244 pthread_mutex_unlock(&qahw_stream_out->lock);
245
246exit:
247 return rate;
248}
249
250/*
251 * currently unused - use set_parameters with key
252 * AUDIO_PARAMETER_STREAM_SAMPLING_RATE
253 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530254int qahw_out_set_sample_rate_l(qahw_stream_handle_t *out_handle, uint32_t rate)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530255{
256 int32_t rc = -EINVAL;
257 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
258 audio_stream_out_t *out = NULL;
259
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530260 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530261 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
262 goto exit;
263 }
264 pthread_mutex_lock(&qahw_stream_out->lock);
265 out = qahw_stream_out->stream;
266 if (out->common.set_sample_rate) {
267 rc = out->common.set_sample_rate(&out->common, rate);
268 } else {
269 rc = -ENOSYS;
270 ALOGW("%s not supported", __func__);
271 }
272 pthread_mutex_unlock(&qahw_stream_out->lock);
273exit:
274 return rc;
275}
276
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530277size_t qahw_out_get_buffer_size_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530278{
279 size_t buf_size = 0;
280 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
281 audio_stream_out_t *out = NULL;
282
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530283 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530284 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
285 goto exit;
286 }
287 pthread_mutex_lock(&qahw_stream_out->lock);
288 out = qahw_stream_out->stream;
289 if (out->common.get_buffer_size) {
290 buf_size = out->common.get_buffer_size(&out->common);
291 } else {
292 ALOGW("%s not supported", __func__);
293 }
294 pthread_mutex_unlock(&qahw_stream_out->lock);
295
296exit:
297 return buf_size;
298}
299
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530300audio_channel_mask_t qahw_out_get_channels_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530301{
302 audio_channel_mask_t ch_mask = 0;
303 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
304 audio_stream_out_t *out = NULL;
305
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530306 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530307 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
308 goto exit;
309 }
310 pthread_mutex_lock(&qahw_stream_out->lock);
311 out = qahw_stream_out->stream;
312 if (out->common.get_channels) {
313 ch_mask = out->common.get_channels(&out->common);
314 } else {
315 ALOGW("%s not supported", __func__);
316 }
317 pthread_mutex_unlock(&qahw_stream_out->lock);
318
319exit:
320 return ch_mask;
321}
322
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530323audio_format_t qahw_out_get_format_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530324{
325 audio_format_t format = AUDIO_FORMAT_INVALID;
326 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
327 audio_stream_out_t *out = NULL;
328
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530329 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530330 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
331 goto exit;
332 }
333 pthread_mutex_lock(&qahw_stream_out->lock);
334 out = qahw_stream_out->stream;
335 if (out->common.get_format) {
336 format = out->common.get_format(&out->common);
337 } else {
338 ALOGW("%s not supported", __func__);
339 }
340 pthread_mutex_unlock(&qahw_stream_out->lock);
341
342exit:
343 return format;
344}
345
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530346int qahw_out_standby_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530347{
348 int32_t rc = -EINVAL;
349 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
350 audio_stream_out_t *out = NULL;
351
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530352 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530353 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
354 goto exit;
355 }
356
357 pthread_mutex_lock(&qahw_stream_out->lock);
358 out = qahw_stream_out->stream;
359 if (out->common.standby) {
360 rc = out->common.standby(&out->common);
361 } else {
362 rc = -ENOSYS;
363 ALOGW("%s not supported", __func__);
364 }
365 pthread_mutex_unlock(&qahw_stream_out->lock);
366
367exit:
368 return rc;
369}
370
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530371int qahw_out_set_parameters_l(qahw_stream_handle_t *out_handle, const char *kv_pairs)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530372{
373 int rc = NO_ERROR;
374 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
375 audio_stream_out_t *out = NULL;
376
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530377 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530378 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
379 rc = -EINVAL;
380 goto exit;
381 }
382
383 pthread_mutex_lock(&qahw_stream_out->lock);
384 out = qahw_stream_out->stream;
385 if (out->common.set_parameters) {
386 rc = out->common.set_parameters(&out->common, kv_pairs);
387 } else {
388 rc = -ENOSYS;
389 ALOGW("%s not supported", __func__);
390 }
391 pthread_mutex_unlock(&qahw_stream_out->lock);
392
393exit:
394 return rc;
395}
396
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530397char *qahw_out_get_parameters_l(const qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530398 const char *keys)
399{
400 char *str_param = NULL;
401 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
402 audio_stream_out_t *out = NULL;
403
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530404 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530405 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
406 goto exit;
407 }
408
409 pthread_mutex_lock(&qahw_stream_out->lock);
410 out = qahw_stream_out->stream;
411 if (out->common.get_parameters) {
412 str_param = out->common.get_parameters(&out->common, keys);
413 } else {
414 ALOGW("%s not supported", __func__);
415 }
416 pthread_mutex_unlock(&qahw_stream_out->lock);
417
418exit:
419 return str_param;
420}
421
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530422/* API to get playback stream specific config parameters */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530423int qahw_out_set_param_data_l(qahw_stream_handle_t *out_handle,
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530424 qahw_param_id param_id,
425 qahw_param_payload *payload)
426{
427 int rc = -EINVAL;
428 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
429 audio_stream_out_t *out = NULL;
430
431 if (!payload) {
432 ALOGE("%s::Invalid param", __func__);
433 goto exit;
434 }
435
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530436 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530437 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
438 goto exit;
439 }
440
441 pthread_mutex_lock(&qahw_stream_out->lock);
442 out = qahw_stream_out->stream;
443 if (qahw_stream_out->qahwi_out_set_param_data) {
444 rc = qahw_stream_out->qahwi_out_set_param_data(out, param_id, payload);
445 } else {
446 rc = -ENOSYS;
447 ALOGW("%s not supported", __func__);
448 }
449 pthread_mutex_unlock(&qahw_stream_out->lock);
450
451exit:
452 return rc;
453}
454
455/* API to get playback stream specific config parameters */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530456int qahw_out_get_param_data_l(qahw_stream_handle_t *out_handle,
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530457 qahw_param_id param_id,
458 qahw_param_payload *payload)
459{
460 int rc = -EINVAL;
461 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
462 audio_stream_out_t *out = NULL;
463
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530464 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530465 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
466 goto exit;
467 }
468
469 pthread_mutex_lock(&qahw_stream_out->lock);
470 out = qahw_stream_out->stream;
471 if (qahw_stream_out->qahwi_out_get_param_data) {
472 rc = qahw_stream_out->qahwi_out_get_param_data(out, param_id, payload);
473 } else {
474 rc = -ENOSYS;
475 ALOGW("%s not supported", __func__);
476 }
477 pthread_mutex_unlock(&qahw_stream_out->lock);
478
479exit:
480 return rc;
481}
482
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530483uint32_t qahw_out_get_latency_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530484{
485 uint32_t latency = 0;
486 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
487 audio_stream_out_t *out = NULL;
488
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530489 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530490 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
491 goto exit;
492 }
493
494 pthread_mutex_lock(&qahw_stream_out->lock);
495 out = qahw_stream_out->stream;
496 if (out->get_latency) {
497 latency = out->get_latency(out);
498 } else {
499 ALOGW("%s not supported", __func__);
500 }
501 pthread_mutex_unlock(&qahw_stream_out->lock);
502
503exit:
504 return latency;
505}
506
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530507int qahw_out_set_volume_l(qahw_stream_handle_t *out_handle, float left, float right)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530508{
509 int rc = -EINVAL;
510 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
511 audio_stream_out_t *out = NULL;
512
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530513 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530514 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
515 goto exit;
516 }
517
518 pthread_mutex_lock(&qahw_stream_out->lock);
519 out = qahw_stream_out->stream;
520 if (out->set_volume) {
521 rc = out->set_volume(out, left, right);
522 } else {
523 rc = -ENOSYS;
524 ALOGW("%s not supported", __func__);
525 }
526 pthread_mutex_unlock(&qahw_stream_out->lock);
527
528exit:
529 return rc;
530}
531
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530532ssize_t qahw_out_write_l(qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530533 qahw_out_buffer_t *out_buf)
534{
535 int rc = -EINVAL;
536 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
537 audio_stream_out_t *out = NULL;
538
539 if ((out_buf == NULL) || (out_buf->buffer == NULL)) {
540 ALOGE("%s::Invalid meta data %p", __func__, out_buf);
541 goto exit;
542 }
543
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530544 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530545 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
546 goto exit;
547 }
548
549 /*TBD:: validate other meta data parameters */
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530550 pthread_mutex_lock(&qahw_stream_out->lock);
551 out = qahw_stream_out->stream;
Naresh Tanniruee3499a2017-01-05 14:05:35 +0530552 if (qahw_stream_out->qahwi_out_write_v2) {
553 rc = qahw_stream_out->qahwi_out_write_v2(out, out_buf->buffer,
554 out_buf->bytes, out_buf->timestamp);
555 out_buf->offset = 0;
556 } else if (out->write) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530557 rc = out->write(out, out_buf->buffer, out_buf->bytes);
558 } else {
559 rc = -ENOSYS;
560 ALOGW("%s not supported", __func__);
561 }
562 pthread_mutex_unlock(&qahw_stream_out->lock);
563exit:
564 return rc;
565}
566
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530567int qahw_out_get_render_position_l(const qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530568 uint32_t *dsp_frames)
569{
570 int rc = -EINVAL;
571 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
572 audio_stream_out_t *out = NULL;
573
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530574 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530575 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
576 goto exit;
577 }
578
579 pthread_mutex_lock(&qahw_stream_out->lock);
580 out = qahw_stream_out->stream;
581 if (out->get_render_position) {
582 rc = out->get_render_position(out, dsp_frames);
583 } else {
584 rc = -ENOSYS;
585 ALOGW("%s not supported", __func__);
586 }
587 pthread_mutex_unlock(&qahw_stream_out->lock);
588exit:
589 return rc;
590}
591
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530592int qahw_out_set_callback_l(qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530593 qahw_stream_callback_t callback,
594 void *cookie)
595{
596 /*TBD:load hal func pointer and call */
597 int rc = -EINVAL;
598 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
599 audio_stream_out_t *out = NULL;
600
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530601 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530602 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
603 goto exit;
604 }
605
606 pthread_mutex_lock(&qahw_stream_out->lock);
607 out = qahw_stream_out->stream;
608 if (out->set_callback) {
609 rc = out->set_callback(out, (stream_callback_t)callback, cookie);
610 } else {
611 rc = -ENOSYS;
612 ALOGW("%s not supported", __func__);
613 }
614 pthread_mutex_unlock(&qahw_stream_out->lock);
615
616exit:
617 return rc;
618}
619
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530620int qahw_out_pause_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530621{
622 /*TBD:load hal func pointer and call */
623 int rc = -EINVAL;
624 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
625 audio_stream_out_t *out = NULL;
626
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530627 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530628 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
629 goto exit;
630 }
631
632 pthread_mutex_lock(&qahw_stream_out->lock);
633 out = qahw_stream_out->stream;
634 if (out->pause) {
635 rc = out->pause(out);
636 } else {
637 rc = -ENOSYS;
638 ALOGW("%s not supported", __func__);
639 }
640 pthread_mutex_unlock(&qahw_stream_out->lock);
641
642exit:
643 return rc;
644}
645
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530646int qahw_out_resume_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530647{
648 /*TBD:load hal func pointer and call */
649 int rc = -EINVAL;
650 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
651 audio_stream_out_t *out = NULL;
652
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530653 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530654 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
655 goto exit;
656 }
657
658 pthread_mutex_lock(&qahw_stream_out->lock);
659 out = qahw_stream_out->stream;
660 if (out->resume) {
661 rc = out->resume(out);
662 } else {
663 rc = -ENOSYS;
664 ALOGW("%s not supported", __func__);
665 }
666 pthread_mutex_unlock(&qahw_stream_out->lock);
667
668exit:
669 return rc;
670}
671
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530672int qahw_out_drain_l(qahw_stream_handle_t *out_handle, qahw_drain_type_t type )
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530673{
674 /*TBD:load hal func pointer and call */
675 int rc = -EINVAL;
676 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
677 audio_stream_out_t *out = NULL;
678
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530679 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530680 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
681 goto exit;
682 }
683
684 pthread_mutex_lock(&qahw_stream_out->lock);
685 out = qahw_stream_out->stream;
686 if (out->drain) {
687 rc = out->drain(out,(audio_drain_type_t)type);
688 } else {
689 rc = -ENOSYS;
690 ALOGW("%s not supported", __func__);
691 }
692 pthread_mutex_unlock(&qahw_stream_out->lock);
693
694exit:
695 return rc;
696}
697
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530698int qahw_out_flush_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530699{
700 int rc = -EINVAL;
701 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
702 audio_stream_out_t *out = NULL;
703
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530704 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530705 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
706 goto exit;
707 }
708
709 pthread_mutex_lock(&qahw_stream_out->lock);
710 out = qahw_stream_out->stream;
711 if (out->flush) {
712 rc = out->flush(out);
713 } else {
714 rc = -ENOSYS;
715 ALOGW("%s not supported", __func__);
716 }
717 pthread_mutex_unlock(&qahw_stream_out->lock);
718
719exit:
720 return rc;
721}
722
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530723int qahw_out_get_presentation_position_l(const qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530724 uint64_t *frames, struct timespec *timestamp)
725{
726 int rc = -EINVAL;
727 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
728 audio_stream_out_t *out = NULL;
729
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530730 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530731 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
732 goto exit;
733 }
734
735 pthread_mutex_lock(&qahw_stream_out->lock);
736 out = qahw_stream_out->stream;
737 if (out->get_presentation_position) {
738 rc = out->get_presentation_position(out, frames, timestamp);
739 } else {
740 rc = -ENOSYS;
741 ALOGW("%s not supported", __func__);
742 }
743 pthread_mutex_unlock(&qahw_stream_out->lock);
744
745exit:
746 return rc;
747}
748
749/* Input stream specific APIs */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530750uint32_t qahw_in_get_sample_rate_l(const qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530751{
752 uint32_t rate = 0;
753 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
754 audio_stream_in_t *in = NULL;
755
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530756 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530757 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
758 goto exit;
759 }
760
761 pthread_mutex_lock(&qahw_stream_in->lock);
762 in = qahw_stream_in->stream;
763 if (in->common.get_sample_rate) {
764 rate = in->common.get_sample_rate(&in->common);
765 } else {
766 ALOGW("%s not supported", __func__);
767 }
768 pthread_mutex_unlock(&qahw_stream_in->lock);
769
770exit:
771 return rate;
772}
773
774/*
775 * currently unused - use set_parameters with key
776 * AUDIO_PARAMETER_STREAM_SAMPLING_RATE
777 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530778int qahw_in_set_sample_rate_l(qahw_stream_handle_t *in_handle, uint32_t rate)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530779{
780 int rc = -EINVAL;
781 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
782 audio_stream_in_t *in = NULL;
783
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530784 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530785 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
786 goto exit;
787 }
788
789 pthread_mutex_lock(&qahw_stream_in->lock);
790 in = qahw_stream_in->stream;
791 if (in->common.set_sample_rate) {
792 rc = in->common.set_sample_rate(&in->common, rate);
793 } else {
794 rc = -ENOSYS;
795 ALOGW("%s not supported", __func__);
796 }
797 pthread_mutex_unlock(&qahw_stream_in->lock);
798
799exit:
800 return rc;
801}
802
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530803size_t qahw_in_get_buffer_size_l(const qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530804{
805 size_t buf_size = 0;
806 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
807 audio_stream_in_t *in = NULL;
808
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530809 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530810 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
811 goto exit;
812 }
813
814 pthread_mutex_lock(&qahw_stream_in->lock);
815 in = qahw_stream_in->stream;
816 if (in->common.get_sample_rate) {
817 buf_size = in->common.get_buffer_size(&in->common);
818 } else {
819 ALOGW("%s not supported", __func__);
820 }
821 pthread_mutex_unlock(&qahw_stream_in->lock);
822
823exit:
824 return buf_size;
825}
826
827
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530828audio_channel_mask_t qahw_in_get_channels_l(const qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530829{
830 audio_channel_mask_t ch_mask = 0;;
831 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
832 audio_stream_in_t *in = NULL;
833
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530834 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530835 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
836 goto exit;
837 }
838
839 pthread_mutex_lock(&qahw_stream_in->lock);
840 in = qahw_stream_in->stream;
841 if (in->common.get_channels) {
842 ch_mask = in->common.get_channels(&in->common);
843 } else {
844 ALOGW("%s not supported", __func__);
845 }
846 pthread_mutex_unlock(&qahw_stream_in->lock);
847
848exit:
849 return ch_mask;
850}
851
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530852audio_format_t qahw_in_get_format_l(const qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530853{
854 audio_format_t format = AUDIO_FORMAT_INVALID;
855 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
856 audio_stream_in_t *in = NULL;
857
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530858 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530859 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
860 goto exit;
861 }
862
863 pthread_mutex_lock(&qahw_stream_in->lock);
864 in = qahw_stream_in->stream;
865 if (in->common.get_format) {
866 format = in->common.get_format(&in->common);
867 } else {
868 ALOGW("%s not supported", __func__);
869 }
870 pthread_mutex_unlock(&qahw_stream_in->lock);
871
872exit:
873 return format;
874}
875
876/*
877 * currently unused - use set_parameters with key
878 * AUDIO_PARAMETER_STREAM_FORMAT
879 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530880int qahw_in_set_format_l(qahw_stream_handle_t *in_handle, audio_format_t format)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530881{
882 int rc = -EINVAL;
883 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
884 audio_stream_in_t *in = NULL;
885
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530886 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530887 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
888 goto exit;
889 }
890
891 pthread_mutex_lock(&qahw_stream_in->lock);
892 in = qahw_stream_in->stream;
893 if (in->common.set_format) {
894 rc = in->common.set_format(&in->common, format);
895 } else {
896 rc = -ENOSYS;
897 ALOGW("%s not supported", __func__);
898 }
899 pthread_mutex_unlock(&qahw_stream_in->lock);
900
901exit:
902 return rc;
903}
904
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530905int qahw_in_standby_l(qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530906{
907 int rc = -EINVAL;
908 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
909 audio_stream_in_t *in = NULL;
910
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530911 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530912 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
913 goto exit;
914 }
915
916 pthread_mutex_lock(&qahw_stream_in->lock);
917 in = qahw_stream_in->stream;
918 if (in->common.standby) {
919 rc = in->common.standby(&in->common);
920 } else {
921 rc = -ENOSYS;
922 ALOGW("%s not supported", __func__);
923 }
924 pthread_mutex_unlock(&qahw_stream_in->lock);
925
926exit:
927 return rc;
928}
929
930/*
931 * set/get audio stream parameters. The function accepts a list of
932 * parameter key value pairs in the form: key1=value1;key2=value2;...
933 *
934 * Some keys are reserved for standard parameters (See AudioParameter class)
935 *
936 * If the implementation does not accept a parameter change while
937 * the output is active but the parameter is acceptable otherwise, it must
938 * return -ENOSYS.
939 *
940 * The audio flinger will put the stream in standby and then change the
941 * parameter value.
942 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530943int qahw_in_set_parameters_l(qahw_stream_handle_t *in_handle, const char *kv_pairs)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530944{
945 int rc = -EINVAL;
946 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
947 audio_stream_in_t *in = NULL;
948
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530949 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530950 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
951 goto exit;
952 }
953
954 pthread_mutex_lock(&qahw_stream_in->lock);
955 in = qahw_stream_in->stream;
956 if (in->common.set_parameters) {
957 rc = in->common.set_parameters(&in->common, kv_pairs);
958 } else {
959 rc = -ENOSYS;
960 ALOGW("%s not supported", __func__);
961 }
962 pthread_mutex_unlock(&qahw_stream_in->lock);
963exit:
964 return rc;
965}
966
967/*
968 * Returns a pointer to a heap allocated string. The caller is responsible
969 * for freeing the memory for it using free().
970 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530971char * qahw_in_get_parameters_l(const qahw_stream_handle_t *in_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530972 const char *keys)
973{
974 char *str_param = NULL;
975 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
976 audio_stream_in_t *in = NULL;
977
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530978 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530979 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
980 goto exit;
981 }
982
983 pthread_mutex_lock(&qahw_stream_in->lock);
984 in = qahw_stream_in->stream;
985 if (in->common.get_parameters) {
986 str_param = in->common.get_parameters(&in->common, keys);
987 } else {
988 ALOGW("%s not supported", __func__);
989 }
990 pthread_mutex_unlock(&qahw_stream_in->lock);
991
992exit:
993 return str_param;
994}
995
996/*
997 * Read audio buffer in from audio driver. Returns number of bytes read, or a
998 * negative status_t. If at least one frame was read prior to the error,
999 * read should return that byte count and then return an error in the subsequent call.
1000 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301001ssize_t qahw_in_read_l(qahw_stream_handle_t *in_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301002 qahw_in_buffer_t *in_buf)
1003{
1004 int rc = -EINVAL;
1005 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
1006 audio_stream_in_t *in = NULL;
1007
1008 if ((in_buf == NULL) || (in_buf->buffer == NULL)) {
1009 ALOGE("%s::Invalid meta data %p", __func__, in_buf);
1010 goto exit;
1011 }
1012
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301013 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301014 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
1015 goto exit;
1016 }
1017
1018 pthread_mutex_lock(&qahw_stream_in->lock);
1019 in = qahw_stream_in->stream;
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05301020 if (qahw_stream_in->qahwi_in_read_v2) {
1021 rc = qahw_stream_in->qahwi_in_read_v2(in, in_buf->buffer,
1022 in_buf->bytes, in_buf->timestamp);
1023 in_buf->offset = 0;
1024 } else if (in->read) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301025 rc = in->read(in, in_buf->buffer, in_buf->bytes);
1026 in_buf->offset = 0;
1027 } else {
1028 rc = -ENOSYS;
1029 ALOGW("%s not supported", __func__);
1030 }
1031 pthread_mutex_unlock(&qahw_stream_in->lock);
1032
1033exit:
1034 return rc;
1035}
1036
1037/*
1038 * Return the amount of input frames lost in the audio driver since the
1039 * last call of this function.
1040 * Audio driver is expected to reset the value to 0 and restart counting
1041 * upon returning the current value by this function call.
1042 * Such loss typically occurs when the user space process is blocked
1043 * longer than the capacity of audio driver buffers.
1044 *
1045 * Unit: the number of input audio frames
1046 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301047uint32_t qahw_in_get_input_frames_lost_l(qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301048{
1049 uint32_t rc = 0;
1050 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
1051 audio_stream_in_t *in = NULL;
1052
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301053 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301054 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
1055 goto exit;
1056 }
1057
1058 pthread_mutex_lock(&qahw_stream_in->lock);
1059 in = qahw_stream_in->stream;
1060 if (in->get_input_frames_lost) {
1061 rc = in->get_input_frames_lost(in);
1062 } else {
1063 rc = -ENOSYS;
1064 ALOGW("%s not supported", __func__);
1065 }
1066 pthread_mutex_unlock(&qahw_stream_in->lock);
1067
1068exit:
1069 return rc;
1070}
1071
1072/*
1073 * Return a recent count of the number of audio frames received and
1074 * the clock time associated with that frame count.
1075 *
1076 * frames is the total frame count received. This should be as early in
1077 * the capture pipeline as possible. In general,
1078 * frames should be non-negative and should not go "backwards".
1079 *
1080 * time is the clock MONOTONIC time when frames was measured. In general,
1081 * time should be a positive quantity and should not go "backwards".
1082 *
1083 * The status returned is 0 on success, -ENOSYS if the device is not
1084 * ready/available, or -EINVAL if the arguments are null or otherwise invalid.
1085 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301086int qahw_in_get_capture_position_l(const qahw_stream_handle_t *in_handle __unused,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301087 int64_t *frames __unused, int64_t *time __unused)
1088{
1089 /*TBD:: do we need this*/
1090 return -ENOSYS;
1091}
1092
1093/*
1094 * check to see if the audio hardware interface has been initialized.
1095 * returns 0 on success, -ENODEV on failure.
1096 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301097int qahw_init_check_l(const qahw_module_handle_t *hw_module)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301098{
1099 int rc = -EINVAL;
1100 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1101 qahw_module_t *qahw_module_temp;
1102
1103 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301104 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301105 pthread_mutex_unlock(&qahw_module_init_lock);
1106 if (qahw_module_temp == NULL) {
1107 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1108 goto exit;
1109 }
1110
1111 pthread_mutex_lock(&qahw_module->lock);
1112 if (qahw_module->audio_device->init_check) {
1113 rc = qahw_module->audio_device->init_check(qahw_module->audio_device);
1114 } else {
1115 rc = -ENOSYS;
1116 ALOGW("%s not supported", __func__);
1117 }
1118 pthread_mutex_unlock(&qahw_module->lock);
1119
1120exit:
1121 return rc;
1122}
1123/* set the audio volume of a voice call. Range is between 0.0 and 1.0 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301124int qahw_set_voice_volume_l(qahw_module_handle_t *hw_module, float volume)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301125{
1126 int rc = -EINVAL;
1127 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1128 qahw_module_t *qahw_module_temp;
1129
1130 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301131 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301132 pthread_mutex_unlock(&qahw_module_init_lock);
1133 if (qahw_module_temp == NULL) {
1134 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1135 goto exit;
1136 }
1137
1138 pthread_mutex_lock(&qahw_module->lock);
1139 if (qahw_module->audio_device->set_voice_volume) {
1140 rc = qahw_module->audio_device->set_voice_volume(qahw_module->audio_device,
1141 volume);
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
1152/*
1153 * set_mode is called when the audio mode changes. AUDIO_MODE_NORMAL mode
1154 * is for standard audio playback, AUDIO_MODE_RINGTONE when a ringtone is
1155 * playing, and AUDIO_MODE_IN_CALL when a call is in progress.
1156 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301157int qahw_set_mode_l(qahw_module_handle_t *hw_module, audio_mode_t mode)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301158{
1159 int rc = -EINVAL;
1160 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1161 qahw_module_t *qahw_module_temp;
1162
1163 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301164 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301165 pthread_mutex_unlock(&qahw_module_init_lock);
1166 if (qahw_module_temp == NULL) {
1167 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1168 goto exit;
1169 }
1170
1171 pthread_mutex_lock(&qahw_module->lock);
1172 if (qahw_module->audio_device->set_mode) {
1173 rc = qahw_module->audio_device->set_mode(qahw_module->audio_device,
1174 mode);
1175 } else {
1176 rc = -ENOSYS;
1177 ALOGW("%s not supported", __func__);
1178 }
1179 pthread_mutex_unlock(&qahw_module->lock);
1180
1181exit:
1182 return rc;
1183}
1184
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301185int qahw_set_mic_mute_l(qahw_module_handle_t *hw_module, bool state)
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +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);
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +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_mic_mute) {
1201 rc = qahw_module->audio_device->set_mic_mute(qahw_module->audio_device,
1202 state);
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_get_mic_mute_l(qahw_module_handle_t *hw_module, bool *state)
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301214{
1215 size_t rc = 0;
1216 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1217 qahw_module_t *qahw_module_temp;
1218 audio_hw_device_t *audio_device;
1219
1220 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301221 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301222 pthread_mutex_unlock(&qahw_module_init_lock);
1223 if (qahw_module_temp == NULL) {
1224 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1225 goto exit;
1226 }
1227
1228 pthread_mutex_lock(&qahw_module->lock);
1229 audio_device = qahw_module->audio_device;
1230 if (qahw_module->audio_device->get_mic_mute) {
Dhananjay Kumar23a3bec2017-01-11 18:38:09 +05301231 rc = audio_device->get_mic_mute(qahw_module->audio_device, state);
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301232 } else {
1233 rc = -ENOSYS;
1234 ALOGW("%s not supported", __func__);
1235 }
1236 pthread_mutex_unlock(&qahw_module->lock);
1237
1238exit:
1239 return rc;
1240}
1241
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301242/* set/get global audio parameters */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301243int qahw_set_parameters_l(qahw_module_handle_t *hw_module, const char *kv_pairs)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301244{
1245 int rc = -EINVAL;
1246 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1247 qahw_module_t *qahw_module_temp;
1248 audio_hw_device_t *audio_device;
1249
1250 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301251 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301252 pthread_mutex_unlock(&qahw_module_init_lock);
1253 if (qahw_module_temp == NULL) {
1254 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1255 goto exit;
1256 }
1257
1258 pthread_mutex_lock(&qahw_module->lock);
1259 audio_device = qahw_module->audio_device;
1260 if (qahw_module->audio_device->set_parameters) {
1261 rc = audio_device->set_parameters(qahw_module->audio_device, kv_pairs);
1262 } else {
1263 rc = -ENOSYS;
1264 ALOGW("%s not supported", __func__);
1265 }
1266 pthread_mutex_unlock(&qahw_module->lock);
1267
1268exit:
1269 return rc;
1270}
1271
1272/*
1273 * Returns a pointer to a heap allocated string. The caller is responsible
1274 * for freeing the memory for it using free().
1275 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301276char * qahw_get_parameters_l(const qahw_module_handle_t *hw_module,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301277 const char *keys)
1278{
1279 char *str_param = NULL;
1280 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1281 qahw_module_t *qahw_module_temp;
1282 audio_hw_device_t *audio_device;
1283
1284 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301285 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301286 pthread_mutex_unlock(&qahw_module_init_lock);
1287 if (qahw_module_temp == NULL) {
1288 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1289 goto exit;
1290 }
1291
1292 pthread_mutex_lock(&qahw_module->lock);
1293 audio_device = qahw_module->audio_device;
1294 if (qahw_module->audio_device->get_parameters) {
1295 str_param = audio_device->get_parameters(qahw_module->audio_device, keys);
1296 } else {
1297 ALOGW("%s not supported", __func__);
1298 }
1299 pthread_mutex_unlock(&qahw_module->lock);
1300
1301exit:
1302 return str_param;
1303}
1304
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301305/* Api to implement get parameters based on keyword param_id
1306 * and store data in payload.
1307 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301308int qahw_get_param_data_l(const qahw_module_handle_t *hw_module,
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301309 qahw_param_id param_id,
1310 qahw_param_payload *payload)
1311{
1312 int ret = 0;
1313 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1314 qahw_module_t *qahw_module_temp;
1315
1316 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301317 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301318 pthread_mutex_unlock(&qahw_module_init_lock);
1319 if (qahw_module_temp == NULL) {
1320 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1321 goto exit;
1322 }
1323
1324 pthread_mutex_lock(&qahw_module->lock);
1325
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301326 if (qahw_module->qahwi_get_param_data){
1327 ret = qahw_module->qahwi_get_param_data (qahw_module->audio_device,
1328 param_id, payload);
1329 } else {
1330 ret = -ENOSYS;
1331 ALOGE("%s not supported\n",__func__);
1332 }
1333 pthread_mutex_unlock(&qahw_module->lock);
1334
1335exit:
1336 return ret;
1337}
1338
1339/* Api to implement set parameters based on keyword param_id
1340 * and data present in payload.
1341 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301342int qahw_set_param_data_l(const qahw_module_handle_t *hw_module,
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301343 qahw_param_id param_id,
1344 qahw_param_payload *payload)
1345{
1346 int ret = 0;
1347 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1348 qahw_module_t *qahw_module_temp;
1349
1350 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301351 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301352 pthread_mutex_unlock(&qahw_module_init_lock);
1353 if (qahw_module_temp == NULL) {
1354 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1355 goto exit;
1356 }
1357
1358 pthread_mutex_lock(&qahw_module->lock);
1359
1360 if (qahw_module->qahwi_set_param_data){
1361 ret = qahw_module->qahwi_set_param_data (qahw_module->audio_device,
1362 param_id, payload);
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301363 } else {
1364 ret = -ENOSYS;
1365 ALOGE("%s not supported\n",__func__);
1366 }
1367 pthread_mutex_unlock(&qahw_module->lock);
1368
1369exit:
1370 return ret;
1371}
1372
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301373/* Creates an audio patch between several source and sink ports.
1374 * The handle is allocated by the HAL and should be unique for this
1375 * audio HAL module.
1376 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301377int qahw_create_audio_patch_l(qahw_module_handle_t *hw_module,
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301378 unsigned int num_sources,
1379 const struct audio_port_config *sources,
1380 unsigned int num_sinks,
1381 const struct audio_port_config *sinks,
1382 audio_patch_handle_t *handle)
1383{
1384 int ret = 0;
1385 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1386 qahw_module_t *qahw_module_temp;
1387
1388 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301389 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301390 pthread_mutex_unlock(&qahw_module_init_lock);
1391 if (qahw_module_temp == NULL) {
1392 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1393 goto exit;
1394 }
1395
1396 pthread_mutex_lock(&qahw_module->lock);
1397 if (qahw_module->audio_device->create_audio_patch) {
1398 ret = qahw_module->audio_device->create_audio_patch(
1399 qahw_module->audio_device,
1400 num_sources,
1401 sources,
1402 num_sinks,
1403 sinks,
1404 handle);
1405 } else {
1406 ret = -ENOSYS;
1407 ALOGE("%s not supported\n",__func__);
1408 }
1409 pthread_mutex_unlock(&qahw_module->lock);
1410
1411exit:
1412 return ret;
1413}
1414
1415/* Release an audio patch */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301416int qahw_release_audio_patch_l(qahw_module_handle_t *hw_module,
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301417 audio_patch_handle_t handle)
1418{
1419 int ret = 0;
1420 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1421 qahw_module_t *qahw_module_temp;
1422
1423 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301424 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301425 pthread_mutex_unlock(&qahw_module_init_lock);
1426 if (qahw_module_temp == NULL) {
1427 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1428 goto exit;
1429 }
1430
1431 pthread_mutex_lock(&qahw_module->lock);
1432 if (qahw_module->audio_device->release_audio_patch) {
1433 ret = qahw_module->audio_device->release_audio_patch(
1434 qahw_module->audio_device,
1435 handle);
1436 } else {
1437 ret = -ENOSYS;
1438 ALOGE("%s not supported\n",__func__);
1439 }
1440 pthread_mutex_unlock(&qahw_module->lock);
1441
1442exit:
1443 return ret;
1444}
1445
Trinath Thammishetty580f1de2018-09-28 12:43:24 +05301446int qahw_loopback_set_param_data_l(qahw_module_handle_t *hw_module,
1447 audio_patch_handle_t handle,
1448 qahw_loopback_param_id param_id,
1449 qahw_loopback_param_payload *payload)
1450
1451{
1452 int ret = -EINVAL;
1453 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1454
1455 if (!payload) {
1456 ALOGE("%s:: invalid param", __func__);
1457 goto exit;
1458 }
1459
1460 if (qahw_module->qahwi_loopback_set_param_data) {
1461 ret = qahw_module->qahwi_loopback_set_param_data(handle,
1462 param_id,
Trinath Thammishetty15cd3402018-10-29 11:57:19 +05301463 payload);
Trinath Thammishetty580f1de2018-09-28 12:43:24 +05301464 } else {
1465 ret = -ENOSYS;
1466 ALOGE("%s not supported\n", __func__);
1467 }
1468
1469exit:
1470 return ret;
1471
1472}
1473
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301474/* Fills the list of supported attributes for a given audio port.
1475 * As input, "port" contains the information (type, role, address etc...)
1476 * needed by the HAL to identify the port.
1477 * As output, "port" contains possible attributes (sampling rates, formats,
1478 * channel masks, gain controllers...) for this port.
1479 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301480int qahw_get_audio_port_l(qahw_module_handle_t *hw_module,
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301481 struct audio_port *port)
1482{
1483 int ret = 0;
1484 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1485 qahw_module_t *qahw_module_temp;
1486
1487 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301488 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301489 pthread_mutex_unlock(&qahw_module_init_lock);
1490 if (qahw_module_temp == NULL) {
1491 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1492 goto exit;
1493 }
1494
1495 pthread_mutex_lock(&qahw_module->lock);
1496 if (qahw_module->audio_device->get_audio_port) {
1497 ret = qahw_module->audio_device->get_audio_port(
1498 qahw_module->audio_device,
1499 port);
1500 } else {
1501 ret = -ENOSYS;
1502 ALOGE("%s not supported\n",__func__);
1503 }
1504 pthread_mutex_unlock(&qahw_module->lock);
1505
1506exit:
1507 return ret;
1508}
1509
1510/* Set audio port configuration */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301511int qahw_set_audio_port_config_l(qahw_module_handle_t *hw_module,
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301512 const struct audio_port_config *config)
1513{
1514 int ret = 0;
1515 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1516 qahw_module_t *qahw_module_temp;
1517
1518 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301519 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301520 pthread_mutex_unlock(&qahw_module_init_lock);
1521 if (qahw_module_temp == NULL) {
1522 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1523 goto exit;
1524 }
1525
1526 pthread_mutex_lock(&qahw_module->lock);
1527 if (qahw_module->audio_device->set_audio_port_config) {
1528 ret = qahw_module->audio_device->set_audio_port_config(
1529 qahw_module->audio_device,
1530 config);
1531 } else {
1532 ret = -ENOSYS;
1533 ALOGE("%s not supported\n",__func__);
1534 }
1535 pthread_mutex_unlock(&qahw_module->lock);
1536
1537exit:
1538 return ret;
1539}
1540
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301541/* Returns audio input buffer size according to parameters passed or
1542 * 0 if one of the parameters is not supported.
1543 * See also get_buffer_size which is for a particular stream.
1544 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301545size_t qahw_get_input_buffer_size_l(const qahw_module_handle_t *hw_module,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301546 const struct audio_config *config)
1547{
1548 size_t rc = 0;
1549 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1550 qahw_module_t *qahw_module_temp;
1551 audio_hw_device_t *audio_device;
1552
1553 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301554 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301555 pthread_mutex_unlock(&qahw_module_init_lock);
1556 if (qahw_module_temp == NULL) {
1557 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1558 goto exit;
1559 }
1560
1561 pthread_mutex_lock(&qahw_module->lock);
1562 audio_device = qahw_module->audio_device;
1563 if (qahw_module->audio_device->get_input_buffer_size) {
1564 rc = audio_device->get_input_buffer_size(qahw_module->audio_device,
1565 config);
1566 } else {
1567 rc = -ENOSYS;
1568 ALOGW("%s not supported", __func__);
1569 }
1570 pthread_mutex_unlock(&qahw_module->lock);
1571
1572exit:
1573 return rc;
1574}
1575
1576/*
1577 * This method creates and opens the audio hardware output stream.
1578 * The "address" parameter qualifies the "devices" audio device type if needed.
1579 * The format format depends on the device type:
1580 * - Bluetooth devices use the MAC address of the device in the form "00:11:22:AA:BB:CC"
1581 * - USB devices use the ALSA card and device numbers in the form "card=X;device=Y"
1582 * - Other devices may use a number or any other string.
1583 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301584int qahw_open_output_stream_l(qahw_module_handle_t *hw_module,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301585 audio_io_handle_t handle,
1586 audio_devices_t devices,
1587 audio_output_flags_t flags,
1588 struct audio_config *config,
1589 qahw_stream_handle_t **out_handle,
1590 const char *address)
1591{
1592 int rc = -EINVAL;
1593 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1594 qahw_module_t *qahw_module_temp = NULL;
1595 audio_hw_device_t *audio_device = NULL;
1596 qahw_stream_out_t *qahw_stream_out = NULL;
1597
1598 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301599 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301600 pthread_mutex_unlock(&qahw_module_init_lock);
1601 if (qahw_module_temp == NULL) {
1602 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1603 return rc;
1604 }
1605
1606 pthread_mutex_lock(&qahw_module->lock);
1607 audio_device = qahw_module->audio_device;
1608 qahw_stream_out = (qahw_stream_out_t *)calloc(1, sizeof(qahw_stream_out_t));
1609 if (qahw_stream_out == NULL) {
1610 ALOGE("%s:: calloc failed for out stream_out_t",__func__);
1611 rc = -ENOMEM;
1612 goto exit;
1613 }
1614
1615 rc = audio_device->open_output_stream(audio_device,
1616 handle,
1617 devices,
1618 flags,
1619 config,
1620 &qahw_stream_out->stream,
1621 address);
1622 if (rc) {
1623 ALOGE("%s::open output stream failed %d",__func__, rc);
1624 free(qahw_stream_out);
1625 } else {
1626 qahw_stream_out->module = hw_module;
1627 *out_handle = (void *)qahw_stream_out;
1628 pthread_mutex_init(&qahw_stream_out->lock, (const pthread_mutexattr_t *)NULL);
1629 list_add_tail(&qahw_module->out_list, &qahw_stream_out->list);
Manish Dewangan3ccdea52017-02-13 19:31:54 +05301630
1631 /* clear any existing errors */
1632 const char *error;
1633 dlerror();
1634 qahw_stream_out->qahwi_out_get_param_data = (qahwi_out_get_param_data_t)
1635 dlsym(qahw_module->module->dso,
1636 "qahwi_out_get_param_data");
1637 if ((error = dlerror()) != NULL) {
1638 ALOGI("%s: dlsym error %s for qahwi_out_get_param_data",
1639 __func__, error);
1640 qahw_stream_out->qahwi_out_get_param_data = NULL;
1641 }
1642
1643 dlerror();
1644 qahw_stream_out->qahwi_out_set_param_data = (qahwi_out_set_param_data_t)
1645 dlsym(qahw_module->module->dso,
1646 "qahwi_out_set_param_data");
1647 if ((error = dlerror()) != NULL) {
1648 ALOGI("%s: dlsym error %s for qahwi_out_set_param_data",
1649 __func__, error);
1650 qahw_stream_out->qahwi_out_set_param_data = NULL;
1651 }
1652}
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301653
Naresh Tanniruee3499a2017-01-05 14:05:35 +05301654 /* dlsym qahwi_out_write_v2 */
1655 if (!rc) {
1656 const char *error;
1657
1658 /* clear any existing errors */
1659 dlerror();
1660 qahw_stream_out->qahwi_out_write_v2 = (qahwi_out_write_v2_t)dlsym(qahw_module->module->dso, "qahwi_out_write_v2");
1661 if ((error = dlerror()) != NULL) {
1662 ALOGI("%s: dlsym error %s for qahwi_out_write_v2", __func__, error);
1663 qahw_stream_out->qahwi_out_write_v2 = NULL;
1664 }
1665 }
1666
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301667exit:
1668 pthread_mutex_unlock(&qahw_module->lock);
1669 return rc;
1670}
1671
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301672int qahw_close_output_stream_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301673{
1674
1675 int rc = 0;
1676 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
1677 qahw_module_t *qahw_module = NULL;
1678 audio_hw_device_t *audio_device = NULL;
1679
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301680 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301681 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
1682 rc = -EINVAL;
1683 goto exit;
1684 }
1685
1686 ALOGV("%s::calling device close_output_stream %p", __func__, out_handle);
1687 pthread_mutex_lock(&qahw_stream_out->lock);
1688 qahw_module = qahw_stream_out->module;
1689 audio_device = qahw_module->audio_device;
1690 audio_device->close_output_stream(audio_device,
1691 qahw_stream_out->stream);
1692
1693 pthread_mutex_lock(&qahw_module->lock);
1694 list_remove(&qahw_stream_out->list);
1695 pthread_mutex_unlock(&qahw_module->lock);
1696
1697 pthread_mutex_unlock(&qahw_stream_out->lock);
1698
1699 pthread_mutex_destroy(&qahw_stream_out->lock);
1700 free(qahw_stream_out);
1701
1702exit:
1703 return rc;
1704}
1705
1706/* This method creates and opens the audio hardware input stream */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301707int qahw_open_input_stream_l(qahw_module_handle_t *hw_module,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301708 audio_io_handle_t handle,
1709 audio_devices_t devices,
1710 struct audio_config *config,
1711 qahw_stream_handle_t **in_handle,
1712 audio_input_flags_t flags,
1713 const char *address,
1714 audio_source_t source)
1715{
1716 int rc = -EINVAL;
1717 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1718 qahw_module_t *qahw_module_temp = NULL;
1719 audio_hw_device_t *audio_device = NULL;
1720 qahw_stream_in_t *qahw_stream_in = NULL;
1721
1722 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301723 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301724 pthread_mutex_unlock(&qahw_module_init_lock);
1725 if (qahw_module_temp == NULL) {
1726 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1727 return rc;
1728 }
1729
1730 pthread_mutex_lock(&qahw_module->lock);
1731 audio_device = qahw_module->audio_device;
1732 qahw_stream_in = (qahw_stream_in_t *)calloc(1, sizeof(qahw_stream_in_t));
1733 if (qahw_stream_in == NULL) {
1734 ALOGE("%s:: calloc failed for in stream_in_t",__func__);
1735 rc = -ENOMEM;
1736 goto exit;
1737 }
1738
1739 rc = audio_device->open_input_stream(audio_device,
1740 handle,
1741 devices,
1742 config,
1743 &qahw_stream_in->stream,
1744 flags,
1745 address,
1746 source);
1747 if (rc) {
1748 ALOGE("%s::open input stream failed %d",__func__, rc);
1749 free(qahw_stream_in);
1750 } else {
1751 qahw_stream_in->module = hw_module;
1752 *in_handle = (void *)qahw_stream_in;
1753 pthread_mutex_init(&qahw_stream_in->lock, (const pthread_mutexattr_t *)NULL);
1754 list_add_tail(&qahw_module->in_list, &qahw_stream_in->list);
1755 }
1756
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05301757 /* dlsym qahwi_in_read_v2 if timestamp flag is used */
Ralf Herzaec80262018-07-03 07:08:49 +02001758 if (!rc && ((flags & QAHW_INPUT_FLAG_TIMESTAMP) ||
1759 (flags & QAHW_INPUT_FLAG_PASSTHROUGH))) {
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05301760 const char *error;
1761
1762 /* clear any existing errors */
1763 dlerror();
1764 qahw_stream_in->qahwi_in_read_v2 = (qahwi_in_read_v2_t)
1765 dlsym(qahw_module->module->dso, "qahwi_in_read_v2");
1766 if ((error = dlerror()) != NULL) {
1767 ALOGI("%s: dlsym error %s for qahwi_in_read_v2", __func__, error);
1768 qahw_stream_in->qahwi_in_read_v2 = NULL;
1769 }
1770 }
1771
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301772exit:
1773 pthread_mutex_unlock(&qahw_module->lock);
1774 return rc;
1775}
1776
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301777int qahw_close_input_stream_l(qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301778{
1779 int rc = 0;
1780 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
1781 qahw_module_t *qahw_module = NULL;
1782 audio_hw_device_t *audio_device = NULL;
1783
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301784 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301785 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
1786 rc = -EINVAL;
1787 goto exit;
1788 }
1789
1790 ALOGV("%s:: calling device close_input_stream %p", __func__, in_handle);
1791 pthread_mutex_lock(&qahw_stream_in->lock);
1792 qahw_module = qahw_stream_in->module;
1793 audio_device = qahw_module->audio_device;
1794 audio_device->close_input_stream(audio_device,
1795 qahw_stream_in->stream);
1796
1797 pthread_mutex_lock(&qahw_module->lock);
1798 list_remove(&qahw_stream_in->list);
1799 pthread_mutex_unlock(&qahw_module->lock);
1800
1801 pthread_mutex_unlock(&qahw_stream_in->lock);
1802
1803 pthread_mutex_destroy(&qahw_stream_in->lock);
1804 free(qahw_stream_in);
1805
1806exit:
1807 return rc;
1808}
1809
1810/*returns current QTI HAL verison */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301811int qahw_get_version_l() {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301812 return QAHW_MODULE_API_VERSION_CURRENT;
1813}
1814
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +05301815/* Load AHAL module to run audio and sva concurrency */
1816static void load_st_hal()
1817{
1818#ifdef SVA_AUDIO_CONC
1819 int rc = -EINVAL;
1820 const hw_module_t* module = NULL;
1821
1822 rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, "primary", &module);
1823 if (rc) {
1824 ALOGE("%s: AHAL Loading failed %d", __func__, rc);
1825 goto error;
1826 }
1827
1828 rc = sound_trigger_hw_device_open(module, &st_hw_device);
1829 if (rc) {
1830 ALOGE("%s: AHAL Device open failed %d", __func__, rc);
1831 st_hw_device = NULL;
1832 }
1833error:
1834 return;
1835#else
1836 return;
1837#endif /*SVA_AUDIO_CONC*/
1838}
1839
1840static void unload_st_hal()
1841{
1842#ifdef SVA_AUDIO_CONC
1843 if (st_hw_device == NULL) {
1844 ALOGE("%s: audio device is NULL",__func__);
1845 return;
1846 }
1847 sound_trigger_hw_device_close(st_hw_device);
1848 st_hw_device = NULL;
1849#else
1850 return;
1851#endif /*SVA_AUDIO_CONC*/
1852}
1853
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301854/* convenience API for opening and closing an audio HAL module */
1855
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301856qahw_module_handle_t *qahw_load_module_l(const char *hw_module_id)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301857{
1858 int rc = -EINVAL;
1859 qahw_module_handle_t *qahw_mod_handle = NULL;
1860 qahw_module_t *qahw_module = NULL;
1861 char *ahal_name = NULL;
1862 const hw_module_t* module = NULL;
1863 audio_hw_device_t* audio_device = NULL;
1864
1865 if (hw_module_id == NULL) {
1866 ALOGE("%s::module id is NULL",__func__);
1867 goto exit;
1868 }
1869
1870 if (!strcmp(hw_module_id, QAHW_MODULE_ID_PRIMARY)) {
1871 ahal_name = "primary";
1872 } else if (!strcmp(hw_module_id, QAHW_MODULE_ID_A2DP)) {
1873 ahal_name = "a2dp";
1874 } else if (!strcmp(hw_module_id, QAHW_MODULE_ID_USB)) {
1875 ahal_name = "usb";
1876 } else {
1877 ALOGE("%s::Invalid Module id %s", __func__, hw_module_id);
1878 goto exit;
1879 }
1880
1881 /* return exiting module ptr if already loaded */
1882 pthread_mutex_lock(&qahw_module_init_lock);
1883 if (qahw_list_count > 0) {
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301884 qahw_module = get_qahw_module_by_name_l(hw_module_id);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301885 if(qahw_module != NULL) {
1886 qahw_mod_handle = (void *)qahw_module;
1887 pthread_mutex_lock(&qahw_module->lock);
1888 qahw_module->ref_count++;
1889 pthread_mutex_unlock(&qahw_module->lock);
1890 goto error_exit;
1891 }
1892 }
1893
1894 rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, ahal_name, &module);
1895 if(rc) {
1896 ALOGE("%s::HAL Loading failed %d", __func__, rc);
1897 goto error_exit;
1898 }
1899
1900 rc = audio_hw_device_open(module, &audio_device);
1901 if(rc) {
1902 ALOGE("%s::HAL Device open failed %d", __func__, rc);
1903 goto error_exit;
1904 }
1905
1906 qahw_module = (qahw_module_t *)calloc(1, sizeof(qahw_module_t));
1907 if(qahw_module == NULL) {
1908 ALOGE("%s::calloc failed", __func__);
1909 audio_hw_device_close(audio_device);
1910 goto error_exit;
1911 }
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05301912 qahw_module->module = module;
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301913 ALOGD("%s::Loaded HAL %s module %p", __func__, ahal_name, qahw_module);
1914
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301915 qahw_module->qahwi_get_param_data = (qahwi_get_param_data_t) dlsym (module->dso,
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301916 "qahwi_get_param_data");
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301917 if (!qahw_module->qahwi_get_param_data)
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301918 ALOGD("%s::qahwi_get_param_data api is not defined\n",__func__);
1919
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301920 qahw_module->qahwi_set_param_data = (qahwi_set_param_data_t) dlsym (module->dso,
1921 "qahwi_set_param_data");
1922 if (!qahw_module->qahwi_set_param_data)
1923 ALOGD("%s::qahwi_set_param_data api is not defined\n",__func__);
1924
Trinath Thammishetty580f1de2018-09-28 12:43:24 +05301925 qahw_module->qahwi_loopback_set_param_data = (qahwi_loopback_set_param_data_t)
1926 dlsym(module->dso,
1927 "qahwi_loopback_set_param_data");
1928 if (!qahw_module->qahwi_loopback_set_param_data)
1929 ALOGD("%s::qahwi_loopback_set_param_data api is not defined\n", __func__);
1930
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301931 if (!qahw_list_count)
1932 list_init(&qahw_module_list);
1933 qahw_list_count++;
1934
1935 pthread_mutex_init(&qahw_module->lock, (const pthread_mutexattr_t *) NULL);
1936 pthread_mutex_lock(&qahw_module->lock);
1937 qahw_module->ref_count++;
1938 pthread_mutex_unlock(&qahw_module->lock);
1939
1940 list_init(&qahw_module->out_list);
1941 list_init(&qahw_module->in_list);
1942
1943 /* update qahw_module */
1944 qahw_module->audio_device = audio_device;
1945 strlcpy(&qahw_module->module_name[0], hw_module_id, MAX_MODULE_NAME_LENGTH);
1946
1947 qahw_mod_handle = (void *)qahw_module;
1948
1949 /* Add module list to global module list */
1950 list_add_tail(&qahw_module_list, &qahw_module->module_list);
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +05301951 load_st_hal();
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301952
1953error_exit:
1954 pthread_mutex_unlock(&qahw_module_init_lock);
1955
1956exit:
1957 return qahw_mod_handle;
1958}
1959
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301960int qahw_unload_module_l(qahw_module_handle_t *hw_module)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301961{
1962 int rc = -EINVAL;
1963 bool is_empty = false;
1964 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1965 qahw_module_t *qahw_module_temp = NULL;
1966
1967 /* close HW device if its valid and all the streams on
1968 * it is closed
1969 */
1970 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301971 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301972 if (qahw_module_temp == NULL) {
1973 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1974 goto error_exit;
1975 }
1976
1977 pthread_mutex_lock(&qahw_module->lock);
1978 qahw_module->ref_count--;
1979 if (qahw_module->ref_count > 0) {
1980 rc = 0;
1981 ALOGE("%s:: skipping module unload of %p count %d", __func__,
1982 qahw_module,
1983 qahw_module->ref_count);
1984 pthread_mutex_unlock(&qahw_module->lock);
1985 goto error_exit;
1986 }
1987
1988 is_empty = (list_empty(&qahw_module->out_list) &&
1989 list_empty(&qahw_module->in_list));
1990 if (is_empty) {
1991 rc = audio_hw_device_close(qahw_module->audio_device);
1992 if(rc) {
1993 ALOGE("%s::HAL Device close failed Error %d Module %p",__func__,
1994 rc, qahw_module);
1995 rc = 0;
1996 }
1997 qahw_list_count--;
1998 list_remove(&qahw_module->module_list);
1999 pthread_mutex_unlock(&qahw_module->lock);
2000 pthread_mutex_destroy(&qahw_module->lock);
2001 free(qahw_module);
2002 } else {
2003 pthread_mutex_unlock(&qahw_module->lock);
2004 ALOGE("%s::failed as all the streams on this module"
2005 "is not closed", __func__);
2006 rc = -EINVAL;
2007 }
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +05302008 unload_st_hal();
Manish Dewanganb8c83a42016-09-23 15:10:48 +05302009
2010error_exit:
2011 pthread_mutex_unlock(&qahw_module_init_lock);
2012
Manish Dewanganb8c83a42016-09-23 15:10:48 +05302013 return rc;
2014}
2015
2016__END_DECLS