aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/pcm.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-10-30 06:08:25 -0400
committerTakashi Iwai <tiwai@suse.de>2012-10-30 06:08:25 -0400
commita5d00dc3a4b65ed38249f3225e453944c633747b (patch)
tree6249ca5a5f13059f42890525a9ea7133778f3891 /sound/usb/pcm.c
parent1a8506d4402b6e96c2ed778dc7ccbb48d1e02fce (diff)
parent0914f7961babbf28aaa2f19b453951fb4841c03f (diff)
Merge branch 'for-linus' into for-next
... for migrating the core changes for USB-audio disconnection fixes
Diffstat (limited to 'sound/usb/pcm.c')
-rw-r--r--sound/usb/pcm.c53
1 files changed, 34 insertions, 19 deletions
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index f77b87ad0256..8ca6edf29fee 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -71,6 +71,8 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
71 unsigned int hwptr_done; 71 unsigned int hwptr_done;
72 72
73 subs = (struct snd_usb_substream *)substream->runtime->private_data; 73 subs = (struct snd_usb_substream *)substream->runtime->private_data;
74 if (subs->stream->chip->shutdown)
75 return SNDRV_PCM_POS_XRUN;
74 spin_lock(&subs->lock); 76 spin_lock(&subs->lock);
75 hwptr_done = subs->hwptr_done; 77 hwptr_done = subs->hwptr_done;
76 substream->runtime->delay = snd_usb_pcm_delay(subs, 78 substream->runtime->delay = snd_usb_pcm_delay(subs,
@@ -441,7 +443,6 @@ static int configure_endpoint(struct snd_usb_substream *subs)
441{ 443{
442 int ret; 444 int ret;
443 445
444 mutex_lock(&subs->stream->chip->shutdown_mutex);
445 /* format changed */ 446 /* format changed */
446 stop_endpoints(subs, 0, 0, 0); 447 stop_endpoints(subs, 0, 0, 0);
447 ret = snd_usb_endpoint_set_params(subs->data_endpoint, 448 ret = snd_usb_endpoint_set_params(subs->data_endpoint,
@@ -452,7 +453,7 @@ static int configure_endpoint(struct snd_usb_substream *subs)
452 subs->cur_audiofmt, 453 subs->cur_audiofmt,
453 subs->sync_endpoint); 454 subs->sync_endpoint);
454 if (ret < 0) 455 if (ret < 0)
455 goto unlock; 456 return ret;
456 457
457 if (subs->sync_endpoint) 458 if (subs->sync_endpoint)
458 ret = snd_usb_endpoint_set_params(subs->data_endpoint, 459 ret = snd_usb_endpoint_set_params(subs->data_endpoint,
@@ -462,9 +463,6 @@ static int configure_endpoint(struct snd_usb_substream *subs)
462 subs->cur_rate, 463 subs->cur_rate,
463 subs->cur_audiofmt, 464 subs->cur_audiofmt,
464 NULL); 465 NULL);
465
466unlock:
467 mutex_unlock(&subs->stream->chip->shutdown_mutex);
468 return ret; 466 return ret;
469} 467}
470 468
@@ -502,7 +500,13 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
502 return -EINVAL; 500 return -EINVAL;
503 } 501 }
504 502
505 if ((ret = set_format(subs, fmt)) < 0) 503 down_read(&subs->stream->chip->shutdown_rwsem);
504 if (subs->stream->chip->shutdown)
505 ret = -ENODEV;
506 else
507 ret = set_format(subs, fmt);
508 up_read(&subs->stream->chip->shutdown_rwsem);
509 if (ret < 0)
506 return ret; 510 return ret;
507 511
508 subs->interface = fmt->iface; 512 subs->interface = fmt->iface;
@@ -524,10 +528,12 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
524 subs->cur_audiofmt = NULL; 528 subs->cur_audiofmt = NULL;
525 subs->cur_rate = 0; 529 subs->cur_rate = 0;
526 subs->period_bytes = 0; 530 subs->period_bytes = 0;
527 mutex_lock(&subs->stream->chip->shutdown_mutex); 531 down_read(&subs->stream->chip->shutdown_rwsem);
528 stop_endpoints(subs, 0, 1, 1); 532 if (!subs->stream->chip->shutdown) {
529 deactivate_endpoints(subs); 533 stop_endpoints(subs, 0, 1, 1);
530 mutex_unlock(&subs->stream->chip->shutdown_mutex); 534 deactivate_endpoints(subs);
535 }
536 up_read(&subs->stream->chip->shutdown_rwsem);
531 return snd_pcm_lib_free_vmalloc_buffer(substream); 537 return snd_pcm_lib_free_vmalloc_buffer(substream);
532} 538}
533 539
@@ -549,12 +555,19 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
549 return -ENXIO; 555 return -ENXIO;
550 } 556 }
551 557
552 if (snd_BUG_ON(!subs->data_endpoint)) 558 down_read(&subs->stream->chip->shutdown_rwsem);
553 return -EIO; 559 if (subs->stream->chip->shutdown) {
560 ret = -ENODEV;
561 goto unlock;
562 }
563 if (snd_BUG_ON(!subs->data_endpoint)) {
564 ret = -EIO;
565 goto unlock;
566 }
554 567
555 ret = set_format(subs, subs->cur_audiofmt); 568 ret = set_format(subs, subs->cur_audiofmt);
556 if (ret < 0) 569 if (ret < 0)
557 return ret; 570 goto unlock;
558 571
559 iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface); 572 iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface);
560 alts = &iface->altsetting[subs->cur_audiofmt->altset_idx]; 573 alts = &iface->altsetting[subs->cur_audiofmt->altset_idx];
@@ -564,12 +577,12 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
564 subs->cur_audiofmt, 577 subs->cur_audiofmt,
565 subs->cur_rate); 578 subs->cur_rate);
566 if (ret < 0) 579 if (ret < 0)
567 return ret; 580 goto unlock;
568 581
569 if (subs->need_setup_ep) { 582 if (subs->need_setup_ep) {
570 ret = configure_endpoint(subs); 583 ret = configure_endpoint(subs);
571 if (ret < 0) 584 if (ret < 0)
572 return ret; 585 goto unlock;
573 subs->need_setup_ep = false; 586 subs->need_setup_ep = false;
574 } 587 }
575 588
@@ -589,9 +602,11 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
589 /* for playback, submit the URBs now; otherwise, the first hwptr_done 602 /* for playback, submit the URBs now; otherwise, the first hwptr_done
590 * updates for all URBs would happen at the same time when starting */ 603 * updates for all URBs would happen at the same time when starting */
591 if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) 604 if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
592 return start_endpoints(subs, 1); 605 ret = start_endpoints(subs, 1);
593 606
594 return 0; 607 unlock:
608 up_read(&subs->stream->chip->shutdown_rwsem);
609 return ret;
595} 610}
596 611
597static struct snd_pcm_hardware snd_usb_hardware = 612static struct snd_pcm_hardware snd_usb_hardware =
@@ -644,7 +659,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs,
644 return 0; 659 return 0;
645 } 660 }
646 /* check whether the period time is >= the data packet interval */ 661 /* check whether the period time is >= the data packet interval */
647 if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) { 662 if (subs->speed != USB_SPEED_FULL) {
648 ptime = 125 * (1 << fp->datainterval); 663 ptime = 125 * (1 << fp->datainterval);
649 if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { 664 if (ptime > pt->max || (ptime == pt->max && pt->openmax)) {
650 hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); 665 hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max);
@@ -922,7 +937,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
922 return err; 937 return err;
923 938
924 param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; 939 param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
925 if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) 940 if (subs->speed == USB_SPEED_FULL)
926 /* full speed devices have fixed data packet interval */ 941 /* full speed devices have fixed data packet interval */
927 ptmin = 1000; 942 ptmin = 1000;
928 if (ptmin == 1000) 943 if (ptmin == 1000)