sound fixes for 5.11-rc5
Here is a collection of sound fixes targeted for 5.11-rc5. Most notably, USB-audio still got a few intensive changes for covering the regressions while the rest are all small fixes. - A trivial fix for sequencer OSS emulation error path - HD-audio runtime PM regression fix, a few quirks and new IDs - USB-audio regression fixes for Pioneer device, Logitech webcams, etc - ASoC SOF Intel coverage - MAINTAINERS file update - A fix in the jack handling in ASoC HDMI codec -----BEGIN PGP SIGNATURE----- iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmAJj6sOHHRpd2FpQHN1 c2UuZGUACgkQLtJE4w1nLE9uSg//cMS9BjlRT63nK6GIpBMY76FHkJT9Layj7AFD DLElEnUslberM+4/UiFtLM3bSaIuOH+BUgTcBgs4tADA/kGHsz/+/idx7aZSMYcP Qh1SbRetNVCcOwT5+tzYJYjMYG2f4RRRUKJ1YTns5w/0p8NCfUSTxGpZbm38rILN 8FuOjRkcR3awCbEYI9q4VbRAbeF7b0WU1JVF1d/eXFdiYWkiZvCZoH9Tl8wgptvF 1ijVemE6mvGh3xpTwxfU1IDfxd9B6vDumIrKvjUJ8L3tuz1sMvaC05nOz1UuFbus uE4B53Jy8/DbzqDbiUmrOVh80qRpp9JMOWgEnYi9ro7QoQHgvVEksuWDmQxhtNhk ogyYMdKhB2zDcZBVHgdK8gWk/gpaH3QeUQwVaFYPEnQJLn/4NxATVr8S+X99Dtix AhKpThRdGwcmnkKPFzvxm63pnl3uqLeB73hCJMC7fB7FAskFr4Bwi8MVJ0ZE95jD /A/oxvKBClt5goi+1EzNXFD371i1u3B/FWcVESVdgt1CZyXR/wSi/zaGgzuk5i/H 9WtEPlqyHNfjsiUbwMnF1nrkZxIimFWrNNpO5cwm8MzDgBQMy/AniOisZBg4AkSD XN0VGQ4ZxtfxBhNJtXJRSYI/JM7cTJ1/J/yDN3toVgCtXxKlxyLe3EcJNFUxpixT j/n+dz4= =r+rh -----END PGP SIGNATURE----- Merge tag 'sound-5.11-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound fixes from Takashi Iwai: "Here is a collection of sound fixes targeted for 5.11-rc5. Most notably, USB-audio still got a few intensive changes for covering the regressions while the rest are all small fixes. - A trivial fix for sequencer OSS emulation error path - HD-audio runtime PM regression fix, a few quirks and new IDs - USB-audio regression fixes for Pioneer device, Logitech webcams, etc - ASoC SOF Intel coverage - MAINTAINERS file update - A fix in the jack handling in ASoC HDMI codec" * tag 'sound-5.11-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: ALSA: usb-audio: Fix hw constraints dependencies ALSA: hda: Balance runtime/system PM if direct-complete is disabled ALSA: usb-audio: Avoid implicit feedback on Pioneer devices ALSA: usb-audio: Set sample rate for all sharing EPs on UAC1 ALSA: usb-audio: Fix UAC1 rate setup for secondary endpoints MAINTAINERS: update qcom ASoC drivers list MAINTAINERS: update maintainers of qcom audio ALSA: hda: Add Cometlake-R PCI ID ALSA: seq: oss: Fix missing error check in snd_seq_oss_synth_make_info() ALSA: hda/via: Add minimum mute flag ALSA: hda/realtek - Limit int mic boost on Acer Aspire E5-575T ALSA: usb-audio: Always apply the hw constraints for implicit fb sync ASoC: SOF: Intel: fix page fault at probe if i915 init fails ALSA: hda: Add AlderLake-P PCI ID and HDMI codec vid ASoC: SOF: Intel: hda: Avoid checking jack on system suspend ASoC: SOF: Intel: hda: Modify existing helper to disable WAKEEN ASoC: SOF: Intel: hda: Resume codec to do jack detection MAINTAINERS: update references to stm32 audio bindings ASoC: hdmi-codec: Fix return value in hdmi_codec_set_jack()
This commit is contained in:
Коммит
120fbdb84f
12
MAINTAINERS
12
MAINTAINERS
|
@ -14504,10 +14504,18 @@ S: Supported
|
|||
F: drivers/crypto/qat/
|
||||
|
||||
QCOM AUDIO (ASoC) DRIVERS
|
||||
M: Patrick Lai <plai@codeaurora.org>
|
||||
M: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
M: Banajit Goswami <bgoswami@codeaurora.org>
|
||||
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||
S: Supported
|
||||
F: sound/soc/codecs/lpass-va-macro.c
|
||||
F: sound/soc/codecs/lpass-wsa-macro.*
|
||||
F: sound/soc/codecs/msm8916-wcd-analog.c
|
||||
F: sound/soc/codecs/msm8916-wcd-digital.c
|
||||
F: sound/soc/codecs/wcd9335.*
|
||||
F: sound/soc/codecs/wcd934x.c
|
||||
F: sound/soc/codecs/wcd-clsh-v2.*
|
||||
F: sound/soc/codecs/wsa881x.c
|
||||
F: sound/soc/qcom/
|
||||
|
||||
QCOM IPA DRIVER
|
||||
|
@ -16959,7 +16967,7 @@ M: Olivier Moysan <olivier.moysan@st.com>
|
|||
M: Arnaud Pouliquen <arnaud.pouliquen@st.com>
|
||||
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/sound/st,stm32-*.txt
|
||||
F: Documentation/devicetree/bindings/iio/adc/st,stm32-*.yaml
|
||||
F: sound/soc/stm/
|
||||
|
||||
STM32 TIMER/LPTIMER DRIVERS
|
||||
|
|
|
@ -611,7 +611,8 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in
|
|||
|
||||
if (info->is_midi) {
|
||||
struct midi_info minf;
|
||||
snd_seq_oss_midi_make_info(dp, info->midi_mapped, &minf);
|
||||
if (snd_seq_oss_midi_make_info(dp, info->midi_mapped, &minf))
|
||||
return -ENXIO;
|
||||
inf->synth_type = SYNTH_TYPE_MIDI;
|
||||
inf->synth_subtype = 0;
|
||||
inf->nr_voices = 16;
|
||||
|
|
|
@ -2934,7 +2934,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
|
|||
snd_hdac_leave_pm(&codec->core);
|
||||
}
|
||||
|
||||
static int hda_codec_suspend(struct device *dev)
|
||||
static int hda_codec_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct hda_codec *codec = dev_to_hda_codec(dev);
|
||||
unsigned int state;
|
||||
|
@ -2953,7 +2953,7 @@ static int hda_codec_suspend(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int hda_codec_resume(struct device *dev)
|
||||
static int hda_codec_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct hda_codec *codec = dev_to_hda_codec(dev);
|
||||
|
||||
|
@ -2968,16 +2968,6 @@ static int hda_codec_resume(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int hda_codec_runtime_suspend(struct device *dev)
|
||||
{
|
||||
return hda_codec_suspend(dev);
|
||||
}
|
||||
|
||||
static int hda_codec_runtime_resume(struct device *dev)
|
||||
{
|
||||
return hda_codec_resume(dev);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
@ -2998,31 +2988,31 @@ static void hda_codec_pm_complete(struct device *dev)
|
|||
static int hda_codec_pm_suspend(struct device *dev)
|
||||
{
|
||||
dev->power.power_state = PMSG_SUSPEND;
|
||||
return hda_codec_suspend(dev);
|
||||
return pm_runtime_force_suspend(dev);
|
||||
}
|
||||
|
||||
static int hda_codec_pm_resume(struct device *dev)
|
||||
{
|
||||
dev->power.power_state = PMSG_RESUME;
|
||||
return hda_codec_resume(dev);
|
||||
return pm_runtime_force_resume(dev);
|
||||
}
|
||||
|
||||
static int hda_codec_pm_freeze(struct device *dev)
|
||||
{
|
||||
dev->power.power_state = PMSG_FREEZE;
|
||||
return hda_codec_suspend(dev);
|
||||
return pm_runtime_force_suspend(dev);
|
||||
}
|
||||
|
||||
static int hda_codec_pm_thaw(struct device *dev)
|
||||
{
|
||||
dev->power.power_state = PMSG_THAW;
|
||||
return hda_codec_resume(dev);
|
||||
return pm_runtime_force_resume(dev);
|
||||
}
|
||||
|
||||
static int hda_codec_pm_restore(struct device *dev)
|
||||
{
|
||||
dev->power.power_state = PMSG_RESTORE;
|
||||
return hda_codec_resume(dev);
|
||||
return pm_runtime_force_resume(dev);
|
||||
}
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
|
|
|
@ -2484,6 +2484,9 @@ static const struct pci_device_id azx_ids[] = {
|
|||
/* CometLake-S */
|
||||
{ PCI_DEVICE(0x8086, 0xa3f0),
|
||||
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
|
||||
/* CometLake-R */
|
||||
{ PCI_DEVICE(0x8086, 0xf0c8),
|
||||
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
|
||||
/* Icelake */
|
||||
{ PCI_DEVICE(0x8086, 0x34c8),
|
||||
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
|
||||
|
@ -2507,6 +2510,9 @@ static const struct pci_device_id azx_ids[] = {
|
|||
/* Alderlake-S */
|
||||
{ PCI_DEVICE(0x8086, 0x7ad0),
|
||||
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
|
||||
/* Alderlake-P */
|
||||
{ PCI_DEVICE(0x8086, 0x51c8),
|
||||
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
|
||||
/* Elkhart Lake */
|
||||
{ PCI_DEVICE(0x8086, 0x4b55),
|
||||
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
|
||||
|
|
|
@ -4346,6 +4346,7 @@ HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI", patch_i915_icl_hdmi),
|
|||
HDA_CODEC_ENTRY(0x80862812, "Tigerlake HDMI", patch_i915_tgl_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862814, "DG1 HDMI", patch_i915_tgl_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862815, "Alderlake HDMI", patch_i915_tgl_hdmi),
|
||||
HDA_CODEC_ENTRY(0x8086281c, "Alderlake-P HDMI", patch_i915_tgl_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862816, "Rocketlake HDMI", patch_i915_tgl_hdmi),
|
||||
HDA_CODEC_ENTRY(0x8086281a, "Jasperlake HDMI", patch_i915_icl_hdmi),
|
||||
HDA_CODEC_ENTRY(0x8086281b, "Elkhartlake HDMI", patch_i915_icl_hdmi),
|
||||
|
|
|
@ -6371,6 +6371,7 @@ enum {
|
|||
ALC256_FIXUP_HP_HEADSET_MIC,
|
||||
ALC236_FIXUP_DELL_AIO_HEADSET_MIC,
|
||||
ALC282_FIXUP_ACER_DISABLE_LINEOUT,
|
||||
ALC255_FIXUP_ACER_LIMIT_INT_MIC_BOOST,
|
||||
};
|
||||
|
||||
static const struct hda_fixup alc269_fixups[] = {
|
||||
|
@ -7808,6 +7809,12 @@ static const struct hda_fixup alc269_fixups[] = {
|
|||
.chained = true,
|
||||
.chain_id = ALC269_FIXUP_HEADSET_MODE
|
||||
},
|
||||
[ALC255_FIXUP_ACER_LIMIT_INT_MIC_BOOST] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc269_fixup_limit_int_mic_boost,
|
||||
.chained = true,
|
||||
.chain_id = ALC255_FIXUP_ACER_MIC_NO_PRESENCE,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
|
@ -7826,6 +7833,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1025, 0x102b, "Acer Aspire C24-860", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1025, 0x1065, "Acer Aspire C20-820", ALC269VC_FIXUP_ACER_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x106d, "Acer Cloudbook 14", ALC283_FIXUP_CHROME_BOOK),
|
||||
SND_PCI_QUIRK(0x1025, 0x1094, "Acer Aspire E5-575T", ALC255_FIXUP_ACER_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x1025, 0x1099, "Acer Aspire E5-523G", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1025, 0x110e, "Acer Aspire ES1-432", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1025, 0x1166, "Acer Veriton N4640G", ALC269_FIXUP_LIFEBOOK),
|
||||
|
|
|
@ -113,6 +113,7 @@ static struct via_spec *via_new_spec(struct hda_codec *codec)
|
|||
spec->codec_type = VT1708S;
|
||||
spec->gen.indep_hp = 1;
|
||||
spec->gen.keep_eapd_on = 1;
|
||||
spec->gen.dac_min_mute = 1;
|
||||
spec->gen.pcm_playback_hook = via_playback_pcm_hook;
|
||||
spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO;
|
||||
codec->power_save_node = 1;
|
||||
|
|
|
@ -717,7 +717,7 @@ static int hdmi_codec_set_jack(struct snd_soc_component *component,
|
|||
void *data)
|
||||
{
|
||||
struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
|
||||
int ret = -EOPNOTSUPP;
|
||||
int ret = -ENOTSUPP;
|
||||
|
||||
if (hcp->hcd.ops->hook_plugged_cb) {
|
||||
hcp->jack = jack;
|
||||
|
|
|
@ -90,7 +90,7 @@ static int imx_hdmi_init(struct snd_soc_pcm_runtime *rtd)
|
|||
}
|
||||
|
||||
ret = snd_soc_component_set_jack(component, &data->hdmi_jack, NULL);
|
||||
if (ret && ret != -EOPNOTSUPP) {
|
||||
if (ret && ret != -ENOTSUPP) {
|
||||
dev_err(card->dev, "Can't set HDMI Jack %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -63,16 +63,18 @@ static int hda_codec_load_module(struct hda_codec *codec)
|
|||
}
|
||||
|
||||
/* enable controller wake up event for all codecs with jack connectors */
|
||||
void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev)
|
||||
void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev, bool enable)
|
||||
{
|
||||
struct hda_bus *hbus = sof_to_hbus(sdev);
|
||||
struct hdac_bus *bus = sof_to_bus(sdev);
|
||||
struct hda_codec *codec;
|
||||
unsigned int mask = 0;
|
||||
|
||||
list_for_each_codec(codec, hbus)
|
||||
if (codec->jacktbl.used)
|
||||
mask |= BIT(codec->core.addr);
|
||||
if (enable) {
|
||||
list_for_each_codec(codec, hbus)
|
||||
if (codec->jacktbl.used)
|
||||
mask |= BIT(codec->core.addr);
|
||||
}
|
||||
|
||||
snd_hdac_chip_updatew(bus, WAKEEN, STATESTS_INT_MASK, mask);
|
||||
}
|
||||
|
@ -81,23 +83,18 @@ void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev)
|
|||
void hda_codec_jack_check(struct snd_sof_dev *sdev)
|
||||
{
|
||||
struct hda_bus *hbus = sof_to_hbus(sdev);
|
||||
struct hdac_bus *bus = sof_to_bus(sdev);
|
||||
struct hda_codec *codec;
|
||||
|
||||
/* disable controller Wake Up event*/
|
||||
snd_hdac_chip_updatew(bus, WAKEEN, STATESTS_INT_MASK, 0);
|
||||
|
||||
list_for_each_codec(codec, hbus)
|
||||
/*
|
||||
* Wake up all jack-detecting codecs regardless whether an event
|
||||
* has been recorded in STATESTS
|
||||
*/
|
||||
if (codec->jacktbl.used)
|
||||
schedule_delayed_work(&codec->jackpoll_work,
|
||||
codec->jackpoll_interval);
|
||||
pm_request_resume(&codec->core.dev);
|
||||
}
|
||||
#else
|
||||
void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev) {}
|
||||
void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev, bool enable) {}
|
||||
void hda_codec_jack_check(struct snd_sof_dev *sdev) {}
|
||||
#endif /* CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC */
|
||||
EXPORT_SYMBOL_NS(hda_codec_jack_wake_enable, SND_SOC_SOF_HDA_AUDIO_CODEC);
|
||||
|
@ -156,7 +153,8 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address,
|
|||
if (!hdev->bus->audio_component) {
|
||||
dev_dbg(sdev->dev,
|
||||
"iDisp hw present but no driver\n");
|
||||
goto error;
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
hda_priv->need_display_power = true;
|
||||
}
|
||||
|
@ -173,24 +171,23 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address,
|
|||
* other return codes without modification
|
||||
*/
|
||||
if (ret == 0)
|
||||
goto error;
|
||||
ret = -ENOENT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
snd_hdac_ext_bus_device_exit(hdev);
|
||||
return -ENOENT;
|
||||
|
||||
out:
|
||||
if (ret < 0) {
|
||||
snd_hdac_device_unregister(hdev);
|
||||
put_device(&hdev->dev);
|
||||
}
|
||||
#else
|
||||
hdev = devm_kzalloc(sdev->dev, sizeof(*hdev), GFP_KERNEL);
|
||||
if (!hdev)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = snd_hdac_ext_bus_device_init(&hbus->core, address, hdev, HDA_DEV_ASOC);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Codec initialization */
|
||||
|
|
|
@ -617,7 +617,7 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend)
|
|||
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
|
||||
if (runtime_suspend)
|
||||
hda_codec_jack_wake_enable(sdev);
|
||||
hda_codec_jack_wake_enable(sdev, true);
|
||||
|
||||
/* power down all hda link */
|
||||
snd_hdac_ext_bus_link_power_down_all(bus);
|
||||
|
@ -683,8 +683,11 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume)
|
|||
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
|
||||
/* check jack status */
|
||||
if (runtime_resume)
|
||||
hda_codec_jack_check(sdev);
|
||||
if (runtime_resume) {
|
||||
hda_codec_jack_wake_enable(sdev, false);
|
||||
if (sdev->system_suspend_target == SOF_SUSPEND_NONE)
|
||||
hda_codec_jack_check(sdev);
|
||||
}
|
||||
|
||||
/* turn off the links that were off before suspend */
|
||||
list_for_each_entry(hlink, &bus->hlink_list, list) {
|
||||
|
|
|
@ -650,7 +650,7 @@ void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev);
|
|||
*/
|
||||
void hda_codec_probe_bus(struct snd_sof_dev *sdev,
|
||||
bool hda_codec_use_common_hdmi);
|
||||
void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev);
|
||||
void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev, bool enable);
|
||||
void hda_codec_jack_check(struct snd_sof_dev *sdev);
|
||||
|
||||
#endif /* CONFIG_SND_SOC_SOF_HDA */
|
||||
|
|
|
@ -485,18 +485,9 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip,
|
|||
const struct audioformat *fmt, int rate)
|
||||
{
|
||||
struct usb_device *dev = chip->dev;
|
||||
struct usb_host_interface *alts;
|
||||
unsigned int ep;
|
||||
unsigned char data[3];
|
||||
int err, crate;
|
||||
|
||||
alts = snd_usb_get_host_interface(chip, fmt->iface, fmt->altsetting);
|
||||
if (!alts)
|
||||
return -EINVAL;
|
||||
if (get_iface_desc(alts)->bNumEndpoints < 1)
|
||||
return -EINVAL;
|
||||
ep = get_endpoint(alts, 0)->bEndpointAddress;
|
||||
|
||||
/* if endpoint doesn't have sampling rate control, bail out */
|
||||
if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE))
|
||||
return 0;
|
||||
|
@ -506,11 +497,11 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip,
|
|||
data[2] = rate >> 16;
|
||||
err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
|
||||
USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
|
||||
UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
|
||||
data, sizeof(data));
|
||||
UAC_EP_CS_ATTR_SAMPLE_RATE << 8,
|
||||
fmt->endpoint, data, sizeof(data));
|
||||
if (err < 0) {
|
||||
dev_err(&dev->dev, "%d:%d: cannot set freq %d to ep %#x\n",
|
||||
fmt->iface, fmt->altsetting, rate, ep);
|
||||
fmt->iface, fmt->altsetting, rate, fmt->endpoint);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -524,11 +515,11 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip,
|
|||
|
||||
err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
|
||||
USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN,
|
||||
UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
|
||||
data, sizeof(data));
|
||||
UAC_EP_CS_ATTR_SAMPLE_RATE << 8,
|
||||
fmt->endpoint, data, sizeof(data));
|
||||
if (err < 0) {
|
||||
dev_err(&dev->dev, "%d:%d: cannot get freq at ep %#x\n",
|
||||
fmt->iface, fmt->altsetting, ep);
|
||||
fmt->iface, fmt->altsetting, fmt->endpoint);
|
||||
chip->sample_rate_read_error++;
|
||||
return 0; /* some devices don't support reading */
|
||||
}
|
||||
|
|
|
@ -1252,6 +1252,15 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
|
|||
|
||||
/* If the interface has been already set up, just set EP parameters */
|
||||
if (!ep->iface_ref->need_setup) {
|
||||
/* sample rate setup of UAC1 is per endpoint, and we need
|
||||
* to update at each EP configuration
|
||||
*/
|
||||
if (ep->cur_audiofmt->protocol == UAC_VERSION_1) {
|
||||
err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt,
|
||||
ep->cur_rate);
|
||||
if (err < 0)
|
||||
goto unlock;
|
||||
}
|
||||
err = snd_usb_endpoint_set_params(chip, ep);
|
||||
if (err < 0)
|
||||
goto unlock;
|
||||
|
|
|
@ -175,11 +175,13 @@ static int add_roland_implicit_fb(struct snd_usb_audio *chip,
|
|||
ifnum, alts);
|
||||
}
|
||||
|
||||
/* Pioneer devices: playback and capture streams sharing the same iface/altset
|
||||
/* Playback and capture EPs on Pioneer devices share the same iface/altset,
|
||||
* but they don't seem working with the implicit fb mode well, hence we
|
||||
* just return as if the sync were already set up.
|
||||
*/
|
||||
static int add_pioneer_implicit_fb(struct snd_usb_audio *chip,
|
||||
struct audioformat *fmt,
|
||||
struct usb_host_interface *alts)
|
||||
static int skip_pioneer_sync_ep(struct snd_usb_audio *chip,
|
||||
struct audioformat *fmt,
|
||||
struct usb_host_interface *alts)
|
||||
{
|
||||
struct usb_endpoint_descriptor *epd;
|
||||
|
||||
|
@ -194,8 +196,7 @@ static int add_pioneer_implicit_fb(struct snd_usb_audio *chip,
|
|||
(epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
|
||||
USB_ENDPOINT_USAGE_IMPLICIT_FB))
|
||||
return 0;
|
||||
return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, 1,
|
||||
alts->desc.bInterfaceNumber, alts);
|
||||
return 1; /* don't handle with the implicit fb, just skip sync EP */
|
||||
}
|
||||
|
||||
static int __add_generic_implicit_fb(struct snd_usb_audio *chip,
|
||||
|
@ -298,11 +299,11 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Pioneer devices implicit feedback with vendor spec class */
|
||||
/* Pioneer devices with vendor spec class */
|
||||
if (attr == USB_ENDPOINT_SYNC_ASYNC &&
|
||||
alts->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
|
||||
USB_ID_VENDOR(chip->usb_id) == 0x2b73 /* Pioneer */) {
|
||||
if (add_pioneer_implicit_fb(chip, fmt, alts))
|
||||
if (skip_pioneer_sync_ep(chip, fmt, alts))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
174
sound/usb/pcm.c
174
sound/usb/pcm.c
|
@ -663,7 +663,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs,
|
|||
check_fmts.bits[1] = (u32)(fp->formats >> 32);
|
||||
snd_mask_intersect(&check_fmts, fmts);
|
||||
if (snd_mask_empty(&check_fmts)) {
|
||||
hwc_debug(" > check: no supported format %d\n", fp->format);
|
||||
hwc_debug(" > check: no supported format 0x%llx\n", fp->formats);
|
||||
return 0;
|
||||
}
|
||||
/* check the channels */
|
||||
|
@ -775,24 +775,11 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params,
|
|||
return apply_hw_params_minmax(it, rmin, rmax);
|
||||
}
|
||||
|
||||
static int hw_rule_format(struct snd_pcm_hw_params *params,
|
||||
struct snd_pcm_hw_rule *rule)
|
||||
static int apply_hw_params_format_bits(struct snd_mask *fmt, u64 fbits)
|
||||
{
|
||||
struct snd_usb_substream *subs = rule->private;
|
||||
const struct audioformat *fp;
|
||||
struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
|
||||
u64 fbits;
|
||||
u32 oldbits[2];
|
||||
int changed;
|
||||
|
||||
hwc_debug("hw_rule_format: %x:%x\n", fmt->bits[0], fmt->bits[1]);
|
||||
fbits = 0;
|
||||
list_for_each_entry(fp, &subs->fmt_list, list) {
|
||||
if (!hw_check_valid_format(subs, params, fp))
|
||||
continue;
|
||||
fbits |= fp->formats;
|
||||
}
|
||||
|
||||
oldbits[0] = fmt->bits[0];
|
||||
oldbits[1] = fmt->bits[1];
|
||||
fmt->bits[0] &= (u32)fbits;
|
||||
|
@ -806,6 +793,24 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
|
|||
return changed;
|
||||
}
|
||||
|
||||
static int hw_rule_format(struct snd_pcm_hw_params *params,
|
||||
struct snd_pcm_hw_rule *rule)
|
||||
{
|
||||
struct snd_usb_substream *subs = rule->private;
|
||||
const struct audioformat *fp;
|
||||
struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
|
||||
u64 fbits;
|
||||
|
||||
hwc_debug("hw_rule_format: %x:%x\n", fmt->bits[0], fmt->bits[1]);
|
||||
fbits = 0;
|
||||
list_for_each_entry(fp, &subs->fmt_list, list) {
|
||||
if (!hw_check_valid_format(subs, params, fp))
|
||||
continue;
|
||||
fbits |= fp->formats;
|
||||
}
|
||||
return apply_hw_params_format_bits(fmt, fbits);
|
||||
}
|
||||
|
||||
static int hw_rule_period_time(struct snd_pcm_hw_params *params,
|
||||
struct snd_pcm_hw_rule *rule)
|
||||
{
|
||||
|
@ -833,64 +838,92 @@ static int hw_rule_period_time(struct snd_pcm_hw_params *params,
|
|||
return apply_hw_params_minmax(it, pmin, UINT_MAX);
|
||||
}
|
||||
|
||||
/* apply PCM hw constraints from the concurrent sync EP */
|
||||
static int apply_hw_constraint_from_sync(struct snd_pcm_runtime *runtime,
|
||||
struct snd_usb_substream *subs)
|
||||
/* get the EP or the sync EP for implicit fb when it's already set up */
|
||||
static const struct snd_usb_endpoint *
|
||||
get_sync_ep_from_substream(struct snd_usb_substream *subs)
|
||||
{
|
||||
struct snd_usb_audio *chip = subs->stream->chip;
|
||||
struct snd_usb_endpoint *ep;
|
||||
const struct audioformat *fp;
|
||||
int err;
|
||||
const struct snd_usb_endpoint *ep;
|
||||
|
||||
list_for_each_entry(fp, &subs->fmt_list, list) {
|
||||
ep = snd_usb_get_endpoint(chip, fp->endpoint);
|
||||
if (ep && ep->cur_rate)
|
||||
goto found;
|
||||
return ep;
|
||||
if (!fp->implicit_fb)
|
||||
continue;
|
||||
/* for the implicit fb, check the sync ep as well */
|
||||
ep = snd_usb_get_endpoint(chip, fp->sync_ep);
|
||||
if (ep && ep->cur_rate)
|
||||
goto found;
|
||||
return ep;
|
||||
}
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
found:
|
||||
if (!find_format(&subs->fmt_list, ep->cur_format, ep->cur_rate,
|
||||
ep->cur_channels, false, NULL)) {
|
||||
usb_audio_dbg(chip, "EP 0x%x being used, but not applicable\n",
|
||||
ep->ep_num);
|
||||
/* additional hw constraints for implicit feedback mode */
|
||||
static int hw_rule_format_implicit_fb(struct snd_pcm_hw_params *params,
|
||||
struct snd_pcm_hw_rule *rule)
|
||||
{
|
||||
struct snd_usb_substream *subs = rule->private;
|
||||
const struct snd_usb_endpoint *ep;
|
||||
struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
|
||||
|
||||
ep = get_sync_ep_from_substream(subs);
|
||||
if (!ep)
|
||||
return 0;
|
||||
}
|
||||
|
||||
usb_audio_dbg(chip, "EP 0x%x being used, using fixed params:\n",
|
||||
ep->ep_num);
|
||||
usb_audio_dbg(chip, "rate=%d, period_size=%d, periods=%d\n",
|
||||
ep->cur_rate, ep->cur_period_frames,
|
||||
ep->cur_buffer_periods);
|
||||
hwc_debug("applying %s\n", __func__);
|
||||
return apply_hw_params_format_bits(fmt, pcm_format_to_bits(ep->cur_format));
|
||||
}
|
||||
|
||||
runtime->hw.formats = subs->formats;
|
||||
runtime->hw.rate_min = runtime->hw.rate_max = ep->cur_rate;
|
||||
runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
|
||||
runtime->hw.periods_min = runtime->hw.periods_max =
|
||||
ep->cur_buffer_periods;
|
||||
static int hw_rule_rate_implicit_fb(struct snd_pcm_hw_params *params,
|
||||
struct snd_pcm_hw_rule *rule)
|
||||
{
|
||||
struct snd_usb_substream *subs = rule->private;
|
||||
const struct snd_usb_endpoint *ep;
|
||||
struct snd_interval *it;
|
||||
|
||||
err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||
hw_rule_channels, subs,
|
||||
SNDRV_PCM_HW_PARAM_FORMAT,
|
||||
SNDRV_PCM_HW_PARAM_RATE,
|
||||
-1);
|
||||
if (err < 0)
|
||||
return err;
|
||||
ep = get_sync_ep_from_substream(subs);
|
||||
if (!ep)
|
||||
return 0;
|
||||
|
||||
err = snd_pcm_hw_constraint_minmax(runtime,
|
||||
SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
|
||||
ep->cur_period_frames,
|
||||
ep->cur_period_frames);
|
||||
if (err < 0)
|
||||
return err;
|
||||
hwc_debug("applying %s\n", __func__);
|
||||
it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
|
||||
return apply_hw_params_minmax(it, ep->cur_rate, ep->cur_rate);
|
||||
}
|
||||
|
||||
return 1; /* notify the finding */
|
||||
static int hw_rule_period_size_implicit_fb(struct snd_pcm_hw_params *params,
|
||||
struct snd_pcm_hw_rule *rule)
|
||||
{
|
||||
struct snd_usb_substream *subs = rule->private;
|
||||
const struct snd_usb_endpoint *ep;
|
||||
struct snd_interval *it;
|
||||
|
||||
ep = get_sync_ep_from_substream(subs);
|
||||
if (!ep)
|
||||
return 0;
|
||||
|
||||
hwc_debug("applying %s\n", __func__);
|
||||
it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
|
||||
return apply_hw_params_minmax(it, ep->cur_period_frames,
|
||||
ep->cur_period_frames);
|
||||
}
|
||||
|
||||
static int hw_rule_periods_implicit_fb(struct snd_pcm_hw_params *params,
|
||||
struct snd_pcm_hw_rule *rule)
|
||||
{
|
||||
struct snd_usb_substream *subs = rule->private;
|
||||
const struct snd_usb_endpoint *ep;
|
||||
struct snd_interval *it;
|
||||
|
||||
ep = get_sync_ep_from_substream(subs);
|
||||
if (!ep)
|
||||
return 0;
|
||||
|
||||
hwc_debug("applying %s\n", __func__);
|
||||
it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIODS);
|
||||
return apply_hw_params_minmax(it, ep->cur_buffer_periods,
|
||||
ep->cur_buffer_periods);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -899,20 +932,11 @@ static int apply_hw_constraint_from_sync(struct snd_pcm_runtime *runtime,
|
|||
|
||||
static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substream *subs)
|
||||
{
|
||||
struct snd_usb_audio *chip = subs->stream->chip;
|
||||
const struct audioformat *fp;
|
||||
unsigned int pt, ptmin;
|
||||
int param_period_time_if_needed = -1;
|
||||
int err;
|
||||
|
||||
mutex_lock(&chip->mutex);
|
||||
err = apply_hw_constraint_from_sync(runtime, subs);
|
||||
mutex_unlock(&chip->mutex);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (err > 0) /* found the matching? */
|
||||
goto add_extra_rules;
|
||||
|
||||
runtime->hw.formats = subs->formats;
|
||||
|
||||
runtime->hw.rate_min = 0x7fffffff;
|
||||
|
@ -957,6 +981,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
|
|||
|
||||
err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
|
||||
hw_rule_rate, subs,
|
||||
SNDRV_PCM_HW_PARAM_RATE,
|
||||
SNDRV_PCM_HW_PARAM_FORMAT,
|
||||
SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||
param_period_time_if_needed,
|
||||
|
@ -964,9 +989,9 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
add_extra_rules:
|
||||
err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||
hw_rule_channels, subs,
|
||||
SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||
SNDRV_PCM_HW_PARAM_FORMAT,
|
||||
SNDRV_PCM_HW_PARAM_RATE,
|
||||
param_period_time_if_needed,
|
||||
|
@ -975,6 +1000,7 @@ add_extra_rules:
|
|||
return err;
|
||||
err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
|
||||
hw_rule_format, subs,
|
||||
SNDRV_PCM_HW_PARAM_FORMAT,
|
||||
SNDRV_PCM_HW_PARAM_RATE,
|
||||
SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||
param_period_time_if_needed,
|
||||
|
@ -993,6 +1019,28 @@ add_extra_rules:
|
|||
return err;
|
||||
}
|
||||
|
||||
/* additional hw constraints for implicit fb */
|
||||
err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
|
||||
hw_rule_format_implicit_fb, subs,
|
||||
SNDRV_PCM_HW_PARAM_FORMAT, -1);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
|
||||
hw_rule_rate_implicit_fb, subs,
|
||||
SNDRV_PCM_HW_PARAM_RATE, -1);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
|
||||
hw_rule_period_size_implicit_fb, subs,
|
||||
SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS,
|
||||
hw_rule_periods_implicit_fb, subs,
|
||||
SNDRV_PCM_HW_PARAM_PERIODS, -1);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1470,30 +1470,6 @@ static void set_format_emu_quirk(struct snd_usb_substream *subs,
|
|||
subs->pkt_offset_adj = (emu_samplerate_id >= EMU_QUIRK_SR_176400HZ) ? 4 : 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Pioneer DJ DJM-900NXS2
|
||||
* Device needs to know the sample rate each time substream is started
|
||||
*/
|
||||
static int pioneer_djm_set_format_quirk(struct snd_usb_substream *subs)
|
||||
{
|
||||
unsigned int cur_rate = subs->data_endpoint->cur_rate;
|
||||
/* Convert sample rate value to little endian */
|
||||
u8 sr[3];
|
||||
|
||||
sr[0] = cur_rate & 0xff;
|
||||
sr[1] = (cur_rate >> 8) & 0xff;
|
||||
sr[2] = (cur_rate >> 16) & 0xff;
|
||||
|
||||
/* Configure device */
|
||||
usb_set_interface(subs->dev, 0, 1);
|
||||
snd_usb_ctl_msg(subs->stream->chip->dev,
|
||||
usb_rcvctrlpipe(subs->stream->chip->dev, 0),
|
||||
0x01, 0x22, 0x0100, 0x0082, &sr, 0x0003);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
|
||||
const struct audioformat *fmt)
|
||||
{
|
||||
|
@ -1504,10 +1480,6 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
|
|||
case USB_ID(0x041e, 0x3f19): /* E-Mu 0204 USB */
|
||||
set_format_emu_quirk(subs, fmt);
|
||||
break;
|
||||
case USB_ID(0x2b73, 0x000a): /* Pioneer DJ DJM-900NXS2 */
|
||||
case USB_ID(0x2b73, 0x0017): /* Pioneer DJ DJM-250MK2 */
|
||||
pioneer_djm_set_format_quirk(subs);
|
||||
break;
|
||||
case USB_ID(0x534d, 0x2109): /* MacroSilicon MS2109 */
|
||||
subs->stream_offset_adj = 2;
|
||||
break;
|
||||
|
|
Загрузка…
Ссылка в новой задаче