Jiri Slaby eeab2a
From: =?UTF-8?q?Martin=20Povi=C5=A1er?= <povik+lin@cutebit.org>
Jiri Slaby eeab2a
Date: Fri, 24 Feb 2023 16:33:01 +0100
Jiri Slaby eeab2a
Subject: [PATCH] ASoC: apple: mca: Fix SERDES reset sequence
Jiri Slaby eeab2a
MIME-Version: 1.0
Jiri Slaby eeab2a
Content-Type: text/plain; charset=UTF-8
Jiri Slaby eeab2a
Content-Transfer-Encoding: 8bit
Jiri Slaby eeab2a
References: bsc#1012628
Jiri Slaby eeab2a
Patch-mainline: 6.2.5
Jiri Slaby eeab2a
Git-commit: d8b3e396088d787771f19fd3b7949e080dc31d6f
Jiri Slaby eeab2a
Jiri Slaby eeab2a
[ Upstream commit d8b3e396088d787771f19fd3b7949e080dc31d6f ]
Jiri Slaby eeab2a
Jiri Slaby eeab2a
Fix the reset sequence of reads and writes that we invoke from within
Jiri Slaby eeab2a
the early trigger. It looks like there never was a SERDES_CONF_SOME_RST
Jiri Slaby eeab2a
bit that should be involved in the reset sequence, and its presence in
Jiri Slaby eeab2a
the driver code is a mistake from earlier.
Jiri Slaby eeab2a
Jiri Slaby eeab2a
Instead, the reset sequence should go as follows: We should switch the
Jiri Slaby eeab2a
the SERDES unit's SYNC_SEL mux to the value of 7 (so outside the range
Jiri Slaby eeab2a
of 1...6 representing cluster's SYNCGEN units), then raise the RST bit
Jiri Slaby eeab2a
in SERDES_STATUS and wait for it to clear.
Jiri Slaby eeab2a
Jiri Slaby eeab2a
Properly resetting the SERDES unit fixes frame desynchronization hazard
Jiri Slaby eeab2a
in case of long frames (longer than 4 used slots). The desynchronization
Jiri Slaby eeab2a
manifests itself by rotating the PCM channels.
Jiri Slaby eeab2a
Jiri Slaby eeab2a
Fixes: 3df5d0d97289 ("ASoC: apple: mca: Start new platform driver")
Jiri Slaby eeab2a
Signed-off-by: Martin PoviĊĦer <povik+lin@cutebit.org>
Jiri Slaby eeab2a
Link: https://lore.kernel.org/r/20230224153302.45365-2-povik+lin@cutebit.org
Jiri Slaby eeab2a
Signed-off-by: Mark Brown <broonie@kernel.org>
Jiri Slaby eeab2a
Signed-off-by: Sasha Levin <sashal@kernel.org>
Jiri Slaby eeab2a
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Jiri Slaby eeab2a
---
Jiri Slaby eeab2a
 sound/soc/apple/mca.c | 18 +++++++++++++-----
Jiri Slaby eeab2a
 1 file changed, 13 insertions(+), 5 deletions(-)
Jiri Slaby eeab2a
Jiri Slaby eeab2a
diff --git a/sound/soc/apple/mca.c b/sound/soc/apple/mca.c
Jiri Slaby eeab2a
index 9cceeb25..aea08c7b 100644
Jiri Slaby eeab2a
--- a/sound/soc/apple/mca.c
Jiri Slaby eeab2a
+++ b/sound/soc/apple/mca.c
Jiri Slaby eeab2a
@@ -101,7 +101,6 @@
Jiri Slaby eeab2a
 #define SERDES_CONF_UNK3	BIT(14)
Jiri Slaby eeab2a
 #define SERDES_CONF_NO_DATA_FEEDBACK	BIT(15)
Jiri Slaby eeab2a
 #define SERDES_CONF_SYNC_SEL	GENMASK(18, 16)
Jiri Slaby eeab2a
-#define SERDES_CONF_SOME_RST	BIT(19)
Jiri Slaby eeab2a
 #define REG_TX_SERDES_BITSTART	0x08
Jiri Slaby eeab2a
 #define REG_RX_SERDES_BITSTART	0x0c
Jiri Slaby eeab2a
 #define REG_TX_SERDES_SLOTMASK	0x0c
Jiri Slaby eeab2a
@@ -203,15 +202,24 @@ static void mca_fe_early_trigger(struct snd_pcm_substream *substream, int cmd,
Jiri Slaby eeab2a
 	case SNDRV_PCM_TRIGGER_START:
Jiri Slaby eeab2a
 	case SNDRV_PCM_TRIGGER_RESUME:
Jiri Slaby eeab2a
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
Jiri Slaby eeab2a
+		mca_modify(cl, serdes_conf, SERDES_CONF_SYNC_SEL,
Jiri Slaby eeab2a
+			   FIELD_PREP(SERDES_CONF_SYNC_SEL, 0));
Jiri Slaby eeab2a
+		mca_modify(cl, serdes_conf, SERDES_CONF_SYNC_SEL,
Jiri Slaby eeab2a
+			   FIELD_PREP(SERDES_CONF_SYNC_SEL, 7));
Jiri Slaby eeab2a
 		mca_modify(cl, serdes_unit + REG_SERDES_STATUS,
Jiri Slaby eeab2a
 			   SERDES_STATUS_EN | SERDES_STATUS_RST,
Jiri Slaby eeab2a
 			   SERDES_STATUS_RST);
Jiri Slaby eeab2a
-		mca_modify(cl, serdes_conf, SERDES_CONF_SOME_RST,
Jiri Slaby eeab2a
-			   SERDES_CONF_SOME_RST);
Jiri Slaby eeab2a
-		readl_relaxed(cl->base + serdes_conf);
Jiri Slaby eeab2a
-		mca_modify(cl, serdes_conf, SERDES_STATUS_RST, 0);
Jiri Slaby eeab2a
+		/*
Jiri Slaby eeab2a
+		 * Experiments suggest that it takes at most ~1 us
Jiri Slaby eeab2a
+		 * for the bit to clear, so wait 2 us for good measure.
Jiri Slaby eeab2a
+		 */
Jiri Slaby eeab2a
+		udelay(2);
Jiri Slaby eeab2a
 		WARN_ON(readl_relaxed(cl->base + serdes_unit + REG_SERDES_STATUS) &
Jiri Slaby eeab2a
 			SERDES_STATUS_RST);
Jiri Slaby eeab2a
+		mca_modify(cl, serdes_conf, SERDES_CONF_SYNC_SEL,
Jiri Slaby eeab2a
+			   FIELD_PREP(SERDES_CONF_SYNC_SEL, 0));
Jiri Slaby eeab2a
+		mca_modify(cl, serdes_conf, SERDES_CONF_SYNC_SEL,
Jiri Slaby eeab2a
+			   FIELD_PREP(SERDES_CONF_SYNC_SEL, cl->no + 1));
Jiri Slaby eeab2a
 		break;
Jiri Slaby eeab2a
 	default:
Jiri Slaby eeab2a
 		break;
Jiri Slaby eeab2a
-- 
Jiri Slaby eeab2a
2.35.3
Jiri Slaby eeab2a