summaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
authorAndrej Krutak <dev@andree.sk>2016-09-18 20:59:22 +0200
committerTakashi Iwai <tiwai@suse.de>2016-09-19 22:58:50 +0200
commit79faa2b048b23f28a24a7b232d8933cb53df95b7 (patch)
tree0195ebdcd10c70f6e4171fda0aa225c4b6dc7b33 /sound/usb
parentALSA: line6: Enable different number of URBs for frame transfers (diff)
downloadlinux-79faa2b048b23f28a24a7b232d8933cb53df95b7.tar.xz
linux-79faa2b048b23f28a24a7b232d8933cb53df95b7.zip
ALSA: line6: Add high-speed USB support
This has two parts: * intervals_per_second setup (high speed needs 8000, instead of 1000) * iso_buffers setup (count of iso buffers depends on USB speed, 2 is not enough for high speed) Signed-off-by: Andrej Krutak <dev@andree.sk> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/line6/capture.c10
-rw-r--r--sound/usb/line6/driver.c15
-rw-r--r--sound/usb/line6/driver.h15
-rw-r--r--sound/usb/line6/pcm.h7
-rw-r--r--sound/usb/line6/playback.c2
5 files changed, 35 insertions, 14 deletions
diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c
index c2808a0b771a..596bc53d0775 100644
--- a/sound/usb/line6/capture.c
+++ b/sound/usb/line6/capture.c
@@ -181,7 +181,15 @@ static void audio_in_callback(struct urb *urb)
length += fsize;
- /* the following assumes LINE6_ISO_PACKETS == 1: */
+ BUILD_BUG_ON_MSG(LINE6_ISO_PACKETS != 1,
+ "The following code assumes LINE6_ISO_PACKETS == 1");
+ /* TODO:
+ * Also, if iso_buffers != 2, the prev frame is almost random at
+ * playback side.
+ * This needs to be redesigned. It should be "stable", but we may
+ * experience sync problems on such high-speed configs.
+ */
+
line6pcm->prev_fbuf = fbuf;
line6pcm->prev_fsize = fsize;
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
index 527c4086f6fc..14032d96da67 100644
--- a/sound/usb/line6/driver.c
+++ b/sound/usb/line6/driver.c
@@ -462,14 +462,18 @@ static void line6_destruct(struct snd_card *card)
static void line6_get_interval(struct usb_line6 *line6)
{
struct usb_device *usbdev = line6->usbdev;
- struct usb_host_endpoint *ep;
- unsigned pipe = usb_rcvintpipe(usbdev, line6->properties->ep_ctrl_r);
- unsigned epnum = usb_pipeendpoint(pipe);
+ struct usb_host_endpoint *ep = usbdev->ep_in[line6->properties->ep_ctrl_r];
- ep = usbdev->ep_in[epnum];
- line6->iso_buffers = LINE6_ISO_BUFFERS;
if (ep) {
line6->interval = ep->desc.bInterval;
+ if (usbdev->speed == USB_SPEED_LOW) {
+ line6->intervals_per_second = USB_LOW_INTERVALS_PER_SECOND;
+ line6->iso_buffers = USB_LOW_ISO_BUFFERS;
+ } else {
+ line6->intervals_per_second = USB_HIGH_INTERVALS_PER_SECOND;
+ line6->iso_buffers = USB_HIGH_ISO_BUFFERS;
+ }
+
line6->max_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize);
} else {
dev_err(line6->ifcdev,
@@ -559,6 +563,7 @@ int line6_probe(struct usb_interface *interface,
/* query interface number */
interface_number = interface->cur_altsetting->desc.bInterfaceNumber;
+ /* TODO reserves the bus bandwidth even without actual transfer */
ret = usb_set_interface(usbdev, interface_number,
properties->altsetting);
if (ret < 0) {
diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h
index 43dd1d06b5fa..a55eb8871b51 100644
--- a/sound/usb/line6/driver.h
+++ b/sound/usb/line6/driver.h
@@ -18,7 +18,13 @@
#include "midi.h"
-#define USB_INTERVALS_PER_SECOND 1000
+/* USB 1.1 speed configuration */
+#define USB_LOW_INTERVALS_PER_SECOND 1000
+#define USB_LOW_ISO_BUFFERS 2
+
+/* USB 2.0+ speed configuration */
+#define USB_HIGH_INTERVALS_PER_SECOND 8000
+#define USB_HIGH_ISO_BUFFERS 16
/* Fallback USB interval and max packet size values */
#define LINE6_FALLBACK_INTERVAL 10
@@ -109,12 +115,15 @@ struct usb_line6 {
/* Properties */
const struct line6_properties *properties;
- /* Interval (ms) */
+ /* Interval for data USB packets */
int interval;
+ /* ...for isochronous transfers framing */
+ int intervals_per_second;
+
/* Number of isochronous URBs used for frame transfers */
int iso_buffers;
- /* Maximum size of USB packet */
+ /* Maximum size of data USB packet */
int max_packet_size;
/* Device representing the USB interface */
diff --git a/sound/usb/line6/pcm.h b/sound/usb/line6/pcm.h
index e983880703ea..f41e34166d68 100644
--- a/sound/usb/line6/pcm.h
+++ b/sound/usb/line6/pcm.h
@@ -20,9 +20,6 @@
#include "driver.h"
-/* number of URBs */
-#define LINE6_ISO_BUFFERS 2
-
/*
number of USB frames per URB
The Line 6 Windows driver always transmits two frames per packet, but
@@ -31,7 +28,9 @@
*/
#define LINE6_ISO_PACKETS 1
-/* in a "full speed" device (such as the PODxt Pro) this means 1ms */
+/* in a "full speed" device (such as the PODxt Pro) this means 1ms,
+ * for "high speed" it's 1/8ms
+ */
#define LINE6_ISO_INTERVAL 1
#define LINE6_IMPULSE_DEFAULT_PERIOD 100
diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c
index 1380facda427..6048d0fe4068 100644
--- a/sound/usb/line6/playback.c
+++ b/sound/usb/line6/playback.c
@@ -151,7 +151,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
line6pcm->properties->rates.rats[0].num_min;
const int frame_factor =
line6pcm->properties->rates.rats[0].den *
- (USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL);
+ (line6pcm->line6->intervals_per_second / LINE6_ISO_INTERVAL);
struct urb *urb_out;
index = find_first_zero_bit(&line6pcm->out.active_urbs,