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