From 34dac73efe779b110ab27329c349d3bc8de9c9c3 Mon Sep 17 00:00:00 2001 From: "prompt.ac/@jeffrey" Date: Tue, 14 Apr 2026 23:36:07 -0700 Subject: [PATCH] native: SOF-aware audio period sizing (fixes G7 DAPM amp storm) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause of silent G7 speakers with everything else correct: the old audio.c config hardcoded ~1ms ALSA period (rate/1000 frames) + 4ms total buffer. Works fine on HDA-direct codecs (ThinkPad X13 etc.) but on SOF+MAX98360A the boot log shows **10,686 sdmode toggles per boot** — once per period, matching the ~5ms toggle spacing exactly. Mechanism: MAX98357A's DAPM event handler flips SD_MODE high on POST_PMU and low on PRE_PMD. At 4ms buffer depth, ac-native's 16ms paint-loop audio submission cadence misses every period = constant underrun = stream bounces PMU/PMD every period = amp physically toggles faster than it can stabilize = silence even though the ALSA layer looks fine. Probe sound/soc/sof's presence (card0 exists AND no legacy HDA codec97 node) and bump to 10ms period / 40ms buffer — same shape ChromeOS uses on Dedede. HDA paths unaffected; ThinkPad keeps its tight latency. Also: drop loglevel=7 + per-subsystem dyndbg from kernel cmdline now that we've extracted the diagnosis. Flooding tty0 with kernel messages was slowing userspace enough that the trackpad's HID polling was failing to register. Keep only max98357a dyndbg so the next boot confirms sdmode stays HIGH during playback instead of cycling. Co-Authored-By: Claude Opus 4.6 (1M context) --- fedac/native/kernel/config-minimal | 2 +- fedac/native/src/audio.c | 32 +++++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/fedac/native/kernel/config-minimal b/fedac/native/kernel/config-minimal index b5b4e4d381..380223a10b 100644 --- a/fedac/native/kernel/config-minimal +++ b/fedac/native/kernel/config-minimal @@ -425,7 +425,7 @@ CONFIG_HOTPLUG_CPU=y CONFIG_LEGACY_VSYSCALL_XONLY=y # CONFIG_LEGACY_VSYSCALL_NONE is not set CONFIG_CMDLINE_BOOL=y -CONFIG_CMDLINE="initrd=\\initramfs.cpio.gz console=tty0 loglevel=7 vt.global_cursor_default=0 init=/init mitigations=off snd_hda_intel.power_save=0 nmi_watchdog=0 tsc=reliable no_timer_check acpi_backlight=native thinkpad_acpi.brightness_enable=1 i8042.reset i8042.nomux reboot=efi,cold dyndbg=\"file drivers/pinctrl/intel/* +p; file drivers/gpio/* +p; file sound/soc/codecs/max98357a.c +p\"" +CONFIG_CMDLINE="initrd=\\initramfs.cpio.gz console=tty0 quiet loglevel=3 vt.global_cursor_default=0 init=/init mitigations=off snd_hda_intel.power_save=0 nmi_watchdog=0 tsc=reliable no_timer_check acpi_backlight=native thinkpad_acpi.brightness_enable=1 i8042.reset i8042.nomux reboot=efi,cold dyndbg=\"file sound/soc/codecs/max98357a.c +p\"" # CONFIG_CMDLINE_OVERRIDE is not set CONFIG_MODIFY_LDT_SYSCALL=y # CONFIG_STRICT_SIGALTSTACK_SIZE is not set diff --git a/fedac/native/src/audio.c b/fedac/native/src/audio.c index 50bf5a2cf3..177634be3a 100644 --- a/fedac/native/src/audio.c +++ b/fedac/native/src/audio.c @@ -1842,12 +1842,34 @@ ACAudio *audio_init(void) { fprintf(stderr, "[audio] Selected rate: %u Hz (hw range %u–%u)\n", rate, rate_min, rate_max); snd_pcm_hw_params_set_rate_near(pcm, params, &rate, 0); - // Scale period and buffer to ~1ms latency at the negotiated rate - snd_pcm_uframes_t period = rate / 1000; // ~1ms worth of frames - if (period < 64) period = 64; + // Period + buffer sizing. The old config aimed for ~1ms latency (period = + // rate/1000, buffer = 4 periods) which works on HDA-direct codecs but + // breaks SOF+MAX98360A on Jasper Lake Chromebooks: the MAX98357A DAPM + // event handler toggles the amp's SD_MODE GPIO on every PMU/PMD event, + // and with a 4ms buffer the stream underruns constantly → DAPM rapid- + // cycles the amp on/off → audio never stabilizes → speakers stay silent + // despite mixer, codec, and GPIO all looking correct. We saw 10,686 + // sdmode toggles in a single boot's kmsg on the G7 at the 1ms setting. + // + // Probe whether we're on a SOF platform (sound/soc/sof is one path) and + // bump to 10ms / 40ms which is what ChromeOS itself uses. Non-SOF HDA + // devices (ThinkPads, most laptops) keep the tight latency because their + // amp/codec model doesn't gate on per-period DAPM events. + int sof_active = (access("/sys/class/sound/card0/id", R_OK) == 0) && + (access("/proc/asound/card0/codec97#0", F_OK) != 0); + snd_pcm_uframes_t period; + snd_pcm_uframes_t buffer_size; + if (sof_active) { + period = rate / 100; // 10ms (480 frames at 48kHz) + buffer_size = period * 4; // 40ms total — SOF DAPM-friendly + fprintf(stderr, "[audio] SOF platform detected — period=%lu buffer=%lu (10ms/40ms)\n", + (unsigned long)period, (unsigned long)buffer_size); + } else { + period = rate / 1000; // 1ms on HDA-direct paths + if (period < 64) period = 64; + buffer_size = period * 4; + } snd_pcm_hw_params_set_period_size_near(pcm, params, &period, 0); - - snd_pcm_uframes_t buffer_size = period * 4; // 4 periods (~4ms total) snd_pcm_hw_params_set_buffer_size_near(pcm, params, &buffer_size); err = snd_pcm_hw_params(pcm, params); -- 2.54.0