提交 4f4e8f69 编写于 作者: P Paul Zimmerman 提交者: Takashi Iwai

ALSA: usb: USB3 SuperSpeed sound support

This is V2 of the patch, after feedback from Clemens and Daniel.

This patch adds SuperSpeed support to the USB drivers under sound/. It adds
tests for USB_SPEED_SUPER to the appropriate places that check for the USB
speed.

This patch has been tested with our SS USB3 device emulating a set of Yamaha
speakers and a Logitech microphone, but with the descriptors modified to add
USB3 support. It has also been tested with the real speakers and microphone,
to make sure that USB2 devices still work.
Signed-off-by: NPaul Zimmerman <paulz@synopsys.com>
Cc: Clemens Ladisch <clemens@ladisch.de>
Cc: Daniel Mack <daniel@caiaq.de>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: NTakashi Iwai <tiwai@suse.de>
上级 31cbd977
...@@ -299,9 +299,13 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, ...@@ -299,9 +299,13 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
*rchip = NULL; *rchip = NULL;
if (snd_usb_get_speed(dev) != USB_SPEED_LOW && switch (snd_usb_get_speed(dev)) {
snd_usb_get_speed(dev) != USB_SPEED_FULL && case USB_SPEED_LOW:
snd_usb_get_speed(dev) != USB_SPEED_HIGH) { case USB_SPEED_FULL:
case USB_SPEED_HIGH:
case USB_SPEED_SUPER:
break;
default:
snd_printk(KERN_ERR "unknown device speed %d\n", snd_usb_get_speed(dev)); snd_printk(KERN_ERR "unknown device speed %d\n", snd_usb_get_speed(dev));
return -ENXIO; return -ENXIO;
} }
...@@ -377,11 +381,22 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, ...@@ -377,11 +381,22 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
if (len < sizeof(card->longname)) if (len < sizeof(card->longname))
usb_make_path(dev, card->longname + len, sizeof(card->longname) - len); usb_make_path(dev, card->longname + len, sizeof(card->longname) - len);
strlcat(card->longname, switch (snd_usb_get_speed(dev)) {
snd_usb_get_speed(dev) == USB_SPEED_LOW ? ", low speed" : case USB_SPEED_LOW:
snd_usb_get_speed(dev) == USB_SPEED_FULL ? ", full speed" : strlcat(card->longname, ", low speed", sizeof(card->longname));
", high speed", break;
sizeof(card->longname)); case USB_SPEED_FULL:
strlcat(card->longname, ", full speed", sizeof(card->longname));
break;
case USB_SPEED_HIGH:
strlcat(card->longname, ", high speed", sizeof(card->longname));
break;
case USB_SPEED_SUPER:
strlcat(card->longname, ", super speed", sizeof(card->longname));
break;
default:
break;
}
snd_usb_audio_create_proc(chip); snd_usb_audio_create_proc(chip);
......
...@@ -103,11 +103,16 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, ...@@ -103,11 +103,16 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip, unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
struct usb_host_interface *alts) struct usb_host_interface *alts)
{ {
if (snd_usb_get_speed(chip->dev) == USB_SPEED_HIGH && switch (snd_usb_get_speed(chip->dev)) {
get_endpoint(alts, 0)->bInterval >= 1 && case USB_SPEED_HIGH:
get_endpoint(alts, 0)->bInterval <= 4) case USB_SPEED_SUPER:
return get_endpoint(alts, 0)->bInterval - 1; if (get_endpoint(alts, 0)->bInterval >= 1 &&
else get_endpoint(alts, 0)->bInterval <= 4)
return 0; return get_endpoint(alts, 0)->bInterval - 1;
break;
default:
break;
}
return 0;
} }
...@@ -834,7 +834,14 @@ static void snd_usbmidi_us122l_output(struct snd_usb_midi_out_endpoint *ep, ...@@ -834,7 +834,14 @@ static void snd_usbmidi_us122l_output(struct snd_usb_midi_out_endpoint *ep,
if (!ep->ports[0].active) if (!ep->ports[0].active)
return; return;
count = snd_usb_get_speed(ep->umidi->dev) == USB_SPEED_HIGH ? 1 : 2; switch (snd_usb_get_speed(ep->umidi->dev)) {
case USB_SPEED_HIGH:
case USB_SPEED_SUPER:
count = 1;
break;
default:
count = 2;
}
count = snd_rawmidi_transmit(ep->ports[0].substream, count = snd_rawmidi_transmit(ep->ports[0].substream,
urb->transfer_buffer, urb->transfer_buffer,
count); count);
......
...@@ -467,7 +467,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs, ...@@ -467,7 +467,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs,
return 0; return 0;
} }
/* check whether the period time is >= the data packet interval */ /* check whether the period time is >= the data packet interval */
if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) { if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) {
ptime = 125 * (1 << fp->datainterval); ptime = 125 * (1 << fp->datainterval);
if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { if (ptime > pt->max || (ptime == pt->max && pt->openmax)) {
hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max);
...@@ -735,7 +735,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre ...@@ -735,7 +735,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
} }
param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
if (snd_usb_get_speed(subs->dev) != USB_SPEED_HIGH) if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
/* full speed devices have fixed data packet interval */ /* full speed devices have fixed data packet interval */
ptmin = 1000; ptmin = 1000;
if (ptmin == 1000) if (ptmin == 1000)
......
...@@ -107,7 +107,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s ...@@ -107,7 +107,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
} }
snd_iprintf(buffer, "\n"); snd_iprintf(buffer, "\n");
} }
if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
snd_iprintf(buffer, " Data packet interval: %d us\n", snd_iprintf(buffer, " Data packet interval: %d us\n",
125 * (1 << fp->datainterval)); 125 * (1 << fp->datainterval));
// snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize); // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize);
......
...@@ -244,7 +244,7 @@ int snd_usb_init_substream_urbs(struct snd_usb_substream *subs, ...@@ -244,7 +244,7 @@ int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
else else
subs->curpacksize = maxsize; subs->curpacksize = maxsize;
if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
packs_per_ms = 8 >> subs->datainterval; packs_per_ms = 8 >> subs->datainterval;
else else
packs_per_ms = 1; packs_per_ms = 1;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册