[PATCH 4/7] ASoC: soc-dai: define TDM idle behaviour modes

James Calligeros posted 7 patches 2 months ago
There is a newer version of this series
[PATCH 4/7] ASoC: soc-dai: define TDM idle behaviour modes
Posted by James Calligeros 2 months ago
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
Re: [PATCH 4/7] ASoC: soc-dai: define TDM idle behaviour modes
Posted by Mark Brown 2 months ago
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?
Re: [PATCH 4/7] ASoC: soc-dai: define TDM idle behaviour modes
Posted by James Calligeros 2 months ago
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
Re: [PATCH 4/7] ASoC: soc-dai: define TDM idle behaviour modes
Posted by Mark Brown 2 months ago
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.