Skip to content

Instantly share code, notes, and snippets.

@masselstine
Last active April 1, 2024 21:05
Show Gist options
  • Save masselstine/8fe9634b4c31cef07b8dfab089e4eb38 to your computer and use it in GitHub Desktop.
Save masselstine/8fe9634b4c31cef07b8dfab089e4eb38 to your computer and use it in GitHub Desktop.
Linux on the Zenbook 14 OLED refresh (UM3402YAR)

Linux on the Zenbook 14 OLED (refresh) - Model UM3402YAR

BIOS

The latest BIOS is version 303 "UM3402YAR.303" (Release Date: 09/05/2023). All items posted here will be specific to the model number and BIOS version described here (BIOS 300, 302 were known working). Some things might be specific to Arch Linux but should be generic and portable to other distributions. There are no guarantees and should you wish to try any of this out it is assumed to be at your own risk.

Sound

The sound does not work out of the box (at least not on Arch but I am guessing for most Distros as well).

The patch 0001-ALSA-hda-realtek-Add-quirk-for-ASUS-UM3402YAR-using-.patch is required to be applied to kernels older than v6.4 to ensure that the Realtek sound device is properly bound to the Cirrus amplifiers. If you are using kernel v6.4 or newer this patch is not needed.

The ssdt_csc3551.dsl file can be used per the instructions found in the file header. No need to patch the DSDT, this is a stand-alone SSDT that is easily used via GRUB. It can also be used as an EFI var and the efivar_ssdt= kernel command line option. The values are prelimary as I review the Windows oem50.inf and oem37.inf files from Windows in order to extract the proper values.

The firmware files are missing from the linux-firmware on Arch Linux (and most likely other distros as well, until someone submits them for merge). Originally I was using direct copies of firmware files for the similar "10431e12" device that were present in /lib/firmware/cirrus. At the time these appeared to be identical. Updating the Windows OS recently and looking again shows that there are differences. So I am now copying the firmware files from Windows and running the "compress-rename.sh" script to prepare them on Linux.

To start grab the full contents of c:\windows\system32\csaudio from Windows. Once you have these files on Linux you should have something like

$ ls -l
total 1080
-rw-r--r-- 1 mark mark   5532 Nov 24 14:16 10431E12_220304_V0_A0.bin
-rw-r--r-- 1 mark mark   2012 Nov 24 14:16 10431E12_220304_V0_A0_cal.bin
-rw-r--r-- 1 mark mark   5532 Nov 24 14:16 10431E12_220304_V0_A1.bin
-rw-r--r-- 1 mark mark   2012 Nov 24 14:16 10431E12_220304_V0_A1_cal.bin
-rw-r--r-- 1 mark mark   5532 Nov 24 14:16 10431E12_220304_V1_A0.bin
-rw-r--r-- 1 mark mark   2012 Nov 24 14:16 10431E12_220304_V1_A0_cal.bin
-rw-r--r-- 1 mark mark   5532 Nov 24 14:16 10431E12_220304_V1_A1.bin
-rw-r--r-- 1 mark mark   2012 Nov 24 14:16 10431E12_220304_V1_A1_cal.bin
-rw-r--r-- 1 mark mark   2600 Nov 24 14:16 Calibration_and_Diagnostics_CS35L41B_48000_29.63.1_left_cal.bin
-rw-r--r-- 1 mark mark   1548 Nov 24 14:16 Calibration_CS35L41B_48000_29.63.1_left_cal.bin
-rw-r--r-- 1 mark mark  11556 Nov 24 14:38 csaudio.cat
-rw-r--r-- 1 mark mark 100255 Nov 24 14:38 csaudioext.cat
-rw-r--r-- 1 mark mark 110868 Nov 24 14:35 csaudioext.inf
-rw-r--r-- 1 mark mark   6392 Nov 24 14:35 csaudio.inf
-rw-r--r-- 1 mark mark 350632 Nov 24 14:37 csaudio.sys
-rw-r--r-- 1 mark mark   5208 Nov 24 14:16 Enhance_Protect_Lite_Mono_CS35L41B_48000_29.63.1_left.bin
-rw-r--r-- 1 mark mark  33456 Nov 24 14:16 halo_cspl_RAM_diag_revB2_29.63.1.wmfw
-rw-r--r-- 1 mark mark  34068 Nov 24 14:16 halo_cspl_RAM_revB2_29.63.1.wmfw
-rw-r--r-- 1 mark mark   6392 Nov 24 14:31 oem37.inf
-rw-r--r-- 1 mark mark   9812 Nov 24 14:31 oem37.PNF
-rw-r--r-- 1 mark mark 110868 Nov 24 14:31 oem50.inf
-rw-r--r-- 1 mark mark  91068 Nov 24 14:31 oem50.PNF
-rw-r--r-- 1 mark mark 136610 Nov 24 14:32 oem82.inf
-rw-r--r-- 1 mark mark   3920 Nov 24 14:16 Protect_Lite_CS35L41B_48000_29.63.1_left.bin
-rw-r--r-- 1 mark mark    760 Nov 24 14:16 top_passthrough_CS35L41B_48000_29.63.1_full.bin

From this directory run the $ bash compress-rename.sh script to generate the firmware files. You should now have

$ ls -l *zst
-rw-r--r-- 1 mark mark  1148 Nov 24 14:16 cs35l41-dsp1-spk-cali-10431683-spkid0-l0.bin.zst
-rw-r--r-- 1 mark mark  1144 Nov 24 14:16 cs35l41-dsp1-spk-cali-10431683-spkid0-r0.bin.zst
-rw-r--r-- 1 mark mark  1145 Nov 24 14:16 cs35l41-dsp1-spk-cali-10431683-spkid1-l0.bin.zst
-rw-r--r-- 1 mark mark  1147 Nov 24 14:16 cs35l41-dsp1-spk-cali-10431683-spkid1-r0.bin.zst
-rw-r--r-- 1 mark mark 18852 Nov 24 16:39 cs35l41-dsp1-spk-cali-10431683.wmfw.zst
-rw-r--r-- 1 mark mark  3122 Nov 24 14:16 cs35l41-dsp1-spk-prot-10431683-spkid0-l0.bin.zst
-rw-r--r-- 1 mark mark  3117 Nov 24 14:16 cs35l41-dsp1-spk-prot-10431683-spkid0-r0.bin.zst
-rw-r--r-- 1 mark mark  3146 Nov 24 14:16 cs35l41-dsp1-spk-prot-10431683-spkid1-l0.bin.zst
-rw-r--r-- 1 mark mark  3127 Nov 24 14:16 cs35l41-dsp1-spk-prot-10431683-spkid1-r0.bin.zst
-rw-r--r-- 1 mark mark 18852 Nov 24 16:39 cs35l41-dsp1-spk-prot-10431683.wmfw.zst

Copy all of these files to /lib/firmware/cirrus.

SPKR _DSD validation

Elements are described in the kernel documentation found here

100% Confirmed

  • "cirrus,dev-index": Confirmed by: Simple printk() was used to determine the values of the two AMPs. These are used to determine the index used ('0' or '1') when retrieving values from other elements in the _DSD
  • "reset-gpios": Confirmed by: The driver issues a reset after reading the ACPI data and waits for the reset to complete by polling IRQ status for CS35L41_OTP_BOOT_DONE. If this is not set correctly then the reset would fail and a OTP_BOOT_DONE waiting message would be printed.
  • "spk-id-gpios": Mostly confirmed by: There are 4 GPIOs listed in the 'shipped' ACPI DSDT. Index 0 is the reset-gpios Indicies 0x02 and 0x03 share a pin and are "shared". So by processes of elimination GPIO at index 'One' remains. The 0th element is definitely SPKR the 2nd and 3rd elements are best guess.
  • "cirrus,speaker-position": Confirmed by: Simple left and right position in driver code & left and right are properly outputting sound in sound settings with isolated output
  • "cirrus,gpio1-func": Confirmed by: the comment in the oem50.inf for "CONF_0330.NT"
  • "cirrus,gpio2-func": Mostly confirmed by: the speakers working. Also a "Amp short error" interrupt was received while this work was being done.
  • "cirrus,boost-type": Confirmed by: the comment in the oem50.inf for "CONF_0330.NT"
  • "cirrus,gpio1-output-enable": Confirmed by: with GPIO1 being VSPK_SWITCH then GPIO1 needs to be an output
  • "cirrus,gpio1-src-select": Confirmed by: with GPIO1 being used as a GPIO output, then this is the only thing that makes sense

The patch and the SSDT are the only changes required to get sound working. Again, use of items posted here is use-at-your-own-risk.

Fingerprint

Not working

From f309c07e244945b9b3b3c473d5e8394cce132ddf Mon Sep 17 00:00:00 2001
From: Mark Asselstine <mark@tundrafam.ca>
Date: Sat, 29 Apr 2023 11:21:55 -0400
Subject: [PATCH] ALSA: hda/realtek: Add quirk for ASUS UM3402YAR using CS35L41
This Asus Zenbook laptop use Realtek HDA codec combined with
2xCS35L41 Amplifiers using I2C with External Boost.
Signed-off-by: Mark Asselstine <mark@tundrafam.ca>
---
sound/pci/hda/patch_realtek.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index f70d6a33421d..905acd66ea01 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -9500,6 +9500,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK),
SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A),
SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK),
+ SND_PCI_QUIRK(0x1043, 0x1683, "ASUS UM3402YAR", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x16b2, "ASUS GU603", ALC289_FIXUP_ASUS_GA401),
SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x1043, 0x1740, "ASUS UX430UA", ALC295_FIXUP_ASUS_DACS),
--
2.40.1
#!/usr/bin/bash
#
# Create the needed Linux firmware files from a copy of the firmware
# files from Windows (c:\windows\system32\csaudio)
#
zstd halo_cspl_RAM_revB2_29.63.1.wmfw -o halo_cspl_RAM_revB2_29.63.1.wmfw.zst
for t in cali prot
do
for i in 0 1
do
for side in l r
do
j=0
if [ $side == "r" ]; then
j=1
fi
deco=""
if [ $t == "cali" ]; then
deco="_cal"
fi
ofile=10431E12_220304_V${i}_A${j}${deco}.bin
zstd ${ofile} -o ${ofile}.zstd
mv ${ofile}.zstd cs35l41-dsp1-spk-${t}-10431683-spkid${i}-${side}0.bin.zst
done
done
cp halo_cspl_RAM_revB2_29.63.1.wmfw.zst cs35l41-dsp1-spk-${t}-10431683.wmfw.zst
done
rm halo_cspl_RAM_revB2_29.63.1.wmfw.zst
# dmesg | grep cs3
[ 12.582998] cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: Cirrus Logic CS35L41 (35a40), Revision: B2
[ 12.591327] cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: Reset line busy, assuming shared reset
[ 12.636874] cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: Cirrus Logic CS35L41 (35a40), Revision: B2
[ 12.758779] cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: DSP1: Firmware version: 3
[ 12.762457] cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: DSP1: cirrus/cs35l41-dsp1-spk-prot-10431683.wmfw: Fri 27 Aug 2021 14:58:19 W. Europe Daylight Time
[ 13.262629] cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: DSP1: Firmware: 400a4 vendor: 0x2 v0.43.1, 2 algorithms
[ 13.266856] cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: DSP1: 0: ID cd v29.63.1 XM@94 YM@e
[ 13.270159] cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: DSP1: 1: ID f20b v0.1.0 XM@176 YM@0
[ 13.274041] cs35l41-hda i2c-CSC3551:00-cs35l41-hda.0: DSP1: spk-prot: C:\Users\tyang\Desktop\Product Setting\SmartAMP\ASUS\ASUS_Zenbook\UM3402\Tuning_Release\220304\ASUS_UM3402_L_tuning_IDHX_ReDC_Finish_PICL_RTL_0304.bin
[ 13.379459] snd_hda_codec_realtek hdaudioC1D0: bound i2c-CSC3551:00-cs35l41-hda.0 (ops cs35l41_hda_comp_ops [snd_hda_scodec_cs35l41])
[ 13.393246] cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: DSP1: Firmware version: 3
[ 13.397723] cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: DSP1: cirrus/cs35l41-dsp1-spk-prot-10431683.wmfw: Fri 27 Aug 2021 14:58:19 W. Europe Daylight Time
[ 13.898417] cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: DSP1: Firmware: 400a4 vendor: 0x2 v0.43.1, 2 algorithms
[ 13.903515] cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: DSP1: 0: ID cd v29.63.1 XM@94 YM@e
[ 13.907164] cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: DSP1: 1: ID f20b v0.1.0 XM@176 YM@0
[ 13.909854] cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: DSP1: spk-prot: C:\Users\tyang\Desktop\Product Setting\SmartAMP\ASUS\ASUS_Zenbook\UM3402\Tuning_Release\220304\ASUS_UM3402_R_tuning_IDHX_ReDC_Finish_PICL_RTL_0304.bin
[ 14.014944] snd_hda_codec_realtek hdaudioC1D0: bound i2c-CSC3551:00-cs35l41-hda.1 (ops cs35l41_hda_comp_ops [snd_hda_scodec_cs35l41])
...
;; ASUSTEK Zenbook notebook (see FC-2054)
%CirrusSpeakerAmp% = CONF_0322, ACPI\VEN_CSC&DEV_3551&SUBSYS_104316A3 ; UX3402VA [FC-1831] [FC-1905]
%CirrusSpeakerAmp% = CONF_0451, ACPI\VEN_CSC&DEV_3551&SUBSYS_104316D3 ; UX5304VA [FC-2056]
%CirrusSpeakerAmp% = CONF_0450, ACPI\VEN_CSC&DEV_3551&SUBSYS_104316F3 ; UX7602VZ [FC-1836]
%CirrusSpeakerAmp% = CONF_0460, ACPI\VEN_CSC&DEV_3551&SUBSYS_10431F1F ; H7604JV/HU/W7604J3D [FC-2033]
%CirrusSpeakerAmp% = CONF_0470, ACPI\VEN_CSC&DEV_3551&SUBSYS_10431863 ; UX6404VA/VU [FC-2015]
%CirrusSpeakerAmp% = CONF_0330, ACPI\VEN_CSC&DEV_3551&SUBSYS_10431683 ; UM3402YAR [FC-1827] (UM3402_refresh)
%CirrusSpeakerAmp% = CONF_0430, ACPI\VEN_CSC&DEV_3551&SUBSYS_104318D3 ; UM3504DA [FC-2054]
...
;; 2-ch I2C, ext. VSPK, SPKR_ID
[CONF_0330.NT]
AddReg=CONF_0320.Settings.AddReg, CONF_0330.Config.AddReg, L51_2_VSPK.Init.AddReg
AddReg=PB6.61.1.Firmware.AddReg, PB6.61.1.Tunings.AddReg, CONF_0330.Tunings.AddReg, 2_SPK_2_VEN_DefaultGain.AddReg
CopyFiles=PB6.61.1.Firmware.CopyFiles, PB6.61.1.Tunings.CopyFiles, CONF_0330.Tunings.CopyFiles
//
// Build
// # iasl -tc ssdt_csc3551.dsl
// Create the proper directory structure and copy .aml file
// # mkdir -p kernel/firmware/acpi
// # cp ssdt_csc3551.aml kernel/firmware/acpi/ssdt_csc3551.aml
// Package into a format loadable by grub
// # find kernel | cpio -H newc --create > acpi_override
// Copy to /boot
// # cp acpi_override /boot/.
// Load via grub
// initrd /acpi_override /amd-ucode.img /initramfs-linux.img
// Supporting docs
// https://www.kernel.org/doc/Documentation/devicetree/bindings/sound/cirrus%2Ccs35l41.yaml
//
DefinitionBlock ("", "SSDT", 2, "CUSTOM", "CSC3551", 0x00000003)
{
External (_SB_.I2CD, DeviceObj)
External (_SB_.I2CD.SPKR, DeviceObj)
Scope (\_SB.I2CD.SPKR)
{
Name(_DSD, Package ()
{
ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package ()
{
Package () { "cirrus,dev-index", Package () { 0x40, 0x41 }},
// reset-gpios: 2nd elem is GPIO index: Zero, One, 0x02 or 0x03
Package () { "reset-gpios", Package () {
SPKR, Zero, Zero, Zero,
SPKR, Zero, Zero, Zero
} },
// spk-id-gpios: 2nd elem is GPIO index: Zero, One, 0x02 or 0x03
Package () { "spk-id-gpios", Package () {
SPKR, One, Zero, Zero,
SPKR, One, Zero, Zero
} },
Package () { "cirrus,speaker-position", Package () { Zero, One } },
// gpioX-func: 0 not used, 1 VSPK_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 } },
// gpio1-output-enable: true, false (default: false, ie: input)
Package () { "cirrus,gpio1-output-enable", Package () { One, One } },
// gpio1-src-select: 0 High Impedance (default), 1 GPIO, 2 Sync, 3 MCLK input
Package () { "cirrus,gpio1-src-select", Package () { One, One } }
}
})
}
}
@ransur0t
Copy link

Try this link to Cirrus firmware for the amp:
https://github.com/CirrusLogic/linux-firmware/tree/main/cirrus

I use it and see Falling back to default firmware. in dmesg. Volume is low

Did you run $ bash compress-rename.sh and place the renamed files in proper directory?

@nullptroma
Copy link

Did you run $ bash compress-rename.sh and place the renamed files in proper directory?

This script is needed to change files taken from Windows. I didn't take files from Windows because I don't have it on my laptop. I want to set up sound without Windows and ask people to send me these files

@ransur0t
Copy link

Did you run $ bash compress-rename.sh and place the renamed files in proper directory?

This script is needed to change files taken from Windows. I didn't take files from Windows because I don't have it on my laptop. I want to set up sound without Windows and ask people to send me these files

I believe the files posted in the firmware repo are all named *.bin, hence the need for rename them per comment above.

@nullptroma
Copy link

nullptroma commented Jan 12, 2024

I believe the files posted in the firmware repo are all named *.bin, hence the need for rename them per comment above.

It work! Thank you!

@nullptroma
Copy link

@ransur0t
Copy link

ransur0t commented Jan 13, 2024 via email

@asp345
Copy link

asp345 commented Jan 15, 2024

With kernel 6.7, a patch (https://lore.kernel.org/all/20231218151221.388745-1-sbinding@opensource.cirrus.com/ )is added for cs35l41 which fixes sound on many Asus laptops. Unfortunately this device (UM3402YAR) has PCI_SUBSYS_ID=1043:1683 (result of udevadm info /sys/bus/pci/devices/0000:00:00.0 | grep PCI_SUBSYS_ID) and it does not appear here. https://github.com/torvalds/linux/blob/master/sound/pci/hda/cs35l41_hda_property.c
Adding correct values to that table might fix speakers. But I don't know what are the correct values for reset_gpio_index, spkid_gpio_index, cs_gpio_index, boost_ind_nanohenry, boost_peak_milliam, boost_cap_microfarad. Last three are probably not needed as this device uses external boost.

@nullptroma
Copy link

Modified script + .bin files from https://github.com/CirrusLogic/linux-firmware/tree/main/cirrus, run script and move .zst to /lib/firmware/cirrus

Oh
I can see cs35l41-hda i2c-CSC3551:00-cs35l41-hda.1: DSP1: Algorithm coefficient version 29.63.1 but expected 29.85.0 In dmesg | grep CSC, mistake versions. How should files are naming for new version from cirrus github?

@Targa250R
Copy link

Targa250R commented Feb 5, 2024

Good news, the UM3402YAR (device 10431683) has been added to the table in sound/pci/hda/cs35l41_hda_property.c for kernel 6.8-rc3 as per this commit.

I don't own a UM3402YAR, but rather its 2022 predecessor UM3402YA with the Ryzen 5825U (device 10431E12). Does anyone know how I should go about contacting a kernel maintainer to have this model added to the table? I am not familiar with the LKML and I am assuming it is bad etiquette to directly email one of the persons listed in the patch comments. I built a kernel using the GPIO values from the UM3402YAR and it seems to be working fine with no error messages on the UM3402YA.

@masselstine
Copy link
Author

@Targa250R I can prepare a patch, pass it to you to verify and would be fine submitting it to the kernel.

@masselstine
Copy link
Author

@Targa250R I am preparing the patch. In your initial testing did you also require the I2C quirk change? I am pretty sure you would not as that device already has a quirk listed (just a different laptop model #). But I would like to confirm.

@Targa250R
Copy link

@masselstine The UM3402YA quirk has been mainlined since kernel 6.2-rc8, but someone made an error when editing the Realtek patch file for kernel 6.7-rc7 and accidentally swapped the device IDs for the UM3402YA (10431E12) and the UM6702RA (10431EE2). There is a patch proposed as of yesterday to correct this issue, but it is functionally trivial since both devices use the same quirk.

@Targa250R
Copy link

@masselstine It looks like that same patch proposal also inserts the UM3402YA device ID to the table in the CS35L41 property file, so the kernel maintainers are already reviewing it for inclusion with kernel 6.8.

I thank you very much for your assistance and for your many efforts over the past year to help us all get the sound hardware working in these devices!

@masselstine
Copy link
Author

@Targa250R , perfect. Prior to sending a patch out it is good to look on the mailing lists for similar submissions, so I would have seen this (hopefully). Thanks for saving me the trouble and pointing it out. I am glad things will be sorted once Linus gets the next release out or the commits are back-ported by the stable kernel folks.

@nullptroma
Copy link

After the release of 6.8, when everything works, will it be necessary to somehow remove the current fixes in the form of renamed drivers?

@zonkypop
Copy link

Upgraded the kernel to 6.8-rc5 and sound is working for the first time 🥳

@nullptroma
Copy link

Upgraded the kernel to 6.8-rc5 and sound is working for the first time 🥳

but the sound is quiet. Cisco .zst files are still needed, aren't they?

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