ASoC: add ESS Technology ES9039Q2M codec driver

Karl Asseily <karl@asseily.com> says:

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 also has a hardware mode strapped by
HW0/HW1/HW2 with no control bus at all; this driver implements the
software mode that MODE = GND selects.

Two things about the part shape the driver:

 - Selecting an input format takes two registers, not one. INPUT_SEL
   chooses the port; SYS MODE CONFIG enables the matching 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, so it finds nothing and mutes. The
   driver writes both.

 - Several registers have non-zero reserved defaults - register 88 reads
   0xb8 at reset - so every write is read-modify-write.

The programmable FIR coefficient controls are write-only by design.
PROG_COEFF_OUT is documented as a coefficient readback but is not a RAM
read port: it returns the last coefficient written, whatever address is
selected in PROG_COEFF_ADDR. Measured with the driver out of the path,
five sequences, ten reads, all returning the same value. A get() built on
that register would return something with the shape of data and none of
its meaning, so there is none.

Every control has been verified against the silicon rather than against
the driver's own read-back - written through ALSA, then read over raw I2C
- and DSD, DoP and S/PDIF input are all implemented and tested on
hardware.

ESS Technology has no bindings in the tree today, so the series also adds
the vendor prefix, taken from the company's domain esstech.com.

Link: https://patch.msgid.link/20260918182317.143223-1-karl@asseily.com
This commit is contained in:
Mark Brown 2026-09-18 23:15:35 +02:00
commit 00e208e9ed
6 changed files with 2127 additions and 0 deletions

View File

@ -0,0 +1,94 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/esstech,es9039q2m.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ESS Technology ES9039Q2M audio DAC
maintainers:
- Karl Asseily <karl@asseily.com>
description:
The ES9039Q2M is a 32-bit two-channel audio DAC supporting PCM to 768 kHz,
DSD64 to DSD1024, DoP and S/PDIF. It is controlled over I2C or SPI when the
MODE pin selects software mode; this binding covers the I2C interface. The
part contains an asynchronous sample rate converter, so the system clock need
not be synchronous with the audio bit or frame clocks.
The four supplies are all nominally 3.3V and the datasheet requires a set
order - AVDD first, then VCCA about 200us later, then AVCC_DAC1 and
AVCC_DAC2, and the reverse on the way down. DVDD, the part's 1.2V rail, is
on-chip and needs only its decoupling capacitor - it is not a supply input
and has no property here.
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
const: esstech,es9039q2m
reg:
description:
I2C address, selected by the ADDR0 and ADDR1 pins - 0x48, 0x49, 0x4a or
0x4b for GND/GND, GND/AVDD, AVDD/GND and AVDD/AVDD respectively.
enum: [ 0x48, 0x49, 0x4a, 0x4b ]
clocks:
maxItems: 1
clock-names:
const: mclk
avdd-supply:
description:
3.3V supply for the part's internal digital regulator, pin AVDD. It is
the first rail up and the last down, per the ordering described above.
vcca-supply:
description: 3.3V analogue supply, pin VCCA.
avcc-dac1-supply:
description:
3.3V reference supply for the channel 1 analogue output stage, pin
AVCC_DAC1. The datasheet allows this rail to move by up to 15% where a
calibrating regulator tracks the DAC's output impedance.
avcc-dac2-supply:
description:
3.3V reference supply for the channel 2 analogue output stage, pin
AVCC_DAC2, with the same 15% allowance as channel 1.
"#sound-dai-cells":
const: 0
required:
- compatible
- reg
- avdd-supply
- vcca-supply
- avcc-dac1-supply
- avcc-dac2-supply
- "#sound-dai-cells"
unevaluatedProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
audio-codec@48 {
compatible = "esstech,es9039q2m";
reg = <0x48>;
#sound-dai-cells = <0>;
clocks = <&dac_mclk>;
clock-names = "mclk";
avdd-supply = <&dac_3v3>;
vcca-supply = <&dac_3v3>;
avcc-dac1-supply = <&dac_avcc1>;
avcc-dac2-supply = <&dac_avcc2>;
};
};

View File

@ -559,6 +559,8 @@ patternProperties:
description: Seiko Epson Corp.
"^esp,.*":
description: Espressif Systems Co. Ltd.
"^esstech,.*":
description: ESS Technology, Inc.
"^est,.*":
description: ESTeem Wireless Modems
"^eswin,.*":

View File

@ -9699,6 +9699,13 @@ S: Maintained
F: include/linux/errseq.h
F: lib/errseq.c
ES9039Q2M AUDIO CODEC DRIVER
M: Karl Asseily <karl@asseily.com>
L: linux-sound@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/sound/esstech,es9039q2m.yaml
F: sound/soc/codecs/es9039q2m.c
ESD CAN NETWORK DRIVERS
M: Stefan Mätje <stefan.maetje@esd.eu>
R: socketcan@esd.eu

View File

@ -123,6 +123,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_ES8328_I2C
imply SND_SOC_ES8375
imply SND_SOC_ES8389
imply SND_SOC_ES9039Q2M
imply SND_SOC_ES9356
imply SND_SOC_ES7134
imply SND_SOC_ES7241
@ -1317,6 +1318,19 @@ config SND_SOC_ES8389
tristate "Everest Semi ES8389 CODEC"
depends on I2C
config SND_SOC_ES9039Q2M
tristate "ESS Technology ES9039Q2M CODEC"
depends on I2C
select REGMAP_I2C
help
Enable support for the ESS Technology ES9039Q2M, a 32-bit
two-channel audio DAC with an asynchronous sample rate converter,
supporting PCM, DSD, DoP and S/PDIF input. This driver covers the
I2C control interface, which the MODE pin selects.
To compile this driver as a module, choose M here: the module
will be called snd-soc-es9039q2m.
config SND_SOC_ES9356
tristate "Everest Semi ES9356 CODEC SDW"
depends on SND_SOC_SDCA

View File

@ -140,6 +140,7 @@ snd-soc-es8328-i2c-y := es8328-i2c.o
snd-soc-es8328-spi-y := es8328-spi.o
snd-soc-es8375-y := es8375.o
snd-soc-es8389-y := es8389.o
snd-soc-es9039q2m-y := es9039q2m.o
snd-soc-es9356-y := es9356.o
snd-soc-framer-y := framer-codec.o
snd-soc-fs-amp-lib-y := fs-amp-lib.o
@ -586,6 +587,7 @@ obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o
obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o
obj-$(CONFIG_SND_SOC_ES8375) += snd-soc-es8375.o
obj-$(CONFIG_SND_SOC_ES8389) += snd-soc-es8389.o
obj-$(CONFIG_SND_SOC_ES9039Q2M) += snd-soc-es9039q2m.o
obj-$(CONFIG_SND_SOC_ES9356) += snd-soc-es9356.o
obj-$(CONFIG_SND_SOC_FRAMER) += snd-soc-framer.o
obj-$(CONFIG_SND_SOC_FS_AMP_LIB)+= snd-soc-fs-amp-lib.o

2008
sound/soc/codecs/es9039q2m.c Normal file

File diff suppressed because it is too large Load Diff