hal: add USB capture backend configuration support

Add USB capture BE configuration support and update the parsing
function to retrieve USB device capability.

Change-Id: I3dc7d289b3fcc96d522a2df3b8168f546737c036
CRs-Fixed: 1050510 1054988 1050666 1058845
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index d2cb9d3..ce2cb46 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -155,7 +155,7 @@
 #define audio_extn_usb_deinit()                                        (0)
 #define audio_extn_usb_add_device(device, card)                        (0)
 #define audio_extn_usb_remove_device(device, card)                     (0)
-#define audio_extn_usb_is_config_supported(bit_width, sample_rate, ch) (0)
+#define audio_extn_usb_is_config_supported(bit_width, sample_rate, ch, pb) (0)
 #define audio_extn_usb_enable_sidetone(device, enable)                 (0)
 #define audio_extn_usb_set_sidetone_gain(parms, value, len)            (0)
 #else
@@ -165,7 +165,8 @@
 void audio_extn_usb_remove_device(audio_devices_t device, int card);
 bool audio_extn_usb_is_config_supported(unsigned int *bit_width,
                                         unsigned int *sample_rate,
-                                        unsigned int *ch);
+                                        unsigned int *ch,
+                                        bool is_playback);
 int audio_extn_usb_enable_sidetone(int device, bool enable);
 int audio_extn_usb_set_sidetone_gain(struct str_parms *parms,
                                      char *value, int len);
diff --git a/hal/audio_extn/usb.c b/hal/audio_extn/usb.c
index f95d6a7..501472b 100644
--- a/hal/audio_extn/usb.c
+++ b/hal/audio_extn/usb.c
@@ -300,25 +300,34 @@
                               struct usb_card_config *usb_card_info,
                               int card)
 {
-    int32_t err = 1;
     int32_t size = 0;
     int32_t fd=-1;
-    int32_t altset_index = 1;
     int32_t channels_no;
-    char *str_start, *channel_start, *bit_width_start, *rates_str_start,
-         *target;
+    char *str_start = NULL;
+    char *str_end = NULL;
+    char *channel_start = NULL;
+    char *bit_width_start = NULL;
+    char *rates_str_start = NULL;
+    char *target = NULL;
     char *read_buf = NULL;
     char *rates_str = NULL;
-    char path[128], altset[9];
+    char path[128];
     int ret = 0;
     char *bit_width_str = NULL;
     struct usb_device_config * usb_device_info;
+    bool check = false;
 
+    memset(path, 0, sizeof(path));
     ALOGV("%s: for %s", __func__, (type == USB_PLAYBACK) ?
           PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR);
 
-    snprintf(path, sizeof(path), "/proc/asound/card%u/stream0",
+    ret = snprintf(path, sizeof(path), "/proc/asound/card%u/stream0",
              card);
+    if(ret < 0) {
+        ALOGE("%s: failed on snprintf (%d) to path %s\n",
+          __func__, ret, path);
+        goto done;
+    }
 
     fd = open(path, O_RDONLY);
     if (fd <0) {
@@ -336,7 +345,10 @@
         goto done;
     }
 
-    err = read(fd, read_buf, USB_BUFF_SIZE);
+    if(read(fd, read_buf, USB_BUFF_SIZE) < 0) {
+        ALOGE("file read error\n");
+        goto done;
+    }
     str_start = strstr(read_buf, ((type == USB_PLAYBACK) ?
                        PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
     if (str_start == NULL) {
@@ -346,21 +358,21 @@
         ret = -EINVAL;
         goto done;
     }
-    ALOGV("%s: usb_config = %s\n", __func__, str_start);
+    str_end = strstr(read_buf, ((type == USB_PLAYBACK) ?
+                       CAPTURE_PROFILE_STR : PLAYBACK_PROFILE_STR));
+    if (str_end > str_start)
+        check = true;
+
+    ALOGV("%s: usb_config = %s, check %d\n", __func__, str_start, check);
 
     while (str_start != NULL) {
-        sprintf(altset, "Altset %d", altset_index);
-        ALOGV("%s: altset_index %d\n", __func__, altset_index);
-        str_start = strstr(str_start, altset);
-        if (str_start == NULL) {
-            if (altset_index == 1) {
-                ALOGE("%s: error %s section not found in usb config file",
-                       __func__, (type == USB_PLAYBACK) ?
-                      PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR);
-                ret = -EINVAL;
-            }
+        str_start = strstr(str_start, "Altset");
+        if ((str_start == NULL) || (check  && (str_start >= str_end))) {
+            ALOGV("%s: done parsing %s\n", __func__, str_start);
             break;
         }
+        ALOGV("%s: remaining string %s\n", __func__, str_start);
+        str_start += sizeof("Altset");
         usb_device_info = calloc(1, sizeof(struct usb_device_config));
         if (usb_device_info == NULL) {
             ALOGE("%s: error unable to allocate memory",
@@ -368,7 +380,6 @@
             ret = -ENOMEM;
             break;
         }
-        altset_index++;
         /* Bit bit_width parsing */
         bit_width_start = strstr(str_start, "Format: ");
         if (bit_width_start == NULL) {
@@ -883,7 +894,8 @@
 
 bool audio_extn_usb_is_config_supported(unsigned int *bit_width,
                                         unsigned int *sample_rate,
-                                        unsigned int *ch)
+                                        unsigned int *ch,
+                                        bool is_playback)
 {
     struct listnode *node_i;
     struct usb_card_config *card_info;
@@ -897,7 +909,14 @@
                  "%s: card_dev_type (0x%x), card_no(%d)",
                  __func__,  card_info->usb_device_type, card_info->usb_card);
         /* Currently only apply the first playback sound card configuration */
-        if (card_info->usb_device_type == AUDIO_DEVICE_OUT_USB_DEVICE) {
+        if (is_playback && card_info->usb_device_type == AUDIO_DEVICE_OUT_USB_DEVICE) {
+            is_usb_supported = usb_audio_backend_apply_policy(
+                                           &card_info->usb_device_conf_list,
+                                           bit_width,
+                                           sample_rate,
+                                           ch);
+            break;
+        } else if (card_info->usb_device_type == AUDIO_DEVICE_IN_USB_DEVICE ) {
             is_usb_supported = usb_audio_backend_apply_policy(
                                            &card_info->usb_device_conf_list,
                                            bit_width,
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 07def67..2540184 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -1933,10 +1933,15 @@
         my_data->current_backend_cfg[DEFAULT_CODEC_BACKEND].samplerate_mixer_ctl =
             strdup("MI2S_RX SampleRate");
 
-        my_data->current_tx_backend_cfg[DEFAULT_CODEC_BACKEND].bitwidth_mixer_ctl =
+        my_data->current_tx_backend_cfg[DEFAULT_CODEC_TX_BACKEND].bitwidth_mixer_ctl =
             strdup("MI2S_TX Format");
-        my_data->current_tx_backend_cfg[DEFAULT_CODEC_BACKEND].samplerate_mixer_ctl =
+        my_data->current_tx_backend_cfg[DEFAULT_CODEC_TX_BACKEND].samplerate_mixer_ctl =
             strdup("MI2S_TX SampleRate");
+
+        my_data->current_tx_backend_cfg[USB_AUDIO_TX_BACKEND].bitwidth_mixer_ctl =
+            strdup("USB_AUDIO_TX Format");
+        my_data->current_tx_backend_cfg[USB_AUDIO_TX_BACKEND].samplerate_mixer_ctl =
+            strdup("USB_AUDIO_TX SampleRate");
     }
 
     my_data->current_backend_cfg[USB_AUDIO_RX_BACKEND].bitwidth_mixer_ctl =
@@ -2504,6 +2509,23 @@
     return port;
 }
 
+static int platform_get_capture_backend_index(snd_device_t snd_device)
+{
+    int32_t port = DEFAULT_CODEC_TX_BACKEND;
+
+    if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX) {
+        if (backend_tag_table[snd_device] != NULL) {
+                if (strcmp(backend_tag_table[snd_device], "usb-headset-mic") == 0)
+                        port = USB_AUDIO_TX_BACKEND;
+        }
+    } else {
+        ALOGW("%s: Invalid device - %d ", __func__, snd_device);
+    }
+
+    ALOGV("%s: backend port - %d snd_device %d", __func__, port, snd_device);
+    return port;
+}
+
 int platform_send_audio_calibration(void *platform, struct audio_usecase *usecase,
                                     int app_type, int sample_rate)
 {
@@ -4596,7 +4618,7 @@
     }
 
     if (backend_idx == USB_AUDIO_RX_BACKEND) {
-        audio_extn_usb_is_config_supported(&bit_width, &sample_rate, &channels);
+        audio_extn_usb_is_config_supported(&bit_width, &sample_rate, &channels, true);
         ALOGV("%s: USB BE configured as bit_width(%d)sample_rate(%d)channels(%d)",
                    __func__, bit_width, sample_rate, channels);
         if (channels != my_data->current_backend_cfg[backend_idx].channels)
@@ -4669,20 +4691,19 @@
  * configures afe with bit width and Sample Rate
  */
 
-int platform_set_capture_codec_backend_cfg(struct audio_device* adev,
+static int platform_set_capture_codec_backend_cfg(struct audio_device* adev,
                          snd_device_t snd_device,
-                         unsigned int bit_width, unsigned int sample_rate,
-                         audio_format_t format)
+                         struct audio_backend_cfg backend_cfg)
 {
     int ret = 0;
-    int backend_idx = DEFAULT_CODEC_BACKEND;
+    int backend_idx = platform_get_capture_backend_index(snd_device);
     struct platform_data *my_data = (struct platform_data *)adev->platform;
 
     ALOGI("%s:txbecf: afe: bitwidth %d, samplerate %d, backend_idx %d device (%s)",
-          __func__, bit_width, sample_rate, backend_idx,
+          __func__, backend_cfg.bit_width, backend_cfg.sample_rate, backend_idx,
           platform_get_snd_device_name(snd_device));
 
-    if (bit_width !=
+    if (backend_cfg.bit_width !=
         my_data->current_tx_backend_cfg[backend_idx].bit_width) {
 
         struct  mixer_ctl *ctl = NULL;
@@ -4695,8 +4716,8 @@
             return -EINVAL;
         }
 
-        if (bit_width == 24) {
-            if (format == AUDIO_FORMAT_PCM_24_BIT_PACKED)
+        if (backend_cfg.bit_width == 24) {
+            if (backend_cfg.format == AUDIO_FORMAT_PCM_24_BIT_PACKED)
                 ret = mixer_ctl_set_enum_by_string(ctl, "S24_3LE");
             else
                 ret = mixer_ctl_set_enum_by_string(ctl, "S24_LE");
@@ -4711,9 +4732,10 @@
             return -EINVAL;
         }
 
-        my_data->current_tx_backend_cfg[backend_idx].bit_width = bit_width;
+        my_data->current_tx_backend_cfg[backend_idx].bit_width = backend_cfg.bit_width;
         ALOGD("%s:txbecf: afe: %s mixer set to %d bit", __func__,
-              my_data->current_tx_backend_cfg[backend_idx].bitwidth_mixer_ctl, bit_width);
+              my_data->current_tx_backend_cfg[backend_idx].bitwidth_mixer_ctl,
+              backend_cfg.bit_width);
     }
 
     /*
@@ -4726,14 +4748,15 @@
      */
     // TODO: This has to be more dynamic based on policy file
 
-    if (sample_rate != my_data->current_tx_backend_cfg[(int)backend_idx].sample_rate) {
+    if (backend_cfg.sample_rate !=
+        my_data->current_tx_backend_cfg[(int)backend_idx].sample_rate) {
             /*
              * sample rate update is needed only for hifi audio enabled platforms
              */
             char *rate_str = NULL;
             struct  mixer_ctl *ctl = NULL;
 
-            switch (sample_rate) {
+            switch (backend_cfg.sample_rate) {
             case 8000:
             case 11025:
             case 16000:
@@ -4778,7 +4801,8 @@
                 return -EINVAL;
             }
 
-            my_data->current_tx_backend_cfg[backend_idx].sample_rate = sample_rate;
+            my_data->current_tx_backend_cfg[backend_idx].sample_rate =
+                                        backend_cfg.sample_rate;
     }
 
     return ret;
@@ -4788,18 +4812,19 @@
  * goes through all the current usecases and picks the highest
  * bitwidth & samplerate
  */
-bool platform_check_capture_codec_backend_cfg(struct audio_device* adev,
-                                   unsigned int* new_bit_width,
-                                   unsigned int* new_sample_rate)
+static bool platform_check_capture_codec_backend_cfg(struct audio_device* adev,
+                                          int backend_idx,
+                                          struct audio_backend_cfg *backend_cfg)
 {
     bool backend_change = false;
     unsigned int bit_width;
     unsigned int sample_rate;
-    int backend_idx = DEFAULT_CODEC_BACKEND;
+    unsigned int channels;
     struct platform_data *my_data = (struct platform_data *)adev->platform;
 
-    bit_width = *new_bit_width;
-    sample_rate = *new_sample_rate;
+    bit_width = backend_cfg->bit_width;
+    sample_rate = backend_cfg->sample_rate;
+    channels = backend_cfg->channels;
 
     ALOGI("%s:txbecf: afe: Codec selected backend: %d current bit width: %d and "
           "sample rate: %d",__func__,backend_idx, bit_width, sample_rate);
@@ -4814,6 +4839,11 @@
         bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
         sample_rate =  CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
     }
+    if (backend_idx == USB_AUDIO_TX_BACKEND) {
+        audio_extn_usb_is_config_supported(&bit_width, &sample_rate, &channels, false);
+        ALOGV("%s: USB BE configured as bit_width(%d)sample_rate(%d)channels(%d)",
+              __func__, bit_width, sample_rate, channels);
+    }
 
     ALOGI("%s:txbecf: afe: Codec selected backend: %d updated bit width: %d and "
           "sample rate: %d", __func__, backend_idx, bit_width, sample_rate);
@@ -4821,11 +4851,12 @@
     // is not same as current backend comfiguration
     if ((bit_width != my_data->current_tx_backend_cfg[backend_idx].bit_width) ||
         (sample_rate != my_data->current_tx_backend_cfg[backend_idx].sample_rate)) {
-        *new_bit_width = bit_width;
-        *new_sample_rate = sample_rate;
+        backend_cfg->bit_width = bit_width;
+        backend_cfg->sample_rate= sample_rate;
         backend_change = true;
         ALOGI("%s:txbecf: afe: Codec backend needs to be updated. new bit width: %d "
-              "new sample rate: %d", __func__, *new_bit_width, *new_sample_rate);
+              "new sample rate: %d", __func__, backend_cfg->bit_width,
+              backend_cfg->sample_rate);
     }
 
     return backend_change;
@@ -4834,29 +4865,34 @@
 bool platform_check_and_set_capture_codec_backend_cfg(struct audio_device* adev,
     struct audio_usecase *usecase, snd_device_t snd_device)
 {
-    unsigned int new_bit_width;
-    unsigned int new_sample_rate;
-    audio_format_t format = AUDIO_FORMAT_PCM_16_BIT;
-    int backend_idx = DEFAULT_CODEC_BACKEND;
+    int backend_idx = platform_get_capture_backend_index(snd_device);
     int ret = 0;
+    struct audio_backend_cfg backend_cfg;
 
+    backend_cfg.passthrough_enabled = false;
     if(usecase->type == PCM_CAPTURE) {
-        new_sample_rate = usecase->stream.in->sample_rate;
-        new_bit_width = usecase->stream.in->bit_width;
-        format = usecase->stream.in->format;
+        backend_cfg.sample_rate= usecase->stream.in->sample_rate;
+        backend_cfg.bit_width= usecase->stream.in->bit_width;
+        backend_cfg.format= usecase->stream.in->format;
+        backend_cfg.channels = audio_channel_count_from_in_mask(usecase->stream.in->channel_mask);
     } else {
-        new_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
-        new_sample_rate =  CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+        backend_cfg.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+        backend_cfg.sample_rate =  CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+        backend_cfg.format = AUDIO_FORMAT_PCM_16_BIT;
+        backend_cfg.channels = 1;
     }
 
-    ALOGI("%s:txbecf: afe: bitwidth %d, samplerate %d"
-          ", backend_idx %d usecase = %d device (%s)", __func__, new_bit_width,
-          new_sample_rate, backend_idx, usecase->id,
+    ALOGI("%s:txbecf: afe: bitwidth %d, samplerate %d, channel %d"
+          ", backend_idx %d usecase = %d device (%s)", __func__,
+          backend_cfg.bit_width,
+          backend_cfg.sample_rate,
+          backend_cfg.channels,
+          backend_idx, usecase->id,
           platform_get_snd_device_name(snd_device));
-    if (platform_check_capture_codec_backend_cfg(adev, &new_bit_width,
-                                       &new_sample_rate)) {
+    if (platform_check_capture_codec_backend_cfg(adev, backend_idx,
+                                                 &backend_cfg)) {
         ret = platform_set_capture_codec_backend_cfg(adev, snd_device,
-                                       new_bit_width, new_sample_rate, format);
+                                                     backend_cfg);
         if(!ret)
             return true;
     }
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index 516a298..1e54ee1 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -209,7 +209,6 @@
 #define MAX_PORT                        6
 #define ALL_CODEC_BACKEND_PORT          0
 #define HEADPHONE_44_1_BACKEND_PORT     5
-#define MAX_CODEC_TX_BACKENDS           1
 enum {
     DEFAULT_CODEC_BACKEND,
     SLIMBUS_0_RX = DEFAULT_CODEC_BACKEND,
@@ -224,6 +223,12 @@
     USB_AUDIO_RX_BACKEND,
     MAX_CODEC_BACKENDS
 };
+enum {
+    DEFAULT_CODEC_TX_BACKEND,
+    SLIMBUS_0_TX = DEFAULT_CODEC_TX_BACKEND,
+    USB_AUDIO_TX_BACKEND,
+    MAX_CODEC_TX_BACKENDS
+};
 #define AUDIO_PARAMETER_KEY_NATIVE_AUDIO "audio.nat.codec.enabled"
 #define AUDIO_PARAMETER_KEY_NATIVE_AUDIO_MODE "native_audio_mode"
 
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 8327130..91e7235 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -1751,11 +1751,16 @@
     my_data->current_backend_cfg[HEADPHONE_44_1_BACKEND].samplerate_mixer_ctl =
         strdup("SLIM_5_RX SampleRate");
 
-    my_data->current_tx_backend_cfg[DEFAULT_CODEC_BACKEND].bitwidth_mixer_ctl =
+    my_data->current_tx_backend_cfg[DEFAULT_CODEC_TX_BACKEND].bitwidth_mixer_ctl =
         strdup("SLIM_0_TX Format");
-    my_data->current_tx_backend_cfg[DEFAULT_CODEC_BACKEND].samplerate_mixer_ctl =
+    my_data->current_tx_backend_cfg[DEFAULT_CODEC_TX_BACKEND].samplerate_mixer_ctl =
         strdup("SLIM_0_TX SampleRate");
 
+    my_data->current_tx_backend_cfg[USB_AUDIO_TX_BACKEND].bitwidth_mixer_ctl =
+        strdup("USB_AUDIO_TX Format");
+    my_data->current_tx_backend_cfg[USB_AUDIO_TX_BACKEND].samplerate_mixer_ctl =
+        strdup("USB_AUDIO_TX SampleRate");
+
     ret = audio_extn_utils_get_codec_version(snd_card_name,
                                              my_data->adev->snd_card,
                                              my_data->codec_version);
@@ -2355,6 +2360,23 @@
     return port;
 }
 
+static int platform_get_capture_backend_index(snd_device_t snd_device)
+{
+    int32_t port = DEFAULT_CODEC_TX_BACKEND;
+
+    if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX) {
+        if (backend_tag_table[snd_device] != NULL) {
+                if (strcmp(backend_tag_table[snd_device], "usb-headset-mic") == 0)
+                        port = USB_AUDIO_TX_BACKEND;
+        }
+    } else {
+        ALOGW("%s: Invalid device - %d ", __func__, snd_device);
+    }
+
+    ALOGV("%s: backend port - %d snd_device %d", __func__, port, snd_device);
+    return port;
+}
+
 int platform_send_audio_calibration(void *platform, struct audio_usecase *usecase,
                                     int app_type, int sample_rate)
 {
@@ -4599,7 +4621,7 @@
     }
 
     if (backend_idx == USB_AUDIO_RX_BACKEND) {
-        audio_extn_usb_is_config_supported(&bit_width, &sample_rate, &channels);
+        audio_extn_usb_is_config_supported(&bit_width, &sample_rate, &channels, true);
         ALOGV("%s: USB BE configured as bit_width(%d)sample_rate(%d)channels(%d)",
                    __func__, bit_width, sample_rate, channels);
         if (channels != my_data->current_backend_cfg[backend_idx].channels)
@@ -4717,20 +4739,19 @@
  * configures afe with bit width and Sample Rate
  */
 
-int platform_set_capture_codec_backend_cfg(struct audio_device* adev,
+static int platform_set_capture_codec_backend_cfg(struct audio_device* adev,
                          snd_device_t snd_device,
-                         unsigned int bit_width, unsigned int sample_rate,
-                         audio_format_t format)
+                         struct audio_backend_cfg backend_cfg)
 {
     int ret = 0;
-    int backend_idx = DEFAULT_CODEC_BACKEND;
+    int backend_idx = platform_get_capture_backend_index(snd_device);
     struct platform_data *my_data = (struct platform_data *)adev->platform;
 
     ALOGI("%s:txbecf: afe: bitwidth %d, samplerate %d, backend_idx %d device (%s)",
-          __func__, bit_width, sample_rate, backend_idx,
+          __func__, backend_cfg.bit_width, backend_cfg.sample_rate, backend_idx,
           platform_get_snd_device_name(snd_device));
 
-    if (bit_width !=
+    if (backend_cfg.bit_width!=
         my_data->current_tx_backend_cfg[backend_idx].bit_width) {
 
         struct  mixer_ctl *ctl = NULL;
@@ -4742,8 +4763,8 @@
                   my_data->current_tx_backend_cfg[backend_idx].bitwidth_mixer_ctl);
             return -EINVAL;
         }
-        if (bit_width == 24) {
-            if (format == AUDIO_FORMAT_PCM_24_BIT_PACKED)
+        if (backend_cfg.bit_width == 24) {
+            if (backend_cfg.format == AUDIO_FORMAT_PCM_24_BIT_PACKED)
                 ret = mixer_ctl_set_enum_by_string(ctl, "S24_3LE");
             else
                 ret = mixer_ctl_set_enum_by_string(ctl, "S24_LE");
@@ -4758,9 +4779,10 @@
             return -EINVAL;
         }
 
-        my_data->current_tx_backend_cfg[backend_idx].bit_width = bit_width;
+        my_data->current_tx_backend_cfg[backend_idx].bit_width = backend_cfg.bit_width;
         ALOGD("%s:txbecf: afe: %s mixer set to %d bit", __func__,
-              my_data->current_tx_backend_cfg[backend_idx].bitwidth_mixer_ctl, bit_width);
+              my_data->current_tx_backend_cfg[backend_idx].bitwidth_mixer_ctl,
+              backend_cfg.bit_width);
     }
 
     /*
@@ -4773,14 +4795,15 @@
      */
     // TODO: This has to be more dynamic based on policy file
 
-    if (sample_rate != my_data->current_tx_backend_cfg[(int)backend_idx].sample_rate) {
+    if (backend_cfg.sample_rate !=
+        my_data->current_tx_backend_cfg[(int)backend_idx].sample_rate) {
             /*
              * sample rate update is needed only for hifi audio enabled platforms
              */
             char *rate_str = NULL;
             struct  mixer_ctl *ctl = NULL;
 
-            switch (sample_rate) {
+            switch (backend_cfg.sample_rate) {
             case 8000:
             case 11025:
             case 16000:
@@ -4825,7 +4848,8 @@
                 return -EINVAL;
             }
 
-            my_data->current_tx_backend_cfg[backend_idx].sample_rate = sample_rate;
+            my_data->current_tx_backend_cfg[backend_idx].sample_rate =
+                                        backend_cfg.sample_rate;
     }
 
     return ret;
@@ -4835,18 +4859,19 @@
  * goes through all the current usecases and picks the highest
  * bitwidth & samplerate
  */
-bool platform_check_capture_codec_backend_cfg(struct audio_device* adev,
-                                   unsigned int* new_bit_width,
-                                   unsigned int* new_sample_rate)
+static bool platform_check_capture_codec_backend_cfg(struct audio_device* adev,
+                                   int backend_idx,
+                                   struct audio_backend_cfg *backend_cfg)
 {
     bool backend_change = false;
     unsigned int bit_width;
     unsigned int sample_rate;
-    int backend_idx = DEFAULT_CODEC_BACKEND;
+    unsigned int channels;
     struct platform_data *my_data = (struct platform_data *)adev->platform;
 
-    bit_width = *new_bit_width;
-    sample_rate = *new_sample_rate;
+    bit_width = backend_cfg->bit_width;
+    sample_rate = backend_cfg->sample_rate;
+    channels = backend_cfg->channels;
 
     ALOGI("%s:txbecf: afe: Codec selected backend: %d current bit width: %d and "
           "sample rate: %d",__func__,backend_idx, bit_width, sample_rate);
@@ -4860,6 +4885,11 @@
         bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
         sample_rate =  CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
     }
+    if (backend_idx == USB_AUDIO_TX_BACKEND) {
+        audio_extn_usb_is_config_supported(&bit_width, &sample_rate, &channels, false);
+        ALOGV("%s: USB BE configured as bit_width(%d)sample_rate(%d)channels(%d)",
+              __func__, bit_width, sample_rate, channels);
+    }
 
     ALOGI("%s:txbecf: afe: Codec selected backend: %d updated bit width: %d and "
           "sample rate: %d", __func__, backend_idx, bit_width, sample_rate);
@@ -4867,11 +4897,12 @@
     // is not same as current backend comfiguration
     if ((bit_width != my_data->current_tx_backend_cfg[backend_idx].bit_width) ||
         (sample_rate != my_data->current_tx_backend_cfg[backend_idx].sample_rate)) {
-        *new_bit_width = bit_width;
-        *new_sample_rate = sample_rate;
+        backend_cfg->bit_width = bit_width;
+        backend_cfg->sample_rate= sample_rate;
         backend_change = true;
         ALOGI("%s:txbecf: afe: Codec backend needs to be updated. new bit width: %d "
-              "new sample rate: %d", __func__, *new_bit_width, *new_sample_rate);
+              "new sample rate: %d", __func__, backend_cfg->bit_width,
+              backend_cfg->sample_rate);
     }
 
     return backend_change;
@@ -4880,28 +4911,34 @@
 bool platform_check_and_set_capture_codec_backend_cfg(struct audio_device* adev,
     struct audio_usecase *usecase, snd_device_t snd_device)
 {
-    unsigned int new_bit_width;
-    unsigned int new_sample_rate;
-    audio_format_t format = AUDIO_FORMAT_PCM_16_BIT;
-    int backend_idx = DEFAULT_CODEC_BACKEND;
+    int backend_idx = platform_get_capture_backend_index(snd_device);
     int ret = 0;
+    struct audio_backend_cfg backend_cfg;
+
+    backend_cfg.passthrough_enabled = false;
     if(usecase->type == PCM_CAPTURE) {
-        new_sample_rate = usecase->stream.in->sample_rate;
-        new_bit_width = usecase->stream.in->bit_width;
-        format = usecase->stream.in->format;
+        backend_cfg.sample_rate= usecase->stream.in->sample_rate;
+        backend_cfg.bit_width= usecase->stream.in->bit_width;
+        backend_cfg.format= usecase->stream.in->format;
+        backend_cfg.channels = audio_channel_count_from_in_mask(usecase->stream.in->channel_mask);
     } else {
-        new_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
-        new_sample_rate =  CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+        backend_cfg.bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+        backend_cfg.sample_rate =  CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+        backend_cfg.format = AUDIO_FORMAT_PCM_16_BIT;
+        backend_cfg.channels = 1;
     }
 
-    ALOGI("%s:txbecf: afe: bitwidth %d, samplerate %d"
-          ", backend_idx %d usecase = %d device (%s)", __func__, new_bit_width,
-          new_sample_rate, backend_idx, usecase->id,
+    ALOGI("%s:txbecf: afe: bitwidth %d, samplerate %d, channel %d"
+          ", backend_idx %d usecase = %d device (%s)", __func__,
+          backend_cfg.bit_width,
+          backend_cfg.sample_rate,
+          backend_cfg.channels,
+          backend_idx, usecase->id,
           platform_get_snd_device_name(snd_device));
-    if (platform_check_capture_codec_backend_cfg(adev, &new_bit_width,
-                                                 &new_sample_rate)) {
+    if (platform_check_capture_codec_backend_cfg(adev, backend_idx,
+                                                 &backend_cfg)) {
         ret = platform_set_capture_codec_backend_cfg(adev, snd_device,
-                                       new_bit_width, new_sample_rate, format);
+                                                     backend_cfg);
         if(!ret)
             return true;
     }
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 9b8c01b..bcf5d93 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -201,7 +201,6 @@
 #define OUTPUT_SAMPLING_RATE_44100      44100
 #define OUTPUT_SAMPLING_RATE_DSD64       176400
 #define OUTPUT_SAMPLING_RATE_DSD128      352800
-#define MAX_CODEC_TX_BACKENDS           1
 enum {
     DEFAULT_CODEC_BACKEND,
     SLIMBUS_0_RX = DEFAULT_CODEC_BACKEND,
@@ -217,6 +216,13 @@
     MAX_CODEC_BACKENDS
 };
 
+enum {
+    DEFAULT_CODEC_TX_BACKEND,
+    SLIMBUS_0_TX = DEFAULT_CODEC_TX_BACKEND,
+    USB_AUDIO_TX_BACKEND,
+    MAX_CODEC_TX_BACKENDS
+};
+
 #define AUDIO_PARAMETER_KEY_NATIVE_AUDIO "audio.nat.codec.enabled"
 #define AUDIO_PARAMETER_KEY_NATIVE_AUDIO_MODE "native_audio_mode"