hal: Initial bringup changes for aptx adaptive

Initial bringup changes for aptx adaptive
This profile is added as a part of
FR46465:A2DP Audio with aptX Adaptive

CRs-fixed: 2272312
Change-Id: Ie45196359b622223c2e53d70eb8c0daeb7aa94e5
diff --git a/hal/audio_extn/a2dp.c b/hal/audio_extn/a2dp.c
index d228123..0d0a48b 100644
--- a/hal/audio_extn/a2dp.c
+++ b/hal/audio_extn/a2dp.c
@@ -55,6 +55,7 @@
 #define ENC_MEDIA_FMT_AAC                                  0x00010DA6
 #define ENC_MEDIA_FMT_APTX                                 0x000131ff
 #define ENC_MEDIA_FMT_APTX_HD                              0x00013200
+#define ENC_MEDIA_FMT_APTX_AD                              0x00013204
 #define ENC_MEDIA_FMT_SBC                                  0x00010BF2
 #define ENC_MEDIA_FMT_CELT                                 0x00013221
 #define ENC_MEDIA_FMT_LDAC                                 0x00013224
@@ -112,6 +113,10 @@
 // Instance identifier for A2DP
 #define MAX_INSTANCE_ID                (UINT32_MAX / 2)
 
+#define SAMPLING_RATE_48K               48000
+#define SAMPLING_RATE_441K              44100
+#define CH_STEREO                       2
+#define CH_MONO                         1
 /*
  * Below enum values are extended from audio_base.h to
  * to keep encoder codec type local to bthost_ipc
@@ -129,8 +134,33 @@
 #endif
     ENC_CODEC_TYPE_LDAC = AUDIO_FORMAT_LDAC, // 0x23000000UL
     ENC_CODEC_TYPE_CELT = 603979776u, // 0x24000000UL
+    ENC_CODEC_TYPE_APTX_AD = 620756992u, // 0x25000000UL
 }enc_codec_t;
 
+/*
+ * enums which describes the APTX Adaptive
+ * channel mode, these values are used by encoder
+ */
+ typedef enum {
+    APTX_AD_CHANNEL_UNCHANGED = -1,
+    APTX_AD_CHANNEL_JOINT_STEREO = 0, // default
+    APTX_AD_CHANNEL_MONO = 1,
+    APTX_AD_CHANNEL_DUAL_MONO = 2,
+    APTX_AD_CHANNEL_STEREO_TWS = 4,
+    APTX_AD_CHANNEL_EARBUD = 8,
+} enc_aptx_ad_channel_mode;
+
+/*
+ * enums which describes the APTX Adaptive
+ * sampling frequency, these values are used
+ * by encoder
+ */
+typedef enum {
+    APTX_AD_SR_UNCHANGED = 0x0,
+    APTX_AD_48 = 0x1,  // 48 KHz default
+    APTX_AD_44_1 = 0x2, // 44.1kHz
+} enc_aptx_ad_s_rate;
+
 typedef int (*audio_stream_open_t)(void);
 typedef int (*audio_stream_close_t)(void);
 typedef int (*audio_start_stream_t)(void);
@@ -215,6 +245,7 @@
     bool is_a2dp_offload_supported;
     bool is_handoff_in_progress;
     bool is_aptx_dual_mono_supported;
+    bool is_aptx_adaptive;
     /* Adaptive bitrate config for A2DP codecs */
     struct a2dp_abr_config abr_config;
 };
@@ -373,6 +404,27 @@
     struct aptx_v2_enc_cfg_ext_t aptx_v2_cfg;
 } __attribute__ ((packed));
 
+/* APTX AD structure */
+struct aptx_ad_enc_cfg_ext_t
+{
+    uint32_t  sampling_freq;
+    uint32_t  mtu;
+    uint32_t  channel_mode;
+    uint32_t  min_sink_modeA;
+    uint32_t  max_sink_modeA;
+    uint32_t  min_sink_modeB;
+    uint32_t  max_sink_modeB;
+    uint32_t  min_sink_modeC;
+    uint32_t  max_sink_modeC;
+} __attribute__ ((packed));
+
+struct aptx_ad_enc_cfg_t
+{
+    struct custom_enc_cfg_t  custom_cfg;
+    struct aptx_ad_enc_cfg_ext_t aptx_ad_cfg;
+    struct abr_enc_cfg_t abr_cfg;
+} __attribute__ ((packed));
+
 struct ldac_specific_enc_cfg_t
 {
     uint32_t      bit_rate;
@@ -421,6 +473,22 @@
 } audio_aptx_default_config;
 
 typedef struct {
+    uint8_t  sampling_rate;
+    uint8_t  channel_mode;
+    uint16_t mtu;
+    uint8_t  min_sink_modeA;
+    uint8_t  max_sink_modeA;
+    uint8_t  min_sink_modeB;
+    uint8_t  max_sink_modeB;
+    uint8_t  min_sink_modeC;
+    uint8_t  max_sink_modeC;
+    uint8_t  TTP_modeA_low;
+    uint8_t  TTP_modeA_high;
+    uint8_t  TTP_modeB_low;
+    uint8_t  TTP_modeB_high;
+} audio_aptx_ad_config;
+
+typedef struct {
     uint16_t sampling_rate;
     uint8_t  channels;
     uint32_t bitrate;
@@ -430,6 +498,7 @@
 typedef union {
     audio_aptx_default_config *default_cfg;
     audio_aptx_dual_mono_config *dual_mono_cfg;
+    audio_aptx_ad_config *ad_cfg;
 } audio_aptx_encoder_config;
 
 /* Information about BT AAC encoder configuration
@@ -509,6 +578,9 @@
             ALOGD("%s: ldac offload supported\n",__func__);
             a2dp.is_a2dp_offload_supported = true;
             break;
+        } else if( strcmp(tok, "aptxadaptive") == 0) {
+            ALOGD("%s: aptx adaptive offload supported\n",__func__);
+            a2dp.is_a2dp_offload_supported = true;
         }
         tok = strtok_r(NULL, "-", &saveptr);
     };
@@ -1021,6 +1093,73 @@
 }
 
 #ifndef LINUX_ENABLED
+static int update_aptx_ad_dsp_config(struct aptx_ad_enc_cfg_t *aptx_dsp_cfg,
+                                     audio_aptx_encoder_config *aptx_bt_cfg)
+{
+    int ret = 0;
+
+    if(aptx_dsp_cfg == NULL || aptx_bt_cfg == NULL) {
+        ALOGE("Invalid param, aptx_dsp_cfg %p aptx_bt_cfg %p",
+              aptx_dsp_cfg, aptx_bt_cfg);
+        return -EINVAL;
+    }
+
+    memset(aptx_dsp_cfg, 0x0, sizeof(struct aptx_ad_enc_cfg_t));
+    aptx_dsp_cfg->custom_cfg.enc_format = ENC_MEDIA_FMT_APTX_AD;
+
+
+    aptx_dsp_cfg->aptx_ad_cfg.sampling_freq = aptx_bt_cfg->ad_cfg->sampling_rate;
+    aptx_dsp_cfg->aptx_ad_cfg.mtu = aptx_bt_cfg->ad_cfg->mtu;
+    aptx_dsp_cfg->aptx_ad_cfg.channel_mode = aptx_bt_cfg->ad_cfg->channel_mode;
+    aptx_dsp_cfg->aptx_ad_cfg.min_sink_modeA = aptx_bt_cfg->ad_cfg->min_sink_modeA;
+    aptx_dsp_cfg->aptx_ad_cfg.max_sink_modeA = aptx_bt_cfg->ad_cfg->max_sink_modeA;
+    aptx_dsp_cfg->aptx_ad_cfg.min_sink_modeB = aptx_bt_cfg->ad_cfg->min_sink_modeB;
+    aptx_dsp_cfg->aptx_ad_cfg.max_sink_modeB = aptx_bt_cfg->ad_cfg->max_sink_modeB;
+    aptx_dsp_cfg->aptx_ad_cfg.min_sink_modeC = aptx_bt_cfg->ad_cfg->min_sink_modeC;
+    aptx_dsp_cfg->aptx_ad_cfg.max_sink_modeC = aptx_bt_cfg->ad_cfg->max_sink_modeC;
+    aptx_dsp_cfg->abr_cfg.imc_info.direction = IMC_RECEIVE;
+    aptx_dsp_cfg->abr_cfg.imc_info.enable = IMC_ENABLE;
+    aptx_dsp_cfg->abr_cfg.imc_info.purpose = IMC_PURPOSE_ID_BT_INFO;
+    aptx_dsp_cfg->abr_cfg.imc_info.comm_instance = a2dp.abr_config.imc_instance;
+
+
+    switch(aptx_dsp_cfg->aptx_ad_cfg.channel_mode) {
+        case APTX_AD_CHANNEL_UNCHANGED:
+        case APTX_AD_CHANNEL_JOINT_STEREO:
+        case APTX_AD_CHANNEL_DUAL_MONO:
+        case APTX_AD_CHANNEL_STEREO_TWS:
+        case APTX_AD_CHANNEL_EARBUD:
+        default:
+             a2dp.enc_channels = CH_STEREO;
+             aptx_dsp_cfg->custom_cfg.num_channels = CH_STEREO;
+             aptx_dsp_cfg->custom_cfg.channel_mapping[0] = PCM_CHANNEL_L;
+             aptx_dsp_cfg->custom_cfg.channel_mapping[1] = PCM_CHANNEL_R;
+             break;
+        case APTX_AD_CHANNEL_MONO:
+             a2dp.enc_channels = CH_MONO;
+             aptx_dsp_cfg->custom_cfg.num_channels = CH_MONO;
+             aptx_dsp_cfg->custom_cfg.channel_mapping[0] = PCM_CHANNEL_C;
+            break;
+    }
+    switch(aptx_dsp_cfg->aptx_ad_cfg.sampling_freq) {
+        case APTX_AD_SR_UNCHANGED:
+        case APTX_AD_48:
+        default:
+            a2dp.enc_sampling_rate = SAMPLING_RATE_48K;
+            aptx_dsp_cfg->custom_cfg.sample_rate = SAMPLING_RATE_48K;
+            break;
+        case APTX_AD_44_1:
+            a2dp.enc_sampling_rate = SAMPLING_RATE_441K;
+            aptx_dsp_cfg->custom_cfg.sample_rate = SAMPLING_RATE_441K;
+        break;
+    }
+    ALOGV("Successfully updated APTX AD enc format with \
+               samplingrate: %d channels:%d",
+               aptx_dsp_cfg->custom_cfg.sample_rate,
+               aptx_dsp_cfg->custom_cfg.num_channels);
+
+    return ret;
+}
 static int update_aptx_dsp_config_v2(struct aptx_enc_cfg_t *aptx_dsp_cfg,
                                      audio_aptx_encoder_config *aptx_bt_cfg)
 {
@@ -1118,8 +1257,13 @@
 
 #ifndef LINUX_ENABLED
     struct aptx_enc_cfg_t aptx_dsp_cfg;
-    mixer_size = sizeof(struct aptx_enc_cfg_t);
-    sample_rate_backup = aptx_bt_cfg->default_cfg->sampling_rate;
+    struct aptx_ad_enc_cfg_t aptx_ad_dsp_cfg;
+    if(a2dp.is_aptx_adaptive)
+       mixer_size = sizeof(struct aptx_ad_enc_cfg_t);
+    else {
+        mixer_size = sizeof(struct aptx_enc_cfg_t);
+        sample_rate_backup = aptx_bt_cfg->default_cfg->sampling_rate;
+    }
 #else
     struct custom_enc_cfg_t aptx_dsp_cfg;
     mixer_size = sizeof(struct custom_enc_cfg_t);
@@ -1134,7 +1278,11 @@
     }
 
 #ifndef LINUX_ENABLED
-    ret = update_aptx_dsp_config_v2(&aptx_dsp_cfg, aptx_bt_cfg);
+    if(a2dp.is_aptx_adaptive) {
+        ret = update_aptx_ad_dsp_config(&aptx_ad_dsp_cfg, aptx_bt_cfg);
+        sample_rate_backup = aptx_ad_dsp_cfg.custom_cfg.sample_rate;
+    } else
+        ret = update_aptx_dsp_config_v2(&aptx_dsp_cfg, aptx_bt_cfg);
 #else
     ret = update_aptx_dsp_config_v1(&aptx_dsp_cfg, aptx_bt_cfg);
 #endif
@@ -1143,7 +1291,11 @@
         is_configured = false;
         goto fail;
     }
-    ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_dsp_cfg,
+    if(a2dp.is_aptx_adaptive)
+        ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_ad_dsp_cfg,
+                             mixer_size);
+    else
+        ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_dsp_cfg,
                               mixer_size);
     if (ret != 0) {
         ALOGE("%s: Failed to set APTX encoder config", __func__);
@@ -1157,7 +1309,10 @@
         is_configured = false;
         goto fail;
     } else {
-        ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S16_LE");
+        if (a2dp.is_aptx_adaptive)
+            ret = mixer_ctl_set_enum_by_string(ctrl_bit_format, "S24_LE");
+        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;
@@ -1165,7 +1320,10 @@
         }
     }
     is_configured = true;
-    a2dp.bt_encoder_format = ENC_CODEC_TYPE_APTX;
+    if (a2dp.is_aptx_adaptive)
+        a2dp.bt_encoder_format = ENC_CODEC_TYPE_APTX_AD;
+    else
+        a2dp.bt_encoder_format = ENC_CODEC_TYPE_APTX;
 fail:
     /*restore sample rate */
     if(!is_configured)
@@ -1465,6 +1623,7 @@
 
     // ABR disabled by default for all codecs
     a2dp.abr_config.is_abr_enabled = false;
+    a2dp.is_aptx_adaptive = false;
 
     switch(codec_type) {
         case ENC_CODEC_TYPE_SBC:
@@ -1519,6 +1678,18 @@
                 (configure_ldac_enc_format((audio_ldac_encoder_config *)codec_info) &&
                  configure_a2dp_decoder_format(ENC_CODEC_TYPE_LDAC));
             break;
+         case ENC_CODEC_TYPE_APTX_AD:
+             ALOGD(" Received APTX AD encoder supported BT device");
+             if (!instance_id || instance_id > MAX_INSTANCE_ID)
+                 instance_id = MAX_INSTANCE_ID;
+              a2dp.abr_config.imc_instance = instance_id--;
+              a2dp.abr_config.is_abr_enabled = true; // for APTX Adaptive ABR is Always on
+              a2dp.is_aptx_adaptive = true;
+              aptx_encoder_cfg.ad_cfg = (audio_aptx_ad_config *)codec_info;
+              is_configured =
+                (configure_aptx_enc_format(&aptx_encoder_cfg) &&
+                 configure_a2dp_decoder_format(ENC_MEDIA_FMT_APTX_AD));
+            break;
         default:
             ALOGD(" Received Unsupported encoder formar");
             is_configured = false;
@@ -1819,6 +1990,7 @@
   a2dp.is_a2dp_offload_supported = false;
   a2dp.is_handoff_in_progress = false;
   a2dp.is_aptx_dual_mono_supported = false;
+  a2dp.is_aptx_adaptive = false;
   a2dp.abr_config.is_abr_enabled = false;
   a2dp.abr_config.abr_started = false;
   a2dp.abr_config.imc_instance = 0;