Skip to content

Commit

Permalink
ASoC: rsnd: control SSICR::EN correctly
Browse files Browse the repository at this point in the history
In case of SSI0 playback, SSI1 capture, SSI0 might be shared for
clock output if clock master mode.

Current rsnd driver had been assumed that SSI clock contiguous
output which is needed for SSI parent needs SSICR::EN (SSI module
enable) bit.
But, this bit controls data input/output, not for clock.
Clock contiguous output needs SSICR : FORCE, SCKD, SWSD,
and SSIWSR : CONT. Not SSICR : EN.

Because of this wrong assumption, and insufficient control, on current
code, for example, if it starts SSI0(playback) -> SSI1(capture) order,
SSI0 SSICR::EN bit will temporarily be 0.
It causes playback side underrun error. This is bug.
We can reproduce this issue with SSI+SRC (without DVC), and capture
during playback operation.

This patch fixup current (wrong) assumption, and control SSICR::EN bit
correctly.

Reported-by: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx@renesas.com>
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Tested-by: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
morimoto authored and broonie committed Aug 8, 2017
1 parent e3c6de4 commit 597b046
Showing 1 changed file with 31 additions and 9 deletions.
40 changes: 31 additions & 9 deletions sound/soc/sh/rcar/ssi.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ struct rsnd_ssi {
u32 cr_own;
u32 cr_clk;
u32 cr_mode;
u32 cr_en;
u32 wsr;
int chan;
int rate;
Expand Down Expand Up @@ -291,6 +292,16 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
if (ret < 0)
return ret;

/*
* SSI clock will be output contiguously
* by below settings.
* This means, rsnd_ssi_master_clk_start()
* and rsnd_ssi_register_setup() are necessary
* for SSI parent
*
* SSICR : FORCE, SCKD, SWSD
* SSIWSR : CONT
*/
ssi->cr_clk = FORCE | SWL_32 | SCKD | SWSD | CKDV(idx);
ssi->wsr = CONT;
ssi->rate = rate;
Expand Down Expand Up @@ -393,7 +404,8 @@ static void rsnd_ssi_register_setup(struct rsnd_mod *mod)
rsnd_mod_write(mod, SSIWSR, ssi->wsr);
rsnd_mod_write(mod, SSICR, ssi->cr_own |
ssi->cr_clk |
ssi->cr_mode); /* without EN */
ssi->cr_mode |
ssi->cr_en);
}

static void rsnd_ssi_pointer_init(struct rsnd_mod *mod,
Expand Down Expand Up @@ -544,6 +556,8 @@ static int rsnd_ssi_start(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct rsnd_priv *priv)
{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);

if (!rsnd_ssi_is_run_mods(mod, io))
return 0;

Expand All @@ -554,7 +568,19 @@ static int rsnd_ssi_start(struct rsnd_mod *mod,
if (rsnd_ssi_multi_slaves_runtime(io))
return 0;

rsnd_mod_bset(mod, SSICR, EN, EN);
/*
* EN is for data output.
* SSI parent EN is not needed.
*/
if (rsnd_ssi_is_parent(mod, io))
return 0;

ssi->cr_en = EN;

rsnd_mod_write(mod, SSICR, ssi->cr_own |
ssi->cr_clk |
ssi->cr_mode |
ssi->cr_en);

return 0;
}
Expand All @@ -569,13 +595,7 @@ static int rsnd_ssi_stop(struct rsnd_mod *mod,
if (!rsnd_ssi_is_run_mods(mod, io))
return 0;

/*
* don't stop if not last user
* see also
* rsnd_ssi_start
* rsnd_ssi_interrupt
*/
if (ssi->usrcnt > 1)
if (rsnd_ssi_is_parent(mod, io))
return 0;

/*
Expand All @@ -595,6 +615,8 @@ static int rsnd_ssi_stop(struct rsnd_mod *mod,
rsnd_mod_write(mod, SSICR, cr); /* disabled all */
rsnd_ssi_status_check(mod, IIRQ);

ssi->cr_en = 0;

return 0;
}

Expand Down

0 comments on commit 597b046

Please sign in to comment.