Skip to content

Instantly share code, notes, and snippets.

@lamperez
Last active November 11, 2024 11:16
Show Gist options
  • Save lamperez/862763881c0e1c812392b5574727f6ff to your computer and use it in GitHub Desktop.
Save lamperez/862763881c0e1c812392b5574727f6ff to your computer and use it in GitHub Desktop.
CS35L41 amplifiers in an ASUS Zenbook on linux

Asus Zenbook UX3402 speakers on Linux

Important

THIS IS NOW OBSOLETE WITH KERNEL VERSIONS ≥ 6.7.0

A recent announcement in the kernel mail list by Cirrus developers will solve the problem described here. Therefore, the proposed solutions will be soon obsolete. See this comment (thanks, @flukejones, for the tip).

I got the speakers working on my Asus Zenbook 14 OLED UX3402, the one with Intel CPU and the two CS35L41 audio amplifiers connected over SPI (not the UM3402YA, with AMD and I²C). The amplifiers are supported by the snd_hda_scodec_cs35l41 module in recent kernel versions, but they require some model-specific configuration paramaters, that should be provided by the BIOS, via ACPI. Of course, they are missing. It seems that the Windows drivers have those parameters somehow hardcoded, instead of using ACPI (bad idea, but who am I to criticise). Since Asus has been nasty and refused/was not able to update the BIOS with the missing data, I have patched the ACPI tables myself.

Warning

As stated by Cirrus developers, if you try this there is a non-zero (low, I hope) possibility of blowing your speakers. Take into account that this procedure is not just configuring your box, it is hardware-level hacking with very scarce information about the hardware (thank you, ASUS, and thank you, Cirrus, for not publishing the CS35L41 datasheet and making it only available by request). Additionally, You should know how to work with DSDT or SSDT files (I have a brief guide here) and how to recover from a non booting system. You are on your own. You have been warned.

Note

I have used the patch for some months, and everything seems OK. As you can see, the most recent versions do not require electrical parameters to be specified, just providing the functions of several GPIO pins, that are already present in the original BIOS, and the behavior associated to them. I am almost sure that the patch is totally safe.

My BIOS is the most recent one (version 310). I have added two _DSD objects in the SSDT file (ssdt_csc3551.dsl, or its already assembled version, ssdt_csc3551.aml):

  • One inside the SPK1 device, providing the missing "cirrus,dev-index" and other properties, just like the I2C models. You can also provide these properties by patching the kernel module (the linux/sound/pci/hda/cs35l41_hda.c file).

  • Another one, after the SPK1 device, with the chip select GPIOs, "cs-gpios", required by the SPI bus (the somehow simpler I²C bus does not use chip select pins, but addresses). Without this _DSD object, only one amplifier can be addressed and activated. In this case, the driver refuses to load even for this single working amplifier.

Obsolete: DSDT patch

Instead of applying a SSDT file, you may patch the full DSDT dissassembled DSDT file (dsdt.dsl). This was my original solution (thanks to @thor2002ro for pointing to the simpler, nicer SSDT solution, see the comment, especially if you use grub). The patch is available for reference, just apply the SSDT file.

Obsolete: internal boost

I keep the old, original patch, that produced AMP short error messages when the volume was high enough, for reference. Please try first the simpler patch with external boost, that seems to work without flaws (thanks to @bdandy, see the comment).

Boot log

Output from journalctl -b -g CSC3551 --output short-monotonic after the old patch:

[5.358062] zenbook kernel: Serial bus multi instantiate pseudo device driver CSC3551:00: Instantiated 2 SPI devices.
[5.643640] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: Cirrus Logic CS35L41 (35a40), Revision: B2
[5.680302] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: Cirrus Logic CS35L41 (35a40), Revision: B2
[5.996217] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: Falling back to default firmware.
[5.996608] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: DSP1: Firmware version: 3
[5.996611] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: DSP1: cirrus/cs35l41-dsp1-spk-prot.wmfw: Fri 24 Jun 2022 14:55:56 GMT Daylight Time
[6.069598] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: DSP1: Firmware: 400a4 vendor: 0x2 v0.58.0, 2 algorithms
[6.070173] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: DSP1: 0: ID cd v29.78.0 XM@94 YM@e
[6.070185] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: DSP1: 1: ID f20b v0.1.0 XM@17c YM@0
[6.070192] zenbook kernel: cs35l41-hda spi1-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
[6.083485] zenbook kernel: snd_hda_codec_realtek ehdaudio0D0: bound spi1-CSC3551:00-cs35l41-hda.0 (ops cs35l41_hda_comp_ops [snd_hda_scodec_cs35l41])
[6.083899] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: Falling back to default firmware.
[6.083962] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: DSP1: Firmware version: 3
[6.083966] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: DSP1: cirrus/cs35l41-dsp1-spk-prot.wmfw: Fri 24 Jun 2022 14:55:56 GMT Daylight Time
[6.145224] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: DSP1: Firmware: 400a4 vendor: 0x2 v0.58.0, 2 algorithms
[6.145817] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: DSP1: 0: ID cd v29.78.0 XM@94 YM@e
[6.145828] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: DSP1: 1: ID f20b v0.1.0 XM@17c YM@0
[6.145834] zenbook kernel: cs35l41-hda spi1-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
[6.161484] zenbook kernel: snd_hda_codec_realtek ehdaudio0D0: bound spi1-CSC3551:00-cs35l41-hda.1 (ops cs35l41_hda_comp_ops [snd_hda_scodec_cs35l41])

The "Falling back to default firmware" disappears if spk-id-gpios are provided (the block is commented in the patch). As a result, a different firmware is loaded, resulting in very low volume and strong distortion. If the new patch is used, that uses external boost, the sound is correct, and the log is

[0.004000] zenbook kernel: ACPI: Table Upgrade: install [SSDT-CUSTOM- CSC3551]
[0.004000] zenbook kernel: ACPI: SSDT 0x00000000368FD000 0001A0 (v01 CUSTOM CSC3551  00000001 INTL 20200925)
[5.607253] zenbook kernel: Serial bus multi instantiate pseudo device driver CSC3551:00: Instantiated 2 SPI devices.
[5.906936] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: Cirrus Logic CS35L41 (35a40), Revision: B2
[5.907354] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: Reset line busy, assuming shared reset
[5.938136] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: Cirrus Logic CS35L41 (35a40), Revision: B2
[6.239406] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: DSP1: Firmware version: 3
[6.239415] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: DSP1: cirrus/cs35l41-dsp1-spk-prot-10431e02.wmfw: Fri 27 Aug 2021 14:58:19 W. Europe Daylight Time
[6.313109] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: DSP1: Firmware: 400a4 vendor: 0x2 v0.43.1, 2 algorithms
[6.313524] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: DSP1: 0: ID cd v29.63.1 XM@94 YM@e
[6.313530] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: DSP1: 1: ID f20b v0.1.0 XM@176 YM@0
[6.313535] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: DSP1: spk-prot: C:\Users\tyang\Desktop\Product Setting\SmartAMP\ASUS\ASUS_Zenbook\UX3402\Tuning Release\220304\ASUS_UX3402_L_tuning_IDYC_ReDc_PICL_RTL_0304.bin
[6.337211] zenbook kernel: snd_hda_codec_realtek ehdaudio0D0: bound spi1-CSC3551:00-cs35l41-hda.0 (ops cs35l41_hda_comp_ops [snd_hda_scodec_cs35l41])
[6.337534] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: DSP1: Firmware version: 3
[6.337540] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: DSP1: cirrus/cs35l41-dsp1-spk-prot-10431e02.wmfw: Fri 27 Aug 2021 14:58:19 W. Europe Daylight Time
[6.399070] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: DSP1: Firmware: 400a4 vendor: 0x2 v0.43.1, 2 algorithms
[6.399612] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: DSP1: 0: ID cd v29.63.1 XM@94 YM@e
[6.399623] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: DSP1: 1: ID f20b v0.1.0 XM@176 YM@0
[6.399629] zenbook kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: DSP1: spk-prot: C:\Users\tyang\Desktop\Product Setting\SmartAMP\ASUS\ASUS_Zenbook\UX3402\Tuning Release\220304\ASUS_UX3402_R_tuning_IDYC_ReDc_PICL_RTL_0304.bin
[6.427637] zenbook kernel: snd_hda_codec_realtek ehdaudio0D0: bound spi1-CSC3551:00-cs35l41-hda.1 (ops cs35l41_hda_comp_ops [snd_hda_scodec_cs35l41])
--- dsdt.dsl.old 2023-03-26 01:06:48.845795666 +0100
+++ dsdt.dsl 2023-03-26 12:00:45.643851841 +0200
@@ -18,7 +18,7 @@
* Compiler ID "INTL"
* Compiler Version 0x20200717 (538969879)
*/
-DefinitionBlock ("", "DSDT", 2, "_ASUS_", "Notebook", 0x01072009)
+DefinitionBlock ("", "DSDT", 2, "_ASUS_", "Notebook", 0x0107200A)
{
/*
* iASL Warning: There were 233 external control methods found during
@@ -90642,7 +90642,48 @@
Method (_DIS, 0, NotSerialized) // _DIS: Disable Device
{
}
+
+ Name (_DSD, Package () // _DSD: Device-Specific Data
+ {
+ ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+ Package ()
+ {
+ Package () { "cirrus,dev-index", Package () { Zero, One }},
+ Package () { "reset-gpios", Package () {
+ SPK1, One, Zero, Zero,
+ SPK1, One, Zero, Zero,
+ } },
+ // Package () { "spk-id-gpios", Package () {
+ // SPK1, 0x02, Zero, Zero,
+ // SPK1, 0x02, Zero, Zero,
+ // } },
+ Package () { "cirrus,speaker-position", Package () { Zero, One } },
+ Package () { "cirrus,gpio1-func", Package () { Zero, Zero } },
+ Package () { "cirrus,gpio2-func", Package () { 0x02, 0x02 } },
+ // boost-type: 0 internal, 1 external
+ Package () { "cirrus,boost-type", Package () { Zero, Zero } },
+ // boost-peak-milliamp: 1600 to 4500, increments of 50 mA
+ Package () { "cirrus,boost-peak-milliamp", Package () { 4500, 4500 } },
+ // boost-ind-nanohenry: 1000 | 1200 | 1500 | 2200 nH
+ Package () { "cirrus,boost-ind-nanohenry", Package () { 1000, 1000 } },
+ // boost-cap-microfarad: rounded to the nearest integer
+ Package () { "cirrus,boost-cap-microfarad", Package () { 24, 24 } },
+ },
+ })
}
+
+ Name (_DSD, Package ()
+ {
+ ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+ Package ()
+ {
+ Package () { "cs-gpios", Package () {
+ Zero, // Native CS
+ SPK1, Zero, Zero, Zero // GPIO CS
+ } }
+ }
+ })
+
}
Scope (_SB.PC00.LPCB)
--- dsdt.dsl.old 2023-03-26 01:06:48.845795666 +0100
+++ dsdt.dsl 2023-03-26 12:00:45.643851841 +0200
@@ -18,7 +18,7 @@
* Compiler ID "INTL"
* Compiler Version 0x20200717 (538969879)
*/
-DefinitionBlock ("", "DSDT", 2, "_ASUS_", "Notebook", 0x01072009)
+DefinitionBlock ("", "DSDT", 2, "_ASUS_", "Notebook", 0x0107200A)
{
/*
* iASL Warning: There were 233 external control methods found during
@@ -90642,7 +90642,43 @@
Method (_DIS, 0, NotSerialized) // _DIS: Disable Device
{
}
+
+ Name (_DSD, Package () // _DSD: Device-Specific Data
+ {
+ ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+ Package ()
+ {
+ Package () { "cirrus,dev-index", Package () { Zero, One }},
+ Package () { "reset-gpios", Package () {
+ SPK1, One, Zero, Zero,
+ SPK1, One, Zero, Zero,
+ } },
+ Package () { "spk-id-gpios", Package () {
+ SPK1, 0x02, Zero, Zero,
+ SPK1, 0x02, Zero, Zero,
+ } },
+ Package () { "cirrus,speaker-position", Package () { Zero, One } },
+ // gpioX-func: 0 not used, 1 VPSK_SWITCH, 2: INTERRUPT, 3: SYNC
+ Package () { "cirrus,gpio1-func", Package () { One, One } },
+ Package () { "cirrus,gpio2-func", Package () { 0x02, 0x02 } },
+ // boost-type: 0 internal, 1 external
+ Package () { "cirrus,boost-type", Package () { One, One } },
+ },
+ })
}
+
+ Name (_DSD, Package ()
+ {
+ ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+ Package ()
+ {
+ Package () { "cs-gpios", Package () {
+ Zero, // Native CS
+ SPK1, Zero, Zero, Zero // GPIO CS
+ } }
+ }
+ })
+
}
Scope (_SB.PC00.LPCB)
DefinitionBlock ("", "SSDT", 1, "CUSTOM", "CSC3551", 0x00000001)
{
External (_SB_.PC00.SPI0, DeviceObj)
External (_SB_.PC00.SPI0.SPK1, DeviceObj)
Scope (_SB.PC00.SPI0.SPK1)
{
Name (_DSD, Package ()
{
ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package ()
{
Package () { "cirrus,dev-index", Package () { Zero, One }},
Package () { "reset-gpios", Package () {
SPK1, One, Zero, Zero,
SPK1, One, Zero, Zero
} },
Package () { "spk-id-gpios", Package () {
SPK1, 0x02, Zero, Zero,
SPK1, 0x02, Zero, Zero
} },
Package () { "cirrus,speaker-position", Package () { Zero, One } },
// gpioX-func: 0 not used, 1 VPSK_SWITCH, 2: INTERRUPT, 3: SYNC
Package () { "cirrus,gpio1-func", Package () { One, One } },
Package () { "cirrus,gpio2-func", Package () { 0x02, 0x02 } },
// boost-type: 0 internal, 1 external
Package () { "cirrus,boost-type", Package () { One, One } }
}
})
}
Scope (_SB.PC00.SPI0)
{
Name (_DSD, Package ()
{
ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package ()
{
Package () { "cs-gpios", Package () {
Zero, // Native CS
SPK1, Zero, Zero, Zero // GPIO CS
} }
}
})
}
}
@hmyzna
Copy link

hmyzna commented Nov 27, 2023

Thanks to you all I got sound working on UM3504DA (Asus Zenbook 15 OLED)!

My dsl file looks like this:

DefinitionBlock ("", "SSDT", 1, "CUSTOM", "CS3551", 0x0000300A)
{

    External (_SB_.I2CB, DeviceObj)
    External (_SB_.I2CB.SPKR, DeviceObj)

    Scope (_SB.I2CB.SPKR)
    {
        Method (_DSD, 0, NotSerialized)  // _DSD: Device Specific Data
        {
            Return (Package ()
                {
                    ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                    Package ()
                    {
                        Package () { "cirrus,dev-index", Package () { 0x0040, 0x0041 }},
                        Package () { "reset-gpios", Package () {
                           SPKR, One, Zero, Zero,
                           SPKR, One, Zero, Zero
                        } },
                        Package () { "spk-id-gpios", Package () {
                             SPKR, 0x02, Zero, Zero,
                             SPKR, 0x02, Zero, Zero,
                        } },
                        Package () { "cirrus,speaker-position", Package () { Zero, One } },
                        Package () { "cirrus,gpio1-func", Package () { One, One } },
                        Package () { "cirrus,gpio2-func", Package () { 0x02, 0x02 } },
                        // boost-type: 0 internal, 1 external
                        Package () { "cirrus,boost-type", Package () { One, One } },
                        // boost-peak-milliamp: 1600 to 4500, increments of 50 mA
                        //Package () { "cirrus,boost-peak-milliamp",  Package () { 3000, 3000 } },
                        // boost-ind-nanohenry: 1000 | 1200 | 1500 | 2200 nH
                        //Package () { "cirrus,boost-ind-nanohenry",  Package () { 1000, 1000 } },
                        // boost-cap-microfarad: rounded to the nearest integer
                        //Package () { "cirrus,boost-cap-microfarad", Package () { 15, 15 } },
                    }
                }) /* \_SB.I2CB.SPKR._DSD */
        }
    }

    Scope (_SB.I2CB)
    {
        Method (_DSD, 0, NotSerialized)  // _DSD: Device Specific Data
        {
            Return (Package ()
                {
                    ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                    Package ()
                    {
                        Package () { "cs-gpios", Package () { 
                            Zero,                    // Native CS
                            SPKR, Zero, Zero, Zero   // GPIO CS
                        } }
                    }
                }) /* \_SB.I2CB.SPKR._DSD */
        }
    }
}

I had to add SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS UM3504DA", ALC287_FIXUP_CS35L41_I2C_2), to static const struct snd_pci_quirk alc269_fixup_tbl at line 9500 in file sound/pci/hda/patch_realtek.c and compile linux 6.6.2 kernel (never did it before).

In 6.7 there's ALC294_FIXUP_CS35L41_I2C_2 which appears to do the same as ALC287_FIXUP_CS35L41_I2C_2. UM3504 has ALC294 by the way.

Is there anything I can do to make SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS UM3504DA", ALC294_FIXUP_CS35L41_I2C_2), appear in source code of the linux kernel so that I never have to compile it again?

@armeldemarsac92
Copy link

Thanks to you all I got sound working on UM3504DA (Asus Zenbook 15 OLED)!

My dsl file looks like this:

DefinitionBlock ("", "SSDT", 1, "CUSTOM", "CS3551", 0x0000300A)
{

    External (_SB_.I2CB, DeviceObj)
    External (_SB_.I2CB.SPKR, DeviceObj)

    Scope (_SB.I2CB.SPKR)
    {
        Method (_DSD, 0, NotSerialized)  // _DSD: Device Specific Data
        {
            Return (Package ()
                {
                    ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                    Package ()
                    {
                        Package () { "cirrus,dev-index", Package () { 0x0040, 0x0041 }},
                        Package () { "reset-gpios", Package () {
                           SPKR, One, Zero, Zero,
                           SPKR, One, Zero, Zero
                        } },
                        Package () { "spk-id-gpios", Package () {
                             SPKR, 0x02, Zero, Zero,
                             SPKR, 0x02, Zero, Zero,
                        } },
                        Package () { "cirrus,speaker-position", Package () { Zero, One } },
                        Package () { "cirrus,gpio1-func", Package () { One, One } },
                        Package () { "cirrus,gpio2-func", Package () { 0x02, 0x02 } },
                        // boost-type: 0 internal, 1 external
                        Package () { "cirrus,boost-type", Package () { One, One } },
                        // boost-peak-milliamp: 1600 to 4500, increments of 50 mA
                        //Package () { "cirrus,boost-peak-milliamp",  Package () { 3000, 3000 } },
                        // boost-ind-nanohenry: 1000 | 1200 | 1500 | 2200 nH
                        //Package () { "cirrus,boost-ind-nanohenry",  Package () { 1000, 1000 } },
                        // boost-cap-microfarad: rounded to the nearest integer
                        //Package () { "cirrus,boost-cap-microfarad", Package () { 15, 15 } },
                    }
                }) /* \_SB.I2CB.SPKR._DSD */
        }
    }

    Scope (_SB.I2CB)
    {
        Method (_DSD, 0, NotSerialized)  // _DSD: Device Specific Data
        {
            Return (Package ()
                {
                    ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                    Package ()
                    {
                        Package () { "cs-gpios", Package () { 
                            Zero,                    // Native CS
                            SPKR, Zero, Zero, Zero   // GPIO CS
                        } }
                    }
                }) /* \_SB.I2CB.SPKR._DSD */
        }
    }
}

I had to add SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS UM3504DA", ALC287_FIXUP_CS35L41_I2C_2), to static const struct snd_pci_quirk alc269_fixup_tbl at line 9500 in file sound/pci/hda/patch_realtek.c and compile linux 6.6.2 kernel (never did it before).

In 6.7 there's ALC294_FIXUP_CS35L41_I2C_2 which appears to do the same as ALC287_FIXUP_CS35L41_I2C_2. UM3504 has ALC294 by the way.

Is there anything I can do to make SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS UM3504DA", ALC294_FIXUP_CS35L41_I2C_2), appear in source code of the linux kernel so that I never have to compile it again?

awesome ! could you please elaborate a bit on the kernel part ? where you downloaded it and how you edited it ? it would be very nice of you, i have the same model and the sound issue is driving me mad.

@hmyzna
Copy link

hmyzna commented Nov 27, 2023

awesome ! could you please elaborate a bit on the kernel part ? where you downloaded it and how you edited it ? it would be very nice of you, i have the same model and the sound issue is driving me mad.

I downloaded tarball with wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.2.tar.xz, extracted it, copied default arch linux configuration with sudo zcat /proc/config.gz > .config and added a single line SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS UM3504DA", ALC287_FIXUP_CS35L41_I2C_2), to file patch_realtek.c, 9876 on screenshot
image
then built it with the help of this 3 y.o. youtube video.

I barely know what I'm doing so there's probably better way to handle "custom" kernels.

@lamentary
Copy link

Is there anything I can do to make SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS UM3504DA", ALC294_FIXUP_CS35L41_I2C_2), appear in source code of the linux kernel so that I never have to compile it again?

Great work! I'll have to give it a try, as I have the same model. FWIW, if you want to submit it as a kernel patch (as your question seems to indicate), here are the instructions: https://docs.kernel.org/process/submitting-patches.html

@Peter-Ries
Copy link

Finally got it working on ASUS Zenbook 14 OLED Model UX3402VA.

Using Ubuntu 23.10.

Working dsl file looks like this:

DefinitionBlock ("", "SSDT", 1, "CUSTOM", "CSC3551", 0x00000001)
{
    External (_SB_.PC00.SPI0, DeviceObj)
    External (_SB_.PC00.SPI0.SPK1, DeviceObj)

    Scope (_SB.PC00.SPI0.SPK1)
    {
        Name (_DSD, Package ()
        {
            ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
            Package ()
            {
                Package () { "cirrus,dev-index", Package () { Zero, One }},
                Package () { "reset-gpios", Package () {
                    SPK1, One, Zero, Zero,
                    SPK1, One, Zero, Zero
                } },
                Package () { "spk-id-gpios", Package () {
                    SPK1, 0x02, Zero, Zero,
                    SPK1, 0x02, Zero, Zero
                } },
                Package () { "cirrus,speaker-position", Package () { Zero, One } },
                // gpioX-func: 0 not used, 1 VPSK_SWITCH, 2: INTERRUPT, 3: SYNC
                Package () { "cirrus,gpio1-func", Package () { One, One } },
                Package () { "cirrus,gpio2-func", Package () { 0x02, 0x02 } },
                // boost-type: 0 internal, 1 external
                Package () { "cirrus,boost-type", Package () { One, One } }
            }
        })
    }

    Scope (_SB.PC00.SPI0)
    {
        Name (_DSD, Package ()
        {
            ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
            Package ()
            {
                Package () { "cs-gpios", Package () { 
                    Zero,                    // Native CS
                    SPK1, Zero, Zero, Zero   // GPIO CS
                } }
            }
        })
    }
}

Using the commands provided here for Ubuntu/Debain it worked. My mistake was to copy the 01_acpi file into /etc/default/grub.d instead of /etc/grub.d

Furthermore I found out that the Kernel patch to distinguish betweek UX3402ZA and UX3402VA has been added starting with Kernel 6.5.6 so you need a Kernel >= 6.5.6

For Ubuntu 23.10 shipping 6.5.0-xxx at this time I use a mainline kernel for this. Please google for mainline ppa ubuntu. three lines of code then you can use a mainline-gtk interface to easily install a suitable kernel.

So as of thor2002ro git page:

  • create the aml file from my dsl file
  • copy aml file to /boot
  • copy acpi_01 fiel to /etc/grub.d and make it executable
  • get a mainline kernel 6.5.6+
  • sudo update-grub
  • reboot & select kernel
  • have sound :)

Thanks community.

@staropram
Copy link

staropram commented Dec 1, 2023

I'm trying to get sound working on Zenbook UP6502ZD_UP6502ZD. I've tried various dsl variants, but the best I can get is this:

[    0.012272] ACPI: Table Upgrade: install [SSDT-CUSTOM- CSC3551]
[    0.012274] ACPI: SSDT 0x00000000546E6000 0001A0 (v01 CUSTOM CSC3551  00000001 INTL 20200925)
[   11.234682] Serial bus multi instantiate pseudo device driver CSC3551:00: Instantiated 2 SPI devices.
[   11.811372] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: Reset line busy, assuming shared reset
[   11.914416] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: Failed waiting for OTP_BOOT_DONE: -110
[   11.927120] cs35l41-hda: probe of spi0-CSC3551:00-cs35l41-hda.0 failed with error -110
[   11.927667] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: Reset line busy, assuming shared reset
[   12.032348] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: Failed waiting for OTP_BOOT_DONE: -110
[   12.043625] cs35l41-hda: probe of spi0-CSC3551:00-cs35l41-hda.1 failed with error -110

I'm a bit confused about what I can expect to see depending on the absence/presence of the factors.

What is needed to initialise the SPI amplifiers? Just the correct _DSD or do you need that, the firmware, and the kernel patched?

If I get the _DSD correct should I then expect to see non-erroneous output in dmesg or would I also need to have firmware and kernel to see non-erroneous output?

How are people figuring out the correct parameters for the dsl file? (besides the SPI address and SPK name which we get from disassembling the acpidump)

Are people just using random trial and error for things like the reset-gpios parameters? Or is there some logic here? Its a shame we can't just look at the technical spec of the amplifier...

@lamperez
Copy link
Author

lamperez commented Dec 4, 2023

@staropram You should see:

ACPI: Table Upgrade: install [SSDT-CUSTOM- CSC3551]
ACPI: SSDT 0x00000000368FC000 0001A0 (v01 CUSTOM CSC3551  00000001 INTL 20200925)
Serial bus multi instantiate pseudo device driver CSC3551:00: Instantiated 2 SPI devices.
cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: Cirrus Logic CS35L41 (35a40), Revision: B2
cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: Reset line busy, assuming shared reset
cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: Cirrus Logic CS35L41 (35a40), Revision: B2

This means that both amplifiers have been detected and reset, that is, both cs-gpios and reset-gpios are good. Notice that the reset GPIO is the same for both amplifiers, and therefore the message Reset line busy, assuming shared reset. Also for SPI, the first chip select GPIO (cs-gpios) is Zero, meaning the default pin provided by the SPI bus, while the other is another GPIO, specified in the ACPI dump. As a result, typically only one amplifier is reset, but this is not your case.

After this, the next log lines should be about loading the correct firmware files, that must be available (package provided by your distro). If only one amplifier is reset, the kernel refuses to load the firmware and nothing works.

And yes, trial and error was the name of the game to get the first working patch. That, and reading a lot of kernel code and specifications of the SPI bus.

@staropram
Copy link

@lamperez thanks for that! I've got a bit of an odd situation now where I have patched the kernel as the top of https://asus-linux.org/wiki/cirrus-amps/ and then I just defined a _DSD for the cs-gpios section:

DefinitionBlock ("", "SSDT", 1, "CUSTOM", "CSC3551", 0x00000001)
{
    External (_SB_.PC00.SPI1, DeviceObj)
    External (_SB_.PC00.SPI1.SPK1, DeviceObj)

   Scope (_SB.PC00.SPI1)
    {
        Name (_DSD, Package ()
        {
            ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
            Package ()
            {
                Package () { "cs-gpios", Package () {
                    Zero,                    // Native CS
                    SPK1, Zero, Zero, Zero   // GPIO CS
                } }
            }
        })
    }
}

Now I get something a little bid odd from the dmesg output:

$ sudo dmesg | grep CSC
[   11.706278] Serial bus multi instantiate pseudo device driver CSC3551:00: Instantiated 2 SPI devices.
[   12.412121] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: Using extra _DSD properties, bypassing _DSD in ACPI
[   12.461060] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: Cirrus Logic CS35L41 (35a40), Revision: B2
[   12.484874] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: Using extra _DSD properties, bypassing _DSD in ACPI
[   12.484901] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: Reset line busy, assuming shared reset
[   12.587890] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: Failed waiting for OTP_BOOT_DONE: -110
[   12.599850] cs35l41-hda: probe of spi0-CSC3551:00-cs35l41-hda.1 failed with error -110

So now it looks like progress was made but that only the first amplifier has been detected? reset?

It's quite hard to understand if they are both detected and not reset or if only one is detected, and whether I have a problem with the reset-gpios in the patch or the cs-gpios in the _DSD.

What do you think?

@alexVinarskis
Copy link

Dell laptop here, XPS 9530 with SPI connected CS35L41, making some progress thanks to this thread, but there are weird SPI issues - takes ~3 minutes to load the firmware, then it all works. I suspect there are misconfiguration in Dell's ACPI tables wrt to SPI configuration. Anyone by chance had a similar problem?

@Peter-Ries I see that you also have SPI connected amp, and managed to make it work - is there a chance you could share ACPI dumps from your machine? Complete one via sudo acpidump > acpi.log , that would really help. Thanks in advance :)

@AlexeyPashnin1
Copy link

Hey guys! Sorry for asking but I'm ubuntu newbee. I've downloaded the files, what should I do next? Except for killing myself with my new laptop of course

@staropram
Copy link

staropram commented Dec 6, 2023

Hey guys! Sorry for asking but I'm ubuntu newbee. I've downloaded the files, what should I do next? Except for killing myself with my new laptop of course

what laptop do you have: can you share the output of

inxi -MA

This should give us the model and the audio system. You might get lucky and have a laptop that already has bleeding edge kernel integration.

Also:

sudo dmesg | grep CSC

@AlexeyPashnin1
Copy link

Hi @staropram :) Here's the outputs

inxi -MA

Machine:
Type: Laptop System: ASUSTeK product: Zenbook UX3402VA_UX3402VA v: 1.0
serial:
Mobo: ASUSTeK model: UX3402VA v: 1.0 serial:
UEFI: American Megatrends LLC. v: UX3402VA.302 date: 05/23/2023
Audio:
Device-1: Intel Raptor Lake-P/U/H cAVS driver: sof-audio-pci-intel-tgl
API: ALSA v: k6.5.0-13-generic status: kernel-api
Server-1: PipeWire v: 0.3.79 status: active

sudo dmesg | grep CSC

[ 2.103571] Serial bus multi instantiate pseudo device driver CSC3551:00: Instantiated 2 SPI devices.
[ 2.345764] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: Cirrus Logic CS35L41 (35a40), Revision: B2
[ 2.346390] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: Reset line busy, assuming shared reset
[ 2.381187] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: Cirrus Logic CS35L41 (35a40), Revision: B2

Is there a chance to fix it? Thank you!

@staropram
Copy link

staropram commented Dec 7, 2023

@AlexeyPashnin1

You're lucky, it isn't an issue with the CSC3551 in your case as both CS35l41 ppear to be instantiated, and by the looks of it a quirk was added recently for your machine: see this mailing list entry

Was that all the output from dmesg relating to CSC? There should also be some lines about firmware?

In anycase, you can try applying that kernel patch. Follow this tutorial to compile the linux kernel: don't worry the old kernel will still be an option in the boot menu if something goes wrong (make sure you edit /etc/default/grub and comment out the GRUB_TIMEOUT_STYLE=hidden option and then add GRUB_TIMEOUT=10 otherwise you'll never see the boot menu if something was going wrong, then run sudo update-grub to make sure this change is applied).

The patch looks like it is already in the current stable version 6.6.4 if you look here: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/sound/pci/hda/patch_realtek.c?h=v6.6.4#n9892

So it hopefully is as straightforward as compiling and installing the 6.6.4 kernel and it should work.

What kernel are you currently running btw? run uname -a pls

@AlexeyPashnin1
Copy link

@staropram

Was that all the output from dmesg relating to CSC?

Yeah, that's it. I've grepped this now, too
sudo dmesg | grep 'firmware'

[ 1.869087] systemd[1]: systemd-pcrmachine.service - TPM2 PCR Machine ID Measurement was skipped because of an unmet condition check (ConditionPathExists=/sys/firmware/efi/efivars/StubPcrKernelImage-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f).
[ 2.330088] iwlwifi 0000:00:14.3: loaded firmware version 83.e8f84e98.0 so-a0-gf-a0-83.ucode op_mode iwlmvm
[ 2.707903] i915 0000:00:02.0: [drm] Finished loading DMC firmware i915/adlp_dmc.bin (v2.20)
[ 2.729786] i915 0000:00:02.0: [drm] GT0: GuC firmware i915/adlp_guc_70.bin version 70.5.1
[ 2.729797] i915 0000:00:02.0: [drm] GT0: HuC firmware i915/tgl_huc.bin version 7.9.3
[ 2.829317] Bluetooth: hci0: Minimum firmware build 1 week 10 2014
[ 2.839905] Bluetooth: hci0: Found device firmware: intel/ibt-0040-0041.sfi
[ 4.363514] Bluetooth: hci0: Waiting for firmware download to complete
[ 4.405729] iwlwifi 0000:00:14.3: Loaded firmware version: 83.e8f84e98.0 so-a0-gf-a0-83.ucode
[26973.001094] i915 0000:00:02.0: [drm] GT0: GuC firmware i915/adlp_guc_70.bin version 70.5.1
[26973.001098] i915 0000:00:02.0: [drm] GT0: HuC firmware i915/tgl_huc.bin version 7.9.3
[26973.594981] audit: type=1400 audit(1701948974.855:188): apparmor="DENIED" operation="open" class="file" profile="snap.firmware-updater.firmware-notifier" name="/proc/sys/vm/max_map_count" pid=4008 comm="firmware-notifi" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

Follow this tutorial to compile the linux kernel

I've run the command for Debian users (because Ubuntu is Debian-based, if I get it right)
sudo apt install bc binutils bison dwarves flex gcc git gnupg2 gzip libelf-dev libncurses5-dev libssl-dev make openssl pahole perl-base rsync tar xz-utils

downloaded the patch,

then unxz --keep linux-*.tar.xz

then gpg2 --locate-keys [email protected] [email protected] (got the same output as in the manual)

but stuck on the next step gpg2 --verify linux-*.tar.sign with this output

gpg: can't open 'linux-*.tar.sign': No such file or directory
gpg: verify signatures failed: No such file or directory

I was in the Downloads folder. Also tried cd to .gnupg and run the command there - no luck. God, its so embarrassing

Could you please point out to me where I failed?

What kernel are you currently running btw

I've found that previously, sorry that didn't specify it
6.5.0-13-generic

@staropram
Copy link

@AlexeyPashnin1 yes that step isn't particularly clear as you have to manually download the signature from kernel.org homepage it's the link for the kernel you chose called pgp

@kverb
Copy link

kverb commented Dec 7, 2023

[updated solution at the bottom] ux5304va (raptor-lake intel, SPI amp) here still with no sound, and I believe i've grokked all the steps involved. I've followed steps from this gist, asus-linux.org, and Badger's solution, but still have no sound. I'm using EndeavourOS (arch-based) and systemd-boot. I do not have windows dual-booted. In alsamixer / pavucontrol etc, i can see the sound card, the speaker output can be used as a playback device, and its meters show as if sound is playing, but nothing is audible over the speakers.

My output of journalctl -b -g 'hda|audio' --case-sensitive=false --output short-monotonic[1] shows something a little different from @lamperez 's gist - i don't see the cs35l41 firmware being loaded. instead, it appears that sof-audio-pci-intel-tgl is being used. I'm not sure how to override this to use the firmware files from asus-linux's git repo. Uninstalling the sof-firmware package in pacman just results in firmware files not being found.

great info in the comments here, TIA for any guidance.

1:

[    5.426584] zb13 kernel: snd_hda_intel 0000:00:1f.3: Digital mics found on Skylake+ platform, using SOF driver
[    5.514875] zb13 kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: Cirrus Logic CS35L41 (35a40), Revision: B2
[    5.517543] zb13 kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: Reset line busy, assuming shared reset
[    5.559239] zb13 kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: Cirrus Logic CS35L41 (35a40), Revision: B2
[    5.742253] zb13 kernel: sof-audio-pci-intel-tgl 0000:00:1f.3: DSP detected with PCI class/subclass/prog-if info 0x040100
[    5.742324] zb13 kernel: sof-audio-pci-intel-tgl 0000:00:1f.3: Digital mics found on Skylake+ platform, using SOF driver
[    5.742359] zb13 kernel: sof-audio-pci-intel-tgl 0000:00:1f.3: enabling device (0000 -> 0002)
[    5.743009] zb13 kernel: sof-audio-pci-intel-tgl 0000:00:1f.3: DSP detected with PCI class/subclass/prog-if 0x040100
[    7.293260] zb13 kernel: sof-audio-pci-intel-tgl 0000:00:1f.3: bound 0000:00:02.0 (ops i915_audio_component_bind_ops [i915])
[    7.397241] zb13 kernel: sof-audio-pci-intel-tgl 0000:00:1f.3: use msi interrupt mode
[    7.454518] zb13 kernel: sof-audio-pci-intel-tgl 0000:00:1f.3: hda codecs found, mask 5
[    7.454525] zb13 kernel: sof-audio-pci-intel-tgl 0000:00:1f.3: using HDA machine driver skl_hda_dsp_generic now
[    7.454530] zb13 kernel: sof-audio-pci-intel-tgl 0000:00:1f.3: DMICs detected in NHLT tables: 2
[    7.456071] zb13 kernel: sof-audio-pci-intel-tgl 0000:00:1f.3: Firmware info: version 2:2:0-57864
[    7.456075] zb13 kernel: sof-audio-pci-intel-tgl 0000:00:1f.3: Firmware: ABI 3:22:1 Kernel ABI 3:23:0
[    7.456082] zb13 kernel: sof-audio-pci-intel-tgl 0000:00:1f.3: unknown sof_ext_man header type 3 size 0x30
[    7.570438] zb13 kernel: sof-audio-pci-intel-tgl 0000:00:1f.3: Firmware info: version 2:2:0-57864
[    7.570454] zb13 kernel: sof-audio-pci-intel-tgl 0000:00:1f.3: Firmware: ABI 3:22:1 Kernel ABI 3:23:0
[    7.602488] zb13 kernel: sof-audio-pci-intel-tgl 0000:00:1f.3: Topology: ABI 3:22:1 Kernel ABI 3:23:0
[    7.602820] zb13 kernel: skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: Parent card not yet available, widget card binding deferred
[    7.645047] zb13 kernel: snd_hda_codec_realtek ehdaudio0D0: autoconfig for ALC294: line_outs=1 (0x17/0x0/0x0/0x0/0x0) type:speaker
[    7.645054] zb13 kernel: snd_hda_codec_realtek ehdaudio0D0:    speaker_outs=0 (0x0/0x0/0x0/0x0/0x0)
[    7.645056] zb13 kernel: snd_hda_codec_realtek ehdaudio0D0:    hp_outs=1 (0x21/0x0/0x0/0x0/0x0)
[    7.645059] zb13 kernel: snd_hda_codec_realtek ehdaudio0D0:    mono: mono_out=0x0
[    7.645060] zb13 kernel: snd_hda_codec_realtek ehdaudio0D0:    inputs:
[    7.645061] zb13 kernel: snd_hda_codec_realtek ehdaudio0D0:      Headset Mic=0x19
[    8.087668] zb13 kernel: snd_hda_codec_realtek ehdaudio0D0: ASoC: sink widget AIF1TX overwritten
[    8.087689] zb13 kernel: snd_hda_codec_realtek ehdaudio0D0: ASoC: source widget AIF1RX overwritten
[    8.088062] zb13 kernel: skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: sink widget hifi3 overwritten
[    8.088076] zb13 kernel: skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: sink widget hifi2 overwritten
[    8.088087] zb13 kernel: skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: sink widget hifi1 overwritten
[    8.088098] zb13 kernel: skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: source widget Codec Output Pin1 overwritten
[    8.088109] zb13 kernel: skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: sink widget Codec Input Pin1 overwritten
[    8.088125] zb13 kernel: skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: sink widget Analog Codec Playback overwritten
[    8.088140] zb13 kernel: skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: sink widget Digital Codec Playback overwritten
[    8.088156] zb13 kernel: skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: sink widget Alt Analog Codec Playback overwritten
[    8.088182] zb13 kernel: skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: source widget Analog Codec Capture overwritten
[    8.088198] zb13 kernel: skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: source widget Digital Codec Capture overwritten
[    8.088213] zb13 kernel: skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: source widget Alt Analog Codec Capture overwritten
[    8.088247] zb13 kernel: skl_hda_dsp_generic skl_hda_dsp_generic: hda_dsp_hdmi_build_controls: no PCM in topology for HDMI converter 3
[    8.111434] zb13 kernel: input: sof-hda-dsp Headset Mic as /devices/pci0000:00/0000:00:1f.3/skl_hda_dsp_generic/sound/card0/input11
[    8.111595] zb13 kernel: input: sof-hda-dsp Headphone as /devices/pci0000:00/0000:00:1f.3/skl_hda_dsp_generic/sound/card0/input12
[    8.111834] zb13 kernel: input: sof-hda-dsp HDMI/DP,pcm=3 as /devices/pci0000:00/0000:00:1f.3/skl_hda_dsp_generic/sound/card0/input13
[    8.111932] zb13 kernel: input: sof-hda-dsp HDMI/DP,pcm=4 as /devices/pci0000:00/0000:00:1f.3/skl_hda_dsp_generic/sound/card0/input14
[    8.112140] zb13 kernel: input: sof-hda-dsp HDMI/DP,pcm=5 as /devices/pci0000:00/0000:00:1f.3/skl_hda_dsp_generic/sound/card0/input15

update, Dec 9 2023. SOLVED, sort of. In addition to the SSDT and kernel patch, I added to a modprobe.d conf, and sudo depmod -a to rebuild module deps:

options snd-intel-dspcfg dsp_driver=1
options snd-hda-intel model=1043:1c9f

With both of these options enabled, I now get the DSP firmware files loaded and speaker sound works. Still not sure why my firmware is not getting loaded otherwise. My best guess is that I'm not doing the patch to patch_realtek.c correctly, and dmesg output matches similarly to OP's.

@abishekmuthian
Copy link

G634JY Audio success thanks to @alex-spataru & @flukejones . Special mention @v-gu for sharing his trick as well.

After patching the SSDT as per advice of Alex https://gist.github.com/lamperez/862763881c0e1c812392b5574727f6ff?permalink_comment_id=4752975#gistcomment-4752975 and with recent kernel of Luke (6.6.3-666.rog.fc39.x86_64) which has reset_gpio = 1 for 10431CAF the audio is perfect.

intel VMD has to be disabled for fixing the crackling noise (Note if you dual boot Windows, it needs to be enabled each time). Asus doesn't seem to be providing bios profiles for laptops?

dmesg |grep CSC3551
[    0.019249] ACPI: Table Upgrade: install [SSDT-CUSTOM- CSC3551]
[    0.019250] ACPI: SSDT 0x0000000039533000 0002DE (v01 CUSTOM CSC3551  00000002 INTL 20220331)
[   27.382513] Serial bus multi instantiate pseudo device driver CSC3551:00: Instantiated 2 SPI devices.
[   27.523446] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: Using extra _DSD properties, bypassing _DSD in ACPI
[   27.561671] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: Cirrus Logic CS35L41 (35a40), Revision: B2
[   27.561877] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: Using extra _DSD properties, bypassing _DSD in ACPI
[   27.561879] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: Reset line busy, assuming shared reset
[   27.586603] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: Cirrus Logic CS35L41 (35a40), Revision: B2
[   27.646130] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: DSP1: Firmware version: 3
[   27.646134] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: DSP1: cirrus/cs35l41-dsp1-spk-prot-10431caf.wmfw: Fri 27 Aug 2021 14:58:19 W. Europe Daylight Time
[   27.787018] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: DSP1: Firmware: 400a4 vendor: 0x2 v0.43.1, 2 algorithms
[   27.787769] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: DSP1: cirrus/cs35l41-dsp1-spk-prot-10431caf-spkid0-l0.bin: v0.43.1
[   27.787772] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: DSP1: spk-prot: C:\Users\dchunyi\Documents\Asus_ROG\Project\G6_Strix16\Tuning\20220930\G634\10431CAF_220930_V1_A0.bin
[   27.821862] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: CS35L41 Bound - SSID: 10431CAF, BST: 1, VSPK: 1, CH: L, FW EN: 1, SPKID: 0
[   27.821865] snd_hda_codec_realtek hdaudioC0D0: bound spi0-CSC3551:00-cs35l41-hda.0 (ops cs35l41_hda_comp_ops [snd_hda_scodec_cs35l41])
[   27.824017] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: DSP1: Firmware version: 3
[   27.824020] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: DSP1: cirrus/cs35l41-dsp1-spk-prot-10431caf.wmfw: Fri 27 Aug 2021 14:58:19 W. Europe Daylight Time
[   27.963499] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: DSP1: Firmware: 400a4 vendor: 0x2 v0.43.1, 2 algorithms
[   27.964142] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: DSP1: cirrus/cs35l41-dsp1-spk-prot-10431caf-spkid0-r0.bin: v0.43.1
[   27.964144] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: DSP1: spk-prot: C:\Users\dchunyi\Documents\Asus_ROG\Project\G6_Strix16\Tuning\20220930\G634\10431CAF_220930_V1_A1.bin
[   28.003888] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: CS35L41 Bound - SSID: 10431CAF, BST: 1, VSPK: 1, CH: R, FW EN: 1, SPKID: 0
[   28.003891] snd_hda_codec_realtek hdaudioC0D0: bound spi0-CSC3551:00-cs35l41-hda.1 (ops cs35l41_hda_comp_ops [snd_hda_scodec_cs35l41])
[  358.577016] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: DSP1: Failed to read 256 bytes from 2800608: -16

@AlexeyPashnin1
Copy link

AlexeyPashnin1 commented Dec 8, 2023

@staropram when I make sudo gpg2 --locate-keys [email protected] [email protected] i can see this path with the .pgp in the output /root/.gnupg/trustdb.gpg

Oh, I saw the mistake after I wrote this: you told about the pgp link, not gpg. Then I don't see anything like it :(

gpg: directory '/root/.gnupg' created
gpg: keybox '/root/.gnupg/pubring.kbx' created
gpg: /root/.gnupg/trustdb.gpg: trustdb created
gpg: key 38DBBDC86092693E: public key "Greg Kroah-Hartman [email protected]" imported
gpg: Total number processed: 1
gpg: imported: 1
gpg: key 79BE3E4300411886: public key "Linus Torvalds [email protected]" imported
gpg: Total number processed: 1
gpg: imported: 1
pub rsa4096 2011-09-23 [SC]
647F28654894E3BD457199BE38DBBDC86092693E
uid [ unknown] Greg Kroah-Hartman [email protected]
sub rsa4096 2011-09-23 [E]

pub rsa2048 2011-09-20 [SC]
ABAF11C65A2970B130ABE3C479BE3E4300411886
uid [ unknown] Linus Torvalds [email protected]
sub rsa2048 2011-09-20 [E]

but when I try gpg2 --verify /root/.gnupg/trustdb.gpg as a superuser I get the following

gpg: no valid OpenPGP data found.
gpg: the signature could not be verified.
Please remember that the signature file (.sig or .asc)
should be the first file given on the command line.

Or did I misunderstand you and something else needs to be done with this file?

UPD: I get that I need to load the archive and .sign file. Now I'm in the process of finding the suitable for 6.5.0-13-generic

UPD2: got the linux_6.5.0.orig.tar.gz package from https://launchpad.net/ubuntu/+source/linux/6.5.0-13.13, but the unxz linux_6.5.0.orig.tar.gz returns

unxz: linux_6.5.0.orig.tar.gz: File format not recognized

And also I can't find the .sign file for this :(

@staropram
Copy link

staropram commented Dec 8, 2023

@AlexeyPashnin1 hi

Checking the signature isn't strictly necessary depending on how paranoid you are. You are checking that the kernel source tar is signed by one of the kernel devs so that there hasn't been a man-in-the-middle attack. I think this is unlikely but is always wise to be cautious as the kernel would be the perfect place to put a rootkit. You should see output like this:

ash@sparky2:~/kernel$ ls | grep 6.6.3
linux-6.6.3
linux-6.6.3.tar
linux-6.6.3.tar.sign
linux-6.6.3.tar.xz

ash@sparky2:~/kernel$ gpg2 --verify linux-*.tar.sign
gpg: assuming signed data in 'linux-6.6.3.tar'
gpg: Signature made Tue 28 Nov 2023 17:21:00 GMT
gpg:                using RSA key 647F28654894E3BD457199BE38DBBDC86092693E
gpg: Good signature from "Greg Kroah-Hartman <[email protected]>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 647F 2865 4894 E3BD 4571  99BE 38DB BDC8 6092 693E

The WARNING it gives can be ignored if we are sure we trust Greg and that really is his signature. You'll see this fingerprint everywhere associated with him so we can safely assume it is him (or someone is able to impersonate him over multiple years and trusted positions, at which point it may as well be him).

Once you know your tar is legit, you can proceed.

Why are you trying to find 6.5.0-13-generic? Just use 6.6.5 directly from kernel.org. Unless there is some specific reason you need 6.5.0-13-generic?

@AlexeyPashnin1
Copy link

AlexeyPashnin1 commented Dec 8, 2023

@staropram Hi!

From your previous answer, I understood that I need to download a different version. Obviously, I got it wrong.

I'm still at the verifying step and I don't know what I need to do to get off it. Did I understand correctly that it is optional? gpg2 --verify linux-*.tar.sign.

I'm not paranoid and just want to hear the sound on the laptop, but I get the No such file or directory output and does it make sense to move to the next step?

UPD: I tried to go from the beginning.

  1. downloaded the linux-6.6.5.tar.xz
  2. unxz --keep linux-*.tar.xz
  3. the linux-6.6.5.tar archive has appeared in the Downloads folder
  4. unpacked it
  5. cd to the Downloads/linux-6.6.5/kernel
  6. ls | grep 6.6.5 - nothing
  7. gpg2 --verify linux-*.tar.sign - No such file or directory

Obviously, I don't understand some basic things, but I won't jump over this wall without help. I'm sorry if I'm being stupid.

UPD2: I just skipped this step and followed the commands further along the manual. I broke the system, now it doesn't boot. Reinstalling it.
R.I.P.

@alexVinarskis
Copy link

alexVinarskis commented Dec 8, 2023

Not sure you guys were familiar with it - i was debugging Dell's Cirrus amps over SPI, which were also missing cs-gpios, and found a way to set them from kernel patch, no more need for .dsl at all

From what i saw above, some of Asus models with SPI also are missing cs-gpio pins, and on top of your upcoming kernel patch required smaller .dsl overwrite. This should help you fix it:

From c814d07190a645dcce33e4407c6f6d8bb7ebaef2 Mon Sep 17 00:00:00 2001
From: Aleksandrs Vinarskis <[email protected]>
Date: Mon, 4 Dec 2023 19:16:18 +0100
Subject: [PATCH] ALSA: hda: cs35l41: Dell Fiorano add missing _DSD properties

---
 sound/pci/hda/cs35l41_hda_property.c | 39 ++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c
index c83328971728..066ec38e3d3c 100644
--- a/sound/pci/hda/cs35l41_hda_property.c
+++ b/sound/pci/hda/cs35l41_hda_property.c
@@ -8,6 +8,7 @@
 
 #include <linux/gpio/consumer.h>
 #include <linux/string.h>
+#include <linux/spi/spi.h>
 #include "cs35l41_hda_property.h"
 
 /*
@@ -43,6 +44,43 @@ static int lenovo_legion_no_acpi(struct cs35l41_hda *cs35l41, struct device *phy
 	return 0;
 }
 
+/*
+ * Device 10280BEB (Dell XPS 9530) doesn't have _DSD at all. Moreover, pin that is typically
+ * used for `speaker_id` is missing.
+ * The CSC3551 is SPI connected. Since chip select GPIOs are not present either, at the
+ * moment 10280BEB requires an ACPI table patch in addition to this patch.
+ */
+static int dell_fiorano_no_acpi(struct cs35l41_hda *cs35l41, struct device *physdev, int id,
+				const char *hid)
+{
+	struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;
+
+	dev_info(cs35l41->dev, "Adding DSD properties for %s\n", cs35l41->acpi_subsystem_id);
+
+	/* check SPI address to assign the index */
+	cs35l41->index = id;
+	cs35l41->channel_index = 0;
+	/* 10280BEB is missing pin which is typically assigned to `spk-id-gpios` */
+	cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, cs35l41->index, 2, -1);
+	cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 1, GPIOD_OUT_LOW);
+
+	hw_cfg->spk_pos = cs35l41->index  ? 1 : 0;	// 0th L, 1st R
+	hw_cfg->bst_type = CS35L41_EXT_BOOST;
+	hw_cfg->gpio1.func = CS35l41_VSPK_SWITCH;
+	hw_cfg->gpio1.valid = true;
+	hw_cfg->gpio2.func = CS35L41_INTERRUPT;
+	hw_cfg->gpio2.valid = true;
+	hw_cfg->valid = true;
+
+	/* Add second cs-gpio here */
+	if (cs35l41->index) {
+		struct spi_device *spi = to_spi_device(cs35l41->dev);
+		spi->cs_gpiod = gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH);
+	}
+
+	return 0;
+}
+
 /*
  * Device 103C89C6 does have _DSD, however it is setup to use the wrong boost type.
  * We can override the _DSD to correct the boost type here.
@@ -92,6 +130,7 @@ static const struct cs35l41_prop_model cs35l41_prop_model_table[] = {
 	{ "CLSA0100", NULL, lenovo_legion_no_acpi },
 	{ "CLSA0101", NULL, lenovo_legion_no_acpi },
 	{ "CSC3551", "103C89C6", hp_vision_acpi_fix },
+	{ "CSC3551", "10280BEB", dell_fiorano_no_acpi },
 	{}
 };
 
-- 
2.40.1


Particularly:

include <linux/spi/spi.h>
...

	if (cs35l41->index) {
		struct spi_device *spi = to_spi_device(cs35l41->dev);
		spi->cs_gpiod = gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH);
	}

this adds 0th pin from ACPI table to as 2nd amp's chipselect. 1st amp uses native chip select by default, which makes it equivalent to:

Scope (_SB.SPI2)
    {
        Method (_DSD, 0, NotSerialized)  // _DSD: Device Specific Data
        {
            Return (Package ()
                {
                    ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                    Package ()
                    {
                        Package () { "cs-gpios", Package () { 
                            Zero,                    // Native CS
                            SPKR, Zero, Zero, Zero   // GPIO CS
                        } }
                    }
                }) /* \_SB.SPI2.SPKR._DSD */
        }
    }

Hope this helps!

@staropram
Copy link

@AlexeyPashnin1 the reason the command doesn't work is because the signature file isn't there.

Say you download 6.6.5 from kernel.org then you also need the signature file, which for 6.6.5 is this on kernel.org this is the file called pgp that is on the same line as 6.6.5, does that make sense? Now the verification should work

@staropram
Copy link

@alexVinarskis that's cool, thanks, it's quite similar to luke's patch here except you are also setting the 2nd CS, I will give that a go.

Is id always 0 on the first call and then 1 on the subsequent call? Presumably, would make sense.

How did you figure out that for your device you needed cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 1, GPIOD_OUT_LOW); for the 1st chip and spi->cs_gpiod = gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH); for the 2nd chip? How did you know this corresponds to those _DSD settings?

I feel like I'm missing some information others seem to have, did you manage to get the spec sheet or something?

@alexVinarskis
Copy link

@staropram unfortunately I do not have anymore information, most of my cirrus knowladge comes from this thread, and luke's patch you have posted.

it's quite similar to luke's patch here except you are also setting the 2nd CS, I will give that a go.

Correct, its mostly similar to Luke's patch, and to HP patch that Cirrus devs already added to the file. Minor differnces in pin configs

Is id always 0 on the first call and then 1 on the subsequent call? Presumably, would make sense.

yes seems that the order of initialization. One may change which one is left, which is right, but seems matching id with index is correct way to go

How did you figure out that for your device you needed cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 1, GPIOD_OUT_LOW); for the 1st chip and spi->cs_gpiod = gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH);

Some confusion here - both chips have reset pins, and both chips need chip select pin.

The pin number (Zero, One, 0x02 for .dsl, and gpiod_get_index(physdev, NULL, XX, GPIOD_OUT_LOW); - XX in kernel) represent order of pins in ACPI table. You first see x2 SPI/I2C identifiers, then followed by 4 or 5 pins definitions - these pins shall be allocated to functions.

Last two pins are the same pin (check by hex number), which are also shared - this seems to be interrupt, and we do not need to allocated them. It leaves us with 3 pins (for most of you) or 2 pins (for my unlucky case) to allocated.

Seems that on all dual CS amps system reset line is shared. Reset line is output and it is active HIGH (electronics), so default state is PullDown (.dsl) or GPIOD_OUT_LOW (kernel). That means both chips would have the same entry of cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 1, GPIOD_OUT_LOW); for those who have reset pin 1st (seems that SPI devices have chip select pin 0th, while for I2C devices reset is 0th, but you guys already figured this one out :)

Next, for SPI devices there shall be chip select pin. The way it works is the SPI controller has one native chip select, but you have two chips, so there need to be two pins to talk to two chips - one is used by default (SPI controller's native one), and it opens connection to 1st instance of driver (whichever device has id 0). Second pin is generic motherboard pin which shall be allocated for SPI driver to know that - which is why you would require .dsl patch to add SPKR, Zero, Zero, Zero - here 1st Zero you see is 0th pin from ACPI table. Easy way to tell which one it is that chip select is active low (again electronics), so default state would be PullUp/GPIOD_OUT_HIGH. It is also an Output pin. Taking a glance at ACPI pins order, for devices with SPI its the 0th entry.

Thus, in my patch i added the code

if (cs35l41->index) {
		struct spi_device *spi = to_spi_device(cs35l41->dev);
		spi->cs_gpiod = gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH);
	}

=> non-0 index (aka index=1) set chip select to 0th pin from ACPI table, in 'PullUp' mode. Strictly speaking probably even if you set it low instead, and same for reset, it would still work, as driver starts fast and switch them to correct mode. Doesn't hurt to be correct though. The reason 0th chip did not need to specify pin select is because every SPI master has one native chip select pin, and would use that one on its own, assuming its connected somewhere. For any more pins, someone has to inform it about.

Finally, in your cases guys, SPI devices have 5th pin, which in ACPI is indicated as InputOnly, meaning it can be used for reading data in - its index 0x02 for you. That is the only pin which can be used as spk-id pin, and is also likely shared for both ICs. In my case, that pin is simply missing, similarly to HP device which Cirrus dev's already added. Which is why in my case I call internal function with different parameters (id of current chip, total number of chips, and negative pin number, so that it will not use external pin for that), which evaluated to SPK_ID=-19, and loads firmware without _spkidX_ prefix in its name.

To summarize, i believe all you have to do is to add my code extract above to all SPI powered devices (if you do it to I2C device, it will likely crash), without any modification, and it should just work without .dsl. Only exception would be if there is different pin order in ACPI table, but i believe with info i wrote above one shall be able to easily identify which pin is used for what

@staropram
Copy link

staropram commented Dec 8, 2023

@alexVinarskis you're a genius! by adding

if (cs35l41->index) {
		struct spi_device *spi = to_spi_device(cs35l41->dev);
		spi->cs_gpiod = gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH);
}

it appears as if both cs35l41 are initialised:

$ sudo dmesg | grep CSC
[   11.824760] Serial bus multi instantiate pseudo device driver CSC3551:00: Instantiated 2 SPI devices.
[   12.579937] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: Calling cs35l41_hda_probe
[   12.580115] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: Adding DSD properties for 10431DA2
[   12.580857] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: Using extra _DSD properties, bypassing _DSD in ACPI
[   12.629292] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: Cirrus Logic CS35L41 (35a40), Revision: B2
[   12.629833] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: Calling cs35l41_hda_probe
[   12.630020] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: Adding DSD properties for 10431DA2
[   12.631180] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: Using extra _DSD properties, bypassing _DSD in ACPI
[   12.631197] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: Reset line busy, assuming shared reset
[   12.674447] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: Cirrus Logic CS35L41 (35a40), Revision: B2

Sound still doesn't work as I still see no speaker:

$ sudo dmesg | grep speaker
[   13.045871] snd_hda_codec_realtek ehdaudio0D0: autoconfig for ALC294: line_outs=1 (0x17/0x0/0x0/0x0/0x0) type:speaker
[   13.045881] snd_hda_codec_realtek ehdaudio0D0:    speaker_outs=0 (0x0/0x0/0x0/0x0/0x0)

Not sure why it's not working. I tried adding ALC294_FIXUP_ASUS_DUAL_SPK to patch_realtek.c for my model but I am completely guessing at this point so I've deleted that.

My current speaker Id line is this: cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, 0, 0, 2); since that was from another patch. I'm guessing this is incorrect and this is why I don't init speakers.

@alexVinarskis
Copy link

@staropram indeed you would need ALC294_FIXUP_ASUS_DUAL_SPK or something similar to a) do 0x17 quirk and b) initialize x2 SPI instances of the Cirrus - as per your dmesg there is no firmware loading attempt. ALC245_FIXUP_CS35L41_SPI_2 should enable firmware loading - try it, and you should see firmware loading in dmesg, altough most likely speakers still will not work due to missing 0x17 quirk

In that case, try something similar to ALC289_FIXUP_DELL_CS35L41_SPI_2 in this commit - you need to create new function which chains ALC245_FIXUP_CS35L41_SPI_2 and ALC294_FIXUP_ASUS_DUAL_SPK

@staropram
Copy link

@alexVinarskis it works!! The speakers actually work!

ALC245_FIXUP_CS35L41_SPI_2 quirk was the final piece of the puzzle! Thank you so much for your help.

@armeldemarsac92
Copy link

awesome ! could you please elaborate a bit on the kernel part ? where you downloaded it and how you edited it ? it would be very nice of you, i have the same model and the sound issue is driving me mad.

I downloaded tarball with wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.2.tar.xz, extracted it, copied default arch linux configuration with sudo zcat /proc/config.gz > .config and added a single line SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS UM3504DA", ALC287_FIXUP_CS35L41_I2C_2), to file patch_realtek.c, 9876 on screenshot image then built it with the help of this 3 y.o. youtube video.

I barely know what I'm doing so there's probably better way to handle "custom" kernels.

I finally got it working thanks to your explanations and those from Sir Desjardin ! Thanks a lot 👍

@jnbrunet
Copy link

jnbrunet commented Dec 9, 2023

Hey all,

I've got an asus UX7602Z (no M at the end) and I'm trying to make the sound work. Following this tutorial by @alex-spataru for the asus UX7602ZM, along with installing the 6.7.rc4 kernel on my fedora 39, the sound is much better than before (much louder).

However it is still not completely right. It looks like I have only 3 or 4 sound "volume stage", each time I have to turn the volume up a couple of time for it to finally change and jump to another sound "volume stage". It is also a bit distorted.

I have the following log using journalctl -b -g CSC3551 --output short-monotonic:

[    0.013934] fedora kernel: ACPI: SSDT 0x000000004D5FE6D3 0002D6 (v01 CUSTOM CSC3551  00000003 INTL 20220331)
[    7.583769] fedora kernel: Serial bus multi instantiate pseudo device driver CSC3551:00: Instantiated 2 SPI devices.
[    7.833083] fedora kernel: cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: Cirrus Logic CS35L41 (35a40), Revision: B2
[    7.834786] fedora kernel: cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: Reset line busy, assuming shared reset
[    7.876442] fedora kernel: cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: Cirrus Logic CS35L41 (35a40), Revision: B2
[    8.237378] fedora kernel: cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: Falling back to default firmware.
[    8.239523] fedora kernel: cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: DSP1: Firmware version: 3
[    8.239525] fedora kernel: cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: DSP1: cirrus/cs35l41-dsp1-spk-prot.wmfw: Fri 24 Jun 2022 14:55:56 GMT Daylight Time
[    8.392367] fedora kernel: cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: DSP1: Firmware: 400a4 vendor: 0x2 v0.58.0, 2 algorithms
[    8.393684] fedora kernel: cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: DSP1: cirrus/cs35l41-dsp1-spk-prot.bin: v0.58.0
[    8.393687] fedora kernel: cs35l41-hda spi0-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\Fix>
[    8.417152] fedora kernel: cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: CS35L41 Bound - SSID: 10431F62, BST: 1, VSPK: 1, CH: L, FW EN: 1, SPKID: 0
[    8.417161] fedora kernel: snd_hda_codec_realtek ehdaudio0D0: bound spi0-CSC3551:00-cs35l41-hda.0 (ops cs35l41_hda_comp_ops [snd_hda_scodec_cs35l41])
[    8.417307] fedora kernel: cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: Falling back to default firmware.
[    8.419473] fedora kernel: cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: DSP1: Firmware version: 3
[    8.419476] fedora kernel: cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: DSP1: cirrus/cs35l41-dsp1-spk-prot.wmfw: Fri 24 Jun 2022 14:55:56 GMT Daylight Time
[    8.559588] fedora kernel: cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: DSP1: Firmware: 400a4 vendor: 0x2 v0.58.0, 2 algorithms
[    8.560734] fedora kernel: cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: DSP1: cirrus/cs35l41-dsp1-spk-prot.bin: v0.58.0
[    8.560736] fedora kernel: cs35l41-hda spi0-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\Fix>
[    8.586371] fedora kernel: cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: CS35L41 Bound - SSID: 10431F62, BST: 1, VSPK: 1, CH: R, FW EN: 1, SPKID: 0
[    8.586378] fedora kernel: snd_hda_codec_realtek ehdaudio0D0: bound spi0-CSC3551:00-cs35l41-hda.1 (ops cs35l41_hda_comp_ops [snd_hda_scodec_cs35l41])

Any idea what could be going on here?

@staropram
Copy link

staropram commented Dec 9, 2023

@jnbrunet this might be a red herring but does Falling back to default firmware mean that it isn't using the exact firmware for your machine? I actually get the same and I do wonder why this is as I did copy the firmware files.

Looking at the function cs35l41_request_firmware_files in cs35141_hda.c the function cs35l41_fallback_firmware_file which outputs our message is only called if all the various ways of looking up the firmware fail. So, let us examine these outputs. I will add a printout to cs35l41_request_firmware_file :

printk(KERN_INFO "Stripped firmware name: \"%s\"\n",*filename);

Just after it constructs the filename and strips it to see what it is actually looking for. Rebooted and this is the output:

[   13.074470] Stripped firmware name: "cirrus/cs35l41-dsp1-spk-prot-10431da2-l0.wmfw"
[   13.076476] Stripped firmware name: "cirrus/cs35l41-dsp1-spk-prot-10431da2.wmfw"
[   13.078222] Stripped firmware name: "cirrus/cs35l41-dsp1-spk-prot-10431da2-l0.bin"
[   13.079021] Stripped firmware name: "cirrus/cs35l41-dsp1-spk-prot-10431da2.bin"
[   13.079636] Stripped firmware name: "cirrus/cs35l41-dsp1-spk-prot.wmfw"
[   13.080231] Stripped firmware name: "cirrus/cs35l41-dsp1-spk-prot.bin"

And what do I have:

# ls -l /lib/firmware/cirrus/ | grep 10431da2
-rw-r--r-- 1 root root  1152 Dec  1 21:25 cs35l41-dsp1-spk-cali-10431da2-spkid1-l0.bin.zst
-rw-r--r-- 1 root root  1150 Dec  1 21:25 cs35l41-dsp1-spk-cali-10431da2-spkid1-r0.bin.zst
lrwxrwxrwx 1 root root    73 Dec  1 21:27 cs35l41-dsp1-spk-cali-10431da2.wmfw -> /lib/firmware/cirrus/cs35l41/v6.61.1/halo_cspl_RAM_revB2_29.63.1.wmfw.zst
lrwxrwxrwx 1 root root    73 Dec  1 21:28 cs35l41-dsp1-spk-cali-10431da2.wmfw.zst -> /lib/firmware/cirrus/cs35l41/v6.61.1/halo_cspl_RAM_revB2_29.63.1.wmfw.zst
-rw-r--r-- 1 root root  2869 Dec  1 21:25 cs35l41-dsp1-spk-prot-10431da2-spkid1-l0.bin.zst
-rw-r--r-- 1 root root  2873 Dec  1 21:25 cs35l41-dsp1-spk-prot-10431da2-spkid1-r0.bin.zst
lrwxrwxrwx 1 root root    73 Dec  9 08:14 cs35l41-dsp1-spk-prot-10431da2.wmfw -> /lib/firmware/cirrus/cs35l41/v6.83.0/halo_cspl_RAM_revB2_29.85.0.wmfw.zst
lrwxrwxrwx 1 root root    73 Dec  1 21:28 cs35l41-dsp1-spk-prot-10431da2.wmfw.zst -> /lib/firmware/cirrus/cs35l41/v6.61.1/halo_cspl_RAM_revB2_29.63.1.wmfw.zst

So not sure what is going on here, only filename that would directly match is cirrus/cs35l41-dsp1-spk-prot-10431da2.wmfw so I wonder if its symlink is wrong as there are several options:

# ls /lib/firmware/cirrus/cs35l41/
v6.39.0  v6.47.0  v6.61.1  v6.63.0  v6.78.0  v6.83.0

I will try symlinking my matching file to the latest version.

...OK that didn't work.

but I would guess either this is your issue or there is some quirk you need in patch_realtek.c. I'll see if I can fix this firmware issue later (my sound works fine but I wonder if it would sound better if the correct firmware was loaded).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment