Skip to content

Commit 52a5250

Browse files
bijudasbroonie
authored andcommitted
ASoC: renesas: rz-ssi: Fix channel swap issue in full duplex mode
The full duplex audio starts with half duplex mode and then switch to full duplex mode (another FIFO reset) when both playback/capture streams available leading to random audio left/right channel swap issue. Fix this channel swap issue by detecting the full duplex condition by populating struct dup variable in startup() callback and synchronize starting both the play and capture at the same time in rz_ssi_start(). Cc: stable@kernel.org Fixes: 4f8cd05 ("ASoC: sh: rz-ssi: Add full duplex support") Co-developed-by: Tony Tang <tony.tang.ks@renesas.com> Signed-off-by: Tony Tang <tony.tang.ks@renesas.com> Reviewed-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com> Link: https://patch.msgid.link/20251114073709.4376-2-biju.das.jz@bp.renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 2196e81 commit 52a5250

1 file changed

Lines changed: 43 additions & 8 deletions

File tree

sound/soc/renesas/rz-ssi.c

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@ struct rz_ssi_priv {
133133
bool bckp_rise; /* Bit clock polarity (SSICR.BCKP) */
134134
bool dma_rt;
135135

136+
struct {
137+
bool tx_active;
138+
bool rx_active;
139+
bool one_stream_triggered;
140+
} dup;
141+
136142
/* Full duplex communication support */
137143
struct {
138144
unsigned int rate;
@@ -332,13 +338,12 @@ static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
332338
bool is_full_duplex;
333339
u32 ssicr, ssifcr;
334340

335-
is_full_duplex = rz_ssi_is_stream_running(&ssi->playback) ||
336-
rz_ssi_is_stream_running(&ssi->capture);
341+
is_full_duplex = ssi->dup.tx_active && ssi->dup.rx_active;
337342
ssicr = rz_ssi_reg_readl(ssi, SSICR);
338343
ssifcr = rz_ssi_reg_readl(ssi, SSIFCR);
339344
if (!is_full_duplex) {
340345
ssifcr &= ~0xF;
341-
} else {
346+
} else if (ssi->dup.one_stream_triggered) {
342347
rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TEN | SSICR_REN, 0);
343348
rz_ssi_set_idle(ssi);
344349
ssifcr &= ~SSIFCR_FIFO_RST;
@@ -374,12 +379,16 @@ static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
374379
SSISR_RUIRQ), 0);
375380

376381
strm->running = 1;
377-
if (is_full_duplex)
378-
ssicr |= SSICR_TEN | SSICR_REN;
379-
else
382+
if (!is_full_duplex) {
380383
ssicr |= is_play ? SSICR_TEN : SSICR_REN;
381-
382-
rz_ssi_reg_writel(ssi, SSICR, ssicr);
384+
rz_ssi_reg_writel(ssi, SSICR, ssicr);
385+
} else if (ssi->dup.one_stream_triggered) {
386+
ssicr |= SSICR_TEN | SSICR_REN;
387+
rz_ssi_reg_writel(ssi, SSICR, ssicr);
388+
ssi->dup.one_stream_triggered = false;
389+
} else {
390+
ssi->dup.one_stream_triggered = true;
391+
}
383392

384393
return 0;
385394
}
@@ -915,6 +924,30 @@ static int rz_ssi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
915924
return 0;
916925
}
917926

927+
static int rz_ssi_startup(struct snd_pcm_substream *substream,
928+
struct snd_soc_dai *dai)
929+
{
930+
struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
931+
932+
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
933+
ssi->dup.tx_active = true;
934+
else
935+
ssi->dup.rx_active = true;
936+
937+
return 0;
938+
}
939+
940+
static void rz_ssi_shutdown(struct snd_pcm_substream *substream,
941+
struct snd_soc_dai *dai)
942+
{
943+
struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
944+
945+
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
946+
ssi->dup.tx_active = false;
947+
else
948+
ssi->dup.rx_active = false;
949+
}
950+
918951
static bool rz_ssi_is_valid_hw_params(struct rz_ssi_priv *ssi, unsigned int rate,
919952
unsigned int channels,
920953
unsigned int sample_width,
@@ -985,6 +1018,8 @@ static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream,
9851018
}
9861019

9871020
static const struct snd_soc_dai_ops rz_ssi_dai_ops = {
1021+
.startup = rz_ssi_startup,
1022+
.shutdown = rz_ssi_shutdown,
9881023
.trigger = rz_ssi_dai_trigger,
9891024
.set_fmt = rz_ssi_dai_set_fmt,
9901025
.hw_params = rz_ssi_dai_hw_params,

0 commit comments

Comments
 (0)