From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
commit 1a5658c2131 ("ASoC: rsnd: count .probe/.remove for rsnd_mod_call()") solved multi-resource-free issue, by putting .probe/.remove under count control. But,it breaks sound mixing case (if it was used under DPCM). In such case, it uses MIXn/DVCn/SSIn, and these should be always probed. This patch reverted above patch, and solved the same issue by modifing _rsnd_kctrl_remove() function.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/sh/rcar/core.c | 6 +++++- sound/soc/sh/rcar/dma.c | 11 +++++++++++ sound/soc/sh/rcar/rsnd.h | 14 +++++++------- sound/soc/sh/rcar/ssi.c | 5 ++++- 4 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index f181410..209e736 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -993,7 +993,11 @@ static int __rsnd_kctrl_new(struct rsnd_mod *mod,
void _rsnd_kctrl_remove(struct rsnd_kctrl_cfg *cfg) { - snd_ctl_remove(cfg->card, cfg->kctrl); + if (cfg->card && cfg->kctrl) + snd_ctl_remove(cfg->card, cfg->kctrl); + + cfg->card = NULL; + cfg->kctrl = NULL; }
int rsnd_kctrl_new_m(struct rsnd_mod *mod, diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index 6bc93cb..b3bdd36 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -707,6 +707,17 @@ int rsnd_dma_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod, return 0; }
+void rsnd_dma_detach(struct rsnd_mod *mod, struct rsnd_mod **dma_mod) +{ + if (*dma_mod) { + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct device *dev = rsnd_priv_to_dev(priv); + + devm_kfree(dev, *dma_mod); + *dma_mod = NULL; + } +} + int rsnd_dma_probe(struct rsnd_priv *priv) { struct platform_device *pdev = rsnd_priv_to_pdev(priv); diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index a8f61d7..901095c 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -200,6 +200,7 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io); */ int rsnd_dma_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod, struct rsnd_mod **dma_mod, int id); +void rsnd_dma_detach(struct rsnd_mod *mod, struct rsnd_mod **dma_mod); int rsnd_dma_probe(struct rsnd_priv *priv); struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node, struct rsnd_mod *mod, char *name); @@ -276,9 +277,8 @@ struct rsnd_mod { /* * status * - * 0xH0000CBA + * 0xH0000CB0 * - * A 0: probe 1: remove * B 0: init 1: quit * C 0: start 1: stop * @@ -288,19 +288,19 @@ struct rsnd_mod { * H 0: fallback * H 0: hw_params */ -#define __rsnd_mod_shift_probe 0 -#define __rsnd_mod_shift_remove 0 #define __rsnd_mod_shift_init 4 #define __rsnd_mod_shift_quit 4 #define __rsnd_mod_shift_start 8 #define __rsnd_mod_shift_stop 8 +#define __rsnd_mod_shift_probe 28 /* always called */ +#define __rsnd_mod_shift_remove 28 /* always called */ #define __rsnd_mod_shift_irq 28 /* always called */ #define __rsnd_mod_shift_pcm_new 28 /* always called */ #define __rsnd_mod_shift_fallback 28 /* always called */ #define __rsnd_mod_shift_hw_params 28 /* always called */
-#define __rsnd_mod_add_probe 1 -#define __rsnd_mod_add_remove -1 +#define __rsnd_mod_add_probe 0 +#define __rsnd_mod_add_remove 0 #define __rsnd_mod_add_init 1 #define __rsnd_mod_add_quit -1 #define __rsnd_mod_add_start 1 @@ -311,7 +311,7 @@ struct rsnd_mod { #define __rsnd_mod_add_hw_params 0
#define __rsnd_mod_call_probe 0 -#define __rsnd_mod_call_remove 1 +#define __rsnd_mod_call_remove 0 #define __rsnd_mod_call_init 0 #define __rsnd_mod_call_quit 1 #define __rsnd_mod_call_start 0 diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 6cb6db0..94a19f9 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -698,7 +698,10 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, int irq = ssi->irq;
/* PIO will request IRQ again */ - devm_free_irq(dev, irq, mod); + if (ssi->dma) + devm_free_irq(dev, irq, mod); + + rsnd_dma_detach(mod, &ssi->dma);
return 0; }