diff options
author | Jaroslav Kysela <perex@suse.cz> | 2004-04-24 19:57:44 +0200 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2004-04-24 19:57:44 +0200 |
commit | 0e38be1097b579381053f9a23572e975475c18fa (patch) | |
tree | f35006dfd5695de4c8e8777278284d348648b371 /sound | |
parent | adf81ab101c1505a8d1ebdcc875cb121c8180f45 (diff) | |
download | history-0e38be1097b579381053f9a23572e975475c18fa.tar.gz |
ALSA CVS update - Clemens Ladisch <clemens@ladisch.de>
USB generic driver
Edirol UA-700 advanced modes support
Diffstat (limited to 'sound')
-rw-r--r-- | sound/usb/usbaudio.c | 79 | ||||
-rw-r--r-- | sound/usb/usbaudio.h | 3 | ||||
-rw-r--r-- | sound/usb/usbquirks.h | 30 |
3 files changed, 106 insertions, 6 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 425622ed744be1..0a97a9cce748a2 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -2742,6 +2742,83 @@ static int create_standard_interface_quirk(snd_usb_audio_t *chip, return 0; } +/* + * Create a stream for an Edirol UA-700 interface. The only way + * to detect the sample rate is by looking at wMaxPacketSize. + */ +static int create_ua700_quirk(snd_usb_audio_t *chip, struct usb_interface *iface) +{ + static const struct audioformat ua700_format = { + .format = SNDRV_PCM_FORMAT_S24_3LE, + .channels = 2, + .fmt_type = USB_FORMAT_TYPE_I, + .altsetting = 1, + .altset_idx = 1, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + }; + struct usb_host_interface *alts; + struct usb_interface_descriptor *altsd; + struct audioformat *fp; + int stream, err; + + /* both PCM and MIDI interfaces have 2 altsettings */ + if (iface->num_altsetting != 2) + return -ENXIO; + alts = &iface->altsetting[1]; + altsd = get_iface_desc(alts); + + if (altsd->bNumEndpoints == 2) { + static const snd_usb_midi_endpoint_info_t ep = { + .out_cables = 0x0003, + .in_cables = 0x0003 + }; + static const snd_usb_audio_quirk_t quirk = { + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = &ep + }; + return snd_usb_create_midi_interface(chip, iface, &quirk); + } + + if (altsd->bNumEndpoints != 1) + return -ENXIO; + + fp = kmalloc(sizeof(*fp), GFP_KERNEL); + if (!fp) + return -ENOMEM; + memcpy(fp, &ua700_format, sizeof(*fp)); + + fp->iface = altsd->bInterfaceNumber; + fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; + fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; + fp->maxpacksize = get_endpoint(alts, 0)->wMaxPacketSize; + + switch (fp->maxpacksize) { + case 0x120: + fp->rate_max = fp->rate_min = 44100; + break; + case 0x138: + fp->rate_max = fp->rate_min = 48000; + break; + case 0x258: + fp->rate_max = fp->rate_min = 96000; + break; + default: + snd_printk(KERN_ERR "unknown sample rate\n"); + kfree(fp); + return -ENXIO; + } + + stream = (fp->endpoint & USB_DIR_IN) + ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; + err = add_audio_endpoint(chip, stream, fp); + if (err < 0) { + kfree(fp); + return err; + } + usb_set_interface(chip->dev, fp->iface, 0); + return 0; +} + static int snd_usb_create_quirk(snd_usb_audio_t *chip, struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk); @@ -2829,6 +2906,8 @@ static int snd_usb_create_quirk(snd_usb_audio_t *chip, case QUIRK_AUDIO_STANDARD_INTERFACE: case QUIRK_MIDI_STANDARD_INTERFACE: return create_standard_interface_quirk(chip, iface, quirk); + case QUIRK_AUDIO_EDIROL_UA700: + return create_ua700_quirk(chip, iface); default: snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); return -ENXIO; diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index d3b4b551abc674..2fe29989ea5906 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -154,6 +154,7 @@ struct snd_usb_audio { #define QUIRK_AUDIO_FIXED_ENDPOINT 4 #define QUIRK_AUDIO_STANDARD_INTERFACE 5 #define QUIRK_MIDI_STANDARD_INTERFACE 6 +#define QUIRK_AUDIO_EDIROL_UA700 7 typedef struct snd_usb_audio_quirk snd_usb_audio_quirk_t; typedef struct snd_usb_midi_endpoint_info snd_usb_midi_endpoint_info_t; @@ -185,6 +186,8 @@ struct snd_usb_midi_endpoint_info { /* for QUIRK_AUDIO/MIDI_STANDARD_INTERFACE, data is NULL */ +/* for QUIRK_AUDIO_EDIROL_UA700, data is NULL */ + /* */ diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index fe0e14bf1cfd12..ed2eccb4096863 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h @@ -488,16 +488,34 @@ YAMAHA_DEVICE(0x5008, "01V96"), } } }, -{ +{ /* + * This quirk is for the "Advanced" modes of the Edirol UA-700. + * If the sample format switch is not in an advanced setting, the + * UA-700 has ID 0x0582/0x002c and is standard compliant (no quirks), + * but offers only 16-bit PCM and no MIDI. + */ USB_DEVICE_VENDOR_SPEC(0x0582, 0x002b), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", .product_name = "UA-700", - .ifnum = 3, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const snd_usb_midi_endpoint_info_t) { - .out_cables = 0x0003, - .in_cables = 0x0003 + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const snd_usb_audio_quirk_t[]) { + { + .ifnum = 1, + .type = QUIRK_AUDIO_EDIROL_UA700 + }, + { + .ifnum = 2, + .type = QUIRK_AUDIO_EDIROL_UA700 + }, + { + .ifnum = 3, + .type = QUIRK_AUDIO_EDIROL_UA700 + }, + { + .ifnum = -1 + } } } }, |