mirror of
https://github.com/hanwckf/immortalwrt-mt798x.git
synced 2025-01-10 03:09:08 +08:00
949f0dd900
Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
176 lines
6.0 KiB
Diff
176 lines
6.0 KiB
Diff
From f12dcaf65b9a780f0cc72e3b86479e71a59116f1 Mon Sep 17 00:00:00 2001
|
|
From: Tianling Shen <cnsztl@gmail.com>
|
|
Date: Thu, 31 Aug 2023 11:05:11 +0800
|
|
Subject: [PATCH] Revert "ASoC: fsl_sai: Refine enable/disable TE/RE sequence
|
|
in trigger()"
|
|
|
|
This reverts commit 1b3d751045425ec38e1e68cd1d64da1856772144.
|
|
---
|
|
sound/soc/fsl/fsl_sai.c | 126 +++++++++++++---------------------------
|
|
1 file changed, 41 insertions(+), 85 deletions(-)
|
|
|
|
--- a/sound/soc/fsl/fsl_sai.c
|
|
+++ b/sound/soc/fsl/fsl_sai.c
|
|
@@ -37,24 +37,6 @@ static const struct snd_pcm_hw_constrain
|
|
.list = fsl_sai_rates,
|
|
};
|
|
|
|
-/**
|
|
- * fsl_sai_dir_is_synced - Check if stream is synced by the opposite stream
|
|
- *
|
|
- * SAI supports synchronous mode using bit/frame clocks of either Transmitter's
|
|
- * or Receiver's for both streams. This function is used to check if clocks of
|
|
- * the stream's are synced by the opposite stream.
|
|
- *
|
|
- * @sai: SAI context
|
|
- * @dir: stream direction
|
|
- */
|
|
-static inline bool fsl_sai_dir_is_synced(struct fsl_sai *sai, int dir)
|
|
-{
|
|
- int adir = (dir == TX) ? RX : TX;
|
|
-
|
|
- /* current dir in async mode while opposite dir in sync mode */
|
|
- return !sai->synchronous[dir] && sai->synchronous[adir];
|
|
-}
|
|
-
|
|
static irqreturn_t fsl_sai_isr(int irq, void *devid)
|
|
{
|
|
struct fsl_sai *sai = (struct fsl_sai *)devid;
|
|
@@ -541,38 +523,6 @@ static int fsl_sai_hw_free(struct snd_pc
|
|
return 0;
|
|
}
|
|
|
|
-static void fsl_sai_config_disable(struct fsl_sai *sai, int dir)
|
|
-{
|
|
- unsigned int ofs = sai->soc_data->reg_offset;
|
|
- bool tx = dir == TX;
|
|
- u32 xcsr, count = 100;
|
|
-
|
|
- regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
|
|
- FSL_SAI_CSR_TERE, 0);
|
|
-
|
|
- /* TERE will remain set till the end of current frame */
|
|
- do {
|
|
- udelay(10);
|
|
- regmap_read(sai->regmap, FSL_SAI_xCSR(tx, ofs), &xcsr);
|
|
- } while (--count && xcsr & FSL_SAI_CSR_TERE);
|
|
-
|
|
- regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
|
|
- FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
|
|
-
|
|
- /*
|
|
- * For sai master mode, after several open/close sai,
|
|
- * there will be no frame clock, and can't recover
|
|
- * anymore. Add software reset to fix this issue.
|
|
- * This is a hardware bug, and will be fix in the
|
|
- * next sai version.
|
|
- */
|
|
- if (!sai->is_slave_mode) {
|
|
- /* Software Reset */
|
|
- regmap_write(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_SR);
|
|
- /* Clear SR bit to finish the reset */
|
|
- regmap_write(sai->regmap, FSL_SAI_xCSR(tx, ofs), 0);
|
|
- }
|
|
-}
|
|
|
|
static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
|
|
struct snd_soc_dai *cpu_dai)
|
|
@@ -581,9 +531,7 @@ static int fsl_sai_trigger(struct snd_pc
|
|
unsigned int ofs = sai->soc_data->reg_offset;
|
|
|
|
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
|
|
- int adir = tx ? RX : TX;
|
|
- int dir = tx ? TX : RX;
|
|
- u32 xcsr;
|
|
+ u32 xcsr, count = 100;
|
|
|
|
/*
|
|
* Asynchronous mode: Clear SYNC for both Tx and Rx.
|
|
@@ -606,22 +554,10 @@ static int fsl_sai_trigger(struct snd_pc
|
|
regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
|
|
FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE);
|
|
|
|
- regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
|
|
+ regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs),
|
|
+ FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
|
|
+ regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs),
|
|
FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
|
|
- /*
|
|
- * Enable the opposite direction for synchronous mode
|
|
- * 1. Tx sync with Rx: only set RE for Rx; set TE & RE for Tx
|
|
- * 2. Rx sync with Tx: only set TE for Tx; set RE & TE for Rx
|
|
- *
|
|
- * RM recommends to enable RE after TE for case 1 and to enable
|
|
- * TE after RE for case 2, but we here may not always guarantee
|
|
- * that happens: "arecord 1.wav; aplay 2.wav" in case 1 enables
|
|
- * TE after RE, which is against what RM recommends but should
|
|
- * be safe to do, judging by years of testing results.
|
|
- */
|
|
- if (fsl_sai_dir_is_synced(sai, adir))
|
|
- regmap_update_bits(sai->regmap, FSL_SAI_xCSR((!tx), ofs),
|
|
- FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
|
|
|
|
regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
|
|
FSL_SAI_CSR_xIE_MASK, FSL_SAI_FLAGS);
|
|
@@ -636,23 +572,43 @@ static int fsl_sai_trigger(struct snd_pc
|
|
|
|
/* Check if the opposite FRDE is also disabled */
|
|
regmap_read(sai->regmap, FSL_SAI_xCSR(!tx, ofs), &xcsr);
|
|
-
|
|
- /*
|
|
- * If opposite stream provides clocks for synchronous mode and
|
|
- * it is inactive, disable it before disabling the current one
|
|
- */
|
|
- if (fsl_sai_dir_is_synced(sai, adir) && !(xcsr & FSL_SAI_CSR_FRDE))
|
|
- fsl_sai_config_disable(sai, adir);
|
|
-
|
|
- /*
|
|
- * Disable current stream if either of:
|
|
- * 1. current stream doesn't provide clocks for synchronous mode
|
|
- * 2. current stream provides clocks for synchronous mode but no
|
|
- * more stream is active.
|
|
- */
|
|
- if (!fsl_sai_dir_is_synced(sai, dir) || !(xcsr & FSL_SAI_CSR_FRDE))
|
|
- fsl_sai_config_disable(sai, dir);
|
|
-
|
|
+ if (!(xcsr & FSL_SAI_CSR_FRDE)) {
|
|
+ /* Disable both directions and reset their FIFOs */
|
|
+ regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs),
|
|
+ FSL_SAI_CSR_TERE, 0);
|
|
+ regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs),
|
|
+ FSL_SAI_CSR_TERE, 0);
|
|
+
|
|
+ /* TERE will remain set till the end of current frame */
|
|
+ do {
|
|
+ udelay(10);
|
|
+ regmap_read(sai->regmap,
|
|
+ FSL_SAI_xCSR(tx, ofs), &xcsr);
|
|
+ } while (--count && xcsr & FSL_SAI_CSR_TERE);
|
|
+
|
|
+ regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs),
|
|
+ FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
|
|
+ regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs),
|
|
+ FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
|
|
+
|
|
+ /*
|
|
+ * For sai master mode, after several open/close sai,
|
|
+ * there will be no frame clock, and can't recover
|
|
+ * anymore. Add software reset to fix this issue.
|
|
+ * This is a hardware bug, and will be fix in the
|
|
+ * next sai version.
|
|
+ */
|
|
+ if (!sai->is_slave_mode) {
|
|
+ /* Software Reset for both Tx and Rx */
|
|
+ regmap_write(sai->regmap, FSL_SAI_TCSR(ofs),
|
|
+ FSL_SAI_CSR_SR);
|
|
+ regmap_write(sai->regmap, FSL_SAI_RCSR(ofs),
|
|
+ FSL_SAI_CSR_SR);
|
|
+ /* Clear SR bit to finish the reset */
|
|
+ regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
|
|
+ regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
|
|
+ }
|
|
+ }
|
|
break;
|
|
default:
|
|
return -EINVAL;
|