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).
Unified · Split
| @@ -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; |
| @@ -769,7 +769,8 @@ struct snd_usb_endpoint * · 768 unmodified lines | |||
| 769 | snd_usb_endpoint_open(struct snd_usb_audio *chip, | 769 | snd_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) |
| @@ -14,7 +14,8 @@ struct snd_usb_endpoint * · 13 unmodified lines | |||
| 14 | snd_usb_endpoint_open(struct snd_usb_audio *chip, | 14 | snd_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); | ||
| 18 | void snd_usb_endpoint_close(struct snd_usb_audio *chip, | 19 | void snd_usb_endpoint_close(struct snd_usb_audio *chip, |
| 19 | struct snd_usb_endpoint *ep); | 20 | struct snd_usb_endpoint *ep); |
| 20 | int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, | 21 | int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, |
| @@ -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 | ||
| 20 | enum { | 21 | enum { |
| @@ -455,7 +456,8 @@ const struct audioformat * · 434 unmodified lines | |||
| 455 | snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip, | 456 | snd_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 | ||
| @@ -9,6 +9,6 @@ const struct audioformat * · 8 unmodified lines | |||
| 9 | snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip, | 9 | snd_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 */ |
| @@ -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 | ||
| 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 | static int init_pitch_v1(struct snd_usb_audio *chip, int ep) | 185 | static 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; |
| @@ -6,6 +6,8 @@ void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream); · 5 unmodified lines | |||
| 6 | int snd_usb_pcm_suspend(struct snd_usb_stream *as); | 6 | int snd_usb_pcm_suspend(struct snd_usb_stream *as); |
| 7 | int snd_usb_pcm_resume(struct snd_usb_stream *as); | 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 | int snd_usb_init_pitch(struct snd_usb_audio *chip, | 11 | int snd_usb_init_pitch(struct snd_usb_audio *chip, |
| 10 | const struct audioformat *fmt); | 12 | const struct audioformat *fmt); |
| 11 | void snd_usb_preallocate_buffer(struct snd_usb_substream *subs); | 13 | void snd_usb_preallocate_buffer(struct snd_usb_substream *subs); |
| @@ -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 */ |
| @@ -175,6 +175,9 @@ extern bool snd_usb_skip_validation; · 174 unmodified lines | |||
| 175 | * QUIRK_FLAG_FORCE_IFACE_RESET | 175 | * QUIRK_FLAG_FORCE_IFACE_RESET |
| 176 | * Force an interface reset whenever stopping & restarting a stream | 176 | * 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 */ |