diff options
Diffstat (limited to 'sound/usb/endpoint.c')
-rw-r--r-- | sound/usb/endpoint.c | 39 |
1 files changed, 26 insertions, 13 deletions
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 060dccb9ec75..7f78c6d782b0 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "card.h" | 31 | #include "card.h" |
32 | #include "endpoint.h" | 32 | #include "endpoint.h" |
33 | #include "pcm.h" | 33 | #include "pcm.h" |
34 | #include "quirks.h" | ||
34 | 35 | ||
35 | #define EP_FLAG_ACTIVATED 0 | 36 | #define EP_FLAG_ACTIVATED 0 |
36 | #define EP_FLAG_RUNNING 1 | 37 | #define EP_FLAG_RUNNING 1 |
@@ -170,6 +171,11 @@ static void retire_inbound_urb(struct snd_usb_endpoint *ep, | |||
170 | { | 171 | { |
171 | struct urb *urb = urb_ctx->urb; | 172 | struct urb *urb = urb_ctx->urb; |
172 | 173 | ||
174 | if (unlikely(ep->skip_packets > 0)) { | ||
175 | ep->skip_packets--; | ||
176 | return; | ||
177 | } | ||
178 | |||
173 | if (ep->sync_slave) | 179 | if (ep->sync_slave) |
174 | snd_usb_handle_sync_urb(ep->sync_slave, ep, urb); | 180 | snd_usb_handle_sync_urb(ep->sync_slave, ep, urb); |
175 | 181 | ||
@@ -567,20 +573,19 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force) | |||
567 | * configure a data endpoint | 573 | * configure a data endpoint |
568 | */ | 574 | */ |
569 | static int data_ep_set_params(struct snd_usb_endpoint *ep, | 575 | static int data_ep_set_params(struct snd_usb_endpoint *ep, |
570 | struct snd_pcm_hw_params *hw_params, | 576 | snd_pcm_format_t pcm_format, |
577 | unsigned int channels, | ||
578 | unsigned int period_bytes, | ||
571 | struct audioformat *fmt, | 579 | struct audioformat *fmt, |
572 | struct snd_usb_endpoint *sync_ep) | 580 | struct snd_usb_endpoint *sync_ep) |
573 | { | 581 | { |
574 | unsigned int maxsize, i, urb_packs, total_packs, packs_per_ms; | 582 | unsigned int maxsize, i, urb_packs, total_packs, packs_per_ms; |
575 | int period_bytes = params_period_bytes(hw_params); | ||
576 | int format = params_format(hw_params); | ||
577 | int is_playback = usb_pipeout(ep->pipe); | 583 | int is_playback = usb_pipeout(ep->pipe); |
578 | int frame_bits = snd_pcm_format_physical_width(params_format(hw_params)) * | 584 | int frame_bits = snd_pcm_format_physical_width(pcm_format) * channels; |
579 | params_channels(hw_params); | ||
580 | 585 | ||
581 | ep->datainterval = fmt->datainterval; | 586 | ep->datainterval = fmt->datainterval; |
582 | ep->stride = frame_bits >> 3; | 587 | ep->stride = frame_bits >> 3; |
583 | ep->silence_value = format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0; | 588 | ep->silence_value = pcm_format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0; |
584 | 589 | ||
585 | /* calculate max. frequency */ | 590 | /* calculate max. frequency */ |
586 | if (ep->maxpacksize) { | 591 | if (ep->maxpacksize) { |
@@ -693,7 +698,6 @@ out_of_memory: | |||
693 | * configure a sync endpoint | 698 | * configure a sync endpoint |
694 | */ | 699 | */ |
695 | static int sync_ep_set_params(struct snd_usb_endpoint *ep, | 700 | static int sync_ep_set_params(struct snd_usb_endpoint *ep, |
696 | struct snd_pcm_hw_params *hw_params, | ||
697 | struct audioformat *fmt) | 701 | struct audioformat *fmt) |
698 | { | 702 | { |
699 | int i; | 703 | int i; |
@@ -736,7 +740,10 @@ out_of_memory: | |||
736 | * snd_usb_endpoint_set_params: configure an snd_usb_endpoint | 740 | * snd_usb_endpoint_set_params: configure an snd_usb_endpoint |
737 | * | 741 | * |
738 | * @ep: the snd_usb_endpoint to configure | 742 | * @ep: the snd_usb_endpoint to configure |
739 | * @hw_params: the hardware parameters | 743 | * @pcm_format: the audio fomat. |
744 | * @channels: the number of audio channels. | ||
745 | * @period_bytes: the number of bytes in one alsa period. | ||
746 | * @rate: the frame rate. | ||
740 | * @fmt: the USB audio format information | 747 | * @fmt: the USB audio format information |
741 | * @sync_ep: the sync endpoint to use, if any | 748 | * @sync_ep: the sync endpoint to use, if any |
742 | * | 749 | * |
@@ -745,7 +752,10 @@ out_of_memory: | |||
745 | * An endpoint that is already running can not be reconfigured. | 752 | * An endpoint that is already running can not be reconfigured. |
746 | */ | 753 | */ |
747 | int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, | 754 | int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, |
748 | struct snd_pcm_hw_params *hw_params, | 755 | snd_pcm_format_t pcm_format, |
756 | unsigned int channels, | ||
757 | unsigned int period_bytes, | ||
758 | unsigned int rate, | ||
749 | struct audioformat *fmt, | 759 | struct audioformat *fmt, |
750 | struct snd_usb_endpoint *sync_ep) | 760 | struct snd_usb_endpoint *sync_ep) |
751 | { | 761 | { |
@@ -765,9 +775,9 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, | |||
765 | ep->fill_max = !!(fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX); | 775 | ep->fill_max = !!(fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX); |
766 | 776 | ||
767 | if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_FULL) | 777 | if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_FULL) |
768 | ep->freqn = get_usb_full_speed_rate(params_rate(hw_params)); | 778 | ep->freqn = get_usb_full_speed_rate(rate); |
769 | else | 779 | else |
770 | ep->freqn = get_usb_high_speed_rate(params_rate(hw_params)); | 780 | ep->freqn = get_usb_high_speed_rate(rate); |
771 | 781 | ||
772 | /* calculate the frequency in 16.16 format */ | 782 | /* calculate the frequency in 16.16 format */ |
773 | ep->freqm = ep->freqn; | 783 | ep->freqm = ep->freqn; |
@@ -777,10 +787,11 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, | |||
777 | 787 | ||
778 | switch (ep->type) { | 788 | switch (ep->type) { |
779 | case SND_USB_ENDPOINT_TYPE_DATA: | 789 | case SND_USB_ENDPOINT_TYPE_DATA: |
780 | err = data_ep_set_params(ep, hw_params, fmt, sync_ep); | 790 | err = data_ep_set_params(ep, pcm_format, channels, |
791 | period_bytes, fmt, sync_ep); | ||
781 | break; | 792 | break; |
782 | case SND_USB_ENDPOINT_TYPE_SYNC: | 793 | case SND_USB_ENDPOINT_TYPE_SYNC: |
783 | err = sync_ep_set_params(ep, hw_params, fmt); | 794 | err = sync_ep_set_params(ep, fmt); |
784 | break; | 795 | break; |
785 | default: | 796 | default: |
786 | err = -EINVAL; | 797 | err = -EINVAL; |
@@ -828,6 +839,8 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep) | |||
828 | ep->unlink_mask = 0; | 839 | ep->unlink_mask = 0; |
829 | ep->phase = 0; | 840 | ep->phase = 0; |
830 | 841 | ||
842 | snd_usb_endpoint_start_quirk(ep); | ||
843 | |||
831 | /* | 844 | /* |
832 | * If this endpoint has a data endpoint as implicit feedback source, | 845 | * If this endpoint has a data endpoint as implicit feedback source, |
833 | * don't start the urbs here. Instead, mark them all as available, | 846 | * don't start the urbs here. Instead, mark them all as available, |