Promotion of audio-userspace.lnx.2.1-00037.

CRs      Change ID                                   Subject
--------------------------------------------------------------------------------------------------------------
1075152   I4a81e93d246d234b86a81eb6597cf641e1ea1991   hal: Changes Relating to DisplayPort Audio
1065036   I94df832ba5e2a26e9179d66d4639f168b5c30eeb   hal: native DSD and mix path concurrency fix.
1074909   Ic1c437d4cb15db709941eec065d40b2ae173ea9d   audio: Update hal to handle 32bit/384kHz playback.
1073616   Ic89553a69fd4746c7b6731b0f38ae830f44c3914   hal: Add support for aptxHD encoder for a2dp
1065036   Ie2b44ab26ed2262d1ed79fd8bead4a703096a861   configs: msmcobalt: select fractional output mode for as

Change-Id: Ifbc40248e9f9cacb06d793ff878159a85ba807d8
CRs-Fixed: 1065036, 1073616, 1074909, 1075152
diff --git a/configs/msmcobalt/mixer_paths_tavil.xml b/configs/msmcobalt/mixer_paths_tavil.xml
index 34543f5..29212f9 100644
--- a/configs/msmcobalt/mixer_paths_tavil.xml
+++ b/configs/msmcobalt/mixer_paths_tavil.xml
@@ -474,6 +474,8 @@
 
     <!-- Headphone Default mode - uLP -->
     <ctl name="RX HPH Mode" value="CLS_H_ULP" />
+    <ctl name="ASRC0 Output Mode" value="INT" />
+    <ctl name="ASRC1 Output Mode" value="INT" />
 
     <!-- IIR/voice anc -->
     <ctl name="IIR0 Band1" id ="0" value="268435456" />
@@ -1881,6 +1883,8 @@
     </path>
 
     <path name="asrc-mode">
+        <ctl name="ASRC0 Output Mode" value="FRAC" />
+        <ctl name="ASRC1 Output Mode" value="FRAC" />
         <ctl name="RX INT1_2 NATIVE MUX" value="ON" />
         <ctl name="RX INT2_2 NATIVE MUX" value="ON" />
         <ctl name="ASRC0 MUX" value="ASRC_IN_HPHL" />
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.c b/hal/audio_extn/audio_extn.c
index 65f516c..083b925 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -129,7 +129,7 @@
     int i = 0;
     FILE *ext_disp_fd = NULL;
 
-    for(i = 0; i < 3; i++) {
+    while (1) {
         snprintf(fbpath, sizeof(fbpath),
                   "/sys/class/graphics/fb%d/msm_fb_type", i);
         ext_disp_fd = fopen(fbpath, "r");
@@ -146,8 +146,10 @@
                 }
             }
             fclose(ext_disp_fd);
+            i++;
         } else {
-            ALOGE("%s: Failed to open fb node %d", __func__, i);
+            ALOGE("%s: Scanned till end of fbs or Failed to open fb node %d", __func__, i);
+            break;
         }
     }
 
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/usb.c b/hal/audio_extn/usb.c
index b3bd58f..f936f99 100644
--- a/hal/audio_extn/usb.c
+++ b/hal/audio_extn/usb.c
@@ -47,7 +47,7 @@
 #define SAMPLE_RATE_11025         11025
 // Supported sample rates for USB
 static uint32_t supported_sample_rates[] =
-    {44100, 48000, 64000, 88200, 96000, 176400, 192000};
+    {44100, 48000, 64000, 88200, 96000, 176400, 192000, 384000};
 
 #define  MAX_SAMPLE_RATE_SIZE  sizeof(supported_sample_rates)/sizeof(supported_sample_rates[0])
 
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 26c43b4..9542fbd 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -495,7 +495,7 @@
     struct stream_format *sf_info;
     char value[PROPERTY_VALUE_MAX] = {0};
 
-    if ((24 == bit_width) &&
+    if ((bit_width >= 24) &&
         (devices & AUDIO_DEVICE_OUT_SPEAKER)) {
         int32_t bw = platform_get_snd_device_bit_width(SND_DEVICE_OUT_SPEAKER);
         if (-ENOSYS != bw)
@@ -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) {
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 673c17e..7888e5a 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -622,29 +622,75 @@
     return 0;
 }
 
-/*
- * Enable ASRC mode if native or DSD stream is active.
- */
-static void audio_check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
+static void enable_asrc_mode(struct audio_device *adev)
 {
-    if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
-       !adev->asrc_mode_enabled) {
+    ALOGV("%s", __func__);
+    audio_route_apply_and_update_path(adev->audio_route,
+                                  "asrc-mode");
+    adev->asrc_mode_enabled = true;
+}
+
+static void disable_asrc_mode(struct audio_device *adev)
+{
+    ALOGV("%s", __func__);
+    audio_route_reset_and_update_path(adev->audio_route,
+                                  "asrc-mode");
+    adev->asrc_mode_enabled = false;
+}
+
+/*
+ * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
+ *   44.1 or Native DSD backends are enabled for any of current use case.
+ *   e.g. 48-> + (Naitve DSD or Headphone 44.1)
+ * - Disable current mix path use case(Headphone backend) and re-enable it with
+ *   ASRC mode for incoming Headphone 44.1 or Native DSD use case.
+ *   e.g. Naitve DSD or Headphone 44.1 -> + 48
+ */
+static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
+{
+    ALOGV("%s snd device %d", __func__, snd_device);
+    int new_backend_idx = platform_get_backend_index(snd_device);
+
+    if (((new_backend_idx == HEADPHONE_BACKEND) ||
+            (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
+            (new_backend_idx == DSD_NATIVE_BACKEND)) &&
+            !adev->asrc_mode_enabled) {
         struct listnode *node = NULL;
         struct audio_usecase *uc = NULL;
         struct stream_out *curr_out = NULL;
+        int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
 
         list_for_each(node, &adev->usecase_list) {
             uc = node_to_item(node, struct audio_usecase, list);
             curr_out = (struct stream_out*) uc->stream.out;
-
             if (curr_out && PCM_PLAYBACK == uc->type) {
-                if((platform_get_backend_index(uc->out_snd_device) == HEADPHONE_44_1_BACKEND) ||
-                      (platform_get_backend_index(uc->out_snd_device) == DSD_NATIVE_BACKEND)) {
+                usecase_backend_idx = platform_get_backend_index(uc->out_snd_device);
+
+                if((new_backend_idx == HEADPHONE_BACKEND) &&
+                       ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
+                       (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
                     ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
                           __func__);
-                    audio_route_apply_and_update_path(adev->audio_route,
-                                                  "asrc-mode");
-                    adev->asrc_mode_enabled = true;
+                    enable_asrc_mode(adev);
+                    break;
+                } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
+                          (new_backend_idx == DSD_NATIVE_BACKEND)) &&
+                          (usecase_backend_idx == HEADPHONE_BACKEND)) {
+                    ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
+                          __func__);
+                    disable_audio_route(adev, uc);
+                    disable_snd_device(adev, uc->out_snd_device);
+                    // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
+                    if (new_backend_idx == DSD_NATIVE_BACKEND)
+                        audio_route_apply_and_update_path(adev->audio_route,
+                                                "hph-true-highquality-mode");
+                    else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
+                             (curr_out->bit_width >= 24))
+                        audio_route_apply_and_update_path(adev->audio_route,
+                                                     "hph-highquality-mode");
+                    enable_asrc_mode(adev);
+                    enable_snd_device(adev, uc->out_snd_device);
+                    enable_audio_route(adev, uc);
                     break;
                 }
             }
@@ -802,8 +848,7 @@
             audio_route_apply_and_update_path(adev->audio_route,
                                               "true-native-mode");
             adev->native_playback_enabled = true;
-        } else
-            audio_check_and_set_asrc_mode(adev, snd_device);
+        }
     }
     return 0;
 }
@@ -862,8 +907,8 @@
         } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
                  adev->asrc_mode_enabled) {
             ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
-            audio_route_reset_and_update_path(adev->audio_route, "asrc-mode");
-            adev->asrc_mode_enabled = false;
+            disable_asrc_mode(adev);
+            audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
         }
 
         audio_extn_dev_arbi_release(snd_device);
@@ -936,9 +981,8 @@
              (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
              (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
              (force_restart_session)) &&
-            (platform_check_backends_match(snd_device, usecase->out_snd_device)||
-             (platform_check_codec_asrc_support(adev->platform) && !adev->asrc_mode_enabled &&
-              platform_check_if_backend_has_to_be_disabled(snd_device,usecase->out_snd_device)))) {
+             (platform_check_backends_match(snd_device, usecase->out_snd_device))) {
+
                 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
                     __func__, use_case_table[usecase->id],
                       platform_get_snd_device_name(usecase->out_snd_device));
@@ -1087,10 +1131,9 @@
     reset_hdmi_sink_caps(out);
 
     /* Cache ext disp type */
-    ret = platform_get_ext_disp_type(adev->platform);
-    if (ret < 0) {
+    if (platform_get_ext_disp_type(adev->platform) <= 0) {
         ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
-        return ret;
+        return -EINVAL;
     }
 
     switch (channels) {
@@ -1422,6 +1465,8 @@
     /* Enable new sound devices */
     if (out_snd_device != SND_DEVICE_NONE) {
         check_usecases_codec_backend(adev, usecase, out_snd_device);
+        if (platform_check_codec_asrc_support(adev->platform))
+            check_and_set_asrc_mode(adev, out_snd_device);
         enable_snd_device(adev, out_snd_device);
     }
 
@@ -2183,6 +2228,35 @@
     return size;
 }
 
+static size_t get_output_period_size(uint32_t sample_rate,
+                                    audio_format_t format,
+                                    int channel_count,
+                                    int duration /*in millisecs*/)
+{
+    size_t size = 0;
+    uint32_t bytes_per_sample = audio_bytes_per_sample(format);
+
+    if ((duration == 0) || (sample_rate == 0) ||
+        (bytes_per_sample == 0) || (channel_count == 0)) {
+        ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
+               bytes_per_sample, channel_count);
+        return -EINVAL;
+    }
+
+    size = (sample_rate *
+            duration *
+            bytes_per_sample *
+            channel_count) / 1000;
+    /*
+     * To have same PCM samples for all channels, the buffer size requires to
+     * be multiple of (number of channels * bytes per sample)
+     * For writes to succeed, the buffer must be written at address which is multiple of 32
+     */
+    size = ALIGN(size, (bytes_per_sample * channel_count * 32));
+
+    return (size/(channel_count * bytes_per_sample));
+}
+
 static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
 {
     uint64_t actual_frames_rendered = 0;
@@ -3853,6 +3927,17 @@
         out->config = pcm_config_afe_proxy_playback;
         adev->voice_tx_output = out;
     } else {
+        unsigned int channels = 0;
+        /*Update config params to default if not set by the caller*/
+        if (config->sample_rate == 0)
+            config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
+        if (config->channel_mask == AUDIO_CHANNEL_NONE)
+            config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+        if (config->format == AUDIO_FORMAT_DEFAULT)
+            config->format = AUDIO_FORMAT_PCM_16_BIT;
+
+        channels = audio_channel_count_from_out_mask(out->channel_mask);
+
         if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
             out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
             out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
@@ -3864,6 +3949,13 @@
         } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
             out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
             out->config = pcm_config_deep_buffer;
+            out->config.period_size = get_output_period_size(config->sample_rate, out->format,
+                                                 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
+            if (out->config.period_size <= 0) {
+                ALOGE("Invalid configuration period size is not valid");
+                ret = -EINVAL;
+                goto error_open;
+            }
         } else {
             /* primary path is the default path selected if no other outputs are available/suitable */
             out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
@@ -3875,7 +3967,7 @@
         out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
         out->config.rate = config->sample_rate;
         out->sample_rate = out->config.rate;
-        out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
+        out->config.channels = channels;
         if (out->hal_ip_format != out->hal_op_format) {
             uint32_t buffer_size = out->config.period_size *
                                    format_to_bitwidth_table[out->hal_op_format] *
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 47943da..a5cc804 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -4304,7 +4304,7 @@
             else
                 mixer_ctl_set_enum_by_string(ctl, "S24_LE");
         } else if (bit_width == 32) {
-            mixer_ctl_set_enum_by_string(ctl, "S24_LE");
+            mixer_ctl_set_enum_by_string(ctl, "S32_LE");
         } else {
             mixer_ctl_set_enum_by_string(ctl, "S16_LE");
         }
@@ -4640,6 +4640,13 @@
     } else if ((usecase->devices & AUDIO_DEVICE_OUT_SPEAKER) ||
                (usecase->devices & AUDIO_DEVICE_OUT_EARPIECE) ) {
         sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+
+        if (bit_width >= 24) {
+            bit_width = platform_get_snd_device_bit_width(SND_DEVICE_OUT_SPEAKER);
+            ALOGD("%s:becf: afe: reset bitwidth to %d (based on supported"
+                  " value for this platform)", __func__, bit_width);
+        }
+
         ALOGD("%s:becf: afe: playback on codec device not supporting native playback set "
             "default Sample Rate(48k)", __func__);
     }
@@ -4660,6 +4667,13 @@
         hdmi_backend_cfg.channels = channels;
         hdmi_backend_cfg.passthrough_enabled = false;
 
+        /*HDMI does not support 384Khz/32bit playback hence configure BE to 24b/192Khz*/
+        /* TODO: Instead have the validation against edid return the next best match*/
+        if (bit_width > 24)
+            hdmi_backend_cfg.bit_width = 24;
+        if (sample_rate > 192000)
+            hdmi_backend_cfg.sample_rate = 192000;
+
         platform_check_hdmi_backend_cfg(adev, usecase, backend_idx, &hdmi_backend_cfg);
 
         bit_width = hdmi_backend_cfg.bit_width;
@@ -5618,12 +5632,6 @@
     return false;
 }
 
-bool platform_check_if_backend_has_to_be_disabled(snd_device_t new_snd_device __unused,
-                                                  snd_device_t cuurent_snd_device __unused)
-{
-    return false;
-}
-
 int platform_send_audio_cal(void* platform __unused,
         int acdb_dev_id __unused, int acdb_device_type __unused,
         int app_type __unused, int topology_id __unused,
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index 33be141..cba9068 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -267,6 +267,7 @@
  * the buffer size of an input/output stream
  */
 #define DEEP_BUFFER_OUTPUT_PERIOD_SIZE 1920
+#define DEEP_BUFFER_OUTPUT_PERIOD_DURATION 40 /* 40 millisecs */
 #define DEEP_BUFFER_OUTPUT_PERIOD_COUNT 2
 #define LOW_LATENCY_OUTPUT_PERIOD_SIZE 240
 #define LOW_LATENCY_OUTPUT_PERIOD_COUNT 2
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index b687d96..b5a4f11 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1330,8 +1330,3 @@
     return false;
 }
 
-bool platform_check_if_backend_has_to_be_disabled(snd_device_t new_snd_device __unused,
-                                                  snd_device_t cuurent_snd_device __unused)
-{
-    return false;
-}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 6930286..fa67342 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -1987,32 +1987,6 @@
     return result;
 }
 
-bool platform_check_if_backend_has_to_be_disabled(snd_device_t new_snd_device,
-                                                  snd_device_t cuurent_snd_device)
-{
-    bool result = false;
-
-    ALOGV("%s: current snd device = %s, new snd device = %s", __func__,
-                platform_get_snd_device_name(cuurent_snd_device),
-                platform_get_snd_device_name(new_snd_device));
-
-    if ((new_snd_device < SND_DEVICE_MIN) || (new_snd_device >= SND_DEVICE_OUT_END) ||
-            (cuurent_snd_device < SND_DEVICE_MIN) || (cuurent_snd_device >= SND_DEVICE_OUT_END)) {
-        ALOGE("%s: Invalid snd_device",__func__);
-        return false;
-    }
-
-    if (cuurent_snd_device == SND_DEVICE_OUT_HEADPHONES &&
-            (new_snd_device == SND_DEVICE_OUT_HEADPHONES_44_1 ||
-             new_snd_device == SND_DEVICE_OUT_HEADPHONES_DSD)) {
-        result = true;
-    }
-
-    ALOGV("%s: Need to disable current backend %s, %d",
-          __func__, platform_get_snd_device_name(cuurent_snd_device), result);
-    return result;
-}
-
 int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
 {
     int device_id;
@@ -2191,7 +2165,7 @@
 {
     if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
         ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
-        return DEFAULT_OUTPUT_SAMPLING_RATE;
+        return CODEC_BACKEND_DEFAULT_BIT_WIDTH;
     }
     return backend_bit_width_table[snd_device];
 }
@@ -4389,7 +4363,7 @@
             else
                  ret = mixer_ctl_set_enum_by_string(ctl, "S24_LE");
         } else if (bit_width == 32) {
-            ret = mixer_ctl_set_enum_by_string(ctl, "S24_LE");
+            ret = mixer_ctl_set_enum_by_string(ctl, "S32_LE");
         } else {
             ret = mixer_ctl_set_enum_by_string(ctl, "S16_LE");
         }
@@ -4723,13 +4697,20 @@
                  ALOGD("%s:becf: afe: true napb active set rate to 44.1 khz",
                        __func__);
             }
-        } else if (OUTPUT_SAMPLING_RATE_44100 == sample_rate) {
+        } else if ((OUTPUT_SAMPLING_RATE_44100 == sample_rate) &&
+                   (na_mode != NATIVE_AUDIO_MODE_MULTIPLE_44_1)) {
                  sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
                  ALOGD("%s:becf: afe: napb not active - set (48k) default rate",
                        __func__);
         }
     } else if ((usecase->devices & AUDIO_DEVICE_OUT_SPEAKER) ||
                (usecase->devices & AUDIO_DEVICE_OUT_EARPIECE) ) {
+
+        if (bit_width >= 24) {
+            bit_width = platform_get_snd_device_bit_width(SND_DEVICE_OUT_SPEAKER);
+            ALOGD("%s:becf: afe: reset bitwidth to %d (based on supported"
+                   " value for this platform)", __func__, bit_width);
+        }
         sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
         ALOGD("%s:becf: afe: playback on codec device not supporting native playback set "
             "default Sample Rate(48k)", __func__);
@@ -4750,6 +4731,15 @@
         hdmi_backend_cfg.channels = channels;
         hdmi_backend_cfg.passthrough_enabled = false;
 
+        /*
+         * HDMI does not support 384Khz/32bit playback hence configure BE to 24b/192Khz
+         * TODO: Instead have the validation against edid return the next best match
+         */
+        if (bit_width > 24)
+            hdmi_backend_cfg.bit_width = 24;
+        if (sample_rate > 192000)
+            hdmi_backend_cfg.sample_rate = 192000;
+
         platform_check_hdmi_backend_cfg(adev, usecase, backend_idx, &hdmi_backend_cfg);
 
         bit_width = hdmi_backend_cfg.bit_width;
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 2b65950..c231843 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -257,7 +257,14 @@
  * We should take care of returning proper size when AudioFlinger queries for
  * the buffer size of an input/output stream
  */
+
+/* for 384Khz output below period size corresponds to 20ms worth duration of buffer,
+ * current implementation can support buffer size of 40ms duration
+ * for 32b/384Khz/stereo output.
+ */
 #define DEEP_BUFFER_OUTPUT_PERIOD_SIZE 1920
+#define DEEP_BUFFER_OUTPUT_PERIOD_DURATION 40 /* 40 milisecs */
+
 #define DEEP_BUFFER_OUTPUT_PERIOD_COUNT 2
 #define LOW_LATENCY_OUTPUT_PERIOD_SIZE 240
 #define LOW_LATENCY_OUTPUT_PERIOD_COUNT 2