blob: 30ebe6dd258f2d9c0415f1988e8ba40a68c93d8f [file] [log] [blame]
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05301/*
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002 * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +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 "audio_hw_qap"
31#define LOG_NDEBUG 0
32#define VERY_VERY_VERBOSE_LOGGING
33#ifdef VERY_VERY_VERBOSE_LOGGING
34#define DEBUG_MSG_VV DEBUG_MSG
35#else
36#define DEBUG_MSG_VV(a...) do { } while(0)
37#endif
38
39#define DEBUG_MSG(arg,...) ALOGE("%s: %d: " arg, __func__, __LINE__, ##__VA_ARGS__)
40#define ERROR_MSG(arg,...) ALOGE("%s: %d: " arg, __func__, __LINE__, ##__VA_ARGS__)
41
42#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 2
43#define COMPRESS_PASSTHROUGH_DDP_FRAGMENT_SIZE 4608
44
45#define QAP_DEFAULT_COMPR_AUDIO_HANDLE 1001
46#define QAP_DEFAULT_COMPR_PASSTHROUGH_HANDLE 1002
47#define QAP_DEFAULT_PASSTHROUGH_HANDLE 1003
48
49#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 300
50
51#define MIN_PCM_OFFLOAD_FRAGMENT_SIZE 512
52#define MAX_PCM_OFFLOAD_FRAGMENT_SIZE (240 * 1024)
53
54#define DIV_ROUND_UP(x, y) (((x) + (y) - 1)/(y))
55#define ALIGN(x, y) ((y) * DIV_ROUND_UP((x), (y)))
56
57/* Pcm input node buffer size is 6144 bytes, i.e, 32msec for 48000 samplerate */
58#define QAP_MODULE_PCM_INPUT_BUFFER_LATENCY 32
59
60#define MS12_PCM_OUT_FRAGMENT_SIZE 1536 //samples
61#define MS12_PCM_IN_FRAGMENT_SIZE 1536 //samples
62
63#define DD_FRAME_SIZE 1536
64#define DDP_FRAME_SIZE DD_FRAME_SIZE
65/*
66 * DD encoder output size for one frame.
67 */
68#define DD_ENCODER_OUTPUT_SIZE 2560
69/*
70 * DDP encoder output size for one frame.
71 */
72#define DDP_ENCODER_OUTPUT_SIZE 4608
73
74/*********TODO Need to get correct values.*************************/
75
76#define DTS_PCM_OUT_FRAGMENT_SIZE 1024 //samples
77
78#define DTS_FRAME_SIZE 1536
79#define DTSHD_FRAME_SIZE DTS_FRAME_SIZE
80/*
81 * DTS encoder output size for one frame.
82 */
83#define DTS_ENCODER_OUTPUT_SIZE 2560
84/*
85 * DTSHD encoder output size for one frame.
86 */
87#define DTSHD_ENCODER_OUTPUT_SIZE 4608
88/******************************************************************/
89
90/*
91 * QAP Latency to process buffers since out_write from primary HAL
92 */
93#define QAP_COMPRESS_OFFLOAD_PROCESSING_LATENCY 18
94#define QAP_PCM_OFFLOAD_PROCESSING_LATENCY 48
95
96//TODO: Need to handle for DTS
97#define QAP_DEEP_BUFFER_OUTPUT_PERIOD_SIZE 1536
98
99#include <stdlib.h>
100#include <pthread.h>
101#include <errno.h>
102#include <dlfcn.h>
103#include <unistd.h>
104#include <sys/resource.h>
105#include <sys/prctl.h>
106#include <cutils/properties.h>
107#include <cutils/str_parms.h>
108#include <cutils/log.h>
109#include <cutils/atomic.h>
110#include "audio_utils/primitives.h"
111#include "audio_hw.h"
112#include "platform_api.h"
113#include <platform.h>
114#include <system/thread_defs.h>
115#include <cutils/sched_policy.h>
116#include "audio_extn.h"
117#include <qti_audio.h>
118#include <qap_api.h>
119#include "sound/compress_params.h"
120#include "ip_hdlr_intf.h"
121#include "dolby_ms12.h"
122
123#ifdef DYNAMIC_LOG_ENABLED
124#include <log_xml_parser.h>
125#define LOG_MASK HAL_MOD_FILE_QAF
126#include <log_utils.h>
127#endif
128
129//TODO: Need to remove this.
130#define QAP_OUTPUT_SAMPLING_RATE 48000
131
132#ifdef QAP_DUMP_ENABLED
133FILE *fp_output_writer_hdmi = NULL;
134#endif
135
136//Types of MM module, currently supported by QAP.
137typedef enum {
138 MS12,
139 DTS_M8,
140 MAX_MM_MODULE_TYPE,
141 INVALID_MM_MODULE
142} mm_module_type;
143
144typedef enum {
145 QAP_OUT_TRANSCODE_PASSTHROUGH = 0, /* Transcode passthrough via MM module*/
146 QAP_OUT_OFFLOAD_MCH, /* Multi-channel PCM offload*/
147 QAP_OUT_OFFLOAD, /* PCM offload */
148
149 MAX_QAP_MODULE_OUT
150} mm_module_output_type;
151
152typedef enum {
153 QAP_IN_MAIN = 0, /* Single PID Main/Primary or Dual-PID stream */
154 QAP_IN_ASSOC, /* Associated/Secondary stream */
155 QAP_IN_PCM, /* PCM stream. */
156 QAP_IN_MAIN_2, /* Single PID Main2 stream */
157 MAX_QAP_MODULE_IN
158} mm_module_input_type;
159
160typedef enum {
161 STOPPED, /*Stream is in stop state. */
162 STOPPING, /*Stream is stopping, waiting for EOS. */
163 RUN, /*Stream is in run state. */
164 MAX_STATES
165} qap_stream_state;
166
167struct qap_module {
168 audio_session_handle_t session_handle;
169 void *qap_lib;
170 void *qap_handle;
171
172 /*Input stream of MM module */
173 struct stream_out *stream_in[MAX_QAP_MODULE_IN];
174 /*Output Stream from MM module */
175 struct stream_out *stream_out[MAX_QAP_MODULE_OUT];
176
177 /*Media format associated with each output id raised by mm module. */
178 qap_session_outputs_config_t session_outputs_config;
179 /*Flag is set if media format is changed for an mm module output. */
180 bool is_media_fmt_changed[MAX_QAP_MODULE_OUT];
181 /*Index to be updated in session_outputs_config array for a new mm module output. */
182 int new_out_format_index;
183
184 //BT session handle.
185 void *bt_hdl;
186
187 float vol_left;
188 float vol_right;
189 bool is_vol_set;
190 qap_stream_state stream_state[MAX_QAP_MODULE_IN];
191 bool is_session_closing;
192 bool is_session_output_active;
193 pthread_cond_t session_output_cond;
194 pthread_mutex_t session_output_lock;
195
196};
197
198struct qap {
199 struct audio_device *adev;
200
201 pthread_mutex_t lock;
202
203 bool bt_connect;
204 bool hdmi_connect;
205 int hdmi_sink_channels;
206
207 //Flag to indicate if QAP transcode output stream is enabled from any mm module.
208 bool passthrough_enabled;
209 //Flag to indicate if QAP mch pcm output stream is enabled from any mm module.
210 bool mch_pcm_hdmi_enabled;
211
212 //Flag to indicate if msmd is supported.
213 bool qap_msmd_enabled;
214
215 bool qap_output_block_handling;
216 //Handle of QAP input stream, which is routed as QAP passthrough.
217 struct stream_out *passthrough_in;
218 //Handle of QAP passthrough stream.
219 struct stream_out *passthrough_out;
220
221 struct qap_module qap_mod[MAX_MM_MODULE_TYPE];
222};
223
224//Global handle of QAP. Access to this should be protected by mutex lock.
225static struct qap *p_qap = NULL;
226
227/* Gets the pointer to qap module for the qap input stream. */
228static struct qap_module* get_qap_module_for_input_stream_l(struct stream_out *out)
229{
230 struct qap_module *qap_mod = NULL;
231 int i, j;
232 if (!p_qap) return NULL;
233
234 for (i = 0; i < MAX_MM_MODULE_TYPE; i++) {
235 for (j = 0; j < MAX_QAP_MODULE_IN; j++) {
236 if (p_qap->qap_mod[i].stream_in[j] == out) {
237 qap_mod = &(p_qap->qap_mod[i]);
238 break;
239 }
240 }
241 }
242
243 return qap_mod;
244}
245
246/* Finds the mm module input stream index for the QAP input stream. */
247static int get_input_stream_index_l(struct stream_out *out)
248{
249 int index = -1, j;
250 struct qap_module* qap_mod = NULL;
251
252 qap_mod = get_qap_module_for_input_stream_l(out);
253 if (!qap_mod) return index;
254
255 for (j = 0; j < MAX_QAP_MODULE_IN; j++) {
256 if (qap_mod->stream_in[j] == out) {
257 index = j;
258 break;
259 }
260 }
261
262 return index;
263}
264
265static void set_stream_state_l(struct stream_out *out, int state)
266{
267 struct qap_module *qap_mod = get_qap_module_for_input_stream_l(out);
268 int index = get_input_stream_index_l(out);
269 if (qap_mod && index >= 0) qap_mod->stream_state[index] = state;
270}
271
272static bool check_stream_state_l(struct stream_out *out, int state)
273{
274 struct qap_module *qap_mod = get_qap_module_for_input_stream_l(out);
275 int index = get_input_stream_index_l(out);
276 if (qap_mod && index >= 0) return ((int)qap_mod->stream_state[index] == state);
277 return false;
278}
279
280/* Finds the right mm module for the QAP input stream format. */
281static mm_module_type get_mm_module_for_format_l(audio_format_t format)
282{
283 int j;
284
285 DEBUG_MSG("Format 0x%x", format);
286
287 if (format == AUDIO_FORMAT_PCM_16_BIT) {
288 //If dts is not supported then alway support pcm with MS12
289 if (!property_get_bool("vendor.audio.qap.dts_m8", false)) { //TODO: Need to add this property for DTS.
290 return MS12;
291 }
292
293 //If QAP passthrough is active then send the PCM stream to primary HAL.
294 if (!p_qap->passthrough_out) {
295 /* Iff any stream is active in MS12 module then route PCM stream to it. */
296 for (j = 0; j < MAX_QAP_MODULE_IN; j++) {
297 if (p_qap->qap_mod[MS12].stream_in[j]) {
298 return MS12;
299 }
300 }
301 }
302 return INVALID_MM_MODULE;
303 }
304
305 switch (format & AUDIO_FORMAT_MAIN_MASK) {
306 case AUDIO_FORMAT_AC3:
307 case AUDIO_FORMAT_E_AC3:
308 case AUDIO_FORMAT_AAC:
309 case AUDIO_FORMAT_AAC_ADTS:
310 case AUDIO_FORMAT_AC4:
311 return MS12;
312 case AUDIO_FORMAT_DTS:
313 case AUDIO_FORMAT_DTS_HD:
314 return DTS_M8;
315 default:
316 return INVALID_MM_MODULE;
317 }
318}
319
320static bool is_main_active_l(struct qap_module* qap_mod)
321{
322 return (qap_mod->stream_in[QAP_IN_MAIN] || qap_mod->stream_in[QAP_IN_MAIN_2]);
323}
324
325static bool is_dual_main_active_l(struct qap_module* qap_mod)
326{
327 return (qap_mod->stream_in[QAP_IN_MAIN] && qap_mod->stream_in[QAP_IN_MAIN_2]);
328}
329
330//Checks if any main or pcm stream is running in the session.
331static bool is_any_stream_running_l(struct qap_module* qap_mod)
332{
333 //Not checking associated stream.
334 struct stream_out *out = qap_mod->stream_in[QAP_IN_MAIN];
335 struct stream_out *out_pcm = qap_mod->stream_in[QAP_IN_PCM];
336 struct stream_out *out_main2 = qap_mod->stream_in[QAP_IN_MAIN_2];
337
338 if ((out == NULL || (out != NULL && check_stream_state_l(out, STOPPED)))
339 && (out_main2 == NULL || (out_main2 != NULL && check_stream_state_l(out_main2, STOPPED)))
340 && (out_pcm == NULL || (out_pcm != NULL && check_stream_state_l(out_pcm, STOPPED)))) {
341 return false;
342 }
343 return true;
344}
345
346/* Gets the pcm output buffer size(in samples) for the mm module. */
347static uint32_t get_pcm_output_buffer_size_samples_l(struct qap_module *qap_mod)
348{
349 uint32_t pcm_output_buffer_size = 0;
350
351 if (qap_mod == &p_qap->qap_mod[MS12]) {
352 pcm_output_buffer_size = MS12_PCM_OUT_FRAGMENT_SIZE;
353 } else if (qap_mod == &p_qap->qap_mod[DTS_M8]) {
354 pcm_output_buffer_size = DTS_PCM_OUT_FRAGMENT_SIZE;
355 }
356
357 return pcm_output_buffer_size;
358}
359
360static int get_media_fmt_array_index_for_output_id_l(
361 struct qap_module* qap_mod,
362 uint32_t output_id)
363{
364 int i;
365 for (i = 0; i < MAX_SUPPORTED_OUTPUTS; i++) {
366 if (qap_mod->session_outputs_config.output_config[i].id == output_id) {
367 return i;
368 }
369 }
370 return -1;
371}
372
373/* Acquire Mutex lock on output stream */
374static void lock_output_stream_l(struct stream_out *out)
375{
376 pthread_mutex_lock(&out->pre_lock);
377 pthread_mutex_lock(&out->lock);
378 pthread_mutex_unlock(&out->pre_lock);
379}
380
381/* Release Mutex lock on output stream */
382static void unlock_output_stream_l(struct stream_out *out)
383{
384 pthread_mutex_unlock(&out->lock);
385}
386
387/* Checks if stream can be routed as QAP passthrough or not. */
388static bool audio_extn_qap_passthrough_enabled(struct stream_out *out)
389{
390 DEBUG_MSG("Format 0x%x", out->format);
391 bool is_enabled = false;
392
393 if (!p_qap) return false;
394
395 if ((!property_get_bool("vendor.audio.qap.reencode", false))
396 && property_get_bool("vendor.audio.qap.passthrough", false)) {
397
398 if ((out->format == AUDIO_FORMAT_PCM_16_BIT) && (popcount(out->channel_mask) > 2)) {
399 is_enabled = true;
400 } else if (property_get_bool("vendor.audio.offload.passthrough", false)) {
401 switch (out->format) {
402 case AUDIO_FORMAT_AC3:
403 case AUDIO_FORMAT_E_AC3:
404 case AUDIO_FORMAT_DTS:
405 case AUDIO_FORMAT_DTS_HD:
406 case AUDIO_FORMAT_DOLBY_TRUEHD:
407 case AUDIO_FORMAT_IEC61937: {
408 is_enabled = true;
409 break;
410 }
411 default:
412 is_enabled = false;
413 break;
414 }
415 }
416 }
417
418 return is_enabled;
419}
420
421/*Closes all pcm hdmi output from QAP. */
422static void close_all_pcm_hdmi_output_l()
423{
424 int i;
425 //Closing all the PCM HDMI output stream from QAP.
426 for (i = 0; i < MAX_MM_MODULE_TYPE; i++) {
427 if (p_qap->qap_mod[i].stream_out[QAP_OUT_OFFLOAD_MCH]) {
428 adev_close_output_stream((struct audio_hw_device *)p_qap->adev,
429 (struct audio_stream_out *)(p_qap->qap_mod[i].stream_out[QAP_OUT_OFFLOAD_MCH]));
430 p_qap->qap_mod[i].stream_out[QAP_OUT_OFFLOAD_MCH] = NULL;
431 }
432
433 if ((p_qap->qap_mod[i].stream_out[QAP_OUT_OFFLOAD])
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800434 && compare_device_type(
435 &p_qap->qap_mod[i].stream_out[QAP_OUT_OFFLOAD]->device_list,
436 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +0530437 adev_close_output_stream((struct audio_hw_device *)p_qap->adev,
438 (struct audio_stream_out *)(p_qap->qap_mod[i].stream_out[QAP_OUT_OFFLOAD]));
439 p_qap->qap_mod[i].stream_out[QAP_OUT_OFFLOAD] = NULL;
440 }
441 }
442
443 p_qap->mch_pcm_hdmi_enabled = 0;
444}
445
446static void close_all_hdmi_output_l()
447{
448 int k;
449 for (k = 0; k < MAX_MM_MODULE_TYPE; k++) {
450 if (p_qap->qap_mod[k].stream_out[QAP_OUT_TRANSCODE_PASSTHROUGH]) {
451 adev_close_output_stream((struct audio_hw_device *)p_qap->adev,
452 (struct audio_stream_out *)(p_qap->qap_mod[k].stream_out[QAP_OUT_TRANSCODE_PASSTHROUGH]));
453 p_qap->qap_mod[k].stream_out[QAP_OUT_TRANSCODE_PASSTHROUGH] = NULL;
454 }
455 }
456 p_qap->passthrough_enabled = 0;
457
458 close_all_pcm_hdmi_output_l();
459}
460
461static int qap_out_callback(stream_callback_event_t event, void *param __unused, void *cookie)
462{
463 struct stream_out *out = (struct stream_out *)cookie;
464
465 out->client_callback(event, NULL, out->client_cookie);
466 return 0;
467}
468
469/* Creates the QAP passthrough output stream. */
470static int create_qap_passthrough_stream_l()
471{
472 DEBUG_MSG("Entry");
473
474 int ret = 0;
475 struct stream_out *out = p_qap->passthrough_in;
476
477 if (!out) return -EINVAL;
478
479 pthread_mutex_lock(&p_qap->lock);
480 lock_output_stream_l(out);
481
482 //Creating QAP passthrough output stream.
483 if (NULL == p_qap->passthrough_out) {
484 audio_output_flags_t flags;
485 struct audio_config config;
486 audio_devices_t devices;
487
488 config.sample_rate = config.offload_info.sample_rate = out->sample_rate;
489 config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
490 config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
491 config.offload_info.format = out->format;
492 config.offload_info.bit_width = out->bit_width;
493 config.format = out->format;
494 config.offload_info.channel_mask = config.channel_mask = out->channel_mask;
495
496 //Device is copied from the QAP passthrough input stream.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800497 devices = get_device_types(&out->device_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +0530498 flags = out->flags;
499
500 ret = adev_open_output_stream((struct audio_hw_device *)p_qap->adev,
501 QAP_DEFAULT_PASSTHROUGH_HANDLE,
502 devices,
503 flags,
504 &config,
505 (struct audio_stream_out **)&(p_qap->passthrough_out),
506 NULL);
507 if (ret < 0) {
508 ERROR_MSG("adev_open_output_stream failed with ret = %d!", ret);
509 unlock_output_stream_l(out);
510 return ret;
511 }
512 p_qap->passthrough_in = out;
513 p_qap->passthrough_out->stream.set_callback((struct audio_stream_out *)p_qap->passthrough_out,
514 (stream_callback_t) qap_out_callback, out);
515 }
516
517 unlock_output_stream_l(out);
518
519 //Since QAP-Passthrough is created, close other HDMI outputs.
520 close_all_hdmi_output_l();
521
522 pthread_mutex_unlock(&p_qap->lock);
523 return ret;
524}
525
526
527/* Stops a QAP module stream.*/
528static int audio_extn_qap_stream_stop(struct stream_out *out)
529{
530 int ret = 0;
531 DEBUG_MSG("Output Stream 0x%x", (int)out);
532
533 if (!check_stream_state_l(out, RUN)) return ret;
534
535 struct qap_module *qap_mod = get_qap_module_for_input_stream_l(out);
536
537 if (!qap_mod || !qap_mod->session_handle|| !out->qap_stream_handle) {
538 ERROR_MSG("Wrong state to process qap_mod(%p) sess_hadl(%p) strm hndl(%p)",
539 qap_mod, qap_mod->session_handle, out->qap_stream_handle);
540 return -EINVAL;
541 }
542
543 ret = qap_module_cmd(out->qap_stream_handle,
544 QAP_MODULE_CMD_STOP,
545 sizeof(QAP_MODULE_CMD_STOP),
546 NULL,
547 NULL,
548 NULL);
549 if (QAP_STATUS_OK != ret) {
550 ERROR_MSG("stop failed %d", ret);
551 return -EINVAL;
552 }
553
554 return ret;
555}
556
557static int qap_out_drain(struct audio_stream_out* stream, audio_drain_type_t type)
558{
559 struct stream_out *out = (struct stream_out *)stream;
560 int status = 0;
561 struct qap_module *qap_mod = NULL;
562
563 qap_mod = get_qap_module_for_input_stream_l(out);
564 DEBUG_MSG("Output Stream %p", out);
565
566 lock_output_stream_l(out);
567
568 //If QAP passthrough is enabled then block the drain on module stream.
569 if (p_qap->passthrough_out) {
570 pthread_mutex_lock(&p_qap->lock);
571 //If drain is received for QAP passthorugh stream then call the primary HAL api.
572 if (p_qap->passthrough_in == out) {
573 status = p_qap->passthrough_out->stream.drain(
574 (struct audio_stream_out *)p_qap->passthrough_out, type);
575 }
576 pthread_mutex_unlock(&p_qap->lock);
577 } else if (!is_any_stream_running_l(qap_mod)) {
578 //If stream is already stopped then send the drain ready.
579 out->client_callback(STREAM_CBK_EVENT_DRAIN_READY, NULL, out->client_cookie);
580 set_stream_state_l(out, STOPPED);
581 } else {
582 qap_audio_buffer_t *buffer;
583 buffer = (qap_audio_buffer_t *) calloc(1, sizeof(qap_audio_buffer_t));
584 buffer->common_params.offset = 0;
585 buffer->common_params.data = buffer;
586 buffer->common_params.size = 0;
587 buffer->buffer_parms.input_buf_params.flags = QAP_BUFFER_EOS;
588 DEBUG_MSG("Queing EOS buffer %p flags %d size %d", buffer, buffer->buffer_parms.input_buf_params.flags, buffer->common_params.size);
589 status = qap_module_process(out->qap_stream_handle, buffer);
590 if (QAP_STATUS_OK != status) {
591 ERROR_MSG("EOS buffer queing failed%d", status);
592 return -EINVAL;
593 }
594
595 //Drain the module input stream.
596 /* Stream stop will trigger EOS and on EOS_EVENT received
597 from callback DRAIN_READY command is sent */
598 status = audio_extn_qap_stream_stop(out);
599
600 if (status == 0) {
601 //Setting state to stopping as client is expecting drain_ready event.
602 set_stream_state_l(out, STOPPING);
603 }
604 }
605
606 unlock_output_stream_l(out);
607 return status;
608}
609
610
611/* Flush the QAP module input stream. */
612static int audio_extn_qap_stream_flush(struct stream_out *out)
613{
614 DEBUG_MSG("Output Stream %p", out);
615 int ret = -EINVAL;
616 struct qap_module *qap_mod = NULL;
617
618 qap_mod = get_qap_module_for_input_stream_l(out);
619 if (!qap_mod || !qap_mod->session_handle|| !out->qap_stream_handle) {
620 ERROR_MSG("Wrong state to process qap_mod(%p) sess_hadl(%p) strm hndl(%p)",
621 qap_mod, qap_mod->session_handle, out->qap_stream_handle);
622 return -EINVAL;
623 }
624
625 ret = qap_module_cmd(out->qap_stream_handle,
626 QAP_MODULE_CMD_FLUSH,
627 sizeof(QAP_MODULE_CMD_FLUSH),
628 NULL,
629 NULL,
630 NULL);
631 if (QAP_STATUS_OK != ret) {
632 ERROR_MSG("flush failed %d", ret);
633 return -EINVAL;
634 }
635
636 return ret;
637}
638
639
640/* Pause the QAP module input stream. */
641static int qap_stream_pause_l(struct stream_out *out)
642{
643 struct qap_module *qap_mod = NULL;
644 int ret = -EINVAL;
645
646 qap_mod = get_qap_module_for_input_stream_l(out);
647 if (!qap_mod || !qap_mod->session_handle|| !out->qap_stream_handle) {
648 ERROR_MSG("Wrong state to process qap_mod(%p) sess_hadl(%p) strm hndl(%p)",
649 qap_mod, qap_mod->session_handle, out->qap_stream_handle);
650 return -EINVAL;
651 }
652
653 ret = qap_module_cmd(out->qap_stream_handle,
654 QAP_MODULE_CMD_PAUSE,
655 sizeof(QAP_MODULE_CMD_PAUSE),
656 NULL,
657 NULL,
658 NULL);
659 if (QAP_STATUS_OK != ret) {
660 ERROR_MSG("pause failed %d", ret);
661 return -EINVAL;
662 }
663
664 return ret;
665}
666
667
668/* Flush the QAP input stream. */
669static int qap_out_flush(struct audio_stream_out* stream)
670{
671 struct stream_out *out = (struct stream_out *)stream;
672 int status = 0;
673
674 DEBUG_MSG("Output Stream %p", out);
675 lock_output_stream_l(out);
676
677 if (!out->standby) {
678 //If QAP passthrough is active then block the flush on module input streams.
679 if (p_qap->passthrough_out) {
680 pthread_mutex_lock(&p_qap->lock);
681 //If flush is received for the QAP passthrough stream then call the primary HAL api.
682 if (p_qap->passthrough_in == out) {
683 status = p_qap->passthrough_out->stream.flush(
684 (struct audio_stream_out *)p_qap->passthrough_out);
685 out->offload_state = OFFLOAD_STATE_IDLE;
686 }
687 pthread_mutex_unlock(&p_qap->lock);
688 } else {
689 //Flush the module input stream.
690 status = audio_extn_qap_stream_flush(out);
691 }
692 }
693 unlock_output_stream_l(out);
694 DEBUG_MSG("Exit");
695 return status;
696}
697
698
699/* Pause a QAP input stream. */
700static int qap_out_pause(struct audio_stream_out* stream)
701{
702 struct stream_out *out = (struct stream_out *)stream;
703 int status = 0;
704 DEBUG_MSG("Output Stream %p", out);
705
706 lock_output_stream_l(out);
707
708 //If QAP passthrough is enabled then block the pause on module stream.
709 if (p_qap->passthrough_out) {
710 pthread_mutex_lock(&p_qap->lock);
711 //If pause is received for QAP passthorugh stream then call the primary HAL api.
712 if (p_qap->passthrough_in == out) {
713 status = p_qap->passthrough_out->stream.pause(
714 (struct audio_stream_out *)p_qap->passthrough_out);
715 out->offload_state = OFFLOAD_STATE_PAUSED;
716 }
717 pthread_mutex_unlock(&p_qap->lock);
718 } else {
719 //Pause the module input stream.
720 status = qap_stream_pause_l(out);
721 }
722
723 unlock_output_stream_l(out);
724 return status;
725}
726
727static void close_qap_passthrough_stream_l()
728{
729 if (p_qap->passthrough_out != NULL) { //QAP pasthroug is enabled. Close it.
730 pthread_mutex_lock(&p_qap->lock);
731 adev_close_output_stream((struct audio_hw_device *)p_qap->adev,
732 (struct audio_stream_out *)(p_qap->passthrough_out));
733 p_qap->passthrough_out = NULL;
734 pthread_mutex_unlock(&p_qap->lock);
735
736 if (p_qap->passthrough_in->qap_stream_handle) {
737 qap_out_pause((struct audio_stream_out*)p_qap->passthrough_in);
738 qap_out_flush((struct audio_stream_out*)p_qap->passthrough_in);
739 qap_out_drain((struct audio_stream_out*)p_qap->passthrough_in,
740 (audio_drain_type_t)STREAM_CBK_EVENT_DRAIN_READY);
741 }
742 }
743}
744
745static int qap_out_standby(struct audio_stream *stream)
746{
747 struct stream_out *out = (struct stream_out *)stream;
748 struct qap_module *qap_mod = NULL;
749 int status = 0;
750 int i;
751
752 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
753 stream, out->usecase, use_case_table[out->usecase]);
754
755 lock_output_stream_l(out);
756
757 //If QAP passthrough is active then block standby on all the input streams of QAP mm modules.
758 if (p_qap->passthrough_out) {
759 //If standby is received on QAP passthrough stream then forward it to primary HAL.
760 if (p_qap->passthrough_in == out) {
761 status = p_qap->passthrough_out->stream.common.standby(
762 (struct audio_stream *)p_qap->passthrough_out);
763 }
764 } else if (check_stream_state_l(out, RUN)) {
765 //If QAP passthrough stream is not active then stop the QAP module stream.
766 status = audio_extn_qap_stream_stop(out);
767
768 if (status == 0) {
769 //Setting state to stopped as client not expecting drain_ready event.
770 set_stream_state_l(out, STOPPED);
771 }
772 if(p_qap->qap_output_block_handling) {
773 qap_mod = get_qap_module_for_input_stream_l(out);
774 for (i = 0; i < MAX_QAP_MODULE_IN; i++) {
775 if (qap_mod->stream_in[i] != NULL &&
776 check_stream_state_l(qap_mod->stream_in[i], RUN)) {
777 break;
778 }
779 }
780
781 if (i != MAX_QAP_MODULE_IN) {
782 DEBUG_MSG("[%s] stream is still active.", use_case_table[qap_mod->stream_in[i]->usecase]);
783 } else {
784 pthread_mutex_lock(&qap_mod->session_output_lock);
785 qap_mod->is_session_output_active = false;
786 pthread_mutex_unlock(&qap_mod->session_output_lock);
787 DEBUG_MSG(" all the input streams are either closed or stopped(standby) block the MM module output");
788 }
789 }
790 }
791
792 if (!out->standby) {
793 out->standby = true;
794 }
795
796 unlock_output_stream_l(out);
797 return status;
798}
799
800/* Sets the volume to PCM output stream. */
801static int qap_out_set_volume(struct audio_stream_out *stream, float left, float right)
802{
803 int ret = 0;
804 struct stream_out *out = (struct stream_out *)stream;
805 struct qap_module *qap_mod = NULL;
806
807 DEBUG_MSG("Left %f, Right %f", left, right);
808
809 qap_mod = get_qap_module_for_input_stream_l(out);
810 if (!qap_mod) {
811 return -EINVAL;
812 }
813
814 pthread_mutex_lock(&p_qap->lock);
815 qap_mod->vol_left = left;
816 qap_mod->vol_right = right;
817 qap_mod->is_vol_set = true;
818 pthread_mutex_unlock(&p_qap->lock);
819
820 if (qap_mod->stream_out[QAP_OUT_OFFLOAD] != NULL) {
821 ret = qap_mod->stream_out[QAP_OUT_OFFLOAD]->stream.set_volume(
822 (struct audio_stream_out *)qap_mod->stream_out[QAP_OUT_OFFLOAD], left, right);
823 }
824
825 return ret;
826}
827
828/* Starts a QAP module stream. */
829static int qap_stream_start_l(struct stream_out *out)
830{
831 int ret = 0;
832 struct qap_module *qap_mod = NULL;
833
834 DEBUG_MSG("Output Stream = %p", out);
835
836 qap_mod = get_qap_module_for_input_stream_l(out);
837 if ((!qap_mod) || (!qap_mod->session_handle)) {
838 ERROR_MSG("QAP mod is not inited (%p) or session is not yet opened (%p) ",
839 qap_mod, qap_mod->session_handle);
840 return -EINVAL;
841 }
842 if (out->qap_stream_handle) {
843 ret = qap_module_cmd(out->qap_stream_handle,
844 QAP_MODULE_CMD_START,
845 sizeof(QAP_MODULE_CMD_START),
846 NULL,
847 NULL,
848 NULL);
849 if (ret != QAP_STATUS_OK) {
850 ERROR_MSG("start failed");
851 ret = -EINVAL;
852 }
853 } else
854 ERROR_MSG("QAP stream not yet opened, drop this cmd");
855
856 DEBUG_MSG("exit");
857 return ret;
858
859}
860
861static int qap_start_output_stream(struct stream_out *out)
862{
863 int ret = 0;
864 struct audio_device *adev = out->dev;
865
866 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
867 ret = -EINVAL;
868 DEBUG_MSG("Use case out of bounds sleeping for 500ms");
869 usleep(50000);
870 return ret;
871 }
872
873 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
874 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800875 get_device_types(&out->device_list));
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +0530876
877 if (CARD_STATUS_OFFLINE == out->card_status ||
878 CARD_STATUS_OFFLINE == adev->card_status) {
879 ALOGE("%s: sound card is not active/SSR returning error", __func__);
880 ret = -EIO;
881 usleep(50000);
882 return ret;
883 }
884
885 return qap_stream_start_l(out);
886}
887
888/* Sends input buffer to the QAP MM module. */
889static int qap_module_write_input_buffer(struct stream_out *out, const void *buffer, int bytes)
890{
891 int ret = -EINVAL;
892 struct qap_module *qap_mod = NULL;
893 qap_audio_buffer_t buff;
894
895 qap_mod = get_qap_module_for_input_stream_l(out);
896 if ((!qap_mod) || (!qap_mod->session_handle) || (!out->qap_stream_handle)) {
897 return ret;
898 }
899
900 //If data received on associated stream when all other stream are stopped then drop the data.
901 if (out == qap_mod->stream_in[QAP_IN_ASSOC] && !is_any_stream_running_l(qap_mod))
902 return bytes;
903
904 memset(&buff, 0, sizeof(buff));
905 buff.common_params.offset = 0;
906 buff.common_params.size = bytes;
907 buff.common_params.data = (void *) buffer;
908 buff.common_params.timestamp = QAP_BUFFER_NO_TSTAMP;
909 buff.buffer_parms.input_buf_params.flags = QAP_BUFFER_NO_TSTAMP;
910 DEBUG_MSG("calling module process with bytes %d %p", bytes, buffer);
911 ret = qap_module_process(out->qap_stream_handle, &buff);
912
913 if(ret > 0) set_stream_state_l(out, RUN);
914
915 return ret;
916}
917
918static ssize_t qap_out_write(struct audio_stream_out *stream, const void *buffer, size_t bytes)
919{
920 struct stream_out *out = (struct stream_out *)stream;
921 struct audio_device *adev = out->dev;
922 ssize_t ret = 0;
923 struct qap_module *qap_mod = NULL;
924
925 DEBUG_MSG_VV("bytes = %d, usecase[%s] and flags[%x] for handle[%p]",
926 (int)bytes, use_case_table[out->usecase], out->flags, out);
927
928 lock_output_stream_l(out);
929
930 // If QAP passthrough is active then block writing data to QAP mm module.
931 if (p_qap->passthrough_out) {
932 //If write is received for the QAP passthrough stream then send the buffer to primary HAL.
933 if (p_qap->passthrough_in == out) {
934 ret = p_qap->passthrough_out->stream.write(
935 (struct audio_stream_out *)(p_qap->passthrough_out),
936 buffer,
937 bytes);
938 if (ret > 0) out->standby = false;
939 }
940 unlock_output_stream_l(out);
941 return ret;
942 } else if (out->standby) {
943 pthread_mutex_lock(&adev->lock);
944 ret = qap_start_output_stream(out);
945 pthread_mutex_unlock(&adev->lock);
946 if (ret == 0) {
947 out->standby = false;
948 if(p_qap->qap_output_block_handling) {
949 qap_mod = get_qap_module_for_input_stream_l(out);
950
951 pthread_mutex_lock(&qap_mod->session_output_lock);
952 if (qap_mod->is_session_output_active == false) {
953 qap_mod->is_session_output_active = true;
954 pthread_cond_signal(&qap_mod->session_output_cond);
955 DEBUG_MSG("Wake up MM module output thread");
956 }
957 pthread_mutex_unlock(&qap_mod->session_output_lock);
958 }
959 } else {
960 goto exit;
961 }
962 }
963
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800964 if ((adev->is_channel_status_set == false) &&
965 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +0530966 audio_utils_set_hdmi_channel_status(out, (char *)buffer, bytes);
967 adev->is_channel_status_set = true;
968 }
969
970 ret = qap_module_write_input_buffer(out, buffer, bytes);
971 DEBUG_MSG_VV("Bytes consumed [%d] by MM Module", (int)ret);
972
973 if (ret >= 0) {
974 out->written += ret / ((popcount(out->channel_mask) * sizeof(short)));
975 }
976
977
978exit:
979 unlock_output_stream_l(out);
980
981 if (ret < 0) {
982 if (ret == -EAGAIN) {
983 DEBUG_MSG_VV("No space available to consume bytes, post msg to cb thread");
984 bytes = 0;
985 } else if (ret == -ENOMEM || ret == -EPERM) {
986 if (out->pcm)
987 ERROR_MSG("error %d, %s", (int)ret, pcm_get_error(out->pcm));
988 qap_out_standby(&out->stream.common);
989 DEBUG_MSG("SLEEP for 100sec");
990 usleep(bytes * 1000000
991 / audio_stream_out_frame_size(stream)
992 / out->stream.common.get_sample_rate(&out->stream.common));
993 }
994 } else if (ret < (ssize_t)bytes) {
995 //partial buffer copied to the module.
996 DEBUG_MSG_VV("Not enough space available to consume all the bytes");
997 bytes = ret;
998 }
999 return bytes;
1000}
1001
1002/* Gets PCM offload buffer size for a given config. */
1003static uint32_t qap_get_pcm_offload_buffer_size(audio_offload_info_t* info,
1004 uint32_t samples_per_frame)
1005{
1006 uint32_t fragment_size = 0;
1007
1008 fragment_size = (samples_per_frame * (info->bit_width >> 3) * popcount(info->channel_mask));
1009
1010 if (fragment_size < MIN_PCM_OFFLOAD_FRAGMENT_SIZE)
1011 fragment_size = MIN_PCM_OFFLOAD_FRAGMENT_SIZE;
1012 else if (fragment_size > MAX_PCM_OFFLOAD_FRAGMENT_SIZE)
1013 fragment_size = MAX_PCM_OFFLOAD_FRAGMENT_SIZE;
1014
1015 // To have same PCM samples for all channels, the buffer size requires to
1016 // be multiple of (number of channels * bytes per sample)
1017 // For writes to succeed, the buffer must be written at address which is multiple of 32
1018 fragment_size = ALIGN(fragment_size,
1019 ((info->bit_width >> 3) * popcount(info->channel_mask) * 32));
1020
1021 ALOGI("Qap PCM offload Fragment size is %d bytes", fragment_size);
1022
1023 return fragment_size;
1024}
1025
1026static uint32_t qap_get_pcm_offload_input_buffer_size(audio_offload_info_t* info)
1027{
1028 return qap_get_pcm_offload_buffer_size(info, MS12_PCM_IN_FRAGMENT_SIZE);
1029}
1030
1031static uint32_t qap_get_pcm_offload_output_buffer_size(struct qap_module *qap_mod,
1032 audio_offload_info_t* info)
1033{
1034 return qap_get_pcm_offload_buffer_size(info, get_pcm_output_buffer_size_samples_l(qap_mod));
1035}
1036
1037/* Gets buffer latency in samples. */
1038static int get_buffer_latency(struct stream_out *out, uint32_t buffer_size, uint32_t *latency)
1039{
1040 unsigned long int samples_in_one_encoded_frame;
1041 unsigned long int size_of_one_encoded_frame;
1042
1043 switch (out->format) {
1044 case AUDIO_FORMAT_AC3:
1045 samples_in_one_encoded_frame = DD_FRAME_SIZE;
1046 size_of_one_encoded_frame = DD_ENCODER_OUTPUT_SIZE;
1047 break;
1048 case AUDIO_FORMAT_E_AC3:
1049 samples_in_one_encoded_frame = DDP_FRAME_SIZE;
1050 size_of_one_encoded_frame = DDP_ENCODER_OUTPUT_SIZE;
1051 break;
1052 case AUDIO_FORMAT_DTS:
1053 samples_in_one_encoded_frame = DTS_FRAME_SIZE;
1054 size_of_one_encoded_frame = DTS_ENCODER_OUTPUT_SIZE;
1055 break;
1056 case AUDIO_FORMAT_DTS_HD:
1057 samples_in_one_encoded_frame = DTSHD_FRAME_SIZE;
1058 size_of_one_encoded_frame = DTSHD_ENCODER_OUTPUT_SIZE;
1059 break;
1060 case AUDIO_FORMAT_PCM_16_BIT:
1061 samples_in_one_encoded_frame = 1;
1062 size_of_one_encoded_frame = ((out->bit_width) >> 3) * popcount(out->channel_mask);
1063 break;
1064 default:
1065 *latency = 0;
1066 return (-EINVAL);
1067 }
1068
1069 *latency = ((buffer_size * samples_in_one_encoded_frame) / size_of_one_encoded_frame);
1070 return 0;
1071}
1072
1073/* Returns the number of frames rendered to outside observer. */
1074static int qap_get_rendered_frames(struct stream_out *out, uint64_t *frames)
1075{
1076 int ret = 0, i;
1077 struct str_parms *parms;
1078// int value = 0;
1079 int module_latency = 0;
1080 uint32_t kernel_latency = 0;
1081 uint32_t dsp_latency = 0;
1082 int signed_frames = 0;
1083 char* kvpairs = NULL;
1084 struct qap_module *qap_mod = NULL;
1085
1086 DEBUG_MSG("Output Format %d", out->format);
1087
1088 qap_mod = get_qap_module_for_input_stream_l(out);
1089 if (!qap_mod || !qap_mod->session_handle|| !out->qap_stream_handle) {
1090 ERROR_MSG("Wrong state to process qap_mod(%p) sess_hadl(%p) strm hndl(%p)",
1091 qap_mod, qap_mod->session_handle, out->qap_stream_handle);
1092 return -EINVAL;
1093 }
1094
1095 //Get MM module latency.
1096/* Tobeported
1097 kvpairs = qap_mod->qap_audio_stream_get_param(out->qap_stream_handle, "get_latency");
1098*/
1099 if (kvpairs) {
1100 parms = str_parms_create_str(kvpairs);
1101 ret = str_parms_get_int(parms, "get_latency", &module_latency);
1102 if (ret >= 0) {
1103 str_parms_destroy(parms);
1104 parms = NULL;
1105 }
1106 free(kvpairs);
1107 kvpairs = NULL;
1108 }
1109
1110 //Get kernel Latency
1111 for (i = MAX_QAP_MODULE_OUT - 1; i >= 0; i--) {
1112 if (qap_mod->stream_out[i] == NULL) {
1113 continue;
1114 } else {
1115 unsigned int num_fragments = qap_mod->stream_out[i]->compr_config.fragments;
1116 uint32_t fragment_size = qap_mod->stream_out[i]->compr_config.fragment_size;
1117 uint32_t kernel_buffer_size = num_fragments * fragment_size;
1118 get_buffer_latency(qap_mod->stream_out[i], kernel_buffer_size, &kernel_latency);
1119 break;
1120 }
1121 }
1122
1123 //Get DSP latency
1124 if ((qap_mod->stream_out[QAP_OUT_OFFLOAD] != NULL)
1125 || (qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH] != NULL)) {
1126 unsigned int sample_rate = 0;
1127 audio_usecase_t platform_latency = 0;
1128
1129 if (qap_mod->stream_out[QAP_OUT_OFFLOAD])
1130 sample_rate = qap_mod->stream_out[QAP_OUT_OFFLOAD]->sample_rate;
1131 else if (qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH])
1132 sample_rate = qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH]->sample_rate;
1133
1134 if (qap_mod->stream_out[QAP_OUT_OFFLOAD])
1135 platform_latency =
1136 platform_render_latency(qap_mod->stream_out[QAP_OUT_OFFLOAD]->usecase);
1137 else
1138 platform_latency =
1139 platform_render_latency(qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH]->usecase);
1140
1141 dsp_latency = (platform_latency * sample_rate) / 1000000LL;
1142 } else if (qap_mod->stream_out[QAP_OUT_TRANSCODE_PASSTHROUGH] != NULL) {
1143 unsigned int sample_rate = 0;
1144
1145 sample_rate = qap_mod->stream_out[QAP_OUT_TRANSCODE_PASSTHROUGH]->sample_rate; //TODO: How this sample rate can be used?
1146 dsp_latency = (COMPRESS_OFFLOAD_PLAYBACK_LATENCY * sample_rate) / 1000;
1147 }
1148
1149 // MM Module Latency + Kernel Latency + DSP Latency
1150 if ( audio_extn_bt_hal_get_output_stream(qap_mod->bt_hdl) != NULL) {
1151 out->platform_latency = module_latency + audio_extn_bt_hal_get_latency(qap_mod->bt_hdl);
1152 } else {
1153 out->platform_latency = (uint32_t)module_latency + kernel_latency + dsp_latency;
1154 }
1155
1156 if (out->format & AUDIO_FORMAT_PCM_16_BIT) {
1157 *frames = 0;
1158 signed_frames = out->written - out->platform_latency;
1159 // It would be unusual for this value to be negative, but check just in case ...
1160 if (signed_frames >= 0) {
1161 *frames = signed_frames;
1162 }
1163/* Tobeported
1164 }
1165 else {
1166
1167 kvpairs = qap_mod->qap_audio_stream_get_param(out->qap_stream_handle, "position");
1168 if (kvpairs) {
1169 parms = str_parms_create_str(kvpairs);
1170 ret = str_parms_get_int(parms, "position", &value);
1171 if (ret >= 0) {
1172 *frames = value;
1173 signed_frames = value - out->platform_latency;
1174 // It would be unusual for this value to be negative, but check just in case ...
1175 if (signed_frames >= 0) {
1176 *frames = signed_frames;
1177 }
1178 }
1179 str_parms_destroy(parms);
1180 }
1181*/
1182 } else {
1183 ret = -EINVAL;
1184 }
1185
1186 return ret;
1187}
1188
1189static int qap_out_get_render_position(const struct audio_stream_out *stream,
1190 uint32_t *dsp_frames)
1191{
1192 struct stream_out *out = (struct stream_out *)stream;
1193 int ret = 0;
1194 uint64_t frames=0;
1195 struct qap_module* qap_mod = NULL;
1196 ALOGV("%s, Output Stream %p,dsp frames %d",__func__, stream, (int)dsp_frames);
1197
1198 qap_mod = get_qap_module_for_input_stream_l(out);
1199 if (!qap_mod) {
1200 ret = out->stream.get_render_position(stream, dsp_frames);
1201 ALOGV("%s, non qap_MOD DSP FRAMES %d",__func__, (int)dsp_frames);
1202 return ret;
1203 }
1204
1205 if (p_qap->passthrough_out) {
1206 pthread_mutex_lock(&p_qap->lock);
1207 ret = p_qap->passthrough_out->stream.get_render_position((struct audio_stream_out *)p_qap->passthrough_out, dsp_frames);
1208 pthread_mutex_unlock(&p_qap->lock);
1209 ALOGV("%s, PASS THROUGH DSP FRAMES %p",__func__, dsp_frames);
1210 return ret;
1211 }
1212 frames=*dsp_frames;
1213 ret = qap_get_rendered_frames(out, &frames);
1214 *dsp_frames = (uint32_t)frames;
1215 ALOGV("%s, DSP FRAMES %d",__func__, (int)dsp_frames);
1216 return ret;
1217}
1218
1219static int qap_out_get_presentation_position(const struct audio_stream_out *stream,
1220 uint64_t *frames,
1221 struct timespec *timestamp)
1222{
1223 struct stream_out *out = (struct stream_out *)stream;
1224 int ret = 0;
1225
1226// DEBUG_MSG_VV("Output Stream %p", stream);
1227
1228 //If QAP passthorugh output stream is active.
1229 if (p_qap->passthrough_out) {
1230 if (p_qap->passthrough_in == out) {
1231 //If api is called for QAP passthorugh stream then call the primary HAL api to get the position.
1232 pthread_mutex_lock(&p_qap->lock);
1233 ret = p_qap->passthrough_out->stream.get_presentation_position(
1234 (struct audio_stream_out *)p_qap->passthrough_out,
1235 frames,
1236 timestamp);
1237 pthread_mutex_unlock(&p_qap->lock);
1238 } else {
1239 //If api is called for other stream then return zero frames.
1240 *frames = 0;
1241 clock_gettime(CLOCK_MONOTONIC, timestamp);
1242 }
1243 return ret;
1244 }
1245
1246 ret = qap_get_rendered_frames(out, frames);
1247 clock_gettime(CLOCK_MONOTONIC, timestamp);
1248
1249 return ret;
1250}
1251
1252static uint32_t qap_out_get_latency(const struct audio_stream_out *stream)
1253{
1254 struct stream_out *out = (struct stream_out *)stream;
1255 uint32_t latency = 0;
1256 struct qap_module *qap_mod = NULL;
1257 DEBUG_MSG_VV("Output Stream %p", out);
1258
1259 qap_mod = get_qap_module_for_input_stream_l(out);
1260 if (!qap_mod) {
1261 return 0;
1262 }
1263
1264 //If QAP passthrough is active then block the get latency on module input streams.
1265 if (p_qap->passthrough_out) {
1266 pthread_mutex_lock(&p_qap->lock);
1267 //If get latency is called for the QAP passthrough stream then call the primary HAL api.
1268 if (p_qap->passthrough_in == out) {
1269 latency = p_qap->passthrough_out->stream.get_latency(
1270 (struct audio_stream_out *)p_qap->passthrough_out);
1271 }
1272 pthread_mutex_unlock(&p_qap->lock);
1273 } else {
1274 if (is_offload_usecase(out->usecase)) {
1275 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
1276 } else {
1277 uint32_t sample_rate = 0;
1278 latency = QAP_MODULE_PCM_INPUT_BUFFER_LATENCY; //Input latency
1279
1280 if (qap_mod->stream_out[QAP_OUT_OFFLOAD])
1281 sample_rate = qap_mod->stream_out[QAP_OUT_OFFLOAD]->sample_rate;
1282 else if (qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH])
1283 sample_rate = qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH]->sample_rate;
1284
1285 if (sample_rate) {
1286 latency += (get_pcm_output_buffer_size_samples_l(qap_mod) * 1000) / out->sample_rate;
1287 }
1288 }
1289
1290 if ( audio_extn_bt_hal_get_output_stream(qap_mod->bt_hdl) != NULL) {
1291 if (is_offload_usecase(out->usecase)) {
1292 latency = audio_extn_bt_hal_get_latency(qap_mod->bt_hdl) +
1293 QAP_COMPRESS_OFFLOAD_PROCESSING_LATENCY;
1294 } else {
1295 latency = audio_extn_bt_hal_get_latency(qap_mod->bt_hdl) +
1296 QAP_PCM_OFFLOAD_PROCESSING_LATENCY;
1297 }
1298 }
1299 }
1300
1301 DEBUG_MSG_VV("Latency %d", latency);
1302 return latency;
1303}
1304
1305static bool qap_check_and_get_compressed_device_format(int device, int *format)
1306{
1307 switch (device) {
1308 case (AUDIO_DEVICE_OUT_AUX_DIGITAL | QAP_AUDIO_FORMAT_AC3):
1309 *format = AUDIO_FORMAT_AC3;
1310 return true;
1311 case (AUDIO_DEVICE_OUT_AUX_DIGITAL | QAP_AUDIO_FORMAT_EAC3):
1312 *format = AUDIO_FORMAT_E_AC3;
1313 return true;
1314 case (AUDIO_DEVICE_OUT_AUX_DIGITAL | QAP_AUDIO_FORMAT_DTS):
1315 *format = AUDIO_FORMAT_DTS;
1316 return true;
1317 default:
1318 return false;
1319 }
1320}
1321
1322static void set_out_stream_channel_map(struct stream_out *out, qap_output_config_t * media_fmt)
1323{
1324 if (media_fmt == NULL || out == NULL) {
1325 return;
1326 }
1327 struct audio_out_channel_map_param chmap = {0,{0}};
1328 int i = 0;
1329 chmap.channels = media_fmt->channels;
1330 for (i = 0; i < chmap.channels && i < AUDIO_CHANNEL_COUNT_MAX && i < AUDIO_QAF_MAX_CHANNELS;
1331 i++) {
1332 chmap.channel_map[i] = media_fmt->ch_map[i];
1333 }
1334 audio_extn_utils_set_channel_map(out, &chmap);
1335}
1336
1337bool audio_extn_is_qap_enabled()
1338{
1339 bool prop_enabled = false;
1340 char value[PROPERTY_VALUE_MAX] = {0};
1341 property_get("vendor.audio.qap.enabled", value, NULL);
1342 prop_enabled = atoi(value) || !strncmp("true", value, 4);
1343 DEBUG_MSG("%d", prop_enabled);
1344 return (prop_enabled);
1345}
1346
1347void static qap_close_all_output_streams(struct qap_module *qap_mod)
1348{
1349 int i =0;
1350 struct stream_out *stream_out = NULL;
1351 DEBUG_MSG("Entry");
1352
1353 for (i = 0; i < MAX_QAP_MODULE_OUT; i++) {
1354 stream_out = qap_mod->stream_out[i];
1355 if (stream_out != NULL) {
1356 adev_close_output_stream((struct audio_hw_device *)p_qap->adev, (struct audio_stream_out *)stream_out);
1357 DEBUG_MSG("Closed outputenum=%d session 0x%x %s",
1358 i, (int)stream_out, use_case_table[stream_out->usecase]);
1359 qap_mod->stream_out[i] = NULL;
1360 }
1361 memset(&qap_mod->session_outputs_config.output_config[i], 0, sizeof(qap_session_outputs_config_t));
1362 qap_mod->is_media_fmt_changed[i] = false;
1363 }
1364 DEBUG_MSG("exit");
1365}
1366
1367/* Call back function for mm module. */
1368static void qap_session_callback(qap_session_handle_t session_handle __unused,
1369 void *prv_data,
1370 qap_callback_event_t event_id,
1371 int size,
1372 void *data)
1373{
1374
1375 /*
1376 For SPKR:
1377 1. Open pcm device if device_id passed to it SPKR and write the data to
1378 pcm device
1379
1380 For HDMI
1381 1.Open compress device for HDMI(PCM or AC3) based on current hdmi o/p format and write
1382 data to the HDMI device.
1383 */
1384 int ret;
1385 audio_output_flags_t flags;
1386 struct qap_module* qap_mod = (struct qap_module*)prv_data;
1387 struct audio_stream_out *bt_stream = NULL;
1388 int format;
1389 int8_t *data_buffer_p = NULL;
1390 uint32_t buffer_size = 0;
1391 bool need_to_recreate_stream = false;
1392 struct audio_config config;
1393 qap_output_config_t *new_conf = NULL;
1394 qap_audio_buffer_t *buffer = (qap_audio_buffer_t *) data;
1395 uint32_t device = 0;
1396
1397 if (qap_mod->is_session_closing) {
1398 DEBUG_MSG("Dropping event as session is closing."
1399 "Event = 0x%X, Bytes to write %d", event_id, size);
1400 return;
1401 }
1402
1403 if(p_qap->qap_output_block_handling) {
1404 pthread_mutex_lock(&qap_mod->session_output_lock);
1405 if (!qap_mod->is_session_output_active) {
1406 qap_close_all_output_streams(qap_mod);
1407 DEBUG_MSG("disabling MM module output by blocking the output thread");
1408 pthread_cond_wait(&qap_mod->session_output_cond, &qap_mod->session_output_lock);
1409 DEBUG_MSG("MM module output Enabled, output thread active");
1410 }
1411 pthread_mutex_unlock(&qap_mod->session_output_lock);
1412 }
1413
1414 /* Default config initialization. */
1415 config.sample_rate = config.offload_info.sample_rate = QAP_OUTPUT_SAMPLING_RATE;
1416 config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
1417 config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
1418 config.format = config.offload_info.format = AUDIO_FORMAT_PCM_16_BIT;
1419 config.offload_info.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
1420 config.offload_info.channel_mask = config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
1421
1422 pthread_mutex_lock(&p_qap->lock);
1423
1424 if (event_id == QAP_CALLBACK_EVENT_OUTPUT_CFG_CHANGE) {
1425 new_conf = &buffer->buffer_parms.output_buf_params.output_config;
1426 qap_output_config_t *cached_conf = NULL;
1427 int index = -1;
1428
1429 DEBUG_MSG("Received QAP_CALLBACK_EVENT_OUTPUT_CFG_CHANGE event for output id=0x%x",
1430 buffer->buffer_parms.output_buf_params.output_id);
1431
1432 DEBUG_MSG("sample rate=%d bitwidth=%d format = %d channels =0x%x",
1433 new_conf->sample_rate,
1434 new_conf->bit_width,
1435 new_conf->format,
1436 new_conf->channels);
1437
1438 if ( (uint32_t)size < sizeof(qap_output_config_t)) {
1439 ERROR_MSG("Size is not proper for the event AUDIO_OUTPUT_MEDIA_FORMAT_EVENT.");
1440 return ;
1441 }
1442
1443 index = get_media_fmt_array_index_for_output_id_l(qap_mod, buffer->buffer_parms.output_buf_params.output_id);
1444
1445 DEBUG_MSG("index = %d", index);
1446
1447 if (index >= 0) {
1448 cached_conf = &qap_mod->session_outputs_config.output_config[index];
1449 } else if (index < 0 && qap_mod->new_out_format_index < MAX_QAP_MODULE_OUT) {
1450 index = qap_mod->new_out_format_index;
1451 cached_conf = &qap_mod->session_outputs_config.output_config[index];
1452 qap_mod->new_out_format_index++;
1453 }
1454
1455 if (cached_conf == NULL) {
1456 ERROR_MSG("Maximum output from a QAP module is reached. Can not process new output.");
1457 return ;
1458 }
1459
1460 if (memcmp(cached_conf, new_conf, sizeof(qap_output_config_t)) != 0) {
1461 memcpy(cached_conf, new_conf, sizeof(qap_output_config_t));
1462 qap_mod->is_media_fmt_changed[index] = true;
1463 }
1464 } else if (event_id == QAP_CALLBACK_EVENT_DATA) {
1465 data_buffer_p = (int8_t*)buffer->common_params.data+buffer->common_params.offset;
1466 buffer_size = buffer->common_params.size;
1467 device = buffer->buffer_parms.output_buf_params.output_id;
1468
1469 DEBUG_MSG_VV("Received QAP_CALLBACK_EVENT_DATA event buff size(%d) for outputid=0x%x",
1470 buffer_size, buffer->buffer_parms.output_buf_params.output_id);
1471
1472 if (buffer && buffer->common_params.data) {
1473 int index = -1;
1474
1475 index = get_media_fmt_array_index_for_output_id_l(qap_mod, buffer->buffer_parms.output_buf_params.output_id);
1476 DEBUG_MSG("index = %d", index);
1477 if (index > -1 && qap_mod->is_media_fmt_changed[index]) {
1478 DEBUG_MSG("FORMAT changed, recreate stream");
1479 need_to_recreate_stream = true;
1480 qap_mod->is_media_fmt_changed[index] = false;
1481
1482 qap_output_config_t *new_config = &qap_mod->session_outputs_config.output_config[index];
1483
1484 config.sample_rate = config.offload_info.sample_rate = new_config->sample_rate;
1485 config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
1486 config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
1487 config.offload_info.bit_width = new_config->bit_width;
1488
1489 if (new_config->format == QAP_AUDIO_FORMAT_PCM_16_BIT) {
1490 if (new_config->bit_width == 16)
1491 config.format = config.offload_info.format = AUDIO_FORMAT_PCM_16_BIT;
1492 else if (new_config->bit_width == 24)
1493 config.format = config.offload_info.format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1494 else
1495 config.format = config.offload_info.format = AUDIO_FORMAT_PCM_32_BIT;
1496 } else if (new_config->format == QAP_AUDIO_FORMAT_AC3)
1497 config.format = config.offload_info.format = AUDIO_FORMAT_AC3;
1498 else if (new_config->format == QAP_AUDIO_FORMAT_EAC3)
1499 config.format = config.offload_info.format = AUDIO_FORMAT_E_AC3;
1500 else if (new_config->format == QAP_AUDIO_FORMAT_DTS)
1501 config.format = config.offload_info.format = AUDIO_FORMAT_DTS;
1502
1503 device |= (new_config->format & AUDIO_FORMAT_MAIN_MASK);
1504
1505 config.channel_mask = audio_channel_out_mask_from_count(new_config->channels);
1506 config.offload_info.channel_mask = config.channel_mask;
1507 DEBUG_MSG("sample rate=%d bitwidth=%d format = %d channels=%d channel_mask=%d device =0x%x",
1508 config.sample_rate,
1509 config.offload_info.bit_width,
1510 config.offload_info.format,
1511 new_config->channels,
1512 config.channel_mask,
1513 device);
1514 }
1515 }
1516
1517 if (p_qap->passthrough_out != NULL) {
1518 //If QAP passthrough is active then all the module output will be dropped.
1519 pthread_mutex_unlock(&p_qap->lock);
1520 DEBUG_MSG("QAP-PSTH is active, DROPPING DATA!");
1521 return;
1522 }
1523
1524 if (qap_check_and_get_compressed_device_format(device, &format)) {
1525 /*
1526 * CASE 1: Transcoded output of mm module.
1527 * If HDMI is not connected then drop the data.
1528 * Only one HDMI output can be supported from all the mm modules of QAP.
1529 * Multi-Channel PCM HDMI output streams will be closed from all the mm modules.
1530 * If transcoded output of other module is already enabled then this data will be dropped.
1531 */
1532
1533 if (!p_qap->hdmi_connect) {
1534 DEBUG_MSG("HDMI not connected, DROPPING DATA!");
1535 pthread_mutex_unlock(&p_qap->lock);
1536 return;
1537 }
1538
1539 //Closing all the PCM HDMI output stream from QAP.
1540 close_all_pcm_hdmi_output_l();
1541
1542 /* If Media format was changed for this stream then need to re-create the stream. */
1543 if (need_to_recreate_stream && qap_mod->stream_out[QAP_OUT_TRANSCODE_PASSTHROUGH]) {
1544 DEBUG_MSG("closing Transcode Passthrough session ox%x",
1545 (int)qap_mod->stream_out[QAP_OUT_TRANSCODE_PASSTHROUGH]);
1546 adev_close_output_stream((struct audio_hw_device *)p_qap->adev,
1547 (struct audio_stream_out *)(qap_mod->stream_out[QAP_OUT_TRANSCODE_PASSTHROUGH]));
1548 qap_mod->stream_out[QAP_OUT_TRANSCODE_PASSTHROUGH] = NULL;
1549 p_qap->passthrough_enabled = false;
1550 }
1551
1552 if (!p_qap->passthrough_enabled
1553 && !(qap_mod->stream_out[QAP_OUT_TRANSCODE_PASSTHROUGH])) {
1554
1555 audio_devices_t devices;
1556
1557 config.format = config.offload_info.format = format;
1558 config.offload_info.channel_mask = config.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
1559
1560 flags = (AUDIO_OUTPUT_FLAG_NON_BLOCKING
1561 | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD
1562 | AUDIO_OUTPUT_FLAG_DIRECT
1563 | AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH);
1564 devices = AUDIO_DEVICE_OUT_AUX_DIGITAL;
1565
1566 DEBUG_MSG("Opening Transcode Passthrough out(outputenum=%d) session 0x%x with below params",
1567 QAP_OUT_TRANSCODE_PASSTHROUGH,
1568 (int)qap_mod->stream_out[QAP_OUT_TRANSCODE_PASSTHROUGH]);
1569
1570 DEBUG_MSG("sample rate=%d bitwidth=%d format = 0x%x channel mask=0x%x flags=0x%x device =0x%x",
1571 config.sample_rate,
1572 config.offload_info.bit_width,
1573 config.offload_info.format,
1574 config.offload_info.channel_mask,
1575 flags,
1576 devices);
1577
1578 ret = adev_open_output_stream((struct audio_hw_device *)p_qap->adev,
1579 QAP_DEFAULT_COMPR_PASSTHROUGH_HANDLE,
1580 devices,
1581 flags,
1582 &config,
1583 (struct audio_stream_out **)&(qap_mod->stream_out[QAP_OUT_TRANSCODE_PASSTHROUGH]),
1584 NULL);
1585 if (ret < 0) {
1586 ERROR_MSG("Failed opening Transcode Passthrough out(outputenum=%d) session 0x%x",
1587 QAP_OUT_TRANSCODE_PASSTHROUGH,
1588 (int)qap_mod->stream_out[QAP_OUT_TRANSCODE_PASSTHROUGH]);
1589 pthread_mutex_unlock(&p_qap->lock);
1590 return;
1591 } else
1592 DEBUG_MSG("Opened Transcode Passthrough out(outputenum=%d) session 0x%x",
1593 QAP_OUT_TRANSCODE_PASSTHROUGH,
1594 (int)qap_mod->stream_out[QAP_OUT_TRANSCODE_PASSTHROUGH]);
1595
1596
1597 if (format == AUDIO_FORMAT_E_AC3) {
1598 qap_mod->stream_out[QAP_OUT_TRANSCODE_PASSTHROUGH]->compr_config.fragment_size =
1599 COMPRESS_PASSTHROUGH_DDP_FRAGMENT_SIZE;
1600 }
1601 qap_mod->stream_out[QAP_OUT_TRANSCODE_PASSTHROUGH]->compr_config.fragments =
1602 COMPRESS_OFFLOAD_NUM_FRAGMENTS;
1603
1604 p_qap->passthrough_enabled = true;
1605 }
1606
1607 if (qap_mod->stream_out[QAP_OUT_TRANSCODE_PASSTHROUGH]) {
1608 DEBUG_MSG_VV("Writing Bytes(%d) to QAP_OUT_TRANSCODE_PASSTHROUGH output(%p) buff ptr(%p)",
1609 buffer_size, qap_mod->stream_out[QAP_OUT_TRANSCODE_PASSTHROUGH],
1610 data_buffer_p);
1611 ret = qap_mod->stream_out[QAP_OUT_TRANSCODE_PASSTHROUGH]->stream.write(
1612 (struct audio_stream_out *)qap_mod->stream_out[QAP_OUT_TRANSCODE_PASSTHROUGH],
1613 data_buffer_p,
1614 buffer_size);
1615 }
1616 }
1617 else if ((device & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1618 && (p_qap->hdmi_connect)
1619 && (p_qap->hdmi_sink_channels > 2)) {
1620
1621 /* CASE 2: Multi-Channel PCM output to HDMI.
1622 * If any other HDMI output is already enabled then this has to be dropped.
1623 */
1624
1625 if (p_qap->passthrough_enabled) {
1626 //Closing all the multi-Channel PCM HDMI output stream from QAP.
1627 close_all_pcm_hdmi_output_l();
1628
1629 //If passthrough is active then pcm hdmi output has to be dropped.
1630 pthread_mutex_unlock(&p_qap->lock);
1631 DEBUG_MSG("Compressed passthrough enabled, DROPPING DATA!");
1632 return;
1633 }
1634
1635 /* If Media format was changed for this stream then need to re-create the stream. */
1636 if (need_to_recreate_stream && qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH]) {
1637 DEBUG_MSG("closing MCH PCM session ox%x", (int)qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH]);
1638 adev_close_output_stream((struct audio_hw_device *)p_qap->adev,
1639 (struct audio_stream_out *)(qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH]));
1640 qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH] = NULL;
1641 p_qap->mch_pcm_hdmi_enabled = false;
1642 }
1643
1644 if (!p_qap->mch_pcm_hdmi_enabled && !(qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH])) {
1645 audio_devices_t devices;
1646
1647 if (event_id == AUDIO_DATA_EVENT) {
1648 config.offload_info.format = config.format = AUDIO_FORMAT_PCM_16_BIT;
1649
1650 if (p_qap->hdmi_sink_channels == 8) {
1651 config.offload_info.channel_mask = config.channel_mask =
1652 AUDIO_CHANNEL_OUT_7POINT1;
1653 } else if (p_qap->hdmi_sink_channels == 6) {
1654 config.offload_info.channel_mask = config.channel_mask =
1655 AUDIO_CHANNEL_OUT_5POINT1;
1656 } else {
1657 config.offload_info.channel_mask = config.channel_mask =
1658 AUDIO_CHANNEL_OUT_STEREO;
1659 }
1660 }
1661
1662 devices = AUDIO_DEVICE_OUT_AUX_DIGITAL;
1663 flags = AUDIO_OUTPUT_FLAG_DIRECT;
1664
1665 DEBUG_MSG("Opening MCH PCM out(outputenum=%d) session ox%x with below params",
1666 QAP_OUT_OFFLOAD_MCH,
1667 (int)qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH]);
1668
1669 DEBUG_MSG("sample rate=%d bitwidth=%d format = 0x%x channel mask=0x%x flags=0x%x device =0x%x",
1670 config.sample_rate,
1671 config.offload_info.bit_width,
1672 config.offload_info.format,
1673 config.offload_info.channel_mask,
1674 flags,
1675 devices);
1676
1677 ret = adev_open_output_stream((struct audio_hw_device *)p_qap->adev,
1678 QAP_DEFAULT_COMPR_AUDIO_HANDLE,
1679 devices,
1680 flags,
1681 &config,
1682 (struct audio_stream_out **)&(qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH]),
1683 NULL);
1684 if (ret < 0) {
1685 ERROR_MSG("Failed opening MCH PCM out(outputenum=%d) session ox%x",
1686 QAP_OUT_OFFLOAD_MCH,
1687 (int)qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH]);
1688 pthread_mutex_unlock(&p_qap->lock);
1689 return;
1690 } else
1691 DEBUG_MSG("Opened MCH PCM out(outputenum=%d) session ox%x",
1692 QAP_OUT_OFFLOAD_MCH,
1693 (int)qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH]);
1694
1695 set_out_stream_channel_map(qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH], new_conf);
1696
1697 qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH]->compr_config.fragments =
1698 COMPRESS_OFFLOAD_NUM_FRAGMENTS;
1699 qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH]->compr_config.fragment_size =
1700 qap_get_pcm_offload_output_buffer_size(qap_mod, &config.offload_info);
1701
1702 p_qap->mch_pcm_hdmi_enabled = true;
1703
1704 if ((qap_mod->stream_in[QAP_IN_MAIN]
1705 && qap_mod->stream_in[QAP_IN_MAIN]->client_callback != NULL) ||
1706 (qap_mod->stream_in[QAP_IN_MAIN_2]
1707 && qap_mod->stream_in[QAP_IN_MAIN_2]->client_callback != NULL)) {
1708
1709 if (qap_mod->stream_in[QAP_IN_MAIN]) {
1710 qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH]->stream.set_callback(
1711 (struct audio_stream_out *)qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH],
1712 qap_mod->stream_in[QAP_IN_MAIN]->client_callback,
1713 qap_mod->stream_in[QAP_IN_MAIN]->client_cookie);
1714 }
1715 if (qap_mod->stream_in[QAP_IN_MAIN_2]) {
1716 qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH]->stream.set_callback(
1717 (struct audio_stream_out *)qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH],
1718 qap_mod->stream_in[QAP_IN_MAIN_2]->client_callback,
1719 qap_mod->stream_in[QAP_IN_MAIN_2]->client_cookie);
1720 }
1721 } else if (qap_mod->stream_in[QAP_IN_PCM]
1722 && qap_mod->stream_in[QAP_IN_PCM]->client_callback != NULL) {
1723
1724 qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH]->stream.set_callback(
1725 (struct audio_stream_out *)qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH],
1726 qap_mod->stream_in[QAP_IN_PCM]->client_callback,
1727 qap_mod->stream_in[QAP_IN_PCM]->client_cookie);
1728 }
1729 }
1730 if (qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH]) {
1731 DEBUG_MSG_VV("Writing Bytes(%d) to QAP_OUT_OFFLOAD_MCH output(%p) buff ptr(%p)",
1732 buffer_size, qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH],
1733 data_buffer_p);
1734 ret = qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH]->stream.write(
1735 (struct audio_stream_out *)qap_mod->stream_out[QAP_OUT_OFFLOAD_MCH],
1736 data_buffer_p,
1737 buffer_size);
1738 }
1739 }
1740 else {
1741 /* CASE 3: PCM output.
1742 */
1743
1744 /* If Media format was changed for this stream then need to re-create the stream. */
1745 if (need_to_recreate_stream && qap_mod->stream_out[QAP_OUT_OFFLOAD]) {
1746 DEBUG_MSG("closing PCM session ox%x", (int)qap_mod->stream_out[QAP_OUT_OFFLOAD]);
1747 adev_close_output_stream((struct audio_hw_device *)p_qap->adev,
1748 (struct audio_stream_out *)(qap_mod->stream_out[QAP_OUT_OFFLOAD]));
1749 qap_mod->stream_out[QAP_OUT_OFFLOAD] = NULL;
1750 }
1751
1752 bt_stream = audio_extn_bt_hal_get_output_stream(qap_mod->bt_hdl);
1753 if (bt_stream != NULL) {
1754 if (qap_mod->stream_out[QAP_OUT_OFFLOAD]) {
1755 adev_close_output_stream((struct audio_hw_device *)p_qap->adev,
1756 (struct audio_stream_out *)(qap_mod->stream_out[QAP_OUT_OFFLOAD]));
1757 qap_mod->stream_out[QAP_OUT_OFFLOAD] = NULL;
1758 }
1759
1760 audio_extn_bt_hal_out_write(p_qap->bt_hdl, data_buffer_p, buffer_size);
1761 } else if (NULL == qap_mod->stream_out[QAP_OUT_OFFLOAD]) {
1762 audio_devices_t devices;
1763
1764 if (qap_mod->stream_in[QAP_IN_MAIN])
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001765 devices = get_device_types(&qap_mod->stream_in[QAP_IN_MAIN]->device_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05301766 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001767 devices = get_device_types(&qap_mod->stream_in[QAP_IN_PCM]->device_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05301768
1769 //If multi channel pcm or passthrough is already enabled then remove the hdmi flag from device.
1770 if (p_qap->mch_pcm_hdmi_enabled || p_qap->passthrough_enabled) {
1771 if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1772 devices ^= AUDIO_DEVICE_OUT_AUX_DIGITAL;
1773 }
1774 if (devices == 0) {
1775 devices = device;
1776 }
1777
1778 flags = AUDIO_OUTPUT_FLAG_DIRECT;
1779
1780
1781 DEBUG_MSG("Opening Stereo PCM out(outputenum=%d) session ox%x with below params",
1782 QAP_OUT_OFFLOAD,
1783 (int)qap_mod->stream_out[QAP_OUT_OFFLOAD]);
1784
1785
1786 DEBUG_MSG("sample rate=%d bitwidth=%d format = 0x%x channel mask=0x%x flags=0x%x device =0x%x",
1787 config.sample_rate,
1788 config.offload_info.bit_width,
1789 config.offload_info.format,
1790 config.offload_info.channel_mask,
1791 flags,
1792 devices);
1793
1794
1795 /* TODO:: Need to Propagate errors to framework */
1796 ret = adev_open_output_stream((struct audio_hw_device *)p_qap->adev,
1797 QAP_DEFAULT_COMPR_AUDIO_HANDLE,
1798 devices,
1799 flags,
1800 &config,
1801 (struct audio_stream_out **)&(qap_mod->stream_out[QAP_OUT_OFFLOAD]),
1802 NULL);
1803 if (ret < 0) {
1804 ERROR_MSG("Failed opening Stereo PCM out(outputenum=%d) session ox%x",
1805 QAP_OUT_OFFLOAD,
1806 (int)qap_mod->stream_out[QAP_OUT_OFFLOAD]);
1807 pthread_mutex_unlock(&p_qap->lock);
1808 return;
1809 } else
1810 DEBUG_MSG("Opened Stereo PCM out(outputenum=%d) session ox%x",
1811 QAP_OUT_OFFLOAD,
1812 (int)qap_mod->stream_out[QAP_OUT_OFFLOAD]);
1813
1814 set_out_stream_channel_map(qap_mod->stream_out[QAP_OUT_OFFLOAD], new_conf);
1815
1816 if ((qap_mod->stream_in[QAP_IN_MAIN]
1817 && qap_mod->stream_in[QAP_IN_MAIN]->client_callback != NULL) ||
1818 (qap_mod->stream_in[QAP_IN_MAIN_2]
1819 && qap_mod->stream_in[QAP_IN_MAIN_2]->client_callback != NULL)) {
1820
1821 if (qap_mod->stream_in[QAP_IN_MAIN]) {
1822 qap_mod->stream_out[QAP_OUT_OFFLOAD]->stream.set_callback(
1823 (struct audio_stream_out *)qap_mod->stream_out[QAP_OUT_OFFLOAD],
1824 qap_mod->stream_in[QAP_IN_MAIN]->client_callback,
1825 qap_mod->stream_in[QAP_IN_MAIN]->client_cookie);
1826 }
1827 if (qap_mod->stream_in[QAP_IN_MAIN_2]) {
1828 qap_mod->stream_out[QAP_OUT_OFFLOAD]->stream.set_callback(
1829 (struct audio_stream_out *)qap_mod->stream_out[QAP_OUT_OFFLOAD],
1830 qap_mod->stream_in[QAP_IN_MAIN_2]->client_callback,
1831 qap_mod->stream_in[QAP_IN_MAIN_2]->client_cookie);
1832 }
1833 } else if (qap_mod->stream_in[QAP_IN_PCM]
1834 && qap_mod->stream_in[QAP_IN_PCM]->client_callback != NULL) {
1835
1836 qap_mod->stream_out[QAP_OUT_OFFLOAD]->stream.set_callback(
1837 (struct audio_stream_out *)qap_mod->stream_out[QAP_OUT_OFFLOAD],
1838 qap_mod->stream_in[QAP_IN_PCM]->client_callback,
1839 qap_mod->stream_in[QAP_IN_PCM]->client_cookie);
1840 }
1841
1842 qap_mod->stream_out[QAP_OUT_OFFLOAD]->compr_config.fragments =
1843 COMPRESS_OFFLOAD_NUM_FRAGMENTS;
1844 qap_mod->stream_out[QAP_OUT_OFFLOAD]->compr_config.fragment_size =
1845 qap_get_pcm_offload_output_buffer_size(qap_mod, &config.offload_info);
1846
1847 if (qap_mod->is_vol_set) {
1848 DEBUG_MSG("Setting Volume Left[%f], Right[%f]", qap_mod->vol_left, qap_mod->vol_right);
1849 qap_mod->stream_out[QAP_OUT_OFFLOAD]->stream.set_volume(
1850 (struct audio_stream_out *)qap_mod->stream_out[QAP_OUT_OFFLOAD],
1851 qap_mod->vol_left,
1852 qap_mod->vol_right);
1853 }
1854 }
1855
1856 if (qap_mod->stream_out[QAP_OUT_OFFLOAD]) {
1857 DEBUG_MSG_VV("Writing Bytes(%d) to QAP_OUT_OFFLOAD output(%p) buff ptr(%p)",
1858 buffer_size, qap_mod->stream_out[QAP_OUT_OFFLOAD],
1859 data_buffer_p);
1860 ret = qap_mod->stream_out[QAP_OUT_OFFLOAD]->stream.write(
1861 (struct audio_stream_out *)qap_mod->stream_out[QAP_OUT_OFFLOAD],
1862 data_buffer_p,
1863 buffer_size);
1864 }
1865 }
1866 DEBUG_MSG_VV("Bytes consumed [%d] by Audio HAL", ret);
1867 }
1868 else if (event_id == QAP_CALLBACK_EVENT_EOS
1869 || event_id == QAP_CALLBACK_EVENT_MAIN_2_EOS
1870 || event_id == QAP_CALLBACK_EVENT_EOS_ASSOC) {
1871 struct stream_out *out = qap_mod->stream_in[QAP_IN_MAIN];
1872 struct stream_out *out_pcm = qap_mod->stream_in[QAP_IN_PCM];
1873 struct stream_out *out_main2 = qap_mod->stream_in[QAP_IN_MAIN_2];
1874 struct stream_out *out_assoc = qap_mod->stream_in[QAP_IN_ASSOC];
1875
1876 /**
1877 * TODO:: Only DD/DDP Associate Eos is handled, need to add support
1878 * for other formats.
1879 */
1880 if (event_id == QAP_CALLBACK_EVENT_EOS
1881 && (out_pcm != NULL)
1882 && (check_stream_state_l(out_pcm, STOPPING))) {
1883
1884 lock_output_stream_l(out_pcm);
1885 out_pcm->client_callback(STREAM_CBK_EVENT_DRAIN_READY, NULL, out_pcm->client_cookie);
1886 set_stream_state_l(out_pcm, STOPPED);
1887 unlock_output_stream_l(out_pcm);
1888 DEBUG_MSG("sent pcm DRAIN_READY");
1889 } else if ( event_id == QAP_CALLBACK_EVENT_EOS_ASSOC
1890 && (out_assoc != NULL)
1891 && (check_stream_state_l(out_assoc, STOPPING))) {
1892
1893 lock_output_stream_l(out_assoc);
1894 out_assoc->client_callback(STREAM_CBK_EVENT_DRAIN_READY, NULL, out_assoc->client_cookie);
1895 set_stream_state_l(out_assoc, STOPPED);
1896 unlock_output_stream_l(out_assoc);
1897 DEBUG_MSG("sent associated DRAIN_READY");
1898 } else if (event_id == QAP_CALLBACK_EVENT_MAIN_2_EOS
1899 && (out_main2 != NULL)
1900 && (check_stream_state_l(out_main2, STOPPING))) {
1901
1902 lock_output_stream_l(out_main2);
1903 out_main2->client_callback(STREAM_CBK_EVENT_DRAIN_READY, NULL, out_main2->client_cookie);
1904 set_stream_state_l(out_main2, STOPPED);
1905 unlock_output_stream_l(out_main2);
1906 DEBUG_MSG("sent main2 DRAIN_READY");
1907 } else if ((out != NULL) && (check_stream_state_l(out, STOPPING))) {
1908 lock_output_stream_l(out);
1909 out->client_callback(STREAM_CBK_EVENT_DRAIN_READY, NULL, out->client_cookie);
1910 set_stream_state_l(out, STOPPED);
1911 unlock_output_stream_l(out);
1912 DEBUG_MSG("sent main DRAIN_READY");
1913 }
1914 }
1915 else if (event_id == QAP_CALLBACK_EVENT_EOS || event_id == QAP_CALLBACK_EVENT_EOS_ASSOC) {
1916 struct stream_out *out = NULL;
1917
1918 if (event_id == QAP_CALLBACK_EVENT_EOS) {
1919 out = qap_mod->stream_in[QAP_IN_MAIN];
1920 } else {
1921 out = qap_mod->stream_in[QAP_IN_ASSOC];
1922 }
1923
1924 if ((out != NULL) && (check_stream_state_l(out, STOPPING))) {
1925 lock_output_stream_l(out);
1926 out->client_callback(STREAM_CBK_EVENT_DRAIN_READY, NULL, out->client_cookie);
1927 set_stream_state_l(out, STOPPED);
1928 unlock_output_stream_l(out);
1929 DEBUG_MSG("sent DRAIN_READY");
1930 }
1931 }
1932
1933 pthread_mutex_unlock(&p_qap->lock);
1934 return;
1935}
1936
1937static int qap_sess_close(struct qap_module* qap_mod)
1938{
1939 int j;
1940 int ret = -EINVAL;
1941
1942 DEBUG_MSG("Closing Session.");
1943
1944 //Check if all streams are closed or not.
1945 for (j = 0; j < MAX_QAP_MODULE_IN; j++) {
1946 if (qap_mod->stream_in[j] != NULL) {
1947 break;
1948 }
1949 }
1950 if (j != MAX_QAP_MODULE_IN) {
1951 DEBUG_MSG("Some stream is still active, Can not close session.");
1952 return 0;
1953 }
1954
1955 qap_mod->is_session_closing = true;
1956 if(p_qap->qap_output_block_handling) {
1957 pthread_mutex_lock(&qap_mod->session_output_lock);
1958 if (qap_mod->is_session_output_active == false) {
1959 pthread_cond_signal(&qap_mod->session_output_cond);
1960 DEBUG_MSG("Wake up MM module output thread");
1961 }
1962 pthread_mutex_unlock(&qap_mod->session_output_lock);
1963 }
1964 pthread_mutex_lock(&p_qap->lock);
1965
1966 if (!qap_mod || !qap_mod->session_handle) {
1967 ERROR_MSG("Wrong state to process qap_mod(%p) sess_hadl(%p)",
1968 qap_mod, qap_mod->session_handle);
1969 return -EINVAL;
1970 }
1971
1972 ret = qap_session_close(qap_mod->session_handle);
1973 if (QAP_STATUS_OK != ret) {
1974 ERROR_MSG("close session failed %d", ret);
1975 return -EINVAL;
1976 } else
1977 DEBUG_MSG("Closed QAP session 0x%x", (int)qap_mod->session_handle);
1978
1979 qap_mod->session_handle = NULL;
1980 qap_mod->is_vol_set = false;
1981 memset(qap_mod->stream_state, 0, sizeof(qap_mod->stream_state));
1982
1983 qap_close_all_output_streams(qap_mod);
1984
1985 qap_mod->new_out_format_index = 0;
1986
1987 pthread_mutex_unlock(&p_qap->lock);
1988 qap_mod->is_session_closing = false;
1989 DEBUG_MSG("Exit.");
1990
1991 return 0;
1992}
1993
1994static int qap_stream_close(struct stream_out *out)
1995{
1996 int ret = -EINVAL;
1997 struct qap_module *qap_mod = NULL;
1998 int index = -1;
1999 DEBUG_MSG("Flag [0x%x], Stream handle [%p]", out->flags, out->qap_stream_handle);
2000
2001 qap_mod = get_qap_module_for_input_stream_l(out);
2002 index = get_input_stream_index_l(out);
2003
2004 if (!qap_mod || !qap_mod->session_handle || (index < 0) || !out->qap_stream_handle) {
2005 ERROR_MSG("Wrong state to process qap_mod(%p) sess_hadl(%p) strm hndl(%p), index %d",
2006 qap_mod, qap_mod->session_handle, out->qap_stream_handle, index);
2007 return -EINVAL;
2008 }
2009
2010 pthread_mutex_lock(&p_qap->lock);
2011
2012 set_stream_state_l(out,STOPPED);
2013 qap_mod->stream_in[index] = NULL;
2014
2015 lock_output_stream_l(out);
2016
2017 ret = qap_module_deinit(out->qap_stream_handle);
2018 if (QAP_STATUS_OK != ret) {
2019 ERROR_MSG("deinit failed %d", ret);
2020 return -EINVAL;
2021 } else
2022 DEBUG_MSG("module(ox%x) closed successfully", (int)out->qap_stream_handle);
2023
2024
2025 out->qap_stream_handle = NULL;
2026 unlock_output_stream_l(out);
2027
2028 pthread_mutex_unlock(&p_qap->lock);
2029
2030 //If all streams are closed then close the session.
2031 qap_sess_close(qap_mod);
2032
2033 DEBUG_MSG("Exit");
2034 return ret;
2035}
2036
2037#define MAX_INIT_PARAMS 6
2038
2039static void update_qap_session_init_params(audio_session_handle_t session_handle) {
2040 DEBUG_MSG("Entry");
2041 qap_status_t ret = QAP_STATUS_OK;
2042 uint32_t cmd_data[MAX_INIT_PARAMS] = {0};
2043
2044 /* all init params should be sent
2045 * together so gang them up.
2046 */
2047 cmd_data[0] = MS12_SESSION_CFG_MAX_CHS;
2048 cmd_data[1] = 6;/*5.1 channels*/
2049
2050 cmd_data[2] = MS12_SESSION_CFG_BS_OUTPUT_MODE;
2051 cmd_data[3] = 3;/*DDP Re-encoding and DDP to DD Transcoding*/
2052
2053 cmd_data[4] = MS12_SESSION_CFG_CHMOD_LOCKING;
2054 cmd_data[MAX_INIT_PARAMS - 1] = 1;/*Lock to 6 channel*/
2055
2056 ret = qap_session_cmd(session_handle,
2057 QAP_SESSION_CMD_SET_PARAM,
2058 MAX_INIT_PARAMS * sizeof(uint32_t),
2059 &cmd_data[0],
2060 NULL,
2061 NULL);
2062 if (ret != QAP_STATUS_OK) {
2063 ERROR_MSG("session init params config failed");
2064 }
2065 DEBUG_MSG("Exit");
2066 return;
2067}
2068
2069/* Query HDMI EDID and sets module output accordingly.*/
2070static void qap_set_hdmi_configuration_to_module()
2071{
2072 int ret = 0;
2073 int channels = 0;
2074 char prop_value[PROPERTY_VALUE_MAX] = {0};
2075 bool passth_support = false;
2076 qap_session_outputs_config_t *session_outputs_config = NULL;
2077
2078
2079 DEBUG_MSG("Entry");
2080
2081 if (!p_qap) {
2082 return;
2083 }
2084
2085 if (!p_qap->hdmi_connect) {
2086 return;
2087 }
2088
2089 p_qap->hdmi_sink_channels = 0;
2090
2091 if (p_qap->qap_mod[MS12].session_handle)
2092 session_outputs_config = &p_qap->qap_mod[MS12].session_outputs_config;
2093 else if (p_qap->qap_mod[DTS_M8].session_handle)
2094 session_outputs_config = &p_qap->qap_mod[DTS_M8].session_outputs_config;
2095 else {
2096 DEBUG_MSG("HDMI connection comes even before session is setup");
2097 return;
2098 }
2099
2100 session_outputs_config->num_output = 1;
2101 //QAP re-encoding and DSP offload passthrough is supported.
2102 if (property_get_bool("vendor.audio.offload.passthrough", false)
2103 && property_get_bool("vendor.audio.qap.reencode", false)) {
2104
2105 if (p_qap->qap_mod[MS12].session_handle) {
2106
2107 bool do_setparam = false;
2108 property_get("vendor.audio.qap.hdmi.out", prop_value, NULL);
2109
2110 if (platform_is_edid_supported_format(p_qap->adev->platform, AUDIO_FORMAT_E_AC3)
2111 && (strncmp(prop_value, "ddp", 3) == 0)) {
2112 do_setparam = true;
2113 session_outputs_config->output_config[0].format = QAP_AUDIO_FORMAT_EAC3;
2114 session_outputs_config->output_config[0].id = AUDIO_DEVICE_OUT_HDMI|QAP_AUDIO_FORMAT_EAC3;
2115 } else if (platform_is_edid_supported_format(p_qap->adev->platform, AUDIO_FORMAT_AC3)) {
2116 do_setparam = true;
2117 session_outputs_config->output_config[0].format = QAP_AUDIO_FORMAT_AC3;
2118 session_outputs_config->output_config[0].id = AUDIO_DEVICE_OUT_HDMI|QAP_AUDIO_FORMAT_AC3;
2119 }
2120 if (do_setparam) {
2121 DEBUG_MSG(" Enabling HDMI(Passthrough out) from MS12 wrapper outputid=0x%x",
2122 session_outputs_config->output_config[0].id);
2123 ret = qap_session_cmd(p_qap->qap_mod[MS12].session_handle,
2124 QAP_SESSION_CMD_SET_OUTPUTS,
2125 sizeof(qap_session_outputs_config_t),
2126 session_outputs_config,
2127 NULL,
2128 NULL);
2129 if (QAP_STATUS_OK != ret) {
2130 ERROR_MSG("Unable to register AUDIO_DEVICE_OUT_HDMI device with QAP %d", ret);
2131 return;
2132 }
2133 passth_support = true;
2134 }
2135 }
2136
2137 if (p_qap->qap_mod[DTS_M8].session_handle) {
2138
2139 bool do_setparam = false;
2140 if (platform_is_edid_supported_format(p_qap->adev->platform, AUDIO_FORMAT_DTS)) {
2141 do_setparam = true;
2142 session_outputs_config->output_config[0].format = QAP_AUDIO_FORMAT_DTS;
2143 session_outputs_config->output_config[0].id = AUDIO_DEVICE_OUT_HDMI|QAP_AUDIO_FORMAT_DTS;
2144 }
2145
2146 if (do_setparam) {
2147 ret = qap_session_cmd(p_qap->qap_mod[DTS_M8].session_handle,
2148 QAP_SESSION_CMD_SET_OUTPUTS,
2149 sizeof(qap_session_outputs_config_t),
2150 session_outputs_config,
2151 NULL,
2152 NULL);
2153 if (QAP_STATUS_OK != ret) {
2154 ERROR_MSG("Unable to register AUDIO_DEVICE_OUT_HDMI device with QAP %d", ret);
2155 return;
2156 }
2157 passth_support = true;
2158 }
2159 }
2160 }
2161 //Compressed passthrough is not enabled.
2162 if (!passth_support) {
2163
2164 channels = platform_edid_get_max_channels(p_qap->adev->platform);
2165 session_outputs_config->output_config[0].format = QAP_AUDIO_FORMAT_PCM_16_BIT;
2166
2167 switch (channels) {
2168 case 8:
2169 DEBUG_MSG("Switching Qap output to 7.1 channels");
2170 session_outputs_config->output_config[0].channels = 8;
2171 if (!p_qap->qap_msmd_enabled)
2172 session_outputs_config->output_config[0].id = AUDIO_DEVICE_OUT_HDMI|QAP_AUDIO_FORMAT_PCM_16_BIT;
2173 p_qap->hdmi_sink_channels = channels;
2174 break;
2175 case 6:
2176 DEBUG_MSG("Switching Qap output to 5.1 channels");
2177 session_outputs_config->output_config[0].channels = 6;
2178 if (!p_qap->qap_msmd_enabled)
2179 session_outputs_config->output_config[0].id = AUDIO_DEVICE_OUT_HDMI|QAP_AUDIO_FORMAT_PCM_16_BIT;
2180 p_qap->hdmi_sink_channels = channels;
2181 break;
2182 default:
2183 DEBUG_MSG("Switching Qap output to default channels");
2184 session_outputs_config->output_config[0].channels = 2;
2185 if (!p_qap->qap_msmd_enabled)
2186 session_outputs_config->output_config[0].id = AUDIO_DEVICE_OUT_HDMI|QAP_AUDIO_FORMAT_PCM_16_BIT;
2187 p_qap->hdmi_sink_channels = 2;
2188 break;
2189 }
2190
2191 if (p_qap->qap_mod[MS12].session_handle) {
2192 DEBUG_MSG(" Enabling HDMI(MCH PCM out) from MS12 wrapper outputid = %x", session_outputs_config->output_config[0].id);
2193 ret = qap_session_cmd(p_qap->qap_mod[MS12].session_handle,
2194 QAP_SESSION_CMD_SET_OUTPUTS,
2195 sizeof(qap_session_outputs_config_t),
2196 session_outputs_config,
2197 NULL,
2198 NULL);
2199 if (QAP_STATUS_OK != ret) {
2200 ERROR_MSG("Unable to register AUDIO_DEVICE_OUT_HDMI device with QAP %d", ret);
2201 return;
2202 }
2203 }
2204 if (p_qap->qap_mod[DTS_M8].session_handle) {
2205 ret = qap_session_cmd(p_qap->qap_mod[MS12].session_handle,
2206 QAP_SESSION_CMD_SET_OUTPUTS,
2207 sizeof(qap_session_outputs_config_t),
2208 session_outputs_config,
2209 NULL,
2210 NULL);
2211 if (QAP_STATUS_OK != ret) {
2212 ERROR_MSG("Unable to register AUDIO_DEVICE_OUT_HDMI device with QAP %d", ret);
2213 return;
2214 }
2215 }
2216
2217 }
2218 DEBUG_MSG("Exit");
2219}
2220
2221
2222static void qap_set_default_configuration_to_module()
2223{
2224 qap_session_outputs_config_t *session_outputs_config = NULL;
2225 int ret = 0;
2226
2227 DEBUG_MSG("Entry");
2228
2229 if (!p_qap) {
2230 return;
2231 }
2232
2233 if (!p_qap->bt_connect) {
2234 DEBUG_MSG("BT is not connected.");
2235 }
2236
2237 //ms12 wrapper don't support bt, treat this as speaker and routign to bt
2238 //will take care as a part of data callback notifier
2239
2240
2241 if (p_qap->qap_mod[MS12].session_handle)
2242 session_outputs_config = &p_qap->qap_mod[MS12].session_outputs_config;
2243 else if (p_qap->qap_mod[DTS_M8].session_handle)
2244 session_outputs_config = &p_qap->qap_mod[DTS_M8].session_outputs_config;
2245
2246 session_outputs_config->num_output = 1;
2247 session_outputs_config->output_config[0].id = AUDIO_DEVICE_OUT_SPEAKER;
2248 session_outputs_config->output_config[0].format = QAP_AUDIO_FORMAT_PCM_16_BIT;
2249
2250
2251 if (p_qap->qap_mod[MS12].session_handle) {
2252 DEBUG_MSG(" Enabling speaker(PCM out) from MS12 wrapper outputid = %x", session_outputs_config->output_config[0].id);
2253 ret = qap_session_cmd(p_qap->qap_mod[MS12].session_handle,
2254 QAP_SESSION_CMD_SET_OUTPUTS,
2255 sizeof(qap_session_outputs_config_t),
2256 session_outputs_config,
2257 NULL,
2258 NULL);
2259 if (QAP_STATUS_OK != ret) {
2260 ERROR_MSG("Unable to register AUDIO_DEVICE_OUT_SPEAKER device with QAP %d", ret);
2261 return;
2262 }
2263 }
2264 if (p_qap->qap_mod[DTS_M8].session_handle) {
2265 ret = qap_session_cmd(p_qap->qap_mod[DTS_M8].session_handle,
2266 QAP_SESSION_CMD_SET_OUTPUTS,
2267 sizeof(qap_session_outputs_config_t),
2268 session_outputs_config,
2269 NULL,
2270 NULL);
2271 if (QAP_STATUS_OK != ret) {
2272 ERROR_MSG("Unable to register AUDIO_DEVICE_OUT_SPEAKER device with QAP %d", ret);
2273 return;
2274 }
2275 }
2276}
2277
2278
2279/* Open a MM module session with QAP. */
2280static int audio_extn_qap_session_open(mm_module_type mod_type, __unused struct stream_out *out)
2281{
2282 DEBUG_MSG("%s %d", __func__, __LINE__);
2283 int ret = 0;
2284
2285 struct qap_module *qap_mod = NULL;
2286
2287 if (mod_type >= MAX_MM_MODULE_TYPE)
2288 return -ENOTSUP; //Not supported by QAP module.
2289
2290 pthread_mutex_lock(&p_qap->lock);
2291
2292 qap_mod = &(p_qap->qap_mod[mod_type]);
2293
2294 //If session is already opened then return.
2295 if (qap_mod->session_handle) {
2296 DEBUG_MSG("QAP Session is already opened.");
2297 pthread_mutex_unlock(&p_qap->lock);
2298 return 0;
2299 }
2300
2301 if (MS12 == mod_type) {
2302 if (NULL == (qap_mod->session_handle = (void *)qap_session_open(QAP_SESSION_MS12_OTT, qap_mod->qap_lib))) {
2303 ERROR_MSG("Failed to open QAP session, lib_handle 0x%x", (int)qap_mod->qap_lib);
2304 ret = -EINVAL;
2305 goto exit;
2306 } else
2307 DEBUG_MSG("Opened QAP session 0x%x", (int)qap_mod->session_handle);
2308
2309 update_qap_session_init_params(qap_mod->session_handle);
2310 }
2311
2312 if (QAP_STATUS_OK != (qap_session_set_callback (qap_mod->session_handle, &qap_session_callback, (void *)qap_mod))) {
2313 ERROR_MSG("Failed to register QAP session callback");
2314 ret = -EINVAL;
2315 goto exit;
2316 }
2317
2318 qap_mod->is_session_output_active = true;
2319
2320 if(p_qap->hdmi_connect)
2321 qap_set_hdmi_configuration_to_module();
2322 else
2323 qap_set_default_configuration_to_module();
2324
2325exit:
2326 pthread_mutex_unlock(&p_qap->lock);
2327 return ret;
2328}
2329
2330
2331
2332static int qap_map_input_format(audio_format_t audio_format, qap_audio_format_t *format)
2333{
2334 if (audio_format == AUDIO_FORMAT_AC3) {
2335 *format = QAP_AUDIO_FORMAT_AC3;
2336 DEBUG_MSG( "File Format is AC3!");
2337 } else if (audio_format == AUDIO_FORMAT_E_AC3) {
2338 *format = QAP_AUDIO_FORMAT_EAC3;
2339 DEBUG_MSG( "File Format is E_AC3!");
2340 } else if ((audio_format == AUDIO_FORMAT_AAC_ADTS_LC) ||
2341 (audio_format == AUDIO_FORMAT_AAC_ADTS_HE_V1) ||
2342 (audio_format == AUDIO_FORMAT_AAC_ADTS_HE_V2) ||
2343 (audio_format == AUDIO_FORMAT_AAC_LC) ||
2344 (audio_format == AUDIO_FORMAT_AAC_HE_V1) ||
2345 (audio_format == AUDIO_FORMAT_AAC_HE_V2) ||
2346 (audio_format == AUDIO_FORMAT_AAC_LATM_LC) ||
2347 (audio_format == AUDIO_FORMAT_AAC_LATM_HE_V1) ||
2348 (audio_format == AUDIO_FORMAT_AAC_LATM_HE_V2)) {
2349 *format = QAP_AUDIO_FORMAT_AAC_ADTS;
2350 DEBUG_MSG( "File Format is AAC!");
2351 } else if (audio_format == AUDIO_FORMAT_DTS) {
2352 *format = QAP_AUDIO_FORMAT_DTS;
2353 DEBUG_MSG( "File Format is DTS!");
2354 } else if (audio_format == AUDIO_FORMAT_DTS_HD) {
2355 *format = QAP_AUDIO_FORMAT_DTS_HD;
2356 DEBUG_MSG( "File Format is DTS_HD!");
2357 } else if (audio_format == AUDIO_FORMAT_PCM_16_BIT) {
2358 *format = QAP_AUDIO_FORMAT_PCM_16_BIT;
2359 DEBUG_MSG( "File Format is PCM_16!");
2360 } else if (audio_format == AUDIO_FORMAT_PCM_32_BIT) {
2361 *format = QAP_AUDIO_FORMAT_PCM_32_BIT;
2362 DEBUG_MSG( "File Format is PCM_32!");
2363 } else if (audio_format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
2364 *format = QAP_AUDIO_FORMAT_PCM_24_BIT_PACKED;
2365 DEBUG_MSG( "File Format is PCM_24!");
2366 } else if ((audio_format == AUDIO_FORMAT_PCM_8_BIT) ||
2367 (audio_format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2368 *format = QAP_AUDIO_FORMAT_PCM_8_24_BIT;
2369 DEBUG_MSG( "File Format is PCM_8_24!");
2370 } else {
2371 ERROR_MSG( "File Format not supported!");
2372 return -EINVAL;
2373 }
2374 return 0;
2375}
2376
2377
2378void qap_module_callback(__unused qap_module_handle_t module_handle,
2379 void* priv_data,
2380 qap_module_callback_event_t event_id,
2381 __unused int size,
2382 __unused void *data)
2383{
2384 struct stream_out *out=(struct stream_out *)priv_data;
2385
2386 DEBUG_MSG("Entry");
2387 if (QAP_MODULE_CALLBACK_EVENT_SEND_INPUT_BUFFER == event_id) {
2388 DEBUG_MSG("QAP_MODULE_CALLBACK_EVENT_SEND_INPUT_BUFFER for (%p)", out);
2389 if (out->client_callback) {
2390 out->client_callback(STREAM_CBK_EVENT_WRITE_READY, NULL, out->client_cookie);
2391 }
2392 else
2393 DEBUG_MSG("client has no callback registered, no action needed for this event %d",
2394 event_id);
2395 }
2396 else
2397 DEBUG_MSG("Un Recognized event %d", event_id);
2398
2399 DEBUG_MSG("exit");
2400 return;
2401}
2402
2403
2404/* opens a stream in QAP module. */
2405static int qap_stream_open(struct stream_out *out,
2406 struct audio_config *config,
2407 audio_output_flags_t flags,
2408 audio_devices_t devices)
2409{
2410 int status = -EINVAL;
2411 mm_module_type mmtype = get_mm_module_for_format_l(config->format);
2412 struct qap_module* qap_mod = NULL;
2413 qap_module_config_t input_config = {0};
2414
2415 DEBUG_MSG("Flags 0x%x, Device 0x%x for use case %s out 0x%x", flags, devices, use_case_table[out->usecase], (int)out);
2416
2417 if (mmtype >= MAX_MM_MODULE_TYPE) {
2418 ERROR_MSG("Unsupported Stream");
2419 return -ENOTSUP;
2420 }
2421
2422 //Open the module session, if not opened already.
2423 status = audio_extn_qap_session_open(mmtype, out);
2424 qap_mod = &(p_qap->qap_mod[mmtype]);
2425
2426 if ((status != 0) || (!qap_mod->session_handle ))
2427 return status;
2428
2429 input_config.sample_rate = config->sample_rate;
2430 input_config.channels = popcount(config->channel_mask);
2431 if (input_config.format != AUDIO_FORMAT_PCM_16_BIT) {
2432 input_config.format &= AUDIO_FORMAT_MAIN_MASK;
2433 }
2434 input_config.module_type = QAP_MODULE_DECODER;
2435 status = qap_map_input_format(config->format, &input_config.format);
2436 if (status == -EINVAL)
2437 return -EINVAL;
2438
2439 DEBUG_MSG("qap_stream_open sample_rate(%d) channels(%d) devices(%#x) flags(%#x) format(%#x)",
2440 input_config.sample_rate, input_config.channels, devices, flags, input_config.format);
2441
2442 if (input_config.format == QAP_AUDIO_FORMAT_PCM_16_BIT) {
2443 //If PCM stream is already opened then fail this stream open.
2444 if (qap_mod->stream_in[QAP_IN_PCM]) {
2445 ERROR_MSG("PCM input is already active.");
2446 return -ENOTSUP;
2447 }
2448 input_config.flags = QAP_MODULE_FLAG_SYSTEM_SOUND;
2449 status = qap_module_init(qap_mod->session_handle, &input_config, &out->qap_stream_handle);
2450 if (QAP_STATUS_OK != status) {
2451 ERROR_MSG("Unable to open PCM(QAP_MODULE_FLAG_SYSTEM_SOUND) QAP module %d", status);
2452 return -EINVAL;
2453 } else
2454 DEBUG_MSG("QAP_MODULE_FLAG_SYSTEM_SOUND, module(ox%x) opened successfully", (int)out->qap_stream_handle);
2455
2456 qap_mod->stream_in[QAP_IN_PCM] = out;
2457 } else if ((flags & AUDIO_OUTPUT_FLAG_MAIN) && (flags & AUDIO_OUTPUT_FLAG_ASSOCIATED)) {
2458 if (is_main_active_l(qap_mod) || is_dual_main_active_l(qap_mod)) {
2459 ERROR_MSG("Dual Main or Main already active. So, Cannot open main and associated stream");
2460 return -EINVAL;
2461 } else {
2462 input_config.flags = QAP_MODULE_FLAG_PRIMARY;
2463 status = qap_module_init(qap_mod->session_handle, &input_config, &out->qap_stream_handle);
2464 if (QAP_STATUS_OK != status) {
2465 ERROR_MSG("Unable to open QAP stream/module with QAP_MODULE_FLAG_PRIMARY flag %d", status);
2466 return -EINVAL;
2467 } else
2468 DEBUG_MSG("QAP_MODULE_FLAG_PRIMARY, module opened successfully 0x%x", (int)out->qap_stream_handle);;
2469
2470 qap_mod->stream_in[QAP_IN_MAIN] = out;
2471 }
2472 } else if ((flags & AUDIO_OUTPUT_FLAG_MAIN) || ((!(flags & AUDIO_OUTPUT_FLAG_MAIN)) && (!(flags & AUDIO_OUTPUT_FLAG_ASSOCIATED)))) {
2473 /* Assume Main if no flag is set */
2474 if (is_dual_main_active_l(qap_mod)) {
2475 ERROR_MSG("Dual Main already active. So, Cannot open main stream");
2476 return -EINVAL;
2477 } else if (is_main_active_l(qap_mod) && qap_mod->stream_in[QAP_IN_ASSOC]) {
2478 ERROR_MSG("Main and Associated already active. So, Cannot open main stream");
2479 return -EINVAL;
2480 } else if (is_main_active_l(qap_mod) && (mmtype != MS12)) {
2481 ERROR_MSG("Main already active and Not an MS12 format. So, Cannot open another main stream");
2482 return -EINVAL;
2483 } else {
2484 input_config.flags = QAP_MODULE_FLAG_PRIMARY;
2485 status = qap_module_init(qap_mod->session_handle, &input_config, &out->qap_stream_handle);
2486 if (QAP_STATUS_OK != status) {
2487 ERROR_MSG("Unable to open QAP stream/module with QAP_MODULE_FLAG_PRIMARY flag %d", status);
2488 return -EINVAL;
2489 } else
2490 DEBUG_MSG("QAP_MODULE_FLAG_PRIMARY, module opened successfully 0x%x", (int)out->qap_stream_handle);
2491
2492 if(qap_mod->stream_in[QAP_IN_MAIN]) {
2493 qap_mod->stream_in[QAP_IN_MAIN_2] = out;
2494 } else {
2495 qap_mod->stream_in[QAP_IN_MAIN] = out;
2496 }
2497 }
2498 } else if ((flags & AUDIO_OUTPUT_FLAG_ASSOCIATED)) {
2499 if (is_dual_main_active_l(qap_mod)) {
2500 ERROR_MSG("Dual Main already active. So, Cannot open associated stream");
2501 return -EINVAL;
2502 } else if (!is_main_active_l(qap_mod)) {
2503 ERROR_MSG("Main not active. So, Cannot open associated stream");
2504 return -EINVAL;
2505 } else if (qap_mod->stream_in[QAP_IN_ASSOC]) {
2506 ERROR_MSG("Associated already active. So, Cannot open associated stream");
2507 return -EINVAL;
2508 }
2509 input_config.flags = QAP_MODULE_FLAG_SECONDARY;
2510 status = qap_module_init(qap_mod->session_handle, &input_config, &out->qap_stream_handle);
2511 if (QAP_STATUS_OK != status) {
2512 ERROR_MSG("Unable to open QAP stream/module with QAP_MODULE_FLAG_SECONDARY flag %d", status);
2513 return -EINVAL;
2514 } else
2515 DEBUG_MSG("QAP_MODULE_FLAG_SECONDARY, module opened successfully 0x%x", (int)out->qap_stream_handle);
2516
2517 qap_mod->stream_in[QAP_IN_ASSOC] = out;
2518 }
2519
2520 if (out->qap_stream_handle) {
2521 status = qap_module_set_callback(out->qap_stream_handle, &qap_module_callback, out);
2522 if (QAP_STATUS_OK != status) {
2523 ERROR_MSG("Unable to register module callback %d", status);
2524 return -EINVAL;
2525 } else
2526 DEBUG_MSG("Module call back registered 0x%x cookie 0x%x", (int)out->qap_stream_handle, (int)out);
2527 }
2528
2529 if (status != 0) {
2530 //If no stream is active then close the session.
2531 qap_sess_close(qap_mod);
2532 return 0;
2533 }
2534
2535 //If Device is HDMI, QAP passthrough is enabled and there is no previous QAP passthrough input stream.
2536 if ((!p_qap->passthrough_in)
2537 && (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2538 && audio_extn_qap_passthrough_enabled(out)) {
2539 //Assign the QAP passthrough input stream.
2540 p_qap->passthrough_in = out;
2541
2542 //If HDMI is connected and format is supported by HDMI then create QAP passthrough output stream.
2543 if (p_qap->hdmi_connect
2544 && platform_is_edid_supported_format(p_qap->adev->platform, out->format)) {
2545 status = create_qap_passthrough_stream_l();
2546 if (status < 0) {
2547 qap_stream_close(out);
2548 ERROR_MSG("QAP passthrough stream creation failed with error %d", status);
2549 return status;
2550 }
2551 }
2552 /*Else: since QAP passthrough input stream is already initialized,
2553 * when hdmi is connected
2554 * then qap passthrough output stream will be created.
2555 */
2556 }
2557
2558 DEBUG_MSG();
2559 return status;
2560}
2561
2562static int qap_out_resume(struct audio_stream_out* stream)
2563{
2564 struct stream_out *out = (struct stream_out *)stream;
2565 int status = 0;
2566 DEBUG_MSG("Output Stream %p", out);
2567
2568
2569 lock_output_stream_l(out);
2570
2571 //If QAP passthrough is active then block the resume on module input streams.
2572 if (p_qap->passthrough_out) {
2573 //If resume is received for the QAP passthrough stream then call the primary HAL api.
2574 pthread_mutex_lock(&p_qap->lock);
2575 if (p_qap->passthrough_in == out) {
2576 status = p_qap->passthrough_out->stream.resume(
2577 (struct audio_stream_out*)p_qap->passthrough_out);
2578 if (!status) out->offload_state = OFFLOAD_STATE_PLAYING;
2579 }
2580 pthread_mutex_unlock(&p_qap->lock);
2581 } else {
2582 //Flush the module input stream.
2583 status = qap_stream_start_l(out);
2584 }
2585
2586 unlock_output_stream_l(out);
2587
2588 DEBUG_MSG();
2589 return status;
2590}
2591
2592static int qap_out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2593{
2594 struct str_parms *parms;
2595 char value[32];
2596 int val = 0;
2597 struct stream_out *out = (struct stream_out *)stream;
2598 int ret = 0;
2599 int err = 0;
2600 struct qap_module *qap_mod = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002601 char *address = "";
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05302602
2603 DEBUG_MSG("usecase(%d: %s) kvpairs: %s", out->usecase, use_case_table[out->usecase], kvpairs);
2604
2605 parms = str_parms_create_str(kvpairs);
2606 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2607 if (err < 0)
2608 return err;
2609 val = atoi(value);
2610
2611 qap_mod = get_qap_module_for_input_stream_l(out);
2612 if (!qap_mod) return (-EINVAL);
2613
2614 //TODO: HDMI is connected but user doesn't want HDMI output, close both HDMI outputs.
2615
2616 /* Setting new device information to the mm module input streams.
2617 * This is needed if QAP module output streams are not created yet.
2618 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002619 reassign_device_list(&out->device_list, val, address);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05302620
2621#ifndef SPLIT_A2DP_ENABLED
2622 if (val == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) {
2623 //If device is BT then open the BT stream if not already opened.
2624 if ( audio_extn_bt_hal_get_output_stream(qap_mod->bt_hdl) == NULL
2625 && audio_extn_bt_hal_get_device(qap_mod->bt_hdl) != NULL) {
2626 ret = audio_extn_bt_hal_open_output_stream(qap_mod->bt_hdl,
2627 QAP_OUTPUT_SAMPLING_RATE,
2628 AUDIO_CHANNEL_OUT_STEREO,
2629 CODEC_BACKEND_DEFAULT_BIT_WIDTH);
2630 if (ret != 0) {
2631 ERROR_MSG("BT Output stream open failure!");
2632 }
2633 }
2634 } else if (val != 0) {
2635 //If device is not BT then close the BT stream if already opened.
2636 if ( audio_extn_bt_hal_get_output_stream(qap_mod->bt_hdl) != NULL) {
2637 audio_extn_bt_hal_close_output_stream(qap_mod->bt_hdl);
2638 }
2639 }
2640#endif
2641
2642 if (p_qap->passthrough_in == out) { //Device routing is received for QAP passthrough stream.
2643
2644 if (!(val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) { //HDMI route is disabled.
2645
2646 //If QAP pasthrough output is enabled. Close it.
2647 close_qap_passthrough_stream_l();
2648
2649 //Send the routing information to mm module pcm output.
2650 if (qap_mod->stream_out[QAP_OUT_OFFLOAD]) {
2651 ret = qap_mod->stream_out[QAP_OUT_OFFLOAD]->stream.common.set_parameters(
2652 (struct audio_stream *)qap_mod->stream_out[QAP_OUT_OFFLOAD], kvpairs);
2653 }
2654 //else: device info is updated in the input streams.
2655 } else { //HDMI route is enabled.
2656
2657 //create the QAf passthrough stream, if not created already.
2658 ret = create_qap_passthrough_stream_l();
2659
2660 if (p_qap->passthrough_out != NULL) { //If QAP passthrough out is enabled then send routing information.
2661 ret = p_qap->passthrough_out->stream.common.set_parameters(
2662 (struct audio_stream *)p_qap->passthrough_out, kvpairs);
2663 }
2664 }
2665 } else {
2666 //Send the routing information to mm module pcm output.
2667 if (qap_mod->stream_out[QAP_OUT_OFFLOAD]) {
2668 ret = qap_mod->stream_out[QAP_OUT_OFFLOAD]->stream.common.set_parameters(
2669 (struct audio_stream *)qap_mod->stream_out[QAP_OUT_OFFLOAD], kvpairs);
2670 }
2671 //else: device info is updated in the input streams.
2672 }
2673 str_parms_destroy(parms);
2674
2675 return ret;
2676}
2677
2678/* Checks if a stream is QAP stream or not. */
2679bool audio_extn_is_qap_stream(struct stream_out *out)
2680{
2681 struct qap_module *qap_mod = get_qap_module_for_input_stream_l(out);
2682
2683 if (qap_mod) {
2684 return true;
2685 }
2686 return false;
2687}
2688
2689#if 0
2690/* API to send playback stream specific config parameters */
2691int audio_extn_qap_out_set_param_data(struct stream_out *out,
2692 audio_extn_param_id param_id,
2693 audio_extn_param_payload *payload)
2694{
2695 int ret = -EINVAL;
2696 int index;
2697 struct stream_out *new_out = NULL;
2698 struct audio_adsp_event *adsp_event;
2699 struct qap_module *qap_mod = get_qap_module_for_input_stream_l(out);
2700
2701 if (!out || !qap_mod || !payload) {
2702 ERROR_MSG("Invalid Param");
2703 return ret;
2704 }
2705
2706 /* apply param for all active out sessions */
2707 for (index = 0; index < MAX_QAP_MODULE_OUT; index++) {
2708 new_out = qap_mod->stream_out[index];
2709 if (!new_out) continue;
2710
2711 /*ADSP event is not supported for passthrough*/
2712 if ((param_id == AUDIO_EXTN_PARAM_ADSP_STREAM_CMD)
2713 && !(new_out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) continue;
2714 if (new_out->standby)
2715 new_out->stream.write((struct audio_stream_out *)new_out, NULL, 0);
2716 lock_output_stream_l(new_out);
2717 ret = audio_extn_out_set_param_data(new_out, param_id, payload);
2718 if (ret)
2719 ERROR_MSG("audio_extn_out_set_param_data error %d", ret);
2720 unlock_output_stream_l(new_out);
2721 }
2722 return ret;
2723}
2724
2725int audio_extn_qap_out_get_param_data(struct stream_out *out,
2726 audio_extn_param_id param_id,
2727 audio_extn_param_payload *payload)
2728{
2729 int ret = -EINVAL, i;
2730 struct stream_out *new_out = NULL;
2731 struct qap_module *qap_mod = get_qap_module_for_input_stream_l(out);
2732
2733 if (!out || !qap_mod || !payload) {
2734 ERROR_MSG("Invalid Param");
2735 return ret;
2736 }
2737
2738 if (!p_qap->hdmi_connect) {
2739 ERROR_MSG("hdmi not connected");
2740 return ret;
2741 }
2742
2743 /* get session which is routed to hdmi*/
2744 if (p_qap->passthrough_out)
2745 new_out = p_qap->passthrough_out;
2746 else {
2747 for (i = 0; i < MAX_QAP_MODULE_OUT; i++) {
2748 if (qap_mod->stream_out[i]) {
2749 new_out = qap_mod->stream_out[i];
2750 break;
2751 }
2752 }
2753 }
2754
2755 if (!new_out) {
2756 ERROR_MSG("No stream active.");
2757 return ret;
2758 }
2759
2760 if (new_out->standby)
2761 new_out->stream.write((struct audio_stream_out *)new_out, NULL, 0);
2762
2763 lock_output_stream_l(new_out);
2764 ret = audio_extn_out_get_param_data(new_out, param_id, payload);
2765 if (ret)
2766 ERROR_MSG("audio_extn_out_get_param_data error %d", ret);
2767 unlock_output_stream_l(new_out);
2768
2769 return ret;
2770}
2771#endif
2772
2773int audio_extn_qap_open_output_stream(struct audio_hw_device *dev,
2774 audio_io_handle_t handle,
2775 audio_devices_t devices,
2776 audio_output_flags_t flags,
2777 struct audio_config *config,
2778 struct audio_stream_out **stream_out,
2779 const char *address)
2780{
2781 int ret = 0;
2782 struct stream_out *out;
2783
2784 DEBUG_MSG("Entry");
2785 ret = adev_open_output_stream(dev, handle, devices, flags, config, stream_out, address);
2786 if (*stream_out == NULL) {
2787 ERROR_MSG("Stream open failed %d", ret);
2788 return ret;
2789 }
2790
2791#ifndef LINUX_ENABLED
2792//Bypass QAP for dummy PCM session opened by APM during boot time
2793 if(flags == 0) {
2794 ALOGD("bypassing QAP for flags is equal to none");
2795 return ret;
2796 }
2797#endif
2798
2799 out = (struct stream_out *)*stream_out;
2800
2801 DEBUG_MSG("%s 0x%x", use_case_table[out->usecase], (int)out);
2802
2803 ret = qap_stream_open(out, config, flags, devices);
2804 if (ret < 0) {
2805 ERROR_MSG("Error opening QAP stream err[%d]", ret);
2806 //Stream not supported by QAP, Bypass QAP.
2807 return 0;
2808 }
2809
2810 /* Override function pointers based on qap definitions */
2811 out->stream.set_volume = qap_out_set_volume;
2812 out->stream.pause = qap_out_pause;
2813 out->stream.resume = qap_out_resume;
2814 out->stream.drain = qap_out_drain;
2815 out->stream.flush = qap_out_flush;
2816
2817 out->stream.common.standby = qap_out_standby;
2818 out->stream.common.set_parameters = qap_out_set_parameters;
2819 out->stream.get_latency = qap_out_get_latency;
2820 out->stream.get_render_position = qap_out_get_render_position;
2821 out->stream.write = qap_out_write;
2822 out->stream.get_presentation_position = qap_out_get_presentation_position;
2823 out->platform_latency = 0;
2824
2825 /*TODO: Need to handle this for DTS*/
2826 if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY) {
2827 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2828 out->config.period_size = QAP_DEEP_BUFFER_OUTPUT_PERIOD_SIZE;
2829 out->config.period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT;
2830 out->config.start_threshold = QAP_DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4;
2831 out->config.avail_min = QAP_DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4;
2832 } else if(out->flags == AUDIO_OUTPUT_FLAG_DIRECT) {
2833 out->compr_config.fragment_size = qap_get_pcm_offload_input_buffer_size(&(config->offload_info));
2834 }
2835
2836 *stream_out = &out->stream;
2837
2838 DEBUG_MSG("Exit");
2839 return 0;
2840}
2841
2842void audio_extn_qap_close_output_stream(struct audio_hw_device *dev,
2843 struct audio_stream_out *stream)
2844{
2845 struct stream_out *out = (struct stream_out *)stream;
2846 struct qap_module* qap_mod = get_qap_module_for_input_stream_l(out);
2847
2848 DEBUG_MSG("%s 0x%x", use_case_table[out->usecase], (int)out);
2849
2850 if (!qap_mod) {
2851 DEBUG_MSG("qap module is NULL, nothing to close");
2852 /*closing non-MS12/default output stream opened with qap */
2853 adev_close_output_stream(dev, stream);
2854 return;
2855 }
2856
2857 DEBUG_MSG("stream_handle(%p) format = %x", out, out->format);
2858
2859 //If close is received for QAP passthrough stream then close the QAP passthrough output.
2860 if (p_qap->passthrough_in == out) {
2861 if (p_qap->passthrough_out) {
2862 ALOGD("%s %d closing stream handle %p", __func__, __LINE__, p_qap->passthrough_out);
2863 pthread_mutex_lock(&p_qap->lock);
2864 adev_close_output_stream((struct audio_hw_device *)p_qap->adev,
2865 (struct audio_stream_out *)(p_qap->passthrough_out));
2866 pthread_mutex_unlock(&p_qap->lock);
2867 p_qap->passthrough_out = NULL;
2868 }
2869
2870 p_qap->passthrough_in = NULL;
2871 }
2872
2873 qap_stream_close(out);
2874
2875 adev_close_output_stream(dev, stream);
2876
2877 DEBUG_MSG("Exit");
2878}
2879
2880/* Check if QAP is supported or not. */
2881bool audio_extn_qap_is_enabled()
2882{
2883 bool prop_enabled = false;
2884 char value[PROPERTY_VALUE_MAX] = {0};
2885 property_get("vendor.audio.qap.enabled", value, NULL);
2886 prop_enabled = atoi(value) || !strncmp("true", value, 4);
2887 return (prop_enabled);
2888}
2889
2890/* QAP set parameter function. For Device connect and disconnect. */
2891int audio_extn_qap_set_parameters(struct audio_device *adev, struct str_parms *parms)
2892{
2893 int status = 0, val = 0;
2894 qap_session_outputs_config_t *session_outputs_config = NULL;
2895
2896 if (!p_qap) {
2897 return -EINVAL;
2898 }
2899
2900 DEBUG_MSG("Entry");
2901
2902 status = str_parms_get_int(parms, AUDIO_PARAMETER_DEVICE_CONNECT, &val);
2903
2904 if ((status >= 0) && audio_is_output_device(val)) {
2905 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) { //HDMI is connected.
2906 DEBUG_MSG("AUDIO_DEVICE_OUT_AUX_DIGITAL connected");
2907 p_qap->hdmi_connect = 1;
2908 p_qap->hdmi_sink_channels = 0;
2909
2910 if (p_qap->passthrough_in) { //If QAP passthrough is already initialized.
2911 lock_output_stream_l(p_qap->passthrough_in);
2912 if (platform_is_edid_supported_format(adev->platform,
2913 p_qap->passthrough_in->format)) {
2914 //If passthrough format is supported by HDMI then create the QAP passthrough output if not created already.
2915 create_qap_passthrough_stream_l();
2916 //Ignoring the returned error, If error then QAP passthrough is disabled.
2917 } else {
2918 //If passthrough format is not supported by HDMI then close the QAP passthrough output if already created.
2919 close_qap_passthrough_stream_l();
2920 }
2921 unlock_output_stream_l(p_qap->passthrough_in);
2922 }
2923
2924 qap_set_hdmi_configuration_to_module();
2925
2926 } else if (val & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) {
2927 DEBUG_MSG("AUDIO_DEVICE_OUT_BLUETOOTH_A2DP connected");
2928 p_qap->bt_connect = 1;
2929 qap_set_default_configuration_to_module();
2930#ifndef SPLIT_A2DP_ENABLED
2931 for (k = 0; k < MAX_MM_MODULE_TYPE; k++) {
2932 if (!p_qap->qap_mod[k].bt_hdl) {
2933 DEBUG_MSG("Opening a2dp output...");
2934 status = audio_extn_bt_hal_load(&p_qap->qap_mod[k].bt_hdl);
2935 if (status != 0) {
2936 ERROR_MSG("Error opening BT module");
2937 return status;
2938 }
2939 }
2940 }
2941#endif
2942 }
2943 //TODO else if: Need to consider other devices.
2944 }
2945
2946 status = str_parms_get_int(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, &val);
2947 if ((status >= 0) && audio_is_output_device(val)) {
2948 DEBUG_MSG("AUDIO_DEVICE_OUT_AUX_DIGITAL disconnected");
2949 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2950
2951 p_qap->hdmi_sink_channels = 0;
2952
2953 p_qap->passthrough_enabled = 0;
2954 p_qap->mch_pcm_hdmi_enabled = 0;
2955 p_qap->hdmi_connect = 0;
2956
2957 if (p_qap->qap_mod[MS12].session_handle)
2958 session_outputs_config = &p_qap->qap_mod[MS12].session_outputs_config;
2959 else if (p_qap->qap_mod[DTS_M8].session_handle)
2960 session_outputs_config = &p_qap->qap_mod[DTS_M8].session_outputs_config;
2961 else {
2962 DEBUG_MSG("HDMI disconnection comes even before session is setup");
2963 return 0;
2964 }
2965
2966 session_outputs_config->num_output = 1;
2967
2968 session_outputs_config->output_config[0].id = AUDIO_DEVICE_OUT_SPEAKER;
2969 session_outputs_config->output_config[0].format = QAP_AUDIO_FORMAT_PCM_16_BIT;
2970
2971
2972 if (p_qap->qap_mod[MS12].session_handle) {
2973 DEBUG_MSG(" Enabling speaker(PCM out) from MS12 wrapper outputid = %x", session_outputs_config->output_config[0].id);
2974 status = qap_session_cmd(p_qap->qap_mod[MS12].session_handle,
2975 QAP_SESSION_CMD_SET_OUTPUTS,
2976 sizeof(qap_session_outputs_config_t),
2977 session_outputs_config,
2978 NULL,
2979 NULL);
2980 if (QAP_STATUS_OK != status) {
2981 ERROR_MSG("Unable to register AUDIO_DEVICE_OUT_SPEAKER device with QAP %d",status);
2982 return -EINVAL;
2983 }
2984 }
2985 if (p_qap->qap_mod[DTS_M8].session_handle) {
2986 status = qap_session_cmd(p_qap->qap_mod[MS12].session_handle,
2987 QAP_SESSION_CMD_SET_OUTPUTS,
2988 sizeof(qap_session_outputs_config_t),
2989 session_outputs_config,
2990 NULL,
2991 NULL);
2992 if (QAP_STATUS_OK != status) {
2993 ERROR_MSG("Unable to register AUDIO_DEVICE_OUT_SPEAKER device with QAP %d", status);
2994 return -EINVAL;
2995 }
2996 }
2997
2998 close_all_hdmi_output_l();
2999 close_qap_passthrough_stream_l();
3000 } else if (val & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) {
3001 DEBUG_MSG("AUDIO_DEVICE_OUT_BLUETOOTH_A2DP disconnected");
3002 p_qap->bt_connect = 0;
3003 //reconfig HDMI as end device (if connected)
3004 if(p_qap->hdmi_connect)
3005 qap_set_hdmi_configuration_to_module();
3006#ifndef SPLIT_A2DP_ENABLED
3007 DEBUG_MSG("Closing a2dp output...");
3008 for (k = 0; k < MAX_MM_MODULE_TYPE; k++) {
3009 if (p_qap->qap_mod[k].bt_hdl) {
3010 audio_extn_bt_hal_unload(p_qap->qap_mod[k].bt_hdl);
3011 p_qap->qap_mod[k].bt_hdl = NULL;
3012 }
3013 }
3014#endif
3015 }
3016 //TODO else if: Need to consider other devices.
3017 }
3018
3019#if 0
3020 /* does this need to be ported to QAP?*/
3021 for (k = 0; k < MAX_MM_MODULE_TYPE; k++) {
3022 kv_parirs = str_parms_to_str(parms);
3023 if (p_qap->qap_mod[k].session_handle) {
3024 p_qap->qap_mod[k].qap_audio_session_set_param(
3025 p_qap->qap_mod[k].session_handle, kv_parirs);
3026 }
3027 }
3028#endif
3029
3030 DEBUG_MSG("Exit");
3031 return status;
3032}
3033
3034/* Create the QAP. */
3035int audio_extn_qap_init(struct audio_device *adev)
3036{
3037 DEBUG_MSG("Entry");
3038
3039 p_qap = calloc(1, sizeof(struct qap));
3040 if (p_qap == NULL) {
3041 ERROR_MSG("Out of memory");
3042 return -ENOMEM;
3043 }
3044
3045 p_qap->adev = adev;
3046
3047 if (property_get_bool("vendor.audio.qap.msmd", false)) {
3048 DEBUG_MSG("MSMD enabled.");
3049 p_qap->qap_msmd_enabled = 1;
3050 }
3051
3052 if (property_get_bool("vendor.audio.qap.output.block.handling", false)) {
3053 DEBUG_MSG("out put thread blocking handling enabled.");
3054 p_qap->qap_output_block_handling = 1;
3055 }
3056 pthread_mutex_init(&p_qap->lock, (const pthread_mutexattr_t *) NULL);
3057
3058 int i = 0;
3059
3060 for (i = 0; i < MAX_MM_MODULE_TYPE; i++) {
3061 char value[PROPERTY_VALUE_MAX] = {0};
3062 char lib_name[PROPERTY_VALUE_MAX] = {0};
3063 struct qap_module *qap_mod = &(p_qap->qap_mod[i]);
3064
3065 if (i == MS12) {
3066 property_get("vendor.audio.qap.library", value, NULL);
3067 snprintf(lib_name, PROPERTY_VALUE_MAX, "%s", value);
3068
3069 DEBUG_MSG("Opening Ms12 library at %s", lib_name);
3070 qap_mod->qap_lib = ( void *) qap_load_library(lib_name);
3071 if (qap_mod->qap_lib == NULL) {
3072 ERROR_MSG("qap load lib failed for MS12 %s", lib_name);
3073 continue;
3074 }
3075 DEBUG_MSG("Loaded QAP lib at %s", lib_name);
3076 pthread_mutex_init(&qap_mod->session_output_lock, (const pthread_mutexattr_t *) NULL);
3077 pthread_cond_init(&qap_mod->session_output_cond, (const pthread_condattr_t *)NULL);
3078 } else if (i == DTS_M8) {
3079 property_get("vendor.audio.qap.m8.library", value, NULL);
3080 snprintf(lib_name, PROPERTY_VALUE_MAX, "%s", value);
3081 qap_mod->qap_lib = dlopen(lib_name, RTLD_NOW);
3082 if (qap_mod->qap_lib == NULL) {
3083 ERROR_MSG("DLOPEN failed for DTS M8 %s", lib_name);
3084 continue;
3085 }
3086 DEBUG_MSG("DLOPEN successful for %s", lib_name);
3087 pthread_mutex_init(&qap_mod->session_output_lock, (const pthread_mutexattr_t *) NULL);
3088 pthread_cond_init(&qap_mod->session_output_cond, (const pthread_condattr_t *)NULL);
3089 } else {
3090 continue;
3091 }
3092 }
3093
3094 DEBUG_MSG("Exit");
3095 return 0;
3096}
3097
3098/* Tear down the qap extension. */
3099void audio_extn_qap_deinit()
3100{
3101 int i;
3102 DEBUG_MSG("Entry");
3103 char value[PROPERTY_VALUE_MAX] = {0};
3104 char lib_name[PROPERTY_VALUE_MAX] = {0};
3105
3106 if (p_qap != NULL) {
3107 for (i = 0; i < MAX_MM_MODULE_TYPE; i++) {
3108 if (p_qap->qap_mod[i].session_handle != NULL)
3109 qap_sess_close(&p_qap->qap_mod[i]);
3110
3111 if (p_qap->qap_mod[i].qap_lib != NULL) {
3112 if (i == MS12) {
3113 property_get("vendor.audio.qap.library", value, NULL);
3114 snprintf(lib_name, PROPERTY_VALUE_MAX, "%s", value);
3115 DEBUG_MSG("lib_name %s", lib_name);
3116 if (QAP_STATUS_OK != qap_unload_library(p_qap->qap_mod[i].qap_lib))
3117 ERROR_MSG("Failed to unload MS12 library lib name %s", lib_name);
3118 else
3119 DEBUG_MSG("closed/unloaded QAP lib at %s", lib_name);
3120 p_qap->qap_mod[i].qap_lib = NULL;
3121 } else {
3122 dlclose(p_qap->qap_mod[i].qap_lib);
3123 p_qap->qap_mod[i].qap_lib = NULL;
3124 }
3125 pthread_mutex_destroy(&p_qap->qap_mod[i].session_output_lock);
3126 pthread_cond_destroy(&p_qap->qap_mod[i].session_output_cond);
3127 }
3128 }
3129
3130 if (p_qap->passthrough_out) {
3131 adev_close_output_stream((struct audio_hw_device *)p_qap->adev,
3132 (struct audio_stream_out *)(p_qap->passthrough_out));
3133 p_qap->passthrough_out = NULL;
3134 }
3135
3136 pthread_mutex_destroy(&p_qap->lock);
3137 free(p_qap);
3138 p_qap = NULL;
3139 }
3140 DEBUG_MSG("Exit");
3141}