Commit bcb43fda authored by Pierre-Louis Bossart's avatar Pierre-Louis Bossart Committed by Mark Brown

ASoC: Intel: bdw-rt5677: fix module load/unload issues

The mainline code currently prevents modules from being removed.

The BE dailink .init() function calls devm_gpiod_get() using the codec
component device as argument. When the machine driver is removed, the
references to the gpiod are not released, and it's not possible to
remove the codec driver module - which is the only entity which could
free the gpiod.

This conceptual deadlock can be avoided by invoking gpiod_get() in the
.init() callback, and calling gpiod_put() in the exit() callback.

Tested on SAMUS Chromebook with SOF driver.
Suggested-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: default avatarGuennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Reviewed-by: default avatarCurtis Malainey <curtis@malainey.com>
Link: https://lore.kernel.org/r/20200622154241.29053-3-pierre-louis.bossart@linux.intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 21a00fb3
......@@ -272,8 +272,8 @@ static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd)
RT5677_CLK_SEL_SYS2);
/* Request rt5677 GPIO for headphone amp control */
bdw_rt5677->gpio_hp_en = devm_gpiod_get(component->dev, "headphone-enable",
GPIOD_OUT_LOW);
bdw_rt5677->gpio_hp_en = gpiod_get(component->dev, "headphone-enable",
GPIOD_OUT_LOW);
if (IS_ERR(bdw_rt5677->gpio_hp_en)) {
dev_err(component->dev, "Can't find HP_AMP_SHDN_L gpio\n");
return PTR_ERR(bdw_rt5677->gpio_hp_en);
......@@ -307,6 +307,19 @@ static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd)
return 0;
}
static void bdw_rt5677_exit(struct snd_soc_pcm_runtime *rtd)
{
struct bdw_rt5677_priv *bdw_rt5677 =
snd_soc_card_get_drvdata(rtd->card);
/*
* The .exit() can be reached without going through the .init()
* so explicitly test if the gpiod is valid
*/
if (!IS_ERR_OR_NULL(bdw_rt5677->gpio_hp_en))
gpiod_put(bdw_rt5677->gpio_hp_en);
}
/* broadwell digital audio interface glue - connects codec <--> CPU */
SND_SOC_DAILINK_DEF(dummy,
DAILINK_COMP_ARRAY(COMP_DUMMY()));
......@@ -372,6 +385,7 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = {
.dpcm_playback = 1,
.dpcm_capture = 1,
.init = bdw_rt5677_init,
.exit = bdw_rt5677_exit,
#if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL)
SND_SOC_DAILINK_REG(dummy, be, dummy),
#else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment