Commit 7a0f55ae authored by Andrej Krutak's avatar Andrej Krutak Committed by Takashi Iwai

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: default avatarAndrej Krutak <dev@andree.sk>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 79faa2b0
...@@ -44,13 +44,13 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm) ...@@ -44,13 +44,13 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm)
struct usb_iso_packet_descriptor *fin = struct usb_iso_packet_descriptor *fin =
&urb_in->iso_frame_desc[i]; &urb_in->iso_frame_desc[i];
fin->offset = urb_size; fin->offset = urb_size;
fin->length = line6pcm->max_packet_size; fin->length = line6pcm->max_packet_size_in;
urb_size += line6pcm->max_packet_size; urb_size += line6pcm->max_packet_size_in;
} }
urb_in->transfer_buffer = urb_in->transfer_buffer =
line6pcm->in.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->transfer_buffer_length = urb_size;
urb_in->context = line6pcm; urb_in->context = line6pcm;
...@@ -173,10 +173,10 @@ static void audio_in_callback(struct urb *urb) ...@@ -173,10 +173,10 @@ static void audio_in_callback(struct urb *urb)
fbuf = urb->transfer_buffer + fin->offset; fbuf = urb->transfer_buffer + fin->offset;
fsize = fin->actual_length; fsize = fin->actual_length;
if (fsize > line6pcm->max_packet_size) { if (fsize > line6pcm->max_packet_size_in) {
dev_err(line6pcm->line6->ifcdev, dev_err(line6pcm->line6->ifcdev,
"driver and/or device bug: packet too large (%d > %d)\n", "driver and/or device bug: packet too large (%d > %d)\n",
fsize, line6pcm->max_packet_size); fsize, line6pcm->max_packet_size_in);
} }
length += fsize; length += fsize;
......
...@@ -146,16 +146,20 @@ get_stream(struct snd_line6_pcm *line6pcm, int direction) ...@@ -146,16 +146,20 @@ get_stream(struct snd_line6_pcm *line6pcm, int direction)
} }
/* allocate a buffer if not opened yet; /* 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, 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 */ /* 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(line6pcm->line6->iso_buffers * pstr->buffer = kmalloc(line6pcm->line6->iso_buffers *
LINE6_ISO_PACKETS * LINE6_ISO_PACKETS * pkt_size, GFP_KERNEL);
line6pcm->max_packet_size, GFP_KERNEL);
if (!pstr->buffer) if (!pstr->buffer)
return -ENOMEM; return -ENOMEM;
} }
...@@ -163,12 +167,11 @@ static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm, ...@@ -163,12 +167,11 @@ static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm,
} }
/* free a buffer if all streams are closed; /* 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, static void line6_buffer_release(struct snd_line6_pcm *line6pcm,
struct line6_pcm_stream *pstr, int type) struct line6_pcm_stream *pstr, int type)
{ {
clear_bit(type, &pstr->opened); clear_bit(type, &pstr->opened);
if (!pstr->opened) { if (!pstr->opened) {
line6_wait_clear_audio_urbs(line6pcm, pstr); line6_wait_clear_audio_urbs(line6pcm, pstr);
...@@ -195,6 +198,7 @@ static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction, ...@@ -195,6 +198,7 @@ static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction,
else else
ret = line6_submit_audio_in_all_urbs(line6pcm); ret = line6_submit_audio_in_all_urbs(line6pcm);
} }
if (ret < 0) if (ret < 0)
clear_bit(type, &pstr->running); clear_bit(type, &pstr->running);
spin_unlock_irqrestore(&pstr->lock, flags); spin_unlock_irqrestore(&pstr->lock, flags);
...@@ -290,7 +294,7 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type) ...@@ -290,7 +294,7 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type)
mutex_lock(&line6pcm->state_mutex); mutex_lock(&line6pcm->state_mutex);
for (dir = 0; dir < 2; dir++) { for (dir = 0; dir < 2; dir++) {
pstr = get_stream(line6pcm, dir); pstr = get_stream(line6pcm, dir);
ret = line6_buffer_acquire(line6pcm, pstr, type); ret = line6_buffer_acquire(line6pcm, pstr, dir, type);
if (ret < 0) if (ret < 0)
goto error; goto error;
if (!pstr->running) if (!pstr->running)
...@@ -335,7 +339,8 @@ int snd_line6_hw_params(struct snd_pcm_substream *substream, ...@@ -335,7 +339,8 @@ int snd_line6_hw_params(struct snd_pcm_substream *substream,
struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream); struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
mutex_lock(&line6pcm->state_mutex); 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) if (ret < 0)
goto error; goto error;
...@@ -530,12 +535,12 @@ int line6_init_pcm(struct usb_line6 *line6, ...@@ -530,12 +535,12 @@ int line6_init_pcm(struct usb_line6 *line6,
line6pcm->volume_monitor = 255; line6pcm->volume_monitor = 255;
line6pcm->line6 = line6; line6pcm->line6 = line6;
/* Read and write buffers are sized identically, so choose minimum */ line6pcm->max_packet_size_in =
line6pcm->max_packet_size = min(
usb_maxpacket(line6->usbdev, usb_maxpacket(line6->usbdev,
usb_rcvisocpipe(line6->usbdev, ep_read), 0), usb_rcvisocpipe(line6->usbdev, ep_read), 0);
line6pcm->max_packet_size_out =
usb_maxpacket(line6->usbdev, usb_maxpacket(line6->usbdev,
usb_sndisocpipe(line6->usbdev, ep_write), 1)); usb_sndisocpipe(line6->usbdev, ep_write), 1);
spin_lock_init(&line6pcm->out.lock); spin_lock_init(&line6pcm->out.lock);
spin_lock_init(&line6pcm->in.lock); spin_lock_init(&line6pcm->in.lock);
......
...@@ -156,11 +156,12 @@ struct snd_line6_pcm { ...@@ -156,11 +156,12 @@ struct snd_line6_pcm {
/* Previously captured frame (for software monitoring) */ /* Previously captured frame (for software monitoring) */
unsigned char *prev_fbuf; unsigned char *prev_fbuf;
/* Size of previously captured frame (for software monitoring) */ /* Size of previously captured frame (for software monitoring/sync) */
int prev_fsize; int prev_fsize;
/* Maximum size of USB packet */ /* 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) */ /* PCM playback volume (left and right) */
int volume_playback[2]; int volume_playback[2];
......
...@@ -195,7 +195,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) ...@@ -195,7 +195,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
urb_frames = urb_size / bytes_per_frame; urb_frames = urb_size / bytes_per_frame;
urb_out->transfer_buffer = urb_out->transfer_buffer =
line6pcm->out.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->transfer_buffer_length = urb_size;
urb_out->context = line6pcm; urb_out->context = line6pcm;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment