mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 04:18:39 +08:00
sound fixes for 6.2-rc4
This became a slightly big update, but it's more or less expected, as the first batch after holidays. All changes (but for the last two last-minute fixes) have been stewed in linux-next long enough, so it's fairly safe to take. - PCM UAF fix in 32bit compat layer - ASoC board-specific fixes for Intel, AMD, Medathek, Qualcomm - SOF power management fixes - ASoC Intel link failure fixes - A series of fixes for USB-audio regressions - CS35L41 HD-audio codec regression fixes - HD-audio device-specific fixes / quirks Note that one SPI patch has been taken in ASoC subtree mistakenly, and the same fix is found in spi tree, but it should be OK to apply. -----BEGIN PGP SIGNATURE----- iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmPBZIsOHHRpd2FpQHN1 c2UuZGUACgkQLtJE4w1nLE/LEQ//XLbjI0EnjdpBgYRMocykaI2Y3n+72rncfTwQ FX8mtGtVpBsOp6LCQhJX/0A5B+NcBRk1atyJRsuaAuWxC298jZPMQaSBjlHiP56f 3IcV67gBM5Ve3JwttjF3AtveQPHe+pYh0RRy9HHd4qEEPpO+JdTwHbex+5Xnf3Qq jLDPwtrC5fd/Q38mfs881yoRLmnq3OppHJ630SklJBmdjuvVjHhXinOaDY5KBR42 /ewf946RKJFUpz0w72Hl4Kaw6kQ1HWb2kef+RZmdSp49EmUXyVmi9mxSSBJlDV0f QueZlvcZj+Hm6cAw1Kt6pSpShDJO/LwuCuRTaiprBYq+SbCSxaq2mWz0vzyGx8un U9QmLK4FRtPsZm3SPfVfDpROXc7ovydMOvOzFF6uRou/UdJZLnQYXmFTV5gphREa jSaekWqQhrV53LTYBFn38PDfq+xLEeBx7VsYBOLUHyR7QX2rdpRpLc9XJkgLy5tJ xozwrQFNdAvynfPGwBPBUAuWQOvRnuj0W9QIUmA4U2mxwvCbNGJETkI46/Wzixx0 C7n6JA6bc8rBsWHWXefGaabUaCqnBrPKxVqThYLJy05FUh58SP85Xo+k780CRQT7 tLMw2P7sJ1KKlvrVrmCqA2DlsraRT2pBcQEghKmfgded31/3PxAylhPuNO+E1QxP Eq2uo2g= =PKWN -----END PGP SIGNATURE----- Merge tag 'sound-6.2-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound fixes from Takashi Iwai: "This became a slightly big update, but it's more or less expected, as the first batch after holidays. All changes (but for the last two last-minute fixes) have been stewed in linux-next long enough, so it's fairly safe to take: - PCM UAF fix in 32bit compat layer - ASoC board-specific fixes for Intel, AMD, Medathek, Qualcomm - SOF power management fixes - ASoC Intel link failure fixes - A series of fixes for USB-audio regressions - CS35L41 HD-audio codec regression fixes - HD-audio device-specific fixes / quirks Note that one SPI patch has been taken in ASoC subtree mistakenly, and the same fix is found in spi tree, but it should be OK to apply" * tag 'sound-6.2-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (39 commits) ALSA: pcm: Move rwsem lock inside snd_ctl_elem_read to prevent UAF ALSA: usb-audio: Fix possible NULL pointer dereference in snd_usb_pcm_has_fixed_rate() ALSA: hda/realtek: Enable mute/micmute LEDs on HP Spectre x360 13-aw0xxx ASoC: fsl-asoc-card: Fix naming of AC'97 CODEC widgets ASoC: fsl_ssi: Rename AC'97 streams to avoid collisions with AC'97 CODEC ALSA: hda/hdmi: Add a HP device 0x8715 to force connect list ALSA: control-led: use strscpy in set_led_id() ALSA: usb-audio: Always initialize fixed_rate in snd_usb_find_implicit_fb_sync_format() ASoC: dt-bindings: qcom,lpass-tx-macro: correct clocks on SC7280 ASoC: dt-bindings: qcom,lpass-wsa-macro: correct clocks on SM8250 ASoC: qcom: Fix building APQ8016 machine driver without SOUNDWIRE ALSA: hda: cs35l41: Check runtime suspend capability at runtime_idle ALSA: hda: cs35l41: Don't return -EINVAL from system suspend/resume ASoC: fsl_micfil: Correct the number of steps on SX controls ALSA: hda/realtek: fix mute/micmute LEDs don't work for a HP platform Revert "ALSA: usb-audio: Drop superfluous interface setup at parsing" ALSA: usb-audio: More refactoring of hw constraint rules ALSA: usb-audio: Relax hw constraints for implicit fb sync ALSA: usb-audio: Make sure to stop endpoints before closing EPs ALSA: hda - Enable headset mic on another Dell laptop with ALC3254 ...
This commit is contained in:
commit
689968db7b
@ -16,6 +16,7 @@ properties:
|
||||
compatible:
|
||||
enum:
|
||||
- mediatek,mt8186-mt6366-rt1019-rt5682s-sound
|
||||
- mediatek,mt8186-mt6366-rt5682s-max98360-sound
|
||||
|
||||
mediatek,platform:
|
||||
$ref: "/schemas/types.yaml#/definitions/phandle"
|
||||
|
@ -30,7 +30,9 @@ properties:
|
||||
const: 0
|
||||
|
||||
clocks:
|
||||
maxItems: 5
|
||||
oneOf:
|
||||
- maxItems: 3
|
||||
- maxItems: 5
|
||||
|
||||
clock-names:
|
||||
oneOf:
|
||||
|
@ -9,9 +9,6 @@ title: LPASS(Low Power Audio Subsystem) VA Macro audio codec
|
||||
maintainers:
|
||||
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
@ -30,15 +27,12 @@ properties:
|
||||
const: 0
|
||||
|
||||
clocks:
|
||||
maxItems: 5
|
||||
minItems: 5
|
||||
maxItems: 6
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: mclk
|
||||
- const: npl
|
||||
- const: macro
|
||||
- const: dcodec
|
||||
- const: fsgen
|
||||
minItems: 5
|
||||
maxItems: 6
|
||||
|
||||
clock-output-names:
|
||||
maxItems: 1
|
||||
@ -55,10 +49,51 @@ required:
|
||||
- reg
|
||||
- "#sound-dai-cells"
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,sc7280-lpass-wsa-macro
|
||||
- qcom,sm8450-lpass-wsa-macro
|
||||
- qcom,sc8280xp-lpass-wsa-macro
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 5
|
||||
clock-names:
|
||||
items:
|
||||
- const: mclk
|
||||
- const: npl
|
||||
- const: macro
|
||||
- const: dcodec
|
||||
- const: fsgen
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,sm8250-lpass-wsa-macro
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 6
|
||||
clock-names:
|
||||
items:
|
||||
- const: mclk
|
||||
- const: npl
|
||||
- const: macro
|
||||
- const: dcodec
|
||||
- const: va
|
||||
- const: fsgen
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,sm8250-lpass-aoncc.h>
|
||||
#include <dt-bindings/sound/qcom,q6afe.h>
|
||||
codec@3240000 {
|
||||
compatible = "qcom,sm8250-lpass-wsa-macro";
|
||||
@ -69,7 +104,8 @@ examples:
|
||||
<&audiocc 0>,
|
||||
<&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
|
||||
<&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
|
||||
<&aoncc LPASS_CDC_VA_MCLK>,
|
||||
<&vamacro>;
|
||||
clock-names = "mclk", "npl", "macro", "dcodec", "fsgen";
|
||||
clock-names = "mclk", "npl", "macro", "dcodec", "va", "fsgen";
|
||||
clock-output-names = "mclk";
|
||||
};
|
||||
|
@ -1203,14 +1203,19 @@ static int snd_ctl_elem_read(struct snd_card *card,
|
||||
const u32 pattern = 0xdeadbeef;
|
||||
int ret;
|
||||
|
||||
down_read(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id(card, &control->id);
|
||||
if (kctl == NULL)
|
||||
return -ENOENT;
|
||||
if (kctl == NULL) {
|
||||
ret = -ENOENT;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
index_offset = snd_ctl_get_ioff(kctl, &control->id);
|
||||
vd = &kctl->vd[index_offset];
|
||||
if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_READ) || kctl->get == NULL)
|
||||
return -EPERM;
|
||||
if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_READ) || kctl->get == NULL) {
|
||||
ret = -EPERM;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
snd_ctl_build_ioff(&control->id, kctl, index_offset);
|
||||
|
||||
@ -1220,7 +1225,7 @@ static int snd_ctl_elem_read(struct snd_card *card,
|
||||
info.id = control->id;
|
||||
ret = __snd_ctl_elem_info(card, kctl, &info, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto unlock;
|
||||
#endif
|
||||
|
||||
if (!snd_ctl_skip_validation(&info))
|
||||
@ -1230,7 +1235,7 @@ static int snd_ctl_elem_read(struct snd_card *card,
|
||||
ret = kctl->get(kctl, control);
|
||||
snd_power_unref(card);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto unlock;
|
||||
if (!snd_ctl_skip_validation(&info) &&
|
||||
sanity_check_elem_value(card, control, &info, pattern) < 0) {
|
||||
dev_err(card->dev,
|
||||
@ -1238,8 +1243,11 @@ static int snd_ctl_elem_read(struct snd_card *card,
|
||||
control->id.iface, control->id.device,
|
||||
control->id.subdevice, control->id.name,
|
||||
control->id.index);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
unlock:
|
||||
up_read(&card->controls_rwsem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1253,9 +1261,7 @@ static int snd_ctl_elem_read_user(struct snd_card *card,
|
||||
if (IS_ERR(control))
|
||||
return PTR_ERR(control);
|
||||
|
||||
down_read(&card->controls_rwsem);
|
||||
result = snd_ctl_elem_read(card, control);
|
||||
up_read(&card->controls_rwsem);
|
||||
if (result < 0)
|
||||
goto error;
|
||||
|
||||
|
@ -530,12 +530,11 @@ static ssize_t set_led_id(struct snd_ctl_led_card *led_card, const char *buf, si
|
||||
bool attach)
|
||||
{
|
||||
char buf2[256], *s, *os;
|
||||
size_t len = max(sizeof(s) - 1, count);
|
||||
struct snd_ctl_elem_id id;
|
||||
int err;
|
||||
|
||||
strncpy(buf2, buf, len);
|
||||
buf2[len] = '\0';
|
||||
if (strscpy(buf2, buf, sizeof(buf2)) < 0)
|
||||
return -E2BIG;
|
||||
memset(&id, 0, sizeof(id));
|
||||
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
s = buf2;
|
||||
|
@ -598,8 +598,8 @@ static int cs35l41_system_suspend(struct device *dev)
|
||||
dev_dbg(cs35l41->dev, "System Suspend\n");
|
||||
|
||||
if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) {
|
||||
dev_err(cs35l41->dev, "System Suspend not supported\n");
|
||||
return -EINVAL;
|
||||
dev_err_once(cs35l41->dev, "System Suspend not supported\n");
|
||||
return 0; /* don't block the whole system suspend */
|
||||
}
|
||||
|
||||
ret = pm_runtime_force_suspend(dev);
|
||||
@ -624,8 +624,8 @@ static int cs35l41_system_resume(struct device *dev)
|
||||
dev_dbg(cs35l41->dev, "System Resume\n");
|
||||
|
||||
if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) {
|
||||
dev_err(cs35l41->dev, "System Resume not supported\n");
|
||||
return -EINVAL;
|
||||
dev_err_once(cs35l41->dev, "System Resume not supported\n");
|
||||
return 0; /* don't block the whole system resume */
|
||||
}
|
||||
|
||||
if (cs35l41->reset_gpio) {
|
||||
@ -647,6 +647,15 @@ static int cs35l41_system_resume(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cs35l41_runtime_idle(struct device *dev)
|
||||
{
|
||||
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
|
||||
|
||||
if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH)
|
||||
return -EBUSY; /* suspend not supported yet on this model */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs35l41_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
|
||||
@ -1536,7 +1545,8 @@ void cs35l41_hda_remove(struct device *dev)
|
||||
EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, SND_HDA_SCODEC_CS35L41);
|
||||
|
||||
const struct dev_pm_ops cs35l41_hda_pm_ops = {
|
||||
RUNTIME_PM_OPS(cs35l41_runtime_suspend, cs35l41_runtime_resume, NULL)
|
||||
RUNTIME_PM_OPS(cs35l41_runtime_suspend, cs35l41_runtime_resume,
|
||||
cs35l41_runtime_idle)
|
||||
SYSTEM_SLEEP_PM_OPS(cs35l41_system_suspend, cs35l41_system_resume)
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(cs35l41_hda_pm_ops, SND_HDA_SCODEC_CS35L41);
|
||||
|
@ -1981,6 +1981,7 @@ static const struct snd_pci_quirk force_connect_list[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x870f, "HP", 1),
|
||||
SND_PCI_QUIRK(0x103c, 0x871a, "HP", 1),
|
||||
SND_PCI_QUIRK(0x103c, 0x8711, "HP", 1),
|
||||
SND_PCI_QUIRK(0x103c, 0x8715, "HP", 1),
|
||||
SND_PCI_QUIRK(0x1462, 0xec94, "MS-7C94", 1),
|
||||
SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", 1),
|
||||
{}
|
||||
|
@ -3564,6 +3564,15 @@ static void alc256_init(struct hda_codec *codec)
|
||||
hda_nid_t hp_pin = alc_get_hp_pin(spec);
|
||||
bool hp_pin_sense;
|
||||
|
||||
if (spec->ultra_low_power) {
|
||||
alc_update_coef_idx(codec, 0x03, 1<<1, 1<<1);
|
||||
alc_update_coef_idx(codec, 0x08, 3<<2, 3<<2);
|
||||
alc_update_coef_idx(codec, 0x08, 7<<4, 0);
|
||||
alc_update_coef_idx(codec, 0x3b, 1<<15, 0);
|
||||
alc_update_coef_idx(codec, 0x0e, 7<<6, 7<<6);
|
||||
msleep(30);
|
||||
}
|
||||
|
||||
if (!hp_pin)
|
||||
hp_pin = 0x21;
|
||||
|
||||
@ -3575,14 +3584,6 @@ static void alc256_init(struct hda_codec *codec)
|
||||
msleep(2);
|
||||
|
||||
alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
|
||||
if (spec->ultra_low_power) {
|
||||
alc_update_coef_idx(codec, 0x03, 1<<1, 1<<1);
|
||||
alc_update_coef_idx(codec, 0x08, 3<<2, 3<<2);
|
||||
alc_update_coef_idx(codec, 0x08, 7<<4, 0);
|
||||
alc_update_coef_idx(codec, 0x3b, 1<<15, 0);
|
||||
alc_update_coef_idx(codec, 0x0e, 7<<6, 7<<6);
|
||||
msleep(30);
|
||||
}
|
||||
|
||||
snd_hda_codec_write(codec, hp_pin, 0,
|
||||
AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
|
||||
@ -3713,6 +3714,13 @@ static void alc225_init(struct hda_codec *codec)
|
||||
hda_nid_t hp_pin = alc_get_hp_pin(spec);
|
||||
bool hp1_pin_sense, hp2_pin_sense;
|
||||
|
||||
if (spec->ultra_low_power) {
|
||||
alc_update_coef_idx(codec, 0x08, 0x0f << 2, 3<<2);
|
||||
alc_update_coef_idx(codec, 0x0e, 7<<6, 7<<6);
|
||||
alc_update_coef_idx(codec, 0x33, 1<<11, 0);
|
||||
msleep(30);
|
||||
}
|
||||
|
||||
if (spec->codec_variant != ALC269_TYPE_ALC287 &&
|
||||
spec->codec_variant != ALC269_TYPE_ALC245)
|
||||
/* required only at boot or S3 and S4 resume time */
|
||||
@ -3734,12 +3742,6 @@ static void alc225_init(struct hda_codec *codec)
|
||||
msleep(2);
|
||||
|
||||
alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
|
||||
if (spec->ultra_low_power) {
|
||||
alc_update_coef_idx(codec, 0x08, 0x0f << 2, 3<<2);
|
||||
alc_update_coef_idx(codec, 0x0e, 7<<6, 7<<6);
|
||||
alc_update_coef_idx(codec, 0x33, 1<<11, 0);
|
||||
msleep(30);
|
||||
}
|
||||
|
||||
if (hp1_pin_sense || spec->ultra_low_power)
|
||||
snd_hda_codec_write(codec, hp_pin, 0,
|
||||
@ -4644,6 +4646,16 @@ static void alc285_fixup_hp_coef_micmute_led(struct hda_codec *codec,
|
||||
}
|
||||
}
|
||||
|
||||
static void alc285_fixup_hp_gpio_micmute_led(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
struct alc_spec *spec = codec->spec;
|
||||
|
||||
if (action == HDA_FIXUP_ACT_PRE_PROBE)
|
||||
spec->micmute_led_polarity = 1;
|
||||
alc_fixup_hp_gpio_led(codec, action, 0, 0x04);
|
||||
}
|
||||
|
||||
static void alc236_fixup_hp_coef_micmute_led(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
@ -4665,6 +4677,13 @@ static void alc285_fixup_hp_mute_led(struct hda_codec *codec,
|
||||
alc285_fixup_hp_coef_micmute_led(codec, fix, action);
|
||||
}
|
||||
|
||||
static void alc285_fixup_hp_spectre_x360_mute_led(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
alc285_fixup_hp_mute_led_coefbit(codec, fix, action);
|
||||
alc285_fixup_hp_gpio_micmute_led(codec, fix, action);
|
||||
}
|
||||
|
||||
static void alc236_fixup_hp_mute_led(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
@ -7106,6 +7125,7 @@ enum {
|
||||
ALC285_FIXUP_ASUS_G533Z_PINS,
|
||||
ALC285_FIXUP_HP_GPIO_LED,
|
||||
ALC285_FIXUP_HP_MUTE_LED,
|
||||
ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED,
|
||||
ALC236_FIXUP_HP_GPIO_LED,
|
||||
ALC236_FIXUP_HP_MUTE_LED,
|
||||
ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF,
|
||||
@ -8486,6 +8506,10 @@ static const struct hda_fixup alc269_fixups[] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc285_fixup_hp_mute_led,
|
||||
},
|
||||
[ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc285_fixup_hp_spectre_x360_mute_led,
|
||||
},
|
||||
[ALC236_FIXUP_HP_GPIO_LED] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc236_fixup_hp_gpio_led,
|
||||
@ -9239,6 +9263,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1028, 0x0b1a, "Dell Precision 5570", ALC289_FIXUP_DUAL_SPK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0b37, "Dell Inspiron 16 Plus 7620 2-in-1", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS),
|
||||
SND_PCI_QUIRK(0x1028, 0x0b71, "Dell Inspiron 16 Plus 7620", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS),
|
||||
SND_PCI_QUIRK(0x1028, 0x0c03, "Dell Precision 5340", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1028, 0x0c19, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS),
|
||||
SND_PCI_QUIRK(0x1028, 0x0c1a, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS),
|
||||
SND_PCI_QUIRK(0x1028, 0x0c1b, "Dell Precision 3440", ALC236_FIXUP_DELL_DUAL_CODECS),
|
||||
@ -9327,6 +9352,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO),
|
||||
SND_PCI_QUIRK(0x103c, 0x86e7, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
|
||||
SND_PCI_QUIRK(0x103c, 0x86e8, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
|
||||
SND_PCI_QUIRK(0x103c, 0x86f9, "HP Spectre x360 13-aw0xxx", ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8716, "HP Elite Dragonfly G2 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
|
||||
SND_PCI_QUIRK(0x103c, 0x8720, "HP EliteBook x360 1040 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
|
||||
SND_PCI_QUIRK(0x103c, 0x8724, "HP EliteBook 850 G7", ALC285_FIXUP_HP_GPIO_LED),
|
||||
@ -9406,6 +9432,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x8ad2, "HP EliteBook 860 16 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8b5d, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
|
||||
SND_PCI_QUIRK(0x103c, 0x8b5e, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
|
||||
SND_PCI_QUIRK(0x103c, 0x8bf0, "HP", ALC236_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
|
||||
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
|
@ -206,6 +206,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "UM5302TA"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.driver_data = &acp6x_card,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "M5402RA"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.driver_data = &acp6x_card,
|
||||
.matches = {
|
||||
@ -220,6 +227,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Redmi Book Pro 14 2022"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.driver_data = &acp6x_card,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "Razer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Blade 14 (2022) - RZ09-0427"),
|
||||
}
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -177,8 +177,20 @@ static int rt9120_codec_probe(struct snd_soc_component *comp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt9120_codec_suspend(struct snd_soc_component *comp)
|
||||
{
|
||||
return pm_runtime_force_suspend(comp->dev);
|
||||
}
|
||||
|
||||
static int rt9120_codec_resume(struct snd_soc_component *comp)
|
||||
{
|
||||
return pm_runtime_force_resume(comp->dev);
|
||||
}
|
||||
|
||||
static const struct snd_soc_component_driver rt9120_component_driver = {
|
||||
.probe = rt9120_codec_probe,
|
||||
.suspend = rt9120_codec_suspend,
|
||||
.resume = rt9120_codec_resume,
|
||||
.controls = rt9120_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(rt9120_snd_controls),
|
||||
.dapm_widgets = rt9120_dapm_widgets,
|
||||
|
@ -697,6 +697,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
|
||||
int dcs_mask;
|
||||
int dcs_l, dcs_r;
|
||||
int dcs_l_reg, dcs_r_reg;
|
||||
int an_out_reg;
|
||||
int timeout;
|
||||
int pwr_reg;
|
||||
|
||||
@ -712,6 +713,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
|
||||
dcs_mask = WM8904_DCS_ENA_CHAN_0 | WM8904_DCS_ENA_CHAN_1;
|
||||
dcs_r_reg = WM8904_DC_SERVO_8;
|
||||
dcs_l_reg = WM8904_DC_SERVO_9;
|
||||
an_out_reg = WM8904_ANALOGUE_OUT1_LEFT;
|
||||
dcs_l = 0;
|
||||
dcs_r = 1;
|
||||
break;
|
||||
@ -720,6 +722,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
|
||||
dcs_mask = WM8904_DCS_ENA_CHAN_2 | WM8904_DCS_ENA_CHAN_3;
|
||||
dcs_r_reg = WM8904_DC_SERVO_6;
|
||||
dcs_l_reg = WM8904_DC_SERVO_7;
|
||||
an_out_reg = WM8904_ANALOGUE_OUT2_LEFT;
|
||||
dcs_l = 2;
|
||||
dcs_r = 3;
|
||||
break;
|
||||
@ -792,6 +795,10 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
|
||||
snd_soc_component_update_bits(component, reg,
|
||||
WM8904_HPL_ENA_OUTP | WM8904_HPR_ENA_OUTP,
|
||||
WM8904_HPL_ENA_OUTP | WM8904_HPR_ENA_OUTP);
|
||||
|
||||
/* Update volume, requires PGA to be powered */
|
||||
val = snd_soc_component_read(component, an_out_reg);
|
||||
snd_soc_component_write(component, an_out_reg, val);
|
||||
break;
|
||||
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
|
@ -121,11 +121,11 @@ static const struct snd_soc_dapm_route audio_map[] = {
|
||||
|
||||
static const struct snd_soc_dapm_route audio_map_ac97[] = {
|
||||
/* 1st half -- Normal DAPM routes */
|
||||
{"Playback", NULL, "AC97 Playback"},
|
||||
{"AC97 Capture", NULL, "Capture"},
|
||||
{"AC97 Playback", NULL, "CPU AC97 Playback"},
|
||||
{"CPU AC97 Capture", NULL, "AC97 Capture"},
|
||||
/* 2nd half -- ASRC DAPM routes */
|
||||
{"AC97 Playback", NULL, "ASRC-Playback"},
|
||||
{"ASRC-Capture", NULL, "AC97 Capture"},
|
||||
{"CPU AC97 Playback", NULL, "ASRC-Playback"},
|
||||
{"ASRC-Capture", NULL, "CPU AC97 Capture"},
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route audio_map_tx[] = {
|
||||
|
@ -315,21 +315,21 @@ static int hwvad_detected(struct snd_kcontrol *kcontrol,
|
||||
|
||||
static const struct snd_kcontrol_new fsl_micfil_snd_controls[] = {
|
||||
SOC_SINGLE_SX_TLV("CH0 Volume", REG_MICFIL_OUT_CTRL,
|
||||
MICFIL_OUTGAIN_CHX_SHIFT(0), 0xF, 0x7, gain_tlv),
|
||||
MICFIL_OUTGAIN_CHX_SHIFT(0), 0x8, 0xF, gain_tlv),
|
||||
SOC_SINGLE_SX_TLV("CH1 Volume", REG_MICFIL_OUT_CTRL,
|
||||
MICFIL_OUTGAIN_CHX_SHIFT(1), 0xF, 0x7, gain_tlv),
|
||||
MICFIL_OUTGAIN_CHX_SHIFT(1), 0x8, 0xF, gain_tlv),
|
||||
SOC_SINGLE_SX_TLV("CH2 Volume", REG_MICFIL_OUT_CTRL,
|
||||
MICFIL_OUTGAIN_CHX_SHIFT(2), 0xF, 0x7, gain_tlv),
|
||||
MICFIL_OUTGAIN_CHX_SHIFT(2), 0x8, 0xF, gain_tlv),
|
||||
SOC_SINGLE_SX_TLV("CH3 Volume", REG_MICFIL_OUT_CTRL,
|
||||
MICFIL_OUTGAIN_CHX_SHIFT(3), 0xF, 0x7, gain_tlv),
|
||||
MICFIL_OUTGAIN_CHX_SHIFT(3), 0x8, 0xF, gain_tlv),
|
||||
SOC_SINGLE_SX_TLV("CH4 Volume", REG_MICFIL_OUT_CTRL,
|
||||
MICFIL_OUTGAIN_CHX_SHIFT(4), 0xF, 0x7, gain_tlv),
|
||||
MICFIL_OUTGAIN_CHX_SHIFT(4), 0x8, 0xF, gain_tlv),
|
||||
SOC_SINGLE_SX_TLV("CH5 Volume", REG_MICFIL_OUT_CTRL,
|
||||
MICFIL_OUTGAIN_CHX_SHIFT(5), 0xF, 0x7, gain_tlv),
|
||||
MICFIL_OUTGAIN_CHX_SHIFT(5), 0x8, 0xF, gain_tlv),
|
||||
SOC_SINGLE_SX_TLV("CH6 Volume", REG_MICFIL_OUT_CTRL,
|
||||
MICFIL_OUTGAIN_CHX_SHIFT(6), 0xF, 0x7, gain_tlv),
|
||||
MICFIL_OUTGAIN_CHX_SHIFT(6), 0x8, 0xF, gain_tlv),
|
||||
SOC_SINGLE_SX_TLV("CH7 Volume", REG_MICFIL_OUT_CTRL,
|
||||
MICFIL_OUTGAIN_CHX_SHIFT(7), 0xF, 0x7, gain_tlv),
|
||||
MICFIL_OUTGAIN_CHX_SHIFT(7), 0x8, 0xF, gain_tlv),
|
||||
SOC_ENUM_EXT("MICFIL Quality Select",
|
||||
fsl_micfil_quality_enum,
|
||||
micfil_quality_get, micfil_quality_set),
|
||||
|
@ -1189,14 +1189,14 @@ static struct snd_soc_dai_driver fsl_ssi_ac97_dai = {
|
||||
.symmetric_channels = 1,
|
||||
.probe = fsl_ssi_dai_probe,
|
||||
.playback = {
|
||||
.stream_name = "AC97 Playback",
|
||||
.stream_name = "CPU AC97 Playback",
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_8000_48000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_S20,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "AC97 Capture",
|
||||
.stream_name = "CPU AC97 Capture",
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_48000,
|
||||
|
@ -554,10 +554,12 @@ config SND_SOC_INTEL_SOF_NAU8825_MACH
|
||||
select SND_SOC_RT1015P
|
||||
select SND_SOC_MAX98373_I2C
|
||||
select SND_SOC_MAX98357A
|
||||
select SND_SOC_NAU8315
|
||||
select SND_SOC_DMIC
|
||||
select SND_SOC_HDAC_HDMI
|
||||
select SND_SOC_INTEL_HDA_DSP_COMMON
|
||||
select SND_SOC_INTEL_SOF_MAXIM_COMMON
|
||||
select SND_SOC_INTEL_SOF_REALTEK_COMMON
|
||||
help
|
||||
This adds support for ASoC machine driver for SOF platforms
|
||||
with nau8825 codec.
|
||||
|
@ -48,6 +48,7 @@
|
||||
#define SOF_MAX98373_SPEAKER_AMP_PRESENT BIT(15)
|
||||
#define SOF_MAX98360A_SPEAKER_AMP_PRESENT BIT(16)
|
||||
#define SOF_RT1015P_SPEAKER_AMP_PRESENT BIT(17)
|
||||
#define SOF_NAU8318_SPEAKER_AMP_PRESENT BIT(18)
|
||||
|
||||
static unsigned long sof_nau8825_quirk = SOF_NAU8825_SSP_CODEC(0);
|
||||
|
||||
@ -338,6 +339,13 @@ static struct snd_soc_dai_link_component rt1019p_component[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_link_component nau8318_components[] = {
|
||||
{
|
||||
.name = "NVTN2012:00",
|
||||
.dai_name = "nau8315-hifi",
|
||||
}
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_link_component dummy_component[] = {
|
||||
{
|
||||
.name = "snd-soc-dummy",
|
||||
@ -486,6 +494,11 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
|
||||
max_98360a_dai_link(&links[id]);
|
||||
} else if (sof_nau8825_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT) {
|
||||
sof_rt1015p_dai_link(&links[id]);
|
||||
} else if (sof_nau8825_quirk &
|
||||
SOF_NAU8318_SPEAKER_AMP_PRESENT) {
|
||||
links[id].codecs = nau8318_components;
|
||||
links[id].num_codecs = ARRAY_SIZE(nau8318_components);
|
||||
links[id].init = speaker_codec_init;
|
||||
} else {
|
||||
goto devm_err;
|
||||
}
|
||||
@ -618,7 +631,7 @@ static const struct platform_device_id board_ids[] = {
|
||||
|
||||
},
|
||||
{
|
||||
.name = "adl_rt1019p_nau8825",
|
||||
.name = "adl_rt1019p_8825",
|
||||
.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
|
||||
SOF_SPEAKER_AMP_PRESENT |
|
||||
SOF_RT1019P_SPEAKER_AMP_PRESENT |
|
||||
@ -626,7 +639,7 @@ static const struct platform_device_id board_ids[] = {
|
||||
SOF_NAU8825_NUM_HDMIDEV(4)),
|
||||
},
|
||||
{
|
||||
.name = "adl_max98373_nau8825",
|
||||
.name = "adl_max98373_8825",
|
||||
.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
|
||||
SOF_SPEAKER_AMP_PRESENT |
|
||||
SOF_MAX98373_SPEAKER_AMP_PRESENT |
|
||||
@ -637,7 +650,7 @@ static const struct platform_device_id board_ids[] = {
|
||||
},
|
||||
{
|
||||
/* The limitation of length of char array, shorten the name */
|
||||
.name = "adl_mx98360a_nau8825",
|
||||
.name = "adl_mx98360a_8825",
|
||||
.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
|
||||
SOF_SPEAKER_AMP_PRESENT |
|
||||
SOF_MAX98360A_SPEAKER_AMP_PRESENT |
|
||||
@ -648,7 +661,7 @@ static const struct platform_device_id board_ids[] = {
|
||||
|
||||
},
|
||||
{
|
||||
.name = "adl_rt1015p_nau8825",
|
||||
.name = "adl_rt1015p_8825",
|
||||
.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
|
||||
SOF_SPEAKER_AMP_PRESENT |
|
||||
SOF_RT1015P_SPEAKER_AMP_PRESENT |
|
||||
@ -657,6 +670,16 @@ static const struct platform_device_id board_ids[] = {
|
||||
SOF_BT_OFFLOAD_SSP(2) |
|
||||
SOF_SSP_BT_OFFLOAD_PRESENT),
|
||||
},
|
||||
{
|
||||
.name = "adl_nau8318_8825",
|
||||
.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
|
||||
SOF_SPEAKER_AMP_PRESENT |
|
||||
SOF_NAU8318_SPEAKER_AMP_PRESENT |
|
||||
SOF_NAU8825_SSP_AMP(1) |
|
||||
SOF_NAU8825_NUM_HDMIDEV(4) |
|
||||
SOF_BT_OFFLOAD_SSP(2) |
|
||||
SOF_SSP_BT_OFFLOAD_PRESENT),
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, board_ids);
|
||||
|
@ -450,6 +450,11 @@ static const struct snd_soc_acpi_codecs adl_lt6911_hdmi = {
|
||||
.codecs = {"INTC10B0"}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_codecs adl_nau8318_amp = {
|
||||
.num_codecs = 1,
|
||||
.codecs = {"NVTN2012"}
|
||||
};
|
||||
|
||||
struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
|
||||
{
|
||||
.comp_ids = &adl_rt5682_rt5682s_hp,
|
||||
@ -474,21 +479,21 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
|
||||
},
|
||||
{
|
||||
.id = "10508825",
|
||||
.drv_name = "adl_rt1019p_nau8825",
|
||||
.drv_name = "adl_rt1019p_8825",
|
||||
.machine_quirk = snd_soc_acpi_codec_list,
|
||||
.quirk_data = &adl_rt1019p_amp,
|
||||
.sof_tplg_filename = "sof-adl-rt1019-nau8825.tplg",
|
||||
},
|
||||
{
|
||||
.id = "10508825",
|
||||
.drv_name = "adl_max98373_nau8825",
|
||||
.drv_name = "adl_max98373_8825",
|
||||
.machine_quirk = snd_soc_acpi_codec_list,
|
||||
.quirk_data = &adl_max98373_amp,
|
||||
.sof_tplg_filename = "sof-adl-max98373-nau8825.tplg",
|
||||
},
|
||||
{
|
||||
.id = "10508825",
|
||||
.drv_name = "adl_mx98360a_nau8825",
|
||||
.drv_name = "adl_mx98360a_8825",
|
||||
.machine_quirk = snd_soc_acpi_codec_list,
|
||||
.quirk_data = &adl_max98360a_amp,
|
||||
.sof_tplg_filename = "sof-adl-max98360a-nau8825.tplg",
|
||||
@ -502,11 +507,18 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
|
||||
},
|
||||
{
|
||||
.id = "10508825",
|
||||
.drv_name = "adl_rt1015p_nau8825",
|
||||
.drv_name = "adl_rt1015p_8825",
|
||||
.machine_quirk = snd_soc_acpi_codec_list,
|
||||
.quirk_data = &adl_rt1015p_amp,
|
||||
.sof_tplg_filename = "sof-adl-rt1015-nau8825.tplg",
|
||||
},
|
||||
{
|
||||
.id = "10508825",
|
||||
.drv_name = "adl_nau8318_8825",
|
||||
.machine_quirk = snd_soc_acpi_codec_list,
|
||||
.quirk_data = &adl_nau8318_amp,
|
||||
.sof_tplg_filename = "sof-adl-nau8318-nau8825.tplg",
|
||||
},
|
||||
{
|
||||
.id = "10508825",
|
||||
.drv_name = "sof_nau8825",
|
||||
|
@ -203,6 +203,25 @@ static const struct snd_soc_acpi_link_adr rpl_sdw_rt711_link2_rt1316_link01_rt71
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_link_adr rpl_sdw_rt711_link2_rt1316_link01[] = {
|
||||
{
|
||||
.mask = BIT(2),
|
||||
.num_adr = ARRAY_SIZE(rt711_sdca_2_adr),
|
||||
.adr_d = rt711_sdca_2_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(0),
|
||||
.num_adr = ARRAY_SIZE(rt1316_0_group2_adr),
|
||||
.adr_d = rt1316_0_group2_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(1),
|
||||
.num_adr = ARRAY_SIZE(rt1316_1_group2_adr),
|
||||
.adr_d = rt1316_1_group2_adr,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_link_adr rpl_sdw_rt711_link0_rt1318_link12_rt714_link3[] = {
|
||||
{
|
||||
.mask = BIT(0),
|
||||
@ -227,6 +246,25 @@ static const struct snd_soc_acpi_link_adr rpl_sdw_rt711_link0_rt1318_link12_rt71
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_link_adr rpl_sdw_rt711_link0_rt1318_link12[] = {
|
||||
{
|
||||
.mask = BIT(0),
|
||||
.num_adr = ARRAY_SIZE(rt711_sdca_0_adr),
|
||||
.adr_d = rt711_sdca_0_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(1),
|
||||
.num_adr = ARRAY_SIZE(rt1318_1_group1_adr),
|
||||
.adr_d = rt1318_1_group1_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(2),
|
||||
.num_adr = ARRAY_SIZE(rt1318_2_group1_adr),
|
||||
.adr_d = rt1318_2_group1_adr,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_link_adr rpl_sdw_rt1316_link12_rt714_link0[] = {
|
||||
{
|
||||
.mask = BIT(1),
|
||||
@ -271,12 +309,24 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_sdw_machines[] = {
|
||||
.drv_name = "sof_sdw",
|
||||
.sof_tplg_filename = "sof-rpl-rt711-l0-rt1318-l12-rt714-l3.tplg",
|
||||
},
|
||||
{
|
||||
.link_mask = 0x7, /* rt711 on link0 & two rt1318s on link1 and link2 */
|
||||
.links = rpl_sdw_rt711_link0_rt1318_link12,
|
||||
.drv_name = "sof_sdw",
|
||||
.sof_tplg_filename = "sof-rpl-rt711-l0-rt1318-l12.tplg",
|
||||
},
|
||||
{
|
||||
.link_mask = 0x7, /* rt714 on link0 & two rt1316s on link1 and link2 */
|
||||
.links = rpl_sdw_rt1316_link12_rt714_link0,
|
||||
.drv_name = "sof_sdw",
|
||||
.sof_tplg_filename = "sof-rpl-rt1316-l12-rt714-l0.tplg",
|
||||
},
|
||||
{
|
||||
.link_mask = 0x7, /* rt711 on link2 & two rt1316s on link0 and link1 */
|
||||
.links = rpl_sdw_rt711_link2_rt1316_link01,
|
||||
.drv_name = "sof_sdw",
|
||||
.sof_tplg_filename = "sof-rpl-rt711-l2-rt1316-l01.tplg",
|
||||
},
|
||||
{
|
||||
.link_mask = 0x1, /* link0 required */
|
||||
.links = rpl_rvp,
|
||||
|
@ -182,10 +182,12 @@ config SND_SOC_MT8186_MT6366_DA7219_MAX98357
|
||||
If unsure select "N".
|
||||
|
||||
config SND_SOC_MT8186_MT6366_RT1019_RT5682S
|
||||
tristate "ASoC Audio driver for MT8186 with RT1019 RT5682S codec"
|
||||
tristate "ASoC Audio driver for MT8186 with RT1019 RT5682S MAX98357A/MAX98360 codec"
|
||||
depends on I2C && GPIOLIB
|
||||
depends on SND_SOC_MT8186 && MTK_PMIC_WRAP
|
||||
select SND_SOC_MAX98357A
|
||||
select SND_SOC_MT6358
|
||||
select SND_SOC_MAX98357A
|
||||
select SND_SOC_RT1015P
|
||||
select SND_SOC_RT5682S
|
||||
select SND_SOC_BT_SCO
|
||||
|
@ -1083,6 +1083,21 @@ static struct snd_soc_card mt8186_mt6366_rt1019_rt5682s_soc_card = {
|
||||
.num_configs = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_codec_conf),
|
||||
};
|
||||
|
||||
static struct snd_soc_card mt8186_mt6366_rt5682s_max98360_soc_card = {
|
||||
.name = "mt8186_rt5682s_max98360",
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = mt8186_mt6366_rt1019_rt5682s_dai_links,
|
||||
.num_links = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_dai_links),
|
||||
.controls = mt8186_mt6366_rt1019_rt5682s_controls,
|
||||
.num_controls = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_controls),
|
||||
.dapm_widgets = mt8186_mt6366_rt1019_rt5682s_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_widgets),
|
||||
.dapm_routes = mt8186_mt6366_rt1019_rt5682s_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_routes),
|
||||
.codec_conf = mt8186_mt6366_rt1019_rt5682s_codec_conf,
|
||||
.num_configs = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_codec_conf),
|
||||
};
|
||||
|
||||
static int mt8186_mt6366_rt1019_rt5682s_dev_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card;
|
||||
@ -1232,9 +1247,14 @@ err_adsp_node:
|
||||
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
static const struct of_device_id mt8186_mt6366_rt1019_rt5682s_dt_match[] = {
|
||||
{ .compatible = "mediatek,mt8186-mt6366-rt1019-rt5682s-sound",
|
||||
{
|
||||
.compatible = "mediatek,mt8186-mt6366-rt1019-rt5682s-sound",
|
||||
.data = &mt8186_mt6366_rt1019_rt5682s_soc_card,
|
||||
},
|
||||
{
|
||||
.compatible = "mediatek,mt8186-mt6366-rt5682s-max98360-sound",
|
||||
.data = &mt8186_mt6366_rt5682s_max98360_soc_card,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mt8186_mt6366_rt1019_rt5682s_dt_match);
|
||||
|
@ -2,7 +2,6 @@
|
||||
menuconfig SND_SOC_QCOM
|
||||
tristate "ASoC support for QCOM platforms"
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
imply SND_SOC_QCOM_COMMON
|
||||
help
|
||||
Say Y or M if you want to add support to use audio devices
|
||||
in Qualcomm Technologies SOC-based platforms.
|
||||
@ -60,14 +59,16 @@ config SND_SOC_STORM
|
||||
config SND_SOC_APQ8016_SBC
|
||||
tristate "SoC Audio support for APQ8016 SBC platforms"
|
||||
select SND_SOC_LPASS_APQ8016
|
||||
depends on SND_SOC_QCOM_COMMON
|
||||
select SND_SOC_QCOM_COMMON
|
||||
help
|
||||
Support for Qualcomm Technologies LPASS audio block in
|
||||
APQ8016 SOC-based systems.
|
||||
Say Y if you want to use audio devices on MI2S.
|
||||
|
||||
config SND_SOC_QCOM_COMMON
|
||||
depends on SOUNDWIRE
|
||||
tristate
|
||||
|
||||
config SND_SOC_QCOM_SDW
|
||||
tristate
|
||||
|
||||
config SND_SOC_QDSP6_COMMON
|
||||
@ -144,7 +145,7 @@ config SND_SOC_MSM8996
|
||||
depends on QCOM_APR
|
||||
depends on COMMON_CLK
|
||||
select SND_SOC_QDSP6
|
||||
depends on SND_SOC_QCOM_COMMON
|
||||
select SND_SOC_QCOM_COMMON
|
||||
help
|
||||
Support for Qualcomm Technologies LPASS audio block in
|
||||
APQ8096 SoC-based systems.
|
||||
@ -155,7 +156,7 @@ config SND_SOC_SDM845
|
||||
depends on QCOM_APR && I2C && SOUNDWIRE
|
||||
depends on COMMON_CLK
|
||||
select SND_SOC_QDSP6
|
||||
depends on SND_SOC_QCOM_COMMON
|
||||
select SND_SOC_QCOM_COMMON
|
||||
select SND_SOC_RT5663
|
||||
select SND_SOC_MAX98927
|
||||
imply SND_SOC_CROS_EC_CODEC
|
||||
@ -169,7 +170,8 @@ config SND_SOC_SM8250
|
||||
depends on QCOM_APR && SOUNDWIRE
|
||||
depends on COMMON_CLK
|
||||
select SND_SOC_QDSP6
|
||||
depends on SND_SOC_QCOM_COMMON
|
||||
select SND_SOC_QCOM_COMMON
|
||||
select SND_SOC_QCOM_SDW
|
||||
help
|
||||
To add support for audio on Qualcomm Technologies Inc.
|
||||
SM8250 SoC-based systems.
|
||||
@ -180,7 +182,8 @@ config SND_SOC_SC8280XP
|
||||
depends on QCOM_APR && SOUNDWIRE
|
||||
depends on COMMON_CLK
|
||||
select SND_SOC_QDSP6
|
||||
depends on SND_SOC_QCOM_COMMON
|
||||
select SND_SOC_QCOM_COMMON
|
||||
select SND_SOC_QCOM_SDW
|
||||
help
|
||||
To add support for audio on Qualcomm Technologies Inc.
|
||||
SC8280XP SoC-based systems.
|
||||
@ -190,7 +193,7 @@ config SND_SOC_SC7180
|
||||
tristate "SoC Machine driver for SC7180 boards"
|
||||
depends on I2C && GPIOLIB
|
||||
depends on SOUNDWIRE || SOUNDWIRE=n
|
||||
depends on SND_SOC_QCOM_COMMON
|
||||
select SND_SOC_QCOM_COMMON
|
||||
select SND_SOC_LPASS_SC7180
|
||||
select SND_SOC_MAX98357A
|
||||
select SND_SOC_RT5682_I2C
|
||||
@ -204,7 +207,7 @@ config SND_SOC_SC7180
|
||||
config SND_SOC_SC7280
|
||||
tristate "SoC Machine driver for SC7280 boards"
|
||||
depends on I2C && SOUNDWIRE
|
||||
depends on SND_SOC_QCOM_COMMON
|
||||
select SND_SOC_QCOM_COMMON
|
||||
select SND_SOC_LPASS_SC7280
|
||||
select SND_SOC_MAX98357A
|
||||
select SND_SOC_WCD938X_SDW
|
||||
|
@ -28,6 +28,7 @@ snd-soc-sdm845-objs := sdm845.o
|
||||
snd-soc-sm8250-objs := sm8250.o
|
||||
snd-soc-sc8280xp-objs := sc8280xp.o
|
||||
snd-soc-qcom-common-objs := common.o
|
||||
snd-soc-qcom-sdw-objs := sdw.o
|
||||
|
||||
obj-$(CONFIG_SND_SOC_STORM) += snd-soc-storm.o
|
||||
obj-$(CONFIG_SND_SOC_APQ8016_SBC) += snd-soc-apq8016-sbc.o
|
||||
@ -38,6 +39,7 @@ obj-$(CONFIG_SND_SOC_SC8280XP) += snd-soc-sc8280xp.o
|
||||
obj-$(CONFIG_SND_SOC_SDM845) += snd-soc-sdm845.o
|
||||
obj-$(CONFIG_SND_SOC_SM8250) += snd-soc-sm8250.o
|
||||
obj-$(CONFIG_SND_SOC_QCOM_COMMON) += snd-soc-qcom-common.o
|
||||
obj-$(CONFIG_SND_SOC_QCOM_SDW) += snd-soc-qcom-sdw.o
|
||||
|
||||
#DSP lib
|
||||
obj-$(CONFIG_SND_SOC_QDSP6) += qdsp6/
|
||||
|
@ -180,120 +180,6 @@ err_put_np:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_snd_parse_of);
|
||||
|
||||
int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
|
||||
struct sdw_stream_runtime *sruntime,
|
||||
bool *stream_prepared)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
|
||||
int ret;
|
||||
|
||||
if (!sruntime)
|
||||
return 0;
|
||||
|
||||
switch (cpu_dai->id) {
|
||||
case WSA_CODEC_DMA_RX_0:
|
||||
case WSA_CODEC_DMA_RX_1:
|
||||
case RX_CODEC_DMA_RX_0:
|
||||
case RX_CODEC_DMA_RX_1:
|
||||
case TX_CODEC_DMA_TX_0:
|
||||
case TX_CODEC_DMA_TX_1:
|
||||
case TX_CODEC_DMA_TX_2:
|
||||
case TX_CODEC_DMA_TX_3:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*stream_prepared) {
|
||||
sdw_disable_stream(sruntime);
|
||||
sdw_deprepare_stream(sruntime);
|
||||
*stream_prepared = false;
|
||||
}
|
||||
|
||||
ret = sdw_prepare_stream(sruntime);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/**
|
||||
* NOTE: there is a strict hw requirement about the ordering of port
|
||||
* enables and actual WSA881x PA enable. PA enable should only happen
|
||||
* after soundwire ports are enabled if not DC on the line is
|
||||
* accumulated resulting in Click/Pop Noise
|
||||
* PA enable/mute are handled as part of codec DAPM and digital mute.
|
||||
*/
|
||||
|
||||
ret = sdw_enable_stream(sruntime);
|
||||
if (ret) {
|
||||
sdw_deprepare_stream(sruntime);
|
||||
return ret;
|
||||
}
|
||||
*stream_prepared = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_snd_sdw_prepare);
|
||||
|
||||
int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct sdw_stream_runtime **psruntime)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
|
||||
struct sdw_stream_runtime *sruntime;
|
||||
int i;
|
||||
|
||||
switch (cpu_dai->id) {
|
||||
case WSA_CODEC_DMA_RX_0:
|
||||
case RX_CODEC_DMA_RX_0:
|
||||
case RX_CODEC_DMA_RX_1:
|
||||
case TX_CODEC_DMA_TX_0:
|
||||
case TX_CODEC_DMA_TX_1:
|
||||
case TX_CODEC_DMA_TX_2:
|
||||
case TX_CODEC_DMA_TX_3:
|
||||
for_each_rtd_codec_dais(rtd, i, codec_dai) {
|
||||
sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream);
|
||||
if (sruntime != ERR_PTR(-ENOTSUPP))
|
||||
*psruntime = sruntime;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_params);
|
||||
|
||||
int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream,
|
||||
struct sdw_stream_runtime *sruntime, bool *stream_prepared)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
|
||||
|
||||
switch (cpu_dai->id) {
|
||||
case WSA_CODEC_DMA_RX_0:
|
||||
case WSA_CODEC_DMA_RX_1:
|
||||
case RX_CODEC_DMA_RX_0:
|
||||
case RX_CODEC_DMA_RX_1:
|
||||
case TX_CODEC_DMA_TX_0:
|
||||
case TX_CODEC_DMA_TX_1:
|
||||
case TX_CODEC_DMA_TX_2:
|
||||
case TX_CODEC_DMA_TX_3:
|
||||
if (sruntime && *stream_prepared) {
|
||||
sdw_disable_stream(sruntime);
|
||||
sdw_deprepare_stream(sruntime);
|
||||
*stream_prepared = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_free);
|
||||
|
||||
int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_soc_jack *jack, bool *jack_setup)
|
||||
{
|
||||
|
@ -5,19 +5,9 @@
|
||||
#define __QCOM_SND_COMMON_H__
|
||||
|
||||
#include <sound/soc.h>
|
||||
#include <linux/soundwire/sdw.h>
|
||||
|
||||
int qcom_snd_parse_of(struct snd_soc_card *card);
|
||||
int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_soc_jack *jack, bool *jack_setup);
|
||||
|
||||
int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
|
||||
struct sdw_stream_runtime *runtime,
|
||||
bool *stream_prepared);
|
||||
int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct sdw_stream_runtime **psruntime);
|
||||
int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream,
|
||||
struct sdw_stream_runtime *sruntime,
|
||||
bool *stream_prepared);
|
||||
#endif
|
||||
|
@ -1037,10 +1037,11 @@ static void of_lpass_cpu_parse_dai_data(struct device *dev,
|
||||
struct lpass_data *data)
|
||||
{
|
||||
struct device_node *node;
|
||||
int ret, id;
|
||||
int ret, i, id;
|
||||
|
||||
/* Allow all channels by default for backwards compatibility */
|
||||
for (id = 0; id < data->variant->num_dai; id++) {
|
||||
for (i = 0; i < data->variant->num_dai; i++) {
|
||||
id = data->variant->dai_driver[i].id;
|
||||
data->mi2s_playback_sd_mode[id] = LPAIF_I2SCTL_MODE_8CH;
|
||||
data->mi2s_capture_sd_mode[id] = LPAIF_I2SCTL_MODE_8CH;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <linux/input-event-codes.h>
|
||||
#include "qdsp6/q6afe.h"
|
||||
#include "common.h"
|
||||
#include "sdw.h"
|
||||
|
||||
#define DRIVER_NAME "sc8280xp"
|
||||
|
||||
|
123
sound/soc/qcom/sdw.c
Normal file
123
sound/soc/qcom/sdw.c
Normal file
@ -0,0 +1,123 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (c) 2018, Linaro Limited.
|
||||
// Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <sound/soc.h>
|
||||
#include "qdsp6/q6afe.h"
|
||||
#include "sdw.h"
|
||||
|
||||
int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
|
||||
struct sdw_stream_runtime *sruntime,
|
||||
bool *stream_prepared)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
|
||||
int ret;
|
||||
|
||||
if (!sruntime)
|
||||
return 0;
|
||||
|
||||
switch (cpu_dai->id) {
|
||||
case WSA_CODEC_DMA_RX_0:
|
||||
case WSA_CODEC_DMA_RX_1:
|
||||
case RX_CODEC_DMA_RX_0:
|
||||
case RX_CODEC_DMA_RX_1:
|
||||
case TX_CODEC_DMA_TX_0:
|
||||
case TX_CODEC_DMA_TX_1:
|
||||
case TX_CODEC_DMA_TX_2:
|
||||
case TX_CODEC_DMA_TX_3:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*stream_prepared) {
|
||||
sdw_disable_stream(sruntime);
|
||||
sdw_deprepare_stream(sruntime);
|
||||
*stream_prepared = false;
|
||||
}
|
||||
|
||||
ret = sdw_prepare_stream(sruntime);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/**
|
||||
* NOTE: there is a strict hw requirement about the ordering of port
|
||||
* enables and actual WSA881x PA enable. PA enable should only happen
|
||||
* after soundwire ports are enabled if not DC on the line is
|
||||
* accumulated resulting in Click/Pop Noise
|
||||
* PA enable/mute are handled as part of codec DAPM and digital mute.
|
||||
*/
|
||||
|
||||
ret = sdw_enable_stream(sruntime);
|
||||
if (ret) {
|
||||
sdw_deprepare_stream(sruntime);
|
||||
return ret;
|
||||
}
|
||||
*stream_prepared = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_snd_sdw_prepare);
|
||||
|
||||
int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct sdw_stream_runtime **psruntime)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
|
||||
struct sdw_stream_runtime *sruntime;
|
||||
int i;
|
||||
|
||||
switch (cpu_dai->id) {
|
||||
case WSA_CODEC_DMA_RX_0:
|
||||
case RX_CODEC_DMA_RX_0:
|
||||
case RX_CODEC_DMA_RX_1:
|
||||
case TX_CODEC_DMA_TX_0:
|
||||
case TX_CODEC_DMA_TX_1:
|
||||
case TX_CODEC_DMA_TX_2:
|
||||
case TX_CODEC_DMA_TX_3:
|
||||
for_each_rtd_codec_dais(rtd, i, codec_dai) {
|
||||
sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream);
|
||||
if (sruntime != ERR_PTR(-ENOTSUPP))
|
||||
*psruntime = sruntime;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_params);
|
||||
|
||||
int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream,
|
||||
struct sdw_stream_runtime *sruntime, bool *stream_prepared)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
|
||||
|
||||
switch (cpu_dai->id) {
|
||||
case WSA_CODEC_DMA_RX_0:
|
||||
case WSA_CODEC_DMA_RX_1:
|
||||
case RX_CODEC_DMA_RX_0:
|
||||
case RX_CODEC_DMA_RX_1:
|
||||
case TX_CODEC_DMA_TX_0:
|
||||
case TX_CODEC_DMA_TX_1:
|
||||
case TX_CODEC_DMA_TX_2:
|
||||
case TX_CODEC_DMA_TX_3:
|
||||
if (sruntime && *stream_prepared) {
|
||||
sdw_disable_stream(sruntime);
|
||||
sdw_deprepare_stream(sruntime);
|
||||
*stream_prepared = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_free);
|
||||
MODULE_LICENSE("GPL v2");
|
18
sound/soc/qcom/sdw.h
Normal file
18
sound/soc/qcom/sdw.h
Normal file
@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
// Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
|
||||
#ifndef __QCOM_SND_SDW_H__
|
||||
#define __QCOM_SND_SDW_H__
|
||||
|
||||
#include <linux/soundwire/sdw.h>
|
||||
|
||||
int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
|
||||
struct sdw_stream_runtime *runtime,
|
||||
bool *stream_prepared);
|
||||
int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct sdw_stream_runtime **psruntime);
|
||||
int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream,
|
||||
struct sdw_stream_runtime *sruntime,
|
||||
bool *stream_prepared);
|
||||
#endif
|
@ -12,6 +12,7 @@
|
||||
#include <linux/input-event-codes.h>
|
||||
#include "qdsp6/q6afe.h"
|
||||
#include "common.h"
|
||||
#include "sdw.h"
|
||||
|
||||
#define DRIVER_NAME "sm8250"
|
||||
#define MI2S_BCLK_RATE 1536000
|
||||
|
@ -353,7 +353,9 @@ int snd_sof_dbg_init(struct snd_sof_dev *sdev)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return snd_sof_debugfs_buf_item(sdev, &sdev->fw_state,
|
||||
sizeof(sdev->fw_state),
|
||||
"fw_state", 0444);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_sof_dbg_init);
|
||||
|
||||
|
@ -182,7 +182,7 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)
|
||||
const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm;
|
||||
const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg;
|
||||
pm_message_t pm_state;
|
||||
u32 target_state = 0;
|
||||
u32 target_state = snd_sof_dsp_power_target(sdev);
|
||||
int ret;
|
||||
|
||||
/* do nothing if dsp suspend callback is not set */
|
||||
@ -192,6 +192,9 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)
|
||||
if (runtime_suspend && !sof_ops(sdev)->runtime_suspend)
|
||||
return 0;
|
||||
|
||||
if (tplg_ops && tplg_ops->tear_down_all_pipelines)
|
||||
tplg_ops->tear_down_all_pipelines(sdev, false);
|
||||
|
||||
if (sdev->fw_state != SOF_FW_BOOT_COMPLETE)
|
||||
goto suspend;
|
||||
|
||||
@ -206,7 +209,6 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)
|
||||
}
|
||||
}
|
||||
|
||||
target_state = snd_sof_dsp_power_target(sdev);
|
||||
pm_state.event = target_state;
|
||||
|
||||
/* Skip to platform-specific suspend if DSP is entering D0 */
|
||||
@ -217,9 +219,6 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)
|
||||
goto suspend;
|
||||
}
|
||||
|
||||
if (tplg_ops->tear_down_all_pipelines)
|
||||
tplg_ops->tear_down_all_pipelines(sdev, false);
|
||||
|
||||
/* suspend DMA trace */
|
||||
sof_fw_trace_suspend(sdev, pm_state);
|
||||
|
||||
|
@ -471,7 +471,7 @@ snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,
|
||||
subs = find_matching_substream(chip, stream, target->sync_ep,
|
||||
target->fmt_type);
|
||||
if (!subs)
|
||||
return sync_fmt;
|
||||
goto end;
|
||||
|
||||
high_score = 0;
|
||||
list_for_each_entry(fp, &subs->fmt_list, list) {
|
||||
@ -485,6 +485,7 @@ snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
if (fixed_rate)
|
||||
*fixed_rate = snd_usb_pcm_has_fixed_rate(subs);
|
||||
return sync_fmt;
|
||||
|
222
sound/usb/pcm.c
222
sound/usb/pcm.c
@ -160,9 +160,12 @@ find_substream_format(struct snd_usb_substream *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;
|
||||
struct snd_usb_audio *chip;
|
||||
int rate = -1;
|
||||
|
||||
if (!subs)
|
||||
return false;
|
||||
chip = subs->stream->chip;
|
||||
if (!(chip->quirk_flags & QUIRK_FLAG_FIXED_RATE))
|
||||
return false;
|
||||
list_for_each_entry(fp, &subs->fmt_list, list) {
|
||||
@ -525,6 +528,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
|
||||
if (snd_usb_endpoint_compatible(chip, subs->data_endpoint,
|
||||
fmt, hw_params))
|
||||
goto unlock;
|
||||
if (stop_endpoints(subs, false))
|
||||
sync_pending_stops(subs);
|
||||
close_endpoints(chip, subs);
|
||||
}
|
||||
|
||||
@ -787,11 +792,27 @@ static int apply_hw_params_minmax(struct snd_interval *it, unsigned int rmin,
|
||||
return changed;
|
||||
}
|
||||
|
||||
/* get the specified endpoint object that is being used by other streams
|
||||
* (i.e. the parameter is locked)
|
||||
*/
|
||||
static const struct snd_usb_endpoint *
|
||||
get_endpoint_in_use(struct snd_usb_audio *chip, int endpoint,
|
||||
const struct snd_usb_endpoint *ref_ep)
|
||||
{
|
||||
const struct snd_usb_endpoint *ep;
|
||||
|
||||
ep = snd_usb_get_endpoint(chip, endpoint);
|
||||
if (ep && ep->cur_audiofmt && (ep != ref_ep || ep->opened > 1))
|
||||
return ep;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int hw_rule_rate(struct snd_pcm_hw_params *params,
|
||||
struct snd_pcm_hw_rule *rule)
|
||||
{
|
||||
struct snd_usb_substream *subs = rule->private;
|
||||
struct snd_usb_audio *chip = subs->stream->chip;
|
||||
const struct snd_usb_endpoint *ep;
|
||||
const struct audioformat *fp;
|
||||
struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
|
||||
unsigned int rmin, rmax, r;
|
||||
@ -803,6 +824,29 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
|
||||
list_for_each_entry(fp, &subs->fmt_list, list) {
|
||||
if (!hw_check_valid_format(subs, params, fp))
|
||||
continue;
|
||||
|
||||
ep = get_endpoint_in_use(chip, fp->endpoint,
|
||||
subs->data_endpoint);
|
||||
if (ep) {
|
||||
hwc_debug("rate limit %d for ep#%x\n",
|
||||
ep->cur_rate, fp->endpoint);
|
||||
rmin = min(rmin, ep->cur_rate);
|
||||
rmax = max(rmax, ep->cur_rate);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fp->implicit_fb) {
|
||||
ep = get_endpoint_in_use(chip, fp->sync_ep,
|
||||
subs->sync_endpoint);
|
||||
if (ep) {
|
||||
hwc_debug("rate limit %d for sync_ep#%x\n",
|
||||
ep->cur_rate, fp->sync_ep);
|
||||
rmin = min(rmin, ep->cur_rate);
|
||||
rmax = max(rmax, ep->cur_rate);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
r = snd_usb_endpoint_get_clock_rate(chip, fp->clock);
|
||||
if (r > 0) {
|
||||
if (!snd_interval_test(it, r))
|
||||
@ -872,6 +916,8 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
|
||||
struct snd_pcm_hw_rule *rule)
|
||||
{
|
||||
struct snd_usb_substream *subs = rule->private;
|
||||
struct snd_usb_audio *chip = subs->stream->chip;
|
||||
const struct snd_usb_endpoint *ep;
|
||||
const struct audioformat *fp;
|
||||
struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
|
||||
u64 fbits;
|
||||
@ -881,6 +927,27 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
|
||||
list_for_each_entry(fp, &subs->fmt_list, list) {
|
||||
if (!hw_check_valid_format(subs, params, fp))
|
||||
continue;
|
||||
|
||||
ep = get_endpoint_in_use(chip, fp->endpoint,
|
||||
subs->data_endpoint);
|
||||
if (ep) {
|
||||
hwc_debug("format limit %d for ep#%x\n",
|
||||
ep->cur_format, fp->endpoint);
|
||||
fbits |= pcm_format_to_bits(ep->cur_format);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fp->implicit_fb) {
|
||||
ep = get_endpoint_in_use(chip, fp->sync_ep,
|
||||
subs->sync_endpoint);
|
||||
if (ep) {
|
||||
hwc_debug("format limit %d for sync_ep#%x\n",
|
||||
ep->cur_format, fp->sync_ep);
|
||||
fbits |= pcm_format_to_bits(ep->cur_format);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
fbits |= fp->formats;
|
||||
}
|
||||
return apply_hw_params_format_bits(fmt, fbits);
|
||||
@ -913,98 +980,95 @@ static int hw_rule_period_time(struct snd_pcm_hw_params *params,
|
||||
return apply_hw_params_minmax(it, pmin, UINT_MAX);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
const struct audioformat *fp;
|
||||
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_audiofmt) {
|
||||
/* if EP is already opened solely for this substream,
|
||||
* we still allow us to change the parameter; otherwise
|
||||
* this substream has to follow the existing parameter
|
||||
*/
|
||||
if (ep->cur_audiofmt != subs->cur_audiofmt || ep->opened > 1)
|
||||
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_audiofmt)
|
||||
return ep;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
hwc_debug("applying %s\n", __func__);
|
||||
return apply_hw_params_format_bits(fmt, pcm_format_to_bits(ep->cur_format));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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_RATE);
|
||||
return apply_hw_params_minmax(it, ep->cur_rate, ep->cur_rate);
|
||||
}
|
||||
|
||||
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;
|
||||
struct snd_usb_audio *chip = subs->stream->chip;
|
||||
const struct audioformat *fp;
|
||||
const struct snd_usb_endpoint *ep;
|
||||
struct snd_interval *it;
|
||||
unsigned int rmin, rmax;
|
||||
|
||||
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);
|
||||
hwc_debug("hw_rule_period_size: (%u,%u)\n", it->min, it->max);
|
||||
rmin = UINT_MAX;
|
||||
rmax = 0;
|
||||
list_for_each_entry(fp, &subs->fmt_list, list) {
|
||||
if (!hw_check_valid_format(subs, params, fp))
|
||||
continue;
|
||||
ep = get_endpoint_in_use(chip, fp->endpoint,
|
||||
subs->data_endpoint);
|
||||
if (ep) {
|
||||
hwc_debug("period size limit %d for ep#%x\n",
|
||||
ep->cur_period_frames, fp->endpoint);
|
||||
rmin = min(rmin, ep->cur_period_frames);
|
||||
rmax = max(rmax, ep->cur_period_frames);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fp->implicit_fb) {
|
||||
ep = get_endpoint_in_use(chip, fp->sync_ep,
|
||||
subs->sync_endpoint);
|
||||
if (ep) {
|
||||
hwc_debug("period size limit %d for sync_ep#%x\n",
|
||||
ep->cur_period_frames, fp->sync_ep);
|
||||
rmin = min(rmin, ep->cur_period_frames);
|
||||
rmax = max(rmax, ep->cur_period_frames);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!rmax)
|
||||
return 0; /* no limit by implicit fb */
|
||||
return apply_hw_params_minmax(it, rmin, rmax);
|
||||
}
|
||||
|
||||
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;
|
||||
struct snd_usb_audio *chip = subs->stream->chip;
|
||||
const struct audioformat *fp;
|
||||
const struct snd_usb_endpoint *ep;
|
||||
struct snd_interval *it;
|
||||
unsigned int rmin, rmax;
|
||||
|
||||
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);
|
||||
hwc_debug("hw_rule_periods: (%u,%u)\n", it->min, it->max);
|
||||
rmin = UINT_MAX;
|
||||
rmax = 0;
|
||||
list_for_each_entry(fp, &subs->fmt_list, list) {
|
||||
if (!hw_check_valid_format(subs, params, fp))
|
||||
continue;
|
||||
ep = get_endpoint_in_use(chip, fp->endpoint,
|
||||
subs->data_endpoint);
|
||||
if (ep) {
|
||||
hwc_debug("periods limit %d for ep#%x\n",
|
||||
ep->cur_buffer_periods, fp->endpoint);
|
||||
rmin = min(rmin, ep->cur_buffer_periods);
|
||||
rmax = max(rmax, ep->cur_buffer_periods);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fp->implicit_fb) {
|
||||
ep = get_endpoint_in_use(chip, fp->sync_ep,
|
||||
subs->sync_endpoint);
|
||||
if (ep) {
|
||||
hwc_debug("periods limit %d for sync_ep#%x\n",
|
||||
ep->cur_buffer_periods, fp->sync_ep);
|
||||
rmin = min(rmin, ep->cur_buffer_periods);
|
||||
rmax = max(rmax, ep->cur_buffer_periods);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!rmax)
|
||||
return 0; /* no limit by implicit fb */
|
||||
return apply_hw_params_minmax(it, rmin, rmax);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1113,16 +1177,6 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
|
||||
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);
|
||||
|
@ -1222,6 +1222,12 @@ static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip,
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* try to set the interface... */
|
||||
usb_set_interface(chip->dev, iface_no, 0);
|
||||
snd_usb_init_pitch(chip, fp);
|
||||
snd_usb_init_sample_rate(chip, fp, fp->rate_max);
|
||||
usb_set_interface(chip->dev, iface_no, altno);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user