Skip to content

Commit 1fe39f5

Browse files
bijudasgregkh
authored andcommitted
ASoC: renesas: rz-ssi: Fix channel swap issue in full duplex mode
[ Upstream commit 52a5250 ] 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent f5b7f49 commit 1fe39f5

1 file changed

Lines changed: 43 additions & 8 deletions

File tree

sound/soc/sh/rz-ssi.c

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

135+
struct {
136+
bool tx_active;
137+
bool rx_active;
138+
bool one_stream_triggered;
139+
} dup;
140+
135141
/* Full duplex communication support */
136142
struct {
137143
unsigned int rate;
@@ -352,13 +358,12 @@ static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
352358
bool is_full_duplex;
353359
u32 ssicr, ssifcr;
354360

355-
is_full_duplex = rz_ssi_is_stream_running(&ssi->playback) ||
356-
rz_ssi_is_stream_running(&ssi->capture);
361+
is_full_duplex = ssi->dup.tx_active && ssi->dup.rx_active;
357362
ssicr = rz_ssi_reg_readl(ssi, SSICR);
358363
ssifcr = rz_ssi_reg_readl(ssi, SSIFCR);
359364
if (!is_full_duplex) {
360365
ssifcr &= ~0xF;
361-
} else {
366+
} else if (ssi->dup.one_stream_triggered) {
362367
rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TEN | SSICR_REN, 0);
363368
rz_ssi_set_idle(ssi);
364369
ssifcr &= ~SSIFCR_FIFO_RST;
@@ -394,12 +399,16 @@ static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
394399
SSISR_RUIRQ), 0);
395400

396401
strm->running = 1;
397-
if (is_full_duplex)
398-
ssicr |= SSICR_TEN | SSICR_REN;
399-
else
402+
if (!is_full_duplex) {
400403
ssicr |= is_play ? SSICR_TEN : SSICR_REN;
401-
402-
rz_ssi_reg_writel(ssi, SSICR, ssicr);
404+
rz_ssi_reg_writel(ssi, SSICR, ssicr);
405+
} else if (ssi->dup.one_stream_triggered) {
406+
ssicr |= SSICR_TEN | SSICR_REN;
407+
rz_ssi_reg_writel(ssi, SSICR, ssicr);
408+
ssi->dup.one_stream_triggered = false;
409+
} else {
410+
ssi->dup.one_stream_triggered = true;
411+
}
403412

404413
return 0;
405414
}
@@ -897,6 +906,30 @@ static int rz_ssi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
897906
return 0;
898907
}
899908

909+
static int rz_ssi_startup(struct snd_pcm_substream *substream,
910+
struct snd_soc_dai *dai)
911+
{
912+
struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
913+
914+
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
915+
ssi->dup.tx_active = true;
916+
else
917+
ssi->dup.rx_active = true;
918+
919+
return 0;
920+
}
921+
922+
static void rz_ssi_shutdown(struct snd_pcm_substream *substream,
923+
struct snd_soc_dai *dai)
924+
{
925+
struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
926+
927+
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
928+
ssi->dup.tx_active = false;
929+
else
930+
ssi->dup.rx_active = false;
931+
}
932+
900933
static bool rz_ssi_is_valid_hw_params(struct rz_ssi_priv *ssi, unsigned int rate,
901934
unsigned int channels,
902935
unsigned int sample_width,
@@ -962,6 +995,8 @@ static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream,
962995
}
963996

964997
static const struct snd_soc_dai_ops rz_ssi_dai_ops = {
998+
.startup = rz_ssi_startup,
999+
.shutdown = rz_ssi_shutdown,
9651000
.trigger = rz_ssi_dai_trigger,
9661001
.set_fmt = rz_ssi_dai_set_fmt,
9671002
.hw_params = rz_ssi_dai_hw_params,

0 commit comments

Comments
 (0)