blob: 1ffa968e9ce9a1f3b440e558c474aa5257a3ea6f [file] [log] [blame]
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301/*
Naresh Tannirued694c82017-02-07 17:01:28 +05302* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303*
4* Redistribution and use in source and binary forms, with or without
5* modification, are permitted provided that the following conditions are
6* met:
7* * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above
10* copyright notice, this list of conditions and the following
11* disclaimer in the documentation and/or other materials provided
12* with the distribution.
13* * Neither the name of The Linux Foundation nor the names of its
14* contributors may be used to endorse or promote products derived
15* from this software without specific prior written permission.
16*
17* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*/
29#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
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053044#ifdef DYNAMIC_LOG_ENABLED
45#include <log_xml_parser.h>
46#define LOG_MASK HAL_MOD_FILE_A2DP
47#include <log_utils.h>
48#endif
49
Naresh Tanniru9d027a62015-03-13 01:32:10 +053050#ifdef SPLIT_A2DP_ENABLED
51#define AUDIO_PARAMETER_A2DP_STARTED "A2dpStarted"
52#define BT_IPC_LIB_NAME "libbthost_if.so"
53#define ENC_MEDIA_FMT_NONE 0
54#define ENC_MEDIA_FMT_AAC 0x00010DA6
55#define ENC_MEDIA_FMT_APTX 0x000131ff
56#define ENC_MEDIA_FMT_APTX_HD 0x00013200
57#define ENC_MEDIA_FMT_SBC 0x00010BF2
58#define MEDIA_FMT_AAC_AOT_LC 2
59#define MEDIA_FMT_AAC_AOT_SBR 5
60#define MEDIA_FMT_AAC_AOT_PS 29
Naresh Tanniru9d027a62015-03-13 01:32:10 +053061#define PCM_CHANNEL_L 1
62#define PCM_CHANNEL_R 2
63#define PCM_CHANNEL_C 3
64#define MEDIA_FMT_SBC_CHANNEL_MODE_MONO 1
65#define MEDIA_FMT_SBC_CHANNEL_MODE_STEREO 2
66#define MEDIA_FMT_SBC_CHANNEL_MODE_DUAL_MONO 8
67#define MEDIA_FMT_SBC_CHANNEL_MODE_JOINT_STEREO 9
68#define MEDIA_FMT_SBC_ALLOCATION_METHOD_LOUDNESS 0
69#define MEDIA_FMT_SBC_ALLOCATION_METHOD_SNR 1
70#define MIXER_ENC_CONFIG_BLOCK "SLIM_7_RX Encoder Config"
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +053071#define MIXER_ENC_BIT_FORMAT "AFE Input Bit Format"
Naresh Tanniru9d027a62015-03-13 01:32:10 +053072#define MIXER_ENC_FMT_SBC "SBC"
73#define MIXER_ENC_FMT_AAC "AAC"
74#define MIXER_ENC_FMT_APTX "APTX"
75#define MIXER_ENC_FMT_APTXHD "APTXHD"
76#define MIXER_ENC_FMT_NONE "NONE"
77
Naresh Tanniru9d027a62015-03-13 01:32:10 +053078typedef int (*audio_stream_open_t)(void);
79typedef int (*audio_stream_close_t)(void);
80typedef int (*audio_start_stream_t)(void);
81typedef int (*audio_stop_stream_t)(void);
82typedef int (*audio_suspend_stream_t)(void);
83typedef void (*audio_handoff_triggered_t)(void);
84typedef void (*clear_a2dpsuspend_flag_t)(void);
85typedef void * (*audio_get_codec_config_t)(uint8_t *multicast_status,uint8_t *num_dev,
86 audio_format_t *codec_type);
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +053087typedef int (*audio_check_a2dp_ready_t)(void);
Naresh Tanniru9d027a62015-03-13 01:32:10 +053088
89enum A2DP_STATE {
90 A2DP_STATE_CONNECTED,
91 A2DP_STATE_STARTED,
92 A2DP_STATE_STOPPED,
93 A2DP_STATE_DISCONNECTED,
94};
95
96/* structure used to update a2dp state machine
97 * to communicate IPC library
98 * to store DSP encoder configuration information
99 */
100struct a2dp_data {
101 struct audio_device *adev;
102 void *bt_lib_handle;
103 audio_stream_open_t audio_stream_open;
104 audio_stream_close_t audio_stream_close;
105 audio_start_stream_t audio_start_stream;
106 audio_stop_stream_t audio_stop_stream;
107 audio_suspend_stream_t audio_suspend_stream;
108 audio_handoff_triggered_t audio_handoff_triggered;
109 clear_a2dpsuspend_flag_t clear_a2dpsuspend_flag;
110 audio_get_codec_config_t audio_get_codec_config;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +0530111 audio_check_a2dp_ready_t audio_check_a2dp_ready;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530112 enum A2DP_STATE bt_state;
113 audio_format_t bt_encoder_format;
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530114 uint32_t enc_sampling_rate;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530115 bool a2dp_started;
116 bool a2dp_suspended;
117 int a2dp_total_active_session_request;
118 bool is_a2dp_offload_supported;
119 bool is_handoff_in_progress;
120};
121
122struct a2dp_data a2dp;
123
124/* START of DSP configurable structures
125 * These values should match with DSP interface defintion
126 */
127
128/* AAC encoder configuration structure. */
129typedef struct aac_enc_cfg_t aac_enc_cfg_t;
130
131/* supported enc_mode are AAC_LC, AAC_SBR, AAC_PS
132 * supported aac_fmt_flag are ADTS/RAW
133 * supported channel_cfg are Native mode, Mono , Stereo
134 */
135struct aac_enc_cfg_t {
136 uint32_t enc_format;
137 uint32_t bit_rate;
138 uint32_t enc_mode;
139 uint16_t aac_fmt_flag;
Naresh Tannirua42d0bd2016-09-21 15:30:46 +0530140 uint16_t channel_cfg;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530141 uint32_t sample_rate;
142} ;
143
144/* SBC encoder configuration structure. */
145typedef struct sbc_enc_cfg_t sbc_enc_cfg_t;
146
147/* supported num_subbands are 4/8
148 * supported blk_len are 4, 8, 12, 16
149 * supported channel_mode are MONO, STEREO, DUAL_MONO, JOINT_STEREO
150 * supported alloc_method are LOUNDNESS/SNR
151 * supported bit_rate for mono channel is max 320kbps
152 * supported bit rate for stereo channel is max 512 kbps
153 */
154struct sbc_enc_cfg_t{
155 uint32_t enc_format;
156 uint32_t num_subbands;
157 uint32_t blk_len;
158 uint32_t channel_mode;
159 uint32_t alloc_method;
160 uint32_t bit_rate;
161 uint32_t sample_rate;
162};
163
164
165/* supported num_channels are Mono/Stereo
166 * supported channel_mapping for mono is CHANNEL_C
167 * supported channel mapping for stereo is CHANNEL_L and CHANNEL_R
168 * custom size and reserved are not used(for future enhancement)
169 */
170struct custom_enc_cfg_aptx_t
171{
172 uint32_t enc_format;
173 uint32_t sample_rate;
174 uint16_t num_channels;
175 uint16_t reserved;
176 uint8_t channel_mapping[8];
177 uint32_t custom_size;
178};
179
Satya Krishna Pindiprolif7d65712017-04-26 14:24:53 +0530180/* TODO: Define the following structures only for O using PLATFORM_VERSION */
181/* Information about BT SBC encoder configuration
182 * This data is used between audio HAL module and
183 * BT IPC library to configure DSP encoder
184 */
185typedef struct {
186 uint32_t subband; /* 4, 8 */
187 uint32_t blk_len; /* 4, 8, 12, 16 */
188 uint16_t sampling_rate; /*44.1khz,48khz*/
189 uint8_t channels; /*0(Mono),1(Dual_mono),2(Stereo),3(JS)*/
190 uint8_t alloc; /*0(Loudness),1(SNR)*/
191 uint8_t min_bitpool; /* 2 */
192 uint8_t max_bitpool; /*53(44.1khz),51 (48khz) */
193 uint32_t bitrate; /* 320kbps to 512kbps */
194} audio_sbc_encoder_config;
195
196
197/* Information about BT APTX encoder configuration
198 * This data is used between audio HAL module and
199 * BT IPC library to configure DSP encoder
200 */
201typedef struct {
202 uint16_t sampling_rate;
203 uint8_t channels;
204 uint32_t bitrate;
205} audio_aptx_encoder_config;
206
207
208/* Information about BT AAC encoder configuration
209 * This data is used between audio HAL module and
210 * BT IPC library to configure DSP encoder
211 */
212typedef struct {
213 uint32_t enc_mode; /* LC, SBR, PS */
214 uint16_t format_flag; /* RAW, ADTS */
215 uint16_t channels; /* 1-Mono, 2-Stereo */
216 uint32_t sampling_rate;
217 uint32_t bitrate;
218} audio_aac_encoder_config;
219
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530220/*********** END of DSP configurable structures ********************/
221
222/* API to identify DSP encoder captabilities */
223static void a2dp_offload_codec_cap_parser(char *value)
224{
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530225 char *tok = NULL,*saveptr;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530226
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530227 tok = strtok_r(value, "-", &saveptr);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530228 while (tok != NULL) {
229 if (strcmp(tok, "sbc") == 0) {
230 ALOGD("%s: SBC offload supported\n",__func__);
231 a2dp.is_a2dp_offload_supported = true;
232 break;
233 } else if (strcmp(tok, "aptx") == 0) {
234 ALOGD("%s: aptx offload supported\n",__func__);
235 a2dp.is_a2dp_offload_supported = true;
236 break;
Naresh Tannirued694c82017-02-07 17:01:28 +0530237 } else if (strcmp(tok, "aptxhd") == 0) {
238 ALOGD("%s: aptx HD offload supported\n",__func__);
239 a2dp.is_a2dp_offload_supported = true;
240 break;
241 } else if (strcmp(tok, "aac") == 0) {
242 ALOGD("%s: aac offload supported\n",__func__);
243 a2dp.is_a2dp_offload_supported = true;
244 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530245 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530246 tok = strtok_r(NULL, "-", &saveptr);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530247 };
248}
249
250static void update_offload_codec_capabilities()
251{
252 char value[PROPERTY_VALUE_MAX] = {'\0'};
253
254 property_get("persist.bt.a2dp_offload_cap", value, "false");
255 ALOGD("get_offload_codec_capabilities = %s",value);
256 a2dp.is_a2dp_offload_supported =
257 property_get_bool("persist.bt.a2dp_offload_cap", false);
258 if (strcmp(value, "false") != 0)
259 a2dp_offload_codec_cap_parser(value);
260 ALOGD("%s: codec cap = %s",__func__,value);
261}
262
263/* API to open BT IPC library to start IPC communication */
264static void open_a2dp_output()
265{
266 int ret = 0;
267
268 ALOGD(" Open A2DP output start ");
269 if (a2dp.bt_lib_handle == NULL){
270 ALOGD(" Requesting for BT lib handle");
271 a2dp.bt_lib_handle = dlopen(BT_IPC_LIB_NAME, RTLD_NOW);
272
273 if (a2dp.bt_lib_handle == NULL) {
274 ALOGE("%s: DLOPEN failed for %s", __func__, BT_IPC_LIB_NAME);
275 ret = -ENOSYS;
276 goto init_fail;
277 } else {
278 a2dp.audio_stream_open = (audio_stream_open_t)
279 dlsym(a2dp.bt_lib_handle, "audio_stream_open");
280 a2dp.audio_start_stream = (audio_start_stream_t)
281 dlsym(a2dp.bt_lib_handle, "audio_start_stream");
282 a2dp.audio_get_codec_config = (audio_get_codec_config_t)
283 dlsym(a2dp.bt_lib_handle, "audio_get_codec_config");
284 a2dp.audio_suspend_stream = (audio_suspend_stream_t)
285 dlsym(a2dp.bt_lib_handle, "audio_suspend_stream");
286 a2dp.audio_handoff_triggered = (audio_handoff_triggered_t)
287 dlsym(a2dp.bt_lib_handle, "audio_handoff_triggered");
288 a2dp.clear_a2dpsuspend_flag = (clear_a2dpsuspend_flag_t)
289 dlsym(a2dp.bt_lib_handle, "clear_a2dpsuspend_flag");
290 a2dp.audio_stop_stream = (audio_stop_stream_t)
291 dlsym(a2dp.bt_lib_handle, "audio_stop_stream");
292 a2dp.audio_stream_close = (audio_stream_close_t)
293 dlsym(a2dp.bt_lib_handle, "audio_stream_close");
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +0530294 a2dp.audio_check_a2dp_ready = (audio_check_a2dp_ready_t)
295 dlsym(a2dp.bt_lib_handle,"audio_check_a2dp_ready");
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530296 }
297 }
298
299 if (a2dp.bt_lib_handle && a2dp.audio_stream_open) {
300 if (a2dp.bt_state == A2DP_STATE_DISCONNECTED) {
301 ALOGD("calling BT stream open");
302 ret = a2dp.audio_stream_open();
303 if(ret != 0) {
304 ALOGE("Failed to open output stream for a2dp: status %d", ret);
305 goto init_fail;
306 }
307 a2dp.bt_state = A2DP_STATE_CONNECTED;
308 } else {
309 ALOGD("Called a2dp open with improper state, Ignoring request state %d", a2dp.bt_state);
310 }
311 } else {
312 ALOGE("a2dp handle is not identified, Ignoring open request");
313 a2dp.bt_state = A2DP_STATE_DISCONNECTED;
314 goto init_fail;
315 }
316
317init_fail:
318 if(ret != 0 && (a2dp.bt_lib_handle != NULL)) {
319 dlclose(a2dp.bt_lib_handle);
320 a2dp.bt_lib_handle = NULL;
321 }
322}
323
324static int close_a2dp_output()
325{
326 ALOGV("%s\n",__func__);
327 if (!(a2dp.bt_lib_handle && a2dp.audio_stream_close)) {
328 ALOGE("a2dp handle is not identified, Ignoring close request");
329 return -ENOSYS;
330 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +0530331 if (a2dp.bt_state != A2DP_STATE_DISCONNECTED) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530332 ALOGD("calling BT stream close");
333 if(a2dp.audio_stream_close() == false)
334 ALOGE("failed close a2dp control path from BT library");
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530335 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +0530336 a2dp.a2dp_started = false;
337 a2dp.a2dp_total_active_session_request = 0;
338 a2dp.a2dp_suspended = false;
339 a2dp.bt_encoder_format = AUDIO_FORMAT_INVALID;
340 a2dp.enc_sampling_rate = 48000;
341 a2dp.bt_state = A2DP_STATE_DISCONNECTED;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530342
343 return 0;
344}
345
346/* API to configure SBC DSP encoder */
347bool configure_sbc_enc_format(audio_sbc_encoder_config *sbc_bt_cfg)
348{
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530349 struct mixer_ctl *ctl_enc_data = NULL, *ctrl_bit_format = NULL;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530350 struct sbc_enc_cfg_t sbc_dsp_cfg;
351 bool is_configured = false;
352 int ret = 0;
353
354 if(sbc_bt_cfg == NULL)
355 return false;
356
357 ctl_enc_data = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_ENC_CONFIG_BLOCK);
358 if (!ctl_enc_data) {
359 ALOGE(" ERROR a2dp encoder CONFIG data mixer control not identifed");
360 is_configured = false;
361 goto fail;
362 }
363 a2dp.bt_encoder_format = AUDIO_FORMAT_SBC;
364 memset(&sbc_dsp_cfg, 0x0, sizeof(struct sbc_enc_cfg_t));
365 sbc_dsp_cfg.enc_format = ENC_MEDIA_FMT_SBC;
366 sbc_dsp_cfg.num_subbands = sbc_bt_cfg->subband;
367 sbc_dsp_cfg.blk_len = sbc_bt_cfg->blk_len;
368 switch(sbc_bt_cfg->channels) {
369 case 0:
370 sbc_dsp_cfg.channel_mode = MEDIA_FMT_SBC_CHANNEL_MODE_MONO;
371 break;
372 case 1:
373 sbc_dsp_cfg.channel_mode = MEDIA_FMT_SBC_CHANNEL_MODE_DUAL_MONO;
374 break;
375 case 3:
376 sbc_dsp_cfg.channel_mode = MEDIA_FMT_SBC_CHANNEL_MODE_JOINT_STEREO;
377 break;
378 case 2:
379 default:
380 sbc_dsp_cfg.channel_mode = MEDIA_FMT_SBC_CHANNEL_MODE_STEREO;
381 break;
382 }
383 if (sbc_bt_cfg->alloc)
384 sbc_dsp_cfg.alloc_method = MEDIA_FMT_SBC_ALLOCATION_METHOD_LOUDNESS;
385 else
386 sbc_dsp_cfg.alloc_method = MEDIA_FMT_SBC_ALLOCATION_METHOD_SNR;
387 sbc_dsp_cfg.bit_rate = sbc_bt_cfg->bitrate;
388 sbc_dsp_cfg.sample_rate = sbc_bt_cfg->sampling_rate;
389 ret = mixer_ctl_set_array(ctl_enc_data, (void *)&sbc_dsp_cfg,
390 sizeof(struct sbc_enc_cfg_t));
391 if (ret != 0) {
392 ALOGE("%s: failed to set SBC encoder config", __func__);
393 is_configured = false;
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530394 goto fail;
395 }
396 ctrl_bit_format = mixer_get_ctl_by_name(a2dp.adev->mixer,
397 MIXER_ENC_BIT_FORMAT);
398 if (!ctrl_bit_format) {
399 ALOGE(" ERROR bit format CONFIG data mixer control not identifed");
400 is_configured = false;
401 goto fail;
402 }
403 ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S16_LE");
404 if (ret != 0) {
405 ALOGE("%s: Failed to set bit format to encoder", __func__);
406 is_configured = false;
407 goto fail;
408 }
409 is_configured = true;
410 a2dp.enc_sampling_rate = sbc_bt_cfg->sampling_rate;
411 ALOGV("Successfully updated SBC enc format with samplingrate: %d channelmode:%d",
412 sbc_dsp_cfg.sample_rate, sbc_dsp_cfg.channel_mode);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530413fail:
414 return is_configured;
415}
416
417/* API to configure APTX DSP encoder */
418bool configure_aptx_enc_format(audio_aptx_encoder_config *aptx_bt_cfg)
419{
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530420 struct mixer_ctl *ctl_enc_data = NULL, *ctrl_bit_format = NULL;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530421 struct custom_enc_cfg_aptx_t aptx_dsp_cfg;
422 bool is_configured = false;
423 int ret = 0;
424
425 if(aptx_bt_cfg == NULL)
426 return false;
427
428 ctl_enc_data = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_ENC_CONFIG_BLOCK);
429 if (!ctl_enc_data) {
430 ALOGE(" ERROR a2dp encoder CONFIG data mixer control not identifed");
431 is_configured = false;
432 goto fail;
433 }
434 a2dp.bt_encoder_format = AUDIO_FORMAT_APTX;
435 memset(&aptx_dsp_cfg, 0x0, sizeof(struct custom_enc_cfg_aptx_t));
436 aptx_dsp_cfg.enc_format = ENC_MEDIA_FMT_APTX;
437 aptx_dsp_cfg.sample_rate = aptx_bt_cfg->sampling_rate;
438 aptx_dsp_cfg.num_channels = aptx_bt_cfg->channels;
439 switch(aptx_dsp_cfg.num_channels) {
440 case 1:
441 aptx_dsp_cfg.channel_mapping[0] = PCM_CHANNEL_C;
442 break;
443 case 2:
444 default:
445 aptx_dsp_cfg.channel_mapping[0] = PCM_CHANNEL_L;
446 aptx_dsp_cfg.channel_mapping[1] = PCM_CHANNEL_R;
447 break;
448 }
449 ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_dsp_cfg,
450 sizeof(struct custom_enc_cfg_aptx_t));
451 if (ret != 0) {
452 ALOGE("%s: Failed to set APTX encoder config", __func__);
453 is_configured = false;
454 goto fail;
455 }
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530456 ctrl_bit_format = mixer_get_ctl_by_name(a2dp.adev->mixer,
457 MIXER_ENC_BIT_FORMAT);
458 if (!ctrl_bit_format) {
459 ALOGE("ERROR bit format CONFIG data mixer control not identifed");
460 is_configured = false;
461 goto fail;
462 } else {
463 ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S16_LE");
464 if (ret != 0) {
465 ALOGE("%s: Failed to set bit format to encoder", __func__);
466 is_configured = false;
467 goto fail;
468 }
469 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530470 is_configured = true;
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530471 a2dp.enc_sampling_rate = aptx_bt_cfg->sampling_rate;
472 ALOGV("Successfully updated APTX enc format with samplingrate: %d channels:%d",
473 aptx_dsp_cfg.sample_rate, aptx_dsp_cfg.num_channels);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530474fail:
475 return is_configured;
476}
477
478/* API to configure APTX HD DSP encoder
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530479 */
480bool configure_aptx_hd_enc_format(audio_aptx_encoder_config *aptx_bt_cfg)
481{
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530482 struct mixer_ctl *ctl_enc_data = NULL, *ctrl_bit_format = NULL;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530483 struct custom_enc_cfg_aptx_t aptx_dsp_cfg;
484 bool is_configured = false;
485 int ret = 0;
486
487 if(aptx_bt_cfg == NULL)
488 return false;
489
490 ctl_enc_data = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_ENC_CONFIG_BLOCK);
491 if (!ctl_enc_data) {
492 ALOGE(" ERROR a2dp encoder CONFIG data mixer control not identifed");
493 is_configured = false;
494 goto fail;
495 }
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530496
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530497 a2dp.bt_encoder_format = AUDIO_FORMAT_APTX_HD;
498 memset(&aptx_dsp_cfg, 0x0, sizeof(struct custom_enc_cfg_aptx_t));
499 aptx_dsp_cfg.enc_format = ENC_MEDIA_FMT_APTX_HD;
500 aptx_dsp_cfg.sample_rate = aptx_bt_cfg->sampling_rate;
501 aptx_dsp_cfg.num_channels = aptx_bt_cfg->channels;
502 switch(aptx_dsp_cfg.num_channels) {
503 case 1:
504 aptx_dsp_cfg.channel_mapping[0] = PCM_CHANNEL_C;
505 break;
506 case 2:
507 default:
508 aptx_dsp_cfg.channel_mapping[0] = PCM_CHANNEL_L;
509 aptx_dsp_cfg.channel_mapping[1] = PCM_CHANNEL_R;
510 break;
511 }
512 ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_dsp_cfg,
513 sizeof(struct custom_enc_cfg_aptx_t));
514 if (ret != 0) {
515 ALOGE("%s: Failed to set APTX HD encoder config", __func__);
516 is_configured = false;
517 goto fail;
518 }
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530519 ctrl_bit_format = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_ENC_BIT_FORMAT);
520 if (!ctrl_bit_format) {
521 ALOGE(" ERROR bit format CONFIG data mixer control not identifed");
522 is_configured = false;
523 goto fail;
524 }
525 ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S24_LE");
526 if (ret != 0) {
527 ALOGE("%s: Failed to set APTX HD encoder config", __func__);
528 is_configured = false;
529 goto fail;
530 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530531 is_configured = true;
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530532 a2dp.enc_sampling_rate = aptx_bt_cfg->sampling_rate;
533 ALOGV("Successfully updated APTX HD encformat with samplingrate: %d channels:%d",
534 aptx_dsp_cfg.sample_rate, aptx_dsp_cfg.num_channels);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530535fail:
536 return is_configured;
537}
538
539/* API to configure AAC DSP encoder */
540bool configure_aac_enc_format(audio_aac_encoder_config *aac_bt_cfg)
541{
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530542 struct mixer_ctl *ctl_enc_data = NULL, *ctrl_bit_format = NULL;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530543 struct aac_enc_cfg_t aac_dsp_cfg;
544 bool is_configured = false;
545 int ret = 0;
546
547 if(aac_bt_cfg == NULL)
548 return false;
549
550 ctl_enc_data = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_ENC_CONFIG_BLOCK);
551 if (!ctl_enc_data) {
552 ALOGE(" ERROR a2dp encoder CONFIG data mixer control not identifed");
553 is_configured = false;
554 goto fail;
555 }
556 a2dp.bt_encoder_format = AUDIO_FORMAT_AAC;
557 memset(&aac_dsp_cfg, 0x0, sizeof(struct aac_enc_cfg_t));
558 aac_dsp_cfg.enc_format = ENC_MEDIA_FMT_AAC;
559 aac_dsp_cfg.bit_rate = aac_bt_cfg->bitrate;
Naresh Tannirua42d0bd2016-09-21 15:30:46 +0530560 aac_dsp_cfg.sample_rate = aac_bt_cfg->sampling_rate;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530561 switch(aac_bt_cfg->enc_mode) {
562 case 0:
563 aac_dsp_cfg.enc_mode = MEDIA_FMT_AAC_AOT_LC;
564 break;
565 case 2:
566 aac_dsp_cfg.enc_mode = MEDIA_FMT_AAC_AOT_PS;
567 break;
568 case 1:
569 default:
570 aac_dsp_cfg.enc_mode = MEDIA_FMT_AAC_AOT_SBR;
571 break;
572 }
Naresh Tannirua42d0bd2016-09-21 15:30:46 +0530573 aac_dsp_cfg.aac_fmt_flag = aac_bt_cfg->format_flag;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530574 aac_dsp_cfg.channel_cfg = aac_bt_cfg->channels;
575 ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aac_dsp_cfg,
576 sizeof(struct aac_enc_cfg_t));
577 if (ret != 0) {
578 ALOGE("%s: failed to set SBC encoder config", __func__);
579 is_configured = false;
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530580 goto fail;
581 }
582 ctrl_bit_format = mixer_get_ctl_by_name(a2dp.adev->mixer,
583 MIXER_ENC_BIT_FORMAT);
584 if (!ctrl_bit_format) {
585 is_configured = false;
586 ALOGE(" ERROR bit format CONFIG data mixer control not identifed");
587 goto fail;
588 }
589 ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S16_LE");
590 if (ret != 0) {
591 ALOGE("%s: Failed to set bit format to encoder", __func__);
592 is_configured = false;
593 goto fail;
594 }
595 is_configured = true;
596 a2dp.enc_sampling_rate = aac_bt_cfg->sampling_rate;
597 ALOGV("Successfully updated AAC enc format with samplingrate: %d channels:%d",
598 aac_dsp_cfg.sample_rate, aac_dsp_cfg.channel_cfg);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530599fail:
600 return is_configured;
601}
602
603bool configure_a2dp_encoder_format()
604{
605 void *codec_info = NULL;
606 uint8_t multi_cast = 0, num_dev = 1;
607 audio_format_t codec_type = AUDIO_FORMAT_INVALID;
608 bool is_configured = false;
609
610 if (!a2dp.audio_get_codec_config) {
611 ALOGE(" a2dp handle is not identified, ignoring a2dp encoder config");
612 return false;
613 }
614 ALOGD("configure_a2dp_encoder_format start");
615 codec_info = a2dp.audio_get_codec_config(&multi_cast, &num_dev,
616 &codec_type);
617
618 switch(codec_type) {
619 case AUDIO_FORMAT_SBC:
620 ALOGD(" Received SBC encoder supported BT device");
621 is_configured =
622 configure_sbc_enc_format((audio_sbc_encoder_config *)codec_info);
623 break;
624 case AUDIO_FORMAT_APTX:
625 ALOGD(" Received APTX encoder supported BT device");
626 is_configured =
627 configure_aptx_enc_format((audio_aptx_encoder_config *)codec_info);
628 break;
629 case AUDIO_FORMAT_APTX_HD:
630 ALOGD(" Received APTX HD encoder supported BT device");
631 is_configured =
632 configure_aptx_hd_enc_format((audio_aptx_encoder_config *)codec_info);
633 break;
634 case AUDIO_FORMAT_AAC:
635 ALOGD(" Received AAC encoder supported BT device");
636 is_configured =
637 configure_aac_enc_format((audio_aac_encoder_config *)codec_info);
638 break;
639 default:
640 ALOGD(" Received Unsupported encoder formar");
641 is_configured = false;
642 break;
643 }
644 return is_configured;
645}
646
647int audio_extn_a2dp_start_playback()
648{
649 int ret = 0;
650
651 ALOGD("audio_extn_a2dp_start_playback start");
652
653 if(!(a2dp.bt_lib_handle && a2dp.audio_start_stream
654 && a2dp.audio_get_codec_config)) {
655 ALOGE("a2dp handle is not identified, Ignoring start request");
656 return -ENOSYS;
657 }
658
659 if(a2dp.a2dp_suspended == true) {
660 //session will be restarted after suspend completion
661 ALOGD("a2dp start requested during suspend state");
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530662 return -ENOSYS;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530663 }
664
665 if (!a2dp.a2dp_started && !a2dp.a2dp_total_active_session_request) {
666 ALOGD("calling BT module stream start");
667 /* This call indicates BT IPC lib to start playback */
668 ret = a2dp.audio_start_stream();
669 ALOGE("BT controller start return = %d",ret);
670 if (ret != 0 ) {
671 ALOGE("BT controller start failed");
672 a2dp.a2dp_started = false;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530673 } else {
674 if(configure_a2dp_encoder_format() == true) {
675 a2dp.a2dp_started = true;
676 ret = 0;
677 ALOGD("Start playback successful to BT library");
678 } else {
679 ALOGD(" unable to configure DSP encoder");
680 a2dp.a2dp_started = false;
681 ret = -ETIMEDOUT;
682 }
683 }
684 }
685
686 if (a2dp.a2dp_started)
687 a2dp.a2dp_total_active_session_request++;
688
689 ALOGD("start A2DP playback total active sessions :%d",
690 a2dp.a2dp_total_active_session_request);
691 return ret;
692}
693
Naresh Tanniru03f9dd52016-10-19 18:46:22 +0530694static void reset_a2dp_enc_config_params()
695{
696 int ret =0;
697
698 struct mixer_ctl *ctl_enc_config, *ctrl_bit_format;
699 struct sbc_enc_cfg_t dummy_reset_config;
700
701 memset(&dummy_reset_config, 0x0, sizeof(struct sbc_enc_cfg_t));
702 ctl_enc_config = mixer_get_ctl_by_name(a2dp.adev->mixer,
703 MIXER_ENC_CONFIG_BLOCK);
704 if (!ctl_enc_config) {
705 ALOGE(" ERROR a2dp encoder format mixer control not identifed");
706 } else {
707 ret = mixer_ctl_set_array(ctl_enc_config, (void *)&dummy_reset_config,
708 sizeof(struct sbc_enc_cfg_t));
709 a2dp.bt_encoder_format = ENC_MEDIA_FMT_NONE;
710 }
711 ctrl_bit_format = mixer_get_ctl_by_name(a2dp.adev->mixer,
712 MIXER_ENC_BIT_FORMAT);
713 if (!ctrl_bit_format) {
714 ALOGE(" ERROR bit format CONFIG data mixer control not identifed");
715 } else {
716 ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S16_LE");
717 if (ret != 0) {
718 ALOGE("%s: Failed to set bit format to encoder", __func__);
719 }
720 }
721}
722
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530723int audio_extn_a2dp_stop_playback()
724{
725 int ret =0;
726
727 ALOGV("audio_extn_a2dp_stop_playback start");
728 if(!(a2dp.bt_lib_handle && a2dp.audio_stop_stream)) {
729 ALOGE("a2dp handle is not identified, Ignoring start request");
730 return -ENOSYS;
731 }
732
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +0530733 if (a2dp.a2dp_total_active_session_request > 0)
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530734 a2dp.a2dp_total_active_session_request--;
735
736 if ( a2dp.a2dp_started && !a2dp.a2dp_total_active_session_request) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530737 ALOGV("calling BT module stream stop");
738 ret = a2dp.audio_stop_stream();
739 if (ret < 0)
740 ALOGE("stop stream to BT IPC lib failed");
741 else
742 ALOGV("stop steam to BT IPC lib successful");
Naresh Tanniru03f9dd52016-10-19 18:46:22 +0530743 reset_a2dp_enc_config_params();
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530744 }
745 if(!a2dp.a2dp_total_active_session_request)
746 a2dp.a2dp_started = false;
747 ALOGD("Stop A2DP playback total active sessions :%d",
748 a2dp.a2dp_total_active_session_request);
749 return 0;
750}
751
752void audio_extn_a2dp_set_parameters(struct str_parms *parms)
753{
754 int ret, val;
755 char value[32]={0};
756
757 if(a2dp.is_a2dp_offload_supported == false) {
758 ALOGV("no supported encoders identified,ignoring a2dp setparam");
759 return;
760 }
761
762 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value,
763 sizeof(value));
764 if( ret >= 0) {
765 val = atoi(value);
766 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
767 ALOGV("Received device connect request for A2DP");
768 open_a2dp_output();
769 }
770 goto param_handled;
771 }
772
773 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value,
774 sizeof(value));
775
776 if( ret >= 0) {
777 val = atoi(value);
778 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
779 ALOGV("Received device dis- connect request");
Naresh Tanniru03f9dd52016-10-19 18:46:22 +0530780 reset_a2dp_enc_config_params();
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530781 close_a2dp_output();
782 }
783 goto param_handled;
784 }
785
786 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
787 if (ret >= 0) {
788 if (a2dp.bt_lib_handle && (a2dp.bt_state != A2DP_STATE_DISCONNECTED) ) {
789 if ((!strncmp(value,"true",sizeof(value)))) {
790 ALOGD("Setting a2dp to suspend state");
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530791 a2dp.a2dp_suspended = true;
Naresh Tanniru03f9dd52016-10-19 18:46:22 +0530792 reset_a2dp_enc_config_params();
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530793 if(a2dp.audio_suspend_stream)
794 a2dp.audio_suspend_stream();
795 } else if (a2dp.a2dp_suspended == true) {
796 ALOGD("Resetting a2dp suspend state");
797 if(a2dp.clear_a2dpsuspend_flag)
798 a2dp.clear_a2dpsuspend_flag();
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530799 a2dp.a2dp_suspended = false;
Naresh Tanniru649871a2016-11-04 18:08:32 +0530800 /*
801 * It is possible that before suspend,a2dp sessions can be active
802 * for example during music + voice activation concurrency
803 * a2dp suspend will be called & BT will change to sco mode
804 * though music is paused as a part of voice activation
805 * compress session close happens only after pause timeout(10secs)
806 * so if resume request comes before pause timeout as a2dp session
807 * is already active IPC start will not be called from APM/audio_hw
808 * Fix is to call a2dp start for IPC library post suspend
809 * based on number of active session count
810 */
811 if (a2dp.a2dp_total_active_session_request > 0) {
812 ALOGD(" Calling IPC lib start post suspend state");
813 if(a2dp.audio_start_stream) {
814 ret = a2dp.audio_start_stream();
815 if (ret != 0) {
816 ALOGE("BT controller start failed");
817 a2dp.a2dp_started = false;
818 }
819 }
820 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530821 }
822 }
823 goto param_handled;
824 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530825param_handled:
826 ALOGV("end of a2dp setparam");
827}
828
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530829void audio_extn_a2dp_set_handoff_mode(bool is_on)
830{
831 a2dp.is_handoff_in_progress = is_on;
832}
833
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530834bool audio_extn_a2dp_is_force_device_switch()
835{
836 //During encoder reconfiguration mode, force a2dp device switch
Ashish Jainc597d102016-12-12 10:31:34 +0530837 // Or if a2dp device is selected but earlier start failed ( as a2dp
838 // was suspended, force retry.
839 return a2dp.is_handoff_in_progress || !a2dp.a2dp_started;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530840}
841
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530842void audio_extn_a2dp_get_apptype_params(uint32_t *sample_rate,
843 uint32_t *bit_width)
844{
845 if(a2dp.bt_encoder_format == AUDIO_FORMAT_APTX_HD)
846 *bit_width = 24;
847 else
848 *bit_width = 16;
849 *sample_rate = a2dp.enc_sampling_rate;
850}
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +0530851
852bool audio_extn_a2dp_is_ready()
853{
854 bool ret = false;
855
Aniket Kumar Lata901bcb82017-03-10 15:42:46 -0800856 if ((a2dp.bt_state != A2DP_STATE_DISCONNECTED) &&
857 (a2dp.is_a2dp_offload_supported) &&
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +0530858 (a2dp.audio_check_a2dp_ready))
859 ret = a2dp.audio_check_a2dp_ready();
860 return ret;
861}
862
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530863void audio_extn_a2dp_init (void *adev)
864{
865 a2dp.adev = (struct audio_device*)adev;
866 a2dp.bt_lib_handle = NULL;
867 a2dp.a2dp_started = false;
868 a2dp.bt_state = A2DP_STATE_DISCONNECTED;
869 a2dp.a2dp_total_active_session_request = 0;
870 a2dp.a2dp_suspended = false;
871 a2dp.bt_encoder_format = AUDIO_FORMAT_INVALID;
Naresh Tanniruf5ba8d02016-09-29 18:06:37 +0530872 a2dp.enc_sampling_rate = 48000;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530873 a2dp.is_a2dp_offload_supported = false;
874 a2dp.is_handoff_in_progress = false;
875 update_offload_codec_capabilities();
876}
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -0800877
878uint32_t audio_extn_a2dp_get_encoder_latency()
879{
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -0800880 uint32_t latency = 0;
881 int avsync_runtime_prop = 0;
882 int sbc_offset = 0, aptx_offset = 0, aptxhd_offset = 0, aac_offset = 0;
883 char value[PROPERTY_VALUE_MAX];
884
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -0800885 memset(value, '\0', sizeof(char)*PROPERTY_VALUE_MAX);
886 avsync_runtime_prop = property_get("audio.a2dp.codec.latency", value, NULL);
887 if (avsync_runtime_prop > 0) {
888 if (sscanf(value, "%d/%d/%d/%d",
889 &sbc_offset, &aptx_offset, &aptxhd_offset, &aac_offset) != 4) {
890 ALOGI("Failed to parse avsync offset params from '%s'.", value);
891 avsync_runtime_prop = 0;
892 }
893 }
894
Aniket Kumar Latafaaffde2017-03-22 19:18:15 -0700895 switch(a2dp.bt_encoder_format) {
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -0800896 case AUDIO_FORMAT_SBC:
897 latency = (avsync_runtime_prop > 0) ? sbc_offset : 150;
898 break;
899 case AUDIO_FORMAT_APTX:
900 latency = (avsync_runtime_prop > 0) ? aptx_offset : 200;
901 break;
902 case AUDIO_FORMAT_APTX_HD:
903 latency = (avsync_runtime_prop > 0) ? aptxhd_offset : 200;
904 break;
905 case AUDIO_FORMAT_AAC:
906 latency = (avsync_runtime_prop > 0) ? aac_offset : 250;
907 break;
908 default:
909 latency = 200;
910 break;
911 }
912 return latency;
913}
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530914#endif // SPLIT_A2DP_ENABLED