blob: d631275f2bd97d2a1c7a3b189206da33c2199478 [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
39#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
40#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
41#define QAF_DEFAULT_COMPR_AUDIO_HANDLE 1001
42#define QAF_DEFAULT_COMPR_PASSTHROUGH_HANDLE 1002
43
44#include <stdlib.h>
45#include <pthread.h>
46#include <errno.h>
47#include <dlfcn.h>
48#include <sys/resource.h>
49#include <sys/prctl.h>
50#include <cutils/properties.h>
51#include <cutils/str_parms.h>
52#include <cutils/log.h>
53#include <cutils/atomic.h>
54#include "audio_utils/primitives.h"
55#include "audio_hw.h"
56#include "platform_api.h"
57#include <platform.h>
58#include <system/thread_defs.h>
59#include <cutils/sched_policy.h>
60#include "audio_extn.h"
61#include <qti_audio.h>
62#include "sound/compress_params.h"
63
64#define QAF_OUTPUT_SAMPLING_RATE 48000
65#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
66#define QAF_PLAYBACK_LATENCY 30
67
68#define QAF_LATENCY (COMPRESS_OFFLOAD_PLAYBACK_LATENCY + QAF_PLAYBACK_LATENCY)
69
70#ifdef QAF_DUMP_ENABLED
71FILE *fp_output_writer_hdmi = NULL;
72#endif
73
74typedef enum {
75AUDIO_OUTPUT_FLAG_MAIN = 0x4000, // Flag for Main Input Stream
76AUDIO_OUTPUT_FLAG_ASSOCIATED = 0x8000, // Flag for Assocated Input Stream
77} qaf_audio_output_flags_t;
78
79struct qaf {
80 struct audio_device *adev;
81 audio_session_handle_t session_handle;
82 void *qaf_lib;
83 int (*qaf_audio_session_open)(audio_session_handle_t* session_handle, void *p_data, void* license_data);
84 int (*qaf_audio_session_close)(audio_session_handle_t session_handle);
85 int (*qaf_audio_stream_open)(audio_session_handle_t session_handle, audio_stream_handle_t* stream_handle,
86 audio_stream_config_t input_config, audio_devices_t devices, stream_type_t flags);
87 int (*qaf_audio_stream_close)(audio_stream_handle_t stream_handle);
88 int (*qaf_audio_stream_set_param)(audio_stream_handle_t stream_handle, const char* kv_pairs);
89 int (*qaf_audio_session_set_param)(audio_session_handle_t handle, const char* kv_pairs);
90 char* (*qaf_audio_stream_get_param)(audio_stream_handle_t stream_handle, const char* key);
91 char* (*qaf_audio_session_get_param)(audio_session_handle_t handle, const char* key);
92 int (*qaf_audio_stream_start)(audio_stream_handle_t handle);
93 int (*qaf_audio_stream_stop)(audio_stream_handle_t stream_handle);
94 int (*qaf_audio_stream_pause)(audio_stream_handle_t stream_handle);
95 int (*qaf_audio_stream_flush)(audio_stream_handle_t stream_handle);
96 int (*qaf_audio_stream_write)(audio_stream_handle_t stream_handle, const void* buf, int size);
97 void (*qaf_register_event_callback)(audio_session_handle_t session_handle, void *priv_data,
98 notify_event_callback_t event_callback, audio_event_id_t event_id);
99 pthread_mutex_t lock;
100 struct stream_out *stream_drain_main;
101 struct stream_out *qaf_compr_offload_out;
102 struct stream_out *qaf_compr_passthrough_out;
103 int passthrough_enabled;
104 int hdmi_sink_channels;
105 bool multi_ch_out_enabled;
106 bool main_output_active;
107 bool assoc_output_active;
108};
109
110static struct qaf *qaf_mod = NULL;
111
112static void lock_output_stream(struct stream_out *out)
113{
114 pthread_mutex_lock(&out->pre_lock);
115 pthread_mutex_lock(&out->lock);
116 pthread_mutex_unlock(&out->pre_lock);
117}
118
119static int qaf_send_offload_cmd_l(struct stream_out* out, int command)
120{
121 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
122
123 if (!cmd) {
124 ALOGE("failed to allocate mem for command 0x%x", command);
125 return -ENOMEM;
126 }
127
128 ALOGV("%s %d", __func__, command);
129
130 cmd->cmd = command;
131 list_add_tail(&out->qaf_offload_cmd_list, &cmd->node);
132 pthread_cond_signal(&out->qaf_offload_cond);
133 return 0;
134}
135
136static int audio_extn_qaf_stream_stop(struct stream_out *out)
137{
138 ALOGV("%s: %d start", __func__, __LINE__);
139 if (!qaf_mod->qaf_audio_stream_stop)
140 return -EINVAL;
141
142 return qaf_mod->qaf_audio_stream_stop(out->qaf_stream_handle);
143}
144
145static int qaf_out_standby(struct audio_stream *stream)
146{
147 struct stream_out *out = (struct stream_out *)stream;
148 int status = 0;
149
150 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
151 stream, out->usecase, use_case_table[out->usecase]);
152
153 lock_output_stream(out);
154 if (!out->standby) {
155 out->standby = true;
156 status = audio_extn_qaf_stream_stop(out);
157 }
158 pthread_mutex_unlock(&out->lock);
159 out->written = 0;
160 return status;
161}
162
163static int qaf_stream_set_param(struct stream_out *out, const char *kv_pair)
164{
165 ALOGV("%s %d kvpair: %s", __func__, __LINE__, kv_pair);
166 if (!qaf_mod->qaf_audio_stream_set_param)
167 return -EINVAL;
168
169 return qaf_mod->qaf_audio_stream_set_param(out->qaf_stream_handle, kv_pair);
170}
171
172static int qaf_out_set_parameters(struct audio_stream *stream, const char *kvpairs)
173{
174 struct stream_out *out = (struct stream_out *)stream;
175 int ret = 0;
176
177 ALOGV("%s: enter: usecase(%d: %s) kvpairs: %s",
178 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
179 lock_output_stream(out);
180 ret = qaf_stream_set_param(out, kvpairs);
181 pthread_mutex_unlock(&out->lock);
182 if ((NULL != qaf_mod->qaf_compr_offload_out)) {
183 qaf_mod->qaf_compr_offload_out->stream.common.set_parameters((struct audio_stream *) qaf_mod->qaf_compr_offload_out, kvpairs);
184 }
185 return ret;
186}
187
188static int qaf_write_input_buffer(struct stream_out *out, const void *buffer, int bytes)
189{
190 int ret = 0;
191 ALOGVV("%s bytes = %d [%p]", __func__, bytes, out->qaf_stream_handle);
192 if (!qaf_mod->qaf_audio_stream_write)
193 return -EINVAL;
194
195 if (out->qaf_stream_handle)
196 ret = qaf_mod->qaf_audio_stream_write(out->qaf_stream_handle, buffer, bytes);
197 return ret;
198}
199
200static int qaf_out_set_volume(struct audio_stream_out *stream __unused, float left,
201 float right)
202{
203 if (qaf_mod->qaf_compr_offload_out != NULL) {
204 return qaf_mod->qaf_compr_offload_out->stream.set_volume(
205 (struct audio_stream_out *)qaf_mod->qaf_compr_offload_out, left, right);
206 }
207 return -ENOSYS;
208}
209
210static int qaf_stream_start(struct stream_out *out)
211{
212 if (!qaf_mod->qaf_audio_stream_start)
213 return -EINVAL;
214
215 return qaf_mod->qaf_audio_stream_start(out->qaf_stream_handle);
216}
217
218static int qaf_start_output_stream(struct stream_out *out)
219{
220 int ret = 0;
221 struct audio_device *adev = out->dev;
222 int snd_card_status = get_snd_card_state(adev);
223
224 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
225 ret = -EINVAL;
226 usleep(50000);
227 return ret;
228 }
229
230 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
231 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
232 out->devices);
233
234 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
235 ALOGE("%s: sound card is not active/SSR returning error", __func__);
236 ret = -EIO;
237 usleep(50000);
238 return ret;
239 }
240
241 return qaf_stream_start(out);
242}
243
244static ssize_t qaf_out_write(struct audio_stream_out *stream, const void *buffer,
245 size_t bytes)
246{
247 struct stream_out *out = (struct stream_out *)stream;
248 struct audio_device *adev = out->dev;
249 ssize_t ret = 0;
250
251 ALOGV("qaf_out_write bytes = %d, usecase[%d] and flags[%x] for handle[%p]",(int)bytes, out->usecase, out->flags, out);
252 lock_output_stream(out);
253
254 if (out->standby) {
255 out->standby = false;
256 pthread_mutex_lock(&adev->lock);
257 ret = qaf_start_output_stream(out);
258 pthread_mutex_unlock(&adev->lock);
259 /* ToDo: If use case is compress offload should return 0 */
260 if (ret != 0) {
261 out->standby = true;
262 goto exit;
263 }
264 }
265
266 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
267 audio_utils_set_hdmi_channel_status(out, (char *)buffer, bytes);
268 adev->is_channel_status_set = true;
269 }
270
271 ret = qaf_write_input_buffer(out, buffer, bytes);
272 ALOGV("%s, ret [%d] ", __func__, (int)ret);
273 if (ret < 0) {
274 goto exit;
275 }
276 out->written += bytes / ((popcount(out->channel_mask) * sizeof(short)));
277
278exit:
279
280 pthread_mutex_unlock(&out->lock);
281
282 if (ret < 0) {
283 if (ret == -EAGAIN) {
284 ALOGV("No space available in ms12 driver, post msg to cb thread");
285 lock_output_stream(out);
286 ret = qaf_send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
287 pthread_mutex_unlock(&out->lock);
288 bytes = 0;
289 }
290 if(ret == -ENOMEM || ret == -EPERM){
291 if (out->pcm)
292 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
293 qaf_out_standby(&out->stream.common);
294 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
295 out->stream.common.get_sample_rate(&out->stream.common));
296 }
297 }
298 return bytes;
299}
300
301static int qaf_get_timestamp(struct stream_out *out, uint64_t *frames, struct timespec *timestamp)
302{
303 int ret = 0;
304 struct str_parms *parms;
305 int value = 0;
306 int signed_frames = 0;
307 const char* kvpairs = NULL;
308
309 ALOGV("%s out->format %d", __func__, out->format);
310 if(out->format & AUDIO_FORMAT_PCM_16_BIT) {
311 *frames = out->written;
312 signed_frames = out->written - (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
313 // It would be unusual for this value to be negative, but check just in case ...
314 if (signed_frames >= 0) {
315 *frames = signed_frames;
316 }
317 clock_gettime(CLOCK_MONOTONIC, timestamp);
318 } else if (qaf_mod->qaf_audio_stream_get_param) {
319 kvpairs = qaf_mod->qaf_audio_stream_get_param(out->qaf_stream_handle, "position");
320 if (kvpairs) {
321 parms = str_parms_create_str(kvpairs);
322 ret = str_parms_get_int(parms, "position", &value);
323 if (ret >= 0) {
324 *frames = value;
325 signed_frames = value - (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
326 // It would be unusual for this value to be negative, but check just in case ...
327 if (signed_frames >= 0) {
328 *frames = signed_frames;
329 }
330 clock_gettime(CLOCK_MONOTONIC, timestamp);
331 }
332 str_parms_destroy(parms);
333 }
334 } else {
335 ret = -EINVAL;
336 }
337 return ret;
338}
339
340static int qaf_out_get_presentation_position(const struct audio_stream_out *stream,
341 uint64_t *frames, struct timespec *timestamp)
342{
343 struct stream_out *out = (struct stream_out *)stream;
344 int ret = -1;
345 lock_output_stream(out);
346 ret = qaf_get_timestamp(out, frames, timestamp);
347 pthread_mutex_unlock(&out->lock);
348
349 return ret;
350}
351
352static int qaf_stream_pause(struct stream_out *out)
353{
354 ALOGV("%s: %d start", __func__, __LINE__);
355 if (!qaf_mod->qaf_audio_stream_pause)
356 return -EINVAL;
357
358 return qaf_mod->qaf_audio_stream_pause(out->qaf_stream_handle);
359}
360
361static int qaf_out_pause(struct audio_stream_out* stream)
362{
363 struct stream_out *out = (struct stream_out *)stream;
364 int status = -ENOSYS;
365 ALOGE("%s", __func__);
366 lock_output_stream(out);
367 status = qaf_stream_pause(out);
368 pthread_mutex_unlock(&out->lock);
369 return status;
370}
371
372static int qaf_out_resume(struct audio_stream_out* stream)
373{
374 struct stream_out *out = (struct stream_out *)stream;
375 int status = -ENOSYS;
376 ALOGD("%s", __func__);
377 lock_output_stream(out);
378 status = qaf_stream_start(out);
379 pthread_mutex_unlock(&out->lock);
380 ALOGD("%s Exit", __func__);
381 return status;
382}
383
384static int qaf_out_drain(struct audio_stream_out* stream, audio_drain_type_t type __unused )
385{
386 struct stream_out *out = (struct stream_out *)stream;
387 int status = 0;
388 ALOGV("%s stream_handle = %p , format = %x", __func__, out->qaf_stream_handle, out->format);
389 lock_output_stream(out);
390 if (out->offload_callback && out->qaf_stream_handle) {
391 /* Stream stop will trigger EOS and on EOS_EVENT received
392 from callback DRAIN_READY command is sent */
393 status = audio_extn_qaf_stream_stop(out);
394 if (out->format != AUDIO_FORMAT_PCM_16_BIT)
395 qaf_mod->stream_drain_main = out;
396 }
397 pthread_mutex_unlock(&out->lock);
398 return status;
399}
400
401static int audio_extn_qaf_stream_flush(struct stream_out *out)
402{
403 ALOGV("%s: %d exit", __func__, __LINE__);
404 if (!qaf_mod->qaf_audio_stream_flush)
405 return -EINVAL;
406
407 return qaf_mod->qaf_audio_stream_flush(out->qaf_stream_handle);
408}
409
410static int qaf_out_flush(struct audio_stream_out* stream)
411{
412 struct stream_out *out = (struct stream_out *)stream;
413 ALOGV("%s", __func__);
414 int status = -ENOSYS;
415 lock_output_stream(out);
416 status = audio_extn_qaf_stream_flush(out);
417 pthread_mutex_unlock(&out->lock);
418 ALOGV("%s Exit", __func__);
419 return status;
420}
421
422static uint32_t qaf_out_get_latency(const struct audio_stream_out *stream __unused)
423{
424 uint32_t latency = 0;
425
426 latency = QAF_LATENCY;
427 ALOGV("%s: Latency %d", __func__, latency);
428 return latency;
429}
430
431static 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)
432{
433
434/*
435 For SPKR:
436 1. Open pcm device if device_id passed to it SPKR and write the data to pcm device
437
438 For HDMI
439 1.Open compress device for HDMI(PCM or AC3) based on current_hdmi_output_format
440 2.create offload_callback thread to receive async events
441 3.Write the data to compress device. If not all the data is consumed by the driver,
442 add a command to offload_callback thread.
443*/
444 int ret;
445 audio_output_flags_t flags;
446 struct qaf* qaf_module = (struct qaf* ) prv_data;
447 ALOGV("%s device 0x%X, %d in event = %d", __func__, device, __LINE__, event_id);
448
449 if (event_id == AUDIO_DATA_EVENT) {
450 ALOGVV("Device id %x %s %d, bytes to written %d", device, __func__,__LINE__, size);
451
452 pthread_mutex_lock(&qaf_module->lock);
453 if ((device == (AUDIO_DEVICE_OUT_AUX_DIGITAL | AUDIO_COMPRESSED_OUT_DD)) ||
454 (device == (AUDIO_DEVICE_OUT_AUX_DIGITAL | AUDIO_COMPRESSED_OUT_DDP))) {
455
456 if (NULL == qaf_mod->qaf_compr_passthrough_out) {
457 struct audio_config config;
458 audio_devices_t devices;
459
460 if (qaf_mod->qaf_compr_offload_out) {
461 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev,
462 (struct audio_stream_out *) (qaf_mod->qaf_compr_offload_out));
463 qaf_mod->qaf_compr_offload_out = NULL;
464 }
465
466 config.sample_rate = config.offload_info.sample_rate = QAF_OUTPUT_SAMPLING_RATE;
467 config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
468 config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
469
470 if (device == (AUDIO_DEVICE_OUT_AUX_DIGITAL | AUDIO_COMPRESSED_OUT_DDP))
471 config.format = config.offload_info.format = AUDIO_FORMAT_E_AC3;
472 else
473 config.format = config.offload_info.format = AUDIO_FORMAT_AC3;
474
475 config.offload_info.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
476 config.offload_info.channel_mask = config.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
477 flags = AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_NON_BLOCKING;
478 devices = AUDIO_DEVICE_OUT_AUX_DIGITAL;
479
480 ret = adev_open_output_stream((struct audio_hw_device *) qaf_mod->adev, QAF_DEFAULT_COMPR_PASSTHROUGH_HANDLE, devices,
481 flags, &config, (struct audio_stream_out **) &(qaf_mod->qaf_compr_passthrough_out), NULL);
482 if (ret < 0) {
483 ALOGE("%s: adev_open_output_stream failed with ret = %d!", __func__, ret);
484 pthread_mutex_unlock(&qaf_module->lock);
485 return;
486 }
487 }
488
489 if (!qaf_mod->passthrough_enabled)
490 qaf_mod->passthrough_enabled = 1;
491
492 ret = qaf_mod->qaf_compr_passthrough_out->stream.write((struct audio_stream_out *) qaf_mod->qaf_compr_passthrough_out, buf, size);
493 } else {
494 if (device == AUDIO_DEVICE_OUT_AUX_DIGITAL && !qaf_mod->multi_ch_out_enabled) {
495 if (qaf_mod->qaf_compr_offload_out) {
496 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev,
497 (struct audio_stream_out *) (qaf_mod->qaf_compr_offload_out));
498 qaf_mod->qaf_compr_offload_out = NULL;
499 }
500 qaf_mod->multi_ch_out_enabled = 1;
501 } else if (device == AUDIO_DEVICE_OUT_SPEAKER && qaf_mod->multi_ch_out_enabled) {
502 if (qaf_mod->qaf_compr_offload_out) {
503 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev,
504 (struct audio_stream_out *) (qaf_mod->qaf_compr_offload_out));
505 qaf_mod->qaf_compr_offload_out = NULL;
506 }
507 qaf_mod->multi_ch_out_enabled = 0;
508 }
509
510 if (NULL == qaf_mod->qaf_compr_offload_out) {
511 struct audio_config config;
512 audio_devices_t devices;
513
514 config.sample_rate = config.offload_info.sample_rate = QAF_OUTPUT_SAMPLING_RATE;
515 config.offload_info.version = AUDIO_INFO_INITIALIZER.version;
516 config.offload_info.size = AUDIO_INFO_INITIALIZER.size;
517 config.offload_info.format = AUDIO_FORMAT_PCM_16_BIT_OFFLOAD;
518 config.offload_info.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
519 config.format = AUDIO_FORMAT_PCM_16_BIT_OFFLOAD;
520 devices = AUDIO_DEVICE_NONE;
521
522 if (device == AUDIO_DEVICE_OUT_AUX_DIGITAL) {
523 if (qaf_mod->hdmi_sink_channels == 8) {
524 config.offload_info.channel_mask = config.channel_mask = AUDIO_CHANNEL_OUT_7POINT1;
525 } else if (qaf_mod->hdmi_sink_channels == 6) {
526 config.offload_info.channel_mask = config.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
527 } else {
528 config.offload_info.channel_mask = config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
529 }
530 devices = AUDIO_DEVICE_OUT_AUX_DIGITAL;
531 } else {
532 config.offload_info.channel_mask = config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
533 qaf_mod->multi_ch_out_enabled = 0;
534 }
535 flags = AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING;
536
537 /* TODO:: Need to Propagate errors to framework */
538 ret = adev_open_output_stream((struct audio_hw_device *) qaf_mod->adev, QAF_DEFAULT_COMPR_AUDIO_HANDLE, devices,
539 flags, &config, (struct audio_stream_out **) &(qaf_mod->qaf_compr_offload_out), NULL);
540 if (ret < 0) {
541 ALOGE("%s: adev_open_output_stream failed with ret = %d!", __func__, ret);
542 pthread_mutex_unlock(&qaf_module->lock);
543 return;
544 }
545 }
546
547 if (qaf_mod->passthrough_enabled) {
548 qaf_mod->passthrough_enabled = 0;
549 if (qaf_mod->qaf_compr_passthrough_out) {
550 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev,
551 (struct audio_stream_out *) (qaf_mod->qaf_compr_passthrough_out));
552 qaf_mod->qaf_compr_passthrough_out = NULL;
553 }
554 }
555
556 /*
557 * TODO:: Since this is mixed data,
558 * need to identify to which stream the error should be sent
559 */
560 ret = qaf_mod->qaf_compr_offload_out->stream.write((struct audio_stream_out *) qaf_mod->qaf_compr_offload_out, buf, size);
561 }
562
563 ALOGVV("%s:%d stream write ret = %d for out handle[%p]", __func__, __LINE__, ret, qaf_mod->qaf_compr_offload_out);
564 pthread_mutex_unlock(&qaf_module->lock);
565 } else if (event_id == AUDIO_EOS_MAIN_DD_DDP_EVENT || event_id == AUDIO_EOS_MAIN_AAC_EVENT) {
566 /* TODO:: Only MAIN Stream EOS Event is added, need to add ASSOC stream EOS Event */
567 struct stream_out *out = qaf_module->stream_drain_main;
568 if (out != NULL) {
569 lock_output_stream(out);
570 out->offload_callback(STREAM_CBK_EVENT_DRAIN_READY, NULL, out->offload_cookie);
571 pthread_mutex_unlock(&out->lock);
572 qaf_module->stream_drain_main = NULL;
573 ALOGV("%s %d sent DRAIN_READY", __func__, __LINE__);
574 }
575 }
576 ALOGV("%s %d", __func__, __LINE__);
577}
578
579static int qaf_session_close()
580{
581 ALOGV("%s %d", __func__, __LINE__);
582 if (qaf_mod != NULL) {
583 if (!qaf_mod->qaf_audio_session_close)
584 return -EINVAL;
585
586 qaf_mod->qaf_audio_session_close(qaf_mod->session_handle);
587 qaf_mod->session_handle = NULL;
588 pthread_mutex_destroy(&qaf_mod->lock);
589 }
590 return 0;
591}
592
593static int qaf_stream_close(struct stream_out *out)
594{
595 int ret = 0;
596 ALOGV( "%s %d", __func__, __LINE__);
597 if (!qaf_mod->qaf_audio_stream_close)
598 return -EINVAL;
599 if (out->qaf_stream_handle) {
600 ALOGV( "%s %d output active flag is %x and stream handle %p", __func__, __LINE__, out->flags, out->qaf_stream_handle);
601 if ((out->flags & AUDIO_OUTPUT_FLAG_ASSOCIATED) && (out->flags & AUDIO_OUTPUT_FLAG_MAIN)) { /* Close for Stream with Main and Associated Content*/
602 qaf_mod->main_output_active = false;
603 qaf_mod->assoc_output_active = false;
604 } else if (out->flags & AUDIO_OUTPUT_FLAG_MAIN) {/*Close for Main Stream*/
605 qaf_mod->main_output_active = false;
606 qaf_mod->assoc_output_active = false; /* TODO to remove resetting associated stream active flag when main stream is closed*/
607 } else if (out->flags & AUDIO_OUTPUT_FLAG_ASSOCIATED) { /*Close for Associated Stream*/
608 qaf_mod->assoc_output_active = false;
609 } else { /*Close for Local Playback*/
610 qaf_mod->main_output_active = false;
611 }
612 ret = qaf_mod->qaf_audio_stream_close(out->qaf_stream_handle);
613 out->qaf_stream_handle = NULL;
614 }
615 ALOGV( "%s %d", __func__, __LINE__);
616 return ret;
617}
618
619static int qaf_stream_open(struct stream_out *out, struct audio_config *config, audio_output_flags_t flags, audio_devices_t devices)
620{
621 int status = 0;
622 ALOGV("%s %d", __func__, __LINE__);
623
624 if (!qaf_mod->qaf_audio_stream_open)
625 return -EINVAL;
626
627 audio_stream_config_t input_config;
628 input_config.sample_rate = config->sample_rate;
629 input_config.channel_mask = config->channel_mask;
630 input_config.format = config->format;
631
632 if ((config->format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC) {
633 input_config.format = AUDIO_FORMAT_AAC;
634 } else if((config->format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS) {
635 input_config.format = AUDIO_FORMAT_AAC_ADTS;
636 }
637
638 ALOGV("%s %d audio_stream_open sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x) format(%#x)\
639 ",__func__, __LINE__, input_config.sample_rate, input_config.channel_mask, devices, flags, input_config.format);
640
641 /* TODO to send appropriated flags when support for system tones is added */
642 if (input_config.format == AUDIO_FORMAT_PCM_16_BIT) {
643 status = qaf_mod->qaf_audio_stream_open(qaf_mod->session_handle, &out->qaf_stream_handle, input_config, devices, /*flags*/AUDIO_STREAM_SYSTEM_TONE);
644 } else if (input_config.format == AUDIO_FORMAT_AC3 ||
645 input_config.format == AUDIO_FORMAT_E_AC3 ||
646 input_config.format == AUDIO_FORMAT_AAC ||
647 input_config.format == AUDIO_FORMAT_AAC_ADTS) {
648 if (qaf_mod->main_output_active == false) {
649 if ((flags & AUDIO_OUTPUT_FLAG_MAIN) && (flags & AUDIO_OUTPUT_FLAG_ASSOCIATED)) {
650 status = qaf_mod->qaf_audio_stream_open(qaf_mod->session_handle, &out->qaf_stream_handle, input_config, devices, /*flags*/AUDIO_STREAM_MAIN);
651 if (status == 0) {
652 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);
653 qaf_mod->main_output_active = true;
654 qaf_mod->assoc_output_active = true;
655 }
656 } else if (flags & AUDIO_OUTPUT_FLAG_MAIN) {
657 status = qaf_mod->qaf_audio_stream_open(qaf_mod->session_handle, &out->qaf_stream_handle, input_config, devices, /*flags*/AUDIO_STREAM_MAIN);
658 if (status == 0) {
659 ALOGV("%s %d Open stream for Input with only Main flag [%x] stream handle [%p]", __func__, __LINE__, flags, out->qaf_stream_handle);
660 qaf_mod->main_output_active = true;
661 }
662 } else if (flags & AUDIO_OUTPUT_FLAG_ASSOCIATED) {
663 ALOGE("%s %d Error main input is not active", __func__, __LINE__);
664 return -EINVAL;
665 } else {
666 status = qaf_mod->qaf_audio_stream_open(qaf_mod->session_handle, &out->qaf_stream_handle, input_config, devices, /*flags*/AUDIO_STREAM_MAIN);
667 if (status == 0) {
668 ALOGV("%s %d Open stream for Local playback with flag [%x] stream handle [%p] ", __func__, __LINE__, flags, out->qaf_stream_handle);
669 qaf_mod->main_output_active = true;
670 }
671 }
672 } else {
673 if (flags & AUDIO_OUTPUT_FLAG_MAIN) {
674 ALOGE("%s %d Error main input is already active", __func__, __LINE__);
675 return -EINVAL;
676 } else if (flags & AUDIO_OUTPUT_FLAG_ASSOCIATED) {
677 if (qaf_mod->assoc_output_active) {
678 ALOGE("%s %d Error assoc input is already active", __func__, __LINE__);
679 return -EINVAL;
680 } else {
681 status = qaf_mod->qaf_audio_stream_open(qaf_mod->session_handle, &out->qaf_stream_handle, input_config, devices, /*flags*/AUDIO_STREAM_ASSOCIATED);
682 if (status == 0) {
683 ALOGV("%s %d Open stream for Input with only Associated flag [%x] stream handle [%p]", __func__, __LINE__, flags, out->qaf_stream_handle);
684 qaf_mod->assoc_output_active = true;
685 }
686 }
687 } else {
688 ALOGE("%s %d Error main input is already active", __func__, __LINE__);
689 return -EINVAL;
690 }
691 }
692 }
693
694 return status;
695}
696
697static int qaf_deinit()
698{
699 ALOGV("%s %d", __func__, __LINE__);
700 if (qaf_mod != NULL) {
701 if (qaf_mod->qaf_compr_offload_out != NULL)
702 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev, (struct audio_stream_out *) (qaf_mod->qaf_compr_offload_out));
703 if (qaf_mod->qaf_compr_passthrough_out != NULL)
704 adev_close_output_stream((struct audio_hw_device *) qaf_mod->adev, (struct audio_stream_out *) (qaf_mod->qaf_compr_passthrough_out));
705
706 if (qaf_mod->qaf_lib != NULL) {
707 dlclose(qaf_mod->qaf_lib);
708 qaf_mod->qaf_lib = NULL;
709 }
710 free(qaf_mod);
711 qaf_mod = NULL;
712 }
713 return 0;
714}
715
716static void *qaf_offload_thread_loop(void *context)
717{
718 struct stream_out *out = (struct stream_out *) context;
719 struct listnode *item;
720 int ret = 0;
721 struct str_parms *parms = NULL;
722 int value = 0;
723 char* kvpairs = NULL;
724
725 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
726 set_sched_policy(0, SP_FOREGROUND);
727 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
728
729 ALOGE("%s", __func__);
730 lock_output_stream(out);
731 for (;;) {
732 struct offload_cmd *cmd = NULL;
733 stream_callback_event_t event;
734 bool send_callback = false;
735
736 ALOGV("%s qaf_offload_cmd_list %d",
737 __func__, list_empty(&out->qaf_offload_cmd_list));
738 if (list_empty(&out->qaf_offload_cmd_list)) {
739 ALOGV("%s SLEEPING", __func__);
740 pthread_cond_wait(&out->qaf_offload_cond, &out->lock);
741 ALOGV("%s RUNNING", __func__);
742 continue;
743 }
744
745 item = list_head(&out->qaf_offload_cmd_list);
746 cmd = node_to_item(item, struct offload_cmd, node);
747 list_remove(item);
748
749 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
750 free(cmd);
751 break;
752 }
753
754 pthread_mutex_unlock(&out->lock);
755 send_callback = false;
756 switch(cmd->cmd) {
757 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
758 ALOGV("wait for ms12 buffer availability");
759 while (1) {
760 kvpairs = qaf_mod->qaf_audio_stream_get_param(out->qaf_stream_handle, "buf_available");
761 if (kvpairs) {
762 parms = str_parms_create_str(kvpairs);
763 ret = str_parms_get_int(parms, "buf_available", &value);
764 if (ret >= 0) {
765 if (value >= (int)out->compr_config.fragment_size) {
766 ALOGV("%s buffer available", __func__);
767 str_parms_destroy(parms);
768 parms = NULL;
769 break;
770 } else {
771 ALOGV("%s sleep", __func__);
772 str_parms_destroy(parms);
773 parms = NULL;
774 usleep(10000);
775 }
776 }
777 free(kvpairs);
778 kvpairs = NULL;
779 }
780 }
781 send_callback = true;
782 event = STREAM_CBK_EVENT_WRITE_READY;
783 break;
784 default:
785 ALOGV("%s unknown command received: %d", __func__, cmd->cmd);
786 break;
787 }
788 lock_output_stream(out);
789 if (send_callback && out->offload_callback) {
790 out->offload_callback(event, NULL, out->offload_cookie);
791 }
792 free(cmd);
793 }
794
795 while (!list_empty(&out->qaf_offload_cmd_list)) {
796 item = list_head(&out->qaf_offload_cmd_list);
797 list_remove(item);
798 free(node_to_item(item, struct offload_cmd, node));
799 }
800 pthread_mutex_unlock(&out->lock);
801
802 return NULL;
803}
804
805static int qaf_create_offload_callback_thread(struct stream_out *out)
806{
807 ALOGV("%s", __func__);
808 pthread_cond_init(&out->qaf_offload_cond, (const pthread_condattr_t *) NULL);
809 list_init(&out->qaf_offload_cmd_list);
810 pthread_create(&out->qaf_offload_thread, (const pthread_attr_t *) NULL,
811 qaf_offload_thread_loop, out);
812 return 0;
813}
814
815static int qaf_destroy_offload_callback_thread(struct stream_out *out)
816{
817 ALOGV("%s", __func__);
818 lock_output_stream(out);
819 qaf_send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
820 pthread_mutex_unlock(&out->lock);
821
822 pthread_join(out->qaf_offload_thread, (void **) NULL);
823 pthread_cond_destroy(&out->qaf_offload_cond);
824
825 return 0;
826}
827
828int audio_extn_qaf_open_output_stream(struct audio_hw_device *dev,
829 audio_io_handle_t handle,
830 audio_devices_t devices,
831 audio_output_flags_t flags,
832 struct audio_config *config,
833 struct audio_stream_out **stream_out,
834 const char *address __unused)
835{
836 int ret = 0;
837 struct stream_out *out;
838
839 ret = adev_open_output_stream(dev, handle, devices, flags, config, stream_out, address);
840 if (*stream_out == NULL) {
841 goto error_open;
842 }
843
844 out = (struct stream_out *) *stream_out;
845
846 /* Override function pointers based on qaf definitions */
847 out->stream.set_volume = qaf_out_set_volume;
848 out->stream.pause = qaf_out_pause;
849 out->stream.resume = qaf_out_resume;
850 out->stream.drain = qaf_out_drain;
851 out->stream.flush = qaf_out_flush;
852
853 out->stream.common.standby = qaf_out_standby;
854 out->stream.common.set_parameters = qaf_out_set_parameters;
855 out->stream.get_latency = qaf_out_get_latency;
856 out->stream.write = qaf_out_write;
857 out->stream.get_presentation_position = qaf_out_get_presentation_position;
858
859 ret = qaf_stream_open(out, config, flags, devices);
860 if (ret < 0) {
861 ALOGE("%s, Error opening QAF stream err[%d]!", __func__, ret);
862 adev_close_output_stream(dev, *stream_out);
863 goto error_open;
864 }
865
866 if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY) {
867 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
868 out->config.period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE;
869 out->config.period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT;
870 out->config.start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4;
871 out->config.avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4;
872 }
873
874 *stream_out = &out->stream;
875 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
876 qaf_create_offload_callback_thread(out);
877 }
878 ALOGV("%s: exit", __func__);
879 return 0;
880error_open:
881 *stream_out = NULL;
882 ALOGD("%s: exit: ret %d", __func__, ret);
883 return ret;
884}
885
886void audio_extn_qaf_close_output_stream(struct audio_hw_device *dev,
887 struct audio_stream_out *stream)
888{
889 struct stream_out *out = (struct stream_out *)stream;
890
891 ALOGV("%s: enter:stream_handle(%p) format = %x", __func__, out, out->format);
892 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
893 qaf_destroy_offload_callback_thread(out);
894 }
895 qaf_mod->stream_drain_main = NULL;
896 lock_output_stream(out);
897 qaf_stream_close(out);
898 pthread_mutex_unlock(&out->lock);
899
900 adev_close_output_stream(dev, stream);
901 ALOGV("%s: exit", __func__);
902}
903
904bool audio_extn_qaf_is_enabled()
905{
906 bool prop_enabled = false;
907 char value[PROPERTY_VALUE_MAX] = {0};
908 property_get("audio.qaf.enabled", value, NULL);
909 prop_enabled = atoi(value) || !strncmp("true", value, 4);
910 return (prop_enabled);
911}
912
913int audio_extn_qaf_session_open(struct qaf *qaf_mod,
914 device_license_config_t* lic_config)
915{
916 ALOGV("%s %d", __func__, __LINE__);
917 int status = -ENOSYS;
918
919 pthread_mutex_init(&qaf_mod->lock, (const pthread_mutexattr_t *) NULL);
920
921 if (!qaf_mod->qaf_audio_session_open)
922 return -EINVAL;
923
924 status = qaf_mod->qaf_audio_session_open(&qaf_mod->session_handle,
925 (void *)(qaf_mod), (void *)lic_config);
926 if(status < 0)
927 return status;
928
929 if (qaf_mod->session_handle == NULL) {
930 ALOGE("%s %d QAF wrapper session handle is NULL", __func__, __LINE__);
931 return -ENOMEM;
932 }
933 if (qaf_mod->qaf_register_event_callback)
934 qaf_mod->qaf_register_event_callback(qaf_mod->session_handle,
935 qaf_mod, &notify_event_callback,
936 AUDIO_DATA_EVENT);
937 return status;
938}
939
940char* audio_extn_qaf_stream_get_param(struct stream_out *out __unused, const char *kv_pair __unused)
941{
942 return NULL;
943}
944
945int audio_extn_qaf_set_parameters(struct audio_device *adev, struct str_parms *parms)
946{
947 int status = 0, val = 0, channels = 0;
948 char *format_params, *kv_parirs;
949 struct str_parms *qaf_params;
950 char value[32];
951 bool passth_support = false;
952
953 ALOGV("%s %d ", __func__, __LINE__);
954 if (!qaf_mod || !qaf_mod->qaf_audio_session_set_param) {
955 return -EINVAL;
956 }
957
958 status = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
959 if (status >= 0) {
960 val = atoi(value);
961 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
962 if (property_get_bool("audio.offload.passthrough", false) &&
963 property_get_bool("audio.qaf.reencode", false)) {
964
965 qaf_params = str_parms_create();
966 if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_E_AC3)) {
967 passth_support = true;
968 if (qaf_params) {
969 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_RENDER_FORMAT,
970 AUDIO_QAF_PARAMETER_VALUE_REENCODE_EAC3);
971 }
972 } else if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_AC3)) {
973 passth_support = true;
974 if (qaf_params) {
975 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_RENDER_FORMAT,
976 AUDIO_QAF_PARAMETER_VALUE_REENCODE_AC3);
977 }
978 }
979
980 if (passth_support) {
981 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
982 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI);
983 format_params = str_parms_to_str(qaf_params);
984
985 qaf_mod->qaf_audio_session_set_param(qaf_mod->session_handle, format_params);
986 }
987 str_parms_destroy(qaf_params);
988 }
989
990 if (!passth_support) {
991 channels = platform_edid_get_max_channels(adev->platform);
992
993 qaf_params = str_parms_create();
994 switch (channels) {
995 case 8:
996 ALOGV("%s: Switching Qaf output to 7.1 channels", __func__);
997 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_CHANNELS,
998 AUDIO_QAF_PARAMETER_VALUE_8_CHANNELS);
999 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1000 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI);
1001 qaf_mod->hdmi_sink_channels = channels;
1002 break;
1003 case 6:
1004 ALOGV("%s: Switching Qaf output to 5.1 channels", __func__);
1005 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_CHANNELS,
1006 AUDIO_QAF_PARAMETER_VALUE_6_CHANNELS);
1007 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1008 AUDIO_QAF_PARAMETER_VALUE_DEVICE_HDMI);
1009 qaf_mod->hdmi_sink_channels = channels;
1010 break;
1011 default:
1012 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1013 AUDIO_QAF_PARAMETER_VALUE_DEVICE_SPEAKER);
1014 qaf_mod->hdmi_sink_channels = 2;
1015 break;
1016 }
1017
1018 format_params = str_parms_to_str(qaf_params);
1019 qaf_mod->qaf_audio_session_set_param(qaf_mod->session_handle, format_params);
1020 str_parms_destroy(qaf_params);
1021 }
1022 }
1023 }
1024
1025 status = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
1026 if (status >= 0) {
1027 val = atoi(value);
1028 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1029 qaf_params = str_parms_create();
1030 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_DEVICE,
1031 AUDIO_QAF_PARAMETER_VALUE_DEVICE_SPEAKER);
1032 str_parms_add_str(qaf_params, AUDIO_QAF_PARAMETER_KEY_RENDER_FORMAT,
1033 AUDIO_QAF_PARAMETER_VALUE_PCM);
1034 qaf_mod->hdmi_sink_channels = 0;
1035
1036 format_params = str_parms_to_str(qaf_params);
1037 qaf_mod->qaf_audio_session_set_param(qaf_mod->session_handle, format_params);
1038 str_parms_destroy(qaf_params);
1039 }
1040 }
1041
1042 kv_parirs = str_parms_to_str(parms);
1043 qaf_mod->qaf_audio_session_set_param(qaf_mod->session_handle, kv_parirs);
1044
1045 return status;
1046}
1047
1048char* audio_extn_qaf_get_param(struct audio_device *adev __unused, const char *kv_pair __unused)
1049{
1050 return 0;
1051}
1052
1053int audio_extn_qaf_init(struct audio_device *adev)
1054{
1055 char value[PROPERTY_VALUE_MAX] = {0};
1056 char lib_name[PROPERTY_VALUE_MAX] = {0};
1057 unsigned char* license_data = NULL;
1058 device_license_config_t* lic_config = NULL;
1059 ALOGV("%s %d", __func__, __LINE__);
1060 int ret = 0, size = 0;
1061
1062 qaf_mod = malloc(sizeof(struct qaf));
1063 if(qaf_mod == NULL) {
1064 ALOGE("%s, out of memory", __func__);
1065 ret = -ENOMEM;
1066 goto done;
1067 }
1068 memset(qaf_mod, 0, sizeof(struct qaf));
1069 lic_config = (device_license_config_t*) calloc(1, sizeof(device_license_config_t));
1070 if(lic_config == NULL) {
1071 ALOGE("%s, out of memory", __func__);
1072 ret = -ENOMEM;
1073 goto done;
1074 }
1075 qaf_mod->adev = adev;
1076 property_get("audio.qaf.library", value, NULL);
1077 snprintf(lib_name, PROPERTY_VALUE_MAX, "%s", value);
1078
1079 license_data = platform_get_license((struct audio_hw_device *)(qaf_mod->adev->platform), &size);
1080 if (!license_data) {
1081 ALOGE("License is not present");
1082 ret = -EINVAL;
1083 goto done;
1084 }
1085 lic_config->p_license = (unsigned char* ) calloc(1, size);
1086 if(lic_config->p_license == NULL) {
1087 ALOGE("%s, out of memory", __func__);
1088 ret = -ENOMEM;
1089 goto done;
1090 }
1091 lic_config->l_size = size;
1092 memcpy(lic_config->p_license, license_data, size);
1093
1094 if (property_get("audio.qaf.manufacturer", value, "") && atoi(value)) {
1095 lic_config->manufacturer_id = (unsigned long) atoi (value);
1096 } else {
1097 ALOGE("audio.qaf.manufacturer id is not set");
1098 ret = -EINVAL;
1099 goto done;
1100 }
1101
1102 ret = audio_extn_qaf_session_open(qaf_mod, lic_config);
1103done:
1104 if (license_data != NULL) {
1105 free(license_data);
1106 license_data = NULL;
1107 }
1108 if (lic_config->p_license != NULL) {
1109 free(lic_config->p_license);
1110 lic_config->p_license = NULL;
1111 }
1112 if (lic_config != NULL) {
1113 free(lic_config);
1114 lic_config = NULL;
1115 }
1116 if (ret != 0) {
1117 if (qaf_mod != NULL) {
1118 free(qaf_mod);
1119 qaf_mod = NULL;
1120 }
1121 }
1122 return ret;
1123}
1124
1125void audio_extn_qaf_deinit()
1126{
1127 qaf_session_close();
1128 qaf_deinit();
1129}