ALSA: line6: Support assymetrical in/out configurations
authorAndrej Krutak <dev@andree.sk>
Sun, 18 Sep 2016 18:59:23 +0000 (20:59 +0200)
committerTakashi Iwai <tiwai@suse.de>
Mon, 19 Sep 2016 21:00:10 +0000 (23:00 +0200)
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>
sound/usb/line6/capture.c
sound/usb/line6/pcm.c
sound/usb/line6/pcm.h
sound/usb/line6/playback.c

index 596bc53d0775a81267200cd7d1421e334b7104da..8f9647853acdcef0a00f1b6017e8fded92ac8060 100644 (file)
@@ -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;
index 317ba68446c64e1f322df49605d323dcbba4002e..a5a44309bc9dbaefda20a688f82a4a146650c60d 100644 (file)
@@ -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);
index f41e34166d68bc1f853cb017905f8223df095660..f040c81a48436a4413db861d6268f425e6fc1db6 100644 (file)
@@ -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];
index 6048d0fe4068108d7a9737addfc54bd7e4eee62f..08bacf3b025ea7dcb3508a410dcc3d8435cc6e03 100644 (file)
@@ -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;