Free, open source speaker audio for Dell Chromebook 3100 and Chromebook 3100
2-in-1 (board fleex, Celeron N4000/N4020) running Windows 10 or 11 on
MrChromebox firmware. Also relevant to other Gemini Lake chromebooks with the same
codecs.
If Windows says "No audio output device is installed" on a chromebook, or the speakers are silent with no audio device in Device Manager, this is the missing piece: the Intel AudioDSP (SOF / Sound Open Firmware) with a DA7219 headset codec and a MAX98357A speaker amplifier has no in-box Windows driver.
Written from open sources only:
the Linux SOF driver for the hardware protocol, and CoolStar's BSD-licensed
sklhdaudbus and codec drivers for everything around it. No part of it is derived
from disassembling anyone's binary.
This is experimental kernel code that drives an amplifier connected to your speakers. It has already destroyed one speaker on the development machine — read "Damage warning" below before installing it.
| your situation | this driver |
|---|---|
| Dell Chromebook 3100 or 3100 2-in-1, Windows installed, no sound | yes, speakers |
| "No audio output device is installed" in Sound settings | yes - there is no endpoint until a driver publishes one |
| Another Gemini Lake chromebook with DA7219 + MAX98357A | very likely, same topology |
| Gemini Lake chromebook with cs42l42 or rt5682 instead | needs its own .tplg and widget names - see docs/PROGRESS.md |
| Headphone jack or microphone | not yet |
| Apollo Lake, Braswell, Tiger Lake, AMD | no - different DSP or different firmware |
You also need CoolStar's sklhdaudbus and codec drivers installed first; they are
free and open source, and the install script checks for them.
- Boots SOF firmware on the AudioDSP and talks IPC3 both ways
- Parses the real
.tplgtopology and takes the SSP clocking from it - Publishes a WaveRT render endpoint, so ordinary applications play to it
- The Windows volume slider and mute drive the DSP's volume stage in hardware,
not the software mixer.
QueryHardwareSupporton the endpoint returns 0x3. - A ceiling the slider cannot exceed, enforced three times over: in the topology
handler, in the driver's setter, and by the firmware's own
max_value
- Speakers only. No headphones, no microphone. SSP2 and DMIC are unwired.
- 48 kHz, 16 bit, stereo only. Windows resamples everything else, which works, but the driver refuses other formats outright.
- Mono in practice — and this is the hardware, not the driver. The MAX98357A is one mono amplifier; both speakers get the same signal, so there is no left / right separation to be had and volume is a single control.
- Hardcoded for GLK with DA7219 + MAX98357A. A chromebook with cs42l42 or rt5682 needs its own topology file and different widget names.
- No power management worth the name: D3 means a full firmware re-download.
Fixed in the current build — the full hunt is in docs/PROGRESS.md, phases 14
and 15. Two distinct bugs stacked on top of each other:
- The mailbox was polled from a timer that could not keep up with the
firmware's notification rate, so under CPU load the doorbell went unanswered
and the IPC channel deadlocked. The driver now takes the interrupt through
sklhdaudbus'sRegisterInterrupt, acknowledged at DIRQL where nothing can starve it. PCM_FREEwas only sent when a stream closed, not when it stopped. Linux frees the PCM on every stop (pcm.c,reset_hw_params); this driver did not, so a pause/resume inside one long-lived stream — which is what changing videos in a browser is — sentPCM_PARAMSon top of a still-configured host component. Some time later the firmware's IPC task simply stopped: cores powered, no panic, no notifications, every later request a pure timeout. The stop path now runsTRIG_STOP→ DMA stop →PCM_FREE, in Linux's order.
Health is readable without a debugger, under the device's hardware key:
| value | healthy reading |
|---|---|
IrqRegistered |
1 |
MailboxIrq |
climbing steadily while audio plays |
DspStalls |
0 — increments when the DSP goes quiet mid-stream |
IpcFailures |
0 — increments when a request times out |
FwPanicHipct |
0 — non-zero is a firmware oops, with its code |
Belt and braces, both in this repo:
fix-audio.bat(run as administrator) restarts the device and brings the sound back in seconds, without rebooting.sofglk-watchdog.ps1— register it as a SYSTEM scheduled task and forget it: it watchesIpcFailures + DspStalls, restarts the device when they move, frees the browser's audio process if that blocks the restart, and re-enables a device found disabled. 60 s cooldown so it cannot loop.
| Hardware | Gemini Lake chromebook, DA7219 + MAX98357A |
| Firmware | MrChromebox (or anything that leaves Secure Boot off) |
sklhdaudbus |
installed first — it publishes the CSAUDIO\ADSP device |
max98357a driver |
installed — it owns the amplifier's SD_MODE pin |
| Test signing | on (bcdedit /set testsigning on, then reboot) |
sklhdaudbus, max98357a and da7219 are at https://github.com/chrultrabook.
Test signing is needed because this driver is signed with a self-signed WDK certificate. Attestation signing, which is what CoolStar's drivers carry, needs an EV code signing certificate, which needs a registered company; Azure Trusted Signing does not cover kernel drivers. There is no free path to a signature that Windows accepts without test mode.
powershell -ExecutionPolicy Bypass -File install.ps1
It checks the prerequisites, trusts the bundled test certificate, installs the driver, and prints what the driver reported: firmware state, topology counts, whether the graph came up, and the volume ceiling.
To remove it again:
powershell -ExecutionPolicy Bypass -File uninstall.ps1
Use the normal Windows volume slider — it controls the DSP directly.
The driver also holds a ceiling that the slider cannot pass, because this amplifier can drive more power than the speakers are rated for. Slider at maximum means "as loud as the ceiling allows". To move the ceiling:
powershell -File set-volume.ps1 -AttenDb 3
Lower numbers are louder; the default is 6, meaning 6 dB below full scale. Dell rates these speakers at 2 W average / 2.5 W peak and the MAX98357A can deliver about 3.2 W into 4 ohms, so 0 dB with continuous content is outside what the hardware is rated for. Going below 6 is your call.
The MAX98357A has no registers. It has an enable pin, and this driver decides when that pin is high. Get that wrong and the amplifier drives a constant level into the voice coil: the cone parks off centre, no sound comes out, and every watt becomes heat in one spot. That destroyed a speaker on the development machine before the cause was understood — the smell was the first symptom, and by then it was too late.
The driver now:
- enables the amplifier only while it can see audio actually moving through the DMA, and drops it within ~100 ms of silence — flowing zeros do not count
- enables it after the DMA is running and disables it before the DMA stops
- zero fills the buffer and lets it drain before stopping anything
- keeps enable/disable notifications at least 25 ms apart, because the codec
driver raises its pin from a work item that sleeps 5 ms first and a Stop landing
inside that window is silently undone (see
max98357a-sdmode-race.md) - answers
Stopwhen a codec announces itself, so nothing is left enabled from a previous session - kills the DSP clocks outright if the DMA position freezes while the amplifier is on — the amp mutes itself without a bit clock — and does the same from a bugcheck callback, so a crash cannot leave the speaker energised
None of that is a guarantee. If the speakers ever get warm, unplug them and say so.
Driver source: BSD-3-Clause, same as the surrounding ecosystem.
Redistributed binaries, both from https://github.com/thesofproject/sof-bin:
| file | what it is | licence |
|---|---|---|
sofglk-fw.ri |
sof-apl.ri from sof-bin v2.2 — Gemini Lake runs the Apollo Lake image, and sof-bin's sof-glk.ri is a symlink to it |
BSD-3-Clause plus Intel's limited patent licence (LICENCE.Intel) |
sof-glk-da7219.tplg |
topology from sof-bin v2.2 | same |
The firmware is installed under our own name so that uninstalling this driver
cannot disturb a sof-glk.ri that belongs to somebody else's package.
Everything the driver does is reported under the device's hardware key, readable without a debugger:
powershell -c "$k=(Get-ChildItem -Recurse 'HKLM:\SYSTEM\CurrentControlSet\Enum\CSAUDIO' | ? PSChildName -eq 'Device Parameters')[0].PSPath; Get-ItemProperty $k | Format-List"
| value | healthy reading |
|---|---|
FsrAfterDlState |
5, FW_ENTERED; anything else means the firmware did not boot |
TplgParseStatus |
0, with TplgWidgets 60 / TplgRoutes 28 / TplgLinks 6 on this board |
GraphReady |
1 once the pipeline is built |
SubdeviceStatus / TopologyStatus / ConnectionStatus |
all 0 — the wave filter, the topology filter, and the link between them |
*ReplyError |
per-IPC firmware errors, all 0 on a healthy bring-up |
AmpEnabled |
the amplifier right now — should be 0 whenever nothing is playing |
VolumeGain |
current DSP gain, Qx.16; 65536 would be 0 dB, the ceiling is lower |
ClocksKilled |
1 means the stall watchdog fired; restart the device to play again |
WaveRtMaxPos |
how far the DMA got; should reach the buffer size |
CsAudioListening |
1 once the driver is receiving codec notifications too |
FmtValidBits / FmtForce32Container |
what the amplifier asked for: 16 valid bits in a 32-bit container |