[PATCH 4/4] ASoC: fsl_asrc: swap input and output clocks in capture mode

Arnaud Ferraris
2020-07-02T14:26:29Z

The input clock is the reference clock we need to convert the stream to,
which therefore has to be the clock of the origin stream/device.

When the stream is bi-directional and we want ASRC to act on both
directions, we need to swap the input and output clocks between the
playback and capture streams.

As some of the clocks have different ID's depending on whether they are
used as input or output, this requires adding a new function to find the
output clock ID corresponding to a given input clock.

Signed-off-by: Arnaud Ferraris <arnaud.ferraris@collabora.com>
---
sound/soc/fsl/fsl_asrc.c | 50 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 48 insertions(+), 2 deletions(-)

diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 65e7307a3df0..5aeab1fbcdd9 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -506,6 +506,50 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate)
return fsl_asrc_set_ideal_ratio(pair, inrate, outrate);
}

+/**
+ * Select the output clock corresponding to a given input clock (and vice-versa)
+ *
+ * If we want to setup a capture channel, the input and output clocks have to
+ * be swapped.
+ * However, even if most of the clocks have the same index when used as input
+ * or output, some of them (ESAI, SSI* and SPDIF) are different:
+ * - the TX output clock has the index of the corresponding RX input clock
+ * - the RX output clock has the index of the corresponding TX input clock
+ *
+ * This function makes sure that we use the proper clock index when swapping
+ * the input and output clocks.
+ */
+static enum asrc_outclk fsl_asrc_get_capture_clock(enum asrc_inclk inclk)
+{
+ enum asrc_outclk outclk;
+
+ switch (inclk) {
+ case INCLK_ESAI_RX:
+ case INCLK_SSI1_RX:
+ case INCLK_SSI2_RX:
+ case INCLK_SPDIF_RX:
+ outclk = inclk + 0x8;
+ break;
+ case INCLK_SSI3_RX:
+ outclk = OUTCLK_SSI3_RX;
+ break;
+ case INCLK_ESAI_TX:
+ case INCLK_SSI1_TX:
+ case INCLK_SSI2_TX:
+ case INCLK_SPDIF_TX:
+ outclk = inclk - 0x8;
+ break;
+ case INCLK_SSI3_TX:
+ outclk = OUTCLK_SSI3_TX;
+ break;
+ default:
+ outclk = inclk;
+ break;
+ }
+
+ return outclk;
+}
+
/**
* Start the assigned ASRC pair
*
@@ -604,15 +648,17 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,

config.pair = pair->index;
config.channel_num = channels;
- config.inclk = asrc->inclk;
- config.outclk = asrc->outclk;

if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ config.inclk = asrc->inclk;
+ config.outclk = asrc->outclk;
config.input_format = params_format(params);
config.output_format = asrc->asrc_format;
config.input_sample_rate = rate;
config.output_sample_rate = asrc->asrc_rate;
} else {
+ config.inclk = fsl_asrc_get_capture_clock(asrc->outclk);
+ config.outclk = fsl_asrc_get_capture_clock(asrc->inclk);
config.input_format = asrc->asrc_format;
config.output_format = params_format(params);
config.input_sample_rate = asrc->asrc_rate;
--
2.27.0