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}
4083EXPORT_SYMBOL_GPL(snd_soc_register_component);
4086 4084
4087/** 4085/**
4088 * snd_soc_unregister_component - Unregister a component from the ASoC core 4086 * snd_soc_unregister_component - Unregister a component from the ASoC core
@@ -4099,7 +4097,9 @@ void snd_soc_unregister_component(struct device *dev)
4099 return; 4097 return;
4100 4098
4101found: 4099found:
4102 __snd_soc_unregister_component(cmpnt); 4100 snd_soc_component_del(cmpnt);
4101 snd_soc_component_cleanup(cmpnt);
4102 kfree(cmpnt);
4103} 4103}
4104EXPORT_SYMBOL_GPL(snd_soc_unregister_component); 4104EXPORT_SYMBOL_GPL(snd_soc_unregister_component);
4105 4105
@@ -4132,6 +4132,11 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform,
4132{ 4132{
4133 int ret; 4133 int ret;
4134 4134
4135 ret = snd_soc_component_initialize(&platform->component,
4136 &platform_drv->component_driver, dev);
4137 if (ret)
4138 return ret;
4139
4135 platform->dev = dev; 4140 platform->dev = dev;
4136 platform->driver = platform_drv; 4141 platform->driver = platform_drv;
4137 platform->dapm.dev = dev; 4142 platform->dapm.dev = dev;
@@ -4143,17 +4148,8 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform,
4143 if (platform_drv->read) 4148 if (platform_drv->read)
4144 platform->component.read = snd_soc_platform_drv_read; 4149 platform->component.read = snd_soc_platform_drv_read;
4145 4150
4146 /* register component */
4147 ret = __snd_soc_register_component(dev, &platform->component,
4148 &platform_drv->component_driver,
4149 NULL, NULL, 0, false);
4150 if (ret < 0) {
4151 dev_err(platform->component.dev,
4152 "ASoC: Failed to register component: %d\n", ret);
4153 return ret;
4154 }
4155
4156 mutex_lock(&client_mutex); 4151 mutex_lock(&client_mutex);
4152 snd_soc_component_add_unlocked(&platform->component);
4157 list_add(&platform->list, &platform_list); 4153 list_add(&platform->list, &platform_list);
4158 mutex_unlock(&client_mutex); 4154 mutex_unlock(&client_mutex);
4159 4155
@@ -4195,12 +4191,14 @@ EXPORT_SYMBOL_GPL(snd_soc_register_platform);
4195 */ 4191 */
4196void snd_soc_remove_platform(struct snd_soc_platform *platform) 4192void snd_soc_remove_platform(struct snd_soc_platform *platform)
4197{ 4193{
4198 __snd_soc_unregister_component(&platform->component);
4199 4194
4200 mutex_lock(&client_mutex); 4195 mutex_lock(&client_mutex);
4201 list_del(&platform->list); 4196 list_del(&platform->list);
4197 snd_soc_component_del_unlocked(&platform->component);
4202 mutex_unlock(&client_mutex); 4198 mutex_unlock(&client_mutex);
4203 4199
4200 snd_soc_component_cleanup(&platform->component);
4201
4204 dev_dbg(platform->dev, "ASoC: Unregistered platform '%s'\n", 4202 dev_dbg(platform->dev, "ASoC: Unregistered platform '%s'\n",
4205 platform->component.name); 4203 platform->component.name);
4206} 4204}
@@ -4299,6 +4297,7 @@ int snd_soc_register_codec(struct device *dev,
4299 int num_dai) 4297 int num_dai)
4300{ 4298{
4301 struct snd_soc_codec *codec; 4299 struct snd_soc_codec *codec;
4300 struct snd_soc_dai *dai;
4302 struct regmap *regmap; 4301 struct regmap *regmap;
4303 int ret, i; 4302 int ret, i;
4304 4303
@@ -4308,6 +4307,11 @@ int snd_soc_register_codec(struct device *dev,
4308 if (codec == NULL) 4307 if (codec == NULL)
4309 return -ENOMEM; 4308 return -ENOMEM;
4310 4309
4310 ret = snd_soc_component_initialize(&codec->component,
4311 &codec_drv->component_driver, dev);
4312 if (ret)
4313 goto err_free;
4314
4311 if (codec_drv->write) 4315 if (codec_drv->write)
4312 codec->component.write = snd_soc_codec_drv_write; 4316 codec->component.write = snd_soc_codec_drv_write;
4313 if (codec_drv->read) 4317 if (codec_drv->read)
@@ -4337,7 +4341,7 @@ int snd_soc_register_codec(struct device *dev,
4337 dev_err(codec->dev, 4341 dev_err(codec->dev,
4338 "Failed to set cache I/O:%d\n", 4342 "Failed to set cache I/O:%d\n",
4339 ret); 4343 ret);
4340 return ret; 4344 goto err_cleanup;
4341 } 4345 }
4342 } 4346 }
4343 } 4347 }
@@ -4347,27 +4351,27 @@ int snd_soc_register_codec(struct device *dev,
4347 fixup_codec_formats(&dai_drv[i].capture); 4351 fixup_codec_formats(&dai_drv[i].capture);
4348 } 4352 }
4349 4353
4354 ret = snd_soc_register_dais(&codec->component, dai_drv, num_dai, false);
4355 if (ret < 0) {
4356 dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
4357 goto err_cleanup;
4358 }
4359
4360 list_for_each_entry(dai, &codec->component.dai_list, list)
4361 dai->codec = codec;
4362
4350 mutex_lock(&client_mutex); 4363 mutex_lock(&client_mutex);
4364 snd_soc_component_add_unlocked(&codec->component);
4351 list_add(&codec->list, &codec_list); 4365 list_add(&codec->list, &codec_list);
4352 mutex_unlock(&client_mutex); 4366 mutex_unlock(&client_mutex);
4353 4367
4354 /* register component */
4355 ret = __snd_soc_register_component(dev, &codec->component,
4356 &codec_drv->component_driver,
4357 codec, dai_drv, num_dai, false);
4358 if (ret < 0) {
4359 dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret);
4360 goto fail_codec;
4361 }
4362
4363 dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n", 4368 dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n",
4364 codec->component.name); 4369 codec->component.name);
4365 return 0; 4370 return 0;
4366 4371
4367fail_codec: 4372err_cleanup:
4368 mutex_lock(&client_mutex); 4373 snd_soc_component_cleanup(&codec->component);
4369 list_del(&codec->list); 4374err_free:
4370 mutex_unlock(&client_mutex);
4371 kfree(codec); 4375 kfree(codec);
4372 return ret; 4376 return ret;
4373} 4377}
@@ -4389,15 +4393,16 @@ void snd_soc_unregister_codec(struct device *dev)
4389 return; 4393 return;
4390 4394
4391found: 4395found:
4392 __snd_soc_unregister_component(&codec->component);
4393 4396
4394 mutex_lock(&client_mutex); 4397 mutex_lock(&client_mutex);
4395 list_del(&codec->list); 4398 list_del(&codec->list);
4399 snd_soc_component_del_unlocked(&codec->component);
4396 mutex_unlock(&client_mutex); 4400 mutex_unlock(&client_mutex);
4397 4401
4398 dev_dbg(codec->dev, "ASoC: Unregistered codec '%s'\n", 4402 dev_dbg(codec->dev, "ASoC: Unregistered codec '%s'\n",
4399 codec->component.name); 4403 codec->component.name);
4400 4404
4405 snd_soc_component_cleanup(&codec->component);
4401 snd_soc_cache_exit(codec); 4406 snd_soc_cache_exit(codec);
4402 kfree(codec); 4407 kfree(codec);
4403} 4408}