aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-08 18:07:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-08 18:07:14 -0400
commitf5a246eab9a268f51ba8189ea5b098a1bfff200e (patch)
treea6ff7169e0bcaca498d9aec8b0624de1b74eaecb /sound/usb
parentd5bbd43d5f450c3fca058f5b85f3dfb4e8cc88c9 (diff)
parent7ff34ad80b7080fafaac8efa9ef0061708eddd51 (diff)
Merge tag 'sound-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "This contains pretty many small commits covering fairly large range of files in sound/ directory. Partly because of additional API support and partly because of constantly developed ASoC and ARM stuff. Some highlights: - Introduced the helper function and documentation for exposing the channel map via control API, as discussed in Plumbers; most of PCI drivers are covered, will follow more drivers later - Most of drivers have been replaced with the new PM callbacks (if the bus is supported) - HD-audio controller got the support of runtime PM and the support of D3 clock-stop. Also changing the power_save option in sysfs kicks off immediately to enable / disable the power-save mode. - Another significant code change in HD-audio is the rewrite of firmware loading code. Other than that, most of changes in HD-audio are continued cleanups and standardization for the generic auto parser and bug fixes (HBR, device-specific fixups), in addition to the support of channel-map API. - Addition of ASoC bindings for the compressed API, used by the mid-x86 drivers. - Lots of cleanups and API refreshes for ASoC codec drivers and DaVinci. - Conversion of OMAP to dmaengine. - New machine driver for Wolfson Microelectronics Bells. - New CODEC driver for Wolfson Microelectronics WM0010. - Enhancements to the ux500 and wm2000 drivers - A new driver for DA9055 and the support for regulator bypass mode." Fix up various arm soc header file reorg conflicts. * tag 'sound-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (339 commits) ALSA: hda - Add new codec ALC283 ALC290 support ALSA: hda - avoid unneccesary indices on "Headphone Jack" controls ALSA: hda - fix indices on boost volume on Conexant ALSA: aloop - add locking to timer access ALSA: hda - Fix hang caused by race during suspend. sound: Remove unnecessary semicolon ALSA: hda/realtek - Fix detection of ALC271X codec ALSA: hda - Add inverted internal mic quirk for Lenovo IdeaPad U310 ALSA: hda - make Realtek/Sigmatel/Conexant use the generic unsol event ALSA: hda - make a generic unsol event handler ASoC: codecs: Add DA9055 codec driver ASoC: eukrea-tlv320: Convert it to platform driver ALSA: ASoC: add DT bindings for CS4271 ASoC: wm_hubs: Ensure volume updates are handled during class W startup ASoC: wm5110: Adding missing volume update bits ASoC: wm5110: Add OUT3R support ASoC: wm5110: Add AEC loopback support ASoC: wm5110: Rename EPOUT to HPOUT3 ASoC: arizona: Add more clock rates ASoC: arizona: Add more DSP options for mixer input muxes ...
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/6fire/firmware.c5
-rw-r--r--sound/usb/card.c2
-rw-r--r--sound/usb/card.h7
-rw-r--r--sound/usb/endpoint.c39
-rw-r--r--sound/usb/endpoint.h5
-rw-r--r--sound/usb/helper.c5
-rw-r--r--sound/usb/mixer.c7
-rw-r--r--sound/usb/pcm.c126
-rw-r--r--sound/usb/quirks-table.h53
-rw-r--r--sound/usb/quirks.c24
-rw-r--r--sound/usb/quirks.h10
11 files changed, 216 insertions, 67 deletions
diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c
index 56ad923bf6b5..a1d9b0792a1e 100644
--- a/sound/usb/6fire/firmware.c
+++ b/sound/usb/6fire/firmware.c
@@ -346,11 +346,10 @@ static int usb6fire_fw_check(u8 *version)
346 if (!memcmp(version, known_fw_versions + i, 4)) 346 if (!memcmp(version, known_fw_versions + i, 4))
347 return 0; 347 return 0;
348 348
349 snd_printk(KERN_ERR PREFIX "invalid fimware version in device: " 349 snd_printk(KERN_ERR PREFIX "invalid fimware version in device: %*ph. "
350 "%02x %02x %02x %02x. "
351 "please reconnect to power. if this failure " 350 "please reconnect to power. if this failure "
352 "still happens, check your firmware installation.", 351 "still happens, check your firmware installation.",
353 version[0], version[1], version[2], version[3]); 352 4, version);
354 return -EINVAL; 353 return -EINVAL;
355} 354}
356 355
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 4a469f0cb6d4..561bb74fd364 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -646,6 +646,8 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
646 list_for_each(p, &chip->pcm_list) { 646 list_for_each(p, &chip->pcm_list) {
647 as = list_entry(p, struct snd_usb_stream, list); 647 as = list_entry(p, struct snd_usb_stream, list);
648 snd_pcm_suspend_all(as->pcm); 648 snd_pcm_suspend_all(as->pcm);
649 as->substream[0].need_setup_ep =
650 as->substream[1].need_setup_ep = true;
649 } 651 }
650 } 652 }
651 } else { 653 } else {
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 2b9fffff23b6..afa4f9e9b27a 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -92,6 +92,8 @@ struct snd_usb_endpoint {
92 unsigned char silence_value; 92 unsigned char silence_value;
93 unsigned int stride; 93 unsigned int stride;
94 int iface, alt_idx; 94 int iface, alt_idx;
95 int skip_packets; /* quirks for devices to ignore the first n packets
96 in a stream */
95 97
96 spinlock_t lock; 98 spinlock_t lock;
97 struct list_head list; 99 struct list_head list;
@@ -105,6 +107,8 @@ struct snd_usb_substream {
105 int interface; /* current interface */ 107 int interface; /* current interface */
106 int endpoint; /* assigned endpoint */ 108 int endpoint; /* assigned endpoint */
107 struct audioformat *cur_audiofmt; /* current audioformat pointer (for hw_params callback) */ 109 struct audioformat *cur_audiofmt; /* current audioformat pointer (for hw_params callback) */
110 snd_pcm_format_t pcm_format; /* current audio format (for hw_params callback) */
111 unsigned int channels; /* current number of channels (for hw_params callback) */
108 unsigned int cur_rate; /* current rate (for hw_params callback) */ 112 unsigned int cur_rate; /* current rate (for hw_params callback) */
109 unsigned int period_bytes; /* current period bytes (for hw_params callback) */ 113 unsigned int period_bytes; /* current period bytes (for hw_params callback) */
110 unsigned int altset_idx; /* USB data format: index of alternate setting */ 114 unsigned int altset_idx; /* USB data format: index of alternate setting */
@@ -115,14 +119,13 @@ struct snd_usb_substream {
115 119
116 unsigned int hwptr_done; /* processed byte position in the buffer */ 120 unsigned int hwptr_done; /* processed byte position in the buffer */
117 unsigned int transfer_done; /* processed frames since last period update */ 121 unsigned int transfer_done; /* processed frames since last period update */
118 unsigned long active_mask; /* bitmask of active urbs */
119 unsigned long unlink_mask; /* bitmask of unlinked urbs */
120 122
121 /* data and sync endpoints for this stream */ 123 /* data and sync endpoints for this stream */
122 unsigned int ep_num; /* the endpoint number */ 124 unsigned int ep_num; /* the endpoint number */
123 struct snd_usb_endpoint *data_endpoint; 125 struct snd_usb_endpoint *data_endpoint;
124 struct snd_usb_endpoint *sync_endpoint; 126 struct snd_usb_endpoint *sync_endpoint;
125 unsigned long flags; 127 unsigned long flags;
128 bool need_setup_ep; /* (re)configure EP at prepare? */
126 129
127 u64 formats; /* format bitmasks (all or'ed) */ 130 u64 formats; /* format bitmasks (all or'ed) */
128 unsigned int num_formats; /* number of supported audio formats (list) */ 131 unsigned int num_formats; /* number of supported audio formats (list) */
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 */
569static int data_ep_set_params(struct snd_usb_endpoint *ep, 575static 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 */
695static int sync_ep_set_params(struct snd_usb_endpoint *ep, 700static 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 */
747int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, 754int 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,
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index cbbbdf226d66..6376ccf10fd4 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -9,7 +9,10 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
9 int ep_num, int direction, int type); 9 int ep_num, int direction, int type);
10 10
11int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, 11int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
12 struct snd_pcm_hw_params *hw_params, 12 snd_pcm_format_t pcm_format,
13 unsigned int channels,
14 unsigned int period_bytes,
15 unsigned int rate,
13 struct audioformat *fmt, 16 struct audioformat *fmt,
14 struct snd_usb_endpoint *sync_ep); 17 struct snd_usb_endpoint *sync_ep);
15 18
diff --git a/sound/usb/helper.c b/sound/usb/helper.c
index 9eed8f40b179..c1db28f874c2 100644
--- a/sound/usb/helper.c
+++ b/sound/usb/helper.c
@@ -21,6 +21,7 @@
21 21
22#include "usbaudio.h" 22#include "usbaudio.h"
23#include "helper.h" 23#include "helper.h"
24#include "quirks.h"
24 25
25/* 26/*
26 * combine bytes and get an integer value 27 * combine bytes and get an integer value
@@ -97,6 +98,10 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
97 memcpy(data, buf, size); 98 memcpy(data, buf, size);
98 kfree(buf); 99 kfree(buf);
99 } 100 }
101
102 snd_usb_ctl_msg_quirk(dev, pipe, request, requesttype,
103 value, index, data, size);
104
100 return err; 105 return err;
101} 106}
102 107
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 4f40ba823163..fe56c9da38e9 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1267,6 +1267,13 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
1267 /* disable non-functional volume control */ 1267 /* disable non-functional volume control */
1268 master_bits &= ~UAC_CONTROL_BIT(UAC_FU_VOLUME); 1268 master_bits &= ~UAC_CONTROL_BIT(UAC_FU_VOLUME);
1269 break; 1269 break;
1270 case USB_ID(0x1130, 0xf211):
1271 snd_printk(KERN_INFO
1272 "usbmixer: volume control quirk for Tenx TP6911 Audio Headset\n");
1273 /* disable non-functional volume control */
1274 channels = 0;
1275 break;
1276
1270 } 1277 }
1271 if (channels > 0) 1278 if (channels > 0)
1272 first_ch_bits = snd_usb_combine_bytes(bmaControls + csize, csize); 1279 first_ch_bits = snd_usb_combine_bytes(bmaControls + csize, csize);
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index f782ce19bf5a..55e19e1b80ec 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -82,8 +82,7 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
82/* 82/*
83 * find a matching audio format 83 * find a matching audio format
84 */ 84 */
85static struct audioformat *find_format(struct snd_usb_substream *subs, unsigned int format, 85static struct audioformat *find_format(struct snd_usb_substream *subs)
86 unsigned int rate, unsigned int channels)
87{ 86{
88 struct list_head *p; 87 struct list_head *p;
89 struct audioformat *found = NULL; 88 struct audioformat *found = NULL;
@@ -92,16 +91,17 @@ static struct audioformat *find_format(struct snd_usb_substream *subs, unsigned
92 list_for_each(p, &subs->fmt_list) { 91 list_for_each(p, &subs->fmt_list) {
93 struct audioformat *fp; 92 struct audioformat *fp;
94 fp = list_entry(p, struct audioformat, list); 93 fp = list_entry(p, struct audioformat, list);
95 if (!(fp->formats & (1uLL << format))) 94 if (!(fp->formats & (1uLL << subs->pcm_format)))
96 continue; 95 continue;
97 if (fp->channels != channels) 96 if (fp->channels != subs->channels)
98 continue; 97 continue;
99 if (rate < fp->rate_min || rate > fp->rate_max) 98 if (subs->cur_rate < fp->rate_min ||
99 subs->cur_rate > fp->rate_max)
100 continue; 100 continue;
101 if (! (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)) { 101 if (! (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)) {
102 unsigned int i; 102 unsigned int i;
103 for (i = 0; i < fp->nr_rates; i++) 103 for (i = 0; i < fp->nr_rates; i++)
104 if (fp->rate_table[i] == rate) 104 if (fp->rate_table[i] == subs->cur_rate)
105 break; 105 break;
106 if (i >= fp->nr_rates) 106 if (i >= fp->nr_rates)
107 continue; 107 continue;
@@ -436,6 +436,42 @@ add_sync_ep:
436} 436}
437 437
438/* 438/*
439 * configure endpoint params
440 *
441 * called during initial setup and upon resume
442 */
443static int configure_endpoint(struct snd_usb_substream *subs)
444{
445 int ret;
446
447 mutex_lock(&subs->stream->chip->shutdown_mutex);
448 /* format changed */
449 stop_endpoints(subs, 0, 0, 0);
450 ret = snd_usb_endpoint_set_params(subs->data_endpoint,
451 subs->pcm_format,
452 subs->channels,
453 subs->period_bytes,
454 subs->cur_rate,
455 subs->cur_audiofmt,
456 subs->sync_endpoint);
457 if (ret < 0)
458 goto unlock;
459
460 if (subs->sync_endpoint)
461 ret = snd_usb_endpoint_set_params(subs->data_endpoint,
462 subs->pcm_format,
463 subs->channels,
464 subs->period_bytes,
465 subs->cur_rate,
466 subs->cur_audiofmt,
467 NULL);
468
469unlock:
470 mutex_unlock(&subs->stream->chip->shutdown_mutex);
471 return ret;
472}
473
474/*
439 * hw_params callback 475 * hw_params callback
440 * 476 *
441 * allocate a buffer and set the given audio format. 477 * allocate a buffer and set the given audio format.
@@ -450,63 +486,33 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
450{ 486{
451 struct snd_usb_substream *subs = substream->runtime->private_data; 487 struct snd_usb_substream *subs = substream->runtime->private_data;
452 struct audioformat *fmt; 488 struct audioformat *fmt;
453 unsigned int channels, rate, format; 489 int ret;
454 int ret, changed;
455 490
456 ret = snd_pcm_lib_alloc_vmalloc_buffer(substream, 491 ret = snd_pcm_lib_alloc_vmalloc_buffer(substream,
457 params_buffer_bytes(hw_params)); 492 params_buffer_bytes(hw_params));
458 if (ret < 0) 493 if (ret < 0)
459 return ret; 494 return ret;
460 495
461 format = params_format(hw_params); 496 subs->pcm_format = params_format(hw_params);
462 rate = params_rate(hw_params); 497 subs->period_bytes = params_period_bytes(hw_params);
463 channels = params_channels(hw_params); 498 subs->channels = params_channels(hw_params);
464 fmt = find_format(subs, format, rate, channels); 499 subs->cur_rate = params_rate(hw_params);
500
501 fmt = find_format(subs);
465 if (!fmt) { 502 if (!fmt) {
466 snd_printd(KERN_DEBUG "cannot set format: format = %#x, rate = %d, channels = %d\n", 503 snd_printd(KERN_DEBUG "cannot set format: format = %#x, rate = %d, channels = %d\n",
467 format, rate, channels); 504 subs->pcm_format, subs->cur_rate, subs->channels);
468 return -EINVAL; 505 return -EINVAL;
469 } 506 }
470 507
471 changed = subs->cur_audiofmt != fmt ||
472 subs->period_bytes != params_period_bytes(hw_params) ||
473 subs->cur_rate != rate;
474 if ((ret = set_format(subs, fmt)) < 0) 508 if ((ret = set_format(subs, fmt)) < 0)
475 return ret; 509 return ret;
476 510
477 if (subs->cur_rate != rate) { 511 subs->interface = fmt->iface;
478 struct usb_host_interface *alts; 512 subs->altset_idx = fmt->altset_idx;
479 struct usb_interface *iface; 513 subs->need_setup_ep = true;
480 iface = usb_ifnum_to_if(subs->dev, fmt->iface);
481 alts = &iface->altsetting[fmt->altset_idx];
482 ret = snd_usb_init_sample_rate(subs->stream->chip, fmt->iface, alts, fmt, rate);
483 if (ret < 0)
484 return ret;
485 subs->cur_rate = rate;
486 }
487
488 if (changed) {
489 mutex_lock(&subs->stream->chip->shutdown_mutex);
490 /* format changed */
491 stop_endpoints(subs, 0, 0, 0);
492 ret = snd_usb_endpoint_set_params(subs->data_endpoint, hw_params, fmt,
493 subs->sync_endpoint);
494 if (ret < 0)
495 goto unlock;
496 514
497 if (subs->sync_endpoint) 515 return 0;
498 ret = snd_usb_endpoint_set_params(subs->sync_endpoint,
499 hw_params, fmt, NULL);
500unlock:
501 mutex_unlock(&subs->stream->chip->shutdown_mutex);
502 }
503
504 if (ret == 0) {
505 subs->interface = fmt->iface;
506 subs->altset_idx = fmt->altset_idx;
507 }
508
509 return ret;
510} 516}
511 517
512/* 518/*
@@ -537,6 +543,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
537{ 543{
538 struct snd_pcm_runtime *runtime = substream->runtime; 544 struct snd_pcm_runtime *runtime = substream->runtime;
539 struct snd_usb_substream *subs = runtime->private_data; 545 struct snd_usb_substream *subs = runtime->private_data;
546 struct usb_host_interface *alts;
547 struct usb_interface *iface;
548 int ret;
540 549
541 if (! subs->cur_audiofmt) { 550 if (! subs->cur_audiofmt) {
542 snd_printk(KERN_ERR "usbaudio: no format is specified!\n"); 551 snd_printk(KERN_ERR "usbaudio: no format is specified!\n");
@@ -546,6 +555,27 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
546 if (snd_BUG_ON(!subs->data_endpoint)) 555 if (snd_BUG_ON(!subs->data_endpoint))
547 return -EIO; 556 return -EIO;
548 557
558 ret = set_format(subs, subs->cur_audiofmt);
559 if (ret < 0)
560 return ret;
561
562 iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface);
563 alts = &iface->altsetting[subs->cur_audiofmt->altset_idx];
564 ret = snd_usb_init_sample_rate(subs->stream->chip,
565 subs->cur_audiofmt->iface,
566 alts,
567 subs->cur_audiofmt,
568 subs->cur_rate);
569 if (ret < 0)
570 return ret;
571
572 if (subs->need_setup_ep) {
573 ret = configure_endpoint(subs);
574 if (ret < 0)
575 return ret;
576 subs->need_setup_ep = false;
577 }
578
549 /* some unit conversions in runtime */ 579 /* some unit conversions in runtime */
550 subs->data_endpoint->maxframesize = 580 subs->data_endpoint->maxframesize =
551 bytes_to_frames(runtime, subs->data_endpoint->maxpacksize); 581 bytes_to_frames(runtime, subs->data_endpoint->maxpacksize);
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 79780fa57a43..d73ac9bc4272 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2781,6 +2781,59 @@ YAMAHA_DEVICE(0x7010, "UB99"),
2781 } 2781 }
2782}, 2782},
2783 2783
2784/* Microsoft XboxLive Headset/Xbox Communicator */
2785{
2786 USB_DEVICE(0x045e, 0x0283),
2787 .bInterfaceClass = USB_CLASS_PER_INTERFACE,
2788 .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
2789 .vendor_name = "Microsoft",
2790 .product_name = "XboxLive Headset/Xbox Communicator",
2791 .ifnum = QUIRK_ANY_INTERFACE,
2792 .type = QUIRK_COMPOSITE,
2793 .data = &(const struct snd_usb_audio_quirk[]) {
2794 {
2795 /* playback */
2796 .ifnum = 0,
2797 .type = QUIRK_AUDIO_FIXED_ENDPOINT,
2798 .data = &(const struct audioformat) {
2799 .formats = SNDRV_PCM_FMTBIT_S16_LE,
2800 .channels = 1,
2801 .iface = 0,
2802 .altsetting = 0,
2803 .altset_idx = 0,
2804 .attributes = 0,
2805 .endpoint = 0x04,
2806 .ep_attr = 0x05,
2807 .rates = SNDRV_PCM_RATE_CONTINUOUS,
2808 .rate_min = 22050,
2809 .rate_max = 22050
2810 }
2811 },
2812 {
2813 /* capture */
2814 .ifnum = 1,
2815 .type = QUIRK_AUDIO_FIXED_ENDPOINT,
2816 .data = &(const struct audioformat) {
2817 .formats = SNDRV_PCM_FMTBIT_S16_LE,
2818 .channels = 1,
2819 .iface = 1,
2820 .altsetting = 0,
2821 .altset_idx = 0,
2822 .attributes = 0,
2823 .endpoint = 0x85,
2824 .ep_attr = 0x05,
2825 .rates = SNDRV_PCM_RATE_CONTINUOUS,
2826 .rate_min = 16000,
2827 .rate_max = 16000
2828 }
2829 },
2830 {
2831 .ifnum = -1
2832 }
2833 }
2834 }
2835},
2836
2784{ 2837{
2785 /* 2838 /*
2786 * Some USB MIDI devices don't have an audio control interface, 2839 * Some USB MIDI devices don't have an audio control interface,
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 27817266867a..0f58b4b6d702 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -761,3 +761,27 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
761 } 761 }
762} 762}
763 763
764void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
765{
766 /*
767 * "Playback Design" products send bogus feedback data at the start
768 * of the stream. Ignore them.
769 */
770 if ((le16_to_cpu(ep->chip->dev->descriptor.idVendor) == 0x23ba) &&
771 ep->type == SND_USB_ENDPOINT_TYPE_SYNC)
772 ep->skip_packets = 4;
773}
774
775void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
776 __u8 request, __u8 requesttype, __u16 value,
777 __u16 index, void *data, __u16 size)
778{
779 /*
780 * "Playback Design" products need a 20ms delay after each
781 * class compliant request
782 */
783 if ((le16_to_cpu(dev->descriptor.idVendor) == 0x23ba) &&
784 (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
785 mdelay(20);
786}
787
diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h
index 03e5e94098cd..0ca9e91067a6 100644
--- a/sound/usb/quirks.h
+++ b/sound/usb/quirks.h
@@ -1,6 +1,10 @@
1#ifndef __USBAUDIO_QUIRKS_H 1#ifndef __USBAUDIO_QUIRKS_H
2#define __USBAUDIO_QUIRKS_H 2#define __USBAUDIO_QUIRKS_H
3 3
4struct audioformat;
5struct snd_usb_endpoint;
6struct snd_usb_substream;
7
4int snd_usb_create_quirk(struct snd_usb_audio *chip, 8int snd_usb_create_quirk(struct snd_usb_audio *chip,
5 struct usb_interface *iface, 9 struct usb_interface *iface,
6 struct usb_driver *driver, 10 struct usb_driver *driver,
@@ -20,4 +24,10 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
20int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, 24int snd_usb_is_big_endian_format(struct snd_usb_audio *chip,
21 struct audioformat *fp); 25 struct audioformat *fp);
22 26
27void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep);
28
29void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
30 __u8 request, __u8 requesttype, __u16 value,
31 __u16 index, void *data, __u16 size);
32
23#endif /* __USBAUDIO_QUIRKS_H */ 33#endif /* __USBAUDIO_QUIRKS_H */