hal: Add support for scrambler and backend configuration
-Check for scrambler support with BT IPC lib and
enable scrambler.
-Add support to configure backend with multiple sampling rates
and different channels over a2dp path.
Change-Id: I2324d4867f8f8a498768a41f4db04e138cc26e21
diff --git a/hal/audio_extn/a2dp.c b/hal/audio_extn/a2dp.c
index 2c0c53b..803cf4a 100644
--- a/hal/audio_extn/a2dp.c
+++ b/hal/audio_extn/a2dp.c
@@ -70,6 +70,9 @@
#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_SCRAMBLER_MODE "AFE Scrambler Mode"
+#define MIXER_SAMPLE_RATE "BT SampleRate"
+#define MIXER_AFE_IN_CHANNELS "AFE Input Channels"
#define MIXER_ENC_FMT_SBC "SBC"
#define MIXER_ENC_FMT_AAC "AAC"
#define MIXER_ENC_FMT_APTX "APTX"
@@ -115,6 +118,7 @@
enc_codec_t *codec_type);
typedef int (*audio_check_a2dp_ready_t)(void);
typedef uint16_t (*audio_get_a2dp_sink_latency_t)(void);
+typedef int (*audio_is_scrambling_enabled_t)(void);
enum A2DP_STATE {
A2DP_STATE_CONNECTED,
@@ -140,9 +144,11 @@
audio_get_codec_config_t audio_get_codec_config;
audio_check_a2dp_ready_t audio_check_a2dp_ready;
audio_get_a2dp_sink_latency_t audio_get_a2dp_sink_latency;
+ audio_is_scrambling_enabled_t audio_is_scrambling_enabled;
enum A2DP_STATE bt_state;
enc_codec_t bt_encoder_format;
uint32_t enc_sampling_rate;
+ uint32_t enc_channels;
bool a2dp_started;
bool a2dp_suspended;
int a2dp_total_active_session_request;
@@ -399,6 +405,8 @@
dlsym(a2dp.bt_lib_handle,"audio_check_a2dp_ready");
a2dp.audio_get_a2dp_sink_latency = (audio_get_a2dp_sink_latency_t)
dlsym(a2dp.bt_lib_handle,"audio_get_a2dp_sink_latency");
+ a2dp.audio_is_scrambling_enabled = (audio_is_scrambling_enabled_t)
+ dlsym(a2dp.bt_lib_handle,"audio_is_scrambling_enabled");
}
}
@@ -444,11 +452,130 @@
a2dp.a2dp_suspended = false;
a2dp.bt_encoder_format = ENC_CODEC_TYPE_INVALID;
a2dp.enc_sampling_rate = 48000;
+ a2dp.enc_channels = 2;
a2dp.bt_state = A2DP_STATE_DISCONNECTED;
return 0;
}
+static void a2dp_check_and_set_scrambler()
+{
+ bool scrambler_mode = false;
+ struct mixer_ctl *ctrl_scrambler_mode = NULL;
+ if (a2dp.audio_is_scrambling_enabled && (a2dp.bt_state != A2DP_STATE_DISCONNECTED))
+ scrambler_mode = a2dp.audio_is_scrambling_enabled();
+
+ if (scrambler_mode) {
+ //enable scrambler in dsp
+ ctrl_scrambler_mode = mixer_get_ctl_by_name(a2dp.adev->mixer,
+ MIXER_SCRAMBLER_MODE);
+ if (!ctrl_scrambler_mode) {
+ ALOGE(" ERROR scrambler mode mixer control not identifed");
+ return;
+ } else {
+ if (mixer_ctl_set_value(ctrl_scrambler_mode, 0, true) != 0) {
+ ALOGE("%s: Could not set scrambler mode", __func__);
+ return;
+ }
+ }
+ }
+}
+
+static void a2dp_set_backend_cfg()
+{
+ char *rate_str = NULL, *in_channels = NULL;
+ struct mixer_ctl *ctl_sample_rate = NULL, *ctrl_in_channels = NULL;
+ //Configure backend sampling rate
+ switch (a2dp.enc_sampling_rate) {
+ case 44100:
+ rate_str = "KHZ_44P1";
+ break;
+ case 48000:
+ rate_str = "KHZ_48";
+ break;
+ case 88200:
+ rate_str = "KHZ_88P2";
+ break;
+ case 96000:
+ rate_str = "KHZ_96";
+ break;
+ default:
+ rate_str = "KHZ_48";
+ break;
+ }
+
+ ALOGD("%s: set backend sample rate =%s", __func__, rate_str);
+ ctl_sample_rate = mixer_get_ctl_by_name(a2dp.adev->mixer,
+ MIXER_SAMPLE_RATE);
+ if (!ctl_sample_rate) {
+ ALOGE(" ERROR backend sample rate mixer control not identifed");
+ return;
+ } else {
+ if (mixer_ctl_set_enum_by_string(ctl_sample_rate, rate_str) != 0) {
+ ALOGE("%s: Failed to set backend sample rate =%s", __func__, rate_str);
+ return;
+ }
+ }
+
+ //Configure AFE input channels
+ switch (a2dp.enc_channels) {
+ case 1:
+ in_channels = "One";
+ break;
+ case 2:
+ default:
+ in_channels = "Two";
+ break;
+ }
+
+ ALOGD("%s: set afe input channels =%d", __func__, a2dp.enc_channels);
+ ctrl_in_channels = mixer_get_ctl_by_name(a2dp.adev->mixer,
+ MIXER_AFE_IN_CHANNELS);
+ if (!ctrl_in_channels) {
+ ALOGE(" ERROR AFE input channels mixer control not identifed");
+ return;
+ } else {
+ if (mixer_ctl_set_enum_by_string(ctrl_in_channels, in_channels) != 0) {
+ ALOGE("%s: Failed to set AFE in channels =%d", __func__, a2dp.enc_channels);
+ return;
+ }
+ }
+}
+
+static void a2dp_reset_backend_cfg()
+{
+ char *rate_str = "KHZ_8", *in_channels = "Zero";
+ struct mixer_ctl *ctl_sample_rate = NULL, *ctrl_in_channels = NULL;
+
+ //reset backend sampling rate
+ ALOGD("%s: reset backend sample rate =%s", __func__, rate_str);
+ ctl_sample_rate = mixer_get_ctl_by_name(a2dp.adev->mixer,
+ MIXER_SAMPLE_RATE);
+ if (!ctl_sample_rate) {
+ ALOGE(" ERROR backend sample rate mixer control not identifed");
+ return;
+ } else {
+ if (mixer_ctl_set_enum_by_string(ctl_sample_rate, rate_str) != 0) {
+ ALOGE("%s: Failed to reset backend sample rate =%s", __func__, rate_str);
+ return;
+ }
+ }
+
+ //reset AFE input channels
+ ALOGD("%s: reset afe input channels =%s", __func__, in_channels);
+ ctrl_in_channels = mixer_get_ctl_by_name(a2dp.adev->mixer,
+ MIXER_AFE_IN_CHANNELS);
+ if (!ctrl_in_channels) {
+ ALOGE(" ERROR AFE input channels mixer control not identifed");
+ return;
+ } else {
+ if (mixer_ctl_set_enum_by_string(ctrl_in_channels, in_channels) != 0) {
+ ALOGE("%s: Failed to reset AFE in channels =%d", __func__, a2dp.enc_channels);
+ return;
+ }
+ }
+}
+
/* API to configure SBC DSP encoder */
bool configure_sbc_enc_format(audio_sbc_encoder_config *sbc_bt_cfg)
{
@@ -514,6 +641,12 @@
is_configured = true;
a2dp.bt_encoder_format = ENC_CODEC_TYPE_SBC;
a2dp.enc_sampling_rate = sbc_bt_cfg->sampling_rate;
+
+ if (sbc_dsp_cfg.channel_mode == MEDIA_FMT_SBC_CHANNEL_MODE_MONO)
+ a2dp.enc_channels = 1;
+ else
+ a2dp.enc_channels = 2;
+
ALOGV("Successfully updated SBC enc format with samplingrate: %d channelmode:%d",
sbc_dsp_cfg.sample_rate, sbc_dsp_cfg.channel_mode);
fail:
@@ -583,6 +716,7 @@
}
is_configured = true;
a2dp.bt_encoder_format = ENC_CODEC_TYPE_APTX;
+ a2dp.enc_channels = aptx_dsp_cfg.custom_cfg.num_channels;
if (!a2dp.is_aptx_dual_mono_supported) {
a2dp.enc_sampling_rate = aptx_bt_cfg->default_cfg->sampling_rate;
ALOGV("Successfully updated APTX enc format with samplingrate: %d \
@@ -655,6 +789,7 @@
is_configured = true;
a2dp.bt_encoder_format = ENC_CODEC_TYPE_APTX_HD;
a2dp.enc_sampling_rate = aptx_bt_cfg->sampling_rate;
+ a2dp.enc_channels = aptx_bt_cfg->channels;
ALOGV("Successfully updated APTX HD encformat with samplingrate: %d channels:%d",
aptx_dsp_cfg.sample_rate, aptx_dsp_cfg.num_channels);
fail:
@@ -719,6 +854,7 @@
is_configured = true;
a2dp.bt_encoder_format = ENC_CODEC_TYPE_AAC;
a2dp.enc_sampling_rate = aac_bt_cfg->sampling_rate;
+ a2dp.enc_channels = aac_bt_cfg->channels;;
ALOGV("Successfully updated AAC enc format with samplingrate: %d channels:%d",
aac_dsp_cfg.sample_rate, aac_dsp_cfg.channel_cfg);
fail:
@@ -786,6 +922,7 @@
is_configured = true;
a2dp.bt_encoder_format = ENC_CODEC_TYPE_CELT;
a2dp.enc_sampling_rate = celt_bt_cfg->sampling_rate;
+ a2dp.enc_channels = celt_bt_cfg->channels;
ALOGV("Successfully updated CELT encformat with samplingrate: %d channels:%d",
celt_dsp_cfg.custom_cfg.sample_rate, celt_dsp_cfg.custom_cfg.num_channels);
fail:
@@ -889,8 +1026,11 @@
}
}
- if (a2dp.a2dp_started)
+ if (a2dp.a2dp_started) {
a2dp.a2dp_total_active_session_request++;
+ a2dp_check_and_set_scrambler();
+ a2dp_set_backend_cfg();
+ }
ALOGD("start A2DP playback total active sessions :%d",
a2dp.a2dp_total_active_session_request);
@@ -947,6 +1087,7 @@
else
ALOGV("stop steam to BT IPC lib successful");
reset_a2dp_enc_config_params();
+ a2dp_reset_backend_cfg();
}
if(!a2dp.a2dp_total_active_session_request)
a2dp.a2dp_started = false;