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 (thelinux/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.
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.
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).
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])
Sorry for replying a bit late, I was busy during the weekend and I faced some other problems with my laptop and I just managed to solve it yesterday.
First, you want to see whether your amps are on
i2c
orspi
. To do this, you run the commansudo journalctl -b -g CSC3551
. If it does not show up anything then maybe you do not have the exactly same amp. My laptop has it oni2c
so I see similar things like this:Then you'll have to dump your
dsdt
table following OP's guide (here). One you have it decompiled and got thedsdt.dsl
, you open it and search forCSC3551
. All of the things you have to patch will be inside thatscope (...)
block. First you copy the first_DSD
block from the patch and add it directly after the empty_DIS
method, so it will look something like this:The whole
scope
block of my laptop could be found in my previous post.Notice that I have
SPKR
instead ofSPK1
andPackage () { "cirrus,dev-index", Package () { 0x0040, 0x0041 }}
instead of{Zero, One}
? These are the device specific thing you have to change here. The device name could be found in the brackets of the header of thedevice
block, in my case it is:Device (SPKR) {...
so I replaceSPK1
withSPKR
. Since your device is also ASUS maybe it is the sameSPK1
so you don't have to change it.The second change there was the ID of the two buses. You kind find these information under the
Name (BRUF, ...
which is inside theName (_UID, ...
. That for my device looks like:So I replace the
{Zero, One}
with{0x0040, 0x0041}
.According to OP, if your amps are on SPI then you also want to add the second
_DSD
block in the patch outside of thedevice (...)
block but still inside thescope
.Once you done that, go back to nearly the beginning of the file, change the very last parameter in the
DefinitionBlock (...
to a larger value to prioritize this patched table over that from the BIOS. It was0x00
on my device, but it is probably a larger value on your device and you just have to change it to a larger number. Mine is:After that you follow the guide to recompile and package it into a
.cpio
file. Copy the.cpio
file into/boot
. If you use grub, on reboot you press "e" toward the boot option to enter the edit screen, load this cpio as an init ramdisk after the microcode and before the kernel's initrd. For example it might look like this:Run
sudo journalctl -b -g CSC3551
again, if there is no error but similar output as that in my previous post, then the ACPI table patch worked. If your speakers work at this moment, then you are done (you may want to write the initrd loading command into grub's config so you won't need to type that manually on every reboot).If they are still not working, you need to patch the driver in the kernel. Look for a guide to build a mainline kernel (btw. you need Linux 6.1+ for these speakers to work). I am using Manjaro Linux and I followed the guide on ArchWiki. Once you have the full kernel source ready, go to
kernel_source_root/sound/pci/hda/patch_realtek.c
and search forFIXUP_CS35L41_
until you find a list of things like this:Add a new line in the same format for your laptop.
The first two parameters can be find from the Subsystem ID. Run
alsa-info
to obtain it. In the output file, search forSubsystem Id
and you get a 4 bytes long hex string, for example mine looks like:Subsystem Id: 0x17aa3875
. Put the first four characters into the first parameter and the second for characters into the second parameter. The third parameter is just how you call your laptop, it does not matter in terms of functions and can be whatever. The last parameter could beALC245_FIXUP_CS35L41_SPI_2
orALC287_FIXUP_CS35L41_I2C_2
depends on whether your amps are onspi
ori2c
.For my device specifically, the line is like:
Then you just build the kernel and set it up for the bootloader. Don't forget to include the
.cpio
with your patched dsdt table as a initrd. If you are lucky enough at this point your speakers should be finally working.