Skip to content

Commit fd28941

Browse files
perexgtiwai
authored andcommitted
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent a95e163 commit fd28941

File tree

9 files changed

+60
-12
lines changed

9 files changed

+60
-12
lines changed

sound/usb/card.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ struct snd_usb_endpoint {
131131
bool lowlatency_playback; /* low-latency playback mode */
132132
bool need_setup; /* (re-)need for hw_params? */
133133
bool need_prepare; /* (re-)need for prepare? */
134+
bool fixed_rate; /* skip rate setup */
134135

135136
/* for hw constraints */
136137
const struct audioformat *cur_audiofmt;

sound/usb/endpoint.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,8 @@ struct snd_usb_endpoint *
769769
snd_usb_endpoint_open(struct snd_usb_audio *chip,
770770
const struct audioformat *fp,
771771
const struct snd_pcm_hw_params *params,
772-
bool is_sync_ep)
772+
bool is_sync_ep,
773+
bool fixed_rate)
773774
{
774775
struct snd_usb_endpoint *ep;
775776
int ep_num = is_sync_ep ? fp->sync_ep : fp->endpoint;
@@ -825,6 +826,7 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
825826
ep->implicit_fb_sync = fp->implicit_fb;
826827
ep->need_setup = true;
827828
ep->need_prepare = true;
829+
ep->fixed_rate = fixed_rate;
828830

829831
usb_audio_dbg(chip, " channels=%d, rate=%d, format=%s, period_bytes=%d, periods=%d, implicit_fb=%d\n",
830832
ep->cur_channels, ep->cur_rate,
@@ -1413,11 +1415,13 @@ static int init_sample_rate(struct snd_usb_audio *chip,
14131415
if (clock && !clock->need_setup)
14141416
return 0;
14151417

1416-
err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, rate);
1417-
if (err < 0) {
1418-
if (clock)
1419-
clock->rate = 0; /* reset rate */
1420-
return err;
1418+
if (!ep->fixed_rate) {
1419+
err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, rate);
1420+
if (err < 0) {
1421+
if (clock)
1422+
clock->rate = 0; /* reset rate */
1423+
return err;
1424+
}
14211425
}
14221426

14231427
if (clock)

sound/usb/endpoint.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ struct snd_usb_endpoint *
1414
snd_usb_endpoint_open(struct snd_usb_audio *chip,
1515
const struct audioformat *fp,
1616
const struct snd_pcm_hw_params *params,
17-
bool is_sync_ep);
17+
bool is_sync_ep,
18+
bool fixed_rate);
1819
void snd_usb_endpoint_close(struct snd_usb_audio *chip,
1920
struct snd_usb_endpoint *ep);
2021
int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,

sound/usb/implicit.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "usbaudio.h"
1616
#include "card.h"
1717
#include "helper.h"
18+
#include "pcm.h"
1819
#include "implicit.h"
1920

2021
enum {
@@ -455,7 +456,8 @@ const struct audioformat *
455456
snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,
456457
const struct audioformat *target,
457458
const struct snd_pcm_hw_params *params,
458-
int stream)
459+
int stream,
460+
bool *fixed_rate)
459461
{
460462
struct snd_usb_substream *subs;
461463
const struct audioformat *fp, *sync_fmt = NULL;
@@ -483,6 +485,8 @@ snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,
483485
}
484486
}
485487

488+
if (fixed_rate)
489+
*fixed_rate = snd_usb_pcm_has_fixed_rate(subs);
486490
return sync_fmt;
487491
}
488492

sound/usb/implicit.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ const struct audioformat *
99
snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,
1010
const struct audioformat *target,
1111
const struct snd_pcm_hw_params *params,
12-
int stream);
12+
int stream, bool *fixed_rate);
1313

1414
#endif /* __USBAUDIO_IMPLICIT_H */

sound/usb/pcm.c

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,31 @@ find_substream_format(struct snd_usb_substream *subs,
157157
true, subs);
158158
}
159159

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+
160185
static int init_pitch_v1(struct snd_usb_audio *chip, int ep)
161186
{
162187
struct usb_device *dev = chip->dev;
@@ -450,12 +475,14 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
450475
struct snd_usb_audio *chip = subs->stream->chip;
451476
const struct audioformat *fmt;
452477
const struct audioformat *sync_fmt;
478+
bool fixed_rate, sync_fixed_rate;
453479
int ret;
454480

455481
ret = snd_media_start_pipeline(subs);
456482
if (ret)
457483
return ret;
458484

485+
fixed_rate = snd_usb_pcm_has_fixed_rate(subs);
459486
fmt = find_substream_format(subs, hw_params);
460487
if (!fmt) {
461488
usb_audio_dbg(chip,
@@ -469,7 +496,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
469496
if (fmt->implicit_fb) {
470497
sync_fmt = snd_usb_find_implicit_fb_sync_format(chip, fmt,
471498
hw_params,
472-
!substream->stream);
499+
!substream->stream,
500+
&sync_fixed_rate);
473501
if (!sync_fmt) {
474502
usb_audio_dbg(chip,
475503
"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,
482510
}
483511
} else {
484512
sync_fmt = fmt;
513+
sync_fixed_rate = fixed_rate;
485514
}
486515

487516
ret = snd_usb_lock_shutdown(chip);
@@ -499,7 +528,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
499528
close_endpoints(chip, subs);
500529
}
501530

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);
503532
if (!subs->data_endpoint) {
504533
ret = -EINVAL;
505534
goto unlock;
@@ -508,7 +537,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
508537
if (fmt->sync_ep) {
509538
subs->sync_endpoint = snd_usb_endpoint_open(chip, sync_fmt,
510539
hw_params,
511-
fmt == sync_fmt);
540+
fmt == sync_fmt,
541+
sync_fixed_rate);
512542
if (!subs->sync_endpoint) {
513543
ret = -EINVAL;
514544
goto unlock;

sound/usb/pcm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream);
66
int snd_usb_pcm_suspend(struct snd_usb_stream *as);
77
int snd_usb_pcm_resume(struct snd_usb_stream *as);
88

9+
bool snd_usb_pcm_has_fixed_rate(struct snd_usb_substream *as);
10+
911
int snd_usb_init_pitch(struct snd_usb_audio *chip,
1012
const struct audioformat *fmt);
1113
void snd_usb_preallocate_buffer(struct snd_usb_substream *subs);

sound/usb/quirks.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2152,6 +2152,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
21522152
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
21532153
DEVICE_FLG(0x0525, 0xa4ad, /* Hamedal C20 usb camero */
21542154
QUIRK_FLAG_IFACE_SKIP_CLOSE),
2155+
DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */
2156+
QUIRK_FLAG_FIXED_RATE),
21552157

21562158
/* Vendor matches */
21572159
VENDOR_FLG(0x045e, /* MS Lifecam */

sound/usb/usbaudio.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,9 @@ extern bool snd_usb_skip_validation;
175175
* QUIRK_FLAG_FORCE_IFACE_RESET
176176
* Force an interface reset whenever stopping & restarting a stream
177177
* (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.
178181
*/
179182

180183
#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0)
@@ -198,5 +201,6 @@ extern bool snd_usb_skip_validation;
198201
#define QUIRK_FLAG_SKIP_IMPLICIT_FB (1U << 18)
199202
#define QUIRK_FLAG_IFACE_SKIP_CLOSE (1U << 19)
200203
#define QUIRK_FLAG_FORCE_IFACE_RESET (1U << 20)
204+
#define QUIRK_FLAG_FIXED_RATE (1U << 21)
201205

202206
#endif /* __USBAUDIO_H */

0 commit comments

Comments
 (0)