Skip to content

Commit

Permalink
ALSA: snd-usb: add support for implicit feedback
Browse files Browse the repository at this point in the history
Implicit feedback is a streaming mode that does not rely on dedicated
sync endpoints but uses the information provided by record streams to
clock output streams. Now that the streaming logic is decoupled from the
PCM streams, this is easy to implement.

Signed-off-by: Daniel Mack <zonque@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
Daniel Mack authored and Takashi Iwai committed Apr 13, 2012
1 parent d399ff9 commit c75a8a7
Showing 1 changed file with 26 additions and 11 deletions.
37 changes: 26 additions & 11 deletions sound/usb/pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
struct usb_interface *iface;
unsigned int ep, attr;
int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
int err;
int err, implicit_fb = 0;

iface = usb_ifnum_to_if(dev, fmt->iface);
if (WARN_ON(!iface))
Expand All @@ -326,42 +326,57 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
* assume it as adaptive-out or sync-in.
*/
attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE;
if (((is_playback && attr == USB_ENDPOINT_SYNC_ASYNC) ||
(! is_playback && attr == USB_ENDPOINT_SYNC_ADAPTIVE)) &&
altsd->bNumEndpoints >= 2) {
switch (subs->stream->chip->usb_id) {
case USB_ID(0x0763, 0x2080): /* M-Audio FastTrack Ultra */
case USB_ID(0x0763, 0x2081):

switch (subs->stream->chip->usb_id) {
case USB_ID(0x0763, 0x2080): /* M-Audio FastTrack Ultra */
case USB_ID(0x0763, 0x2081):
if (is_playback) {
implicit_fb = 1;
ep = 0x81;
iface = usb_ifnum_to_if(dev, 2);

if (!iface || iface->num_altsetting == 0)
return -EINVAL;

alts = &iface->altsetting[1];
goto add_sync_ep;
}
}

if (((is_playback && attr == USB_ENDPOINT_SYNC_ASYNC) ||
(!is_playback && attr == USB_ENDPOINT_SYNC_ADAPTIVE)) &&
altsd->bNumEndpoints >= 2) {
/* check sync-pipe endpoint */
/* ... and check descriptor size before accessing bSynchAddress
because there is a version of the SB Audigy 2 NX firmware lacking
the audio fields in the endpoint descriptors */
if ((get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != 0x01 ||
(get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
get_endpoint(alts, 1)->bSynchAddress != 0)) {
get_endpoint(alts, 1)->bSynchAddress != 0 &&
!implicit_fb)) {
snd_printk(KERN_ERR "%d:%d:%d : invalid synch pipe\n",
dev->devnum, fmt->iface, fmt->altsetting);
return -EINVAL;
}
ep = get_endpoint(alts, 1)->bEndpointAddress;
if (get_endpoint(alts, 0)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
(( is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress | USB_DIR_IN)) ||
(!is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress & ~USB_DIR_IN)))) {
(!is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress & ~USB_DIR_IN)) ||
( is_playback && !implicit_fb))) {
snd_printk(KERN_ERR "%d:%d:%d : invalid synch pipe\n",
dev->devnum, fmt->iface, fmt->altsetting);
return -EINVAL;
}

implicit_fb = (get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_USAGE_MASK)
== USB_ENDPOINT_USAGE_IMPLICIT_FB;

add_sync_ep:
subs->sync_endpoint = snd_usb_add_endpoint(subs->stream->chip,
alts, ep, !subs->direction,
SND_USB_ENDPOINT_TYPE_SYNC);

implicit_fb ?
SND_USB_ENDPOINT_TYPE_DATA :
SND_USB_ENDPOINT_TYPE_SYNC);
if (!subs->sync_endpoint)
return -EINVAL;

Expand Down

0 comments on commit c75a8a7

Please sign in to comment.