summaryrefslogtreecommitdiff
path: root/sound/usb/pcm.c
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@perex.cz>2022-12-15 16:30:37 +0100
committerTakashi Iwai <tiwai@suse.de>2022-12-22 09:13:54 +0100
commitfd28941cff1cd9d8ffa59fe11eb64148e09b6ed6 (patch)
tree9c0679676244b77031a44dae881298bf3269ab95 /sound/usb/pcm.c
parenta95e163a4bfa7780f64e589bbedc6bdeb7cf3839 (diff)
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>
Diffstat (limited to 'sound/usb/pcm.c')
-rw-r--r--sound/usb/pcm.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 9557bd4d1bbc..99a66d0ef5b2 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -157,6 +157,31 @@ find_substream_format(struct snd_usb_substream *subs,
true, subs);
}
+bool snd_usb_pcm_has_fixed_rate(struct snd_usb_substream *subs)
+{
+ const struct audioformat *fp;
+ struct snd_usb_audio *chip = subs->stream->chip;
+ int rate = -1;
+
+ if (!(chip->quirk_flags & QUIRK_FLAG_FIXED_RATE))
+ return false;
+ list_for_each_entry(fp, &subs->fmt_list, list) {
+ if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)
+ return false;
+ if (fp->nr_rates < 1)
+ continue;
+ if (fp->nr_rates > 1)
+ return false;
+ if (rate < 0) {
+ rate = fp->rate_table[0];
+ continue;
+ }
+ if (rate != fp->rate_table[0])
+ return false;
+ }
+ return true;
+}
+
static int init_pitch_v1(struct snd_usb_audio *chip, int ep)
{
struct usb_device *dev = chip->dev;
@@ -450,12 +475,14 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
struct snd_usb_audio *chip = subs->stream->chip;
const struct audioformat *fmt;
const struct audioformat *sync_fmt;
+ bool fixed_rate, sync_fixed_rate;
int ret;
ret = snd_media_start_pipeline(subs);
if (ret)
return ret;
+ fixed_rate = snd_usb_pcm_has_fixed_rate(subs);
fmt = find_substream_format(subs, hw_params);
if (!fmt) {
usb_audio_dbg(chip,
@@ -469,7 +496,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
if (fmt->implicit_fb) {
sync_fmt = snd_usb_find_implicit_fb_sync_format(chip, fmt,
hw_params,
- !substream->stream);
+ !substream->stream,
+ &sync_fixed_rate);
if (!sync_fmt) {
usb_audio_dbg(chip,
"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,
}
} else {
sync_fmt = fmt;
+ sync_fixed_rate = fixed_rate;
}
ret = snd_usb_lock_shutdown(chip);
@@ -499,7 +528,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
close_endpoints(chip, subs);
}
- subs->data_endpoint = snd_usb_endpoint_open(chip, fmt, hw_params, false);
+ subs->data_endpoint = snd_usb_endpoint_open(chip, fmt, hw_params, false, fixed_rate);
if (!subs->data_endpoint) {
ret = -EINVAL;
goto unlock;
@@ -508,7 +537,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
if (fmt->sync_ep) {
subs->sync_endpoint = snd_usb_endpoint_open(chip, sync_fmt,
hw_params,
- fmt == sync_fmt);
+ fmt == sync_fmt,
+ sync_fixed_rate);
if (!subs->sync_endpoint) {
ret = -EINVAL;
goto unlock;