blob: d0959e826ddd6a3d00d0488930140dda6602f3fa [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"
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +053065#define MIXER_ENC_BIT_FORMAT "AFE Input Bit Format"
Naresh Tanniru9d027a62015-03-13 01:32:10 +053066#define MIXER_ENC_FMT_SBC "SBC"
67#define MIXER_ENC_FMT_AAC "AAC"
68#define MIXER_ENC_FMT_APTX "APTX"
69#define MIXER_ENC_FMT_APTXHD "APTXHD"
70#define MIXER_ENC_FMT_NONE "NONE"
71
72
73typedef int (*audio_stream_open_t)(void);
74typedef int (*audio_stream_close_t)(void);
75typedef int (*audio_start_stream_t)(void);
76typedef int (*audio_stop_stream_t)(void);
77typedef int (*audio_suspend_stream_t)(void);
78typedef void (*audio_handoff_triggered_t)(void);
79typedef void (*clear_a2dpsuspend_flag_t)(void);
80typedef void * (*audio_get_codec_config_t)(uint8_t *multicast_status,uint8_t *num_dev,
81 audio_format_t *codec_type);
82
83enum A2DP_STATE {
84 A2DP_STATE_CONNECTED,
85 A2DP_STATE_STARTED,
86 A2DP_STATE_STOPPED,
87 A2DP_STATE_DISCONNECTED,
88};
89
90/* structure used to update a2dp state machine
91 * to communicate IPC library
92 * to store DSP encoder configuration information
93 */
94struct a2dp_data {
95 struct audio_device *adev;
96 void *bt_lib_handle;
97 audio_stream_open_t audio_stream_open;
98 audio_stream_close_t audio_stream_close;
99 audio_start_stream_t audio_start_stream;
100 audio_stop_stream_t audio_stop_stream;
101 audio_suspend_stream_t audio_suspend_stream;
102 audio_handoff_triggered_t audio_handoff_triggered;
103 clear_a2dpsuspend_flag_t clear_a2dpsuspend_flag;
104 audio_get_codec_config_t audio_get_codec_config;
105 enum A2DP_STATE bt_state;
106 audio_format_t bt_encoder_format;
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530107 uint32_t enc_sampling_rate;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530108 bool a2dp_started;
109 bool a2dp_suspended;
110 int a2dp_total_active_session_request;
111 bool is_a2dp_offload_supported;
112 bool is_handoff_in_progress;
113};
114
115struct a2dp_data a2dp;
116
117/* START of DSP configurable structures
118 * These values should match with DSP interface defintion
119 */
120
121/* AAC encoder configuration structure. */
122typedef struct aac_enc_cfg_t aac_enc_cfg_t;
123
124/* supported enc_mode are AAC_LC, AAC_SBR, AAC_PS
125 * supported aac_fmt_flag are ADTS/RAW
126 * supported channel_cfg are Native mode, Mono , Stereo
127 */
128struct aac_enc_cfg_t {
129 uint32_t enc_format;
130 uint32_t bit_rate;
131 uint32_t enc_mode;
132 uint16_t aac_fmt_flag;
Naresh Tannirua42d0bd2016-09-21 15:30:46 +0530133 uint16_t channel_cfg;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530134 uint32_t sample_rate;
135} ;
136
137/* SBC encoder configuration structure. */
138typedef struct sbc_enc_cfg_t sbc_enc_cfg_t;
139
140/* supported num_subbands are 4/8
141 * supported blk_len are 4, 8, 12, 16
142 * supported channel_mode are MONO, STEREO, DUAL_MONO, JOINT_STEREO
143 * supported alloc_method are LOUNDNESS/SNR
144 * supported bit_rate for mono channel is max 320kbps
145 * supported bit rate for stereo channel is max 512 kbps
146 */
147struct sbc_enc_cfg_t{
148 uint32_t enc_format;
149 uint32_t num_subbands;
150 uint32_t blk_len;
151 uint32_t channel_mode;
152 uint32_t alloc_method;
153 uint32_t bit_rate;
154 uint32_t sample_rate;
155};
156
157
158/* supported num_channels are Mono/Stereo
159 * supported channel_mapping for mono is CHANNEL_C
160 * supported channel mapping for stereo is CHANNEL_L and CHANNEL_R
161 * custom size and reserved are not used(for future enhancement)
162 */
163struct custom_enc_cfg_aptx_t
164{
165 uint32_t enc_format;
166 uint32_t sample_rate;
167 uint16_t num_channels;
168 uint16_t reserved;
169 uint8_t channel_mapping[8];
170 uint32_t custom_size;
171};
172
173/*********** END of DSP configurable structures ********************/
174
175/* API to identify DSP encoder captabilities */
176static void a2dp_offload_codec_cap_parser(char *value)
177{
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530178 char *tok = NULL,*saveptr;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530179
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530180 tok = strtok_r(value, "-", &saveptr);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530181 while (tok != NULL) {
182 if (strcmp(tok, "sbc") == 0) {
183 ALOGD("%s: SBC offload supported\n",__func__);
184 a2dp.is_a2dp_offload_supported = true;
185 break;
186 } else if (strcmp(tok, "aptx") == 0) {
187 ALOGD("%s: aptx offload supported\n",__func__);
188 a2dp.is_a2dp_offload_supported = true;
189 break;
190 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530191 tok = strtok_r(NULL, "-", &saveptr);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530192 };
193}
194
195static void update_offload_codec_capabilities()
196{
197 char value[PROPERTY_VALUE_MAX] = {'\0'};
198
199 property_get("persist.bt.a2dp_offload_cap", value, "false");
200 ALOGD("get_offload_codec_capabilities = %s",value);
201 a2dp.is_a2dp_offload_supported =
202 property_get_bool("persist.bt.a2dp_offload_cap", false);
203 if (strcmp(value, "false") != 0)
204 a2dp_offload_codec_cap_parser(value);
205 ALOGD("%s: codec cap = %s",__func__,value);
206}
207
208/* API to open BT IPC library to start IPC communication */
209static void open_a2dp_output()
210{
211 int ret = 0;
212
213 ALOGD(" Open A2DP output start ");
214 if (a2dp.bt_lib_handle == NULL){
215 ALOGD(" Requesting for BT lib handle");
216 a2dp.bt_lib_handle = dlopen(BT_IPC_LIB_NAME, RTLD_NOW);
217
218 if (a2dp.bt_lib_handle == NULL) {
219 ALOGE("%s: DLOPEN failed for %s", __func__, BT_IPC_LIB_NAME);
220 ret = -ENOSYS;
221 goto init_fail;
222 } else {
223 a2dp.audio_stream_open = (audio_stream_open_t)
224 dlsym(a2dp.bt_lib_handle, "audio_stream_open");
225 a2dp.audio_start_stream = (audio_start_stream_t)
226 dlsym(a2dp.bt_lib_handle, "audio_start_stream");
227 a2dp.audio_get_codec_config = (audio_get_codec_config_t)
228 dlsym(a2dp.bt_lib_handle, "audio_get_codec_config");
229 a2dp.audio_suspend_stream = (audio_suspend_stream_t)
230 dlsym(a2dp.bt_lib_handle, "audio_suspend_stream");
231 a2dp.audio_handoff_triggered = (audio_handoff_triggered_t)
232 dlsym(a2dp.bt_lib_handle, "audio_handoff_triggered");
233 a2dp.clear_a2dpsuspend_flag = (clear_a2dpsuspend_flag_t)
234 dlsym(a2dp.bt_lib_handle, "clear_a2dpsuspend_flag");
235 a2dp.audio_stop_stream = (audio_stop_stream_t)
236 dlsym(a2dp.bt_lib_handle, "audio_stop_stream");
237 a2dp.audio_stream_close = (audio_stream_close_t)
238 dlsym(a2dp.bt_lib_handle, "audio_stream_close");
239 }
240 }
241
242 if (a2dp.bt_lib_handle && a2dp.audio_stream_open) {
243 if (a2dp.bt_state == A2DP_STATE_DISCONNECTED) {
244 ALOGD("calling BT stream open");
245 ret = a2dp.audio_stream_open();
246 if(ret != 0) {
247 ALOGE("Failed to open output stream for a2dp: status %d", ret);
248 goto init_fail;
249 }
250 a2dp.bt_state = A2DP_STATE_CONNECTED;
251 } else {
252 ALOGD("Called a2dp open with improper state, Ignoring request state %d", a2dp.bt_state);
253 }
254 } else {
255 ALOGE("a2dp handle is not identified, Ignoring open request");
256 a2dp.bt_state = A2DP_STATE_DISCONNECTED;
257 goto init_fail;
258 }
259
260init_fail:
261 if(ret != 0 && (a2dp.bt_lib_handle != NULL)) {
262 dlclose(a2dp.bt_lib_handle);
263 a2dp.bt_lib_handle = NULL;
264 }
265}
266
267static int close_a2dp_output()
268{
269 ALOGV("%s\n",__func__);
270 if (!(a2dp.bt_lib_handle && a2dp.audio_stream_close)) {
271 ALOGE("a2dp handle is not identified, Ignoring close request");
272 return -ENOSYS;
273 }
274 if ((a2dp.bt_state == A2DP_STATE_CONNECTED) &&
275 (a2dp.bt_state == A2DP_STATE_STARTED) &&
276 (a2dp.bt_state == A2DP_STATE_STOPPED)) {
277 ALOGD("calling BT stream close");
278 if(a2dp.audio_stream_close() == false)
279 ALOGE("failed close a2dp control path from BT library");
280 a2dp.a2dp_started = false;
281 a2dp.a2dp_total_active_session_request = 0;
282 a2dp.a2dp_suspended = false;
283 a2dp.bt_encoder_format = AUDIO_FORMAT_INVALID;
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530284 a2dp.enc_sampling_rate = 48000;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530285 a2dp.bt_state = A2DP_STATE_DISCONNECTED;
286 } else {
287 ALOGD("close a2dp called in improper state");
288 a2dp.a2dp_started = false;
289 a2dp.a2dp_total_active_session_request = 0;
290 a2dp.a2dp_suspended = false;
291 a2dp.bt_encoder_format = AUDIO_FORMAT_INVALID;
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530292 a2dp.enc_sampling_rate = 48000;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530293 a2dp.bt_state = A2DP_STATE_DISCONNECTED;
294 }
295
296 return 0;
297}
298
299/* API to configure SBC DSP encoder */
300bool configure_sbc_enc_format(audio_sbc_encoder_config *sbc_bt_cfg)
301{
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530302 struct mixer_ctl *ctl_enc_data = NULL, *ctrl_bit_format = NULL;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530303 struct sbc_enc_cfg_t sbc_dsp_cfg;
304 bool is_configured = false;
305 int ret = 0;
306
307 if(sbc_bt_cfg == NULL)
308 return false;
309
310 ctl_enc_data = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_ENC_CONFIG_BLOCK);
311 if (!ctl_enc_data) {
312 ALOGE(" ERROR a2dp encoder CONFIG data mixer control not identifed");
313 is_configured = false;
314 goto fail;
315 }
316 a2dp.bt_encoder_format = AUDIO_FORMAT_SBC;
317 memset(&sbc_dsp_cfg, 0x0, sizeof(struct sbc_enc_cfg_t));
318 sbc_dsp_cfg.enc_format = ENC_MEDIA_FMT_SBC;
319 sbc_dsp_cfg.num_subbands = sbc_bt_cfg->subband;
320 sbc_dsp_cfg.blk_len = sbc_bt_cfg->blk_len;
321 switch(sbc_bt_cfg->channels) {
322 case 0:
323 sbc_dsp_cfg.channel_mode = MEDIA_FMT_SBC_CHANNEL_MODE_MONO;
324 break;
325 case 1:
326 sbc_dsp_cfg.channel_mode = MEDIA_FMT_SBC_CHANNEL_MODE_DUAL_MONO;
327 break;
328 case 3:
329 sbc_dsp_cfg.channel_mode = MEDIA_FMT_SBC_CHANNEL_MODE_JOINT_STEREO;
330 break;
331 case 2:
332 default:
333 sbc_dsp_cfg.channel_mode = MEDIA_FMT_SBC_CHANNEL_MODE_STEREO;
334 break;
335 }
336 if (sbc_bt_cfg->alloc)
337 sbc_dsp_cfg.alloc_method = MEDIA_FMT_SBC_ALLOCATION_METHOD_LOUDNESS;
338 else
339 sbc_dsp_cfg.alloc_method = MEDIA_FMT_SBC_ALLOCATION_METHOD_SNR;
340 sbc_dsp_cfg.bit_rate = sbc_bt_cfg->bitrate;
341 sbc_dsp_cfg.sample_rate = sbc_bt_cfg->sampling_rate;
342 ret = mixer_ctl_set_array(ctl_enc_data, (void *)&sbc_dsp_cfg,
343 sizeof(struct sbc_enc_cfg_t));
344 if (ret != 0) {
345 ALOGE("%s: failed to set SBC encoder config", __func__);
346 is_configured = false;
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530347 goto fail;
348 }
349 ctrl_bit_format = mixer_get_ctl_by_name(a2dp.adev->mixer,
350 MIXER_ENC_BIT_FORMAT);
351 if (!ctrl_bit_format) {
352 ALOGE(" ERROR bit format CONFIG data mixer control not identifed");
353 is_configured = false;
354 goto fail;
355 }
356 ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S16_LE");
357 if (ret != 0) {
358 ALOGE("%s: Failed to set bit format to encoder", __func__);
359 is_configured = false;
360 goto fail;
361 }
362 is_configured = true;
363 a2dp.enc_sampling_rate = sbc_bt_cfg->sampling_rate;
364 ALOGV("Successfully updated SBC enc format with samplingrate: %d channelmode:%d",
365 sbc_dsp_cfg.sample_rate, sbc_dsp_cfg.channel_mode);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530366fail:
367 return is_configured;
368}
369
370/* API to configure APTX DSP encoder */
371bool configure_aptx_enc_format(audio_aptx_encoder_config *aptx_bt_cfg)
372{
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530373 struct mixer_ctl *ctl_enc_data = NULL, *ctrl_bit_format = NULL;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530374 struct custom_enc_cfg_aptx_t aptx_dsp_cfg;
375 bool is_configured = false;
376 int ret = 0;
377
378 if(aptx_bt_cfg == NULL)
379 return false;
380
381 ctl_enc_data = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_ENC_CONFIG_BLOCK);
382 if (!ctl_enc_data) {
383 ALOGE(" ERROR a2dp encoder CONFIG data mixer control not identifed");
384 is_configured = false;
385 goto fail;
386 }
387 a2dp.bt_encoder_format = AUDIO_FORMAT_APTX;
388 memset(&aptx_dsp_cfg, 0x0, sizeof(struct custom_enc_cfg_aptx_t));
389 aptx_dsp_cfg.enc_format = ENC_MEDIA_FMT_APTX;
390 aptx_dsp_cfg.sample_rate = aptx_bt_cfg->sampling_rate;
391 aptx_dsp_cfg.num_channels = aptx_bt_cfg->channels;
392 switch(aptx_dsp_cfg.num_channels) {
393 case 1:
394 aptx_dsp_cfg.channel_mapping[0] = PCM_CHANNEL_C;
395 break;
396 case 2:
397 default:
398 aptx_dsp_cfg.channel_mapping[0] = PCM_CHANNEL_L;
399 aptx_dsp_cfg.channel_mapping[1] = PCM_CHANNEL_R;
400 break;
401 }
402 ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_dsp_cfg,
403 sizeof(struct custom_enc_cfg_aptx_t));
404 if (ret != 0) {
405 ALOGE("%s: Failed to set APTX encoder config", __func__);
406 is_configured = false;
407 goto fail;
408 }
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530409 ctrl_bit_format = mixer_get_ctl_by_name(a2dp.adev->mixer,
410 MIXER_ENC_BIT_FORMAT);
411 if (!ctrl_bit_format) {
412 ALOGE("ERROR bit format CONFIG data mixer control not identifed");
413 is_configured = false;
414 goto fail;
415 } else {
416 ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S16_LE");
417 if (ret != 0) {
418 ALOGE("%s: Failed to set bit format to encoder", __func__);
419 is_configured = false;
420 goto fail;
421 }
422 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530423 is_configured = true;
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530424 a2dp.enc_sampling_rate = aptx_bt_cfg->sampling_rate;
425 ALOGV("Successfully updated APTX enc format with samplingrate: %d channels:%d",
426 aptx_dsp_cfg.sample_rate, aptx_dsp_cfg.num_channels);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530427fail:
428 return is_configured;
429}
430
431/* API to configure APTX HD DSP encoder
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530432 */
433bool configure_aptx_hd_enc_format(audio_aptx_encoder_config *aptx_bt_cfg)
434{
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530435 struct mixer_ctl *ctl_enc_data = NULL, *ctrl_bit_format = NULL;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530436 struct custom_enc_cfg_aptx_t aptx_dsp_cfg;
437 bool is_configured = false;
438 int ret = 0;
439
440 if(aptx_bt_cfg == NULL)
441 return false;
442
443 ctl_enc_data = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_ENC_CONFIG_BLOCK);
444 if (!ctl_enc_data) {
445 ALOGE(" ERROR a2dp encoder CONFIG data mixer control not identifed");
446 is_configured = false;
447 goto fail;
448 }
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530449
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530450 a2dp.bt_encoder_format = AUDIO_FORMAT_APTX_HD;
451 memset(&aptx_dsp_cfg, 0x0, sizeof(struct custom_enc_cfg_aptx_t));
452 aptx_dsp_cfg.enc_format = ENC_MEDIA_FMT_APTX_HD;
453 aptx_dsp_cfg.sample_rate = aptx_bt_cfg->sampling_rate;
454 aptx_dsp_cfg.num_channels = aptx_bt_cfg->channels;
455 switch(aptx_dsp_cfg.num_channels) {
456 case 1:
457 aptx_dsp_cfg.channel_mapping[0] = PCM_CHANNEL_C;
458 break;
459 case 2:
460 default:
461 aptx_dsp_cfg.channel_mapping[0] = PCM_CHANNEL_L;
462 aptx_dsp_cfg.channel_mapping[1] = PCM_CHANNEL_R;
463 break;
464 }
465 ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_dsp_cfg,
466 sizeof(struct custom_enc_cfg_aptx_t));
467 if (ret != 0) {
468 ALOGE("%s: Failed to set APTX HD encoder config", __func__);
469 is_configured = false;
470 goto fail;
471 }
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530472 ctrl_bit_format = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_ENC_BIT_FORMAT);
473 if (!ctrl_bit_format) {
474 ALOGE(" ERROR bit format CONFIG data mixer control not identifed");
475 is_configured = false;
476 goto fail;
477 }
478 ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S24_LE");
479 if (ret != 0) {
480 ALOGE("%s: Failed to set APTX HD encoder config", __func__);
481 is_configured = false;
482 goto fail;
483 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530484 is_configured = true;
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530485 a2dp.enc_sampling_rate = aptx_bt_cfg->sampling_rate;
486 ALOGV("Successfully updated APTX HD encformat with samplingrate: %d channels:%d",
487 aptx_dsp_cfg.sample_rate, aptx_dsp_cfg.num_channels);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530488fail:
489 return is_configured;
490}
491
492/* API to configure AAC DSP encoder */
493bool configure_aac_enc_format(audio_aac_encoder_config *aac_bt_cfg)
494{
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530495 struct mixer_ctl *ctl_enc_data = NULL, *ctrl_bit_format = NULL;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530496 struct aac_enc_cfg_t aac_dsp_cfg;
497 bool is_configured = false;
498 int ret = 0;
499
500 if(aac_bt_cfg == NULL)
501 return false;
502
503 ctl_enc_data = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_ENC_CONFIG_BLOCK);
504 if (!ctl_enc_data) {
505 ALOGE(" ERROR a2dp encoder CONFIG data mixer control not identifed");
506 is_configured = false;
507 goto fail;
508 }
509 a2dp.bt_encoder_format = AUDIO_FORMAT_AAC;
510 memset(&aac_dsp_cfg, 0x0, sizeof(struct aac_enc_cfg_t));
511 aac_dsp_cfg.enc_format = ENC_MEDIA_FMT_AAC;
512 aac_dsp_cfg.bit_rate = aac_bt_cfg->bitrate;
Naresh Tannirua42d0bd2016-09-21 15:30:46 +0530513 aac_dsp_cfg.sample_rate = aac_bt_cfg->sampling_rate;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530514 switch(aac_bt_cfg->enc_mode) {
515 case 0:
516 aac_dsp_cfg.enc_mode = MEDIA_FMT_AAC_AOT_LC;
517 break;
518 case 2:
519 aac_dsp_cfg.enc_mode = MEDIA_FMT_AAC_AOT_PS;
520 break;
521 case 1:
522 default:
523 aac_dsp_cfg.enc_mode = MEDIA_FMT_AAC_AOT_SBR;
524 break;
525 }
Naresh Tannirua42d0bd2016-09-21 15:30:46 +0530526 aac_dsp_cfg.aac_fmt_flag = aac_bt_cfg->format_flag;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530527 aac_dsp_cfg.channel_cfg = aac_bt_cfg->channels;
528 ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aac_dsp_cfg,
529 sizeof(struct aac_enc_cfg_t));
530 if (ret != 0) {
531 ALOGE("%s: failed to set SBC encoder config", __func__);
532 is_configured = false;
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530533 goto fail;
534 }
535 ctrl_bit_format = mixer_get_ctl_by_name(a2dp.adev->mixer,
536 MIXER_ENC_BIT_FORMAT);
537 if (!ctrl_bit_format) {
538 is_configured = false;
539 ALOGE(" ERROR bit format CONFIG data mixer control not identifed");
540 goto fail;
541 }
542 ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S16_LE");
543 if (ret != 0) {
544 ALOGE("%s: Failed to set bit format to encoder", __func__);
545 is_configured = false;
546 goto fail;
547 }
548 is_configured = true;
549 a2dp.enc_sampling_rate = aac_bt_cfg->sampling_rate;
550 ALOGV("Successfully updated AAC enc format with samplingrate: %d channels:%d",
551 aac_dsp_cfg.sample_rate, aac_dsp_cfg.channel_cfg);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530552fail:
553 return is_configured;
554}
555
556bool configure_a2dp_encoder_format()
557{
558 void *codec_info = NULL;
559 uint8_t multi_cast = 0, num_dev = 1;
560 audio_format_t codec_type = AUDIO_FORMAT_INVALID;
561 bool is_configured = false;
562
563 if (!a2dp.audio_get_codec_config) {
564 ALOGE(" a2dp handle is not identified, ignoring a2dp encoder config");
565 return false;
566 }
567 ALOGD("configure_a2dp_encoder_format start");
568 codec_info = a2dp.audio_get_codec_config(&multi_cast, &num_dev,
569 &codec_type);
570
571 switch(codec_type) {
572 case AUDIO_FORMAT_SBC:
573 ALOGD(" Received SBC encoder supported BT device");
574 is_configured =
575 configure_sbc_enc_format((audio_sbc_encoder_config *)codec_info);
576 break;
577 case AUDIO_FORMAT_APTX:
578 ALOGD(" Received APTX encoder supported BT device");
579 is_configured =
580 configure_aptx_enc_format((audio_aptx_encoder_config *)codec_info);
581 break;
582 case AUDIO_FORMAT_APTX_HD:
583 ALOGD(" Received APTX HD encoder supported BT device");
584 is_configured =
585 configure_aptx_hd_enc_format((audio_aptx_encoder_config *)codec_info);
586 break;
587 case AUDIO_FORMAT_AAC:
588 ALOGD(" Received AAC encoder supported BT device");
589 is_configured =
590 configure_aac_enc_format((audio_aac_encoder_config *)codec_info);
591 break;
592 default:
593 ALOGD(" Received Unsupported encoder formar");
594 is_configured = false;
595 break;
596 }
597 return is_configured;
598}
599
600int audio_extn_a2dp_start_playback()
601{
602 int ret = 0;
603
604 ALOGD("audio_extn_a2dp_start_playback start");
605
606 if(!(a2dp.bt_lib_handle && a2dp.audio_start_stream
607 && a2dp.audio_get_codec_config)) {
608 ALOGE("a2dp handle is not identified, Ignoring start request");
609 return -ENOSYS;
610 }
611
612 if(a2dp.a2dp_suspended == true) {
613 //session will be restarted after suspend completion
614 ALOGD("a2dp start requested during suspend state");
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530615 return -ENOSYS;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530616 }
617
618 if (!a2dp.a2dp_started && !a2dp.a2dp_total_active_session_request) {
619 ALOGD("calling BT module stream start");
620 /* This call indicates BT IPC lib to start playback */
621 ret = a2dp.audio_start_stream();
622 ALOGE("BT controller start return = %d",ret);
623 if (ret != 0 ) {
624 ALOGE("BT controller start failed");
625 a2dp.a2dp_started = false;
626 ret = -ETIMEDOUT;
627 } else {
628 if(configure_a2dp_encoder_format() == true) {
629 a2dp.a2dp_started = true;
630 ret = 0;
631 ALOGD("Start playback successful to BT library");
632 } else {
633 ALOGD(" unable to configure DSP encoder");
634 a2dp.a2dp_started = false;
635 ret = -ETIMEDOUT;
636 }
637 }
638 }
639
640 if (a2dp.a2dp_started)
641 a2dp.a2dp_total_active_session_request++;
642
643 ALOGD("start A2DP playback total active sessions :%d",
644 a2dp.a2dp_total_active_session_request);
645 return ret;
646}
647
Naresh Tanniru03f9dd52016-10-19 18:46:22 +0530648static void reset_a2dp_enc_config_params()
649{
650 int ret =0;
651
652 struct mixer_ctl *ctl_enc_config, *ctrl_bit_format;
653 struct sbc_enc_cfg_t dummy_reset_config;
654
655 memset(&dummy_reset_config, 0x0, sizeof(struct sbc_enc_cfg_t));
656 ctl_enc_config = mixer_get_ctl_by_name(a2dp.adev->mixer,
657 MIXER_ENC_CONFIG_BLOCK);
658 if (!ctl_enc_config) {
659 ALOGE(" ERROR a2dp encoder format mixer control not identifed");
660 } else {
661 ret = mixer_ctl_set_array(ctl_enc_config, (void *)&dummy_reset_config,
662 sizeof(struct sbc_enc_cfg_t));
663 a2dp.bt_encoder_format = ENC_MEDIA_FMT_NONE;
664 }
665 ctrl_bit_format = mixer_get_ctl_by_name(a2dp.adev->mixer,
666 MIXER_ENC_BIT_FORMAT);
667 if (!ctrl_bit_format) {
668 ALOGE(" ERROR bit format CONFIG data mixer control not identifed");
669 } else {
670 ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S16_LE");
671 if (ret != 0) {
672 ALOGE("%s: Failed to set bit format to encoder", __func__);
673 }
674 }
675}
676
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530677int audio_extn_a2dp_stop_playback()
678{
679 int ret =0;
680
681 ALOGV("audio_extn_a2dp_stop_playback start");
682 if(!(a2dp.bt_lib_handle && a2dp.audio_stop_stream)) {
683 ALOGE("a2dp handle is not identified, Ignoring start request");
684 return -ENOSYS;
685 }
686
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530687 if (a2dp.a2dp_started && (a2dp.a2dp_total_active_session_request > 0))
688 a2dp.a2dp_total_active_session_request--;
689
690 if ( a2dp.a2dp_started && !a2dp.a2dp_total_active_session_request) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530691 ALOGV("calling BT module stream stop");
692 ret = a2dp.audio_stop_stream();
693 if (ret < 0)
694 ALOGE("stop stream to BT IPC lib failed");
695 else
696 ALOGV("stop steam to BT IPC lib successful");
Naresh Tanniru03f9dd52016-10-19 18:46:22 +0530697 reset_a2dp_enc_config_params();
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530698 }
699 if(!a2dp.a2dp_total_active_session_request)
700 a2dp.a2dp_started = false;
701 ALOGD("Stop A2DP playback total active sessions :%d",
702 a2dp.a2dp_total_active_session_request);
703 return 0;
704}
705
706void audio_extn_a2dp_set_parameters(struct str_parms *parms)
707{
708 int ret, val;
709 char value[32]={0};
710
711 if(a2dp.is_a2dp_offload_supported == false) {
712 ALOGV("no supported encoders identified,ignoring a2dp setparam");
713 return;
714 }
715
716 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value,
717 sizeof(value));
718 if( ret >= 0) {
719 val = atoi(value);
720 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
721 ALOGV("Received device connect request for A2DP");
722 open_a2dp_output();
723 }
724 goto param_handled;
725 }
726
727 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value,
728 sizeof(value));
729
730 if( ret >= 0) {
731 val = atoi(value);
732 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
733 ALOGV("Received device dis- connect request");
Naresh Tanniru03f9dd52016-10-19 18:46:22 +0530734 reset_a2dp_enc_config_params();
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530735 close_a2dp_output();
736 }
737 goto param_handled;
738 }
739
740 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
741 if (ret >= 0) {
742 if (a2dp.bt_lib_handle && (a2dp.bt_state != A2DP_STATE_DISCONNECTED) ) {
743 if ((!strncmp(value,"true",sizeof(value)))) {
744 ALOGD("Setting a2dp to suspend state");
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530745 a2dp.a2dp_suspended = true;
Naresh Tanniru03f9dd52016-10-19 18:46:22 +0530746 reset_a2dp_enc_config_params();
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530747 if(a2dp.audio_suspend_stream)
748 a2dp.audio_suspend_stream();
749 } else if (a2dp.a2dp_suspended == true) {
750 ALOGD("Resetting a2dp suspend state");
751 if(a2dp.clear_a2dpsuspend_flag)
752 a2dp.clear_a2dpsuspend_flag();
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530753 a2dp.a2dp_suspended = false;
Naresh Tanniru649871a2016-11-04 18:08:32 +0530754 /*
755 * It is possible that before suspend,a2dp sessions can be active
756 * for example during music + voice activation concurrency
757 * a2dp suspend will be called & BT will change to sco mode
758 * though music is paused as a part of voice activation
759 * compress session close happens only after pause timeout(10secs)
760 * so if resume request comes before pause timeout as a2dp session
761 * is already active IPC start will not be called from APM/audio_hw
762 * Fix is to call a2dp start for IPC library post suspend
763 * based on number of active session count
764 */
765 if (a2dp.a2dp_total_active_session_request > 0) {
766 ALOGD(" Calling IPC lib start post suspend state");
767 if(a2dp.audio_start_stream) {
768 ret = a2dp.audio_start_stream();
769 if (ret != 0) {
770 ALOGE("BT controller start failed");
771 a2dp.a2dp_started = false;
772 }
773 }
774 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530775 }
776 }
777 goto param_handled;
778 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530779param_handled:
780 ALOGV("end of a2dp setparam");
781}
782
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530783void audio_extn_a2dp_set_handoff_mode(bool is_on)
784{
785 a2dp.is_handoff_in_progress = is_on;
786}
787
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530788bool audio_extn_a2dp_is_force_device_switch()
789{
790 //During encoder reconfiguration mode, force a2dp device switch
791 return a2dp.is_handoff_in_progress;
792}
793
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530794void audio_extn_a2dp_get_apptype_params(uint32_t *sample_rate,
795 uint32_t *bit_width)
796{
797 if(a2dp.bt_encoder_format == AUDIO_FORMAT_APTX_HD)
798 *bit_width = 24;
799 else
800 *bit_width = 16;
801 *sample_rate = a2dp.enc_sampling_rate;
802}
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530803void audio_extn_a2dp_init (void *adev)
804{
805 a2dp.adev = (struct audio_device*)adev;
806 a2dp.bt_lib_handle = NULL;
807 a2dp.a2dp_started = false;
808 a2dp.bt_state = A2DP_STATE_DISCONNECTED;
809 a2dp.a2dp_total_active_session_request = 0;
810 a2dp.a2dp_suspended = false;
811 a2dp.bt_encoder_format = AUDIO_FORMAT_INVALID;
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530812 a2dp.enc_sampling_rate = 48000;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530813 a2dp.is_a2dp_offload_supported = false;
814 a2dp.is_handoff_in_progress = false;
815 update_offload_codec_capabilities();
816}
817#endif // SPLIT_A2DP_ENABLED