Skip to content

Neo: take the jack codec's register restore off the wake (400 kHz bus, card-resume restore) - #1700

Merged
DjDeveloperr merged 3 commits into
integration/aurorafrom
fix/t8140-codec-resume
Nov 12, 2026
Merged

DjDeveloperr merged 3 commits into
integration/aurorafrom
fix/t8140-codec-resume

Conversation

@DjDeveloperr

@DjDeveloperr DjDeveloperr commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Waking from a DRAM-kept sleep, the Neo (J700) used to spend 101 ms on the jack codec, the longest step of the resume phase after #1658. This takes it off the wake's critical path, and makes the work itself about 2.6 times faster.

Commits (on integration cae47c00)

  • 4f556ae5 arm64: dts: apple: t8140-j700: run the jack codec's bus at 400 kHz
    • The ADT gives each I2C device an SCL period in ns. Measured on the J700, J414s and J714s:
      • 2500 (400 kHz) for the codecs, speaker amps and backlight controllers;
      • 10000 (100 kHz) for slower parts such as the SD reader and the DisplayPort converter.
    • The J700's i2c0 carries the CS42L83 alone. Linux used the 100 kHz default.
  • ecdc0b67 ASoC: cs42l83: restore the registers from the card's resume
    • When ASoC has suspended the codec, the device's resume only powers it up, about 6 ms.
    • The register restore moves to the component's resume, which ASoC calls from its deferred card resume, before DAPM and before user space can reach the card again.
    • Either may run first: the restore happens once, on a powered codec, and a sleep that comes before it runs it first.
    • The interrupt masks reset to masked, so the codec signals nothing in between.
    • snd_soc_cs42l83_i2c.defer_restore=0 restores in the device's resume, as before.
  • 489291aa ASoC: cs42l83: defer the register restore on T8140 only
    • The deferral applies only when the root is apple,t8140, the one machine it was measured on.
    • The T8103 machines with this codec (J274, J293, J313, J456, J457) get the component driver unchanged, without the new suspend/resume hooks, so their device resume restores the registers inline as before.
    • CS42L84 is a separate driver and isn't touched.

Measured on the Neo (J700), 2026-11-12

Kit: the first two commits plus a debug-only commit (#1682's diagnostic line) on cae47c00, aura main Stage 2, one boot (f48fc579). The booted DT has clock-frequency = <400000> on i2c@385010000.

before this PR
cs42l83 resume callback (power trace, median of 3) 101.1 ms (async, the resume phase's critical path) 5.7 ms
dpm_resume phase 157.6 ms 110.4 ms; usb1 at 51 ms is now the longest
regcache_sync (kprobes) 94 ms in the device's resume, 100 kHz 36 ms, at 400 kHz, inside ASoC's deferred card resume

The "before" column is the #1658 measurements, on an earlier integration head.

Wake timing on the same boot, 16 DRAM-kept wakes alternating defer_restore (both arms at 400 kHz). Medians, seconds after the PMU RTC alarm:

defer_restore=0 defer_restore=1 (default)
Suspend exit 0.293 0.279
Internal DCP firmware up 0.200 0.184
KWin's mode set 0.353 0.335
Backlight on 0.474 0.456

Safety, same boot:

  • 10 DRAM-kept sleeps returned, all DRAM-kept.
  • H.264/HEVC encodes were byte-identical after the wakes.
  • No cs42l83/cs42l42 line in any sleep's log.
  • Wi-Fi and Bluetooth OK.

489291aa was build-checked only. On the J700 it changes nothing, since the root there is "apple,j700", "apple,t8140". It hasn't been run on a T8103 machine; there, it keeps the code path from before this PR.

Playback right after a wake

Separate boot (2026-11-12 11:20), same kit: 3 DRAM-kept RTC wakes. At each wake, 1 s of silence was played on the jack's PCM (card AppleJ700, device 0 "Primary"; never the speakers) the moment user space thawed:

  • 3/3 played, aplay rc 0;
  • aplay returned 1214, 1105 and 1104 ms after the thaw for 1 s of audio, so the card was usable within about 0.1–0.2 s, including its deferred register restore.

🤖 Generated with Claude Code

The ADT gives each I2C device an SCL period in ns: 2500 for the
codecs, speaker amps and backlight controllers of the J700, J414s and
J714s, 10000 for slower parts such as the SD card reader and the
DisplayPort converter. The J700's i2c0 carries the CS42L83 alone, and
macOS runs it at 400 kHz. Linux took the 100 kHz default, and the
codec's register restore after a sleep, single writes over a paged
regmap, took 94 ms of the wake.

Signed-off-by: Diljit Singh <hey@djdev.me>
The register restore after a sleep is about 100 ms of I2C writes,
done in the device's resume, which the PM core waits for before user
space thaws: the longest device resume of a J700 wake.

ASoC resumes the card from deferred work, so that a slow codec doesn't
hold up the system resume, and keeps user space off the card until it
has finished. When ASoC suspended the codec, power it up in the
device's resume as before and leave the restore to the component's
resume, which that deferred work calls before DAPM and before the card
is usable. The interrupt masks reset to masked, so the codec signals
nothing until then. Either may come first; the restore runs once, on
a powered codec, and a sleep that comes before it runs it first.

defer_restore=0 restores in the device's resume, as before.

Signed-off-by: Diljit Singh <hey@djdev.me>
@DjDeveloperr
DjDeveloperr marked this pull request as ready for review November 12, 2026 16:25
The deferred restore was measured on the J700 alone. On the T8103
machines that use the same codec, ASoC gets the component driver
without suspend and resume hooks, so the device's resume restores
the registers itself, as before.

Signed-off-by: Diljit Singh <hey@djdev.me>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant