summaryrefslogtreecommitdiff
path: root/sound/usb/line6/pcm.c
diff options
context:
space:
mode:
authorAndrej Krutak <dev@andree.sk>2016-09-18 20:59:25 +0200
committerTakashi Iwai <tiwai@suse.de>2016-09-19 23:00:37 +0200
commitf56742cc41895b1ed3742406dc3587b0d6424acb (patch)
tree8c359bd99c6905273dc9968c4de13c895010e1e6 /sound/usb/line6/pcm.c
parent97d78acfb870a67339957e9c4d36dc03242df315 (diff)
ALSA: line6: Add LINE6_CAP_IN_NEEDS_OUT, a void playback stream during capture
E.g. POD X3 seems to require playback data to be sent to it to generate capture data. Otherwise the device stalls and doesn't send any more capture data until it's reset. Signed-off-by: Andrej Krutak <dev@andree.sk> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb/line6/pcm.c')
-rw-r--r--sound/usb/line6/pcm.c31
1 files changed, 24 insertions, 7 deletions
diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c
index a5a44309bc9d..fab53f58d447 100644
--- a/sound/usb/line6/pcm.c
+++ b/sound/usb/line6/pcm.c
@@ -52,7 +52,7 @@ static int snd_line6_impulse_volume_put(struct snd_kcontrol *kcontrol,
line6pcm->impulse_volume = value;
if (value > 0) {
- err = line6_pcm_acquire(line6pcm, LINE6_STREAM_IMPULSE);
+ err = line6_pcm_acquire(line6pcm, LINE6_STREAM_IMPULSE, true);
if (err < 0) {
line6pcm->impulse_volume = 0;
return err;
@@ -242,6 +242,14 @@ int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
+ if (s->stream == SNDRV_PCM_STREAM_CAPTURE &&
+ (line6pcm->line6->properties->capabilities &
+ LINE6_CAP_IN_NEEDS_OUT)) {
+ err = line6_stream_start(line6pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ LINE6_STREAM_CAPTURE_HELPER);
+ if (err < 0)
+ return err;
+ }
err = line6_stream_start(line6pcm, s->stream,
LINE6_STREAM_PCM);
if (err < 0)
@@ -250,6 +258,12 @@ int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
+ if (s->stream == SNDRV_PCM_STREAM_CAPTURE &&
+ (line6pcm->line6->properties->capabilities &
+ LINE6_CAP_IN_NEEDS_OUT)) {
+ line6_stream_stop(line6pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ LINE6_STREAM_CAPTURE_HELPER);
+ }
line6_stream_stop(line6pcm, s->stream,
LINE6_STREAM_PCM);
break;
@@ -283,14 +297,15 @@ snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream)
return pstr->pos_done;
}
-/* Acquire and start duplex streams:
+/* Acquire and optionally start duplex streams:
* type is either LINE6_STREAM_IMPULSE or LINE6_STREAM_MONITOR
*/
-int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type)
+int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type, bool start)
{
struct line6_pcm_stream *pstr;
int ret = 0, dir;
+ /* TODO: We should assert SNDRV_PCM_STREAM_PLAYBACK/CAPTURE == 0/1 */
mutex_lock(&line6pcm->state_mutex);
for (dir = 0; dir < 2; dir++) {
pstr = get_stream(line6pcm, dir);
@@ -300,10 +315,12 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type)
if (!pstr->running)
line6_wait_clear_audio_urbs(line6pcm, pstr);
}
- for (dir = 0; dir < 2; dir++) {
- ret = line6_stream_start(line6pcm, dir, type);
- if (ret < 0)
- goto error;
+ if (start) {
+ for (dir = 0; dir < 2; dir++) {
+ ret = line6_stream_start(line6pcm, dir, type);
+ if (ret < 0)
+ goto error;
+ }
}
error:
mutex_unlock(&line6pcm->state_mutex);