From patchwork Sun May 18 12:24:10 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lars-Peter Clausen X-Patchwork-Id: 4197821 X-Patchwork-Delegate: tiwai@suse.de Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id E678BBEEAB for ; Sun, 18 May 2014 12:27:30 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C8FFD20254 for ; Sun, 18 May 2014 12:27:29 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 1D3F22020F for ; Sun, 18 May 2014 12:27:28 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 1DCED2651CB; Sun, 18 May 2014 14:27:27 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id 6F407264ED5; Sun, 18 May 2014 14:24:42 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 23BEE264F2D; Sun, 18 May 2014 14:24:36 +0200 (CEST) Received: from smtp-out-145.synserver.de (smtp-out-151.synserver.de [212.40.185.151]) by alsa0.perex.cz (Postfix) with ESMTP id D9E2E264EFF for ; Sun, 18 May 2014 14:24:26 +0200 (CEST) Received: (qmail 19746 invoked by uid 0); 18 May 2014 12:24:24 -0000 X-SynServer-TrustedSrc: 1 X-SynServer-AuthUser: lars@metafoo.de X-SynServer-PPID: 19571 Received: from ppp-212-114-237-253.dynamic.mnet-online.de (HELO lars-adi-laptop.fritz.box) [212.114.237.253] by 217.119.54.77 with SMTP; 18 May 2014 12:24:23 -0000 From: Lars-Peter Clausen To: Mark Brown , Liam Girdwood Date: Sun, 18 May 2014 14:24:10 +0200 Message-Id: <1400415858-11025-4-git-send-email-lars@metafoo.de> X-Mailer: git-send-email 1.8.0 In-Reply-To: <1400415858-11025-1-git-send-email-lars@metafoo.de> References: <1400415858-11025-1-git-send-email-lars@metafoo.de> Cc: alsa-devel@alsa-project.org, Lars-Peter Clausen Subject: [alsa-devel] [PATCH 03/11] ASoC: Split component registration into two steps X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- sound/soc/soc-core.c | 177 ++++++++++++++++++++++++++------------------------- 1 file changed, 91 insertions(+), 86 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b8cc88a..0944da6 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); }