From: Kuninori Morimoto Date: Thu, 10 Aug 2017 00:07:38 +0000 (+0000) Subject: ASoC: rsnd: call request_irq/free_irq once in MIX case X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=b6e58fcacb3edc6245ecf700207ba675cba18018;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git ASoC: rsnd: call request_irq/free_irq once in MIX case Each module's dai callback function availability is controlled by mod->status. For example "always called", "call once". In .probe/.remove case, it needs to be called always, because .probe will call xxx_attach() function on .probe, especially if platform is using MIXer. For example, below case, MIX0/DVC0/SSI0 needs to be called twice. playback = <&src0 &ctu02 &mix0 &dvc0 &ssi0>; playback = <&src2 &ctu03 &mix0 &dvc0 &ssi0>; But in this case, SSI0 will call request_irq() twice. This patch add new RSND_SSI_PROBED flag and control it Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index ca9355b86bd9..8bb47144660b 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -90,6 +90,7 @@ struct rsnd_ssi { #define RSND_SSI_NO_BUSIF (1 << 1) /* SSI+DMA without BUSIF */ #define RSND_SSI_HDMI0 (1 << 2) /* for HDMI0 */ #define RSND_SSI_HDMI1 (1 << 3) /* for HDMI1 */ +#define RSND_SSI_PROBED (1 << 4) #define for_each_rsnd_ssi(pos, priv, i) \ for (i = 0; \ @@ -103,6 +104,7 @@ struct rsnd_ssi { #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod) #define rsnd_ssi_flags_has(p, f) ((p)->flags & f) #define rsnd_ssi_flags_set(p, f) ((p)->flags |= f) +#define rsnd_ssi_flags_del(p, f) ((p)->flags = ((p)->flags & ~f)) #define rsnd_ssi_is_parent(ssi, io) ((ssi) == rsnd_io_to_mod_ssip(io)) #define rsnd_ssi_is_multi_slave(mod, io) \ (rsnd_ssi_multi_slaves(io) & (1 << rsnd_mod_id(mod))) @@ -784,11 +786,22 @@ static int rsnd_ssi_common_probe(struct rsnd_mod *mod, /* * SSI might be called again as PIO fallback * It is easy to manual handling for IRQ request/free + * + * OTOH, this function might be called many times if platform is + * using MIX. It needs xxx_attach() many times on xxx_probe(). + * Because of it, we can't control .probe/.remove calling count by + * mod->status. + * But it don't need to call request_irq() many times. + * Let's control it by RSND_SSI_PROBED flag. */ - ret = request_irq(ssi->irq, - rsnd_ssi_interrupt, - IRQF_SHARED, - dev_name(dev), mod); + if (!rsnd_ssi_flags_has(ssi, RSND_SSI_PROBED)) { + ret = request_irq(ssi->irq, + rsnd_ssi_interrupt, + IRQF_SHARED, + dev_name(dev), mod); + + rsnd_ssi_flags_set(ssi, RSND_SSI_PROBED); + } return ret; } @@ -805,7 +818,11 @@ static int rsnd_ssi_common_remove(struct rsnd_mod *mod, return 0; /* PIO will request IRQ again */ - free_irq(ssi->irq, mod); + if (rsnd_ssi_flags_has(ssi, RSND_SSI_PROBED)) { + free_irq(ssi->irq, mod); + + rsnd_ssi_flags_del(ssi, RSND_SSI_PROBED); + } return 0; }