blob: 9739201b4e71286bd7ced5b091390d018bfbc700 [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;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530151};
152
153static struct qaf *qaf_mod = NULL;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530154static int qaf_stream_set_param(struct stream_out *out, const char *kv_pair) __attribute__ ((unused));
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530155
156static void lock_output_stream(struct stream_out *out)
157{
158 pthread_mutex_lock(&out->pre_lock);
159 pthread_mutex_lock(&out->lock);
160 pthread_mutex_unlock(&out->pre_lock);
161}
162
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530163static bool audio_extn_qaf_passthrough_enabled(struct stream_out *out)
164{
165 ALOGV("%s %d ", __func__, __LINE__);
166 if ((!property_get_bool("audio.qaf.reencode", false)) &&
167 property_get_bool("audio.qaf.passthrough", false)) {
168 if (property_get_bool("audio.offload.passthrough", false)) {
169 if (((out->format == AUDIO_FORMAT_AC3) && platform_is_edid_supported_format(qaf_mod->adev->platform, AUDIO_FORMAT_AC3)) ||
170 ((out->format == AUDIO_FORMAT_E_AC3) && platform_is_edid_supported_format(qaf_mod->adev->platform, AUDIO_FORMAT_E_AC3)) ||
171 ((out->format == AUDIO_FORMAT_DTS) && platform_is_edid_supported_format(qaf_mod->adev->platform, AUDIO_FORMAT_DTS)) ||
172 ((out->format == AUDIO_FORMAT_DTS_HD) && platform_is_edid_supported_format(qaf_mod->adev->platform, AUDIO_FORMAT_DTS_HD))) {
173 return true;
174 }
175 } else {
176 if ((out->format == AUDIO_FORMAT_PCM_16_BIT) && (popcount(out->channel_mask) > 2)) {
177 return true;
178 }
179 }
180 }
181 return false;
182}
183
184static int qaf_out_callback(stream_callback_event_t event, void *param __unused, void *cookie)
185{
186 struct stream_out *out = (struct stream_out *)cookie;
187
188 out->offload_callback(event, NULL, out->offload_cookie);
189 return 0;
190}
191
192static int create_output_stream(struct stream_out *out, struct audio_config *config, audio_output_flags_t flags, audio_devices_t devices, int handle_id)
193{
194 int ret = 0;
195
196 ALOGV("%s %d", __func__, __LINE__);
197 if ((handle_id == QAF_DEFAULT_PASSTHROUGH_HANDLE) &&
198 (NULL == qaf_mod->qaf_passthrough_out)) {
199 pthread_mutex_lock(&qaf_mod->lock);
200 lock_output_stream(out);
201 ret = adev_open_output_stream((struct audio_hw_device *) qaf_mod->adev, handle_id, devices,
202 flags, config, (struct audio_stream_out **) &(qaf_mod->qaf_passthrough_out), NULL);
203 if (ret < 0) {
204 pthread_mutex_unlock(&out->lock);
205 pthread_mutex_unlock(&qaf_mod->lock);
206 ALOGE("%s: adev_open_output_stream failed with ret = %d!", __func__, ret);
207 return -EINVAL;
208 }
209 qaf_mod->qaf_passthrough_out->stream.set_callback((struct audio_stream_out *)qaf_mod->qaf_passthrough_out, (stream_callback_t) qaf_out_callback, out);
210 pthread_mutex_unlock(&out->lock);
211 pthread_mutex_unlock(&qaf_mod->lock);
212 }
213 return ret;
214}
215
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530216static int qaf_send_offload_cmd_l(struct stream_out* out, int command)
217{
218 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
219
220 if (!cmd) {
221 ALOGE("failed to allocate mem for command 0x%x", command);
222 return -ENOMEM;
223 }
224
225 ALOGV("%s %d", __func__, command);
226
227 cmd->cmd = command;
228 list_add_tail(&out->qaf_offload_cmd_list, &cmd->node);
229 pthread_cond_signal(&out->qaf_offload_cond);
230 return 0;
231}
232
233static int audio_extn_qaf_stream_stop(struct stream_out *out)
234{
235 ALOGV("%s: %d start", __func__, __LINE__);
236 if (!qaf_mod->qaf_audio_stream_stop)
237 return -EINVAL;
238
239 return qaf_mod->qaf_audio_stream_stop(out->qaf_stream_handle);
240}
241
242static int qaf_out_standby(struct audio_stream *stream)
243{
244 struct stream_out *out = (struct stream_out *)stream;
245 int status = 0;
246
247 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
248 stream, out->usecase, use_case_table[out->usecase]);
249
250 lock_output_stream(out);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530251 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
252 if ((out->format == AUDIO_FORMAT_PCM_16_BIT) && (popcount(out->channel_mask) <= 2)) {
253 pthread_mutex_unlock(&out->lock);
254 return status;
255 }
256 status = qaf_mod->qaf_passthrough_out->stream.common.standby((struct audio_stream *) qaf_mod->qaf_passthrough_out);
257 if (!out->standby) {
258 out->standby = true;
259 }
260 pthread_mutex_unlock(&out->lock);
261 return status;
262 }
263
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530264 if (!out->standby) {
265 out->standby = true;
266 status = audio_extn_qaf_stream_stop(out);
267 }
268 pthread_mutex_unlock(&out->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530269 return status;
270}
271
272static int qaf_stream_set_param(struct stream_out *out, const char *kv_pair)
273{
274 ALOGV("%s %d kvpair: %s", __func__, __LINE__, kv_pair);
275 if (!qaf_mod->qaf_audio_stream_set_param)
276 return -EINVAL;
277
278 return qaf_mod->qaf_audio_stream_set_param(out->qaf_stream_handle, kv_pair);
279}
280
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530281static int qaf_write_input_buffer(struct stream_out *out, const void *buffer, int bytes)
282{
283 int ret = 0;
284 ALOGVV("%s bytes = %d [%p]", __func__, bytes, out->qaf_stream_handle);
285 if (!qaf_mod->qaf_audio_stream_write)
286 return -EINVAL;
287
288 if (out->qaf_stream_handle)
289 ret = qaf_mod->qaf_audio_stream_write(out->qaf_stream_handle, buffer, bytes);
290 return ret;
291}
292
293static int qaf_out_set_volume(struct audio_stream_out *stream __unused, float left,
294 float right)
295{
296 if (qaf_mod->qaf_compr_offload_out != NULL) {
297 return qaf_mod->qaf_compr_offload_out->stream.set_volume(
298 (struct audio_stream_out *)qaf_mod->qaf_compr_offload_out, left, right);
299 }
300 return -ENOSYS;
301}
302
303static int qaf_stream_start(struct stream_out *out)
304{
305 if (!qaf_mod->qaf_audio_stream_start)
306 return -EINVAL;
307
308 return qaf_mod->qaf_audio_stream_start(out->qaf_stream_handle);
309}
310
311static int qaf_start_output_stream(struct stream_out *out)
312{
313 int ret = 0;
314 struct audio_device *adev = out->dev;
315 int snd_card_status = get_snd_card_state(adev);
316
317 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
318 ret = -EINVAL;
319 usleep(50000);
320 return ret;
321 }
322
323 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
324 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
325 out->devices);
326
327 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
328 ALOGE("%s: sound card is not active/SSR returning error", __func__);
329 ret = -EIO;
330 usleep(50000);
331 return ret;
332 }
333
334 return qaf_stream_start(out);
335}
336
337static ssize_t qaf_out_write(struct audio_stream_out *stream, const void *buffer,
338 size_t bytes)
339{
340 struct stream_out *out = (struct stream_out *)stream;
341 struct audio_device *adev = out->dev;
342 ssize_t ret = 0;
343
344 ALOGV("qaf_out_write bytes = %d, usecase[%d] and flags[%x] for handle[%p]",(int)bytes, out->usecase, out->flags, out);
345 lock_output_stream(out);
346
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530347 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
348 if ((out->format == AUDIO_FORMAT_PCM_16_BIT) && (popcount(out->channel_mask) <= 2)) {
349 ALOGD(" %s : Drop data as compress passthrough session is going on", __func__);
350 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
351 out->stream.common.get_sample_rate(&out->stream.common));
352 goto exit;
353 }
354 ret = qaf_mod->qaf_passthrough_out->stream.write((struct audio_stream_out *)(qaf_mod->qaf_passthrough_out), buffer, bytes);
355 pthread_mutex_unlock(&out->lock);
356 return ret;
357 }
358
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530359 if (out->standby) {
360 out->standby = false;
361 pthread_mutex_lock(&adev->lock);
362 ret = qaf_start_output_stream(out);
363 pthread_mutex_unlock(&adev->lock);
364 /* ToDo: If use case is compress offload should return 0 */
365 if (ret != 0) {
366 out->standby = true;
367 goto exit;
368 }
369 }
370
371 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
372 audio_utils_set_hdmi_channel_status(out, (char *)buffer, bytes);
373 adev->is_channel_status_set = true;
374 }
375
376 ret = qaf_write_input_buffer(out, buffer, bytes);
377 ALOGV("%s, ret [%d] ", __func__, (int)ret);
378 if (ret < 0) {
379 goto exit;
380 }
381 out->written += bytes / ((popcount(out->channel_mask) * sizeof(short)));
382
383exit:
384
385 pthread_mutex_unlock(&out->lock);
386
387 if (ret < 0) {
388 if (ret == -EAGAIN) {
389 ALOGV("No space available in ms12 driver, post msg to cb thread");
390 lock_output_stream(out);
391 ret = qaf_send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
392 pthread_mutex_unlock(&out->lock);
393 bytes = 0;
394 }
395 if(ret == -ENOMEM || ret == -EPERM){
396 if (out->pcm)
397 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
398 qaf_out_standby(&out->stream.common);
399 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
400 out->stream.common.get_sample_rate(&out->stream.common));
401 }
402 }
403 return bytes;
404}
405
406static int qaf_get_timestamp(struct stream_out *out, uint64_t *frames, struct timespec *timestamp)
407{
408 int ret = 0;
409 struct str_parms *parms;
410 int value = 0;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530411 int latency = 0;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530412 int signed_frames = 0;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530413 char* kvpairs = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530414
415 ALOGV("%s out->format %d", __func__, out->format);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530416 kvpairs = qaf_mod->qaf_audio_stream_get_param(out->qaf_stream_handle, "get_latency");
417 if (kvpairs) {
418 parms = str_parms_create_str(kvpairs);
419 ret = str_parms_get_int(parms, "get_latency", &latency);
420 if (ret >= 0) {
421 str_parms_destroy(parms);
422 parms = NULL;
423 }
424 free(kvpairs);
425 kvpairs = NULL;
426 }
427 // MS12 Latency + Kernel Latency + Dsp Latency
428 if (qaf_mod->qaf_compr_offload_out != NULL) {
429 out->platform_latency = latency + (COMPRESS_OFFLOAD_NUM_FRAGMENTS * PCM_OFFLOAD_BUFFER_SIZE \
430 /(popcount(qaf_mod->qaf_compr_offload_out->channel_mask) * sizeof(short))) \
431 +((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 +0530432 } else if (audio_extn_bt_hal_get_output_stream(qaf_mod->bt_hdl) != NULL) {
433 out->platform_latency = latency + audio_extn_bt_hal_get_latency(qaf_mod->bt_hdl);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530434 } else if (NULL != qaf_mod->qaf_compr_passthrough_out) {
435 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)) \
436 + (COMPRESS_OFFLOAD_PLAYBACK_LATENCY * qaf_mod->qaf_compr_passthrough_out->sample_rate/1000);
437 }
438
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530439 if(out->format & AUDIO_FORMAT_PCM_16_BIT) {
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530440 *frames = 0;
441 signed_frames = out->written - out->platform_latency;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530442 // It would be unusual for this value to be negative, but check just in case ...
443 if (signed_frames >= 0) {
444 *frames = signed_frames;
445 }
446 clock_gettime(CLOCK_MONOTONIC, timestamp);
447 } else if (qaf_mod->qaf_audio_stream_get_param) {
448 kvpairs = qaf_mod->qaf_audio_stream_get_param(out->qaf_stream_handle, "position");
449 if (kvpairs) {
450 parms = str_parms_create_str(kvpairs);
451 ret = str_parms_get_int(parms, "position", &value);
452 if (ret >= 0) {
453 *frames = value;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530454 signed_frames = value - out->platform_latency;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530455 // It would be unusual for this value to be negative, but check just in case ...
456 if (signed_frames >= 0) {
457 *frames = signed_frames;
458 }
459 clock_gettime(CLOCK_MONOTONIC, timestamp);
460 }
461 str_parms_destroy(parms);
462 }
463 } else {
464 ret = -EINVAL;
465 }
466 return ret;
467}
468
469static int qaf_out_get_presentation_position(const struct audio_stream_out *stream,
470 uint64_t *frames, struct timespec *timestamp)
471{
472 struct stream_out *out = (struct stream_out *)stream;
473 int ret = -1;
474 lock_output_stream(out);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530475
476 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
477 ret = qaf_mod->qaf_passthrough_out->stream.get_presentation_position((struct audio_stream_out *)qaf_mod->qaf_passthrough_out, frames, timestamp);
478 pthread_mutex_unlock(&out->lock);
479 return ret;
480 }
481
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530482 ret = qaf_get_timestamp(out, frames, timestamp);
483 pthread_mutex_unlock(&out->lock);
484
485 return ret;
486}
487
488static int qaf_stream_pause(struct stream_out *out)
489{
490 ALOGV("%s: %d start", __func__, __LINE__);
491 if (!qaf_mod->qaf_audio_stream_pause)
492 return -EINVAL;
493
494 return qaf_mod->qaf_audio_stream_pause(out->qaf_stream_handle);
495}
496
497static int qaf_out_pause(struct audio_stream_out* stream)
498{
499 struct stream_out *out = (struct stream_out *)stream;
500 int status = -ENOSYS;
501 ALOGE("%s", __func__);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530502
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530503 lock_output_stream(out);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530504 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
505 status = qaf_mod->qaf_passthrough_out->stream.pause((struct audio_stream_out *) qaf_mod->qaf_passthrough_out);
506 out->offload_state = OFFLOAD_STATE_PAUSED;
507 pthread_mutex_unlock(&out->lock);
508 return status;
509 }
510
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530511 status = qaf_stream_pause(out);
512 pthread_mutex_unlock(&out->lock);
513 return status;
514}
515
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530516static int qaf_out_drain(struct audio_stream_out* stream, audio_drain_type_t type)
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530517{
518 struct stream_out *out = (struct stream_out *)stream;
519 int status = 0;
520 ALOGV("%s stream_handle = %p , format = %x", __func__, out->qaf_stream_handle, out->format);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530521
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530522 lock_output_stream(out);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530523 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
524 status = qaf_mod->qaf_passthrough_out->stream.drain((struct audio_stream_out*)(qaf_mod->qaf_passthrough_out), type);
525 pthread_mutex_unlock(&out->lock);
526 return status;
527 }
528
529
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530530 if (out->offload_callback && out->qaf_stream_handle) {
531 /* Stream stop will trigger EOS and on EOS_EVENT received
532 from callback DRAIN_READY command is sent */
533 status = audio_extn_qaf_stream_stop(out);
534 if (out->format != AUDIO_FORMAT_PCM_16_BIT)
535 qaf_mod->stream_drain_main = out;
536 }
537 pthread_mutex_unlock(&out->lock);
538 return status;
539}
540
541static int audio_extn_qaf_stream_flush(struct stream_out *out)
542{
543 ALOGV("%s: %d exit", __func__, __LINE__);
544 if (!qaf_mod->qaf_audio_stream_flush)
545 return -EINVAL;
546
547 return qaf_mod->qaf_audio_stream_flush(out->qaf_stream_handle);
548}
549
550static int qaf_out_flush(struct audio_stream_out* stream)
551{
552 struct stream_out *out = (struct stream_out *)stream;
553 ALOGV("%s", __func__);
554 int status = -ENOSYS;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530555
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530556 lock_output_stream(out);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530557 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
558 status = qaf_mod->qaf_passthrough_out->stream.flush((struct audio_stream_out *)qaf_mod->qaf_passthrough_out);
559 out->offload_state = OFFLOAD_STATE_IDLE;
560 pthread_mutex_unlock(&out->lock);
561 return status;
562 }
563
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530564 status = audio_extn_qaf_stream_flush(out);
565 pthread_mutex_unlock(&out->lock);
566 ALOGV("%s Exit", __func__);
567 return status;
568}
569
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530570static uint32_t qaf_out_get_latency(const struct audio_stream_out *stream)
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530571{
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530572 struct stream_out *out = (struct stream_out *)stream;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530573 uint32_t latency = 0;
574
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530575
576 lock_output_stream(out);
577 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
578 latency = qaf_mod->qaf_passthrough_out->stream.get_latency((struct audio_stream_out *)qaf_mod->qaf_passthrough_out);
579 ALOGV("%s: latency = %u", __FUNCTION__, latency);
580 pthread_mutex_unlock(&out->lock);
581 return latency;
582 }
583 pthread_mutex_unlock(&out->lock);
584
585 if (is_offload_usecase(out->usecase)) {
586 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
587 } else {
588 latency = PCM_OFFLOAD_PLAYBACK_LATENCY;
589 }
Bharath Gopal01310bb2016-12-05 15:39:32 +0530590
591 if (audio_extn_bt_hal_get_output_stream(qaf_mod->bt_hdl) != NULL) {
592
593 if (is_offload_usecase(out->usecase)) {
594 latency = audio_extn_bt_hal_get_latency(qaf_mod->bt_hdl) + QAF_COMPRESS_OFFLOAD_PROCESSING_LATENCY;
595 } else {
596 latency = audio_extn_bt_hal_get_latency(qaf_mod->bt_hdl) + QAF_PCM_OFFLOAD_PROCESSING_LATENCY;
597 }
598 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530599 ALOGV("%s: Latency %d", __func__, latency);
600 return latency;
601}
602
603static 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)
604{
605
606/*
607 For SPKR:
608 1. Open pcm device if device_id passed to it SPKR and write the data to pcm device
609
610 For HDMI
611 1.Open compress device for HDMI(PCM or AC3) based on current_hdmi_output_format
612 2.create offload_callback thread to receive async events
613 3.Write the data to compress device. If not all the data is consumed by the driver,
614 add a command to offload_callback thread.
615*/
616 int ret;
617 audio_output_flags_t flags;
618 struct qaf* qaf_module = (struct qaf* ) prv_data;
Bharath Gopal01310bb2016-12-05 15:39:32 +0530619 struct audio_stream_out *bt_stream = NULL;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530620
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530621 ALOGV("%s device 0x%X, %d in event = %d", __func__, device, __LINE__, event_id);
622
623 if (event_id == AUDIO_DATA_EVENT) {
624 ALOGVV("Device id %x %s %d, bytes to written %d", device, __func__,__LINE__, size);
625
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530626 if ((qaf_mod->qaf_passthrough_out != NULL) && qaf_mod->hdmi_connect) {
627 pthread_mutex_lock(&qaf_module->lock);
628 if (qaf_mod->qaf_compr_offload_out != NULL) {
629 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev,
630 (struct audio_stream_out *) (qaf_mod->qaf_compr_offload_out));
631 qaf_mod->qaf_compr_offload_out = NULL;
632 }
633 if (qaf_mod->qaf_compr_offload_out_mch) {
634 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev,
635 (struct audio_stream_out *) (qaf_mod->qaf_compr_offload_out_mch));
636 qaf_mod->qaf_compr_offload_out_mch = NULL;
637 }
638 pthread_mutex_unlock(&qaf_module->lock);
639 ALOGV("%s %d DROPPING DATA", __func__, __LINE__);
640 return;
641 } else {
642 if (qaf_mod->qaf_passthrough_out != NULL) {
643 pthread_mutex_lock(&qaf_module->lock);
644 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev,
645 (struct audio_stream_out *) (qaf_mod->qaf_passthrough_out));
646 qaf_mod->qaf_passthrough_out = NULL;
647 qaf_mod->main_output_active = false;
648 pthread_mutex_unlock(&qaf_module->lock);
649 }
650 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530651 pthread_mutex_lock(&qaf_module->lock);
652 if ((device == (AUDIO_DEVICE_OUT_AUX_DIGITAL | AUDIO_COMPRESSED_OUT_DD)) ||
653 (device == (AUDIO_DEVICE_OUT_AUX_DIGITAL | AUDIO_COMPRESSED_OUT_DDP))) {
654
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530655 if (NULL == qaf_mod->qaf_compr_passthrough_out && qaf_mod->hdmi_connect) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530656 struct audio_config config;
657 audio_devices_t devices;
658
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530659 if (qaf_mod->qaf_compr_offload_out_mch) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530660 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev,
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530661 (struct audio_stream_out *) (qaf_mod->qaf_compr_offload_out_mch));
662 qaf_mod->qaf_compr_offload_out_mch = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530663 }
664
665 config.sample_rate = config.offload_info.sample_rate = QAF_OUTPUT_SAMPLING_RATE;
666 config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
667 config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
668
669 if (device == (AUDIO_DEVICE_OUT_AUX_DIGITAL | AUDIO_COMPRESSED_OUT_DDP))
670 config.format = config.offload_info.format = AUDIO_FORMAT_E_AC3;
671 else
672 config.format = config.offload_info.format = AUDIO_FORMAT_AC3;
673
674 config.offload_info.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
675 config.offload_info.channel_mask = config.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530676 flags = AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_DIRECT_PCM;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530677 devices = AUDIO_DEVICE_OUT_AUX_DIGITAL;
678
679 ret = adev_open_output_stream((struct audio_hw_device *) qaf_mod->adev, QAF_DEFAULT_COMPR_PASSTHROUGH_HANDLE, devices,
680 flags, &config, (struct audio_stream_out **) &(qaf_mod->qaf_compr_passthrough_out), NULL);
681 if (ret < 0) {
682 ALOGE("%s: adev_open_output_stream failed with ret = %d!", __func__, ret);
683 pthread_mutex_unlock(&qaf_module->lock);
684 return;
685 }
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530686 qaf_mod->qaf_compr_passthrough_out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530687 }
688
689 if (!qaf_mod->passthrough_enabled)
690 qaf_mod->passthrough_enabled = 1;
691
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530692 if (qaf_mod->qaf_compr_passthrough_out)
693 ret = qaf_mod->qaf_compr_passthrough_out->stream.write((struct audio_stream_out *) qaf_mod->qaf_compr_passthrough_out, buf, size);
694 } else if ((device & AUDIO_DEVICE_OUT_AUX_DIGITAL) && ((qaf_mod->hdmi_connect) &&
695 (qaf_mod->qaf_passthrough_out == NULL) && (qaf_mod->hdmi_sink_channels > 2))) {
696 if (NULL == qaf_mod->qaf_compr_offload_out_mch) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530697 struct audio_config config;
698 audio_devices_t devices;
699
700 config.sample_rate = config.offload_info.sample_rate = QAF_OUTPUT_SAMPLING_RATE;
701 config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
702 config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530703 config.offload_info.format = AUDIO_FORMAT_PCM_16_BIT;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530704 config.offload_info.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530705 config.format = AUDIO_FORMAT_PCM_16_BIT;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530706 devices = AUDIO_DEVICE_NONE;
707
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530708 if (qaf_mod->hdmi_sink_channels == 8) {
709 config.offload_info.channel_mask = config.channel_mask = AUDIO_CHANNEL_OUT_7POINT1;
710 } else if (qaf_mod->hdmi_sink_channels == 6) {
711 config.offload_info.channel_mask = config.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530712 } else {
713 config.offload_info.channel_mask = config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530714 }
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530715 devices = AUDIO_DEVICE_OUT_AUX_DIGITAL;
716 flags = AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_DIRECT_PCM;
717
718 ret = adev_open_output_stream((struct audio_hw_device *) qaf_mod->adev, QAF_DEFAULT_COMPR_AUDIO_HANDLE, devices,
719 flags, &config, (struct audio_stream_out **) &(qaf_mod->qaf_compr_offload_out_mch), NULL);
720 if (ret < 0) {
721 ALOGE("%s: adev_open_output_stream failed with ret = %d!", __func__, ret);
722 pthread_mutex_unlock(&qaf_module->lock);
723 return;
724 }
725 qaf_mod->qaf_compr_offload_out_mch->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
726 }
727
728 if (qaf_mod->qaf_compr_offload_out_mch)
729 ret = qaf_mod->qaf_compr_offload_out_mch->stream.write((struct audio_stream_out *) qaf_mod->qaf_compr_offload_out_mch, buf, size);
730 } else {
Bharath Gopal01310bb2016-12-05 15:39:32 +0530731 bt_stream = audio_extn_bt_hal_get_output_stream(qaf_mod->bt_hdl);
732 if (bt_stream != NULL) {
733 if (qaf_mod->qaf_compr_offload_out) {
734 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev,
735 (struct audio_stream_out *) (qaf_mod->qaf_compr_offload_out));
736 qaf_mod->qaf_compr_offload_out = NULL;
737 }
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530738
Bharath Gopal01310bb2016-12-05 15:39:32 +0530739 audio_extn_bt_hal_out_write(qaf_mod->bt_hdl, buf, size);
740 }
741
742 if (NULL == qaf_mod->qaf_compr_offload_out && bt_stream == NULL && qaf_mod->qaf_passthrough_out == NULL) {
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530743 struct audio_config config;
744 audio_devices_t devices;
745
746 config.sample_rate = config.offload_info.sample_rate = QAF_OUTPUT_SAMPLING_RATE;
747 config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
748 config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
749 config.offload_info.format = AUDIO_FORMAT_PCM_16_BIT;
750 config.offload_info.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
751 config.format = AUDIO_FORMAT_PCM_16_BIT;
752 config.offload_info.channel_mask = config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
753 devices = AUDIO_DEVICE_OUT_SPEAKER;
754 flags = AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_DIRECT_PCM;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530755
756 /* TODO:: Need to Propagate errors to framework */
757 ret = adev_open_output_stream((struct audio_hw_device *) qaf_mod->adev, QAF_DEFAULT_COMPR_AUDIO_HANDLE, devices,
758 flags, &config, (struct audio_stream_out **) &(qaf_mod->qaf_compr_offload_out), NULL);
759 if (ret < 0) {
760 ALOGE("%s: adev_open_output_stream failed with ret = %d!", __func__, ret);
761 pthread_mutex_unlock(&qaf_module->lock);
762 return;
763 }
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530764 qaf_mod->qaf_compr_offload_out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
765 qaf_mod->qaf_compr_offload_out->info.channel_mask = config.offload_info.channel_mask;
766 qaf_mod->qaf_compr_offload_out->info.format = config.offload_info.format;
767 qaf_mod->qaf_compr_offload_out->info.sample_rate = config.offload_info.sample_rate;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530768 }
769
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530770 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 +0530771 qaf_mod->passthrough_enabled = 0;
772 if (qaf_mod->qaf_compr_passthrough_out) {
773 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev,
774 (struct audio_stream_out *) (qaf_mod->qaf_compr_passthrough_out));
775 qaf_mod->qaf_compr_passthrough_out = NULL;
776 }
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530777 if (qaf_mod->qaf_compr_offload_out_mch) {
778 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev,
779 (struct audio_stream_out *) (qaf_mod->qaf_compr_offload_out_mch));
780 qaf_mod->qaf_compr_offload_out_mch = NULL;
781 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530782 }
783
784 /*
785 * TODO:: Since this is mixed data,
786 * need to identify to which stream the error should be sent
787 */
Bharath Gopal01310bb2016-12-05 15:39:32 +0530788 if (bt_stream == NULL && qaf_mod->qaf_compr_offload_out)
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530789 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 +0530790 }
791
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530792 ALOGVV("%s:%d stream write ret = %d", __func__, __LINE__, ret);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530793 pthread_mutex_unlock(&qaf_module->lock);
794 } else if (event_id == AUDIO_EOS_MAIN_DD_DDP_EVENT || event_id == AUDIO_EOS_MAIN_AAC_EVENT) {
795 /* TODO:: Only MAIN Stream EOS Event is added, need to add ASSOC stream EOS Event */
796 struct stream_out *out = qaf_module->stream_drain_main;
797 if (out != NULL) {
798 lock_output_stream(out);
799 out->offload_callback(STREAM_CBK_EVENT_DRAIN_READY, NULL, out->offload_cookie);
800 pthread_mutex_unlock(&out->lock);
801 qaf_module->stream_drain_main = NULL;
802 ALOGV("%s %d sent DRAIN_READY", __func__, __LINE__);
803 }
804 }
805 ALOGV("%s %d", __func__, __LINE__);
806}
807
808static int qaf_session_close()
809{
810 ALOGV("%s %d", __func__, __LINE__);
811 if (qaf_mod != NULL) {
812 if (!qaf_mod->qaf_audio_session_close)
813 return -EINVAL;
814
815 qaf_mod->qaf_audio_session_close(qaf_mod->session_handle);
816 qaf_mod->session_handle = NULL;
817 pthread_mutex_destroy(&qaf_mod->lock);
818 }
819 return 0;
820}
821
822static int qaf_stream_close(struct stream_out *out)
823{
824 int ret = 0;
825 ALOGV( "%s %d", __func__, __LINE__);
826 if (!qaf_mod->qaf_audio_stream_close)
827 return -EINVAL;
828 if (out->qaf_stream_handle) {
829 ALOGV( "%s %d output active flag is %x and stream handle %p", __func__, __LINE__, out->flags, out->qaf_stream_handle);
830 if ((out->flags & AUDIO_OUTPUT_FLAG_ASSOCIATED) && (out->flags & AUDIO_OUTPUT_FLAG_MAIN)) { /* Close for Stream with Main and Associated Content*/
831 qaf_mod->main_output_active = false;
832 qaf_mod->assoc_output_active = false;
833 } else if (out->flags & AUDIO_OUTPUT_FLAG_MAIN) {/*Close for Main Stream*/
834 qaf_mod->main_output_active = false;
835 qaf_mod->assoc_output_active = false; /* TODO to remove resetting associated stream active flag when main stream is closed*/
836 } else if (out->flags & AUDIO_OUTPUT_FLAG_ASSOCIATED) { /*Close for Associated Stream*/
837 qaf_mod->assoc_output_active = false;
838 } else { /*Close for Local Playback*/
839 qaf_mod->main_output_active = false;
840 }
841 ret = qaf_mod->qaf_audio_stream_close(out->qaf_stream_handle);
842 out->qaf_stream_handle = NULL;
843 }
844 ALOGV( "%s %d", __func__, __LINE__);
845 return ret;
846}
847
848static int qaf_stream_open(struct stream_out *out, struct audio_config *config, audio_output_flags_t flags, audio_devices_t devices)
849{
850 int status = 0;
851 ALOGV("%s %d", __func__, __LINE__);
852
853 if (!qaf_mod->qaf_audio_stream_open)
854 return -EINVAL;
855
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530856 if (audio_extn_qaf_passthrough_enabled(out) && qaf_mod->hdmi_connect) {
857 ALOGV("%s %d passthrough is enabled", __func__, __LINE__);
858 status = create_output_stream(out, config, flags, devices, QAF_DEFAULT_PASSTHROUGH_HANDLE);
859 if (status < 0) {
860 ALOGE("%s: adev_open_output_stream failed with ret = %d!", __func__, status);
861 return -EINVAL;
862 }
863 return 0;
864 }
865
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530866 audio_stream_config_t input_config;
867 input_config.sample_rate = config->sample_rate;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530868 input_config.channels = popcount(config->channel_mask);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530869 input_config.format = config->format;
870
871 if ((config->format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC) {
872 input_config.format = AUDIO_FORMAT_AAC;
873 } else if((config->format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS) {
874 input_config.format = AUDIO_FORMAT_AAC_ADTS;
875 }
876
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530877 ALOGV("%s %d audio_stream_open sample_rate(%d) channels(%d) devices(%#x) flags(%#x) format(%#x)\
878 ",__func__, __LINE__, input_config.sample_rate, input_config.channels, devices, flags, input_config.format);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530879
880 /* TODO to send appropriated flags when support for system tones is added */
881 if (input_config.format == AUDIO_FORMAT_PCM_16_BIT) {
882 status = qaf_mod->qaf_audio_stream_open(qaf_mod->session_handle, &out->qaf_stream_handle, input_config, devices, /*flags*/AUDIO_STREAM_SYSTEM_TONE);
883 } else if (input_config.format == AUDIO_FORMAT_AC3 ||
884 input_config.format == AUDIO_FORMAT_E_AC3 ||
885 input_config.format == AUDIO_FORMAT_AAC ||
886 input_config.format == AUDIO_FORMAT_AAC_ADTS) {
887 if (qaf_mod->main_output_active == false) {
888 if ((flags & AUDIO_OUTPUT_FLAG_MAIN) && (flags & AUDIO_OUTPUT_FLAG_ASSOCIATED)) {
889 status = qaf_mod->qaf_audio_stream_open(qaf_mod->session_handle, &out->qaf_stream_handle, input_config, devices, /*flags*/AUDIO_STREAM_MAIN);
890 if (status == 0) {
891 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);
892 qaf_mod->main_output_active = true;
893 qaf_mod->assoc_output_active = true;
894 }
895 } else if (flags & AUDIO_OUTPUT_FLAG_MAIN) {
896 status = qaf_mod->qaf_audio_stream_open(qaf_mod->session_handle, &out->qaf_stream_handle, input_config, devices, /*flags*/AUDIO_STREAM_MAIN);
897 if (status == 0) {
898 ALOGV("%s %d Open stream for Input with only Main flag [%x] stream handle [%p]", __func__, __LINE__, flags, out->qaf_stream_handle);
899 qaf_mod->main_output_active = true;
900 }
901 } else if (flags & AUDIO_OUTPUT_FLAG_ASSOCIATED) {
902 ALOGE("%s %d Error main input is not active", __func__, __LINE__);
903 return -EINVAL;
904 } else {
905 status = qaf_mod->qaf_audio_stream_open(qaf_mod->session_handle, &out->qaf_stream_handle, input_config, devices, /*flags*/AUDIO_STREAM_MAIN);
906 if (status == 0) {
907 ALOGV("%s %d Open stream for Local playback with flag [%x] stream handle [%p] ", __func__, __LINE__, flags, out->qaf_stream_handle);
908 qaf_mod->main_output_active = true;
909 }
910 }
911 } else {
912 if (flags & AUDIO_OUTPUT_FLAG_MAIN) {
913 ALOGE("%s %d Error main input is already active", __func__, __LINE__);
914 return -EINVAL;
915 } else if (flags & AUDIO_OUTPUT_FLAG_ASSOCIATED) {
916 if (qaf_mod->assoc_output_active) {
917 ALOGE("%s %d Error assoc input is already active", __func__, __LINE__);
918 return -EINVAL;
919 } else {
920 status = qaf_mod->qaf_audio_stream_open(qaf_mod->session_handle, &out->qaf_stream_handle, input_config, devices, /*flags*/AUDIO_STREAM_ASSOCIATED);
921 if (status == 0) {
922 ALOGV("%s %d Open stream for Input with only Associated flag [%x] stream handle [%p]", __func__, __LINE__, flags, out->qaf_stream_handle);
923 qaf_mod->assoc_output_active = true;
924 }
925 }
926 } else {
927 ALOGE("%s %d Error main input is already active", __func__, __LINE__);
928 return -EINVAL;
929 }
930 }
931 }
932
933 return status;
934}
935
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530936static int audio_extn_qaf_stream_open(struct stream_out *out)
937{
938 int status = -ENOSYS;
939 struct audio_config config;
940 audio_devices_t devices;
941
942 config.sample_rate = config.offload_info.sample_rate = QAF_OUTPUT_SAMPLING_RATE;
943 config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
944 config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
945 config.offload_info.format = out->format;
946 config.offload_info.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
947 config.format = out->format;
948 config.offload_info.channel_mask = config.channel_mask = out->channel_mask;
949
950 devices = AUDIO_DEVICE_OUT_SPEAKER;
951 status = qaf_stream_open(out, &config, out->flags, devices);
952 ALOGV("%s %d status %d", __func__, __LINE__, status);
953 return status;
954}
955
956static int qaf_out_resume(struct audio_stream_out* stream)
957{
958 struct stream_out *out = (struct stream_out *)stream;
959 int status = -ENOSYS;
960 ALOGV("%s", __func__);
961 lock_output_stream(out);
962 if ((!property_get_bool("audio.qaf.reencode", false)) &&
963 property_get_bool("audio.qaf.passthrough", false)) {
964 if (property_get_bool("audio.offload.passthrough", false)) {
965 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect &&
966 (((out->format == AUDIO_FORMAT_E_AC3) && platform_is_edid_supported_format(qaf_mod->adev->platform, AUDIO_FORMAT_E_AC3)) ||
967 ((out->format == AUDIO_FORMAT_AC3) && platform_is_edid_supported_format(qaf_mod->adev->platform, AUDIO_FORMAT_AC3)))) {
968 status = qaf_mod->qaf_passthrough_out->stream.resume((struct audio_stream_out*) qaf_mod->qaf_passthrough_out);
969 if (!status)
970 out->offload_state = OFFLOAD_STATE_PLAYING;
971 pthread_mutex_unlock(&out->lock);
972 return status;
973 } else {
974 if ((out->format == AUDIO_FORMAT_E_AC3) || (out->format == AUDIO_FORMAT_AC3)) {
975 status = audio_extn_qaf_stream_open(out);
976 if (!status)
977 out->offload_state = OFFLOAD_STATE_PLAYING;
978 out->offload_callback(STREAM_CBK_EVENT_WRITE_READY, NULL, out->offload_cookie);
979 }
980 }
981 } else {
982 if ((out->format == AUDIO_FORMAT_PCM_16_BIT) && (popcount(out->channel_mask) > 2)) {
983 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
984 status = qaf_mod->qaf_passthrough_out->stream.resume((struct audio_stream_out*) qaf_mod->qaf_passthrough_out);
985 if (!status)
986 out->offload_state = OFFLOAD_STATE_PLAYING;
987 pthread_mutex_unlock(&out->lock);
988 return status;
989 }
990 }
991 }
992 }
993
994 status = qaf_stream_start(out);
995 pthread_mutex_unlock(&out->lock);
996 ALOGD("%s Exit", __func__);
997 return status;
998}
999
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301000static int qaf_deinit()
1001{
1002 ALOGV("%s %d", __func__, __LINE__);
1003 if (qaf_mod != NULL) {
1004 if (qaf_mod->qaf_compr_offload_out != NULL)
1005 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev, (struct audio_stream_out *) (qaf_mod->qaf_compr_offload_out));
1006 if (qaf_mod->qaf_compr_passthrough_out != NULL)
1007 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev, (struct audio_stream_out *) (qaf_mod->qaf_compr_passthrough_out));
1008
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301009 if (qaf_mod->qaf_passthrough_out) {
1010 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev, (struct audio_stream_out *) (qaf_mod->qaf_passthrough_out));
1011 qaf_mod->qaf_passthrough_out = NULL;
1012 }
1013
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301014 if (qaf_mod->qaf_lib != NULL) {
1015 dlclose(qaf_mod->qaf_lib);
1016 qaf_mod->qaf_lib = NULL;
1017 }
1018 free(qaf_mod);
1019 qaf_mod = NULL;
1020 }
1021 return 0;
1022}
1023
1024static void *qaf_offload_thread_loop(void *context)
1025{
1026 struct stream_out *out = (struct stream_out *) context;
1027 struct listnode *item;
1028 int ret = 0;
1029 struct str_parms *parms = NULL;
1030 int value = 0;
1031 char* kvpairs = NULL;
1032
1033 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1034 set_sched_policy(0, SP_FOREGROUND);
1035 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1036
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301037 ALOGV("%s", __func__);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301038 lock_output_stream(out);
1039 for (;;) {
1040 struct offload_cmd *cmd = NULL;
1041 stream_callback_event_t event;
1042 bool send_callback = false;
1043
1044 ALOGV("%s qaf_offload_cmd_list %d",
1045 __func__, list_empty(&out->qaf_offload_cmd_list));
1046 if (list_empty(&out->qaf_offload_cmd_list)) {
1047 ALOGV("%s SLEEPING", __func__);
1048 pthread_cond_wait(&out->qaf_offload_cond, &out->lock);
1049 ALOGV("%s RUNNING", __func__);
1050 continue;
1051 }
1052
1053 item = list_head(&out->qaf_offload_cmd_list);
1054 cmd = node_to_item(item, struct offload_cmd, node);
1055 list_remove(item);
1056
1057 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1058 free(cmd);
1059 break;
1060 }
1061
1062 pthread_mutex_unlock(&out->lock);
1063 send_callback = false;
1064 switch(cmd->cmd) {
1065 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1066 ALOGV("wait for ms12 buffer availability");
1067 while (1) {
1068 kvpairs = qaf_mod->qaf_audio_stream_get_param(out->qaf_stream_handle, "buf_available");
1069 if (kvpairs) {
1070 parms = str_parms_create_str(kvpairs);
1071 ret = str_parms_get_int(parms, "buf_available", &value);
1072 if (ret >= 0) {
1073 if (value >= (int)out->compr_config.fragment_size) {
1074 ALOGV("%s buffer available", __func__);
1075 str_parms_destroy(parms);
1076 parms = NULL;
1077 break;
1078 } else {
1079 ALOGV("%s sleep", __func__);
1080 str_parms_destroy(parms);
1081 parms = NULL;
1082 usleep(10000);
1083 }
1084 }
1085 free(kvpairs);
1086 kvpairs = NULL;
1087 }
1088 }
1089 send_callback = true;
1090 event = STREAM_CBK_EVENT_WRITE_READY;
1091 break;
1092 default:
1093 ALOGV("%s unknown command received: %d", __func__, cmd->cmd);
1094 break;
1095 }
1096 lock_output_stream(out);
1097 if (send_callback && out->offload_callback) {
1098 out->offload_callback(event, NULL, out->offload_cookie);
1099 }
1100 free(cmd);
1101 }
1102
1103 while (!list_empty(&out->qaf_offload_cmd_list)) {
1104 item = list_head(&out->qaf_offload_cmd_list);
1105 list_remove(item);
1106 free(node_to_item(item, struct offload_cmd, node));
1107 }
1108 pthread_mutex_unlock(&out->lock);
1109
1110 return NULL;
1111}
1112
1113static int qaf_create_offload_callback_thread(struct stream_out *out)
1114{
1115 ALOGV("%s", __func__);
1116 pthread_cond_init(&out->qaf_offload_cond, (const pthread_condattr_t *) NULL);
1117 list_init(&out->qaf_offload_cmd_list);
1118 pthread_create(&out->qaf_offload_thread, (const pthread_attr_t *) NULL,
1119 qaf_offload_thread_loop, out);
1120 return 0;
1121}
1122
1123static int qaf_destroy_offload_callback_thread(struct stream_out *out)
1124{
1125 ALOGV("%s", __func__);
1126 lock_output_stream(out);
1127 qaf_send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1128 pthread_mutex_unlock(&out->lock);
1129
1130 pthread_join(out->qaf_offload_thread, (void **) NULL);
1131 pthread_cond_destroy(&out->qaf_offload_cond);
1132
1133 return 0;
1134}
1135
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301136static int qaf_out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1137{
1138 struct str_parms *parms, *new_parms;
1139 char value[32];
1140 char *new_kv_pairs;
1141 int val = 0;
1142 struct stream_out *out = (struct stream_out *)stream;
1143 int ret = 0;
1144 int err = 0;
1145
1146 ALOGV("%s: enter: usecase(%d: %s) kvpairs: %s",
1147 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
1148 if ((NULL != qaf_mod->qaf_compr_offload_out)) {
1149 if (qaf_mod->qaf_msmd_enabled) {
1150 if (qaf_mod->passthrough_enabled && qaf_mod->hdmi_connect)
1151 return 1;
1152
1153 parms = str_parms_create_str(kvpairs);
1154 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1155
1156 /* usecase : hdmi sink which supports only 2-channel pcm */
1157 if (err >= 0) {
1158 val = atoi(value);
1159 if ((val & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1160 ((qaf_mod->hdmi_sink_channels == 2) && !(qaf_mod->passthrough_enabled))) {
1161 new_parms = str_parms_create();
1162 val |= AUDIO_DEVICE_OUT_SPEAKER;
1163 str_parms_add_int(new_parms, AUDIO_PARAMETER_STREAM_ROUTING, val);
1164 new_kv_pairs = str_parms_to_str(new_parms);
1165 qaf_mod->qaf_compr_offload_out->stream.common.set_parameters((struct audio_stream *) qaf_mod->qaf_compr_offload_out, new_kv_pairs);
1166 free(new_kv_pairs);
1167 str_parms_destroy(new_parms);
1168 }
1169 }
1170 str_parms_destroy(parms);
1171 } else {
1172 if (!(qaf_mod->passthrough_enabled && qaf_mod->hdmi_connect))
1173 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 +05301174
1175 parms = str_parms_create_str(kvpairs);
1176 if (!parms) {
1177 ALOGE("str_parms_create_str failed!");
1178 } else {
1179 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1180 if (err >= 0) {
1181 val = atoi(value);
1182 if (val == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) { //BT routing
1183 if (audio_extn_bt_hal_get_output_stream(qaf_mod->bt_hdl) == NULL && audio_extn_bt_hal_get_device(qaf_mod->bt_hdl) != NULL) {
1184 ret = audio_extn_bt_hal_open_output_stream(qaf_mod->bt_hdl,
1185 QAF_OUTPUT_SAMPLING_RATE,
1186 AUDIO_CHANNEL_OUT_STEREO,
1187 CODEC_BACKEND_DEFAULT_BIT_WIDTH);
1188 if (ret != 0) {
1189 ALOGE("%s: BT Output stream open failure!", __FUNCTION__);
1190 }
1191 }
1192 } else if (val != 0) {
1193 if (audio_extn_bt_hal_get_output_stream(qaf_mod->bt_hdl)!= NULL) {
1194 audio_extn_bt_hal_close_output_stream(qaf_mod->bt_hdl);
1195 }
1196 }
1197 }
1198 str_parms_destroy(parms);
1199 }
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301200 }
1201 }
1202
1203 if (audio_extn_qaf_passthrough_enabled(out)) {
1204 parms = str_parms_create_str(kvpairs);
1205 if (!parms) {
1206 ALOGE("str_parms_create_str failed!");
1207 } else {
1208 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1209 if (err >= 0) {
1210 val = atoi(value);
1211 if ((val & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1212 (qaf_mod->qaf_passthrough_out == NULL)) {
1213 audio_output_flags_t flags;
1214 struct audio_config config;
1215 audio_devices_t devices;
1216
1217 config.sample_rate = config.offload_info.sample_rate = QAF_OUTPUT_SAMPLING_RATE;
1218 config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
1219 config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
1220 config.offload_info.format = out->format;
1221 config.offload_info.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
1222 config.format = out->format;
1223 config.offload_info.channel_mask = config.channel_mask = out->channel_mask;
1224
1225 devices = AUDIO_DEVICE_OUT_AUX_DIGITAL;
1226 flags = out->flags;
1227
1228 if (out->qaf_stream_handle) {
1229 qaf_out_pause((struct audio_stream_out*)out);
1230 qaf_out_flush((struct audio_stream_out*)out);
1231 qaf_out_drain((struct audio_stream_out*)out, (audio_drain_type_t)STREAM_CBK_EVENT_DRAIN_READY);
1232 qaf_stream_close(out);
1233 }
1234 create_output_stream(out, &config, flags, devices, QAF_DEFAULT_PASSTHROUGH_HANDLE);
1235 qaf_mod->main_output_active = true;
1236 }
1237 }
1238 str_parms_destroy(parms);
1239 }
1240 }
1241
1242 return ret;
1243}
1244
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301245int audio_extn_qaf_open_output_stream(struct audio_hw_device *dev,
1246 audio_io_handle_t handle,
1247 audio_devices_t devices,
1248 audio_output_flags_t flags,
1249 struct audio_config *config,
1250 struct audio_stream_out **stream_out,
1251 const char *address __unused)
1252{
1253 int ret = 0;
1254 struct stream_out *out;
1255
1256 ret = adev_open_output_stream(dev, handle, devices, flags, config, stream_out, address);
1257 if (*stream_out == NULL) {
1258 goto error_open;
1259 }
1260
1261 out = (struct stream_out *) *stream_out;
1262
1263 /* Override function pointers based on qaf definitions */
1264 out->stream.set_volume = qaf_out_set_volume;
1265 out->stream.pause = qaf_out_pause;
1266 out->stream.resume = qaf_out_resume;
1267 out->stream.drain = qaf_out_drain;
1268 out->stream.flush = qaf_out_flush;
1269
1270 out->stream.common.standby = qaf_out_standby;
1271 out->stream.common.set_parameters = qaf_out_set_parameters;
1272 out->stream.get_latency = qaf_out_get_latency;
1273 out->stream.write = qaf_out_write;
1274 out->stream.get_presentation_position = qaf_out_get_presentation_position;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301275 out->platform_latency = 0;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301276 ret = qaf_stream_open(out, config, flags, devices);
1277 if (ret < 0) {
1278 ALOGE("%s, Error opening QAF stream err[%d]!", __func__, ret);
1279 adev_close_output_stream(dev, *stream_out);
1280 goto error_open;
1281 }
1282
1283 if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY) {
1284 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
1285 out->config.period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE;
1286 out->config.period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT;
1287 out->config.start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4;
1288 out->config.avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4;
1289 }
1290
1291 *stream_out = &out->stream;
1292 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
1293 qaf_create_offload_callback_thread(out);
1294 }
1295 ALOGV("%s: exit", __func__);
1296 return 0;
1297error_open:
1298 *stream_out = NULL;
1299 ALOGD("%s: exit: ret %d", __func__, ret);
1300 return ret;
1301}
1302
1303void audio_extn_qaf_close_output_stream(struct audio_hw_device *dev,
1304 struct audio_stream_out *stream)
1305{
1306 struct stream_out *out = (struct stream_out *)stream;
1307
1308 ALOGV("%s: enter:stream_handle(%p) format = %x", __func__, out, out->format);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301309 if (qaf_mod->qaf_passthrough_out) {
1310 ALOGD("%s %d closing stream handle %p", __func__, __LINE__, qaf_mod->qaf_passthrough_out);
1311 pthread_mutex_lock(&qaf_mod->lock);
1312 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev, (struct audio_stream_out *) (qaf_mod->qaf_passthrough_out));
1313 adev_close_output_stream(dev, stream);
1314 qaf_mod->qaf_passthrough_out = NULL;
1315 qaf_mod->main_output_active = false;
1316 pthread_mutex_unlock(&qaf_mod->lock);
1317 return;
1318 }
1319
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301320 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
1321 qaf_destroy_offload_callback_thread(out);
1322 }
1323 qaf_mod->stream_drain_main = NULL;
1324 lock_output_stream(out);
1325 qaf_stream_close(out);
1326 pthread_mutex_unlock(&out->lock);
1327
1328 adev_close_output_stream(dev, stream);
1329 ALOGV("%s: exit", __func__);
1330}
1331
1332bool audio_extn_qaf_is_enabled()
1333{
1334 bool prop_enabled = false;
1335 char value[PROPERTY_VALUE_MAX] = {0};
1336 property_get("audio.qaf.enabled", value, NULL);
1337 prop_enabled = atoi(value) || !strncmp("true", value, 4);
1338 return (prop_enabled);
1339}
1340
1341int audio_extn_qaf_session_open(struct qaf *qaf_mod,
1342 device_license_config_t* lic_config)
1343{
1344 ALOGV("%s %d", __func__, __LINE__);
1345 int status = -ENOSYS;
1346
1347 pthread_mutex_init(&qaf_mod->lock, (const pthread_mutexattr_t *) NULL);
1348
1349 if (!qaf_mod->qaf_audio_session_open)
1350 return -EINVAL;
1351
1352 status = qaf_mod->qaf_audio_session_open(&qaf_mod->session_handle,
1353 (void *)(qaf_mod), (void *)lic_config);
1354 if(status < 0)
1355 return status;
1356
1357 if (qaf_mod->session_handle == NULL) {
1358 ALOGE("%s %d QAF wrapper session handle is NULL", __func__, __LINE__);
1359 return -ENOMEM;
1360 }
1361 if (qaf_mod->qaf_register_event_callback)
1362 qaf_mod->qaf_register_event_callback(qaf_mod->session_handle,
1363 qaf_mod, &notify_event_callback,
1364 AUDIO_DATA_EVENT);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301365
1366 if (property_get_bool("audio.qaf.msmd", false)) {
1367 qaf_mod->qaf_msmd_enabled = 1;
1368 }
1369
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301370 return status;
1371}
1372
1373char* audio_extn_qaf_stream_get_param(struct stream_out *out __unused, const char *kv_pair __unused)
1374{
1375 return NULL;
1376}
1377
1378int audio_extn_qaf_set_parameters(struct audio_device *adev, struct str_parms *parms)
1379{
1380 int status = 0, val = 0, channels = 0;
1381 char *format_params, *kv_parirs;
1382 struct str_parms *qaf_params;
1383 char value[32];
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301384 char prop_value[PROPERTY_VALUE_MAX];
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301385 bool passth_support = false;
1386
1387 ALOGV("%s %d ", __func__, __LINE__);
1388 if (!qaf_mod || !qaf_mod->qaf_audio_session_set_param) {
1389 return -EINVAL;
1390 }
1391
1392 status = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
1393 if (status >= 0) {
1394 val = atoi(value);
1395 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1396 if (property_get_bool("audio.offload.passthrough", false) &&
1397 property_get_bool("audio.qaf.reencode", false)) {
1398
1399 qaf_params = str_parms_create();
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301400 property_get("audio.qaf.hdmi.out", prop_value, NULL);
1401 if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_E_AC3) &&
1402 (strncmp(prop_value, "ddp", 3) == 0)) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301403 passth_support = true;
1404 if (qaf_params) {
1405 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_RENDER_FORMAT,
1406 AUDIO_QAF_PARAMETER_VALUE_REENCODE_EAC3);
1407 }
1408 } else if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_AC3)) {
1409 passth_support = true;
1410 if (qaf_params) {
1411 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_RENDER_FORMAT,
1412 AUDIO_QAF_PARAMETER_VALUE_REENCODE_AC3);
1413 }
1414 }
1415
1416 if (passth_support) {
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301417 qaf_mod->passthrough_enabled = 1;
1418 if (qaf_mod->qaf_msmd_enabled) {
1419 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1420 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI_AND_SPK);
1421 } else {
1422 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1423 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI);
1424 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301425 format_params = str_parms_to_str(qaf_params);
1426
1427 qaf_mod->qaf_audio_session_set_param(qaf_mod->session_handle, format_params);
1428 }
1429 str_parms_destroy(qaf_params);
1430 }
1431
1432 if (!passth_support) {
1433 channels = platform_edid_get_max_channels(adev->platform);
1434
1435 qaf_params = str_parms_create();
1436 switch (channels) {
1437 case 8:
1438 ALOGV("%s: Switching Qaf output to 7.1 channels", __func__);
1439 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_CHANNELS,
1440 AUDIO_QAF_PARAMETER_VALUE_8_CHANNELS);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301441 if (qaf_mod->qaf_msmd_enabled) {
1442 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1443 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI_AND_SPK);
1444 } else {
1445 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1446 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI);
1447 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301448 qaf_mod->hdmi_sink_channels = channels;
1449 break;
1450 case 6:
1451 ALOGV("%s: Switching Qaf output to 5.1 channels", __func__);
1452 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_CHANNELS,
1453 AUDIO_QAF_PARAMETER_VALUE_6_CHANNELS);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301454 if (qaf_mod->qaf_msmd_enabled) {
1455 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1456 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI_AND_SPK);
1457 } else {
1458 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1459 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI);
1460 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301461 qaf_mod->hdmi_sink_channels = channels;
1462 break;
1463 default:
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301464 ALOGV("%s: Switching Qaf output to default channels", __func__);
1465 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_CHANNELS,
1466 AUDIO_QAF_PARAMETER_VALUE_DEFAULT_CHANNELS);
1467 if (qaf_mod->qaf_msmd_enabled) {
1468 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1469 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI_AND_SPK);
1470 } else {
1471 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1472 AUDIO_QAF_PARAMETER_VALUE_DEVICE_SPEAKER);
1473 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301474 qaf_mod->hdmi_sink_channels = 2;
1475 break;
1476 }
1477
1478 format_params = str_parms_to_str(qaf_params);
1479 qaf_mod->qaf_audio_session_set_param(qaf_mod->session_handle, format_params);
1480 str_parms_destroy(qaf_params);
1481 }
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301482 qaf_mod->hdmi_connect = 1;
Bharath Gopal01310bb2016-12-05 15:39:32 +05301483 } else if (val & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) {
1484 ALOGV("%s: Opening a2dp output...", __FUNCTION__);
1485 status = audio_extn_bt_hal_load(&qaf_mod->bt_hdl);
1486 if(status != 0) {
1487 ALOGE("%s:Error opening BT module", __FUNCTION__);
1488 return status;
1489 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301490 }
1491 }
1492
1493 status = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
1494 if (status >= 0) {
1495 val = atoi(value);
1496 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1497 qaf_params = str_parms_create();
1498 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1499 AUDIO_QAF_PARAMETER_VALUE_DEVICE_SPEAKER);
1500 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_RENDER_FORMAT,
1501 AUDIO_QAF_PARAMETER_VALUE_PCM);
1502 qaf_mod->hdmi_sink_channels = 0;
1503
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301504 qaf_mod->passthrough_enabled = 0;
1505 qaf_mod->hdmi_connect = 0;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301506 format_params = str_parms_to_str(qaf_params);
1507 qaf_mod->qaf_audio_session_set_param(qaf_mod->session_handle, format_params);
1508 str_parms_destroy(qaf_params);
Bharath Gopal01310bb2016-12-05 15:39:32 +05301509 } else if (val & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) {
1510 ALOGV("%s: Closing a2dp output...", __FUNCTION__);
1511 audio_extn_bt_hal_unload(qaf_mod->bt_hdl);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301512 }
1513 }
1514
1515 kv_parirs = str_parms_to_str(parms);
1516 qaf_mod->qaf_audio_session_set_param(qaf_mod->session_handle, kv_parirs);
1517
1518 return status;
1519}
1520
1521char* audio_extn_qaf_get_param(struct audio_device *adev __unused, const char *kv_pair __unused)
1522{
1523 return 0;
1524}
1525
1526int audio_extn_qaf_init(struct audio_device *adev)
1527{
1528 char value[PROPERTY_VALUE_MAX] = {0};
1529 char lib_name[PROPERTY_VALUE_MAX] = {0};
1530 unsigned char* license_data = NULL;
1531 device_license_config_t* lic_config = NULL;
1532 ALOGV("%s %d", __func__, __LINE__);
1533 int ret = 0, size = 0;
1534
1535 qaf_mod = malloc(sizeof(struct qaf));
1536 if(qaf_mod == NULL) {
1537 ALOGE("%s, out of memory", __func__);
1538 ret = -ENOMEM;
1539 goto done;
1540 }
1541 memset(qaf_mod, 0, sizeof(struct qaf));
1542 lic_config = (device_license_config_t*) calloc(1, sizeof(device_license_config_t));
1543 if(lic_config == NULL) {
1544 ALOGE("%s, out of memory", __func__);
1545 ret = -ENOMEM;
1546 goto done;
1547 }
1548 qaf_mod->adev = adev;
1549 property_get("audio.qaf.library", value, NULL);
1550 snprintf(lib_name, PROPERTY_VALUE_MAX, "%s", value);
1551
1552 license_data = platform_get_license((struct audio_hw_device *)(qaf_mod->adev->platform), &size);
1553 if (!license_data) {
1554 ALOGE("License is not present");
1555 ret = -EINVAL;
1556 goto done;
1557 }
1558 lic_config->p_license = (unsigned char* ) calloc(1, size);
1559 if(lic_config->p_license == NULL) {
1560 ALOGE("%s, out of memory", __func__);
1561 ret = -ENOMEM;
1562 goto done;
1563 }
1564 lic_config->l_size = size;
1565 memcpy(lic_config->p_license, license_data, size);
1566
1567 if (property_get("audio.qaf.manufacturer", value, "") && atoi(value)) {
1568 lic_config->manufacturer_id = (unsigned long) atoi (value);
1569 } else {
1570 ALOGE("audio.qaf.manufacturer id is not set");
1571 ret = -EINVAL;
1572 goto done;
1573 }
1574
1575 ret = audio_extn_qaf_session_open(qaf_mod, lic_config);
1576done:
1577 if (license_data != NULL) {
1578 free(license_data);
1579 license_data = NULL;
1580 }
1581 if (lic_config->p_license != NULL) {
1582 free(lic_config->p_license);
1583 lic_config->p_license = NULL;
1584 }
1585 if (lic_config != NULL) {
1586 free(lic_config);
1587 lic_config = NULL;
1588 }
1589 if (ret != 0) {
1590 if (qaf_mod != NULL) {
1591 free(qaf_mod);
1592 qaf_mod = NULL;
1593 }
1594 }
1595 return ret;
1596}
1597
1598void audio_extn_qaf_deinit()
1599{
1600 qaf_session_close();
1601 qaf_deinit();
1602}