summaryrefslogtreecommitdiffstats
path: root/sound/usb/pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/pcm.c')
-rw-r--r--sound/usb/pcm.c29
1 files changed, 25 insertions, 4 deletions
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 056af0a57b22..5d8494b2a026 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -35,6 +35,7 @@
#include "pcm.h"
#include "clock.h"
#include "power.h"
+#include "media.h"
#define SUBSTREAM_FLAG_DATA_EP_STARTED 0
#define SUBSTREAM_FLAG_SYNC_EP_STARTED 1
@@ -787,6 +788,10 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
struct audioformat *fmt;
int ret;
+ ret = snd_media_start_pipeline(subs);
+ if (ret)
+ return ret;
+
if (snd_usb_use_vmalloc)
ret = snd_pcm_lib_alloc_vmalloc_buffer(substream,
params_buffer_bytes(hw_params));
@@ -794,7 +799,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
ret = snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params));
if (ret < 0)
- return ret;
+ goto stop_pipeline;
subs->pcm_format = params_format(hw_params);
subs->period_bytes = params_period_bytes(hw_params);
@@ -808,12 +813,13 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
dev_dbg(&subs->dev->dev,
"cannot set format: format = %#x, rate = %d, channels = %d\n",
subs->pcm_format, subs->cur_rate, subs->channels);
- return -EINVAL;
+ ret = -EINVAL;
+ goto stop_pipeline;
}
ret = snd_usb_lock_shutdown(subs->stream->chip);
if (ret < 0)
- return ret;
+ goto stop_pipeline;
ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0);
if (ret < 0)
@@ -829,6 +835,12 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
unlock:
snd_usb_unlock_shutdown(subs->stream->chip);
+ if (ret < 0)
+ goto stop_pipeline;
+ return ret;
+
+ stop_pipeline:
+ snd_media_stop_pipeline(subs);
return ret;
}
@@ -841,6 +853,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
{
struct snd_usb_substream *subs = substream->runtime->private_data;
+ snd_media_stop_pipeline(subs);
subs->cur_audiofmt = NULL;
subs->cur_rate = 0;
subs->period_bytes = 0;
@@ -1313,6 +1326,7 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream)
struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_usb_substream *subs = &as->substream[direction];
+ int ret;
subs->interface = -1;
subs->altset_idx = 0;
@@ -1326,7 +1340,13 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream)
subs->dsd_dop.channel = 0;
subs->dsd_dop.marker = 1;
- return setup_hw_info(runtime, subs);
+ ret = setup_hw_info(runtime, subs);
+ if (ret == 0) {
+ ret = snd_media_stream_init(subs, as->pcm, direction);
+ if (ret)
+ snd_usb_autosuspend(subs->stream->chip);
+ }
+ return ret;
}
static int snd_usb_pcm_close(struct snd_pcm_substream *substream)
@@ -1337,6 +1357,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream)
int ret;
stop_endpoints(subs, true);
+ snd_media_stop_pipeline(subs);
if (!as->chip->keep_iface &&
subs->interface >= 0 &&