diff mbox series

ALSA: hda/realtek: Fix internal speakers for Legion Y9000X 2022 IAH7

Message ID TYCP286MB25352F3E995FED9CCE90F1F6C40B2@TYCP286MB2535.JPNP286.PROD.OUTLOOK.COM (mailing list archive)
State Superseded
Headers show
Series ALSA: hda/realtek: Fix internal speakers for Legion Y9000X 2022 IAH7 | expand

Commit Message

Qi Qi April 13, 2024, 1:07 p.m. UTC
This fixes the sound not working from internal speakers on
Lenovo Legion Y9000X 2022 IAH7 models.

Signed-off-by: ArcticLampyrid <ArcticLampyrid@outlook.com>
Cc: <stable@vger.kernel.org>
---
 sound/pci/hda/cs35l41_hda_property.c | 17 +++++++++++++++++
 sound/pci/hda/patch_realtek.c        |  1 +
 2 files changed, 18 insertions(+)

Comments

Stefan Binding April 15, 2024, 9:55 a.m. UTC | #1
Hi,

On 13/04/2024 14:07, ArcticLampyrid wrote:
> This fixes the sound not working from internal speakers on
> Lenovo Legion Y9000X 2022 IAH7 models.
>
> Signed-off-by: ArcticLampyrid <ArcticLampyrid@outlook.com>
> Cc: <stable@vger.kernel.org>
> ---
>   sound/pci/hda/cs35l41_hda_property.c | 17 +++++++++++++++++
>   sound/pci/hda/patch_realtek.c        |  1 +
>   2 files changed, 18 insertions(+)
>
> diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c
> index 8fb688e41..244e41d51 100644
> --- a/sound/pci/hda/cs35l41_hda_property.c
> +++ b/sound/pci/hda/cs35l41_hda_property.c
> @@ -109,6 +109,7 @@ static const struct cs35l41_config cs35l41_config_table[] = {
>   	{ "10431F1F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 0, 0, 0 },
>   	{ "10431F62", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
>   	{ "10433A60", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
> +	{ "17AA386E", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },

According to the ACPI that I have access to, this is not correct - the 
Speaker ID is on index 2 not index 1.
Index 1 has a reference to the interrupt line. Therefore this should be:

	{ "17AA386E", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 2, -1, 0, 0, 0 },

>   	{ "17AA386F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
>   	{ "17AA3877", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
>   	{ "17AA3878", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
> @@ -414,6 +415,21 @@ static int lenovo_legion_no_acpi(struct cs35l41_hda *cs35l41, struct device *phy
>   	return 0;
>   }
>   
> +/*
> + * Some devices just have a single interrupt line for multiple amps, for which we
> + * should just register the interrupt for the first amp. Otherwise, we would meet EBUSY
> + * when registering the interrupt for the second amp.
> + */
> +static int single_interrupt_dsd_config(struct cs35l41_hda *cs35l41, struct device *physdev, int id,
> +			       const char *hid)
> +{
> +	generic_dsd_config(cs35l41, physdev, id, hid);
> +	if (id != 0x40) {
> +		cs35l41->hw_cfg.gpio2.func = CS35L41_NOT_USED;
> +	}
> +	return 0;
> +}
> +

According to the schematics I have access to, both amps have a reset 
line. The reason for any issue you see may be
because you have assigned the speaker id for the interrupt gpio in ACPI 
as mentioned above.

Thanks,

Stefan

>   struct cs35l41_prop_model {
>   	const char *hid;
>   	const char *ssid;
> @@ -500,6 +516,7 @@ static const struct cs35l41_prop_model cs35l41_prop_model_table[] = {
>   	{ "CSC3551", "10431F1F", generic_dsd_config },
>   	{ "CSC3551", "10431F62", generic_dsd_config },
>   	{ "CSC3551", "10433A60", generic_dsd_config },
> +	{ "CSC3551", "17AA386E", single_interrupt_dsd_config },
>   	{ "CSC3551", "17AA386F", generic_dsd_config },
>   	{ "CSC3551", "17AA3877", generic_dsd_config },
>   	{ "CSC3551", "17AA3878", generic_dsd_config },
> diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
> index cdcb28aa9..ac729187f 100644
> --- a/sound/pci/hda/patch_realtek.c
> +++ b/sound/pci/hda/patch_realtek.c
> @@ -10382,6 +10382,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
>   	SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
>   	SND_PCI_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6),
>   	SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
> +	SND_PCI_QUIRK(0x17aa, 0x386e, "Legion Y9000X 2022 IAH7", ALC287_FIXUP_CS35L41_I2C_2),
>   	SND_PCI_QUIRK(0x17aa, 0x386f, "Legion 7i 16IAX7", ALC287_FIXUP_CS35L41_I2C_2),
>   	SND_PCI_QUIRK(0x17aa, 0x3870, "Lenovo Yoga 7 14ARB7", ALC287_FIXUP_YOGA7_14ARB7_I2C),
>   	SND_PCI_QUIRK(0x17aa, 0x3877, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),
Qi Qi April 15, 2024, 4:49 p.m. UTC | #2
> According to the ACPI that I have access to, this is not correct - the
> Speaker ID is on index 2 not index 1.
> Index 1 has a reference to the interrupt line. Therefore this should be:
>
> 	{ "17AA386E", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 2, -1, 0, 0, 0 },

Sorry, but I'm unable to retrieve the speaker ID index from my BIOS.
Please tell me how to check it, thanks.

I've tried using `spkid_gpio_index = 2`, but haven't noticed any changes.

> The reason for any issue you see may be
> because you have assigned the speaker id for the interrupt gpio in ACPI
> as mentioned above.

Despite changing `spkid_gpio_index` to 2, it hasn't worked with `generic_dsd_config`.

The journal logs show:
```log
kernel: Serial bus multi instantiate pseudo device driver CSC3551:00: Instantiated 2 I2C devices.
kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: Adding DSD properties for 17AA386E
kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: Using extra _DSD properties, bypassing _DSD in ACPI
kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: Cirrus Logic CS35L41 (35a40), Revision: B2
kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: Adding DSD properties for 17AA386E
kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: Using extra _DSD properties, bypassing _DSD in ACPI
kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: Reset line busy, assuming shared reset
kernel: genirq: Flags mismatch irq 58. 00002088 (cs35l41 IRQ1 Controller) vs. 00002088 (cs35l41 IRQ1 Controller)
kernel:  cs35l41_hda_probe+0x94b/0x9d0 [snd_hda_scodec_cs35l41 5706d5af6d4d4abb9d294b49d5cd4cc8a51aad9d]
kernel:  ? __pfx_cs35l41_i2c_driver_init+0x10/0x10 [snd_hda_scodec_cs35l41_i2c 8858b01ad506c8ac36ad9a656c7cb71d39d6ec09]
kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: Failed to request IRQ 58 for cs35l41 IRQ1 Controller: -16
kernel: cs35l41-hda: probe of i2c-CSC3551:00-cs35l41-hda.1 failed with error -16
```

I believe this error might be caused by the configuration of the same IRQ multiple times.

Additionally, I checked the Cirrus SmartAMP driver on Windows, which appears to use only one IRQ (ID 58) on my device.
Therefore, I don't believe there is a need to configure two IRQs on my device.

The message `Flags mismatch 00002088 vs. 00002088` is confusing.
Further investigation reveals that the following check in `__setup_irq` failed:
```c
if (irqd_trigger_type_was_set(&desc->irq_data)) {
    oldtype = irqd_get_trigger_type(&desc->irq_data);
} else {
    oldtype = new->flags & IRQF_TRIGGER_MASK;
    irqd_set_trigger_type(&desc->irq_data, oldtype);
}

if (!((old->flags & new->flags) & IRQF_SHARED) ||
    (oldtype != (new->flags & IRQF_TRIGGER_MASK)))
    goto mismatch;
```

While the previous request used flags `0x00002088 = IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW`,
the `oldtype` was actually `IRQF_TRIGGER_RISING` (0x1) rather than `IRQF_TRIGGER_LOW` (0x8), leading to the mismatch.

I am new to Linux Kernel, not sure if this is expected behavior or a bug for `IRQF_SHARED`.
Ideally, a clearer message may be provided to facilitate understanding.

Sorry to bother you if I make some foolish mistakes.
Stefan Binding April 17, 2024, 3:18 p.m. UTC | #3
Hi,

To clarify, was the log you attached here using:
 	{ "17AA386E", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0,
0}, 0, 2, -1, 0, 0, 0 },
Or was it using your original value (index 1)?

The Speaker ID for this laptop should be index 2, if my ACPI for this
laptop is correct.
Both amps use the same GPIO for the interrupt line, thus the interrupt
is shared, and there is only a single interrupt line.
Disabling the interrupt on the second laptop is not a good idea, since
the interrupts are used to detect and recover from errors.

For further investigation, can you create a bugzilla ticket at the
below address and CC Cirrus Patches (patches@opensource.cirrus.com) to
it.

https://bugzilla.kernel.org/

Can you also mention which distro you are using, as well which Kernel
you are using.
Also, can you please attach a dmesg of the error, as well as the
acpidump of your laptop.
($ acpidump > acpidump.out)
(You may need to install acpica-tools to do this)

Thanks,
Stefan

> -----Original Message-----
> From: ArcticLampyrid <ArcticLampyrid@outlook.com>
> Sent: Monday, April 15, 2024 5:50 PM
> To: sbinding@opensource.cirrus.com
> Cc: ArcticLampyrid@outlook.com; david.rhodes@cirrus.com;
> james.schulman@cirrus.com; linux-kernel@vger.kernel.org; linux-
> sound@vger.kernel.org; patches@opensource.cirrus.com;
> rf@opensource.cirrus.com; stable@vger.kernel.org
> Subject: Re: Re: [PATCH] ALSA: hda/realtek: Fix internal speakers
for Legion
> Y9000X 2022 IAH7
> 
> > According to the ACPI that I have access to, this is not correct -
the
> > Speaker ID is on index 2 not index 1.
> > Index 1 has a reference to the interrupt line. Therefore this
should be:
> >
> > 	{ "17AA386E", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0
> }, 0, 2, -1, 0, 0, 0 },
> 
> Sorry, but I'm unable to retrieve the speaker ID index from my BIOS.
> Please tell me how to check it, thanks.
> 
> I've tried using `spkid_gpio_index = 2`, but haven't noticed any
changes.
> 
> > The reason for any issue you see may be
> > because you have assigned the speaker id for the interrupt gpio in
ACPI
> > as mentioned above.
> 
> Despite changing `spkid_gpio_index` to 2, it hasn't worked with
> `generic_dsd_config`.
> 
> The journal logs show:
> ```log
> kernel: Serial bus multi instantiate pseudo device driver
CSC3551:00:
> Instantiated 2 I2C devices.
> kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: Adding DSD
properties
> for 17AA386E
> kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: Using extra _DSD
> properties, bypassing _DSD in ACPI
> kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: Cirrus Logic
CS35L41
> (35a40), Revision: B2
> kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: Adding DSD
properties
> for 17AA386E
> kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: Using extra _DSD
> properties, bypassing _DSD in ACPI
> kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: Reset line busy,
> assuming shared reset
> kernel: genirq: Flags mismatch irq 58. 00002088 (cs35l41 IRQ1
Controller)
> vs. 00002088 (cs35l41 IRQ1 Controller)
> kernel:  cs35l41_hda_probe+0x94b/0x9d0 [snd_hda_scodec_cs35l41
> 5706d5af6d4d4abb9d294b49d5cd4cc8a51aad9d]
> kernel:  ? __pfx_cs35l41_i2c_driver_init+0x10/0x10
> [snd_hda_scodec_cs35l41_i2c
> 8858b01ad506c8ac36ad9a656c7cb71d39d6ec09]
> kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: Failed to request
IRQ
> 58 for cs35l41 IRQ1 Controller: -16
> kernel: cs35l41-hda: probe of i2c-CSC3551:00-cs35l41-hda.1 failed
with
> error -16
> ```
> 
> I believe this error might be caused by the configuration of the
same IRQ
> multiple times.
> 
> Additionally, I checked the Cirrus SmartAMP driver on Windows, which
> appears to use only one IRQ (ID 58) on my device.
> Therefore, I don't believe there is a need to configure two IRQs on
my
> device.
> 
> The message `Flags mismatch 00002088 vs. 00002088` is confusing.
> Further investigation reveals that the following check in
`__setup_irq`
> failed:
> ```c
> if (irqd_trigger_type_was_set(&desc->irq_data)) {
>     oldtype = irqd_get_trigger_type(&desc->irq_data);
> } else {
>     oldtype = new->flags & IRQF_TRIGGER_MASK;
>     irqd_set_trigger_type(&desc->irq_data, oldtype);
> }
> 
> if (!((old->flags & new->flags) & IRQF_SHARED) ||
>     (oldtype != (new->flags & IRQF_TRIGGER_MASK)))
>     goto mismatch;
> ```
> 
> While the previous request used flags `0x00002088 = IRQF_ONESHOT |
> IRQF_SHARED | IRQF_TRIGGER_LOW`,
> the `oldtype` was actually `IRQF_TRIGGER_RISING` (0x1) rather than
> `IRQF_TRIGGER_LOW` (0x8), leading to the mismatch.
> 
> I am new to Linux Kernel, not sure if this is expected behavior or a
bug for
> `IRQF_SHARED`.
> Ideally, a clearer message may be provided to facilitate
understanding.
> 
> Sorry to bother you if I make some foolish mistakes.
Qi Qi April 18, 2024, 4:03 a.m. UTC | #4
> To clarify, was the log you attached here using:
>   { "17AA386E", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0}, 0, 2, -1, 0, 0, 0 },
> Or was it using your original value (index 1)?

Both get the same log.

> For further investigation, can you create a bugzilla ticket at the
> below address and CC Cirrus Patches (patches@opensource.cirrus.com) to
> it.

OK. https://bugzilla.kernel.org/show_bug.cgi?id=218744

> Can you also mention which distro you are using, as well which Kernel you are using.

I'm using Arch Linux, the kernel is v6.8.5-arch1.

> Both amps use the same GPIO for the interrupt line, thus the interrupt is shared, and there is only a single interrupt line.

BTW, it's connected to APIC.

> Also, can you please attach a dmesg of the error

Without any patches, I got
```log
    Serial bus multi instantiate pseudo device driver CSC3551:00: Instantiated 2 I2C devices.
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: Failed property cirrus,dev-index: -22
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: error -EINVAL: Platform not supported
    cs35l41-hda: probe of i2c-CSC3551:00-cs35l41-hda.0 failed with error -22
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: Failed property cirrus,dev-index: -22
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: error -EINVAL: Platform not supported
    cs35l41-hda: probe of i2c-CSC3551:00-cs35l41-hda.1 failed with error -22
```

With `generic_dsd_config` I got
```log
    kernel: genirq: Flags mismatch irq 58. 00002088 (cs35l41 IRQ1 Controller) vs. 00002088 (cs35l41 IRQ1 Controller)
```
as memtioned in the previous email.

With my initial patch:
```log
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: Adding DSD properties for 17AA386E
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: Using extra _DSD properties, bypassing _DSD in ACPI
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: Cirrus Logic CS35L41 (35a40), Revision: B2
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: Adding DSD properties for 17AA386E
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: Using extra _DSD properties, bypassing _DSD in ACPI
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: Reset line busy, assuming shared reset
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: Cirrus Logic CS35L41 (35a40), Revision: B2
    Serial bus multi instantiate pseudo device driver CSC3551:00: Instantiated 2 I2C devices.
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: Falling back to default firmware.
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: DSP1: Firmware version: 3
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: DSP1: cirrus/cs35l41-dsp1-spk-prot.wmfw: Fri 24 Jun 2022 14:55:56 GMT Daylight Time
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: DSP1: Firmware: 400a4 vendor: 0x2 v0.58.0, 2 algorithms
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: DSP1: cirrus/cs35l41-dsp1-spk-prot.bin: v0.58.0
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: DSP1: spk-prot: e:\workspace\workspace\tibranch_release_playback_6.76_2\ormis\staging\default_tunings\internal\CS35L53\Fixed_Attenuation_Mono_48000_29.78.0\full\Fixed_Attenuation_Mono_48000_29.78.0_full.bin
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: CS35L41 Bound - SSID: 17AA386E, BST: 1, VSPK: 1, CH: L, FW EN: 1, SPKID: 1
    snd_hda_codec_realtek ehdaudio0D0: bound i2c-CSC3551:00-cs35l41-hda.0 (ops cs35l41_hda_comp_ops [snd_hda_scodec_cs35l41])
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: Falling back to default firmware.
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: DSP1: Firmware version: 3
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: DSP1: cirrus/cs35l41-dsp1-spk-prot.wmfw: Fri 24 Jun 2022 14:55:56 GMT Daylight Time
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: DSP1: Firmware: 400a4 vendor: 0x2 v0.58.0, 2 algorithms
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: DSP1: cirrus/cs35l41-dsp1-spk-prot.bin: v0.58.0
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: DSP1: spk-prot: e:\workspace\workspace\tibranch_release_playback_6.76_2\ormis\staging\default_tunings\internal\CS35L53\Fixed_Attenuation_Mono_48000_29.78.0\full\Fixed_Attenuation_Mono_48000_29.78.0_full.bin
    cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: CS35L41 Bound - SSID: 17AA386E, BST: 1, VSPK: 1, CH: R, FW EN: 1, SPKID: 1
    snd_hda_codec_realtek ehdaudio0D0: bound i2c-CSC3551:00-cs35l41-hda.1 (ops cs35l41_hda_comp_ops [snd_hda_scodec_cs35l41])
```

> as well as the acpidump of your laptop.

The full acpi dump is shared via
https://bugzilla.kernel.org/show_bug.cgi?id=218744

The related item I think in DSDT table may be:
```
    Device (SPKR)
    {
        Name (_HID, "CSC3551")  // _HID: Hardware ID
        Name (_SUB, "17AA386E")  // _SUB: Subsystem ID
        Name (_UID, One)  // _UID: Unique ID
        Name (SRS0, 0x09060000)
        Name (SIN0, 0x0908000E)
        Name (SID0, 0x09060001)
        Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
        {
            Name (RBUF, ResourceTemplate ()
            {
                I2cSerialBusV2 (0x0040, ControllerInitiated, 0x000F4240,
                    AddressingMode7Bit, "\\_SB.PC00.I2C3",
                    0x00, ResourceConsumer, , Exclusive,
                    )
                I2cSerialBusV2 (0x0041, ControllerInitiated, 0x000F4240,
                    AddressingMode7Bit, "\\_SB.PC00.I2C3",
                    0x00, ResourceConsumer, , Exclusive,
                    )
                GpioIo (Exclusive, PullNone, 0x0000, 0x0000, IoRestrictionOutputOnly,
                    "\\_SB.GPI0", 0x00, ResourceConsumer, ,
                    )
                    {   // Pin list
                        0x0000
                    }
                GpioIo (Shared, PullNone, 0x0064, 0x0000, IoRestrictionInputOnly,
                    "\\_SB.GPI0", 0x00, ResourceConsumer, ,
                    )
                    {   // Pin list
                        0x0000
                    }
                GpioIo (Exclusive, PullNone, 0x0000, 0x0000, IoRestrictionInputOnly,
                    "\\_SB.GPI0", 0x00, ResourceConsumer, ,
                    )
                    {   // Pin list
                        0x0000
                    }
                Interrupt (ResourceConsumer, Edge, ActiveHigh, SharedAndWake, ,, _Y58)
                {
                    0x00000000,
                }
            })
            CreateWordField (RBUF, 0x59, RST0)
            CreateWordField (RBUF, 0x7C, INT0)
            CreateWordField (RBUF, 0x9F, PID0)
            CreateDWordField (RBUF, \_SB.PC00.I2C3.SPKR._CRS._Y58._INT, INT1)  // _INT: Interrupts
            RST0 = GNUM (SRS0)
            INT0 = GNUM (SIN0)
            PID0 = GNUM (SID0)
            INT1 = INUM (SIN0)
            Return (RBUF) /* \_SB_.PC00.I2C3.SPKR._CRS.RBUF */
        }

        Method (_INI, 0, NotSerialized)  // _INI: Initialize
        {
            SGRA (0x0908000E, One)
            SGII (0x0908000E, Zero)
            GRXE (0x0908000E, 0x03)
        }

        Method (_STA, 0, NotSerialized)  // _STA: Status
        {
            Return (0x0F)
        }

        Method (_DIS, 0, NotSerialized)  // _DIS: Disable Device
        {
        }

        Method (_PS0, 0, Serialized)  // _PS0: Power State 0
        {
            ^^^LPCB.H_EC.ECWT (Zero, RefOf (^^^LPCB.H_EC.AM12))
        }

        Method (_PS2, 0, Serialized)  // _PS2: Power State 2
        {
            ^^^LPCB.H_EC.ECWT (One, RefOf (^^^LPCB.H_EC.AM12))
        }

        Method (_PS3, 0, Serialized)  // _PS3: Power State 3
        {
        }
    }
```
Qi Qi April 18, 2024, 6:51 a.m. UTC | #5
I've sent a new patch (v2), which enables interrupt well.

Link to v2: https://lore.kernel.org/lkml/TYCP286MB253523D85F6E0ECAA3E03D58C40E2@TYCP286MB2535.JPNP286.PROD.OUTLOOK.COM/T
diff mbox series

Patch

diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c
index 8fb688e41..244e41d51 100644
--- a/sound/pci/hda/cs35l41_hda_property.c
+++ b/sound/pci/hda/cs35l41_hda_property.c
@@ -109,6 +109,7 @@  static const struct cs35l41_config cs35l41_config_table[] = {
 	{ "10431F1F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 0, 0, 0 },
 	{ "10431F62", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
 	{ "10433A60", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
+	{ "17AA386E", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
 	{ "17AA386F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
 	{ "17AA3877", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
 	{ "17AA3878", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
@@ -414,6 +415,21 @@  static int lenovo_legion_no_acpi(struct cs35l41_hda *cs35l41, struct device *phy
 	return 0;
 }
 
+/*
+ * Some devices just have a single interrupt line for multiple amps, for which we
+ * should just register the interrupt for the first amp. Otherwise, we would meet EBUSY
+ * when registering the interrupt for the second amp.
+ */
+static int single_interrupt_dsd_config(struct cs35l41_hda *cs35l41, struct device *physdev, int id,
+			       const char *hid)
+{
+	generic_dsd_config(cs35l41, physdev, id, hid);
+	if (id != 0x40) {
+		cs35l41->hw_cfg.gpio2.func = CS35L41_NOT_USED;
+	}
+	return 0;
+}
+
 struct cs35l41_prop_model {
 	const char *hid;
 	const char *ssid;
@@ -500,6 +516,7 @@  static const struct cs35l41_prop_model cs35l41_prop_model_table[] = {
 	{ "CSC3551", "10431F1F", generic_dsd_config },
 	{ "CSC3551", "10431F62", generic_dsd_config },
 	{ "CSC3551", "10433A60", generic_dsd_config },
+	{ "CSC3551", "17AA386E", single_interrupt_dsd_config },
 	{ "CSC3551", "17AA386F", generic_dsd_config },
 	{ "CSC3551", "17AA3877", generic_dsd_config },
 	{ "CSC3551", "17AA3878", generic_dsd_config },
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index cdcb28aa9..ac729187f 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -10382,6 +10382,7 @@  static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
 	SND_PCI_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6),
 	SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
+	SND_PCI_QUIRK(0x17aa, 0x386e, "Legion Y9000X 2022 IAH7", ALC287_FIXUP_CS35L41_I2C_2),
 	SND_PCI_QUIRK(0x17aa, 0x386f, "Legion 7i 16IAX7", ALC287_FIXUP_CS35L41_I2C_2),
 	SND_PCI_QUIRK(0x17aa, 0x3870, "Lenovo Yoga 7 14ARB7", ALC287_FIXUP_YOGA7_14ARB7_I2C),
 	SND_PCI_QUIRK(0x17aa, 0x3877, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),