diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-14 16:03:08 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-14 16:03:08 -0400 |
| commit | 1daaa5e4ff2f09af58f9f7425bbd02e28f125d8e (patch) | |
| tree | 71fc13b8829fe25ed9341f1b343dc6d37f3228d7 | |
| parent | c5b01acff187b12ec56363193208a7a4cf2469d8 (diff) | |
| parent | 68e67f40b7343383517c3f951b4b8db7626406bc (diff) | |
Merge tag 'sound-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound fixes from Takashi Iwai:
"Containing the regression fixes for USB-audio due to the transition to
the new streaming logic, mostly found on Logitech webcams."
* tag 'sound-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
ALSA: snd-usb: move calls to usb_set_interface
ALSA: usb-audio: Fix the first PCM interface assignment
| -rw-r--r-- | sound/usb/endpoint.c | 73 | ||||
| -rw-r--r-- | sound/usb/pcm.c | 61 |
2 files changed, 43 insertions, 91 deletions
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index e6906901debb..0f647d22cb4a 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c | |||
| @@ -414,7 +414,7 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, | |||
| 414 | { | 414 | { |
| 415 | struct list_head *p; | 415 | struct list_head *p; |
| 416 | struct snd_usb_endpoint *ep; | 416 | struct snd_usb_endpoint *ep; |
| 417 | int ret, is_playback = direction == SNDRV_PCM_STREAM_PLAYBACK; | 417 | int is_playback = direction == SNDRV_PCM_STREAM_PLAYBACK; |
| 418 | 418 | ||
| 419 | mutex_lock(&chip->mutex); | 419 | mutex_lock(&chip->mutex); |
| 420 | 420 | ||
| @@ -434,16 +434,6 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, | |||
| 434 | type == SND_USB_ENDPOINT_TYPE_DATA ? "data" : "sync", | 434 | type == SND_USB_ENDPOINT_TYPE_DATA ? "data" : "sync", |
| 435 | ep_num); | 435 | ep_num); |
| 436 | 436 | ||
| 437 | /* select the alt setting once so the endpoints become valid */ | ||
| 438 | ret = usb_set_interface(chip->dev, alts->desc.bInterfaceNumber, | ||
| 439 | alts->desc.bAlternateSetting); | ||
| 440 | if (ret < 0) { | ||
| 441 | snd_printk(KERN_ERR "%s(): usb_set_interface() failed, ret = %d\n", | ||
| 442 | __func__, ret); | ||
| 443 | ep = NULL; | ||
| 444 | goto __exit_unlock; | ||
| 445 | } | ||
| 446 | |||
| 447 | ep = kzalloc(sizeof(*ep), GFP_KERNEL); | 437 | ep = kzalloc(sizeof(*ep), GFP_KERNEL); |
| 448 | if (!ep) | 438 | if (!ep) |
| 449 | goto __exit_unlock; | 439 | goto __exit_unlock; |
| @@ -831,9 +821,6 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) | |||
| 831 | if (++ep->use_count != 1) | 821 | if (++ep->use_count != 1) |
| 832 | return 0; | 822 | return 0; |
| 833 | 823 | ||
| 834 | if (snd_BUG_ON(!test_bit(EP_FLAG_ACTIVATED, &ep->flags))) | ||
| 835 | return -EINVAL; | ||
| 836 | |||
| 837 | /* just to be sure */ | 824 | /* just to be sure */ |
| 838 | deactivate_urbs(ep, 0, 1); | 825 | deactivate_urbs(ep, 0, 1); |
| 839 | wait_clear_urbs(ep); | 826 | wait_clear_urbs(ep); |
| @@ -911,9 +898,6 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, | |||
| 911 | if (snd_BUG_ON(ep->use_count == 0)) | 898 | if (snd_BUG_ON(ep->use_count == 0)) |
| 912 | return; | 899 | return; |
| 913 | 900 | ||
| 914 | if (snd_BUG_ON(!test_bit(EP_FLAG_ACTIVATED, &ep->flags))) | ||
| 915 | return; | ||
| 916 | |||
| 917 | if (--ep->use_count == 0) { | 901 | if (--ep->use_count == 0) { |
| 918 | deactivate_urbs(ep, force, can_sleep); | 902 | deactivate_urbs(ep, force, can_sleep); |
| 919 | ep->data_subs = NULL; | 903 | ep->data_subs = NULL; |
| @@ -927,42 +911,6 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, | |||
| 927 | } | 911 | } |
| 928 | 912 | ||
| 929 | /** | 913 | /** |
| 930 | * snd_usb_endpoint_activate: activate an snd_usb_endpoint | ||
| 931 | * | ||
| 932 | * @ep: the endpoint to activate | ||
| 933 | * | ||
| 934 | * If the endpoint is not currently in use, this functions will select the | ||
| 935 | * correct alternate interface setting for the interface of this endpoint. | ||
| 936 | * | ||
| 937 | * In case of any active users, this functions does nothing. | ||
| 938 | * | ||
| 939 | * Returns an error if usb_set_interface() failed, 0 in all other | ||
| 940 | * cases. | ||
| 941 | */ | ||
| 942 | int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep) | ||
| 943 | { | ||
| 944 | if (ep->use_count != 0) | ||
| 945 | return 0; | ||
| 946 | |||
| 947 | if (!ep->chip->shutdown && | ||
| 948 | !test_and_set_bit(EP_FLAG_ACTIVATED, &ep->flags)) { | ||
| 949 | int ret; | ||
| 950 | |||
| 951 | ret = usb_set_interface(ep->chip->dev, ep->iface, ep->alt_idx); | ||
| 952 | if (ret < 0) { | ||
| 953 | snd_printk(KERN_ERR "%s() usb_set_interface() failed, ret = %d\n", | ||
| 954 | __func__, ret); | ||
| 955 | clear_bit(EP_FLAG_ACTIVATED, &ep->flags); | ||
| 956 | return ret; | ||
| 957 | } | ||
| 958 | |||
| 959 | return 0; | ||
| 960 | } | ||
| 961 | |||
| 962 | return -EBUSY; | ||
| 963 | } | ||
| 964 | |||
| 965 | /** | ||
| 966 | * snd_usb_endpoint_deactivate: deactivate an snd_usb_endpoint | 914 | * snd_usb_endpoint_deactivate: deactivate an snd_usb_endpoint |
| 967 | * | 915 | * |
| 968 | * @ep: the endpoint to deactivate | 916 | * @ep: the endpoint to deactivate |
| @@ -980,24 +928,15 @@ int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep) | |||
| 980 | if (!ep) | 928 | if (!ep) |
| 981 | return -EINVAL; | 929 | return -EINVAL; |
| 982 | 930 | ||
| 931 | deactivate_urbs(ep, 1, 1); | ||
| 932 | wait_clear_urbs(ep); | ||
| 933 | |||
| 983 | if (ep->use_count != 0) | 934 | if (ep->use_count != 0) |
| 984 | return 0; | 935 | return 0; |
| 985 | 936 | ||
| 986 | if (!ep->chip->shutdown && | 937 | clear_bit(EP_FLAG_ACTIVATED, &ep->flags); |
| 987 | test_and_clear_bit(EP_FLAG_ACTIVATED, &ep->flags)) { | ||
| 988 | int ret; | ||
| 989 | |||
| 990 | ret = usb_set_interface(ep->chip->dev, ep->iface, 0); | ||
| 991 | if (ret < 0) { | ||
| 992 | snd_printk(KERN_ERR "%s(): usb_set_interface() failed, ret = %d\n", | ||
| 993 | __func__, ret); | ||
| 994 | return ret; | ||
| 995 | } | ||
| 996 | 938 | ||
| 997 | return 0; | 939 | return 0; |
| 998 | } | ||
| 999 | |||
| 1000 | return -EBUSY; | ||
| 1001 | } | 940 | } |
| 1002 | 941 | ||
| 1003 | /** | 942 | /** |
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 54607f8c4f66..a1298f379428 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c | |||
| @@ -261,19 +261,6 @@ static void stop_endpoints(struct snd_usb_substream *subs, | |||
| 261 | force, can_sleep, wait); | 261 | force, can_sleep, wait); |
| 262 | } | 262 | } |
| 263 | 263 | ||
| 264 | static int activate_endpoints(struct snd_usb_substream *subs) | ||
| 265 | { | ||
| 266 | if (subs->sync_endpoint) { | ||
| 267 | int ret; | ||
| 268 | |||
| 269 | ret = snd_usb_endpoint_activate(subs->sync_endpoint); | ||
| 270 | if (ret < 0) | ||
| 271 | return ret; | ||
| 272 | } | ||
| 273 | |||
| 274 | return snd_usb_endpoint_activate(subs->data_endpoint); | ||
| 275 | } | ||
| 276 | |||
| 277 | static int deactivate_endpoints(struct snd_usb_substream *subs) | 264 | static int deactivate_endpoints(struct snd_usb_substream *subs) |
| 278 | { | 265 | { |
| 279 | int reta, retb; | 266 | int reta, retb; |
| @@ -314,6 +301,33 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) | |||
| 314 | if (fmt == subs->cur_audiofmt) | 301 | if (fmt == subs->cur_audiofmt) |
| 315 | return 0; | 302 | return 0; |
| 316 | 303 | ||
| 304 | /* close the old interface */ | ||
| 305 | if (subs->interface >= 0 && subs->interface != fmt->iface) { | ||
| 306 | err = usb_set_interface(subs->dev, subs->interface, 0); | ||
| 307 | if (err < 0) { | ||
| 308 | snd_printk(KERN_ERR "%d:%d:%d: return to setting 0 failed (%d)\n", | ||
| 309 | dev->devnum, fmt->iface, fmt->altsetting, err); | ||
| 310 | return -EIO; | ||
| 311 | } | ||
| 312 | subs->interface = -1; | ||
| 313 | subs->altset_idx = 0; | ||
| 314 | } | ||
| 315 | |||
| 316 | /* set interface */ | ||
| 317 | if (subs->interface != fmt->iface || | ||
| 318 | subs->altset_idx != fmt->altset_idx) { | ||
| 319 | err = usb_set_interface(dev, fmt->iface, fmt->altsetting); | ||
| 320 | if (err < 0) { | ||
| 321 | snd_printk(KERN_ERR "%d:%d:%d: usb_set_interface failed (%d)\n", | ||
| 322 | dev->devnum, fmt->iface, fmt->altsetting, err); | ||
| 323 | return -EIO; | ||
| 324 | } | ||
| 325 | snd_printdd(KERN_INFO "setting usb interface %d:%d\n", | ||
| 326 | fmt->iface, fmt->altsetting); | ||
| 327 | subs->interface = fmt->iface; | ||
| 328 | subs->altset_idx = fmt->altset_idx; | ||
| 329 | } | ||
| 330 | |||
| 317 | subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip, | 331 | subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip, |
| 318 | alts, fmt->endpoint, subs->direction, | 332 | alts, fmt->endpoint, subs->direction, |
| 319 | SND_USB_ENDPOINT_TYPE_DATA); | 333 | SND_USB_ENDPOINT_TYPE_DATA); |
| @@ -387,7 +401,7 @@ add_sync_ep: | |||
| 387 | subs->data_endpoint->sync_master = subs->sync_endpoint; | 401 | subs->data_endpoint->sync_master = subs->sync_endpoint; |
| 388 | } | 402 | } |
| 389 | 403 | ||
| 390 | if ((err = snd_usb_init_pitch(subs->stream->chip, subs->interface, alts, fmt)) < 0) | 404 | if ((err = snd_usb_init_pitch(subs->stream->chip, fmt->iface, alts, fmt)) < 0) |
| 391 | return err; | 405 | return err; |
| 392 | 406 | ||
| 393 | subs->cur_audiofmt = fmt; | 407 | subs->cur_audiofmt = fmt; |
| @@ -450,7 +464,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, | |||
| 450 | struct usb_interface *iface; | 464 | struct usb_interface *iface; |
| 451 | iface = usb_ifnum_to_if(subs->dev, fmt->iface); | 465 | iface = usb_ifnum_to_if(subs->dev, fmt->iface); |
| 452 | alts = &iface->altsetting[fmt->altset_idx]; | 466 | alts = &iface->altsetting[fmt->altset_idx]; |
| 453 | ret = snd_usb_init_sample_rate(subs->stream->chip, subs->interface, alts, fmt, rate); | 467 | ret = snd_usb_init_sample_rate(subs->stream->chip, fmt->iface, alts, fmt, rate); |
| 454 | if (ret < 0) | 468 | if (ret < 0) |
| 455 | return ret; | 469 | return ret; |
| 456 | subs->cur_rate = rate; | 470 | subs->cur_rate = rate; |
| @@ -460,12 +474,6 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, | |||
| 460 | mutex_lock(&subs->stream->chip->shutdown_mutex); | 474 | mutex_lock(&subs->stream->chip->shutdown_mutex); |
| 461 | /* format changed */ | 475 | /* format changed */ |
| 462 | stop_endpoints(subs, 0, 0, 0); | 476 | stop_endpoints(subs, 0, 0, 0); |
| 463 | deactivate_endpoints(subs); | ||
| 464 | |||
| 465 | ret = activate_endpoints(subs); | ||
| 466 | if (ret < 0) | ||
| 467 | goto unlock; | ||
| 468 | |||
| 469 | ret = snd_usb_endpoint_set_params(subs->data_endpoint, hw_params, fmt, | 477 | ret = snd_usb_endpoint_set_params(subs->data_endpoint, hw_params, fmt, |
| 470 | subs->sync_endpoint); | 478 | subs->sync_endpoint); |
| 471 | if (ret < 0) | 479 | if (ret < 0) |
| @@ -500,6 +508,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) | |||
| 500 | subs->period_bytes = 0; | 508 | subs->period_bytes = 0; |
| 501 | mutex_lock(&subs->stream->chip->shutdown_mutex); | 509 | mutex_lock(&subs->stream->chip->shutdown_mutex); |
| 502 | stop_endpoints(subs, 0, 1, 1); | 510 | stop_endpoints(subs, 0, 1, 1); |
| 511 | deactivate_endpoints(subs); | ||
| 503 | mutex_unlock(&subs->stream->chip->shutdown_mutex); | 512 | mutex_unlock(&subs->stream->chip->shutdown_mutex); |
| 504 | return snd_pcm_lib_free_vmalloc_buffer(substream); | 513 | return snd_pcm_lib_free_vmalloc_buffer(substream); |
| 505 | } | 514 | } |
| @@ -938,16 +947,20 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction) | |||
| 938 | 947 | ||
| 939 | static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction) | 948 | static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction) |
| 940 | { | 949 | { |
| 941 | int ret; | ||
| 942 | struct snd_usb_stream *as = snd_pcm_substream_chip(substream); | 950 | struct snd_usb_stream *as = snd_pcm_substream_chip(substream); |
| 943 | struct snd_usb_substream *subs = &as->substream[direction]; | 951 | struct snd_usb_substream *subs = &as->substream[direction]; |
| 944 | 952 | ||
| 945 | stop_endpoints(subs, 0, 0, 0); | 953 | stop_endpoints(subs, 0, 0, 0); |
| 946 | ret = deactivate_endpoints(subs); | 954 | |
| 955 | if (!as->chip->shutdown && subs->interface >= 0) { | ||
| 956 | usb_set_interface(subs->dev, subs->interface, 0); | ||
| 957 | subs->interface = -1; | ||
| 958 | } | ||
| 959 | |||
| 947 | subs->pcm_substream = NULL; | 960 | subs->pcm_substream = NULL; |
| 948 | snd_usb_autosuspend(subs->stream->chip); | 961 | snd_usb_autosuspend(subs->stream->chip); |
| 949 | 962 | ||
| 950 | return ret; | 963 | return 0; |
| 951 | } | 964 | } |
| 952 | 965 | ||
| 953 | /* Since a URB can handle only a single linear buffer, we must use double | 966 | /* Since a URB can handle only a single linear buffer, we must use double |
