ALSA: line6: Enable different number of URBs for frame transfers
This basically changes LINE6_ISO_BUFFERS constant to a configurable iso_buffers property. Signed-off-by: Andrej Krutak <dev@andree.sk> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
c5a905d312
commit
b2233d97a0
|
@ -29,10 +29,10 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm)
|
||||||
int ret;
|
int ret;
|
||||||
struct urb *urb_in;
|
struct urb *urb_in;
|
||||||
|
|
||||||
index =
|
index = find_first_zero_bit(&line6pcm->in.active_urbs,
|
||||||
find_first_zero_bit(&line6pcm->in.active_urbs, LINE6_ISO_BUFFERS);
|
line6pcm->line6->iso_buffers);
|
||||||
|
|
||||||
if (index < 0 || index >= LINE6_ISO_BUFFERS) {
|
if (index < 0 || index >= line6pcm->line6->iso_buffers) {
|
||||||
dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
|
dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm)
|
||||||
{
|
{
|
||||||
int ret = 0, i;
|
int ret = 0, i;
|
||||||
|
|
||||||
for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
|
for (i = 0; i < line6pcm->line6->iso_buffers; ++i) {
|
||||||
ret = submit_audio_in_urb(line6pcm);
|
ret = submit_audio_in_urb(line6pcm);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
break;
|
break;
|
||||||
|
@ -154,7 +154,7 @@ static void audio_in_callback(struct urb *urb)
|
||||||
line6pcm->in.last_frame = urb->start_frame;
|
line6pcm->in.last_frame = urb->start_frame;
|
||||||
|
|
||||||
/* find index of URB */
|
/* find index of URB */
|
||||||
for (index = 0; index < LINE6_ISO_BUFFERS; ++index)
|
for (index = 0; index < line6pcm->line6->iso_buffers; ++index)
|
||||||
if (urb == line6pcm->in.urbs[index])
|
if (urb == line6pcm->in.urbs[index])
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -247,8 +247,13 @@ int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm)
|
||||||
struct usb_line6 *line6 = line6pcm->line6;
|
struct usb_line6 *line6 = line6pcm->line6;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
line6pcm->in.urbs = kzalloc(
|
||||||
|
sizeof(struct urb *) * line6->iso_buffers, GFP_KERNEL);
|
||||||
|
if (line6pcm->in.urbs == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
/* create audio URBs and fill in constant values: */
|
/* create audio URBs and fill in constant values: */
|
||||||
for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
|
for (i = 0; i < line6->iso_buffers; ++i) {
|
||||||
struct urb *urb;
|
struct urb *urb;
|
||||||
|
|
||||||
/* URB for audio in: */
|
/* URB for audio in: */
|
||||||
|
|
|
@ -467,6 +467,7 @@ static void line6_get_interval(struct usb_line6 *line6)
|
||||||
unsigned epnum = usb_pipeendpoint(pipe);
|
unsigned epnum = usb_pipeendpoint(pipe);
|
||||||
|
|
||||||
ep = usbdev->ep_in[epnum];
|
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;
|
||||||
line6->max_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize);
|
line6->max_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize);
|
||||||
|
|
|
@ -111,6 +111,8 @@ struct usb_line6 {
|
||||||
|
|
||||||
/* Interval (ms) */
|
/* Interval (ms) */
|
||||||
int interval;
|
int interval;
|
||||||
|
/* Number of isochronous URBs used for frame transfers */
|
||||||
|
int iso_buffers;
|
||||||
|
|
||||||
/* Maximum size of USB packet */
|
/* Maximum size of USB packet */
|
||||||
int max_packet_size;
|
int max_packet_size;
|
||||||
|
|
|
@ -104,7 +104,7 @@ static void line6_unlink_audio_urbs(struct snd_line6_pcm *line6pcm,
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
|
for (i = 0; i < line6pcm->line6->iso_buffers; i++) {
|
||||||
if (test_bit(i, &pcms->active_urbs)) {
|
if (test_bit(i, &pcms->active_urbs)) {
|
||||||
if (!test_and_set_bit(i, &pcms->unlink_urbs))
|
if (!test_and_set_bit(i, &pcms->unlink_urbs))
|
||||||
usb_unlink_urb(pcms->urbs[i]);
|
usb_unlink_urb(pcms->urbs[i]);
|
||||||
|
@ -124,7 +124,7 @@ static void line6_wait_clear_audio_urbs(struct snd_line6_pcm *line6pcm,
|
||||||
|
|
||||||
do {
|
do {
|
||||||
alive = 0;
|
alive = 0;
|
||||||
for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
|
for (i = 0; i < line6pcm->line6->iso_buffers; i++) {
|
||||||
if (test_bit(i, &pcms->active_urbs))
|
if (test_bit(i, &pcms->active_urbs))
|
||||||
alive++;
|
alive++;
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,8 @@ static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm,
|
||||||
{
|
{
|
||||||
/* Invoked multiple times in a row so allocate once only */
|
/* Invoked multiple times in a row so allocate once only */
|
||||||
if (!test_and_set_bit(type, &pstr->opened) && !pstr->buffer) {
|
if (!test_and_set_bit(type, &pstr->opened) && !pstr->buffer) {
|
||||||
pstr->buffer = kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
|
pstr->buffer = kmalloc(line6pcm->line6->iso_buffers *
|
||||||
|
LINE6_ISO_PACKETS *
|
||||||
line6pcm->max_packet_size, GFP_KERNEL);
|
line6pcm->max_packet_size, GFP_KERNEL);
|
||||||
if (!pstr->buffer)
|
if (!pstr->buffer)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -434,24 +435,30 @@ static struct snd_kcontrol_new line6_controls[] = {
|
||||||
/*
|
/*
|
||||||
Cleanup the PCM device.
|
Cleanup the PCM device.
|
||||||
*/
|
*/
|
||||||
static void cleanup_urbs(struct line6_pcm_stream *pcms)
|
static void cleanup_urbs(struct line6_pcm_stream *pcms, int iso_buffers)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
|
/* Most likely impossible in current code... */
|
||||||
|
if (pcms->urbs == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < iso_buffers; i++) {
|
||||||
if (pcms->urbs[i]) {
|
if (pcms->urbs[i]) {
|
||||||
usb_kill_urb(pcms->urbs[i]);
|
usb_kill_urb(pcms->urbs[i]);
|
||||||
usb_free_urb(pcms->urbs[i]);
|
usb_free_urb(pcms->urbs[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
kfree(pcms->urbs);
|
||||||
|
pcms->urbs = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void line6_cleanup_pcm(struct snd_pcm *pcm)
|
static void line6_cleanup_pcm(struct snd_pcm *pcm)
|
||||||
{
|
{
|
||||||
struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);
|
struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);
|
||||||
|
|
||||||
cleanup_urbs(&line6pcm->out);
|
cleanup_urbs(&line6pcm->out, line6pcm->line6->iso_buffers);
|
||||||
cleanup_urbs(&line6pcm->in);
|
cleanup_urbs(&line6pcm->in, line6pcm->line6->iso_buffers);
|
||||||
kfree(line6pcm);
|
kfree(line6pcm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ struct line6_pcm_properties {
|
||||||
|
|
||||||
struct line6_pcm_stream {
|
struct line6_pcm_stream {
|
||||||
/* allocated URBs */
|
/* allocated URBs */
|
||||||
struct urb *urbs[LINE6_ISO_BUFFERS];
|
struct urb **urbs;
|
||||||
|
|
||||||
/* Temporary buffer;
|
/* Temporary buffer;
|
||||||
* Since the packet size is not known in advance, this buffer is
|
* Since the packet size is not known in advance, this buffer is
|
||||||
|
|
|
@ -154,10 +154,10 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
|
||||||
(USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL);
|
(USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL);
|
||||||
struct urb *urb_out;
|
struct urb *urb_out;
|
||||||
|
|
||||||
index =
|
index = find_first_zero_bit(&line6pcm->out.active_urbs,
|
||||||
find_first_zero_bit(&line6pcm->out.active_urbs, LINE6_ISO_BUFFERS);
|
line6pcm->line6->iso_buffers);
|
||||||
|
|
||||||
if (index < 0 || index >= LINE6_ISO_BUFFERS) {
|
if (index < 0 || index >= line6pcm->line6->iso_buffers) {
|
||||||
dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
|
dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -286,7 +286,7 @@ int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm)
|
||||||
{
|
{
|
||||||
int ret = 0, i;
|
int ret = 0, i;
|
||||||
|
|
||||||
for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
|
for (i = 0; i < line6pcm->line6->iso_buffers; ++i) {
|
||||||
ret = submit_audio_out_urb(line6pcm);
|
ret = submit_audio_out_urb(line6pcm);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
break;
|
break;
|
||||||
|
@ -313,11 +313,11 @@ static void audio_out_callback(struct urb *urb)
|
||||||
line6pcm->out.last_frame = urb->start_frame;
|
line6pcm->out.last_frame = urb->start_frame;
|
||||||
|
|
||||||
/* find index of URB */
|
/* find index of URB */
|
||||||
for (index = 0; index < LINE6_ISO_BUFFERS; index++)
|
for (index = 0; index < line6pcm->line6->iso_buffers; index++)
|
||||||
if (urb == line6pcm->out.urbs[index])
|
if (urb == line6pcm->out.urbs[index])
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (index >= LINE6_ISO_BUFFERS)
|
if (index >= line6pcm->line6->iso_buffers)
|
||||||
return; /* URB has been unlinked asynchronously */
|
return; /* URB has been unlinked asynchronously */
|
||||||
|
|
||||||
for (i = 0; i < LINE6_ISO_PACKETS; i++)
|
for (i = 0; i < LINE6_ISO_PACKETS; i++)
|
||||||
|
@ -401,8 +401,13 @@ int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm)
|
||||||
struct usb_line6 *line6 = line6pcm->line6;
|
struct usb_line6 *line6 = line6pcm->line6;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
line6pcm->out.urbs = kzalloc(
|
||||||
|
sizeof(struct urb *) * line6->iso_buffers, GFP_KERNEL);
|
||||||
|
if (line6pcm->out.urbs == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
/* create audio URBs and fill in constant values: */
|
/* create audio URBs and fill in constant values: */
|
||||||
for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
|
for (i = 0; i < line6->iso_buffers; ++i) {
|
||||||
struct urb *urb;
|
struct urb *urb;
|
||||||
|
|
||||||
/* URB for audio out: */
|
/* URB for audio out: */
|
||||||
|
|
Loading…
Reference in a new issue