Merge "hal: accumulate written frames when error occurred during write"
diff --git a/configs/sdm660/mixer_paths_skus.xml b/configs/sdm660/mixer_paths_skus.xml
index 98b0733..2dbcd2a 100644
--- a/configs/sdm660/mixer_paths_skus.xml
+++ b/configs/sdm660/mixer_paths_skus.xml
@@ -2516,7 +2516,7 @@
         <ctl name="DMIC MUX7" value="DMIC5" />
         <ctl name="SLIM TX8 MUX" value="DEC8" />
         <ctl name="ADC MUX8" value="DMIC" />
-        <ctl name="DMIC MUX8" value="DMIC1" />
+        <ctl name="DMIC MUX8" value="DMIC5" />
     </path>
 
     <path name="speaker-qmic-liquid">
diff --git a/configs/sdm660/sound_trigger_mixer_paths_wcd9335.xml b/configs/sdm660/sound_trigger_mixer_paths_wcd9335.xml
index 691b2e3..0efade0 100644
--- a/configs/sdm660/sound_trigger_mixer_paths_wcd9335.xml
+++ b/configs/sdm660/sound_trigger_mixer_paths_wcd9335.xml
@@ -36,6 +36,14 @@
     <ctl name="LSM6 Mixer SLIMBUS_5_TX" value="0" />
     <ctl name="LSM7 Mixer SLIMBUS_5_TX" value="0" />
     <ctl name="LSM8 Mixer SLIMBUS_5_TX" value="0" />
+    <ctl name="LSM1 Mixer SLIMBUS_0_TX" value="0" />
+    <ctl name="LSM2 Mixer SLIMBUS_0_TX" value="0" />
+    <ctl name="LSM3 Mixer SLIMBUS_0_TX" value="0" />
+    <ctl name="LSM4 Mixer SLIMBUS_0_TX" value="0" />
+    <ctl name="LSM5 Mixer SLIMBUS_0_TX" value="0" />
+    <ctl name="LSM6 Mixer SLIMBUS_0_TX" value="0" />
+    <ctl name="LSM7 Mixer SLIMBUS_0_TX" value="0" />
+    <ctl name="LSM8 Mixer SLIMBUS_0_TX" value="0" />
     <ctl name="LSM1 Port" value="None" />
     <ctl name="LSM2 Port" value="None" />
     <ctl name="LSM3 Port" value="None" />
@@ -45,6 +53,7 @@
     <ctl name="LSM7 Port" value="None" />
     <ctl name="LSM8 Port" value="None" />
     <ctl name="SLIMBUS_5_TX LSM Function" value="None" />
+    <ctl name="SLIMBUS_0_TX LSM Function" value="None" />
     <ctl name="MADONOFF Switch" value="0" />
     <ctl name="MAD Input" value="DMIC1" />
     <ctl name="MAD_BROADCAST Switch" value="0" />
@@ -52,10 +61,27 @@
     <ctl name="AIF4_MAD Mixer SLIM TX12" value="0" />
     <ctl name="AIF4_MAD Mixer SLIM TX13" value="0" />
     <ctl name="CPE AFE MAD Enable" value="0"/>
+    <ctl name="AIF1_CAP Mixer SLIM TX8" value="0"/>
+    <ctl name="AIF1_CAP Mixer SLIM TX7" value="0" />
+    <ctl name="AIF1_CAP Mixer SLIM TX6" value="0" />
+    <ctl name="AIF1_CAP Mixer SLIM TX5" value="0"/>
+    <ctl name="SLIM TX5 MUX" value="ZERO" />
+    <ctl name="SLIM TX6 MUX" value="ZERO" />
+    <ctl name="SLIM TX7 MUX" value="ZERO" />
+    <ctl name="SLIM TX8 MUX" value="ZERO" />
+    <ctl name="ADC MUX5" value="AMIC" />
+    <ctl name="ADC MUX6" value="AMIC" />
+    <ctl name="ADC MUX7" value="AMIC" />
+    <ctl name="ADC MUX8" value="AMIC" />
+    <ctl name="DMIC MUX5" value="ZERO" />
+    <ctl name="DMIC MUX6" value="ZERO" />
+    <ctl name="DMIC MUX7" value="ZERO" />
+    <ctl name="DMIC MUX8" value="ZERO" />
     <ctl name="CLK MODE" value="EXTERNAL" />
     <ctl name="EC BUF MUX INP" value="ZERO" />
     <ctl name="ADC MUX1" value="DMIC" />
     <ctl name="DMIC MUX1" value="ZERO" />
+    <ctl name="IIR0 INP0 MUX" value="ZERO" />
 
     <path name="listen-voice-wakeup-1">
         <ctl name="SLIMBUS_5_TX LSM Function" value="AUDIO" />
@@ -99,11 +125,59 @@
         <ctl name="LSM8 Mixer SLIMBUS_5_TX" value="1" />
     </path>
 
+    <path name="listen-voice-wakeup-1 preproc">
+        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="LSM1 Port" value="ADM_LSM_TX" />
+        <ctl name="LSM1 Mixer SLIMBUS_0_TX" value="1" />
+    </path>
+
+    <path name="listen-voice-wakeup-2 preproc">
+        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="LSM2 Port" value="ADM_LSM_TX" />
+        <ctl name="LSM2 Mixer SLIMBUS_0_TX" value="1" />
+    </path>
+
+    <path name="listen-voice-wakeup-3 preproc">
+        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="LSM3 Port" value="ADM_LSM_TX" />
+        <ctl name="LSM3 Mixer SLIMBUS_0_TX" value="1" />
+    </path>
+
+    <path name="listen-voice-wakeup-4 preproc">
+        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="LSM4 Port" value="ADM_LSM_TX" />
+        <ctl name="LSM4 Mixer SLIMBUS_0_TX" value="1" />
+    </path>
+
+    <path name="listen-voice-wakeup-5 preproc">
+        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="LSM5 Port" value="ADM_LSM_TX" />
+        <ctl name="LSM5 Mixer SLIMBUS_0_TX" value="1" />
+    </path>
+
+    <path name="listen-voice-wakeup-6 preproc">
+        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="LSM6 Port" value="ADM_LSM_TX" />
+        <ctl name="LSM6 Mixer SLIMBUS_0_TX" value="1" />
+    </path>
+
+    <path name="listen-voice-wakeup-7 preproc">
+        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="LSM7 Port" value="ADM_LSM_TX" />
+        <ctl name="LSM7 Mixer SLIMBUS_0_TX" value="1" />
+    </path>
+
+    <path name="listen-voice-wakeup-8 preproc">
+        <ctl name="SLIMBUS_0_TX LSM Function" value="SWAUDIO" />
+        <ctl name="LSM8 Port" value="ADM_LSM_TX" />
+        <ctl name="LSM8 Mixer SLIMBUS_0_TX" value="1" />
+    </path>
+
     <path name="listen-cpe-handset-mic">
         <ctl name="MADONOFF Switch" value="1" />
         <ctl name="TX13 INP MUX" value="CPE_TX_PP" />
         <ctl name="AIF4_MAD Mixer SLIM TX13" value="1" />
-        <ctl name="MAD Input" value="DMIC2" />
+        <ctl name="MAD Input" value="DMIC3" />
         <ctl name="CPE AFE MAD Enable" value="1"/>
     </path>
 
@@ -111,14 +185,14 @@
         <ctl name="CLK MODE" value="INTERNAL" />
         <ctl name="EC BUF MUX INP" value="DEC1" />
         <ctl name="ADC MUX1" value="DMIC" />
-        <ctl name="DMIC MUX1" value="DMIC2" />
+        <ctl name="DMIC MUX1" value="DMIC3" />
     </path>
 
     <!-- path name used for low bandwidth FTRT codec interface -->
     <path name="listen-cpe-handset-mic low-speed-intf">
         <ctl name="MADONOFF Switch" value="1" />
         <ctl name="AIF4_MAD Mixer SLIM TX12" value="1" />
-        <ctl name="MAD Input" value="DMIC2" />
+        <ctl name="MAD Input" value="DMIC3" />
         <ctl name="CPE AFE MAD Enable" value="1"/>
     </path>
 
@@ -126,7 +200,43 @@
         <ctl name="MAD_BROADCAST Switch" value="1" />
         <ctl name="TX13 INP MUX" value="MAD_BRDCST" />
         <ctl name="AIF4_MAD Mixer SLIM TX13" value="1" />
-        <ctl name="MAD Input" value="DMIC2" />
+        <ctl name="MAD Input" value="DMIC3" />
     </path>
 
+    <path name="listen-ape-handset-mic-preproc">
+       <ctl name="AIF1_CAP Mixer SLIM TX7" value="1"/>
+       <ctl name="SLIM_0_TX Channels" value="One" />
+       <ctl name="SLIM TX7 MUX" value="DEC7" />
+       <ctl name="ADC MUX7" value="DMIC" />
+       <ctl name="DMIC MUX7" value="DMIC3" />
+       <ctl name="IIR0 INP0 MUX" value="DEC7" />
+    </path>
+
+    <path name="listen-ape-handset-qmic">
+       <ctl name="AIF1_CAP Mixer SLIM TX5" value="1" />
+       <ctl name="AIF1_CAP Mixer SLIM TX6" value="1" />
+       <ctl name="AIF1_CAP Mixer SLIM TX7" value="1" />
+       <ctl name="AIF1_CAP Mixer SLIM TX8" value="1" />
+       <ctl name="SLIM_0_TX Channels" value="Four" />
+       <ctl name="SLIM TX5 MUX" value="DEC5" />
+       <ctl name="ADC MUX5" value="DMIC" />
+       <ctl name="DMIC MUX5" value="DMIC0" />
+       <ctl name="SLIM TX6 MUX" value="DEC6" />
+       <ctl name="ADC MUX6" value="DMIC" />
+       <ctl name="DMIC MUX6" value="DMIC3" />
+       <ctl name="SLIM TX7 MUX" value="DEC7" />
+       <ctl name="ADC MUX7" value="DMIC" />
+       <ctl name="DMIC MUX7" value="DMIC5" />
+       <ctl name="SLIM TX8 MUX" value="DEC8" />
+       <ctl name="ADC MUX8" value="DMIC" />
+       <ctl name="DMIC MUX8" value="DMIC5" />
+   </path>
+
+   <path name="echo-reference">
+        <ctl name="AUDIO_REF_EC_UL1 MUX" value="SLIM_RX"/>
+        <ctl name="EC Reference Channels" value="One"/>
+        <ctl name="EC Reference Bit Format" value="S16_LE"/>
+        <ctl name="EC Reference SampleRate" value="48000"/>
+   </path>
+
 </mixer>
diff --git a/hal/audio_extn/a2dp.c b/hal/audio_extn/a2dp.c
index 548bb7c..2103930 100644
--- a/hal/audio_extn/a2dp.c
+++ b/hal/audio_extn/a2dp.c
@@ -55,6 +55,7 @@
 #define ENC_MEDIA_FMT_APTX                                 0x000131ff
 #define ENC_MEDIA_FMT_APTX_HD                              0x00013200
 #define ENC_MEDIA_FMT_SBC                                  0x00010BF2
+#define ENC_MEDIA_FMT_CELT                                 0x00013221
 #define MEDIA_FMT_AAC_AOT_LC                               2
 #define MEDIA_FMT_AAC_AOT_SBR                              5
 #define MEDIA_FMT_AAC_AOT_PS                               29
@@ -78,10 +79,29 @@
 #define ENCODER_LATENCY_APTX       40
 #define ENCODER_LATENCY_APTX_HD    20
 #define ENCODER_LATENCY_AAC        70
+//To Do: Fine Tune Encoder CELT latency.
+#define ENCODER_LATENCY_CELT       40
 #define DEFAULT_SINK_LATENCY_SBC       140
 #define DEFAULT_SINK_LATENCY_APTX      160
 #define DEFAULT_SINK_LATENCY_APTX_HD   180
 #define DEFAULT_SINK_LATENCY_AAC       180
+//To Do: Fine Tune Default CELT Latency.
+#define DEFAULT_SINK_LATENCY_CELT      180
+
+/*
+ * Below enum values are extended from audio_base.h to
+ * to keep encoder codec type local to bthost_ipc
+ * and audio_hal as these are intended only for handshake
+ * between IPC lib and Audio HAL.
+ */
+typedef enum {
+    ENC_CODEC_TYPE_INVALID = 4294967295u, // 0xFFFFFFFFUL
+    ENC_CODEC_TYPE_AAC = 67108864u, // 0x04000000UL
+    ENC_CODEC_TYPE_SBC = 520093696u, // 0x1F000000UL
+    ENC_CODEC_TYPE_APTX = 536870912u, // 0x20000000UL
+    ENC_CODEC_TYPE_APTX_HD = 553648128u, // 0x21000000UL
+    ENC_CODEC_TYPE_CELT = 603979776u, // 0x24000000UL
+}enc_codec_t;
 
 typedef int (*audio_stream_open_t)(void);
 typedef int (*audio_stream_close_t)(void);
@@ -91,7 +111,7 @@
 typedef void (*audio_handoff_triggered_t)(void);
 typedef void (*clear_a2dpsuspend_flag_t)(void);
 typedef void * (*audio_get_codec_config_t)(uint8_t *multicast_status,uint8_t *num_dev,
-                               audio_format_t *codec_type);
+                               enc_codec_t *codec_type);
 typedef int (*audio_check_a2dp_ready_t)(void);
 typedef uint16_t (*audio_get_a2dp_sink_latency_t)(void);
 
@@ -120,7 +140,7 @@
     audio_check_a2dp_ready_t audio_check_a2dp_ready;
     audio_get_a2dp_sink_latency_t audio_get_a2dp_sink_latency;
     enum A2DP_STATE bt_state;
-    audio_format_t bt_encoder_format;
+    enc_codec_t bt_encoder_format;
     uint32_t enc_sampling_rate;
     bool a2dp_started;
     bool a2dp_suspended;
@@ -177,7 +197,7 @@
  * supported channel mapping for stereo is CHANNEL_L and CHANNEL_R
  * custom size and reserved are not used(for future enhancement)
   */
-struct custom_enc_cfg_aptx_t
+struct custom_enc_cfg_t
 {
     uint32_t      enc_format;
     uint32_t      sample_rate;
@@ -187,20 +207,35 @@
     uint32_t      custom_size;
 };
 
+struct celt_specific_enc_cfg_t
+{
+    uint32_t      bit_rate;
+    uint16_t      frame_size;
+    uint16_t      complexity;
+    uint16_t      prediction_mode;
+    uint16_t      vbr_flag;
+};
+
+struct celt_enc_cfg_t
+{
+    struct custom_enc_cfg_t  custom_cfg;
+    struct celt_specific_enc_cfg_t celt_cfg;
+};
+
 /* TODO: Define the following structures only for O using PLATFORM_VERSION */
 /* Information about BT SBC encoder configuration
  * This data is used between audio HAL module and
  * BT IPC library to configure DSP encoder
  */
 typedef struct {
-    uint32_t subband;    /* 4, 8 */
-    uint32_t blk_len;    /* 4, 8, 12, 16 */
-    uint16_t sampling_rate; /*44.1khz,48khz*/
-    uint8_t  channels;      /*0(Mono),1(Dual_mono),2(Stereo),3(JS)*/
-    uint8_t  alloc;         /*0(Loudness),1(SNR)*/
-    uint8_t  min_bitpool;   /* 2 */
-    uint8_t  max_bitpool;   /*53(44.1khz),51 (48khz) */
-    uint32_t bitrate;      /* 320kbps to 512kbps */
+    uint32_t subband;        /* 4, 8 */
+    uint32_t blk_len;        /* 4, 8, 12, 16 */
+    uint16_t sampling_rate;  /*44.1khz,48khz*/
+    uint8_t  channels;       /*0(Mono),1(Dual_mono),2(Stereo),3(JS)*/
+    uint8_t  alloc;          /*0(Loudness),1(SNR)*/
+    uint8_t  min_bitpool;    /* 2 */
+    uint8_t  max_bitpool;    /*53(44.1khz),51 (48khz) */
+    uint32_t bitrate;        /* 320kbps to 512kbps */
 } audio_sbc_encoder_config;
 
 
@@ -227,6 +262,20 @@
     uint32_t bitrate;
 } audio_aac_encoder_config;
 
+/* Information about BT CELT encoder configuration
+ * This data is used between audio HAL module and
+ * BT IPC library to configure DSP encoder
+ */
+typedef struct {
+    uint32_t sampling_rate; /* 32000 - 48000, 48000 */
+    uint16_t channels; /* 1-Mono, 2-Stereo, 2*/
+    uint16_t frame_size; /* 64-128-256-512, 512 */
+    uint16_t complexity; /* 0-10, 1 */
+    uint16_t prediction_mode; /* 0-1-2, 0 */
+    uint16_t vbr_flag; /* 0-1, 0*/
+    uint32_t bitrate; /*32000 - 1536000, 139500*/
+} audio_celt_encoder_config;
+
 /*********** END of DSP configurable structures ********************/
 
 /* API to identify DSP encoder captabilities */
@@ -252,6 +301,10 @@
             ALOGD("%s: aac offload supported\n",__func__);
             a2dp.is_a2dp_offload_supported = true;
             break;
+        } else if (strcmp(tok, "celt") == 0) {
+            ALOGD("%s: celt offload supported\n",__func__);
+            a2dp.is_a2dp_offload_supported = true;
+            break;
         }
         tok = strtok_r(NULL, "-", &saveptr);
     };
@@ -348,7 +401,7 @@
     a2dp.a2dp_started = false;
     a2dp.a2dp_total_active_session_request = 0;
     a2dp.a2dp_suspended = false;
-    a2dp.bt_encoder_format = AUDIO_FORMAT_INVALID;
+    a2dp.bt_encoder_format = ENC_CODEC_TYPE_INVALID;
     a2dp.enc_sampling_rate = 48000;
     a2dp.bt_state = A2DP_STATE_DISCONNECTED;
 
@@ -372,7 +425,6 @@
         is_configured = false;
         goto fail;
     }
-    a2dp.bt_encoder_format = AUDIO_FORMAT_SBC;
     memset(&sbc_dsp_cfg, 0x0, sizeof(struct sbc_enc_cfg_t));
     sbc_dsp_cfg.enc_format = ENC_MEDIA_FMT_SBC;
     sbc_dsp_cfg.num_subbands = sbc_bt_cfg->subband;
@@ -419,6 +471,7 @@
         goto fail;
     }
     is_configured = true;
+    a2dp.bt_encoder_format = ENC_CODEC_TYPE_SBC;
     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);
@@ -430,7 +483,7 @@
 bool configure_aptx_enc_format(audio_aptx_encoder_config *aptx_bt_cfg)
 {
     struct mixer_ctl *ctl_enc_data = NULL, *ctrl_bit_format = NULL;
-    struct custom_enc_cfg_aptx_t aptx_dsp_cfg;
+    struct custom_enc_cfg_t aptx_dsp_cfg;
     bool is_configured = false;
     int ret = 0;
 
@@ -443,8 +496,7 @@
         is_configured = false;
         goto fail;
     }
-    a2dp.bt_encoder_format = AUDIO_FORMAT_APTX;
-    memset(&aptx_dsp_cfg, 0x0, sizeof(struct custom_enc_cfg_aptx_t));
+    memset(&aptx_dsp_cfg, 0x0, sizeof(struct custom_enc_cfg_t));
     aptx_dsp_cfg.enc_format = ENC_MEDIA_FMT_APTX;
     aptx_dsp_cfg.sample_rate = aptx_bt_cfg->sampling_rate;
     aptx_dsp_cfg.num_channels = aptx_bt_cfg->channels;
@@ -459,7 +511,7 @@
             break;
     }
     ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_dsp_cfg,
-                              sizeof(struct custom_enc_cfg_aptx_t));
+                              sizeof(struct custom_enc_cfg_t));
     if (ret != 0) {
         ALOGE("%s: Failed to set APTX encoder config", __func__);
         is_configured = false;
@@ -480,6 +532,7 @@
         }
     }
     is_configured = true;
+    a2dp.bt_encoder_format = ENC_CODEC_TYPE_APTX;
     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);
@@ -492,7 +545,7 @@
 bool configure_aptx_hd_enc_format(audio_aptx_encoder_config *aptx_bt_cfg)
 {
     struct mixer_ctl *ctl_enc_data = NULL, *ctrl_bit_format = NULL;
-    struct custom_enc_cfg_aptx_t aptx_dsp_cfg;
+    struct custom_enc_cfg_t aptx_dsp_cfg;
     bool is_configured = false;
     int ret = 0;
 
@@ -506,8 +559,7 @@
         goto fail;
     }
 
-    a2dp.bt_encoder_format = AUDIO_FORMAT_APTX_HD;
-    memset(&aptx_dsp_cfg, 0x0, sizeof(struct custom_enc_cfg_aptx_t));
+    memset(&aptx_dsp_cfg, 0x0, sizeof(struct custom_enc_cfg_t));
     aptx_dsp_cfg.enc_format = ENC_MEDIA_FMT_APTX_HD;
     aptx_dsp_cfg.sample_rate = aptx_bt_cfg->sampling_rate;
     aptx_dsp_cfg.num_channels = aptx_bt_cfg->channels;
@@ -522,7 +574,7 @@
             break;
     }
     ret = mixer_ctl_set_array(ctl_enc_data, (void *)&aptx_dsp_cfg,
-                              sizeof(struct custom_enc_cfg_aptx_t));
+                              sizeof(struct custom_enc_cfg_t));
     if (ret != 0) {
         ALOGE("%s: Failed to set APTX HD encoder config", __func__);
         is_configured = false;
@@ -541,6 +593,7 @@
         goto fail;
     }
     is_configured = true;
+    a2dp.bt_encoder_format = ENC_CODEC_TYPE_APTX_HD;
     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);
@@ -565,7 +618,6 @@
         is_configured = false;
         goto fail;
     }
-    a2dp.bt_encoder_format = AUDIO_FORMAT_AAC;
     memset(&aac_dsp_cfg, 0x0, sizeof(struct aac_enc_cfg_t));
     aac_dsp_cfg.enc_format = ENC_MEDIA_FMT_AAC;
     aac_dsp_cfg.bit_rate = aac_bt_cfg->bitrate;
@@ -605,6 +657,7 @@
         goto fail;
     }
     is_configured = true;
+    a2dp.bt_encoder_format = ENC_CODEC_TYPE_AAC;
     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);
@@ -612,11 +665,77 @@
     return is_configured;
 }
 
+bool configure_celt_enc_format(audio_celt_encoder_config *celt_bt_cfg)
+{
+    struct mixer_ctl *ctl_enc_data = NULL, *ctrl_bit_format = NULL;
+    struct celt_enc_cfg_t celt_dsp_cfg;
+    bool is_configured = false;
+    int ret = 0;
+    if(celt_bt_cfg == NULL)
+        return false;
+
+    ctl_enc_data = mixer_get_ctl_by_name(a2dp.adev->mixer, MIXER_ENC_CONFIG_BLOCK);
+    if (!ctl_enc_data) {
+        ALOGE(" ERROR  a2dp encoder CONFIG data mixer control not identifed");
+        is_configured = false;
+        goto fail;
+    }
+    memset(&celt_dsp_cfg, 0x0, sizeof(struct celt_enc_cfg_t));
+
+    celt_dsp_cfg.custom_cfg.enc_format = ENC_MEDIA_FMT_CELT;
+    celt_dsp_cfg.custom_cfg.sample_rate = celt_bt_cfg->sampling_rate;
+    celt_dsp_cfg.custom_cfg.num_channels = celt_bt_cfg->channels;
+    switch(celt_dsp_cfg.custom_cfg.num_channels) {
+        case 1:
+            celt_dsp_cfg.custom_cfg.channel_mapping[0] = PCM_CHANNEL_C;
+            break;
+        case 2:
+        default:
+            celt_dsp_cfg.custom_cfg.channel_mapping[0] = PCM_CHANNEL_L;
+            celt_dsp_cfg.custom_cfg.channel_mapping[1] = PCM_CHANNEL_R;
+            break;
+    }
+
+    celt_dsp_cfg.custom_cfg.custom_size = sizeof(struct celt_enc_cfg_t);
+
+    celt_dsp_cfg.celt_cfg.frame_size = celt_bt_cfg->frame_size;
+    celt_dsp_cfg.celt_cfg.complexity = celt_bt_cfg->complexity;
+    celt_dsp_cfg.celt_cfg.prediction_mode = celt_bt_cfg->prediction_mode;
+    celt_dsp_cfg.celt_cfg.vbr_flag = celt_bt_cfg->vbr_flag;
+    celt_dsp_cfg.celt_cfg.bit_rate = celt_bt_cfg->bitrate;
+
+    ret = mixer_ctl_set_array(ctl_enc_data, (void *)&celt_dsp_cfg,
+                              sizeof(struct celt_enc_cfg_t));
+    if (ret != 0) {
+        ALOGE("%s: Failed to set CELT encoder config", __func__);
+        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, "S16_LE");
+    if (ret != 0) {
+        ALOGE("%s: Failed to set bit format to encoder", __func__);
+        is_configured = false;
+        goto fail;
+    }
+    is_configured = true;
+    a2dp.bt_encoder_format = ENC_CODEC_TYPE_CELT;
+    a2dp.enc_sampling_rate = celt_bt_cfg->sampling_rate;
+    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:
+    return is_configured;
+}
 bool configure_a2dp_encoder_format()
 {
     void *codec_info = NULL;
     uint8_t multi_cast = 0, num_dev = 1;
-    audio_format_t codec_type = AUDIO_FORMAT_INVALID;
+    enc_codec_t codec_type = ENC_CODEC_TYPE_INVALID;
     bool is_configured = false;
 
     if (!a2dp.audio_get_codec_config) {
@@ -628,26 +747,31 @@
                                &codec_type);
 
     switch(codec_type) {
-        case AUDIO_FORMAT_SBC:
+        case ENC_CODEC_TYPE_SBC:
             ALOGD(" Received SBC encoder supported BT device");
             is_configured =
                configure_sbc_enc_format((audio_sbc_encoder_config *)codec_info);
             break;
-        case AUDIO_FORMAT_APTX:
+        case ENC_CODEC_TYPE_APTX:
             ALOGD(" Received APTX encoder supported BT device");
             is_configured =
               configure_aptx_enc_format((audio_aptx_encoder_config *)codec_info);
             break;
-        case AUDIO_FORMAT_APTX_HD:
+        case ENC_CODEC_TYPE_APTX_HD:
             ALOGD(" Received APTX HD encoder supported BT device");
             is_configured =
              configure_aptx_hd_enc_format((audio_aptx_encoder_config *)codec_info);
             break;
-        case AUDIO_FORMAT_AAC:
+        case ENC_CODEC_TYPE_AAC:
             ALOGD(" Received AAC encoder supported BT device");
             is_configured =
               configure_aac_enc_format((audio_aac_encoder_config *)codec_info);
             break;
+        case ENC_CODEC_TYPE_CELT:
+            ALOGD(" Received CELT encoder supported BT device");
+            is_configured =
+              configure_celt_enc_format((audio_celt_encoder_config *)codec_info);
+            break;
         default:
             ALOGD(" Received Unsupported encoder formar");
             is_configured = false;
@@ -876,7 +1000,7 @@
 void audio_extn_a2dp_get_apptype_params(uint32_t *sample_rate,
                                         uint32_t *bit_width)
 {
-    if(a2dp.bt_encoder_format == AUDIO_FORMAT_APTX_HD)
+    if(a2dp.bt_encoder_format == ENC_CODEC_TYPE_APTX_HD)
         *bit_width = 24;
     else
         *bit_width = 16;
@@ -910,7 +1034,7 @@
   a2dp.bt_state = A2DP_STATE_DISCONNECTED;
   a2dp.a2dp_total_active_session_request = 0;
   a2dp.a2dp_suspended = false;
-  a2dp.bt_encoder_format = AUDIO_FORMAT_INVALID;
+  a2dp.bt_encoder_format = ENC_CODEC_TYPE_INVALID;
   a2dp.enc_sampling_rate = 48000;
   a2dp.is_a2dp_offload_supported = false;
   a2dp.is_handoff_in_progress = false;
@@ -921,14 +1045,14 @@
 {
     uint32_t latency = 0;
     int avsync_runtime_prop = 0;
-    int sbc_offset = 0, aptx_offset = 0, aptxhd_offset = 0, aac_offset = 0;
+    int sbc_offset = 0, aptx_offset = 0, aptxhd_offset = 0, aac_offset = 0, celt_offset = 0;
     char value[PROPERTY_VALUE_MAX];
 
     memset(value, '\0', sizeof(char)*PROPERTY_VALUE_MAX);
     avsync_runtime_prop = property_get("vendor.audio.a2dp.codec.latency", value, NULL);
     if (avsync_runtime_prop > 0) {
-        if (sscanf(value, "%d/%d/%d/%d",
-                  &sbc_offset, &aptx_offset, &aptxhd_offset, &aac_offset) != 4) {
+        if (sscanf(value, "%d/%d/%d/%d/%d",
+                  &sbc_offset, &aptx_offset, &aptxhd_offset, &aac_offset, &celt_offset) != 5) {
             ALOGI("Failed to parse avsync offset params from '%s'.", value);
             avsync_runtime_prop = 0;
         }
@@ -940,22 +1064,26 @@
     }
 
     switch(a2dp.bt_encoder_format) {
-        case AUDIO_FORMAT_SBC:
+        case ENC_CODEC_TYPE_SBC:
             latency = (avsync_runtime_prop > 0) ? sbc_offset : ENCODER_LATENCY_SBC;
             latency += (slatency <= 0) ? DEFAULT_SINK_LATENCY_SBC : slatency;
             break;
-        case AUDIO_FORMAT_APTX:
+        case ENC_CODEC_TYPE_APTX:
             latency = (avsync_runtime_prop > 0) ? aptx_offset : ENCODER_LATENCY_APTX;
             latency += (slatency <= 0) ? DEFAULT_SINK_LATENCY_APTX : slatency;
             break;
-        case AUDIO_FORMAT_APTX_HD:
+        case ENC_CODEC_TYPE_APTX_HD:
             latency = (avsync_runtime_prop > 0) ? aptxhd_offset : ENCODER_LATENCY_APTX_HD;
             latency += (slatency <= 0) ? DEFAULT_SINK_LATENCY_APTX_HD : slatency;
             break;
-        case AUDIO_FORMAT_AAC:
+        case ENC_CODEC_TYPE_AAC:
             latency = (avsync_runtime_prop > 0) ? aac_offset : ENCODER_LATENCY_AAC;
             latency += (slatency <= 0) ? DEFAULT_SINK_LATENCY_AAC : slatency;
             break;
+        case ENC_CODEC_TYPE_CELT:
+            latency = (avsync_runtime_prop > 0) ? celt_offset : ENCODER_LATENCY_CELT;
+            latency += (slatency <= 0) ? DEFAULT_SINK_LATENCY_CELT : slatency;
+            break;
         default:
             latency = 200;
             break;
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 8360703..5707742 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -603,6 +603,7 @@
                                   struct audio_device *adev,
                                   struct audio_usecase *usecase);
 int audio_extn_utils_get_snd_card_num();
+bool audio_extn_is_dsp_bit_width_enforce_mode_supported(audio_output_flags_t flags);
 
 #ifdef DS2_DOLBY_DAP_ENABLED
 #define LIB_DS2_DAP_HAL "vendor/lib/libhwdaphal.so"
diff --git a/hal/audio_extn/hw_loopback.c b/hal/audio_extn/hw_loopback.c
index 6da9313..180e575 100644
--- a/hal/audio_extn/hw_loopback.c
+++ b/hal/audio_extn/hw_loopback.c
@@ -270,7 +270,7 @@
 
     adev->active_input = get_next_active_input(adev);
 
-    if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format) && inout->ip_hdlr_handle) {
+    if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format, false) && inout->ip_hdlr_handle) {
         ret = audio_extn_ip_hdlr_intf_close(inout->ip_hdlr_handle, true, inout);
         if (ret < 0)
             ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
@@ -284,7 +284,7 @@
         inout->adsp_hdlr_stream_handle = NULL;
     }
 
-    if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format) &&
+    if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format, false) &&
         inout->ip_hdlr_handle) {
         audio_extn_ip_hdlr_intf_deinit(inout->ip_hdlr_handle);
         inout->ip_hdlr_handle = NULL;
@@ -381,7 +381,7 @@
         inout->adsp_hdlr_stream_handle = NULL;
         goto exit;
     }
-    if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format)) {
+    if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format, false)) {
         ret = audio_extn_ip_hdlr_intf_init(&inout->ip_hdlr_handle, NULL, NULL);
         if (ret < 0) {
             ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d", __func__, ret);
@@ -467,7 +467,7 @@
         ret = -EINVAL;
         goto exit;
     }
-    if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format) && inout->ip_hdlr_handle) {
+    if (audio_extn_ip_hdlr_intf_supported(source_patch_config->format, false) && inout->ip_hdlr_handle) {
         ret = audio_extn_ip_hdlr_intf_open(inout->ip_hdlr_handle, true, inout,
                                            USECASE_AUDIO_TRANSCODE_LOOPBACK);
         if (ret < 0) {
diff --git a/hal/audio_extn/ip_hdlr_intf.c b/hal/audio_extn/ip_hdlr_intf.c
index 21d4e07..0f31f21 100644
--- a/hal/audio_extn/ip_hdlr_intf.c
+++ b/hal/audio_extn/ip_hdlr_intf.c
@@ -116,10 +116,10 @@
     uint8_t payload[0];
 };
 
-bool audio_extn_ip_hdlr_intf_supported(audio_format_t format)
+bool audio_extn_ip_hdlr_intf_supported(audio_format_t format,bool is_direct_passthru)
 {
     if (((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_DOLBY_TRUEHD) ||
-        ((!property_get_bool("audio.offload.passthrough", false)) &&
+        ((!is_direct_passthru) &&
          (((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_E_AC3) ||
          ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AC3))))
         return true;
diff --git a/hal/audio_extn/ip_hdlr_intf.h b/hal/audio_extn/ip_hdlr_intf.h
index e8a9166..1f2c304 100644
--- a/hal/audio_extn/ip_hdlr_intf.h
+++ b/hal/audio_extn/ip_hdlr_intf.h
@@ -37,7 +37,7 @@
 int audio_extn_ip_hdlr_intf_close(void *handle, bool is_dsp_decode, void *aud_sess_handle);
 int audio_extn_ip_hdlr_intf_init(void **handle, char *lib_path, void **lib_handle);
 int audio_extn_ip_hdlr_intf_deinit(void *handle);
-bool audio_extn_ip_hdlr_intf_supported(audio_format_t format);
+bool audio_extn_ip_hdlr_intf_supported(audio_format_t format, bool is_direct_passthru);
 
 #else
 
@@ -45,7 +45,7 @@
 #define audio_extn_ip_hdlr_intf_close(handle, is_dsp_decode, aud_sess_handle) (0)
 #define audio_extn_ip_hdlr_intf_init(handle, lib_path, lib_handle)            (0)
 #define audio_extn_ip_hdlr_intf_deinit(handle)                                (0)
-#define audio_extn_ip_hdlr_intf_supported(format)                             (0)
+#define audio_extn_ip_hdlr_intf_supported(format, is_direct_passthru)                             (0)
 
 #endif
 
diff --git a/hal/audio_extn/passthru.c b/hal/audio_extn/passthru.c
index 31c94f6..ee9995c 100644
--- a/hal/audio_extn/passthru.c
+++ b/hal/audio_extn/passthru.c
@@ -417,6 +417,19 @@
 
 }
 
+bool audio_extn_passthru_is_direct_passthrough(struct stream_out *out)
+{
+    //check passthrough system property
+    if (!property_get_bool("audio.offload.passthrough", false)) {
+        return false;
+    }
+
+    if ((out != NULL) && (out->compr_config.codec->compr_passthr == PASSTHROUGH || out->compr_config.codec->compr_passthr == PASSTHROUGH_IEC61937))
+        return true;
+    else
+        return false;
+}
+
 bool audio_extn_passthru_is_passthrough_stream(struct stream_out *out)
 {
     //check passthrough system property
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index fb1362c..48d20ee 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -393,6 +393,7 @@
     struct mixer_ctl *ctl = NULL;
     const char *mixer_ctl_name = "App Type Config";
     struct streams_io_cfg *s_info = NULL;
+    uint32_t target_bit_width = 0;
 
     if (!mixer) {
         ALOGE("%s: mixer is null",__func__);
@@ -418,6 +419,9 @@
         num_app_types += 1;
     }
 
+    /* get target bit width for ADM enforce mode */
+    target_bit_width = adev_get_dsp_bit_width_enforce_mode();
+
     list_for_each(node, streams_output_cfg_list) {
         s_info = node_to_item(node, struct streams_io_cfg, list);
         update = true;
@@ -429,6 +433,11 @@
                     app_type_cfg[i+2] = s_info->app_type_cfg.sample_rate;
                 if (app_type_cfg[i+3] < (size_t)s_info->app_type_cfg.bit_width)
                     app_type_cfg[i+3] = s_info->app_type_cfg.bit_width;
+                /* ADM bit width = max(enforce_bit_width, bit_width from s_info */
+                if (audio_extn_is_dsp_bit_width_enforce_mode_supported(s_info->flags.out_flags) &&
+                    (target_bit_width > app_type_cfg[i+3]))
+                    app_type_cfg[i+3] = target_bit_width;
+
                 update = false;
                 break;
             }
@@ -437,7 +446,12 @@
             num_app_types += 1;
             app_type_cfg[length++] = s_info->app_type_cfg.app_type;
             app_type_cfg[length++] = s_info->app_type_cfg.sample_rate;
-            app_type_cfg[length++] = s_info->app_type_cfg.bit_width;
+            app_type_cfg[length] = s_info->app_type_cfg.bit_width;
+            if (audio_extn_is_dsp_bit_width_enforce_mode_supported(s_info->flags.out_flags) &&
+                (target_bit_width > app_type_cfg[length]))
+                app_type_cfg[length] = target_bit_width;
+
+            length++;
         }
     }
     list_for_each(node, streams_input_cfg_list) {
@@ -767,6 +781,28 @@
     return native_usecase;
 }
 
+bool audio_extn_is_dsp_bit_width_enforce_mode_supported(audio_output_flags_t flags)
+{
+    /* DSP bitwidth enforce mode for ADM and AFE:
+    * includes:
+    *     deep buffer, low latency, direct pcm and offload.
+    * excludes:
+    *     ull(raw+fast), VOIP.
+    */
+    if ((flags & AUDIO_OUTPUT_FLAG_VOIP_RX) ||
+            ((flags & AUDIO_OUTPUT_FLAG_RAW) &&
+            (flags & AUDIO_OUTPUT_FLAG_FAST)))
+        return false;
+
+
+    if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
+            (flags & AUDIO_OUTPUT_FLAG_DIRECT) ||
+            (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) ||
+            (flags & AUDIO_OUTPUT_FLAG_PRIMARY))
+        return true;
+    else
+        return false;
+}
 
 static inline bool audio_is_vr_mode_on(struct audio_device *(__attribute__((unused)) adev))
 {
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index a59e1ea..6029c4a 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -1515,6 +1515,84 @@
     return active;
 }
 
+uint32_t adev_get_dsp_bit_width_enforce_mode()
+{
+    if (adev == NULL) {
+        ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
+        return 0;
+    }
+    return adev->dsp_bit_width_enforce_mode;
+}
+
+static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
+{
+    char value[PROPERTY_VALUE_MAX];
+    int trial;
+    uint32_t dsp_bit_width_enforce_mode = 0;
+
+    if (!mixer) {
+        ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
+                __func__);
+        return 0;
+    }
+
+    if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
+                        value, NULL) > 0) {
+        trial = atoi(value);
+        switch (trial) {
+        case 16:
+            dsp_bit_width_enforce_mode = 16;
+            break;
+        case 24:
+            dsp_bit_width_enforce_mode = 24;
+            break;
+        case 32:
+            dsp_bit_width_enforce_mode = 32;
+            break;
+       default:
+            dsp_bit_width_enforce_mode = 0;
+            ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
+            break;
+        }
+    }
+
+    return dsp_bit_width_enforce_mode;
+}
+
+static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
+                                                uint32_t enforce_mode,
+                                                bool enable)
+{
+    struct mixer_ctl *ctl = NULL;
+    const char *mixer_ctl_name = "ASM Bit Width";
+    uint32_t asm_bit_width_mode = 0;
+
+    if (enforce_mode == 0) {
+        ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
+        return;
+    }
+
+    ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
+    if (!ctl) {
+        ALOGE("%s: Could not get ctl for mixer cmd - %s",
+                __func__, mixer_ctl_name);
+        return;
+    }
+
+    if (enable)
+        asm_bit_width_mode = enforce_mode;
+    else
+        asm_bit_width_mode = 0;
+
+    ALOGV("%s DSP bit width feature status is %d width=%d",
+        __func__, enable, asm_bit_width_mode);
+    if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
+        ALOGE("%s: Could not set ASM biwidth %d", __func__,
+                asm_bit_width_mode);
+
+    return;
+}
+
 /*
  * if native DSD playback active
  */
@@ -2444,6 +2522,12 @@
     /* 2. Disable the rx device */
     disable_snd_device(adev, uc_info->out_snd_device);
 
+    if (is_offload_usecase(out->usecase)) {
+        audio_enable_asm_bit_width_enforce_mode(adev->mixer,
+                                                adev->dsp_bit_width_enforce_mode,
+                                                false);
+    }
+
     list_remove(&uc_info->list);
     free(uc_info);
     out->started = 0;
@@ -2460,7 +2544,7 @@
     if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
         audio_extn_keep_alive_start();
 
-    if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
+    if (audio_extn_ip_hdlr_intf_supported(out->format, audio_extn_passthru_is_direct_passthrough(out)) && out->ip_hdlr_handle) {
         ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
         if (ret < 0)
             ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
@@ -2653,6 +2737,9 @@
     } else {
         platform_set_stream_channel_map(adev->platform, out->channel_mask,
                    out->pcm_device_id, &out->channel_map_param.channel_map[0]);
+        audio_enable_asm_bit_width_enforce_mode(adev->mixer,
+                                                adev->dsp_bit_width_enforce_mode,
+                                                true);
         out->pcm = NULL;
         out->compr = compress_open(adev->snd_card,
                                    out->pcm_device_id,
@@ -2712,7 +2799,7 @@
     audio_extn_perf_lock_release(&adev->perf_lock_handle);
     ALOGD("%s: exit", __func__);
 
-    if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
+    if (audio_extn_ip_hdlr_intf_supported(out->format, audio_extn_passthru_is_direct_passthrough(out)) && out->ip_hdlr_handle) {
         ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
         if (ret < 0)
             ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
@@ -5402,7 +5489,7 @@
     /* setup a channel for client <--> adsp communication for stream events */
     if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
             (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
-            (audio_extn_ip_hdlr_intf_supported(config->format))) {
+            (audio_extn_ip_hdlr_intf_supported(config->format, audio_extn_passthru_is_direct_passthrough(out)))) {
         hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
                 out->usecase, PCM_PLAYBACK);
         hdlr_stream_cfg.flags = out->flags;
@@ -5414,7 +5501,7 @@
             out->adsp_hdlr_stream_handle = NULL;
         }
     }
-    if (audio_extn_ip_hdlr_intf_supported(config->format)) {
+    if (audio_extn_ip_hdlr_intf_supported(config->format, audio_extn_passthru_is_direct_passthrough(out))) {
         ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL);
         if (ret < 0) {
             ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
@@ -5454,7 +5541,7 @@
         out->adsp_hdlr_stream_handle = NULL;
     }
 
-    if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
+    if (audio_extn_ip_hdlr_intf_supported(out->format, audio_extn_passthru_is_direct_passthrough(out)) && out->ip_hdlr_handle) {
         audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
         out->ip_hdlr_handle = NULL;
     }
@@ -6410,6 +6497,7 @@
     adev->perf_lock_opts[0] = 0x101;
     adev->perf_lock_opts[1] = 0x20E;
     adev->perf_lock_opts_size = 2;
+    adev->dsp_bit_width_enforce_mode = 0;
 
     /* Loads platform specific libraries dynamically */
     adev->platform = platform_init(adev);
@@ -6522,6 +6610,8 @@
 
     audio_extn_ds2_enable(adev);
     *device = &adev->device.common;
+    adev->dsp_bit_width_enforce_mode =
+        adev_init_dsp_bit_width_enforce_mode(adev->mixer);
 
     audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
                                              &adev->streams_output_cfg_list,
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index fec2400..0a6d85b 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -493,6 +493,7 @@
     bool asrc_mode_enabled;
     qahwi_device_t qahwi_dev;
     bool vr_audio_mode_enabled;
+    uint32_t dsp_bit_width_enforce_mode;
     bool bt_sco_on;
     struct audio_device_config_param *device_cfg_params;
     unsigned int interactive_usecase_state;
@@ -521,6 +522,8 @@
 
 bool audio_is_dsd_native_stream_active(struct audio_device *adev);
 
+uint32_t adev_get_dsp_bit_width_enforce_mode();
+
 int pcm_ioctl(struct pcm *pcm, int request, ...);
 
 audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 3e71527..52e3138 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -5888,6 +5888,10 @@
         backend_cfg.format = usecase->stream.out->format;
         backend_cfg.channels = audio_channel_count_from_out_mask(usecase->stream.out->channel_mask);
     }
+    /* enforce AFE bitwidth mode via backend_cfg */
+    if (audio_extn_is_dsp_bit_width_enforce_mode_supported(usecase->stream.out->flags) &&
+                (adev->dsp_bit_width_enforce_mode > backend_cfg.bit_width))
+        backend_cfg.bit_width = adev->dsp_bit_width_enforce_mode;
 
     /*this is populated by check_codec_backend_cfg hence set default value to false*/
     backend_cfg.passthrough_enabled = false;
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 6c1ab76..e88673b 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -5734,6 +5734,9 @@
         backend_cfg.format = usecase->stream.out->format;
         backend_cfg.channels = audio_channel_count_from_out_mask(usecase->stream.out->channel_mask);
     }
+    if (audio_extn_is_dsp_bit_width_enforce_mode_supported(usecase->stream.out->flags) &&
+                (adev->dsp_bit_width_enforce_mode > backend_cfg.bit_width))
+        backend_cfg.bit_width = adev->dsp_bit_width_enforce_mode;
 
     /*this is populated by check_codec_backend_cfg hence set default value to false*/
     backend_cfg.passthrough_enabled = false;
diff --git a/post_proc/Android.mk b/post_proc/Android.mk
index 0fdd136..e27214b 100644
--- a/post_proc/Android.mk
+++ b/post_proc/Android.mk
@@ -104,10 +104,12 @@
 LOCAL_MODULE:= libvolumelistener
 LOCAL_VENDOR_MODULE := true
 
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+
 LOCAL_C_INCLUDES := \
         hardware/qcom/audio/hal \
         $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include \
-	$(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/techpack/audio/include \
+        $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/techpack/audio/include \
         external/tinyalsa/include \
         $(call include-path-for, audio-effects) \
         $(call include-path-for, audio-route) \