blob: 32af216b55471e2a8c9a66ee9aa98e910c09373f [file] [log] [blame]
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301/*
2 * Copyright (c) 2016, 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_qaf"
31/*#define LOG_NDEBUG 0*/
32/*#define VERY_VERY_VERBOSE_LOGGING*/
33#ifdef VERY_VERY_VERBOSE_LOGGING
34#define ALOGVV ALOGV
35#else
36#define ALOGVV(a...) do { } while(0)
37#endif
38
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +053039#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 2
40#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (2 * 1024)
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053041#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
42#define QAF_DEFAULT_COMPR_AUDIO_HANDLE 1001
43#define QAF_DEFAULT_COMPR_PASSTHROUGH_HANDLE 1002
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +053044#define QAF_DEFAULT_PASSTHROUGH_HANDLE 1003
45/*
46 * MS12 Latency (Input Buffer Processing latency)+
47 * Kernel Latency (Calculated based on the available offload buffer size) +
48 * DSP Latency (Calculated based on the Platform render latency)
49*/
50#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 300
51#define PCM_OFFLOAD_PLAYBACK_LATENCY 248
52
53/*
54 * Buffer size for compress passthrough is 8192 bytes
55 */
56#define COMPRESS_PASSTHROUGH_BUFFER_SIZE \
57 (COMPRESS_OFFLOAD_NUM_FRAGMENTS * COMPRESS_OFFLOAD_FRAGMENT_SIZE)
58/*
59 * Frame size for DD/DDP is 1536 samples corresponding to 32ms.
60 */
61#define DD_FRAME_SIZE 1536
62/*
63 * DD encoder output size for 32ms.
64 */
65#define DD_ENCODER_OUTPUT_SIZE 2560
66/*
67 * DDP encoder output size for 32ms.
68 */
69#define DDP_ENCODER_OUTPUT_SIZE 4608
70
71/*
72 * Frame size for DD/DDP is 1536 samples.
73 * For a bit rate of 640 bps, DD encoder output size is 2560 bytes of
74 * 32ms;
75 * DDP encoder output size is 4608 bytes of 32 ms.
76 * Kernel buffer buffer allocation for compress passthrough is
77 * 2 x 2048 bytes = 4096 bytes
78 * The Latency for DD (measured in samples) is calculated as:
79 * Time taken to play 8192 bytes (for DD) = 4096 x 32/2560 = 51.2ms
80 * Samples for 51.2ms = 51.2 x 1536/32 = 2457 samples.
81 * Latency calculated similarly for DPP is 1365 samples.
82 */
83#define TRANSCODE_LATENCY(buffer_size, frame_size, encoder_output_in_bytes) ((buffer_size * frame_size) / encoder_output_in_bytes)
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053084
Bharath Gopal01310bb2016-12-05 15:39:32 +053085/*
86 * QAF Latency to process buffers since out_write from primary HAL
87 */
88#define QAF_COMPRESS_OFFLOAD_PROCESSING_LATENCY 18
89#define QAF_PCM_OFFLOAD_PROCESSING_LATENCY 48
90
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053091#include <stdlib.h>
92#include <pthread.h>
93#include <errno.h>
94#include <dlfcn.h>
95#include <sys/resource.h>
96#include <sys/prctl.h>
97#include <cutils/properties.h>
98#include <cutils/str_parms.h>
99#include <cutils/log.h>
100#include <cutils/atomic.h>
101#include "audio_utils/primitives.h"
102#include "audio_hw.h"
103#include "platform_api.h"
104#include <platform.h>
105#include <system/thread_defs.h>
106#include <cutils/sched_policy.h>
107#include "audio_extn.h"
108#include <qti_audio.h>
109#include "sound/compress_params.h"
110
111#define QAF_OUTPUT_SAMPLING_RATE 48000
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530112#define PCM_OFFLOAD_BUFFER_SIZE 7680
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530113
114#ifdef QAF_DUMP_ENABLED
115FILE *fp_output_writer_hdmi = NULL;
116#endif
117
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530118struct qaf {
119 struct audio_device *adev;
120 audio_session_handle_t session_handle;
121 void *qaf_lib;
122 int (*qaf_audio_session_open)(audio_session_handle_t* session_handle, void *p_data, void* license_data);
123 int (*qaf_audio_session_close)(audio_session_handle_t session_handle);
124 int (*qaf_audio_stream_open)(audio_session_handle_t session_handle, audio_stream_handle_t* stream_handle,
125 audio_stream_config_t input_config, audio_devices_t devices, stream_type_t flags);
126 int (*qaf_audio_stream_close)(audio_stream_handle_t stream_handle);
127 int (*qaf_audio_stream_set_param)(audio_stream_handle_t stream_handle, const char* kv_pairs);
128 int (*qaf_audio_session_set_param)(audio_session_handle_t handle, const char* kv_pairs);
129 char* (*qaf_audio_stream_get_param)(audio_stream_handle_t stream_handle, const char* key);
130 char* (*qaf_audio_session_get_param)(audio_session_handle_t handle, const char* key);
131 int (*qaf_audio_stream_start)(audio_stream_handle_t handle);
132 int (*qaf_audio_stream_stop)(audio_stream_handle_t stream_handle);
133 int (*qaf_audio_stream_pause)(audio_stream_handle_t stream_handle);
134 int (*qaf_audio_stream_flush)(audio_stream_handle_t stream_handle);
135 int (*qaf_audio_stream_write)(audio_stream_handle_t stream_handle, const void* buf, int size);
136 void (*qaf_register_event_callback)(audio_session_handle_t session_handle, void *priv_data,
137 notify_event_callback_t event_callback, audio_event_id_t event_id);
138 pthread_mutex_t lock;
139 struct stream_out *stream_drain_main;
140 struct stream_out *qaf_compr_offload_out;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530141 struct stream_out *qaf_compr_offload_out_mch;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530142 struct stream_out *qaf_compr_passthrough_out;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530143 struct stream_out *qaf_passthrough_out;
Bharath Gopal01310bb2016-12-05 15:39:32 +0530144 void *bt_hdl;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530145 bool hdmi_connect;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530146 int passthrough_enabled;
147 int hdmi_sink_channels;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530148 bool main_output_active;
149 bool assoc_output_active;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530150 bool qaf_msmd_enabled;
Deepak Agarwal1e42b852017-02-11 17:57:04 +0530151 float vol_left;
152 float vol_right;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530153};
154
155static struct qaf *qaf_mod = NULL;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530156static int qaf_stream_set_param(struct stream_out *out, const char *kv_pair) __attribute__ ((unused));
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530157
Deepak Agarwal1e42b852017-02-11 17:57:04 +0530158static bool is_ms12_format(audio_format_t format)
159{
160 if((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AC3)
161 return true;
162 if((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_E_AC3)
163 return true;
164 if((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
165 return true;
166 if((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
167 return true;
168 if(format == AUDIO_FORMAT_PCM_16_BIT)
169 return true;
170
171 return false;
172}
173
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530174static void lock_output_stream(struct stream_out *out)
175{
176 pthread_mutex_lock(&out->pre_lock);
177 pthread_mutex_lock(&out->lock);
178 pthread_mutex_unlock(&out->pre_lock);
179}
180
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530181static bool audio_extn_qaf_passthrough_enabled(struct stream_out *out)
182{
183 ALOGV("%s %d ", __func__, __LINE__);
184 if ((!property_get_bool("audio.qaf.reencode", false)) &&
185 property_get_bool("audio.qaf.passthrough", false)) {
186 if (property_get_bool("audio.offload.passthrough", false)) {
187 if (((out->format == AUDIO_FORMAT_AC3) && platform_is_edid_supported_format(qaf_mod->adev->platform, AUDIO_FORMAT_AC3)) ||
188 ((out->format == AUDIO_FORMAT_E_AC3) && platform_is_edid_supported_format(qaf_mod->adev->platform, AUDIO_FORMAT_E_AC3)) ||
189 ((out->format == AUDIO_FORMAT_DTS) && platform_is_edid_supported_format(qaf_mod->adev->platform, AUDIO_FORMAT_DTS)) ||
190 ((out->format == AUDIO_FORMAT_DTS_HD) && platform_is_edid_supported_format(qaf_mod->adev->platform, AUDIO_FORMAT_DTS_HD))) {
191 return true;
192 }
193 } else {
194 if ((out->format == AUDIO_FORMAT_PCM_16_BIT) && (popcount(out->channel_mask) > 2)) {
195 return true;
196 }
197 }
198 }
199 return false;
200}
201
202static int qaf_out_callback(stream_callback_event_t event, void *param __unused, void *cookie)
203{
204 struct stream_out *out = (struct stream_out *)cookie;
205
206 out->offload_callback(event, NULL, out->offload_cookie);
207 return 0;
208}
209
210static int create_output_stream(struct stream_out *out, struct audio_config *config, audio_output_flags_t flags, audio_devices_t devices, int handle_id)
211{
212 int ret = 0;
213
214 ALOGV("%s %d", __func__, __LINE__);
215 if ((handle_id == QAF_DEFAULT_PASSTHROUGH_HANDLE) &&
216 (NULL == qaf_mod->qaf_passthrough_out)) {
217 pthread_mutex_lock(&qaf_mod->lock);
218 lock_output_stream(out);
219 ret = adev_open_output_stream((struct audio_hw_device *) qaf_mod->adev, handle_id, devices,
220 flags, config, (struct audio_stream_out **) &(qaf_mod->qaf_passthrough_out), NULL);
221 if (ret < 0) {
222 pthread_mutex_unlock(&out->lock);
223 pthread_mutex_unlock(&qaf_mod->lock);
224 ALOGE("%s: adev_open_output_stream failed with ret = %d!", __func__, ret);
225 return -EINVAL;
226 }
227 qaf_mod->qaf_passthrough_out->stream.set_callback((struct audio_stream_out *)qaf_mod->qaf_passthrough_out, (stream_callback_t) qaf_out_callback, out);
228 pthread_mutex_unlock(&out->lock);
229 pthread_mutex_unlock(&qaf_mod->lock);
230 }
231 return ret;
232}
233
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530234static int qaf_send_offload_cmd_l(struct stream_out* out, int command)
235{
236 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
237
238 if (!cmd) {
239 ALOGE("failed to allocate mem for command 0x%x", command);
240 return -ENOMEM;
241 }
242
243 ALOGV("%s %d", __func__, command);
244
245 cmd->cmd = command;
246 list_add_tail(&out->qaf_offload_cmd_list, &cmd->node);
247 pthread_cond_signal(&out->qaf_offload_cond);
248 return 0;
249}
250
251static int audio_extn_qaf_stream_stop(struct stream_out *out)
252{
253 ALOGV("%s: %d start", __func__, __LINE__);
254 if (!qaf_mod->qaf_audio_stream_stop)
255 return -EINVAL;
256
257 return qaf_mod->qaf_audio_stream_stop(out->qaf_stream_handle);
258}
259
260static int qaf_out_standby(struct audio_stream *stream)
261{
262 struct stream_out *out = (struct stream_out *)stream;
263 int status = 0;
264
265 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
266 stream, out->usecase, use_case_table[out->usecase]);
267
268 lock_output_stream(out);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530269 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
270 if ((out->format == AUDIO_FORMAT_PCM_16_BIT) && (popcount(out->channel_mask) <= 2)) {
271 pthread_mutex_unlock(&out->lock);
272 return status;
273 }
274 status = qaf_mod->qaf_passthrough_out->stream.common.standby((struct audio_stream *) qaf_mod->qaf_passthrough_out);
275 if (!out->standby) {
276 out->standby = true;
277 }
278 pthread_mutex_unlock(&out->lock);
279 return status;
280 }
281
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530282 if (!out->standby) {
283 out->standby = true;
284 status = audio_extn_qaf_stream_stop(out);
285 }
286 pthread_mutex_unlock(&out->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530287 return status;
288}
289
290static int qaf_stream_set_param(struct stream_out *out, const char *kv_pair)
291{
292 ALOGV("%s %d kvpair: %s", __func__, __LINE__, kv_pair);
293 if (!qaf_mod->qaf_audio_stream_set_param)
294 return -EINVAL;
295
296 return qaf_mod->qaf_audio_stream_set_param(out->qaf_stream_handle, kv_pair);
297}
298
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530299static int qaf_write_input_buffer(struct stream_out *out, const void *buffer, int bytes)
300{
301 int ret = 0;
302 ALOGVV("%s bytes = %d [%p]", __func__, bytes, out->qaf_stream_handle);
303 if (!qaf_mod->qaf_audio_stream_write)
304 return -EINVAL;
305
306 if (out->qaf_stream_handle)
307 ret = qaf_mod->qaf_audio_stream_write(out->qaf_stream_handle, buffer, bytes);
308 return ret;
309}
310
311static int qaf_out_set_volume(struct audio_stream_out *stream __unused, float left,
312 float right)
313{
Deepak Agarwal1e42b852017-02-11 17:57:04 +0530314 /* For ms12 formats, qaf_mod->qaf_compr_offload_out is allocated during the first
315 * call of notify_event_callback(). Therefore, the volume levels set during session
316 * open have to be cached and applied later */
317 qaf_mod->vol_left = left;
318 qaf_mod->vol_right = right;
319
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530320 if (qaf_mod->qaf_compr_offload_out != NULL) {
321 return qaf_mod->qaf_compr_offload_out->stream.set_volume(
322 (struct audio_stream_out *)qaf_mod->qaf_compr_offload_out, left, right);
323 }
324 return -ENOSYS;
325}
326
327static int qaf_stream_start(struct stream_out *out)
328{
329 if (!qaf_mod->qaf_audio_stream_start)
330 return -EINVAL;
331
332 return qaf_mod->qaf_audio_stream_start(out->qaf_stream_handle);
333}
334
335static int qaf_start_output_stream(struct stream_out *out)
336{
337 int ret = 0;
338 struct audio_device *adev = out->dev;
339 int snd_card_status = get_snd_card_state(adev);
340
341 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
342 ret = -EINVAL;
343 usleep(50000);
344 return ret;
345 }
346
347 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
348 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
349 out->devices);
350
351 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
352 ALOGE("%s: sound card is not active/SSR returning error", __func__);
353 ret = -EIO;
354 usleep(50000);
355 return ret;
356 }
357
358 return qaf_stream_start(out);
359}
360
361static ssize_t qaf_out_write(struct audio_stream_out *stream, const void *buffer,
362 size_t bytes)
363{
364 struct stream_out *out = (struct stream_out *)stream;
365 struct audio_device *adev = out->dev;
366 ssize_t ret = 0;
367
368 ALOGV("qaf_out_write bytes = %d, usecase[%d] and flags[%x] for handle[%p]",(int)bytes, out->usecase, out->flags, out);
369 lock_output_stream(out);
370
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530371 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
372 if ((out->format == AUDIO_FORMAT_PCM_16_BIT) && (popcount(out->channel_mask) <= 2)) {
373 ALOGD(" %s : Drop data as compress passthrough session is going on", __func__);
374 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
375 out->stream.common.get_sample_rate(&out->stream.common));
376 goto exit;
377 }
378 ret = qaf_mod->qaf_passthrough_out->stream.write((struct audio_stream_out *)(qaf_mod->qaf_passthrough_out), buffer, bytes);
379 pthread_mutex_unlock(&out->lock);
380 return ret;
381 }
382
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530383 if (out->standby) {
384 out->standby = false;
385 pthread_mutex_lock(&adev->lock);
386 ret = qaf_start_output_stream(out);
387 pthread_mutex_unlock(&adev->lock);
388 /* ToDo: If use case is compress offload should return 0 */
389 if (ret != 0) {
390 out->standby = true;
391 goto exit;
392 }
393 }
394
395 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
396 audio_utils_set_hdmi_channel_status(out, (char *)buffer, bytes);
397 adev->is_channel_status_set = true;
398 }
399
400 ret = qaf_write_input_buffer(out, buffer, bytes);
401 ALOGV("%s, ret [%d] ", __func__, (int)ret);
402 if (ret < 0) {
403 goto exit;
404 }
405 out->written += bytes / ((popcount(out->channel_mask) * sizeof(short)));
406
407exit:
408
409 pthread_mutex_unlock(&out->lock);
410
411 if (ret < 0) {
412 if (ret == -EAGAIN) {
413 ALOGV("No space available in ms12 driver, post msg to cb thread");
414 lock_output_stream(out);
415 ret = qaf_send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
416 pthread_mutex_unlock(&out->lock);
417 bytes = 0;
418 }
419 if(ret == -ENOMEM || ret == -EPERM){
420 if (out->pcm)
421 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
422 qaf_out_standby(&out->stream.common);
423 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
424 out->stream.common.get_sample_rate(&out->stream.common));
425 }
426 }
427 return bytes;
428}
429
430static int qaf_get_timestamp(struct stream_out *out, uint64_t *frames, struct timespec *timestamp)
431{
432 int ret = 0;
433 struct str_parms *parms;
434 int value = 0;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530435 int latency = 0;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530436 int signed_frames = 0;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530437 char* kvpairs = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530438
439 ALOGV("%s out->format %d", __func__, out->format);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530440 kvpairs = qaf_mod->qaf_audio_stream_get_param(out->qaf_stream_handle, "get_latency");
441 if (kvpairs) {
442 parms = str_parms_create_str(kvpairs);
443 ret = str_parms_get_int(parms, "get_latency", &latency);
444 if (ret >= 0) {
445 str_parms_destroy(parms);
446 parms = NULL;
447 }
448 free(kvpairs);
449 kvpairs = NULL;
450 }
451 // MS12 Latency + Kernel Latency + Dsp Latency
452 if (qaf_mod->qaf_compr_offload_out != NULL) {
453 out->platform_latency = latency + (COMPRESS_OFFLOAD_NUM_FRAGMENTS * PCM_OFFLOAD_BUFFER_SIZE \
454 /(popcount(qaf_mod->qaf_compr_offload_out->channel_mask) * sizeof(short))) \
455 +((platform_render_latency(qaf_mod->qaf_compr_offload_out->usecase) * qaf_mod->qaf_compr_offload_out->sample_rate) / 1000000LL);
Bharath Gopal01310bb2016-12-05 15:39:32 +0530456 } else if (audio_extn_bt_hal_get_output_stream(qaf_mod->bt_hdl) != NULL) {
457 out->platform_latency = latency + audio_extn_bt_hal_get_latency(qaf_mod->bt_hdl);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530458 } else if (NULL != qaf_mod->qaf_compr_passthrough_out) {
459 out->platform_latency = latency + ((qaf_mod->qaf_compr_passthrough_out->format == AUDIO_FORMAT_AC3) ? TRANSCODE_LATENCY(COMPRESS_PASSTHROUGH_BUFFER_SIZE, DD_FRAME_SIZE, DD_ENCODER_OUTPUT_SIZE) : TRANSCODE_LATENCY(COMPRESS_PASSTHROUGH_BUFFER_SIZE, DD_FRAME_SIZE, DDP_ENCODER_OUTPUT_SIZE)) \
460 + (COMPRESS_OFFLOAD_PLAYBACK_LATENCY * qaf_mod->qaf_compr_passthrough_out->sample_rate/1000);
461 }
462
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530463 if(out->format & AUDIO_FORMAT_PCM_16_BIT) {
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530464 *frames = 0;
465 signed_frames = out->written - out->platform_latency;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530466 // It would be unusual for this value to be negative, but check just in case ...
467 if (signed_frames >= 0) {
468 *frames = signed_frames;
469 }
470 clock_gettime(CLOCK_MONOTONIC, timestamp);
471 } else if (qaf_mod->qaf_audio_stream_get_param) {
472 kvpairs = qaf_mod->qaf_audio_stream_get_param(out->qaf_stream_handle, "position");
473 if (kvpairs) {
474 parms = str_parms_create_str(kvpairs);
475 ret = str_parms_get_int(parms, "position", &value);
476 if (ret >= 0) {
477 *frames = value;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530478 signed_frames = value - out->platform_latency;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530479 // It would be unusual for this value to be negative, but check just in case ...
480 if (signed_frames >= 0) {
481 *frames = signed_frames;
482 }
483 clock_gettime(CLOCK_MONOTONIC, timestamp);
484 }
485 str_parms_destroy(parms);
486 }
487 } else {
488 ret = -EINVAL;
489 }
490 return ret;
491}
492
493static int qaf_out_get_presentation_position(const struct audio_stream_out *stream,
494 uint64_t *frames, struct timespec *timestamp)
495{
496 struct stream_out *out = (struct stream_out *)stream;
497 int ret = -1;
498 lock_output_stream(out);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530499
500 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
501 ret = qaf_mod->qaf_passthrough_out->stream.get_presentation_position((struct audio_stream_out *)qaf_mod->qaf_passthrough_out, frames, timestamp);
502 pthread_mutex_unlock(&out->lock);
503 return ret;
504 }
505
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530506 ret = qaf_get_timestamp(out, frames, timestamp);
507 pthread_mutex_unlock(&out->lock);
508
509 return ret;
510}
511
512static int qaf_stream_pause(struct stream_out *out)
513{
514 ALOGV("%s: %d start", __func__, __LINE__);
515 if (!qaf_mod->qaf_audio_stream_pause)
516 return -EINVAL;
517
518 return qaf_mod->qaf_audio_stream_pause(out->qaf_stream_handle);
519}
520
521static int qaf_out_pause(struct audio_stream_out* stream)
522{
523 struct stream_out *out = (struct stream_out *)stream;
524 int status = -ENOSYS;
525 ALOGE("%s", __func__);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530526
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530527 lock_output_stream(out);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530528 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
529 status = qaf_mod->qaf_passthrough_out->stream.pause((struct audio_stream_out *) qaf_mod->qaf_passthrough_out);
530 out->offload_state = OFFLOAD_STATE_PAUSED;
531 pthread_mutex_unlock(&out->lock);
532 return status;
533 }
534
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530535 status = qaf_stream_pause(out);
536 pthread_mutex_unlock(&out->lock);
537 return status;
538}
539
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530540static int qaf_out_drain(struct audio_stream_out* stream, audio_drain_type_t type)
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530541{
542 struct stream_out *out = (struct stream_out *)stream;
543 int status = 0;
544 ALOGV("%s stream_handle = %p , format = %x", __func__, out->qaf_stream_handle, out->format);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530545
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530546 lock_output_stream(out);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530547 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
548 status = qaf_mod->qaf_passthrough_out->stream.drain((struct audio_stream_out*)(qaf_mod->qaf_passthrough_out), type);
549 pthread_mutex_unlock(&out->lock);
550 return status;
551 }
552
553
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530554 if (out->offload_callback && out->qaf_stream_handle) {
555 /* Stream stop will trigger EOS and on EOS_EVENT received
556 from callback DRAIN_READY command is sent */
557 status = audio_extn_qaf_stream_stop(out);
558 if (out->format != AUDIO_FORMAT_PCM_16_BIT)
559 qaf_mod->stream_drain_main = out;
560 }
561 pthread_mutex_unlock(&out->lock);
562 return status;
563}
564
565static int audio_extn_qaf_stream_flush(struct stream_out *out)
566{
567 ALOGV("%s: %d exit", __func__, __LINE__);
568 if (!qaf_mod->qaf_audio_stream_flush)
569 return -EINVAL;
570
571 return qaf_mod->qaf_audio_stream_flush(out->qaf_stream_handle);
572}
573
574static int qaf_out_flush(struct audio_stream_out* stream)
575{
576 struct stream_out *out = (struct stream_out *)stream;
577 ALOGV("%s", __func__);
578 int status = -ENOSYS;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530579
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530580 lock_output_stream(out);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530581 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
582 status = qaf_mod->qaf_passthrough_out->stream.flush((struct audio_stream_out *)qaf_mod->qaf_passthrough_out);
583 out->offload_state = OFFLOAD_STATE_IDLE;
584 pthread_mutex_unlock(&out->lock);
585 return status;
586 }
587
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530588 status = audio_extn_qaf_stream_flush(out);
589 pthread_mutex_unlock(&out->lock);
590 ALOGV("%s Exit", __func__);
591 return status;
592}
593
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530594static uint32_t qaf_out_get_latency(const struct audio_stream_out *stream)
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530595{
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530596 struct stream_out *out = (struct stream_out *)stream;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530597 uint32_t latency = 0;
598
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530599
600 lock_output_stream(out);
601 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
602 latency = qaf_mod->qaf_passthrough_out->stream.get_latency((struct audio_stream_out *)qaf_mod->qaf_passthrough_out);
603 ALOGV("%s: latency = %u", __FUNCTION__, latency);
604 pthread_mutex_unlock(&out->lock);
605 return latency;
606 }
607 pthread_mutex_unlock(&out->lock);
608
609 if (is_offload_usecase(out->usecase)) {
610 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
611 } else {
612 latency = PCM_OFFLOAD_PLAYBACK_LATENCY;
613 }
Bharath Gopal01310bb2016-12-05 15:39:32 +0530614
615 if (audio_extn_bt_hal_get_output_stream(qaf_mod->bt_hdl) != NULL) {
616
617 if (is_offload_usecase(out->usecase)) {
618 latency = audio_extn_bt_hal_get_latency(qaf_mod->bt_hdl) + QAF_COMPRESS_OFFLOAD_PROCESSING_LATENCY;
619 } else {
620 latency = audio_extn_bt_hal_get_latency(qaf_mod->bt_hdl) + QAF_PCM_OFFLOAD_PROCESSING_LATENCY;
621 }
622 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530623 ALOGV("%s: Latency %d", __func__, latency);
624 return latency;
625}
626
627static void notify_event_callback(audio_session_handle_t session_handle __unused, void *prv_data, void *buf, audio_event_id_t event_id, int size, int device)
628{
629
630/*
631 For SPKR:
632 1. Open pcm device if device_id passed to it SPKR and write the data to pcm device
633
634 For HDMI
635 1.Open compress device for HDMI(PCM or AC3) based on current_hdmi_output_format
636 2.create offload_callback thread to receive async events
637 3.Write the data to compress device. If not all the data is consumed by the driver,
638 add a command to offload_callback thread.
639*/
640 int ret;
641 audio_output_flags_t flags;
642 struct qaf* qaf_module = (struct qaf* ) prv_data;
Bharath Gopal01310bb2016-12-05 15:39:32 +0530643 struct audio_stream_out *bt_stream = NULL;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530644
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530645 ALOGV("%s device 0x%X, %d in event = %d", __func__, device, __LINE__, event_id);
646
647 if (event_id == AUDIO_DATA_EVENT) {
648 ALOGVV("Device id %x %s %d, bytes to written %d", device, __func__,__LINE__, size);
649
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530650 if ((qaf_mod->qaf_passthrough_out != NULL) && qaf_mod->hdmi_connect) {
651 pthread_mutex_lock(&qaf_module->lock);
652 if (qaf_mod->qaf_compr_offload_out != NULL) {
653 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev,
654 (struct audio_stream_out *) (qaf_mod->qaf_compr_offload_out));
655 qaf_mod->qaf_compr_offload_out = NULL;
656 }
657 if (qaf_mod->qaf_compr_offload_out_mch) {
658 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev,
659 (struct audio_stream_out *) (qaf_mod->qaf_compr_offload_out_mch));
660 qaf_mod->qaf_compr_offload_out_mch = NULL;
661 }
662 pthread_mutex_unlock(&qaf_module->lock);
663 ALOGV("%s %d DROPPING DATA", __func__, __LINE__);
664 return;
665 } else {
666 if (qaf_mod->qaf_passthrough_out != NULL) {
667 pthread_mutex_lock(&qaf_module->lock);
668 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev,
669 (struct audio_stream_out *) (qaf_mod->qaf_passthrough_out));
670 qaf_mod->qaf_passthrough_out = NULL;
671 qaf_mod->main_output_active = false;
672 pthread_mutex_unlock(&qaf_module->lock);
673 }
674 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530675 pthread_mutex_lock(&qaf_module->lock);
676 if ((device == (AUDIO_DEVICE_OUT_AUX_DIGITAL | AUDIO_COMPRESSED_OUT_DD)) ||
677 (device == (AUDIO_DEVICE_OUT_AUX_DIGITAL | AUDIO_COMPRESSED_OUT_DDP))) {
678
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530679 if (NULL == qaf_mod->qaf_compr_passthrough_out && qaf_mod->hdmi_connect) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530680 struct audio_config config;
681 audio_devices_t devices;
682
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530683 if (qaf_mod->qaf_compr_offload_out_mch) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530684 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev,
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530685 (struct audio_stream_out *) (qaf_mod->qaf_compr_offload_out_mch));
686 qaf_mod->qaf_compr_offload_out_mch = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530687 }
688
689 config.sample_rate = config.offload_info.sample_rate = QAF_OUTPUT_SAMPLING_RATE;
690 config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
691 config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
692
693 if (device == (AUDIO_DEVICE_OUT_AUX_DIGITAL | AUDIO_COMPRESSED_OUT_DDP))
694 config.format = config.offload_info.format = AUDIO_FORMAT_E_AC3;
695 else
696 config.format = config.offload_info.format = AUDIO_FORMAT_AC3;
697
698 config.offload_info.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
699 config.offload_info.channel_mask = config.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530700 flags = AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_DIRECT_PCM;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530701 devices = AUDIO_DEVICE_OUT_AUX_DIGITAL;
702
703 ret = adev_open_output_stream((struct audio_hw_device *) qaf_mod->adev, QAF_DEFAULT_COMPR_PASSTHROUGH_HANDLE, devices,
704 flags, &config, (struct audio_stream_out **) &(qaf_mod->qaf_compr_passthrough_out), NULL);
705 if (ret < 0) {
706 ALOGE("%s: adev_open_output_stream failed with ret = %d!", __func__, ret);
707 pthread_mutex_unlock(&qaf_module->lock);
708 return;
709 }
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530710 qaf_mod->qaf_compr_passthrough_out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530711 }
712
713 if (!qaf_mod->passthrough_enabled)
714 qaf_mod->passthrough_enabled = 1;
715
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530716 if (qaf_mod->qaf_compr_passthrough_out)
717 ret = qaf_mod->qaf_compr_passthrough_out->stream.write((struct audio_stream_out *) qaf_mod->qaf_compr_passthrough_out, buf, size);
718 } else if ((device & AUDIO_DEVICE_OUT_AUX_DIGITAL) && ((qaf_mod->hdmi_connect) &&
719 (qaf_mod->qaf_passthrough_out == NULL) && (qaf_mod->hdmi_sink_channels > 2))) {
720 if (NULL == qaf_mod->qaf_compr_offload_out_mch) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530721 struct audio_config config;
722 audio_devices_t devices;
723
724 config.sample_rate = config.offload_info.sample_rate = QAF_OUTPUT_SAMPLING_RATE;
725 config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
726 config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530727 config.offload_info.format = AUDIO_FORMAT_PCM_16_BIT;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530728 config.offload_info.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530729 config.format = AUDIO_FORMAT_PCM_16_BIT;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530730 devices = AUDIO_DEVICE_NONE;
731
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530732 if (qaf_mod->hdmi_sink_channels == 8) {
733 config.offload_info.channel_mask = config.channel_mask = AUDIO_CHANNEL_OUT_7POINT1;
734 } else if (qaf_mod->hdmi_sink_channels == 6) {
735 config.offload_info.channel_mask = config.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530736 } else {
737 config.offload_info.channel_mask = config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530738 }
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530739 devices = AUDIO_DEVICE_OUT_AUX_DIGITAL;
740 flags = AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_DIRECT_PCM;
741
742 ret = adev_open_output_stream((struct audio_hw_device *) qaf_mod->adev, QAF_DEFAULT_COMPR_AUDIO_HANDLE, devices,
743 flags, &config, (struct audio_stream_out **) &(qaf_mod->qaf_compr_offload_out_mch), NULL);
744 if (ret < 0) {
745 ALOGE("%s: adev_open_output_stream failed with ret = %d!", __func__, ret);
746 pthread_mutex_unlock(&qaf_module->lock);
747 return;
748 }
749 qaf_mod->qaf_compr_offload_out_mch->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
750 }
751
752 if (qaf_mod->qaf_compr_offload_out_mch)
753 ret = qaf_mod->qaf_compr_offload_out_mch->stream.write((struct audio_stream_out *) qaf_mod->qaf_compr_offload_out_mch, buf, size);
754 } else {
Bharath Gopal01310bb2016-12-05 15:39:32 +0530755 bt_stream = audio_extn_bt_hal_get_output_stream(qaf_mod->bt_hdl);
756 if (bt_stream != NULL) {
757 if (qaf_mod->qaf_compr_offload_out) {
758 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev,
759 (struct audio_stream_out *) (qaf_mod->qaf_compr_offload_out));
760 qaf_mod->qaf_compr_offload_out = NULL;
761 }
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530762
Bharath Gopal01310bb2016-12-05 15:39:32 +0530763 audio_extn_bt_hal_out_write(qaf_mod->bt_hdl, buf, size);
764 }
765
766 if (NULL == qaf_mod->qaf_compr_offload_out && bt_stream == NULL && qaf_mod->qaf_passthrough_out == NULL) {
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530767 struct audio_config config;
768 audio_devices_t devices;
769
770 config.sample_rate = config.offload_info.sample_rate = QAF_OUTPUT_SAMPLING_RATE;
771 config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
772 config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
773 config.offload_info.format = AUDIO_FORMAT_PCM_16_BIT;
774 config.offload_info.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
775 config.format = AUDIO_FORMAT_PCM_16_BIT;
776 config.offload_info.channel_mask = config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
777 devices = AUDIO_DEVICE_OUT_SPEAKER;
778 flags = AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_DIRECT_PCM;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530779
780 /* TODO:: Need to Propagate errors to framework */
781 ret = adev_open_output_stream((struct audio_hw_device *) qaf_mod->adev, QAF_DEFAULT_COMPR_AUDIO_HANDLE, devices,
782 flags, &config, (struct audio_stream_out **) &(qaf_mod->qaf_compr_offload_out), NULL);
783 if (ret < 0) {
784 ALOGE("%s: adev_open_output_stream failed with ret = %d!", __func__, ret);
785 pthread_mutex_unlock(&qaf_module->lock);
786 return;
787 }
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530788 qaf_mod->qaf_compr_offload_out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
789 qaf_mod->qaf_compr_offload_out->info.channel_mask = config.offload_info.channel_mask;
790 qaf_mod->qaf_compr_offload_out->info.format = config.offload_info.format;
791 qaf_mod->qaf_compr_offload_out->info.sample_rate = config.offload_info.sample_rate;
Deepak Agarwal1e42b852017-02-11 17:57:04 +0530792
793 qaf_mod->qaf_compr_offload_out->stream.set_volume((struct audio_stream_out *)qaf_mod->qaf_compr_offload_out, qaf_mod->vol_left, qaf_mod->vol_right);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530794 }
795
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530796 if (!qaf_mod->hdmi_connect && (qaf_mod->qaf_compr_passthrough_out || qaf_mod->qaf_compr_offload_out_mch)) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530797 qaf_mod->passthrough_enabled = 0;
798 if (qaf_mod->qaf_compr_passthrough_out) {
799 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev,
800 (struct audio_stream_out *) (qaf_mod->qaf_compr_passthrough_out));
801 qaf_mod->qaf_compr_passthrough_out = NULL;
802 }
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530803 if (qaf_mod->qaf_compr_offload_out_mch) {
804 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev,
805 (struct audio_stream_out *) (qaf_mod->qaf_compr_offload_out_mch));
806 qaf_mod->qaf_compr_offload_out_mch = NULL;
807 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530808 }
809
810 /*
811 * TODO:: Since this is mixed data,
812 * need to identify to which stream the error should be sent
813 */
Bharath Gopal01310bb2016-12-05 15:39:32 +0530814 if (bt_stream == NULL && qaf_mod->qaf_compr_offload_out)
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530815 ret = qaf_mod->qaf_compr_offload_out->stream.write((struct audio_stream_out *) qaf_mod->qaf_compr_offload_out, buf, size);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530816 }
817
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530818 ALOGVV("%s:%d stream write ret = %d", __func__, __LINE__, ret);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530819 pthread_mutex_unlock(&qaf_module->lock);
820 } else if (event_id == AUDIO_EOS_MAIN_DD_DDP_EVENT || event_id == AUDIO_EOS_MAIN_AAC_EVENT) {
821 /* TODO:: Only MAIN Stream EOS Event is added, need to add ASSOC stream EOS Event */
822 struct stream_out *out = qaf_module->stream_drain_main;
823 if (out != NULL) {
824 lock_output_stream(out);
825 out->offload_callback(STREAM_CBK_EVENT_DRAIN_READY, NULL, out->offload_cookie);
826 pthread_mutex_unlock(&out->lock);
827 qaf_module->stream_drain_main = NULL;
828 ALOGV("%s %d sent DRAIN_READY", __func__, __LINE__);
829 }
830 }
831 ALOGV("%s %d", __func__, __LINE__);
832}
833
834static int qaf_session_close()
835{
836 ALOGV("%s %d", __func__, __LINE__);
837 if (qaf_mod != NULL) {
838 if (!qaf_mod->qaf_audio_session_close)
839 return -EINVAL;
840
841 qaf_mod->qaf_audio_session_close(qaf_mod->session_handle);
842 qaf_mod->session_handle = NULL;
843 pthread_mutex_destroy(&qaf_mod->lock);
844 }
845 return 0;
846}
847
848static int qaf_stream_close(struct stream_out *out)
849{
850 int ret = 0;
851 ALOGV( "%s %d", __func__, __LINE__);
852 if (!qaf_mod->qaf_audio_stream_close)
853 return -EINVAL;
854 if (out->qaf_stream_handle) {
855 ALOGV( "%s %d output active flag is %x and stream handle %p", __func__, __LINE__, out->flags, out->qaf_stream_handle);
856 if ((out->flags & AUDIO_OUTPUT_FLAG_ASSOCIATED) && (out->flags & AUDIO_OUTPUT_FLAG_MAIN)) { /* Close for Stream with Main and Associated Content*/
857 qaf_mod->main_output_active = false;
858 qaf_mod->assoc_output_active = false;
859 } else if (out->flags & AUDIO_OUTPUT_FLAG_MAIN) {/*Close for Main Stream*/
860 qaf_mod->main_output_active = false;
861 qaf_mod->assoc_output_active = false; /* TODO to remove resetting associated stream active flag when main stream is closed*/
862 } else if (out->flags & AUDIO_OUTPUT_FLAG_ASSOCIATED) { /*Close for Associated Stream*/
863 qaf_mod->assoc_output_active = false;
864 } else { /*Close for Local Playback*/
865 qaf_mod->main_output_active = false;
866 }
867 ret = qaf_mod->qaf_audio_stream_close(out->qaf_stream_handle);
868 out->qaf_stream_handle = NULL;
869 }
870 ALOGV( "%s %d", __func__, __LINE__);
871 return ret;
872}
873
874static int qaf_stream_open(struct stream_out *out, struct audio_config *config, audio_output_flags_t flags, audio_devices_t devices)
875{
876 int status = 0;
877 ALOGV("%s %d", __func__, __LINE__);
878
879 if (!qaf_mod->qaf_audio_stream_open)
880 return -EINVAL;
881
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530882 if (audio_extn_qaf_passthrough_enabled(out) && qaf_mod->hdmi_connect) {
883 ALOGV("%s %d passthrough is enabled", __func__, __LINE__);
884 status = create_output_stream(out, config, flags, devices, QAF_DEFAULT_PASSTHROUGH_HANDLE);
885 if (status < 0) {
886 ALOGE("%s: adev_open_output_stream failed with ret = %d!", __func__, status);
887 return -EINVAL;
888 }
889 return 0;
890 }
891
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530892 audio_stream_config_t input_config;
893 input_config.sample_rate = config->sample_rate;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530894 input_config.channels = popcount(config->channel_mask);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530895 input_config.format = config->format;
896
897 if ((config->format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC) {
898 input_config.format = AUDIO_FORMAT_AAC;
899 } else if((config->format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS) {
900 input_config.format = AUDIO_FORMAT_AAC_ADTS;
901 }
902
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530903 ALOGV("%s %d audio_stream_open sample_rate(%d) channels(%d) devices(%#x) flags(%#x) format(%#x)\
904 ",__func__, __LINE__, input_config.sample_rate, input_config.channels, devices, flags, input_config.format);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530905
906 /* TODO to send appropriated flags when support for system tones is added */
907 if (input_config.format == AUDIO_FORMAT_PCM_16_BIT) {
908 status = qaf_mod->qaf_audio_stream_open(qaf_mod->session_handle, &out->qaf_stream_handle, input_config, devices, /*flags*/AUDIO_STREAM_SYSTEM_TONE);
909 } else if (input_config.format == AUDIO_FORMAT_AC3 ||
910 input_config.format == AUDIO_FORMAT_E_AC3 ||
911 input_config.format == AUDIO_FORMAT_AAC ||
912 input_config.format == AUDIO_FORMAT_AAC_ADTS) {
913 if (qaf_mod->main_output_active == false) {
914 if ((flags & AUDIO_OUTPUT_FLAG_MAIN) && (flags & AUDIO_OUTPUT_FLAG_ASSOCIATED)) {
915 status = qaf_mod->qaf_audio_stream_open(qaf_mod->session_handle, &out->qaf_stream_handle, input_config, devices, /*flags*/AUDIO_STREAM_MAIN);
916 if (status == 0) {
917 ALOGV("%s %d Open stream for Input with both Main and Associated stream contents with flag [%x] and stream handle [%p]", __func__, __LINE__, flags, out->qaf_stream_handle);
918 qaf_mod->main_output_active = true;
919 qaf_mod->assoc_output_active = true;
920 }
921 } else if (flags & AUDIO_OUTPUT_FLAG_MAIN) {
922 status = qaf_mod->qaf_audio_stream_open(qaf_mod->session_handle, &out->qaf_stream_handle, input_config, devices, /*flags*/AUDIO_STREAM_MAIN);
923 if (status == 0) {
924 ALOGV("%s %d Open stream for Input with only Main flag [%x] stream handle [%p]", __func__, __LINE__, flags, out->qaf_stream_handle);
925 qaf_mod->main_output_active = true;
926 }
927 } else if (flags & AUDIO_OUTPUT_FLAG_ASSOCIATED) {
928 ALOGE("%s %d Error main input is not active", __func__, __LINE__);
929 return -EINVAL;
930 } else {
931 status = qaf_mod->qaf_audio_stream_open(qaf_mod->session_handle, &out->qaf_stream_handle, input_config, devices, /*flags*/AUDIO_STREAM_MAIN);
932 if (status == 0) {
933 ALOGV("%s %d Open stream for Local playback with flag [%x] stream handle [%p] ", __func__, __LINE__, flags, out->qaf_stream_handle);
934 qaf_mod->main_output_active = true;
935 }
936 }
937 } else {
938 if (flags & AUDIO_OUTPUT_FLAG_MAIN) {
939 ALOGE("%s %d Error main input is already active", __func__, __LINE__);
940 return -EINVAL;
941 } else if (flags & AUDIO_OUTPUT_FLAG_ASSOCIATED) {
942 if (qaf_mod->assoc_output_active) {
943 ALOGE("%s %d Error assoc input is already active", __func__, __LINE__);
944 return -EINVAL;
945 } else {
946 status = qaf_mod->qaf_audio_stream_open(qaf_mod->session_handle, &out->qaf_stream_handle, input_config, devices, /*flags*/AUDIO_STREAM_ASSOCIATED);
947 if (status == 0) {
948 ALOGV("%s %d Open stream for Input with only Associated flag [%x] stream handle [%p]", __func__, __LINE__, flags, out->qaf_stream_handle);
949 qaf_mod->assoc_output_active = true;
950 }
951 }
952 } else {
953 ALOGE("%s %d Error main input is already active", __func__, __LINE__);
954 return -EINVAL;
955 }
956 }
957 }
958
959 return status;
960}
961
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530962static int audio_extn_qaf_stream_open(struct stream_out *out)
963{
964 int status = -ENOSYS;
965 struct audio_config config;
966 audio_devices_t devices;
967
968 config.sample_rate = config.offload_info.sample_rate = QAF_OUTPUT_SAMPLING_RATE;
969 config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
970 config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
971 config.offload_info.format = out->format;
972 config.offload_info.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
973 config.format = out->format;
974 config.offload_info.channel_mask = config.channel_mask = out->channel_mask;
975
976 devices = AUDIO_DEVICE_OUT_SPEAKER;
977 status = qaf_stream_open(out, &config, out->flags, devices);
978 ALOGV("%s %d status %d", __func__, __LINE__, status);
979 return status;
980}
981
982static int qaf_out_resume(struct audio_stream_out* stream)
983{
984 struct stream_out *out = (struct stream_out *)stream;
985 int status = -ENOSYS;
986 ALOGV("%s", __func__);
987 lock_output_stream(out);
988 if ((!property_get_bool("audio.qaf.reencode", false)) &&
989 property_get_bool("audio.qaf.passthrough", false)) {
990 if (property_get_bool("audio.offload.passthrough", false)) {
991 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect &&
992 (((out->format == AUDIO_FORMAT_E_AC3) && platform_is_edid_supported_format(qaf_mod->adev->platform, AUDIO_FORMAT_E_AC3)) ||
993 ((out->format == AUDIO_FORMAT_AC3) && platform_is_edid_supported_format(qaf_mod->adev->platform, AUDIO_FORMAT_AC3)))) {
994 status = qaf_mod->qaf_passthrough_out->stream.resume((struct audio_stream_out*) qaf_mod->qaf_passthrough_out);
995 if (!status)
996 out->offload_state = OFFLOAD_STATE_PLAYING;
997 pthread_mutex_unlock(&out->lock);
998 return status;
999 } else {
1000 if ((out->format == AUDIO_FORMAT_E_AC3) || (out->format == AUDIO_FORMAT_AC3)) {
1001 status = audio_extn_qaf_stream_open(out);
1002 if (!status)
1003 out->offload_state = OFFLOAD_STATE_PLAYING;
1004 out->offload_callback(STREAM_CBK_EVENT_WRITE_READY, NULL, out->offload_cookie);
1005 }
1006 }
1007 } else {
1008 if ((out->format == AUDIO_FORMAT_PCM_16_BIT) && (popcount(out->channel_mask) > 2)) {
1009 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
1010 status = qaf_mod->qaf_passthrough_out->stream.resume((struct audio_stream_out*) qaf_mod->qaf_passthrough_out);
1011 if (!status)
1012 out->offload_state = OFFLOAD_STATE_PLAYING;
1013 pthread_mutex_unlock(&out->lock);
1014 return status;
1015 }
1016 }
1017 }
1018 }
1019
1020 status = qaf_stream_start(out);
1021 pthread_mutex_unlock(&out->lock);
1022 ALOGD("%s Exit", __func__);
1023 return status;
1024}
1025
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301026static int qaf_deinit()
1027{
1028 ALOGV("%s %d", __func__, __LINE__);
1029 if (qaf_mod != NULL) {
1030 if (qaf_mod->qaf_compr_offload_out != NULL)
1031 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev, (struct audio_stream_out *) (qaf_mod->qaf_compr_offload_out));
1032 if (qaf_mod->qaf_compr_passthrough_out != NULL)
1033 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev, (struct audio_stream_out *) (qaf_mod->qaf_compr_passthrough_out));
1034
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301035 if (qaf_mod->qaf_passthrough_out) {
1036 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev, (struct audio_stream_out *) (qaf_mod->qaf_passthrough_out));
1037 qaf_mod->qaf_passthrough_out = NULL;
1038 }
1039
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301040 if (qaf_mod->qaf_lib != NULL) {
1041 dlclose(qaf_mod->qaf_lib);
1042 qaf_mod->qaf_lib = NULL;
1043 }
1044 free(qaf_mod);
1045 qaf_mod = NULL;
1046 }
1047 return 0;
1048}
1049
1050static void *qaf_offload_thread_loop(void *context)
1051{
1052 struct stream_out *out = (struct stream_out *) context;
1053 struct listnode *item;
1054 int ret = 0;
1055 struct str_parms *parms = NULL;
1056 int value = 0;
1057 char* kvpairs = NULL;
1058
1059 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1060 set_sched_policy(0, SP_FOREGROUND);
1061 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1062
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301063 ALOGV("%s", __func__);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301064 lock_output_stream(out);
1065 for (;;) {
1066 struct offload_cmd *cmd = NULL;
1067 stream_callback_event_t event;
1068 bool send_callback = false;
1069
1070 ALOGV("%s qaf_offload_cmd_list %d",
1071 __func__, list_empty(&out->qaf_offload_cmd_list));
1072 if (list_empty(&out->qaf_offload_cmd_list)) {
1073 ALOGV("%s SLEEPING", __func__);
1074 pthread_cond_wait(&out->qaf_offload_cond, &out->lock);
1075 ALOGV("%s RUNNING", __func__);
1076 continue;
1077 }
1078
1079 item = list_head(&out->qaf_offload_cmd_list);
1080 cmd = node_to_item(item, struct offload_cmd, node);
1081 list_remove(item);
1082
1083 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1084 free(cmd);
1085 break;
1086 }
1087
1088 pthread_mutex_unlock(&out->lock);
1089 send_callback = false;
1090 switch(cmd->cmd) {
1091 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1092 ALOGV("wait for ms12 buffer availability");
1093 while (1) {
1094 kvpairs = qaf_mod->qaf_audio_stream_get_param(out->qaf_stream_handle, "buf_available");
1095 if (kvpairs) {
1096 parms = str_parms_create_str(kvpairs);
1097 ret = str_parms_get_int(parms, "buf_available", &value);
1098 if (ret >= 0) {
1099 if (value >= (int)out->compr_config.fragment_size) {
1100 ALOGV("%s buffer available", __func__);
1101 str_parms_destroy(parms);
1102 parms = NULL;
1103 break;
1104 } else {
1105 ALOGV("%s sleep", __func__);
1106 str_parms_destroy(parms);
1107 parms = NULL;
1108 usleep(10000);
1109 }
1110 }
1111 free(kvpairs);
1112 kvpairs = NULL;
1113 }
1114 }
1115 send_callback = true;
1116 event = STREAM_CBK_EVENT_WRITE_READY;
1117 break;
1118 default:
1119 ALOGV("%s unknown command received: %d", __func__, cmd->cmd);
1120 break;
1121 }
1122 lock_output_stream(out);
1123 if (send_callback && out->offload_callback) {
1124 out->offload_callback(event, NULL, out->offload_cookie);
1125 }
1126 free(cmd);
1127 }
1128
1129 while (!list_empty(&out->qaf_offload_cmd_list)) {
1130 item = list_head(&out->qaf_offload_cmd_list);
1131 list_remove(item);
1132 free(node_to_item(item, struct offload_cmd, node));
1133 }
1134 pthread_mutex_unlock(&out->lock);
1135
1136 return NULL;
1137}
1138
1139static int qaf_create_offload_callback_thread(struct stream_out *out)
1140{
1141 ALOGV("%s", __func__);
1142 pthread_cond_init(&out->qaf_offload_cond, (const pthread_condattr_t *) NULL);
1143 list_init(&out->qaf_offload_cmd_list);
1144 pthread_create(&out->qaf_offload_thread, (const pthread_attr_t *) NULL,
1145 qaf_offload_thread_loop, out);
1146 return 0;
1147}
1148
1149static int qaf_destroy_offload_callback_thread(struct stream_out *out)
1150{
1151 ALOGV("%s", __func__);
1152 lock_output_stream(out);
1153 qaf_send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1154 pthread_mutex_unlock(&out->lock);
1155
1156 pthread_join(out->qaf_offload_thread, (void **) NULL);
1157 pthread_cond_destroy(&out->qaf_offload_cond);
1158
1159 return 0;
1160}
1161
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301162static int qaf_out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1163{
1164 struct str_parms *parms, *new_parms;
1165 char value[32];
1166 char *new_kv_pairs;
1167 int val = 0;
1168 struct stream_out *out = (struct stream_out *)stream;
1169 int ret = 0;
1170 int err = 0;
1171
1172 ALOGV("%s: enter: usecase(%d: %s) kvpairs: %s",
1173 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
1174 if ((NULL != qaf_mod->qaf_compr_offload_out)) {
1175 if (qaf_mod->qaf_msmd_enabled) {
1176 if (qaf_mod->passthrough_enabled && qaf_mod->hdmi_connect)
1177 return 1;
1178
1179 parms = str_parms_create_str(kvpairs);
1180 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1181
1182 /* usecase : hdmi sink which supports only 2-channel pcm */
1183 if (err >= 0) {
1184 val = atoi(value);
1185 if ((val & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1186 ((qaf_mod->hdmi_sink_channels == 2) && !(qaf_mod->passthrough_enabled))) {
1187 new_parms = str_parms_create();
1188 val |= AUDIO_DEVICE_OUT_SPEAKER;
1189 str_parms_add_int(new_parms, AUDIO_PARAMETER_STREAM_ROUTING, val);
1190 new_kv_pairs = str_parms_to_str(new_parms);
1191 qaf_mod->qaf_compr_offload_out->stream.common.set_parameters((struct audio_stream *) qaf_mod->qaf_compr_offload_out, new_kv_pairs);
1192 free(new_kv_pairs);
1193 str_parms_destroy(new_parms);
1194 }
1195 }
1196 str_parms_destroy(parms);
1197 } else {
1198 if (!(qaf_mod->passthrough_enabled && qaf_mod->hdmi_connect))
1199 qaf_mod->qaf_compr_offload_out->stream.common.set_parameters((struct audio_stream *) qaf_mod->qaf_compr_offload_out, kvpairs);
Bharath Gopal01310bb2016-12-05 15:39:32 +05301200
1201 parms = str_parms_create_str(kvpairs);
1202 if (!parms) {
1203 ALOGE("str_parms_create_str failed!");
1204 } else {
1205 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1206 if (err >= 0) {
1207 val = atoi(value);
1208 if (val == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) { //BT routing
1209 if (audio_extn_bt_hal_get_output_stream(qaf_mod->bt_hdl) == NULL && audio_extn_bt_hal_get_device(qaf_mod->bt_hdl) != NULL) {
1210 ret = audio_extn_bt_hal_open_output_stream(qaf_mod->bt_hdl,
1211 QAF_OUTPUT_SAMPLING_RATE,
1212 AUDIO_CHANNEL_OUT_STEREO,
1213 CODEC_BACKEND_DEFAULT_BIT_WIDTH);
1214 if (ret != 0) {
1215 ALOGE("%s: BT Output stream open failure!", __FUNCTION__);
1216 }
1217 }
1218 } else if (val != 0) {
1219 if (audio_extn_bt_hal_get_output_stream(qaf_mod->bt_hdl)!= NULL) {
1220 audio_extn_bt_hal_close_output_stream(qaf_mod->bt_hdl);
1221 }
1222 }
1223 }
1224 str_parms_destroy(parms);
1225 }
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301226 }
1227 }
1228
1229 if (audio_extn_qaf_passthrough_enabled(out)) {
1230 parms = str_parms_create_str(kvpairs);
1231 if (!parms) {
1232 ALOGE("str_parms_create_str failed!");
1233 } else {
1234 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1235 if (err >= 0) {
1236 val = atoi(value);
1237 if ((val & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1238 (qaf_mod->qaf_passthrough_out == NULL)) {
1239 audio_output_flags_t flags;
1240 struct audio_config config;
1241 audio_devices_t devices;
1242
1243 config.sample_rate = config.offload_info.sample_rate = QAF_OUTPUT_SAMPLING_RATE;
1244 config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
1245 config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
1246 config.offload_info.format = out->format;
1247 config.offload_info.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
1248 config.format = out->format;
1249 config.offload_info.channel_mask = config.channel_mask = out->channel_mask;
1250
1251 devices = AUDIO_DEVICE_OUT_AUX_DIGITAL;
1252 flags = out->flags;
1253
1254 if (out->qaf_stream_handle) {
1255 qaf_out_pause((struct audio_stream_out*)out);
1256 qaf_out_flush((struct audio_stream_out*)out);
1257 qaf_out_drain((struct audio_stream_out*)out, (audio_drain_type_t)STREAM_CBK_EVENT_DRAIN_READY);
1258 qaf_stream_close(out);
1259 }
1260 create_output_stream(out, &config, flags, devices, QAF_DEFAULT_PASSTHROUGH_HANDLE);
1261 qaf_mod->main_output_active = true;
1262 }
1263 }
1264 str_parms_destroy(parms);
1265 }
1266 }
1267
1268 return ret;
1269}
1270
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301271int audio_extn_qaf_open_output_stream(struct audio_hw_device *dev,
1272 audio_io_handle_t handle,
1273 audio_devices_t devices,
1274 audio_output_flags_t flags,
1275 struct audio_config *config,
1276 struct audio_stream_out **stream_out,
1277 const char *address __unused)
1278{
1279 int ret = 0;
1280 struct stream_out *out;
1281
1282 ret = adev_open_output_stream(dev, handle, devices, flags, config, stream_out, address);
1283 if (*stream_out == NULL) {
1284 goto error_open;
1285 }
1286
Deepak Agarwal1e42b852017-02-11 17:57:04 +05301287 if ( false == is_ms12_format(config->format) ) {
1288 ALOGV("%s: exiting qaf for non-ms12 format %x", __func__, config->format);
1289 return ret;
1290 }
1291
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301292 out = (struct stream_out *) *stream_out;
1293
1294 /* Override function pointers based on qaf definitions */
1295 out->stream.set_volume = qaf_out_set_volume;
1296 out->stream.pause = qaf_out_pause;
1297 out->stream.resume = qaf_out_resume;
1298 out->stream.drain = qaf_out_drain;
1299 out->stream.flush = qaf_out_flush;
1300
1301 out->stream.common.standby = qaf_out_standby;
1302 out->stream.common.set_parameters = qaf_out_set_parameters;
1303 out->stream.get_latency = qaf_out_get_latency;
1304 out->stream.write = qaf_out_write;
1305 out->stream.get_presentation_position = qaf_out_get_presentation_position;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301306 out->platform_latency = 0;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301307 ret = qaf_stream_open(out, config, flags, devices);
1308 if (ret < 0) {
1309 ALOGE("%s, Error opening QAF stream err[%d]!", __func__, ret);
1310 adev_close_output_stream(dev, *stream_out);
1311 goto error_open;
1312 }
1313
1314 if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY) {
1315 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
1316 out->config.period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE;
1317 out->config.period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT;
1318 out->config.start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4;
1319 out->config.avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4;
1320 }
1321
1322 *stream_out = &out->stream;
1323 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
1324 qaf_create_offload_callback_thread(out);
1325 }
1326 ALOGV("%s: exit", __func__);
1327 return 0;
1328error_open:
1329 *stream_out = NULL;
1330 ALOGD("%s: exit: ret %d", __func__, ret);
1331 return ret;
1332}
1333
1334void audio_extn_qaf_close_output_stream(struct audio_hw_device *dev,
1335 struct audio_stream_out *stream)
1336{
1337 struct stream_out *out = (struct stream_out *)stream;
1338
1339 ALOGV("%s: enter:stream_handle(%p) format = %x", __func__, out, out->format);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301340 if (qaf_mod->qaf_passthrough_out) {
1341 ALOGD("%s %d closing stream handle %p", __func__, __LINE__, qaf_mod->qaf_passthrough_out);
1342 pthread_mutex_lock(&qaf_mod->lock);
1343 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev, (struct audio_stream_out *) (qaf_mod->qaf_passthrough_out));
1344 adev_close_output_stream(dev, stream);
1345 qaf_mod->qaf_passthrough_out = NULL;
1346 qaf_mod->main_output_active = false;
1347 pthread_mutex_unlock(&qaf_mod->lock);
1348 return;
1349 }
1350
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301351 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
1352 qaf_destroy_offload_callback_thread(out);
1353 }
1354 qaf_mod->stream_drain_main = NULL;
1355 lock_output_stream(out);
1356 qaf_stream_close(out);
1357 pthread_mutex_unlock(&out->lock);
1358
1359 adev_close_output_stream(dev, stream);
1360 ALOGV("%s: exit", __func__);
1361}
1362
1363bool audio_extn_qaf_is_enabled()
1364{
1365 bool prop_enabled = false;
1366 char value[PROPERTY_VALUE_MAX] = {0};
1367 property_get("audio.qaf.enabled", value, NULL);
1368 prop_enabled = atoi(value) || !strncmp("true", value, 4);
1369 return (prop_enabled);
1370}
1371
1372int audio_extn_qaf_session_open(struct qaf *qaf_mod,
1373 device_license_config_t* lic_config)
1374{
1375 ALOGV("%s %d", __func__, __LINE__);
1376 int status = -ENOSYS;
1377
1378 pthread_mutex_init(&qaf_mod->lock, (const pthread_mutexattr_t *) NULL);
1379
1380 if (!qaf_mod->qaf_audio_session_open)
1381 return -EINVAL;
1382
1383 status = qaf_mod->qaf_audio_session_open(&qaf_mod->session_handle,
1384 (void *)(qaf_mod), (void *)lic_config);
1385 if(status < 0)
1386 return status;
1387
1388 if (qaf_mod->session_handle == NULL) {
1389 ALOGE("%s %d QAF wrapper session handle is NULL", __func__, __LINE__);
1390 return -ENOMEM;
1391 }
1392 if (qaf_mod->qaf_register_event_callback)
1393 qaf_mod->qaf_register_event_callback(qaf_mod->session_handle,
1394 qaf_mod, &notify_event_callback,
1395 AUDIO_DATA_EVENT);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301396
1397 if (property_get_bool("audio.qaf.msmd", false)) {
1398 qaf_mod->qaf_msmd_enabled = 1;
1399 }
1400
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301401 return status;
1402}
1403
1404char* audio_extn_qaf_stream_get_param(struct stream_out *out __unused, const char *kv_pair __unused)
1405{
1406 return NULL;
1407}
1408
1409int audio_extn_qaf_set_parameters(struct audio_device *adev, struct str_parms *parms)
1410{
1411 int status = 0, val = 0, channels = 0;
1412 char *format_params, *kv_parirs;
1413 struct str_parms *qaf_params;
1414 char value[32];
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301415 char prop_value[PROPERTY_VALUE_MAX];
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301416 bool passth_support = false;
1417
1418 ALOGV("%s %d ", __func__, __LINE__);
1419 if (!qaf_mod || !qaf_mod->qaf_audio_session_set_param) {
1420 return -EINVAL;
1421 }
1422
1423 status = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
1424 if (status >= 0) {
1425 val = atoi(value);
1426 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1427 if (property_get_bool("audio.offload.passthrough", false) &&
1428 property_get_bool("audio.qaf.reencode", false)) {
1429
1430 qaf_params = str_parms_create();
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301431 property_get("audio.qaf.hdmi.out", prop_value, NULL);
1432 if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_E_AC3) &&
1433 (strncmp(prop_value, "ddp", 3) == 0)) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301434 passth_support = true;
1435 if (qaf_params) {
1436 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_RENDER_FORMAT,
1437 AUDIO_QAF_PARAMETER_VALUE_REENCODE_EAC3);
1438 }
1439 } else if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_AC3)) {
1440 passth_support = true;
1441 if (qaf_params) {
1442 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_RENDER_FORMAT,
1443 AUDIO_QAF_PARAMETER_VALUE_REENCODE_AC3);
1444 }
1445 }
1446
1447 if (passth_support) {
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301448 qaf_mod->passthrough_enabled = 1;
1449 if (qaf_mod->qaf_msmd_enabled) {
1450 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1451 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI_AND_SPK);
1452 } else {
1453 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1454 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI);
1455 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301456 format_params = str_parms_to_str(qaf_params);
1457
1458 qaf_mod->qaf_audio_session_set_param(qaf_mod->session_handle, format_params);
1459 }
1460 str_parms_destroy(qaf_params);
1461 }
1462
1463 if (!passth_support) {
1464 channels = platform_edid_get_max_channels(adev->platform);
1465
1466 qaf_params = str_parms_create();
1467 switch (channels) {
1468 case 8:
1469 ALOGV("%s: Switching Qaf output to 7.1 channels", __func__);
1470 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_CHANNELS,
1471 AUDIO_QAF_PARAMETER_VALUE_8_CHANNELS);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301472 if (qaf_mod->qaf_msmd_enabled) {
1473 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1474 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI_AND_SPK);
1475 } else {
1476 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1477 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI);
1478 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301479 qaf_mod->hdmi_sink_channels = channels;
1480 break;
1481 case 6:
1482 ALOGV("%s: Switching Qaf output to 5.1 channels", __func__);
1483 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_CHANNELS,
1484 AUDIO_QAF_PARAMETER_VALUE_6_CHANNELS);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301485 if (qaf_mod->qaf_msmd_enabled) {
1486 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1487 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI_AND_SPK);
1488 } else {
1489 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1490 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI);
1491 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301492 qaf_mod->hdmi_sink_channels = channels;
1493 break;
1494 default:
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301495 ALOGV("%s: Switching Qaf output to default channels", __func__);
1496 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_CHANNELS,
1497 AUDIO_QAF_PARAMETER_VALUE_DEFAULT_CHANNELS);
1498 if (qaf_mod->qaf_msmd_enabled) {
1499 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1500 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI_AND_SPK);
1501 } else {
1502 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1503 AUDIO_QAF_PARAMETER_VALUE_DEVICE_SPEAKER);
1504 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301505 qaf_mod->hdmi_sink_channels = 2;
1506 break;
1507 }
1508
1509 format_params = str_parms_to_str(qaf_params);
1510 qaf_mod->qaf_audio_session_set_param(qaf_mod->session_handle, format_params);
1511 str_parms_destroy(qaf_params);
1512 }
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301513 qaf_mod->hdmi_connect = 1;
Bharath Gopal01310bb2016-12-05 15:39:32 +05301514 } else if (val & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) {
1515 ALOGV("%s: Opening a2dp output...", __FUNCTION__);
1516 status = audio_extn_bt_hal_load(&qaf_mod->bt_hdl);
1517 if(status != 0) {
1518 ALOGE("%s:Error opening BT module", __FUNCTION__);
1519 return status;
1520 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301521 }
1522 }
1523
1524 status = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
1525 if (status >= 0) {
1526 val = atoi(value);
1527 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1528 qaf_params = str_parms_create();
1529 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1530 AUDIO_QAF_PARAMETER_VALUE_DEVICE_SPEAKER);
1531 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_RENDER_FORMAT,
1532 AUDIO_QAF_PARAMETER_VALUE_PCM);
1533 qaf_mod->hdmi_sink_channels = 0;
1534
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301535 qaf_mod->passthrough_enabled = 0;
1536 qaf_mod->hdmi_connect = 0;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301537 format_params = str_parms_to_str(qaf_params);
1538 qaf_mod->qaf_audio_session_set_param(qaf_mod->session_handle, format_params);
1539 str_parms_destroy(qaf_params);
Bharath Gopal01310bb2016-12-05 15:39:32 +05301540 } else if (val & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) {
1541 ALOGV("%s: Closing a2dp output...", __FUNCTION__);
1542 audio_extn_bt_hal_unload(qaf_mod->bt_hdl);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301543 }
1544 }
1545
1546 kv_parirs = str_parms_to_str(parms);
1547 qaf_mod->qaf_audio_session_set_param(qaf_mod->session_handle, kv_parirs);
1548
1549 return status;
1550}
1551
1552char* audio_extn_qaf_get_param(struct audio_device *adev __unused, const char *kv_pair __unused)
1553{
1554 return 0;
1555}
1556
1557int audio_extn_qaf_init(struct audio_device *adev)
1558{
1559 char value[PROPERTY_VALUE_MAX] = {0};
1560 char lib_name[PROPERTY_VALUE_MAX] = {0};
1561 unsigned char* license_data = NULL;
1562 device_license_config_t* lic_config = NULL;
1563 ALOGV("%s %d", __func__, __LINE__);
1564 int ret = 0, size = 0;
1565
1566 qaf_mod = malloc(sizeof(struct qaf));
1567 if(qaf_mod == NULL) {
1568 ALOGE("%s, out of memory", __func__);
1569 ret = -ENOMEM;
1570 goto done;
1571 }
1572 memset(qaf_mod, 0, sizeof(struct qaf));
1573 lic_config = (device_license_config_t*) calloc(1, sizeof(device_license_config_t));
1574 if(lic_config == NULL) {
1575 ALOGE("%s, out of memory", __func__);
1576 ret = -ENOMEM;
1577 goto done;
1578 }
1579 qaf_mod->adev = adev;
1580 property_get("audio.qaf.library", value, NULL);
1581 snprintf(lib_name, PROPERTY_VALUE_MAX, "%s", value);
1582
1583 license_data = platform_get_license((struct audio_hw_device *)(qaf_mod->adev->platform), &size);
1584 if (!license_data) {
1585 ALOGE("License is not present");
1586 ret = -EINVAL;
1587 goto done;
1588 }
1589 lic_config->p_license = (unsigned char* ) calloc(1, size);
1590 if(lic_config->p_license == NULL) {
1591 ALOGE("%s, out of memory", __func__);
1592 ret = -ENOMEM;
1593 goto done;
1594 }
1595 lic_config->l_size = size;
1596 memcpy(lic_config->p_license, license_data, size);
1597
1598 if (property_get("audio.qaf.manufacturer", value, "") && atoi(value)) {
1599 lic_config->manufacturer_id = (unsigned long) atoi (value);
1600 } else {
1601 ALOGE("audio.qaf.manufacturer id is not set");
1602 ret = -EINVAL;
1603 goto done;
1604 }
1605
1606 ret = audio_extn_qaf_session_open(qaf_mod, lic_config);
1607done:
1608 if (license_data != NULL) {
1609 free(license_data);
1610 license_data = NULL;
1611 }
1612 if (lic_config->p_license != NULL) {
1613 free(lic_config->p_license);
1614 lic_config->p_license = NULL;
1615 }
1616 if (lic_config != NULL) {
1617 free(lic_config);
1618 lic_config = NULL;
1619 }
1620 if (ret != 0) {
1621 if (qaf_mod != NULL) {
1622 free(qaf_mod);
1623 qaf_mod = NULL;
1624 }
1625 }
1626 return ret;
1627}
1628
1629void audio_extn_qaf_deinit()
1630{
1631 qaf_session_close();
1632 qaf_deinit();
1633}