ALSA: usb: USB3 SuperSpeed sound support
authorPaul Zimmerman <Paul.Zimmerman@synopsys.com>
Fri, 13 Aug 2010 19:42:07 +0000 (12:42 -0700)
committerTakashi Iwai <tiwai@suse.de>
Sat, 14 Aug 2010 08:30:08 +0000 (10:30 +0200)
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: Paul 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: Takashi Iwai <tiwai@suse.de>
sound/usb/card.c
sound/usb/helper.c
sound/usb/midi.c
sound/usb/pcm.c
sound/usb/proc.c
sound/usb/urb.c

index 9feb00c831a02b791227b75294e6dc8e15975f1f..498a2d8fa4bb4601fdd196c6f1b8fa4266fa1081 100644 (file)
@@ -299,9 +299,13 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
 
        *rchip = NULL;
 
-       if (snd_usb_get_speed(dev) != USB_SPEED_LOW &&
-           snd_usb_get_speed(dev) != USB_SPEED_FULL &&
-           snd_usb_get_speed(dev) != USB_SPEED_HIGH) {
+       switch (snd_usb_get_speed(dev)) {
+       case USB_SPEED_LOW:
+       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));
                return -ENXIO;
        }
@@ -377,11 +381,22 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
        if (len < sizeof(card->longname))
                usb_make_path(dev, card->longname + len, sizeof(card->longname) - len);
 
-       strlcat(card->longname,
-               snd_usb_get_speed(dev) == USB_SPEED_LOW ? ", low speed" :
-               snd_usb_get_speed(dev) == USB_SPEED_FULL ? ", full speed" :
-               ", high speed",
-               sizeof(card->longname));
+       switch (snd_usb_get_speed(dev)) {
+       case USB_SPEED_LOW:
+               strlcat(card->longname, ", low speed", sizeof(card->longname));
+               break;
+       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);
 
index d48d6f8f6ac9747343b6c3b7c6e5d3760464c7e4..f280c1903c25bdaa0b20e8456b6753c3dc5edcfb 100644 (file)
@@ -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,
                                         struct usb_host_interface *alts)
 {
-       if (snd_usb_get_speed(chip->dev) == USB_SPEED_HIGH &&
-           get_endpoint(alts, 0)->bInterval >= 1 &&
-           get_endpoint(alts, 0)->bInterval <= 4)
-               return get_endpoint(alts, 0)->bInterval - 1;
-       else
-               return 0;
+       switch (snd_usb_get_speed(chip->dev)) {
+       case USB_SPEED_HIGH:
+       case USB_SPEED_SUPER:
+               if (get_endpoint(alts, 0)->bInterval >= 1 &&
+                   get_endpoint(alts, 0)->bInterval <= 4)
+                       return get_endpoint(alts, 0)->bInterval - 1;
+               break;
+       default:
+               break;
+       }
+       return 0;
 }
 
index b9c2bc65f51ae7bd24da9adfaf8b62c241c2846f..156cd0716c42e4030536bc2d79c01155c68f5b67 100644 (file)
@@ -834,7 +834,14 @@ static void snd_usbmidi_us122l_output(struct snd_usb_midi_out_endpoint *ep,
 
        if (!ep->ports[0].active)
                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,
                                     urb->transfer_buffer,
                                     count);
index 456829882f4061aca8e97f9d53d07f29d309bd1e..ebd09acd186e0ae1c914a13a44210b331eb0bcf9 100644 (file)
@@ -467,7 +467,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs,
                return 0;
        }
        /* 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);
                if (ptime > pt->max || (ptime == pt->max && pt->openmax)) {
                        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
        }
 
        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 */
                ptmin = 1000;
        if (ptmin == 1000)
index f5e3f356b95ff4277e98ad5ad60518f2cac15aa7..3c650ab3c91de8e2edb87e3e0b03ce716b17d894 100644 (file)
@@ -107,7 +107,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
                        }
                        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",
                                    125 * (1 << fp->datainterval));
                // snd_iprintf(buffer, "    Max Packet Size = %d\n", fp->maxpacksize);
index de607d4411acf5137edbeeb4e6af45ea0546b67b..8deeaad10f10caa4827288cc41230ce1cc6eb77e 100644 (file)
@@ -244,7 +244,7 @@ int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
        else
                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;
        else
                packs_per_ms = 1;