aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/pcm.c
diff options
context:
space:
mode:
authorDylan Reid <dgreid@chromium.org>2012-09-18 12:49:48 -0400
committerTakashi Iwai <tiwai@suse.de>2012-09-19 02:08:11 -0400
commit61a709504b079110cd5b12ea9a4590ffea687a5c (patch)
treef49a7338767f2117c4167904a878f27ec9955162 /sound/usb/pcm.c
parent35ec7aa29833de350f51922736aefe22ebf76c4d (diff)
ALSA: usb-audio: Move configuration to prepare.
Move interface and endpoint configuration from hw_params to prepare callback. During system suspend/resume when the USB device power isn't cycled the interface and endpoint configuration need to be set before audio playback can continue. Resume involves another call to prepare but not to hw_params, moving it here allows a playing stream to continue after resume. Signed-off-by: Dylan Reid <dgreid@chromium.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb/pcm.c')
-rw-r--r--sound/usb/pcm.c134
1 files changed, 74 insertions, 60 deletions
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 62ab4fd5880a..ae783d40f55a 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -82,8 +82,7 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
82/* 82/*
83 * find a matching audio format 83 * find a matching audio format
84 */ 84 */
85static struct audioformat *find_format(struct snd_usb_substream *subs, unsigned int format, 85static struct audioformat *find_format(struct snd_usb_substream *subs)
86 unsigned int rate, unsigned int channels)
87{ 86{
88 struct list_head *p; 87 struct list_head *p;
89 struct audioformat *found = NULL; 88 struct audioformat *found = NULL;
@@ -92,16 +91,17 @@ static struct audioformat *find_format(struct snd_usb_substream *subs, unsigned
92 list_for_each(p, &subs->fmt_list) { 91 list_for_each(p, &subs->fmt_list) {
93 struct audioformat *fp; 92 struct audioformat *fp;
94 fp = list_entry(p, struct audioformat, list); 93 fp = list_entry(p, struct audioformat, list);
95 if (!(fp->formats & (1uLL << format))) 94 if (!(fp->formats & (1uLL << subs->pcm_format)))
96 continue; 95 continue;
97 if (fp->channels != channels) 96 if (fp->channels != subs->channels)
98 continue; 97 continue;
99 if (rate < fp->rate_min || rate > fp->rate_max) 98 if (subs->cur_rate < fp->rate_min ||
99 subs->cur_rate > fp->rate_max)
100 continue; 100 continue;
101 if (! (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)) { 101 if (! (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)) {
102 unsigned int i; 102 unsigned int i;
103 for (i = 0; i < fp->nr_rates; i++) 103 for (i = 0; i < fp->nr_rates; i++)
104 if (fp->rate_table[i] == rate) 104 if (fp->rate_table[i] == subs->cur_rate)
105 break; 105 break;
106 if (i >= fp->nr_rates) 106 if (i >= fp->nr_rates)
107 continue; 107 continue;
@@ -436,6 +436,42 @@ add_sync_ep:
436} 436}
437 437
438/* 438/*
439 * configure endpoint params
440 *
441 * called during initial setup and upon resume
442 */
443static int configure_endpoint(struct snd_usb_substream *subs)
444{
445 int ret;
446
447 mutex_lock(&subs->stream->chip->shutdown_mutex);
448 /* format changed */
449 stop_endpoints(subs, 0, 0, 0);
450 ret = snd_usb_endpoint_set_params(subs->data_endpoint,
451 subs->pcm_format,
452 subs->channels,
453 subs->period_bytes,
454 subs->cur_rate,
455 subs->cur_audiofmt,
456 subs->sync_endpoint);
457 if (ret < 0)
458 goto unlock;
459
460 if (subs->sync_endpoint)
461 ret = snd_usb_endpoint_set_params(subs->data_endpoint,
462 subs->pcm_format,
463 subs->channels,
464 subs->period_bytes,
465 subs->cur_rate,
466 subs->cur_audiofmt,
467 NULL);
468
469unlock:
470 mutex_unlock(&subs->stream->chip->shutdown_mutex);
471 return ret;
472}
473
474/*
439 * hw_params callback 475 * hw_params callback
440 * 476 *
441 * allocate a buffer and set the given audio format. 477 * allocate a buffer and set the given audio format.
@@ -450,75 +486,32 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
450{ 486{
451 struct snd_usb_substream *subs = substream->runtime->private_data; 487 struct snd_usb_substream *subs = substream->runtime->private_data;
452 struct audioformat *fmt; 488 struct audioformat *fmt;
453 unsigned int channels, rate, format; 489 int ret;
454 int ret, changed;
455 490
456 ret = snd_pcm_lib_alloc_vmalloc_buffer(substream, 491 ret = snd_pcm_lib_alloc_vmalloc_buffer(substream,
457 params_buffer_bytes(hw_params)); 492 params_buffer_bytes(hw_params));
458 if (ret < 0) 493 if (ret < 0)
459 return ret; 494 return ret;
460 495
461 format = params_format(hw_params); 496 subs->pcm_format = params_format(hw_params);
462 rate = params_rate(hw_params); 497 subs->period_bytes = params_period_bytes(hw_params);
463 channels = params_channels(hw_params); 498 subs->channels = params_channels(hw_params);
464 fmt = find_format(subs, format, rate, channels); 499 subs->cur_rate = params_rate(hw_params);
500
501 fmt = find_format(subs);
465 if (!fmt) { 502 if (!fmt) {
466 snd_printd(KERN_DEBUG "cannot set format: format = %#x, rate = %d, channels = %d\n", 503 snd_printd(KERN_DEBUG "cannot set format: format = %#x, rate = %d, channels = %d\n",
467 format, rate, channels); 504 subs->pcm_format, subs->cur_rate, subs->channels);
468 return -EINVAL; 505 return -EINVAL;
469 } 506 }
470 507
471 changed = subs->cur_audiofmt != fmt ||
472 subs->period_bytes != params_period_bytes(hw_params) ||
473 subs->cur_rate != rate;
474 if ((ret = set_format(subs, fmt)) < 0) 508 if ((ret = set_format(subs, fmt)) < 0)
475 return ret; 509 return ret;
476 510
477 if (subs->cur_rate != rate) { 511 subs->interface = fmt->iface;
478 struct usb_host_interface *alts; 512 subs->altset_idx = fmt->altset_idx;
479 struct usb_interface *iface;
480 iface = usb_ifnum_to_if(subs->dev, fmt->iface);
481 alts = &iface->altsetting[fmt->altset_idx];
482 ret = snd_usb_init_sample_rate(subs->stream->chip, fmt->iface, alts, fmt, rate);
483 if (ret < 0)
484 return ret;
485 subs->cur_rate = rate;
486 }
487
488 if (changed) {
489 subs->period_bytes = params_period_bytes(hw_params);
490 513
491 mutex_lock(&subs->stream->chip->shutdown_mutex); 514 return 0;
492 /* format changed */
493 stop_endpoints(subs, 0, 0, 0);
494 ret = snd_usb_endpoint_set_params(subs->data_endpoint,
495 format,
496 channels,
497 subs->period_bytes,
498 rate,
499 fmt,
500 subs->sync_endpoint);
501 if (ret < 0)
502 goto unlock;
503
504 if (subs->sync_endpoint)
505 ret = snd_usb_endpoint_set_params(subs->data_endpoint,
506 format,
507 channels,
508 subs->period_bytes,
509 rate,
510 fmt,
511 NULL);
512unlock:
513 mutex_unlock(&subs->stream->chip->shutdown_mutex);
514 }
515
516 if (ret == 0) {
517 subs->interface = fmt->iface;
518 subs->altset_idx = fmt->altset_idx;
519 }
520
521 return ret;
522} 515}
523 516
524/* 517/*
@@ -549,6 +542,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
549{ 542{
550 struct snd_pcm_runtime *runtime = substream->runtime; 543 struct snd_pcm_runtime *runtime = substream->runtime;
551 struct snd_usb_substream *subs = runtime->private_data; 544 struct snd_usb_substream *subs = runtime->private_data;
545 struct usb_host_interface *alts;
546 struct usb_interface *iface;
547 int ret;
552 548
553 if (! subs->cur_audiofmt) { 549 if (! subs->cur_audiofmt) {
554 snd_printk(KERN_ERR "usbaudio: no format is specified!\n"); 550 snd_printk(KERN_ERR "usbaudio: no format is specified!\n");
@@ -558,6 +554,24 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
558 if (snd_BUG_ON(!subs->data_endpoint)) 554 if (snd_BUG_ON(!subs->data_endpoint))
559 return -EIO; 555 return -EIO;
560 556
557 ret = set_format(subs, subs->cur_audiofmt);
558 if (ret < 0)
559 return ret;
560
561 iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface);
562 alts = &iface->altsetting[subs->cur_audiofmt->altset_idx];
563 ret = snd_usb_init_sample_rate(subs->stream->chip,
564 subs->cur_audiofmt->iface,
565 alts,
566 subs->cur_audiofmt,
567 subs->cur_rate);
568 if (ret < 0)
569 return ret;
570
571 ret = configure_endpoint(subs);
572 if (ret < 0)
573 return ret;
574
561 /* some unit conversions in runtime */ 575 /* some unit conversions in runtime */
562 subs->data_endpoint->maxframesize = 576 subs->data_endpoint->maxframesize =
563 bytes_to_frames(runtime, subs->data_endpoint->maxpacksize); 577 bytes_to_frames(runtime, subs->data_endpoint->maxpacksize);