All of lore.kernel.org
 help / color / mirror / Atom feed
* sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2
@ 2010-11-24 12:59 Damien Zammit
  2010-11-25 21:39 ` Daniel Mack
  0 siblings, 1 reply; 27+ messages in thread
From: Damien Zammit @ 2010-11-24 12:59 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: alsa-devel

Hi folks,

I have put together full support for Digidesign Mbox 2, but it needs
someone to help me merge it into alsa.  I haven't seen the latest
snd-usb-audio code since last year, it seems to have branched into
multiple files.

I have worked out how the Digidesign Mbox 2 needs to be configured, it
supports SPDIF i/o simultaneously with analogue but can be toggled on
and off by using different altsettings.
Also the sample clock rate must be configured via a special method.

Therefore I have provided for this in a device_setup parameter with 4 settings:
48Khz Spdif+analog = 0
44.1Khz Spdif+analog = 1
48Khz Analog only = 2
44.1Khz Analog only = 3

###### audio

        /* Digidesign Mbox 2 workaround:
         * supports S24_3BE BIG ENDIAN in an unusual way */
        if (chip->usb_id == USB_ID(0x0dba, 0x3000))
            pcm_format = SNDRV_PCM_FORMAT_S24_3BE;

static int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
                                        int iface, int altno);
static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
{
 .....
.....
            /* Digidesign Mbox 2: skip altsets incompatible with device_setup
                 */
                if (chip->usb_id == USB_ID(0x0dba, 0x3000) &&
                    mbox2_skip_setting_quirk(chip, iface_no, altno))
                        continue;
.....
}


#define MBOX2_SET_48K_SPDIF            0
#define MBOX2_SET_44K_SPDIF            1
#define MBOX2_SET_48K_ANALOG           2
#define MBOX2_SET_44K_ANALOG           3

static int mbox2_skip_setting_quirk(struct snd_usb_audio *chip,
                                        int iface, int altno)
{
        u8 srate[3];
        /* Reset ifaces 2-5 to 0 altsetting. */
        usb_set_interface(chip->dev, iface, 0);

    if (device_setup[chip->index] == MBOX2_SET_48K_SPDIF ||
        device_setup[chip->index] == MBOX2_SET_48K_ANALOG) {
            //setup 48k
                        srate[0]=0x80;
                        srate[1]=0xbb;
                        srate[2]=0x00;

                        /* Send the magic! */
                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
                                0x01, 0x22, 0x0100, 0x0085, &srate,
0x0003, 1000);

                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
                                0x81, 0xa2, 0x0100, 0x0085, &srate,
0x0003, 1000);

                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
                                0x81, 0xa2, 0x0100, 0x0086, &srate,
0x0003, 1000);

                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
                                0x81, 0xa2, 0x0100, 0x0003, &srate,
0x0003, 1000);
            snd_printk(KERN_INFO "Digidesign Mbox 2: 24 Bit 48000Hz");
        if (device_setup[chip->index] == MBOX2_SET_48K_SPDIF) {
            //setup spdif
            snd_printk(KERN_INFO ", SPDIF\n");
            if (altno != 2) return 1;
        } else {
            //setup analog
            snd_printk(KERN_INFO ", ANALOGUE\n");
            if (altno != 3) return 1;
        }
    } else {
            //setup 44k
                        srate[0]=0x44;
                        srate[1]=0xac;
                        srate[2]=0x00;

                        /* Send the magic! */
                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
                                0x01, 0x22, 0x0100, 0x0085, &srate,
0x0003, 1000);

                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
                                0x81, 0xa2, 0x0100, 0x0085, &srate,
0x0003, 1000);

                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
                                0x81, 0xa2, 0x0100, 0x0086, &srate,
0x0003, 1000);

                        snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0),
                                0x81, 0xa2, 0x0100, 0x0003, &srate,
0x0003, 1000);

            snd_printk(KERN_INFO "Digidesign Mbox 2: 24 Bit 44100Hz");
                        if (device_setup[chip->index] == MBOX2_SET_44K_SPDIF ||
                        device_setup[chip->index] == MBOX2_SET_44K_ANALOG) {

            //setup spdif
            snd_printk(KERN_INFO ", SPDIF\n");
            if (altno != 2) return 1;
        } else {
            //setup analog
            snd_printk(KERN_INFO ", ANALOGUE\n");
            if (altno != 3) return 1;
        }
    }

    return 0;
}


#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 */

static int snd_usb_mbox2_boot_quirk(struct usb_device *dev)
{
        struct usb_host_config *config = dev->actconfig;
        int err;
        u8 enablemagic[3];
        u8 bootresponse;
        int fwsize;

        if ((fwsize = le16_to_cpu(get_cfg_desc(config)->wTotalLength))
== MBOX2_FIRMWARE_SIZE) {
                snd_printdd("Sending Digidesign Mbox 2 boot sequence...\n");

                        /* From USB Snoop,
                         *
                         * SetupPacket = RT RQ VHVL INDX SIZE
                         * RT = 0xRT Request Type
                         * RQ = 0xRQ Request
                         * VHVL = 0xVLVH Value in reverse byte order
                         * INDX = 0xDXIN Index in reverse byte order
                         * SIZE = 0xZESI Size in reverse byte order
                         *
                         * Magic boot code setup packet: c0 85 01 00 00 00 12 00
                         *           RQ    RT    VLVH    DXIN
       ZESI
                         * becomes 0x85, 0xc0, 0x0001, 0x0000,
&RETURNDATA, 0x0012, TIMEOUT
                         * for snd_usb_ctl_msg()
                         */

mbox2_reboot:
                snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
                        0x85, 0xc0, 0x0001, 0x0000, &bootresponse,
0x0012, 1000);

                if (bootresponse == MBOX2_BOOT_LOADING) {
                        snd_printdd("device not ready, resending boot
sequence...\n");
                        goto mbox2_reboot;
                }

                if (bootresponse == MBOX2_BOOT_READY) {
                        snd_printdd("device initialised!\n");

                        err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
                                &dev->descriptor, sizeof(dev->descriptor));
                        config = dev->actconfig;
                        if (err < 0) snd_printdd("error
usb_get_descriptor: %d\n", err);
                        err = usb_reset_configuration(dev);
                        if (err < 0) snd_printdd("error
usb_reset_configuration: %d\n", err);
                        snd_printdd("mbox2_boot: new boot length = %d\n",
                            le16_to_cpu(get_cfg_desc(config)->wTotalLength));

                        /* Successful boot, (should reset all
altsettings to 0 like windows does, but works without it)
                         * but now we will try sending
capture/playback enable magic
                         *
                         * 80 bb 00 = 24bit mode - S24_3BE
                         * 44 ac 00 = 16bit mode?
                         *
                         */

                        /* We want 48khz mode for now */
                        enablemagic[0]=0x80;
                        enablemagic[1]=0xbb;
                        enablemagic[2]=0x00;

                        /* Send the magic! */
                        snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
                                0x01, 0x22, 0x0100, 0x0085,
&enablemagic, 0x0003, 1000);

                        snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
                                0x81, 0xa2, 0x0100, 0x0085,
&enablemagic, 0x0003, 1000);

                        snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
                                0x81, 0xa2, 0x0100, 0x0086,
&enablemagic, 0x0003, 1000);

                        snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
                                0x81, 0xa2, 0x0100, 0x0003,
&enablemagic, 0x0003, 1000);

                        return 0; /* Succesful boot */
                }

                snd_printdd("unknown bootresponse, ignoring device:
%d\n",bootresponse);
                return -ENODEV;
        }
        snd_printk("Invalid firmware size: %d\n",fwsize);
        return -ENODEV;
}


#######   quirk:
{

       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_AUDIO_STANDARD_INTERFACE
                       },
                       {
                               .ifnum = 2,
                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
                       },
                       {
                               .ifnum = 3,
                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
                       },
                       {
                                .ifnum = 4,
                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
                       },
                       {
                                .ifnum = 5,
                               .type = QUIRK_AUDIO_STANDARD_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
                       }
               }
       }
},

##### midi

        case QUIRK_MIDI_MBOX2:
                /* Digidesign Mbox 2 uses MIDIMAN MIDI protocol */
                umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops;
                /*
                 * We have to make sure that the USB core looks
                 * again at interface 6 by calling usb_set_interface() on it.
                 */
                usb_set_interface(umidi->chip->dev, 6, 0);
                memcpy(&endpoints[0], quirk->data,
                       sizeof(struct snd_usb_midi_endpoint_info));
                err = 0;
                break;


Damien

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

end of thread, other threads:[~2012-12-23  3:36 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-11-24 12:59 sound: usb-audio: full capture/playback/spdif support for Digidesign Mbox 2 Damien Zammit
2010-11-25 21:39 ` Daniel Mack
2010-11-29 13:03   ` Damien Zammit
2010-11-29 14:50     ` Takashi Iwai
2010-11-30 11:09       ` Damien Zammit
2010-11-30 15:26         ` Clemens Ladisch
2010-12-14  9:57           ` Damien Zammit
2010-12-27 14:50             ` Damien Zammit
2012-12-13  6:21               ` Damien Zammit
2012-12-13  7:01                 ` Takashi Iwai
2012-12-13 13:09                   ` Damien Zammit
2012-12-13 13:18                     ` Takashi Iwai
2012-12-13 13:27                       ` Takashi Iwai
2012-12-13 14:20                         ` Damien Zammit
2012-12-13 14:59                           ` Takashi Iwai
2012-12-13 15:29                             ` Clemens Ladisch
2012-12-16 10:49                             ` [PATCH] " Damien Zammit
2012-12-16 11:06                               ` Damien Zammit
2012-12-17 10:25                                 ` Takashi Iwai
2012-12-18 12:09                                   ` Damien Zammit
2012-12-18 13:08                                     ` Takashi Iwai
2012-12-19 10:30                                       ` Takashi Iwai
2012-12-19 10:37                                         ` Damien Zammit
2012-12-22 23:38                                           ` Damien Zammit
2012-12-23  0:31                                             ` Damien Zammit
2012-12-23  2:18                                               ` Damien Zammit
2012-12-23  3:36                                                 ` Damien Zammit

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.