diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 56099db8f86ddf..57031b6d4d45e0 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -1462,9 +1462,16 @@ static int skl_platform_soc_probe(struct snd_soc_component *component) return 0; } +static void skl_pcm_remove(struct snd_soc_component *component) +{ + /* remove topology */ + snd_soc_tplg_component_remove(component, SND_SOC_TPLG_INDEX_ALL); +} + static const struct snd_soc_component_driver skl_component = { .name = "pcm", .probe = skl_platform_soc_probe, + .remove = skl_pcm_remove, .ops = &skl_platform_ops, .pcm_new = skl_pcm_new, .pcm_free = skl_pcm_free, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6f4842977b8d0d..75f6a8085a766f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2831,10 +2831,21 @@ EXPORT_SYMBOL_GPL(snd_soc_register_card); static void snd_soc_unbind_card(struct snd_soc_card *card, bool unregister) { + struct snd_soc_pcm_runtime *rtd; + int order; + if (card->instantiated) { card->instantiated = false; snd_soc_dapm_shutdown(card); snd_soc_flush_all_delayed_work(card); + + /* remove all components used by DAI links on this card */ + for_each_comp_order(order) { + for_each_card_rtds(card, rtd) { + soc_remove_link_components(card, rtd, order); + } + } + soc_cleanup_card_resources(card); if (!unregister) list_add(&card->list, &unbind_card_list); diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 4d3d527de7df53..b3b5ce6b04a461 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -355,9 +355,9 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) sdev->first_boot = false; /* now register audio DSP platform driver and dai */ - ret = snd_soc_register_component(sdev->dev, &sdev->plat_drv, - sof_ops(sdev)->drv, - sof_ops(sdev)->num_drv); + ret = devm_snd_soc_register_component(sdev->dev, &sdev->plat_drv, + sof_ops(sdev)->drv, + sof_ops(sdev)->num_drv); if (ret < 0) { dev_err(sdev->dev, "error: failed to register DSP DAI driver %d\n", ret); @@ -466,16 +466,16 @@ int snd_sof_device_remove(struct device *dev) if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) cancel_work_sync(&sdev->probe_work); - snd_soc_unregister_component(dev); snd_sof_fw_unload(sdev); snd_sof_ipc_free(sdev); snd_sof_free_debug(sdev); snd_sof_free_trace(sdev); snd_sof_remove(sdev); + /* - * platform_device_unregister() frees the card and its resources. - * So it should be called after unregistering the comp driver - * so that the card is valid while unregistering comp driver. + * Unregister machine driver. This will unbind the snd_card which + * will remove the component driver and unload the topology + * before freeing the snd_card. */ if (!IS_ERR_OR_NULL(pdata->pdev_mach)) platform_device_unregister(pdata->pdev_mach); diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 0cf790225cec29..4f48a8bcc1e175 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -703,6 +703,8 @@ static int sof_pcm_probe(struct snd_soc_component *component) static void sof_pcm_remove(struct snd_soc_component *component) { + /* remove topology */ + snd_soc_tplg_component_remove(component, SND_SOC_TPLG_INDEX_ALL); } void snd_sof_new_platform_drv(struct snd_sof_dev *sdev)