blob: ea1092a716907d07bd70fc4e271b010fe0fde108 [file] [log] [blame]
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301/*
2* Copyright (c) 2015-16, 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#define LOG_TAG "split_a2dp"
30/*#define LOG_NDEBUG 0*/
31#define LOG_NDDEBUG 0
32#include <errno.h>
33#include <cutils/log.h>
34#include <dlfcn.h>
35#include "audio_hw.h"
36#include "platform.h"
37#include "platform_api.h"
38#include <stdlib.h>
39#include <cutils/str_parms.h>
40#include <hardware/audio.h>
41#include <hardware/hardware.h>
42#include <cutils/properties.h>
43
44#ifdef SPLIT_A2DP_ENABLED
45#define AUDIO_PARAMETER_A2DP_STARTED "A2dpStarted"
46#define BT_IPC_LIB_NAME "libbthost_if.so"
47#define ENC_MEDIA_FMT_NONE 0
48#define ENC_MEDIA_FMT_AAC 0x00010DA6
49#define ENC_MEDIA_FMT_APTX 0x000131ff
50#define ENC_MEDIA_FMT_APTX_HD 0x00013200
51#define ENC_MEDIA_FMT_SBC 0x00010BF2
52#define MEDIA_FMT_AAC_AOT_LC 2
53#define MEDIA_FMT_AAC_AOT_SBR 5
54#define MEDIA_FMT_AAC_AOT_PS 29
Naresh Tanniru9d027a62015-03-13 01:32:10 +053055#define PCM_CHANNEL_L 1
56#define PCM_CHANNEL_R 2
57#define PCM_CHANNEL_C 3
58#define MEDIA_FMT_SBC_CHANNEL_MODE_MONO 1
59#define MEDIA_FMT_SBC_CHANNEL_MODE_STEREO 2
60#define MEDIA_FMT_SBC_CHANNEL_MODE_DUAL_MONO 8
61#define MEDIA_FMT_SBC_CHANNEL_MODE_JOINT_STEREO 9
62#define MEDIA_FMT_SBC_ALLOCATION_METHOD_LOUDNESS 0
63#define MEDIA_FMT_SBC_ALLOCATION_METHOD_SNR 1
64#define MIXER_ENC_CONFIG_BLOCK "SLIM_7_RX Encoder Config"
65#define MIXER_ENC_FMT_SBC "SBC"
66#define MIXER_ENC_FMT_AAC "AAC"
67#define MIXER_ENC_FMT_APTX "APTX"
68#define MIXER_ENC_FMT_APTXHD "APTXHD"
69#define MIXER_ENC_FMT_NONE "NONE"
70
71
72typedef int (*audio_stream_open_t)(void);
73typedef int (*audio_stream_close_t)(void);
74typedef int (*audio_start_stream_t)(void);
75typedef int (*audio_stop_stream_t)(void);
76typedef int (*audio_suspend_stream_t)(void);
77typedef void (*audio_handoff_triggered_t)(void);
78typedef void (*clear_a2dpsuspend_flag_t)(void);
79typedef void * (*audio_get_codec_config_t)(uint8_t *multicast_status,uint8_t *num_dev,
80 audio_format_t *codec_type);
81
82enum A2DP_STATE {
83 A2DP_STATE_CONNECTED,
84 A2DP_STATE_STARTED,
85 A2DP_STATE_STOPPED,
86 A2DP_STATE_DISCONNECTED,
87};
88
89/* structure used to update a2dp state machine
90 * to communicate IPC library
91 * to store DSP encoder configuration information
92 */
93struct a2dp_data {
94 struct audio_device *adev;
95 void *bt_lib_handle;
96 audio_stream_open_t audio_stream_open;
97 audio_stream_close_t audio_stream_close;
98 audio_start_stream_t audio_start_stream;
99 audio_stop_stream_t audio_stop_stream;
100 audio_suspend_stream_t audio_suspend_stream;
101 audio_handoff_triggered_t audio_handoff_triggered;
102 clear_a2dpsuspend_flag_t clear_a2dpsuspend_flag;
103 audio_get_codec_config_t audio_get_codec_config;
104 enum A2DP_STATE bt_state;
105 audio_format_t bt_encoder_format;
106 void *enc_config_data;
107 bool a2dp_started;
108 bool a2dp_suspended;
109 int a2dp_total_active_session_request;
110 bool is_a2dp_offload_supported;
111 bool is_handoff_in_progress;
112};
113
114struct a2dp_data a2dp;
115
116/* START of DSP configurable structures
117 * These values should match with DSP interface defintion
118 */
119
120/* AAC encoder configuration structure. */
121typedef struct aac_enc_cfg_t aac_enc_cfg_t;
122
123/* supported enc_mode are AAC_LC, AAC_SBR, AAC_PS
124 * supported aac_fmt_flag are ADTS/RAW
125 * supported channel_cfg are Native mode, Mono , Stereo
126 */
127struct aac_enc_cfg_t {
128 uint32_t enc_format;
129 uint32_t bit_rate;
130 uint32_t enc_mode;
131 uint16_t aac_fmt_flag;
Naresh Tannirua42d0bd2016-09-21 15:30:46 +0530132 uint16_t channel_cfg;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530133 uint32_t sample_rate;
134} ;
135
136/* SBC encoder configuration structure. */
137typedef struct sbc_enc_cfg_t sbc_enc_cfg_t;
138
139/* supported num_subbands are 4/8
140 * supported blk_len are 4, 8, 12, 16
141 * supported channel_mode are MONO, STEREO, DUAL_MONO, JOINT_STEREO
142 * supported alloc_method are LOUNDNESS/SNR
143 * supported bit_rate for mono channel is max 320kbps
144 * supported bit rate for stereo channel is max 512 kbps
145 */
146struct sbc_enc_cfg_t{
147 uint32_t enc_format;
148 uint32_t num_subbands;
149 uint32_t blk_len;
150 uint32_t channel_mode;
151 uint32_t alloc_method;
152 uint32_t bit_rate;
153 uint32_t sample_rate;
154};
155
156
157/* supported num_channels are Mono/Stereo
158 * supported channel_mapping for mono is CHANNEL_C
159 * supported channel mapping for stereo is CHANNEL_L and CHANNEL_R
160 * custom size and reserved are not used(for future enhancement)
161 */
162struct custom_enc_cfg_aptx_t
163{
164 uint32_t enc_format;
165 uint32_t sample_rate;
166 uint16_t num_channels;
167 uint16_t reserved;
168 uint8_t channel_mapping[8];
169 uint32_t custom_size;
170};
171
172/*********** END of DSP configurable structures ********************/
173
174/* API to identify DSP encoder captabilities */
175static void a2dp_offload_codec_cap_parser(char *value)
176{
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530177 char *tok = NULL,*saveptr;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530178
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530179 tok = strtok_r(value, "-", &saveptr);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530180 while (tok != NULL) {
181 if (strcmp(tok, "sbc") == 0) {
182 ALOGD("%s: SBC offload supported\n",__func__);
183 a2dp.is_a2dp_offload_supported = true;
184 break;
185 } else if (strcmp(tok, "aptx") == 0) {
186 ALOGD("%s: aptx offload supported\n",__func__);
187 a2dp.is_a2dp_offload_supported = true;
188 break;
189 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530190 tok = strtok_r(NULL, "-", &saveptr);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530191 };
192}
193
194static void update_offload_codec_capabilities()
195{
196 char value[PROPERTY_VALUE_MAX] = {'\0'};
197
198 property_get("persist.bt.a2dp_offload_cap", value, "false");
199 ALOGD("get_offload_codec_capabilities = %s",value);
200 a2dp.is_a2dp_offload_supported =
201 property_get_bool("persist.bt.a2dp_offload_cap", false);
202 if (strcmp(value, "false") != 0)
203 a2dp_offload_codec_cap_parser(value);
204 ALOGD("%s: codec cap = %s",__func__,value);
205}
206
207/* API to open BT IPC library to start IPC communication */
208static void open_a2dp_output()
209{
210 int ret = 0;
211
212 ALOGD(" Open A2DP output start ");
213 if (a2dp.bt_lib_handle == NULL){
214 ALOGD(" Requesting for BT lib handle");
215 a2dp.bt_lib_handle = dlopen(BT_IPC_LIB_NAME, RTLD_NOW);
216
217 if (a2dp.bt_lib_handle == NULL) {
218 ALOGE("%s: DLOPEN failed for %s", __func__, BT_IPC_LIB_NAME);
219 ret = -ENOSYS;
220 goto init_fail;
221 } else {
222 a2dp.audio_stream_open = (audio_stream_open_t)
223 dlsym(a2dp.bt_lib_handle, "audio_stream_open");
224 a2dp.audio_start_stream = (audio_start_stream_t)
225 dlsym(a2dp.bt_lib_handle, "audio_start_stream");
226 a2dp.audio_get_codec_config = (audio_get_codec_config_t)
227 dlsym(a2dp.bt_lib_handle, "audio_get_codec_config");
228 a2dp.audio_suspend_stream = (audio_suspend_stream_t)
229 dlsym(a2dp.bt_lib_handle, "audio_suspend_stream");
230 a2dp.audio_handoff_triggered = (audio_handoff_triggered_t)
231 dlsym(a2dp.bt_lib_handle, "audio_handoff_triggered");
232 a2dp.clear_a2dpsuspend_flag = (clear_a2dpsuspend_flag_t)
233 dlsym(a2dp.bt_lib_handle, "clear_a2dpsuspend_flag");
234 a2dp.audio_stop_stream = (audio_stop_stream_t)
235 dlsym(a2dp.bt_lib_handle, "audio_stop_stream");
236 a2dp.audio_stream_close = (audio_stream_close_t)
237 dlsym(a2dp.bt_lib_handle, "audio_stream_close");
238 }
239 }
240
241 if (a2dp.bt_lib_handle && a2dp.audio_stream_open) {
242 if (a2dp.bt_state == A2DP_STATE_DISCONNECTED) {
243 ALOGD("calling BT stream open");
244 ret = a2dp.audio_stream_open();
245 if(ret != 0) {
246 ALOGE("Failed to open output stream for a2dp: status %d", ret);
247 goto init_fail;
248 }
249 a2dp.bt_state = A2DP_STATE_CONNECTED;
250 } else {
251 ALOGD("Called a2dp open with improper state, Ignoring request state %d", a2dp.bt_state);
252 }
253 } else {
254 ALOGE("a2dp handle is not identified, Ignoring open request");
255 a2dp.bt_state = A2DP_STATE_DISCONNECTED;
256 goto init_fail;
257 }
258
259init_fail:
260 if(ret != 0 && (a2dp.bt_lib_handle != NULL)) {
261 dlclose(a2dp.bt_lib_handle);
262 a2dp.bt_lib_handle = NULL;
263 }
264}
265
266static int close_a2dp_output()
267{
268 ALOGV("%s\n",__func__);
269 if (!(a2dp.bt_lib_handle && a2dp.audio_stream_close)) {
270 ALOGE("a2dp handle is not identified, Ignoring close request");
271 return -ENOSYS;
272 }
273 if ((a2dp.bt_state == A2DP_STATE_CONNECTED) &&
274 (a2dp.bt_state == A2DP_STATE_STARTED) &&
275 (a2dp.bt_state == A2DP_STATE_STOPPED)) {
276 ALOGD("calling BT stream close");
277 if(a2dp.audio_stream_close() == false)
278 ALOGE("failed close a2dp control path from BT library");
279 a2dp.a2dp_started = false;
280 a2dp.a2dp_total_active_session_request = 0;
281 a2dp.a2dp_suspended = false;
282 a2dp.bt_encoder_format = AUDIO_FORMAT_INVALID;
283 a2dp.enc_config_data = NULL;
284 a2dp.bt_state = A2DP_STATE_DISCONNECTED;
285 } else {
286 ALOGD("close a2dp called in improper state");
287 a2dp.a2dp_started = false;
288 a2dp.a2dp_total_active_session_request = 0;
289 a2dp.a2dp_suspended = false;
290 a2dp.bt_encoder_format = AUDIO_FORMAT_INVALID;
291 a2dp.enc_config_data = NULL;
292 a2dp.bt_state = A2DP_STATE_DISCONNECTED;
293 }
294
295 return 0;
296}
297
298/* API to configure SBC DSP encoder */
299bool configure_sbc_enc_format(audio_sbc_encoder_config *sbc_bt_cfg)
300{
301 struct mixer_ctl *ctl_enc_data;
302 struct sbc_enc_cfg_t sbc_dsp_cfg;
303 bool is_configured = false;
304 int ret = 0;
305
306 if(sbc_bt_cfg == NULL)
307 return false;
308
309 ctl_enc_data = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_ENC_CONFIG_BLOCK);
310 if (!ctl_enc_data) {
311 ALOGE(" ERROR a2dp encoder CONFIG data mixer control not identifed");
312 is_configured = false;
313 goto fail;
314 }
315 a2dp.bt_encoder_format = AUDIO_FORMAT_SBC;
316 memset(&sbc_dsp_cfg, 0x0, sizeof(struct sbc_enc_cfg_t));
317 sbc_dsp_cfg.enc_format = ENC_MEDIA_FMT_SBC;
318 sbc_dsp_cfg.num_subbands = sbc_bt_cfg->subband;
319 sbc_dsp_cfg.blk_len = sbc_bt_cfg->blk_len;
320 switch(sbc_bt_cfg->channels) {
321 case 0:
322 sbc_dsp_cfg.channel_mode = MEDIA_FMT_SBC_CHANNEL_MODE_MONO;
323 break;
324 case 1:
325 sbc_dsp_cfg.channel_mode = MEDIA_FMT_SBC_CHANNEL_MODE_DUAL_MONO;
326 break;
327 case 3:
328 sbc_dsp_cfg.channel_mode = MEDIA_FMT_SBC_CHANNEL_MODE_JOINT_STEREO;
329 break;
330 case 2:
331 default:
332 sbc_dsp_cfg.channel_mode = MEDIA_FMT_SBC_CHANNEL_MODE_STEREO;
333 break;
334 }
335 if (sbc_bt_cfg->alloc)
336 sbc_dsp_cfg.alloc_method = MEDIA_FMT_SBC_ALLOCATION_METHOD_LOUDNESS;
337 else
338 sbc_dsp_cfg.alloc_method = MEDIA_FMT_SBC_ALLOCATION_METHOD_SNR;
339 sbc_dsp_cfg.bit_rate = sbc_bt_cfg->bitrate;
340 sbc_dsp_cfg.sample_rate = sbc_bt_cfg->sampling_rate;
341 ret = mixer_ctl_set_array(ctl_enc_data, (void *)&sbc_dsp_cfg,
342 sizeof(struct sbc_enc_cfg_t));
343 if (ret != 0) {
344 ALOGE("%s: failed to set SBC encoder config", __func__);
345 is_configured = false;
346 } else
347 is_configured = true;
348fail:
349 return is_configured;
350}
351
352/* API to configure APTX DSP encoder */
353bool configure_aptx_enc_format(audio_aptx_encoder_config *aptx_bt_cfg)
354{
355 struct mixer_ctl *ctl_enc_data;
356 struct custom_enc_cfg_aptx_t aptx_dsp_cfg;
357 bool is_configured = false;
358 int ret = 0;
359
360 if(aptx_bt_cfg == NULL)
361 return false;
362
363 ctl_enc_data = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_ENC_CONFIG_BLOCK);
364 if (!ctl_enc_data) {
365 ALOGE(" ERROR a2dp encoder CONFIG data mixer control not identifed");
366 is_configured = false;
367 goto fail;
368 }
369 a2dp.bt_encoder_format = AUDIO_FORMAT_APTX;
370 memset(&aptx_dsp_cfg, 0x0, sizeof(struct custom_enc_cfg_aptx_t));
371 aptx_dsp_cfg.enc_format = ENC_MEDIA_FMT_APTX;
372 aptx_dsp_cfg.sample_rate = aptx_bt_cfg->sampling_rate;
373 aptx_dsp_cfg.num_channels = aptx_bt_cfg->channels;
374 switch(aptx_dsp_cfg.num_channels) {
375 case 1:
376 aptx_dsp_cfg.channel_mapping[0] = PCM_CHANNEL_C;
377 break;
378 case 2:
379 default:
380 aptx_dsp_cfg.channel_mapping[0] = PCM_CHANNEL_L;
381 aptx_dsp_cfg.channel_mapping[1] = PCM_CHANNEL_R;
382 break;
383 }
384 ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_dsp_cfg,
385 sizeof(struct custom_enc_cfg_aptx_t));
386 if (ret != 0) {
387 ALOGE("%s: Failed to set APTX encoder config", __func__);
388 is_configured = false;
389 goto fail;
390 }
391 is_configured = true;
392fail:
393 return is_configured;
394}
395
396/* API to configure APTX HD DSP encoder
397 * TODO: ADD 24 bit configuration support
398 */
399bool configure_aptx_hd_enc_format(audio_aptx_encoder_config *aptx_bt_cfg)
400{
401 struct mixer_ctl *ctl_enc_data;
402 struct custom_enc_cfg_aptx_t aptx_dsp_cfg;
403 bool is_configured = false;
404 int ret = 0;
405
406 if(aptx_bt_cfg == NULL)
407 return false;
408
409 ctl_enc_data = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_ENC_CONFIG_BLOCK);
410 if (!ctl_enc_data) {
411 ALOGE(" ERROR a2dp encoder CONFIG data mixer control not identifed");
412 is_configured = false;
413 goto fail;
414 }
415 a2dp.bt_encoder_format = AUDIO_FORMAT_APTX_HD;
416 memset(&aptx_dsp_cfg, 0x0, sizeof(struct custom_enc_cfg_aptx_t));
417 aptx_dsp_cfg.enc_format = ENC_MEDIA_FMT_APTX_HD;
418 aptx_dsp_cfg.sample_rate = aptx_bt_cfg->sampling_rate;
419 aptx_dsp_cfg.num_channels = aptx_bt_cfg->channels;
420 switch(aptx_dsp_cfg.num_channels) {
421 case 1:
422 aptx_dsp_cfg.channel_mapping[0] = PCM_CHANNEL_C;
423 break;
424 case 2:
425 default:
426 aptx_dsp_cfg.channel_mapping[0] = PCM_CHANNEL_L;
427 aptx_dsp_cfg.channel_mapping[1] = PCM_CHANNEL_R;
428 break;
429 }
430 ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_dsp_cfg,
431 sizeof(struct custom_enc_cfg_aptx_t));
432 if (ret != 0) {
433 ALOGE("%s: Failed to set APTX HD encoder config", __func__);
434 is_configured = false;
435 goto fail;
436 }
437 is_configured = true;
438fail:
439 return is_configured;
440}
441
442/* API to configure AAC DSP encoder */
443bool configure_aac_enc_format(audio_aac_encoder_config *aac_bt_cfg)
444{
445 struct mixer_ctl *ctl_enc_data;
446 struct aac_enc_cfg_t aac_dsp_cfg;
447 bool is_configured = false;
448 int ret = 0;
449
450 if(aac_bt_cfg == NULL)
451 return false;
452
453 ctl_enc_data = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_ENC_CONFIG_BLOCK);
454 if (!ctl_enc_data) {
455 ALOGE(" ERROR a2dp encoder CONFIG data mixer control not identifed");
456 is_configured = false;
457 goto fail;
458 }
459 a2dp.bt_encoder_format = AUDIO_FORMAT_AAC;
460 memset(&aac_dsp_cfg, 0x0, sizeof(struct aac_enc_cfg_t));
461 aac_dsp_cfg.enc_format = ENC_MEDIA_FMT_AAC;
462 aac_dsp_cfg.bit_rate = aac_bt_cfg->bitrate;
Naresh Tannirua42d0bd2016-09-21 15:30:46 +0530463 aac_dsp_cfg.sample_rate = aac_bt_cfg->sampling_rate;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530464 switch(aac_bt_cfg->enc_mode) {
465 case 0:
466 aac_dsp_cfg.enc_mode = MEDIA_FMT_AAC_AOT_LC;
467 break;
468 case 2:
469 aac_dsp_cfg.enc_mode = MEDIA_FMT_AAC_AOT_PS;
470 break;
471 case 1:
472 default:
473 aac_dsp_cfg.enc_mode = MEDIA_FMT_AAC_AOT_SBR;
474 break;
475 }
Naresh Tannirua42d0bd2016-09-21 15:30:46 +0530476 aac_dsp_cfg.aac_fmt_flag = aac_bt_cfg->format_flag;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530477 aac_dsp_cfg.channel_cfg = aac_bt_cfg->channels;
478 ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aac_dsp_cfg,
479 sizeof(struct aac_enc_cfg_t));
480 if (ret != 0) {
481 ALOGE("%s: failed to set SBC encoder config", __func__);
482 is_configured = false;
483 } else
484 is_configured = true;
485fail:
486 return is_configured;
487}
488
489bool configure_a2dp_encoder_format()
490{
491 void *codec_info = NULL;
492 uint8_t multi_cast = 0, num_dev = 1;
493 audio_format_t codec_type = AUDIO_FORMAT_INVALID;
494 bool is_configured = false;
495
496 if (!a2dp.audio_get_codec_config) {
497 ALOGE(" a2dp handle is not identified, ignoring a2dp encoder config");
498 return false;
499 }
500 ALOGD("configure_a2dp_encoder_format start");
501 codec_info = a2dp.audio_get_codec_config(&multi_cast, &num_dev,
502 &codec_type);
503
504 switch(codec_type) {
505 case AUDIO_FORMAT_SBC:
506 ALOGD(" Received SBC encoder supported BT device");
507 is_configured =
508 configure_sbc_enc_format((audio_sbc_encoder_config *)codec_info);
509 break;
510 case AUDIO_FORMAT_APTX:
511 ALOGD(" Received APTX encoder supported BT device");
512 is_configured =
513 configure_aptx_enc_format((audio_aptx_encoder_config *)codec_info);
514 break;
515 case AUDIO_FORMAT_APTX_HD:
516 ALOGD(" Received APTX HD encoder supported BT device");
517 is_configured =
518 configure_aptx_hd_enc_format((audio_aptx_encoder_config *)codec_info);
519 break;
520 case AUDIO_FORMAT_AAC:
521 ALOGD(" Received AAC encoder supported BT device");
522 is_configured =
523 configure_aac_enc_format((audio_aac_encoder_config *)codec_info);
524 break;
525 default:
526 ALOGD(" Received Unsupported encoder formar");
527 is_configured = false;
528 break;
529 }
530 return is_configured;
531}
532
533int audio_extn_a2dp_start_playback()
534{
535 int ret = 0;
536
537 ALOGD("audio_extn_a2dp_start_playback start");
538
539 if(!(a2dp.bt_lib_handle && a2dp.audio_start_stream
540 && a2dp.audio_get_codec_config)) {
541 ALOGE("a2dp handle is not identified, Ignoring start request");
542 return -ENOSYS;
543 }
544
545 if(a2dp.a2dp_suspended == true) {
546 //session will be restarted after suspend completion
547 ALOGD("a2dp start requested during suspend state");
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530548 return -ENOSYS;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530549 }
550
551 if (!a2dp.a2dp_started && !a2dp.a2dp_total_active_session_request) {
552 ALOGD("calling BT module stream start");
553 /* This call indicates BT IPC lib to start playback */
554 ret = a2dp.audio_start_stream();
555 ALOGE("BT controller start return = %d",ret);
556 if (ret != 0 ) {
557 ALOGE("BT controller start failed");
558 a2dp.a2dp_started = false;
559 ret = -ETIMEDOUT;
560 } else {
561 if(configure_a2dp_encoder_format() == true) {
562 a2dp.a2dp_started = true;
563 ret = 0;
564 ALOGD("Start playback successful to BT library");
565 } else {
566 ALOGD(" unable to configure DSP encoder");
567 a2dp.a2dp_started = false;
568 ret = -ETIMEDOUT;
569 }
570 }
571 }
572
573 if (a2dp.a2dp_started)
574 a2dp.a2dp_total_active_session_request++;
575
576 ALOGD("start A2DP playback total active sessions :%d",
577 a2dp.a2dp_total_active_session_request);
578 return ret;
579}
580
581int audio_extn_a2dp_stop_playback()
582{
583 int ret =0;
584
585 ALOGV("audio_extn_a2dp_stop_playback start");
586 if(!(a2dp.bt_lib_handle && a2dp.audio_stop_stream)) {
587 ALOGE("a2dp handle is not identified, Ignoring start request");
588 return -ENOSYS;
589 }
590
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530591 if (a2dp.a2dp_started && (a2dp.a2dp_total_active_session_request > 0))
592 a2dp.a2dp_total_active_session_request--;
593
594 if ( a2dp.a2dp_started && !a2dp.a2dp_total_active_session_request) {
595 struct mixer_ctl *ctl_enc_config;
596 struct sbc_enc_cfg_t dummy_reset_config;
597
598 ALOGV("calling BT module stream stop");
599 ret = a2dp.audio_stop_stream();
600 if (ret < 0)
601 ALOGE("stop stream to BT IPC lib failed");
602 else
603 ALOGV("stop steam to BT IPC lib successful");
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530604 memset(&dummy_reset_config, 0x0, sizeof(struct sbc_enc_cfg_t));
605 ctl_enc_config = mixer_get_ctl_by_name(a2dp.adev->mixer,
606 MIXER_ENC_CONFIG_BLOCK);
607 if (!ctl_enc_config) {
608 ALOGE(" ERROR a2dp encoder format mixer control not identifed");
609 } else {
610 ret = mixer_ctl_set_array(ctl_enc_config, (void *)&dummy_reset_config,
611 sizeof(struct sbc_enc_cfg_t));
612 a2dp.bt_encoder_format = ENC_MEDIA_FMT_NONE;
613 }
614 }
615 if(!a2dp.a2dp_total_active_session_request)
616 a2dp.a2dp_started = false;
617 ALOGD("Stop A2DP playback total active sessions :%d",
618 a2dp.a2dp_total_active_session_request);
619 return 0;
620}
621
622void audio_extn_a2dp_set_parameters(struct str_parms *parms)
623{
624 int ret, val;
625 char value[32]={0};
626
627 if(a2dp.is_a2dp_offload_supported == false) {
628 ALOGV("no supported encoders identified,ignoring a2dp setparam");
629 return;
630 }
631
632 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value,
633 sizeof(value));
634 if( ret >= 0) {
635 val = atoi(value);
636 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
637 ALOGV("Received device connect request for A2DP");
638 open_a2dp_output();
639 }
640 goto param_handled;
641 }
642
643 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value,
644 sizeof(value));
645
646 if( ret >= 0) {
647 val = atoi(value);
648 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
649 ALOGV("Received device dis- connect request");
650 close_a2dp_output();
651 }
652 goto param_handled;
653 }
654
655 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
656 if (ret >= 0) {
657 if (a2dp.bt_lib_handle && (a2dp.bt_state != A2DP_STATE_DISCONNECTED) ) {
658 if ((!strncmp(value,"true",sizeof(value)))) {
659 ALOGD("Setting a2dp to suspend state");
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530660 a2dp.a2dp_suspended = true;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530661 if(a2dp.audio_suspend_stream)
662 a2dp.audio_suspend_stream();
663 } else if (a2dp.a2dp_suspended == true) {
664 ALOGD("Resetting a2dp suspend state");
665 if(a2dp.clear_a2dpsuspend_flag)
666 a2dp.clear_a2dpsuspend_flag();
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530667 a2dp.a2dp_suspended = false;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530668 }
669 }
670 goto param_handled;
671 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530672param_handled:
673 ALOGV("end of a2dp setparam");
674}
675
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530676void audio_extn_a2dp_set_handoff_mode(bool is_on)
677{
678 a2dp.is_handoff_in_progress = is_on;
679}
680
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530681bool audio_extn_a2dp_is_force_device_switch()
682{
683 //During encoder reconfiguration mode, force a2dp device switch
684 return a2dp.is_handoff_in_progress;
685}
686
687void audio_extn_a2dp_init (void *adev)
688{
689 a2dp.adev = (struct audio_device*)adev;
690 a2dp.bt_lib_handle = NULL;
691 a2dp.a2dp_started = false;
692 a2dp.bt_state = A2DP_STATE_DISCONNECTED;
693 a2dp.a2dp_total_active_session_request = 0;
694 a2dp.a2dp_suspended = false;
695 a2dp.bt_encoder_format = AUDIO_FORMAT_INVALID;
696 a2dp.enc_config_data = NULL;
697 a2dp.is_a2dp_offload_supported = false;
698 a2dp.is_handoff_in_progress = false;
699 update_offload_codec_capabilities();
700}
701#endif // SPLIT_A2DP_ENABLED