Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -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;

+10 −5
Original line number Diff line number Diff line
@@ -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) {
+12 −3
Original line number Diff line number Diff line
@@ -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 */
+3 −4
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -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,