OSDN Git Service

ASoC: stm32: spdifrx: manage rebind issue
authorOlivier Moysan <olivier.moysan@st.com>
Wed, 18 Mar 2020 14:41:24 +0000 (15:41 +0100)
committerMark Brown <broonie@kernel.org>
Wed, 18 Mar 2020 19:55:25 +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 SPDFIRX driver.

Signed-off-by: Olivier Moysan <olivier.moysan@st.com>
Link: https://lore.kernel.org/r/20200318144125.9163-3-olivier.moysan@st.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/stm/stm32_spdifrx.c

index 49766af..ae7a0f4 100644 (file)
@@ -944,6 +944,22 @@ static int stm32_spdifrx_parse_of(struct platform_device *pdev,
        return 0;
 }
 
+static int stm32_spdifrx_remove(struct platform_device *pdev)
+{
+       struct stm32_spdifrx_data *spdifrx = platform_get_drvdata(pdev);
+
+       if (spdifrx->ctrl_chan)
+               dma_release_channel(spdifrx->ctrl_chan);
+
+       if (spdifrx->dmab)
+               snd_dma_free_pages(spdifrx->dmab);
+
+       snd_dmaengine_pcm_unregister(&pdev->dev);
+       snd_soc_unregister_component(&pdev->dev);
+
+       return 0;
+}
+
 static int stm32_spdifrx_probe(struct platform_device *pdev)
 {
        struct stm32_spdifrx_data *spdifrx;
@@ -995,25 +1011,27 @@ static int stm32_spdifrx_probe(struct platform_device *pdev)
        udelay(2);
        reset_control_deassert(rst);
 
-       ret = devm_snd_soc_register_component(&pdev->dev,
-                                             &stm32_spdifrx_component,
-                                             stm32_spdifrx_dai,
-                                             ARRAY_SIZE(stm32_spdifrx_dai));
-       if (ret)
-               return ret;
-
-       ret = stm32_spdifrx_dma_ctrl_register(&pdev->dev, spdifrx);
-       if (ret)
-               goto error;
-
        pcm_config = &stm32_spdifrx_pcm_config;
-       ret = devm_snd_dmaengine_pcm_register(&pdev->dev, pcm_config, 0);
+       ret = snd_dmaengine_pcm_register(&pdev->dev, pcm_config, 0);
        if (ret) {
                if (ret != -EPROBE_DEFER)
                        dev_err(&pdev->dev, "PCM DMA register error %d\n", ret);
-               goto error;
+               return ret;
        }
 
+       ret = snd_soc_register_component(&pdev->dev,
+                                        &stm32_spdifrx_component,
+                                        stm32_spdifrx_dai,
+                                        ARRAY_SIZE(stm32_spdifrx_dai));
+       if (ret) {
+               snd_dmaengine_pcm_unregister(&pdev->dev);
+               return ret;
+       }
+
+       ret = stm32_spdifrx_dma_ctrl_register(&pdev->dev, spdifrx);
+       if (ret)
+               goto error;
+
        ret = regmap_read(spdifrx->regmap, STM32_SPDIFRX_IDR, &idr);
        if (ret)
                goto error;
@@ -1029,27 +1047,11 @@ static int stm32_spdifrx_probe(struct platform_device *pdev)
        return ret;
 
 error:
-       if (!IS_ERR(spdifrx->ctrl_chan))
-               dma_release_channel(spdifrx->ctrl_chan);
-       if (spdifrx->dmab)
-               snd_dma_free_pages(spdifrx->dmab);
+       stm32_spdifrx_remove(pdev);
 
        return ret;
 }
 
-static int stm32_spdifrx_remove(struct platform_device *pdev)
-{
-       struct stm32_spdifrx_data *spdifrx = platform_get_drvdata(pdev);
-
-       if (spdifrx->ctrl_chan)
-               dma_release_channel(spdifrx->ctrl_chan);
-
-       if (spdifrx->dmab)
-               snd_dma_free_pages(spdifrx->dmab);
-
-       return 0;
-}
-
 MODULE_DEVICE_TABLE(of, stm32_spdifrx_ids);
 
 #ifdef CONFIG_PM_SLEEP