Merge tag 'sound-4.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai...
[deliverable/linux.git] / sound / usb / pcm.c
index 9245f52d43bdecfeb710b6cfc6ae99b3202aae90..0e4e0640c50486b608b4a3df4c83b18fd11cae17 100644 (file)
@@ -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
@@ -159,6 +160,8 @@ static int init_pitch_v1(struct snd_usb_audio *chip, int iface,
        unsigned char data[1];
        int err;
 
+       if (get_iface_desc(alts)->bNumEndpoints < 1)
+               return -EINVAL;
        ep = get_endpoint(alts, 0)->bEndpointAddress;
 
        data[0] = 1;
@@ -715,10 +718,14 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
        struct audioformat *fmt;
        int ret;
 
+       ret = media_snd_start_pipeline(subs);
+       if (ret)
+               return ret;
+
        ret = snd_pcm_lib_alloc_vmalloc_buffer(substream,
                                               params_buffer_bytes(hw_params));
        if (ret < 0)
-               return ret;
+               goto err_ret;
 
        subs->pcm_format = params_format(hw_params);
        subs->period_bytes = params_period_bytes(hw_params);
@@ -732,22 +739,27 @@ 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 err_ret;
        }
 
        ret = snd_usb_lock_shutdown(subs->stream->chip);
        if (ret < 0)
-               return ret;
+               goto err_ret;
        ret = set_format(subs, fmt);
        snd_usb_unlock_shutdown(subs->stream->chip);
        if (ret < 0)
-               return ret;
+               goto err_ret;
 
        subs->interface = fmt->iface;
        subs->altset_idx = fmt->altset_idx;
        subs->need_setup_ep = true;
 
        return 0;
+
+err_ret:
+       media_snd_stop_pipeline(subs);
+       return ret;
 }
 
 /*
@@ -759,6 +771,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
 {
        struct snd_usb_substream *subs = substream->runtime->private_data;
 
+       media_snd_stop_pipeline(subs);
        subs->cur_audiofmt = NULL;
        subs->cur_rate = 0;
        subs->period_bytes = 0;
@@ -1219,6 +1232,7 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
        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;
@@ -1232,7 +1246,12 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
        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 = media_snd_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, int direction)
@@ -1241,6 +1260,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
        struct snd_usb_substream *subs = &as->substream[direction];
 
        stop_endpoints(subs, true);
+       media_snd_stop_pipeline(subs);
 
        if (subs->interface >= 0 &&
            !snd_usb_lock_shutdown(subs->stream->chip)) {
This page took 0.025943 seconds and 5 git commands to generate.