Hi Jiada, again
The solution looks very over-kill to me, especiallyq [3/3] patch is too much to me.
1st, can we start clock at .hw_param, instead of .prepare ? and stop it at .hw_free ?
2nd, can we keep usrcnt setup as-is ? I guess we can just avoid rsnd_ssi_master_clk_start() if ssi->rate was not 0 ? similar for rsnd_ssi_master_clk_stop()
In my quick check, I used your [1/3] patch and below. It works for me, but I don't know detail of your test case.
---------- diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index f6a7466..f26ffd1 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -286,19 +286,8 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod, if (rsnd_ssi_is_multi_slave(mod, io)) return 0;
- if (ssi->usrcnt > 0) { - if (ssi->rate != rate) { - dev_err(dev, "SSI parent/child should use same rate\n"); - return -EINVAL; - } - - if (ssi->chan != chan) { - dev_err(dev, "SSI parent/child should use same chan\n"); - return -EINVAL; - } - + if (ssi->rate) return 0; - }
if (rsnd_runtime_is_tdm_split(io)) chan = rsnd_io_converted_chan(io); @@ -349,7 +338,7 @@ static void rsnd_ssi_master_clk_stop(struct rsnd_mod *mod, if (!rsnd_ssi_can_output_clk(mod)) return;
- if (ssi->usrcnt > 1) + if (!ssi->rate) return;
ssi->cr_clk = 0; @@ -539,6 +528,17 @@ static int rsnd_ssi_hw_params(struct rsnd_mod *mod, return 0; }
+static int rsnd_ssi_hw_free(struct rsnd_mod *mod, struct rsnd_dai_stream *io, + struct snd_pcm_substream *substream) +{ + if (!rsnd_ssi_is_run_mods(mod, io)) + return 0; + + rsnd_ssi_master_clk_stop(mod, io); + + return 0; +} + static int rsnd_ssi_start(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) @@ -925,6 +925,7 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = { .pointer = rsnd_ssi_pio_pointer, .pcm_new = rsnd_ssi_pcm_new, .hw_params = rsnd_ssi_hw_params, + .hw_free = rsnd_ssi_hw_free, .prepare = rsnd_ssi_prepare, .get_status = rsnd_ssi_get_status, }; @@ -1012,6 +1013,7 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = { .pcm_new = rsnd_ssi_pcm_new, .fallback = rsnd_ssi_fallback, .hw_params = rsnd_ssi_hw_params, + .hw_free = rsnd_ssi_hw_free, .prepare = rsnd_ssi_prepare, .get_status = rsnd_ssi_get_status, }; ----------