From caff4ce8cc582a97b17d10b7c7f5fe8500323135 Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Wed, 18 Mar 2020 15:41:25 +0100 Subject: [PATCH] ASoC: stm32: i2s: manage rebind issue The commit e894efef9ac7 ("ASoC: core: add support to card rebind") allows to rebind the sound card after a rebind of one of its component. With this commit, the sound card is actually rebound, but may be no more functional. Corrections: - Call snd_dmaengine_pcm_register() before snd_soc_register_component(). - Call snd_dmaengine_pcm_unregister() and snd_soc_unregister_component() explicitly from I2S driver. Signed-off-by: Olivier Moysan Link: https://lore.kernel.org/r/20200318144125.9163-4-olivier.moysan@st.com Signed-off-by: Mark Brown --- sound/soc/stm/stm32_i2s.c | 40 ++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c index 2478405727c3..7c4d63c33f15 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c @@ -888,6 +888,14 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, return 0; } +static int stm32_i2s_remove(struct platform_device *pdev) +{ + snd_dmaengine_pcm_unregister(&pdev->dev); + snd_soc_unregister_component(&pdev->dev); + + return 0; +} + static int stm32_i2s_probe(struct platform_device *pdev) { struct stm32_i2s_data *i2s; @@ -921,47 +929,56 @@ static int stm32_i2s_probe(struct platform_device *pdev) return PTR_ERR(i2s->regmap); } - ret = devm_snd_soc_register_component(&pdev->dev, &stm32_i2s_component, - i2s->dai_drv, 1); - if (ret) - return ret; - - ret = devm_snd_dmaengine_pcm_register(&pdev->dev, - &stm32_i2s_pcm_config, 0); + ret = snd_dmaengine_pcm_register(&pdev->dev, &stm32_i2s_pcm_config, 0); if (ret) { if (ret != -EPROBE_DEFER) dev_err(&pdev->dev, "PCM DMA register error %d\n", ret); return ret; } + ret = snd_soc_register_component(&pdev->dev, &stm32_i2s_component, + i2s->dai_drv, 1); + if (ret) { + snd_dmaengine_pcm_unregister(&pdev->dev); + return ret; + } + /* Set SPI/I2S in i2s mode */ ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, I2S_CGFR_I2SMOD, I2S_CGFR_I2SMOD); if (ret) - return ret; + goto error; ret = regmap_read(i2s->regmap, STM32_I2S_IPIDR_REG, &val); if (ret) - return ret; + goto error; if (val == I2S_IPIDR_NUMBER) { ret = regmap_read(i2s->regmap, STM32_I2S_HWCFGR_REG, &val); if (ret) - return ret; + goto error; if (!FIELD_GET(I2S_HWCFGR_I2S_SUPPORT_MASK, val)) { dev_err(&pdev->dev, "Device does not support i2s mode\n"); - return -EPERM; + ret = -EPERM; + goto error; } ret = regmap_read(i2s->regmap, STM32_I2S_VERR_REG, &val); + if (ret) + goto error; dev_dbg(&pdev->dev, "I2S version: %lu.%lu registered\n", FIELD_GET(I2S_VERR_MAJ_MASK, val), FIELD_GET(I2S_VERR_MIN_MASK, val)); } + return ret; + +error: + stm32_i2s_remove(pdev); + return ret; } @@ -998,6 +1015,7 @@ static struct platform_driver stm32_i2s_driver = { .pm = &stm32_i2s_pm_ops, }, .probe = stm32_i2s_probe, + .remove = stm32_i2s_remove, }; module_platform_driver(stm32_i2s_driver);