aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/pcm.c')
-rw-r--r--sound/usb/pcm.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 4132522ac90f..b8dcbf407bbb 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -32,6 +32,7 @@
32#include "helper.h" 32#include "helper.h"
33#include "pcm.h" 33#include "pcm.h"
34#include "clock.h" 34#include "clock.h"
35#include "power.h"
35 36
36/* 37/*
37 * return the current pcm pointer. just based on the hwptr_done value. 38 * return the current pcm pointer. just based on the hwptr_done value.
@@ -361,6 +362,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
361 } 362 }
362 363
363 if (changed) { 364 if (changed) {
365 mutex_lock(&subs->stream->chip->shutdown_mutex);
364 /* format changed */ 366 /* format changed */
365 snd_usb_release_substream_urbs(subs, 0); 367 snd_usb_release_substream_urbs(subs, 0);
366 /* influenced: period_bytes, channels, rate, format, */ 368 /* influenced: period_bytes, channels, rate, format, */
@@ -368,6 +370,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
368 params_rate(hw_params), 370 params_rate(hw_params),
369 snd_pcm_format_physical_width(params_format(hw_params)) * 371 snd_pcm_format_physical_width(params_format(hw_params)) *
370 params_channels(hw_params)); 372 params_channels(hw_params));
373 mutex_unlock(&subs->stream->chip->shutdown_mutex);
371 } 374 }
372 375
373 return ret; 376 return ret;
@@ -385,8 +388,9 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
385 subs->cur_audiofmt = NULL; 388 subs->cur_audiofmt = NULL;
386 subs->cur_rate = 0; 389 subs->cur_rate = 0;
387 subs->period_bytes = 0; 390 subs->period_bytes = 0;
388 if (!subs->stream->chip->shutdown) 391 mutex_lock(&subs->stream->chip->shutdown_mutex);
389 snd_usb_release_substream_urbs(subs, 0); 392 snd_usb_release_substream_urbs(subs, 0);
393 mutex_unlock(&subs->stream->chip->shutdown_mutex);
390 return snd_pcm_lib_free_vmalloc_buffer(substream); 394 return snd_pcm_lib_free_vmalloc_buffer(substream);
391} 395}
392 396
@@ -736,6 +740,9 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
736 pt = 125 * (1 << fp->datainterval); 740 pt = 125 * (1 << fp->datainterval);
737 ptmin = min(ptmin, pt); 741 ptmin = min(ptmin, pt);
738 } 742 }
743 err = snd_usb_autoresume(subs->stream->chip);
744 if (err < 0)
745 return err;
739 746
740 param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; 747 param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
741 if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) 748 if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
@@ -753,21 +760,21 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
753 SNDRV_PCM_HW_PARAM_CHANNELS, 760 SNDRV_PCM_HW_PARAM_CHANNELS,
754 param_period_time_if_needed, 761 param_period_time_if_needed,
755 -1)) < 0) 762 -1)) < 0)
756 return err; 763 goto rep_err;
757 if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 764 if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
758 hw_rule_channels, subs, 765 hw_rule_channels, subs,
759 SNDRV_PCM_HW_PARAM_FORMAT, 766 SNDRV_PCM_HW_PARAM_FORMAT,
760 SNDRV_PCM_HW_PARAM_RATE, 767 SNDRV_PCM_HW_PARAM_RATE,
761 param_period_time_if_needed, 768 param_period_time_if_needed,
762 -1)) < 0) 769 -1)) < 0)
763 return err; 770 goto rep_err;
764 if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, 771 if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
765 hw_rule_format, subs, 772 hw_rule_format, subs,
766 SNDRV_PCM_HW_PARAM_RATE, 773 SNDRV_PCM_HW_PARAM_RATE,
767 SNDRV_PCM_HW_PARAM_CHANNELS, 774 SNDRV_PCM_HW_PARAM_CHANNELS,
768 param_period_time_if_needed, 775 param_period_time_if_needed,
769 -1)) < 0) 776 -1)) < 0)
770 return err; 777 goto rep_err;
771 if (param_period_time_if_needed >= 0) { 778 if (param_period_time_if_needed >= 0) {
772 err = snd_pcm_hw_rule_add(runtime, 0, 779 err = snd_pcm_hw_rule_add(runtime, 0,
773 SNDRV_PCM_HW_PARAM_PERIOD_TIME, 780 SNDRV_PCM_HW_PARAM_PERIOD_TIME,
@@ -777,11 +784,15 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
777 SNDRV_PCM_HW_PARAM_RATE, 784 SNDRV_PCM_HW_PARAM_RATE,
778 -1); 785 -1);
779 if (err < 0) 786 if (err < 0)
780 return err; 787 goto rep_err;
781 } 788 }
782 if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0) 789 if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0)
783 return err; 790 goto rep_err;
784 return 0; 791 return 0;
792
793rep_err:
794 snd_usb_autosuspend(subs->stream->chip);
795 return err;
785} 796}
786 797
787static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction) 798static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
@@ -795,6 +806,7 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
795 runtime->hw = snd_usb_hardware; 806 runtime->hw = snd_usb_hardware;
796 runtime->private_data = subs; 807 runtime->private_data = subs;
797 subs->pcm_substream = substream; 808 subs->pcm_substream = substream;
809 /* runtime PM is also done there */
798 return setup_hw_info(runtime, subs); 810 return setup_hw_info(runtime, subs);
799} 811}
800 812
@@ -808,6 +820,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
808 subs->interface = -1; 820 subs->interface = -1;
809 } 821 }
810 subs->pcm_substream = NULL; 822 subs->pcm_substream = NULL;
823 snd_usb_autosuspend(subs->stream->chip);
811 return 0; 824 return 0;
812} 825}
813 826