diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-10-30 06:08:25 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-10-30 06:08:25 -0400 |
commit | a5d00dc3a4b65ed38249f3225e453944c633747b (patch) | |
tree | 6249ca5a5f13059f42890525a9ea7133778f3891 /sound/usb/pcm.c | |
parent | 1a8506d4402b6e96c2ed778dc7ccbb48d1e02fce (diff) | |
parent | 0914f7961babbf28aaa2f19b453951fb4841c03f (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.c | 53 |
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 | |||
466 | unlock: | ||
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 | ||
597 | static struct snd_pcm_hardware snd_usb_hardware = | 612 | static 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) |