audio: usb: Set endianness mixer control

Derive supported endianness from usb stream_info
and use it to configure USB interface. This is
needed to configure AFE with the appropriate
endianness supported by a USB DAC.

CRs-Fixed: 2003730
Change-Id: I0b0af613743c00c2704e4732a8ddb8d43adbd20f
diff --git a/hal/audio_extn/usb.c b/hal/audio_extn/usb.c
index d0225ec..7416e92 100644
--- a/hal/audio_extn/usb.c
+++ b/hal/audio_extn/usb.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013, 2016-2017 The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -79,6 +79,7 @@
     int usb_sidetone_index[USB_SIDETONE_MAX_INDEX];
     int usb_sidetone_vol_min;
     int usb_sidetone_vol_max;
+    int endian;
 };
 
 struct usb_module {
@@ -216,6 +217,29 @@
     return 0;
 }
 
+static int usb_set_endian_mixer_ctl(int endian, char *endian_mixer_ctl_name)
+{
+    struct mixer_ctl *ctl = mixer_get_ctl_by_name(usbmod->adev->mixer,
+                                                  endian_mixer_ctl_name);
+    if (!ctl) {
+       ALOGE("%s: Could not get ctl for mixer cmd - %s",
+             __func__, endian_mixer_ctl_name);
+       return -EINVAL;
+    }
+
+    switch (endian) {
+       case 0:
+       case 1:
+           mixer_ctl_set_value(ctl, 0, endian);
+           break;
+       default:
+           ALOGW("%s: endianness(%d) not supported",
+                 __func__, endian);
+           break;
+    }
+    return 0;
+}
+
 static int usb_get_sample_rates(char *rates_str,
                                 struct usb_device_config *config)
 {
@@ -377,14 +401,17 @@
         }
         memcpy(bit_width_str, bit_width_start, size);
         bit_width_str[size] = '\0';
-        if (strstr(bit_width_str, "S16_LE"))
-            usb_device_info->bit_width = 16;
-        else if (strstr(bit_width_str, "S24_LE"))
-            usb_device_info->bit_width = 24;
-        else if (strstr(bit_width_str, "S24_3LE"))
-            usb_device_info->bit_width = 24;
-        else if (strstr(bit_width_str, "S32_LE"))
-            usb_device_info->bit_width = 32;
+
+        const char * formats[] = { "S32", "S24_3", "S24", "S16" };
+        const int    bit_width[] = { 32,  24,      24,     16};
+        for (size_t i = 0; i < ARRAY_SIZE(formats); i++) {
+            const char * s = strstr(bit_width_str, formats[i]);
+            if (s) {
+                usb_device_info->bit_width = bit_width[i];
+                usb_card_info->endian = strstr(s, "BE") ? 1 : 0;
+                break;
+            }
+        }
 
         if (bit_width_str)
             free(bit_width_str);
@@ -454,7 +481,7 @@
         goto exit;
     }
     usb_set_dev_id_mixer_ctl(USB_PLAYBACK, card, "USB_AUDIO_RX dev_token");
-
+    usb_set_endian_mixer_ctl(usb_card_info->endian, "USB_AUDIO_RX endian");
 exit:
 
     return ret;
@@ -472,6 +499,7 @@
         goto exit;
     }
     usb_set_dev_id_mixer_ctl(USB_CAPTURE, card, "USB_AUDIO_TX dev_token");
+    usb_set_endian_mixer_ctl(usb_card_info->endian, "USB_AUDIO_TX endian");
 
 exit:
     return ret;
@@ -535,12 +563,13 @@
     ALOGI("%s", __func__);
     list_for_each(node_i, &usbmod->usb_card_conf_list) {
         card_info = node_to_item(node_i, struct usb_card_config, list);
-        ALOGI("%s: card_dev_type (0x%x), card_no(%d)",
-               __func__,  card_info->usb_device_type, card_info->usb_card);
+        ALOGI("%s: card_dev_type (0x%x), card_no(%d), %s",
+               __func__,  card_info->usb_device_type,
+              card_info->usb_card, card_info->endian ? "BE" : "LE");
         list_for_each(node_j, &card_info->usb_device_conf_list) {
             dev_info = node_to_item(node_j, struct usb_device_config, list);
             ALOGI("%s: bit-width(%d) channel(%d)",
-                   __func__, dev_info->bit_width, dev_info->channels);
+                  __func__, dev_info->bit_width, dev_info->channels);
             for (i =  0; i < dev_info->rate_size; i++)
                 ALOGI("%s: rate %d", __func__, dev_info->rates[i]);
         }