devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] ASoC: basic support for configuring bus keepers
@ 2025-12-09  9:31 James Calligeros
  2025-12-09  9:31 ` [PATCH 1/7] ASoC: dt-bindings: convert tdm-slot to YAML James Calligeros
                   ` (7 more replies)
  0 siblings, 8 replies; 15+ messages in thread
From: James Calligeros @ 2025-12-09  9:31 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Kuninori Morimoto, Shengjiu Wang, Jaroslav Kysela,
	Takashi Iwai, Shenghao Ding, Kevin Lu, Baojun Xu
  Cc: linux-sound, devicetree, imx, linux-arm-kernel, linux-kernel,
	asahi, James Calligeros

Hi all,

This series introduces some infrastructure to allow platform drivers
to specify what a DAI should be doing when it is not active on the
bus. The primary use case for this is configuring bus keepers which
may be integrated into various codecs.

Consider a device with two codecs that report voice coil voltage and
current data back to the host via I2S. Codec A is configured to transmit
its V/ISENSE data on TDM slots 1 and 3, while Codec B is configured to
do so on slots 2 and 4. The receiving end sums the two together.
If Codec A transmits anything on slots 2 or 4 (and vice versa), the
result is a bus conflict.

Some codecs include configurable bus keepers to ameliorate this issue.
Notable examples are the TI TAS2764 and TAS2770. By default, these
codecs keep their SDOUT pin floating during unconfigured TDM slots,
however this can result in garbage data on the bus. TAS2764 can be
set up to fill specific TDM slots with zeroes, TAS2770 can hold its
SDOUT pin to ground.

This feature is necessary to properly drive the speaker systems found
on most Apple Silicon laptops. All but three models include six codecs
in two groups of three driving two woofers and a tweeter on both the left
and right channels. Each codec group has a single line for SDOUT, to
which all codecs are connected. The two groups are then summed on to
one I2S port. Each group must ensure that it is silent on the bus while
the other is supposed to be active.

In the downstream Asahi Linux kernel[1], we set up one codec in each
group to zero-fill or pull down its group's side of the bus for the
opposite group's transmit slots. This is done entirely in the codec
driver, however this approach is perhaps over-fit for our use case.
Following previous mailing list discussions[2], I have tried to
expose the functionality in a more configurable and generic way.

I have integrated this approach into our downstream platform driver
and select Devicetrees as an example of how this mechanism is intended
to be used[3].

Regards,
James

[1] https://github.com/AsahiLinux/linux/tree/bits/070-audio
[2] https://lore.kernel.org/asahi/20250227-apple-codec-changes-v3-17-cbb130030acf@gmail.com/
[3] https://github.com/chadmed/tree/tdm-revised2

---
James Calligeros (7):
      ASoC: dt-bindings: convert tdm-slot to YAML
      ASoC: dt-bindings: update tdm-slot.txt references to tdm-slot.yaml
      ASoC: dt-bindings: add TDM slot idle mode properties
      ASoC: soc-dai: define TDM idle behaviour modes
      ASoC: soc-dai: add common operation to set TDM idle mode
      ASoC: tas2764: expose SDOUT bus keeper via set_tdm_idle operation
      ASoC: tas2770: expose SDOUT bus keeper via set_tdm_idle

 .../bindings/sound/imx-audio-card.yaml   |  4 +-
 .../bindings/sound/simple-card.yaml      |  4 +-
 .../bindings/sound/tdm-slot.txt          | 29 --------
 .../bindings/sound/tdm-slot.yaml         | 66 +++++++++++++++++
 include/sound/soc-dai.h                  | 20 ++++++
 sound/soc/codecs/tas2764.c               | 95 +++++++++++++++++++++++++
 sound/soc/codecs/tas2764.h               | 11 +++
 sound/soc/codecs/tas2770.c               | 75 +++++++++++++++++++
 sound/soc/codecs/tas2770.h               | 12 ++++
 sound/soc/soc-dai.c                      | 40 +++++++++++
 10 files changed, 323 insertions(+), 33 deletions(-)
---
base-commit: e4deadb3e562aadf2825f28be3dcbbf01cf2ef17
change-id: 20251201-tdm-idle-slots-10ba92516da4

Best regards,
-- 
James Calligeros <jcalligeros99@gmail.com>


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

* [PATCH 1/7] ASoC: dt-bindings: convert tdm-slot to YAML
  2025-12-09  9:31 [PATCH 0/7] ASoC: basic support for configuring bus keepers James Calligeros
@ 2025-12-09  9:31 ` James Calligeros
  2025-12-09 10:38   ` Rob Herring (Arm)
  2025-12-09  9:31 ` [PATCH 2/7] ASoC: dt-bindings: update tdm-slot.txt references to tdm-slot.yaml James Calligeros
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: James Calligeros @ 2025-12-09  9:31 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Kuninori Morimoto, Shengjiu Wang, Jaroslav Kysela,
	Takashi Iwai, Shenghao Ding, Kevin Lu, Baojun Xu
  Cc: linux-sound, devicetree, imx, linux-arm-kernel, linux-kernel,
	asahi, James Calligeros

This schema was still in plaintext form. Convert to YAML format.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
 .../bindings/sound/tdm-slot.txt          | 29 ---------------------
 .../bindings/sound/tdm-slot.yaml         | 34 +++++++++++++++++++++++++
 2 files changed, 34 insertions(+), 29 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/tdm-slot.txt b/Documentation/devicetree/bindings/sound/tdm-slot.txt
deleted file mode 100644
index 4bb513ae62fc..000000000000
--- a/Documentation/devicetree/bindings/sound/tdm-slot.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-TDM slot:
-
-This specifies audio DAI's TDM slot.
-
-TDM slot properties:
-dai-tdm-slot-num : Number of slots in use.
-dai-tdm-slot-width : Width in bits for each slot.
-dai-tdm-slot-tx-mask : Transmit direction slot mask, optional
-dai-tdm-slot-rx-mask : Receive direction slot mask, optional
-
-For instance:
-	dai-tdm-slot-num = <2>;
-	dai-tdm-slot-width = <8>;
-	dai-tdm-slot-tx-mask = <0 1>;
-	dai-tdm-slot-rx-mask = <1 0>;
-
-And for each specified driver, there could be one .of_xlate_tdm_slot_mask()
-to specify an explicit mapping of the channels and the slots. If it's absent
-the default snd_soc_of_xlate_tdm_slot_mask() will be used to generating the
-tx and rx masks.
-
-For snd_soc_of_xlate_tdm_slot_mask(), the tx and rx masks will use a 1 bit
-for an active slot as default, and the default active bits are at the LSB of
-the masks.
-
-The explicit masks are given as array of integers, where the first
-number presents bit-0 (LSB), second presents bit-1, etc. Any non zero
-number is considered 1 and 0 is 0. snd_soc_of_xlate_tdm_slot_mask()
-does not do anything, if either mask is set non zero value.
diff --git a/Documentation/devicetree/bindings/sound/tdm-slot.yaml b/Documentation/devicetree/bindings/sound/tdm-slot.yaml
new file mode 100644
index 000000000000..b67844e1dfd5
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tdm-slot.yaml
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/tdm-slot.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Time Division Multiplexing (TDM) Slot Parameters
+
+maintainers:
+  - Liam Girdwood <lgirdwood@gmail.com>
+
+select: false
+
+definitions:
+  dai-tdm-slot-num:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: Number of slots in use
+
+  dai-tdm-slot-width:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: Width, in bits, of each slot
+
+  dai-tdm-slot-tx-mask:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    description: Transmit direction slot mask. Optional. Drivers may specify an
+      .xlate_tdm_slot_mask() to generate a slot mask dynamically. If neither
+      this property nor a driver-specific function are specified, the default
+      snd_soc_xlate_tdm_slot_mask() function will be used to generate a mask.
+      The first element of the array is slot 0 (LSB). Any nonzero value will be
+      treated as 1.
+
+  dai-tdm-slot-rx-mask:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    description: Receive direction slot mask. Optional. Identical to TX mask.

-- 
2.52.0


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

* [PATCH 2/7] ASoC: dt-bindings: update tdm-slot.txt references to tdm-slot.yaml
  2025-12-09  9:31 [PATCH 0/7] ASoC: basic support for configuring bus keepers James Calligeros
  2025-12-09  9:31 ` [PATCH 1/7] ASoC: dt-bindings: convert tdm-slot to YAML James Calligeros
@ 2025-12-09  9:31 ` James Calligeros
  2025-12-09 16:11   ` Frank Li
  2025-12-09 19:13   ` Rob Herring
  2025-12-09  9:31 ` [PATCH 3/7] ASoC: dt-bindings: add TDM slot idle mode properties James Calligeros
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 15+ messages in thread
From: James Calligeros @ 2025-12-09  9:31 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Kuninori Morimoto, Shengjiu Wang, Jaroslav Kysela,
	Takashi Iwai, Shenghao Ding, Kevin Lu, Baojun Xu
  Cc: linux-sound, devicetree, imx, linux-arm-kernel, linux-kernel,
	asahi, James Calligeros

Ensure that all references to tdm-slot.txt have been updated to
tdm-slot.yaml.

Achieved by running "sed -i 's/tdm-slot.txt/tdm-slot.yaml/g' *"
against the bindings/sound. No other references to the file
were found in the tree.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
 .../bindings/sound/imx-audio-card.yaml   | 4 ++--
 .../bindings/sound/simple-card.yaml      | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/imx-audio-card.yaml b/Documentation/devicetree/bindings/sound/imx-audio-card.yaml
index 3c75c8c78987..1df29a556120 100644
--- a/Documentation/devicetree/bindings/sound/imx-audio-card.yaml
+++ b/Documentation/devicetree/bindings/sound/imx-audio-card.yaml
@@ -39,11 +39,11 @@ patternProperties:
             - dsp_b
 
       dai-tdm-slot-num:
-        description: see tdm-slot.txt.
+        description: see tdm-slot.yaml.
         $ref: /schemas/types.yaml#/definitions/uint32
 
       dai-tdm-slot-width:
-        description: see tdm-slot.txt.
+        description: see tdm-slot.yaml.
         $ref: /schemas/types.yaml#/definitions/uint32
 
       playback-only:
diff --git a/Documentation/devicetree/bindings/sound/simple-card.yaml b/Documentation/devicetree/bindings/sound/simple-card.yaml
index 533d0a1da56e..2e1a5b3216c5 100644
--- a/Documentation/devicetree/bindings/sound/simple-card.yaml
+++ b/Documentation/devicetree/bindings/sound/simple-card.yaml
@@ -28,11 +28,11 @@ definitions:
     $ref: /schemas/types.yaml#/definitions/flag
 
   dai-tdm-slot-num:
-    description: see tdm-slot.txt.
+    description: see tdm-slot.yaml.
     $ref: /schemas/types.yaml#/definitions/uint32
 
   dai-tdm-slot-width:
-    description: see tdm-slot.txt.
+    description: see tdm-slot.yaml.
     $ref: /schemas/types.yaml#/definitions/uint32
 
   system-clock-frequency:

-- 
2.52.0


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

* [PATCH 3/7] ASoC: dt-bindings: add TDM slot idle mode properties
  2025-12-09  9:31 [PATCH 0/7] ASoC: basic support for configuring bus keepers James Calligeros
  2025-12-09  9:31 ` [PATCH 1/7] ASoC: dt-bindings: convert tdm-slot to YAML James Calligeros
  2025-12-09  9:31 ` [PATCH 2/7] ASoC: dt-bindings: update tdm-slot.txt references to tdm-slot.yaml James Calligeros
@ 2025-12-09  9:31 ` James Calligeros
  2025-12-09  9:31 ` [PATCH 4/7] ASoC: soc-dai: define TDM idle behaviour modes James Calligeros
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: James Calligeros @ 2025-12-09  9:31 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Kuninori Morimoto, Shengjiu Wang, Jaroslav Kysela,
	Takashi Iwai, Shenghao Ding, Kevin Lu, Baojun Xu
  Cc: linux-sound, devicetree, imx, linux-arm-kernel, linux-kernel,
	asahi, James Calligeros

Add properties to describe TDM slot idle behaviour.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
 .../bindings/sound/tdm-slot.yaml         | 32 +++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/tdm-slot.yaml b/Documentation/devicetree/bindings/sound/tdm-slot.yaml
index b67844e1dfd5..b247b315d7f4 100644
--- a/Documentation/devicetree/bindings/sound/tdm-slot.yaml
+++ b/Documentation/devicetree/bindings/sound/tdm-slot.yaml
@@ -11,6 +11,16 @@ maintainers:
 
 select: false
 
+$defs:
+  dai-tdm-idle-mode:
+    $ref: /schemas/types.yaml#/definitions/string
+    enum:
+      - none
+      - off
+      - zero
+      - pulldown
+      - hiz
+
 definitions:
   dai-tdm-slot-num:
     $ref: /schemas/types.yaml#/definitions/uint32
@@ -32,3 +42,25 @@ definitions:
   dai-tdm-slot-rx-mask:
     $ref: /schemas/types.yaml#/definitions/uint32-array
     description: Receive direction slot mask. Optional. Identical to TX mask.
+
+  dai-tdm-slot-tx-idle-mode:
+    $ref: "#/$defs/dai-tdm-idle-mode"
+    description: Transmit direction idle slot mode. Optional. For hardware
+      that can configure its behaviour during idle TDM slots via
+      .set_tdm_idle(). "None" represents UB/unspecified behaviour and is the
+      same as not setting this property.
+
+  dai-tdm-slot-rx-idle-mode:
+    $ref: "#/$defs/dai-tdm-idle-mode"
+    description: Receive direction idle slot mode. Optional. Identical to TX
+      idle slot mode.
+
+  dai-tdm-slot-tx-idle-mask:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: Transmit direction idle slot mask. Optional. 1 represents
+      an idle slot.
+
+  dai-tdm-slot-rx-idle-mask:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: Receive direction idle slot mask. Optional. Identical to
+      TX mask.

-- 
2.52.0


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

* [PATCH 4/7] ASoC: soc-dai: define TDM idle behaviour modes
  2025-12-09  9:31 [PATCH 0/7] ASoC: basic support for configuring bus keepers James Calligeros
                   ` (2 preceding siblings ...)
  2025-12-09  9:31 ` [PATCH 3/7] ASoC: dt-bindings: add TDM slot idle mode properties James Calligeros
@ 2025-12-09  9:31 ` James Calligeros
  2025-12-10  2:22   ` Mark Brown
  2025-12-09  9:31 ` [PATCH 5/7] ASoC: soc-dai: add common operation to set TDM idle mode James Calligeros
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: James Calligeros @ 2025-12-09  9:31 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Kuninori Morimoto, Shengjiu Wang, Jaroslav Kysela,
	Takashi Iwai, Shenghao Ding, Kevin Lu, Baojun Xu
  Cc: linux-sound, devicetree, imx, linux-arm-kernel, linux-kernel,
	asahi, James Calligeros

Some audio devices, such as certain Texas Instruments codecs,
include configurable bus keepers.

Imagine for example two codecs sharing a bus. When one codec is
transmitting, the other must ensure that it is holding its side
to 0, or data from the transmitting codec will be corrupted. We
can trust the "idle" codec to simply do this itself, however
this is undefined behaviour. Some devices may leave the line
floating, others still may pull the line high. We need a way to
control this behaviour.

Thus, we define five possible bus-keeping modes that a device can
be in: NONE (UB/as initialised), OFF (explicitly disabled), ZERO
(actively transmit a 0), PULLDOWN, and HIZ (floating).

These will be consumed by CODEC/CPU drivers via a common DAI
op, enabling the explicit configuration of bus keepers where
required.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
 include/sound/soc-dai.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 224396927aef..a5784ef8e3f7 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -52,6 +52,19 @@ struct snd_compr_stream;
 #define SND_SOC_POSSIBLE_DAIFMT_AC97		(1 << SND_SOC_DAI_FORMAT_AC97)
 #define SND_SOC_POSSIBLE_DAIFMT_PDM		(1 << SND_SOC_DAI_FORMAT_PDM)
 
+/*
+ * DAI TDM slot idle modes
+ *
+ * Describes a CODEC/CPU's behaviour when not actively receiving or
+ * transmitting on a given TDM slot. NONE is undefined behaviour.
+ * Add new modes to the end.
+ */
+#define SND_SOC_DAI_TDM_IDLE_NONE	0
+#define SND_SOC_DAI_TDM_IDLE_OFF	1
+#define SND_SOC_DAI_TDM_IDLE_ZERO	2
+#define SND_SOC_DAI_TDM_IDLE_PULLDOWN	3
+#define SND_SOC_DAI_TDM_IDLE_HIZ	4
+
 /*
  * DAI Clock gating.
  *

-- 
2.52.0


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

* [PATCH 5/7] ASoC: soc-dai: add common operation to set TDM idle mode
  2025-12-09  9:31 [PATCH 0/7] ASoC: basic support for configuring bus keepers James Calligeros
                   ` (3 preceding siblings ...)
  2025-12-09  9:31 ` [PATCH 4/7] ASoC: soc-dai: define TDM idle behaviour modes James Calligeros
@ 2025-12-09  9:31 ` James Calligeros
  2025-12-09  9:31 ` [PATCH 6/7] ASoC: tas2764: expose SDOUT bus keeper via set_tdm_idle operation James Calligeros
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: James Calligeros @ 2025-12-09  9:31 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Kuninori Morimoto, Shengjiu Wang, Jaroslav Kysela,
	Takashi Iwai, Shenghao Ding, Kevin Lu, Baojun Xu
  Cc: linux-sound, devicetree, imx, linux-arm-kernel, linux-kernel,
	asahi, James Calligeros

Some audio devices, like certain Texas Instruments codecs, can be
configured to alter their behaviour when idle on the bus. Now that we
have definitions for various idle modes, add a snd_soc_dai_set_tdm_idle()
operation to control this in a standardised way.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
 include/sound/soc-dai.h |  7 +++++
 sound/soc/soc-dai.c     | 40 +++++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index a5784ef8e3f7..1f411237dde5 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -194,6 +194,10 @@ int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
 int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
 	unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width);
 
+int snd_soc_dai_set_tdm_idle(struct snd_soc_dai *dai,
+			     unsigned int tx_mask, unsigned int rx_mask,
+			     int tx_mode, int rx_mode);
+
 int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai,
 	unsigned int tx_num, const unsigned int *tx_slot,
 	unsigned int rx_num, const unsigned int *rx_slot);
@@ -310,6 +314,9 @@ struct snd_soc_dai_ops {
 	int (*set_tdm_slot)(struct snd_soc_dai *dai,
 		unsigned int tx_mask, unsigned int rx_mask,
 		int slots, int slot_width);
+	int (*set_tdm_idle)(struct snd_soc_dai *dai,
+			    unsigned int tx_mask, unsigned int rx_mask,
+			    int tx_mode, int rx_mode);
 	int (*set_channel_map)(struct snd_soc_dai *dai,
 		unsigned int tx_num, const unsigned int *tx_slot,
 		unsigned int rx_num, const unsigned int *rx_slot);
diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c
index a1e05307067d..2f370fda1266 100644
--- a/sound/soc/soc-dai.c
+++ b/sound/soc/soc-dai.c
@@ -282,6 +282,46 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
 }
 EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
 
+/**
+ * snd_soc_dai_set_tdm_idle() - Configure a DAI's TDM idle mode
+ * @dai: The DAI to configure
+ * @tx_mask: bitmask representing idle TX slots.
+ * @rx_mask: bitmask representing idle RX slots.
+ * @tx_mode: idle mode to set for TX slots.
+ * @rx_mode: idle mode to set for RX slots.
+ *
+ * This function configures the DAI to handle idle TDM slots in the
+ * specified manner. @tx_mode and @rx_mode can be one of
+ * SND_SOC_DAI_TDM_IDLE_NONE, SND_SOC_DAI_TDM_IDLE_ZERO,
+ * SND_SOC_DAI_TDM_IDLE_PULLDOWN, or SND_SOC_DAI_TDM_IDLE_HIZ.
+ * SND_SOC_TDM_IDLE_NONE represents the DAI's default/unset idle slot
+ * handling state and could be any of the other modes depending on the
+ * hardware behind the DAI. It is therefore undefined behaviour when set
+ * explicitly.
+ *
+ * Mode and mask can be set independently for both the TX and RX direction.
+ * Some hardware may ignore both TX and RX masks depending on its
+ * capabilities.
+ */
+int snd_soc_dai_set_tdm_idle(struct snd_soc_dai *dai,
+			     unsigned int tx_mask, unsigned int rx_mask,
+			     int tx_mode, int rx_mode)
+{
+	int ret = -EOPNOTSUPP;
+
+	/* You can't write to the RX line */
+	if (rx_mode == SND_SOC_DAI_TDM_IDLE_ZERO)
+		return soc_dai_ret(dai, -EINVAL);
+
+	if (dai->driver->ops &&
+	    dai->driver->ops->set_tdm_idle)
+		ret = dai->driver->ops->set_tdm_idle(dai, tx_mask, rx_mask,
+						     tx_mode, rx_mode);
+
+	return soc_dai_ret(dai, ret);
+}
+EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_idle);
+
 /**
  * snd_soc_dai_set_channel_map - configure DAI audio channel map
  * @dai: DAI

-- 
2.52.0


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

* [PATCH 6/7] ASoC: tas2764: expose SDOUT bus keeper via set_tdm_idle operation
  2025-12-09  9:31 [PATCH 0/7] ASoC: basic support for configuring bus keepers James Calligeros
                   ` (4 preceding siblings ...)
  2025-12-09  9:31 ` [PATCH 5/7] ASoC: soc-dai: add common operation to set TDM idle mode James Calligeros
@ 2025-12-09  9:31 ` James Calligeros
  2025-12-09  9:31 ` [PATCH 7/7] ASoC: tas2770: expose SDOUT bus keeper via set_tdm_idle James Calligeros
  2025-12-10  2:43 ` [PATCH 0/7] ASoC: basic support for configuring bus keepers Mark Brown
  7 siblings, 0 replies; 15+ messages in thread
From: James Calligeros @ 2025-12-09  9:31 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Kuninori Morimoto, Shengjiu Wang, Jaroslav Kysela,
	Takashi Iwai, Shenghao Ding, Kevin Lu, Baojun Xu
  Cc: linux-sound, devicetree, imx, linux-arm-kernel, linux-kernel,
	asahi, James Calligeros

TAS2764, and the Apple-exclusive variant SN012776, include bus keepers
on the SDOUT pin that can be configured to alter the behaviour of the
SDOUT pin during specified TDM slots. The chip can either leave the
bus floating (default/uninitialised behaviour) or fill the specified
slots with zeroes.

Expose the SDOUT bus keeper and allow it to be configured using the
set_tdm_idle DAI op. The mask must be cropped to only cover slots
valid for the configured BCLK ratio, so introduce a set_bclk_ratio
op that properly configures the bus keeper too.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
 sound/soc/codecs/tas2764.c | 95 +++++++++++++++++++++++++
 sound/soc/codecs/tas2764.h | 11 +++
 2 files changed, 106 insertions(+)

diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c
index 36e25e48b354..423b7073b302 100644
--- a/sound/soc/codecs/tas2764.c
+++ b/sound/soc/codecs/tas2764.c
@@ -44,6 +44,11 @@ struct tas2764_priv {
 
 	bool dac_powered;
 	bool unmuted;
+
+	struct {
+		int tx_mode;
+		unsigned int tx_mask;
+	} idle_slot_config;
 };
 
 #include "tas2764-quirks.h"
@@ -509,11 +514,101 @@ static int tas2764_set_dai_tdm_slot(struct snd_soc_dai *dai,
 	return 0;
 }
 
+static int tas2764_write_sdout_idle_mask(struct tas2764_priv *tas2764, u32 mask)
+{
+	struct snd_soc_component *component = tas2764->component;
+	int i, ret;
+
+	/* Hardware supports up to 64 slots, but we don't */
+	for (i = 0; i < 4; i++) {
+		ret = snd_soc_component_write(component,
+					      TAS2764_SDOUT_HIZ_1 + i,
+					      (mask >> (i * 8)) & 0xff);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int tas2764_set_dai_tdm_idle(struct snd_soc_dai *dai,
+				    unsigned int tx_mask, unsigned int rx_mask,
+				    int tx_mode, int rx_mode)
+{
+	struct snd_soc_component *component = dai->component;
+	struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
+	int ret;
+
+	/* We don't support setting anything on SDIN */
+	if (rx_mode)
+		return -EOPNOTSUPP;
+
+	if (tas2764->idle_slot_config.tx_mask == tx_mask &&
+	    tas2764->idle_slot_config.tx_mode == tx_mode)
+		return 0;
+
+	switch (tx_mode) {
+	case SND_SOC_DAI_TDM_IDLE_ZERO:
+		if (!tx_mask)
+			return -EINVAL;
+
+		ret = tas2764_write_sdout_idle_mask(tas2764, tx_mask);
+		if (ret < 0)
+			return ret;
+
+		ret = snd_soc_component_update_bits(component,
+						    TAS2764_SDOUT_HIZ_9,
+						    TAS2764_SDOUT_HIZ_9_FORCE_0_EN,
+						    TAS2764_SDOUT_HIZ_9_FORCE_0_EN);
+		if (ret < 0)
+			return ret;
+
+		tas2764->idle_slot_config.tx_mask = tx_mask;
+		tas2764->idle_slot_config.tx_mode = tx_mode;
+		break;
+	case SND_SOC_DAI_TDM_IDLE_HIZ:
+	case SND_SOC_DAI_TDM_IDLE_OFF:
+		/* HiZ mode does not support a slot mask */
+		ret = tas2764_write_sdout_idle_mask(tas2764, 0);
+		if (ret < 0)
+			return ret;
+
+		ret = snd_soc_component_update_bits(component,
+						    TAS2764_SDOUT_HIZ_9,
+						    TAS2764_SDOUT_HIZ_9_FORCE_0_EN, 0);
+		if (ret < 0)
+			return ret;
+
+		tas2764->idle_slot_config.tx_mask = 0;
+		tas2764->idle_slot_config.tx_mode = tx_mode;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+/* The SDOUT idle slot mask must be cropped based on the BCLK ratio */
+static int tas2764_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
+{
+	struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(dai->component);
+
+	if (!tas2764->idle_slot_config.tx_mask)
+		return 0;
+
+	tas2764->idle_slot_config.tx_mask &= GENMASK((ratio / 8) - 1, 0);
+
+	return tas2764_write_sdout_idle_mask(tas2764, tas2764->idle_slot_config.tx_mask);
+}
+
 static const struct snd_soc_dai_ops tas2764_dai_ops = {
 	.mute_stream = tas2764_mute,
 	.hw_params  = tas2764_hw_params,
 	.set_fmt    = tas2764_set_fmt,
+	.set_bclk_ratio = tas2764_set_bclk_ratio,
 	.set_tdm_slot = tas2764_set_dai_tdm_slot,
+	.set_tdm_idle = tas2764_set_dai_tdm_idle,
 	.no_capture_mute = 1,
 };
 
diff --git a/sound/soc/codecs/tas2764.h b/sound/soc/codecs/tas2764.h
index 538290ed3d92..4494bc4889dc 100644
--- a/sound/soc/codecs/tas2764.h
+++ b/sound/soc/codecs/tas2764.h
@@ -126,4 +126,15 @@
 
 #define TAS2764_BOP_CFG0                TAS2764_REG(0X0, 0x1d)
 
+#define TAS2764_SDOUT_HIZ_1            TAS2764_REG(0x1, 0x3d)
+#define TAS2764_SDOUT_HIZ_2            TAS2764_REG(0x1, 0x3e)
+#define TAS2764_SDOUT_HIZ_3            TAS2764_REG(0x1, 0x3f)
+#define TAS2764_SDOUT_HIZ_4            TAS2764_REG(0x1, 0x40)
+#define TAS2764_SDOUT_HIZ_5            TAS2764_REG(0x1, 0x41)
+#define TAS2764_SDOUT_HIZ_6            TAS2764_REG(0x1, 0x42)
+#define TAS2764_SDOUT_HIZ_7            TAS2764_REG(0x1, 0x43)
+#define TAS2764_SDOUT_HIZ_8            TAS2764_REG(0x1, 0x44)
+#define TAS2764_SDOUT_HIZ_9            TAS2764_REG(0x1, 0x45)
+#define TAS2764_SDOUT_HIZ_9_FORCE_0_EN BIT(7)
+
 #endif /* __TAS2764__ */

-- 
2.52.0


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

* [PATCH 7/7] ASoC: tas2770: expose SDOUT bus keeper via set_tdm_idle
  2025-12-09  9:31 [PATCH 0/7] ASoC: basic support for configuring bus keepers James Calligeros
                   ` (5 preceding siblings ...)
  2025-12-09  9:31 ` [PATCH 6/7] ASoC: tas2764: expose SDOUT bus keeper via set_tdm_idle operation James Calligeros
@ 2025-12-09  9:31 ` James Calligeros
  2025-12-10  2:43 ` [PATCH 0/7] ASoC: basic support for configuring bus keepers Mark Brown
  7 siblings, 0 replies; 15+ messages in thread
From: James Calligeros @ 2025-12-09  9:31 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Kuninori Morimoto, Shengjiu Wang, Jaroslav Kysela,
	Takashi Iwai, Shenghao Ding, Kevin Lu, Baojun Xu
  Cc: linux-sound, devicetree, imx, linux-arm-kernel, linux-kernel,
	asahi, James Calligeros

TAS2770 includes a bus keeper which can be used to control the behaviour
of the SDOUT pin during specified TDM slots. The chip can either pull
the pin to ground, actively transmit zeroes, or keep the pin floating
(default/uninitialised behaviour).

Expose the bus keeper via the set_tdm_idle DAI op so that it can be
configured by consumers.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
 sound/soc/codecs/tas2770.c | 75 +++++++++++++++++++++++++
 sound/soc/codecs/tas2770.h | 12 ++++
 2 files changed, 87 insertions(+)

diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c
index 6f878b01716f..d4d7d056141b 100644
--- a/sound/soc/codecs/tas2770.c
+++ b/sound/soc/codecs/tas2770.c
@@ -492,11 +492,86 @@ static int tas2770_set_dai_tdm_slot(struct snd_soc_dai *dai,
 	return 0;
 }
 
+static int tas2770_set_dai_tdm_idle(struct snd_soc_dai *dai,
+				    unsigned int tx_mask,
+				    unsigned int rx_mask,
+				    int tx_mode, int rx_mode)
+{
+	struct snd_soc_component *component = dai->component;
+	struct tas2770_priv *tas2770 = snd_soc_component_get_drvdata(component);
+	int ret;
+
+	/* We don't support setting anything for SDIN */
+	if (rx_mode)
+		return -EOPNOTSUPP;
+
+	if (tas2770->idle_tx_mode == tx_mode)
+		return 0;
+
+	switch (tx_mode) {
+	case SND_SOC_DAI_TDM_IDLE_PULLDOWN:
+		ret = snd_soc_component_update_bits(component, TAS2770_DIN_PD,
+						    TAS2770_DIN_PD_SDOUT,
+						    TAS2770_DIN_PD_SDOUT);
+		if (ret)
+			return ret;
+
+		break;
+	case SND_SOC_DAI_TDM_IDLE_ZERO:
+		ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG4,
+						    TAS2770_TDM_CFG_REG4_TX_KEEPER,
+						    TAS2770_TDM_CFG_REG4_TX_KEEPER);
+		if (ret)
+			return ret;
+
+		ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG4,
+						    TAS2770_TDM_CFG_REG4_TX_FILL, 0);
+		if (ret)
+			return ret;
+
+		break;
+	case SND_SOC_DAI_TDM_IDLE_HIZ:
+		ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG4,
+						    TAS2770_TDM_CFG_REG4_TX_KEEPER,
+						    TAS2770_TDM_CFG_REG4_TX_KEEPER);
+		if (ret)
+			return ret;
+
+		ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG4,
+						    TAS2770_TDM_CFG_REG4_TX_FILL,
+						    TAS2770_TDM_CFG_REG4_TX_FILL);
+		if (ret)
+			return ret;
+
+		break;
+	case SND_SOC_DAI_TDM_IDLE_OFF:
+		ret = snd_soc_component_update_bits(component, TAS2770_DIN_PD,
+						    TAS2770_DIN_PD_SDOUT, 0);
+		if (ret)
+			return ret;
+
+		ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG4,
+						    TAS2770_TDM_CFG_REG4_TX_KEEPER, 0);
+		if (ret)
+			return ret;
+
+		break;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	tas2770->idle_tx_mode = tx_mode;
+
+	return 0;
+}
+
 static const struct snd_soc_dai_ops tas2770_dai_ops = {
 	.mute_stream = tas2770_mute,
 	.hw_params  = tas2770_hw_params,
 	.set_fmt    = tas2770_set_fmt,
 	.set_tdm_slot = tas2770_set_dai_tdm_slot,
+	.set_tdm_idle = tas2770_set_dai_tdm_idle,
 	.no_capture_mute = 1,
 };
 
diff --git a/sound/soc/codecs/tas2770.h b/sound/soc/codecs/tas2770.h
index 3fd2e7003c50..102040b6bdf8 100644
--- a/sound/soc/codecs/tas2770.h
+++ b/sound/soc/codecs/tas2770.h
@@ -67,6 +67,14 @@
 #define TAS2770_TDM_CFG_REG3_RXS_SHIFT 0x4
 #define TAS2770_TDM_CFG_REG3_30_MASK  GENMASK(3, 0)
 #define TAS2770_TDM_CFG_REG3_30_SHIFT 0
+    /* TDM Configuration Reg4 */
+#define TAS2770_TDM_CFG_REG4  TAS2770_REG(0X0, 0x0E)
+#define TAS2770_TDM_CFG_REG4_TX_LSB_CFG BIT(7)
+#define TAS2770_TDM_CFG_REG4_TX_KEEPER_CFG BIT(6)
+#define TAS2770_TDM_CFG_REG4_TX_KEEPER BIT(5)
+#define TAS2770_TDM_CFG_REG4_TX_FILL BIT(4)
+#define TAS2770_TDM_CFG_REG4_TX_OFFSET_MASK GENMASK(3, 1)
+#define TAS2770_TDM_CFG_REG4_TX_EDGE_FALLING BIT(0)
     /* TDM Configuration Reg5 */
 #define TAS2770_TDM_CFG_REG5  TAS2770_REG(0X0, 0x0F)
 #define TAS2770_TDM_CFG_REG5_VSNS_MASK  BIT(6)
@@ -115,6 +123,9 @@
 #define TAS2770_TEMP_LSB  TAS2770_REG(0X0, 0x2A)
     /* Interrupt Configuration */
 #define TAS2770_INT_CFG  TAS2770_REG(0X0, 0x30)
+    /* Data In Pull-Down */
+#define TAS2770_DIN_PD  TAS2770_REG(0X0, 0x31)
+#define TAS2770_DIN_PD_SDOUT BIT(7)
     /* Misc IRQ */
 #define TAS2770_MISC_IRQ  TAS2770_REG(0X0, 0x32)
     /* Clock Configuration */
@@ -146,6 +157,7 @@ struct tas2770_priv {
 	int pdm_slot;
 	bool dac_powered;
 	bool unmuted;
+	int idle_tx_mode;
 };
 
 #endif /* __TAS2770__ */

-- 
2.52.0


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

* Re: [PATCH 1/7] ASoC: dt-bindings: convert tdm-slot to YAML
  2025-12-09  9:31 ` [PATCH 1/7] ASoC: dt-bindings: convert tdm-slot to YAML James Calligeros
@ 2025-12-09 10:38   ` Rob Herring (Arm)
  0 siblings, 0 replies; 15+ messages in thread
From: Rob Herring (Arm) @ 2025-12-09 10:38 UTC (permalink / raw)
  To: James Calligeros
  Cc: Kuninori Morimoto, linux-arm-kernel, imx, Krzysztof Kozlowski,
	devicetree, Shengjiu Wang, Shawn Guo, Mark Brown, Liam Girdwood,
	Conor Dooley, linux-sound, Takashi Iwai, Sascha Hauer,
	Pengutronix Kernel Team, Baojun Xu, Jaroslav Kysela, Kevin Lu,
	Fabio Estevam, Shenghao Ding, asahi, linux-kernel


On Tue, 09 Dec 2025 19:31:14 +1000, James Calligeros wrote:
> This schema was still in plaintext form. Convert to YAML format.
> 
> Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
> ---
>  .../bindings/sound/tdm-slot.txt          | 29 ---------------------
>  .../bindings/sound/tdm-slot.yaml         | 34 +++++++++++++++++++++++++
>  2 files changed, 34 insertions(+), 29 deletions(-)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/sound/tdm-slot.yaml: 'oneOf' conditional failed, one must be fixed:
	'unevaluatedProperties' is a required property
	'additionalProperties' is a required property
	hint: Either unevaluatedProperties or additionalProperties must be present
	from schema $id: http://devicetree.org/meta-schemas/core.yaml
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/sound/tdm-slot.yaml: 'anyOf' conditional failed, one must be fixed:
	'properties' is a required property
	'patternProperties' is a required property
	hint: Metaschema for devicetree binding documentation
	from schema $id: http://devicetree.org/meta-schemas/core.yaml

doc reference errors (make refcheckdocs):

See https://patchwork.kernel.org/project/devicetree/patch/20251209-tdm-idle-slots-v1-1-38dabf6bc01e@gmail.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.


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

* Re: [PATCH 2/7] ASoC: dt-bindings: update tdm-slot.txt references to tdm-slot.yaml
  2025-12-09  9:31 ` [PATCH 2/7] ASoC: dt-bindings: update tdm-slot.txt references to tdm-slot.yaml James Calligeros
@ 2025-12-09 16:11   ` Frank Li
  2025-12-09 19:13   ` Rob Herring
  1 sibling, 0 replies; 15+ messages in thread
From: Frank Li @ 2025-12-09 16:11 UTC (permalink / raw)
  To: James Calligeros
  Cc: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Kuninori Morimoto, Shengjiu Wang, Jaroslav Kysela,
	Takashi Iwai, Shenghao Ding, Kevin Lu, Baojun Xu, linux-sound,
	devicetree, imx, linux-arm-kernel, linux-kernel, asahi

On Tue, Dec 09, 2025 at 07:31:15PM +1000, James Calligeros wrote:
> Ensure that all references to tdm-slot.txt have been updated to
> tdm-slot.yaml.
>
> Achieved by running "sed -i 's/tdm-slot.txt/tdm-slot.yaml/g' *"
> against the bindings/sound. No other references to the file
> were found in the tree.
>
> Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
> ---
>  .../bindings/sound/imx-audio-card.yaml   | 4 ++--
>  .../bindings/sound/simple-card.yaml      | 4 ++--
>  2 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/sound/imx-audio-card.yaml b/Documentation/devicetree/bindings/sound/imx-audio-card.yaml
> index 3c75c8c78987..1df29a556120 100644
> --- a/Documentation/devicetree/bindings/sound/imx-audio-card.yaml
> +++ b/Documentation/devicetree/bindings/sound/imx-audio-card.yaml
> @@ -39,11 +39,11 @@ patternProperties:
>              - dsp_b
>
>        dai-tdm-slot-num:
> -        description: see tdm-slot.txt.
> +        description: see tdm-slot.yaml.
>          $ref: /schemas/types.yaml#/definitions/uint32
>
>        dai-tdm-slot-width:
> -        description: see tdm-slot.txt.
> +        description: see tdm-slot.yaml.
>          $ref: /schemas/types.yaml#/definitions/uint32

remove dai-tdm-slot-num and dai-tdm-slot-width and add

$ref: tdm-slot.yaml

Frank

>
>        playback-only:
> diff --git a/Documentation/devicetree/bindings/sound/simple-card.yaml b/Documentation/devicetree/bindings/sound/simple-card.yaml
> index 533d0a1da56e..2e1a5b3216c5 100644
> --- a/Documentation/devicetree/bindings/sound/simple-card.yaml
> +++ b/Documentation/devicetree/bindings/sound/simple-card.yaml
> @@ -28,11 +28,11 @@ definitions:
>      $ref: /schemas/types.yaml#/definitions/flag
>
>    dai-tdm-slot-num:
> -    description: see tdm-slot.txt.
> +    description: see tdm-slot.yaml.
>      $ref: /schemas/types.yaml#/definitions/uint32
>
>    dai-tdm-slot-width:
> -    description: see tdm-slot.txt.
> +    description: see tdm-slot.yaml.
>      $ref: /schemas/types.yaml#/definitions/uint32
>
>    system-clock-frequency:
>
> --
> 2.52.0
>

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

* Re: [PATCH 2/7] ASoC: dt-bindings: update tdm-slot.txt references to tdm-slot.yaml
  2025-12-09  9:31 ` [PATCH 2/7] ASoC: dt-bindings: update tdm-slot.txt references to tdm-slot.yaml James Calligeros
  2025-12-09 16:11   ` Frank Li
@ 2025-12-09 19:13   ` Rob Herring
  1 sibling, 0 replies; 15+ messages in thread
From: Rob Herring @ 2025-12-09 19:13 UTC (permalink / raw)
  To: James Calligeros
  Cc: Liam Girdwood, Mark Brown, Krzysztof Kozlowski, Conor Dooley,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Kuninori Morimoto, Shengjiu Wang, Jaroslav Kysela, Takashi Iwai,
	Shenghao Ding, Kevin Lu, Baojun Xu, linux-sound, devicetree, imx,
	linux-arm-kernel, linux-kernel, asahi

On Tue, Dec 09, 2025 at 07:31:15PM +1000, James Calligeros wrote:
> Ensure that all references to tdm-slot.txt have been updated to
> tdm-slot.yaml.
> 
> Achieved by running "sed -i 's/tdm-slot.txt/tdm-slot.yaml/g' *"
> against the bindings/sound. No other references to the file
> were found in the tree.
> 
> Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
> ---
>  .../bindings/sound/imx-audio-card.yaml   | 4 ++--
>  .../bindings/sound/simple-card.yaml      | 4 ++--
>  2 files changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/sound/imx-audio-card.yaml b/Documentation/devicetree/bindings/sound/imx-audio-card.yaml
> index 3c75c8c78987..1df29a556120 100644
> --- a/Documentation/devicetree/bindings/sound/imx-audio-card.yaml
> +++ b/Documentation/devicetree/bindings/sound/imx-audio-card.yaml
> @@ -39,11 +39,11 @@ patternProperties:
>              - dsp_b
>  
>        dai-tdm-slot-num:
> -        description: see tdm-slot.txt.
> +        description: see tdm-slot.yaml.
>          $ref: /schemas/types.yaml#/definitions/uint32
>  
>        dai-tdm-slot-width:
> -        description: see tdm-slot.txt.
> +        description: see tdm-slot.yaml.
>          $ref: /schemas/types.yaml#/definitions/uint32

These should be removed and replaced with a '$ref: tdm-slot.yaml#' at 
the top-level. 

If you have some constraints to add here, then the property can stay.

>  
>        playback-only:
> diff --git a/Documentation/devicetree/bindings/sound/simple-card.yaml b/Documentation/devicetree/bindings/sound/simple-card.yaml
> index 533d0a1da56e..2e1a5b3216c5 100644
> --- a/Documentation/devicetree/bindings/sound/simple-card.yaml
> +++ b/Documentation/devicetree/bindings/sound/simple-card.yaml
> @@ -28,11 +28,11 @@ definitions:
>      $ref: /schemas/types.yaml#/definitions/flag
>  
>    dai-tdm-slot-num:
> -    description: see tdm-slot.txt.
> +    description: see tdm-slot.yaml.
>      $ref: /schemas/types.yaml#/definitions/uint32
>  
>    dai-tdm-slot-width:
> -    description: see tdm-slot.txt.
> +    description: see tdm-slot.yaml.
>      $ref: /schemas/types.yaml#/definitions/uint32

Same here.

>  
>    system-clock-frequency:
> 
> -- 
> 2.52.0
> 

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

* Re: [PATCH 4/7] ASoC: soc-dai: define TDM idle behaviour modes
  2025-12-09  9:31 ` [PATCH 4/7] ASoC: soc-dai: define TDM idle behaviour modes James Calligeros
@ 2025-12-10  2:22   ` Mark Brown
  2025-12-10  3:57     ` James Calligeros
  0 siblings, 1 reply; 15+ messages in thread
From: Mark Brown @ 2025-12-10  2:22 UTC (permalink / raw)
  To: James Calligeros
  Cc: Liam Girdwood, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Kuninori Morimoto, Shengjiu Wang, Jaroslav Kysela, Takashi Iwai,
	Shenghao Ding, Kevin Lu, Baojun Xu, linux-sound, devicetree, imx,
	linux-arm-kernel, linux-kernel, asahi

[-- Attachment #1: Type: text/plain, Size: 992 bytes --]

On Tue, Dec 09, 2025 at 07:31:17PM +1000, James Calligeros wrote:

> Imagine for example two codecs sharing a bus. When one codec is
> transmitting, the other must ensure that it is holding its side
> to 0, or data from the transmitting codec will be corrupted. We
> can trust the "idle" codec to simply do this itself, however
> this is undefined behaviour. Some devices may leave the line
> floating, others still may pull the line high. We need a way to
> control this behaviour.

I'm finding this explanation quite confusing - you appear to be
describing the situation where two devices simultaneously drive the same
signal which would be extremely unusual and I can't see how it would
work electrically.

> Thus, we define five possible bus-keeping modes that a device can
> be in: NONE (UB/as initialised), OFF (explicitly disabled), ZERO
> (actively transmit a 0), PULLDOWN, and HIZ (floating).

What is "explicitly disabled" in ths context?  Why aren't pull up or
drive high options?

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH 0/7] ASoC: basic support for configuring bus keepers
  2025-12-09  9:31 [PATCH 0/7] ASoC: basic support for configuring bus keepers James Calligeros
                   ` (6 preceding siblings ...)
  2025-12-09  9:31 ` [PATCH 7/7] ASoC: tas2770: expose SDOUT bus keeper via set_tdm_idle James Calligeros
@ 2025-12-10  2:43 ` Mark Brown
  7 siblings, 0 replies; 15+ messages in thread
From: Mark Brown @ 2025-12-10  2:43 UTC (permalink / raw)
  To: James Calligeros
  Cc: Liam Girdwood, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Kuninori Morimoto, Shengjiu Wang, Jaroslav Kysela, Takashi Iwai,
	Shenghao Ding, Kevin Lu, Baojun Xu, linux-sound, devicetree, imx,
	linux-arm-kernel, linux-kernel, asahi

[-- Attachment #1: Type: text/plain, Size: 2598 bytes --]

On Tue, Dec 09, 2025 at 07:31:13PM +1000, James Calligeros wrote:

> Consider a device with two codecs that report voice coil voltage and
> current data back to the host via I2S. Codec A is configured to transmit
> its V/ISENSE data on TDM slots 1 and 3, while Codec B is configured to
> do so on slots 2 and 4. The receiving end sums the two together.
> If Codec A transmits anything on slots 2 or 4 (and vice versa), the
> result is a bus conflict.

> Some codecs include configurable bus keepers to ameliorate this issue.

You've not really mentioned an issue here?  The expected behaviour for
TDM is that devices should only drive the the slots they are configured
to drive and should let the bus float otherwise, otherwise no other
device could transmit.

> Notable examples are the TI TAS2764 and TAS2770. By default, these
> codecs keep their SDOUT pin floating during unconfigured TDM slots,
> however this can result in garbage data on the bus. TAS2764 can be
> set up to fill specific TDM slots with zeroes, TAS2770 can hold its
> SDOUT pin to ground.

Right, so AIUI this is the actual thing you're trying to do - you want
to additionally configure a CODEC to drive slots it's not putting data
on to ensure there are no dead slots on the bus?  I guess you might have
some restrictions on clocking which mean you need extra BCLKs (eg,
needing power of 2 clocks).  But I'm having a hard time connecting this
to your description below so I don't think I've followed what you're
saying here.

> This feature is necessary to properly drive the speaker systems found
> on most Apple Silicon laptops. All but three models include six codecs
> in two groups of three driving two woofers and a tweeter on both the left
> and right channels. Each codec group has a single line for SDOUT, to
> which all codecs are connected. The two groups are then summed on to
> one I2S port. Each group must ensure that it is silent on the bus while
> the other is supposed to be active.

So is there one SDOUT or two which are connected... somehow?  I'm
confused.

> In the downstream Asahi Linux kernel[1], we set up one codec in each
> group to zero-fill or pull down its group's side of the bus for the
> opposite group's transmit slots. This is done entirely in the codec
> driver, however this approach is perhaps over-fit for our use case.
> Following previous mailing list discussions[2], I have tried to
> expose the functionality in a more configurable and generic way.

I can't parse what this is describing at all, sorry.  What is a "side"
of a bus, and how is all this different to idle TDM slots?

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH 4/7] ASoC: soc-dai: define TDM idle behaviour modes
  2025-12-10  2:22   ` Mark Brown
@ 2025-12-10  3:57     ` James Calligeros
  2025-12-11  1:48       ` Mark Brown
  0 siblings, 1 reply; 15+ messages in thread
From: James Calligeros @ 2025-12-10  3:57 UTC (permalink / raw)
  To: Mark Brown
  Cc: Liam Girdwood, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Kuninori Morimoto, Shengjiu Wang, Jaroslav Kysela, Takashi Iwai,
	Shenghao Ding, Kevin Lu, Baojun Xu, linux-sound, devicetree, imx,
	linux-arm-kernel, linux-kernel, asahi

Hi Mark,

On Wed, Dec 10, 2025 at 12:22 PM Mark Brown <broonie@kernel.org> wrote:
>
> On Tue, Dec 09, 2025 at 07:31:17PM +1000, James Calligeros wrote:
>
> > Imagine for example two codecs sharing a bus. When one codec is
> > transmitting, the other must ensure that it is holding its side
> > to 0, or data from the transmitting codec will be corrupted. We
> > can trust the "idle" codec to simply do this itself, however
> > this is undefined behaviour. Some devices may leave the line
> > floating, others still may pull the line high. We need a way to
> > control this behaviour.
>
> I'm finding this explanation quite confusing - you appear to be
> describing the situation where two devices simultaneously drive the same
> signal which would be extremely unusual and I can't see how it would
> work electrically.

We are trying to solve a few of problems here, and one of them is
a bit odd. I've probably jumbled up a bunch of different things here.

We have the use case where a codec enjoys exclusive use of a bus. For
these, the codec can transmit 0 on any unused slots to hold the bus.

We also have the case where multiple codecs share a single bus. One
codec can weakly pull the bus low when it's not being actively driven by
any of the attached codecs.

However, a number of machines split six codecs into groups of three
across two electrical lines and then OR them at the receiving
port such that they appear on a single bus at the SoC. Because the two
data lines are ORed at the receiver, we have to guarantee that line B is
zero while line A is active, and vice versa. To do this, we set a single codec
from each group to zero-fill during the active slots of the other group.

> > Thus, we define five possible bus-keeping modes that a device can
> > be in: NONE (UB/as initialised), OFF (explicitly disabled), ZERO
> > (actively transmit a 0), PULLDOWN, and HIZ (floating).
>
> What is "explicitly disabled" in ths context?  Why aren't pull up or
> drive high options?

The OFF state was added so that consumers can explicitly disable
any and all bus keeping if necessary and supported by the component.
TAS2764 and 2770 both initialise with some bus keeping features enabled,
hence for this hardware NONE != OFF. I suspect this is the case for other
hardware too.

I neglected to add pull up and drive high simply because none of the
initially implemented hardware uses either. I can them for completeness's
sake, however.

Regards,
James

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

* Re: [PATCH 4/7] ASoC: soc-dai: define TDM idle behaviour modes
  2025-12-10  3:57     ` James Calligeros
@ 2025-12-11  1:48       ` Mark Brown
  0 siblings, 0 replies; 15+ messages in thread
From: Mark Brown @ 2025-12-11  1:48 UTC (permalink / raw)
  To: James Calligeros
  Cc: Liam Girdwood, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Kuninori Morimoto, Shengjiu Wang, Jaroslav Kysela, Takashi Iwai,
	Shenghao Ding, Kevin Lu, Baojun Xu, linux-sound, devicetree, imx,
	linux-arm-kernel, linux-kernel, asahi

[-- Attachment #1: Type: text/plain, Size: 1097 bytes --]

On Wed, Dec 10, 2025 at 01:57:50PM +1000, James Calligeros wrote:

> We have the use case where a codec enjoys exclusive use of a bus. For
> these, the codec can transmit 0 on any unused slots to hold the bus.

> We also have the case where multiple codecs share a single bus. One
> codec can weakly pull the bus low when it's not being actively driven by
> any of the attached codecs.

Or configure so you don't have any idle slots.

> However, a number of machines split six codecs into groups of three
> across two electrical lines and then OR them at the receiving
> port such that they appear on a single bus at the SoC. Because the two
> data lines are ORed at the receiver, we have to guarantee that line B is
> zero while line A is active, and vice versa. To do this, we set a single codec
> from each group to zero-fill during the active slots of the other group.

So this is an actual logical OR gate somewhere rather than a direct
electrical connection?

It'd be good to have an explanation more like this in the commit
messages to make it clearer to users what this is intended to do.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

end of thread, other threads:[~2025-12-11  1:48 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-09  9:31 [PATCH 0/7] ASoC: basic support for configuring bus keepers James Calligeros
2025-12-09  9:31 ` [PATCH 1/7] ASoC: dt-bindings: convert tdm-slot to YAML James Calligeros
2025-12-09 10:38   ` Rob Herring (Arm)
2025-12-09  9:31 ` [PATCH 2/7] ASoC: dt-bindings: update tdm-slot.txt references to tdm-slot.yaml James Calligeros
2025-12-09 16:11   ` Frank Li
2025-12-09 19:13   ` Rob Herring
2025-12-09  9:31 ` [PATCH 3/7] ASoC: dt-bindings: add TDM slot idle mode properties James Calligeros
2025-12-09  9:31 ` [PATCH 4/7] ASoC: soc-dai: define TDM idle behaviour modes James Calligeros
2025-12-10  2:22   ` Mark Brown
2025-12-10  3:57     ` James Calligeros
2025-12-11  1:48       ` Mark Brown
2025-12-09  9:31 ` [PATCH 5/7] ASoC: soc-dai: add common operation to set TDM idle mode James Calligeros
2025-12-09  9:31 ` [PATCH 6/7] ASoC: tas2764: expose SDOUT bus keeper via set_tdm_idle operation James Calligeros
2025-12-09  9:31 ` [PATCH 7/7] ASoC: tas2770: expose SDOUT bus keeper via set_tdm_idle James Calligeros
2025-12-10  2:43 ` [PATCH 0/7] ASoC: basic support for configuring bus keepers Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).