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.c126
1 files changed, 78 insertions, 48 deletions
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index f782ce19bf5a..55e19e1b80ec 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,63 +486,33 @@ 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; 513 subs->need_setup_ep = true;
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 mutex_lock(&subs->stream->chip->shutdown_mutex);
490 /* format changed */
491 stop_endpoints(subs, 0, 0, 0);
492 ret = snd_usb_endpoint_set_params(subs->data_endpoint, hw_params, fmt,
493 subs->sync_endpoint);
494 if (ret < 0)
495 goto unlock;
496 514
497 if (subs->sync_endpoint) 515 return 0;
498 ret = snd_usb_endpoint_set_params(subs->sync_endpoint,
499 hw_params, fmt, NULL);
500unlock:
501 mutex_unlock(&subs->stream->chip->shutdown_mutex);
502 }
503
504 if (ret == 0) {
505 subs->interface = fmt->iface;
506 subs->altset_idx = fmt->altset_idx;
507 }
508
509 return ret;
510} 516}
511 517
512/* 518/*
@@ -537,6 +543,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
537{ 543{
538 struct snd_pcm_runtime *runtime = substream->runtime; 544 struct snd_pcm_runtime *runtime = substream->runtime;
539 struct snd_usb_substream *subs = runtime->private_data; 545 struct snd_usb_substream *subs = runtime->private_data;
546 struct usb_host_interface *alts;
547 struct usb_interface *iface;
548 int ret;
540 549
541 if (! subs->cur_audiofmt) { 550 if (! subs->cur_audiofmt) {
542 snd_printk(KERN_ERR "usbaudio: no format is specified!\n"); 551 snd_printk(KERN_ERR "usbaudio: no format is specified!\n");
@@ -546,6 +555,27 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
546 if (snd_BUG_ON(!subs->data_endpoint)) 555 if (snd_BUG_ON(!subs->data_endpoint))
547 return -EIO; 556 return -EIO;
548 557
558 ret = set_format(subs, subs->cur_audiofmt);
559 if (ret < 0)
560 return ret;
561
562 iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface);
563 alts = &iface->altsetting[subs->cur_audiofmt->altset_idx];
564 ret = snd_usb_init_sample_rate(subs->stream->chip,
565 subs->cur_audiofmt->iface,
566 alts,
567 subs->cur_audiofmt,
568 subs->cur_rate);
569 if (ret < 0)
570 return ret;
571
572 if (subs->need_setup_ep) {
573 ret = configure_endpoint(subs);
574 if (ret < 0)
575 return ret;
576 subs->need_setup_ep = false;
577 }
578
549 /* some unit conversions in runtime */ 579 /* some unit conversions in runtime */
550 subs->data_endpoint->maxframesize = 580 subs->data_endpoint->maxframesize =
551 bytes_to_frames(runtime, subs->data_endpoint->maxpacksize); 581 bytes_to_frames(runtime, subs->data_endpoint->maxpacksize);