diff options
author | Mark Brown <broonie@linaro.org> | 2013-09-17 08:25:28 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-09-17 08:25:28 -0400 |
commit | 7d930ce26e01470590cd003484b32df29529906c (patch) | |
tree | 7fd2b7d0f85f104009ef9edeb32806f6bbc47070 /sound/soc/soc-core.c | |
parent | 7f05cc98bd9b10b9a0173f3f5d20c2223fdf7470 (diff) | |
parent | cb470087669a3fab1958fec79dd7db280b33f178 (diff) |
Merge remote-tracking branch 'asoc/topic/component' into asoc-core
Conflicts:
include/sound/soc.h
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r-- | sound/soc/soc-core.c | 237 |
1 files changed, 147 insertions, 90 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 16a3930c6375..67cfb5f5ca96 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -3996,6 +3996,112 @@ static void snd_soc_unregister_dais(struct device *dev, size_t count) | |||
3996 | } | 3996 | } |
3997 | 3997 | ||
3998 | /** | 3998 | /** |
3999 | * snd_soc_register_component - Register a component with the ASoC core | ||
4000 | * | ||
4001 | */ | ||
4002 | static 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_dai_driver *dai_drv, | ||
4007 | int num_dai, bool allow_single_dai) | ||
4008 | { | ||
4009 | int ret; | ||
4010 | |||
4011 | dev_dbg(dev, "component register %s\n", dev_name(dev)); | ||
4012 | |||
4013 | if (!cmpnt) { | ||
4014 | dev_err(dev, "ASoC: Failed to connecting component\n"); | ||
4015 | return -ENOMEM; | ||
4016 | } | ||
4017 | |||
4018 | cmpnt->name = fmt_single_name(dev, &cmpnt->id); | ||
4019 | if (!cmpnt->name) { | ||
4020 | dev_err(dev, "ASoC: Failed to simplifying name\n"); | ||
4021 | return -ENOMEM; | ||
4022 | } | ||
4023 | |||
4024 | cmpnt->dev = dev; | ||
4025 | cmpnt->driver = cmpnt_drv; | ||
4026 | cmpnt->num_dai = num_dai; | ||
4027 | |||
4028 | /* | ||
4029 | * snd_soc_register_dai() uses fmt_single_name(), and | ||
4030 | * snd_soc_register_dais() uses fmt_multiple_name() | ||
4031 | * for dai->name which is used for name based matching | ||
4032 | * | ||
4033 | * this function is used from cpu/codec. | ||
4034 | * allow_single_dai flag can ignore "codec" driver reworking | ||
4035 | * since it had been used snd_soc_register_dais(), | ||
4036 | */ | ||
4037 | if ((1 == num_dai) && allow_single_dai) | ||
4038 | ret = snd_soc_register_dai(dev, dai_drv); | ||
4039 | else | ||
4040 | ret = snd_soc_register_dais(dev, dai_drv, num_dai); | ||
4041 | if (ret < 0) { | ||
4042 | dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); | ||
4043 | goto error_component_name; | ||
4044 | } | ||
4045 | |||
4046 | mutex_lock(&client_mutex); | ||
4047 | list_add(&cmpnt->list, &component_list); | ||
4048 | mutex_unlock(&client_mutex); | ||
4049 | |||
4050 | dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name); | ||
4051 | |||
4052 | return ret; | ||
4053 | |||
4054 | error_component_name: | ||
4055 | kfree(cmpnt->name); | ||
4056 | |||
4057 | return ret; | ||
4058 | } | ||
4059 | |||
4060 | int snd_soc_register_component(struct device *dev, | ||
4061 | const struct snd_soc_component_driver *cmpnt_drv, | ||
4062 | struct snd_soc_dai_driver *dai_drv, | ||
4063 | int num_dai) | ||
4064 | { | ||
4065 | struct snd_soc_component *cmpnt; | ||
4066 | |||
4067 | cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL); | ||
4068 | if (!cmpnt) { | ||
4069 | dev_err(dev, "ASoC: Failed to allocate memory\n"); | ||
4070 | return -ENOMEM; | ||
4071 | } | ||
4072 | |||
4073 | return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, | ||
4074 | dai_drv, num_dai, true); | ||
4075 | } | ||
4076 | EXPORT_SYMBOL_GPL(snd_soc_register_component); | ||
4077 | |||
4078 | /** | ||
4079 | * snd_soc_unregister_component - Unregister a component from the ASoC core | ||
4080 | * | ||
4081 | */ | ||
4082 | void snd_soc_unregister_component(struct device *dev) | ||
4083 | { | ||
4084 | struct snd_soc_component *cmpnt; | ||
4085 | |||
4086 | list_for_each_entry(cmpnt, &component_list, list) { | ||
4087 | if (dev == cmpnt->dev) | ||
4088 | goto found; | ||
4089 | } | ||
4090 | return; | ||
4091 | |||
4092 | found: | ||
4093 | snd_soc_unregister_dais(dev, cmpnt->num_dai); | ||
4094 | |||
4095 | mutex_lock(&client_mutex); | ||
4096 | list_del(&cmpnt->list); | ||
4097 | mutex_unlock(&client_mutex); | ||
4098 | |||
4099 | dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name); | ||
4100 | kfree(cmpnt->name); | ||
4101 | } | ||
4102 | EXPORT_SYMBOL_GPL(snd_soc_unregister_component); | ||
4103 | |||
4104 | /** | ||
3999 | * snd_soc_add_platform - Add a platform to the ASoC core | 4105 | * snd_soc_add_platform - Add a platform to the ASoC core |
4000 | * @dev: The parent device for the platform | 4106 | * @dev: The parent device for the platform |
4001 | * @platform: The platform to add | 4107 | * @platform: The platform to add |
@@ -4182,10 +4288,12 @@ int snd_soc_register_codec(struct device *dev, | |||
4182 | list_add(&codec->list, &codec_list); | 4288 | list_add(&codec->list, &codec_list); |
4183 | mutex_unlock(&client_mutex); | 4289 | mutex_unlock(&client_mutex); |
4184 | 4290 | ||
4185 | /* register any DAIs */ | 4291 | /* register component */ |
4186 | ret = snd_soc_register_dais(dev, dai_drv, num_dai); | 4292 | ret = __snd_soc_register_component(dev, &codec->component, |
4293 | &codec_drv->component_driver, | ||
4294 | dai_drv, num_dai, false); | ||
4187 | if (ret < 0) { | 4295 | if (ret < 0) { |
4188 | dev_err(codec->dev, "ASoC: Failed to regster DAIs: %d\n", ret); | 4296 | dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret); |
4189 | goto fail_codec_name; | 4297 | goto fail_codec_name; |
4190 | } | 4298 | } |
4191 | 4299 | ||
@@ -4220,7 +4328,7 @@ void snd_soc_unregister_codec(struct device *dev) | |||
4220 | return; | 4328 | return; |
4221 | 4329 | ||
4222 | found: | 4330 | found: |
4223 | snd_soc_unregister_dais(dev, codec->num_dai); | 4331 | snd_soc_unregister_component(dev); |
4224 | 4332 | ||
4225 | mutex_lock(&client_mutex); | 4333 | mutex_lock(&client_mutex); |
4226 | list_del(&codec->list); | 4334 | list_del(&codec->list); |
@@ -4234,92 +4342,6 @@ found: | |||
4234 | } | 4342 | } |
4235 | EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); | 4343 | EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); |
4236 | 4344 | ||
4237 | |||
4238 | /** | ||
4239 | * snd_soc_register_component - Register a component with the ASoC core | ||
4240 | * | ||
4241 | */ | ||
4242 | int snd_soc_register_component(struct device *dev, | ||
4243 | const struct snd_soc_component_driver *cmpnt_drv, | ||
4244 | struct snd_soc_dai_driver *dai_drv, | ||
4245 | int num_dai) | ||
4246 | { | ||
4247 | struct snd_soc_component *cmpnt; | ||
4248 | int ret; | ||
4249 | |||
4250 | dev_dbg(dev, "component register %s\n", dev_name(dev)); | ||
4251 | |||
4252 | cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL); | ||
4253 | if (!cmpnt) { | ||
4254 | dev_err(dev, "ASoC: Failed to allocate memory\n"); | ||
4255 | return -ENOMEM; | ||
4256 | } | ||
4257 | |||
4258 | cmpnt->name = fmt_single_name(dev, &cmpnt->id); | ||
4259 | if (!cmpnt->name) { | ||
4260 | dev_err(dev, "ASoC: Failed to simplifying name\n"); | ||
4261 | return -ENOMEM; | ||
4262 | } | ||
4263 | |||
4264 | cmpnt->dev = dev; | ||
4265 | cmpnt->driver = cmpnt_drv; | ||
4266 | cmpnt->num_dai = num_dai; | ||
4267 | |||
4268 | /* | ||
4269 | * snd_soc_register_dai() uses fmt_single_name(), and | ||
4270 | * snd_soc_register_dais() uses fmt_multiple_name() | ||
4271 | * for dai->name which is used for name based matching | ||
4272 | */ | ||
4273 | if (1 == num_dai) | ||
4274 | ret = snd_soc_register_dai(dev, dai_drv); | ||
4275 | else | ||
4276 | ret = snd_soc_register_dais(dev, dai_drv, num_dai); | ||
4277 | if (ret < 0) { | ||
4278 | dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); | ||
4279 | goto error_component_name; | ||
4280 | } | ||
4281 | |||
4282 | mutex_lock(&client_mutex); | ||
4283 | list_add(&cmpnt->list, &component_list); | ||
4284 | mutex_unlock(&client_mutex); | ||
4285 | |||
4286 | dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name); | ||
4287 | |||
4288 | return ret; | ||
4289 | |||
4290 | error_component_name: | ||
4291 | kfree(cmpnt->name); | ||
4292 | |||
4293 | return ret; | ||
4294 | } | ||
4295 | EXPORT_SYMBOL_GPL(snd_soc_register_component); | ||
4296 | |||
4297 | /** | ||
4298 | * snd_soc_unregister_component - Unregister a component from the ASoC core | ||
4299 | * | ||
4300 | */ | ||
4301 | void snd_soc_unregister_component(struct device *dev) | ||
4302 | { | ||
4303 | struct snd_soc_component *cmpnt; | ||
4304 | |||
4305 | list_for_each_entry(cmpnt, &component_list, list) { | ||
4306 | if (dev == cmpnt->dev) | ||
4307 | goto found; | ||
4308 | } | ||
4309 | return; | ||
4310 | |||
4311 | found: | ||
4312 | snd_soc_unregister_dais(dev, cmpnt->num_dai); | ||
4313 | |||
4314 | mutex_lock(&client_mutex); | ||
4315 | list_del(&cmpnt->list); | ||
4316 | mutex_unlock(&client_mutex); | ||
4317 | |||
4318 | dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name); | ||
4319 | kfree(cmpnt->name); | ||
4320 | } | ||
4321 | EXPORT_SYMBOL_GPL(snd_soc_unregister_component); | ||
4322 | |||
4323 | /* Retrieve a card's name from device tree */ | 4345 | /* Retrieve a card's name from device tree */ |
4324 | int snd_soc_of_parse_card_name(struct snd_soc_card *card, | 4346 | int snd_soc_of_parse_card_name(struct snd_soc_card *card, |
4325 | const char *propname) | 4347 | const char *propname) |
@@ -4507,6 +4529,41 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np, | |||
4507 | } | 4529 | } |
4508 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt); | 4530 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt); |
4509 | 4531 | ||
4532 | int snd_soc_of_get_dai_name(struct device_node *of_node, | ||
4533 | const char **dai_name) | ||
4534 | { | ||
4535 | struct snd_soc_component *pos; | ||
4536 | struct of_phandle_args args; | ||
4537 | int ret; | ||
4538 | |||
4539 | ret = of_parse_phandle_with_args(of_node, "sound-dai", | ||
4540 | "#sound-dai-cells", 0, &args); | ||
4541 | if (ret) | ||
4542 | return ret; | ||
4543 | |||
4544 | ret = -EPROBE_DEFER; | ||
4545 | |||
4546 | mutex_lock(&client_mutex); | ||
4547 | list_for_each_entry(pos, &component_list, list) { | ||
4548 | if (pos->dev->of_node != args.np) | ||
4549 | continue; | ||
4550 | |||
4551 | if (!pos->driver->of_xlate_dai_name) { | ||
4552 | ret = -ENOSYS; | ||
4553 | break; | ||
4554 | } | ||
4555 | |||
4556 | ret = pos->driver->of_xlate_dai_name(pos, &args, dai_name); | ||
4557 | break; | ||
4558 | } | ||
4559 | mutex_unlock(&client_mutex); | ||
4560 | |||
4561 | of_node_put(args.np); | ||
4562 | |||
4563 | return ret; | ||
4564 | } | ||
4565 | EXPORT_SYMBOL_GPL(snd_soc_of_get_dai_name); | ||
4566 | |||
4510 | static int __init snd_soc_init(void) | 4567 | static int __init snd_soc_init(void) |
4511 | { | 4568 | { |
4512 | #ifdef CONFIG_DEBUG_FS | 4569 | #ifdef CONFIG_DEBUG_FS |