alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Add quirk to enable Avid Mbox 3 support
@ 2022-04-17  2:54 connerknoxpublic
  2022-08-16  0:44 ` mbarriolinares
  0 siblings, 1 reply; 9+ messages in thread
From: connerknoxpublic @ 2022-04-17  2:54 UTC (permalink / raw)
  To: perex, tiwai, alsa-devel; +Cc: Conner Knox

From: Conner Knox <connerknoxpublic@gmail.com>

Hi all,

I believe these are the right emails to send this patch to,
but if I've missed something please let me know.

This patch enables the Avid Mbox 3 audio interface to
be used through ALSA.  It locks the device at a 48khz sample rate.
Then it mutes and raises the appropriate channels/inputs to allow
for expected functionality.

Thanks for your time.

---
 sound/usb/quirks-table.h |  76 ++++++++++
 sound/usb/quirks.c       | 311 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 387 insertions(+)

diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 0ea39565e623..5f43863e5a5f 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2978,6 +2978,82 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 		}
 	}
 },
+/* DIGIDESIGN MBOX 3 */
+{
+	USB_DEVICE(0x0dba, 0x5000),
+	.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+		.vendor_name = "Digidesign",
+		.product_name = "Mbox 3",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const struct snd_usb_audio_quirk[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+					.formats = SNDRV_PCM_FMTBIT_S24_3LE,
+					.channels = 4,
+					.iface = 2,
+					.altsetting = 1,
+					.altset_idx = 1,
+					.attributes = 0x00,
+					.endpoint = 0x01,
+					.ep_attr = USB_ENDPOINT_XFER_ISOC |
+						USB_ENDPOINT_SYNC_ASYNC,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 3,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+					.formats = SNDRV_PCM_FMTBIT_S24_3LE,
+					.channels = 4,
+					.iface = 3,
+					.altsetting = 1,
+					.altset_idx = 1,
+					.endpoint = 0x81,
+					.attributes = 0x00,
+					.ep_attr = USB_ENDPOINT_XFER_ISOC |
+						USB_ENDPOINT_SYNC_ASYNC,
+					.maxpacksize = 0x009c,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 4,
+				.type = QUIRK_MIDI_FIXED_ENDPOINT,
+				.data = & (const struct snd_usb_midi_endpoint_info) {
+					.out_cables = 0x0001,
+					.in_cables  = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
 {
 	/* Tascam US122 MKII - playback-only support */
 	USB_DEVICE_VENDOR_SPEC(0x0644, 0x8021),
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index ab9f3da49941..e7caa7eeb955 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1020,6 +1020,313 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device *dev)
 	return 0;
 }
 
+static void mbox3_setup_48_24_magic(struct usb_device *dev)
+{
+	u8 com_buff[4];
+
+	/* Load 48000Hz rate into buffer */
+	com_buff[0] = 0x80;
+	com_buff[1] = 0xbb;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+
+	/* Set 48000Hz sample rate */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			0x01, 0x21, 0x0100, 0x0001, &com_buff, 0x0004);
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			0x01, 0x21, 0x0100, 0x8101, &com_buff, 0x0004);
+
+	/* Set clock source to Internal (as opposed to S/PDIF) */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x01;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0100, 0x8001, &com_buff, 1);
+
+	/* Mute the hardware loopbacks to start the device in a known state.
+	 * The Mbox 3 is little endian and
+	 * the data written here seems a bit odd.
+	 * 0x8000 (shown in big endian form) is muted
+	 * and volume increases to 0xffff it seems.
+	 * I've yet to observe 0xffff being sent.
+	 * Instead, full volume seems to be 0x0000.
+	 * Per my understanding of 16 bit integers, this is seems strange, but maybe I'm missing something
+	 */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x80;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	/* Analogue input 1 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0110, 0x4001, &com_buff, 2);
+	/* Analogue input 1 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0111, 0x4001, &com_buff, 2);
+	/* Analogue input 2 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0114, 0x4001, &com_buff, 2);
+	/* Analogue input 2 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0115, 0x4001, &com_buff, 2);
+	/* Analogue input 3 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0118, 0x4001, &com_buff, 2);
+	/* Analogue input 3 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0119, 0x4001, &com_buff, 2);
+	/* Analogue input 4 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011c, 0x4001, &com_buff, 2);
+	/* Analogue input 4 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011d, 0x4001, &com_buff, 2);
+
+	/* Set software sends to output */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	/* Analogue software return 1 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0100, 0x4001, &com_buff, 2);
+	/* Analogue software return 1 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0101, 0x4001, &com_buff, 2);
+	/* Analogue software return 2 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0104, 0x4001, &com_buff, 2);
+	/* Analogue software return 2 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0105, 0x4001, &com_buff, 2);
+	/* Analogue software return 3 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0108, 0x4001, &com_buff, 2);
+	/* Analogue software return 3 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0109, 0x4001, &com_buff, 2);
+	/* Analogue software return 4 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010c, 0x4001, &com_buff, 2);
+	/* Analogue software return 4 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010d, 0x4001, &com_buff, 2);
+
+	/* Return to muting sends */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x80;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	/* Analogue fx return left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0120, 0x4001, &com_buff, 2);
+	/* Analogue fx return right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0121, 0x4001, &com_buff, 2);
+
+	/* Analogue software input 1 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0100, 0x4201, &com_buff, 2);
+	/* Analogue software input 2 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0101, 0x4201, &com_buff, 2);
+	/* Analogue software input 3 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0102, 0x4201, &com_buff, 2);
+	/* Analogue software input 4 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0103, 0x4201, &com_buff, 2);
+	/* Analogue input 1 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0104, 0x4201, &com_buff, 2);
+	/* Analogue input 2 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0105, 0x4201, &com_buff, 2);
+	/* Analogue input 3 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0106, 0x4201, &com_buff, 2);
+	/* Analogue input 4 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0107, 0x4201, &com_buff, 2);
+
+	/* Toggle allowing host control */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x02;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			3, 0x21, 0x0000, 0x2001, &com_buff, 1);
+
+	/* Do not dim fx returns */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3, 0x21, 0x0002, 0x2001, &com_buff, 1);
+
+	/* Do not set fx returns to mono */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3, 0x21, 0x0001, 0x2001, &com_buff, 1);
+
+	/* Mute the S/PDIF hardware loopback
+	 * same odd volume logic here as above
+	 */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x80;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	/* S/PDIF hardware input 1 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0112, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 1 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0113, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 2 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0116, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 2 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0117, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 3 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011a, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 3 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011b, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 4 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011e, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 4 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011f, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 1 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0102, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 1 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0103, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 2 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0106, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 2 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0107, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 3 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010a, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 3 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010b, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 4 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010e, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 4 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010f, 0x4001, &com_buff, 2);
+	/* S/PDIF fx returns left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0122, 0x4001, &com_buff, 2);
+	/* S/PDIF fx returns right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0123, 0x4001, &com_buff, 2);
+
+	/* Set the dropdown "Effect" to the first option */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0200, 0x4301, &com_buff, 1);
+
+	/* Set the effect duration to 0 */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0400, 0x4301, &com_buff, 2);
+
+	/* Set the effect volume and feedback to 0 */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	/* feedback: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0500, 0x4301, &com_buff, 1);
+	/* volume: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0300, 0x4301, &com_buff, 1);
+
+	/* Set soft button hold duration */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x05;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			3, 0x21, 0x0005, 0x2001, &com_buff, 1);
+
+	/* Use dim LEDs for button of state */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			3, 0x21, 0x0004, 0x2001, &com_buff, 1);
+
+	return;
+}
+
+#define MBOX3_DESCRIPTOR_SIZE	464
+
+static int snd_usb_mbox3_boot_quirk(struct usb_device *dev)
+{
+	struct usb_host_config *config = dev->actconfig;
+	int err;
+	int descriptor_size;
+
+	descriptor_size = le16_to_cpu(get_cfg_desc(config)->wTotalLength);
+
+	if (descriptor_size != MBOX3_DESCRIPTOR_SIZE) {
+		dev_err(&dev->dev, "Invalid descriptor size=%d.\n", descriptor_size);
+		return -ENODEV;
+	}
+
+	dev_dbg(&dev->dev, "device initialised!\n");
+
+	err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
+		&dev->descriptor, sizeof(dev->descriptor));
+	config = dev->actconfig;
+	if (err < 0)
+		dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err);
+
+	err = usb_reset_configuration(dev);
+	if (err < 0)
+		dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err);
+	dev_dbg(&dev->dev, "mbox3_boot: new boot length = %d\n",
+		le16_to_cpu(get_cfg_desc(config)->wTotalLength));
+
+	mbox3_setup_48_24_magic(dev);
+	dev_info(&dev->dev, "Digidesign Mbox 3: 24bit 48kHz");
+
+	return 0; /* Successful boot */
+}
 
 #define MICROBOOK_BUF_SIZE 128
 
@@ -1324,6 +1631,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
 	case USB_ID(0x0dba, 0x3000):
 		/* Digidesign Mbox 2 */
 		return snd_usb_mbox2_boot_quirk(dev);
+	case USB_ID(0x0dba, 0x5000):
+		/* Digidesign Mbox 3 */
+		return snd_usb_mbox3_boot_quirk(dev);
+
 
 	case USB_ID(0x1235, 0x0010): /* Focusrite Novation Saffire 6 USB */
 	case USB_ID(0x1235, 0x0018): /* Focusrite Novation Twitch */
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH] Add quirk to enable Avid Mbox 3 support
  2022-04-17  2:54 [PATCH] Add quirk to enable Avid Mbox 3 support connerknoxpublic
@ 2022-08-16  0:44 ` mbarriolinares
  2022-08-16  6:04   ` Takashi Iwai
  0 siblings, 1 reply; 9+ messages in thread
From: mbarriolinares @ 2022-08-16  0:44 UTC (permalink / raw)
  To: connerknoxpublic; +Cc: alsa-devel, tiwai

> Hi all,
> 
> I believe these are the right emails to send this patch to,
> but if I've missed something please let me know.
> 
> This patch enables the Avid Mbox 3 audio interface to
> be used through ALSA.  It locks the device at a 48khz sample rate.
> Then it mutes and raises the appropriate channels/inputs to allow
> for expected functionality.
> 
> Thanks for your time.

Thanks Conner for taking the time to write and submit this!

I have an MBox 3 (USB) and I've tested the patch:

1. Have not tested S/PDIF i/o because I don't have hardware to plug it.
2. Output is in mono. It seems the monitor outputs work only in MONO. 
   (with and without the front mono button switched on or off).
3. Haven't tested if Headphones output work in stereo because I don't
   have hardware for testing.
3. Inputs work great. 

I'll get a stereo 1/4'' jack to 3.5mm for testing the headphones out.
You can contact me directly if needed.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Add quirk to enable Avid Mbox 3 support
  2022-08-16  0:44 ` mbarriolinares
@ 2022-08-16  6:04   ` Takashi Iwai
  2022-08-17  7:15     ` connerknoxpublic
  0 siblings, 1 reply; 9+ messages in thread
From: Takashi Iwai @ 2022-08-16  6:04 UTC (permalink / raw)
  To: mbarriolinares; +Cc: alsa-devel, tiwai, connerknoxpublic

On Tue, 16 Aug 2022 02:44:27 +0200,
mbarriolinares wrote:
> 
> > Hi all,
> > 
> > I believe these are the right emails to send this patch to,
> > but if I've missed something please let me know.
> > 
> > This patch enables the Avid Mbox 3 audio interface to
> > be used through ALSA.  It locks the device at a 48khz sample rate.
> > Then it mutes and raises the appropriate channels/inputs to allow
> > for expected functionality.
> > 
> > Thanks for your time.
> 
> Thanks Conner for taking the time to write and submit this!
> 
> I have an MBox 3 (USB) and I've tested the patch:
> 
> 1. Have not tested S/PDIF i/o because I don't have hardware to plug it.
> 2. Output is in mono. It seems the monitor outputs work only in MONO. 
>    (with and without the front mono button switched on or off).
> 3. Haven't tested if Headphones output work in stereo because I don't
>    have hardware for testing.
> 3. Inputs work great. 
> 
> I'll get a stereo 1/4'' jack to 3.5mm for testing the headphones out.
> You can contact me directly if needed.

It seems that I overlooked this patch some how.

Through a quick glance, the patch needs the proper Signed-off-by line,
at least, for merging to the upstream.  Also, simple memset() with
zero could be used for clearing the com_buf.  Otherwise, it's fine to
apply as long as the stuff works more or less (at least improving
things).


thanks,

Takashi

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH] Add quirk to enable Avid Mbox 3 support
  2022-08-16  6:04   ` Takashi Iwai
@ 2022-08-17  7:15     ` connerknoxpublic
  2022-08-17  7:45       ` Takashi Iwai
  0 siblings, 1 reply; 9+ messages in thread
From: connerknoxpublic @ 2022-08-17  7:15 UTC (permalink / raw)
  To: perex, tiwai, alsa-devel, mbarriolinares; +Cc: Conner Knox

From: Conner Knox <connerknoxpublic@gmail.com>

Appreciate the attention on this, no worries on the wait.
I figured I might have sent something to the wrong spot.

I've added the Signed-off-by line, appologies for
missing that requirement - first time contributor. As
such, please let me know if I need to change
anything else.

I had some memset's in the code already, and the excess
0s were for clarity of what was in the buffer.
Since I wasn't sure exactly what the recommendation was
I left the code alone.  Let me know if it needs changed.

I may make further changes to address the aforementioned
shortcomings when I get time as well.

Thanks again for your time.

Signed-off-by: Conner Knox <connerknoxpublic@gmail.com>
---
 sound/usb/quirks-table.h |  76 ++++++++++
 sound/usb/quirks.c       | 311 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 387 insertions(+)

diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 0ea39565e623..5f43863e5a5f 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2978,6 +2978,82 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 		}
 	}
 },
+/* DIGIDESIGN MBOX 3 */
+{
+	USB_DEVICE(0x0dba, 0x5000),
+	.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+		.vendor_name = "Digidesign",
+		.product_name = "Mbox 3",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const struct snd_usb_audio_quirk[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+					.formats = SNDRV_PCM_FMTBIT_S24_3LE,
+					.channels = 4,
+					.iface = 2,
+					.altsetting = 1,
+					.altset_idx = 1,
+					.attributes = 0x00,
+					.endpoint = 0x01,
+					.ep_attr = USB_ENDPOINT_XFER_ISOC |
+						USB_ENDPOINT_SYNC_ASYNC,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 3,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+					.formats = SNDRV_PCM_FMTBIT_S24_3LE,
+					.channels = 4,
+					.iface = 3,
+					.altsetting = 1,
+					.altset_idx = 1,
+					.endpoint = 0x81,
+					.attributes = 0x00,
+					.ep_attr = USB_ENDPOINT_XFER_ISOC |
+						USB_ENDPOINT_SYNC_ASYNC,
+					.maxpacksize = 0x009c,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 4,
+				.type = QUIRK_MIDI_FIXED_ENDPOINT,
+				.data = & (const struct snd_usb_midi_endpoint_info) {
+					.out_cables = 0x0001,
+					.in_cables  = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
 {
 	/* Tascam US122 MKII - playback-only support */
 	USB_DEVICE_VENDOR_SPEC(0x0644, 0x8021),
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index ab9f3da49941..e7caa7eeb955 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1020,6 +1020,313 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device *dev)
 	return 0;
 }
 
+static void mbox3_setup_48_24_magic(struct usb_device *dev)
+{
+	u8 com_buff[4];
+
+	/* Load 48000Hz rate into buffer */
+	com_buff[0] = 0x80;
+	com_buff[1] = 0xbb;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+
+	/* Set 48000Hz sample rate */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			0x01, 0x21, 0x0100, 0x0001, &com_buff, 0x0004);
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			0x01, 0x21, 0x0100, 0x8101, &com_buff, 0x0004);
+
+	/* Set clock source to Internal (as opposed to S/PDIF) */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x01;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0100, 0x8001, &com_buff, 1);
+
+	/* Mute the hardware loopbacks to start the device in a known state.
+	 * The Mbox 3 is little endian and
+	 * the data written here seems a bit odd.
+	 * 0x8000 (shown in big endian form) is muted
+	 * and volume increases to 0xffff it seems.
+	 * I've yet to observe 0xffff being sent.
+	 * Instead, full volume seems to be 0x0000.
+	 * Per my understanding of 16 bit integers, this is seems strange, but maybe I'm missing something
+	 */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x80;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	/* Analogue input 1 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0110, 0x4001, &com_buff, 2);
+	/* Analogue input 1 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0111, 0x4001, &com_buff, 2);
+	/* Analogue input 2 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0114, 0x4001, &com_buff, 2);
+	/* Analogue input 2 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0115, 0x4001, &com_buff, 2);
+	/* Analogue input 3 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0118, 0x4001, &com_buff, 2);
+	/* Analogue input 3 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0119, 0x4001, &com_buff, 2);
+	/* Analogue input 4 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011c, 0x4001, &com_buff, 2);
+	/* Analogue input 4 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011d, 0x4001, &com_buff, 2);
+
+	/* Set software sends to output */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	/* Analogue software return 1 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0100, 0x4001, &com_buff, 2);
+	/* Analogue software return 1 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0101, 0x4001, &com_buff, 2);
+	/* Analogue software return 2 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0104, 0x4001, &com_buff, 2);
+	/* Analogue software return 2 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0105, 0x4001, &com_buff, 2);
+	/* Analogue software return 3 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0108, 0x4001, &com_buff, 2);
+	/* Analogue software return 3 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0109, 0x4001, &com_buff, 2);
+	/* Analogue software return 4 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010c, 0x4001, &com_buff, 2);
+	/* Analogue software return 4 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010d, 0x4001, &com_buff, 2);
+
+	/* Return to muting sends */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x80;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	/* Analogue fx return left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0120, 0x4001, &com_buff, 2);
+	/* Analogue fx return right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0121, 0x4001, &com_buff, 2);
+
+	/* Analogue software input 1 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0100, 0x4201, &com_buff, 2);
+	/* Analogue software input 2 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0101, 0x4201, &com_buff, 2);
+	/* Analogue software input 3 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0102, 0x4201, &com_buff, 2);
+	/* Analogue software input 4 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0103, 0x4201, &com_buff, 2);
+	/* Analogue input 1 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0104, 0x4201, &com_buff, 2);
+	/* Analogue input 2 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0105, 0x4201, &com_buff, 2);
+	/* Analogue input 3 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0106, 0x4201, &com_buff, 2);
+	/* Analogue input 4 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0107, 0x4201, &com_buff, 2);
+
+	/* Toggle allowing host control */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x02;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			3, 0x21, 0x0000, 0x2001, &com_buff, 1);
+
+	/* Do not dim fx returns */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3, 0x21, 0x0002, 0x2001, &com_buff, 1);
+
+	/* Do not set fx returns to mono */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3, 0x21, 0x0001, 0x2001, &com_buff, 1);
+
+	/* Mute the S/PDIF hardware loopback
+	 * same odd volume logic here as above
+	 */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x80;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	/* S/PDIF hardware input 1 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0112, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 1 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0113, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 2 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0116, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 2 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0117, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 3 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011a, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 3 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011b, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 4 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011e, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 4 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011f, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 1 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0102, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 1 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0103, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 2 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0106, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 2 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0107, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 3 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010a, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 3 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010b, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 4 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010e, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 4 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010f, 0x4001, &com_buff, 2);
+	/* S/PDIF fx returns left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0122, 0x4001, &com_buff, 2);
+	/* S/PDIF fx returns right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0123, 0x4001, &com_buff, 2);
+
+	/* Set the dropdown "Effect" to the first option */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0200, 0x4301, &com_buff, 1);
+
+	/* Set the effect duration to 0 */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0400, 0x4301, &com_buff, 2);
+
+	/* Set the effect volume and feedback to 0 */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	/* feedback: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0500, 0x4301, &com_buff, 1);
+	/* volume: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0300, 0x4301, &com_buff, 1);
+
+	/* Set soft button hold duration */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x05;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			3, 0x21, 0x0005, 0x2001, &com_buff, 1);
+
+	/* Use dim LEDs for button of state */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			3, 0x21, 0x0004, 0x2001, &com_buff, 1);
+
+	return;
+}
+
+#define MBOX3_DESCRIPTOR_SIZE	464
+
+static int snd_usb_mbox3_boot_quirk(struct usb_device *dev)
+{
+	struct usb_host_config *config = dev->actconfig;
+	int err;
+	int descriptor_size;
+
+	descriptor_size = le16_to_cpu(get_cfg_desc(config)->wTotalLength);
+
+	if (descriptor_size != MBOX3_DESCRIPTOR_SIZE) {
+		dev_err(&dev->dev, "Invalid descriptor size=%d.\n", descriptor_size);
+		return -ENODEV;
+	}
+
+	dev_dbg(&dev->dev, "device initialised!\n");
+
+	err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
+		&dev->descriptor, sizeof(dev->descriptor));
+	config = dev->actconfig;
+	if (err < 0)
+		dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err);
+
+	err = usb_reset_configuration(dev);
+	if (err < 0)
+		dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err);
+	dev_dbg(&dev->dev, "mbox3_boot: new boot length = %d\n",
+		le16_to_cpu(get_cfg_desc(config)->wTotalLength));
+
+	mbox3_setup_48_24_magic(dev);
+	dev_info(&dev->dev, "Digidesign Mbox 3: 24bit 48kHz");
+
+	return 0; /* Successful boot */
+}
 
 #define MICROBOOK_BUF_SIZE 128
 
@@ -1324,6 +1631,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
 	case USB_ID(0x0dba, 0x3000):
 		/* Digidesign Mbox 2 */
 		return snd_usb_mbox2_boot_quirk(dev);
+	case USB_ID(0x0dba, 0x5000):
+		/* Digidesign Mbox 3 */
+		return snd_usb_mbox3_boot_quirk(dev);
+
 
 	case USB_ID(0x1235, 0x0010): /* Focusrite Novation Saffire 6 USB */
 	case USB_ID(0x1235, 0x0018): /* Focusrite Novation Twitch */
-- 
2.37.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH] Add quirk to enable Avid Mbox 3 support
  2022-08-17  7:15     ` connerknoxpublic
@ 2022-08-17  7:45       ` Takashi Iwai
  2022-08-17 16:27         ` connerknoxpublic
  0 siblings, 1 reply; 9+ messages in thread
From: Takashi Iwai @ 2022-08-17  7:45 UTC (permalink / raw)
  To: connerknoxpublic; +Cc: mbarriolinares, alsa-devel, tiwai

On Wed, 17 Aug 2022 09:15:50 +0200,
connerknoxpublic@gmail.com wrote:
> 
> From: Conner Knox <connerknoxpublic@gmail.com>
> 
> Appreciate the attention on this, no worries on the wait.
> I figured I might have sent something to the wrong spot.
> 
> I've added the Signed-off-by line, appologies for
> missing that requirement - first time contributor. As
> such, please let me know if I need to change
> anything else.
> 
> I had some memset's in the code already, and the excess
> 0s were for clarity of what was in the buffer.
> Since I wasn't sure exactly what the recommendation was
> I left the code alone.  Let me know if it needs changed.
> 
> I may make further changes to address the aforementioned
> shortcomings when I get time as well.
> 
> Thanks again for your time.
> 
> Signed-off-by: Conner Knox <connerknoxpublic@gmail.com>

Now we have signed-off-by line, but the patch description should
contain what to be put in the git commit log.  So please write what
your patch fixes and some technical details if you want to add there.

The rest comments could be put after the line "---" if you want, but
usually not needed unless you need extra notes.

Care to resubmit with the proper patch description, so that I can take
it as is?


thanks,

Takashi

> ---
>  sound/usb/quirks-table.h |  76 ++++++++++
>  sound/usb/quirks.c       | 311 +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 387 insertions(+)
> 
> diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
> index 0ea39565e623..5f43863e5a5f 100644
> --- a/sound/usb/quirks-table.h
> +++ b/sound/usb/quirks-table.h
> @@ -2978,6 +2978,82 @@ YAMAHA_DEVICE(0x7010, "UB99"),
>  		}
>  	}
>  },
> +/* DIGIDESIGN MBOX 3 */
> +{
> +	USB_DEVICE(0x0dba, 0x5000),
> +	.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
> +		.vendor_name = "Digidesign",
> +		.product_name = "Mbox 3",
> +		.ifnum = QUIRK_ANY_INTERFACE,
> +		.type = QUIRK_COMPOSITE,
> +		.data = (const struct snd_usb_audio_quirk[]) {
> +			{
> +				.ifnum = 0,
> +				.type = QUIRK_IGNORE_INTERFACE
> +			},
> +			{
> +				.ifnum = 1,
> +				.type = QUIRK_IGNORE_INTERFACE
> +			},
> +			{
> +				.ifnum = 2,
> +				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
> +				.data = &(const struct audioformat) {
> +					.formats = SNDRV_PCM_FMTBIT_S24_3LE,
> +					.channels = 4,
> +					.iface = 2,
> +					.altsetting = 1,
> +					.altset_idx = 1,
> +					.attributes = 0x00,
> +					.endpoint = 0x01,
> +					.ep_attr = USB_ENDPOINT_XFER_ISOC |
> +						USB_ENDPOINT_SYNC_ASYNC,
> +					.rates = SNDRV_PCM_RATE_48000,
> +					.rate_min = 48000,
> +					.rate_max = 48000,
> +					.nr_rates = 1,
> +					.rate_table = (unsigned int[]) {
> +						48000
> +					}
> +				}
> +			},
> +			{
> +				.ifnum = 3,
> +				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
> +				.data = &(const struct audioformat) {
> +					.formats = SNDRV_PCM_FMTBIT_S24_3LE,
> +					.channels = 4,
> +					.iface = 3,
> +					.altsetting = 1,
> +					.altset_idx = 1,
> +					.endpoint = 0x81,
> +					.attributes = 0x00,
> +					.ep_attr = USB_ENDPOINT_XFER_ISOC |
> +						USB_ENDPOINT_SYNC_ASYNC,
> +					.maxpacksize = 0x009c,
> +					.rates = SNDRV_PCM_RATE_48000,
> +					.rate_min = 48000,
> +					.rate_max = 48000,
> +					.nr_rates = 1,
> +					.rate_table = (unsigned int[]) {
> +						48000
> +					}
> +				}
> +			},
> +			{
> +				.ifnum = 4,
> +				.type = QUIRK_MIDI_FIXED_ENDPOINT,
> +				.data = & (const struct snd_usb_midi_endpoint_info) {
> +					.out_cables = 0x0001,
> +					.in_cables  = 0x0001
> +				}
> +			},
> +			{
> +				.ifnum = -1
> +			}
> +		}
> +	}
> +},
>  {
>  	/* Tascam US122 MKII - playback-only support */
>  	USB_DEVICE_VENDOR_SPEC(0x0644, 0x8021),
> diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
> index ab9f3da49941..e7caa7eeb955 100644
> --- a/sound/usb/quirks.c
> +++ b/sound/usb/quirks.c
> @@ -1020,6 +1020,313 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device *dev)
>  	return 0;
>  }
>  
> +static void mbox3_setup_48_24_magic(struct usb_device *dev)
> +{
> +	u8 com_buff[4];
> +
> +	/* Load 48000Hz rate into buffer */
> +	com_buff[0] = 0x80;
> +	com_buff[1] = 0xbb;
> +	com_buff[2] = 0x00;
> +	com_buff[3] = 0x00;
> +
> +	/* Set 48000Hz sample rate */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			0x01, 0x21, 0x0100, 0x0001, &com_buff, 0x0004);
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			0x01, 0x21, 0x0100, 0x8101, &com_buff, 0x0004);
> +
> +	/* Set clock source to Internal (as opposed to S/PDIF) */
> +	memset(com_buff, 0x00, 4);
> +	com_buff[0] = 0x01;
> +	com_buff[1] = 0x00;
> +	com_buff[2] = 0x00;
> +	com_buff[3] = 0x00;
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0100, 0x8001, &com_buff, 1);
> +
> +	/* Mute the hardware loopbacks to start the device in a known state.
> +	 * The Mbox 3 is little endian and
> +	 * the data written here seems a bit odd.
> +	 * 0x8000 (shown in big endian form) is muted
> +	 * and volume increases to 0xffff it seems.
> +	 * I've yet to observe 0xffff being sent.
> +	 * Instead, full volume seems to be 0x0000.
> +	 * Per my understanding of 16 bit integers, this is seems strange, but maybe I'm missing something
> +	 */
> +	memset(com_buff, 0x00, 4);
> +	com_buff[0] = 0x00;
> +	com_buff[1] = 0x80;
> +	com_buff[2] = 0x00;
> +	com_buff[3] = 0x00;
> +	/* Analogue input 1 left channel: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0110, 0x4001, &com_buff, 2);
> +	/* Analogue input 1 right channel: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0111, 0x4001, &com_buff, 2);
> +	/* Analogue input 2 left channel: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0114, 0x4001, &com_buff, 2);
> +	/* Analogue input 2 right channel: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0115, 0x4001, &com_buff, 2);
> +	/* Analogue input 3 left channel: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0118, 0x4001, &com_buff, 2);
> +	/* Analogue input 3 right channel: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0119, 0x4001, &com_buff, 2);
> +	/* Analogue input 4 left channel: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x011c, 0x4001, &com_buff, 2);
> +	/* Analogue input 4 right channel: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x011d, 0x4001, &com_buff, 2);
> +
> +	/* Set software sends to output */
> +	memset(com_buff, 0x00, 4);
> +	com_buff[0] = 0x00;
> +	com_buff[1] = 0x00;
> +	com_buff[2] = 0x00;
> +	com_buff[3] = 0x00;
> +	/* Analogue software return 1 left channel: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0100, 0x4001, &com_buff, 2);
> +	/* Analogue software return 1 right channel: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0101, 0x4001, &com_buff, 2);
> +	/* Analogue software return 2 left channel: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0104, 0x4001, &com_buff, 2);
> +	/* Analogue software return 2 right channel: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0105, 0x4001, &com_buff, 2);
> +	/* Analogue software return 3 left channel: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0108, 0x4001, &com_buff, 2);
> +	/* Analogue software return 3 right channel: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0109, 0x4001, &com_buff, 2);
> +	/* Analogue software return 4 left channel: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x010c, 0x4001, &com_buff, 2);
> +	/* Analogue software return 4 right channel: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x010d, 0x4001, &com_buff, 2);
> +
> +	/* Return to muting sends */
> +	memset(com_buff, 0x00, 4);
> +	com_buff[0] = 0x00;
> +	com_buff[1] = 0x80;
> +	com_buff[2] = 0x00;
> +	com_buff[3] = 0x00;
> +	/* Analogue fx return left channel: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0120, 0x4001, &com_buff, 2);
> +	/* Analogue fx return right channel: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0121, 0x4001, &com_buff, 2);
> +
> +	/* Analogue software input 1 fx send: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0100, 0x4201, &com_buff, 2);
> +	/* Analogue software input 2 fx send: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0101, 0x4201, &com_buff, 2);
> +	/* Analogue software input 3 fx send: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0102, 0x4201, &com_buff, 2);
> +	/* Analogue software input 4 fx send: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0103, 0x4201, &com_buff, 2);
> +	/* Analogue input 1 fx send: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0104, 0x4201, &com_buff, 2);
> +	/* Analogue input 2 fx send: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0105, 0x4201, &com_buff, 2);
> +	/* Analogue input 3 fx send: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0106, 0x4201, &com_buff, 2);
> +	/* Analogue input 4 fx send: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0107, 0x4201, &com_buff, 2);
> +
> +	/* Toggle allowing host control */
> +	memset(com_buff, 0x00, 4);
> +	com_buff[0] = 0x02;
> +	com_buff[1] = 0x00;
> +	com_buff[2] = 0x00;
> +	com_buff[3] = 0x00;
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			3, 0x21, 0x0000, 0x2001, &com_buff, 1);
> +
> +	/* Do not dim fx returns */
> +	memset(com_buff, 0x00, 4);
> +	com_buff[0] = 0x00;
> +	com_buff[1] = 0x00;
> +	com_buff[2] = 0x00;
> +	com_buff[3] = 0x00;
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3, 0x21, 0x0002, 0x2001, &com_buff, 1);
> +
> +	/* Do not set fx returns to mono */
> +	memset(com_buff, 0x00, 4);
> +	com_buff[0] = 0x00;
> +	com_buff[1] = 0x00;
> +	com_buff[2] = 0x00;
> +	com_buff[3] = 0x00;
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3, 0x21, 0x0001, 0x2001, &com_buff, 1);
> +
> +	/* Mute the S/PDIF hardware loopback
> +	 * same odd volume logic here as above
> +	 */
> +	memset(com_buff, 0x00, 4);
> +	com_buff[0] = 0x00;
> +	com_buff[1] = 0x80;
> +	com_buff[2] = 0x00;
> +	com_buff[3] = 0x00;
> +	/* S/PDIF hardware input 1 left channel */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0112, 0x4001, &com_buff, 2);
> +	/* S/PDIF hardware input 1 right channel */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0113, 0x4001, &com_buff, 2);
> +	/* S/PDIF hardware input 2 left channel */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0116, 0x4001, &com_buff, 2);
> +	/* S/PDIF hardware input 2 right channel */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0117, 0x4001, &com_buff, 2);
> +	/* S/PDIF hardware input 3 left channel */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x011a, 0x4001, &com_buff, 2);
> +	/* S/PDIF hardware input 3 right channel */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x011b, 0x4001, &com_buff, 2);
> +	/* S/PDIF hardware input 4 left channel */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x011e, 0x4001, &com_buff, 2);
> +	/* S/PDIF hardware input 4 right channel */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x011f, 0x4001, &com_buff, 2);
> +	/* S/PDIF software return 1 left channel */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0102, 0x4001, &com_buff, 2);
> +	/* S/PDIF software return 1 right channel */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0103, 0x4001, &com_buff, 2);
> +	/* S/PDIF software return 2 left channel */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0106, 0x4001, &com_buff, 2);
> +	/* S/PDIF software return 2 right channel */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0107, 0x4001, &com_buff, 2);
> +	/* S/PDIF software return 3 left channel */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x010a, 0x4001, &com_buff, 2);
> +	/* S/PDIF software return 3 right channel */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x010b, 0x4001, &com_buff, 2);
> +	/* S/PDIF software return 4 left channel */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x010e, 0x4001, &com_buff, 2);
> +	/* S/PDIF software return 4 right channel */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x010f, 0x4001, &com_buff, 2);
> +	/* S/PDIF fx returns left channel */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0122, 0x4001, &com_buff, 2);
> +	/* S/PDIF fx returns right channel */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0123, 0x4001, &com_buff, 2);
> +
> +	/* Set the dropdown "Effect" to the first option */
> +	memset(com_buff, 0x00, 4);
> +	com_buff[0] = 0x00;
> +	com_buff[1] = 0x00;
> +	com_buff[2] = 0x00;
> +	com_buff[3] = 0x00;
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0200, 0x4301, &com_buff, 1);
> +
> +	/* Set the effect duration to 0 */
> +	memset(com_buff, 0x00, 4);
> +	com_buff[0] = 0x00;
> +	com_buff[1] = 0x00;
> +	com_buff[2] = 0x00;
> +	com_buff[3] = 0x00;
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0400, 0x4301, &com_buff, 2);
> +
> +	/* Set the effect volume and feedback to 0 */
> +	memset(com_buff, 0x00, 4);
> +	com_buff[0] = 0x00;
> +	com_buff[1] = 0x00;
> +	com_buff[2] = 0x00;
> +	com_buff[3] = 0x00;
> +	/* feedback: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0500, 0x4301, &com_buff, 1);
> +	/* volume: */
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			1, 0x21, 0x0300, 0x4301, &com_buff, 1);
> +
> +	/* Set soft button hold duration */
> +	memset(com_buff, 0x00, 4);
> +	com_buff[0] = 0x05;
> +	com_buff[1] = 0x00;
> +	com_buff[2] = 0x00;
> +	com_buff[3] = 0x00;
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			3, 0x21, 0x0005, 0x2001, &com_buff, 1);
> +
> +	/* Use dim LEDs for button of state */
> +	memset(com_buff, 0x00, 4);
> +	com_buff[0] = 0x00;
> +	com_buff[1] = 0x00;
> +	com_buff[2] = 0x00;
> +	com_buff[3] = 0x00;
> +	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +			3, 0x21, 0x0004, 0x2001, &com_buff, 1);
> +
> +	return;
> +}
> +
> +#define MBOX3_DESCRIPTOR_SIZE	464
> +
> +static int snd_usb_mbox3_boot_quirk(struct usb_device *dev)
> +{
> +	struct usb_host_config *config = dev->actconfig;
> +	int err;
> +	int descriptor_size;
> +
> +	descriptor_size = le16_to_cpu(get_cfg_desc(config)->wTotalLength);
> +
> +	if (descriptor_size != MBOX3_DESCRIPTOR_SIZE) {
> +		dev_err(&dev->dev, "Invalid descriptor size=%d.\n", descriptor_size);
> +		return -ENODEV;
> +	}
> +
> +	dev_dbg(&dev->dev, "device initialised!\n");
> +
> +	err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
> +		&dev->descriptor, sizeof(dev->descriptor));
> +	config = dev->actconfig;
> +	if (err < 0)
> +		dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err);
> +
> +	err = usb_reset_configuration(dev);
> +	if (err < 0)
> +		dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err);
> +	dev_dbg(&dev->dev, "mbox3_boot: new boot length = %d\n",
> +		le16_to_cpu(get_cfg_desc(config)->wTotalLength));
> +
> +	mbox3_setup_48_24_magic(dev);
> +	dev_info(&dev->dev, "Digidesign Mbox 3: 24bit 48kHz");
> +
> +	return 0; /* Successful boot */
> +}
>  
>  #define MICROBOOK_BUF_SIZE 128
>  
> @@ -1324,6 +1631,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
>  	case USB_ID(0x0dba, 0x3000):
>  		/* Digidesign Mbox 2 */
>  		return snd_usb_mbox2_boot_quirk(dev);
> +	case USB_ID(0x0dba, 0x5000):
> +		/* Digidesign Mbox 3 */
> +		return snd_usb_mbox3_boot_quirk(dev);
> +
>  
>  	case USB_ID(0x1235, 0x0010): /* Focusrite Novation Saffire 6 USB */
>  	case USB_ID(0x1235, 0x0018): /* Focusrite Novation Twitch */
> -- 
> 2.37.2
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH] Add quirk to enable Avid Mbox 3 support
  2022-08-17  7:45       ` Takashi Iwai
@ 2022-08-17 16:27         ` connerknoxpublic
  2022-08-17 16:48           ` Manu
  2022-08-18 20:14           ` mbarriolinares
  0 siblings, 2 replies; 9+ messages in thread
From: connerknoxpublic @ 2022-08-17 16:27 UTC (permalink / raw)
  To: perex, tiwai, alsa-devel, mbarriolinares; +Cc: Conner Knox

From: Conner Knox <connerknoxpublic@gmail.com>

Add support for Avid Mbox3 USB audio interface at 48kHz

Signed-off-by: Conner Knox <connerknoxpublic@gmail.com>
---
 sound/usb/quirks-table.h |  76 ++++++++++
 sound/usb/quirks.c       | 311 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 387 insertions(+)

diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 0ea39565e623..5f43863e5a5f 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2978,6 +2978,82 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 		}
 	}
 },
+/* DIGIDESIGN MBOX 3 */
+{
+	USB_DEVICE(0x0dba, 0x5000),
+	.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+		.vendor_name = "Digidesign",
+		.product_name = "Mbox 3",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const struct snd_usb_audio_quirk[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+					.formats = SNDRV_PCM_FMTBIT_S24_3LE,
+					.channels = 4,
+					.iface = 2,
+					.altsetting = 1,
+					.altset_idx = 1,
+					.attributes = 0x00,
+					.endpoint = 0x01,
+					.ep_attr = USB_ENDPOINT_XFER_ISOC |
+						USB_ENDPOINT_SYNC_ASYNC,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 3,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+					.formats = SNDRV_PCM_FMTBIT_S24_3LE,
+					.channels = 4,
+					.iface = 3,
+					.altsetting = 1,
+					.altset_idx = 1,
+					.endpoint = 0x81,
+					.attributes = 0x00,
+					.ep_attr = USB_ENDPOINT_XFER_ISOC |
+						USB_ENDPOINT_SYNC_ASYNC,
+					.maxpacksize = 0x009c,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 4,
+				.type = QUIRK_MIDI_FIXED_ENDPOINT,
+				.data = & (const struct snd_usb_midi_endpoint_info) {
+					.out_cables = 0x0001,
+					.in_cables  = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
 {
 	/* Tascam US122 MKII - playback-only support */
 	USB_DEVICE_VENDOR_SPEC(0x0644, 0x8021),
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index ab9f3da49941..e7caa7eeb955 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1020,6 +1020,313 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device *dev)
 	return 0;
 }
 
+static void mbox3_setup_48_24_magic(struct usb_device *dev)
+{
+	u8 com_buff[4];
+
+	/* Load 48000Hz rate into buffer */
+	com_buff[0] = 0x80;
+	com_buff[1] = 0xbb;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+
+	/* Set 48000Hz sample rate */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			0x01, 0x21, 0x0100, 0x0001, &com_buff, 0x0004);
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			0x01, 0x21, 0x0100, 0x8101, &com_buff, 0x0004);
+
+	/* Set clock source to Internal (as opposed to S/PDIF) */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x01;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0100, 0x8001, &com_buff, 1);
+
+	/* Mute the hardware loopbacks to start the device in a known state.
+	 * The Mbox 3 is little endian and
+	 * the data written here seems a bit odd.
+	 * 0x8000 (shown in big endian form) is muted
+	 * and volume increases to 0xffff it seems.
+	 * I've yet to observe 0xffff being sent.
+	 * Instead, full volume seems to be 0x0000.
+	 * Per my understanding of 16 bit integers, this is seems strange, but maybe I'm missing something
+	 */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x80;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	/* Analogue input 1 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0110, 0x4001, &com_buff, 2);
+	/* Analogue input 1 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0111, 0x4001, &com_buff, 2);
+	/* Analogue input 2 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0114, 0x4001, &com_buff, 2);
+	/* Analogue input 2 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0115, 0x4001, &com_buff, 2);
+	/* Analogue input 3 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0118, 0x4001, &com_buff, 2);
+	/* Analogue input 3 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0119, 0x4001, &com_buff, 2);
+	/* Analogue input 4 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011c, 0x4001, &com_buff, 2);
+	/* Analogue input 4 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011d, 0x4001, &com_buff, 2);
+
+	/* Set software sends to output */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	/* Analogue software return 1 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0100, 0x4001, &com_buff, 2);
+	/* Analogue software return 1 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0101, 0x4001, &com_buff, 2);
+	/* Analogue software return 2 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0104, 0x4001, &com_buff, 2);
+	/* Analogue software return 2 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0105, 0x4001, &com_buff, 2);
+	/* Analogue software return 3 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0108, 0x4001, &com_buff, 2);
+	/* Analogue software return 3 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0109, 0x4001, &com_buff, 2);
+	/* Analogue software return 4 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010c, 0x4001, &com_buff, 2);
+	/* Analogue software return 4 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010d, 0x4001, &com_buff, 2);
+
+	/* Return to muting sends */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x80;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	/* Analogue fx return left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0120, 0x4001, &com_buff, 2);
+	/* Analogue fx return right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0121, 0x4001, &com_buff, 2);
+
+	/* Analogue software input 1 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0100, 0x4201, &com_buff, 2);
+	/* Analogue software input 2 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0101, 0x4201, &com_buff, 2);
+	/* Analogue software input 3 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0102, 0x4201, &com_buff, 2);
+	/* Analogue software input 4 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0103, 0x4201, &com_buff, 2);
+	/* Analogue input 1 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0104, 0x4201, &com_buff, 2);
+	/* Analogue input 2 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0105, 0x4201, &com_buff, 2);
+	/* Analogue input 3 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0106, 0x4201, &com_buff, 2);
+	/* Analogue input 4 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0107, 0x4201, &com_buff, 2);
+
+	/* Toggle allowing host control */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x02;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			3, 0x21, 0x0000, 0x2001, &com_buff, 1);
+
+	/* Do not dim fx returns */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3, 0x21, 0x0002, 0x2001, &com_buff, 1);
+
+	/* Do not set fx returns to mono */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3, 0x21, 0x0001, 0x2001, &com_buff, 1);
+
+	/* Mute the S/PDIF hardware loopback
+	 * same odd volume logic here as above
+	 */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x80;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	/* S/PDIF hardware input 1 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0112, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 1 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0113, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 2 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0116, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 2 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0117, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 3 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011a, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 3 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011b, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 4 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011e, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 4 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011f, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 1 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0102, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 1 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0103, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 2 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0106, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 2 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0107, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 3 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010a, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 3 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010b, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 4 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010e, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 4 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010f, 0x4001, &com_buff, 2);
+	/* S/PDIF fx returns left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0122, 0x4001, &com_buff, 2);
+	/* S/PDIF fx returns right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0123, 0x4001, &com_buff, 2);
+
+	/* Set the dropdown "Effect" to the first option */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0200, 0x4301, &com_buff, 1);
+
+	/* Set the effect duration to 0 */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0400, 0x4301, &com_buff, 2);
+
+	/* Set the effect volume and feedback to 0 */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	/* feedback: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0500, 0x4301, &com_buff, 1);
+	/* volume: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0300, 0x4301, &com_buff, 1);
+
+	/* Set soft button hold duration */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x05;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			3, 0x21, 0x0005, 0x2001, &com_buff, 1);
+
+	/* Use dim LEDs for button of state */
+	memset(com_buff, 0x00, 4);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	com_buff[2] = 0x00;
+	com_buff[3] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			3, 0x21, 0x0004, 0x2001, &com_buff, 1);
+
+	return;
+}
+
+#define MBOX3_DESCRIPTOR_SIZE	464
+
+static int snd_usb_mbox3_boot_quirk(struct usb_device *dev)
+{
+	struct usb_host_config *config = dev->actconfig;
+	int err;
+	int descriptor_size;
+
+	descriptor_size = le16_to_cpu(get_cfg_desc(config)->wTotalLength);
+
+	if (descriptor_size != MBOX3_DESCRIPTOR_SIZE) {
+		dev_err(&dev->dev, "Invalid descriptor size=%d.\n", descriptor_size);
+		return -ENODEV;
+	}
+
+	dev_dbg(&dev->dev, "device initialised!\n");
+
+	err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
+		&dev->descriptor, sizeof(dev->descriptor));
+	config = dev->actconfig;
+	if (err < 0)
+		dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err);
+
+	err = usb_reset_configuration(dev);
+	if (err < 0)
+		dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err);
+	dev_dbg(&dev->dev, "mbox3_boot: new boot length = %d\n",
+		le16_to_cpu(get_cfg_desc(config)->wTotalLength));
+
+	mbox3_setup_48_24_magic(dev);
+	dev_info(&dev->dev, "Digidesign Mbox 3: 24bit 48kHz");
+
+	return 0; /* Successful boot */
+}
 
 #define MICROBOOK_BUF_SIZE 128
 
@@ -1324,6 +1631,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
 	case USB_ID(0x0dba, 0x3000):
 		/* Digidesign Mbox 2 */
 		return snd_usb_mbox2_boot_quirk(dev);
+	case USB_ID(0x0dba, 0x5000):
+		/* Digidesign Mbox 3 */
+		return snd_usb_mbox3_boot_quirk(dev);
+
 
 	case USB_ID(0x1235, 0x0010): /* Focusrite Novation Saffire 6 USB */
 	case USB_ID(0x1235, 0x0018): /* Focusrite Novation Twitch */
-- 
2.37.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH] Add quirk to enable Avid Mbox 3 support
  2022-08-17 16:27         ` connerknoxpublic
@ 2022-08-17 16:48           ` Manu
  2022-08-18 20:14           ` mbarriolinares
  1 sibling, 0 replies; 9+ messages in thread
From: Manu @ 2022-08-17 16:48 UTC (permalink / raw)
  To: connerknoxpublic; +Cc: alsa-devel, tiwai

Could you perhaps make this the defaults, for it to work in stereo?
I've made the Analog 1 to be left, and Analog 2 to be right channels,
and muted Analog 3 and 4, as they are detected as "surround".
This works out of the box with the back Analog outs.
(Still haven't tested front headphones out)

>    /* Set software sends to output */
>    com_buff[0] = 0x00;
>    com_buff[1] = 0x00;
>    /* Analogue software return 1 left channel: */
>    snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 1, 0x21, 0x0100, 0x4001, &com_buff, 2);
>    /* Analogue software return 2 right channel: */
>    snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 1, 0x21, 0x0105, 0x4001, &com_buff, 2);
>    com_buff[0] = 0x00;
>    com_buff[1] = 0x80;
>    /* Analogue software return 1 right channel: */
>    snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 1, 0x21, 0x0101, 0x4001, &com_buff, 2);
>    /* Analogue software return 2 left channel: */
>    snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 1, 0x21, 0x0104, 0x4001, &com_buff, 2);
>    com_buff[0] = 0x00;
>    com_buff[1] = 0x80;
>    /* Analogue software return 3 left channel: */
>    snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 1, 0x21, 0x0108, 0x4001, &com_buff, 2);
>    /* Analogue software return 3 right channel: */
>    snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 1, 0x21, 0x0109, 0x4001, &com_buff, 2);
>    /* Analogue software return 4 left channel: */
>    snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 1, 0x21, 0x010c, 0x4001, &com_buff, 2);
>    /* Analogue software return 4 right channel: */
>    snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 1, 0x21, 0x010d, 0x4001, &com_buff, 2);



On Wed, Aug 17, 2022 at 1:28 PM <connerknoxpublic@gmail.com> wrote:
>
> From: Conner Knox <connerknoxpublic@gmail.com>
>
> Add support for Avid Mbox3 USB audio interface at 48kHz
>
> Signed-off-by: Conner Knox <connerknoxpublic@gmail.com>
> ---
>  sound/usb/quirks-table.h |  76 ++++++++++
>  sound/usb/quirks.c       | 311 +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 387 insertions(+)
>
> diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
> index 0ea39565e623..5f43863e5a5f 100644
> --- a/sound/usb/quirks-table.h
> +++ b/sound/usb/quirks-table.h
> @@ -2978,6 +2978,82 @@ YAMAHA_DEVICE(0x7010, "UB99"),
>                 }
>         }
>  },
> +/* DIGIDESIGN MBOX 3 */
> +{
> +       USB_DEVICE(0x0dba, 0x5000),
> +       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
> +               .vendor_name = "Digidesign",
> +               .product_name = "Mbox 3",
> +               .ifnum = QUIRK_ANY_INTERFACE,
> +               .type = QUIRK_COMPOSITE,
> +               .data = (const struct snd_usb_audio_quirk[]) {
> +                       {
> +                               .ifnum = 0,
> +                               .type = QUIRK_IGNORE_INTERFACE
> +                       },
> +                       {
> +                               .ifnum = 1,
> +                               .type = QUIRK_IGNORE_INTERFACE
> +                       },
> +                       {
> +                               .ifnum = 2,
> +                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
> +                               .data = &(const struct audioformat) {
> +                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
> +                                       .channels = 4,
> +                                       .iface = 2,
> +                                       .altsetting = 1,
> +                                       .altset_idx = 1,
> +                                       .attributes = 0x00,
> +                                       .endpoint = 0x01,
> +                                       .ep_attr = USB_ENDPOINT_XFER_ISOC |
> +                                               USB_ENDPOINT_SYNC_ASYNC,
> +                                       .rates = SNDRV_PCM_RATE_48000,
> +                                       .rate_min = 48000,
> +                                       .rate_max = 48000,
> +                                       .nr_rates = 1,
> +                                       .rate_table = (unsigned int[]) {
> +                                               48000
> +                                       }
> +                               }
> +                       },
> +                       {
> +                               .ifnum = 3,
> +                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
> +                               .data = &(const struct audioformat) {
> +                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
> +                                       .channels = 4,
> +                                       .iface = 3,
> +                                       .altsetting = 1,
> +                                       .altset_idx = 1,
> +                                       .endpoint = 0x81,
> +                                       .attributes = 0x00,
> +                                       .ep_attr = USB_ENDPOINT_XFER_ISOC |
> +                                               USB_ENDPOINT_SYNC_ASYNC,
> +                                       .maxpacksize = 0x009c,
> +                                       .rates = SNDRV_PCM_RATE_48000,
> +                                       .rate_min = 48000,
> +                                       .rate_max = 48000,
> +                                       .nr_rates = 1,
> +                                       .rate_table = (unsigned int[]) {
> +                                               48000
> +                                       }
> +                               }
> +                       },
> +                       {
> +                               .ifnum = 4,
> +                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
> +                               .data = & (const struct snd_usb_midi_endpoint_info) {
> +                                       .out_cables = 0x0001,
> +                                       .in_cables  = 0x0001
> +                               }
> +                       },
> +                       {
> +                               .ifnum = -1
> +                       }
> +               }
> +       }
> +},
>  {
>         /* Tascam US122 MKII - playback-only support */
>         USB_DEVICE_VENDOR_SPEC(0x0644, 0x8021),
> diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
> index ab9f3da49941..e7caa7eeb955 100644
> --- a/sound/usb/quirks.c
> +++ b/sound/usb/quirks.c
> @@ -1020,6 +1020,313 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device *dev)
>         return 0;
>  }
>
> +static void mbox3_setup_48_24_magic(struct usb_device *dev)
> +{
> +       u8 com_buff[4];
> +
> +       /* Load 48000Hz rate into buffer */
> +       com_buff[0] = 0x80;
> +       com_buff[1] = 0xbb;
> +       com_buff[2] = 0x00;
> +       com_buff[3] = 0x00;
> +
> +       /* Set 48000Hz sample rate */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       0x01, 0x21, 0x0100, 0x0001, &com_buff, 0x0004);
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       0x01, 0x21, 0x0100, 0x8101, &com_buff, 0x0004);
> +
> +       /* Set clock source to Internal (as opposed to S/PDIF) */
> +       memset(com_buff, 0x00, 4);
> +       com_buff[0] = 0x01;
> +       com_buff[1] = 0x00;
> +       com_buff[2] = 0x00;
> +       com_buff[3] = 0x00;
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0100, 0x8001, &com_buff, 1);
> +
> +       /* Mute the hardware loopbacks to start the device in a known state.
> +        * The Mbox 3 is little endian and
> +        * the data written here seems a bit odd.
> +        * 0x8000 (shown in big endian form) is muted
> +        * and volume increases to 0xffff it seems.
> +        * I've yet to observe 0xffff being sent.
> +        * Instead, full volume seems to be 0x0000.
> +        * Per my understanding of 16 bit integers, this is seems strange, but maybe I'm missing something
> +        */
> +       memset(com_buff, 0x00, 4);
> +       com_buff[0] = 0x00;
> +       com_buff[1] = 0x80;
> +       com_buff[2] = 0x00;
> +       com_buff[3] = 0x00;
> +       /* Analogue input 1 left channel: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0110, 0x4001, &com_buff, 2);
> +       /* Analogue input 1 right channel: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0111, 0x4001, &com_buff, 2);
> +       /* Analogue input 2 left channel: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0114, 0x4001, &com_buff, 2);
> +       /* Analogue input 2 right channel: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0115, 0x4001, &com_buff, 2);
> +       /* Analogue input 3 left channel: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0118, 0x4001, &com_buff, 2);
> +       /* Analogue input 3 right channel: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0119, 0x4001, &com_buff, 2);
> +       /* Analogue input 4 left channel: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x011c, 0x4001, &com_buff, 2);
> +       /* Analogue input 4 right channel: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x011d, 0x4001, &com_buff, 2);
> +
> +       /* Set software sends to output */
> +       memset(com_buff, 0x00, 4);
> +       com_buff[0] = 0x00;
> +       com_buff[1] = 0x00;
> +       com_buff[2] = 0x00;
> +       com_buff[3] = 0x00;
> +       /* Analogue software return 1 left channel: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0100, 0x4001, &com_buff, 2);
> +       /* Analogue software return 1 right channel: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0101, 0x4001, &com_buff, 2);
> +       /* Analogue software return 2 left channel: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0104, 0x4001, &com_buff, 2);
> +       /* Analogue software return 2 right channel: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0105, 0x4001, &com_buff, 2);
> +       /* Analogue software return 3 left channel: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0108, 0x4001, &com_buff, 2);
> +       /* Analogue software return 3 right channel: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0109, 0x4001, &com_buff, 2);
> +       /* Analogue software return 4 left channel: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x010c, 0x4001, &com_buff, 2);
> +       /* Analogue software return 4 right channel: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x010d, 0x4001, &com_buff, 2);
> +
> +       /* Return to muting sends */
> +       memset(com_buff, 0x00, 4);
> +       com_buff[0] = 0x00;
> +       com_buff[1] = 0x80;
> +       com_buff[2] = 0x00;
> +       com_buff[3] = 0x00;
> +       /* Analogue fx return left channel: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0120, 0x4001, &com_buff, 2);
> +       /* Analogue fx return right channel: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0121, 0x4001, &com_buff, 2);
> +
> +       /* Analogue software input 1 fx send: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0100, 0x4201, &com_buff, 2);
> +       /* Analogue software input 2 fx send: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0101, 0x4201, &com_buff, 2);
> +       /* Analogue software input 3 fx send: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0102, 0x4201, &com_buff, 2);
> +       /* Analogue software input 4 fx send: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0103, 0x4201, &com_buff, 2);
> +       /* Analogue input 1 fx send: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0104, 0x4201, &com_buff, 2);
> +       /* Analogue input 2 fx send: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0105, 0x4201, &com_buff, 2);
> +       /* Analogue input 3 fx send: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0106, 0x4201, &com_buff, 2);
> +       /* Analogue input 4 fx send: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0107, 0x4201, &com_buff, 2);
> +
> +       /* Toggle allowing host control */
> +       memset(com_buff, 0x00, 4);
> +       com_buff[0] = 0x02;
> +       com_buff[1] = 0x00;
> +       com_buff[2] = 0x00;
> +       com_buff[3] = 0x00;
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       3, 0x21, 0x0000, 0x2001, &com_buff, 1);
> +
> +       /* Do not dim fx returns */
> +       memset(com_buff, 0x00, 4);
> +       com_buff[0] = 0x00;
> +       com_buff[1] = 0x00;
> +       com_buff[2] = 0x00;
> +       com_buff[3] = 0x00;
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3, 0x21, 0x0002, 0x2001, &com_buff, 1);
> +
> +       /* Do not set fx returns to mono */
> +       memset(com_buff, 0x00, 4);
> +       com_buff[0] = 0x00;
> +       com_buff[1] = 0x00;
> +       com_buff[2] = 0x00;
> +       com_buff[3] = 0x00;
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3, 0x21, 0x0001, 0x2001, &com_buff, 1);
> +
> +       /* Mute the S/PDIF hardware loopback
> +        * same odd volume logic here as above
> +        */
> +       memset(com_buff, 0x00, 4);
> +       com_buff[0] = 0x00;
> +       com_buff[1] = 0x80;
> +       com_buff[2] = 0x00;
> +       com_buff[3] = 0x00;
> +       /* S/PDIF hardware input 1 left channel */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0112, 0x4001, &com_buff, 2);
> +       /* S/PDIF hardware input 1 right channel */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0113, 0x4001, &com_buff, 2);
> +       /* S/PDIF hardware input 2 left channel */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0116, 0x4001, &com_buff, 2);
> +       /* S/PDIF hardware input 2 right channel */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0117, 0x4001, &com_buff, 2);
> +       /* S/PDIF hardware input 3 left channel */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x011a, 0x4001, &com_buff, 2);
> +       /* S/PDIF hardware input 3 right channel */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x011b, 0x4001, &com_buff, 2);
> +       /* S/PDIF hardware input 4 left channel */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x011e, 0x4001, &com_buff, 2);
> +       /* S/PDIF hardware input 4 right channel */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x011f, 0x4001, &com_buff, 2);
> +       /* S/PDIF software return 1 left channel */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0102, 0x4001, &com_buff, 2);
> +       /* S/PDIF software return 1 right channel */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0103, 0x4001, &com_buff, 2);
> +       /* S/PDIF software return 2 left channel */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0106, 0x4001, &com_buff, 2);
> +       /* S/PDIF software return 2 right channel */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0107, 0x4001, &com_buff, 2);
> +       /* S/PDIF software return 3 left channel */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x010a, 0x4001, &com_buff, 2);
> +       /* S/PDIF software return 3 right channel */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x010b, 0x4001, &com_buff, 2);
> +       /* S/PDIF software return 4 left channel */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x010e, 0x4001, &com_buff, 2);
> +       /* S/PDIF software return 4 right channel */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x010f, 0x4001, &com_buff, 2);
> +       /* S/PDIF fx returns left channel */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0122, 0x4001, &com_buff, 2);
> +       /* S/PDIF fx returns right channel */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0123, 0x4001, &com_buff, 2);
> +
> +       /* Set the dropdown "Effect" to the first option */
> +       memset(com_buff, 0x00, 4);
> +       com_buff[0] = 0x00;
> +       com_buff[1] = 0x00;
> +       com_buff[2] = 0x00;
> +       com_buff[3] = 0x00;
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0200, 0x4301, &com_buff, 1);
> +
> +       /* Set the effect duration to 0 */
> +       memset(com_buff, 0x00, 4);
> +       com_buff[0] = 0x00;
> +       com_buff[1] = 0x00;
> +       com_buff[2] = 0x00;
> +       com_buff[3] = 0x00;
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0400, 0x4301, &com_buff, 2);
> +
> +       /* Set the effect volume and feedback to 0 */
> +       memset(com_buff, 0x00, 4);
> +       com_buff[0] = 0x00;
> +       com_buff[1] = 0x00;
> +       com_buff[2] = 0x00;
> +       com_buff[3] = 0x00;
> +       /* feedback: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0500, 0x4301, &com_buff, 1);
> +       /* volume: */
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       1, 0x21, 0x0300, 0x4301, &com_buff, 1);
> +
> +       /* Set soft button hold duration */
> +       memset(com_buff, 0x00, 4);
> +       com_buff[0] = 0x05;
> +       com_buff[1] = 0x00;
> +       com_buff[2] = 0x00;
> +       com_buff[3] = 0x00;
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       3, 0x21, 0x0005, 0x2001, &com_buff, 1);
> +
> +       /* Use dim LEDs for button of state */
> +       memset(com_buff, 0x00, 4);
> +       com_buff[0] = 0x00;
> +       com_buff[1] = 0x00;
> +       com_buff[2] = 0x00;
> +       com_buff[3] = 0x00;
> +       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
> +                       3, 0x21, 0x0004, 0x2001, &com_buff, 1);
> +
> +       return;
> +}
> +
> +#define MBOX3_DESCRIPTOR_SIZE  464
> +
> +static int snd_usb_mbox3_boot_quirk(struct usb_device *dev)
> +{
> +       struct usb_host_config *config = dev->actconfig;
> +       int err;
> +       int descriptor_size;
> +
> +       descriptor_size = le16_to_cpu(get_cfg_desc(config)->wTotalLength);
> +
> +       if (descriptor_size != MBOX3_DESCRIPTOR_SIZE) {
> +               dev_err(&dev->dev, "Invalid descriptor size=%d.\n", descriptor_size);
> +               return -ENODEV;
> +       }
> +
> +       dev_dbg(&dev->dev, "device initialised!\n");
> +
> +       err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
> +               &dev->descriptor, sizeof(dev->descriptor));
> +       config = dev->actconfig;
> +       if (err < 0)
> +               dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err);
> +
> +       err = usb_reset_configuration(dev);
> +       if (err < 0)
> +               dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err);
> +       dev_dbg(&dev->dev, "mbox3_boot: new boot length = %d\n",
> +               le16_to_cpu(get_cfg_desc(config)->wTotalLength));
> +
> +       mbox3_setup_48_24_magic(dev);
> +       dev_info(&dev->dev, "Digidesign Mbox 3: 24bit 48kHz");
> +
> +       return 0; /* Successful boot */
> +}
>
>  #define MICROBOOK_BUF_SIZE 128
>
> @@ -1324,6 +1631,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
>         case USB_ID(0x0dba, 0x3000):
>                 /* Digidesign Mbox 2 */
>                 return snd_usb_mbox2_boot_quirk(dev);
> +       case USB_ID(0x0dba, 0x5000):
> +               /* Digidesign Mbox 3 */
> +               return snd_usb_mbox3_boot_quirk(dev);
> +
>
>         case USB_ID(0x1235, 0x0010): /* Focusrite Novation Saffire 6 USB */
>         case USB_ID(0x1235, 0x0018): /* Focusrite Novation Twitch */
> --
> 2.37.2
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH] Add quirk to enable Avid Mbox 3 support
  2022-08-17 16:27         ` connerknoxpublic
  2022-08-17 16:48           ` Manu
@ 2022-08-18 20:14           ` mbarriolinares
  2022-08-22 11:03             ` Takashi Iwai
  1 sibling, 1 reply; 9+ messages in thread
From: mbarriolinares @ 2022-08-18 20:14 UTC (permalink / raw)
  To: tiwai; +Cc: mbarriolinares, alsa-devel, connerknoxpublic

From: Conner Knox <connerknoxpublic@gmail.com>

Add support for Avid Mbox3 USB audio interface at 48kHz

Signed-off-by: Conner Knox <connerknoxpublic@gmail.com>
---
:Added some sane defaults for Stereo to work correctly.
:Added comments to specify the complete interface api.
:Cleaned up coding style	

diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index f93201a83..06dfdd45c 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2985,6 +2985,82 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 		}
 	}
 },
+/* DIGIDESIGN MBOX 3 */
+{
+	USB_DEVICE(0x0dba, 0x5000),
+	.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+		.vendor_name = "Digidesign",
+		.product_name = "Mbox 3",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const struct snd_usb_audio_quirk[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+					.formats = SNDRV_PCM_FMTBIT_S24_3LE,
+					.channels = 4,
+					.iface = 2,
+					.altsetting = 1,
+					.altset_idx = 1,
+					.attributes = 0x00,
+					.endpoint = 0x01,
+					.ep_attr = USB_ENDPOINT_XFER_ISOC |
+						USB_ENDPOINT_SYNC_ASYNC,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 3,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = &(const struct audioformat) {
+					.formats = SNDRV_PCM_FMTBIT_S24_3LE,
+					.channels = 4,
+					.iface = 3,
+					.altsetting = 1,
+					.altset_idx = 1,
+					.endpoint = 0x81,
+					.attributes = 0x00,
+					.ep_attr = USB_ENDPOINT_XFER_ISOC |
+						USB_ENDPOINT_SYNC_ASYNC,
+					.maxpacksize = 0x009c,
+					.rates = SNDRV_PCM_RATE_48000,
+					.rate_min = 48000,
+					.rate_max = 48000,
+					.nr_rates = 1,
+					.rate_table = (unsigned int[]) {
+						48000
+					}
+				}
+			},
+			{
+				.ifnum = 4,
+				.type = QUIRK_MIDI_FIXED_ENDPOINT,
+				.data = &(const struct snd_usb_midi_endpoint_info) {
+					.out_cables = 0x0001,
+					.in_cables  = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
 {
 	/* Tascam US122 MKII - playback-only support */
 	USB_DEVICE_VENDOR_SPEC(0x0644, 0x8021),
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 968d90cae..1d818ee64 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1020,6 +1020,304 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device *dev)
 	return 0;
 }
 
+static void mbox3_setup_48_24_magic(struct usb_device *dev)
+{
+	/* The Mbox 3 is "little endian" */
+	/* max volume is: 0x0000. */
+	/* min volume is: 0x0080 (shown in little endian form) */
+
+
+	/* Load 48000Hz rate into buffer */
+	u8 com_buff[4] = {0x80, 0xbb, 0x00, 0x00};
+
+	/* Set 48000Hz sample rate */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			0x01, 0x21, 0x0100, 0x0001, &com_buff, 4);  //Is this really needed?
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			0x01, 0x21, 0x0100, 0x8101, &com_buff, 4);
+
+	/* Deactivate Tuner */
+	/* on  = 0x01*/
+	/* off = 0x00*/
+	com_buff[0] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+		0x01, 0x21, 0x0003, 0x2001, &com_buff, 1);
+
+	/* Set clock source to Internal (as opposed to S/PDIF) */
+	com_buff[0] = 0x01;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0100, 0x8001, &com_buff, 1);
+
+	/* Mute the hardware loopbacks to start the device in a known state. */
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x80;
+	/* Analogue input 1 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0110, 0x4001, &com_buff, 2);
+	/* Analogue input 1 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0111, 0x4001, &com_buff, 2);
+	/* Analogue input 2 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0114, 0x4001, &com_buff, 2);
+	/* Analogue input 2 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0115, 0x4001, &com_buff, 2);
+	/* Analogue input 3 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0118, 0x4001, &com_buff, 2);
+	/* Analogue input 3 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0119, 0x4001, &com_buff, 2);
+	/* Analogue input 4 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011c, 0x4001, &com_buff, 2);
+	/* Analogue input 4 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011d, 0x4001, &com_buff, 2);
+
+	/* Set software sends to output */
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	/* Analogue software return 1 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0100, 0x4001, &com_buff, 2);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x80;
+	/* Analogue software return 1 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0101, 0x4001, &com_buff, 2);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x80;
+	/* Analogue software return 2 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0104, 0x4001, &com_buff, 2);
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	/* Analogue software return 2 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0105, 0x4001, &com_buff, 2);
+
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x80;
+	/* Analogue software return 3 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0108, 0x4001, &com_buff, 2);
+	/* Analogue software return 3 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0109, 0x4001, &com_buff, 2);
+	/* Analogue software return 4 left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010c, 0x4001, &com_buff, 2);
+	/* Analogue software return 4 right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010d, 0x4001, &com_buff, 2);
+
+	/* Return to muting sends */
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x80;
+	/* Analogue fx return left channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0120, 0x4001, &com_buff, 2);
+	/* Analogue fx return right channel: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0121, 0x4001, &com_buff, 2);
+
+	/* Analogue software input 1 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0100, 0x4201, &com_buff, 2);
+	/* Analogue software input 2 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0101, 0x4201, &com_buff, 2);
+	/* Analogue software input 3 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0102, 0x4201, &com_buff, 2);
+	/* Analogue software input 4 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0103, 0x4201, &com_buff, 2);
+	/* Analogue input 1 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0104, 0x4201, &com_buff, 2);
+	/* Analogue input 2 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0105, 0x4201, &com_buff, 2);
+	/* Analogue input 3 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0106, 0x4201, &com_buff, 2);
+	/* Analogue input 4 fx send: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0107, 0x4201, &com_buff, 2);
+
+	/* Toggle allowing host control */
+	com_buff[0] = 0x02;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			3, 0x21, 0x0000, 0x2001, &com_buff, 1);
+
+	/* Do not dim fx returns */
+	com_buff[0] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			3, 0x21, 0x0002, 0x2001, &com_buff, 1);
+
+	/* Do not set fx returns to mono */
+	com_buff[0] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			3, 0x21, 0x0001, 0x2001, &com_buff, 1);
+
+	/* Mute the S/PDIF hardware loopback
+	 * same odd volume logic here as above
+	 */
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x80;
+	/* S/PDIF hardware input 1 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0112, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 1 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0113, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 2 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0116, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 2 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0117, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 3 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011a, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 3 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011b, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 4 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011e, 0x4001, &com_buff, 2);
+	/* S/PDIF hardware input 4 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x011f, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 1 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0102, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 1 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0103, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 2 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0106, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 2 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0107, 0x4001, &com_buff, 2);
+
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	/* S/PDIF software return 3 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010a, 0x4001, &com_buff, 2);
+
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x80;
+	/* S/PDIF software return 3 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010b, 0x4001, &com_buff, 2);
+	/* S/PDIF software return 4 left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010e, 0x4001, &com_buff, 2);
+
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	/* S/PDIF software return 4 right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x010f, 0x4001, &com_buff, 2);
+
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x80;
+	/* S/PDIF fx returns left channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0122, 0x4001, &com_buff, 2);
+	/* S/PDIF fx returns right channel */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0123, 0x4001, &com_buff, 2);
+
+	/* Set the dropdown "Effect" to the first option */
+	/* Room1  = 0x00 */
+	/* Room2  = 0x01 */
+	/* Room3  = 0x02 */
+	/* Hall 1 = 0x03 */
+	/* Hall 2 = 0x04 */
+	/* Plate  = 0x05 */
+	/* Delay  = 0x06 */
+	/* Echo   = 0x07 */
+	com_buff[0] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0200, 0x4301, &com_buff, 1);	/* max is 0xff */
+	/* min is 0x00 */
+
+
+	/* Set the effect duration to 0 */
+	/* max is 0xffff */
+	/* min is 0x0000 */
+	com_buff[0] = 0x00;
+	com_buff[1] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0400, 0x4301, &com_buff, 2);
+
+	/* Set the effect volume and feedback to 0 */
+	/* max is 0xff */
+	/* min is 0x00 */
+	com_buff[0] = 0x00;
+	/* feedback: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0500, 0x4301, &com_buff, 1);
+	/* volume: */
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			1, 0x21, 0x0300, 0x4301, &com_buff, 1);
+
+	/* Set soft button hold duration */
+	/* 0x03 = 250ms */
+	/* 0x05 = 500ms DEFAULT */
+	/* 0x08 = 750ms */
+	/* 0x0a = 1sec */
+	com_buff[0] = 0x05;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			3, 0x21, 0x0005, 0x2001, &com_buff, 1);
+
+	/* Use dim LEDs for button of state */
+	com_buff[0] = 0x00;
+	snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+			3, 0x21, 0x0004, 0x2001, &com_buff, 1);
+}
+
+#define MBOX3_DESCRIPTOR_SIZE	464
+
+static int snd_usb_mbox3_boot_quirk(struct usb_device *dev)
+{
+	struct usb_host_config *config = dev->actconfig;
+	int err;
+	int descriptor_size;
+
+	descriptor_size = le16_to_cpu(get_cfg_desc(config)->wTotalLength);
+
+	if (descriptor_size != MBOX3_DESCRIPTOR_SIZE) {
+		dev_err(&dev->dev, "Invalid descriptor size=%d.\n", descriptor_size);
+		return -ENODEV;
+	}
+
+	dev_dbg(&dev->dev, "device initialised!\n");
+
+	err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
+		&dev->descriptor, sizeof(dev->descriptor));
+	config = dev->actconfig;
+	if (err < 0)
+		dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err);
+
+	err = usb_reset_configuration(dev);
+	if (err < 0)
+		dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err);
+	dev_dbg(&dev->dev, "mbox3_boot: new boot length = %d\n",
+		le16_to_cpu(get_cfg_desc(config)->wTotalLength));
+
+	mbox3_setup_48_24_magic(dev);
+	dev_info(&dev->dev, "Digidesign Mbox 3: 24bit 48kHz");
+
+	return 0; /* Successful boot */
+}
 
 #define MICROBOOK_BUF_SIZE 128
 
@@ -1324,6 +1622,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
 	case USB_ID(0x0dba, 0x3000):
 		/* Digidesign Mbox 2 */
 		return snd_usb_mbox2_boot_quirk(dev);
+	case USB_ID(0x0dba, 0x5000):
+		/* Digidesign Mbox 3 */
+		return snd_usb_mbox3_boot_quirk(dev);
+
 
 	case USB_ID(0x1235, 0x0010): /* Focusrite Novation Saffire 6 USB */
 	case USB_ID(0x1235, 0x0018): /* Focusrite Novation Twitch */

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH] Add quirk to enable Avid Mbox 3 support
  2022-08-18 20:14           ` mbarriolinares
@ 2022-08-22 11:03             ` Takashi Iwai
  0 siblings, 0 replies; 9+ messages in thread
From: Takashi Iwai @ 2022-08-22 11:03 UTC (permalink / raw)
  To: mbarriolinares; +Cc: alsa-devel, tiwai, connerknoxpublic

On Thu, 18 Aug 2022 22:14:33 +0200,
mbarriolinares wrote:
> 
> From: Conner Knox <connerknoxpublic@gmail.com>
> 
> Add support for Avid Mbox3 USB audio interface at 48kHz
> 
> Signed-off-by: Conner Knox <connerknoxpublic@gmail.com>
> ---
> :Added some sane defaults for Stereo to work correctly.
> :Added comments to specify the complete interface api.
> :Cleaned up coding style	

Thanks, applied now to for-next branch.


Takashi

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2022-08-22 11:04 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-17  2:54 [PATCH] Add quirk to enable Avid Mbox 3 support connerknoxpublic
2022-08-16  0:44 ` mbarriolinares
2022-08-16  6:04   ` Takashi Iwai
2022-08-17  7:15     ` connerknoxpublic
2022-08-17  7:45       ` Takashi Iwai
2022-08-17 16:27         ` connerknoxpublic
2022-08-17 16:48           ` Manu
2022-08-18 20:14           ` mbarriolinares
2022-08-22 11:03             ` Takashi Iwai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).