All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] ASoC: add ESS Technology ES9039Q2M codec driver
@ 2026-08-20  6:26 Karl Asseily
  2026-08-20  6:26 ` [PATCH 1/4] dt-bindings: vendor-prefixes: add ESS Technology Karl Asseily
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Karl Asseily @ 2026-08-20  6:26 UTC (permalink / raw)
  To: broonie, lgirdwood, robh, krzk+dt, conor+dt, perex, tiwai
  Cc: linux-sound, devicetree, linux-kernel, Karl Asseily

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


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-08-20  6:48 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-20  6:26 [PATCH 0/4] ASoC: add ESS Technology ES9039Q2M codec driver Karl Asseily
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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.