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