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>
This commit is contained in:
Родитель
b2233d97a0
Коммит
79faa2b048
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче