Linux Sound subsystem development
 help / color / mirror / Atom feed
* [PATCH RFC] ASoC: cs43130: Take the frame layout from set_tdm_slot
@ 2026-10-23  8:14 Olivier Louvignes
  2026-10-23  8:34 ` sashiko-bot
  2026-10-23  9:57 ` Charles Keepax
  0 siblings, 2 replies; 4+ messages in thread
From: Olivier Louvignes @ 2026-10-23  8:14 UTC (permalink / raw)
  To: Mark Brown
  Cc: Liam Girdwood, David Rhodes, Richard Fitzgerald, linux-sound,
	patches, Olivier Louvignes

hw_params() derives the slot width from the frequency given to the DAI's
set_sysclk(), which it takes for SCLK. Generic cards pass MCLK there: the
simple-audio-card of a HiBy R1 (Ingenic X1600 as I2S master, 64 bit
clocks per frame, mclk-fs = 512) hands over 22.5792 MHz, so the driver
sets up 256-bit slots for a 44.1 kHz stream and the CS43131 plays white
noise.

Add a set_tdm_slot() callback so the card can say the layout instead:
two slots of 16 to 32 bits. When set, it takes precedence over the width
derived from set_sysclk(); zero slots go back to deriving it.

Tested on a HiBy R1, on v7.3, with dai-tdm-slot-num = <2> and
dai-tdm-slot-width = <32> on the codec node.

Signed-off-by: Olivier Louvignes <olivier@mgcrea.io>
---
RFC because the way to set the layout is a choice: set_tdm_slot() is what
simple-audio-card can express from the device tree (dai-tdm-slot-num and
dai-tdm-slot-width on the codec node), without a board-specific machine
driver. I would also be fine with the codec deriving the layout from
the sample width, or from a bclk ratio set with set_bclk_ratio(), if you
prefer one of those.

Tested on v7.3 on a HiBy R1; build-tested on 734bef548a96 (v7.3-7363).
Only the CS43131 is covered, as PCM at 44.1 and 48 kHz.

 sound/soc/codecs/cs43130.c | 50 ++++++++++++++++++++++++++++++--------
 sound/soc/codecs/cs43130.h |  1 +
 2 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/sound/soc/codecs/cs43130.c b/sound/soc/codecs/cs43130.c
index 48d88dad4ceb..8450794654c6 100644
--- a/sound/soc/codecs/cs43130.c
+++ b/sound/soc/codecs/cs43130.c
@@ -952,18 +952,24 @@ static int cs43130_hw_params(struct snd_pcm_substream *substream,
 		break;
 	}
 
-	if (!sclk && cs43130->dais[dai->id].dai_mode == SND_SOC_DAIFMT_CBP_CFP)
-		/* Calculate SCLK in master mode if unassigned */
-		sclk = params_rate(params) * bitwidth_dai *
-		       params_channels(params);
+	if (cs43130->dais[dai->id].slot_width) {
+		/* The slot width set with set_tdm_slot() */
+		bitwidth_sclk = cs43130->dais[dai->id].slot_width;
+	} else {
+		if (!sclk && cs43130->dais[dai->id].dai_mode == SND_SOC_DAIFMT_CBP_CFP)
+			/* Calculate SCLK in master mode if unassigned */
+			sclk = params_rate(params) * bitwidth_dai *
+			       params_channels(params);
+
+		if (!sclk) {
+			/* at this point, SCLK must be set */
+			dev_err(cs43130->dev, "SCLK freq is not set\n");
+			return -EINVAL;
+		}
 
-	if (!sclk) {
-		/* at this point, SCLK must be set */
-		dev_err(cs43130->dev, "SCLK freq is not set\n");
-		return -EINVAL;
+		bitwidth_sclk = (sclk / params_rate(params)) /
+				params_channels(params);
 	}
-
-	bitwidth_sclk = (sclk / params_rate(params)) / params_channels(params);
 	if (bitwidth_sclk < bitwidth_dai) {
 		dev_err(cs43130->dev, "Format not supported: SCLK freq is too low\n");
 		return -EINVAL;
@@ -1609,12 +1615,36 @@ static int cs43130_set_sysclk(struct snd_soc_dai *codec_dai,
 	return 0;
 }
 
+/*
+ * Sets the frame layout directly: two slots of slot_width bits, which then
+ * takes precedence over the layout derived from the set_sysclk() frequency.
+ * Generic sound cards pass MCLK to set_sysclk(), not SCLK. Zero slots go
+ * back to the derived layout.
+ */
+static int cs43130_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
+				unsigned int rx_mask, int slots, int slot_width)
+{
+	struct snd_soc_component *component = dai->component;
+	struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);
+
+	if (!slots) {
+		cs43130->dais[dai->id].slot_width = 0;
+		return 0;
+	}
+	if (slots != 2 || slot_width < 16 || slot_width > 32)
+		return -EINVAL;
+
+	cs43130->dais[dai->id].slot_width = slot_width;
+	return 0;
+}
+
 static const struct snd_soc_dai_ops cs43130_pcm_ops = {
 	.startup	= cs43130_pcm_startup,
 	.hw_params	= cs43130_hw_params,
 	.hw_free	= cs43130_hw_free,
 	.set_sysclk	= cs43130_set_sysclk,
 	.set_fmt	= cs43130_pcm_set_fmt,
+	.set_tdm_slot	= cs43130_set_tdm_slot,
 };
 
 static const struct snd_soc_dai_ops cs43130_dop_ops = {
diff --git a/sound/soc/codecs/cs43130.h b/sound/soc/codecs/cs43130.h
index dbdb5b262f1b..6026c14514c0 100644
--- a/sound/soc/codecs/cs43130.h
+++ b/sound/soc/codecs/cs43130.h
@@ -495,6 +495,7 @@ static const char *const cs43130_supply_names[CS43130_NUM_SUPPLIES] = {
 
 struct cs43130_dai {
 	unsigned int			sclk;
+	unsigned int			slot_width;
 	unsigned int			dai_format;
 	unsigned int			dai_mode;
 	unsigned int			dai_invert;

base-commit: 734bef548a96e8774d6eef5dfa2026c6edc4e80b
-- 
2.39.5


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

end of thread, other threads:[~2026-10-23 16:32 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-23  8:14 [PATCH RFC] ASoC: cs43130: Take the frame layout from set_tdm_slot Olivier Louvignes
2026-10-23  8:34 ` sashiko-bot
2026-10-23  9:57 ` Charles Keepax
2026-10-23 16:32   ` Olivier Louvignes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox