ASoC: stm32: i2s: manage rebind issue
authorOlivier Moysan <olivier.moysan@st.com>
Wed, 18 Mar 2020 14:41:25 +0000 (15:41 +0100)
committerMark Brown <broonie@kernel.org>
Wed, 18 Mar 2020 19:55:26 +0000 (19:55 +0000)
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@st.com>
Link: https://lore.kernel.org/r/20200318144125.9163-4-olivier.moysan@st.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/stm/stm32_i2s.c

index 2478405727c3785a7c5b145095b85e644f1c08d5..7c4d63c33f15b33ee71aabb61bf15d17fccd9f65 100644 (file)
@@ -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);