diff options
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/card.h | 1 | ||||
-rw-r--r-- | sound/usb/mixer.c | 65 | ||||
-rw-r--r-- | sound/usb/pcm.c | 49 | ||||
-rw-r--r-- | sound/usb/proc.c | 4 | ||||
-rw-r--r-- | sound/usb/stream.c | 1 |
5 files changed, 79 insertions, 41 deletions
diff --git a/sound/usb/card.h b/sound/usb/card.h index afa4f9e9b27a..814cb357ff88 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h | |||
@@ -126,6 +126,7 @@ struct snd_usb_substream { | |||
126 | struct snd_usb_endpoint *sync_endpoint; | 126 | struct snd_usb_endpoint *sync_endpoint; |
127 | unsigned long flags; | 127 | unsigned long flags; |
128 | bool need_setup_ep; /* (re)configure EP at prepare? */ | 128 | bool need_setup_ep; /* (re)configure EP at prepare? */ |
129 | unsigned int speed; /* USB_SPEED_XXX */ | ||
129 | 130 | ||
130 | u64 formats; /* format bitmasks (all or'ed) */ | 131 | u64 formats; /* format bitmasks (all or'ed) */ |
131 | unsigned int num_formats; /* number of supported audio formats (list) */ | 132 | unsigned int num_formats; /* number of supported audio formats (list) */ |
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index fe56c9da38e9..c2ef11ccd66a 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
@@ -287,25 +287,32 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v | |||
287 | unsigned char buf[2]; | 287 | unsigned char buf[2]; |
288 | int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; | 288 | int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; |
289 | int timeout = 10; | 289 | int timeout = 10; |
290 | int err; | 290 | int idx = 0, err; |
291 | 291 | ||
292 | err = snd_usb_autoresume(cval->mixer->chip); | 292 | err = snd_usb_autoresume(cval->mixer->chip); |
293 | if (err < 0) | 293 | if (err < 0) |
294 | return -EIO; | 294 | return -EIO; |
295 | mutex_lock(&chip->shutdown_mutex); | ||
295 | while (timeout-- > 0) { | 296 | while (timeout-- > 0) { |
297 | if (chip->shutdown) | ||
298 | break; | ||
299 | idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); | ||
296 | if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, | 300 | if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, |
297 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 301 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
298 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), | 302 | validx, idx, buf, val_len) >= val_len) { |
299 | buf, val_len) >= val_len) { | ||
300 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); | 303 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); |
301 | snd_usb_autosuspend(cval->mixer->chip); | 304 | err = 0; |
302 | return 0; | 305 | goto out; |
303 | } | 306 | } |
304 | } | 307 | } |
305 | snd_usb_autosuspend(cval->mixer->chip); | ||
306 | snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", | 308 | snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", |
307 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); | 309 | request, validx, idx, cval->val_type); |
308 | return -EINVAL; | 310 | err = -EINVAL; |
311 | |||
312 | out: | ||
313 | mutex_unlock(&chip->shutdown_mutex); | ||
314 | snd_usb_autosuspend(cval->mixer->chip); | ||
315 | return err; | ||
309 | } | 316 | } |
310 | 317 | ||
311 | static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) | 318 | static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) |
@@ -313,7 +320,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v | |||
313 | struct snd_usb_audio *chip = cval->mixer->chip; | 320 | struct snd_usb_audio *chip = cval->mixer->chip; |
314 | unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */ | 321 | unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */ |
315 | unsigned char *val; | 322 | unsigned char *val; |
316 | int ret, size; | 323 | int idx = 0, ret, size; |
317 | __u8 bRequest; | 324 | __u8 bRequest; |
318 | 325 | ||
319 | if (request == UAC_GET_CUR) { | 326 | if (request == UAC_GET_CUR) { |
@@ -330,16 +337,22 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v | |||
330 | if (ret) | 337 | if (ret) |
331 | goto error; | 338 | goto error; |
332 | 339 | ||
333 | ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, | 340 | mutex_lock(&chip->shutdown_mutex); |
341 | if (chip->shutdown) | ||
342 | ret = -ENODEV; | ||
343 | else { | ||
344 | idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); | ||
345 | ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, | ||
334 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 346 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
335 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), | 347 | validx, idx, buf, size); |
336 | buf, size); | 348 | } |
349 | mutex_unlock(&chip->shutdown_mutex); | ||
337 | snd_usb_autosuspend(chip); | 350 | snd_usb_autosuspend(chip); |
338 | 351 | ||
339 | if (ret < 0) { | 352 | if (ret < 0) { |
340 | error: | 353 | error: |
341 | snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", | 354 | snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", |
342 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); | 355 | request, validx, idx, cval->val_type); |
343 | return ret; | 356 | return ret; |
344 | } | 357 | } |
345 | 358 | ||
@@ -417,7 +430,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, | |||
417 | { | 430 | { |
418 | struct snd_usb_audio *chip = cval->mixer->chip; | 431 | struct snd_usb_audio *chip = cval->mixer->chip; |
419 | unsigned char buf[2]; | 432 | unsigned char buf[2]; |
420 | int val_len, err, timeout = 10; | 433 | int idx = 0, val_len, err, timeout = 10; |
421 | 434 | ||
422 | if (cval->mixer->protocol == UAC_VERSION_1) { | 435 | if (cval->mixer->protocol == UAC_VERSION_1) { |
423 | val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; | 436 | val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; |
@@ -440,19 +453,27 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, | |||
440 | err = snd_usb_autoresume(chip); | 453 | err = snd_usb_autoresume(chip); |
441 | if (err < 0) | 454 | if (err < 0) |
442 | return -EIO; | 455 | return -EIO; |
443 | while (timeout-- > 0) | 456 | mutex_lock(&chip->shutdown_mutex); |
457 | while (timeout-- > 0) { | ||
458 | if (chip->shutdown) | ||
459 | break; | ||
460 | idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); | ||
444 | if (snd_usb_ctl_msg(chip->dev, | 461 | if (snd_usb_ctl_msg(chip->dev, |
445 | usb_sndctrlpipe(chip->dev, 0), request, | 462 | usb_sndctrlpipe(chip->dev, 0), request, |
446 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, | 463 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, |
447 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), | 464 | validx, idx, buf, val_len) >= 0) { |
448 | buf, val_len) >= 0) { | 465 | err = 0; |
449 | snd_usb_autosuspend(chip); | 466 | goto out; |
450 | return 0; | ||
451 | } | 467 | } |
452 | snd_usb_autosuspend(chip); | 468 | } |
453 | snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", | 469 | snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", |
454 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); | 470 | request, validx, idx, cval->val_type, buf[0], buf[1]); |
455 | return -EINVAL; | 471 | err = -EINVAL; |
472 | |||
473 | out: | ||
474 | mutex_unlock(&chip->shutdown_mutex); | ||
475 | snd_usb_autosuspend(chip); | ||
476 | return err; | ||
456 | } | 477 | } |
457 | 478 | ||
458 | static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value) | 479 | static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value) |
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 55e19e1b80ec..55e741c5f231 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, |
@@ -444,7 +446,6 @@ static int configure_endpoint(struct snd_usb_substream *subs) | |||
444 | { | 446 | { |
445 | int ret; | 447 | int ret; |
446 | 448 | ||
447 | mutex_lock(&subs->stream->chip->shutdown_mutex); | ||
448 | /* format changed */ | 449 | /* format changed */ |
449 | stop_endpoints(subs, 0, 0, 0); | 450 | stop_endpoints(subs, 0, 0, 0); |
450 | ret = snd_usb_endpoint_set_params(subs->data_endpoint, | 451 | ret = snd_usb_endpoint_set_params(subs->data_endpoint, |
@@ -455,7 +456,7 @@ static int configure_endpoint(struct snd_usb_substream *subs) | |||
455 | subs->cur_audiofmt, | 456 | subs->cur_audiofmt, |
456 | subs->sync_endpoint); | 457 | subs->sync_endpoint); |
457 | if (ret < 0) | 458 | if (ret < 0) |
458 | goto unlock; | 459 | return ret; |
459 | 460 | ||
460 | if (subs->sync_endpoint) | 461 | if (subs->sync_endpoint) |
461 | ret = snd_usb_endpoint_set_params(subs->data_endpoint, | 462 | ret = snd_usb_endpoint_set_params(subs->data_endpoint, |
@@ -465,9 +466,6 @@ static int configure_endpoint(struct snd_usb_substream *subs) | |||
465 | subs->cur_rate, | 466 | subs->cur_rate, |
466 | subs->cur_audiofmt, | 467 | subs->cur_audiofmt, |
467 | NULL); | 468 | NULL); |
468 | |||
469 | unlock: | ||
470 | mutex_unlock(&subs->stream->chip->shutdown_mutex); | ||
471 | return ret; | 469 | return ret; |
472 | } | 470 | } |
473 | 471 | ||
@@ -505,7 +503,13 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, | |||
505 | return -EINVAL; | 503 | return -EINVAL; |
506 | } | 504 | } |
507 | 505 | ||
508 | if ((ret = set_format(subs, fmt)) < 0) | 506 | mutex_lock(&subs->stream->chip->shutdown_mutex); |
507 | if (subs->stream->chip->shutdown) | ||
508 | ret = -ENODEV; | ||
509 | else | ||
510 | ret = set_format(subs, fmt); | ||
511 | mutex_unlock(&subs->stream->chip->shutdown_mutex); | ||
512 | if (ret < 0) | ||
509 | return ret; | 513 | return ret; |
510 | 514 | ||
511 | subs->interface = fmt->iface; | 515 | subs->interface = fmt->iface; |
@@ -528,8 +532,10 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) | |||
528 | subs->cur_rate = 0; | 532 | subs->cur_rate = 0; |
529 | subs->period_bytes = 0; | 533 | subs->period_bytes = 0; |
530 | mutex_lock(&subs->stream->chip->shutdown_mutex); | 534 | mutex_lock(&subs->stream->chip->shutdown_mutex); |
531 | stop_endpoints(subs, 0, 1, 1); | 535 | if (!subs->stream->chip->shutdown) { |
532 | deactivate_endpoints(subs); | 536 | stop_endpoints(subs, 0, 1, 1); |
537 | deactivate_endpoints(subs); | ||
538 | } | ||
533 | mutex_unlock(&subs->stream->chip->shutdown_mutex); | 539 | mutex_unlock(&subs->stream->chip->shutdown_mutex); |
534 | return snd_pcm_lib_free_vmalloc_buffer(substream); | 540 | return snd_pcm_lib_free_vmalloc_buffer(substream); |
535 | } | 541 | } |
@@ -552,12 +558,19 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) | |||
552 | return -ENXIO; | 558 | return -ENXIO; |
553 | } | 559 | } |
554 | 560 | ||
555 | if (snd_BUG_ON(!subs->data_endpoint)) | 561 | mutex_lock(&subs->stream->chip->shutdown_mutex); |
556 | return -EIO; | 562 | if (subs->stream->chip->shutdown) { |
563 | ret = -ENODEV; | ||
564 | goto unlock; | ||
565 | } | ||
566 | if (snd_BUG_ON(!subs->data_endpoint)) { | ||
567 | ret = -EIO; | ||
568 | goto unlock; | ||
569 | } | ||
557 | 570 | ||
558 | ret = set_format(subs, subs->cur_audiofmt); | 571 | ret = set_format(subs, subs->cur_audiofmt); |
559 | if (ret < 0) | 572 | if (ret < 0) |
560 | return ret; | 573 | goto unlock; |
561 | 574 | ||
562 | iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface); | 575 | iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface); |
563 | alts = &iface->altsetting[subs->cur_audiofmt->altset_idx]; | 576 | alts = &iface->altsetting[subs->cur_audiofmt->altset_idx]; |
@@ -567,12 +580,12 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) | |||
567 | subs->cur_audiofmt, | 580 | subs->cur_audiofmt, |
568 | subs->cur_rate); | 581 | subs->cur_rate); |
569 | if (ret < 0) | 582 | if (ret < 0) |
570 | return ret; | 583 | goto unlock; |
571 | 584 | ||
572 | if (subs->need_setup_ep) { | 585 | if (subs->need_setup_ep) { |
573 | ret = configure_endpoint(subs); | 586 | ret = configure_endpoint(subs); |
574 | if (ret < 0) | 587 | if (ret < 0) |
575 | return ret; | 588 | goto unlock; |
576 | subs->need_setup_ep = false; | 589 | subs->need_setup_ep = false; |
577 | } | 590 | } |
578 | 591 | ||
@@ -592,9 +605,11 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) | |||
592 | /* for playback, submit the URBs now; otherwise, the first hwptr_done | 605 | /* for playback, submit the URBs now; otherwise, the first hwptr_done |
593 | * updates for all URBs would happen at the same time when starting */ | 606 | * updates for all URBs would happen at the same time when starting */ |
594 | if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) | 607 | if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) |
595 | return start_endpoints(subs, 1); | 608 | ret = start_endpoints(subs, 1); |
596 | 609 | ||
597 | return 0; | 610 | unlock: |
611 | mutex_unlock(&subs->stream->chip->shutdown_mutex); | ||
612 | return ret; | ||
598 | } | 613 | } |
599 | 614 | ||
600 | static struct snd_pcm_hardware snd_usb_hardware = | 615 | static struct snd_pcm_hardware snd_usb_hardware = |
@@ -647,7 +662,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs, | |||
647 | return 0; | 662 | return 0; |
648 | } | 663 | } |
649 | /* check whether the period time is >= the data packet interval */ | 664 | /* check whether the period time is >= the data packet interval */ |
650 | if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) { | 665 | if (subs->speed != USB_SPEED_FULL) { |
651 | ptime = 125 * (1 << fp->datainterval); | 666 | ptime = 125 * (1 << fp->datainterval); |
652 | if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { | 667 | if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { |
653 | hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); | 668 | hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); |
@@ -925,7 +940,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre | |||
925 | return err; | 940 | return err; |
926 | 941 | ||
927 | param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; | 942 | param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; |
928 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) | 943 | if (subs->speed == USB_SPEED_FULL) |
929 | /* full speed devices have fixed data packet interval */ | 944 | /* full speed devices have fixed data packet interval */ |
930 | ptmin = 1000; | 945 | ptmin = 1000; |
931 | if (ptmin == 1000) | 946 | if (ptmin == 1000) |
diff --git a/sound/usb/proc.c b/sound/usb/proc.c index ebc1a5b5b3f1..d218f763501f 100644 --- a/sound/usb/proc.c +++ b/sound/usb/proc.c | |||
@@ -108,7 +108,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s | |||
108 | } | 108 | } |
109 | snd_iprintf(buffer, "\n"); | 109 | snd_iprintf(buffer, "\n"); |
110 | } | 110 | } |
111 | if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) | 111 | if (subs->speed != USB_SPEED_FULL) |
112 | snd_iprintf(buffer, " Data packet interval: %d us\n", | 112 | snd_iprintf(buffer, " Data packet interval: %d us\n", |
113 | 125 * (1 << fp->datainterval)); | 113 | 125 * (1 << fp->datainterval)); |
114 | // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize); | 114 | // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize); |
@@ -124,7 +124,7 @@ static void proc_dump_ep_status(struct snd_usb_substream *subs, | |||
124 | return; | 124 | return; |
125 | snd_iprintf(buffer, " Packet Size = %d\n", ep->curpacksize); | 125 | snd_iprintf(buffer, " Packet Size = %d\n", ep->curpacksize); |
126 | snd_iprintf(buffer, " Momentary freq = %u Hz (%#x.%04x)\n", | 126 | snd_iprintf(buffer, " Momentary freq = %u Hz (%#x.%04x)\n", |
127 | snd_usb_get_speed(subs->dev) == USB_SPEED_FULL | 127 | subs->speed == USB_SPEED_FULL |
128 | ? get_full_speed_hz(ep->freqm) | 128 | ? get_full_speed_hz(ep->freqm) |
129 | : get_high_speed_hz(ep->freqm), | 129 | : get_high_speed_hz(ep->freqm), |
130 | ep->freqm >> 16, ep->freqm & 0xffff); | 130 | ep->freqm >> 16, ep->freqm & 0xffff); |
diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 083ed81160e5..1de0c8c002a8 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c | |||
@@ -90,6 +90,7 @@ static void snd_usb_init_substream(struct snd_usb_stream *as, | |||
90 | subs->direction = stream; | 90 | subs->direction = stream; |
91 | subs->dev = as->chip->dev; | 91 | subs->dev = as->chip->dev; |
92 | subs->txfr_quirk = as->chip->txfr_quirk; | 92 | subs->txfr_quirk = as->chip->txfr_quirk; |
93 | subs->speed = snd_usb_get_speed(subs->dev); | ||
93 | 94 | ||
94 | snd_usb_set_pcm_ops(as->pcm, stream); | 95 | snd_usb_set_pcm_ops(as->pcm, stream); |
95 | 96 | ||