History

ALSA: usb-audio: Add new quirk FIXED_RATE for JBL Quantum810 Wireless

It seems that the firmware is broken and does not accept the UAC_EP_CS_ATTR_SAMPLE_RATE URB. There is only one rate (48000Hz) available in the descriptors for the output endpoint. Create a new quirk QUIRK_FLAG_FIXED_RATE to skip the rate setup when only one rate is available (fixed).

Jaroslav Kysela committed 3 years ago

Commit fd289411 parent a95e1639 files · +60 −12Browse files

Unified · Split

9 files
  1. sound/usb/card.h +1 −0
  2. sound/usb/endpoint.c +10 −6
  3. sound/usb/endpoint.h +2 −1
  4. sound/usb/implicit.c +5 −1
  5. sound/usb/implicit.h +1 −1
  6. sound/usb/pcm.c +33 −3
  7. sound/usb/pcm.h +2 −0
  8. sound/usb/quirks.c +2 −0
  9. sound/usb/usbaudio.h +4 −0
sound/usb/card.h+1−0
@@ -131,6 +131,7 @@ struct snd_usb_endpoint { · 130 unmodified lines
131 bool lowlatency_playback; /* low-latency playback mode */131 bool lowlatency_playback; /* low-latency playback mode */
132 bool need_setup; /* (re-)need for hw_params? */132 bool need_setup; /* (re-)need for hw_params? */
133 bool need_prepare; /* (re-)need for prepare? */133 bool need_prepare; /* (re-)need for prepare? */
134 bool fixed_rate; /* skip rate setup */
134 135
135 /* for hw constraints */136 /* for hw constraints */
136 const struct audioformat *cur_audiofmt;137 const struct audioformat *cur_audiofmt;
sound/usb/endpoint.c+10−6
@@ -769,7 +769,8 @@ struct snd_usb_endpoint * · 768 unmodified lines
769snd_usb_endpoint_open(struct snd_usb_audio *chip,769snd_usb_endpoint_open(struct snd_usb_audio *chip,
770 const struct audioformat *fp,770 const struct audioformat *fp,
771 const struct snd_pcm_hw_params *params,771 const struct snd_pcm_hw_params *params,
772 bool is_sync_ep)772 bool is_sync_ep,
773 bool fixed_rate)
773{774{
774 struct snd_usb_endpoint *ep;775 struct snd_usb_endpoint *ep;
775 int ep_num = is_sync_ep ? fp->sync_ep : fp->endpoint;776 int ep_num = is_sync_ep ? fp->sync_ep : fp->endpoint;
@@ -825,6 +826,7 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip, · 49 unmodified lines
825 ep->implicit_fb_sync = fp->implicit_fb;826 ep->implicit_fb_sync = fp->implicit_fb;
826 ep->need_setup = true;827 ep->need_setup = true;
827 ep->need_prepare = true;828 ep->need_prepare = true;
829 ep->fixed_rate = fixed_rate;
828 830
829 usb_audio_dbg(chip, " channels=%d, rate=%d, format=%s, period_bytes=%d, periods=%d, implicit_fb=%d\n",831 usb_audio_dbg(chip, " channels=%d, rate=%d, format=%s, period_bytes=%d, periods=%d, implicit_fb=%d\n",
830 ep->cur_channels, ep->cur_rate,832 ep->cur_channels, ep->cur_rate,
@@ -1413,11 +1415,13 @@ static int init_sample_rate(struct snd_usb_audio *chip, · 582 unmodified lines
1413 if (clock && !clock->need_setup)1415 if (clock && !clock->need_setup)
1414 return 0;1416 return 0;
1415 1417
1416 err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, rate);1418 if (!ep->fixed_rate) {
1417 if (err < 0) {1419 err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, rate);
1418 if (clock)1420 if (err < 0) {
1419 clock->rate = 0; /* reset rate */1421 if (clock)
1420 return err;1422 clock->rate = 0; /* reset rate */
1423 return err;
1424 }
1421 }1425 }
1422 1426
1423 if (clock)1427 if (clock)
sound/usb/endpoint.h+2−1
@@ -14,7 +14,8 @@ struct snd_usb_endpoint * · 13 unmodified lines
14snd_usb_endpoint_open(struct snd_usb_audio *chip,14snd_usb_endpoint_open(struct snd_usb_audio *chip,
15 const struct audioformat *fp,15 const struct audioformat *fp,
16 const struct snd_pcm_hw_params *params,16 const struct snd_pcm_hw_params *params,
17 bool is_sync_ep);17 bool is_sync_ep,
18 bool fixed_rate);
18void snd_usb_endpoint_close(struct snd_usb_audio *chip,19void snd_usb_endpoint_close(struct snd_usb_audio *chip,
19 struct snd_usb_endpoint *ep);20 struct snd_usb_endpoint *ep);
20int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,21int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
sound/usb/implicit.c+5−1
@@ -15,6 +15,7 @@ · 14 unmodified lines
15#include "usbaudio.h"15#include "usbaudio.h"
16#include "card.h"16#include "card.h"
17#include "helper.h"17#include "helper.h"
18#include "pcm.h"
18#include "implicit.h"19#include "implicit.h"
19 20
20enum {21enum {
@@ -455,7 +456,8 @@ const struct audioformat * · 434 unmodified lines
455snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,456snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,
456 const struct audioformat *target,457 const struct audioformat *target,
457 const struct snd_pcm_hw_params *params,458 const struct snd_pcm_hw_params *params,
458 int stream)459 int stream,
460 bool *fixed_rate)
459{461{
460 struct snd_usb_substream *subs;462 struct snd_usb_substream *subs;
461 const struct audioformat *fp, *sync_fmt = NULL;463 const struct audioformat *fp, *sync_fmt = NULL;
@@ -483,6 +485,8 @@ snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip, · 21 unmodified lines
483 }485 }
484 }486 }
485 487
488 if (fixed_rate)
489 *fixed_rate = snd_usb_pcm_has_fixed_rate(subs);
486 return sync_fmt;490 return sync_fmt;
487}491}
488 492
sound/usb/implicit.h+1−1
@@ -9,6 +9,6 @@ const struct audioformat * · 8 unmodified lines
9snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,9snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,
10 const struct audioformat *target,10 const struct audioformat *target,
11 const struct snd_pcm_hw_params *params,11 const struct snd_pcm_hw_params *params,
12 int stream);12 int stream, bool *fixed_rate);
13 13
14#endif /* __USBAUDIO_IMPLICIT_H */14#endif /* __USBAUDIO_IMPLICIT_H */
sound/usb/pcm.c+33−3
@@ -157,6 +157,31 @@ find_substream_format(struct snd_usb_substream *subs, · 156 unmodified lines
157 true, subs);157 true, subs);
158}158}
159 159
160bool snd_usb_pcm_has_fixed_rate(struct snd_usb_substream *subs)
161{
162 const struct audioformat *fp;
163 struct snd_usb_audio *chip = subs->stream->chip;
164 int rate = -1;
165
166 if (!(chip->quirk_flags & QUIRK_FLAG_FIXED_RATE))
167 return false;
168 list_for_each_entry(fp, &subs->fmt_list, list) {
169 if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)
170 return false;
171 if (fp->nr_rates < 1)
172 continue;
173 if (fp->nr_rates > 1)
174 return false;
175 if (rate < 0) {
176 rate = fp->rate_table[0];
177 continue;
178 }
179 if (rate != fp->rate_table[0])
180 return false;
181 }
182 return true;
183}
184
160static int init_pitch_v1(struct snd_usb_audio *chip, int ep)185static int init_pitch_v1(struct snd_usb_audio *chip, int ep)
161{186{
162 struct usb_device *dev = chip->dev;187 struct usb_device *dev = chip->dev;
@@ -450,12 +475,14 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, · 287 unmodified lines
450 struct snd_usb_audio *chip = subs->stream->chip;475 struct snd_usb_audio *chip = subs->stream->chip;
451 const struct audioformat *fmt;476 const struct audioformat *fmt;
452 const struct audioformat *sync_fmt;477 const struct audioformat *sync_fmt;
478 bool fixed_rate, sync_fixed_rate;
453 int ret;479 int ret;
454 480
455 ret = snd_media_start_pipeline(subs);481 ret = snd_media_start_pipeline(subs);
456 if (ret)482 if (ret)
457 return ret;483 return ret;
458 484
485 fixed_rate = snd_usb_pcm_has_fixed_rate(subs);
459 fmt = find_substream_format(subs, hw_params);486 fmt = find_substream_format(subs, hw_params);
460 if (!fmt) {487 if (!fmt) {
461 usb_audio_dbg(chip,488 usb_audio_dbg(chip,
@@ -469,7 +496,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, · 7 unmodified lines
469 if (fmt->implicit_fb) {496 if (fmt->implicit_fb) {
470 sync_fmt = snd_usb_find_implicit_fb_sync_format(chip, fmt,497 sync_fmt = snd_usb_find_implicit_fb_sync_format(chip, fmt,
471 hw_params,498 hw_params,
472 !substream->stream);499 !substream->stream,
500 &sync_fixed_rate);
473 if (!sync_fmt) {501 if (!sync_fmt) {
474 usb_audio_dbg(chip,502 usb_audio_dbg(chip,
475 "cannot find sync format: ep=0x%x, iface=%d:%d, format=%s, rate=%d, channels=%d\n",503 "cannot find sync format: ep=0x%x, iface=%d:%d, format=%s, rate=%d, channels=%d\n",
@@ -482,6 +510,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, · 6 unmodified lines
482 }510 }
483 } else {511 } else {
484 sync_fmt = fmt;512 sync_fmt = fmt;
513 sync_fixed_rate = fixed_rate;
485 }514 }
486 515
487 ret = snd_usb_lock_shutdown(chip);516 ret = snd_usb_lock_shutdown(chip);
@@ -499,7 +528,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, · 11 unmodified lines
499 close_endpoints(chip, subs);528 close_endpoints(chip, subs);
500 }529 }
501 530
502 subs->data_endpoint = snd_usb_endpoint_open(chip, fmt, hw_params, false);531 subs->data_endpoint = snd_usb_endpoint_open(chip, fmt, hw_params, false, fixed_rate);
503 if (!subs->data_endpoint) {532 if (!subs->data_endpoint) {
504 ret = -EINVAL;533 ret = -EINVAL;
505 goto unlock;534 goto unlock;
@@ -508,7 +537,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, · 2 unmodified lines
508 if (fmt->sync_ep) {537 if (fmt->sync_ep) {
509 subs->sync_endpoint = snd_usb_endpoint_open(chip, sync_fmt,538 subs->sync_endpoint = snd_usb_endpoint_open(chip, sync_fmt,
510 hw_params,539 hw_params,
511 fmt == sync_fmt);540 fmt == sync_fmt,
541 sync_fixed_rate);
512 if (!subs->sync_endpoint) {542 if (!subs->sync_endpoint) {
513 ret = -EINVAL;543 ret = -EINVAL;
514 goto unlock;544 goto unlock;
sound/usb/pcm.h+2−0
@@ -6,6 +6,8 @@ void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream); · 5 unmodified lines
6int snd_usb_pcm_suspend(struct snd_usb_stream *as);6int snd_usb_pcm_suspend(struct snd_usb_stream *as);
7int snd_usb_pcm_resume(struct snd_usb_stream *as);7int snd_usb_pcm_resume(struct snd_usb_stream *as);
8 8
9bool snd_usb_pcm_has_fixed_rate(struct snd_usb_substream *as);
10
9int snd_usb_init_pitch(struct snd_usb_audio *chip,11int snd_usb_init_pitch(struct snd_usb_audio *chip,
10 const struct audioformat *fmt);12 const struct audioformat *fmt);
11void snd_usb_preallocate_buffer(struct snd_usb_substream *subs);13void snd_usb_preallocate_buffer(struct snd_usb_substream *subs);
sound/usb/quirks.c+2−0
@@ -2152,6 +2152,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { · 2151 unmodified lines
2152 QUIRK_FLAG_GENERIC_IMPLICIT_FB),2152 QUIRK_FLAG_GENERIC_IMPLICIT_FB),
2153 DEVICE_FLG(0x0525, 0xa4ad, /* Hamedal C20 usb camero */2153 DEVICE_FLG(0x0525, 0xa4ad, /* Hamedal C20 usb camero */
2154 QUIRK_FLAG_IFACE_SKIP_CLOSE),2154 QUIRK_FLAG_IFACE_SKIP_CLOSE),
2155 DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */
2156 QUIRK_FLAG_FIXED_RATE),
2155 2157
2156 /* Vendor matches */2158 /* Vendor matches */
2157 VENDOR_FLG(0x045e, /* MS Lifecam */2159 VENDOR_FLG(0x045e, /* MS Lifecam */
sound/usb/usbaudio.h+4−0
@@ -175,6 +175,9 @@ extern bool snd_usb_skip_validation; · 174 unmodified lines
175 * QUIRK_FLAG_FORCE_IFACE_RESET175 * QUIRK_FLAG_FORCE_IFACE_RESET
176 * Force an interface reset whenever stopping & restarting a stream176 * Force an interface reset whenever stopping & restarting a stream
177 * (e.g. after xrun)177 * (e.g. after xrun)
178 * QUIRK_FLAG_FIXED_RATE
179 * Do not set PCM rate (frequency) when only one rate is available
180 * for the given endpoint.
178 */181 */
179 182
180#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0)183#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0)
@@ -198,5 +201,6 @@ extern bool snd_usb_skip_validation; · 17 unmodified lines
198#define QUIRK_FLAG_SKIP_IMPLICIT_FB (1U << 18)201#define QUIRK_FLAG_SKIP_IMPLICIT_FB (1U << 18)
199#define QUIRK_FLAG_IFACE_SKIP_CLOSE (1U << 19)202#define QUIRK_FLAG_IFACE_SKIP_CLOSE (1U << 19)
200#define QUIRK_FLAG_FORCE_IFACE_RESET (1U << 20)203#define QUIRK_FLAG_FORCE_IFACE_RESET (1U << 20)
204#define QUIRK_FLAG_FIXED_RATE (1U << 21)
201 205
202#endif /* __USBAUDIO_H */206#endif /* __USBAUDIO_H */