From patchwork Tue Mar 8 12:53:56 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnaud POULIQUEN X-Patchwork-Id: 8533701 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.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 7E22BC0553 for ; Tue, 8 Mar 2016 12:54:52 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 87B78201FE for ; Tue, 8 Mar 2016 12:54:50 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 7108120123 for ; Tue, 8 Mar 2016 12:54:48 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 208EF2657E0; Tue, 8 Mar 2016 13:54:47 +0100 (CET) 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, RCVD_IN_DNSWL_NONE, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 5242D2651E4; Tue, 8 Mar 2016 13:54:35 +0100 (CET) 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 E269826522E; Tue, 8 Mar 2016 13:54:33 +0100 (CET) Received: from mx07-00178001.pphosted.com (mx07-00178001.pphosted.com [62.209.51.94]) by alsa0.perex.cz (Postfix) with ESMTP id 88F1126071E for ; Tue, 8 Mar 2016 13:54:26 +0100 (CET) Received: from pps.filterd (m0046668.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.15.0.59/8.15.0.59) with SMTP id u28CpDKx017902; Tue, 8 Mar 2016 13:54:26 +0100 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 21ft2krq8d-1 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Tue, 08 Mar 2016 13:54:26 +0100 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id EA98A3A; Tue, 8 Mar 2016 12:54:24 +0000 (GMT) Received: from Webmail-eu.st.com (Safex1hubcas24.st.com [10.75.90.94]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 91286130E; Tue, 8 Mar 2016 12:54:24 +0000 (GMT) Received: from localhost (10.201.23.162) by webmail-ga.st.com (10.75.90.48) with Microsoft SMTP Server (TLS) id 14.3.248.2; Tue, 8 Mar 2016 13:54:24 +0100 From: Arnaud Pouliquen To: Date: Tue, 8 Mar 2016 13:53:56 +0100 Message-ID: <1457441641-7501-2-git-send-email-arnaud.pouliquen@st.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1457441641-7501-1-git-send-email-arnaud.pouliquen@st.com> References: <1457441641-7501-1-git-send-email-arnaud.pouliquen@st.com> MIME-Version: 1.0 X-Originating-IP: [10.201.23.162] X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2016-03-08_05:, , signatures=0 Cc: Jean-Francois Moine , Lars-Peter Clausen , Russell King - ARM Linux , David Airlie , arnaud.pouliquen@st.com, Liam Girdwood , Jyri Sarha , Takashi Iwai , Mark Brown , Philipp Zabel , Moise Gergaud Subject: [alsa-devel] [PATCH v4 1/6] ASoC: core: add snd_soc_add_dai_pcm_controls helper 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: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP Add helper function to register DAI controls that need to be linked to pcm device. A list is handled in case controls are created before dai_link probe Signed-off-by: Arnaud Pouliquen --- include/sound/soc-dai.h | 1 + include/sound/soc.h | 2 + sound/soc/soc-core.c | 164 +++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 146 insertions(+), 21 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 964b7de..6e0fcb0 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -292,6 +292,7 @@ struct snd_soc_dai { unsigned int rx_mask; struct list_head list; + struct list_head list_pcm_ctl; }; static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai, diff --git a/include/sound/soc.h b/include/sound/soc.h index 02b4a21..044adcf 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -598,6 +598,8 @@ int snd_soc_add_card_controls(struct snd_soc_card *soc_card, const struct snd_kcontrol_new *controls, int num_controls); int snd_soc_add_dai_controls(struct snd_soc_dai *dai, const struct snd_kcontrol_new *controls, int num_controls); +int snd_soc_add_dai_pcm_controls(struct snd_soc_dai *dai, + const struct snd_kcontrol_new *controls, int num_controls); int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 790ee2b..95aae5e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1582,11 +1582,63 @@ static int soc_link_dai_widgets(struct snd_soc_card *card, return 0; } +static int snd_soc_add_controls(struct snd_card *card, struct device *dev, + const struct snd_kcontrol_new *controls, int num_controls, + const char *prefix, void *data) +{ + int err, i; + + for (i = 0; i < num_controls; i++) { + const struct snd_kcontrol_new *control = &controls[i]; + + err = snd_ctl_add(card, snd_soc_cnew(control, data, + control->name, prefix)); + if (err < 0) { + dev_err(dev, "ASoC: Failed to add %s: %d\n", + control->name, err); + return err; + } + } + + return 0; +} + +struct snd_soc_dai_pcm_ctls { + struct snd_kcontrol_new *controls; + int num_controls; + struct list_head list; +}; + +static int soc_link_dai_pcm_controls(struct snd_soc_card *card, + struct snd_soc_dai *dai, + struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dai_pcm_ctls *ctls, *_ctls; + struct snd_kcontrol_new *kctl; + int i, ret; + + list_for_each_entry_safe(ctls, _ctls, &dai->list_pcm_ctl, list) { + kctl = ctls->controls; + for (i = 0; i < ctls->num_controls; i++) + kctl[i].device = rtd->pcm->device; + + ret = snd_soc_add_controls(card->snd_card, dai->dev, kctl, + ctls->num_controls, NULL, dai); + kfree(kctl); + list_del(&ctls->list); + kfree(ctls); + if (ret < 0) + return ret; + } + + return 0; +} + static int soc_probe_link_dais(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd, int order) { struct snd_soc_dai_link *dai_link = rtd->dai_link; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *dai, *cpu_dai = rtd->cpu_dai; int i, ret; dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n", @@ -1651,6 +1703,35 @@ static int soc_probe_link_dais(struct snd_soc_card *card, dai_link->stream_name, ret); return ret; } + + /* link CPU DAI pcm controls to pcm device */ + if (!list_empty(&cpu_dai->list_pcm_ctl)) + ret = soc_link_dai_pcm_controls(card, cpu_dai, + rtd); + if (ret < 0) { + dev_err(card->dev, + "ASoC: Can't link %s control to %s :%d\n", + cpu_dai->name, dai_link->stream_name, + ret); + return ret; + } + + /* link CODEC DAI pcm control to pcm device */ + for (i = 0; i < rtd->num_codecs; i++) { + dai = rtd->codec_dais[i]; + if (!list_empty(&dai->list_pcm_ctl)) + ret = soc_link_dai_pcm_controls(card, + dai, rtd); + if (ret < 0) + break; + } + if (ret < 0) { + dev_err(card->dev, + "ASoC: Can't link %s control to %s :%d\n", + dai->name, dai_link->stream_name, ret); + return ret; + } + } else { INIT_DELAYED_WORK(&rtd->delayed_work, codec2codec_close_delayed_work); @@ -2187,26 +2268,6 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, } EXPORT_SYMBOL_GPL(snd_soc_cnew); -static int snd_soc_add_controls(struct snd_card *card, struct device *dev, - const struct snd_kcontrol_new *controls, int num_controls, - const char *prefix, void *data) -{ - int err, i; - - for (i = 0; i < num_controls; i++) { - const struct snd_kcontrol_new *control = &controls[i]; - err = snd_ctl_add(card, snd_soc_cnew(control, data, - control->name, prefix)); - if (err < 0) { - dev_err(dev, "ASoC: Failed to add %s: %d\n", - control->name, err); - return err; - } - } - - return 0; -} - struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, const char *name) { @@ -2320,6 +2381,65 @@ int snd_soc_add_dai_controls(struct snd_soc_dai *dai, EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls); /** + * snd_soc_add_dai_pcm_controls - add an array of pcm controls to a DAI. + * Convenience function to add a list of DAI controls linked to the PCM device. + * + * @dai: DAI to add controls to + * @controls: array of controls to add + * @num_controls: number of elements in the array + * + * Return 0 for success, else error. + */ +int snd_soc_add_dai_pcm_controls(struct snd_soc_dai *dai, + const struct snd_kcontrol_new *controls, + int num_controls) +{ + struct snd_soc_card *card = dai->component->card; + struct snd_soc_pcm_runtime *rtd; + struct snd_soc_dai_pcm_ctls *ctls_list; + struct snd_kcontrol_new *kctl; + int i, dai_found = 0; + + for (i = 0; i < num_controls; i++) { + if (controls[i].iface != SNDRV_CTL_ELEM_IFACE_PCM) { + dev_err(dai->dev, "%s: not a pcm device control !!!\n", + controls[i].name); + return -EINVAL; + } + } + + kctl = kcalloc(num_controls, sizeof(*kctl), GFP_KERNEL); + memcpy(kctl, controls, sizeof(*kctl) * num_controls); + + if (dai->probed) { + /* pcm device exists. Control can be linked to it */ + list_for_each_entry(rtd, &card->rtd_list, list) { + if (dai == rtd->cpu_dai) { + dai_found = 1; + break; + } + } + if (!dai_found) + return -EINVAL; + + for (i = 0; i < num_controls; i++) + kctl[i].device = rtd->pcm->device; + snd_soc_add_controls(card->snd_card, dai->dev, kctl, + num_controls, NULL, dai); + kfree(kctl); + } else { + /* pcm device does not exists. Postpone to dai link creation */ + ctls_list = kzalloc(sizeof(*ctls_list), GFP_KERNEL); + ctls_list->controls = kctl; + ctls_list->num_controls = num_controls; + list_add(&ctls_list->list, &dai->list_pcm_ctl); + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_add_dai_pcm_controls); + +/** * snd_soc_dai_set_sysclk - configure DAI system or master clock. * @dai: DAI * @clk_id: DAI specific clock ID @@ -2795,6 +2915,8 @@ static struct snd_soc_dai *soc_add_dai(struct snd_soc_component *component, if (!dai->driver->ops) dai->driver->ops = &null_dai_ops; + INIT_LIST_HEAD(&dai->list_pcm_ctl); + list_add(&dai->list, &component->dai_list); component->num_dai++;