blob: 5b8827450769698919c6fa2c7833b08d084520af [file] [log] [blame]
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301/*
Varun B34da7a42017-02-13 16:16:53 +05302 * Copyright (c) 2017, The Linux Foundation. All rights reserved.
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#define LOG_TAG "audio_hw_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
Varun B34da7a42017-02-13 16:16:53 +053051
52/* Used in calculating fragment size for pcm offload */
53#define QAF_PCM_OFFLOAD_BUFFER_DURATION 32 /*32 msecs */
54#define MIN_PCM_OFFLOAD_FRAGMENT_SIZE 512
55#define MAX_PCM_OFFLOAD_FRAGMENT_SIZE (240 * 1024)
56
57#define DIV_ROUND_UP(x, y) (((x) + (y) - 1)/(y))
58#define ALIGN(x, y) ((y) * DIV_ROUND_UP((x), (y)))
59
60/* Pcm input node buffer size is 6144 bytes, i.e, 32msec for 48000 samplerate */
61#define MS12_PCM_INPUT_BUFFER_LATENCY 32
62
63/* In msec for 2 fragments of 32ms */
64#define QAF_PCM_OFFLOAD_PLAYBACK_LATENCY \
65 (QAF_PCM_OFFLOAD_BUFFER_DURATION * COMPRESS_OFFLOAD_NUM_FRAGMENTS)
66
67#define PCM_OFFLOAD_PLAYBACK_LATENCY \
68 (MS12_PCM_INPUT_BUFFER_LATENCY + QAF_PCM_OFFLOAD_PLAYBACK_LATENCY)
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +053069
70/*
71 * Buffer size for compress passthrough is 8192 bytes
72 */
73#define COMPRESS_PASSTHROUGH_BUFFER_SIZE \
74 (COMPRESS_OFFLOAD_NUM_FRAGMENTS * COMPRESS_OFFLOAD_FRAGMENT_SIZE)
75/*
76 * Frame size for DD/DDP is 1536 samples corresponding to 32ms.
77 */
78#define DD_FRAME_SIZE 1536
79/*
80 * DD encoder output size for 32ms.
81 */
82#define DD_ENCODER_OUTPUT_SIZE 2560
83/*
84 * DDP encoder output size for 32ms.
85 */
86#define DDP_ENCODER_OUTPUT_SIZE 4608
87
88/*
89 * Frame size for DD/DDP is 1536 samples.
90 * For a bit rate of 640 bps, DD encoder output size is 2560 bytes of
91 * 32ms;
92 * DDP encoder output size is 4608 bytes of 32 ms.
93 * Kernel buffer buffer allocation for compress passthrough is
94 * 2 x 2048 bytes = 4096 bytes
95 * The Latency for DD (measured in samples) is calculated as:
96 * Time taken to play 8192 bytes (for DD) = 4096 x 32/2560 = 51.2ms
97 * Samples for 51.2ms = 51.2 x 1536/32 = 2457 samples.
98 * Latency calculated similarly for DPP is 1365 samples.
99 */
Varun B34da7a42017-02-13 16:16:53 +0530100#define TRANSCODE_LATENCY(buffer_size, frame_size, encoder_output_in_bytes) \
101 ((buffer_size * frame_size) / encoder_output_in_bytes)
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530102
Bharath Gopal01310bb2016-12-05 15:39:32 +0530103/*
104 * QAF Latency to process buffers since out_write from primary HAL
105 */
106#define QAF_COMPRESS_OFFLOAD_PROCESSING_LATENCY 18
107#define QAF_PCM_OFFLOAD_PROCESSING_LATENCY 48
108
Varun B34da7a42017-02-13 16:16:53 +0530109#define QAF_DEEP_BUFFER_OUTPUT_PERIOD_SIZE 1536
110
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530111#include <stdlib.h>
112#include <pthread.h>
113#include <errno.h>
114#include <dlfcn.h>
115#include <sys/resource.h>
116#include <sys/prctl.h>
117#include <cutils/properties.h>
118#include <cutils/str_parms.h>
119#include <cutils/log.h>
120#include <cutils/atomic.h>
121#include "audio_utils/primitives.h"
122#include "audio_hw.h"
123#include "platform_api.h"
124#include <platform.h>
125#include <system/thread_defs.h>
126#include <cutils/sched_policy.h>
127#include "audio_extn.h"
128#include <qti_audio.h>
129#include "sound/compress_params.h"
130
131#define QAF_OUTPUT_SAMPLING_RATE 48000
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530132
133#ifdef QAF_DUMP_ENABLED
134FILE *fp_output_writer_hdmi = NULL;
135#endif
136
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530137struct qaf {
138 struct audio_device *adev;
139 audio_session_handle_t session_handle;
140 void *qaf_lib;
141 int (*qaf_audio_session_open)(audio_session_handle_t* session_handle, void *p_data, void* license_data);
142 int (*qaf_audio_session_close)(audio_session_handle_t session_handle);
143 int (*qaf_audio_stream_open)(audio_session_handle_t session_handle, audio_stream_handle_t* stream_handle,
144 audio_stream_config_t input_config, audio_devices_t devices, stream_type_t flags);
145 int (*qaf_audio_stream_close)(audio_stream_handle_t stream_handle);
146 int (*qaf_audio_stream_set_param)(audio_stream_handle_t stream_handle, const char* kv_pairs);
147 int (*qaf_audio_session_set_param)(audio_session_handle_t handle, const char* kv_pairs);
148 char* (*qaf_audio_stream_get_param)(audio_stream_handle_t stream_handle, const char* key);
149 char* (*qaf_audio_session_get_param)(audio_session_handle_t handle, const char* key);
150 int (*qaf_audio_stream_start)(audio_stream_handle_t handle);
151 int (*qaf_audio_stream_stop)(audio_stream_handle_t stream_handle);
152 int (*qaf_audio_stream_pause)(audio_stream_handle_t stream_handle);
153 int (*qaf_audio_stream_flush)(audio_stream_handle_t stream_handle);
154 int (*qaf_audio_stream_write)(audio_stream_handle_t stream_handle, const void* buf, int size);
155 void (*qaf_register_event_callback)(audio_session_handle_t session_handle, void *priv_data,
156 notify_event_callback_t event_callback, audio_event_id_t event_id);
157 pthread_mutex_t lock;
158 struct stream_out *stream_drain_main;
Varun B34da7a42017-02-13 16:16:53 +0530159 struct stream_out *stream_drain_assoc;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530160 struct stream_out *qaf_compr_offload_out;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530161 struct stream_out *qaf_compr_offload_out_mch;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530162 struct stream_out *qaf_compr_passthrough_out;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530163 struct stream_out *qaf_passthrough_out;
Bharath Gopal01310bb2016-12-05 15:39:32 +0530164 void *bt_hdl;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530165 bool hdmi_connect;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530166 int passthrough_enabled;
167 int hdmi_sink_channels;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530168 bool main_output_active;
169 bool assoc_output_active;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530170 bool qaf_msmd_enabled;
Deepak Agarwal1e42b852017-02-11 17:57:04 +0530171 float vol_left;
172 float vol_right;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530173};
174
175static struct qaf *qaf_mod = NULL;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530176static int qaf_stream_set_param(struct stream_out *out, const char *kv_pair) __attribute__ ((unused));
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530177
Deepak Agarwal1e42b852017-02-11 17:57:04 +0530178static bool is_ms12_format(audio_format_t format)
179{
180 if((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AC3)
181 return true;
182 if((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_E_AC3)
183 return true;
184 if((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
185 return true;
186 if((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
187 return true;
Varun B34da7a42017-02-13 16:16:53 +0530188 if((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AC4)
189 return true;
Deepak Agarwal1e42b852017-02-11 17:57:04 +0530190 if(format == AUDIO_FORMAT_PCM_16_BIT)
191 return true;
192
193 return false;
194}
195
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530196static void lock_output_stream(struct stream_out *out)
197{
198 pthread_mutex_lock(&out->pre_lock);
199 pthread_mutex_lock(&out->lock);
200 pthread_mutex_unlock(&out->pre_lock);
201}
202
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530203static bool audio_extn_qaf_passthrough_enabled(struct stream_out *out)
204{
205 ALOGV("%s %d ", __func__, __LINE__);
206 if ((!property_get_bool("audio.qaf.reencode", false)) &&
207 property_get_bool("audio.qaf.passthrough", false)) {
208 if (property_get_bool("audio.offload.passthrough", false)) {
209 if (((out->format == AUDIO_FORMAT_AC3) && platform_is_edid_supported_format(qaf_mod->adev->platform, AUDIO_FORMAT_AC3)) ||
210 ((out->format == AUDIO_FORMAT_E_AC3) && platform_is_edid_supported_format(qaf_mod->adev->platform, AUDIO_FORMAT_E_AC3)) ||
211 ((out->format == AUDIO_FORMAT_DTS) && platform_is_edid_supported_format(qaf_mod->adev->platform, AUDIO_FORMAT_DTS)) ||
212 ((out->format == AUDIO_FORMAT_DTS_HD) && platform_is_edid_supported_format(qaf_mod->adev->platform, AUDIO_FORMAT_DTS_HD))) {
213 return true;
214 }
215 } else {
216 if ((out->format == AUDIO_FORMAT_PCM_16_BIT) && (popcount(out->channel_mask) > 2)) {
217 return true;
218 }
219 }
220 }
221 return false;
222}
223
224static int qaf_out_callback(stream_callback_event_t event, void *param __unused, void *cookie)
225{
226 struct stream_out *out = (struct stream_out *)cookie;
227
228 out->offload_callback(event, NULL, out->offload_cookie);
229 return 0;
230}
231
232static int create_output_stream(struct stream_out *out, struct audio_config *config, audio_output_flags_t flags, audio_devices_t devices, int handle_id)
233{
234 int ret = 0;
235
236 ALOGV("%s %d", __func__, __LINE__);
237 if ((handle_id == QAF_DEFAULT_PASSTHROUGH_HANDLE) &&
238 (NULL == qaf_mod->qaf_passthrough_out)) {
239 pthread_mutex_lock(&qaf_mod->lock);
240 lock_output_stream(out);
241 ret = adev_open_output_stream((struct audio_hw_device *) qaf_mod->adev, handle_id, devices,
242 flags, config, (struct audio_stream_out **) &(qaf_mod->qaf_passthrough_out), NULL);
243 if (ret < 0) {
244 pthread_mutex_unlock(&out->lock);
245 pthread_mutex_unlock(&qaf_mod->lock);
246 ALOGE("%s: adev_open_output_stream failed with ret = %d!", __func__, ret);
247 return -EINVAL;
248 }
249 qaf_mod->qaf_passthrough_out->stream.set_callback((struct audio_stream_out *)qaf_mod->qaf_passthrough_out, (stream_callback_t) qaf_out_callback, out);
250 pthread_mutex_unlock(&out->lock);
251 pthread_mutex_unlock(&qaf_mod->lock);
252 }
253 return ret;
254}
255
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530256static int qaf_send_offload_cmd_l(struct stream_out* out, int command)
257{
258 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
259
260 if (!cmd) {
261 ALOGE("failed to allocate mem for command 0x%x", command);
262 return -ENOMEM;
263 }
264
265 ALOGV("%s %d", __func__, command);
266
267 cmd->cmd = command;
268 list_add_tail(&out->qaf_offload_cmd_list, &cmd->node);
269 pthread_cond_signal(&out->qaf_offload_cond);
270 return 0;
271}
272
273static int audio_extn_qaf_stream_stop(struct stream_out *out)
274{
275 ALOGV("%s: %d start", __func__, __LINE__);
276 if (!qaf_mod->qaf_audio_stream_stop)
277 return -EINVAL;
278
279 return qaf_mod->qaf_audio_stream_stop(out->qaf_stream_handle);
280}
281
282static int qaf_out_standby(struct audio_stream *stream)
283{
284 struct stream_out *out = (struct stream_out *)stream;
285 int status = 0;
286
287 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
288 stream, out->usecase, use_case_table[out->usecase]);
289
290 lock_output_stream(out);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530291 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
292 if ((out->format == AUDIO_FORMAT_PCM_16_BIT) && (popcount(out->channel_mask) <= 2)) {
293 pthread_mutex_unlock(&out->lock);
294 return status;
295 }
296 status = qaf_mod->qaf_passthrough_out->stream.common.standby((struct audio_stream *) qaf_mod->qaf_passthrough_out);
297 if (!out->standby) {
298 out->standby = true;
299 }
300 pthread_mutex_unlock(&out->lock);
301 return status;
302 }
303
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530304 if (!out->standby) {
305 out->standby = true;
306 status = audio_extn_qaf_stream_stop(out);
307 }
308 pthread_mutex_unlock(&out->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530309 return status;
310}
311
312static int qaf_stream_set_param(struct stream_out *out, const char *kv_pair)
313{
314 ALOGV("%s %d kvpair: %s", __func__, __LINE__, kv_pair);
315 if (!qaf_mod->qaf_audio_stream_set_param)
316 return -EINVAL;
317
318 return qaf_mod->qaf_audio_stream_set_param(out->qaf_stream_handle, kv_pair);
319}
320
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530321static int qaf_write_input_buffer(struct stream_out *out, const void *buffer, int bytes)
322{
323 int ret = 0;
324 ALOGVV("%s bytes = %d [%p]", __func__, bytes, out->qaf_stream_handle);
325 if (!qaf_mod->qaf_audio_stream_write)
326 return -EINVAL;
327
328 if (out->qaf_stream_handle)
329 ret = qaf_mod->qaf_audio_stream_write(out->qaf_stream_handle, buffer, bytes);
330 return ret;
331}
332
333static int qaf_out_set_volume(struct audio_stream_out *stream __unused, float left,
334 float right)
335{
Deepak Agarwal1e42b852017-02-11 17:57:04 +0530336 /* For ms12 formats, qaf_mod->qaf_compr_offload_out is allocated during the first
337 * call of notify_event_callback(). Therefore, the volume levels set during session
338 * open have to be cached and applied later */
339 qaf_mod->vol_left = left;
340 qaf_mod->vol_right = right;
341
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530342 if (qaf_mod->qaf_compr_offload_out != NULL) {
343 return qaf_mod->qaf_compr_offload_out->stream.set_volume(
344 (struct audio_stream_out *)qaf_mod->qaf_compr_offload_out, left, right);
345 }
346 return -ENOSYS;
347}
348
349static int qaf_stream_start(struct stream_out *out)
350{
351 if (!qaf_mod->qaf_audio_stream_start)
352 return -EINVAL;
353
354 return qaf_mod->qaf_audio_stream_start(out->qaf_stream_handle);
355}
356
357static int qaf_start_output_stream(struct stream_out *out)
358{
359 int ret = 0;
360 struct audio_device *adev = out->dev;
361 int snd_card_status = get_snd_card_state(adev);
362
363 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
364 ret = -EINVAL;
365 usleep(50000);
366 return ret;
367 }
368
369 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
370 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
371 out->devices);
372
373 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
374 ALOGE("%s: sound card is not active/SSR returning error", __func__);
375 ret = -EIO;
376 usleep(50000);
377 return ret;
378 }
379
380 return qaf_stream_start(out);
381}
382
383static ssize_t qaf_out_write(struct audio_stream_out *stream, const void *buffer,
384 size_t bytes)
385{
386 struct stream_out *out = (struct stream_out *)stream;
387 struct audio_device *adev = out->dev;
388 ssize_t ret = 0;
389
390 ALOGV("qaf_out_write bytes = %d, usecase[%d] and flags[%x] for handle[%p]",(int)bytes, out->usecase, out->flags, out);
391 lock_output_stream(out);
392
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530393 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
394 if ((out->format == AUDIO_FORMAT_PCM_16_BIT) && (popcount(out->channel_mask) <= 2)) {
395 ALOGD(" %s : Drop data as compress passthrough session is going on", __func__);
396 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
397 out->stream.common.get_sample_rate(&out->stream.common));
398 goto exit;
399 }
400 ret = qaf_mod->qaf_passthrough_out->stream.write((struct audio_stream_out *)(qaf_mod->qaf_passthrough_out), buffer, bytes);
401 pthread_mutex_unlock(&out->lock);
402 return ret;
403 }
404
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530405 if (out->standby) {
406 out->standby = false;
407 pthread_mutex_lock(&adev->lock);
408 ret = qaf_start_output_stream(out);
409 pthread_mutex_unlock(&adev->lock);
410 /* ToDo: If use case is compress offload should return 0 */
411 if (ret != 0) {
412 out->standby = true;
413 goto exit;
414 }
415 }
416
417 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
418 audio_utils_set_hdmi_channel_status(out, (char *)buffer, bytes);
419 adev->is_channel_status_set = true;
420 }
421
422 ret = qaf_write_input_buffer(out, buffer, bytes);
423 ALOGV("%s, ret [%d] ", __func__, (int)ret);
424 if (ret < 0) {
425 goto exit;
426 }
427 out->written += bytes / ((popcount(out->channel_mask) * sizeof(short)));
428
429exit:
430
431 pthread_mutex_unlock(&out->lock);
432
433 if (ret < 0) {
434 if (ret == -EAGAIN) {
435 ALOGV("No space available in ms12 driver, post msg to cb thread");
436 lock_output_stream(out);
437 ret = qaf_send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
438 pthread_mutex_unlock(&out->lock);
439 bytes = 0;
440 }
441 if(ret == -ENOMEM || ret == -EPERM){
442 if (out->pcm)
443 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
444 qaf_out_standby(&out->stream.common);
445 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
446 out->stream.common.get_sample_rate(&out->stream.common));
447 }
448 }
449 return bytes;
450}
451
Varun B34da7a42017-02-13 16:16:53 +0530452static uint32_t qaf_get_pcm_offload_buffer_size(audio_offload_info_t* info)
453{
454 uint32_t fragment_size = 0;
455 uint32_t bits_per_sample = 16;
456 uint32_t pcm_offload_time = QAF_PCM_OFFLOAD_BUFFER_DURATION;
457
458 //duration is set to 32 ms worth of stereo data at 48Khz
459 //with 16 bit per sample, modify this when the channel
460 //configuration is different
461 fragment_size = (pcm_offload_time
462 * info->sample_rate
463 * (bits_per_sample >> 3)
464 * popcount(info->channel_mask))/1000;
465 if(fragment_size < MIN_PCM_OFFLOAD_FRAGMENT_SIZE)
466 fragment_size = MIN_PCM_OFFLOAD_FRAGMENT_SIZE;
467 else if(fragment_size > MAX_PCM_OFFLOAD_FRAGMENT_SIZE)
468 fragment_size = MAX_PCM_OFFLOAD_FRAGMENT_SIZE;
469 // To have same PCM samples for all channels, the buffer size requires to
470 // be multiple of (number of channels * bytes per sample)
471 // For writes to succeed, the buffer must be written at address which is multiple of 32
472 fragment_size = ALIGN(fragment_size, ((bits_per_sample >> 3)* popcount(info->channel_mask) * 32));
473
474 ALOGI("Qaf PCM offload Fragment size to %d bytes", fragment_size);
475
476 return fragment_size;
477}
478
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530479static int qaf_get_timestamp(struct stream_out *out, uint64_t *frames, struct timespec *timestamp)
480{
481 int ret = 0;
482 struct str_parms *parms;
483 int value = 0;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530484 int latency = 0;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530485 int signed_frames = 0;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530486 char* kvpairs = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530487
488 ALOGV("%s out->format %d", __func__, out->format);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530489 kvpairs = qaf_mod->qaf_audio_stream_get_param(out->qaf_stream_handle, "get_latency");
490 if (kvpairs) {
491 parms = str_parms_create_str(kvpairs);
492 ret = str_parms_get_int(parms, "get_latency", &latency);
493 if (ret >= 0) {
494 str_parms_destroy(parms);
495 parms = NULL;
496 }
497 free(kvpairs);
498 kvpairs = NULL;
499 }
500 // MS12 Latency + Kernel Latency + Dsp Latency
501 if (qaf_mod->qaf_compr_offload_out != NULL) {
Varun B34da7a42017-02-13 16:16:53 +0530502 out->platform_latency = latency + (COMPRESS_OFFLOAD_NUM_FRAGMENTS * qaf_get_pcm_offload_buffer_size(&qaf_mod->qaf_compr_offload_out->info) \
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530503 /(popcount(qaf_mod->qaf_compr_offload_out->channel_mask) * sizeof(short))) \
504 +((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 +0530505 } else if (audio_extn_bt_hal_get_output_stream(qaf_mod->bt_hdl) != NULL) {
506 out->platform_latency = latency + audio_extn_bt_hal_get_latency(qaf_mod->bt_hdl);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530507 } else if (NULL != qaf_mod->qaf_compr_passthrough_out) {
508 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)) \
509 + (COMPRESS_OFFLOAD_PLAYBACK_LATENCY * qaf_mod->qaf_compr_passthrough_out->sample_rate/1000);
510 }
511
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530512 if(out->format & AUDIO_FORMAT_PCM_16_BIT) {
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530513 *frames = 0;
514 signed_frames = out->written - out->platform_latency;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530515 // It would be unusual for this value to be negative, but check just in case ...
516 if (signed_frames >= 0) {
517 *frames = signed_frames;
518 }
519 clock_gettime(CLOCK_MONOTONIC, timestamp);
520 } else if (qaf_mod->qaf_audio_stream_get_param) {
521 kvpairs = qaf_mod->qaf_audio_stream_get_param(out->qaf_stream_handle, "position");
522 if (kvpairs) {
523 parms = str_parms_create_str(kvpairs);
524 ret = str_parms_get_int(parms, "position", &value);
525 if (ret >= 0) {
526 *frames = value;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530527 signed_frames = value - out->platform_latency;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530528 // It would be unusual for this value to be negative, but check just in case ...
529 if (signed_frames >= 0) {
530 *frames = signed_frames;
531 }
532 clock_gettime(CLOCK_MONOTONIC, timestamp);
533 }
534 str_parms_destroy(parms);
535 }
536 } else {
537 ret = -EINVAL;
538 }
539 return ret;
540}
541
542static int qaf_out_get_presentation_position(const struct audio_stream_out *stream,
543 uint64_t *frames, struct timespec *timestamp)
544{
545 struct stream_out *out = (struct stream_out *)stream;
546 int ret = -1;
547 lock_output_stream(out);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530548
549 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
550 ret = qaf_mod->qaf_passthrough_out->stream.get_presentation_position((struct audio_stream_out *)qaf_mod->qaf_passthrough_out, frames, timestamp);
551 pthread_mutex_unlock(&out->lock);
552 return ret;
553 }
554
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530555 ret = qaf_get_timestamp(out, frames, timestamp);
556 pthread_mutex_unlock(&out->lock);
557
558 return ret;
559}
560
561static int qaf_stream_pause(struct stream_out *out)
562{
563 ALOGV("%s: %d start", __func__, __LINE__);
564 if (!qaf_mod->qaf_audio_stream_pause)
565 return -EINVAL;
566
567 return qaf_mod->qaf_audio_stream_pause(out->qaf_stream_handle);
568}
569
570static int qaf_out_pause(struct audio_stream_out* stream)
571{
572 struct stream_out *out = (struct stream_out *)stream;
573 int status = -ENOSYS;
574 ALOGE("%s", __func__);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530575
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530576 lock_output_stream(out);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530577 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
578 status = qaf_mod->qaf_passthrough_out->stream.pause((struct audio_stream_out *) qaf_mod->qaf_passthrough_out);
579 out->offload_state = OFFLOAD_STATE_PAUSED;
580 pthread_mutex_unlock(&out->lock);
581 return status;
582 }
583
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530584 status = qaf_stream_pause(out);
585 pthread_mutex_unlock(&out->lock);
586 return status;
587}
588
Varun B34da7a42017-02-13 16:16:53 +0530589static int qaf_out_drain(struct audio_stream_out* stream,
590 audio_drain_type_t type)
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530591{
592 struct stream_out *out = (struct stream_out *)stream;
593 int status = 0;
Varun B34da7a42017-02-13 16:16:53 +0530594 ALOGV("%s stream_handle = %p , format = %x", __func__,
595 out->qaf_stream_handle, out->format);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530596
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530597 lock_output_stream(out);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530598 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
Varun B34da7a42017-02-13 16:16:53 +0530599 status = qaf_mod->qaf_passthrough_out->stream.drain(
600 (struct audio_stream_out*)(qaf_mod->qaf_passthrough_out), type);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530601 pthread_mutex_unlock(&out->lock);
602 return status;
603 }
604
605
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530606 if (out->offload_callback && out->qaf_stream_handle) {
607 /* Stream stop will trigger EOS and on EOS_EVENT received
608 from callback DRAIN_READY command is sent */
609 status = audio_extn_qaf_stream_stop(out);
Varun B34da7a42017-02-13 16:16:53 +0530610 if (out->format != AUDIO_FORMAT_PCM_16_BIT) {
611 if (out->flags & AUDIO_OUTPUT_FLAG_ASSOCIATED) {
612 qaf_mod->stream_drain_assoc = out;
613 } else {
614 qaf_mod->stream_drain_main = out;
615 }
616 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530617 }
618 pthread_mutex_unlock(&out->lock);
619 return status;
620}
621
622static int audio_extn_qaf_stream_flush(struct stream_out *out)
623{
624 ALOGV("%s: %d exit", __func__, __LINE__);
625 if (!qaf_mod->qaf_audio_stream_flush)
626 return -EINVAL;
627
628 return qaf_mod->qaf_audio_stream_flush(out->qaf_stream_handle);
629}
630
631static int qaf_out_flush(struct audio_stream_out* stream)
632{
633 struct stream_out *out = (struct stream_out *)stream;
634 ALOGV("%s", __func__);
635 int status = -ENOSYS;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530636
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530637 lock_output_stream(out);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530638 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
639 status = qaf_mod->qaf_passthrough_out->stream.flush((struct audio_stream_out *)qaf_mod->qaf_passthrough_out);
640 out->offload_state = OFFLOAD_STATE_IDLE;
641 pthread_mutex_unlock(&out->lock);
642 return status;
643 }
644
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530645 status = audio_extn_qaf_stream_flush(out);
646 pthread_mutex_unlock(&out->lock);
647 ALOGV("%s Exit", __func__);
648 return status;
649}
650
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530651static uint32_t qaf_out_get_latency(const struct audio_stream_out *stream)
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530652{
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530653 struct stream_out *out = (struct stream_out *)stream;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530654 uint32_t latency = 0;
655
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530656
657 lock_output_stream(out);
658 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
659 latency = qaf_mod->qaf_passthrough_out->stream.get_latency((struct audio_stream_out *)qaf_mod->qaf_passthrough_out);
660 ALOGV("%s: latency = %u", __FUNCTION__, latency);
661 pthread_mutex_unlock(&out->lock);
662 return latency;
663 }
664 pthread_mutex_unlock(&out->lock);
665
666 if (is_offload_usecase(out->usecase)) {
667 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
668 } else {
669 latency = PCM_OFFLOAD_PLAYBACK_LATENCY;
670 }
Bharath Gopal01310bb2016-12-05 15:39:32 +0530671
672 if (audio_extn_bt_hal_get_output_stream(qaf_mod->bt_hdl) != NULL) {
673
674 if (is_offload_usecase(out->usecase)) {
675 latency = audio_extn_bt_hal_get_latency(qaf_mod->bt_hdl) + QAF_COMPRESS_OFFLOAD_PROCESSING_LATENCY;
676 } else {
677 latency = audio_extn_bt_hal_get_latency(qaf_mod->bt_hdl) + QAF_PCM_OFFLOAD_PROCESSING_LATENCY;
678 }
679 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530680 ALOGV("%s: Latency %d", __func__, latency);
681 return latency;
682}
683
Varun B34da7a42017-02-13 16:16:53 +0530684static void notify_event_callback(
685 audio_session_handle_t session_handle __unused, void *prv_data,
686 void *buf, audio_event_id_t event_id, int size, int device)
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530687{
688
689/*
690 For SPKR:
Varun B34da7a42017-02-13 16:16:53 +0530691 1. Open pcm device if device_id passed to it SPKR and write the data to
692 pcm device
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530693
694 For HDMI
Varun B34da7a42017-02-13 16:16:53 +0530695 1.Open compress device for HDMI(PCM or AC3) based on current hdmi o/p format
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530696 2.create offload_callback thread to receive async events
Varun B34da7a42017-02-13 16:16:53 +0530697 3.Write the data to compress device. If not all the data is consumed by
698 the driver, add a command to offload_callback thread.
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530699*/
700 int ret;
701 audio_output_flags_t flags;
702 struct qaf* qaf_module = (struct qaf* ) prv_data;
Bharath Gopal01310bb2016-12-05 15:39:32 +0530703 struct audio_stream_out *bt_stream = NULL;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530704
Varun B34da7a42017-02-13 16:16:53 +0530705 ALOGV("%s device 0x%X, %d in event = %d",
706 __func__, device, __LINE__, event_id);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530707
708 if (event_id == AUDIO_DATA_EVENT) {
Varun B34da7a42017-02-13 16:16:53 +0530709 ALOGVV("Device id %x %s %d, bytes to written %d",
710 device, __func__,__LINE__, size);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530711
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530712 if ((qaf_mod->qaf_passthrough_out != NULL) && qaf_mod->hdmi_connect) {
713 pthread_mutex_lock(&qaf_module->lock);
714 if (qaf_mod->qaf_compr_offload_out != NULL) {
Varun B34da7a42017-02-13 16:16:53 +0530715 adev_close_output_stream(
716 (struct audio_hw_device *) qaf_mod->adev,
717 (struct audio_stream_out *) (qaf_mod->qaf_compr_offload_out));
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530718 qaf_mod->qaf_compr_offload_out = NULL;
719 }
720 if (qaf_mod->qaf_compr_offload_out_mch) {
Varun B34da7a42017-02-13 16:16:53 +0530721 adev_close_output_stream(
722 (struct audio_hw_device *) qaf_mod->adev,
723 (struct audio_stream_out *)
724 (qaf_mod->qaf_compr_offload_out_mch));
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530725 qaf_mod->qaf_compr_offload_out_mch = NULL;
726 }
727 pthread_mutex_unlock(&qaf_module->lock);
728 ALOGV("%s %d DROPPING DATA", __func__, __LINE__);
729 return;
730 } else {
731 if (qaf_mod->qaf_passthrough_out != NULL) {
732 pthread_mutex_lock(&qaf_module->lock);
Varun B34da7a42017-02-13 16:16:53 +0530733 adev_close_output_stream(
734 (struct audio_hw_device *) qaf_mod->adev,
735 (struct audio_stream_out *) qaf_mod->qaf_passthrough_out);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530736 qaf_mod->qaf_passthrough_out = NULL;
737 qaf_mod->main_output_active = false;
738 pthread_mutex_unlock(&qaf_module->lock);
739 }
740 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530741 pthread_mutex_lock(&qaf_module->lock);
Varun B34da7a42017-02-13 16:16:53 +0530742 if ((device ==
743 (AUDIO_DEVICE_OUT_AUX_DIGITAL | AUDIO_COMPRESSED_OUT_DD)) ||
744 (device ==
745 (AUDIO_DEVICE_OUT_AUX_DIGITAL | AUDIO_COMPRESSED_OUT_DDP))) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530746
Varun B34da7a42017-02-13 16:16:53 +0530747 if (NULL == qaf_mod->qaf_compr_passthrough_out &&
748 qaf_mod->hdmi_connect) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530749 struct audio_config config;
750 audio_devices_t devices;
751
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530752 if (qaf_mod->qaf_compr_offload_out_mch) {
Varun B34da7a42017-02-13 16:16:53 +0530753 adev_close_output_stream(
754 (struct audio_hw_device *) qaf_mod->adev,
755 (struct audio_stream_out *)
756 (qaf_mod->qaf_compr_offload_out_mch));
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530757 qaf_mod->qaf_compr_offload_out_mch = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530758 }
759
Varun B34da7a42017-02-13 16:16:53 +0530760 config.sample_rate = config.offload_info.sample_rate =
761 QAF_OUTPUT_SAMPLING_RATE;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530762 config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
763 config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
764
Varun B34da7a42017-02-13 16:16:53 +0530765 if (device ==
766 (AUDIO_DEVICE_OUT_AUX_DIGITAL | AUDIO_COMPRESSED_OUT_DDP)) {
767 config.format = config.offload_info.format =
768 AUDIO_FORMAT_E_AC3;
769 } else {
770 config.format = config.offload_info.format =
771 AUDIO_FORMAT_AC3;
772 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530773
774 config.offload_info.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Varun B34da7a42017-02-13 16:16:53 +0530775 config.offload_info.channel_mask = config.channel_mask =
776 AUDIO_CHANNEL_OUT_5POINT1;
777 flags = (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|
778 AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_DIRECT_PCM);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530779 devices = AUDIO_DEVICE_OUT_AUX_DIGITAL;
780
Varun B34da7a42017-02-13 16:16:53 +0530781 ret = adev_open_output_stream(
782 (struct audio_hw_device *) qaf_mod->adev,
783 QAF_DEFAULT_COMPR_PASSTHROUGH_HANDLE, devices,
784 flags, &config,
785 (struct audio_stream_out **)
786 &(qaf_mod->qaf_compr_passthrough_out), NULL);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530787 if (ret < 0) {
Varun B34da7a42017-02-13 16:16:53 +0530788 ALOGE("%s: adev_open_output_stream failed with ret = %d!",
789 __func__, ret);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530790 pthread_mutex_unlock(&qaf_module->lock);
791 return;
792 }
Varun B34da7a42017-02-13 16:16:53 +0530793 qaf_mod->qaf_compr_passthrough_out->compr_config.fragments =
794 COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530795 }
796
797 if (!qaf_mod->passthrough_enabled)
798 qaf_mod->passthrough_enabled = 1;
799
Varun B34da7a42017-02-13 16:16:53 +0530800 if (qaf_mod->qaf_compr_passthrough_out) {
801 ret = qaf_mod->qaf_compr_passthrough_out->stream.write(
802 (struct audio_stream_out *)
803 qaf_mod->qaf_compr_passthrough_out, buf, size);
804 }
805 } else if ((device & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
806 ((qaf_mod->hdmi_connect) &&
807 (qaf_mod->qaf_passthrough_out == NULL) &&
808 (qaf_mod->hdmi_sink_channels > 2))) {
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530809 if (NULL == qaf_mod->qaf_compr_offload_out_mch) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530810 struct audio_config config;
811 audio_devices_t devices;
812
Varun B34da7a42017-02-13 16:16:53 +0530813 config.sample_rate = config.offload_info.sample_rate =
814 QAF_OUTPUT_SAMPLING_RATE;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530815 config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
816 config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530817 config.offload_info.format = AUDIO_FORMAT_PCM_16_BIT;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530818 config.offload_info.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530819 config.format = AUDIO_FORMAT_PCM_16_BIT;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530820 devices = AUDIO_DEVICE_NONE;
821
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530822 if (qaf_mod->hdmi_sink_channels == 8) {
Varun B34da7a42017-02-13 16:16:53 +0530823 config.offload_info.channel_mask = config.channel_mask =
824 AUDIO_CHANNEL_OUT_7POINT1;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530825 } else if (qaf_mod->hdmi_sink_channels == 6) {
Varun B34da7a42017-02-13 16:16:53 +0530826 config.offload_info.channel_mask = config.channel_mask =
827 AUDIO_CHANNEL_OUT_5POINT1;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530828 } else {
Varun B34da7a42017-02-13 16:16:53 +0530829 config.offload_info.channel_mask = config.channel_mask =
830 AUDIO_CHANNEL_OUT_STEREO;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530831 }
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530832 devices = AUDIO_DEVICE_OUT_AUX_DIGITAL;
Varun B34da7a42017-02-13 16:16:53 +0530833 flags = (AUDIO_OUTPUT_FLAG_DIRECT|
834 AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|
835 AUDIO_OUTPUT_FLAG_DIRECT_PCM);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530836
Varun B34da7a42017-02-13 16:16:53 +0530837 ret = adev_open_output_stream(
838 (struct audio_hw_device *) qaf_mod->adev,
839 QAF_DEFAULT_COMPR_AUDIO_HANDLE, devices, flags,
840 &config, (struct audio_stream_out **)
841 &(qaf_mod->qaf_compr_offload_out_mch), NULL);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530842 if (ret < 0) {
Varun B34da7a42017-02-13 16:16:53 +0530843 ALOGE("%s: adev_open_output_stream failed with ret = %d!",
844 __func__, ret);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530845 pthread_mutex_unlock(&qaf_module->lock);
846 return;
847 }
Varun B34da7a42017-02-13 16:16:53 +0530848 qaf_mod->qaf_compr_offload_out_mch->compr_config.fragments =
849 COMPRESS_OFFLOAD_NUM_FRAGMENTS;
850 qaf_mod->qaf_compr_offload_out_mch->compr_config.fragment_size =
851 qaf_get_pcm_offload_buffer_size(&config.offload_info);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530852 }
853
Varun B34da7a42017-02-13 16:16:53 +0530854 if (qaf_mod->qaf_compr_offload_out_mch) {
855 ret = qaf_mod->qaf_compr_offload_out_mch->stream.write(
856 (struct audio_stream_out *)
857 qaf_mod->qaf_compr_offload_out_mch, buf, size);
858 }
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530859 } else {
Bharath Gopal01310bb2016-12-05 15:39:32 +0530860 bt_stream = audio_extn_bt_hal_get_output_stream(qaf_mod->bt_hdl);
861 if (bt_stream != NULL) {
862 if (qaf_mod->qaf_compr_offload_out) {
Varun B34da7a42017-02-13 16:16:53 +0530863 adev_close_output_stream(
864 (struct audio_hw_device *) qaf_mod->adev,
865 (struct audio_stream_out *)
866 (qaf_mod->qaf_compr_offload_out));
Bharath Gopal01310bb2016-12-05 15:39:32 +0530867 qaf_mod->qaf_compr_offload_out = NULL;
868 }
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530869
Bharath Gopal01310bb2016-12-05 15:39:32 +0530870 audio_extn_bt_hal_out_write(qaf_mod->bt_hdl, buf, size);
871 }
872
Varun B34da7a42017-02-13 16:16:53 +0530873 if (NULL == qaf_mod->qaf_compr_offload_out && bt_stream == NULL &&
874 qaf_mod->qaf_passthrough_out == NULL) {
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530875 struct audio_config config;
876 audio_devices_t devices;
877
Varun B34da7a42017-02-13 16:16:53 +0530878 config.sample_rate = config.offload_info.sample_rate =
879 QAF_OUTPUT_SAMPLING_RATE;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530880 config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
881 config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
882 config.offload_info.format = AUDIO_FORMAT_PCM_16_BIT;
883 config.offload_info.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
884 config.format = AUDIO_FORMAT_PCM_16_BIT;
Varun B34da7a42017-02-13 16:16:53 +0530885 config.offload_info.channel_mask = config.channel_mask =
886 AUDIO_CHANNEL_OUT_STEREO;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530887 devices = AUDIO_DEVICE_OUT_SPEAKER;
Varun B34da7a42017-02-13 16:16:53 +0530888 flags = (AUDIO_OUTPUT_FLAG_DIRECT|
889 AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|
890 AUDIO_OUTPUT_FLAG_DIRECT_PCM);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530891
892 /* TODO:: Need to Propagate errors to framework */
Varun B34da7a42017-02-13 16:16:53 +0530893 ret = adev_open_output_stream(
894 (struct audio_hw_device *) qaf_mod->adev,
895 QAF_DEFAULT_COMPR_AUDIO_HANDLE, devices,
896 flags, &config,
897 (struct audio_stream_out **)
898 &(qaf_mod->qaf_compr_offload_out), NULL);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530899 if (ret < 0) {
Varun B34da7a42017-02-13 16:16:53 +0530900 ALOGE("%s: adev_open_output_stream failed with ret = %d!",
901 __func__, ret);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530902 pthread_mutex_unlock(&qaf_module->lock);
903 return;
904 }
Deepak Agarwal1e42b852017-02-11 17:57:04 +0530905
Varun B34da7a42017-02-13 16:16:53 +0530906 qaf_mod->qaf_compr_offload_out->compr_config.fragments =
907 COMPRESS_OFFLOAD_NUM_FRAGMENTS;
908 qaf_mod->qaf_compr_offload_out->compr_config.fragment_size =
909 qaf_get_pcm_offload_buffer_size(&config.offload_info);
910 qaf_mod->qaf_compr_offload_out->info.channel_mask =
911 config.offload_info.channel_mask;
912 qaf_mod->qaf_compr_offload_out->info.format =
913 config.offload_info.format;
914 qaf_mod->qaf_compr_offload_out->info.sample_rate =
915 config.offload_info.sample_rate;
916 qaf_mod->qaf_compr_offload_out->stream.set_volume(
917 (struct audio_stream_out *)qaf_mod->qaf_compr_offload_out,
918 qaf_mod->vol_left, qaf_mod->vol_right);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530919 }
920
Varun B34da7a42017-02-13 16:16:53 +0530921 if (!qaf_mod->hdmi_connect &&
922 (qaf_mod->qaf_compr_passthrough_out ||
923 qaf_mod->qaf_compr_offload_out_mch)) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530924 qaf_mod->passthrough_enabled = 0;
925 if (qaf_mod->qaf_compr_passthrough_out) {
Varun B34da7a42017-02-13 16:16:53 +0530926 adev_close_output_stream(
927 (struct audio_hw_device *) qaf_mod->adev,
928 (struct audio_stream_out *)
929 (qaf_mod->qaf_compr_passthrough_out));
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530930 qaf_mod->qaf_compr_passthrough_out = NULL;
931 }
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530932 if (qaf_mod->qaf_compr_offload_out_mch) {
Varun B34da7a42017-02-13 16:16:53 +0530933 adev_close_output_stream(
934 (struct audio_hw_device *) qaf_mod->adev,
935 (struct audio_stream_out *)
936 (qaf_mod->qaf_compr_offload_out_mch));
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530937 qaf_mod->qaf_compr_offload_out_mch = NULL;
938 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530939 }
940
941 /*
942 * TODO:: Since this is mixed data,
943 * need to identify to which stream the error should be sent
944 */
Varun B34da7a42017-02-13 16:16:53 +0530945 if (bt_stream == NULL && qaf_mod->qaf_compr_offload_out) {
946 ret = qaf_mod->qaf_compr_offload_out->stream.write(
947 (struct audio_stream_out *)
948 qaf_mod->qaf_compr_offload_out, buf, size);
949 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530950 }
951
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +0530952 ALOGVV("%s:%d stream write ret = %d", __func__, __LINE__, ret);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530953 pthread_mutex_unlock(&qaf_module->lock);
Varun B34da7a42017-02-13 16:16:53 +0530954 } else if (event_id == AUDIO_EOS_MAIN_DD_DDP_EVENT
955 || event_id == AUDIO_EOS_MAIN_AAC_EVENT
956 || event_id == AUDIO_EOS_MAIN_AC4_EVENT
957 || event_id == AUDIO_EOS_ASSOC_DD_DDP_EVENT) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530958 struct stream_out *out = qaf_module->stream_drain_main;
Varun B34da7a42017-02-13 16:16:53 +0530959 struct stream_out *out_assoc = qaf_module->stream_drain_assoc;
960
961 /**
962 * TODO:: Only DD/DDP Associate Eos is handled, need to add support
963 * for other formats.
964 */
965 if (event_id == AUDIO_EOS_ASSOC_DD_DDP_EVENT && out_assoc != NULL) {
966 lock_output_stream(out_assoc);
967 out_assoc->offload_callback(STREAM_CBK_EVENT_DRAIN_READY, NULL,
968 out_assoc->offload_cookie);
969 pthread_mutex_unlock(&out_assoc->lock);
970 qaf_module->stream_drain_assoc = NULL;
971 } else if (out != NULL) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530972 lock_output_stream(out);
Varun B34da7a42017-02-13 16:16:53 +0530973 out->offload_callback(STREAM_CBK_EVENT_DRAIN_READY, NULL,
974 out->offload_cookie);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +0530975 pthread_mutex_unlock(&out->lock);
976 qaf_module->stream_drain_main = NULL;
977 ALOGV("%s %d sent DRAIN_READY", __func__, __LINE__);
978 }
979 }
980 ALOGV("%s %d", __func__, __LINE__);
981}
982
983static int qaf_session_close()
984{
985 ALOGV("%s %d", __func__, __LINE__);
986 if (qaf_mod != NULL) {
987 if (!qaf_mod->qaf_audio_session_close)
988 return -EINVAL;
989
990 qaf_mod->qaf_audio_session_close(qaf_mod->session_handle);
991 qaf_mod->session_handle = NULL;
992 pthread_mutex_destroy(&qaf_mod->lock);
993 }
994 return 0;
995}
996
997static int qaf_stream_close(struct stream_out *out)
998{
999 int ret = 0;
1000 ALOGV( "%s %d", __func__, __LINE__);
1001 if (!qaf_mod->qaf_audio_stream_close)
1002 return -EINVAL;
1003 if (out->qaf_stream_handle) {
1004 ALOGV( "%s %d output active flag is %x and stream handle %p", __func__, __LINE__, out->flags, out->qaf_stream_handle);
1005 if ((out->flags & AUDIO_OUTPUT_FLAG_ASSOCIATED) && (out->flags & AUDIO_OUTPUT_FLAG_MAIN)) { /* Close for Stream with Main and Associated Content*/
1006 qaf_mod->main_output_active = false;
1007 qaf_mod->assoc_output_active = false;
1008 } else if (out->flags & AUDIO_OUTPUT_FLAG_MAIN) {/*Close for Main Stream*/
1009 qaf_mod->main_output_active = false;
1010 qaf_mod->assoc_output_active = false; /* TODO to remove resetting associated stream active flag when main stream is closed*/
1011 } else if (out->flags & AUDIO_OUTPUT_FLAG_ASSOCIATED) { /*Close for Associated Stream*/
1012 qaf_mod->assoc_output_active = false;
1013 } else { /*Close for Local Playback*/
1014 qaf_mod->main_output_active = false;
1015 }
1016 ret = qaf_mod->qaf_audio_stream_close(out->qaf_stream_handle);
1017 out->qaf_stream_handle = NULL;
1018 }
1019 ALOGV( "%s %d", __func__, __LINE__);
1020 return ret;
1021}
1022
1023static int qaf_stream_open(struct stream_out *out, struct audio_config *config, audio_output_flags_t flags, audio_devices_t devices)
1024{
1025 int status = 0;
1026 ALOGV("%s %d", __func__, __LINE__);
1027
1028 if (!qaf_mod->qaf_audio_stream_open)
1029 return -EINVAL;
1030
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301031 if (audio_extn_qaf_passthrough_enabled(out) && qaf_mod->hdmi_connect) {
1032 ALOGV("%s %d passthrough is enabled", __func__, __LINE__);
1033 status = create_output_stream(out, config, flags, devices, QAF_DEFAULT_PASSTHROUGH_HANDLE);
1034 if (status < 0) {
1035 ALOGE("%s: adev_open_output_stream failed with ret = %d!", __func__, status);
1036 return -EINVAL;
1037 }
1038 return 0;
1039 }
1040
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301041 audio_stream_config_t input_config;
1042 input_config.sample_rate = config->sample_rate;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301043 input_config.channels = popcount(config->channel_mask);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301044 input_config.format = config->format;
1045
1046 if ((config->format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC) {
1047 input_config.format = AUDIO_FORMAT_AAC;
1048 } else if((config->format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS) {
1049 input_config.format = AUDIO_FORMAT_AAC_ADTS;
1050 }
1051
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301052 ALOGV("%s %d audio_stream_open sample_rate(%d) channels(%d) devices(%#x) flags(%#x) format(%#x)\
1053 ",__func__, __LINE__, input_config.sample_rate, input_config.channels, devices, flags, input_config.format);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301054
1055 /* TODO to send appropriated flags when support for system tones is added */
1056 if (input_config.format == AUDIO_FORMAT_PCM_16_BIT) {
1057 status = qaf_mod->qaf_audio_stream_open(qaf_mod->session_handle, &out->qaf_stream_handle, input_config, devices, /*flags*/AUDIO_STREAM_SYSTEM_TONE);
1058 } else if (input_config.format == AUDIO_FORMAT_AC3 ||
1059 input_config.format == AUDIO_FORMAT_E_AC3 ||
Varun B34da7a42017-02-13 16:16:53 +05301060 input_config.format == AUDIO_FORMAT_AC4 ||
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301061 input_config.format == AUDIO_FORMAT_AAC ||
1062 input_config.format == AUDIO_FORMAT_AAC_ADTS) {
1063 if (qaf_mod->main_output_active == false) {
1064 if ((flags & AUDIO_OUTPUT_FLAG_MAIN) && (flags & AUDIO_OUTPUT_FLAG_ASSOCIATED)) {
1065 status = qaf_mod->qaf_audio_stream_open(qaf_mod->session_handle, &out->qaf_stream_handle, input_config, devices, /*flags*/AUDIO_STREAM_MAIN);
1066 if (status == 0) {
1067 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);
1068 qaf_mod->main_output_active = true;
1069 qaf_mod->assoc_output_active = true;
1070 }
1071 } else if (flags & AUDIO_OUTPUT_FLAG_MAIN) {
1072 status = qaf_mod->qaf_audio_stream_open(qaf_mod->session_handle, &out->qaf_stream_handle, input_config, devices, /*flags*/AUDIO_STREAM_MAIN);
1073 if (status == 0) {
1074 ALOGV("%s %d Open stream for Input with only Main flag [%x] stream handle [%p]", __func__, __LINE__, flags, out->qaf_stream_handle);
1075 qaf_mod->main_output_active = true;
1076 }
1077 } else if (flags & AUDIO_OUTPUT_FLAG_ASSOCIATED) {
1078 ALOGE("%s %d Error main input is not active", __func__, __LINE__);
1079 return -EINVAL;
1080 } else {
1081 status = qaf_mod->qaf_audio_stream_open(qaf_mod->session_handle, &out->qaf_stream_handle, input_config, devices, /*flags*/AUDIO_STREAM_MAIN);
1082 if (status == 0) {
1083 ALOGV("%s %d Open stream for Local playback with flag [%x] stream handle [%p] ", __func__, __LINE__, flags, out->qaf_stream_handle);
1084 qaf_mod->main_output_active = true;
1085 }
1086 }
1087 } else {
1088 if (flags & AUDIO_OUTPUT_FLAG_MAIN) {
1089 ALOGE("%s %d Error main input is already active", __func__, __LINE__);
1090 return -EINVAL;
1091 } else if (flags & AUDIO_OUTPUT_FLAG_ASSOCIATED) {
1092 if (qaf_mod->assoc_output_active) {
1093 ALOGE("%s %d Error assoc input is already active", __func__, __LINE__);
1094 return -EINVAL;
1095 } else {
1096 status = qaf_mod->qaf_audio_stream_open(qaf_mod->session_handle, &out->qaf_stream_handle, input_config, devices, /*flags*/AUDIO_STREAM_ASSOCIATED);
1097 if (status == 0) {
1098 ALOGV("%s %d Open stream for Input with only Associated flag [%x] stream handle [%p]", __func__, __LINE__, flags, out->qaf_stream_handle);
1099 qaf_mod->assoc_output_active = true;
1100 }
1101 }
1102 } else {
1103 ALOGE("%s %d Error main input is already active", __func__, __LINE__);
1104 return -EINVAL;
1105 }
1106 }
1107 }
1108
1109 return status;
1110}
1111
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301112static int audio_extn_qaf_stream_open(struct stream_out *out)
1113{
1114 int status = -ENOSYS;
1115 struct audio_config config;
1116 audio_devices_t devices;
1117
1118 config.sample_rate = config.offload_info.sample_rate = QAF_OUTPUT_SAMPLING_RATE;
1119 config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
1120 config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
1121 config.offload_info.format = out->format;
1122 config.offload_info.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
1123 config.format = out->format;
1124 config.offload_info.channel_mask = config.channel_mask = out->channel_mask;
1125
1126 devices = AUDIO_DEVICE_OUT_SPEAKER;
1127 status = qaf_stream_open(out, &config, out->flags, devices);
1128 ALOGV("%s %d status %d", __func__, __LINE__, status);
1129 return status;
1130}
1131
1132static int qaf_out_resume(struct audio_stream_out* stream)
1133{
1134 struct stream_out *out = (struct stream_out *)stream;
1135 int status = -ENOSYS;
1136 ALOGV("%s", __func__);
1137 lock_output_stream(out);
1138 if ((!property_get_bool("audio.qaf.reencode", false)) &&
1139 property_get_bool("audio.qaf.passthrough", false)) {
1140 if (property_get_bool("audio.offload.passthrough", false)) {
1141 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect &&
1142 (((out->format == AUDIO_FORMAT_E_AC3) && platform_is_edid_supported_format(qaf_mod->adev->platform, AUDIO_FORMAT_E_AC3)) ||
1143 ((out->format == AUDIO_FORMAT_AC3) && platform_is_edid_supported_format(qaf_mod->adev->platform, AUDIO_FORMAT_AC3)))) {
1144 status = qaf_mod->qaf_passthrough_out->stream.resume((struct audio_stream_out*) qaf_mod->qaf_passthrough_out);
1145 if (!status)
1146 out->offload_state = OFFLOAD_STATE_PLAYING;
1147 pthread_mutex_unlock(&out->lock);
1148 return status;
1149 } else {
1150 if ((out->format == AUDIO_FORMAT_E_AC3) || (out->format == AUDIO_FORMAT_AC3)) {
1151 status = audio_extn_qaf_stream_open(out);
1152 if (!status)
1153 out->offload_state = OFFLOAD_STATE_PLAYING;
1154 out->offload_callback(STREAM_CBK_EVENT_WRITE_READY, NULL, out->offload_cookie);
1155 }
1156 }
1157 } else {
1158 if ((out->format == AUDIO_FORMAT_PCM_16_BIT) && (popcount(out->channel_mask) > 2)) {
1159 if (qaf_mod->qaf_passthrough_out && qaf_mod->hdmi_connect) {
1160 status = qaf_mod->qaf_passthrough_out->stream.resume((struct audio_stream_out*) qaf_mod->qaf_passthrough_out);
1161 if (!status)
1162 out->offload_state = OFFLOAD_STATE_PLAYING;
1163 pthread_mutex_unlock(&out->lock);
1164 return status;
1165 }
1166 }
1167 }
1168 }
1169
1170 status = qaf_stream_start(out);
1171 pthread_mutex_unlock(&out->lock);
1172 ALOGD("%s Exit", __func__);
1173 return status;
1174}
1175
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301176static int qaf_deinit()
1177{
1178 ALOGV("%s %d", __func__, __LINE__);
1179 if (qaf_mod != NULL) {
1180 if (qaf_mod->qaf_compr_offload_out != NULL)
1181 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev, (struct audio_stream_out *) (qaf_mod->qaf_compr_offload_out));
1182 if (qaf_mod->qaf_compr_passthrough_out != NULL)
1183 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev, (struct audio_stream_out *) (qaf_mod->qaf_compr_passthrough_out));
1184
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301185 if (qaf_mod->qaf_passthrough_out) {
1186 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev, (struct audio_stream_out *) (qaf_mod->qaf_passthrough_out));
1187 qaf_mod->qaf_passthrough_out = NULL;
1188 }
1189
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301190 if (qaf_mod->qaf_lib != NULL) {
1191 dlclose(qaf_mod->qaf_lib);
1192 qaf_mod->qaf_lib = NULL;
1193 }
1194 free(qaf_mod);
1195 qaf_mod = NULL;
1196 }
1197 return 0;
1198}
1199
1200static void *qaf_offload_thread_loop(void *context)
1201{
1202 struct stream_out *out = (struct stream_out *) context;
1203 struct listnode *item;
1204 int ret = 0;
1205 struct str_parms *parms = NULL;
1206 int value = 0;
1207 char* kvpairs = NULL;
1208
1209 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1210 set_sched_policy(0, SP_FOREGROUND);
1211 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1212
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301213 ALOGV("%s", __func__);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301214 lock_output_stream(out);
1215 for (;;) {
1216 struct offload_cmd *cmd = NULL;
1217 stream_callback_event_t event;
1218 bool send_callback = false;
1219
1220 ALOGV("%s qaf_offload_cmd_list %d",
1221 __func__, list_empty(&out->qaf_offload_cmd_list));
1222 if (list_empty(&out->qaf_offload_cmd_list)) {
1223 ALOGV("%s SLEEPING", __func__);
1224 pthread_cond_wait(&out->qaf_offload_cond, &out->lock);
1225 ALOGV("%s RUNNING", __func__);
1226 continue;
1227 }
1228
1229 item = list_head(&out->qaf_offload_cmd_list);
1230 cmd = node_to_item(item, struct offload_cmd, node);
1231 list_remove(item);
1232
1233 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1234 free(cmd);
1235 break;
1236 }
1237
1238 pthread_mutex_unlock(&out->lock);
1239 send_callback = false;
1240 switch(cmd->cmd) {
1241 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1242 ALOGV("wait for ms12 buffer availability");
1243 while (1) {
1244 kvpairs = qaf_mod->qaf_audio_stream_get_param(out->qaf_stream_handle, "buf_available");
1245 if (kvpairs) {
1246 parms = str_parms_create_str(kvpairs);
1247 ret = str_parms_get_int(parms, "buf_available", &value);
1248 if (ret >= 0) {
1249 if (value >= (int)out->compr_config.fragment_size) {
1250 ALOGV("%s buffer available", __func__);
1251 str_parms_destroy(parms);
1252 parms = NULL;
1253 break;
1254 } else {
1255 ALOGV("%s sleep", __func__);
1256 str_parms_destroy(parms);
1257 parms = NULL;
1258 usleep(10000);
1259 }
1260 }
1261 free(kvpairs);
1262 kvpairs = NULL;
1263 }
1264 }
1265 send_callback = true;
1266 event = STREAM_CBK_EVENT_WRITE_READY;
1267 break;
1268 default:
1269 ALOGV("%s unknown command received: %d", __func__, cmd->cmd);
1270 break;
1271 }
1272 lock_output_stream(out);
1273 if (send_callback && out->offload_callback) {
1274 out->offload_callback(event, NULL, out->offload_cookie);
1275 }
1276 free(cmd);
1277 }
1278
1279 while (!list_empty(&out->qaf_offload_cmd_list)) {
1280 item = list_head(&out->qaf_offload_cmd_list);
1281 list_remove(item);
1282 free(node_to_item(item, struct offload_cmd, node));
1283 }
1284 pthread_mutex_unlock(&out->lock);
1285
1286 return NULL;
1287}
1288
1289static int qaf_create_offload_callback_thread(struct stream_out *out)
1290{
1291 ALOGV("%s", __func__);
1292 pthread_cond_init(&out->qaf_offload_cond, (const pthread_condattr_t *) NULL);
1293 list_init(&out->qaf_offload_cmd_list);
1294 pthread_create(&out->qaf_offload_thread, (const pthread_attr_t *) NULL,
1295 qaf_offload_thread_loop, out);
1296 return 0;
1297}
1298
1299static int qaf_destroy_offload_callback_thread(struct stream_out *out)
1300{
1301 ALOGV("%s", __func__);
1302 lock_output_stream(out);
1303 qaf_send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1304 pthread_mutex_unlock(&out->lock);
1305
1306 pthread_join(out->qaf_offload_thread, (void **) NULL);
1307 pthread_cond_destroy(&out->qaf_offload_cond);
1308
1309 return 0;
1310}
1311
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301312static int qaf_out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1313{
1314 struct str_parms *parms, *new_parms;
1315 char value[32];
1316 char *new_kv_pairs;
1317 int val = 0;
1318 struct stream_out *out = (struct stream_out *)stream;
1319 int ret = 0;
1320 int err = 0;
1321
1322 ALOGV("%s: enter: usecase(%d: %s) kvpairs: %s",
1323 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
1324 if ((NULL != qaf_mod->qaf_compr_offload_out)) {
1325 if (qaf_mod->qaf_msmd_enabled) {
1326 if (qaf_mod->passthrough_enabled && qaf_mod->hdmi_connect)
1327 return 1;
1328
1329 parms = str_parms_create_str(kvpairs);
1330 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1331
1332 /* usecase : hdmi sink which supports only 2-channel pcm */
1333 if (err >= 0) {
1334 val = atoi(value);
1335 if ((val & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1336 ((qaf_mod->hdmi_sink_channels == 2) && !(qaf_mod->passthrough_enabled))) {
1337 new_parms = str_parms_create();
1338 val |= AUDIO_DEVICE_OUT_SPEAKER;
1339 str_parms_add_int(new_parms, AUDIO_PARAMETER_STREAM_ROUTING, val);
1340 new_kv_pairs = str_parms_to_str(new_parms);
1341 qaf_mod->qaf_compr_offload_out->stream.common.set_parameters((struct audio_stream *) qaf_mod->qaf_compr_offload_out, new_kv_pairs);
1342 free(new_kv_pairs);
1343 str_parms_destroy(new_parms);
1344 }
1345 }
1346 str_parms_destroy(parms);
1347 } else {
1348 if (!(qaf_mod->passthrough_enabled && qaf_mod->hdmi_connect))
1349 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 +05301350
1351 parms = str_parms_create_str(kvpairs);
1352 if (!parms) {
1353 ALOGE("str_parms_create_str failed!");
1354 } else {
1355 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1356 if (err >= 0) {
1357 val = atoi(value);
1358 if (val == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) { //BT routing
1359 if (audio_extn_bt_hal_get_output_stream(qaf_mod->bt_hdl) == NULL && audio_extn_bt_hal_get_device(qaf_mod->bt_hdl) != NULL) {
1360 ret = audio_extn_bt_hal_open_output_stream(qaf_mod->bt_hdl,
1361 QAF_OUTPUT_SAMPLING_RATE,
1362 AUDIO_CHANNEL_OUT_STEREO,
1363 CODEC_BACKEND_DEFAULT_BIT_WIDTH);
1364 if (ret != 0) {
1365 ALOGE("%s: BT Output stream open failure!", __FUNCTION__);
1366 }
1367 }
1368 } else if (val != 0) {
1369 if (audio_extn_bt_hal_get_output_stream(qaf_mod->bt_hdl)!= NULL) {
1370 audio_extn_bt_hal_close_output_stream(qaf_mod->bt_hdl);
1371 }
1372 }
1373 }
1374 str_parms_destroy(parms);
1375 }
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301376 }
1377 }
1378
1379 if (audio_extn_qaf_passthrough_enabled(out)) {
1380 parms = str_parms_create_str(kvpairs);
1381 if (!parms) {
1382 ALOGE("str_parms_create_str failed!");
1383 } else {
1384 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1385 if (err >= 0) {
1386 val = atoi(value);
1387 if ((val & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1388 (qaf_mod->qaf_passthrough_out == NULL)) {
1389 audio_output_flags_t flags;
1390 struct audio_config config;
1391 audio_devices_t devices;
1392
1393 config.sample_rate = config.offload_info.sample_rate = QAF_OUTPUT_SAMPLING_RATE;
1394 config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
1395 config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
1396 config.offload_info.format = out->format;
1397 config.offload_info.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
1398 config.format = out->format;
1399 config.offload_info.channel_mask = config.channel_mask = out->channel_mask;
1400
1401 devices = AUDIO_DEVICE_OUT_AUX_DIGITAL;
1402 flags = out->flags;
1403
1404 if (out->qaf_stream_handle) {
1405 qaf_out_pause((struct audio_stream_out*)out);
1406 qaf_out_flush((struct audio_stream_out*)out);
1407 qaf_out_drain((struct audio_stream_out*)out, (audio_drain_type_t)STREAM_CBK_EVENT_DRAIN_READY);
1408 qaf_stream_close(out);
1409 }
1410 create_output_stream(out, &config, flags, devices, QAF_DEFAULT_PASSTHROUGH_HANDLE);
1411 qaf_mod->main_output_active = true;
1412 }
1413 }
1414 str_parms_destroy(parms);
1415 }
1416 }
1417
1418 return ret;
1419}
1420
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301421int audio_extn_qaf_open_output_stream(struct audio_hw_device *dev,
1422 audio_io_handle_t handle,
1423 audio_devices_t devices,
1424 audio_output_flags_t flags,
1425 struct audio_config *config,
1426 struct audio_stream_out **stream_out,
1427 const char *address __unused)
1428{
1429 int ret = 0;
1430 struct stream_out *out;
1431
1432 ret = adev_open_output_stream(dev, handle, devices, flags, config, stream_out, address);
1433 if (*stream_out == NULL) {
1434 goto error_open;
1435 }
1436
Deepak Agarwal1e42b852017-02-11 17:57:04 +05301437 if ( false == is_ms12_format(config->format) ) {
1438 ALOGV("%s: exiting qaf for non-ms12 format %x", __func__, config->format);
1439 return ret;
1440 }
1441
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301442 out = (struct stream_out *) *stream_out;
1443
1444 /* Override function pointers based on qaf definitions */
1445 out->stream.set_volume = qaf_out_set_volume;
1446 out->stream.pause = qaf_out_pause;
1447 out->stream.resume = qaf_out_resume;
1448 out->stream.drain = qaf_out_drain;
1449 out->stream.flush = qaf_out_flush;
1450
1451 out->stream.common.standby = qaf_out_standby;
1452 out->stream.common.set_parameters = qaf_out_set_parameters;
1453 out->stream.get_latency = qaf_out_get_latency;
1454 out->stream.write = qaf_out_write;
1455 out->stream.get_presentation_position = qaf_out_get_presentation_position;
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301456 out->platform_latency = 0;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301457 ret = qaf_stream_open(out, config, flags, devices);
1458 if (ret < 0) {
1459 ALOGE("%s, Error opening QAF stream err[%d]!", __func__, ret);
1460 adev_close_output_stream(dev, *stream_out);
1461 goto error_open;
1462 }
1463
1464 if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY) {
1465 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
Varun B34da7a42017-02-13 16:16:53 +05301466 out->config.period_size = QAF_DEEP_BUFFER_OUTPUT_PERIOD_SIZE;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301467 out->config.period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT;
Varun B34da7a42017-02-13 16:16:53 +05301468 out->config.start_threshold = QAF_DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4;
1469 out->config.avail_min = QAF_DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301470 }
1471
1472 *stream_out = &out->stream;
1473 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
1474 qaf_create_offload_callback_thread(out);
1475 }
1476 ALOGV("%s: exit", __func__);
1477 return 0;
1478error_open:
1479 *stream_out = NULL;
1480 ALOGD("%s: exit: ret %d", __func__, ret);
1481 return ret;
1482}
1483
1484void audio_extn_qaf_close_output_stream(struct audio_hw_device *dev,
1485 struct audio_stream_out *stream)
1486{
1487 struct stream_out *out = (struct stream_out *)stream;
1488
1489 ALOGV("%s: enter:stream_handle(%p) format = %x", __func__, out, out->format);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301490 if (qaf_mod->qaf_passthrough_out) {
1491 ALOGD("%s %d closing stream handle %p", __func__, __LINE__, qaf_mod->qaf_passthrough_out);
1492 pthread_mutex_lock(&qaf_mod->lock);
1493 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev, (struct audio_stream_out *) (qaf_mod->qaf_passthrough_out));
1494 adev_close_output_stream(dev, stream);
1495 qaf_mod->qaf_passthrough_out = NULL;
1496 qaf_mod->main_output_active = false;
1497 pthread_mutex_unlock(&qaf_mod->lock);
1498 return;
1499 }
1500
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301501 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
1502 qaf_destroy_offload_callback_thread(out);
1503 }
1504 qaf_mod->stream_drain_main = NULL;
1505 lock_output_stream(out);
1506 qaf_stream_close(out);
1507 pthread_mutex_unlock(&out->lock);
1508
1509 adev_close_output_stream(dev, stream);
1510 ALOGV("%s: exit", __func__);
1511}
1512
1513bool audio_extn_qaf_is_enabled()
1514{
1515 bool prop_enabled = false;
1516 char value[PROPERTY_VALUE_MAX] = {0};
1517 property_get("audio.qaf.enabled", value, NULL);
1518 prop_enabled = atoi(value) || !strncmp("true", value, 4);
1519 return (prop_enabled);
1520}
1521
1522int audio_extn_qaf_session_open(struct qaf *qaf_mod,
1523 device_license_config_t* lic_config)
1524{
1525 ALOGV("%s %d", __func__, __LINE__);
1526 int status = -ENOSYS;
1527
1528 pthread_mutex_init(&qaf_mod->lock, (const pthread_mutexattr_t *) NULL);
1529
1530 if (!qaf_mod->qaf_audio_session_open)
1531 return -EINVAL;
1532
1533 status = qaf_mod->qaf_audio_session_open(&qaf_mod->session_handle,
1534 (void *)(qaf_mod), (void *)lic_config);
1535 if(status < 0)
1536 return status;
1537
1538 if (qaf_mod->session_handle == NULL) {
1539 ALOGE("%s %d QAF wrapper session handle is NULL", __func__, __LINE__);
1540 return -ENOMEM;
1541 }
1542 if (qaf_mod->qaf_register_event_callback)
1543 qaf_mod->qaf_register_event_callback(qaf_mod->session_handle,
1544 qaf_mod, &notify_event_callback,
1545 AUDIO_DATA_EVENT);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301546
1547 if (property_get_bool("audio.qaf.msmd", false)) {
1548 qaf_mod->qaf_msmd_enabled = 1;
1549 }
1550
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301551 return status;
1552}
1553
1554char* audio_extn_qaf_stream_get_param(struct stream_out *out __unused, const char *kv_pair __unused)
1555{
1556 return NULL;
1557}
1558
1559int audio_extn_qaf_set_parameters(struct audio_device *adev, struct str_parms *parms)
1560{
1561 int status = 0, val = 0, channels = 0;
1562 char *format_params, *kv_parirs;
1563 struct str_parms *qaf_params;
1564 char value[32];
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301565 char prop_value[PROPERTY_VALUE_MAX];
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301566 bool passth_support = false;
1567
1568 ALOGV("%s %d ", __func__, __LINE__);
1569 if (!qaf_mod || !qaf_mod->qaf_audio_session_set_param) {
1570 return -EINVAL;
1571 }
1572
1573 status = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
1574 if (status >= 0) {
1575 val = atoi(value);
1576 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1577 if (property_get_bool("audio.offload.passthrough", false) &&
1578 property_get_bool("audio.qaf.reencode", false)) {
1579
1580 qaf_params = str_parms_create();
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301581 property_get("audio.qaf.hdmi.out", prop_value, NULL);
1582 if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_E_AC3) &&
1583 (strncmp(prop_value, "ddp", 3) == 0)) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301584 passth_support = true;
1585 if (qaf_params) {
1586 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_RENDER_FORMAT,
1587 AUDIO_QAF_PARAMETER_VALUE_REENCODE_EAC3);
1588 }
1589 } else if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_AC3)) {
1590 passth_support = true;
1591 if (qaf_params) {
1592 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_RENDER_FORMAT,
1593 AUDIO_QAF_PARAMETER_VALUE_REENCODE_AC3);
1594 }
1595 }
1596
1597 if (passth_support) {
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301598 qaf_mod->passthrough_enabled = 1;
1599 if (qaf_mod->qaf_msmd_enabled) {
1600 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1601 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI_AND_SPK);
1602 } else {
1603 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1604 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI);
1605 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301606 format_params = str_parms_to_str(qaf_params);
1607
1608 qaf_mod->qaf_audio_session_set_param(qaf_mod->session_handle, format_params);
1609 }
1610 str_parms_destroy(qaf_params);
1611 }
1612
1613 if (!passth_support) {
1614 channels = platform_edid_get_max_channels(adev->platform);
1615
1616 qaf_params = str_parms_create();
1617 switch (channels) {
1618 case 8:
1619 ALOGV("%s: Switching Qaf output to 7.1 channels", __func__);
1620 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_CHANNELS,
1621 AUDIO_QAF_PARAMETER_VALUE_8_CHANNELS);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301622 if (qaf_mod->qaf_msmd_enabled) {
1623 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1624 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI_AND_SPK);
1625 } else {
1626 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1627 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI);
1628 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301629 qaf_mod->hdmi_sink_channels = channels;
1630 break;
1631 case 6:
1632 ALOGV("%s: Switching Qaf output to 5.1 channels", __func__);
1633 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_CHANNELS,
1634 AUDIO_QAF_PARAMETER_VALUE_6_CHANNELS);
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301635 if (qaf_mod->qaf_msmd_enabled) {
1636 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1637 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI_AND_SPK);
1638 } else {
1639 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1640 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI);
1641 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301642 qaf_mod->hdmi_sink_channels = channels;
1643 break;
1644 default:
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301645 ALOGV("%s: Switching Qaf output to default channels", __func__);
1646 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_CHANNELS,
1647 AUDIO_QAF_PARAMETER_VALUE_DEFAULT_CHANNELS);
1648 if (qaf_mod->qaf_msmd_enabled) {
1649 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1650 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI_AND_SPK);
1651 } else {
1652 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1653 AUDIO_QAF_PARAMETER_VALUE_DEVICE_SPEAKER);
1654 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301655 qaf_mod->hdmi_sink_channels = 2;
1656 break;
1657 }
1658
1659 format_params = str_parms_to_str(qaf_params);
1660 qaf_mod->qaf_audio_session_set_param(qaf_mod->session_handle, format_params);
1661 str_parms_destroy(qaf_params);
1662 }
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301663 qaf_mod->hdmi_connect = 1;
Bharath Gopal01310bb2016-12-05 15:39:32 +05301664 } else if (val & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) {
1665 ALOGV("%s: Opening a2dp output...", __FUNCTION__);
1666 status = audio_extn_bt_hal_load(&qaf_mod->bt_hdl);
1667 if(status != 0) {
1668 ALOGE("%s:Error opening BT module", __FUNCTION__);
1669 return status;
1670 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301671 }
1672 }
1673
1674 status = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
1675 if (status >= 0) {
1676 val = atoi(value);
1677 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1678 qaf_params = str_parms_create();
1679 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1680 AUDIO_QAF_PARAMETER_VALUE_DEVICE_SPEAKER);
1681 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_RENDER_FORMAT,
1682 AUDIO_QAF_PARAMETER_VALUE_PCM);
1683 qaf_mod->hdmi_sink_channels = 0;
1684
Lakshman Chaluvarajub4ec8702016-11-04 19:21:12 +05301685 qaf_mod->passthrough_enabled = 0;
1686 qaf_mod->hdmi_connect = 0;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301687 format_params = str_parms_to_str(qaf_params);
1688 qaf_mod->qaf_audio_session_set_param(qaf_mod->session_handle, format_params);
1689 str_parms_destroy(qaf_params);
Bharath Gopal01310bb2016-12-05 15:39:32 +05301690 } else if (val & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) {
1691 ALOGV("%s: Closing a2dp output...", __FUNCTION__);
1692 audio_extn_bt_hal_unload(qaf_mod->bt_hdl);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301693 }
1694 }
1695
1696 kv_parirs = str_parms_to_str(parms);
1697 qaf_mod->qaf_audio_session_set_param(qaf_mod->session_handle, kv_parirs);
1698
1699 return status;
1700}
1701
1702char* audio_extn_qaf_get_param(struct audio_device *adev __unused, const char *kv_pair __unused)
1703{
1704 return 0;
1705}
1706
1707int audio_extn_qaf_init(struct audio_device *adev)
1708{
1709 char value[PROPERTY_VALUE_MAX] = {0};
1710 char lib_name[PROPERTY_VALUE_MAX] = {0};
1711 unsigned char* license_data = NULL;
1712 device_license_config_t* lic_config = NULL;
1713 ALOGV("%s %d", __func__, __LINE__);
1714 int ret = 0, size = 0;
1715
1716 qaf_mod = malloc(sizeof(struct qaf));
1717 if(qaf_mod == NULL) {
1718 ALOGE("%s, out of memory", __func__);
1719 ret = -ENOMEM;
1720 goto done;
1721 }
1722 memset(qaf_mod, 0, sizeof(struct qaf));
1723 lic_config = (device_license_config_t*) calloc(1, sizeof(device_license_config_t));
1724 if(lic_config == NULL) {
1725 ALOGE("%s, out of memory", __func__);
1726 ret = -ENOMEM;
1727 goto done;
1728 }
1729 qaf_mod->adev = adev;
1730 property_get("audio.qaf.library", value, NULL);
1731 snprintf(lib_name, PROPERTY_VALUE_MAX, "%s", value);
1732
Nikhil Laturkar20c17d52016-06-13 22:08:16 +05301733 qaf_mod->qaf_lib = dlopen(lib_name, RTLD_NOW);
1734 if (qaf_mod->qaf_lib == NULL) {
1735 ALOGE("%s: DLOPEN failed for %s", __func__, lib_name);
1736 ret = -EINVAL;
1737 goto done;
1738 }
1739
1740 ALOGV("%s: DLOPEN successful for %s", __func__, lib_name);
1741 qaf_mod->qaf_audio_session_open =
1742 (int (*)(audio_session_handle_t* session_handle, void *p_data, void* license_data))dlsym(qaf_mod->qaf_lib,
1743 "audio_session_open");
1744 qaf_mod->qaf_audio_session_close =
1745 (int (*)(audio_session_handle_t session_handle))dlsym(qaf_mod->qaf_lib,
1746 "audio_session_close");
1747 qaf_mod->qaf_audio_stream_open =
1748 (int (*)(audio_session_handle_t session_handle, audio_stream_handle_t* stream_handle,
1749 audio_stream_config_t input_config, audio_devices_t devices, stream_type_t flags))dlsym(qaf_mod->qaf_lib,
1750 "audio_stream_open");
1751 qaf_mod->qaf_audio_stream_close =
1752 (int (*)(audio_stream_handle_t stream_handle))dlsym(qaf_mod->qaf_lib,
1753 "audio_stream_close");
1754 qaf_mod->qaf_audio_stream_set_param =
1755 (int (*)(audio_stream_handle_t stream_handle, const char* kv_pairs))dlsym(qaf_mod->qaf_lib,
1756 "audio_stream_set_param");
1757 qaf_mod->qaf_audio_session_set_param =
1758 (int (*)(audio_session_handle_t handle, const char* kv_pairs))dlsym(qaf_mod->qaf_lib,
1759 "audio_session_set_param");
1760 qaf_mod->qaf_audio_stream_get_param =
1761 (char* (*)(audio_stream_handle_t stream_handle, const char* key))dlsym(qaf_mod->qaf_lib,
1762 "audio_stream_get_param");
1763 qaf_mod->qaf_audio_session_get_param =
1764 (char* (*)(audio_session_handle_t handle, const char* key))dlsym(qaf_mod->qaf_lib,
1765 "audio_session_get_param");
1766 qaf_mod->qaf_audio_stream_start =
1767 (int (*)(audio_stream_handle_t stream_handle))dlsym(qaf_mod->qaf_lib,
1768 "audio_stream_start");
1769 qaf_mod->qaf_audio_stream_stop =
1770 (int (*)(audio_stream_handle_t stream_handle))dlsym(qaf_mod->qaf_lib,
1771 "audio_stream_stop");
1772 qaf_mod->qaf_audio_stream_pause =
1773 (int (*)(audio_stream_handle_t stream_handle))dlsym(qaf_mod->qaf_lib,
1774 "audio_stream_pause");
1775 qaf_mod->qaf_audio_stream_flush =
1776 (int (*)(audio_stream_handle_t stream_handle))dlsym(qaf_mod->qaf_lib,
1777 "audio_stream_flush");
1778 qaf_mod->qaf_audio_stream_write =
1779 (int (*)(audio_stream_handle_t stream_handle, const void* buf, int size))dlsym(qaf_mod->qaf_lib,
1780 "audio_stream_write");
1781 qaf_mod->qaf_register_event_callback =
1782 (void (*)(audio_session_handle_t session_handle, void *priv_data, notify_event_callback_t event_callback,
1783 audio_event_id_t event_id))dlsym(qaf_mod->qaf_lib,
1784 "register_event_callback");
1785
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301786 license_data = platform_get_license((struct audio_hw_device *)(qaf_mod->adev->platform), &size);
1787 if (!license_data) {
1788 ALOGE("License is not present");
1789 ret = -EINVAL;
1790 goto done;
1791 }
1792 lic_config->p_license = (unsigned char* ) calloc(1, size);
1793 if(lic_config->p_license == NULL) {
1794 ALOGE("%s, out of memory", __func__);
1795 ret = -ENOMEM;
1796 goto done;
1797 }
1798 lic_config->l_size = size;
1799 memcpy(lic_config->p_license, license_data, size);
1800
1801 if (property_get("audio.qaf.manufacturer", value, "") && atoi(value)) {
1802 lic_config->manufacturer_id = (unsigned long) atoi (value);
1803 } else {
1804 ALOGE("audio.qaf.manufacturer id is not set");
1805 ret = -EINVAL;
1806 goto done;
1807 }
1808
1809 ret = audio_extn_qaf_session_open(qaf_mod, lic_config);
1810done:
1811 if (license_data != NULL) {
1812 free(license_data);
1813 license_data = NULL;
1814 }
1815 if (lic_config->p_license != NULL) {
1816 free(lic_config->p_license);
1817 lic_config->p_license = NULL;
1818 }
1819 if (lic_config != NULL) {
1820 free(lic_config);
1821 lic_config = NULL;
1822 }
1823 if (ret != 0) {
Nikhil Laturkar20c17d52016-06-13 22:08:16 +05301824 if (qaf_mod->qaf_lib != NULL) {
1825 dlclose(qaf_mod->qaf_lib);
1826 qaf_mod->qaf_lib = NULL;
1827 }
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05301828 if (qaf_mod != NULL) {
1829 free(qaf_mod);
1830 qaf_mod = NULL;
1831 }
1832 }
1833 return ret;
1834}
1835
1836void audio_extn_qaf_deinit()
1837{
1838 qaf_session_close();
1839 qaf_deinit();
1840}