From 573567e07bb4470ff177f17d1adca3f3bd310221 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 27 Jun 2005 08:17:30 +0200 Subject: [ALSA] usb-audio - high speed audio support USB generic driver Add support for endpoints with bInterval > 1, and decoding of the wMaxPacketSize field of high-speed endpoints. Signed-off-by: Clemens Ladisch --- sound/usb/usbaudio.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) (limited to 'sound/usb/usbaudio.c') diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index b5e734d975e0..facd9fc11c3c 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -153,6 +153,7 @@ struct snd_usb_substream { unsigned int format; /* USB data format */ unsigned int datapipe; /* the data i/o pipe */ unsigned int syncpipe; /* 1 - async out or adaptive in */ + unsigned int datainterval; /* log_2 of data packet interval */ unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */ unsigned int freqn; /* nominal sampling rate in fs/fps in Q16.16 format */ unsigned int freqm; /* momentary sampling rate in fs/fps in Q16.16 format */ @@ -518,7 +519,8 @@ static int prepare_playback_urb(snd_usb_substream_t *subs, if (subs->fill_max) counts = subs->maxframesize; /* fixed */ else { - subs->phase = (subs->phase & 0xffff) + subs->freqm; + subs->phase = (subs->phase & 0xffff) + + (subs->freqm << subs->datainterval); counts = subs->phase >> 16; if (counts > subs->maxframesize) counts = subs->maxframesize; @@ -899,16 +901,19 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by else subs->freqn = get_usb_high_speed_rate(rate); subs->freqm = subs->freqn; - subs->freqmax = subs->freqn + (subs->freqn >> 2); /* max. allowed frequency */ - subs->phase = 0; - - /* calculate the max. size of packet */ - maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3)) >> 16; - if (subs->maxpacksize && maxsize > subs->maxpacksize) { - //snd_printd(KERN_DEBUG "maxsize %d is greater than defined size %d\n", - // maxsize, subs->maxpacksize); + /* calculate max. frequency */ + if (subs->maxpacksize) { + /* whatever fits into a max. size packet */ maxsize = subs->maxpacksize; + subs->freqmax = (maxsize / (frame_bits >> 3)) + << (16 - subs->datainterval); + } else { + /* no max. packet size: just take 25% higher than nominal */ + subs->freqmax = subs->freqn + (subs->freqn >> 2); + maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3)) + >> (16 - subs->datainterval); } + subs->phase = 0; if (subs->fill_max) subs->curpacksize = subs->maxpacksize; @@ -918,7 +923,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) urb_packs = nrpacks; else - urb_packs = nrpacks * 8; + urb_packs = (nrpacks * 8) >> subs->datainterval; /* allocate a temporary buffer for playback */ if (is_playback) { @@ -991,7 +996,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by u->urb->pipe = subs->datapipe; u->urb->transfer_flags = URB_ISO_ASAP; u->urb->number_of_packets = u->packets; - u->urb->interval = 1; + u->urb->interval = 1 << subs->datainterval; u->urb->context = u; u->urb->complete = snd_usb_complete_callback(snd_complete_urb); } @@ -1195,6 +1200,12 @@ static int set_format(snd_usb_substream_t *subs, struct audioformat *fmt) subs->datapipe = usb_sndisocpipe(dev, ep); else subs->datapipe = usb_rcvisocpipe(dev, ep); + if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH && + get_endpoint(alts, 0)->bInterval >= 1 && + get_endpoint(alts, 0)->bInterval <= 4) + subs->datainterval = get_endpoint(alts, 0)->bInterval - 1; + else + subs->datainterval = 0; subs->syncpipe = subs->syncinterval = 0; subs->maxpacksize = fmt->maxpacksize; subs->fill_max = 0; @@ -2492,8 +2503,10 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no) fp->altset_idx = i; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; - /* FIXME: decode wMaxPacketSize of high bandwith endpoints */ fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); + if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) + fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) + * (fp->maxpacksize & 0x7ff); fp->attributes = csep[3]; /* some quirks for attributes here */ -- cgit v1.2.2 From b4d3f9d452ec574e0ffb292267427f69bb470631 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 27 Jun 2005 08:18:27 +0200 Subject: [ALSA] usb-audio - fix capture of non-48k sample rates on Audigy 2 NX USB generic driver On the SB Audigy 2 NX, capturing with sample rates that are not a multiple of 48 kHz does not seem to work, so disable it. Signed-off-by: Clemens Ladisch --- sound/usb/usbaudio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound/usb/usbaudio.c') diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index facd9fc11c3c..c57b44511b54 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -2408,10 +2408,9 @@ static int parse_audio_format(snd_usb_audio_t *chip, struct audioformat *fp, if (chip->usb_id == USB_ID(0x041e, 0x3000) || chip->usb_id == USB_ID(0x041e, 0x3020)) { if (fmt[3] == USB_FORMAT_TYPE_I && - stream == SNDRV_PCM_STREAM_PLAYBACK && fp->rates != SNDRV_PCM_RATE_48000 && fp->rates != SNDRV_PCM_RATE_96000) - return -1; /* use 48k only */ + return -1; } #endif return 0; -- cgit v1.2.2 From b1c6ef52e2623c81c2124801c783a903f6e5437a Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 4 Jul 2005 09:18:46 +0200 Subject: [ALSA] usb-audio - enable high speed transfers with Audiy 2 NX USB generic driver This patch enables the boot commands to activate high speed mode (and associated sample formats like 8 channels with 24 bits at 96 kHz) on the SB Audigy 2 NX. Signed-off-by: Clemens Ladisch --- sound/usb/usbaudio.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'sound/usb/usbaudio.c') diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index c57b44511b54..aee3c0f28eb6 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -2938,8 +2938,6 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev) { -#if 0 - /* TODO: enable this when high speed synchronization actually works */ u8 buf = 1; snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), 0x2a, @@ -2951,7 +2949,6 @@ static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev) 1, 2000, NULL, 0, 1000); return -ENODEV; } -#endif return 0; } -- cgit v1.2.2 From 6155aff84b98b2aa35eaa4384b539dfbab86afcc Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 4 Jul 2005 09:20:42 +0200 Subject: [ALSA] usb-audio - rename QUIRK_MIDI_MOTU to QUIRK_MIDI_RAW USB generic driver Rename the protocol used by the MOTU FastLane to 'raw' because it might be useful with other devices, and there are other MOTU interfaces that do not use this protocol. Signed-off-by: Clemens Ladisch --- sound/usb/usbaudio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/usb/usbaudio.c') diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index aee3c0f28eb6..3eaa08e3e6a6 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -2970,7 +2970,7 @@ static int snd_usb_create_quirk(snd_usb_audio_t *chip, case QUIRK_MIDI_YAMAHA: case QUIRK_MIDI_MIDIMAN: case QUIRK_MIDI_NOVATION: - case QUIRK_MIDI_MOTU: + case QUIRK_MIDI_RAW: case QUIRK_MIDI_EMAGIC: return snd_usb_create_midi_interface(chip, iface, quirk); case QUIRK_COMPOSITE: -- cgit v1.2.2 From b27c187f95cd6c9f13f26a5088bea384ac557b45 Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Sat, 9 Jul 2005 10:54:37 +0200 Subject: [ALSA] Fix-up sleeping in sound/usb USB generic driver,USB USX2Y Description: Fix-up sleeping in sound/usb. Replace big_mdelay() with msleep() to guarantee the task delays as expected. This also involved replacing/removing custom sleep functions. Patch is compile-tested. Signed-off-by: Nishanth Aravamudan Signed-off-by: Jaroslav Kysela --- sound/usb/usbaudio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/usb/usbaudio.c') diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 3eaa08e3e6a6..f2b760d8d77e 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -792,7 +792,7 @@ static int start_urbs(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime) */ static int wait_clear_urbs(snd_usb_substream_t *subs) { - int timeout = HZ; + unsigned long end_time = jiffies + msecs_to_jiffies(1000); unsigned int i; int alive; @@ -812,7 +812,7 @@ static int wait_clear_urbs(snd_usb_substream_t *subs) break; set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); - } while (--timeout > 0); + } while (time_before(jiffies, end_time)); if (alive) snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive); return 0; -- cgit v1.2.2 From f38275fe994c333b809796230f4f98090f8d919b Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 25 Jul 2005 16:17:29 +0200 Subject: [ALSA] usb-audio - add support for Miditech USB MIDI keyboards USB generic driver Add support for Miditech Midistart and MidiStudio keyboards (another case of devices using the standard protocol but having no descriptors). Signed-off-by: Clemens Ladisch --- sound/usb/usbaudio.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/usb/usbaudio.c') diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index f2b760d8d77e..9a0b0899d156 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -2972,6 +2972,7 @@ static int snd_usb_create_quirk(snd_usb_audio_t *chip, case QUIRK_MIDI_NOVATION: case QUIRK_MIDI_RAW: case QUIRK_MIDI_EMAGIC: + case QUIRK_MIDI_MIDITECH: return snd_usb_create_midi_interface(chip, iface, quirk); case QUIRK_COMPOSITE: return create_composite_quirk(chip, iface, quirk); -- cgit v1.2.2 From 854af9578cb84e4ca3cb1551a6be40c4e81bb455 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 25 Jul 2005 16:19:10 +0200 Subject: [ALSA] usb-audio - change quirk type handling USB generic driver Make the quirk type an enum instead of a #defined integer, and use a table for the quirk constructor functions instead of a big switch statement. Signed-off-by: Clemens Ladisch --- sound/usb/usbaudio.c | 59 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 25 deletions(-) (limited to 'sound/usb/usbaudio.c') diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 9a0b0899d156..8298c462c291 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -2735,7 +2735,8 @@ static int create_standard_interface_quirk(snd_usb_audio_t *chip, * to detect the sample rate is by looking at wMaxPacketSize. */ static int create_ua700_ua25_quirk(snd_usb_audio_t *chip, - struct usb_interface *iface) + struct usb_interface *iface, + const snd_usb_audio_quirk_t *quirk) { static const struct audioformat ua_format = { .format = SNDRV_PCM_FORMAT_S24_3LE, @@ -2826,7 +2827,9 @@ static int create_ua700_ua25_quirk(snd_usb_audio_t *chip, /* * Create a stream for an Edirol UA-1000 interface. */ -static int create_ua1000_quirk(snd_usb_audio_t *chip, struct usb_interface *iface) +static int create_ua1000_quirk(snd_usb_audio_t *chip, + struct usb_interface *iface, + const snd_usb_audio_quirk_t *quirk) { static const struct audioformat ua1000_format = { .format = SNDRV_PCM_FORMAT_S32_LE, @@ -2903,6 +2906,13 @@ static int create_composite_quirk(snd_usb_audio_t *chip, return 0; } +static int ignore_interface_quirk(snd_usb_audio_t *chip, + struct usb_interface *iface, + const snd_usb_audio_quirk_t *quirk) +{ + return 0; +} + /* * boot quirks @@ -2965,29 +2975,28 @@ static int snd_usb_create_quirk(snd_usb_audio_t *chip, struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk) { - switch (quirk->type) { - case QUIRK_MIDI_FIXED_ENDPOINT: - case QUIRK_MIDI_YAMAHA: - case QUIRK_MIDI_MIDIMAN: - case QUIRK_MIDI_NOVATION: - case QUIRK_MIDI_RAW: - case QUIRK_MIDI_EMAGIC: - case QUIRK_MIDI_MIDITECH: - return snd_usb_create_midi_interface(chip, iface, quirk); - case QUIRK_COMPOSITE: - return create_composite_quirk(chip, iface, quirk); - case QUIRK_AUDIO_FIXED_ENDPOINT: - return create_fixed_stream_quirk(chip, iface, quirk); - case QUIRK_AUDIO_STANDARD_INTERFACE: - case QUIRK_MIDI_STANDARD_INTERFACE: - return create_standard_interface_quirk(chip, iface, quirk); - case QUIRK_AUDIO_EDIROL_UA700_UA25: - return create_ua700_ua25_quirk(chip, iface); - case QUIRK_AUDIO_EDIROL_UA1000: - return create_ua1000_quirk(chip, iface); - case QUIRK_IGNORE_INTERFACE: - return 0; - default: + typedef int (*quirk_func_t)(snd_usb_audio_t *, struct usb_interface *, + const snd_usb_audio_quirk_t *); + static const quirk_func_t quirk_funcs[] = { + [QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk, + [QUIRK_COMPOSITE] = create_composite_quirk, + [QUIRK_MIDI_STANDARD_INTERFACE] = snd_usb_create_midi_interface, + [QUIRK_MIDI_FIXED_ENDPOINT] = snd_usb_create_midi_interface, + [QUIRK_MIDI_YAMAHA] = snd_usb_create_midi_interface, + [QUIRK_MIDI_MIDIMAN] = snd_usb_create_midi_interface, + [QUIRK_MIDI_NOVATION] = snd_usb_create_midi_interface, + [QUIRK_MIDI_RAW] = snd_usb_create_midi_interface, + [QUIRK_MIDI_EMAGIC] = snd_usb_create_midi_interface, + [QUIRK_MIDI_MIDITECH] = snd_usb_create_midi_interface, + [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_interface_quirk, + [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, + [QUIRK_AUDIO_EDIROL_UA700_UA25] = create_ua700_ua25_quirk, + [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk, + }; + + if (quirk->type < QUIRK_TYPE_COUNT) { + return quirk_funcs[quirk->type](chip, iface, quirk); + } else { snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); return -ENXIO; } -- cgit v1.2.2