From 18626c7ebc05e6486712cc129d8da83d07da9dc7 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 9 Jun 2014 14:20:29 +0300 Subject: ASoC: dapm: Make sure register value is in sync with DAPM kcontrol state Commit c9e065c27fe9 ("ASoC: dapm: Make sure to always update the DAPM graph in _put_volsw()") stopped updating register values in those cases where initial after boot state of kcontrol appears to not change but where register value still needs update because it is not in sync with the kcontrol state. Fix this by doing snd_soc_test_bits() unconditionally as it was before but by using separate flags for kcontrol and register state changes. This allow both DAPM graph to be updated when disabling auto-muted control and update register if it is out-of-sync in respect of kcontrol state. Signed-off-by: Jarkko Nikula Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index a74b9bf23d9f..cdc837ed144d 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2755,7 +2755,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; unsigned int val; - int connect, change; + int connect, change, reg_change = 0; struct snd_soc_dapm_update update; int ret = 0; @@ -2773,20 +2773,23 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); change = dapm_kcontrol_set_value(kcontrol, val); - if (change) { - if (reg != SND_SOC_NOPM) { - mask = mask << shift; - val = val << shift; - - if (snd_soc_test_bits(codec, reg, mask, val)) { - update.kcontrol = kcontrol; - update.reg = reg; - update.mask = mask; - update.val = val; - card->update = &update; - } + if (reg != SND_SOC_NOPM) { + mask = mask << shift; + val = val << shift; + + reg_change = snd_soc_test_bits(codec, reg, mask, val); + } + + if (change || reg_change) { + if (reg_change) { + update.kcontrol = kcontrol; + update.reg = reg; + update.mask = mask; + update.val = val; + card->update = &update; } + change |= reg_change; ret = soc_dapm_mixer_update_power(card, kcontrol, connect); -- cgit From 94f99c875c109e51decf0d8c25ec2c946db20c56 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 16 Jun 2014 18:13:01 +0200 Subject: ASoC: Move name_prefix from CODEC to component Move the name_prefix from the CODEC struct to the component struct. This will eventually allow to specify prefixes for all types of components. It is also necessary to make the DAPM code component type independent (i.e. a DAPM context does not need to know whether it belongs to a CODEC or a platform or something else). Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 12 ++++++------ sound/soc/soc-dapm.c | 36 ++++++++++++++++++++++-------------- 2 files changed, 28 insertions(+), 20 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b87d7d882e6d..ba822e927187 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1108,7 +1108,7 @@ static void soc_remove_dai_links(struct snd_soc_card *card) } static void soc_set_name_prefix(struct snd_soc_card *card, - struct snd_soc_codec *codec) + struct snd_soc_component *component) { int i; @@ -1117,11 +1117,11 @@ static void soc_set_name_prefix(struct snd_soc_card *card, for (i = 0; i < card->num_configs; i++) { struct snd_soc_codec_conf *map = &card->codec_conf[i]; - if (map->of_node && codec->dev->of_node != map->of_node) + if (map->of_node && component->dev->of_node != map->of_node) continue; - if (map->dev_name && strcmp(codec->name, map->dev_name)) + if (map->dev_name && strcmp(component->name, map->dev_name)) continue; - codec->name_prefix = map->name_prefix; + component->name_prefix = map->name_prefix; break; } } @@ -1135,7 +1135,7 @@ static int soc_probe_codec(struct snd_soc_card *card, codec->card = card; codec->dapm.card = card; - soc_set_name_prefix(card, codec); + soc_set_name_prefix(card, &codec->component); if (!try_module_get(codec->dev->driver->owner)) return -ENODEV; @@ -2403,7 +2403,7 @@ int snd_soc_add_codec_controls(struct snd_soc_codec *codec, struct snd_card *card = codec->card->snd_card; return snd_soc_add_controls(card, codec->dev, controls, num_controls, - codec->name_prefix, &codec->component); + codec->component.name_prefix, &codec->component); } EXPORT_SYMBOL_GPL(snd_soc_add_codec_controls); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index a74b9bf23d9f..2f29b289a333 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -375,6 +375,13 @@ static void dapm_reset(struct snd_soc_card *card) } } +static const char *soc_dapm_prefix(struct snd_soc_dapm_context *dapm) +{ + if (!dapm->component) + return NULL; + return dapm->component->name_prefix; +} + static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg, unsigned int *value) { @@ -570,11 +577,7 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, const char *name; int ret; - if (dapm->codec) - prefix = dapm->codec->name_prefix; - else - prefix = NULL; - + prefix = soc_dapm_prefix(dapm); if (prefix) prefix_len = strlen(prefix) + 1; else @@ -2371,14 +2374,16 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, const char *source; char prefixed_sink[80]; char prefixed_source[80]; + const char *prefix; int ret; - if (dapm->codec && dapm->codec->name_prefix) { + prefix = soc_dapm_prefix(dapm); + if (prefix) { snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", - dapm->codec->name_prefix, route->sink); + prefix, route->sink); sink = prefixed_sink; snprintf(prefixed_source, sizeof(prefixed_source), "%s %s", - dapm->codec->name_prefix, route->source); + prefix, route->source); source = prefixed_source; } else { sink = route->sink; @@ -2439,6 +2444,7 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, const char *source; char prefixed_sink[80]; char prefixed_source[80]; + const char *prefix; if (route->control) { dev_err(dapm->dev, @@ -2446,12 +2452,13 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, return -EINVAL; } - if (dapm->codec && dapm->codec->name_prefix) { + prefix = soc_dapm_prefix(dapm); + if (prefix) { snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", - dapm->codec->name_prefix, route->sink); + prefix, route->sink); sink = prefixed_sink; snprintf(prefixed_source, sizeof(prefixed_source), "%s %s", - dapm->codec->name_prefix, route->source); + prefix, route->source); source = prefixed_source; } else { sink = route->sink; @@ -2968,6 +2975,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, const struct snd_soc_dapm_widget *widget) { struct snd_soc_dapm_widget *w; + const char *prefix; int ret; if ((w = dapm_cnew_widget(widget)) == NULL) @@ -3008,9 +3016,9 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, break; } - if (dapm->codec && dapm->codec->name_prefix) - w->name = kasprintf(GFP_KERNEL, "%s %s", - dapm->codec->name_prefix, widget->name); + prefix = soc_dapm_prefix(dapm); + if (prefix) + w->name = kasprintf(GFP_KERNEL, "%s %s", prefix, widget->name); else w->name = kasprintf(GFP_KERNEL, "%s", widget->name); -- cgit From f4333203ec933f9272c90c7add01774ec2cf94d3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 16 Jun 2014 18:13:02 +0200 Subject: ASoC: Move name and id from CODEC/platform to component The component struct already has a name and id field which are initialized to the same values as the same fields in the CODEC and platform structs. So remove them from the CODEC and platform structs and used the ones from the component struct instead. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320dac33.c | 2 +- sound/soc/soc-cache.c | 7 +++--- sound/soc/soc-compress.c | 8 ++++--- sound/soc/soc-core.c | 53 ++++++++++++++++-------------------------- sound/soc/soc-dapm.c | 8 +++---- sound/soc/soc-pcm.c | 4 ++-- 6 files changed, 35 insertions(+), 47 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index df3a7506c023..ff006cc95520 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -1404,7 +1404,7 @@ static int dac33_soc_probe(struct snd_soc_codec *codec) if (dac33->irq >= 0) { ret = request_irq(dac33->irq, dac33_interrupt_handler, IRQF_TRIGGER_RISING, - codec->name, codec); + codec->component.name, codec); if (ret < 0) { dev_err(codec->dev, "Could not request IRQ%d (%d)\n", dac33->irq, ret); diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 00e70b6c7da2..a9f82b5aba9d 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -78,7 +78,7 @@ int snd_soc_cache_init(struct snd_soc_codec *codec) mutex_init(&codec->cache_rw_mutex); dev_dbg(codec->dev, "ASoC: Initializing cache for %s codec\n", - codec->name); + codec->component.name); if (codec_drv->reg_cache_default) codec->reg_cache = kmemdup(codec_drv->reg_cache_default, @@ -98,8 +98,7 @@ int snd_soc_cache_init(struct snd_soc_codec *codec) int snd_soc_cache_exit(struct snd_soc_codec *codec) { dev_dbg(codec->dev, "ASoC: Destroying cache for %s codec\n", - codec->name); - + codec->component.name); kfree(codec->reg_cache); codec->reg_cache = NULL; return 0; @@ -192,7 +191,7 @@ int snd_soc_cache_sync(struct snd_soc_codec *codec) return 0; dev_dbg(codec->dev, "ASoC: Syncing cache for %s codec\n", - codec->name); + codec->component.name); trace_snd_soc_cache_sync(codec, name, "start"); ret = snd_soc_flat_cache_sync(codec); if (!ret) diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 10f7f1da2aca..f96fb96b2678 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -37,7 +37,8 @@ static int soc_compr_open(struct snd_compr_stream *cstream) if (platform->driver->compr_ops && platform->driver->compr_ops->open) { ret = platform->driver->compr_ops->open(cstream); if (ret < 0) { - pr_err("compress asoc: can't open platform %s\n", platform->name); + pr_err("compress asoc: can't open platform %s\n", + platform->component.name); goto out; } } @@ -84,7 +85,8 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) if (platform->driver->compr_ops && platform->driver->compr_ops->open) { ret = platform->driver->compr_ops->open(cstream); if (ret < 0) { - pr_err("compress asoc: can't open platform %s\n", platform->name); + pr_err("compress asoc: can't open platform %s\n", + platform->component.name); goto out; } } @@ -680,7 +682,7 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) ret = snd_compress_new(rtd->card->snd_card, num, direction, compr); if (ret < 0) { pr_err("compress asoc: can't create compress for codec %s\n", - codec->name); + codec->component.name); goto compr_err; } diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index ba822e927187..b8cc88a9f947 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -274,7 +274,7 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec) { struct dentry *debugfs_card_root = codec->card->debugfs_card_root; - codec->debugfs_codec_root = debugfs_create_dir(codec->name, + codec->debugfs_codec_root = debugfs_create_dir(codec->component.name, debugfs_card_root); if (!codec->debugfs_codec_root) { dev_warn(codec->dev, @@ -306,8 +306,8 @@ static void soc_init_platform_debugfs(struct snd_soc_platform *platform) { struct dentry *debugfs_card_root = platform->card->debugfs_card_root; - platform->debugfs_platform_root = debugfs_create_dir(platform->name, - debugfs_card_root); + platform->debugfs_platform_root = debugfs_create_dir( + platform->component.name, debugfs_card_root); if (!platform->debugfs_platform_root) { dev_warn(platform->dev, "ASoC: Failed to create platform debugfs directory\n"); @@ -335,7 +335,7 @@ static ssize_t codec_list_read_file(struct file *file, char __user *user_buf, list_for_each_entry(codec, &codec_list, list) { len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", - codec->name); + codec->component.name); if (len >= 0) ret += len; if (ret > PAGE_SIZE) { @@ -406,7 +406,7 @@ static ssize_t platform_list_read_file(struct file *file, list_for_each_entry(platform, &platform_list, list) { len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", - platform->name); + platform->component.name); if (len >= 0) ret += len; if (ret > PAGE_SIZE) { @@ -528,7 +528,7 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec) codec->ac97->dev.release = soc_ac97_device_release; dev_set_name(&codec->ac97->dev, "%d-%d:%s", - codec->card->snd_card->number, 0, codec->name); + codec->card->snd_card->number, 0, codec->component.name); err = device_register(&codec->ac97->dev); if (err < 0) { dev_err(codec->dev, "ASoC: Can't register ac97 bus\n"); @@ -857,7 +857,7 @@ static struct snd_soc_codec *soc_find_codec(const struct device_node *codec_of_n if (codec->dev->of_node != codec_of_node) continue; } else { - if (strcmp(codec->name, codec_name)) + if (strcmp(codec->component.name, codec_name)) continue; } @@ -945,7 +945,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) dai_link->platform_of_node) continue; } else { - if (strcmp(platform->name, platform_name)) + if (strcmp(platform->component.name, platform_name)) continue; } @@ -1177,7 +1177,7 @@ static int soc_probe_codec(struct snd_soc_card *card, WARN(codec->dapm.idle_bias_off && codec->dapm.bias_level != SND_SOC_BIAS_OFF, "codec %s can not start from non-off bias with idle_bias_off==1\n", - codec->name); + codec->component.name); } if (driver->controls) @@ -1647,7 +1647,8 @@ static struct snd_soc_codec *soc_find_matching_codec(struct snd_soc_card *card, if (aux_dev->codec_of_node && (codec->dev->of_node != aux_dev->codec_of_node)) continue; - if (aux_dev->codec_name && strcmp(codec->name, aux_dev->codec_name)) + if (aux_dev->codec_name && + strcmp(codec->component.name, aux_dev->codec_name)) continue; return codec; } @@ -4131,11 +4132,6 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, { int ret; - /* create platform component name */ - platform->name = fmt_single_name(dev, &platform->id); - if (platform->name == NULL) - return -ENOMEM; - platform->dev = dev; platform->driver = platform_drv; platform->dapm.dev = dev; @@ -4161,7 +4157,8 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, list_add(&platform->list, &platform_list); mutex_unlock(&client_mutex); - dev_dbg(dev, "ASoC: Registered platform '%s'\n", platform->name); + dev_dbg(dev, "ASoC: Registered platform '%s'\n", + platform->component.name); return 0; } @@ -4205,8 +4202,7 @@ void snd_soc_remove_platform(struct snd_soc_platform *platform) mutex_unlock(&client_mutex); dev_dbg(platform->dev, "ASoC: Unregistered platform '%s'\n", - platform->name); - kfree(platform->name); + platform->component.name); } EXPORT_SYMBOL_GPL(snd_soc_remove_platform); @@ -4312,13 +4308,6 @@ int snd_soc_register_codec(struct device *dev, if (codec == NULL) return -ENOMEM; - /* create CODEC component name */ - codec->name = fmt_single_name(dev, &codec->id); - if (codec->name == NULL) { - ret = -ENOMEM; - goto fail_codec; - } - if (codec_drv->write) codec->component.write = snd_soc_codec_drv_write; if (codec_drv->read) @@ -4368,19 +4357,17 @@ int snd_soc_register_codec(struct device *dev, codec, dai_drv, num_dai, false); if (ret < 0) { dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret); - goto fail_codec_name; + goto fail_codec; } - dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n", codec->name); + dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n", + codec->component.name); return 0; -fail_codec_name: +fail_codec: mutex_lock(&client_mutex); list_del(&codec->list); mutex_unlock(&client_mutex); - - kfree(codec->name); -fail_codec: kfree(codec); return ret; } @@ -4408,10 +4395,10 @@ found: list_del(&codec->list); mutex_unlock(&client_mutex); - dev_dbg(codec->dev, "ASoC: Unregistered codec '%s'\n", codec->name); + dev_dbg(codec->dev, "ASoC: Unregistered codec '%s'\n", + codec->component.name); snd_soc_cache_exit(codec); - kfree(codec->name); kfree(codec); } EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 2f29b289a333..074e9ce136f8 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3400,8 +3400,8 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) source = cpu_dai->playback_widget; sink = codec_dai->playback_widget; dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", - cpu_dai->codec->name, source->name, - codec_dai->platform->name, sink->name); + cpu_dai->component->name, source->name, + codec_dai->component->name, sink->name); snd_soc_dapm_add_path(&card->dapm, source, sink, NULL, NULL); @@ -3412,8 +3412,8 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) source = codec_dai->capture_widget; sink = cpu_dai->capture_widget; dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", - codec_dai->codec->name, source->name, - cpu_dai->platform->name, sink->name); + codec_dai->component->name, source->name, + cpu_dai->component->name, sink->name); snd_soc_dapm_add_path(&card->dapm, source, sink, NULL, NULL); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 54d18f22a33e..9b78bb619bec 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -376,7 +376,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) ret = platform->driver->ops->open(substream); if (ret < 0) { dev_err(platform->dev, "ASoC: can't open platform" - " %s: %d\n", platform->name, ret); + " %s: %d\n", platform->component.name, ret); goto platform_err; } } @@ -707,7 +707,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, ret = platform->driver->ops->hw_params(substream, params); if (ret < 0) { dev_err(platform->dev, "ASoC: %s hw params failed: %d\n", - platform->name, ret); + platform->component.name, ret); goto platform_err; } } -- cgit From bb13109d85ba5f8009f1a26d840e70198537a4e3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 16 Jun 2014 18:13:03 +0200 Subject: 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 Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 177 ++++++++++++++++++++++++++------------------------- 1 file changed, 91 insertions(+), 86 deletions(-) (limited to 'sound/soc') 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) * snd_soc_register_dais - Register a DAI with the ASoC core * * @component: The component the DAIs are registered for - * @codec: The CODEC that the DAIs are registered for, NULL if the component is - * not a CODEC. * @dai_drv: DAI driver to use for the DAIs * @count: Number of DAIs * @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the * parent's name. */ static int snd_soc_register_dais(struct snd_soc_component *component, - struct snd_soc_codec *codec, struct snd_soc_dai_driver *dai_drv, - size_t count, bool legacy_dai_naming) + struct snd_soc_dai_driver *dai_drv, size_t count, + bool legacy_dai_naming) { struct device *dev = component->dev; struct snd_soc_dai *dai; @@ -3940,6 +3938,9 @@ static int snd_soc_register_dais(struct snd_soc_component *component, dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count); + component->dai_drv = dai_drv; + component->num_dai = count; + for (i = 0; i < count; i++) { dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); @@ -3972,7 +3973,6 @@ static int snd_soc_register_dais(struct snd_soc_component *component, } dai->component = component; - dai->codec = codec; dai->dev = dev; dai->driver = &dai_drv[i]; dai->dapm.dev = dev; @@ -3995,60 +3995,52 @@ err: return ret; } -/** - * snd_soc_register_component - Register a component with the ASoC core - * - */ -static int -__snd_soc_register_component(struct device *dev, - struct snd_soc_component *cmpnt, - const struct snd_soc_component_driver *cmpnt_drv, - struct snd_soc_codec *codec, - struct snd_soc_dai_driver *dai_drv, - int num_dai, bool allow_single_dai) +static int snd_soc_component_initialize(struct snd_soc_component *component, + const struct snd_soc_component_driver *driver, struct device *dev) { - int ret; - - dev_dbg(dev, "component register %s\n", dev_name(dev)); - - if (!cmpnt) { - dev_err(dev, "ASoC: Failed to connecting component\n"); + component->name = fmt_single_name(dev, &component->id); + if (!component->name) { + dev_err(dev, "ASoC: Failed to allocate name\n"); return -ENOMEM; } - mutex_init(&cmpnt->io_mutex); + component->dev = dev; + component->driver = driver; - cmpnt->name = fmt_single_name(dev, &cmpnt->id); - if (!cmpnt->name) { - dev_err(dev, "ASoC: Failed to simplifying name\n"); - return -ENOMEM; - } + INIT_LIST_HEAD(&component->dai_list); + mutex_init(&component->io_mutex); - cmpnt->dev = dev; - cmpnt->driver = cmpnt_drv; - cmpnt->dai_drv = dai_drv; - cmpnt->num_dai = num_dai; - INIT_LIST_HEAD(&cmpnt->dai_list); + return 0; +} - ret = snd_soc_register_dais(cmpnt, codec, dai_drv, num_dai, - allow_single_dai); - if (ret < 0) { - dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); - goto error_component_name; - } +static void snd_soc_component_add_unlocked(struct snd_soc_component *component) +{ + list_add(&component->list, &component_list); +} +static void snd_soc_component_add(struct snd_soc_component *component) +{ mutex_lock(&client_mutex); - list_add(&cmpnt->list, &component_list); + snd_soc_component_add_unlocked(component); mutex_unlock(&client_mutex); +} - dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name); - - return ret; +static void snd_soc_component_cleanup(struct snd_soc_component *component) +{ + snd_soc_unregister_dais(component); + kfree(component->name); +} -error_component_name: - kfree(cmpnt->name); +static void snd_soc_component_del_unlocked(struct snd_soc_component *component) +{ + list_del(&component->list); +} - return ret; +static void snd_soc_component_del(struct snd_soc_component *component) +{ + mutex_lock(&client_mutex); + snd_soc_component_del_unlocked(component); + mutex_unlock(&client_mutex); } int snd_soc_register_component(struct device *dev, @@ -4057,32 +4049,38 @@ int snd_soc_register_component(struct device *dev, int num_dai) { struct snd_soc_component *cmpnt; + int ret; - cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL); + cmpnt = kzalloc(sizeof(*cmpnt), GFP_KERNEL); if (!cmpnt) { dev_err(dev, "ASoC: Failed to allocate memory\n"); return -ENOMEM; } + ret = snd_soc_component_initialize(cmpnt, cmpnt_drv, dev); + if (ret) + goto err_free; + cmpnt->ignore_pmdown_time = true; cmpnt->registered_as_component = true; - return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, NULL, - dai_drv, num_dai, true); -} -EXPORT_SYMBOL_GPL(snd_soc_register_component); + ret = snd_soc_register_dais(cmpnt, dai_drv, num_dai, true); + if (ret < 0) { + dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); + goto err_cleanup; + } -static void __snd_soc_unregister_component(struct snd_soc_component *cmpnt) -{ - snd_soc_unregister_dais(cmpnt); + snd_soc_component_add(cmpnt); - mutex_lock(&client_mutex); - list_del(&cmpnt->list); - mutex_unlock(&client_mutex); + return 0; - dev_dbg(cmpnt->dev, "ASoC: Unregistered component '%s'\n", cmpnt->name); - kfree(cmpnt->name); +err_cleanup: + snd_soc_component_cleanup(cmpnt); +err_free: + kfree(cmpnt); + return ret; } +EXPORT_SYMBOL_GPL(snd_soc_register_component); /** * snd_soc_unregister_component - Unregister a component from the ASoC core @@ -4099,7 +4097,9 @@ void snd_soc_unregister_component(struct device *dev) return; found: - __snd_soc_unregister_component(cmpnt); + snd_soc_component_del(cmpnt); + snd_soc_component_cleanup(cmpnt); + kfree(cmpnt); } EXPORT_SYMBOL_GPL(snd_soc_unregister_component); @@ -4132,6 +4132,11 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, { int ret; + ret = snd_soc_component_initialize(&platform->component, + &platform_drv->component_driver, dev); + if (ret) + return ret; + platform->dev = dev; platform->driver = platform_drv; platform->dapm.dev = dev; @@ -4143,17 +4148,8 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, if (platform_drv->read) platform->component.read = snd_soc_platform_drv_read; - /* register component */ - ret = __snd_soc_register_component(dev, &platform->component, - &platform_drv->component_driver, - NULL, NULL, 0, false); - if (ret < 0) { - dev_err(platform->component.dev, - "ASoC: Failed to register component: %d\n", ret); - return ret; - } - mutex_lock(&client_mutex); + snd_soc_component_add_unlocked(&platform->component); list_add(&platform->list, &platform_list); mutex_unlock(&client_mutex); @@ -4195,12 +4191,14 @@ EXPORT_SYMBOL_GPL(snd_soc_register_platform); */ void snd_soc_remove_platform(struct snd_soc_platform *platform) { - __snd_soc_unregister_component(&platform->component); mutex_lock(&client_mutex); list_del(&platform->list); + snd_soc_component_del_unlocked(&platform->component); mutex_unlock(&client_mutex); + snd_soc_component_cleanup(&platform->component); + dev_dbg(platform->dev, "ASoC: Unregistered platform '%s'\n", platform->component.name); } @@ -4299,6 +4297,7 @@ int snd_soc_register_codec(struct device *dev, int num_dai) { struct snd_soc_codec *codec; + struct snd_soc_dai *dai; struct regmap *regmap; int ret, i; @@ -4308,6 +4307,11 @@ int snd_soc_register_codec(struct device *dev, if (codec == NULL) return -ENOMEM; + ret = snd_soc_component_initialize(&codec->component, + &codec_drv->component_driver, dev); + if (ret) + goto err_free; + if (codec_drv->write) codec->component.write = snd_soc_codec_drv_write; if (codec_drv->read) @@ -4337,7 +4341,7 @@ int snd_soc_register_codec(struct device *dev, dev_err(codec->dev, "Failed to set cache I/O:%d\n", ret); - return ret; + goto err_cleanup; } } } @@ -4347,27 +4351,27 @@ int snd_soc_register_codec(struct device *dev, fixup_codec_formats(&dai_drv[i].capture); } + ret = snd_soc_register_dais(&codec->component, dai_drv, num_dai, false); + if (ret < 0) { + dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); + goto err_cleanup; + } + + list_for_each_entry(dai, &codec->component.dai_list, list) + dai->codec = codec; + mutex_lock(&client_mutex); + snd_soc_component_add_unlocked(&codec->component); list_add(&codec->list, &codec_list); mutex_unlock(&client_mutex); - /* register component */ - ret = __snd_soc_register_component(dev, &codec->component, - &codec_drv->component_driver, - codec, dai_drv, num_dai, false); - if (ret < 0) { - dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret); - goto fail_codec; - } - dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n", codec->component.name); return 0; -fail_codec: - mutex_lock(&client_mutex); - list_del(&codec->list); - mutex_unlock(&client_mutex); +err_cleanup: + snd_soc_component_cleanup(&codec->component); +err_free: kfree(codec); return ret; } @@ -4389,15 +4393,16 @@ void snd_soc_unregister_codec(struct device *dev) return; found: - __snd_soc_unregister_component(&codec->component); mutex_lock(&client_mutex); list_del(&codec->list); + snd_soc_component_del_unlocked(&codec->component); mutex_unlock(&client_mutex); dev_dbg(codec->dev, "ASoC: Unregistered codec '%s'\n", codec->component.name); + snd_soc_component_cleanup(&codec->component); snd_soc_cache_exit(codec); kfree(codec); } -- cgit From 7df3788410e674423375b88e2d95c46e4015f5f5 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 16 Jun 2014 18:13:04 +0200 Subject: ASoC: Auto disconnect pins from all DAPM contexts Currently only pins in CODEC DAPM contexts are automatically marked as non-connected if the card has the fully_routed flag set. This makes sense since widgets which qualify for auto-disconnection are only found in CODEC DAPM contexts. But with componentisation this is going to change, so consider all widgets for auto-disconnection. Also it is probably faster to walk the widgets list only once rather than once for each CODEC. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 3 +-- sound/soc/soc-dapm.c | 27 +++++++++++---------------- 2 files changed, 12 insertions(+), 18 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 0944da66538d..bca8a7150a4a 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1928,8 +1928,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) } if (card->fully_routed) - list_for_each_entry(codec, &card->codec_dev_list, card_list) - snd_soc_dapm_auto_nc_codec_pins(codec); + snd_soc_dapm_auto_nc_pins(card); snd_soc_dapm_new_widgets(card); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 074e9ce136f8..3ccbf9ba04b2 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3763,36 +3763,31 @@ static bool snd_soc_dapm_widget_in_card_paths(struct snd_soc_card *card, } /** - * snd_soc_dapm_auto_nc_codec_pins - call snd_soc_dapm_nc_pin for unused pins - * @codec: The codec whose pins should be processed + * snd_soc_dapm_auto_nc_pins - call snd_soc_dapm_nc_pin for unused pins + * @card: The card whose pins should be processed * - * Automatically call snd_soc_dapm_nc_pin() for any external pins in the codec - * which are unused. Pins are used if they are connected externally to the - * codec, whether that be to some other device, or a loop-back connection to - * the codec itself. + * Automatically call snd_soc_dapm_nc_pin() for any external pins in the card + * which are unused. Pins are used if they are connected externally to a + * component, whether that be to some other device, or a loop-back connection to + * the component itself. */ -void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec) +void snd_soc_dapm_auto_nc_pins(struct snd_soc_card *card) { - struct snd_soc_card *card = codec->card; - struct snd_soc_dapm_context *dapm = &codec->dapm; struct snd_soc_dapm_widget *w; - dev_dbg(codec->dev, "ASoC: Auto NC: DAPMs: card:%p codec:%p\n", - &card->dapm, &codec->dapm); + dev_dbg(card->dev, "ASoC: Auto NC: DAPMs: card:%p\n", &card->dapm); list_for_each_entry(w, &card->widgets, list) { - if (w->dapm != dapm) - continue; switch (w->id) { case snd_soc_dapm_input: case snd_soc_dapm_output: case snd_soc_dapm_micbias: - dev_dbg(codec->dev, "ASoC: Auto NC: Checking widget %s\n", + dev_dbg(card->dev, "ASoC: Auto NC: Checking widget %s\n", w->name); if (!snd_soc_dapm_widget_in_card_paths(card, w)) { - dev_dbg(codec->dev, + dev_dbg(card->dev, "... Not in map; disabling\n"); - snd_soc_dapm_nc_pin(dapm, w->name); + snd_soc_dapm_nc_pin(w->dapm, w->name); } break; default: -- cgit From 68f831c2724ab72c0088471b2ed1dc99e81948ef Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 16 Jun 2014 18:13:05 +0200 Subject: ASoC: Add a set_bias_level() callback to the DAPM context struct Currently the DAPM code directly looks at the CODEC driver struct to get a handle to the set_bias_level() callback. This patch adds a new set_bias_level() callback to the DAPM context struct. The DAPM code will use this new callback instead of the CODEC callback. For CODECs the new callback is set up to call the CODEC specific set_bias_level callback(). Not looking directly at the CODEC driver struct will allow non CODEC DAPM contexts to implement a set_bias_level() callback. This is also similar to how the seq_notifier() and stream_event() callbacks are currently handled. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 10 ++++++++++ sound/soc/soc-dapm.c | 11 +++-------- 2 files changed, 13 insertions(+), 8 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index bca8a7150a4a..10e13c43bc54 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -4285,6 +4285,14 @@ static int snd_soc_codec_drv_read(struct snd_soc_component *component, return 0; } +static int snd_soc_codec_set_bias_level(struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); + + return codec->driver->set_bias_level(codec, level); +} + /** * snd_soc_register_codec - Register a codec with the ASoC core * @@ -4322,6 +4330,8 @@ int snd_soc_register_codec(struct device *dev, codec->dapm.component = &codec->component; codec->dapm.seq_notifier = codec_drv->seq_notifier; codec->dapm.stream_event = codec_drv->stream_event; + if (codec_drv->set_bias_level) + codec->dapm.set_bias_level = snd_soc_codec_set_bias_level; codec->dev = dev; codec->driver = codec_drv; codec->component.val_bytes = codec_drv->reg_word_size; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index fab1a8813abf..6c94a6b3fce7 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -427,15 +427,10 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm, if (ret != 0) goto out; - if (dapm->codec) { - if (dapm->codec->driver->set_bias_level) - ret = dapm->codec->driver->set_bias_level(dapm->codec, - level); - else - dapm->bias_level = level; - } else if (!card || dapm != &card->dapm) { + if (dapm->set_bias_level) + ret = dapm->set_bias_level(dapm, level); + else if (!card || dapm != &card->dapm) dapm->bias_level = level; - } if (ret != 0) goto out; -- cgit From ce0fc93ae56e2ba50ff8c220d69e4e860e889320 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 16 Jun 2014 18:13:06 +0200 Subject: ASoC: Add DAPM support at the component level This patch adds full DAPM support at the component level. Previously there was only full DAPM support for CODECs and partial DAPM support (e.g. no Mixers nor MUXs) for platforms. Having DAPM support at the component level will allow all types of components to use DAPM and also help in consolidating the DAPM support between CODECs and platforms. Since the DAPM context is directly embedded into the snd_soc_codec and snd_soc_platform struct and the 'dapm' field is directly referenced in a lot of drivers moving the field just right now is not possible without causing code churn. The approach this patch takes is to add two new fields to the component struct. One field which is the pointer to the actual DAPM context used by the component and one DAPM context that will be used as the default if no other context was specified. For CODECs and platforms the pointer is initialized to point to the CODEC or platform DAPM context. All generic code when referencing a component's DAPM struct will go via the pointer. This will make it possible to eventually seamlessly move the DAPM context from snd_soc_codec and snd_soc_platform struct over once all direct references have been eliminated. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 19 +++++++--- sound/soc/soc-dapm.c | 100 ++++++++++++++++++++++++++++++++------------------- 2 files changed, 78 insertions(+), 41 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 10e13c43bc54..f519a9f7571c 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3997,6 +3997,8 @@ err: static int snd_soc_component_initialize(struct snd_soc_component *component, const struct snd_soc_component_driver *driver, struct device *dev) { + struct snd_soc_dapm_context *dapm; + component->name = fmt_single_name(dev, &component->id); if (!component->name) { dev_err(dev, "ASoC: Failed to allocate name\n"); @@ -4006,6 +4008,14 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, component->dev = dev; component->driver = driver; + if (!component->dapm_ptr) + component->dapm_ptr = &component->dapm; + + dapm = component->dapm_ptr; + dapm->dev = dev; + dapm->component = component; + dapm->bias_level = SND_SOC_BIAS_OFF; + INIT_LIST_HEAD(&component->dai_list); mutex_init(&component->io_mutex); @@ -4131,6 +4141,8 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, { int ret; + platform->component.dapm_ptr = &platform->dapm; + ret = snd_soc_component_initialize(&platform->component, &platform_drv->component_driver, dev); if (ret) @@ -4138,9 +4150,7 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, platform->dev = dev; platform->driver = platform_drv; - platform->dapm.dev = dev; platform->dapm.platform = platform; - platform->dapm.component = &platform->component; platform->dapm.stream_event = platform_drv->stream_event; if (platform_drv->write) platform->component.write = snd_soc_platform_drv_write; @@ -4314,6 +4324,8 @@ int snd_soc_register_codec(struct device *dev, if (codec == NULL) return -ENOMEM; + codec->component.dapm_ptr = &codec->dapm; + ret = snd_soc_component_initialize(&codec->component, &codec_drv->component_driver, dev); if (ret) @@ -4324,10 +4336,7 @@ int snd_soc_register_codec(struct device *dev, if (codec_drv->read) codec->component.read = snd_soc_codec_drv_read; codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time; - codec->dapm.bias_level = SND_SOC_BIAS_OFF; - codec->dapm.dev = dev; codec->dapm.codec = codec; - codec->dapm.component = &codec->component; codec->dapm.seq_notifier = codec_drv->seq_notifier; codec->dapm.stream_event = codec_drv->stream_event; if (codec_drv->set_bias_level) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 6c94a6b3fce7..4702b926a6a0 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -349,13 +349,28 @@ static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol, return true; } +/** + * snd_soc_dapm_kcontrol_dapm() - Returns the dapm context associated to a + * kcontrol + * @kcontrol: The kcontrol + * + * Note: This function must only be used on kcontrols that are known to have + * been registered for a CODEC. Otherwise the behaviour is undefined. + */ +struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm( + struct snd_kcontrol *kcontrol) +{ + return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->dapm; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_dapm); + /** * snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol * @kcontrol: The kcontrol */ struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol) { - return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->codec; + return snd_soc_dapm_to_codec(snd_soc_dapm_kcontrol_dapm(kcontrol)); } EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_codec); @@ -382,23 +397,31 @@ static const char *soc_dapm_prefix(struct snd_soc_dapm_context *dapm) return dapm->component->name_prefix; } -static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg, +static int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg, unsigned int *value) { - if (!w->dapm->component) + if (!dapm->component) return -EIO; - return snd_soc_component_read(w->dapm->component, reg, value); + return snd_soc_component_read(dapm->component, reg, value); } -static int soc_widget_update_bits(struct snd_soc_dapm_widget *w, +static int soc_dapm_update_bits(struct snd_soc_dapm_context *dapm, int reg, unsigned int mask, unsigned int value) { - if (!w->dapm->component) + if (!dapm->component) return -EIO; - return snd_soc_component_update_bits_async(w->dapm->component, reg, + return snd_soc_component_update_bits_async(dapm->component, reg, mask, value); } +static int soc_dapm_test_bits(struct snd_soc_dapm_context *dapm, + int reg, unsigned int mask, unsigned int value) +{ + if (!dapm->component) + return -EIO; + return snd_soc_component_test_bits(dapm->component, reg, mask, value); +} + static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm) { if (dapm->component) @@ -454,7 +477,7 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, int i; if (e->reg != SND_SOC_NOPM) { - soc_widget_read(dest, e->reg, &val); + soc_dapm_read(dapm, e->reg, &val); val = (val >> e->shift_l) & e->mask; item = snd_soc_enum_val_to_item(e, val); } else { @@ -498,7 +521,7 @@ static void dapm_set_mixer_path_status(struct snd_soc_dapm_widget *w, unsigned int val; if (reg != SND_SOC_NOPM) { - soc_widget_read(w, reg, &val); + soc_dapm_read(w->dapm, reg, &val); val = (val >> shift) & mask; if (invert) val = max - val; @@ -1306,16 +1329,18 @@ static void dapm_seq_check_event(struct snd_soc_card *card, static void dapm_seq_run_coalesced(struct snd_soc_card *card, struct list_head *pending) { + struct snd_soc_dapm_context *dapm; struct snd_soc_dapm_widget *w; int reg; unsigned int value = 0; unsigned int mask = 0; - reg = list_first_entry(pending, struct snd_soc_dapm_widget, - power_list)->reg; + w = list_first_entry(pending, struct snd_soc_dapm_widget, power_list); + reg = w->reg; + dapm = w->dapm; list_for_each_entry(w, pending, power_list) { - WARN_ON(reg != w->reg); + WARN_ON(reg != w->reg || dapm != w->dapm); w->power = w->new_power; mask |= w->mask << w->shift; @@ -1324,7 +1349,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_card *card, else value |= w->off_val << w->shift; - pop_dbg(w->dapm->dev, card->pop_time, + pop_dbg(dapm->dev, card->pop_time, "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n", w->name, reg, value, mask); @@ -1337,14 +1362,12 @@ static void dapm_seq_run_coalesced(struct snd_soc_card *card, /* Any widget will do, they should all be updating the * same register. */ - w = list_first_entry(pending, struct snd_soc_dapm_widget, - power_list); - pop_dbg(w->dapm->dev, card->pop_time, + pop_dbg(dapm->dev, card->pop_time, "pop test : Applying 0x%x/0x%x to %x in %dms\n", value, mask, reg, card->pop_time); pop_wait(card->pop_time); - soc_widget_update_bits(w, reg, mask, value); + soc_dapm_update_bits(dapm, reg, mask, value); } list_for_each_entry(w, pending, power_list) { @@ -1490,7 +1513,8 @@ static void dapm_widget_update(struct snd_soc_card *card) if (!w) return; - ret = soc_widget_update_bits(w, update->reg, update->mask, update->val); + ret = soc_dapm_update_bits(w->dapm, update->reg, update->mask, + update->val); if (ret < 0) dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n", w->name, ret); @@ -2672,7 +2696,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) /* Read the initial power state from the device */ if (w->reg >= 0) { - soc_widget_read(w, w->reg, &val); + soc_dapm_read(w->dapm, w->reg, &val); val = val >> w->shift; val &= w->mask; if (val == w->on_val) @@ -2703,8 +2727,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); - struct snd_soc_card *card = codec->card; + struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); + struct snd_soc_card *card = dapm->card; struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; int reg = mc->reg; @@ -2713,17 +2737,20 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; unsigned int val; + int ret = 0; if (snd_soc_volsw_is_stereo(mc)) - dev_warn(codec->dapm.dev, + dev_warn(dapm->dev, "ASoC: Control '%s' is stereo, which is not supported\n", kcontrol->id.name); mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) - val = (snd_soc_read(codec, reg) >> shift) & mask; - else + if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) { + ret = soc_dapm_read(dapm, reg, &val); + val = (val >> shift) & mask; + } else { val = dapm_kcontrol_get_value(kcontrol); + } mutex_unlock(&card->dapm_mutex); if (invert) @@ -2731,7 +2758,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, else ucontrol->value.integer.value[0] = val; - return 0; + return ret; } EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw); @@ -2747,8 +2774,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw); int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); - struct snd_soc_card *card = codec->card; + struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); + struct snd_soc_card *card = dapm->card; struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; int reg = mc->reg; @@ -2762,7 +2789,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, int ret = 0; if (snd_soc_volsw_is_stereo(mc)) - dev_warn(codec->dapm.dev, + dev_warn(dapm->dev, "ASoC: Control '%s' is stereo, which is not supported\n", kcontrol->id.name); @@ -2780,7 +2807,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, mask = mask << shift; val = val << shift; - reg_change = snd_soc_test_bits(codec, reg, mask, val); + reg_change = soc_dapm_test_bits(dapm, reg, mask, val); } if (change || reg_change) { @@ -2819,12 +2846,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); + struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int reg_val, val; + int ret = 0; if (e->reg != SND_SOC_NOPM) - reg_val = snd_soc_read(codec, e->reg); + ret = soc_dapm_read(dapm, e->reg, ®_val); else reg_val = dapm_kcontrol_get_value(kcontrol); @@ -2836,7 +2864,7 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, ucontrol->value.enumerated.item[1] = val; } - return 0; + return ret; } EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); @@ -2852,8 +2880,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); - struct snd_soc_card *card = codec->card; + struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); + struct snd_soc_card *card = dapm->card; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int *item = ucontrol->value.enumerated.item; unsigned int val, change; @@ -2876,7 +2904,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); if (e->reg != SND_SOC_NOPM) - change = snd_soc_test_bits(codec, e->reg, mask, val); + change = soc_dapm_test_bits(dapm, e->reg, mask, val); else change = dapm_kcontrol_set_value(kcontrol, val); -- cgit From bc9af9fa9b89cb74eed020066d882abf238fad69 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 16 Jun 2014 18:13:07 +0200 Subject: ASoC: Use component DAPM context for platforms The snd_soc_platform dapm field is not accessed outside of the ASoC core. Switch it over to using the snd_soc_component DAPM context. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f519a9f7571c..711e99c43be3 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -314,7 +314,7 @@ static void soc_init_platform_debugfs(struct snd_soc_platform *platform) return; } - snd_soc_dapm_debugfs_init(&platform->dapm, + snd_soc_dapm_debugfs_init(&platform->component.dapm, platform->debugfs_platform_root); } @@ -974,7 +974,7 @@ static int soc_remove_platform(struct snd_soc_platform *platform) } /* Make sure all DAPM widgets are freed */ - snd_soc_dapm_free(&platform->dapm); + snd_soc_dapm_free(&platform->component.dapm); soc_cleanup_platform_debugfs(platform); platform->probed = 0; @@ -1210,7 +1210,7 @@ static int soc_probe_platform(struct snd_soc_card *card, struct snd_soc_dai *dai; platform->card = card; - platform->dapm.card = card; + platform->component.dapm.card = card; if (!try_module_get(platform->dev->driver->owner)) return -ENODEV; @@ -1218,7 +1218,7 @@ static int soc_probe_platform(struct snd_soc_card *card, soc_init_platform_debugfs(platform); if (driver->dapm_widgets) - snd_soc_dapm_new_controls(&platform->dapm, + snd_soc_dapm_new_controls(&platform->component.dapm, driver->dapm_widgets, driver->num_dapm_widgets); /* Create DAPM widgets for each DAI stream */ @@ -1226,10 +1226,11 @@ static int soc_probe_platform(struct snd_soc_card *card, if (component->dev != platform->dev) continue; list_for_each_entry(dai, &component->dai_list, list) - snd_soc_dapm_new_dai_widgets(&platform->dapm, dai); + snd_soc_dapm_new_dai_widgets(&platform->component.dapm, + dai); } - platform->dapm.idle_bias_off = 1; + platform->component.dapm.idle_bias_off = 1; if (driver->probe) { ret = driver->probe(platform); @@ -1244,13 +1245,13 @@ static int soc_probe_platform(struct snd_soc_card *card, snd_soc_add_platform_controls(platform, driver->controls, driver->num_controls); if (driver->dapm_routes) - snd_soc_dapm_add_routes(&platform->dapm, driver->dapm_routes, - driver->num_dapm_routes); + snd_soc_dapm_add_routes(&platform->component.dapm, + driver->dapm_routes, driver->num_dapm_routes); /* mark platform as probed and add to card platform list */ platform->probed = 1; list_add(&platform->card_list, &card->platform_dev_list); - list_add(&platform->dapm.list, &card->dapm_list); + list_add(&platform->component.dapm.list, &card->dapm_list); return 0; @@ -4141,8 +4142,6 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, { int ret; - platform->component.dapm_ptr = &platform->dapm; - ret = snd_soc_component_initialize(&platform->component, &platform_drv->component_driver, dev); if (ret) @@ -4150,8 +4149,8 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, platform->dev = dev; platform->driver = platform_drv; - platform->dapm.platform = platform; - platform->dapm.stream_event = platform_drv->stream_event; + platform->component.dapm.platform = platform; + platform->component.dapm.stream_event = platform_drv->stream_event; if (platform_drv->write) platform->component.write = snd_soc_platform_drv_write; if (platform_drv->read) -- cgit From 14e8bdebfbc1d5c8804b3520233b2d4e516056bc Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 16 Jun 2014 18:13:08 +0200 Subject: ASoC: Add component level stream_event() and seq_notifier() support This patch adds stream_event() and seq_notifier() callbacks similar to those found in the snd_soc_codec_driver and snd_soc_platform driver struct to the snd_soc_component_driver struct. This is meant to unify the handling of these callbacks across different types of components and will eventually allow their removal from the CODEC and platfrom driver structs. The new callbacks are slightly different from the old ones in that they take a snd_soc_component as a parameter rather than a snd_soc_dapm_context. This was done since otherwise casting from the DAPM context to the component would typically be the first thing to do in the callback. And the interface becomes slightly cleaner by passing a snd_soc_component to all callbacks in the snd_soc_component_driver struct. The patch also already removes the stream_event() callback from the snd_soc_codec_driver and snd_soc_platform_driver structs as it is currently unused. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 711e99c43be3..5fe732fdfd59 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3995,6 +3995,22 @@ err: return ret; } +static void snd_soc_component_seq_notifier(struct snd_soc_dapm_context *dapm, + enum snd_soc_dapm_type type, int subseq) +{ + struct snd_soc_component *component = dapm->component; + + component->driver->seq_notifier(component, type, subseq); +} + +static int snd_soc_component_stream_event(struct snd_soc_dapm_context *dapm, + int event) +{ + struct snd_soc_component *component = dapm->component; + + return component->driver->stream_event(component, event); +} + static int snd_soc_component_initialize(struct snd_soc_component *component, const struct snd_soc_component_driver *driver, struct device *dev) { @@ -4016,6 +4032,10 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, dapm->dev = dev; dapm->component = component; dapm->bias_level = SND_SOC_BIAS_OFF; + if (driver->seq_notifier) + dapm->seq_notifier = snd_soc_component_seq_notifier; + if (driver->stream_event) + dapm->stream_event = snd_soc_component_stream_event; INIT_LIST_HEAD(&component->dai_list); mutex_init(&component->io_mutex); @@ -4150,7 +4170,6 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, platform->dev = dev; platform->driver = platform_drv; platform->component.dapm.platform = platform; - platform->component.dapm.stream_event = platform_drv->stream_event; if (platform_drv->write) platform->component.write = snd_soc_platform_drv_write; if (platform_drv->read) @@ -4336,8 +4355,8 @@ int snd_soc_register_codec(struct device *dev, codec->component.read = snd_soc_codec_drv_read; codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time; codec->dapm.codec = codec; - codec->dapm.seq_notifier = codec_drv->seq_notifier; - codec->dapm.stream_event = codec_drv->stream_event; + if (codec_drv->seq_notifier) + codec->dapm.seq_notifier = codec_drv->seq_notifier; if (codec_drv->set_bias_level) codec->dapm.set_bias_level = snd_soc_codec_set_bias_level; codec->dev = dev; -- cgit From 9420d97b3f8672478696ae9c3e33051243e1f4a0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 16 Jun 2014 18:13:10 +0200 Subject: ASoC: dapm: Remove DAI DAPM context The DAI DAPM context was added in commit be09ad90 ("ASoC: core: Add platform DAI widget mapping") and the only user was removed again in commit ae10e7e8f ("ASoC: core: Only add platform DAI widgets once."). Now that we have a per component DAPM context it is unlikely that we'll need the DAI DAPM context again. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 5fe732fdfd59..995a4b7f87eb 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1048,11 +1048,8 @@ static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order) cpu_dai->name, err); } cpu_dai->probed = 0; - - if (!cpu_dai->codec) { - snd_soc_dapm_free(&cpu_dai->dapm); + if (!cpu_dai->codec) module_put(cpu_dai->dev->driver->owner); - } } } @@ -1510,11 +1507,8 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) if (!cpu_dai->probed && cpu_dai->driver->probe_order == order) { if (!cpu_dai->codec) { - cpu_dai->dapm.card = card; if (!try_module_get(cpu_dai->dev->driver->owner)) return -ENODEV; - - list_add(&cpu_dai->dapm.list, &card->dapm_list); } if (cpu_dai->driver->probe) { @@ -3975,13 +3969,9 @@ static int snd_soc_register_dais(struct snd_soc_component *component, dai->component = component; dai->dev = dev; dai->driver = &dai_drv[i]; - dai->dapm.dev = dev; if (!dai->driver->ops) dai->driver->ops = &null_dai_ops; - if (!dai->codec) - dai->dapm.idle_bias_off = 1; - list_add(&dai->list, &component->dai_list); dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name); -- cgit From 88a8fe3df65fa0229b04f1c03411062230091cdd Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 16 Jun 2014 18:13:11 +0200 Subject: ASoC: dapm: Remove platform field from widget and dapm context struct The platform field in the snd_soc_dapm_widget and snd_soc_dapm_context structs is now unused can be removed. New code that wants to get the platform for a widget or dapm context should use snd_soc_dapm_to_platform(w->dapm) or snd_soc_dapm_to_platform(dapm). Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 1 - sound/soc/soc-dapm.c | 1 - 2 files changed, 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 995a4b7f87eb..19c1e9588e05 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -4159,7 +4159,6 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, platform->dev = dev; platform->driver = platform_drv; - platform->component.dapm.platform = platform; if (platform_drv->write) platform->component.write = snd_soc_platform_drv_write; if (platform_drv->read) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 4702b926a6a0..4bf08cffd1f1 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3097,7 +3097,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, w->dapm = dapm; w->codec = dapm->codec; - w->platform = dapm->platform; INIT_LIST_HEAD(&w->sources); INIT_LIST_HEAD(&w->sinks); INIT_LIST_HEAD(&w->list); -- cgit From e73f3de5c5eb5285a1b1d8eed111eb229702b20f Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 26 Jun 2014 15:22:50 +0100 Subject: ASoC: fix debugfs directory creation bug Avoid creating duplicate directories by prefixing codecs and platforms with their separate identifiers. This avoids snd-soc-dummy (which can appear both as a dummy platform and a dummy codec on the same card) from clashing. Signed-off-by: Russell King Tested-by: Andrew Lunn Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b87d7d882e6d..91120b8e283e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -270,12 +270,32 @@ static const struct file_operations codec_reg_fops = { .llseek = default_llseek, }; +static struct dentry *soc_debugfs_create_dir(struct dentry *parent, + const char *fmt, ...) +{ + struct dentry *de; + va_list ap; + char *s; + + va_start(ap, fmt); + s = kvasprintf(GFP_KERNEL, fmt, ap); + va_end(ap); + + if (!s) + return NULL; + + de = debugfs_create_dir(s, parent); + kfree(s); + + return de; +} + static void soc_init_codec_debugfs(struct snd_soc_codec *codec) { struct dentry *debugfs_card_root = codec->card->debugfs_card_root; - codec->debugfs_codec_root = debugfs_create_dir(codec->name, - debugfs_card_root); + codec->debugfs_codec_root = soc_debugfs_create_dir(debugfs_card_root, + "codec:%s", codec->name); if (!codec->debugfs_codec_root) { dev_warn(codec->dev, "ASoC: Failed to create codec debugfs directory\n"); @@ -306,8 +326,8 @@ static void soc_init_platform_debugfs(struct snd_soc_platform *platform) { struct dentry *debugfs_card_root = platform->card->debugfs_card_root; - platform->debugfs_platform_root = debugfs_create_dir(platform->name, - debugfs_card_root); + platform->debugfs_platform_root = soc_debugfs_create_dir(debugfs_card_root, + "platform:%s", platform->name); if (!platform->debugfs_platform_root) { dev_warn(platform->dev, "ASoC: Failed to create platform debugfs directory\n"); -- cgit From b8257be5fff447681af8c8b72f1380e8a9c04286 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 1 Jul 2014 22:13:45 +0200 Subject: ASoC: core: Remove duplicated rtd->codec initialization rtd->codec is already initialized in soc_bind_dai_link(), so there is no need to do it again in soc_dai_link_init(). Removing the rtd->codec initialization from soc_dai_link_init() also removes the need for soc_dai_link_init() to know about the CODEC at all. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 72d4a2b009fa..0cd36b781f4d 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1308,9 +1308,7 @@ static int soc_aux_dev_init(struct snd_soc_card *card, return 0; } -static int soc_dai_link_init(struct snd_soc_card *card, - struct snd_soc_codec *codec, - int num) +static int soc_dai_link_init(struct snd_soc_card *card, int num) { struct snd_soc_dai_link *dai_link = &card->dai_link[num]; struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; @@ -1325,8 +1323,6 @@ static int soc_dai_link_init(struct snd_soc_card *card, return ret; } - rtd->codec = codec; - return 0; } @@ -1344,7 +1340,7 @@ static int soc_post_component_init(struct snd_soc_card *card, dai_link = &card->dai_link[num]; rtd = &card->rtd[num]; name = dai_link->name; - ret = soc_dai_link_init(card, codec, num); + ret = soc_dai_link_init(card, num); } else { aux_dev = &card->aux_dev[num]; rtd = &card->rtd_aux[num]; -- cgit From 48f466d112c9ca735ee765d8f5148d07a8c7bb1d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 1 Jul 2014 22:13:46 +0200 Subject: ASoC: core: Replace soc_find_matching_codec() with soc_find_codec() soc_find_matching_codec() works in the same way as soc_find_codec() except that it only works for auxdevs. It can easily be replaced by the generic soc_find_codec(). Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 0cd36b781f4d..c8bdac2db377 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1649,32 +1649,13 @@ static void soc_unregister_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) } #endif -static struct snd_soc_codec *soc_find_matching_codec(struct snd_soc_card *card, - int num) -{ - struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; - struct snd_soc_codec *codec; - - /* find CODEC from registered CODECs */ - list_for_each_entry(codec, &codec_list, list) { - if (aux_dev->codec_of_node && - (codec->dev->of_node != aux_dev->codec_of_node)) - continue; - if (aux_dev->codec_name && - strcmp(codec->component.name, aux_dev->codec_name)) - continue; - return codec; - } - - return NULL; -} - static int soc_check_aux_dev(struct snd_soc_card *card, int num) { struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; const char *codecname = aux_dev->codec_name; - struct snd_soc_codec *codec = soc_find_matching_codec(card, num); + struct snd_soc_codec *codec; + codec = soc_find_codec(aux_dev->codec_of_node, aux_dev->codec_name); if (codec) return 0; if (aux_dev->codec_of_node) @@ -1689,8 +1670,9 @@ static int soc_probe_aux_dev(struct snd_soc_card *card, int num) struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; const char *codecname = aux_dev->codec_name; int ret = -ENODEV; - struct snd_soc_codec *codec = soc_find_matching_codec(card, num); + struct snd_soc_codec *codec; + codec = soc_find_codec(aux_dev->codec_of_node, aux_dev->codec_name); if (!codec) { if (aux_dev->codec_of_node) codecname = of_node_full_name(aux_dev->codec_of_node); -- cgit From 44c69bb13905c3b2281a920c0b44059e88819993 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 1 Jul 2014 22:13:47 +0200 Subject: ASoC: core: Bind aux devs early Currently in snd_soc_instantiate_card() we only check if the aux dev exists, but do not yet assign it to its rtd. This means that we need to lookup the aux dev again in soc_probe_aux_dev(). This patch changes the behavior to assign the aux dev to the rtd in soc_check_aux_dev() (and renames it to soc_bind_aux_dev()). This simplifies the implementation a bit and also removes the need for soc_post_component_init() to know about the specific CODEC that was assigned to the rtd. The later is necessary for componentization as the code should work for all types of components not just CODECs. This new behavior is also more in sync with how soc_bind_dai_link()/soc_probe_link_dais() works. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 67 ++++++++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 42 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index c8bdac2db377..b1600cdcdc14 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1286,9 +1286,7 @@ static void rtd_release(struct device *dev) kfree(dev); } -static int soc_aux_dev_init(struct snd_soc_card *card, - struct snd_soc_codec *codec, - int num) +static int soc_aux_dev_init(struct snd_soc_card *card, int num) { struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; @@ -1298,13 +1296,11 @@ static int soc_aux_dev_init(struct snd_soc_card *card, /* do machine specific initialization */ if (aux_dev->init) { - ret = aux_dev->init(&codec->dapm); + ret = aux_dev->init(&rtd->codec->dapm); if (ret < 0) return ret; } - rtd->codec = codec; - return 0; } @@ -1327,7 +1323,6 @@ static int soc_dai_link_init(struct snd_soc_card *card, int num) } static int soc_post_component_init(struct snd_soc_card *card, - struct snd_soc_codec *codec, int num, int dailess) { struct snd_soc_dai_link *dai_link = NULL; @@ -1345,7 +1340,7 @@ static int soc_post_component_init(struct snd_soc_card *card, aux_dev = &card->aux_dev[num]; rtd = &card->rtd_aux[num]; name = aux_dev->name; - ret = soc_aux_dev_init(card, codec, num); + ret = soc_aux_dev_init(card, num); } if (ret < 0) { @@ -1380,13 +1375,13 @@ static int soc_post_component_init(struct snd_soc_card *card, /* add DAPM sysfs entries for this codec */ ret = snd_soc_dapm_sys_add(rtd->dev); if (ret < 0) - dev_err(codec->dev, + dev_err(rtd->dev, "ASoC: failed to add codec dapm sysfs entries: %d\n", ret); /* add codec sysfs entries */ ret = device_create_file(rtd->dev, &dev_attr_codec_reg); if (ret < 0) - dev_err(codec->dev, + dev_err(rtd->dev, "ASoC: failed to add codec sysfs files: %d\n", ret); #ifdef CONFIG_DEBUG_FS @@ -1551,7 +1546,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) if (order != SND_SOC_COMP_ORDER_LAST) return 0; - ret = soc_post_component_init(card, codec, num, 0); + ret = soc_post_component_init(card, num, 0); if (ret) return ret; @@ -1649,51 +1644,39 @@ static void soc_unregister_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) } #endif -static int soc_check_aux_dev(struct snd_soc_card *card, int num) -{ - struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; - const char *codecname = aux_dev->codec_name; - struct snd_soc_codec *codec; - - codec = soc_find_codec(aux_dev->codec_of_node, aux_dev->codec_name); - if (codec) - return 0; - if (aux_dev->codec_of_node) - codecname = of_node_full_name(aux_dev->codec_of_node); - - dev_err(card->dev, "ASoC: %s not registered\n", codecname); - return -EPROBE_DEFER; -} - -static int soc_probe_aux_dev(struct snd_soc_card *card, int num) +static int soc_bind_aux_dev(struct snd_soc_card *card, int num) { + struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; const char *codecname = aux_dev->codec_name; - int ret = -ENODEV; - struct snd_soc_codec *codec; - codec = soc_find_codec(aux_dev->codec_of_node, aux_dev->codec_name); - if (!codec) { + rtd->codec = soc_find_codec(aux_dev->codec_of_node, codecname); + if (!rtd->codec) { if (aux_dev->codec_of_node) codecname = of_node_full_name(aux_dev->codec_of_node); - /* codec not found */ - dev_err(card->dev, "ASoC: codec %s not found", codecname); + dev_err(card->dev, "ASoC: %s not registered\n", codecname); return -EPROBE_DEFER; } - if (codec->probed) { - dev_err(codec->dev, "ASoC: codec already probed"); + return 0; +} + +static int soc_probe_aux_dev(struct snd_soc_card *card, int num) +{ + struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; + int ret; + + if (rtd->codec->probed) { + dev_err(rtd->codec->dev, "ASoC: codec already probed\n"); return -EBUSY; } - ret = soc_probe_codec(card, codec); + ret = soc_probe_codec(card, rtd->codec); if (ret < 0) return ret; - ret = soc_post_component_init(card, codec, num, 1); - - return ret; + return soc_post_component_init(card, num, 1); } static void soc_remove_aux_dev(struct snd_soc_card *card, int num) @@ -1745,9 +1728,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) goto base_error; } - /* check aux_devs too */ + /* bind aux_devs too */ for (i = 0; i < card->num_aux_devs; i++) { - ret = soc_check_aux_dev(card, i); + ret = soc_bind_aux_dev(card, i); if (ret != 0) goto base_error; } -- cgit From 5f3484ac8775a183f855fd213907c4221d2fb11f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 1 Jul 2014 22:13:48 +0200 Subject: ASoC: core: Move non-shared code paths out of snd_soc_post_component_init() There are two call sites for snd_soc_post_component_init(), one passes 0 and the other 1 for the 'dailess' parameter of snd_soc_post_component_init(). Depending on whether 'dailess' is 0 or 1 snd_soc_post_component_init() runs different code at the beginning and the end of the function. The patch moves this conditional code out of snd_soc_post_component_init() and into the call sites. This removes the need for snd_soc_post_component_init() to know whether it is called for a DAI link or a aux dev. Also do the initialization of rtd->card when the rtd struct is allocated. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 121 ++++++++++++++++++++------------------------------- 1 file changed, 46 insertions(+), 75 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b1600cdcdc14..c4db07f01d10 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1286,74 +1286,17 @@ static void rtd_release(struct device *dev) kfree(dev); } -static int soc_aux_dev_init(struct snd_soc_card *card, int num) +static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd, + const char *name) { - struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; - struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; - int ret; - - rtd->card = card; - - /* do machine specific initialization */ - if (aux_dev->init) { - ret = aux_dev->init(&rtd->codec->dapm); - if (ret < 0) - return ret; - } - - return 0; -} - -static int soc_dai_link_init(struct snd_soc_card *card, int num) -{ - struct snd_soc_dai_link *dai_link = &card->dai_link[num]; - struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; - int ret; - - rtd->card = card; - - /* do machine specific initialization */ - if (dai_link->init) { - ret = dai_link->init(rtd); - if (ret < 0) - return ret; - } - - return 0; -} - -static int soc_post_component_init(struct snd_soc_card *card, - int num, int dailess) -{ - struct snd_soc_dai_link *dai_link = NULL; - struct snd_soc_aux_dev *aux_dev = NULL; - struct snd_soc_pcm_runtime *rtd; - const char *name; int ret = 0; - if (!dailess) { - dai_link = &card->dai_link[num]; - rtd = &card->rtd[num]; - name = dai_link->name; - ret = soc_dai_link_init(card, num); - } else { - aux_dev = &card->aux_dev[num]; - rtd = &card->rtd_aux[num]; - name = aux_dev->name; - ret = soc_aux_dev_init(card, num); - } - - if (ret < 0) { - dev_err(card->dev, "ASoC: failed to init %s: %d\n", name, ret); - return ret; - } - /* register the rtd device */ rtd->dev = kzalloc(sizeof(struct device), GFP_KERNEL); if (!rtd->dev) return -ENOMEM; device_initialize(rtd->dev); - rtd->dev->parent = card->dev; + rtd->dev->parent = rtd->card->dev; rtd->dev->release = rtd_release; rtd->dev->init_name = name; dev_set_drvdata(rtd->dev, rtd); @@ -1366,7 +1309,7 @@ static int soc_post_component_init(struct snd_soc_card *card, if (ret < 0) { /* calling put_device() here to free the rtd->dev */ put_device(rtd->dev); - dev_err(card->dev, + dev_err(rtd->card->dev, "ASoC: failed to register runtime device: %d\n", ret); return ret; } @@ -1384,17 +1327,6 @@ static int soc_post_component_init(struct snd_soc_card *card, dev_err(rtd->dev, "ASoC: failed to add codec sysfs files: %d\n", ret); -#ifdef CONFIG_DEBUG_FS - /* add DPCM sysfs entries */ - if (!dailess && !dai_link->dynamic) - goto out; - - ret = soc_dpcm_debugfs_add(rtd); - if (ret < 0) - dev_err(rtd->dev, "ASoC: failed to add dpcm sysfs entries: %d\n", ret); - -out: -#endif return 0; } @@ -1546,10 +1478,33 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) if (order != SND_SOC_COMP_ORDER_LAST) return 0; - ret = soc_post_component_init(card, num, 0); + /* do machine specific initialization */ + if (dai_link->init) { + ret = dai_link->init(rtd); + if (ret < 0) { + dev_err(card->dev, "ASoC: failed to init %s: %d\n", + dai_link->name, ret); + return ret; + } + } + + ret = soc_post_component_init(rtd, dai_link->name); if (ret) return ret; +#ifdef CONFIG_DEBUG_FS + /* add DPCM sysfs entries */ + if (dai_link->dynamic) { + ret = soc_dpcm_debugfs_add(rtd); + if (ret < 0) { + dev_err(rtd->dev, + "ASoC: failed to add dpcm sysfs entries: %d\n", + ret); + return ret; + } + } +#endif + ret = device_create_file(rtd->dev, &dev_attr_pmdown_time); if (ret < 0) dev_warn(rtd->dev, "ASoC: failed to add pmdown_time sysfs: %d\n", @@ -1665,6 +1620,7 @@ static int soc_bind_aux_dev(struct snd_soc_card *card, int num) static int soc_probe_aux_dev(struct snd_soc_card *card, int num) { struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; + struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; int ret; if (rtd->codec->probed) { @@ -1676,7 +1632,17 @@ static int soc_probe_aux_dev(struct snd_soc_card *card, int num) if (ret < 0) return ret; - return soc_post_component_init(card, num, 1); + /* do machine specific initialization */ + if (aux_dev->init) { + ret = aux_dev->init(&rtd->codec->dapm); + if (ret < 0) { + dev_err(card->dev, "ASoC: failed to init %s: %d\n", + aux_dev->name, ret); + return ret; + } + } + + return soc_post_component_init(rtd, aux_dev->name); } static void soc_remove_aux_dev(struct snd_soc_card *card, int num) @@ -3775,8 +3741,13 @@ int snd_soc_register_card(struct snd_soc_card *card) card->num_rtd = 0; card->rtd_aux = &card->rtd[card->num_links]; - for (i = 0; i < card->num_links; i++) + for (i = 0; i < card->num_links; i++) { + card->rtd[i].card = card; card->rtd[i].dai_link = &card->dai_link[i]; + } + + for (i = 0; i < card->num_aux_devs; i++) + card->rtd_aux[i].card = card; INIT_LIST_HEAD(&card->dapm_dirty); card->instantiated = 0; -- cgit