Commit 79faa2b0 authored by Andrej Krutak's avatar Andrej Krutak Committed by Takashi Iwai

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: default avatarAndrej Krutak <dev@andree.sk>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent b2233d97
...@@ -181,7 +181,15 @@ static void audio_in_callback(struct urb *urb) ...@@ -181,7 +181,15 @@ static void audio_in_callback(struct urb *urb)
length += fsize; 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_fbuf = fbuf;
line6pcm->prev_fsize = fsize; line6pcm->prev_fsize = fsize;
......
...@@ -462,14 +462,18 @@ static void line6_destruct(struct snd_card *card) ...@@ -462,14 +462,18 @@ static void line6_destruct(struct snd_card *card)
static void line6_get_interval(struct usb_line6 *line6) static void line6_get_interval(struct usb_line6 *line6)
{ {
struct usb_device *usbdev = line6->usbdev; struct usb_device *usbdev = line6->usbdev;
struct usb_host_endpoint *ep; struct usb_host_endpoint *ep = usbdev->ep_in[line6->properties->ep_ctrl_r];
unsigned pipe = usb_rcvintpipe(usbdev, line6->properties->ep_ctrl_r);
unsigned epnum = usb_pipeendpoint(pipe);
ep = usbdev->ep_in[epnum];
line6->iso_buffers = LINE6_ISO_BUFFERS;
if (ep) { if (ep) {
line6->interval = ep->desc.bInterval; 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); line6->max_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize);
} else { } else {
dev_err(line6->ifcdev, dev_err(line6->ifcdev,
...@@ -559,6 +563,7 @@ int line6_probe(struct usb_interface *interface, ...@@ -559,6 +563,7 @@ int line6_probe(struct usb_interface *interface,
/* query interface number */ /* query interface number */
interface_number = interface->cur_altsetting->desc.bInterfaceNumber; interface_number = interface->cur_altsetting->desc.bInterfaceNumber;
/* TODO reserves the bus bandwidth even without actual transfer */
ret = usb_set_interface(usbdev, interface_number, ret = usb_set_interface(usbdev, interface_number,
properties->altsetting); properties->altsetting);
if (ret < 0) { if (ret < 0) {
......
...@@ -18,7 +18,13 @@ ...@@ -18,7 +18,13 @@
#include "midi.h" #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 */ /* Fallback USB interval and max packet size values */
#define LINE6_FALLBACK_INTERVAL 10 #define LINE6_FALLBACK_INTERVAL 10
...@@ -109,12 +115,15 @@ struct usb_line6 { ...@@ -109,12 +115,15 @@ struct usb_line6 {
/* Properties */ /* Properties */
const struct line6_properties *properties; const struct line6_properties *properties;
/* Interval (ms) */ /* Interval for data USB packets */
int interval; int interval;
/* ...for isochronous transfers framing */
int intervals_per_second;
/* Number of isochronous URBs used for frame transfers */ /* Number of isochronous URBs used for frame transfers */
int iso_buffers; int iso_buffers;
/* Maximum size of USB packet */ /* Maximum size of data USB packet */
int max_packet_size; int max_packet_size;
/* Device representing the USB interface */ /* Device representing the USB interface */
......
...@@ -20,9 +20,6 @@ ...@@ -20,9 +20,6 @@
#include "driver.h" #include "driver.h"
/* number of URBs */
#define LINE6_ISO_BUFFERS 2
/* /*
number of USB frames per URB number of USB frames per URB
The Line 6 Windows driver always transmits two frames per packet, but The Line 6 Windows driver always transmits two frames per packet, but
...@@ -31,7 +28,9 @@ ...@@ -31,7 +28,9 @@
*/ */
#define LINE6_ISO_PACKETS 1 #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_ISO_INTERVAL 1
#define LINE6_IMPULSE_DEFAULT_PERIOD 100 #define LINE6_IMPULSE_DEFAULT_PERIOD 100
......
...@@ -151,7 +151,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) ...@@ -151,7 +151,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
line6pcm->properties->rates.rats[0].num_min; line6pcm->properties->rates.rats[0].num_min;
const int frame_factor = const int frame_factor =
line6pcm->properties->rates.rats[0].den * 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; struct urb *urb_out;
index = find_first_zero_bit(&line6pcm->out.active_urbs, index = find_first_zero_bit(&line6pcm->out.active_urbs,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment