sound: usb: Populate tunnel mode response struct for BADD devices

For tunnel mode audio functionality, we need to populate
some fields of the QMI response structure with some UAC
device exposed values namely bDelay, bcdADC and
SubSlotSize. Add support for filling in subslotsize
field for BADD 3.0 devices. bDelay and bcdADC fields
are not supported in Audio 3.0 devices.

Change-Id: I26a41bf05e66116511c1b5cf9629a4a9f9c49ab0
Signed-off-by: Ajay Agarwal <ajaya@codeaurora.org>
Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
diff --git a/sound/usb/usb_audio_qmi_svc.c b/sound/usb/usb_audio_qmi_svc.c
index 5a1974e..801508c 100644
--- a/sound/usb/usb_audio_qmi_svc.c
+++ b/sound/usb/usb_audio_qmi_svc.c
@@ -27,6 +27,7 @@
 #include <soc/qcom/msm_qmi_interface.h>
 #include <linux/iommu.h>
 #include <linux/platform_device.h>
+#include <linux/usb/audio-v3.h>
 
 #include "usbaudio.h"
 #include "card.h"
@@ -427,12 +428,14 @@
 	protocol = altsd->bInterfaceProtocol;
 
 	/* get format type */
-	fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL,
-			UAC_FORMAT_TYPE);
-	if (!fmt) {
-		pr_err("%s: %u:%d : no UAC_FORMAT_TYPE desc\n", __func__,
-			subs->interface, subs->altset_idx);
-		goto err;
+	if (protocol != UAC_VERSION_3) {
+		fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL,
+				UAC_FORMAT_TYPE);
+		if (!fmt) {
+			pr_err("%s: %u:%d : no UAC_FORMAT_TYPE desc\n",
+				__func__, subs->interface, subs->altset_idx);
+			goto err;
+		}
 	}
 
 	if (!uadev[card_num].ctrl_intf) {
@@ -440,12 +443,15 @@
 		goto err;
 	}
 
-	hdr_ptr = snd_usb_find_csint_desc(uadev[card_num].ctrl_intf->extra,
-					uadev[card_num].ctrl_intf->extralen,
-					NULL, UAC_HEADER);
-	if (!hdr_ptr) {
-		pr_err("%s: no UAC_HEADER desc\n", __func__);
-		goto err;
+	if (protocol != UAC_VERSION_3) {
+		hdr_ptr = snd_usb_find_csint_desc(
+				uadev[card_num].ctrl_intf->extra,
+				uadev[card_num].ctrl_intf->extralen,
+				NULL, UAC_HEADER);
+		if (!hdr_ptr) {
+			pr_err("%s: no UAC_HEADER desc\n", __func__);
+			goto err;
+		}
 	}
 
 	if (protocol == UAC_VERSION_1) {
@@ -473,6 +479,31 @@
 		resp->usb_audio_spec_revision =
 			((struct uac2_ac_header_descriptor *)hdr_ptr)->bcdADC;
 		resp->usb_audio_spec_revision_valid = 1;
+	} else if (protocol == UAC_VERSION_3) {
+		switch (le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize)) {
+		case BADD_MAXPSIZE_SYNC_MONO_16:
+		case BADD_MAXPSIZE_SYNC_STEREO_16:
+		case BADD_MAXPSIZE_ASYNC_MONO_16:
+		case BADD_MAXPSIZE_ASYNC_STEREO_16: {
+			resp->usb_audio_subslot_size = SUBSLOTSIZE_16_BIT;
+			break;
+		}
+
+		case BADD_MAXPSIZE_SYNC_MONO_24:
+		case BADD_MAXPSIZE_SYNC_STEREO_24:
+		case BADD_MAXPSIZE_ASYNC_MONO_24:
+		case BADD_MAXPSIZE_ASYNC_STEREO_24: {
+			resp->usb_audio_subslot_size = SUBSLOTSIZE_24_BIT;
+			break;
+		}
+
+		default:
+			pr_err("%d: %u: Invalid wMaxPacketSize\n",
+				subs->interface, subs->altset_idx);
+			ret = -EINVAL;
+			goto err;
+		}
+		resp->usb_audio_subslot_size_valid = 1;
 	} else {
 		pr_err("%s: unknown protocol version %x\n", __func__, protocol);
 		goto err;