aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2014-06-16 12:13:03 -0400
committerMark Brown <broonie@linaro.org>2014-06-21 16:05:13 -0400
commitbb13109d85ba5f8009f1a26d840e70198537a4e3 (patch)
tree9728f97f94c4bdc1580de3723cc59c009975adc5
parentf4333203ec933f9272c90c7add01774ec2cf94d3 (diff)
ASoC: Split component registration into two steps
Split snd_soc_component_register() into snd_soc_component_initialize() and snd_soc_component_add(). Using a 2-stage registration approach has the advantage that it is possible to modify the component after it has been initialized, but before it is made visible to the system. This e.g. allows CODECs or platforms to overwrite some of the default settings made in snd_soc_component_initialize(). Similar snd_soc_component_unregister() is split into two steps as well, snd_soc_component_delete(), which removes the component from the system, and snd_soc_component_cleanup(), which frees all the resources allocated by the component. Furthermore this patch makes sure that if a component is visible on two list (e.g. the component list and the CODEC list) it is added or removed to both lists atomically. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--sound/soc/soc-core.c177
1 files changed, 91 insertions, 86 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index b8cc88a9f947..0944da66538d 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3922,16 +3922,14 @@ static void snd_soc_unregister_dais(struct snd_soc_component *component)
3922 * snd_soc_register_dais - Register a DAI with the ASoC core 3922 * snd_soc_register_dais - Register a DAI with the ASoC core
3923 * 3923 *
3924 * @component: The component the DAIs are registered for 3924 * @component: The component the DAIs are registered for
3925 * @codec: The CODEC that the DAIs are registered for, NULL if the component is
3926 * not a CODEC.
3927 * @dai_drv: DAI driver to use for the DAIs 3925 * @dai_drv: DAI driver to use for the DAIs
3928 * @count: Number of DAIs 3926 * @count: Number of DAIs
3929 * @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the 3927 * @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the
3930 * parent's name. 3928 * parent's name.
3931 */ 3929 */
3932static int snd_soc_register_dais(struct snd_soc_component *component, 3930static int snd_soc_register_dais(struct snd_soc_component *component,
3933 struct snd_soc_codec *codec, struct snd_soc_dai_driver *dai_drv, 3931 struct snd_soc_dai_driver *dai_drv, size_t count,
3934 size_t count, bool legacy_dai_naming) 3932 bool legacy_dai_naming)
3935{ 3933{
3936 struct device *dev = component->dev; 3934 struct device *dev = component->dev;
3937 struct snd_soc_dai *dai; 3935 struct snd_soc_dai *dai;
@@ -3940,6 +3938,9 @@ static int snd_soc_register_dais(struct snd_soc_component *component,
3940 3938
3941 dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count); 3939 dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count);
3942 3940
3941 component->dai_drv = dai_drv;
3942 component->num_dai = count;
3943
3943 for (i = 0; i < count; i++) { 3944 for (i = 0; i < count; i++) {
3944 3945
3945 dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); 3946 dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
@@ -3972,7 +3973,6 @@ static int snd_soc_register_dais(struct snd_soc_component *component,
3972 } 3973 }
3973 3974
3974 dai->component = component; 3975 dai->component = component;
3975 dai->codec = codec;
3976 dai->dev = dev; 3976 dai->dev = dev;
3977 dai->driver = &dai_drv[i]; 3977 dai->driver = &dai_drv[i];
3978 dai->dapm.dev = dev; 3978 dai->dapm.dev = dev;
@@ -3995,60 +3995,52 @@ err:
3995 return ret; 3995 return ret;
3996} 3996}
3997 3997
3998/** 3998static int snd_soc_component_initialize(struct snd_soc_component *component,
3999 * snd_soc_register_component - Register a component with the ASoC core 3999 const struct snd_soc_component_driver *driver, struct device *dev)
4000 *
4001 */
4002static int
4003__snd_soc_register_component(struct device *dev,
4004 struct snd_soc_component *cmpnt,
4005 const struct snd_soc_component_driver *cmpnt_drv,
4006 struct snd_soc_codec *codec,
4007 struct snd_soc_dai_driver *dai_drv,
4008 int num_dai, bool allow_single_dai)
4009{ 4000{
4010 int ret; 4001 component->name = fmt_single_name(dev, &component->id);
4011 4002 if (!component->name) {
4012 dev_dbg(dev, "component register %s\n", dev_name(dev)); 4003 dev_err(dev, "ASoC: Failed to allocate name\n");
4013
4014 if (!cmpnt) {
4015 dev_err(dev, "ASoC: Failed to connecting component\n");
4016 return -ENOMEM; 4004 return -ENOMEM;
4017 } 4005 }
4018 4006
4019 mutex_init(&cmpnt->io_mutex); 4007 component->dev = dev;
4008 component->driver = driver;
4020 4009
4021 cmpnt->name = fmt_single_name(dev, &cmpnt->id); 4010 INIT_LIST_HEAD(&component->dai_list);
4022 if (!cmpnt->name) { 4011 mutex_init(&component->io_mutex);
4023 dev_err(dev, "ASoC: Failed to simplifying name\n");
4024 return -ENOMEM;
4025 }
4026 4012
4027 cmpnt->dev = dev; 4013 return 0;
4028 cmpnt->driver = cmpnt_drv; 4014}
4029 cmpnt->dai_drv = dai_drv;
4030 cmpnt->num_dai = num_dai;
4031 INIT_LIST_HEAD(&cmpnt->dai_list);
4032 4015
4033 ret = snd_soc_register_dais(cmpnt, codec, dai_drv, num_dai, 4016static void snd_soc_component_add_unlocked(struct snd_soc_component *component)
4034 allow_single_dai); 4017{
4035 if (ret < 0) { 4018 list_add(&component->list, &component_list);
4036 dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); 4019}
4037 goto error_component_name;
4038 }
4039 4020
4021static void snd_soc_component_add(struct snd_soc_component *component)
4022{
4040 mutex_lock(&client_mutex); 4023 mutex_lock(&client_mutex);
4041 list_add(&cmpnt->list, &component_list); 4024 snd_soc_component_add_unlocked(component);
4042 mutex_unlock(&client_mutex); 4025 mutex_unlock(&client_mutex);
4026}
4043 4027
4044 dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name); 4028static void snd_soc_component_cleanup(struct snd_soc_component *component)
4045 4029{
4046 return ret; 4030 snd_soc_unregister_dais(component);
4031 kfree(component->name);
4032}
4047 4033
4048error_component_name: 4034static void snd_soc_component_del_unlocked(struct snd_soc_component *component)
4049 kfree(cmpnt->name); 4035{
4036 list_del(&component->list);
4037}
4050 4038
4051 return ret; 4039static void snd_soc_component_del(struct snd_soc_component *component)
4040{
4041 mutex_lock(&client_mutex);
4042 snd_soc_component_del_unlocked(component);
4043 mutex_unlock(&client_mutex);
4052} 4044}
4053 4045
4054int snd_soc_register_component(struct device *dev, 4046int snd_soc_register_component(struct device *dev,
@@ -4057,32 +4049,38 @@ int snd_soc_register_component(struct device *dev,
4057 int num_dai) 4049 int num_dai)
4058{ 4050{
4059 struct snd_soc_component *cmpnt; 4051 struct snd_soc_component *cmpnt;
4052 int ret;
4060 4053
4061 cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL); 4054 cmpnt = kzalloc(sizeof(*cmpnt), GFP_KERNEL);
4062 if (!cmpnt) { 4055 if (!cmpnt) {
4063 dev_err(dev, "ASoC: Failed to allocate memory\n"); 4056 dev_err(dev, "ASoC: Failed to allocate memory\n");
4064 return -ENOMEM; 4057 return -ENOMEM;
4065 } 4058 }
4066 4059
4060 ret = snd_soc_component_initialize(cmpnt, cmpnt_drv, dev);
4061 if (ret)
4062 goto err_free;
4063
4067 cmpnt->ignore_pmdown_time = true; 4064 cmpnt->ignore_pmdown_time = true;
4068 cmpnt->registered_as_component = true; 4065 cmpnt->registered_as_component = true;
4069 4066
4070 return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, NULL, 4067 ret = snd_soc_register_dais(cmpnt, dai_drv, num_dai, true);
4071 dai_drv, num_dai, true); 4068 if (ret < 0) {
4072} 4069 dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
4073EXPORT_SYMBOL_GPL(snd_soc_register_component); 4070 goto err_cleanup;
4071 }
4074 4072
4075static void __snd_soc_unregister_component(struct snd_soc_component *cmpnt) 4073 snd_soc_component_add(cmpnt);
4076{
4077 snd_soc_unregister_dais(cmpnt);
4078 4074
4079 mutex_lock(&client_mutex); 4075 return 0;
4080 list_del(&cmpnt->list);
4081 mutex_unlock(&client_mutex);
4082 4076
4083 dev_dbg(cmpnt->dev, "ASoC: Unregistered component '%s'\n", cmpnt->name); 4077err_cleanup:
4084 kfree(cmpnt->name); 4078 snd_soc_component_cleanup(cmpnt);
4079err_free:
4080 kfree(cmpnt);
4081 return ret;
4085} 4082}