Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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).

BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=216798
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Link: https://lore.kernel.org/r/20221215153037.1163786-1-perex@perex.cz
Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by

Jaroslav Kysela and committed by
Takashi Iwai
fd28941c a95e163a

+60 -12
+1
sound/usb/card.h
··· 131 131 bool lowlatency_playback; /* low-latency playback mode */ 132 132 bool need_setup; /* (re-)need for hw_params? */ 133 133 bool need_prepare; /* (re-)need for prepare? */ 134 + bool fixed_rate; /* skip rate setup */ 134 135 135 136 /* for hw constraints */ 136 137 const struct audioformat *cur_audiofmt;
+10 -6
sound/usb/endpoint.c
··· 769 769 snd_usb_endpoint_open(struct snd_usb_audio *chip, 770 770 const struct audioformat *fp, 771 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 775 struct snd_usb_endpoint *ep; 775 776 int ep_num = is_sync_ep ? fp->sync_ep : fp->endpoint; ··· 826 825 ep->implicit_fb_sync = fp->implicit_fb; 827 826 ep->need_setup = true; 828 827 ep->need_prepare = true; 828 + ep->fixed_rate = fixed_rate; 829 829 830 830 usb_audio_dbg(chip, " channels=%d, rate=%d, format=%s, period_bytes=%d, periods=%d, implicit_fb=%d\n", 831 831 ep->cur_channels, ep->cur_rate, ··· 1415 1413 if (clock && !clock->need_setup) 1416 1414 return 0; 1417 1415 1418 - err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, rate); 1419 - if (err < 0) { 1420 - if (clock) 1421 - clock->rate = 0; /* reset rate */ 1422 - return err; 1416 + if (!ep->fixed_rate) { 1417 + err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, rate); 1418 + if (err < 0) { 1419 + if (clock) 1420 + clock->rate = 0; /* reset rate */ 1421 + return err; 1422 + } 1423 1423 } 1424 1424 1425 1425 if (clock)
+2 -1
sound/usb/endpoint.h
··· 14 14 snd_usb_endpoint_open(struct snd_usb_audio *chip, 15 15 const struct audioformat *fp, 16 16 const struct snd_pcm_hw_params *params, 17 - bool is_sync_ep); 17 + bool is_sync_ep, 18 + bool fixed_rate); 18 19 void snd_usb_endpoint_close(struct snd_usb_audio *chip, 19 20 struct snd_usb_endpoint *ep); 20 21 int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
+5 -1
sound/usb/implicit.c
··· 15 15 #include "usbaudio.h" 16 16 #include "card.h" 17 17 #include "helper.h" 18 + #include "pcm.h" 18 19 #include "implicit.h" 19 20 20 21 enum { ··· 456 455 snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip, 457 456 const struct audioformat *target, 458 457 const struct snd_pcm_hw_params *params, 459 - int stream) 458 + int stream, 459 + bool *fixed_rate) 460 460 { 461 461 struct snd_usb_substream *subs; 462 462 const struct audioformat *fp, *sync_fmt = NULL; ··· 485 483 } 486 484 } 487 485 486 + if (fixed_rate) 487 + *fixed_rate = snd_usb_pcm_has_fixed_rate(subs); 488 488 return sync_fmt; 489 489 } 490 490
+1 -1
sound/usb/implicit.h
··· 9 9 snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip, 10 10 const struct audioformat *target, 11 11 const struct snd_pcm_hw_params *params, 12 - int stream); 12 + int stream, bool *fixed_rate); 13 13 14 14 #endif /* __USBAUDIO_IMPLICIT_H */
+33 -3
sound/usb/pcm.c
··· 157 157 true, subs); 158 158 } 159 159 160 + bool 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 + 160 185 static int init_pitch_v1(struct snd_usb_audio *chip, int ep) 161 186 { 162 187 struct usb_device *dev = chip->dev; ··· 475 450 struct snd_usb_audio *chip = subs->stream->chip; 476 451 const struct audioformat *fmt; 477 452 const struct audioformat *sync_fmt; 453 + bool fixed_rate, sync_fixed_rate; 478 454 int ret; 479 455 480 456 ret = snd_media_start_pipeline(subs); 481 457 if (ret) 482 458 return ret; 483 459 460 + fixed_rate = snd_usb_pcm_has_fixed_rate(subs); 484 461 fmt = find_substream_format(subs, hw_params); 485 462 if (!fmt) { 486 463 usb_audio_dbg(chip, ··· 496 469 if (fmt->implicit_fb) { 497 470 sync_fmt = snd_usb_find_implicit_fb_sync_format(chip, fmt, 498 471 hw_params, 499 - !substream->stream); 472 + !substream->stream, 473 + &sync_fixed_rate); 500 474 if (!sync_fmt) { 501 475 usb_audio_dbg(chip, 502 476 "cannot find sync format: ep=0x%x, iface=%d:%d, format=%s, rate=%d, channels=%d\n", ··· 510 482 } 511 483 } else { 512 484 sync_fmt = fmt; 485 + sync_fixed_rate = fixed_rate; 513 486 } 514 487 515 488 ret = snd_usb_lock_shutdown(chip); ··· 528 499 close_endpoints(chip, subs); 529 500 } 530 501 531 - subs->data_endpoint = snd_usb_endpoint_open(chip, fmt, hw_params, false); 502 + subs->data_endpoint = snd_usb_endpoint_open(chip, fmt, hw_params, false, fixed_rate); 532 503 if (!subs->data_endpoint) { 533 504 ret = -EINVAL; 534 505 goto unlock; ··· 537 508 if (fmt->sync_ep) { 538 509 subs->sync_endpoint = snd_usb_endpoint_open(chip, sync_fmt, 539 510 hw_params, 540 - fmt == sync_fmt); 511 + fmt == sync_fmt, 512 + sync_fixed_rate); 541 513 if (!subs->sync_endpoint) { 542 514 ret = -EINVAL; 543 515 goto unlock;
+2
sound/usb/pcm.h
··· 6 6 int snd_usb_pcm_suspend(struct snd_usb_stream *as); 7 7 int snd_usb_pcm_resume(struct snd_usb_stream *as); 8 8 9 + bool snd_usb_pcm_has_fixed_rate(struct snd_usb_substream *as); 10 + 9 11 int snd_usb_init_pitch(struct snd_usb_audio *chip, 10 12 const struct audioformat *fmt); 11 13 void snd_usb_preallocate_buffer(struct snd_usb_substream *subs);
+2
sound/usb/quirks.c
··· 2152 2152 QUIRK_FLAG_GENERIC_IMPLICIT_FB), 2153 2153 DEVICE_FLG(0x0525, 0xa4ad, /* Hamedal C20 usb camero */ 2154 2154 QUIRK_FLAG_IFACE_SKIP_CLOSE), 2155 + DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */ 2156 + QUIRK_FLAG_FIXED_RATE), 2155 2157 2156 2158 /* Vendor matches */ 2157 2159 VENDOR_FLG(0x045e, /* MS Lifecam */
+4
sound/usb/usbaudio.h
··· 175 175 * QUIRK_FLAG_FORCE_IFACE_RESET 176 176 * Force an interface reset whenever stopping & restarting a stream 177 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 183 #define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0) ··· 201 198 #define QUIRK_FLAG_SKIP_IMPLICIT_FB (1U << 18) 202 199 #define QUIRK_FLAG_IFACE_SKIP_CLOSE (1U << 19) 203 200 #define QUIRK_FLAG_FORCE_IFACE_RESET (1U << 20) 201 + #define QUIRK_FLAG_FIXED_RATE (1U << 21) 204 202 205 203 #endif /* __USBAUDIO_H */