[alsa-devel] [PATCH v2 0/5] ASoC: core: add support to card re-bind using component framework
During discussion regarding card re-binding when components unregister and register back at https://lkml.org/lkml/2018/7/9/785 it was suggested that component framework can be added into core to provide this feature.
With this new changes the card will re-bind once the dependent component re-registers after unregistering. This works based on the match done from component name using component framework.
I have tested this patch with qdsp start-stop and module-load-unload usecase for more than 10000 times in loop on Qcom platforms.
Thanks, srini
Changes since v1: - Added new flag to enable/disable auto bind at card level, It is useful if machine driver/module is really removed/unloaded. Also to help cleanup the master component. Without this we will endup with a memory leak if the machine driver and memory associated with card are removed. - removed unregister from unbind callback. - updated match function as suggested by Vinod. - Added qdsp6 cleanup patches to this series.
Srinivas Kandagatla (5): ASoC: core: add support to card re-bind using component framework ASoC: qdsp6: q6afe-dai: remove component fw related code ASoC: qdsp6: q6asm-dai: remove component framework related code ASoC: qdsp6: q6routing: remove component framework related code ASoC: qcom: apq8096: remove component framework related code
include/sound/soc.h | 7 ++++ sound/soc/qcom/apq8096.c | 75 ++++------------------------------------ sound/soc/qcom/qdsp6/q6afe-dai.c | 34 +++--------------- sound/soc/qcom/qdsp6/q6asm-dai.c | 35 +++---------------- sound/soc/qcom/qdsp6/q6routing.c | 32 ++++------------- sound/soc/soc-core.c | 62 +++++++++++++++++++++++++++++++++ 6 files changed, 89 insertions(+), 156 deletions(-)
This patch aims at achieving dynamic behaviour of audio card when the dependent components disappear and reappear.
With this patch the card is removed if any of the dependent component is removed and card is added back if the dependent component comes back. All this is done using component framework and matching based on component name.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- include/sound/soc.h | 7 ++++++ sound/soc/soc-core.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+)
diff --git a/include/sound/soc.h b/include/sound/soc.h index a4915148f739..a23ecdf3eff1 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -17,6 +17,7 @@ #include <linux/workqueue.h> #include <linux/interrupt.h> #include <linux/kernel.h> +#include <linux/component.h> #include <linux/regmap.h> #include <linux/log2.h> #include <sound/core.h> @@ -1090,6 +1091,12 @@ struct snd_soc_card {
struct work_struct deferred_resume_work;
+ /* component framework related */ + bool components_added; + /* set in machine driver to enable/disable auto re-binding */ + bool auto_bind; + struct component_match *match; + /* lists of probed devices belonging to this card */ struct list_head component_dev_list;
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6d33634b934b..65d11c13117f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -279,11 +279,28 @@ static inline void snd_soc_debugfs_exit(void)
#endif
+static int snd_soc_card_comp_compare(struct device *dev, void *data) +{ + struct snd_soc_component *component; + + lockdep_assert_held(&client_mutex); + list_for_each_entry(component, &component_list, list) { + if (dev == component->dev) { + if (!strcmp(component->name, data)) + return 1; + break; + } + } + + return 0; +} + static int snd_soc_rtdcom_add(struct snd_soc_pcm_runtime *rtd, struct snd_soc_component *component) { struct snd_soc_rtdcom_list *rtdcom; struct snd_soc_rtdcom_list *new_rtdcom; + char *cname;
for_each_rtdcom(rtd, rtdcom) { /* already connected */ @@ -300,6 +317,13 @@ static int snd_soc_rtdcom_add(struct snd_soc_pcm_runtime *rtd,
list_add_tail(&new_rtdcom->list, &rtd->component_list);
+ if (rtd->card->auto_bind && !rtd->card->components_added) { + cname = devm_kasprintf(rtd->card->dev, GFP_KERNEL, + "%s", component->name); + component_match_add(rtd->card->dev, &rtd->card->match, + snd_soc_card_comp_compare, cname); + } + return 0; }
@@ -835,6 +859,25 @@ static bool soc_is_dai_link_bound(struct snd_soc_card *card, return false; }
+static int snd_soc_card_comp_bind(struct device *dev) +{ + struct snd_soc_card *card = dev_get_drvdata(dev); + + if (card->instantiated) + return 0; + + return snd_soc_register_card(card); +} + +static void snd_soc_card_comp_unbind(struct device *dev) +{ +} + +static const struct component_master_ops snd_soc_card_comp_ops = { + .bind = snd_soc_card_comp_bind, + .unbind = snd_soc_card_comp_unbind, +}; + static int soc_bind_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) { @@ -2108,6 +2151,12 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
card->instantiated = 1; snd_soc_dapm_sync(&card->dapm); + if (card->auto_bind && !card->components_added) { + component_master_add_with_match(card->dev, + &snd_soc_card_comp_ops, + card->match); + card->components_added = true; + } mutex_unlock(&card->mutex); mutex_unlock(&client_mutex);
@@ -2757,6 +2806,9 @@ int snd_soc_unregister_card(struct snd_soc_card *card) dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name); }
+ if (!card->auto_bind && card->components_added) + component_master_del(card->dev, &snd_soc_card_comp_ops); + return 0; } EXPORT_SYMBOL_GPL(snd_soc_unregister_card); @@ -3169,8 +3221,17 @@ int snd_soc_add_component(struct device *dev,
snd_soc_component_add(component);
+ ret = component_add(dev, NULL); + if (ret < 0) { + dev_err(dev, "ASoC: Failed to add Component: %d\n", ret); + goto err_comp; + } + return 0;
+err_comp: + soc_remove_component(component); + snd_soc_unregister_dais(component); err_cleanup: snd_soc_component_cleanup(component); err_free: @@ -3218,6 +3279,7 @@ static int __snd_soc_unregister_component(struct device *dev) mutex_unlock(&client_mutex);
if (found) { + component_del(dev, NULL); snd_soc_component_cleanup(component); }
The patch
ASoC: core: add support to card re-bind using component framework
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From bb4b894addb09a069c072a0a032f644cc470d17f Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla srinivas.kandagatla@linaro.org Date: Fri, 13 Jul 2018 16:36:28 +0100 Subject: [PATCH] ASoC: core: add support to card re-bind using component framework
This patch aims at achieving dynamic behaviour of audio card when the dependent components disappear and reappear.
With this patch the card is removed if any of the dependent component is removed and card is added back if the dependent component comes back. All this is done using component framework and matching based on component name.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Reviewed-by: Vinod Koul vkoul@kernel.org Signed-off-by: Mark Brown broonie@kernel.org --- include/sound/soc.h | 7 +++++ sound/soc/soc-core.c | 62 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+)
diff --git a/include/sound/soc.h b/include/sound/soc.h index a4915148f739..a23ecdf3eff1 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -17,6 +17,7 @@ #include <linux/workqueue.h> #include <linux/interrupt.h> #include <linux/kernel.h> +#include <linux/component.h> #include <linux/regmap.h> #include <linux/log2.h> #include <sound/core.h> @@ -1090,6 +1091,12 @@ struct snd_soc_card {
struct work_struct deferred_resume_work;
+ /* component framework related */ + bool components_added; + /* set in machine driver to enable/disable auto re-binding */ + bool auto_bind; + struct component_match *match; + /* lists of probed devices belonging to this card */ struct list_head component_dev_list;
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 3be0310d5c81..08e189485009 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -279,11 +279,28 @@ static inline void snd_soc_debugfs_exit(void)
#endif
+static int snd_soc_card_comp_compare(struct device *dev, void *data) +{ + struct snd_soc_component *component; + + lockdep_assert_held(&client_mutex); + list_for_each_entry(component, &component_list, list) { + if (dev == component->dev) { + if (!strcmp(component->name, data)) + return 1; + break; + } + } + + return 0; +} + static int snd_soc_rtdcom_add(struct snd_soc_pcm_runtime *rtd, struct snd_soc_component *component) { struct snd_soc_rtdcom_list *rtdcom; struct snd_soc_rtdcom_list *new_rtdcom; + char *cname;
for_each_rtdcom(rtd, rtdcom) { /* already connected */ @@ -300,6 +317,13 @@ static int snd_soc_rtdcom_add(struct snd_soc_pcm_runtime *rtd,
list_add_tail(&new_rtdcom->list, &rtd->component_list);
+ if (rtd->card->auto_bind && !rtd->card->components_added) { + cname = devm_kasprintf(rtd->card->dev, GFP_KERNEL, + "%s", component->name); + component_match_add(rtd->card->dev, &rtd->card->match, + snd_soc_card_comp_compare, cname); + } + return 0; }
@@ -835,6 +859,25 @@ static bool soc_is_dai_link_bound(struct snd_soc_card *card, return false; }
+static int snd_soc_card_comp_bind(struct device *dev) +{ + struct snd_soc_card *card = dev_get_drvdata(dev); + + if (card->instantiated) + return 0; + + return snd_soc_register_card(card); +} + +static void snd_soc_card_comp_unbind(struct device *dev) +{ +} + +static const struct component_master_ops snd_soc_card_comp_ops = { + .bind = snd_soc_card_comp_bind, + .unbind = snd_soc_card_comp_unbind, +}; + static int soc_bind_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) { @@ -2126,6 +2169,12 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
card->instantiated = 1; snd_soc_dapm_sync(&card->dapm); + if (card->auto_bind && !card->components_added) { + component_master_add_with_match(card->dev, + &snd_soc_card_comp_ops, + card->match); + card->components_added = true; + } mutex_unlock(&card->mutex); mutex_unlock(&client_mutex);
@@ -2749,6 +2798,9 @@ int snd_soc_unregister_card(struct snd_soc_card *card) dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name); }
+ if (!card->auto_bind && card->components_added) + component_master_del(card->dev, &snd_soc_card_comp_ops); + return 0; } EXPORT_SYMBOL_GPL(snd_soc_unregister_card); @@ -3161,8 +3213,17 @@ int snd_soc_add_component(struct device *dev,
snd_soc_component_add(component);
+ ret = component_add(dev, NULL); + if (ret < 0) { + dev_err(dev, "ASoC: Failed to add Component: %d\n", ret); + goto err_comp; + } + return 0;
+err_comp: + soc_remove_component(component); + snd_soc_unregister_dais(component); err_cleanup: snd_soc_component_cleanup(component); err_free: @@ -3210,6 +3271,7 @@ static int __snd_soc_unregister_component(struct device *dev) mutex_unlock(&client_mutex);
if (found) { + component_del(dev, NULL); snd_soc_component_cleanup(component); }
Now that the component framework is integrated into the ASoC core, remove any redundant code in this driver.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- sound/soc/qcom/qdsp6/q6afe-dai.c | 34 ++++------------------------------ 1 file changed, 4 insertions(+), 30 deletions(-)
diff --git a/sound/soc/qcom/qdsp6/q6afe-dai.c b/sound/soc/qcom/qdsp6/q6afe-dai.c index 24d1ffc3e5db..3081464befc7 100644 --- a/sound/soc/qcom/qdsp6/q6afe-dai.c +++ b/sound/soc/qcom/qdsp6/q6afe-dai.c @@ -4,7 +4,6 @@
#include <linux/err.h> #include <linux/init.h> -#include <linux/component.h> #include <linux/module.h> #include <linux/device.h> #include <linux/platform_device.h> @@ -1405,11 +1404,12 @@ static void of_q6afe_parse_dai_data(struct device *dev, } }
-static int q6afe_dai_bind(struct device *dev, struct device *master, void *data) +static int q6afe_dai_dev_probe(struct platform_device *pdev) { struct q6afe_dai_data *dai_data; + struct device *dev = &pdev->dev;
- dai_data = kzalloc(sizeof(*dai_data), GFP_KERNEL); + dai_data = devm_kzalloc(dev, sizeof(*dai_data), GFP_KERNEL); if (!dai_data) return -ENOMEM;
@@ -1417,35 +1417,10 @@ static int q6afe_dai_bind(struct device *dev, struct device *master, void *data)
of_q6afe_parse_dai_data(dev, dai_data);
- return snd_soc_register_component(dev, &q6afe_dai_component, + return devm_snd_soc_register_component(dev, &q6afe_dai_component, q6afe_dais, ARRAY_SIZE(q6afe_dais)); }
-static void q6afe_dai_unbind(struct device *dev, struct device *master, - void *data) -{ - struct q6afe_dai_data *dai_data = dev_get_drvdata(dev); - - snd_soc_unregister_component(dev); - kfree(dai_data); -} - -static const struct component_ops q6afe_dai_comp_ops = { - .bind = q6afe_dai_bind, - .unbind = q6afe_dai_unbind, -}; - -static int q6afe_dai_dev_probe(struct platform_device *pdev) -{ - return component_add(&pdev->dev, &q6afe_dai_comp_ops); -} - -static int q6afe_dai_dev_remove(struct platform_device *pdev) -{ - component_del(&pdev->dev, &q6afe_dai_comp_ops); - return 0; -} - static const struct of_device_id q6afe_dai_device_id[] = { { .compatible = "qcom,q6afe-dais" }, {}, @@ -1458,7 +1433,6 @@ static struct platform_driver q6afe_dai_platform_driver = { .of_match_table = of_match_ptr(q6afe_dai_device_id), }, .probe = q6afe_dai_dev_probe, - .remove = q6afe_dai_dev_remove, }; module_platform_driver(q6afe_dai_platform_driver);
The patch
ASoC: qdsp6: q6afe-dai: remove component fw related code
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 605fcb69918528e1a448cba4d358cbd8ed532146 Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla srinivas.kandagatla@linaro.org Date: Fri, 13 Jul 2018 16:36:29 +0100 Subject: [PATCH] ASoC: qdsp6: q6afe-dai: remove component fw related code
Now that the component framework is integrated into the ASoC core, remove any redundant code in this driver.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Reviewed-by: Vinod Koul vkoul@kernel.org Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/qcom/qdsp6/q6afe-dai.c | 34 ++++---------------------------- 1 file changed, 4 insertions(+), 30 deletions(-)
diff --git a/sound/soc/qcom/qdsp6/q6afe-dai.c b/sound/soc/qcom/qdsp6/q6afe-dai.c index 074582afda85..e988692a3ced 100644 --- a/sound/soc/qcom/qdsp6/q6afe-dai.c +++ b/sound/soc/qcom/qdsp6/q6afe-dai.c @@ -4,7 +4,6 @@
#include <linux/err.h> #include <linux/init.h> -#include <linux/component.h> #include <linux/module.h> #include <linux/device.h> #include <linux/platform_device.h> @@ -1395,11 +1394,12 @@ static void of_q6afe_parse_dai_data(struct device *dev, } }
-static int q6afe_dai_bind(struct device *dev, struct device *master, void *data) +static int q6afe_dai_dev_probe(struct platform_device *pdev) { struct q6afe_dai_data *dai_data; + struct device *dev = &pdev->dev;
- dai_data = kzalloc(sizeof(*dai_data), GFP_KERNEL); + dai_data = devm_kzalloc(dev, sizeof(*dai_data), GFP_KERNEL); if (!dai_data) return -ENOMEM;
@@ -1407,35 +1407,10 @@ static int q6afe_dai_bind(struct device *dev, struct device *master, void *data)
of_q6afe_parse_dai_data(dev, dai_data);
- return snd_soc_register_component(dev, &q6afe_dai_component, + return devm_snd_soc_register_component(dev, &q6afe_dai_component, q6afe_dais, ARRAY_SIZE(q6afe_dais)); }
-static void q6afe_dai_unbind(struct device *dev, struct device *master, - void *data) -{ - struct q6afe_dai_data *dai_data = dev_get_drvdata(dev); - - snd_soc_unregister_component(dev); - kfree(dai_data); -} - -static const struct component_ops q6afe_dai_comp_ops = { - .bind = q6afe_dai_bind, - .unbind = q6afe_dai_unbind, -}; - -static int q6afe_dai_dev_probe(struct platform_device *pdev) -{ - return component_add(&pdev->dev, &q6afe_dai_comp_ops); -} - -static int q6afe_dai_dev_remove(struct platform_device *pdev) -{ - component_del(&pdev->dev, &q6afe_dai_comp_ops); - return 0; -} - static const struct of_device_id q6afe_dai_device_id[] = { { .compatible = "qcom,q6afe-dais" }, {}, @@ -1448,7 +1423,6 @@ static struct platform_driver q6afe_dai_platform_driver = { .of_match_table = of_match_ptr(q6afe_dai_device_id), }, .probe = q6afe_dai_dev_probe, - .remove = q6afe_dai_dev_remove, }; module_platform_driver(q6afe_dai_platform_driver);
Now that the component framework is integrated into the ASoC core, remove any redundant code in this driver.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- sound/soc/qcom/qdsp6/q6asm-dai.c | 35 ++++------------------------------- 1 file changed, 4 insertions(+), 31 deletions(-)
diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index 199d0fb6f90a..9db9a2944ef2 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -7,7 +7,6 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/slab.h> -#include <linux/component.h> #include <sound/soc.h> #include <sound/soc.h> #include <sound/soc-dapm.h> @@ -563,14 +562,15 @@ static struct snd_soc_dai_driver q6asm_fe_dais[] = { Q6ASM_FEDAI_DRIVER(8), };
-static int q6asm_dai_bind(struct device *dev, struct device *master, void *data) +static int q6asm_dai_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct device_node *node = dev->of_node; struct of_phandle_args args; struct q6asm_dai_data *pdata; int rc;
- pdata = kzalloc(sizeof(struct q6asm_dai_data), GFP_KERNEL); + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM;
@@ -582,36 +582,10 @@ static int q6asm_dai_bind(struct device *dev, struct device *master, void *data)
dev_set_drvdata(dev, pdata);
- return snd_soc_register_component(dev, &q6asm_fe_dai_component, + return devm_snd_soc_register_component(dev, &q6asm_fe_dai_component, q6asm_fe_dais, ARRAY_SIZE(q6asm_fe_dais)); } -static void q6asm_dai_unbind(struct device *dev, struct device *master, - void *data) -{ - struct q6asm_dai_data *pdata = dev_get_drvdata(dev); - - snd_soc_unregister_component(dev); - - kfree(pdata); - -} - -static const struct component_ops q6asm_dai_comp_ops = { - .bind = q6asm_dai_bind, - .unbind = q6asm_dai_unbind, -}; - -static int q6asm_dai_probe(struct platform_device *pdev) -{ - return component_add(&pdev->dev, &q6asm_dai_comp_ops); -} - -static int q6asm_dai_dev_remove(struct platform_device *pdev) -{ - component_del(&pdev->dev, &q6asm_dai_comp_ops); - return 0; -}
static const struct of_device_id q6asm_dai_device_id[] = { { .compatible = "qcom,q6asm-dais" }, @@ -625,7 +599,6 @@ static struct platform_driver q6asm_dai_platform_driver = { .of_match_table = of_match_ptr(q6asm_dai_device_id), }, .probe = q6asm_dai_probe, - .remove = q6asm_dai_dev_remove, }; module_platform_driver(q6asm_dai_platform_driver);
The patch
ASoC: qdsp6: q6asm-dai: remove component framework related code
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From f924e4fd89659908107a5529f02c21edb4770dba Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla srinivas.kandagatla@linaro.org Date: Fri, 13 Jul 2018 16:36:30 +0100 Subject: [PATCH] ASoC: qdsp6: q6asm-dai: remove component framework related code
Now that the component framework is integrated into the ASoC core, remove any redundant code in this driver.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Reviewed-by: Vinod Koul vkoul@kernel.org Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/qcom/qdsp6/q6asm-dai.c | 35 ++++---------------------------- 1 file changed, 4 insertions(+), 31 deletions(-)
diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index 1196dc7483d2..acf96c6549fc 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -7,7 +7,6 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/slab.h> -#include <linux/component.h> #include <sound/soc.h> #include <sound/soc.h> #include <sound/soc-dapm.h> @@ -561,14 +560,15 @@ static struct snd_soc_dai_driver q6asm_fe_dais[] = { Q6ASM_FEDAI_DRIVER(8), };
-static int q6asm_dai_bind(struct device *dev, struct device *master, void *data) +static int q6asm_dai_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct device_node *node = dev->of_node; struct of_phandle_args args; struct q6asm_dai_data *pdata; int rc;
- pdata = kzalloc(sizeof(struct q6asm_dai_data), GFP_KERNEL); + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM;
@@ -580,36 +580,10 @@ static int q6asm_dai_bind(struct device *dev, struct device *master, void *data)
dev_set_drvdata(dev, pdata);
- return snd_soc_register_component(dev, &q6asm_fe_dai_component, + return devm_snd_soc_register_component(dev, &q6asm_fe_dai_component, q6asm_fe_dais, ARRAY_SIZE(q6asm_fe_dais)); } -static void q6asm_dai_unbind(struct device *dev, struct device *master, - void *data) -{ - struct q6asm_dai_data *pdata = dev_get_drvdata(dev); - - snd_soc_unregister_component(dev); - - kfree(pdata); - -} - -static const struct component_ops q6asm_dai_comp_ops = { - .bind = q6asm_dai_bind, - .unbind = q6asm_dai_unbind, -}; - -static int q6asm_dai_probe(struct platform_device *pdev) -{ - return component_add(&pdev->dev, &q6asm_dai_comp_ops); -} - -static int q6asm_dai_dev_remove(struct platform_device *pdev) -{ - component_del(&pdev->dev, &q6asm_dai_comp_ops); - return 0; -}
static const struct of_device_id q6asm_dai_device_id[] = { { .compatible = "qcom,q6asm-dais" }, @@ -623,7 +597,6 @@ static struct platform_driver q6asm_dai_platform_driver = { .of_match_table = of_match_ptr(q6asm_dai_device_id), }, .probe = q6asm_dai_probe, - .remove = q6asm_dai_dev_remove, }; module_platform_driver(q6asm_dai_platform_driver);
Now that the component framework is integrated into the ASoC core, remove any redundant code in this driver.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- sound/soc/qcom/qdsp6/q6routing.c | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-)
diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c index 35269b492761..1d33b00e5b44 100644 --- a/sound/soc/qcom/qdsp6/q6routing.c +++ b/sound/soc/qcom/qdsp6/q6routing.c @@ -8,7 +8,6 @@ #include <linux/platform_device.h> #include <linux/of_platform.h> #include <linux/bitops.h> -#include <linux/component.h> #include <linux/mutex.h> #include <linux/of_device.h> #include <linux/slab.h> @@ -977,9 +976,10 @@ static const struct snd_soc_component_driver msm_soc_routing_component = { .num_dapm_routes = ARRAY_SIZE(intercon), };
-static int q6routing_dai_bind(struct device *dev, struct device *master, - void *data) +static int q6pcm_routing_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; + routing_data = kzalloc(sizeof(*routing_data), GFP_KERNEL); if (!routing_data) return -ENOMEM; @@ -989,35 +989,15 @@ static int q6routing_dai_bind(struct device *dev, struct device *master, mutex_init(&routing_data->lock); dev_set_drvdata(dev, routing_data);
- return snd_soc_register_component(dev, &msm_soc_routing_component, + return devm_snd_soc_register_component(dev, &msm_soc_routing_component, NULL, 0); }
-static void q6routing_dai_unbind(struct device *dev, struct device *master, - void *d) +static int q6pcm_routing_remove(struct platform_device *pdev) { - struct msm_routing_data *data = dev_get_drvdata(dev); - - snd_soc_unregister_component(dev); - - kfree(data); - + kfree(routing_data); routing_data = NULL; -}
-static const struct component_ops q6routing_dai_comp_ops = { - .bind = q6routing_dai_bind, - .unbind = q6routing_dai_unbind, -}; - -static int q6pcm_routing_probe(struct platform_device *pdev) -{ - return component_add(&pdev->dev, &q6routing_dai_comp_ops); -} - -static int q6pcm_routing_remove(struct platform_device *pdev) -{ - component_del(&pdev->dev, &q6routing_dai_comp_ops); return 0; }
The patch
ASoC: qdsp6: q6routing: remove component framework related code
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 791940779d651c2219e97702d2245b5420b0c8ae Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla srinivas.kandagatla@linaro.org Date: Fri, 13 Jul 2018 16:36:31 +0100 Subject: [PATCH] ASoC: qdsp6: q6routing: remove component framework related code
Now that the component framework is integrated into the ASoC core, remove any redundant code in this driver.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Reviewed-by: Vinod Koul vkoul@kernel.org Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/qcom/qdsp6/q6routing.c | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-)
diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c index 35269b492761..1d33b00e5b44 100644 --- a/sound/soc/qcom/qdsp6/q6routing.c +++ b/sound/soc/qcom/qdsp6/q6routing.c @@ -8,7 +8,6 @@ #include <linux/platform_device.h> #include <linux/of_platform.h> #include <linux/bitops.h> -#include <linux/component.h> #include <linux/mutex.h> #include <linux/of_device.h> #include <linux/slab.h> @@ -977,9 +976,10 @@ static const struct snd_soc_component_driver msm_soc_routing_component = { .num_dapm_routes = ARRAY_SIZE(intercon), };
-static int q6routing_dai_bind(struct device *dev, struct device *master, - void *data) +static int q6pcm_routing_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; + routing_data = kzalloc(sizeof(*routing_data), GFP_KERNEL); if (!routing_data) return -ENOMEM; @@ -989,35 +989,15 @@ static int q6routing_dai_bind(struct device *dev, struct device *master, mutex_init(&routing_data->lock); dev_set_drvdata(dev, routing_data);
- return snd_soc_register_component(dev, &msm_soc_routing_component, + return devm_snd_soc_register_component(dev, &msm_soc_routing_component, NULL, 0); }
-static void q6routing_dai_unbind(struct device *dev, struct device *master, - void *d) +static int q6pcm_routing_remove(struct platform_device *pdev) { - struct msm_routing_data *data = dev_get_drvdata(dev); - - snd_soc_unregister_component(dev); - - kfree(data); - + kfree(routing_data); routing_data = NULL; -}
-static const struct component_ops q6routing_dai_comp_ops = { - .bind = q6routing_dai_bind, - .unbind = q6routing_dai_unbind, -}; - -static int q6pcm_routing_probe(struct platform_device *pdev) -{ - return component_add(&pdev->dev, &q6routing_dai_comp_ops); -} - -static int q6pcm_routing_remove(struct platform_device *pdev) -{ - component_del(&pdev->dev, &q6routing_dai_comp_ops); return 0; }
Now that the component framework is integrated into the ASoC core, remove any redundant code in this driver.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- sound/soc/qcom/apq8096.c | 75 ++++-------------------------------------------- 1 file changed, 6 insertions(+), 69 deletions(-)
diff --git a/sound/soc/qcom/apq8096.c b/sound/soc/qcom/apq8096.c index cab8c4ff7c00..a56156281c8d 100644 --- a/sound/soc/qcom/apq8096.c +++ b/sound/soc/qcom/apq8096.c @@ -129,17 +129,18 @@ static int apq8096_sbc_parse_of(struct snd_soc_card *card) return ret; }
-static int apq8096_bind(struct device *dev) +static int apq8096_platform_probe(struct platform_device *pdev) { struct snd_soc_card *card; + struct device *dev = &pdev->dev; int ret;
card = kzalloc(sizeof(*card), GFP_KERNEL); if (!card) return -ENOMEM;
- component_bind_all(dev, card); card->dev = dev; + card->auto_bind = true; dev_set_drvdata(dev, card); ret = apq8096_sbc_parse_of(card); if (ret) { @@ -154,82 +155,18 @@ static int apq8096_bind(struct device *dev) return 0;
err: - component_unbind_all(dev, card); kfree(card); return ret; }
-static void apq8096_unbind(struct device *dev) +static int apq8096_platform_remove(struct platform_device *pdev) { - struct snd_soc_card *card = dev_get_drvdata(dev); + struct snd_soc_card *card = dev_get_drvdata(&pdev->dev);
+ card->auto_bind = false; snd_soc_unregister_card(card); - component_unbind_all(dev, card); kfree(card->dai_link); kfree(card); -} - -static const struct component_master_ops apq8096_ops = { - .bind = apq8096_bind, - .unbind = apq8096_unbind, -}; - -static int apq8016_compare_of(struct device *dev, void *data) -{ - return dev->of_node == data; -} - -static void apq8016_release_of(struct device *dev, void *data) -{ - of_node_put(data); -} - -static int add_audio_components(struct device *dev, - struct component_match **matchptr) -{ - struct device_node *np, *platform, *cpu, *node, *dai_node; - - node = dev->of_node; - - for_each_child_of_node(node, np) { - cpu = of_get_child_by_name(np, "cpu"); - if (cpu) { - dai_node = of_parse_phandle(cpu, "sound-dai", 0); - of_node_get(dai_node); - component_match_add_release(dev, matchptr, - apq8016_release_of, - apq8016_compare_of, - dai_node); - } - - platform = of_get_child_by_name(np, "platform"); - if (platform) { - dai_node = of_parse_phandle(platform, "sound-dai", 0); - component_match_add_release(dev, matchptr, - apq8016_release_of, - apq8016_compare_of, - dai_node); - } - } - - return 0; -} - -static int apq8096_platform_probe(struct platform_device *pdev) -{ - struct component_match *match = NULL; - int ret; - - ret = add_audio_components(&pdev->dev, &match); - if (ret) - return ret; - - return component_master_add_with_match(&pdev->dev, &apq8096_ops, match); -} - -static int apq8096_platform_remove(struct platform_device *pdev) -{ - component_master_del(&pdev->dev, &apq8096_ops);
return 0; }
The patch
ASoC: qcom: apq8096: remove component framework related code
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 90ae7105eaf19342bb11e554059d62b84e01da12 Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla srinivas.kandagatla@linaro.org Date: Fri, 13 Jul 2018 16:36:32 +0100 Subject: [PATCH] ASoC: qcom: apq8096: remove component framework related code
Now that the component framework is integrated into the ASoC core, remove any redundant code in this driver.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Reviewed-by: Vinod Koul vkoul@kernel.org Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/qcom/apq8096.c | 75 ++++------------------------------------ 1 file changed, 6 insertions(+), 69 deletions(-)
diff --git a/sound/soc/qcom/apq8096.c b/sound/soc/qcom/apq8096.c index cab8c4ff7c00..a56156281c8d 100644 --- a/sound/soc/qcom/apq8096.c +++ b/sound/soc/qcom/apq8096.c @@ -129,17 +129,18 @@ static int apq8096_sbc_parse_of(struct snd_soc_card *card) return ret; }
-static int apq8096_bind(struct device *dev) +static int apq8096_platform_probe(struct platform_device *pdev) { struct snd_soc_card *card; + struct device *dev = &pdev->dev; int ret;
card = kzalloc(sizeof(*card), GFP_KERNEL); if (!card) return -ENOMEM;
- component_bind_all(dev, card); card->dev = dev; + card->auto_bind = true; dev_set_drvdata(dev, card); ret = apq8096_sbc_parse_of(card); if (ret) { @@ -154,82 +155,18 @@ static int apq8096_bind(struct device *dev) return 0;
err: - component_unbind_all(dev, card); kfree(card); return ret; }
-static void apq8096_unbind(struct device *dev) +static int apq8096_platform_remove(struct platform_device *pdev) { - struct snd_soc_card *card = dev_get_drvdata(dev); + struct snd_soc_card *card = dev_get_drvdata(&pdev->dev);
+ card->auto_bind = false; snd_soc_unregister_card(card); - component_unbind_all(dev, card); kfree(card->dai_link); kfree(card); -} - -static const struct component_master_ops apq8096_ops = { - .bind = apq8096_bind, - .unbind = apq8096_unbind, -}; - -static int apq8016_compare_of(struct device *dev, void *data) -{ - return dev->of_node == data; -} - -static void apq8016_release_of(struct device *dev, void *data) -{ - of_node_put(data); -} - -static int add_audio_components(struct device *dev, - struct component_match **matchptr) -{ - struct device_node *np, *platform, *cpu, *node, *dai_node; - - node = dev->of_node; - - for_each_child_of_node(node, np) { - cpu = of_get_child_by_name(np, "cpu"); - if (cpu) { - dai_node = of_parse_phandle(cpu, "sound-dai", 0); - of_node_get(dai_node); - component_match_add_release(dev, matchptr, - apq8016_release_of, - apq8016_compare_of, - dai_node); - } - - platform = of_get_child_by_name(np, "platform"); - if (platform) { - dai_node = of_parse_phandle(platform, "sound-dai", 0); - component_match_add_release(dev, matchptr, - apq8016_release_of, - apq8016_compare_of, - dai_node); - } - } - - return 0; -} - -static int apq8096_platform_probe(struct platform_device *pdev) -{ - struct component_match *match = NULL; - int ret; - - ret = add_audio_components(&pdev->dev, &match); - if (ret) - return ret; - - return component_master_add_with_match(&pdev->dev, &apq8096_ops, match); -} - -static int apq8096_platform_remove(struct platform_device *pdev) -{ - component_master_del(&pdev->dev, &apq8096_ops);
return 0; }
On 13-07-18, 16:36, Srinivas Kandagatla wrote:
During discussion regarding card re-binding when components unregister and register back at https://lkml.org/lkml/2018/7/9/785 it was suggested that component framework can be added into core to provide this feature.
With this new changes the card will re-bind once the dependent component re-registers after unregistering. This works based on the match done from component name using component framework.
I have tested this patch with qdsp start-stop and module-load-unload usecase for more than 10000 times in loop on Qcom platforms.
6 files changed, 89 insertions(+), 156 deletions(-)
Looks good to me with a nice diff stat.
FWIW: Reviewed-by: Vinod Koul vkoul@kernel.org
participants (3)
-
Mark Brown
-
Srinivas Kandagatla
-
Vinod