mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v4 0/8] Speakers for Pixel 3 / 3 XL
@ 2026-09-24 13:24 David Heidelberg via B4 Relay
  2026-09-24 13:24 ` [PATCH v4 1/8] ASoC: qcom: sdm845: Demystify TDM masks a bit David Heidelberg via B4 Relay
                   ` (8 more replies)
  0 siblings, 9 replies; 17+ messages in thread
From: David Heidelberg via B4 Relay @ 2026-09-24 13:24 UTC (permalink / raw)
  To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, David Rhodes, Richard Fitzgerald, Bjorn Andersson,
	Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, David Rhodes,
	Conor Dooley
  Cc: linux-sound, linux-arm-msm, linux-kernel, patches, devicetree,
	phone-devel, David Heidelberg, Charles Keepax

This series address:

0. demistify the hex to BIT() macro and add left/right rx spk
1. most likely wrongly set DSP_B in sdm845.c
   my guess this is because TDM was never used in the mainline with
   sdm845
2. applying correct mask to left/right speaker for the TDM in sdm845.c,
   so both speakers can work simultaneusly
3. setting sysclk at startups, which some codecs need (such as cs35l36)
4. setting proper tdm slot in the cs35l36 driver
5. device-tree wiring for Pixel 3 / 3 XL

As per previous discussion not seding patch removing the "Input Mux"
which now interferes with TDM callback. If wanted, I can send it as a
follow-up.

Signed-off-by: David Heidelberg <david@ixit.cz>
---
Changes in v4:
- Rebase on top of d4d1619ebd55 ("ASoC: codecs: cs35l*: use .auto_selectable_formats") (Mark)
- Link to v3: https://patch.msgid.link/20260924-pixel3-audio-v3-0-5d06460fc8a9@ixit.cz

Changes in v3:
- De-RFC, applied Reviewed-by tag.
- Link to v2: https://patch.msgid.link/20260903-pixel3-audio-v2-0-7c22ed915291@ixit.cz

Changes in v2:
- Device-tree name sorting, with exception keeping mm1-dai-link in it's
  place. (Konrad)
- Make set_tdm_slot cleaner and less leveled. (Konrad)
- Added TDM MIC defines in sdm845.c.
  Should we in capture use speaker mask?
- Renamed model from 'Google Pixel 3' to 'blueline', I would love to
  hear feedback on this one.
- Link to v1: https://lore.kernel.org/r/20260705-pixel3-audio-v1-0-3b66f33859f1@ixit.cz

---
David Heidelberg (8):
      ASoC: qcom: sdm845: Demystify TDM masks a bit
      ASoC: qcom: sdm845: use DSP_A format for TDM codec DAIs
      ASoC: qcom: sdm845: Use per-speaker RX masks for TDM slot assignment
      ASoC: qcom: sdm845: Set codec dai and component sysclk during startup
      ASoC: cs35l36: Implement set_tdm_slot to program RX and TX slots
      arm64: dts: qcom: sdm845-google: Add basic audio support
      slimbus: qcom-ngd-ctrl: Remove data channels on stream disable
      arm64: dts: qcom: sdm845-google: Add WCD9340 codec and microphone capture

 arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi | 195 ++++++++++++++++++++-
 drivers/slimbus/qcom-ngd-ctrl.c                    |  81 +++++++++
 sound/soc/codecs/cs35l36.c                         |  44 +++++
 sound/soc/qcom/sdm845.c                            |  49 ++++--
 4 files changed, 357 insertions(+), 12 deletions(-)
---
base-commit: 3d7783543c2646af69ad65825e810060494bea21
change-id: 20260613-pixel3-audio-bdbfb49e8037

Best regards,
--  
David Heidelberg <david@ixit.cz>



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

* [PATCH v4 1/8] ASoC: qcom: sdm845: Demystify TDM masks a bit
  2026-09-24 13:24 [PATCH v4 0/8] Speakers for Pixel 3 / 3 XL David Heidelberg via B4 Relay
@ 2026-09-24 13:24 ` David Heidelberg via B4 Relay
  2026-09-25  8:14   ` Srinivas Kandagatla
  2026-09-24 13:24 ` [PATCH v4 2/8] ASoC: qcom: sdm845: use DSP_A format for TDM codec DAIs David Heidelberg via B4 Relay
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 17+ messages in thread
From: David Heidelberg via B4 Relay @ 2026-09-24 13:24 UTC (permalink / raw)
  To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, David Rhodes, Richard Fitzgerald, Bjorn Andersson,
	Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, David Rhodes,
	Conor Dooley
  Cc: linux-sound, linux-arm-msm, linux-kernel, patches, devicetree,
	phone-devel, David Heidelberg

From: David Heidelberg <david@ixit.cz>

Describe the mask with the bits used for each RX/TX.

Signed-off-by: David Heidelberg <david@ixit.cz>
---
 sound/soc/qcom/sdm845.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c
index 6843ab8ba017e..0ce8265ab1c1f 100644
--- a/sound/soc/qcom/sdm845.c
+++ b/sound/soc/qcom/sdm845.c
@@ -18,19 +18,24 @@
 #include "sdw.h"
 #include "../codecs/rt5663.h"
 
 #define DRIVER_NAME	"sdm845"
 #define DEFAULT_SAMPLE_RATE_48K		48000
 #define DEFAULT_MCLK_RATE		24576000
 #define TDM_BCLK_RATE		6144000
 #define MI2S_BCLK_RATE		1536000
-#define LEFT_SPK_TDM_TX_MASK    0x30
-#define RIGHT_SPK_TDM_TX_MASK   0xC0
-#define SPK_TDM_RX_MASK         0x03
+#define LEFT_SPK_TDM_RX_MASK	BIT(0)
+#define RIGHT_SPK_TDM_RX_MASK	BIT(1)
+#define SPK_TDM_RX_MASK		(LEFT_SPK_TDM_RX_MASK | RIGHT_SPK_TDM_RX_MASK)
+#define MIC1_TDM_RX_MASK	BIT(2)
+#define MIC2_TDM_RX_MASK	BIT(3)
+#define MIC_TDM_RX_MASK		(MIC1_TDM_RX_MASK | MIC2_TDM_RX_MASK)
+#define LEFT_SPK_TDM_TX_MASK	(BIT(4) | BIT(5))
+#define RIGHT_SPK_TDM_TX_MASK	(BIT(6) | BIT(7))
 #define NUM_TDM_SLOTS           8
 #define SLIM_MAX_TX_PORTS 16
 #define SLIM_MAX_RX_PORTS 13
 #define WCD934X_DEFAULT_MCLK_RATE	9600000
 
 struct sdm845_snd_data {
 	struct snd_soc_jack jack;
 	bool jack_setup;
@@ -107,34 +112,36 @@ static int sdm845_tdm_snd_hw_params(struct snd_pcm_substream *substream,
 	default:
 		dev_err(rtd->dev, "%s: invalid param format 0x%x\n",
 				__func__, params_format(params));
 		return -EINVAL;
 	}
 
 	channels = params_channels(params);
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, 0x3,
-				8, slot_width);
+		ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, SPK_TDM_RX_MASK,
+					       NUM_TDM_SLOTS, slot_width);
 		if (ret < 0) {
 			dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n",
 					__func__, ret);
 			goto end;
 		}
 
 		ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
 				channels, tdm_slot_offset);
 		if (ret < 0) {
 			dev_err(rtd->dev, "%s: failed to set channel map, err:%d\n",
 					__func__, ret);
 			goto end;
 		}
 	} else {
-		ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xf, 0,
-				8, slot_width);
+		ret = snd_soc_dai_set_tdm_slot(cpu_dai,
+					       SPK_TDM_RX_MASK |
+					       MIC_TDM_RX_MASK, 0,
+					       NUM_TDM_SLOTS, slot_width);
 		if (ret < 0) {
 			dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n",
 					__func__, ret);
 			goto end;
 		}
 
 		ret = snd_soc_dai_set_channel_map(cpu_dai, channels,
 				tdm_slot_offset, 0, NULL);

-- 
2.55.0



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

* [PATCH v4 2/8] ASoC: qcom: sdm845: use DSP_A format for TDM codec DAIs
  2026-09-24 13:24 [PATCH v4 0/8] Speakers for Pixel 3 / 3 XL David Heidelberg via B4 Relay
  2026-09-24 13:24 ` [PATCH v4 1/8] ASoC: qcom: sdm845: Demystify TDM masks a bit David Heidelberg via B4 Relay
@ 2026-09-24 13:24 ` David Heidelberg via B4 Relay
  2026-09-25  8:22   ` Srinivas Kandagatla
  2026-09-24 13:24 ` [PATCH v4 3/8] ASoC: qcom: sdm845: Use per-speaker RX masks for TDM slot assignment David Heidelberg via B4 Relay
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 17+ messages in thread
From: David Heidelberg via B4 Relay @ 2026-09-24 13:24 UTC (permalink / raw)
  To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, David Rhodes, Richard Fitzgerald, Bjorn Andersson,
	Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, David Rhodes,
	Conor Dooley
  Cc: linux-sound, linux-arm-msm, linux-kernel, patches, devicetree,
	phone-devel, David Heidelberg

From: David Heidelberg <david@ixit.cz>

Before the DSP_B only worked because the only close-to-mainline consumer
cs35l36 codec was patched to map both DSP_A and DSP_B to the same
hardware register value (asp_fmt = 0), which is inherently DSP_A timing.
Use the right codec (DSP_A) which works as expected.

Signed-off-by: David Heidelberg <david@ixit.cz>
---
 sound/soc/qcom/sdm845.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c
index 0ce8265ab1c1f..d1cc825fc5cdc 100644
--- a/sound/soc/qcom/sdm845.c
+++ b/sound/soc/qcom/sdm845.c
@@ -382,17 +382,17 @@ static int sdm845_snd_startup(struct snd_pcm_substream *substream)
 	case QUATERNARY_TDM_RX_0:
 	case QUATERNARY_TDM_TX_0:
 		if (++(data->quat_tdm_clk_count) == 1) {
 			snd_soc_dai_set_sysclk(cpu_dai,
 				Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT,
 				TDM_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
 		}
 
-		codec_dai_fmt |= SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_DSP_B;
+		codec_dai_fmt |= SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_DSP_A;
 
 		for_each_rtd_codec_dais(rtd, j, codec_dai) {
 
 			if (!strcmp(codec_dai->component->name_prefix,
 				    "Left")) {
 				ret = snd_soc_dai_set_fmt(
 						codec_dai, codec_dai_fmt);
 				if (ret < 0) {

-- 
2.55.0



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

* [PATCH v4 3/8] ASoC: qcom: sdm845: Use per-speaker RX masks for TDM slot assignment
  2026-09-24 13:24 [PATCH v4 0/8] Speakers for Pixel 3 / 3 XL David Heidelberg via B4 Relay
  2026-09-24 13:24 ` [PATCH v4 1/8] ASoC: qcom: sdm845: Demystify TDM masks a bit David Heidelberg via B4 Relay
  2026-09-24 13:24 ` [PATCH v4 2/8] ASoC: qcom: sdm845: use DSP_A format for TDM codec DAIs David Heidelberg via B4 Relay
@ 2026-09-24 13:24 ` David Heidelberg via B4 Relay
  2026-09-25  8:23   ` Srinivas Kandagatla
  2026-09-24 13:24 ` [PATCH v4 4/8] ASoC: qcom: sdm845: Set codec dai and component sysclk during startup David Heidelberg via B4 Relay
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 17+ messages in thread
From: David Heidelberg via B4 Relay @ 2026-09-24 13:24 UTC (permalink / raw)
  To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, David Rhodes, Richard Fitzgerald, Bjorn Andersson,
	Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, David Rhodes,
	Conor Dooley
  Cc: linux-sound, linux-arm-msm, linux-kernel, patches, devicetree,
	phone-devel, David Heidelberg

From: David Heidelberg <david@ixit.cz>

Both Left and Right codec DAIs were passing the same SPK_TDM_RX_MASK,
both speakers ended up on slot 0, breaking the one speaker in
configuration such as on Pixel 3.

Split SPK_TDM_RX_MASK into per-speaker masks so that the Left codec
gets slot 0 (rx_mask=0x01) and the Right codec gets slot 1
(rx_mask=0x02).

This commit is here, so later CS35L36 receives correct slot for right
and left speakers.

Assisted-by: Claude:claude-4.6-opus
Signed-off-by: David Heidelberg <david@ixit.cz>
---
 sound/soc/qcom/sdm845.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c
index d1cc825fc5cdc..59cfa3b26cd4d 100644
--- a/sound/soc/qcom/sdm845.c
+++ b/sound/soc/qcom/sdm845.c
@@ -152,29 +152,29 @@ static int sdm845_tdm_snd_hw_params(struct snd_pcm_substream *substream,
 		}
 	}
 
 	for_each_rtd_codec_dais(rtd, j, codec_dai) {
 
 		if (!strcmp(codec_dai->component->name_prefix, "Left")) {
 			ret = snd_soc_dai_set_tdm_slot(
 					codec_dai, LEFT_SPK_TDM_TX_MASK,
-					SPK_TDM_RX_MASK, NUM_TDM_SLOTS,
+					LEFT_SPK_TDM_RX_MASK, NUM_TDM_SLOTS,
 					slot_width);
 			if (ret < 0) {
 				dev_err(rtd->dev,
 					"DEV0 TDM slot err:%d\n", ret);
 				return ret;
 			}
 		}
 
 		if (!strcmp(codec_dai->component->name_prefix, "Right")) {
 			ret = snd_soc_dai_set_tdm_slot(
 					codec_dai, RIGHT_SPK_TDM_TX_MASK,
-					SPK_TDM_RX_MASK, NUM_TDM_SLOTS,
+					RIGHT_SPK_TDM_RX_MASK, NUM_TDM_SLOTS,
 					slot_width);
 			if (ret < 0) {
 				dev_err(rtd->dev,
 					"DEV1 TDM slot err:%d\n", ret);
 				return ret;
 			}
 		}
 	}

-- 
2.55.0



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

* [PATCH v4 4/8] ASoC: qcom: sdm845: Set codec dai and component sysclk during startup
  2026-09-24 13:24 [PATCH v4 0/8] Speakers for Pixel 3 / 3 XL David Heidelberg via B4 Relay
                   ` (2 preceding siblings ...)
  2026-09-24 13:24 ` [PATCH v4 3/8] ASoC: qcom: sdm845: Use per-speaker RX masks for TDM slot assignment David Heidelberg via B4 Relay
@ 2026-09-24 13:24 ` David Heidelberg via B4 Relay
  2026-09-25  8:26   ` Srinivas Kandagatla
  2026-09-24 13:24 ` [PATCH v4 5/8] ASoC: cs35l36: Implement set_tdm_slot to program RX and TX slots David Heidelberg via B4 Relay
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 17+ messages in thread
From: David Heidelberg via B4 Relay @ 2026-09-24 13:24 UTC (permalink / raw)
  To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, David Rhodes, Richard Fitzgerald, Bjorn Andersson,
	Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, David Rhodes,
	Conor Dooley
  Cc: linux-sound, linux-arm-msm, linux-kernel, patches, devicetree,
	phone-devel, David Heidelberg

From: David Heidelberg <david@ixit.cz>

The cs35l36 codec needs the codec dai and component sysclk to be set
during TDM startup. Set these for all codec DAIs on the QUATERNARY_TDM
path, gracefully handling codecs that don't support sysclk by ignoring
-ENOTSUPP returns.

Based on work of Joel Selvaraj.

Signed-off-by: David Heidelberg <david@ixit.cz>
---
 sound/soc/qcom/sdm845.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c
index 59cfa3b26cd4d..f0fbec9c8df25 100644
--- a/sound/soc/qcom/sdm845.c
+++ b/sound/soc/qcom/sdm845.c
@@ -407,16 +407,38 @@ static int sdm845_snd_startup(struct snd_pcm_substream *substream)
 				ret = snd_soc_dai_set_fmt(
 						codec_dai, codec_dai_fmt);
 				if (ret < 0) {
 					dev_err(rtd->dev,
 						"Right TDM slot err:%d\n", ret);
 					return ret;
 				}
 			}
+
+			/* Set codec sysclk needed by codecs like cs35l36. */
+			ret = snd_soc_dai_set_sysclk(codec_dai, 0,
+						     TDM_BCLK_RATE,
+						     SND_SOC_CLOCK_IN);
+			if (ret < 0 && ret != -ENOTSUPP) {
+				dev_err(codec_dai->dev,
+					"Failed to set codec dai sysclk: %d\n",
+					ret);
+				return ret;
+			}
+
+			ret = snd_soc_component_set_sysclk(codec_dai->component,
+							   0, 0,
+							   TDM_BCLK_RATE,
+							   SND_SOC_CLOCK_IN);
+			if (ret < 0 && ret != -ENOTSUPP) {
+				dev_err(codec_dai->dev,
+					"Failed to set codec component sysclk: %d\n",
+					ret);
+				return ret;
+			}
 		}
 		break;
 	case SLIMBUS_0_RX...SLIMBUS_6_TX:
 		break;
 
 	default:
 		pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
 		break;

-- 
2.55.0



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

* [PATCH v4 5/8] ASoC: cs35l36: Implement set_tdm_slot to program RX and TX slots
  2026-09-24 13:24 [PATCH v4 0/8] Speakers for Pixel 3 / 3 XL David Heidelberg via B4 Relay
                   ` (3 preceding siblings ...)
  2026-09-24 13:24 ` [PATCH v4 4/8] ASoC: qcom: sdm845: Set codec dai and component sysclk during startup David Heidelberg via B4 Relay
@ 2026-09-24 13:24 ` David Heidelberg via B4 Relay
  2026-09-24 13:24 ` [PATCH v4 6/8] arm64: dts: qcom: sdm845-google: Add basic audio support David Heidelberg via B4 Relay
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: David Heidelberg via B4 Relay @ 2026-09-24 13:24 UTC (permalink / raw)
  To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, David Rhodes, Richard Fitzgerald, Bjorn Andersson,
	Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, David Rhodes,
	Conor Dooley
  Cc: linux-sound, linux-arm-msm, linux-kernel, patches, devicetree,
	phone-devel, David Heidelberg, Charles Keepax

From: David Heidelberg <david@ixit.cz>

Program the ASP RX and TX slot registers from the TDM masks passed by
the machine driver. Each set bit in a mask names a slot; codec channels
are assigned to those slots in order, ASPRX1 taking the first RX slot
and ASPTX1..TX8 the first eight TX slots, with a warning if the mask
names more slots than the device has channels.

Passing slots == 0 or an empty mask restores the hardware defaults,
ASPRX1 in slot 0 and ASPTX1..TX8 in slots 0..7.

This lets a machine driver with several amplifiers on one bus, such as
sdm845 with two CS35L36, put each amplifier on its own RX slot and keep
their TX slots from colliding.

Assisted-by: Claude:claude-4.6-opus
Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
 sound/soc/codecs/cs35l36.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/sound/soc/codecs/cs35l36.c b/sound/soc/codecs/cs35l36.c
index 170588be4dbe3..5fc8ec292e3c4 100644
--- a/sound/soc/codecs/cs35l36.c
+++ b/sound/soc/codecs/cs35l36.c
@@ -942,32 +942,76 @@ static const struct cs35l36_pll_config *cs35l36_get_clk_config(
 	for (i = 0; i < ARRAY_SIZE(cs35l36_pll_sysclk); i++) {
 		if (cs35l36_pll_sysclk[i].freq == freq)
 			return &cs35l36_pll_sysclk[i];
 	}
 
 	return NULL;
 }
 
+static void cs35l36_mask_to_slots(struct cs35l36_private *cs35l36,
+				  unsigned long mask, unsigned int base_reg,
+				  unsigned int nchan)
+{
+	unsigned int chan = 0, shift;
+	int slot;
+
+	/* Two 6-bit slot fields per register, at bits 0 and 16 */
+	for_each_set_bit(slot, &mask, BITS_PER_TYPE(mask)) {
+		if (chan == nchan) {
+			dev_warn(cs35l36->dev,
+				 "Too many slots in TDM mask: %lx\n", mask);
+			return;
+		}
+
+		shift = (chan % 2) * CS35L36_ASP_TX2_SLOT_SHIFT;
+		regmap_update_bits(cs35l36->regmap, base_reg + (chan / 2) * 4,
+				   CS35L36_ASP_RX1_SLOT_MASK << shift,
+				   slot << shift);
+		chan++;
+	}
+}
+
+static int cs35l36_set_tdm_slot(struct snd_soc_dai *dai,
+				unsigned int tx_mask, unsigned int rx_mask,
+				int slots, int slot_width)
+{
+	struct cs35l36_private *cs35l36 =
+			snd_soc_component_get_drvdata(dai->component);
+
+	/* Note: rx/tx is from point of view of the CPU end */
+	if (!slots || !rx_mask)
+		rx_mask = BIT(0);		/* ASPRX1 in slot 0 */
+
+	if (!slots || !tx_mask)
+		tx_mask = GENMASK(7, 0);	/* ASPTX1..8 in slots 0..7 */
+
+	cs35l36_mask_to_slots(cs35l36, rx_mask, CS35L36_ASP_RX1_SLOT, 1);
+	cs35l36_mask_to_slots(cs35l36, tx_mask, CS35L36_ASP_TX1_TX2_SLOT, 8);
+
+	return 0;
+}
+
 static const u64 cs35l36_selectable_formats =
 	SND_SOC_POSSIBLE_DAIFMT_I2S	|
 	SND_SOC_POSSIBLE_DAIFMT_DSP_A	|
 	SND_SOC_POSSIBLE_DAIFMT_GATED	|
 	SND_SOC_POSSIBLE_DAIFMT_CONT	|
 	SND_SOC_POSSIBLE_DAIFMT_NB_NF	|
 	SND_SOC_POSSIBLE_DAIFMT_NB_IF	|
 	SND_SOC_POSSIBLE_DAIFMT_IB_NF	|
 	SND_SOC_POSSIBLE_DAIFMT_IB_IF;
 
 static const struct snd_soc_dai_ops cs35l36_ops = {
 	.set_fmt = cs35l36_set_dai_fmt,
 	.hw_params = cs35l36_pcm_hw_params,
 	.set_sysclk = cs35l36_dai_set_sysclk,
 	.auto_selectable_formats = &cs35l36_selectable_formats,
 	.num_auto_selectable_formats = 1,
+	.set_tdm_slot = cs35l36_set_tdm_slot,
 };
 
 #define CS35L36_RATES (		    \
 	SNDRV_PCM_RATE_8000_48000 | \
 	SNDRV_PCM_RATE_12000 |	    \
 	SNDRV_PCM_RATE_24000 |	    \
 	SNDRV_PCM_RATE_88200 |	    \
 	SNDRV_PCM_RATE_96000 |	    \

-- 
2.55.0



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

* [PATCH v4 6/8] arm64: dts: qcom: sdm845-google: Add basic audio support
  2026-09-24 13:24 [PATCH v4 0/8] Speakers for Pixel 3 / 3 XL David Heidelberg via B4 Relay
                   ` (4 preceding siblings ...)
  2026-09-24 13:24 ` [PATCH v4 5/8] ASoC: cs35l36: Implement set_tdm_slot to program RX and TX slots David Heidelberg via B4 Relay
@ 2026-09-24 13:24 ` David Heidelberg via B4 Relay
  2026-09-24 13:24 ` [PATCH v4 7/8] slimbus: qcom-ngd-ctrl: Remove data channels on stream disable David Heidelberg via B4 Relay
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: David Heidelberg via B4 Relay @ 2026-09-24 13:24 UTC (permalink / raw)
  To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, David Rhodes, Richard Fitzgerald, Bjorn Andersson,
	Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, David Rhodes,
	Conor Dooley
  Cc: linux-sound, linux-arm-msm, linux-kernel, patches, devicetree,
	phone-devel, David Heidelberg

From: David Heidelberg <david@ixit.cz>

Introduce support for sound card and wire two CS35L36 audio codecs for
top and bottom speakers.

Inspired by commit from Joel Selvaraj.

Signed-off-by: David Heidelberg <david@ixit.cz>
---
 arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi | 132 ++++++++++++++++++++-
 1 file changed, 130 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi
index f1379857e2742..bc826d211e4a7 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi
@@ -2,16 +2,18 @@
 
 /dts-v1/;
 
 #include <dt-bindings/arm/qcom,ids.h>
 #include <dt-bindings/dma/qcom-gpi.h>
 #include <dt-bindings/input/linux-event-codes.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+#include <dt-bindings/sound/qcom,q6afe.h>
+#include <dt-bindings/sound/qcom,q6asm.h>
 
 #include "sdm845.dtsi"
 #include "pm8998.dtsi"
 #include "pmi8998.dtsi"
 
 /delete-node/ &mpss_region;
 /delete-node/ &venus_mem;
 /delete-node/ &cdsp_mem;
@@ -406,19 +408,61 @@ nfc@28 {
 		firmware-gpios = <&tlmm 79 GPIO_ACTIVE_HIGH>;
 
 		pinctrl-0 = <&nfc_default>;
 		pinctrl-names = "default";
 	};
 };
 
 &i2c12 {
-	/* Bottom spkr (right) CS35L36 @ 40 */
+	status = "okay";
+
+	cs35l36_bottom: audio-codec@40 {
+		compatible = "cirrus,cs35l36";
+		reg = <0x40>;
+		reset-gpios = <&tlmm 112 GPIO_ACTIVE_HIGH>;
+		#sound-dai-cells = <0>;
+		sound-name-prefix = "Right"; /* Bottom */
+		VA-supply = <&vreg_s4a_1p8>;
+		interrupts-extended = <&tlmm 115 IRQ_TYPE_LEVEL_LOW>;
+
+		pinctrl-0 = <&cs35l36_bottom_default_state>;
+		pinctrl-names = "default";
+
+		cirrus,boost-ind-nanohenry = <1000>;
+		cirrus,boost-ctl-select = <1>;
+		cirrus,boost-ctl-millivolt = <10000>;
+		cirrus,boost-peak-milliamp = <3700>;
+		cirrus,temp-warn-threshold = <1>;
+		cirrus,multi-amp-mode;
+		cirrus,irq-drive-select = <0>;
+		cirrus,irq-gpio-select = <0>;
+	};
+
+	cs35l36_top: audio-codec@41 {
+		compatible = "cirrus,cs35l36";
+		reg = <0x41>;
+		reset-gpios = <&tlmm 75 GPIO_ACTIVE_HIGH>;
+		#sound-dai-cells = <0>;
+		sound-name-prefix = "Left"; /* Top */
+		VA-supply = <&vreg_s4a_1p8>;
+		interrupts-extended = <&tlmm 40 IRQ_TYPE_LEVEL_LOW>;
 
-	/* Top spkr (left) CS35L36 @ 41 */
+		pinctrl-0 = <&cs35l36_top_default_state>;
+		pinctrl-names = "default";
+
+		cirrus,boost-ind-nanohenry = <1000>;
+		cirrus,boost-ctl-select = <0x01>;
+		cirrus,boost-ctl-millivolt = <10000>;
+		cirrus,boost-peak-milliamp = <3700>;
+		cirrus,temp-warn-threshold = <1>;
+		cirrus,multi-amp-mode;
+		cirrus,irq-drive-select = <0>;
+		cirrus,irq-gpio-select = <0>;
+	};
 };
 
 &ipa {
 	firmware-name = "qcom/sdm845/Google/blueline/ipa_fws.mbn";
 	memory-region = <&ipa_fw_mem>;
 
 	status = "okay";
 };
@@ -451,16 +495,35 @@ &pm8998_resin {
 };
 
 &pmi8998_charger {
 	monitored-battery = <&battery>;
 
 	status = "okay";
 };
 
+&q6afedai {
+	dai@72 {
+		reg = <QUATERNARY_TDM_RX_0>;
+
+		qcom,tdm-sync-mode = <0>;
+		qcom,tdm-sync-src = <1>;
+		qcom,tdm-data-out = <0>;
+		qcom,tdm-invert-sync = <0>;
+		qcom,tdm-data-delay = <1>;
+		qcom,tdm-data-align = <0>;
+	};
+};
+
+&q6asmdai {
+	dai@0 {
+		reg = <MSM_FRONTEND_DAI_MULTIMEDIA1>;
+	};
+};
+
 &qupv3_id_0 {
 	status = "okay";
 };
 
 &qupv3_id_1 {
 	status = "okay";
 };
 
@@ -469,16 +532,49 @@ &qup_uart9_rx {
 	bias-pull-up;
 };
 
 &qup_uart9_tx {
 	drive-strength = <2>;
 	bias-disable;
 };
 
+&sound {
+	compatible = "qcom,sdm845-sndcard";
+	model = "blueline";
+	pinctrl-0 = <&quat_mi2s_active>, <&quat_mi2s_sd0_active>,
+		    <&quat_mi2s_sd1_active>;
+	pinctrl-names = "default";
+
+	/* mm[0-9]-dai-link nodes must be positioned first regardless of sorting */
+	mm1-dai-link {
+		link-name = "MultiMedia1";
+
+		cpu {
+			sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
+		};
+	};
+
+	cs35l36-dai-link {
+		link-name = "Speaker Playback";
+
+		codec {
+			sound-dai = <&cs35l36_bottom>, <&cs35l36_top>;
+		};
+
+		cpu {
+			sound-dai = <&q6afedai QUATERNARY_TDM_RX_0>;
+		};
+
+		platform {
+			sound-dai = <&q6routing>;
+		};
+	};
+};
+
 &tlmm {
 	gpio-reserved-ranges = < 0 4>, /* SPI (Intel MNH Pixel Visual Core) */
 			       <81 4>; /* SPI (most likely Fingerprint Cards FPC1075) */
 
 	nfc_default: nfc-default-state {
 		enable-pins {
 			pins = "gpio25";
 			function = "gpio";
@@ -517,16 +613,48 @@ touchscreen_pins: ts-pins-gpio-state {
 	};
 
 	touchscreen_i2c_pins: qup-i2c2-gpio-state {
 		pins = "gpio27", "gpio28";
 		function = "gpio";
 		drive-strength = <2>;
 		bias-disable;
 	};
+
+	cs35l36_bottom_default_state: cs35l36-bottom-default-state {
+		reset-pins {
+			pins = "gpio112";
+			function = "gpio";
+			drive-strength = <2>;
+			bias-disable;
+		};
+
+		irq-pins {
+			pins = "gpio115";
+			function = "gpio";
+			drive-strength = <2>;
+			bias-pull-up;
+		};
+	};
+
+	cs35l36_top_default_state: cs35l36-top-default-state {
+		irq-pins {
+			pins = "gpio40";
+			function = "gpio";
+			drive-strength = <2>;
+			bias-pull-up;
+		};
+
+		reset-pins {
+			pins = "gpio75";
+			function = "gpio";
+			drive-strength = <2>;
+			bias-disable;
+		};
+	};
 };
 
 &uart6 {
 	pinctrl-0 = <&qup_uart6_4pin>;
 
 	status = "okay";
 
 	bluetooth {

-- 
2.55.0



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

* [PATCH v4 7/8] slimbus: qcom-ngd-ctrl: Remove data channels on stream disable
  2026-09-24 13:24 [PATCH v4 0/8] Speakers for Pixel 3 / 3 XL David Heidelberg via B4 Relay
                   ` (5 preceding siblings ...)
  2026-09-24 13:24 ` [PATCH v4 6/8] arm64: dts: qcom: sdm845-google: Add basic audio support David Heidelberg via B4 Relay
@ 2026-09-24 13:24 ` David Heidelberg via B4 Relay
  2026-09-25  8:09   ` Srinivas Kandagatla
  2026-09-24 13:24 ` [PATCH v4 8/8] arm64: dts: qcom: sdm845-google: Add WCD9340 codec and microphone capture David Heidelberg via B4 Relay
  2026-09-24 14:11 ` [PATCH v4 0/8] Speakers for Pixel 3 / 3 XL Mark Brown
  8 siblings, 1 reply; 17+ messages in thread
From: David Heidelberg via B4 Relay @ 2026-09-24 13:24 UTC (permalink / raw)
  To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, David Rhodes, Richard Fitzgerald, Bjorn Andersson,
	Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, David Rhodes,
	Conor Dooley
  Cc: linux-sound, linux-arm-msm, linux-kernel, patches, devicetree,
	phone-devel, David Heidelberg

From: David Heidelberg <david@ixit.cz>

qcom_slim_ngd_xfer_msg() silently returns success for every core
reconfiguration message, so the generic channel removal done by
slim_stream_disable() never reaches the ADSP SLIMbus master. The
master therefore keeps the channels of a closed stream. When the next
stream defines the same channel numbers again, the WCD9340 capture
completes without any error but records only zeros; removing the
channels explicitly when the stream is disabled makes it work again.

Implement the disable_stream controller op with the sequence the
downstream NGD driver sends for channel removal, CHAN_CTRL(REMOVE)
listing the stream's channels followed by RECONFIG_NOW. Like
downstream, treat -EREMOTEIO from the removal as success: it means the
controller is being restarted and the channels are gone anyway.

Based on work done by Casey Tunturi.

Assisted-by: Claude:claude-fable-5-1
Signed-off-by: David Heidelberg <david@ixit.cz>
---
 drivers/slimbus/qcom-ngd-ctrl.c | 81 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/drivers/slimbus/qcom-ngd-ctrl.c b/drivers/slimbus/qcom-ngd-ctrl.c
index eb0ccb31e9074..0a4859466c82d 100644
--- a/drivers/slimbus/qcom-ngd-ctrl.c
+++ b/drivers/slimbus/qcom-ngd-ctrl.c
@@ -1081,16 +1081,96 @@ static int qcom_slim_ngd_enable_stream(struct slim_stream_runtime *rt)
 		slim_free_txn_tid(ctrl, &txn);
 		dev_err(&sdev->dev, "TX timed out:MC:0x%x,mt:0x%x", txn.mc,
 				txn.mt);
 	}
 
 	return ret;
 }
 
+/* CHAN_CTRL operation, bits [7:6] of the first payload byte */
+#define SLIM_USR_CHAN_CTRL_REMOVE	2
+
+static int qcom_slim_ngd_disable_stream(struct slim_stream_runtime *rt)
+{
+	struct slim_device *sdev = rt->dev;
+	struct slim_controller *ctrl = sdev->ctrl;
+	struct slim_val_inf msg =  {0};
+	u8 wbuf[SLIM_MSGQ_BUF_LEN];
+	u8 rbuf[SLIM_MSGQ_BUF_LEN];
+	struct slim_msg_txn txn = {0,};
+	int i, ret;
+
+	txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
+	txn.dt = SLIM_MSG_DEST_LOGICALADDR;
+	txn.la = SLIM_LA_MGR;
+	txn.ec = 0;
+	txn.msg = &msg;
+	txn.msg->num_bytes = 0;
+	txn.msg->wbuf = wbuf;
+	txn.msg->rbuf = rbuf;
+
+	/*
+	 * The NGD drops the core reconfiguration messages that
+	 * slim_stream_disable() uses to remove channels, so ask the master
+	 * to remove them the way the downstream NGD driver does:
+	 * CHAN_CTRL(REMOVE) listing every channel, then RECONFIG_NOW.
+	 * Without this the master keeps the channels active and a later
+	 * DEF_ACT_CHAN with the same channel numbers is a no-op, so the
+	 * data path is never re-armed and a reopened stream moves no data.
+	 */
+	/* 5-bit client number, operation in bits [7:6] */
+	wbuf[txn.msg->num_bytes++] = (SLIM_USR_CHAN_CTRL_REMOVE << 6) |
+				     (sdev->laddr & 0x1f);
+
+	ret = slim_alloc_txn_tid(ctrl, &txn);
+	if (ret) {
+		dev_err(&sdev->dev, "Fail to allocate TID\n");
+		return ret;
+	}
+	wbuf[txn.msg->num_bytes++] = txn.tid;
+
+	for (i = 0; i < rt->num_ports; i++)
+		wbuf[txn.msg->num_bytes++] = rt->ports[i].ch.id;
+
+	txn.mc = SLIM_USR_MC_CHAN_CTRL;
+	txn.rl = txn.msg->num_bytes + 4;
+	ret = qcom_slim_ngd_xfer_msg_sync(ctrl, &txn);
+	if (ret) {
+		slim_free_txn_tid(ctrl, &txn);
+		/* Controller restarting, the channels are gone anyway */
+		if (ret == -EREMOTEIO)
+			return 0;
+		dev_err(&sdev->dev, "TX timed out:MC:0x%x,mt:0x%x", txn.mc,
+				txn.mt);
+		return ret;
+	}
+
+	txn.mc = SLIM_USR_MC_RECONFIG_NOW;
+	txn.msg->num_bytes = 2;
+	wbuf[1] = sdev->laddr;
+	txn.rl = txn.msg->num_bytes + 4;
+
+	ret = slim_alloc_txn_tid(ctrl, &txn);
+	if (ret) {
+		dev_err(ctrl->dev, "Fail to allocate TID\n");
+		return ret;
+	}
+
+	wbuf[0] = txn.tid;
+	ret = qcom_slim_ngd_xfer_msg_sync(ctrl, &txn);
+	if (ret) {
+		slim_free_txn_tid(ctrl, &txn);
+		dev_err(&sdev->dev, "TX timed out:MC:0x%x,mt:0x%x", txn.mc,
+				txn.mt);
+	}
+
+	return ret;
+}
+
 static int qcom_slim_ngd_get_laddr(struct slim_controller *ctrl,
 				   struct slim_eaddr *ea, u8 *laddr)
 {
 	struct slim_val_inf msg =  {0};
 	u8 failed_ea[6] = {0, 0, 0, 0, 0, 0};
 	struct slim_msg_txn txn;
 	u8 wbuf[10] = {0};
 	u8 rbuf[10] = {0};
@@ -1620,16 +1700,17 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
 	ctrl->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
 	ctrl->framer.superfreq =
 		ctrl->framer.rootfreq / SLIM_CL_PER_SUPERFRAME_DIV8;
 
 	ctrl->ctrl.a_framer = &ctrl->framer;
 	ctrl->ctrl.clkgear = SLIM_MAX_CLK_GEAR;
 	ctrl->ctrl.get_laddr = qcom_slim_ngd_get_laddr;
 	ctrl->ctrl.enable_stream = qcom_slim_ngd_enable_stream;
+	ctrl->ctrl.disable_stream = qcom_slim_ngd_disable_stream;
 	ctrl->ctrl.xfer_msg = qcom_slim_ngd_xfer_msg;
 	ctrl->ctrl.wakeup = NULL;
 	ctrl->state = QCOM_SLIM_NGD_CTRL_DOWN;
 
 	mutex_init(&ctrl->tx_lock);
 	mutex_init(&ctrl->ssr_lock);
 	spin_lock_init(&ctrl->tx_buf_lock);
 	init_completion(&ctrl->reconf);

-- 
2.55.0



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

* [PATCH v4 8/8] arm64: dts: qcom: sdm845-google: Add WCD9340 codec and microphone capture
  2026-09-24 13:24 [PATCH v4 0/8] Speakers for Pixel 3 / 3 XL David Heidelberg via B4 Relay
                   ` (6 preceding siblings ...)
  2026-09-24 13:24 ` [PATCH v4 7/8] slimbus: qcom-ngd-ctrl: Remove data channels on stream disable David Heidelberg via B4 Relay
@ 2026-09-24 13:24 ` David Heidelberg via B4 Relay
  2026-09-24 14:11 ` [PATCH v4 0/8] Speakers for Pixel 3 / 3 XL Mark Brown
  8 siblings, 0 replies; 17+ messages in thread
From: David Heidelberg via B4 Relay @ 2026-09-24 13:24 UTC (permalink / raw)
  To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, David Rhodes, Richard Fitzgerald, Bjorn Andersson,
	Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, David Rhodes,
	Conor Dooley
  Cc: linux-sound, linux-arm-msm, linux-kernel, patches, devicetree,
	phone-devel, David Heidelberg

From: David Heidelberg <david@ixit.cz>

The Pixel 3 sound card so far only drove the two CS35L36 speaker
amplifiers. Wire in the WCD9340 codec , add a SLIMbus capture link
for it and route the three digital microphones

Based on work done by Casey Tunturi.

Assisted-by: Claude:claude-fable-5-1
Signed-off-by: David Heidelberg <david@ixit.cz>
---
 arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi | 63 ++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi
index bc826d211e4a7..47ed525acb55e 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi
@@ -4,18 +4,20 @@
 
 #include <dt-bindings/arm/qcom,ids.h>
 #include <dt-bindings/dma/qcom-gpi.h>
 #include <dt-bindings/input/linux-event-codes.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/regulator/qcom,rpmh-regulator.h>
 #include <dt-bindings/sound/qcom,q6afe.h>
 #include <dt-bindings/sound/qcom,q6asm.h>
+#include <dt-bindings/sound/qcom,wcd934x.h>
 
 #include "sdm845.dtsi"
+#include "sdm845-wcd9340.dtsi"
 #include "pm8998.dtsi"
 #include "pmi8998.dtsi"
 
 /delete-node/ &mpss_region;
 /delete-node/ &venus_mem;
 /delete-node/ &cdsp_mem;
 /delete-node/ &mba_region;
 /delete-node/ &slpi_mem;
@@ -512,16 +514,20 @@ dai@72 {
 		qcom,tdm-data-align = <0>;
 	};
 };
 
 &q6asmdai {
 	dai@0 {
 		reg = <MSM_FRONTEND_DAI_MULTIMEDIA1>;
 	};
+
+	dai@1 {
+		reg = <MSM_FRONTEND_DAI_MULTIMEDIA2>;
+	};
 };
 
 &qupv3_id_0 {
 	status = "okay";
 };
 
 &qupv3_id_1 {
 	status = "okay";
@@ -539,40 +545,81 @@ &qup_uart9_tx {
 
 &sound {
 	compatible = "qcom,sdm845-sndcard";
 	model = "blueline";
 	pinctrl-0 = <&quat_mi2s_active>, <&quat_mi2s_sd0_active>,
 		    <&quat_mi2s_sd1_active>;
 	pinctrl-names = "default";
 
+	audio-routing = "DMIC0", "MCLK", /* Top mic */
+			"DMIC0", "MIC BIAS1",
+			"DMIC3", "MCLK", /* Top-edge mic */
+			"DMIC3", "MIC BIAS3",
+			"DMIC4", "MCLK", /* Bottom mic */
+			"DMIC4", "MIC BIAS4";
+
 	/* mm[0-9]-dai-link nodes must be positioned first regardless of sorting */
 	mm1-dai-link {
 		link-name = "MultiMedia1";
 
 		cpu {
 			sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
 		};
 	};
 
+	mm2-dai-link {
+		link-name = "MultiMedia2";
+
+		cpu {
+			sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA2>;
+		};
+	};
+
 	cs35l36-dai-link {
 		link-name = "Speaker Playback";
 
 		codec {
 			sound-dai = <&cs35l36_bottom>, <&cs35l36_top>;
 		};
 
 		cpu {
 			sound-dai = <&q6afedai QUATERNARY_TDM_RX_0>;
 		};
 
 		platform {
 			sound-dai = <&q6routing>;
 		};
 	};
+
+	slimcap-dai-link {
+		link-name = "SLIM Capture 1";
+
+		codec {
+			sound-dai = <&wcd9340 AIF1_CAP>;
+		};
+
+		cpu {
+			sound-dai = <&q6afedai SLIMBUS_0_TX>;
+		};
+
+		platform {
+			sound-dai = <&q6routing>;
+		};
+	};
+};
+
+&swm {
+	/*
+	 * Nothing hangs off the codec's SoundWire bus on this board: the
+	 * speakers are CS35L36 amplifiers on QUAT_TDM. With an empty bus the
+	 * controller reports port mismatches and frame-generator timeouts on
+	 * every boot.
+	 */
+	status = "disabled";
 };
 
 &tlmm {
 	gpio-reserved-ranges = < 0 4>, /* SPI (Intel MNH Pixel Visual Core) */
 			       <81 4>; /* SPI (most likely Fingerprint Cards FPC1075) */
 
 	nfc_default: nfc-default-state {
 		enable-pins {
@@ -718,16 +765,32 @@ &usb_1_qmpphy {
 };
 
 &venus {
 	firmware-name = "qcom/sdm845/Google/blueline/venus.mbn";
 
 	status = "okay";
 };
 
+&wcd9340 {
+	/*
+	 * PM8998 LN_BB_CLK2 feeds the Pixel Visual Core on this board; the
+	 * codec MCLK comes from LN_BB_CLK3. With the wrong buffer the codec
+	 * never sees 19.2 MHz: eFuse sensing times out and every capture
+	 * path reads zeros while SLIMbus control traffic still works.
+	 */
+	clocks = <&rpmhcc RPMH_LN_BB_CLK3>;
+	reset-gpios = <&tlmm 64 GPIO_ACTIVE_HIGH>;
+	vdd-buck-supply = <&vreg_s4a_1p8>;
+	vdd-buck-sido-supply = <&vreg_s4a_1p8>;
+	vdd-tx-supply = <&vreg_s4a_1p8>;
+	vdd-rx-supply = <&vreg_s4a_1p8>;
+	vdd-io-supply = <&vreg_s4a_1p8>;
+};
+
 &wifi {
 	vdd-0.8-cx-mx-supply = <&vreg_l5a_0p8>;
 	vdd-1.8-xo-supply = <&vreg_pmu_xo>;
 	vdd-1.3-rfa-supply = <&vreg_pmu_rf>;
 	vdd-3.3-ch0-supply = <&vreg_pmu_ch0>;
 
 	qcom,snoc-host-cap-8bit-quirk;
 

-- 
2.55.0



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

* Re: [PATCH v4 0/8] Speakers for Pixel 3 / 3 XL
  2026-09-24 13:24 [PATCH v4 0/8] Speakers for Pixel 3 / 3 XL David Heidelberg via B4 Relay
                   ` (7 preceding siblings ...)
  2026-09-24 13:24 ` [PATCH v4 8/8] arm64: dts: qcom: sdm845-google: Add WCD9340 codec and microphone capture David Heidelberg via B4 Relay
@ 2026-09-24 14:11 ` Mark Brown
  2026-09-24 14:13   ` David Heidelberg
  8 siblings, 1 reply; 17+ messages in thread
From: Mark Brown @ 2026-09-24 14:11 UTC (permalink / raw)
  To: david
  Cc: Srinivas Kandagatla, Liam Girdwood, Jaroslav Kysela,
	Takashi Iwai, David Rhodes, Richard Fitzgerald, Bjorn Andersson,
	Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, David Rhodes,
	Conor Dooley, linux-sound, linux-arm-msm, linux-kernel, patches,
	devicetree, phone-devel, Charles Keepax

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

On Thu, Sep 24, 2026 at 03:24:05PM +0200, David Heidelberg via B4 Relay wrote:
> This series address:

> Changes in v4:
> - Rebase on top of d4d1619ebd55 ("ASoC: codecs: cs35l*: use .auto_selectable_formats") (Mark)

That's not what your b4 metadata claims:

> ---
> base-commit: 3d7783543c2646af69ad65825e810060494bea21
> change-id: 20260613-pixel3-audio-bdbfb49e8037

That's yesterday's -next and while this does now apply against that it
doesn't apply against my tree since you've also included DT changes :/

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

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

* Re: [PATCH v4 0/8] Speakers for Pixel 3 / 3 XL
  2026-09-24 14:11 ` [PATCH v4 0/8] Speakers for Pixel 3 / 3 XL Mark Brown
@ 2026-09-24 14:13   ` David Heidelberg
  0 siblings, 0 replies; 17+ messages in thread
From: David Heidelberg @ 2026-09-24 14:13 UTC (permalink / raw)
  To: Mark Brown
  Cc: Srinivas Kandagatla, Liam Girdwood, Jaroslav Kysela,
	Takashi Iwai, David Rhodes, Richard Fitzgerald, Bjorn Andersson,
	Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, David Rhodes,
	Conor Dooley, linux-sound, linux-arm-msm, linux-kernel, patches,
	devicetree, phone-devel, Charles Keepax

On 24/09/2026 16:11, Mark Brown wrote:
> On Thu, Sep 24, 2026 at 03:24:05PM +0200, David Heidelberg via B4 Relay wrote:
>> This series address:
> 
>> Changes in v4:
>> - Rebase on top of d4d1619ebd55 ("ASoC: codecs: cs35l*: use .auto_selectable_formats") (Mark)

wrong wording, I meant by it this was only conflict I noticed. I'll rebase 
against your tree directly.

Sorry for spam.

David>
> That's not what your b4 metadata claims:
> 
>> ---
>> base-commit: 3d7783543c2646af69ad65825e810060494bea21
>> change-id: 20260613-pixel3-audio-bdbfb49e8037
> 
> That's yesterday's -next and while this does now apply against that it
> doesn't apply against my tree since you've also included DT changes :/


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

* Re: [PATCH v4 7/8] slimbus: qcom-ngd-ctrl: Remove data channels on stream disable
  2026-09-24 13:24 ` [PATCH v4 7/8] slimbus: qcom-ngd-ctrl: Remove data channels on stream disable David Heidelberg via B4 Relay
@ 2026-09-25  8:09   ` Srinivas Kandagatla
  2026-09-25  8:34     ` David Heidelberg
  0 siblings, 1 reply; 17+ messages in thread
From: Srinivas Kandagatla @ 2026-09-25  8:09 UTC (permalink / raw)
  To: david, Srinivas Kandagatla, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai, David Rhodes, Richard Fitzgerald,
	Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	David Rhodes, Conor Dooley
  Cc: linux-sound, linux-arm-msm, linux-kernel, patches, devicetree,
	phone-devel

On 9/24/26 2:24 PM, David Heidelberg via B4 Relay wrote:
> From: David Heidelberg <david@ixit.cz>
> 
> qcom_slim_ngd_xfer_msg() silently returns success for every core
> reconfiguration message, so the generic channel removal done by
> slim_stream_disable() never reaches the ADSP SLIMbus master. The
> master therefore keeps the channels of a closed stream. When the next
> stream defines the same channel numbers again, the WCD9340 capture
> completes without any error but records only zeros; removing the
> channels explicitly when the stream is disabled makes it work again.
> 
> Implement the disable_stream controller op with the sequence the
> downstream NGD driver sends for channel removal, CHAN_CTRL(REMOVE)
> listing the stream's channels followed by RECONFIG_NOW. Like
> downstream, treat -EREMOTEIO from the removal as success: it means the
> controller is being restarted and the channels are gone anyway.
> 
> Based on work done by Casey Tunturi.
> 
> Assisted-by: Claude:claude-fable-5-1
> Signed-off-by: David Heidelberg <david@ixit.cz>
> ---

there is an identical patch on the list,
https://lore.kernel.org/linux-arm-msm/247e4ce7-1ba2-43b8-8a11-ec70f99a4fc1@linaro.org/T/#m3b50aa43a6493f8d3b607b1607b37bf14b199f69

--srini


>  drivers/slimbus/qcom-ngd-ctrl.c | 81 +++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 81 insertions(+)
> 
> diff --git a/drivers/slimbus/qcom-ngd-ctrl.c b/drivers/slimbus/qcom-ngd-ctrl.c
> index eb0ccb31e9074..0a4859466c82d 100644
> --- a/drivers/slimbus/qcom-ngd-ctrl.c
> +++ b/drivers/slimbus/qcom-ngd-ctrl.c
> @@ -1081,16 +1081,96 @@ static int qcom_slim_ngd_enable_stream(struct slim_stream_runtime *rt)
>  		slim_free_txn_tid(ctrl, &txn);
>  		dev_err(&sdev->dev, "TX timed out:MC:0x%x,mt:0x%x", txn.mc,
>  				txn.mt);
>  	}
>  
>  	return ret;
>  }
>  
> +/* CHAN_CTRL operation, bits [7:6] of the first payload byte */
> +#define SLIM_USR_CHAN_CTRL_REMOVE	2
> +
> +static int qcom_slim_ngd_disable_stream(struct slim_stream_runtime *rt)
> +{
> +	struct slim_device *sdev = rt->dev;
> +	struct slim_controller *ctrl = sdev->ctrl;
> +	struct slim_val_inf msg =  {0};
> +	u8 wbuf[SLIM_MSGQ_BUF_LEN];
> +	u8 rbuf[SLIM_MSGQ_BUF_LEN];
> +	struct slim_msg_txn txn = {0,};
> +	int i, ret;
> +
> +	txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
> +	txn.dt = SLIM_MSG_DEST_LOGICALADDR;
> +	txn.la = SLIM_LA_MGR;
> +	txn.ec = 0;
> +	txn.msg = &msg;
> +	txn.msg->num_bytes = 0;
> +	txn.msg->wbuf = wbuf;
> +	txn.msg->rbuf = rbuf;
> +
> +	/*
> +	 * The NGD drops the core reconfiguration messages that
> +	 * slim_stream_disable() uses to remove channels, so ask the master
> +	 * to remove them the way the downstream NGD driver does:
> +	 * CHAN_CTRL(REMOVE) listing every channel, then RECONFIG_NOW.
> +	 * Without this the master keeps the channels active and a later
> +	 * DEF_ACT_CHAN with the same channel numbers is a no-op, so the
> +	 * data path is never re-armed and a reopened stream moves no data.
> +	 */
> +	/* 5-bit client number, operation in bits [7:6] */
> +	wbuf[txn.msg->num_bytes++] = (SLIM_USR_CHAN_CTRL_REMOVE << 6) |
> +				     (sdev->laddr & 0x1f);
> +
> +	ret = slim_alloc_txn_tid(ctrl, &txn);
> +	if (ret) {
> +		dev_err(&sdev->dev, "Fail to allocate TID\n");
> +		return ret;
> +	}
> +	wbuf[txn.msg->num_bytes++] = txn.tid;
> +
> +	for (i = 0; i < rt->num_ports; i++)
> +		wbuf[txn.msg->num_bytes++] = rt->ports[i].ch.id;
> +
> +	txn.mc = SLIM_USR_MC_CHAN_CTRL;
> +	txn.rl = txn.msg->num_bytes + 4;
> +	ret = qcom_slim_ngd_xfer_msg_sync(ctrl, &txn);
> +	if (ret) {
> +		slim_free_txn_tid(ctrl, &txn);
> +		/* Controller restarting, the channels are gone anyway */
> +		if (ret == -EREMOTEIO)
> +			return 0;
> +		dev_err(&sdev->dev, "TX timed out:MC:0x%x,mt:0x%x", txn.mc,
> +				txn.mt);
> +		return ret;
> +	}
> +
> +	txn.mc = SLIM_USR_MC_RECONFIG_NOW;
> +	txn.msg->num_bytes = 2;
> +	wbuf[1] = sdev->laddr;
> +	txn.rl = txn.msg->num_bytes + 4;
> +
> +	ret = slim_alloc_txn_tid(ctrl, &txn);
> +	if (ret) {
> +		dev_err(ctrl->dev, "Fail to allocate TID\n");
> +		return ret;
> +	}
> +
> +	wbuf[0] = txn.tid;
> +	ret = qcom_slim_ngd_xfer_msg_sync(ctrl, &txn);
> +	if (ret) {
> +		slim_free_txn_tid(ctrl, &txn);
> +		dev_err(&sdev->dev, "TX timed out:MC:0x%x,mt:0x%x", txn.mc,
> +				txn.mt);
> +	}
> +
> +	return ret;
> +}
> +
>  static int qcom_slim_ngd_get_laddr(struct slim_controller *ctrl,
>  				   struct slim_eaddr *ea, u8 *laddr)
>  {
>  	struct slim_val_inf msg =  {0};
>  	u8 failed_ea[6] = {0, 0, 0, 0, 0, 0};
>  	struct slim_msg_txn txn;
>  	u8 wbuf[10] = {0};
>  	u8 rbuf[10] = {0};
> @@ -1620,16 +1700,17 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
>  	ctrl->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
>  	ctrl->framer.superfreq =
>  		ctrl->framer.rootfreq / SLIM_CL_PER_SUPERFRAME_DIV8;
>  
>  	ctrl->ctrl.a_framer = &ctrl->framer;
>  	ctrl->ctrl.clkgear = SLIM_MAX_CLK_GEAR;
>  	ctrl->ctrl.get_laddr = qcom_slim_ngd_get_laddr;
>  	ctrl->ctrl.enable_stream = qcom_slim_ngd_enable_stream;
> +	ctrl->ctrl.disable_stream = qcom_slim_ngd_disable_stream;
>  	ctrl->ctrl.xfer_msg = qcom_slim_ngd_xfer_msg;
>  	ctrl->ctrl.wakeup = NULL;
>  	ctrl->state = QCOM_SLIM_NGD_CTRL_DOWN;
>  
>  	mutex_init(&ctrl->tx_lock);
>  	mutex_init(&ctrl->ssr_lock);
>  	spin_lock_init(&ctrl->tx_buf_lock);
>  	init_completion(&ctrl->reconf);
> 


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

* Re: [PATCH v4 1/8] ASoC: qcom: sdm845: Demystify TDM masks a bit
  2026-09-24 13:24 ` [PATCH v4 1/8] ASoC: qcom: sdm845: Demystify TDM masks a bit David Heidelberg via B4 Relay
@ 2026-09-25  8:14   ` Srinivas Kandagatla
  0 siblings, 0 replies; 17+ messages in thread
From: Srinivas Kandagatla @ 2026-09-25  8:14 UTC (permalink / raw)
  To: david, Srinivas Kandagatla, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai, David Rhodes, Richard Fitzgerald,
	Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	David Rhodes, Conor Dooley
  Cc: linux-sound, linux-arm-msm, linux-kernel, patches, devicetree,
	phone-devel

On 9/24/26 2:24 PM, David Heidelberg via B4 Relay wrote:
> From: David Heidelberg <david@ixit.cz>
> 
> Describe the mask with the bits used for each RX/TX.
> 
> Signed-off-by: David Heidelberg <david@ixit.cz>

Reviewed-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
> ---
>  sound/soc/qcom/sdm845.c | 21 ++++++++++++++-------
>  1 file changed, 14 insertions(+), 7 deletions(-)
> 
> diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c
> index 6843ab8ba017e..0ce8265ab1c1f 100644
> --- a/sound/soc/qcom/sdm845.c
> +++ b/sound/soc/qcom/sdm845.c
> @@ -18,19 +18,24 @@
>  #include "sdw.h"
>  #include "../codecs/rt5663.h"
>  
>  #define DRIVER_NAME	"sdm845"
>  #define DEFAULT_SAMPLE_RATE_48K		48000
>  #define DEFAULT_MCLK_RATE		24576000
>  #define TDM_BCLK_RATE		6144000
>  #define MI2S_BCLK_RATE		1536000
> -#define LEFT_SPK_TDM_TX_MASK    0x30
> -#define RIGHT_SPK_TDM_TX_MASK   0xC0
> -#define SPK_TDM_RX_MASK         0x03
> +#define LEFT_SPK_TDM_RX_MASK	BIT(0)
> +#define RIGHT_SPK_TDM_RX_MASK	BIT(1)
> +#define SPK_TDM_RX_MASK		(LEFT_SPK_TDM_RX_MASK | RIGHT_SPK_TDM_RX_MASK)
> +#define MIC1_TDM_RX_MASK	BIT(2)
> +#define MIC2_TDM_RX_MASK	BIT(3)
> +#define MIC_TDM_RX_MASK		(MIC1_TDM_RX_MASK | MIC2_TDM_RX_MASK)
> +#define LEFT_SPK_TDM_TX_MASK	(BIT(4) | BIT(5))
> +#define RIGHT_SPK_TDM_TX_MASK	(BIT(6) | BIT(7))
>  #define NUM_TDM_SLOTS           8
>  #define SLIM_MAX_TX_PORTS 16
>  #define SLIM_MAX_RX_PORTS 13
>  #define WCD934X_DEFAULT_MCLK_RATE	9600000
>  
>  struct sdm845_snd_data {
>  	struct snd_soc_jack jack;
>  	bool jack_setup;
> @@ -107,34 +112,36 @@ static int sdm845_tdm_snd_hw_params(struct snd_pcm_substream *substream,
>  	default:
>  		dev_err(rtd->dev, "%s: invalid param format 0x%x\n",
>  				__func__, params_format(params));
>  		return -EINVAL;
>  	}
>  
>  	channels = params_channels(params);
>  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> -		ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, 0x3,
> -				8, slot_width);
> +		ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, SPK_TDM_RX_MASK,
> +					       NUM_TDM_SLOTS, slot_width);
>  		if (ret < 0) {
>  			dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n",
>  					__func__, ret);
>  			goto end;
>  		}
>  
>  		ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
>  				channels, tdm_slot_offset);
>  		if (ret < 0) {
>  			dev_err(rtd->dev, "%s: failed to set channel map, err:%d\n",
>  					__func__, ret);
>  			goto end;
>  		}
>  	} else {
> -		ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xf, 0,
> -				8, slot_width);
> +		ret = snd_soc_dai_set_tdm_slot(cpu_dai,
> +					       SPK_TDM_RX_MASK |
> +					       MIC_TDM_RX_MASK, 0,
> +					       NUM_TDM_SLOTS, slot_width);
>  		if (ret < 0) {
>  			dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n",
>  					__func__, ret);
>  			goto end;
>  		}
>  
>  		ret = snd_soc_dai_set_channel_map(cpu_dai, channels,
>  				tdm_slot_offset, 0, NULL);
> 


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

* Re: [PATCH v4 2/8] ASoC: qcom: sdm845: use DSP_A format for TDM codec DAIs
  2026-09-24 13:24 ` [PATCH v4 2/8] ASoC: qcom: sdm845: use DSP_A format for TDM codec DAIs David Heidelberg via B4 Relay
@ 2026-09-25  8:22   ` Srinivas Kandagatla
  0 siblings, 0 replies; 17+ messages in thread
From: Srinivas Kandagatla @ 2026-09-25  8:22 UTC (permalink / raw)
  To: david, Srinivas Kandagatla, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai, David Rhodes, Richard Fitzgerald,
	Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	David Rhodes, Conor Dooley
  Cc: linux-sound, linux-arm-msm, linux-kernel, patches, devicetree,
	phone-devel

On 9/24/26 2:24 PM, David Heidelberg via B4 Relay wrote:
> From: David Heidelberg <david@ixit.cz>
> 
> Before the DSP_B only worked because the only close-to-mainline consumer
> cs35l36 codec was patched to map both DSP_A and DSP_B to the same
> hardware register value (asp_fmt = 0), which is inherently DSP_A timing.
> Use the right codec (DSP_A) which works as expected.
> 
> Signed-off-by: David Heidelberg <david@ixit.cz>
> ---

Reviewed-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>

>  sound/soc/qcom/sdm845.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c
> index 0ce8265ab1c1f..d1cc825fc5cdc 100644
> --- a/sound/soc/qcom/sdm845.c
> +++ b/sound/soc/qcom/sdm845.c
> @@ -382,17 +382,17 @@ static int sdm845_snd_startup(struct snd_pcm_substream *substream)
>  	case QUATERNARY_TDM_RX_0:
>  	case QUATERNARY_TDM_TX_0:
>  		if (++(data->quat_tdm_clk_count) == 1) {
>  			snd_soc_dai_set_sysclk(cpu_dai,
>  				Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT,
>  				TDM_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
>  		}
>  
> -		codec_dai_fmt |= SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_DSP_B;
> +		codec_dai_fmt |= SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_DSP_A;
>  
>  		for_each_rtd_codec_dais(rtd, j, codec_dai) {
>  
>  			if (!strcmp(codec_dai->component->name_prefix,
>  				    "Left")) {
>  				ret = snd_soc_dai_set_fmt(
>  						codec_dai, codec_dai_fmt);
>  				if (ret < 0) {
> 


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

* Re: [PATCH v4 3/8] ASoC: qcom: sdm845: Use per-speaker RX masks for TDM slot assignment
  2026-09-24 13:24 ` [PATCH v4 3/8] ASoC: qcom: sdm845: Use per-speaker RX masks for TDM slot assignment David Heidelberg via B4 Relay
@ 2026-09-25  8:23   ` Srinivas Kandagatla
  0 siblings, 0 replies; 17+ messages in thread
From: Srinivas Kandagatla @ 2026-09-25  8:23 UTC (permalink / raw)
  To: david, Srinivas Kandagatla, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai, David Rhodes, Richard Fitzgerald,
	Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	David Rhodes, Conor Dooley
  Cc: linux-sound, linux-arm-msm, linux-kernel, patches, devicetree,
	phone-devel

On 9/24/26 2:24 PM, David Heidelberg via B4 Relay wrote:
> From: David Heidelberg <david@ixit.cz>
> 
> Both Left and Right codec DAIs were passing the same SPK_TDM_RX_MASK,
> both speakers ended up on slot 0, breaking the one speaker in
> configuration such as on Pixel 3.
> 
> Split SPK_TDM_RX_MASK into per-speaker masks so that the Left codec
> gets slot 0 (rx_mask=0x01) and the Right codec gets slot 1
> (rx_mask=0x02).
> 
> This commit is here, so later CS35L36 receives correct slot for right
> and left speakers.
> 
> Assisted-by: Claude:claude-4.6-opus
> Signed-off-by: David Heidelberg <david@ixit.cz>
> ---

Reviewed-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>

>  sound/soc/qcom/sdm845.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c
> index d1cc825fc5cdc..59cfa3b26cd4d 100644
> --- a/sound/soc/qcom/sdm845.c
> +++ b/sound/soc/qcom/sdm845.c
> @@ -152,29 +152,29 @@ static int sdm845_tdm_snd_hw_params(struct snd_pcm_substream *substream,
>  		}
>  	}
>  
>  	for_each_rtd_codec_dais(rtd, j, codec_dai) {
>  
>  		if (!strcmp(codec_dai->component->name_prefix, "Left")) {
>  			ret = snd_soc_dai_set_tdm_slot(
>  					codec_dai, LEFT_SPK_TDM_TX_MASK,
> -					SPK_TDM_RX_MASK, NUM_TDM_SLOTS,
> +					LEFT_SPK_TDM_RX_MASK, NUM_TDM_SLOTS,
>  					slot_width);
>  			if (ret < 0) {
>  				dev_err(rtd->dev,
>  					"DEV0 TDM slot err:%d\n", ret);
>  				return ret;
>  			}
>  		}
>  
>  		if (!strcmp(codec_dai->component->name_prefix, "Right")) {
>  			ret = snd_soc_dai_set_tdm_slot(
>  					codec_dai, RIGHT_SPK_TDM_TX_MASK,
> -					SPK_TDM_RX_MASK, NUM_TDM_SLOTS,
> +					RIGHT_SPK_TDM_RX_MASK, NUM_TDM_SLOTS,
>  					slot_width);
>  			if (ret < 0) {
>  				dev_err(rtd->dev,
>  					"DEV1 TDM slot err:%d\n", ret);
>  				return ret;
>  			}
>  		}
>  	}
> 


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

* Re: [PATCH v4 4/8] ASoC: qcom: sdm845: Set codec dai and component sysclk during startup
  2026-09-24 13:24 ` [PATCH v4 4/8] ASoC: qcom: sdm845: Set codec dai and component sysclk during startup David Heidelberg via B4 Relay
@ 2026-09-25  8:26   ` Srinivas Kandagatla
  0 siblings, 0 replies; 17+ messages in thread
From: Srinivas Kandagatla @ 2026-09-25  8:26 UTC (permalink / raw)
  To: david, Srinivas Kandagatla, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai, David Rhodes, Richard Fitzgerald,
	Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	David Rhodes, Conor Dooley
  Cc: linux-sound, linux-arm-msm, linux-kernel, patches, devicetree,
	phone-devel

On 9/24/26 2:24 PM, David Heidelberg via B4 Relay wrote:
> From: David Heidelberg <david@ixit.cz>
> 
> The cs35l36 codec needs the codec dai and component sysclk to be set
> during TDM startup. Set these for all codec DAIs on the QUATERNARY_TDM
> path, gracefully handling codecs that don't support sysclk by ignoring
> -ENOTSUPP returns.
> 
> Based on work of Joel Selvaraj.
> 
> Signed-off-by: David Heidelberg <david@ixit.cz>


It was unusal to see codec needing both dai and component callbacks to
set the sysclk correctly, it could have done with one.. but did not look
into details.. Or may be its me hitting this type for first time.

Otherwise it looks good to me.


Reviewed-by: Srinivas Kandagatla<srinivas.kandagatla@oss.qualcomm.com>


> ---
>  sound/soc/qcom/sdm845.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c
> index 59cfa3b26cd4d..f0fbec9c8df25 100644
> --- a/sound/soc/qcom/sdm845.c
> +++ b/sound/soc/qcom/sdm845.c
> @@ -407,16 +407,38 @@ static int sdm845_snd_startup(struct snd_pcm_substream *substream)
>  				ret = snd_soc_dai_set_fmt(
>  						codec_dai, codec_dai_fmt);
>  				if (ret < 0) {
>  					dev_err(rtd->dev,
>  						"Right TDM slot err:%d\n", ret);
>  					return ret;
>  				}
>  			}
> +
> +			/* Set codec sysclk needed by codecs like cs35l36. */
> +			ret = snd_soc_dai_set_sysclk(codec_dai, 0,
> +						     TDM_BCLK_RATE,
> +						     SND_SOC_CLOCK_IN);
> +			if (ret < 0 && ret != -ENOTSUPP) {
> +				dev_err(codec_dai->dev,
> +					"Failed to set codec dai sysclk: %d\n",
> +					ret);
> +				return ret;
> +			}
> +
> +			ret = snd_soc_component_set_sysclk(codec_dai->component,
> +							   0, 0,
> +							   TDM_BCLK_RATE,
> +							   SND_SOC_CLOCK_IN);
> +			if (ret < 0 && ret != -ENOTSUPP) {
> +				dev_err(codec_dai->dev,
> +					"Failed to set codec component sysclk: %d\n",
> +					ret);
> +				return ret;
> +			}
>  		}
>  		break;
>  	case SLIMBUS_0_RX...SLIMBUS_6_TX:
>  		break;
>  
>  	default:
>  		pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
>  		break;
> 


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

* Re: [PATCH v4 7/8] slimbus: qcom-ngd-ctrl: Remove data channels on stream disable
  2026-09-25  8:09   ` Srinivas Kandagatla
@ 2026-09-25  8:34     ` David Heidelberg
  0 siblings, 0 replies; 17+ messages in thread
From: David Heidelberg @ 2026-09-25  8:34 UTC (permalink / raw)
  To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, David Rhodes, Richard Fitzgerald, Bjorn Andersson,
	Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, David Rhodes,
	Conor Dooley
  Cc: linux-sound, linux-arm-msm, linux-kernel, patches, devicetree,
	phone-devel

On 25/09/2026 10:09, Srinivas Kandagatla wrote:
> On 9/24/26 2:24 PM, David Heidelberg via B4 Relay wrote:
>> From: David Heidelberg <david@ixit.cz>
>>
>> qcom_slim_ngd_xfer_msg() silently returns success for every core
>> reconfiguration message, so the generic channel removal done by
>> slim_stream_disable() never reaches the ADSP SLIMbus master. The
>> master therefore keeps the channels of a closed stream. When the next
>> stream defines the same channel numbers again, the WCD9340 capture
>> completes without any error but records only zeros; removing the
>> channels explicitly when the stream is disabled makes it work again.
>>
>> Implement the disable_stream controller op with the sequence the
>> downstream NGD driver sends for channel removal, CHAN_CTRL(REMOVE)
>> listing the stream's channels followed by RECONFIG_NOW. Like
>> downstream, treat -EREMOTEIO from the removal as success: it means the
>> controller is being restarted and the channels are gone anyway.
>>
>> Based on work done by Casey Tunturi.
>>
>> Assisted-by: Claude:claude-fable-5-1
>> Signed-off-by: David Heidelberg <david@ixit.cz>
>> ---
> 
> there is an identical patch on the list,
> https://lore.kernel.org/linux-arm-msm/247e4ce7-1ba2-43b8-8a11-ec70f99a4fc1@linaro.org/T/#m3b50aa43a6493f8d3b607b1607b37bf14b199f69

I was not aware, I'll try to look into it today and address the comments on the 
original one (and keep the credits as LLM likely "got heavily inspired there").

David

> 
> --srini
> 
> 
>>   drivers/slimbus/qcom-ngd-ctrl.c | 81 +++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 81 insertions(+)
>>
>> diff --git a/drivers/slimbus/qcom-ngd-ctrl.c b/drivers/slimbus/qcom-ngd-ctrl.c
>> index eb0ccb31e9074..0a4859466c82d 100644
>> --- a/drivers/slimbus/qcom-ngd-ctrl.c
>> +++ b/drivers/slimbus/qcom-ngd-ctrl.c
>> @@ -1081,16 +1081,96 @@ static int qcom_slim_ngd_enable_stream(struct slim_stream_runtime *rt)
>>   		slim_free_txn_tid(ctrl, &txn);
>>   		dev_err(&sdev->dev, "TX timed out:MC:0x%x,mt:0x%x", txn.mc,
>>   				txn.mt);
>>   	}
>>   
>>   	return ret;
>>   }
>>   
>> +/* CHAN_CTRL operation, bits [7:6] of the first payload byte */
>> +#define SLIM_USR_CHAN_CTRL_REMOVE	2
>> +
>> +static int qcom_slim_ngd_disable_stream(struct slim_stream_runtime *rt)
>> +{
>> +	struct slim_device *sdev = rt->dev;
>> +	struct slim_controller *ctrl = sdev->ctrl;
>> +	struct slim_val_inf msg =  {0};
>> +	u8 wbuf[SLIM_MSGQ_BUF_LEN];
>> +	u8 rbuf[SLIM_MSGQ_BUF_LEN];
>> +	struct slim_msg_txn txn = {0,};
>> +	int i, ret;
>> +
>> +	txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
>> +	txn.dt = SLIM_MSG_DEST_LOGICALADDR;
>> +	txn.la = SLIM_LA_MGR;
>> +	txn.ec = 0;
>> +	txn.msg = &msg;
>> +	txn.msg->num_bytes = 0;
>> +	txn.msg->wbuf = wbuf;
>> +	txn.msg->rbuf = rbuf;
>> +
>> +	/*
>> +	 * The NGD drops the core reconfiguration messages that
>> +	 * slim_stream_disable() uses to remove channels, so ask the master
>> +	 * to remove them the way the downstream NGD driver does:
>> +	 * CHAN_CTRL(REMOVE) listing every channel, then RECONFIG_NOW.
>> +	 * Without this the master keeps the channels active and a later
>> +	 * DEF_ACT_CHAN with the same channel numbers is a no-op, so the
>> +	 * data path is never re-armed and a reopened stream moves no data.
>> +	 */
>> +	/* 5-bit client number, operation in bits [7:6] */
>> +	wbuf[txn.msg->num_bytes++] = (SLIM_USR_CHAN_CTRL_REMOVE << 6) |
>> +				     (sdev->laddr & 0x1f);
>> +
>> +	ret = slim_alloc_txn_tid(ctrl, &txn);
>> +	if (ret) {
>> +		dev_err(&sdev->dev, "Fail to allocate TID\n");
>> +		return ret;
>> +	}
>> +	wbuf[txn.msg->num_bytes++] = txn.tid;
>> +
>> +	for (i = 0; i < rt->num_ports; i++)
>> +		wbuf[txn.msg->num_bytes++] = rt->ports[i].ch.id;
>> +
>> +	txn.mc = SLIM_USR_MC_CHAN_CTRL;
>> +	txn.rl = txn.msg->num_bytes + 4;
>> +	ret = qcom_slim_ngd_xfer_msg_sync(ctrl, &txn);
>> +	if (ret) {
>> +		slim_free_txn_tid(ctrl, &txn);
>> +		/* Controller restarting, the channels are gone anyway */
>> +		if (ret == -EREMOTEIO)
>> +			return 0;
>> +		dev_err(&sdev->dev, "TX timed out:MC:0x%x,mt:0x%x", txn.mc,
>> +				txn.mt);
>> +		return ret;
>> +	}
>> +
>> +	txn.mc = SLIM_USR_MC_RECONFIG_NOW;
>> +	txn.msg->num_bytes = 2;
>> +	wbuf[1] = sdev->laddr;
>> +	txn.rl = txn.msg->num_bytes + 4;
>> +
>> +	ret = slim_alloc_txn_tid(ctrl, &txn);
>> +	if (ret) {
>> +		dev_err(ctrl->dev, "Fail to allocate TID\n");
>> +		return ret;
>> +	}
>> +
>> +	wbuf[0] = txn.tid;
>> +	ret = qcom_slim_ngd_xfer_msg_sync(ctrl, &txn);
>> +	if (ret) {
>> +		slim_free_txn_tid(ctrl, &txn);
>> +		dev_err(&sdev->dev, "TX timed out:MC:0x%x,mt:0x%x", txn.mc,
>> +				txn.mt);
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>>   static int qcom_slim_ngd_get_laddr(struct slim_controller *ctrl,
>>   				   struct slim_eaddr *ea, u8 *laddr)
>>   {
>>   	struct slim_val_inf msg =  {0};
>>   	u8 failed_ea[6] = {0, 0, 0, 0, 0, 0};
>>   	struct slim_msg_txn txn;
>>   	u8 wbuf[10] = {0};
>>   	u8 rbuf[10] = {0};
>> @@ -1620,16 +1700,17 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
>>   	ctrl->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
>>   	ctrl->framer.superfreq =
>>   		ctrl->framer.rootfreq / SLIM_CL_PER_SUPERFRAME_DIV8;
>>   
>>   	ctrl->ctrl.a_framer = &ctrl->framer;
>>   	ctrl->ctrl.clkgear = SLIM_MAX_CLK_GEAR;
>>   	ctrl->ctrl.get_laddr = qcom_slim_ngd_get_laddr;
>>   	ctrl->ctrl.enable_stream = qcom_slim_ngd_enable_stream;
>> +	ctrl->ctrl.disable_stream = qcom_slim_ngd_disable_stream;
>>   	ctrl->ctrl.xfer_msg = qcom_slim_ngd_xfer_msg;
>>   	ctrl->ctrl.wakeup = NULL;
>>   	ctrl->state = QCOM_SLIM_NGD_CTRL_DOWN;
>>   
>>   	mutex_init(&ctrl->tx_lock);
>>   	mutex_init(&ctrl->ssr_lock);
>>   	spin_lock_init(&ctrl->tx_buf_lock);
>>   	init_completion(&ctrl->reconf);
>>
> 


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

end of thread, other threads:[~2026-09-25  8:34 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-24 13:24 [PATCH v4 0/8] Speakers for Pixel 3 / 3 XL David Heidelberg via B4 Relay
2026-09-24 13:24 ` [PATCH v4 1/8] ASoC: qcom: sdm845: Demystify TDM masks a bit David Heidelberg via B4 Relay
2026-09-25  8:14   ` Srinivas Kandagatla
2026-09-24 13:24 ` [PATCH v4 2/8] ASoC: qcom: sdm845: use DSP_A format for TDM codec DAIs David Heidelberg via B4 Relay
2026-09-25  8:22   ` Srinivas Kandagatla
2026-09-24 13:24 ` [PATCH v4 3/8] ASoC: qcom: sdm845: Use per-speaker RX masks for TDM slot assignment David Heidelberg via B4 Relay
2026-09-25  8:23   ` Srinivas Kandagatla
2026-09-24 13:24 ` [PATCH v4 4/8] ASoC: qcom: sdm845: Set codec dai and component sysclk during startup David Heidelberg via B4 Relay
2026-09-25  8:26   ` Srinivas Kandagatla
2026-09-24 13:24 ` [PATCH v4 5/8] ASoC: cs35l36: Implement set_tdm_slot to program RX and TX slots David Heidelberg via B4 Relay
2026-09-24 13:24 ` [PATCH v4 6/8] arm64: dts: qcom: sdm845-google: Add basic audio support David Heidelberg via B4 Relay
2026-09-24 13:24 ` [PATCH v4 7/8] slimbus: qcom-ngd-ctrl: Remove data channels on stream disable David Heidelberg via B4 Relay
2026-09-25  8:09   ` Srinivas Kandagatla
2026-09-25  8:34     ` David Heidelberg
2026-09-24 13:24 ` [PATCH v4 8/8] arm64: dts: qcom: sdm845-google: Add WCD9340 codec and microphone capture David Heidelberg via B4 Relay
2026-09-24 14:11 ` [PATCH v4 0/8] Speakers for Pixel 3 / 3 XL Mark Brown
2026-09-24 14:13   ` David Heidelberg

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

all inboxes | Powered by JetHome®