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.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 3b5135c93062..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.
@@ -237,6 +238,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
237 subs->datainterval = fmt->datainterval; 238 subs->datainterval = fmt->datainterval;
238 subs->syncpipe = subs->syncinterval = 0; 239 subs->syncpipe = subs->syncinterval = 0;
239 subs->maxpacksize = fmt->maxpacksize; 240 subs->maxpacksize = fmt->maxpacksize;
241 subs->syncmaxsize = 0;
240 subs->fill_max = 0; 242 subs->fill_max = 0;
241 243
242 /* we need a sync pipe in async OUT or adaptive IN mode */ 244 /* we need a sync pipe in async OUT or adaptive IN mode */
@@ -283,6 +285,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
283 subs->syncinterval = get_endpoint(alts, 1)->bInterval - 1; 285 subs->syncinterval = get_endpoint(alts, 1)->bInterval - 1;
284 else 286 else
285 subs->syncinterval = 3; 287 subs->syncinterval = 3;
288 subs->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize);
286 } 289 }
287 290
288 /* always fill max packet size */ 291 /* always fill max packet size */
@@ -359,6 +362,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
359 } 362 }
360 363
361 if (changed) { 364 if (changed) {
365 mutex_lock(&subs->stream->chip->shutdown_mutex);
362 /* format changed */ 366 /* format changed */
363 snd_usb_release_substream_urbs(subs, 0); 367 snd_usb_release_substream_urbs(subs, 0);
364 /* influenced: period_bytes, channels, rate, format, */ 368 /* influenced: period_bytes, channels, rate, format, */
@@ -366,6 +370,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
366 params_rate(hw_params), 370 params_rate(hw_params),
367 snd_pcm_format_physical_width(params_format(hw_params)) * 371 snd_pcm_format_physical_width(params_format(hw_params)) *
368 params_channels(hw_params)); 372 params_channels(hw_params));
373 mutex_unlock(&subs->stream->chip->shutdown_mutex);
369 } 374 }
370 375
371 return ret; 376 return ret;
@@ -383,8 +388,9 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
383 subs->cur_audiofmt = NULL; 388 subs->cur_audiofmt = NULL;
384 subs->cur_rate = 0; 389 subs->cur_rate = 0;
385 subs->period_bytes = 0; 390 subs->period_bytes = 0;
386 if (!subs->stream->chip->shutdown) 391 mutex_lock(&subs->stream->chip->shutdown_mutex);
387 snd_usb_release_substream_urbs(subs, 0); 392 snd_usb_release_substream_urbs(subs, 0);
393 mutex_unlock(&subs->stream->chip->shutdown_mutex);
388 return snd_pcm_lib_free_vmalloc_buffer(substream); 394 return snd_pcm_lib_free_vmalloc_buffer(substream);
389} 395}
390 396
@@ -466,7 +472,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs,
466 return 0; 472 return 0;
467 } 473 }
468 /* check whether the period time is >= the data packet interval */ 474 /* check whether the period time is >= the data packet interval */
469 if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) { 475 if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) {
470 ptime = 125 * (1 << fp->datainterval); 476 ptime = 125 * (1 << fp->datainterval);
471 if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { 477 if (ptime > pt->max || (ptime == pt->max && pt->openmax)) {
472 hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); 478 hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max);
@@ -674,8 +680,10 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
674 if (!needs_knot) 680 if (!needs_knot)
675 return 0; 681 return 0;
676 682
677 subs->rate_list.count = count;
678 subs->rate_list.list = kmalloc(sizeof(int) * count, GFP_KERNEL); 683 subs->rate_list.list = kmalloc(sizeof(int) * count, GFP_KERNEL);
684 if (!subs->rate_list.list)
685 return -ENOMEM;
686 subs->rate_list.count = count;
679 subs->rate_list.mask = 0; 687 subs->rate_list.mask = 0;
680 count = 0; 688 count = 0;
681 list_for_each_entry(fp, &subs->fmt_list, list) { 689 list_for_each_entry(fp, &subs->fmt_list, list) {
@@ -732,9 +740,12 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
732 pt = 125 * (1 << fp->datainterval); 740 pt = 125 * (1 << fp->datainterval);
733 ptmin = min(ptmin, pt); 741 ptmin = min(ptmin, pt);
734 } 742 }
743 err = snd_usb_autoresume(subs->stream->chip);
744 if (err < 0)
745 return err;
735 746
736 param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; 747 param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
737 if (snd_usb_get_speed(subs->dev) != USB_SPEED_HIGH) 748 if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
738 /* full speed devices have fixed data packet interval */ 749 /* full speed devices have fixed data packet interval */
739 ptmin = 1000; 750 ptmin = 1000;
740 if (ptmin == 1000) 751 if (ptmin == 1000)
@@ -749,21 +760,21 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
749 SNDRV_PCM_HW_PARAM_CHANNELS, 760 SNDRV_PCM_HW_PARAM_CHANNELS,
750 param_period_time_if_needed, 761 param_period_time_if_needed,
751 -1)) < 0) 762 -1)) < 0)
752 return err; 763 goto rep_err;
753 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,
754 hw_rule_channels, subs, 765 hw_rule_channels, subs,
755 SNDRV_PCM_HW_PARAM_FORMAT, 766 SNDRV_PCM_HW_PARAM_FORMAT,
756 SNDRV_PCM_HW_PARAM_RATE, 767 SNDRV_PCM_HW_PARAM_RATE,
757 param_period_time_if_needed, 768 param_period_time_if_needed,
758 -1)) < 0) 769 -1)) < 0)
759 return err; 770 goto rep_err;
760 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,
761 hw_rule_format, subs, 772 hw_rule_format, subs,
762 SNDRV_PCM_HW_PARAM_RATE, 773 SNDRV_PCM_HW_PARAM_RATE,
763 SNDRV_PCM_HW_PARAM_CHANNELS, 774 SNDRV_PCM_HW_PARAM_CHANNELS,
764 param_period_time_if_needed, 775 param_period_time_if_needed,
765 -1)) < 0) 776 -1)) < 0)
766 return err; 777 goto rep_err;
767 if (param_period_time_if_needed >= 0) { 778 if (param_period_time_if_needed >= 0) {
768 err = snd_pcm_hw_rule_add(runtime, 0, 779 err = snd_pcm_hw_rule_add(runtime, 0,
769 SNDRV_PCM_HW_PARAM_PERIOD_TIME, 780 SNDRV_PCM_HW_PARAM_PERIOD_TIME,
@@ -773,11 +784,15 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
773 SNDRV_PCM_HW_PARAM_RATE, 784 SNDRV_PCM_HW_PARAM_RATE,
774 -1); 785 -1);
775 if (err < 0) 786 if (err < 0)
776 return err; 787 goto rep_err;
777 } 788 }
778 if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0) 789 if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0)
779 return err; 790 goto rep_err;
780 return 0; 791 return 0;
792
793rep_err:
794 snd_usb_autosuspend(subs->stream->chip);
795 return err;
781} 796}
782 797
783static 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)
@@ -791,6 +806,7 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
791 runtime->hw = snd_usb_hardware; 806 runtime->hw = snd_usb_hardware;
792 runtime->private_data = subs; 807 runtime->private_data = subs;
793 subs->pcm_substream = substream; 808 subs->pcm_substream = substream;
809 /* runtime PM is also done there */
794 return setup_hw_info(runtime, subs); 810 return setup_hw_info(runtime, subs);
795} 811}
796 812
@@ -804,6 +820,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
804 subs->interface = -1; 820 subs->interface = -1;
805 } 821 }
806 subs->pcm_substream = NULL; 822 subs->pcm_substream = NULL;
823 snd_usb_autosuspend(subs->stream->chip);
807 return 0; 824 return 0;
808} 825}
809 826