Skip to content

Commit 597b046

Browse files
morimotobroonie
authored andcommitted
ASoC: rsnd: control SSICR::EN correctly
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 <[email protected]> Signed-off-by: Kuninori Morimoto <[email protected]> Tested-by: Hiroyuki Yokoyama <[email protected]> Signed-off-by: Mark Brown <[email protected]>
1 parent e3c6de4 commit 597b046

File tree

1 file changed

+31
-9
lines changed

1 file changed

+31
-9
lines changed

sound/soc/sh/rcar/ssi.c

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ struct rsnd_ssi {
7272
u32 cr_own;
7373
u32 cr_clk;
7474
u32 cr_mode;
75+
u32 cr_en;
7576
u32 wsr;
7677
int chan;
7778
int rate;
@@ -291,6 +292,16 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
291292
if (ret < 0)
292293
return ret;
293294

295+
/*
296+
* SSI clock will be output contiguously
297+
* by below settings.
298+
* This means, rsnd_ssi_master_clk_start()
299+
* and rsnd_ssi_register_setup() are necessary
300+
* for SSI parent
301+
*
302+
* SSICR : FORCE, SCKD, SWSD
303+
* SSIWSR : CONT
304+
*/
294305
ssi->cr_clk = FORCE | SWL_32 | SCKD | SWSD | CKDV(idx);
295306
ssi->wsr = CONT;
296307
ssi->rate = rate;
@@ -393,7 +404,8 @@ static void rsnd_ssi_register_setup(struct rsnd_mod *mod)
393404
rsnd_mod_write(mod, SSIWSR, ssi->wsr);
394405
rsnd_mod_write(mod, SSICR, ssi->cr_own |
395406
ssi->cr_clk |
396-
ssi->cr_mode); /* without EN */
407+
ssi->cr_mode |
408+
ssi->cr_en);
397409
}
398410

399411
static void rsnd_ssi_pointer_init(struct rsnd_mod *mod,
@@ -544,6 +556,8 @@ static int rsnd_ssi_start(struct rsnd_mod *mod,
544556
struct rsnd_dai_stream *io,
545557
struct rsnd_priv *priv)
546558
{
559+
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
560+
547561
if (!rsnd_ssi_is_run_mods(mod, io))
548562
return 0;
549563

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

557-
rsnd_mod_bset(mod, SSICR, EN, EN);
571+
/*
572+
* EN is for data output.
573+
* SSI parent EN is not needed.
574+
*/
575+
if (rsnd_ssi_is_parent(mod, io))
576+
return 0;
577+
578+
ssi->cr_en = EN;
579+
580+
rsnd_mod_write(mod, SSICR, ssi->cr_own |
581+
ssi->cr_clk |
582+
ssi->cr_mode |
583+
ssi->cr_en);
558584

559585
return 0;
560586
}
@@ -569,13 +595,7 @@ static int rsnd_ssi_stop(struct rsnd_mod *mod,
569595
if (!rsnd_ssi_is_run_mods(mod, io))
570596
return 0;
571597

572-
/*
573-
* don't stop if not last user
574-
* see also
575-
* rsnd_ssi_start
576-
* rsnd_ssi_interrupt
577-
*/
578-
if (ssi->usrcnt > 1)
598+
if (rsnd_ssi_is_parent(mod, io))
579599
return 0;
580600

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

618+
ssi->cr_en = 0;
619+
598620
return 0;
599621
}
600622

0 commit comments

Comments
 (0)