From: Karl Asseily <karl@asseily.com>
To: broonie@kernel.org, lgirdwood@gmail.com, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org, perex@perex.cz,
tiwai@suse.com
Cc: linux-sound@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, Karl Asseily <karl@asseily.com>
Subject: [PATCH 0/4] ASoC: add ESS Technology ES9039Q2M codec driver
Date: Thu, 20 Aug 2026 09:26:22 +0300 [thread overview]
Message-ID: <20260820062626.39218-1-karl@asseily.com> (raw)
This series adds support for the ESS Technology ES9039Q2M, a 32-bit
two-channel audio DAC with an asynchronous sample rate converter,
controlled over I2C.
The part has two control personalities selected by its MODE pin: hardware
mode, strapped by HW0/HW1/HW2 with no bus at all, and software mode over
I2C or SPI. This driver implements software mode over I2C, which MODE = GND
selects.
Three properties of the part shape the driver:
- The ASRC in front of the DAC means MCLK need not be synchronous with
BCLK or LRCK. A board can feed it a fixed oscillator and never touch the
clock again. In that asynchronous mode the part requires MCLK >= 130 x
Fs, so the driver installs a startup constraint deriving the maximum
rate from the MCLK it was given rather than advertising rates the
hardware cannot honour.
- Selecting an input format is two registers, not one. Register 57
INPUT_SEL chooses which port to listen to; register 1 SYS MODE CONFIG
enables the corresponding decoder, and at reset only ENABLE_TDM_DECODE
is set. Selecting DoP without also enabling ENABLE_DOP_DECODE leaves the
part hunting for a marker with the marker decoder switched off; it finds
no valid DoP and mutes. The driver sets both.
- Several registers have non-zero reserved defaults - register 88 reads
0xb8 at reset - so every write is read-modify-write.
Everything the driver exposes has been verified against the silicon on
hardware rather than against the driver's own read-back: each control is
written through ALSA and the chip's register is then read over raw I2C.
That covers the eight filter shapes, the modulator bandwidth, the IIR
bandwidth, the four signed 16-bit THD compensation coefficients at both
extremes of their range, and the automute enable, time, level and off-level
fields including the neighbouring MUTE_RAMP_TO_GND bit that shares a
register with the 11-bit time field.
Two limitations are deliberate and worth stating up front, because both
look like omissions:
- The programmable FIR coefficient controls are write-only. The part has a
PROG_COEFF_OUT register described as "Programmable FIR coefficient
readback", but it is not a RAM read port: it returns the last
coefficient written, whatever address is selected in PROG_COEFF_ADDR.
Measured by writing two different coefficients to addresses 0 and 1 and
reading them back with five different sequences - plain, with a settle
delay, with PROG_COEFF_EN set, with the address written twice, and with
a write-enable pulse after the address. All ten reads returned the value
written to address 1. A get() built on that register would return
something with the shape of data and none of its meaning, so there is
none.
- Coefficient uploads pulse PROG_COEFF_WE per coefficient, as the
datasheet's sequence specifies. Holding it high across the whole upload
also works on this silicon, but that is not what the documentation says.
DSD, DoP and S/PDIF input are all implemented. DoP is detected by the part
rather than announced by the host: AUTO_INPUT_SEL is enabled and both the
TDM and DoP decoders run, so a player can simply send DoP-encoded PCM, which
is the only way DoP works in practice. An earlier revision of this driver
required userspace to select DoP through a kcontrol first; no player can do
that, and the result was that DoP-encoded material rendered as the near-
silent hiss the DoP marker design deliberately degrades to. The datasheet
attaches a "data must be provided on the DATA2 pin" condition to automatic
detection; that applies to identifying DSD, whose channels arrive on separate
data lines, and DoP detects correctly on a two-channel I2S link without it.
DoP was verified end to end by generating a DSD64 test tone, carrying it as
32-bit PCM at 176400 Hz with nothing selected by hand, and confirming the
part's own DOP_VALID flag and INPUT_SELECT_OVERRIDE readback while it played.
ESS Technology has no bindings in the tree today, so the series also
introduces the vendor prefix.
Karl Asseily (4):
dt-bindings: vendor-prefixes: add ESS Technology
ASoC: dt-bindings: add ESS Technology ES9039Q2M
ASoC: es9039q2m: add ESS Technology ES9039Q2M codec driver
MAINTAINERS: add entry for the ES9039Q2M codec driver
.../bindings/sound/ess,es9039q2m.yaml | 61 +
.../devicetree/bindings/vendor-prefixes.yaml | 2 +
MAINTAINERS | 7 +
sound/soc/codecs/Kconfig | 14 +
sound/soc/codecs/Makefile | 2 +
sound/soc/codecs/es9039q2m.c | 1259 +++++++++++++++++
6 files changed, 1345 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/ess,es9039q2m.yaml
create mode 100644 sound/soc/codecs/es9039q2m.c
--
2.34.1
next reply other threads:[~2026-08-20 6:26 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-20 6:26 Karl Asseily [this message]
2026-08-20 6:26 ` [PATCH 1/4] dt-bindings: vendor-prefixes: add ESS Technology Karl Asseily
2026-08-20 6:30 ` Krzysztof Kozlowski
2026-08-20 6:48 ` Karl Asseily
2026-08-20 6:26 ` [PATCH 2/4] ASoC: dt-bindings: add ESS Technology ES9039Q2M Karl Asseily
2026-08-20 6:26 ` [PATCH 3/4] ASoC: es9039q2m: add ESS Technology ES9039Q2M codec driver Karl Asseily
2026-08-20 6:38 ` sashiko-bot
2026-08-20 6:26 ` [PATCH 4/4] MAINTAINERS: add entry for the " Karl Asseily
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260820062626.39218-1-karl@asseily.com \
--to=karl@asseily.com \
--cc=broonie@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=krzk+dt@kernel.org \
--cc=lgirdwood@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=perex@perex.cz \
--cc=robh@kernel.org \
--cc=tiwai@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox