summaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
authorAndrej Krutak <dev@andree.sk>2016-09-18 20:59:23 +0200
committerTakashi Iwai <tiwai@suse.de>2016-09-19 23:00:10 +0200
commit7a0f55aeeb8f1fa32a119d34ddfefc6100936692 (patch)
treec09d5ec340198bad9fde8f47f9098233cb6859ab /sound/usb
parent79faa2b048b23f28a24a7b232d8933cb53df95b7 (diff)
downloadlinux-stable-7a0f55aeeb8f1fa32a119d34ddfefc6100936692.tar.gz
linux-stable-7a0f55aeeb8f1fa32a119d34ddfefc6100936692.tar.bz2
linux-stable-7a0f55aeeb8f1fa32a119d34ddfefc6100936692.zip
ALSA: line6: Support assymetrical in/out configurations
Splits max_packet_size to max_packet_size_in/out (e.g. for different channel counts). Signed-off-by: Andrej Krutak <dev@andree.sk> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/line6/capture.c10
-rw-r--r--sound/usb/line6/pcm.c33
-rw-r--r--sound/usb/line6/pcm.h5
-rw-r--r--sound/usb/line6/playback.c2
4 files changed, 28 insertions, 22 deletions
diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c
index 596bc53d0775..8f9647853acd 100644
--- a/sound/usb/line6/capture.c
+++ b/sound/usb/line6/capture.c
@@ -44,13 +44,13 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm)
struct usb_iso_packet_descriptor *fin =
&urb_in->iso_frame_desc[i];
fin->offset = urb_size;
- fin->length = line6pcm->max_packet_size;
- urb_size += line6pcm->max_packet_size;
+ fin->length = line6pcm->max_packet_size_in;
+ urb_size += line6pcm->max_packet_size_in;
}
urb_in->transfer_buffer =
line6pcm->in.buffer +
- index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;
+ index * LINE6_ISO_PACKETS * line6pcm->max_packet_size_in;
urb_in->transfer_buffer_length = urb_size;
urb_in->context = line6pcm;
@@ -173,10 +173,10 @@ static void audio_in_callback(struct urb *urb)
fbuf = urb->transfer_buffer + fin->offset;
fsize = fin->actual_length;
- if (fsize > line6pcm->max_packet_size) {
+ if (fsize > line6pcm->max_packet_size_in) {
dev_err(line6pcm->line6->ifcdev,
"driver and/or device bug: packet too large (%d > %d)\n",
- fsize, line6pcm->max_packet_size);
+ fsize, line6pcm->max_packet_size_in);
}
length += fsize;
diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c
index 317ba68446c6..a5a44309bc9d 100644
--- a/sound/usb/line6/pcm.c
+++ b/sound/usb/line6/pcm.c
@@ -146,16 +146,20 @@ get_stream(struct snd_line6_pcm *line6pcm, int direction)
}
/* allocate a buffer if not opened yet;
- * call this in line6pcm.state_change mutex
+ * call this in line6pcm.state_mutex
*/
static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm,
- struct line6_pcm_stream *pstr, int type)
+ struct line6_pcm_stream *pstr, int direction, int type)
{
+ const int pkt_size =
+ (direction == SNDRV_PCM_STREAM_PLAYBACK) ?
+ line6pcm->max_packet_size_out :
+ line6pcm->max_packet_size_in;
+
/* Invoked multiple times in a row so allocate once only */
if (!test_and_set_bit(type, &pstr->opened) && !pstr->buffer) {
pstr->buffer = kmalloc(line6pcm->line6->iso_buffers *
- LINE6_ISO_PACKETS *
- line6pcm->max_packet_size, GFP_KERNEL);
+ LINE6_ISO_PACKETS * pkt_size, GFP_KERNEL);
if (!pstr->buffer)
return -ENOMEM;
}
@@ -163,12 +167,11 @@ static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm,
}
/* free a buffer if all streams are closed;
- * call this in line6pcm.state_change mutex
+ * call this in line6pcm.state_mutex
*/
static void line6_buffer_release(struct snd_line6_pcm *line6pcm,
struct line6_pcm_stream *pstr, int type)
{
-
clear_bit(type, &pstr->opened);
if (!pstr->opened) {
line6_wait_clear_audio_urbs(line6pcm, pstr);
@@ -195,6 +198,7 @@ static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction,
else
ret = line6_submit_audio_in_all_urbs(line6pcm);
}
+
if (ret < 0)
clear_bit(type, &pstr->running);
spin_unlock_irqrestore(&pstr->lock, flags);
@@ -290,7 +294,7 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type)
mutex_lock(&line6pcm->state_mutex);
for (dir = 0; dir < 2; dir++) {
pstr = get_stream(line6pcm, dir);
- ret = line6_buffer_acquire(line6pcm, pstr, type);
+ ret = line6_buffer_acquire(line6pcm, pstr, dir, type);
if (ret < 0)
goto error;
if (!pstr->running)
@@ -335,7 +339,8 @@ int snd_line6_hw_params(struct snd_pcm_substream *substream,
struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
mutex_lock(&line6pcm->state_mutex);
- ret = line6_buffer_acquire(line6pcm, pstr, LINE6_STREAM_PCM);
+ ret = line6_buffer_acquire(line6pcm, pstr, substream->stream,
+ LINE6_STREAM_PCM);
if (ret < 0)
goto error;
@@ -530,12 +535,12 @@ int line6_init_pcm(struct usb_line6 *line6,
line6pcm->volume_monitor = 255;
line6pcm->line6 = line6;
- /* Read and write buffers are sized identically, so choose minimum */
- line6pcm->max_packet_size = min(
- usb_maxpacket(line6->usbdev,
- usb_rcvisocpipe(line6->usbdev, ep_read), 0),
- usb_maxpacket(line6->usbdev,
- usb_sndisocpipe(line6->usbdev, ep_write), 1));
+ line6pcm->max_packet_size_in =
+ usb_maxpacket(line6->usbdev,
+ usb_rcvisocpipe(line6->usbdev, ep_read), 0);
+ line6pcm->max_packet_size_out =
+ usb_maxpacket(line6->usbdev,
+ usb_sndisocpipe(line6->usbdev, ep_write), 1);
spin_lock_init(&line6pcm->out.lock);
spin_lock_init(&line6pcm->in.lock);
diff --git a/sound/usb/line6/pcm.h b/sound/usb/line6/pcm.h
index f41e34166d68..f040c81a4843 100644
--- a/sound/usb/line6/pcm.h
+++ b/sound/usb/line6/pcm.h
@@ -156,11 +156,12 @@ struct snd_line6_pcm {
/* Previously captured frame (for software monitoring) */
unsigned char *prev_fbuf;
- /* Size of previously captured frame (for software monitoring) */
+ /* Size of previously captured frame (for software monitoring/sync) */
int prev_fsize;
/* Maximum size of USB packet */
- int max_packet_size;
+ int max_packet_size_in;
+ int max_packet_size_out;
/* PCM playback volume (left and right) */
int volume_playback[2];
diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c
index 6048d0fe4068..08bacf3b025e 100644
--- a/sound/usb/line6/playback.c
+++ b/sound/usb/line6/playback.c
@@ -195,7 +195,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
urb_frames = urb_size / bytes_per_frame;
urb_out->transfer_buffer =
line6pcm->out.buffer +
- index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;
+ index * LINE6_ISO_PACKETS * line6pcm->max_packet_size_out;
urb_out->transfer_buffer_length = urb_size;
urb_out->context = line6pcm;