From b2233d97a0e64aa1f0557ffb409c957748ae7f3a Mon Sep 17 00:00:00 2001 From: Andrej Krutak Date: Sun, 18 Sep 2016 20:59:21 +0200 Subject: 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 Signed-off-by: Takashi Iwai --- sound/usb/line6/capture.c | 17 +++++++++++------ sound/usb/line6/driver.c | 1 + sound/usb/line6/driver.h | 2 ++ sound/usb/line6/pcm.c | 21 ++++++++++++++------- sound/usb/line6/pcm.h | 2 +- sound/usb/line6/playback.c | 19 ++++++++++++------- 6 files changed, 41 insertions(+), 21 deletions(-) (limited to 'sound') diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c index f518fbbe88de..c2808a0b771a 100644 --- a/sound/usb/line6/capture.c +++ b/sound/usb/line6/capture.c @@ -29,10 +29,10 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm) int ret; struct urb *urb_in; - index = - find_first_zero_bit(&line6pcm->in.active_urbs, LINE6_ISO_BUFFERS); + index = find_first_zero_bit(&line6pcm->in.active_urbs, + 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"); return -EINVAL; } @@ -73,7 +73,7 @@ int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm) { 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); if (ret < 0) break; @@ -154,7 +154,7 @@ static void audio_in_callback(struct urb *urb) line6pcm->in.last_frame = urb->start_frame; /* 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]) break; @@ -247,8 +247,13 @@ int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm) struct usb_line6 *line6 = line6pcm->line6; 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: */ - for (i = 0; i < LINE6_ISO_BUFFERS; ++i) { + for (i = 0; i < line6->iso_buffers; ++i) { struct urb *urb; /* URB for audio in: */ diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index 81b7da8e56d3..527c4086f6fc 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -467,6 +467,7 @@ static void line6_get_interval(struct usb_line6 *line6) unsigned epnum = usb_pipeendpoint(pipe); ep = usbdev->ep_in[epnum]; + line6->iso_buffers = LINE6_ISO_BUFFERS; if (ep) { line6->interval = ep->desc.bInterval; line6->max_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h index 7da643e79e3b..43dd1d06b5fa 100644 --- a/sound/usb/line6/driver.h +++ b/sound/usb/line6/driver.h @@ -111,6 +111,8 @@ struct usb_line6 { /* Interval (ms) */ int interval; + /* Number of isochronous URBs used for frame transfers */ + int iso_buffers; /* Maximum size of USB packet */ int max_packet_size; diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c index 41aa3355e920..317ba68446c6 100644 --- a/sound/usb/line6/pcm.c +++ b/sound/usb/line6/pcm.c @@ -104,7 +104,7 @@ static void line6_unlink_audio_urbs(struct snd_line6_pcm *line6pcm, { 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_and_set_bit(i, &pcms->unlink_urbs)) usb_unlink_urb(pcms->urbs[i]); @@ -124,7 +124,7 @@ static void line6_wait_clear_audio_urbs(struct snd_line6_pcm *line6pcm, do { 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)) 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 */ 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); if (!pstr->buffer) return -ENOMEM; @@ -434,24 +435,30 @@ static struct snd_kcontrol_new line6_controls[] = { /* 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; - 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]) { usb_kill_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) { struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm); - cleanup_urbs(&line6pcm->out); - cleanup_urbs(&line6pcm->in); + cleanup_urbs(&line6pcm->out, line6pcm->line6->iso_buffers); + cleanup_urbs(&line6pcm->in, line6pcm->line6->iso_buffers); kfree(line6pcm); } diff --git a/sound/usb/line6/pcm.h b/sound/usb/line6/pcm.h index 508410adbd51..e983880703ea 100644 --- a/sound/usb/line6/pcm.h +++ b/sound/usb/line6/pcm.h @@ -90,7 +90,7 @@ struct line6_pcm_properties { struct line6_pcm_stream { /* allocated URBs */ - struct urb *urbs[LINE6_ISO_BUFFERS]; + struct urb **urbs; /* Temporary buffer; * Since the packet size is not known in advance, this buffer is diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c index 97ed593f6010..1380facda427 100644 --- a/sound/usb/line6/playback.c +++ b/sound/usb/line6/playback.c @@ -154,10 +154,10 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) (USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL); struct urb *urb_out; - index = - find_first_zero_bit(&line6pcm->out.active_urbs, LINE6_ISO_BUFFERS); + index = find_first_zero_bit(&line6pcm->out.active_urbs, + 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"); return -EINVAL; } @@ -286,7 +286,7 @@ int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm) { 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); if (ret < 0) break; @@ -313,11 +313,11 @@ static void audio_out_callback(struct urb *urb) line6pcm->out.last_frame = urb->start_frame; /* 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]) break; - if (index >= LINE6_ISO_BUFFERS) + if (index >= line6pcm->line6->iso_buffers) return; /* URB has been unlinked asynchronously */ 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; 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: */ - for (i = 0; i < LINE6_ISO_BUFFERS; ++i) { + for (i = 0; i < line6->iso_buffers; ++i) { struct urb *urb; /* URB for audio out: */ -- cgit