[PATCH] ASoC: stm32: i2s: manage rebind issue

From: Olivier Moysan
Date: Wed Mar 18 2020 - 10:41:25 EST


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 <olivier.moysan@xxxxxx>
Link: https://lore.kernel.org/r/20200318144125.9163-4-olivier.moysan@xxxxxx
Signed-off-by: Mark Brown <broonie@xxxxxxxxxx>
---
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);
--
2.20.1