aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@suse.cz>2004-04-24 19:57:44 +0200
committerJaroslav Kysela <perex@suse.cz>2004-04-24 19:57:44 +0200
commit0e38be1097b579381053f9a23572e975475c18fa (patch)
treef35006dfd5695de4c8e8777278284d348648b371 /sound
parentadf81ab101c1505a8d1ebdcc875cb121c8180f45 (diff)
downloadhistory-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.c79
-rw-r--r--sound/usb/usbaudio.h3
-rw-r--r--sound/usb/usbquirks.h30
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
+ }
}
}
},