Skip to content

About

Working loudspeaker and headphone audio for the Microsoft Lumia 950 (RM-1104) on LineageOS 18.1 - TAS2553 amplifier driver, Quaternary MI2S backend, and jack detection fix

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

Repository files navigation

Lumia 950 (RM-1104 / talkman) — working audio

Kernel work that makes the loudspeaker and headphones work on the Microsoft Lumia 950 running a community Android ROM (LineageOS 18.1, bullhead port).

The loudspeaker is driven by a TI TAS2553 smart amplifier on I2C that the stock Android kernel knows nothing about — it is not connected to the WCD9330's speaker driver at all. This project adds the amplifier driver, wires it into the device tree over Quaternary MI2S, registers it as an ASoC backend, and fixes the jack detection so Android actually selects the speaker.

Base kernel: Android4Lumia950/android_kernel_mmo_msm8994, branch lineage-18.1-usb (Linux 3.10.108).

Status

Loudspeaker works
Headphones, with automatic switching works
Earpiece plays through the loudspeaker — see Known limitations
Bluetooth / HDMI / voice calls untouched, not tested

Where the code is

Kernel changes live as real commits on a branch, which is what you want if you intend to build or merge them:

https://github.com/EpicLPer/android_kernel_mmo_msm8994  branch: lumia950-audio

The same five commits are exported to patches/ here, if you would rather apply them to a different base.

One change does not belong in the kernel: patches/rom/mixer_paths.xml.patch. See Audio routing below.

Read this before you flash

  • Back up your boot partition. scripts/pack-boot.sh writes a backup to out/device/boot-backup.img automatically, but keep your own copy somewhere off the device.
  • The amplifier can brown out a worn battery. At the chip's default 15 dB gain, playback current peaks can sag an old cell far enough that the PMIC power-cycles the phone mid-song, with nothing in the kernel log. The driver ships a conservative 11 dB default for this reason. If your phone resets during playback, this is the first thing to suspect.
  • An abnormal reboot puts Magisk into safe mode, which silently disables every module. If audio suddenly stops working after a crash, check the Magisk app before assuming the kernel broke.
  • Flashing a kernel built for a different device or ROM will not boot. This is for the Lumia 950 (RM-1104, "talkman") specifically. The Lumia 950 XL (cityman) has not been tested.

Building

Requirements: a Linux host, git, make, gcc, python3, adb, and about 15 GB free.

git clone https://github.com/EpicLPer/Lumia950-Audio-Fix
cd Lumia950-Audio-Fix
scripts/setup.sh        # clones the kernel branch + fetches the aarch64 toolchain
scripts/build.sh        # produces out/Image.gz-dtb

setup.sh is idempotent; re-running it will not clobber local changes.

The path must not contain spaces. kbuild breaks on them in ways that are hard to diagnose, so scripts/env.sh refuses to run rather than failing halfway through a build.

If you want to apply the patches to your own kernel checkout instead:

cd /path/to/android_kernel_mmo_msm8994
git am /path/to/Lumia950-Audio-Fix/patches/*.patch

Flashing

The device must be booted with root over adb (Magisk). This keeps your existing ramdisk, so root survives the kernel swap:

scripts/pack-boot.sh    # pulls the live boot.img, swaps in the new kernel, backs up the original
scripts/flash.sh        # writes it back
adb reboot

To go back, flash the backup:

adb push out/device/boot-backup.img /data/local/tmp/
adb shell su -c 'dd if=/data/local/tmp/boot-backup.img of=/dev/block/bootdevice/by-name/boot'

Audio routing (the part that is not kernel)

The kernel exposes the mixer controls, but which controls to set is decided by the Android audio HAL from mixer_paths.xml. There is no kernel mechanism to influence that, so this one file has to change too.

patches/rom/mixer_paths.xml.patch does two things:

  1. Points the plain playback front-end paths at QUAT_MI2S_RX (the amplifier) instead of SLIMBUS_0_RX.
  2. Repoints headphones from SLIMBUS_5_RX — a backend this kernel does not implement at all, which is why headphone playback froze — to SLIMBUS_0_RX.

The proper way: ROM device tree

Apply it to your device tree and rebuild the ROM. This is the intended end state and needs no root at runtime:

cd device/microsoft/talkman
patch -p1 < /path/to/patches/rom/mixer_paths.xml.patch

The testing way: Magisk module

For iterating on a device without rebuilding a ROM, magisk/lumia950-speaker/ carries the same file as an overlay. Zip the folder's contents and flash it in the Magisk app.

This is a test vehicle, not the end state. If you are shipping a ROM, do the device tree change instead.

Verifying it works

With the jack empty, after boot:

adb shell su -c 'i2cget -y -f 2 0x40 0x12'      # 0x12  -> 11 dB gain, amp is alive
adb shell su -c 'cat /sys/kernel/debug/wcd9xxx_mbhc' | grep 'Insert detect'   # must be 0

Then play something and watch the HAL pick the speaker:

adb logcat -c
adb shell am start -a android.intent.action.VIEW -d file:///sdcard/test.wav -t audio/wav
adb logcat -d | grep -E 'enable_snd_device|Apply path|pcm_prepare'

Expected — and crucially no pcm_prepare returned -1:

enable_snd_device: snd_device(2: speaker)
Apply path: speaker
Apply path: low-latency-playback

docs/TESTING.md covers bypassing the HAL entirely with tinyalsa, which is the fastest way to tell a kernel problem from a routing problem.

Tuning the volume

The gain lives in the device tree, so no runtime hacks are needed:

&i2c_2 {
	tas2552@40 {
		ti,pga-gain = <0x16>;   /* 15 dB; the register value maps to (n - 7) dB */
	};
};

Valid range is 0x00–0x1F. The default is 0x12 (11 dB). Raise it only if your battery is healthy, and re-read the brownout warning above.

You can experiment live before committing to a rebuild:

adb shell su -c 'i2cset -y -f 2 0x40 0x12 0x16 b'

Known limitations

  • Earpiece audio comes out of the loudspeaker. The routing change hijacks the plain front-end paths, so every usecase lands on the amplifier, including the handset one. The proper fix is to give the speaker its own backend suffix so the HAL emits a distinct path name, which means adding a <backend_names> section to audio_platform_info.xml (absent on this ROM).
  • ACDB -> Not correctly initialized! is logged continuously. The loader wants /system/etc/acdbdata/<hw_platform>/ and the ROM ships those files flat. Supplying the SKUAA subdirectory does not silence it, so something else is mismatched between the loader and the HAL. Audio works regardless, but calibration and volume curves are presumably not applied.
  • Voice-call mixers still reference SLIM_5_RX. Deliberately untouched; telephony was out of scope.
  • WiFi is broken on this ROM. Unrelated to this work, and not addressed here.

Documentation

  • docs/HARDWARE.md — what the audio hardware is and how it is wired. Read this first; working it out was most of the effort.
  • docs/DESIGN.md — what each patch does and why it is shaped that way.
  • docs/TESTING.md — verification procedure and the failure modes we hit.

Credits

  • Android4Lumia950 for the base kernel and the Android port.
  • The TAS2552 codec driver derives from the mainline ASoC driver, originally Copyright (C) 2014 Xiaomi Corporation, author Nannan Wang. Retained under GPL-2.0-or-later.

License

GPL-2.0-or-later, matching the kernel it patches. See LICENSE.

About

Working loudspeaker and headphone audio for the Microsoft Lumia 950 (RM-1104) on LineageOS 18.1 - TAS2553 amplifier driver, Quaternary MI2S backend, and jack detection fix

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages