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) {