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
} }
}
})
}
}
@fermino
Copy link

fermino commented May 6, 2023

I just bought a new Zephyrus G16 2023 - GU603VI.

Can this patch also apply for my device? I'm running Arch along with kernel and support from asus-linux.org , and before that speakers were great on Windows. Where did you find informaton about which sound amplifier is used? I don't want to blow my speakers / fk up my device. Thanks

It's a long long shot but would you mind posting the complete output of dmesg? Maybe uploading it to pastebin or something like that.

@fermino
Copy link

fermino commented May 6, 2023

@v4yne1 there is a brief mention in the specs page about a "smart amp" that could or could not be a cirrus amplifier. I haven't been able to find anything else besides that, but with the kernel output we might be able to figure it out :)

@Syraxius
Copy link

Syraxius commented May 6, 2023

Hi @v4yne1 @fermino

I'm on Zephyrus M16 2023 - GU604VI (Singapore set) and got it working last month using this patch as well as several other hacks.

This patch itself is not enough as you also have to install the right firmwares and patch kernel to apply the right quirks.

A quick summary of all the steps and resources required are here:
https://forums.linuxmint.com/viewtopic.php?p=2315036

(BTW, huge thanks to all you guys and your awesome work! :D)

@v4yne1
Copy link

v4yne1 commented May 6, 2023

dmesg

@fermino , Sure, here you go https://pastebin.com/6AeM96Gz

[    3.343851] cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: Error: ACPI _DSD Properties are missing for HID CSC3551.
[    3.343854] cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: error -EINVAL: Platform not supported
[    3.343855] cs35l41-hda: probe of spi1-CSC3551:00-cs35l41-hda.0 failed with error -22
[    3.345544] cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: Error: ACPI _DSD Properties are missing for HID CSC3551.
[    3.345546] cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: error -EINVAL: Platform not supported
[    3.345548] cs35l41-hda: probe of spi1-CSC3551:00-cs35l41-hda.1 failed with error -22
[    3.345564] Serial bus multi instantiate pseudo device driver CSC3551:00: Instantiated 2 SPI devices.

@Syraxius hey! Yes, I saw your post. Can you maybe leave your Discord # ? I already tried following your tutorial but got stuck at one point

@armangurkan
Copy link

armangurkan commented May 7, 2023

I have a ROG Strix G614JI and I am running Pop_OS followed the initial guideline. But no luck, I am not defining ACPI tables, I really appreciate any help at this point. Regardless, I believe I have done it correctly.

@kingcong1
Copy link

kingcong1 commented May 7, 2023

Hi, I have a UP6502ZA which should be the same amp setup as the UX3402. I tried applying the SSDT patch with no luck. Any suggestions on how I may be able to modify the patch for my laptop?

dmesg output:

[ 15.634790] Serial bus multi instantiate pseudo device driver CSC3551:00: Instantiated 2 SPI devices.
[ 16.294877] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: Error: ACPI _DSD Properties are missing for HID CSC3551.
[ 16.294893] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: error -EINVAL: Platform not supported
[ 16.294903] cs35l41-hda: probe of spi0-CSC3551:00-cs35l41-hda.0 failed with error -22
[ 16.299306] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: Error: ACPI _DSD Properties are missing for HID CSC3551.
[ 16.299317] cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: error -EINVAL: Platform not supported
[ 16.299325] cs35l41-hda: probe of spi0-CSC3551:00-cs35l41-hda.1 failed with error -22

@lamperez
Copy link
Author

lamperez commented May 8, 2023

@kingcong1, @armangurkan have you applied the SSDT patch? Try dmesg | grep SSDT. It should show lines like these

ACPI: SSDT ACPI table found in initrd [kernel/firmware/acpi/ssdt_csc3551.aml][0x1a0]
ACPI: SSDT 0x0000000040AC0000 00740E (v02 DptfTb DptfTabl 00001000 INTL 20200717)
(...)
ACPI: Reserving SSDT table memory at [mem 0x40ac0000-0x40ac740d]
(...)
ACPI: Table Upgrade: install [SSDT-CUSTOM- CSC3551]
(...)
ACPI: SSDT 0x00000000368FD000 0001A0 (v01 CUSTOM CSC3551  00000001 INTL 20200925)
(...)

If not, you should review what you have done.

@kingcong1
Copy link

@lamperez, I ran that command and came up with the following output:

[ 0.009900] ACPI: SSDT 0x000000004CD692AB 0001A7 (v01 CUSTOM CS3551 0000300A INTL 20220331)
[ 0.009913] ACPI: SSDT 0x000000004CD6A179 000144 (v02 Intel ADebTabl 00001000 INTL 20200717)
[ 0.009915] ACPI: SSDT 0x000000004CD6A2BD 0035A2 (v02 SocCmn SocCmn 00003000 INTL 20200717)
[ 0.009916] ACPI: SSDT 0x000000004CD6D85F 003AEA (v02 SocGpe SocGpe 00003000 INTL 20200717)
[ 0.009920] ACPI: SSDT 0x000000004CD713D1 000D89 (v02 ASUS UsbCTabl 00001000 INTL 20200717)
[ 0.009925] ACPI: SSDT 0x000000004CD721E2 002357 (v02 ASUS TbtTypeC 00000000 INTL 20200717)
[ 0.009930] ACPI: SSDT 0x000000004CD76167 00AD09 (v02 ASUS AdlP_Rvp 00001000 INTL 20200717)
[ 0.009932] ACPI: SSDT 0x000000004CD80E70 0002A6 (v02 ASUS TcssSsdt 00000000 INTL 20200717)
[ 0.009934] ACPI: SSDT 0x000000004CD81116 0001A4 (v01 ASUS SPKRAMPS 00000002 INTL 20200717)
[ 0.009940] ACPI: SSDT 0x000000004CD8150A 00D39F (v02 INTEL TcssSsdt 00001000 INTL 20200717)
[ 0.009942] ACPI: SSDT 0x000000004CD8E8A9 0033D3 (v02 INTEL IgfxSsdt 00003000 INTL 20200717)
[ 0.009944] ACPI: SSDT 0x000000004CD91C7C 002AA1 (v02 SaSsdt SaSsdt 00003000 INTL 20200717)
[ 0.009946] ACPI: SSDT 0x000000004CD9471D 005D0B (v02 CpuRef CpuSsdt 00003000 INTL 20200717)
[ 0.009947] ACPI: SSDT 0x000000004CD9A428 00038C (v02 PmaxDv Pmax_Dev 00000001 INTL 20200717)
[ 0.009954] ACPI: SSDT 0x000000004CD9A966 006D68 (v02 DptfTa DptfTabl 00001000 INTL 20200717)
[ 0.009963] ACPI: Reserving SSDT table memory at [mem 0x4cd692ab-0x4cd69451]
[ 0.009967] ACPI: Reserving SSDT table memory at [mem 0x4cd6a179-0x4cd6a2bc]
[ 0.009968] ACPI: Reserving SSDT table memory at [mem 0x4cd6a2bd-0x4cd6d85e]
[ 0.009969] ACPI: Reserving SSDT table memory at [mem 0x4cd6d85f-0x4cd71348]
[ 0.009970] ACPI: Reserving SSDT table memory at [mem 0x4cd713d1-0x4cd72159]
[ 0.009971] ACPI: Reserving SSDT table memory at [mem 0x4cd721e2-0x4cd74538]
[ 0.009973] ACPI: Reserving SSDT table memory at [mem 0x4cd76167-0x4cd80e6f]
[ 0.009973] ACPI: Reserving SSDT table memory at [mem 0x4cd80e70-0x4cd81115]
[ 0.009974] ACPI: Reserving SSDT table memory at [mem 0x4cd81116-0x4cd812b9]
[ 0.009976] ACPI: Reserving SSDT table memory at [mem 0x4cd8150a-0x4cd8e8a8]
[ 0.009976] ACPI: Reserving SSDT table memory at [mem 0x4cd8e8a9-0x4cd91c7b]
[ 0.009977] ACPI: Reserving SSDT table memory at [mem 0x4cd91c7c-0x4cd9471c]
[ 0.009977] ACPI: Reserving SSDT table memory at [mem 0x4cd9471d-0x4cd9a427]
[ 0.009978] ACPI: Reserving SSDT table memory at [mem 0x4cd9a428-0x4cd9a7b3]
[ 0.009980] ACPI: Reserving SSDT table memory at [mem 0x4cd9a966-0x4cda16cd]
[ 0.377299] ACPI: SSDT 0xFFFF9ED6C23EAA00 0001AB (v02 PmRef Cpu0Psd 00003000 INTL 20200717)
[ 0.387268] ACPI: SSDT 0xFFFF9ED6C0FE8800 000394 (v02 PmRef Cpu0Cst 00003001 INTL 20200717)
[ 0.388893] ACPI: SSDT 0xFFFF9ED6C23B8800 000626 (v02 PmRef Cpu0Ist 00003000 INTL 20200717)
[ 0.390694] ACPI: SSDT 0xFFFF9ED6C23BF800 0004BA (v02 PmRef Cpu0Hwp 00003000 INTL 20200717)
[ 0.392722] ACPI: SSDT 0xFFFF9ED6C0FC6000 001BAF (v02 PmRef ApIst 00003000 INTL 20200717)
[ 0.395265] ACPI: SSDT 0xFFFF9ED6C0FC0000 001038 (v02 PmRef ApHwp 00003000 INTL 20200717)
[ 0.397366] ACPI: SSDT 0xFFFF9ED6C0FC2000 001349 (v02 PmRef ApPsd 00003000 INTL 20200717)
[ 0.399520] ACPI: SSDT 0xFFFF9ED6C23B2000 000FBB (v02 PmRef ApCst 00003000 INTL 20200717}

@lamperez
Copy link
Author

lamperez commented May 9, 2023

@kingcong1 The lines about SSDT ACPI table found and Table upgrade are missing in your log: your system is not applying any patch.

@thor2002ro
Copy link

thor2002ro commented May 9, 2023

apart from SSDT you need patched kernel for it to work... For our Asus laptop its in the mainline already.... different laptops might not be....

here's the patch https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/sound/pci/hda/patch_realtek.c?h=v6.4-rc1&id=491a4ccd8a0258392900c80c6b2b622c7115fc23
we have 2 amplifiers on spi bus others have them on i2c
you cant just copy/paste and they will work spi and i2c are not that plug and play....

you can also look at the file history to see if the laptop has been added https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/log/sound/pci/hda/patch_realtek.c?h=v6.4-rc1
or search for the sound card id

@brybinski
Copy link

Got it working by applying kernel patch on asus ux3402VA

SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS UX3402", ALC245_FIXUP_CS35L41_SPI_2),

@armangurkan
Copy link

@kingcong1, @armangurkan have you applied the SSDT patch? Try dmesg | grep SSDT. It should show lines like these

ACPI: SSDT ACPI table found in initrd [kernel/firmware/acpi/ssdt_csc3551.aml][0x1a0]
ACPI: SSDT 0x0000000040AC0000 00740E (v02 DptfTb DptfTabl 00001000 INTL 20200717)
(...)
ACPI: Reserving SSDT table memory at [mem 0x40ac0000-0x40ac740d]
(...)
ACPI: Table Upgrade: install [SSDT-CUSTOM- CSC3551]
(...)
ACPI: SSDT 0x00000000368FD000 0001A0 (v01 CUSTOM CSC3551  00000001 INTL 20200925)
(...)

If not, you should review what you have done.
@lamperez
I have applied the DSD patch, following option 1. my dmesg shows the following in two different greps.

May 10 19:53:38 pop-os kernel: Serial bus multi instantiate pseudo device driver CSC3551:00: Instantiated 2 SPI devices.
May 10 19:53:38 pop-os kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: Error: ACPI _DSD Properties are missing for HID CSC3551.
May 10 19:53:38 pop-os kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: error -EINVAL: Platform not supported
May 10 19:53:38 pop-os kernel: cs35l41-hda: probe of spi1-CSC3551:00-cs35l41-hda.0 failed with error -22
May 10 19:53:38 pop-os kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: Error: ACPI _DSD Properties are missing for HID CSC3551.
May 10 19:53:38 pop-os kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: error -EINVAL: Platform not supported
May 10 19:53:38 pop-os kernel: cs35l41-hda: probe of spi1-CSC3551:00-cs35l41-hda.1 failed with error -22


> [    0.020171] ACPI: DSDT ACPI table found in initrd [kernel/firmware/acpi/dsdt.aml][0x997e9]
> [    0.020253] ACPI: Early table checksum verification disabled
> [    0.020321] ACPI: Reserving FACP table memory at [mem 0x43a64000-0x43a64113]
> [    0.020322] ACPI: Reserving DSDT table memory at [mem 0x439c8000-0x43a63072]
> [    0.020322] ACPI: Reserving FACS table memory at [mem 0x43c50000-0x43c5003f]
> [    0.020322] ACPI: Reserving SSDT table memory at [mem 0x43a65000-0x43a67d06]
> [    0.020323] ACPI: Reserving FIDT table memory at [mem 0x439c7000-0x439c709b]
> [    0.020323] ACPI: Reserving MSDM table memory at [mem 0x439c6000-0x439c6054]
> [    0.020324] ACPI: Reserving SSDT table memory at [mem 0x439c3000-0x439c5b0f]
> [    0.020324] ACPI: Reserving SSDT table memory at [mem 0x439c2000-0x439c238b]
> [    0.020324] ACPI: Reserving SSDT table memory at [mem 0x439bc000-0x439c1d83]
> [    0.020325] ACPI: Reserving SSDT table memory at [mem 0x439b9000-0x439bbab4]
> [    0.020325] ACPI: Reserving SSDT table memory at [mem 0x439b5000-0x439b837b]
> [    0.020325] ACPI: Reserving HPET table memory at [mem 0x439b4000-0x439b4037]
> [    0.020326] ACPI: Reserving APIC table memory at [mem 0x439b3000-0x439b31db]
> [    0.020326] ACPI: Reserving MCFG table memory at [mem 0x439b2000-0x439b203b]
> [    0.020326] ACPI: Reserving SSDT table memory at [mem 0x439a7000-0x439b15e6]
> [    0.020327] ACPI: Reserving SSDT table memory at [mem 0x439a5000-0x439a6f19]
> [    0.020327] ACPI: Reserving NHLT table memory at [mem 0x439a4000-0x439a42f0]
> [    0.020328] ACPI: Reserving LPIT table memory at [mem 0x439a3000-0x439a30cb]
> [    0.020328] ACPI: Reserving SSDT table memory at [mem 0x4399f000-0x439a1a82]
> [    0.020328] ACPI: Reserving SSDT table memory at [mem 0x4399c000-0x4399e10a]
> [    0.020329] ACPI: Reserving DBGP table memory at [mem 0x4399b000-0x4399b033]
> [    0.020329] ACPI: Reserving DBG2 table memory at [mem 0x4399a000-0x4399a053]
> [    0.020329] ACPI: Reserving SSDT table memory at [mem 0x43998000-0x4399911b]
> [    0.020330] ACPI: Reserving DMAR table memory at [mem 0x43997000-0x43997087]
> [    0.020330] ACPI: Reserving FPDT table memory at [mem 0x43996000-0x43996043]
> [    0.020331] ACPI: Reserving SSDT table memory at [mem 0x43994000-0x43995226]
> [    0.020331] ACPI: Reserving SSDT table memory at [mem 0x43990000-0x43993ae9]
> [    0.020331] ACPI: Reserving SSDT table memory at [mem 0x4398c000-0x4398f9d9]
> [    0.020332] ACPI: Reserving SSDT table memory at [mem 0x4398b000-0x4398b0ad]
> [    0.020332] ACPI: Reserving SSDT table memory at [mem 0x4398a000-0x4398a143]
> [    0.020333] ACPI: Reserving UEFI table memory at [mem 0x43afd000-0x43afd639]
> [    0.020333] ACPI: Reserving UEFI table memory at [mem 0x43afc000-0x43afc05b]
> [    0.020333] ACPI: Reserving TPM2 table memory at [mem 0x43988000-0x4398804b]
> [    0.020334] ACPI: Reserving SSDT table memory at [mem 0x43987000-0x43987725]
> [    0.020334] ACPI: Reserving SSDT table memory at [mem 0x43981000-0x43986d69]
> [    0.020334] ACPI: Reserving BGRT table memory at [mem 0x43989000-0x43989037]
> [    0.020335] ACPI: Reserving PHAT table memory at [mem 0x43980000-0x4398062c]
> [    0.020335] ACPI: Reserving WSMT table memory at [mem 0x439a2000-0x439a2027]
> [    0.292335] ACPI: 19 ACPI AML tables successfully acquired and loaded

@armangurkan
Copy link

armangurkan commented May 11, 2023

@lamperez thank you for helping by the way brother.
Now I applied the ssdt patch, still does not work and my dmesg says the following:

[    0.019392] ACPI: SSDT ACPI table found in initrd [kernel/firmware/acpi/ssdt_csc3551.aml][0x1a0]
[    0.019436] ACPI: SSDT 0x0000000043A65000 002D07 (v02 DptfTb DptfTabl 00001000 INTL 20200717)
[    0.019442] ACPI: SSDT 0x00000000439C3000 002B10 (v02 INTEL  DTbtSsdt 00001000 INTL 20200717)
[    0.019444] ACPI: SSDT 0x00000000439C2000 00038C (v02 PmaxDv Pmax_Dev 00000001 INTL 20200717)
[    0.019446] ACPI: SSDT 0x00000000439BC000 005D84 (v02 CpuRef CpuSsdt  00003000 INTL 20200717)
[    0.019448] ACPI: SSDT 0x00000000439B9000 002AB5 (v02 SaSsdt SaSsdt   00003000 INTL 20200717)
[    0.019449] ACPI: SSDT 0x00000000439B5000 00337C (v02 INTEL  IgfxSsdt 00003000 INTL 20200717)
[    0.019457] ACPI: SSDT 0x00000000439A7000 00A5E7 (v02 _ASUS_ RplSBTbt 00001000 INTL 20200717)
[    0.019458] ACPI: SSDT 0x00000000439A5000 001F1A (v02 _ASUS_ Ther_Rvp 00001000 INTL 20200717)
[    0.019464] ACPI: SSDT 0x000000004399F000 002A83 (v02 _ASUS_ PtidDevc 00001000 INTL 20200717)
[    0.019466] ACPI: SSDT 0x000000004399C000 00210B (v02 _ASUS_ TbtTypeC 00000000 INTL 20200717)
[    0.019471] ACPI: SSDT 0x0000000043998000 00111C (v02 _ASUS_ UsbCTabl 00001000 INTL 20200717)
[    0.019477] ACPI: SSDT 0x0000000043994000 001227 (v02 INTEL  xh_rplsb 00000000 INTL 20200717)
[    0.019479] ACPI: SSDT 0x0000000043990000 003AEA (v02 SocGpe SocGpe   00003000 INTL 20200717)
[    0.019481] ACPI: SSDT 0x000000004398C000 0039DA (v02 SocCmn SocCmn   00003000 INTL 20200717)
[    0.019482] ACPI: SSDT 0x000000004398B000 0000AE (v02 HgRef  HgPeg    00001000 INTL 20200717)
[    0.019484] ACPI: SSDT 0x000000004398A000 000144 (v02 Intel  ADebTabl 00001000 INTL 20200717)
[    0.019492] ACPI: SSDT 0x0000000043987000 000726 (v01 NvDDS  NvDDSN20 00001000 INTL 20200717)
[    0.019494] ACPI: SSDT 0x0000000043981000 005D6A (v01 OptRf2 Opt2Tabl 00001000 INTL 20200717)
[    0.019501] ACPI: Reserving SSDT table memory at [mem 0x43a65000-0x43a67d06]
[    0.019502] ACPI: Reserving SSDT table memory at [mem 0x439c3000-0x439c5b0f]
[    0.019502] ACPI: Reserving SSDT table memory at [mem 0x439c2000-0x439c238b]
[    0.019503] ACPI: Reserving SSDT table memory at [mem 0x439bc000-0x439c1d83]
[    0.019503] ACPI: Reserving SSDT table memory at [mem 0x439b9000-0x439bbab4]
[    0.019503] ACPI: Reserving SSDT table memory at [mem 0x439b5000-0x439b837b]
[    0.019505] ACPI: Reserving SSDT table memory at [mem 0x439a7000-0x439b15e6]
[    0.019505] ACPI: Reserving SSDT table memory at [mem 0x439a5000-0x439a6f19]
[    0.019506] ACPI: Reserving SSDT table memory at [mem 0x4399f000-0x439a1a82]
[    0.019507] ACPI: Reserving SSDT table memory at [mem 0x4399c000-0x4399e10a]
[    0.019508] ACPI: Reserving SSDT table memory at [mem 0x43998000-0x4399911b]
[    0.019509] ACPI: Reserving SSDT table memory at [mem 0x43994000-0x43995226]
[    0.019509] ACPI: Reserving SSDT table memory at [mem 0x43990000-0x43993ae9]
[    0.019510] ACPI: Reserving SSDT table memory at [mem 0x4398c000-0x4398f9d9]
[    0.019510] ACPI: Reserving SSDT table memory at [mem 0x4398b000-0x4398b0ad]
[    0.019510] ACPI: Reserving SSDT table memory at [mem 0x4398a000-0x4398a143]
[    0.019512] ACPI: Reserving SSDT table memory at [mem 0x43987000-0x43987725]
[    0.019512] ACPI: Reserving SSDT table memory at [mem 0x43981000-0x43986d69]
[    0.019520] ACPI: Table Upgrade: install [SSDT-CUSTOM- CSC3551]
[    0.019521] ACPI: SSDT 0x0000000039A65000 0001A0 (v01 CUSTOM CSC3551  00000001 INTL 20200925)
[    0.369930] ACPI: SSDT 0xFFFF996B03A2C600 0001AB (v02 PmRef  Cpu0Psd  00003000 INTL 20200717)
[    0.371033] ACPI: SSDT 0xFFFF996B017EDC00 000394 (v02 PmRef  Cpu0Cst  00003001 INTL 20200717)
[    0.371728] ACPI: SSDT 0xFFFF996B03A6A800 00053F (v02 PmRef  Cpu0Ist  00003000 INTL 20200717)
[    0.372477] ACPI: SSDT 0xFFFF996B03A6B000 0004B5 (v02 PmRef  Cpu0Hwp  00003000 INTL 20200717)
[    0.373394] ACPI: SSDT 0xFFFF996B017D2000 001BAF (v02 PmRef  ApIst    00003000 INTL 20200717)
[    0.374489] ACPI: SSDT 0xFFFF996B017D0000 001038 (v02 PmRef  ApHwp    00003000 INTL 20200717)
[    0.375453] ACPI: SSDT 0xFFFF996B017D4000 001349 (v02 PmRef  ApPsd    00003000 INTL 20200717)
[    0.376431] ACPI: SSDT 0xFFFF996B017E7000 000FBB (v02 PmRef  ApCst    00003000 INTL 20200717)

@manu3193
Copy link

Hi! I have a similar problem on my Lenovo Thinkpad Z16, dmesg shows messages about Amp short error. I have attached the log output and alsa info output here and here, respectively. I would appreciate your help.

@lamperez
Copy link
Author

@manu3193 In my case short amp errors disappeared when switching from internal to external boost type, that is, when changing from Package () { "cirrus,boost-type", Package () { Zero, Zero } } to Package () { "cirrus,boost-type", Package () { One, One } } in the patches.

Notice that your amplifiers are connected through i2c, not SPI. I suppose that from the point of view of the amplifier output it is not important, but there are differences. For example, your ACPI should define one GPIO less than mine (the chip select, that does not exist in i2c buses).

@BillOTei
Copy link

cs35l41

hey guys thanks for making this alive! Or trying at least,
I gave a try at using the same patch and procedure on my Asus strix scar 18 2023 (G834JY) but without luck.
I believed it had the same speaker configuration, it has CSC3551 for sure.
I did both grub update and grub2-mkconfig

Sourcing file /etc/default/grub' Sourcing file /etc/default/grub.d/init-select.cfg'
Sourcing file `/etc/default/grub.d/kdump-tools.cfg'
Generating grub configuration file ...
Searching for custom ACPI tables in /boot
Found custom ACPI table: /boot/ssdt-csc3551.aml
using custom appearance settings
Found background image: grub-wallpapers.jpg
Found linux image: /boot/vmlinuz-6.2.6-76060206-generic
Found initrd image: /boot/initrd.img-6.2.6-76060206-generic
Warning: os-prober will be executed to detect other bootable partitions.
Its output will be used to detect bootable binaries on them and create new boot entries.
Found Windows Boot Manager on /dev/nvme0n1p1@/efi/Microsoft/Boot/bootmgfw.efi
Adding boot menu entry for UEFI Firmware Settings ...
done

but nothing seem to be loaded in the end (as well as my custom background)

May 19 17:48:48 pop-os kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: Error: ACPI _DSD Properties are missing for HID CSC3551.
May 19 17:48:48 pop-os kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: error -EINVAL: Platform not supported
May 19 17:48:48 pop-os kernel: cs35l41-hda: probe of spi1-CSC3551:00-cs35l41-hda.0 failed with error -22
May 19 17:48:48 pop-os kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: Error: ACPI _DSD Properties are missing for HID CSC3551.
May 19 17:48:48 pop-os kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: error -EINVAL: Platform not supported
May 19 17:48:48 pop-os kernel: cs35l41-hda: probe of spi1-CSC3551:00-cs35l41-hda.1 failed with error -22

secure boot is disabled.

What would you need to provide?
Thanks

@fermino
Copy link

fermino commented May 19, 2023

@BillOTei check the kernel log (dmesg) to see if the SSDT is actually being loaded on boot. If not, check the grub config file (maybe update-grub is not updating the right one, or for some reason the ssdt is not being added although it mentions it when the config file is generated).

@BillOTei
Copy link

no ssdt there :/ https://pastebin.com/raw/t1DnaLmn
I'll check grub then

@fermino
Copy link

fermino commented May 19, 2023

@BillOTei
My grub configuration is the following (for reference, the aml file is in /boot; which is the partition 9FC...).

 insmod part_gpt
 insmod fat
 search --no-floppy --fs-uuid --set=root 9FCD-44E3
acpi ($root)/ssdt-csc3551.aml

@brybinski
Copy link

What kernel version are you on? Iirc on older kernels I couldn't get it to work correctly even with dsdt patch. I also see that PCI QUIRK on your model is not set, you can try to add patch manually

@BillOTei
Copy link

BillOTei commented May 22, 2023

@brybinski

I'm on 6.2.6-76060206-generic pop_os

@lamperez
Copy link
Author

@BillOTei I have tested it in several 6.2.x and 6.3.x kernel versions. It should work.

Check journalctl -b -g CSC3551 to see if it is a problem with the ACPI patch, the kernel module or the firmware files.

@BillOTei
Copy link

journalctl -b -g CSC3551

May 22 10:29:15 pop-os kernel: Serial bus multi instantiate pseudo device driver CSC3551:00: Instantiated 2 SPI devices.
May 22 10:29:15 pop-os kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: Error: ACPI _DSD Properties are missing for HID CSC3551.
May 22 10:29:15 pop-os kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.0: error -EINVAL: Platform not supported
May 22 10:29:15 pop-os kernel: cs35l41-hda: probe of spi1-CSC3551:00-cs35l41-hda.0 failed with error -22
May 22 10:29:15 pop-os kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: Error: ACPI _DSD Properties are missing for HID CSC3551.
May 22 10:29:15 pop-os kernel: cs35l41-hda spi1-CSC3551:00-cs35l41-hda.1: error -EINVAL: Platform not supported
May 22 10:29:15 pop-os kernel: cs35l41-hda: probe of spi1-CSC3551:00-cs35l41-hda.1 failed with error -22

@lamperez
Copy link
Author

@BillOTei No ACPI patch. The two cs35l41 amplifiers are there, but the _DSD properties are missing in the corresponding ACPI table. The patch provides them.

@BillOTei
Copy link

@lamperez indeed... Something must be wrong with my grub as I did all the checks and update steps I think https://gist.github.com/lamperez/862763881c0e1c812392b5574727f6ff?permalink_comment_id=4573514#gistcomment-4573514

@Moooebie
Copy link

Hello. I have a Lenovo Thinkbook Plus Gen 3 (Alder-lake) which has exactly the same cs35l41 amps and exactly the same issue. Would you mind to share about the idea behind this patch and how are the "model specific" configurations obtained?
I'd like to see if I can also get it working on my laptop.
(I am pretty much a noob, these things are a bit overwhelming to me though)

@lamperez
Copy link
Author

lamperez commented May 26, 2023

@Moooebie The cs35l41 amplifiers are smart, they have their own microcontroller that must be booted and some firmware loaded. On the other hand, the ACPI tables contain a description of the computer hardware. Part of this description should be how the amplifiers are connected to the computer main chipset. It can be through a I2C or a SPI bus, with some additional GPIO pins of the chipset, that control things like the reset of the amplifiers during boot. Both buses are rather, similar with small differences (for example, the SPI connection requires an additional pin, a chip-select for the second amp).

Basically, the problem is that official ACPI contains the identification of the bus devices and the GPIO pins, in some lines like these:

SpiSerialBusV2 (0x0000, ... )
SpiSerialBusV2 (0x0001, ... )
GpioIo (Exclusive, PullUp, 0x0000, 0x0000, IoRestrictionOutputOnly,
    "\\_SB.GPI0", 0x00, ResourceConsumer, ,
    )
        0x0156
    }
GpioIo (...)
...

but the functions of these devices and pins are not provided. For example, the kernel has no way to know that these two SpiSerialBusV2 devices connected to the SPI bus are cirrus,dev-index, as the driver expects, or that the 0x0156 GPIO is just the chip select pin for the second amplifier. Therefore the linux kernel is not able to communicate with the amplifiers, or even check their status or existence. I suppose the windows driver contains this information, somehow hardcoded.

The SSDT patch just provides the missing information about the bus devices, GPIO pins functions, and some configuration required to correctly boot the amplifiers and load their corresponding firmware (for example, which amplifier is left, which is right). Everything else is already available in linux kernels version 6.2 and above, and modern distro packages (I have checked current Ubuntu and PopOS!).

If your computer is different, expect different GPIO pins, but they should have the same functions. You should start by:

  • Check if your amplifiers are connected through SPI or I2C. The command journalctl -b -g CSC3551 is your friend.
  • The patches here are for SPI. For I2C they should be a bit simpler (no chip-select, the cs-gpios part).
  • Extract and disassemble your ACPI (see my guide).
  • Find the table corresponding to the amplifiers (mine is called CSC3551, easy to find with an editor).
  • If the table has no _DSD block, this is the one the patch needs to provide.
  • The the GPIOs are identified in the patch in order (the first one is SPK1, Zero, Zero, Zero, the second one SPK1, One, Zero, Zero, and so on).

@Moooebie
Copy link

@Moooebie The cs35l41 amplifiers are smart, they have their own microcontroller that must be booted and some firmware loaded. On the other hand, the ACPI tables contain a description of the computer hardware. Part of this description should be how the amplifiers are connected to the computer main chipset. It can be through a I2C or a SPI bus, with some additional GPIO pins of the chipset, that control things like the reset of the amplifiers during boot. Both buses are rather, similar with small differences (for example, the SPI connection requires an additional pin, a chip-select for the second amp).

Basically, the problem is that official ACPI contains the identification of the bus devices and the GPIO pins, in some lines like these:

SpiSerialBusV2 (0x0000, ... )
SpiSerialBusV2 (0x0001, ... )
GpioIo (Exclusive, PullUp, 0x0000, 0x0000, IoRestrictionOutputOnly,
    "\\_SB.GPI0", 0x00, ResourceConsumer, ,
    )
        0x0156
    }
GpioIo (...)
...

but the functions of these devices and pins are not provided. For example, the kernel has no way to know that these two SpiSerialBusV2 devices connected to the SPI bus are cirrus,dev-index, as the driver expects, or that the 0x0156 GPIO is just the chip select pin for the second amplifier. Therefore the linux kernel is not able to communicate with the amplifiers, or even check their status or existence. I suppose the windows driver contains this information, somehow hardcoded.

The SSDT patch just provides the missing information about the bus devices, GPIO pins functions, and some configuration required to correctly boot the amplifiers and load their corresponding firmware (for example, which amplifier is left, which is right). Everything else is already available in linux kernels version 6.2 and above, and modern distro packages (I have checked current Ubuntu and PopOS!).

If your computer is different, expect different GPIO pins, but they should have the same functions. You should start by:

  • Check if your amplifiers are connected through SPI or I2C. The command journalctl -b -g CSC3551 is your friend.
  • The patches here are for SPI. For I2C they should be a bit simpler (no chip-select, the cs-gpios part).
  • Extract and disassemble your ACPI (see my guide).
  • Find the table corresponding to the amplifiers (mine is called CSC3551, easy to find with an editor).
  • If the table has no _DSD block, this is the one the patch needs to provide.
  • The the GPIOs are identified in the patch in order (the first one is SPK1, Zero, Zero, Zero, the second one SPK1, One, Zero, Zero, and so on).

I run that journalctl command and got these results:

May 26 15:38:06 mx3340-tbplus kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: Error: ACPI _DSD Properties are missing for HID CSC3551.
May 26 15:38:06 mx3340-tbplus kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: error -EINVAL: Platform not supported
May 26 15:38:06 mx3340-tbplus kernel: cs35l41-hda: probe of i2c-CSC3551:00-cs35l41-hda.0 failed with error -22

So I believe they are the same speakers but on i2c bus. Following your guide to dump the file, I got the dsdt.dsl file and as expected it looks different from yours.
Since I don't really understand how the patch works, I just blindly inserted it after the "_DIS" block. The only change is that I replaced the SPK1 with SPKR since my device has a different name there. I also did not include the cs-gpios because it is on I2C bus. The whole scope block looks like this:

    Scope (_SB.PC00.I2C7)
    {
        Name (I2CN, Zero)
        Name (I2CX, Zero)
        Name (I2CI, 0x07)
        Method (_INI, 0, NotSerialized)  // _INI: Initialize
        {
            I2CN = SDS7 /* \SDS7 */
            I2CX = 0x07
        }

        Device (SPKR)
        {
            Name (_HID, "CSC3551")  // _HID: Hardware ID
            Method (_SUB, 0, NotSerialized)  // _SUB: Subsystem ID
            {
                If ((GGIV (0x090E000B) == One))
                {
                    Return ("17AA3846")
                }

                Return ("17AA3845")
            }

            Name (_UID, One)  // _UID: Unique ID
            Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
            {
                Name (RBUF, ResourceTemplate ()
                {
                    I2cSerialBusV2 (0x0040, ControllerInitiated, 0x000F4240,
                        AddressingMode7Bit, "\\_SB.PC00.I2C7",
                        0x00, ResourceConsumer, , Exclusive,
                        )
                    I2cSerialBusV2 (0x0041, ControllerInitiated, 0x000F4240,
                        AddressingMode7Bit, "\\_SB.PC00.I2C7",
                        0x00, ResourceConsumer, , Exclusive,
                        )
                    GpioIo (Exclusive, PullDown, 0x0000, 0x0000, IoRestrictionOutputOnly,
                        "\\_SB.GPI0", 0x00, ResourceConsumer, ,
                        )
                        {   // Pin list
                            0x0166
                        }
                    GpioIo (Shared, PullUp, 0x0064, 0x0000, IoRestrictionInputOnly,
                        "\\_SB.GPI0", 0x00, ResourceConsumer, ,
                        )
                        {   // Pin list
                            0x0165
                        }
                    GpioInt (Edge, ActiveBoth, Shared, PullUp, 0x0064,
                        "\\_SB.GPI0", 0x00, ResourceConsumer, ,
                        )
                        {   // Pin list
                            0x0165
                        }
                })
                Return (RBUF) /* \_SB_.PC00.I2C7.SPKR._CRS.RBUF */
            }

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

            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 () {
                       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 } },
                    // 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 } },
                },
            })

        }



    }

I also changed the Definition line to prioritize it over the ACPI table from BIOS.
I then compiled it and packed it into cpio following your guide, put it under /boot and manually added the initrd command in grub to load it before initramfs just as your example.
Now when I boot into system, the amps are still not working but with a different error:

May 26 16:34:12 mx3340-tbplus kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: No index found in cirrus,dev-index
May 26 16:34:12 mx3340-tbplus kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: Failed property cirrus,dev-index: -19
May 26 16:34:12 mx3340-tbplus kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: error -ENODEV: Platform not supported
May 26 16:34:12 mx3340-tbplus kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: No index found in cirrus,dev-index
May 26 16:34:12 mx3340-tbplus kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: Failed property cirrus,dev-index: -19
May 26 16:34:12 mx3340-tbplus kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: error -ENODEV: Platform not supported

I guess this means the patched ACPI table is loaded but I did not configure the "device specific" part correctly. Would you give me some help on how I should change it to resolve this error?
Sorry if I did ask a dumb question and thank you so much for the help!

@Moooebie
Copy link

I went to do some research and learned some basics about the ACPI Source Language. For now what I understand is that the patch which adds the _DSD object with that particular UUID is defining some properties of the device in package() {Key, Val} format, and according to your reply those are things about "GPIO pins functions" and "buses".
So with these errors, there is likely something I didn't correctly configure for the "cirrus,dev-index" part which defines the buses to be connected? If so, I wonder where I will be able to figure out the correct configuration. Also you said "they (GPIO pins) should have the same functions", does that mean that the configs for "gpio*-func" are likely to be good if I just leave them as is? Or I still have to find some other datasheets to figure out the specific config for my computer?
Sorry again for bothering, I don't have experiences in tinkering around these kind of things before and I am feeling lost. Really appreciate for your help!

@Moooebie
Copy link

Moooebie commented May 27, 2023

Just figured out that I should replace the package() {Zero, One} with the actual number for my device (package() {0x40, 0x41}). Now there are no more errors but speakers still not working:

May 27 02:03:55 mx3340-tbplus kernel: Serial bus multi instantiate pseudo device driver CSC3551:00: Instantiated 2 I2C devices.
May 27 02:03:55 mx3340-tbplus kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: Cirrus Logic CS35L41 (35a40), Revision: B2
May 27 02:03:55 mx3340-tbplus kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: Reset line busy, assuming shared reset
May 27 02:03:55 mx3340-tbplus kernel: cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: Cirrus Logic CS35L41 (35a40), Revision: B2
May 27 02:04:18 mx3340-tbplus dbus-daemon[548]: [system] Activating via systemd: service name='org.freedesktop.home1' unit='dbus-org.freedesktop.home1.service' >
May 27 02:04:19 mx3340-tbplus sudo[1581]:   mx3340 : TTY=pts/1 ; PWD=/home/mx3340 ; USER=root ; COMMAND=/usr/bin/journalctl -b -g CSC3551
May 27 02:05:11 mx3340-tbplus dbus-daemon[548]: [system] Activating via systemd: service name='org.freedesktop.home1' unit='dbus-org.freedesktop.home1.service' >
May 27 02:05:11 mx3340-tbplus sudo[1667]:   mx3340 : TTY=pts/1 ; PWD=/home/mx3340 ; USER=root ; COMMAND=/usr/bin/journalctl -b -g CSC3551

Looks like for now I have to also do some patch on the kernel driver?

EDIT: I saw another person had the exactly same situation, he figured it out and posted the solution under your dsdt patching guide. I'll try it tomorrow and hopefully it will work for me!

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