diff options
author | Mark Brown <broonie@linaro.org> | 2013-11-08 05:43:24 -0500 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-11-08 05:43:24 -0500 |
commit | d20b09f0c5aaaa49a8a0189837a87adbc40095f0 (patch) | |
tree | d16d7c1f74edafee2a9f05d81e4e903d86ad9053 /sound/soc/soc-core.c | |
parent | 2fc175c4a347153a5e4f370a7dd574d56d46bb8a (diff) | |
parent | cb470087669a3fab1958fec79dd7db280b33f178 (diff) |
Merge remote-tracking branch 'asoc/topic/component' into asoc-next
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 09e47c1434a7..b1c472fde84b 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -4036,6 +4036,112 @@ static void snd_soc_unregister_dais(struct device *dev, size_t count) | |||
4036 | } | 4036 | } |
4037 | 4037 | ||
4038 | /** | 4038 | /** |
4039 | * snd_soc_register_component - Register a component with the ASoC core | ||
4040 | * | ||
4041 | */ | ||
4042 | static int | ||
4043 | __snd_soc_register_component(struct device *dev, | ||
4044 | struct snd_soc_component *cmpnt, | ||
4045 | const struct snd_soc_component_driver *cmpnt_drv, | ||
4046 | struct snd_soc_dai_driver *dai_drv, | ||
4047 | int num_dai, bool allow_single_dai) | ||
4048 | { | ||
4049 | int ret; | ||
4050 | |||
4051 | dev_dbg(dev, "component register %s\n", dev_name(dev)); | ||
4052 | |||
4053 | if (!cmpnt) { | ||
4054 | dev_err(dev, "ASoC: Failed to connecting component\n"); | ||
4055 | return -ENOMEM; | ||
4056 | } | ||
4057 | |||
4058 | cmpnt->name = fmt_single_name(dev, &cmpnt->id); | ||
4059 | if (!cmpnt->name) { | ||
4060 | dev_err(dev, "ASoC: Failed to simplifying name\n"); | ||
4061 | return -ENOMEM; | ||
4062 | } | ||
4063 | |||
4064 | cmpnt->dev = dev; | ||
4065 | cmpnt->driver = cmpnt_drv; | ||
4066 | cmpnt->num_dai = num_dai; | ||
4067 | |||
4068 | /* | ||
4069 | * snd_soc_register_dai() uses fmt_single_name(), and | ||
4070 | * snd_soc_register_dais() uses fmt_multiple_name() | ||
4071 | * for dai->name which is used for name based matching | ||
4072 | * | ||
4073 | * this function is used from cpu/codec. | ||
4074 | * allow_single_dai flag can ignore "codec" driver reworking | ||
4075 | * since it had been used snd_soc_register_dais(), | ||
4076 | */ | ||
4077 | if ((1 == num_dai) && allow_single_dai) | ||
4078 | ret = snd_soc_register_dai(dev, dai_drv); | ||
4079 | else | ||
4080 | ret = snd_soc_register_dais(dev, dai_drv, num_dai); | ||
4081 | if (ret < 0) { | ||
4082 | dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); | ||
4083 | goto error_component_name; | ||
4084 | } | ||
4085 | |||
4086 | mutex_lock(&client_mutex); | ||
4087 | list_add(&cmpnt->list, &component_list); | ||
4088 | mutex_unlock(&client_mutex); | ||
4089 | |||
4090 | dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name); | ||
4091 | |||
4092 | return ret; | ||
4093 | |||
4094 | error_component_name: | ||
4095 | kfree(cmpnt->name); | ||
4096 | |||
4097 | return ret; | ||
4098 | } | ||
4099 | |||
4100 | int snd_soc_register_component(struct device *dev, | ||
4101 | const struct snd_soc_component_driver *cmpnt_drv, | ||
4102 | struct snd_soc_dai_driver *dai_drv, | ||
4103 | int num_dai) | ||
4104 | { | ||
4105 | struct snd_soc_component *cmpnt; | ||
4106 | |||
4107 | cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL); | ||
4108 | if (!cmpnt) { | ||
4109 | dev_err(dev, "ASoC: Failed to allocate memory\n"); | ||
4110 | return -ENOMEM; | ||
4111 | } | ||
4112 | |||
4113 | return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, | ||
4114 | dai_drv, num_dai, true); | ||
4115 | } | ||
4116 | EXPORT_SYMBOL_GPL(snd_soc_register_component); | ||
4117 | |||
4118 | /** | ||
4119 | * snd_soc_unregister_component - Unregister a component from the ASoC core | ||
4120 | * | ||
4121 | */ | ||
4122 | void snd_soc_unregister_component(struct device *dev) | ||
4123 | { | ||
4124 | struct snd_soc_component *cmpnt; | ||
4125 | |||
4126 | list_for_each_entry(cmpnt, &component_list, list) { | ||
4127 | if (dev == cmpnt->dev) | ||
4128 | goto found; | ||
4129 | } | ||
4130 | return; | ||
4131 | |||
4132 | found: | ||
4133 | snd_soc_unregister_dais(dev, cmpnt->num_dai); | ||
4134 | |||
4135 | mutex_lock(&client_mutex); | ||
4136 | list_del(&cmpnt->list); | ||
4137 | mutex_unlock(&client_mutex); | ||
4138 | |||
4139 | dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name); | ||
4140 | kfree(cmpnt->name); | ||
4141 | } | ||
4142 | EXPORT_SYMBOL_GPL(snd_soc_unregister_component); | ||
4143 | |||
4144 | /** | ||
4039 | * snd_soc_add_platform - Add a platform to the ASoC core | 4145 | * snd_soc_add_platform - Add a platform to the ASoC core |
4040 | * @dev: The parent device for the platform | 4146 | * @dev: The parent device for the platform |
4041 | * @platform: The platform to add | 4147 | * @platform: The platform to add |
@@ -4257,10 +4363,12 @@ int snd_soc_register_codec(struct device *dev, | |||
4257 | list_add(&codec->list, &codec_list); | 4363 | list_add(&codec->list, &codec_list); |
4258 | mutex_unlock(&client_mutex); | 4364 | mutex_unlock(&client_mutex); |
4259 | 4365 | ||
4260 | /* register any DAIs */ | 4366 | /* register component */ |
4261 | ret = snd_soc_register_dais(dev, dai_drv, num_dai); | 4367 | ret = __snd_soc_register_component(dev, &codec->component, |
4368 | &codec_drv->component_driver, | ||
4369 | dai_drv, num_dai, false); | ||
4262 | if (ret < 0) { | 4370 | if (ret < 0) { |
4263 | dev_err(codec->dev, "ASoC: Failed to regster DAIs: %d\n", ret); | 4371 | dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret); |
4264 | goto fail_codec_name; | 4372 | goto fail_codec_name; |
4265 | } | 4373 | } |
4266 | 4374 | ||
@@ -4295,7 +4403,7 @@ void snd_soc_unregister_codec(struct device *dev) | |||
4295 | return; | 4403 | return; |
4296 | 4404 | ||
4297 | found: | 4405 | found: |
4298 | snd_soc_unregister_dais(dev, codec->num_dai); | 4406 | snd_soc_unregister_component(dev); |
4299 | 4407 | ||
4300 | mutex_lock(&client_mutex); | 4408 | mutex_lock(&client_mutex); |
4301 | list_del(&codec->list); | 4409 | list_del(&codec->list); |
@@ -4310,92 +4418,6 @@ found: | |||
4310 | } | 4418 | } |
4311 | EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); | 4419 | EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); |
4312 | 4420 | ||
4313 | |||
4314 | /** | ||
4315 | * snd_soc_register_component - Register a component with the ASoC core | ||
4316 | * | ||
4317 | */ | ||
4318 | int snd_soc_register_component(struct device *dev, | ||
4319 | const struct snd_soc_component_driver *cmpnt_drv, | ||
4320 | struct snd_soc_dai_driver *dai_drv, | ||
4321 | int num_dai) | ||
4322 | { | ||
4323 | struct snd_soc_component *cmpnt; | ||
4324 | int ret; | ||
4325 | |||
4326 | dev_dbg(dev, "component register %s\n", dev_name(dev)); | ||
4327 | |||
4328 | cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL); | ||
4329 | if (!cmpnt) { | ||
4330 | dev_err(dev, "ASoC: Failed to allocate memory\n"); | ||
4331 | return -ENOMEM; | ||
4332 | } | ||
4333 | |||
4334 | cmpnt->name = fmt_single_name(dev, &cmpnt->id); | ||
4335 | if (!cmpnt->name) { | ||
4336 | dev_err(dev, "ASoC: Failed to simplifying name\n"); | ||
4337 | return -ENOMEM; | ||
4338 | } | ||
4339 | |||
4340 | cmpnt->dev = dev; | ||
4341 | cmpnt->driver = cmpnt_drv; | ||
4342 | cmpnt->num_dai = num_dai; | ||
4343 | |||
4344 | /* | ||
4345 | * snd_soc_register_dai() uses fmt_single_name(), and | ||
4346 | * snd_soc_register_dais() uses fmt_multiple_name() | ||
4347 | * for dai->name which is used for name based matching | ||
4348 | */ | ||
4349 | if (1 == num_dai) | ||
4350 | ret = snd_soc_register_dai(dev, dai_drv); | ||
4351 | else | ||
4352 | ret = snd_soc_register_dais(dev, dai_drv, num_dai); | ||
4353 | if (ret < 0) { | ||
4354 | dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); | ||
4355 | goto error_component_name; | ||
4356 | } | ||
4357 | |||
4358 | mutex_lock(&client_mutex); | ||
4359 | list_add(&cmpnt->list, &component_list); | ||
4360 | mutex_unlock(&client_mutex); | ||
4361 | |||
4362 | dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name); | ||
4363 | |||
4364 | return ret; | ||
4365 | |||
4366 | error_component_name: | ||
4367 | kfree(cmpnt->name); | ||
4368 | |||
4369 | return ret; | ||
4370 | } | ||
4371 | EXPORT_SYMBOL_GPL(snd_soc_register_component); | ||
4372 | |||
4373 | /** | ||
4374 | * snd_soc_unregister_component - Unregister a component from the ASoC core | ||
4375 | * | ||
4376 | */ | ||
4377 | void snd_soc_unregister_component(struct device *dev) | ||
4378 | { | ||
4379 | struct snd_soc_component *cmpnt; | ||
4380 | |||
4381 | list_for_each_entry(cmpnt, &component_list, list) { | ||
4382 | if (dev == cmpnt->dev) | ||
4383 | goto found; | ||
4384 | } | ||
4385 | return; | ||
4386 | |||
4387 | found: | ||
4388 | snd_soc_unregister_dais(dev, cmpnt->num_dai); | ||
4389 | |||
4390 | mutex_lock(&client_mutex); | ||
4391 | list_del(&cmpnt->list); | ||
4392 | mutex_unlock(&client_mutex); | ||
4393 | |||
4394 | dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name); | ||
4395 | kfree(cmpnt->name); | ||
4396 | } | ||
4397 | EXPORT_SYMBOL_GPL(snd_soc_unregister_component); | ||
4398 | |||
4399 | /* Retrieve a card's name from device tree */ | 4421 | /* Retrieve a card's name from device tree */ |
4400 | int snd_soc_of_parse_card_name(struct snd_soc_card *card, | 4422 | int snd_soc_of_parse_card_name(struct snd_soc_card *card, |
4401 | const char *propname) | 4423 | const char *propname) |
@@ -4583,6 +4605,41 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np, | |||
4583 | } | 4605 | } |
4584 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt); | 4606 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt); |
4585 | 4607 | ||
4608 | int snd_soc_of_get_dai_name(struct device_node *of_node, | ||
4609 | const char **dai_name) | ||
4610 | { | ||
4611 | struct snd_soc_component *pos; | ||
4612 | struct of_phandle_args args; | ||
4613 | int ret; | ||
4614 | |||
4615 | ret = of_parse_phandle_with_args(of_node, "sound-dai", | ||
4616 | "#sound-dai-cells", 0, &args); | ||
4617 | if (ret) | ||
4618 | return ret; | ||
4619 | |||
4620 | ret = -EPROBE_DEFER; | ||
4621 | |||
4622 | mutex_lock(&client_mutex); | ||
4623 | list_for_each_entry(pos, &component_list, list) { | ||
4624 | if (pos->dev->of_node != args.np) | ||
4625 | continue; | ||
4626 | |||
4627 | if (!pos->driver->of_xlate_dai_name) { | ||
4628 | ret = -ENOSYS; | ||
4629 | break; | ||
4630 | } | ||
4631 | |||
4632 | ret = pos->driver->of_xlate_dai_name(pos, &args, dai_name); | ||
4633 | break; | ||
4634 | } | ||
4635 | mutex_unlock(&client_mutex); | ||
4636 | |||
4637 | of_node_put(args.np); | ||
4638 | |||
4639 | return ret; | ||
4640 | } | ||
4641 | EXPORT_SYMBOL_GPL(snd_soc_of_get_dai_name); | ||
4642 | |||
4586 | static int __init snd_soc_init(void) | 4643 | static int __init snd_soc_init(void) |
4587 | { | 4644 | { |
4588 | #ifdef CONFIG_DEBUG_FS | 4645 | #ifdef CONFIG_DEBUG_FS |