ALSA: usb-audio: Support for Digidesign Mbox 2 USB sound card:
authorDamien Zammit <damien@zamaudio.com>
Wed, 19 Dec 2012 10:27:22 +0000 (11:27 +0100)
committerTakashi Iwai <tiwai@suse.de>
Wed, 19 Dec 2012 10:27:22 +0000 (11:27 +0100)
This patch is the result of a lot of trial and error, since there are no specs
available for the device.

Full duplex support is provided, i.e. playback and recording in stereo.
The format is hardcoded at 48000Hz @ 24 bit, which is the maximum that the
device supports.  Also, MIDI in and MIDI out both work.

Users will notice that the S/PDIF light also flashes when playback or recording
is active.  I believe this means that S/PDIF input/output is simultaneously
activated with the analogue i/o during use.
But this particular functionality remains untested.

Note that this particular version of the patch is so far untested on the
physical hardware because I have not compiled a full kernel with the changes.
However, extensive testing has been done by many users of the hardware
who believe other versions of my patch have worked since circa 2009.

[Modified to make a function static by tiwai]

Signed-off-by: Damien Zammit <damien@zamaudio.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/usb/midi.c
sound/usb/quirks-table.h
sound/usb/quirks.c
sound/usb/usbaudio.h

index 34b9bb7fe87c8eabed83df8b7b77f510bedbc2b1..c183d34842accdc69ac8b1dec5424bb4373b1bbc 100644 (file)
@@ -2181,6 +2181,10 @@ int snd_usbmidi_create(struct snd_card *card,
                umidi->usb_protocol_ops = &snd_usbmidi_novation_ops;
                err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
                break;
+       case QUIRK_MIDI_MBOX2:
+               umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops;
+               err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
+               break;
        case QUIRK_MIDI_RAW_BYTES:
                umidi->usb_protocol_ops = &snd_usbmidi_raw_ops;
                /*
index 579cf6f6901cbd8e25e5fcd676580c491f66f244..cdcf6b45e8a887746a2f087e680b2c45a3198462 100644 (file)
@@ -2921,6 +2921,93 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 
        }
 },
+
+/* DIGIDESIGN MBOX 2 */
+{
+       USB_DEVICE(0x0dba, 0x3000),
+       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+               .vendor_name = "Digidesign",
+               .product_name = "Mbox 2",
+               .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_3BE,
+                                       .channels = 2,
+                                       .iface = 2,
+                                       .altsetting = 2,
+                                       .altset_idx = 1,
+                                       .attributes = 0x00,
+                                       .endpoint = 0x03,
+                                       .ep_attr = USB_ENDPOINT_SYNC_ASYNC,
+                                       .maxpacksize = 0x128,
+                                       .rates = SNDRV_PCM_RATE_48000,
+                                       .rate_min = 48000,
+                                       .rate_max = 48000,
+                                       .nr_rates = 1,
+                                       .rate_table = (unsigned int[]) {
+                                               48000
+                                       }
+                               }
+                       },
+                       {
+                               .ifnum = 3,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 4,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                               .formats = SNDRV_PCM_FMTBIT_S24_3BE,
+                                       .channels = 2,
+                                       .iface = 4,
+                                       .altsetting = 2,
+                                       .altset_idx = 1,
+                                       .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+                                       .endpoint = 0x85,
+                                       .ep_attr = USB_ENDPOINT_SYNC_SYNC,
+                                       .maxpacksize = 0x128,
+                                       .rates = SNDRV_PCM_RATE_48000,
+                                       .rate_min = 48000,
+                                       .rate_max = 48000,
+                                       .nr_rates = 1,
+                                       .rate_table = (unsigned int[]) {
+                                               48000
+                                       }
+                               }
+                       },
+                       {
+                               .ifnum = 5,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 6,
+                               .type = QUIRK_MIDI_MBOX2,
+                               .data = &(const struct snd_usb_midi_endpoint_info) {
+                                       .out_ep =  0x02,
+                                       .out_cables = 0x0001,
+                                       .in_ep = 0x81,
+                                       .in_interval = 0x01,
+                                       .in_cables = 0x0001
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
 {
        /* Tascam US122 MKII - playback-only support */
        .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
index 0f58b4b6d7023d0e4c47734216e276132c2fbe80..203d72b8a037621019821254a7af92015a25f462 100644 (file)
@@ -306,6 +306,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
                [QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
                [QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk,
                [QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
+               [QUIRK_MIDI_MBOX2] = create_any_midi_quirk,
                [QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk,
                [QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
                [QUIRK_MIDI_CME] = create_any_midi_quirk,
@@ -497,6 +498,92 @@ static int snd_usb_nativeinstruments_boot_quirk(struct usb_device *dev)
        return -EAGAIN;
 }
 
+static void mbox2_setup_48_24_magic(struct usb_device *dev)
+{
+       u8 srate[3];
+       u8 temp[12];
+
+       /* Choose 48000Hz permanently */
+       srate[0] = 0x80;
+       srate[1] = 0xbb;
+       srate[2] = 0x00;
+
+       /* Send the magic! */
+       snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
+               0x01, 0x22, 0x0100, 0x0085, &temp, 0x0003);
+       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+               0x81, 0xa2, 0x0100, 0x0085, &srate, 0x0003);
+       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+               0x81, 0xa2, 0x0100, 0x0086, &srate, 0x0003);
+       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+               0x81, 0xa2, 0x0100, 0x0003, &srate, 0x0003);
+       return;
+}
+
+/* Digidesign Mbox 2 needs to load firmware onboard
+ * and driver must wait a few seconds for initialisation.
+ */
+
+#define MBOX2_FIRMWARE_SIZE    646
+#define MBOX2_BOOT_LOADING     0x01 /* Hard coded into the device */
+#define MBOX2_BOOT_READY       0x02 /* Hard coded into the device */
+
+int snd_usb_mbox2_boot_quirk(struct usb_device *dev)
+{
+       struct usb_host_config *config = dev->actconfig;
+       int err;
+       u8 bootresponse;
+       int fwsize;
+       int count;
+
+       fwsize = le16_to_cpu(get_cfg_desc(config)->wTotalLength);
+
+       if (fwsize != MBOX2_FIRMWARE_SIZE) {
+               snd_printk(KERN_ERR "usb-audio: Invalid firmware size=%d.\n", fwsize);
+               return -ENODEV;
+       }
+
+       snd_printd("usb-audio: Sending Digidesign Mbox 2 boot sequence...\n");
+
+       count = 0;
+       bootresponse = MBOX2_BOOT_LOADING;
+       while ((bootresponse == MBOX2_BOOT_LOADING) && (count < 10)) {
+               msleep(500); /* 0.5 second delay */
+               snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
+                       /* Control magic - load onboard firmware */
+                       0x85, 0xc0, 0x0001, 0x0000, &bootresponse, 0x0012);
+               if (bootresponse == MBOX2_BOOT_READY)
+                       break;
+               snd_printd("usb-audio: device not ready, resending boot sequence...\n");
+               count++;
+       }
+
+       if (bootresponse != MBOX2_BOOT_READY) {
+               snd_printk(KERN_ERR "usb-audio: Unknown bootresponse=%d, or timed out, ignoring device.\n", bootresponse);
+               return -ENODEV;
+       }
+
+       snd_printdd("usb-audio: device initialised!\n");
+
+       err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
+               &dev->descriptor, sizeof(dev->descriptor));
+       config = dev->actconfig;
+       if (err < 0)
+               snd_printd("error usb_get_descriptor: %d\n", err);
+
+       err = usb_reset_configuration(dev);
+       if (err < 0)
+               snd_printd("error usb_reset_configuration: %d\n", err);
+       snd_printdd("mbox2_boot: new boot length = %d\n",
+               le16_to_cpu(get_cfg_desc(config)->wTotalLength));
+
+       mbox2_setup_48_24_magic(dev);
+
+       snd_printk(KERN_INFO "usb-audio: Digidesign Mbox 2: 24bit 48kHz");
+
+       return 0; /* Successful boot */
+}
+
 /*
  * Setup quirks
  */
@@ -655,6 +742,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
        case USB_ID(0x0ccd, 0x00b1): /* Terratec Aureon 7.1 USB */
                return snd_usb_cm6206_boot_quirk(dev);
 
+       case USB_ID(0x0dba, 0x3000):
+               /* Digidesign Mbox 2 */
+               return snd_usb_mbox2_boot_quirk(dev);
+
        case USB_ID(0x133e, 0x0815):
                /* Access Music VirusTI Desktop */
                return snd_usb_accessmusic_boot_quirk(dev);
index 1ac3fd9cc5a625e89cc1290ab3274ebac6982793..a8172c119796015fa2edd0a675d4568c27f83ba7 100644 (file)
@@ -76,6 +76,7 @@ enum quirk_type {
        QUIRK_MIDI_YAMAHA,
        QUIRK_MIDI_MIDIMAN,
        QUIRK_MIDI_NOVATION,
+       QUIRK_MIDI_MBOX2,
        QUIRK_MIDI_RAW_BYTES,
        QUIRK_MIDI_EMAGIC,
        QUIRK_MIDI_CME,