hal: Add support for aptxHD encoder for a2dp
- Add support to configure ADM with encoder
bit width and sampling rate for a2dp device
- Add support to configure AFE bit rate
based on a2dp encoder format
Change-Id: Ic89553a69fd4746c7b6731b0f38ae830f44c3914
diff --git a/hal/audio_extn/a2dp.c b/hal/audio_extn/a2dp.c
index ea1092a..e72cb76 100644
--- a/hal/audio_extn/a2dp.c
+++ b/hal/audio_extn/a2dp.c
@@ -62,6 +62,7 @@
#define MEDIA_FMT_SBC_ALLOCATION_METHOD_LOUDNESS 0
#define MEDIA_FMT_SBC_ALLOCATION_METHOD_SNR 1
#define MIXER_ENC_CONFIG_BLOCK "SLIM_7_RX Encoder Config"
+#define MIXER_ENC_BIT_FORMAT "AFE Input Bit Format"
#define MIXER_ENC_FMT_SBC "SBC"
#define MIXER_ENC_FMT_AAC "AAC"
#define MIXER_ENC_FMT_APTX "APTX"
@@ -103,7 +104,7 @@
audio_get_codec_config_t audio_get_codec_config;
enum A2DP_STATE bt_state;
audio_format_t bt_encoder_format;
- void *enc_config_data;
+ uint32_t enc_sampling_rate;
bool a2dp_started;
bool a2dp_suspended;
int a2dp_total_active_session_request;
@@ -280,7 +281,7 @@
a2dp.a2dp_total_active_session_request = 0;
a2dp.a2dp_suspended = false;
a2dp.bt_encoder_format = AUDIO_FORMAT_INVALID;
- a2dp.enc_config_data = NULL;
+ a2dp.enc_sampling_rate = 48000;
a2dp.bt_state = A2DP_STATE_DISCONNECTED;
} else {
ALOGD("close a2dp called in improper state");
@@ -288,7 +289,7 @@
a2dp.a2dp_total_active_session_request = 0;
a2dp.a2dp_suspended = false;
a2dp.bt_encoder_format = AUDIO_FORMAT_INVALID;
- a2dp.enc_config_data = NULL;
+ a2dp.enc_sampling_rate = 48000;
a2dp.bt_state = A2DP_STATE_DISCONNECTED;
}
@@ -298,7 +299,7 @@
/* API to configure SBC DSP encoder */
bool configure_sbc_enc_format(audio_sbc_encoder_config *sbc_bt_cfg)
{
- struct mixer_ctl *ctl_enc_data;
+ struct mixer_ctl *ctl_enc_data = NULL, *ctrl_bit_format = NULL;
struct sbc_enc_cfg_t sbc_dsp_cfg;
bool is_configured = false;
int ret = 0;
@@ -343,8 +344,25 @@
if (ret != 0) {
ALOGE("%s: failed to set SBC encoder config", __func__);
is_configured = false;
- } else
- is_configured = true;
+ goto fail;
+ }
+ ctrl_bit_format = mixer_get_ctl_by_name(a2dp.adev->mixer,
+ MIXER_ENC_BIT_FORMAT);
+ if (!ctrl_bit_format) {
+ ALOGE(" ERROR bit format CONFIG data mixer control not identifed");
+ is_configured = false;
+ goto fail;
+ }
+ ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S16_LE");
+ if (ret != 0) {
+ ALOGE("%s: Failed to set bit format to encoder", __func__);
+ is_configured = false;
+ goto fail;
+ }
+ is_configured = true;
+ a2dp.enc_sampling_rate = sbc_bt_cfg->sampling_rate;
+ ALOGV("Successfully updated SBC enc format with samplingrate: %d channelmode:%d",
+ sbc_dsp_cfg.sample_rate, sbc_dsp_cfg.channel_mode);
fail:
return is_configured;
}
@@ -352,7 +370,7 @@
/* API to configure APTX DSP encoder */
bool configure_aptx_enc_format(audio_aptx_encoder_config *aptx_bt_cfg)
{
- struct mixer_ctl *ctl_enc_data;
+ struct mixer_ctl *ctl_enc_data = NULL, *ctrl_bit_format = NULL;
struct custom_enc_cfg_aptx_t aptx_dsp_cfg;
bool is_configured = false;
int ret = 0;
@@ -388,17 +406,33 @@
is_configured = false;
goto fail;
}
+ ctrl_bit_format = mixer_get_ctl_by_name(a2dp.adev->mixer,
+ MIXER_ENC_BIT_FORMAT);
+ if (!ctrl_bit_format) {
+ ALOGE("ERROR bit format CONFIG data mixer control not identifed");
+ is_configured = false;
+ goto fail;
+ } else {
+ ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S16_LE");
+ if (ret != 0) {
+ ALOGE("%s: Failed to set bit format to encoder", __func__);
+ is_configured = false;
+ goto fail;
+ }
+ }
is_configured = true;
+ a2dp.enc_sampling_rate = aptx_bt_cfg->sampling_rate;
+ ALOGV("Successfully updated APTX enc format with samplingrate: %d channels:%d",
+ aptx_dsp_cfg.sample_rate, aptx_dsp_cfg.num_channels);
fail:
return is_configured;
}
/* API to configure APTX HD DSP encoder
- * TODO: ADD 24 bit configuration support
*/
bool configure_aptx_hd_enc_format(audio_aptx_encoder_config *aptx_bt_cfg)
{
- struct mixer_ctl *ctl_enc_data;
+ struct mixer_ctl *ctl_enc_data = NULL, *ctrl_bit_format = NULL;
struct custom_enc_cfg_aptx_t aptx_dsp_cfg;
bool is_configured = false;
int ret = 0;
@@ -412,6 +446,7 @@
is_configured = false;
goto fail;
}
+
a2dp.bt_encoder_format = AUDIO_FORMAT_APTX_HD;
memset(&aptx_dsp_cfg, 0x0, sizeof(struct custom_enc_cfg_aptx_t));
aptx_dsp_cfg.enc_format = ENC_MEDIA_FMT_APTX_HD;
@@ -434,7 +469,22 @@
is_configured = false;
goto fail;
}
+ ctrl_bit_format = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_ENC_BIT_FORMAT);
+ if (!ctrl_bit_format) {
+ ALOGE(" ERROR bit format CONFIG data mixer control not identifed");
+ is_configured = false;
+ goto fail;
+ }
+ ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S24_LE");
+ if (ret != 0) {
+ ALOGE("%s: Failed to set APTX HD encoder config", __func__);
+ is_configured = false;
+ goto fail;
+ }
is_configured = true;
+ a2dp.enc_sampling_rate = aptx_bt_cfg->sampling_rate;
+ ALOGV("Successfully updated APTX HD encformat with samplingrate: %d channels:%d",
+ aptx_dsp_cfg.sample_rate, aptx_dsp_cfg.num_channels);
fail:
return is_configured;
}
@@ -442,7 +492,7 @@
/* API to configure AAC DSP encoder */
bool configure_aac_enc_format(audio_aac_encoder_config *aac_bt_cfg)
{
- struct mixer_ctl *ctl_enc_data;
+ struct mixer_ctl *ctl_enc_data = NULL, *ctrl_bit_format = NULL;
struct aac_enc_cfg_t aac_dsp_cfg;
bool is_configured = false;
int ret = 0;
@@ -480,8 +530,25 @@
if (ret != 0) {
ALOGE("%s: failed to set SBC encoder config", __func__);
is_configured = false;
- } else
- is_configured = true;
+ goto fail;
+ }
+ ctrl_bit_format = mixer_get_ctl_by_name(a2dp.adev->mixer,
+ MIXER_ENC_BIT_FORMAT);
+ if (!ctrl_bit_format) {
+ is_configured = false;
+ ALOGE(" ERROR bit format CONFIG data mixer control not identifed");
+ goto fail;
+ }
+ ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S16_LE");
+ if (ret != 0) {
+ ALOGE("%s: Failed to set bit format to encoder", __func__);
+ is_configured = false;
+ goto fail;
+ }
+ is_configured = true;
+ a2dp.enc_sampling_rate = aac_bt_cfg->sampling_rate;
+ ALOGV("Successfully updated AAC enc format with samplingrate: %d channels:%d",
+ aac_dsp_cfg.sample_rate, aac_dsp_cfg.channel_cfg);
fail:
return is_configured;
}
@@ -592,7 +659,7 @@
a2dp.a2dp_total_active_session_request--;
if ( a2dp.a2dp_started && !a2dp.a2dp_total_active_session_request) {
- struct mixer_ctl *ctl_enc_config;
+ struct mixer_ctl *ctl_enc_config, *ctrl_bit_format;
struct sbc_enc_cfg_t dummy_reset_config;
ALOGV("calling BT module stream stop");
@@ -611,6 +678,16 @@
sizeof(struct sbc_enc_cfg_t));
a2dp.bt_encoder_format = ENC_MEDIA_FMT_NONE;
}
+ ctrl_bit_format = mixer_get_ctl_by_name(a2dp.adev->mixer,
+ MIXER_ENC_BIT_FORMAT);
+ if (!ctrl_bit_format) {
+ ALOGE(" ERROR bit format CONFIG data mixer control not identifed");
+ } else {
+ ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S16_LE");
+ if (ret != 0) {
+ ALOGE("%s: Failed to set bit format to encoder", __func__);
+ }
+ }
}
if(!a2dp.a2dp_total_active_session_request)
a2dp.a2dp_started = false;
@@ -684,6 +761,15 @@
return a2dp.is_handoff_in_progress;
}
+void audio_extn_a2dp_get_apptype_params(uint32_t *sample_rate,
+ uint32_t *bit_width)
+{
+ if(a2dp.bt_encoder_format == AUDIO_FORMAT_APTX_HD)
+ *bit_width = 24;
+ else
+ *bit_width = 16;
+ *sample_rate = a2dp.enc_sampling_rate;
+}
void audio_extn_a2dp_init (void *adev)
{
a2dp.adev = (struct audio_device*)adev;
@@ -693,7 +779,7 @@
a2dp.a2dp_total_active_session_request = 0;
a2dp.a2dp_suspended = false;
a2dp.bt_encoder_format = AUDIO_FORMAT_INVALID;
- a2dp.enc_config_data = NULL;
+ a2dp.enc_sampling_rate = 48000;
a2dp.is_a2dp_offload_supported = false;
a2dp.is_handoff_in_progress = false;
update_offload_codec_capabilities();
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index b57bb81..cd9763e 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -179,6 +179,8 @@
#define audio_extn_a2dp_set_parameters(parms) (0)
#define audio_extn_a2dp_is_force_device_switch() (0)
#define audio_extn_a2dp_set_handoff_mode(is_on) (0)
+#define audio_extn_a2dp_get_apptype_params(sample_rate,bit_width) (0)
+
#else
void audio_extn_a2dp_init(void *adev);
int audio_extn_a2dp_start_playback();
@@ -186,6 +188,9 @@
void audio_extn_a2dp_set_parameters(struct str_parms *parms);
bool audio_extn_a2dp_is_force_device_switch();
void audio_extn_a2dp_set_handoff_mode(bool is_on);
+void audio_extn_a2dp_get_apptype_params(uint32_t *sample_rate,
+ uint32_t *bit_width);
+
#endif
#ifndef SSR_ENABLED
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 26c43b4..18c55cf 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -529,6 +529,13 @@
sample_rate = OUTPUT_SAMPLING_RATE_DSD128;
}
+ if(devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
+ //TODO: Handle fractional sampling rate configuration for LL
+ audio_extn_a2dp_get_apptype_params(&sample_rate, &bit_width);
+ ALOGI("%s using %d sampling rate %d bit width for A2DP CoPP",
+ __func__, sample_rate, bit_width);
+ }
+
ALOGV("%s: flags: %x, format: %x sample_rate %d",
__func__, flags, format, sample_rate);
list_for_each(node_i, streams_output_cfg_list) {