From patchwork Thu Oct 11 16:28:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Charles Keepax X-Patchwork-Id: 10637059 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 00A921508 for ; Thu, 11 Oct 2018 17:06:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DF3362BCD3 for ; Thu, 11 Oct 2018 17:06:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D25312BCDA; Thu, 11 Oct 2018 17:06:46 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C90C82BCC7 for ; Thu, 11 Oct 2018 17:06:44 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 0E156267967; Thu, 11 Oct 2018 18:28:45 +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 7C0392678FE; Thu, 11 Oct 2018 18:28:41 +0200 (CEST) Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by alsa0.perex.cz (Postfix) with ESMTP id 62C91267939 for ; Thu, 11 Oct 2018 18:28:36 +0200 (CEST) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w9BGSYgu031844; Thu, 11 Oct 2018 11:28:35 -0500 Authentication-Results: ppops.net; spf=none smtp.mailfrom=ckeepax@opensource.cirrus.com Received: from mail3.cirrus.com ([87.246.76.56]) by mx0a-001ae601.pphosted.com with ESMTP id 2mxwheg3dp-1; Thu, 11 Oct 2018 11:28:35 -0500 Received: from EX17.ad.cirrus.com (ex17.ad.cirrus.com [172.20.9.81]) by mail3.cirrus.com (Postfix) with ESMTP id 8F537611C8B3; Thu, 11 Oct 2018 11:30:45 -0500 (CDT) Received: from imbe.wolfsonmicro.main (198.61.95.81) by EX17.ad.cirrus.com (172.20.9.81) with Microsoft SMTP Server id 14.3.408.0; Thu, 11 Oct 2018 17:28:31 +0100 Received: from algalon.ad.cirrus.com (algalon.ad.cirrus.com [198.90.251.122]) by imbe.wolfsonmicro.main (8.14.4/8.14.4) with ESMTP id w9BGSVIR010322; Thu, 11 Oct 2018 17:28:31 +0100 From: Charles Keepax To: Date: Thu, 11 Oct 2018 17:28:28 +0100 Message-ID: <20181011162831.26351-2-ckeepax@opensource.cirrus.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181011162831.26351-1-ckeepax@opensource.cirrus.com> References: <20181011162831.26351-1-ckeepax@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 priorityscore=1501 malwarescore=0 suspectscore=4 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=944 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1807170000 definitions=main-1810110158 Cc: patches@opensource.cirrus.com, alsa-devel@alsa-project.org, lgirdwood@gmail.com Subject: [alsa-devel] [RFC PATCH 1/4] ASoC: dapm: Add support for hw_free on CODEC to CODEC links 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 Currently, on power down for a CODEC to CODEC DAI link we only call digital_mute and shutdown. Provide a little more flexibility for drivers by adding a call to hw_free as well. Signed-off-by: Charles Keepax --- sound/soc/soc-dapm.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 8c5b065c88806..a5178845065b3 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3737,25 +3737,30 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, ret = 0; } + substream.stream = SNDRV_PCM_STREAM_CAPTURE; snd_soc_dapm_widget_for_each_source_path(w, path) { source = path->source->priv; + if (source->driver->ops->hw_free) + source->driver->ops->hw_free(&substream, + source); + source->active--; - if (source->driver->ops->shutdown) { - substream.stream = SNDRV_PCM_STREAM_CAPTURE; + if (source->driver->ops->shutdown) source->driver->ops->shutdown(&substream, source); - } } + substream.stream = SNDRV_PCM_STREAM_PLAYBACK; snd_soc_dapm_widget_for_each_sink_path(w, path) { sink = path->sink->priv; + if (sink->driver->ops->hw_free) + sink->driver->ops->hw_free(&substream, sink); + sink->active--; - if (sink->driver->ops->shutdown) { - substream.stream = SNDRV_PCM_STREAM_PLAYBACK; + if (sink->driver->ops->shutdown) sink->driver->ops->shutdown(&substream, sink); - } } break; From patchwork Thu Oct 11 16:28:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Charles Keepax X-Patchwork-Id: 10637061 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1455B5CAF for ; Thu, 11 Oct 2018 17:06:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F31AE2BA75 for ; Thu, 11 Oct 2018 17:06:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E7C3E2BCDF; Thu, 11 Oct 2018 17:06:46 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C78EA2BA75 for ; Thu, 11 Oct 2018 17:06:44 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id BD6C92678FE; Thu, 11 Oct 2018 18:28:41 +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 0A9B3267948; Thu, 11 Oct 2018 18:28:40 +0200 (CEST) Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by alsa0.perex.cz (Postfix) with ESMTP id 617832678E9 for ; Thu, 11 Oct 2018 18:28:36 +0200 (CEST) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w9BGSZSM020805; Thu, 11 Oct 2018 11:28:35 -0500 Authentication-Results: ppops.net; spf=none smtp.mailfrom=ckeepax@opensource.cirrus.com Received: from mail3.cirrus.com ([87.246.76.56]) by mx0b-001ae601.pphosted.com with ESMTP id 2mxu49892n-1; Thu, 11 Oct 2018 11:28:33 -0500 Received: from EX17.ad.cirrus.com (ex17.ad.cirrus.com [172.20.9.81]) by mail3.cirrus.com (Postfix) with ESMTP id 91648611C8B5; Thu, 11 Oct 2018 11:30:45 -0500 (CDT) Received: from imbe.wolfsonmicro.main (198.61.95.81) by EX17.ad.cirrus.com (172.20.9.81) with Microsoft SMTP Server id 14.3.408.0; Thu, 11 Oct 2018 17:28:31 +0100 Received: from algalon.ad.cirrus.com (algalon.ad.cirrus.com [198.90.251.122]) by imbe.wolfsonmicro.main (8.14.4/8.14.4) with ESMTP id w9BGSVIS010322; Thu, 11 Oct 2018 17:28:31 +0100 From: Charles Keepax To: Date: Thu, 11 Oct 2018 17:28:29 +0100 Message-ID: <20181011162831.26351-3-ckeepax@opensource.cirrus.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181011162831.26351-1-ckeepax@opensource.cirrus.com> References: <20181011162831.26351-1-ckeepax@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1807170000 definitions=main-1810110158 Cc: patches@opensource.cirrus.com, alsa-devel@alsa-project.org, lgirdwood@gmail.com Subject: [alsa-devel] [RFC PATCH 2/4] ASoC: dapm: Add support for a rate domain widget 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 Some CODECs can support multiple sample rates internally but frequently groups of functionality will be force to the run on the same sample rate. For example, perhaps all the DACs are required to run at a single rate. Utimately, it would be ideal if the sample rates could be propagated through from the top level DAI links to these groups of widgets. This should allow more complex use-cases involving multiple sample rates to be connected and will also allow detection of errors where blocks with incompatible sample rates are connected. A first step in this process is to provide a mechanism that documents which blocks are tidied together with respect to sample rate and track when they are in use. This is acheived by adding a supply like widget that represents a group of widgets that are bound to a single sample rate. This domain widget should be connected to all inputs and outputs to the group of widgets, that way it will power up whenever anything in that group of widgets does. Signed-off-by: Charles Keepax --- include/sound/soc-dapm.h | 4 ++++ sound/soc/soc-dapm.c | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index bd8163f151cb8..c0ef27b2d4b22 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -273,6 +273,9 @@ struct device; .reg = SND_SOC_NOPM, .event = dapm_pinctrl_event, \ .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD } +#define SND_SOC_DAPM_RATE(wname, wreg, wshift, winvert, wops, wpriv) \ +{ .id = snd_soc_dapm_rate, .name = wname, \ + SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert) } /* dapm kcontrol types */ @@ -519,6 +522,7 @@ enum snd_soc_dapm_type { snd_soc_dapm_asrc, /* DSP/CODEC ASRC component */ snd_soc_dapm_encoder, /* FW/SW audio encoder component */ snd_soc_dapm_decoder, /* FW/SW audio decoder component */ + snd_soc_dapm_rate, /* Rate group */ }; enum snd_soc_dapm_subclass { diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index a5178845065b3..7e3858d1e81dc 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -68,6 +68,7 @@ static int dapm_up_seq[] = { [snd_soc_dapm_regulator_supply] = 1, [snd_soc_dapm_pinctrl] = 1, [snd_soc_dapm_clock_supply] = 1, + [snd_soc_dapm_rate] = 2, [snd_soc_dapm_supply] = 2, [snd_soc_dapm_micbias] = 3, [snd_soc_dapm_dai_link] = 2, @@ -115,6 +116,7 @@ static int dapm_down_seq[] = { [snd_soc_dapm_dai_out] = 10, [snd_soc_dapm_dai_link] = 11, [snd_soc_dapm_supply] = 12, + [snd_soc_dapm_rate] = 12, [snd_soc_dapm_clock_supply] = 13, [snd_soc_dapm_pinctrl] = 13, [snd_soc_dapm_regulator_supply] = 13, @@ -1912,6 +1914,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) case snd_soc_dapm_vmid: break; case snd_soc_dapm_supply: + case snd_soc_dapm_rate: case snd_soc_dapm_regulator_supply: case snd_soc_dapm_pinctrl: case snd_soc_dapm_clock_supply: @@ -2326,6 +2329,7 @@ static ssize_t dapm_widget_show_component(struct snd_soc_component *cmpnt, case snd_soc_dapm_mixer: case snd_soc_dapm_mixer_named_ctl: case snd_soc_dapm_supply: + case snd_soc_dapm_rate: case snd_soc_dapm_regulator_supply: case snd_soc_dapm_pinctrl: case snd_soc_dapm_clock_supply: @@ -3522,6 +3526,7 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, w->power_check = dapm_generic_check_power; break; case snd_soc_dapm_supply: + case snd_soc_dapm_rate: case snd_soc_dapm_regulator_supply: case snd_soc_dapm_pinctrl: case snd_soc_dapm_clock_supply: From patchwork Thu Oct 11 16:28:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Charles Keepax X-Patchwork-Id: 10637065 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 15D553CF1 for ; Thu, 11 Oct 2018 17:06:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F33412BA75 for ; Thu, 11 Oct 2018 17:06:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E56052BC72; Thu, 11 Oct 2018 17:06:47 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C994E2BCC8 for ; Thu, 11 Oct 2018 17:06:44 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 8F6AB267987; Thu, 11 Oct 2018 18:28:46 +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 D885626795B; Thu, 11 Oct 2018 18:28:42 +0200 (CEST) Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by alsa0.perex.cz (Postfix) with ESMTP id 62A38267937 for ; Thu, 11 Oct 2018 18:28:36 +0200 (CEST) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w9BGSZBe031851; Thu, 11 Oct 2018 11:28:35 -0500 Authentication-Results: ppops.net; spf=none smtp.mailfrom=ckeepax@opensource.cirrus.com Received: from mail3.cirrus.com ([87.246.76.56]) by mx0a-001ae601.pphosted.com with ESMTP id 2mxwheg3dq-1; Thu, 11 Oct 2018 11:28:34 -0500 Received: from EX17.ad.cirrus.com (ex17.ad.cirrus.com [172.20.9.81]) by mail3.cirrus.com (Postfix) with ESMTP id 9B403611C8B9; Thu, 11 Oct 2018 11:30:45 -0500 (CDT) Received: from imbe.wolfsonmicro.main (198.61.95.81) by EX17.ad.cirrus.com (172.20.9.81) with Microsoft SMTP Server id 14.3.408.0; Thu, 11 Oct 2018 17:28:31 +0100 Received: from algalon.ad.cirrus.com (algalon.ad.cirrus.com [198.90.251.122]) by imbe.wolfsonmicro.main (8.14.4/8.14.4) with ESMTP id w9BGSVIT010322; Thu, 11 Oct 2018 17:28:31 +0100 From: Charles Keepax To: Date: Thu, 11 Oct 2018 17:28:30 +0100 Message-ID: <20181011162831.26351-4-ckeepax@opensource.cirrus.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181011162831.26351-1-ckeepax@opensource.cirrus.com> References: <20181011162831.26351-1-ckeepax@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 priorityscore=1501 malwarescore=0 suspectscore=3 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1807170000 definitions=main-1810110158 Cc: patches@opensource.cirrus.com, alsa-devel@alsa-project.org, lgirdwood@gmail.com Subject: [alsa-devel] [RFC PATCH 3/4] ASoC: domain: Add sample rate domain support 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 The rate domain widgets allowed tracking of which hardware blocks are physically bound to the same sample rate. The next step is to follow which blocks are connected together as two directly connected blocks should also run at the same rate, even though the hardware may provide independent settings for them. To acheive this two new concepts are introduced to ASoC, a rate domain and a rate domain group. The rate domain group corresponds to the rate domain widgets previously added to DAPM. And the domains correspond to actual sample rates. The rate domain groups internally track which other groups they are connected to. These lists of peer groups are updated as DAPM routes are connected/disconnected and form a collection of graphs tracking which domain groups are connected. Note that these graphs are significantly smaller than the DAPM graph itself. When a domain group's corresponding widget is powered up then the group must locate an actual domain to attach to. Firstly, the group will walk its peer graph, should it find it is attached to widgets that require certain domains it will limit the choice to those. For example if a widget is connected into a graph that is already powered up then it will find the only suitable domain is the one being currently used by the groups in the graph. Signed-off-by: Charles Keepax --- Thinking about trying to split this into two patches perhaps one to add the tracking of the rate domain groups connecting together and then a second patch to add the actual domains. Thanks, Charles include/sound/soc-dapm.h | 12 +- include/sound/soc-domain.h | 98 +++++++++++ include/sound/soc.h | 8 + sound/soc/Makefile | 2 +- sound/soc/soc-core.c | 8 + sound/soc/soc-dapm.c | 35 ++++ sound/soc/soc-domain.c | 412 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 573 insertions(+), 2 deletions(-) create mode 100644 include/sound/soc-domain.h create mode 100644 sound/soc/soc-domain.c diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index c0ef27b2d4b22..c736b1d3e4931 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -275,7 +275,12 @@ struct device; #define SND_SOC_DAPM_RATE(wname, wreg, wshift, winvert, wops, wpriv) \ { .id = snd_soc_dapm_rate, .name = wname, \ - SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert) } + SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ + .event = snd_soc_domain_event, \ + .event_flags = SND_SOC_DAPM_WILL_PMU | SND_SOC_DAPM_PRE_PMU | \ + SND_SOC_DAPM_POST_PMD, \ + .priv = (&(struct snd_soc_domain_group_driver){ \ + .name = wname, .ops = wops, .private_data = wpriv}),} /* dapm kcontrol types */ @@ -410,6 +415,9 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card); void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card); +int snd_soc_dapm_connect_domains(struct snd_soc_dapm_context *dapm, + const char * const a, const char * const b); + /* dapm path setup */ int snd_soc_dapm_new_widgets(struct snd_soc_card *card); void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm); @@ -629,6 +637,8 @@ struct snd_soc_dapm_widget { int endpoints[2]; struct clk *clk; + + struct snd_soc_domain_group *dgroup; }; struct snd_soc_dapm_update { diff --git a/include/sound/soc-domain.h b/include/sound/soc-domain.h new file mode 100644 index 0000000000000..94e1c1ae9ff00 --- /dev/null +++ b/include/sound/soc-domain.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ASoC Sample Rate Domain Support + * + * Copyright (c) 2018 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + * + * Author: Charles Keepax + */ + +#ifndef LINUX_SND_SOC_DOMAIN_H +#define LINUX_SND_SOC_DOMAIN_H + +#define SND_SOC_DOMAIN_CURRENT -1 + +struct snd_soc_domain; +struct snd_soc_domain_group; + +struct snd_soc_domain_ops { + int (*set_rate)(struct snd_soc_domain *domain, int rate); + int (*get_rate)(struct snd_soc_domain *domain); +}; + +struct snd_soc_domain_driver { + const char * const name; + + const struct snd_soc_domain_ops *ops; + + void *private_data; +}; + +struct snd_soc_domain { + const struct snd_soc_domain_driver *driver; + struct snd_soc_component *component; + + /* TODO: Probably should be a snd_pcm_hw_params */ + int rate; + + int active_groups; +}; + +struct snd_soc_domain_group_ops { + int (*set_domain)(struct snd_soc_domain_group *group, int dom); + + int (*mask_domains)(struct snd_soc_domain_group *group, + unsigned long *domain_mask); + /* optional */ + int (*pick_domain)(struct snd_soc_domain_group *group, + const unsigned long *domain_mask); +}; + +struct snd_soc_domain_group_driver { + const char * const name; + + const struct snd_soc_domain_group_ops *ops; + + void *private_data; +}; + +struct snd_soc_domain_group { + const struct snd_soc_domain_group_driver *driver; + struct snd_soc_component *component; + + int domain_index; + int attach_count; + + struct list_head peers; + + unsigned int walking:1; + unsigned int power:1; +}; + +int devm_snd_soc_domain_init(struct snd_soc_component *component); + +struct snd_soc_domain_group * +devm_snd_soc_domain_group_new(struct snd_soc_component *component, + const struct snd_soc_domain_group_driver *drv); + +struct snd_soc_domain *snd_soc_domain_get(struct snd_soc_domain_group *group, + int index); +bool snd_soc_domain_active(struct snd_soc_domain *domain); +int snd_soc_domain_get_rate(struct snd_soc_domain *domain); + +int snd_soc_domain_set_rate(struct snd_soc_domain_group *group, int rate); + +/* TODO: API to force a particular domain onto a group? */ +int snd_soc_domain_attach(struct snd_soc_domain_group *group); +int snd_soc_domain_detach(struct snd_soc_domain_group *group); + +int snd_soc_domain_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event); + +int snd_soc_domain_connect_widgets(struct snd_soc_dapm_widget *a, + struct snd_soc_dapm_widget *b, + bool connect); + +#endif diff --git a/include/sound/soc.h b/include/sound/soc.h index f1dab1f4b194d..475843a17ebd4 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -413,6 +413,7 @@ struct snd_soc_jack_pin; #include #include #include +#include struct snd_soc_jack_gpio; @@ -763,6 +764,9 @@ struct snd_soc_component_driver { const struct snd_soc_dapm_route *dapm_routes; unsigned int num_dapm_routes; + const struct snd_soc_domain_driver *domains; + unsigned int num_domains; + int (*probe)(struct snd_soc_component *); void (*remove)(struct snd_soc_component *); int (*suspend)(struct snd_soc_component *); @@ -838,6 +842,9 @@ struct snd_soc_component { struct list_head dai_list; int num_dai; + struct snd_soc_domain *domains; + int num_domains; + struct regmap *regmap; int val_bytes; @@ -1036,6 +1043,7 @@ struct snd_soc_card { struct mutex mutex; struct mutex dapm_mutex; + struct mutex domain_mutex; bool instantiated; bool topology_shortname_created; diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 62a5f87c3cfc4..185f51aa963a2 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o -snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o +snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o soc-domain.o snd-soc-core-$(CONFIG_SND_SOC_COMPRESS) += soc-compress.o ifneq ($(CONFIG_SND_SOC_TOPOLOGY),) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 62e8e36062df0..4623adb27543b 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1345,6 +1345,13 @@ static int soc_probe_component(struct snd_soc_card *card, } } + ret = devm_snd_soc_domain_init(component); + if (ret < 0) { + dev_err(component->dev, "Failed to initialise domains: %d\n", + ret); + goto err_probe; + } + if (component->driver->controls) snd_soc_add_component_controls(component, component->driver->controls, @@ -2739,6 +2746,7 @@ int snd_soc_register_card(struct snd_soc_card *card) card->instantiated = 0; mutex_init(&card->mutex); mutex_init(&card->dapm_mutex); + mutex_init(&card->domain_mutex); return snd_soc_bind_card(card); } diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 7e3858d1e81dc..a3f01626fda76 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2179,6 +2179,9 @@ static void soc_dapm_connect_path(struct snd_soc_dapm_path *path, if (path->connect == connect) return; + /* TODO: Need to handle routes that are already connected */ + snd_soc_domain_connect_widgets(path->source, path->sink, connect); + path->connect = connect; dapm_mark_dirty(path->source, reason); dapm_mark_dirty(path->sink, reason); @@ -2685,6 +2688,14 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, if (wsource->is_supply || wsink->is_supply) path->is_supply = 1; + switch (wsource->id) { + case snd_soc_dapm_rate: + wsink->dgroup = wsource->dgroup; + break; + default: + break; + } + /* connect static paths */ if (control == NULL) { path->connect = 1; @@ -3463,6 +3474,14 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, goto request_failed; } break; + case snd_soc_dapm_rate: + w->dgroup = devm_snd_soc_domain_group_new(dapm->component, + w->priv); + if (IS_ERR(w->dgroup)) { + ret = PTR_ERR(w->dgroup); + goto request_failed; + } + break; default: break; } @@ -4566,6 +4585,22 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card) SND_SOC_BIAS_OFF); } +int snd_soc_dapm_connect_domains(struct snd_soc_dapm_context *dapm, + const char * const a, const char * const b) +{ + struct snd_soc_dapm_widget *wa, *wb; + + wa = dapm_find_widget(dapm, a, false); + if (!wa) + return -ENODEV; + wb = dapm_find_widget(dapm, b, false); + if (!wb) + return -ENODEV; + + return snd_soc_domain_connect_widgets(wa, wb, true); +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_connect_domains); + /* Module information */ MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk"); MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC"); diff --git a/sound/soc/soc-domain.c b/sound/soc/soc-domain.c new file mode 100644 index 0000000000000..01914d5971601 --- /dev/null +++ b/sound/soc/soc-domain.c @@ -0,0 +1,412 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ASoC Sample Rate Domain Support + * + * Copyright (c) 2018 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + * + * Author: Charles Keepax + */ + +#include +#include +#include +#include + +struct domain_group_peer { + struct list_head list; + int link_count; + struct snd_soc_domain_group *group; +}; + +static inline void domain_mutex_lock(struct snd_soc_component *component) +{ + mutex_lock(&component->card->domain_mutex); +} + +static inline void domain_mutex_unlock(struct snd_soc_component *component) +{ + mutex_unlock(&component->card->domain_mutex); +} + +static inline void domain_mutex_assert_held(struct snd_soc_component *component) +{ + lockdep_assert_held(&component->card->domain_mutex); +} + +int devm_snd_soc_domain_init(struct snd_soc_component *component) +{ + int i; + + if (!component->driver->num_domains) + return 0; + + component->num_domains = component->driver->num_domains; + component->domains = devm_kcalloc(component->card->dev, + component->num_domains, + sizeof(*component->domains), + GFP_KERNEL); + if (!component->domains) + return -ENOMEM; + + for (i = 0; i < component->num_domains; i++) { + component->domains[i].component = component; + component->domains[i].driver = &component->driver->domains[i]; + } + + return 0; +} +EXPORT_SYMBOL_GPL(devm_snd_soc_domain_init); + +struct snd_soc_domain_group * +devm_snd_soc_domain_group_new(struct snd_soc_component *component, + const struct snd_soc_domain_group_driver *driver) +{ + struct snd_soc_domain_group *group; + + group = devm_kzalloc(component->card->dev, sizeof(*group), GFP_KERNEL); + if (!group) + return ERR_PTR(-ENOMEM); + + INIT_LIST_HEAD(&group->peers); + + group->component = component; + group->driver = driver; + + return group; +} +EXPORT_SYMBOL_GPL(devm_snd_soc_domain_group_new); + +struct snd_soc_domain *snd_soc_domain_get(struct snd_soc_domain_group *group, + int index) +{ + int ndomains = group->component->num_domains; + + domain_mutex_assert_held(group->component); + + if (index == SND_SOC_DOMAIN_CURRENT) + index = group->domain_index; + + if (index < 0 || index >= ndomains) + return NULL; + + return &group->component->domains[index]; +} +EXPORT_SYMBOL_GPL(snd_soc_domain_get); + +bool snd_soc_domain_active(struct snd_soc_domain *domain) +{ + bool active; + + domain_mutex_assert_held(domain->component); + + active = !!domain->active_groups; + + return active; +} +EXPORT_SYMBOL_GPL(snd_soc_domain_active); + +int snd_soc_domain_get_rate(struct snd_soc_domain *domain) +{ + domain_mutex_assert_held(domain->component); + + return domain->rate; +} +EXPORT_SYMBOL_GPL(snd_soc_domain_get_rate); + +int snd_soc_domain_set_rate(struct snd_soc_domain_group *group, int rate) +{ + struct snd_soc_domain *domain; + int ret = -ENODEV; + + domain_mutex_lock(group->component); + + domain = snd_soc_domain_get(group, SND_SOC_DOMAIN_CURRENT); + if (domain) { + domain->rate = rate; + ret = domain->driver->ops->set_rate(domain, rate); + } + + domain_mutex_unlock(group->component); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_domain_set_rate); + +static struct snd_soc_domain_group * +group_walk(struct snd_soc_domain_group *group, bool local, + bool (*cond)(struct snd_soc_domain_group *g, void *c), void *cookie) +{ + struct domain_group_peer *link; + struct snd_soc_domain_group *target = NULL; + + domain_mutex_assert_held(group->component); + + if (group->walking) + return NULL; + + dev_vdbg(group->component->dev, "Walking %s\n", group->driver->name); + + if (cond(group, cookie)) + return group; + + group->walking = true; + list_for_each_entry(link, &group->peers, list) { + if (!link->group->power) + continue; + + if (local && link->group->component != group->component) + continue; + + target = group_walk(link->group, local, cond, cookie); + if (target) + break; + } + group->walking = false; + + return target; +} + +static bool group_mask(struct snd_soc_domain_group *group, void *cookie) +{ + unsigned long *mask = cookie; + + if (group->attach_count) + *mask &= 1 << group->domain_index; + else if (group->driver->ops->mask_domains) + group->driver->ops->mask_domains(group, mask); + + return false; +} + +static int group_pick(struct snd_soc_domain_group *group, + const unsigned long *domain_mask) +{ + int ndomains = group->component->num_domains; + int i; + + domain_mutex_assert_held(group->component); + + for_each_set_bit(i, domain_mask, ndomains) { + struct snd_soc_domain *domain = &group->component->domains[i]; + + if (!snd_soc_domain_active(domain)) + return i; + } + + return find_first_bit(domain_mask, ndomains); +} + +int snd_soc_domain_attach(struct snd_soc_domain_group *group) +{ + int ret = 0; + + domain_mutex_lock(group->component); + + dev_dbg(group->component->dev, "Attaching domain to %s: %d\n", + group->driver->name, group->attach_count); + + if (!group->attach_count) { + const struct snd_soc_domain_group_ops *ops = group->driver->ops; + unsigned long dom_map = ~0UL; + struct snd_soc_domain *domain; + + group_walk(group, true, group_mask, &dom_map); + + if (ops->pick_domain) + group->domain_index = ops->pick_domain(group, &dom_map); + else + group->domain_index = group_pick(group, &dom_map); + + domain = snd_soc_domain_get(group, SND_SOC_DOMAIN_CURRENT); + if (!domain) { + dev_err(group->component->dev, + "No suitable domain to attach for %s\n", + group->driver->name); + ret = -ENODEV; + goto error; + } + + dev_dbg(group->component->dev, "Apply domain %s to %s\n", + domain->driver->name, group->driver->name); + + ret = ops->set_domain(group, group->domain_index); + if (ret) + goto error; + + domain->active_groups++; + } + + group->attach_count++; + +error: + domain_mutex_unlock(group->component); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_domain_attach); + +int snd_soc_domain_detach(struct snd_soc_domain_group *group) +{ + int ret = 0; + + domain_mutex_lock(group->component); + + dev_dbg(group->component->dev, "Detaching domain from %s: %d\n", + group->driver->name, group->attach_count); + + if (!group->attach_count) { + dev_err(group->component->dev, "Unbalanced detach on %s\n", + group->driver->name); + ret = -EPERM; + } else { + struct snd_soc_domain *domain; + + domain = snd_soc_domain_get(group, SND_SOC_DOMAIN_CURRENT); + if (!domain) { + dev_err(group->component->dev, + "Group %s has missing domain\n", + group->driver->name); + ret = -ENODEV; + goto error; + } + + domain->active_groups--; + group->attach_count--; + } + +error: + domain_mutex_unlock(group->component); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_domain_detach); + +int snd_soc_domain_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + switch (event) { + case SND_SOC_DAPM_WILL_PMU: + w->dgroup->power = true; + return 0; + case SND_SOC_DAPM_PRE_PMU: + return snd_soc_domain_attach(w->dgroup); + case SND_SOC_DAPM_POST_PMD: + w->dgroup->power = false; + return snd_soc_domain_detach(w->dgroup); + default: + return 0; + } +} +EXPORT_SYMBOL_GPL(snd_soc_domain_event); + +static struct domain_group_peer * +group_peer_find(struct snd_soc_domain_group *group, + struct snd_soc_domain_group *peer) +{ + struct domain_group_peer *link; + + domain_mutex_assert_held(group->component); + + list_for_each_entry(link, &group->peers, list) { + if (link->group == peer) + return link; + } + + return NULL; +} + +static int group_peer_new(struct snd_soc_domain_group *group, + struct snd_soc_domain_group *peer) +{ + struct domain_group_peer *link; + + domain_mutex_lock(group->component); + + link = group_peer_find(group, peer); + if (!link) { + dev_dbg(group->component->dev, "New peer: %s -> %s\n", + group->driver->name, peer->driver->name); + + link = kzalloc(sizeof(*link), GFP_KERNEL); + if (!link) + return -ENOMEM; + + INIT_LIST_HEAD(&link->list); + link->group = peer; + + list_add_tail(&link->list, &group->peers); + } + + link->link_count++; + + domain_mutex_unlock(group->component); + + return 0; +} + +static int group_peer_delete(struct snd_soc_domain_group *group, + struct snd_soc_domain_group *peer) +{ + struct domain_group_peer *link; + int ret = 0; + + domain_mutex_lock(group->component); + + link = group_peer_find(group, peer); + if (!link) { + dev_err(group->component->dev, + "Delete on invalid peer: %s -> %s\n", + group->driver->name, peer->driver->name); + ret = -ENOENT; + goto error; + } + + link->link_count--; + if (!link->link_count) { + dev_dbg(group->component->dev, "Delete peer: %s -> %s\n", + group->driver->name, peer->driver->name); + + list_del(&link->list); + kfree(link); + } + +error: + domain_mutex_unlock(group->component); + + return ret; +} + +int snd_soc_domain_connect_widgets(struct snd_soc_dapm_widget *a, + struct snd_soc_dapm_widget *b, + bool connect) +{ + int (*op)(struct snd_soc_domain_group *group, + struct snd_soc_domain_group *peer); + int ret; + + if (!a->dgroup || !b->dgroup) + return 0; + + dev_dbg(a->dapm->dev, "%s %s,%s - %s,%s\n", + connect ? "Connecting" : "Disconnecting", + a->name, a->dgroup->driver->name, + b->name, b->dgroup->driver->name); + + if (connect) + op = group_peer_new; + else + op = group_peer_delete; + + ret = op(a->dgroup, b->dgroup); + if (ret) + return ret; + + ret = op(b->dgroup, a->dgroup); + if (ret) + return ret; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_domain_connect_widgets); From patchwork Thu Oct 11 16:28:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Charles Keepax X-Patchwork-Id: 10637063 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B71D71508 for ; Thu, 11 Oct 2018 17:06:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9EC342BA75 for ; Thu, 11 Oct 2018 17:06:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 929B12BCD3; Thu, 11 Oct 2018 17:06:47 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE,UPPERCASE_50_75 autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C8F652BC72 for ; Thu, 11 Oct 2018 17:06:44 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id F38AE267973; Thu, 11 Oct 2018 18:28:47 +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 F17D7267957; Thu, 11 Oct 2018 18:28:42 +0200 (CEST) Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by alsa0.perex.cz (Postfix) with ESMTP id D455A267943 for ; Thu, 11 Oct 2018 18:28:38 +0200 (CEST) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w9BGSbPl020813; Thu, 11 Oct 2018 11:28:38 -0500 Authentication-Results: ppops.net; spf=none smtp.mailfrom=ckeepax@opensource.cirrus.com Received: from mail3.cirrus.com ([87.246.76.56]) by mx0b-001ae601.pphosted.com with ESMTP id 2mxu49892k-1; Thu, 11 Oct 2018 11:28:33 -0500 Received: from EX17.ad.cirrus.com (ex17.ad.cirrus.com [172.20.9.81]) by mail3.cirrus.com (Postfix) with ESMTP id 94540611C8B6; Thu, 11 Oct 2018 11:30:45 -0500 (CDT) Received: from imbe.wolfsonmicro.main (198.61.95.81) by EX17.ad.cirrus.com (172.20.9.81) with Microsoft SMTP Server id 14.3.408.0; Thu, 11 Oct 2018 17:28:31 +0100 Received: from algalon.ad.cirrus.com (algalon.ad.cirrus.com [198.90.251.122]) by imbe.wolfsonmicro.main (8.14.4/8.14.4) with ESMTP id w9BGSVIU010322; Thu, 11 Oct 2018 17:28:31 +0100 From: Charles Keepax To: Date: Thu, 11 Oct 2018 17:28:31 +0100 Message-ID: <20181011162831.26351-5-ckeepax@opensource.cirrus.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181011162831.26351-1-ckeepax@opensource.cirrus.com> References: <20181011162831.26351-1-ckeepax@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 priorityscore=1501 malwarescore=0 suspectscore=3 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1807170000 definitions=main-1810110158 Cc: patches@opensource.cirrus.com, alsa-devel@alsa-project.org, lgirdwood@gmail.com Subject: [alsa-devel] [RFC PATCH 4/4] ASoC: arizona: Add rate domain support 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 Move to using sample rate domains on the Arizona CODECs. Rate domain group widgets are added and these are connected to all the widgets they supply. arizona_hw_params_rate is updated significantly, it now manually attached the AIF sample rate domain group to a domain at the rate requested by the params. This ensures that any widgets powering up that are connected to the audio interface will be placed on the same sample rate domain. Whilst the SLIMbus technically supports a different sample rate on each channel the driver currently only supports sample rates for capture and playback on each DAI, as such the SLIMBus channels that are grouped onto a single DAI are manually connected together as peers. Signed-off-by: Charles Keepax --- This one is obviously not quite finished yet, the other CODECs in Arizona need updated and the macros that are duplicated will obviously just be updated in that case. Thanks, Charles sound/soc/codecs/arizona.c | 255 ++++++++++++++++++++++------ sound/soc/codecs/arizona.h | 76 ++++++++- sound/soc/codecs/wm5110.c | 414 ++++++++++++++++++++++++++++++++++----------- 3 files changed, 591 insertions(+), 154 deletions(-) diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 5727ea079ad7a..37ce772691739 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -633,12 +633,12 @@ const char *arizona_sample_rate_val_to_name(unsigned int rate_val) EXPORT_SYMBOL_GPL(arizona_sample_rate_val_to_name); const char * const arizona_rate_text[ARIZONA_RATE_ENUM_SIZE] = { - "SYNCCLK rate", "8kHz", "16kHz", "ASYNCCLK rate", + "SYNCCLK rate", "8kHz", "16kHz", "ASYNCCLK rate", "ASYNCCLK rate 2", }; EXPORT_SYMBOL_GPL(arizona_rate_text); const unsigned int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE] = { - 0, 1, 2, 8, + 0, 1, 2, 8, 9, }; EXPORT_SYMBOL_GPL(arizona_rate_val); @@ -1681,40 +1681,15 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct arizona_priv *priv = snd_soc_component_get_drvdata(component); struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1]; - int base = dai->driver->base; - int i, sr_val, ret; - - /* - * We will need to be more flexible than this in future, - * currently we use a single sample rate for SYSCLK. - */ - for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++) - if (arizona_sr_vals[i] == params_rate(params)) - break; - if (i == ARRAY_SIZE(arizona_sr_vals)) { - arizona_aif_err(dai, "Unsupported sample rate %dHz\n", - params_rate(params)); - return -EINVAL; - } - sr_val = i; - - switch (priv->arizona->type) { - case WM5102: - case WM8997: - if (arizona_sr_vals[sr_val] >= 88200) - ret = arizona_dvfs_up(component, ARIZONA_DVFS_SR1_RQ); - else - ret = arizona_dvfs_down(component, ARIZONA_DVFS_SR1_RQ); + int ret; + struct snd_soc_domain_group *dgrp; - if (ret) { - arizona_aif_err(dai, "Failed to change DVFS %d\n", ret); - return ret; - } - break; - default: - break; - } + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + dgrp = dai->playback_widget->dgroup; + else + dgrp = dai->capture_widget->dgroup; + /* TODO: This should be handled on power up of the OUT_RATE widget */ switch (dai_priv->clk) { case ARIZONA_CLK_SYSCLK: switch (priv->arizona->type) { @@ -1725,31 +1700,38 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream, default: break; } - - snd_soc_component_update_bits(component, ARIZONA_SAMPLE_RATE_1, - ARIZONA_SAMPLE_RATE_1_MASK, - sr_val); - if (base) - snd_soc_component_update_bits(component, - base + ARIZONA_AIF_RATE_CTRL, - ARIZONA_AIF1_RATE_MASK, 0); break; case ARIZONA_CLK_ASYNCCLK: - snd_soc_component_update_bits(component, - ARIZONA_ASYNC_SAMPLE_RATE_1, - ARIZONA_ASYNC_SAMPLE_RATE_1_MASK, - sr_val); - if (base) - snd_soc_component_update_bits(component, - base + ARIZONA_AIF_RATE_CTRL, - ARIZONA_AIF1_RATE_MASK, - 8 << ARIZONA_AIF1_RATE_SHIFT); break; default: arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk); return -EINVAL; } + /* TODO: Needs updated to handle multiple calls of hw_params */ + ret = snd_soc_domain_attach(dgrp); + if (ret) + return ret; + + ret = snd_soc_domain_set_rate(dgrp, params_rate(params)); + if (ret) + return ret; + + return 0; +} + +static int arizona_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_domain_group *dgrp; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + dgrp = dai->playback_widget->dgroup; + else + dgrp = dai->capture_widget->dgroup; + + snd_soc_domain_detach(dgrp); + return 0; } @@ -2029,6 +2011,7 @@ const struct snd_soc_dai_ops arizona_dai_ops = { .set_fmt = arizona_set_fmt, .set_tdm_slot = arizona_set_tdm_slot, .hw_params = arizona_hw_params, + .hw_free = arizona_hw_free, .set_sysclk = arizona_dai_set_sysclk, .set_tristate = arizona_set_tristate, }; @@ -2858,6 +2841,176 @@ int arizona_of_get_audio_pdata(struct arizona *arizona) } EXPORT_SYMBOL_GPL(arizona_of_get_audio_pdata); +static int arizona_set_rate(struct snd_soc_domain *dom, int rate) +{ + struct snd_soc_component *component = dom->component; + struct arizona *arizona = dev_get_drvdata(component->dev->parent); + const struct arizona_rate_dom_priv *dpriv = dom->driver->private_data; + int i, ret; + + dev_dbg(arizona->dev, "Set %s to %d Hz\n", dom->driver->name, rate); + + switch (arizona->type) { + case WM5102: + case WM8997: + if (rate >= 88200) + ret = arizona_dvfs_up(component, dpriv->dvfs_mask); + else + ret = arizona_dvfs_down(component, dpriv->dvfs_mask); + + if (ret) { + dev_err(arizona->dev, + "Failed to change DVFS for %s: %d\n", + dom->driver->name, ret); + return ret; + } + break; + default: + break; + } + + for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++) { + if (arizona_sr_vals[i] == rate) + break; + } + + if (i == ARRAY_SIZE(arizona_sr_vals)) { + dev_err(arizona->dev, "Invalid sample rate: %d Hz\n", rate); + return -EINVAL; + } + + return regmap_update_bits(arizona->regmap, dpriv->reg, + ARIZONA_SAMPLE_RATE_1_MASK, i); +} + +static int arizona_get_rate(struct snd_soc_domain *dom) +{ + struct snd_soc_component *component = dom->component; + struct arizona *arizona = dev_get_drvdata(component->dev->parent); + const struct arizona_rate_dom_priv *dpriv = dom->driver->private_data; + unsigned int rate; + int ret; + + ret = regmap_read(arizona->regmap, dpriv->reg, &rate); + if (ret) + return ret; + + rate &= ARIZONA_SAMPLE_RATE_1_MASK; + + if (rate >= ARRAY_SIZE(arizona_sr_vals)) { + dev_err(arizona->dev, "Read bad sample rate: 0x%x\n", rate); + return -EINVAL; + } + + rate = arizona_sr_vals[rate]; + + dev_dbg(arizona->dev, "Got %u Hz for %s\n", rate, dom->driver->name); + + return (int)rate; +} + +static const struct snd_soc_domain_ops arizona_dom_ops = { + .set_rate = arizona_set_rate, + .get_rate = arizona_get_rate, +}; + +const struct snd_soc_domain_driver arizona_rate_domains[ARIZONA_RATE_ENUM_SIZE] = { + { + .name = "Sample Rate 1", + .ops = &arizona_dom_ops, + .private_data = &(struct arizona_rate_dom_priv){ + .reg = ARIZONA_SAMPLE_RATE_1, + .val = 0, + .dvfs_mask = ARIZONA_DVFS_SR1_RQ, + }, + }, + { + .name = "Sample Rate 2", + .ops = &arizona_dom_ops, + .private_data = &(struct arizona_rate_dom_priv){ + .reg = ARIZONA_SAMPLE_RATE_2, + .val = 1, + .dvfs_mask = ARIZONA_DVFS_SR2_RQ, + }, + }, + { + .name = "Sample Rate 3", + .ops = &arizona_dom_ops, + .private_data = &(struct arizona_rate_dom_priv){ + .reg = ARIZONA_SAMPLE_RATE_3, + .val = 2, + .dvfs_mask = ARIZONA_DVFS_SR3_RQ, + }, + }, + { + .name = "Async Sample Rate 1", + .ops = &arizona_dom_ops, + .private_data = &(struct arizona_rate_dom_priv){ + .reg = ARIZONA_ASYNC_SAMPLE_RATE_1, + .val = 8, + .dvfs_mask = ARIZONA_DVFS_ASR1_RQ, + }, + }, + { + .name = "Async Sample Rate 2", + .ops = &arizona_dom_ops, + .private_data = &(struct arizona_rate_dom_priv){ + .reg = ARIZONA_ASYNC_SAMPLE_RATE_2, + .val = 9, + .dvfs_mask = ARIZONA_DVFS_ASR2_RQ, + }, + }, +}; + +int arizona_set_domain(struct snd_soc_domain_group *dgrp, int dom) +{ + struct arizona *arizona = dev_get_drvdata(dgrp->component->dev->parent); + const struct arizona_rate_grp_priv *gpriv = dgrp->driver->private_data; + const struct arizona_rate_dom_priv *dpriv = arizona_rate_domains[dom].private_data; + + return regmap_update_bits(arizona->regmap, gpriv->reg, gpriv->mask, + dpriv->val << gpriv->shift); +} + +int arizona_mask_domain(struct snd_soc_domain_group *dgrp, unsigned long *mask) +{ + const struct arizona_rate_grp_priv *gpriv = dgrp->driver->private_data; + struct snd_soc_component *component = dgrp->component; + struct arizona_priv *priv = snd_soc_component_get_drvdata(component); + unsigned long supported = 0; + + switch (gpriv->reg) { + case ARIZONA_AIF1_RATE_CTRL: + case ARIZONA_AIF2_RATE_CTRL: + case ARIZONA_AIF3_RATE_CTRL: + switch (priv->dai[ARIZONA_AIF1_RATE_CTRL - gpriv->reg].clk) { + case ARIZONA_CLK_ASYNCCLK: + supported |= 0x18; + break; + default: + supported |= 0x7; + break; + } + break; + default: + if (gpriv->sync) + supported |= 0x7; + if (gpriv->async) + supported |= 0x18; + break; + } + + *mask &= supported; + + return 0; +} + +const struct snd_soc_domain_group_ops arizona_dgrp_ops = { + .set_domain = arizona_set_domain, + .mask_domains = arizona_mask_domain, +}; +EXPORT_SYMBOL_GPL(arizona_dgrp_ops); + MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support"); MODULE_AUTHOR("Mark Brown "); MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index e3ccee5627c6b..734a90648224f 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -63,6 +63,10 @@ #define ARIZONA_MAX_ADSP 4 #define ARIZONA_DVFS_SR1_RQ 0x001 +#define ARIZONA_DVFS_SR2_RQ 0x002 +#define ARIZONA_DVFS_SR3_RQ 0x004 +#define ARIZONA_DVFS_ASR1_RQ 0x008 +#define ARIZONA_DVFS_ASR2_RQ 0x010 #define ARIZONA_DVFS_ADSP1_RQ 0x100 /* Notifier events */ @@ -189,6 +193,26 @@ extern unsigned int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; ARIZONA_MIXER_INPUT_ROUTES(name " Input 3"), \ ARIZONA_MIXER_INPUT_ROUTES(name " Input 4") +#define ARIZONA_MUX_ROUTES_R(widget, name, rate) \ + { widget, NULL, name " Input" }, \ + { name " Input", NULL, rate }, \ + ARIZONA_MIXER_INPUT_ROUTES(name " Input") + +#define ARIZONA_MIXER_ROUTES_R(widget, name, rate) \ + { widget, NULL, name " Mixer" }, \ + { name " Mixer", NULL, name " Input 1" }, \ + { name " Mixer", NULL, name " Input 2" }, \ + { name " Mixer", NULL, name " Input 3" }, \ + { name " Mixer", NULL, name " Input 4" }, \ + { name " Input 1", NULL, rate }, \ + { name " Input 2", NULL, rate }, \ + { name " Input 3", NULL, rate }, \ + { name " Input 4", NULL, rate }, \ + ARIZONA_MIXER_INPUT_ROUTES(name " Input 1"), \ + ARIZONA_MIXER_INPUT_ROUTES(name " Input 2"), \ + ARIZONA_MIXER_INPUT_ROUTES(name " Input 3"), \ + ARIZONA_MIXER_INPUT_ROUTES(name " Input 4") + #define ARIZONA_DSP_ROUTES(name) \ { name, NULL, name " Preloader"}, \ { name " Preloader", NULL, "SYSCLK" }, \ @@ -208,6 +232,32 @@ extern unsigned int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; ARIZONA_MIXER_ROUTES(name, name "L"), \ ARIZONA_MIXER_ROUTES(name, name "R") +#define ARIZONA_DSP_ROUTES_R(name, rate) \ + { name, NULL, rate }, \ + { name, NULL, name " Preloader"}, \ + { name " Preloader", NULL, "SYSCLK" }, \ + { name " Preload", NULL, name " Preloader"}, \ + { name, NULL, name " Aux 1" }, \ + { name, NULL, name " Aux 2" }, \ + { name, NULL, name " Aux 3" }, \ + { name, NULL, name " Aux 4" }, \ + { name, NULL, name " Aux 5" }, \ + { name, NULL, name " Aux 6" }, \ + { name " Aux 1", NULL, rate }, \ + { name " Aux 2", NULL, rate }, \ + { name " Aux 3", NULL, rate }, \ + { name " Aux 4", NULL, rate }, \ + { name " Aux 5", NULL, rate }, \ + { name " Aux 6", NULL, rate }, \ + ARIZONA_MIXER_INPUT_ROUTES(name " Aux 1"), \ + ARIZONA_MIXER_INPUT_ROUTES(name " Aux 2"), \ + ARIZONA_MIXER_INPUT_ROUTES(name " Aux 3"), \ + ARIZONA_MIXER_INPUT_ROUTES(name " Aux 4"), \ + ARIZONA_MIXER_INPUT_ROUTES(name " Aux 5"), \ + ARIZONA_MIXER_INPUT_ROUTES(name " Aux 6"), \ + ARIZONA_MIXER_ROUTES_R(name, name "L", rate), \ + ARIZONA_MIXER_ROUTES_R(name, name "R", rate) + #define ARIZONA_EQ_CONTROL(xname, xbase) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \ @@ -222,7 +272,7 @@ extern unsigned int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; ((unsigned long)&(struct soc_bytes) { .base = xbase, \ .num_regs = 1 }) } -#define ARIZONA_RATE_ENUM_SIZE 4 +#define ARIZONA_RATE_ENUM_SIZE 5 #define ARIZONA_SAMPLE_RATE_ENUM_SIZE 14 extern const char * const arizona_rate_text[ARIZONA_RATE_ENUM_SIZE]; @@ -354,4 +404,28 @@ static inline int arizona_unregister_notifier(struct snd_soc_component *componen int arizona_of_get_audio_pdata(struct arizona *arizona); +struct arizona_rate_dom_priv { + unsigned int reg; + unsigned int val; + int dvfs_mask; +}; + +struct arizona_rate_grp_priv { + unsigned int reg; + unsigned int mask; + unsigned int shift; + + bool sync; + bool async; +}; + +#define ARIZONA_RATE_WIDGET(rname, rsync, rasync, rreg, rmask) \ + SND_SOC_DAPM_RATE(rname, SND_SOC_NOPM, 0, 0, &arizona_dgrp_ops, \ + (&(struct arizona_rate_grp_priv){ .reg = rreg, \ + .mask = rmask##_MASK, .shift = rmask##_SHIFT, \ + .sync = rsync, .async = rasync})) + +extern const struct snd_soc_domain_group_ops arizona_dgrp_ops; +extern const struct snd_soc_domain_driver arizona_rate_domains[ARIZONA_RATE_ENUM_SIZE]; + #endif diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index b0789a03d699b..930092370735e 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -1092,6 +1092,88 @@ static const struct snd_kcontrol_new wm5110_output_anc_src[] = { }; static const struct snd_soc_dapm_widget wm5110_dapm_widgets[] = { +ARIZONA_RATE_WIDGET("In Rate", 1, 0, ARIZONA_INPUT_RATE, ARIZONA_IN_RATE), + +ARIZONA_RATE_WIDGET("Out Rate", 1, 0, ARIZONA_OUTPUT_RATE_1, ARIZONA_OUT_RATE), +ARIZONA_RATE_WIDGET("PWM Rate", 1, 0, ARIZONA_PWM_DRIVE_1, ARIZONA_PWM_RATE), + +ARIZONA_RATE_WIDGET("Tone Rate", 1, 1, ARIZONA_TONE_GENERATOR_1, + ARIZONA_TONE_RATE), +ARIZONA_RATE_WIDGET("Noise Rate", 1, 1, ARIZONA_COMFORT_NOISE_GENERATOR, + ARIZONA_NOISE_GEN_RATE), +ARIZONA_RATE_WIDGET("Haptics Rate", 1, 0, ARIZONA_HAPTICS_CONTROL_1, + ARIZONA_HAP_RATE), +ARIZONA_RATE_WIDGET("FX Rate", 1, 1, ARIZONA_FX_CTRL1, ARIZONA_FX_RATE), + +ARIZONA_RATE_WIDGET("AIF1 Rate", 1, 1, ARIZONA_AIF1_RATE_CTRL, + ARIZONA_AIF1_RATE), +ARIZONA_RATE_WIDGET("AIF2 Rate", 1, 1, ARIZONA_AIF2_RATE_CTRL, + ARIZONA_AIF2_RATE), +ARIZONA_RATE_WIDGET("AIF3 Rate", 1, 1, ARIZONA_AIF3_RATE_CTRL, + ARIZONA_AIF3_RATE), + +ARIZONA_RATE_WIDGET("ASRC Rate", 1, 0, ARIZONA_ASRC_RATE1, ARIZONA_ASRC_RATE1), +ARIZONA_RATE_WIDGET("ASRC Async Rate", 0, 1, ARIZONA_ASRC_RATE2, + ARIZONA_ASRC_RATE2), + +ARIZONA_RATE_WIDGET("Mic Mute Rate", 1, 1, ARIZONA_MIC_NOISE_MIX_CONTROL_1, + ARIZONA_MICMUTE_RATE), + +ARIZONA_RATE_WIDGET("ISRC1 FSH", 1, 1, ARIZONA_ISRC_1_CTRL_1, + ARIZONA_ISRC1_FSH), +ARIZONA_RATE_WIDGET("ISRC1 FSL", 1, 1, ARIZONA_ISRC_1_CTRL_2, + ARIZONA_ISRC1_FSL), +ARIZONA_RATE_WIDGET("ISRC2 FSH", 1, 1, ARIZONA_ISRC_2_CTRL_1, + ARIZONA_ISRC2_FSH), +ARIZONA_RATE_WIDGET("ISRC2 FSL", 1, 1, ARIZONA_ISRC_2_CTRL_2, + ARIZONA_ISRC2_FSL), +ARIZONA_RATE_WIDGET("ISRC3 FSH", 1, 1, ARIZONA_ISRC_3_CTRL_1, + ARIZONA_ISRC3_FSH), +ARIZONA_RATE_WIDGET("ISRC3 FSL", 1, 1, ARIZONA_ISRC_3_CTRL_2, + ARIZONA_ISRC3_FSL), + +ARIZONA_RATE_WIDGET("DSP1 Rate", 1, 1, ARIZONA_DSP1_CONTROL_1, + ARIZONA_DSP1_RATE), +ARIZONA_RATE_WIDGET("DSP2 Rate", 1, 1, ARIZONA_DSP2_CONTROL_1, + ARIZONA_DSP1_RATE), +ARIZONA_RATE_WIDGET("DSP3 Rate", 1, 1, ARIZONA_DSP3_CONTROL_1, + ARIZONA_DSP1_RATE), +ARIZONA_RATE_WIDGET("DSP4 Rate", 1, 1, ARIZONA_DSP4_CONTROL_1, + ARIZONA_DSP1_RATE), + +ARIZONA_RATE_WIDGET("SLIMRX1 Rate", 1, 1, ARIZONA_SLIMBUS_RATES_1, + ARIZONA_SLIMRX1_RATE), +ARIZONA_RATE_WIDGET("SLIMRX2 Rate", 1, 1, ARIZONA_SLIMBUS_RATES_1, + ARIZONA_SLIMRX2_RATE), +ARIZONA_RATE_WIDGET("SLIMRX3 Rate", 1, 1, ARIZONA_SLIMBUS_RATES_2, + ARIZONA_SLIMRX3_RATE), +ARIZONA_RATE_WIDGET("SLIMRX4 Rate", 1, 1, ARIZONA_SLIMBUS_RATES_2, + ARIZONA_SLIMRX4_RATE), +ARIZONA_RATE_WIDGET("SLIMRX5 Rate", 1, 1, ARIZONA_SLIMBUS_RATES_3, + ARIZONA_SLIMRX5_RATE), +ARIZONA_RATE_WIDGET("SLIMRX6 Rate", 1, 1, ARIZONA_SLIMBUS_RATES_3, + ARIZONA_SLIMRX6_RATE), +ARIZONA_RATE_WIDGET("SLIMRX7 Rate", 1, 1, ARIZONA_SLIMBUS_RATES_4, + ARIZONA_SLIMRX7_RATE), +ARIZONA_RATE_WIDGET("SLIMRX8 Rate", 1, 1, ARIZONA_SLIMBUS_RATES_4, + ARIZONA_SLIMRX8_RATE), +ARIZONA_RATE_WIDGET("SLIMTX1 Rate", 1, 1, ARIZONA_SLIMBUS_RATES_5, + ARIZONA_SLIMTX1_RATE), +ARIZONA_RATE_WIDGET("SLIMTX2 Rate", 1, 1, ARIZONA_SLIMBUS_RATES_5, + ARIZONA_SLIMTX2_RATE), +ARIZONA_RATE_WIDGET("SLIMTX3 Rate", 1, 1, ARIZONA_SLIMBUS_RATES_6, + ARIZONA_SLIMTX3_RATE), +ARIZONA_RATE_WIDGET("SLIMTX4 Rate", 1, 1, ARIZONA_SLIMBUS_RATES_6, + ARIZONA_SLIMTX4_RATE), +ARIZONA_RATE_WIDGET("SLIMTX5 Rate", 1, 1, ARIZONA_SLIMBUS_RATES_7, + ARIZONA_SLIMTX5_RATE), +ARIZONA_RATE_WIDGET("SLIMTX6 Rate", 1, 1, ARIZONA_SLIMBUS_RATES_7, + ARIZONA_SLIMTX6_RATE), +ARIZONA_RATE_WIDGET("SLIMTX7 Rate", 1, 1, ARIZONA_SLIMBUS_RATES_8, + ARIZONA_SLIMTX7_RATE), +ARIZONA_RATE_WIDGET("SLIMTX8 Rate", 1, 1, ARIZONA_SLIMBUS_RATES_8, + ARIZONA_SLIMTX8_RATE), + SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, 0, wm5110_sysclk_ev, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), @@ -1728,6 +1810,119 @@ SND_SOC_DAPM_OUTPUT("MICSUPP"), { name, "DSP4.6", "DSP4" } static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { + { "IN1L PGA", NULL, "In Rate" }, + { "IN1R PGA", NULL, "In Rate" }, + { "IN2L PGA", NULL, "In Rate" }, + { "IN2R PGA", NULL, "In Rate" }, + { "IN3L PGA", NULL, "In Rate" }, + { "IN3R PGA", NULL, "In Rate" }, + { "IN4L PGA", NULL, "In Rate" }, + { "IN4R PGA", NULL, "In Rate" }, + + { "AIF1 Playback", NULL, "AIF1 Rate" }, + { "AIF1 Capture", NULL, "AIF1 Rate" }, + { "AIF1RX1", NULL, "AIF1 Rate" }, + { "AIF1RX2", NULL, "AIF1 Rate" }, + { "AIF1RX3", NULL, "AIF1 Rate" }, + { "AIF1RX4", NULL, "AIF1 Rate" }, + { "AIF1RX5", NULL, "AIF1 Rate" }, + { "AIF1RX6", NULL, "AIF1 Rate" }, + { "AIF1RX7", NULL, "AIF1 Rate" }, + { "AIF1RX8", NULL, "AIF1 Rate" }, + + { "AIF2 Playback", NULL, "AIF2 Rate" }, + { "AIF2 Capture", NULL, "AIF2 Rate" }, + { "AIF2RX1", NULL, "AIF2 Rate" }, + { "AIF2RX2", NULL, "AIF2 Rate" }, + { "AIF2RX3", NULL, "AIF2 Rate" }, + { "AIF2RX4", NULL, "AIF2 Rate" }, + { "AIF2RX5", NULL, "AIF2 Rate" }, + { "AIF2RX6", NULL, "AIF2 Rate" }, + + { "AIF3 Playback", NULL, "AIF3 Rate" }, + { "AIF3 Capture", NULL, "AIF3 Rate" }, + { "AIF3RX1", NULL, "AIF3 Rate" }, + { "AIF3RX2", NULL, "AIF3 Rate" }, + + { "EQ1", NULL, "FX Rate" }, + { "EQ2", NULL, "FX Rate" }, + { "EQ3", NULL, "FX Rate" }, + { "EQ4", NULL, "FX Rate" }, + + { "DRC1L", NULL, "FX Rate" }, + { "DRC1R", NULL, "FX Rate" }, + { "DRC2L", NULL, "FX Rate" }, + { "DRC2R", NULL, "FX Rate" }, + + { "LHPF1", NULL, "FX Rate" }, + { "LHPF2", NULL, "FX Rate" }, + { "LHPF3", NULL, "FX Rate" }, + { "LHPF4", NULL, "FX Rate" }, + + { "PWM1 Driver", NULL, "PWM Rate" }, + { "PWM2 Driver", NULL, "PWM Rate" }, + + { "HAPTICS", NULL, "Haptics Rate" }, + + { "Noise Generator", NULL, "Noise Rate" }, + { "Tone Generator 1", NULL, "Tone Rate" }, + { "Tone Generator 2", NULL, "Tone Rate" }, + + { "Mic Mute Mixer", NULL, "Mic Mute Rate" }, + + { "ASRC1L", NULL, "ASRC Async Rate" }, + { "ASRC1R", NULL, "ASRC Async Rate" }, + { "ASRC2L", NULL, "ASRC Rate" }, + { "ASRC2R", NULL, "ASRC Rate" }, + + { "ISRC1INT1", NULL, "ISRC1 FSH" }, + { "ISRC1INT2", NULL, "ISRC1 FSH" }, + { "ISRC1INT3", NULL, "ISRC1 FSH" }, + { "ISRC1INT4", NULL, "ISRC1 FSH" }, + + { "ISRC1DEC1", NULL, "ISRC1 FSL" }, + { "ISRC1DEC2", NULL, "ISRC1 FSL" }, + { "ISRC1DEC3", NULL, "ISRC1 FSL" }, + { "ISRC1DEC4", NULL, "ISRC1 FSL" }, + + { "ISRC2INT1", NULL, "ISRC2 FSH" }, + { "ISRC2INT2", NULL, "ISRC2 FSH" }, + { "ISRC2INT3", NULL, "ISRC2 FSH" }, + { "ISRC2INT4", NULL, "ISRC2 FSH" }, + + { "ISRC2DEC1", NULL, "ISRC2 FSL" }, + { "ISRC2DEC2", NULL, "ISRC2 FSL" }, + { "ISRC2DEC3", NULL, "ISRC2 FSL" }, + { "ISRC2DEC4", NULL, "ISRC2 FSL" }, + + { "ISRC3INT1", NULL, "ISRC3 FSH" }, + { "ISRC3INT2", NULL, "ISRC3 FSH" }, + { "ISRC3INT3", NULL, "ISRC3 FSH" }, + { "ISRC3INT4", NULL, "ISRC3 FSH" }, + + { "ISRC3DEC1", NULL, "ISRC3 FSL" }, + { "ISRC3DEC2", NULL, "ISRC3 FSL" }, + { "ISRC3DEC3", NULL, "ISRC3 FSL" }, + { "ISRC3DEC4", NULL, "ISRC3 FSL" }, + + { "SLIMRX1", NULL, "SLIMRX1 Rate" }, + { "SLIMRX2", NULL, "SLIMRX2 Rate" }, + { "SLIMRX3", NULL, "SLIMRX3 Rate" }, + { "SLIMRX4", NULL, "SLIMRX4 Rate" }, + { "SLIMRX5", NULL, "SLIMRX5 Rate" }, + { "SLIMRX6", NULL, "SLIMRX6 Rate" }, + { "SLIMRX7", NULL, "SLIMRX7 Rate" }, + { "SLIMRX8", NULL, "SLIMRX8 Rate" }, + + { "Slim1 Playback", NULL, "SLIMRX1 Rate" }, + { "Slim1 Capture", NULL, "SLIMTX1 Rate" }, + + { "Slim2 Playback", NULL, "SLIMRX5 Rate" }, + { "Slim2 Capture", NULL, "SLIMTX5 Rate" }, + + { "Slim3 Playback", NULL, "SLIMRX7 Rate" }, + { "Slim3 Capture", NULL, "SLIMTX7 Rate" }, + { "AIF2 Capture", NULL, "DBVDD2" }, { "AIF2 Playback", NULL, "DBVDD2" }, @@ -1878,108 +2073,108 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { { "IN4L PGA", NULL, "IN4L" }, { "IN4R PGA", NULL, "IN4R" }, - ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"), - ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), - ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), - ARIZONA_MIXER_ROUTES("OUT2R", "HPOUT2R"), - ARIZONA_MIXER_ROUTES("OUT3L", "HPOUT3L"), - ARIZONA_MIXER_ROUTES("OUT3R", "HPOUT3R"), - - ARIZONA_MIXER_ROUTES("OUT4L", "SPKOUTL"), - ARIZONA_MIXER_ROUTES("OUT4R", "SPKOUTR"), - ARIZONA_MIXER_ROUTES("OUT5L", "SPKDAT1L"), - ARIZONA_MIXER_ROUTES("OUT5R", "SPKDAT1R"), - ARIZONA_MIXER_ROUTES("OUT6L", "SPKDAT2L"), - ARIZONA_MIXER_ROUTES("OUT6R", "SPKDAT2R"), - - ARIZONA_MIXER_ROUTES("PWM1 Driver", "PWM1"), - ARIZONA_MIXER_ROUTES("PWM2 Driver", "PWM2"), - - ARIZONA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"), - ARIZONA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"), - ARIZONA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"), - ARIZONA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"), - ARIZONA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"), - ARIZONA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"), - ARIZONA_MIXER_ROUTES("AIF1TX7", "AIF1TX7"), - ARIZONA_MIXER_ROUTES("AIF1TX8", "AIF1TX8"), - - ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), - ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), - ARIZONA_MIXER_ROUTES("AIF2TX3", "AIF2TX3"), - ARIZONA_MIXER_ROUTES("AIF2TX4", "AIF2TX4"), - ARIZONA_MIXER_ROUTES("AIF2TX5", "AIF2TX5"), - ARIZONA_MIXER_ROUTES("AIF2TX6", "AIF2TX6"), - - ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), - ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), - - ARIZONA_MIXER_ROUTES("SLIMTX1", "SLIMTX1"), - ARIZONA_MIXER_ROUTES("SLIMTX2", "SLIMTX2"), - ARIZONA_MIXER_ROUTES("SLIMTX3", "SLIMTX3"), - ARIZONA_MIXER_ROUTES("SLIMTX4", "SLIMTX4"), - ARIZONA_MIXER_ROUTES("SLIMTX5", "SLIMTX5"), - ARIZONA_MIXER_ROUTES("SLIMTX6", "SLIMTX6"), - ARIZONA_MIXER_ROUTES("SLIMTX7", "SLIMTX7"), - ARIZONA_MIXER_ROUTES("SLIMTX8", "SLIMTX8"), - - ARIZONA_MIXER_ROUTES("EQ1", "EQ1"), - ARIZONA_MIXER_ROUTES("EQ2", "EQ2"), - ARIZONA_MIXER_ROUTES("EQ3", "EQ3"), - ARIZONA_MIXER_ROUTES("EQ4", "EQ4"), - - ARIZONA_MIXER_ROUTES("DRC1L", "DRC1L"), - ARIZONA_MIXER_ROUTES("DRC1R", "DRC1R"), - ARIZONA_MIXER_ROUTES("DRC2L", "DRC2L"), - ARIZONA_MIXER_ROUTES("DRC2R", "DRC2R"), - - ARIZONA_MIXER_ROUTES("LHPF1", "LHPF1"), - ARIZONA_MIXER_ROUTES("LHPF2", "LHPF2"), - ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"), - ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"), - - ARIZONA_MIXER_ROUTES("Mic Mute Mixer", "Noise"), - ARIZONA_MIXER_ROUTES("Mic Mute Mixer", "Mic"), - - ARIZONA_MUX_ROUTES("ASRC1L", "ASRC1L"), - ARIZONA_MUX_ROUTES("ASRC1R", "ASRC1R"), - ARIZONA_MUX_ROUTES("ASRC2L", "ASRC2L"), - ARIZONA_MUX_ROUTES("ASRC2R", "ASRC2R"), - - ARIZONA_DSP_ROUTES("DSP1"), - ARIZONA_DSP_ROUTES("DSP2"), - ARIZONA_DSP_ROUTES("DSP3"), - ARIZONA_DSP_ROUTES("DSP4"), - - ARIZONA_MUX_ROUTES("ISRC1INT1", "ISRC1INT1"), - ARIZONA_MUX_ROUTES("ISRC1INT2", "ISRC1INT2"), - ARIZONA_MUX_ROUTES("ISRC1INT3", "ISRC1INT3"), - ARIZONA_MUX_ROUTES("ISRC1INT4", "ISRC1INT4"), - - ARIZONA_MUX_ROUTES("ISRC1DEC1", "ISRC1DEC1"), - ARIZONA_MUX_ROUTES("ISRC1DEC2", "ISRC1DEC2"), - ARIZONA_MUX_ROUTES("ISRC1DEC3", "ISRC1DEC3"), - ARIZONA_MUX_ROUTES("ISRC1DEC4", "ISRC1DEC4"), - - ARIZONA_MUX_ROUTES("ISRC2INT1", "ISRC2INT1"), - ARIZONA_MUX_ROUTES("ISRC2INT2", "ISRC2INT2"), - ARIZONA_MUX_ROUTES("ISRC2INT3", "ISRC2INT3"), - ARIZONA_MUX_ROUTES("ISRC2INT4", "ISRC2INT4"), - - ARIZONA_MUX_ROUTES("ISRC2DEC1", "ISRC2DEC1"), - ARIZONA_MUX_ROUTES("ISRC2DEC2", "ISRC2DEC2"), - ARIZONA_MUX_ROUTES("ISRC2DEC3", "ISRC2DEC3"), - ARIZONA_MUX_ROUTES("ISRC2DEC4", "ISRC2DEC4"), - - ARIZONA_MUX_ROUTES("ISRC3INT1", "ISRC3INT1"), - ARIZONA_MUX_ROUTES("ISRC3INT2", "ISRC3INT2"), - ARIZONA_MUX_ROUTES("ISRC3INT3", "ISRC3INT3"), - ARIZONA_MUX_ROUTES("ISRC3INT4", "ISRC3INT4"), - - ARIZONA_MUX_ROUTES("ISRC3DEC1", "ISRC3DEC1"), - ARIZONA_MUX_ROUTES("ISRC3DEC2", "ISRC3DEC2"), - ARIZONA_MUX_ROUTES("ISRC3DEC3", "ISRC3DEC3"), - ARIZONA_MUX_ROUTES("ISRC3DEC4", "ISRC3DEC4"), + ARIZONA_MIXER_ROUTES_R("OUT1L", "HPOUT1L", "Out Rate"), + ARIZONA_MIXER_ROUTES_R("OUT1R", "HPOUT1R", "Out Rate"), + ARIZONA_MIXER_ROUTES_R("OUT2L", "HPOUT2L", "Out Rate"), + ARIZONA_MIXER_ROUTES_R("OUT2R", "HPOUT2R", "Out Rate"), + ARIZONA_MIXER_ROUTES_R("OUT3L", "HPOUT3L", "Out Rate"), + ARIZONA_MIXER_ROUTES_R("OUT3R", "HPOUT3R", "Out Rate"), + + ARIZONA_MIXER_ROUTES_R("OUT4L", "SPKOUTL", "Out Rate"), + ARIZONA_MIXER_ROUTES_R("OUT4R", "SPKOUTR", "Out Rate"), + ARIZONA_MIXER_ROUTES_R("OUT5L", "SPKDAT1L", "Out Rate"), + ARIZONA_MIXER_ROUTES_R("OUT5R", "SPKDAT1R", "Out Rate"), + ARIZONA_MIXER_ROUTES_R("OUT6L", "SPKDAT2L", "Out Rate"), + ARIZONA_MIXER_ROUTES_R("OUT6R", "SPKDAT2R", "Out Rate"), + + ARIZONA_MIXER_ROUTES_R("PWM1 Driver", "PWM1", "PWM Rate"), + ARIZONA_MIXER_ROUTES_R("PWM2 Driver", "PWM2", "PWM Rate"), + + ARIZONA_MIXER_ROUTES_R("AIF1TX1", "AIF1TX1", "AIF1 Rate"), + ARIZONA_MIXER_ROUTES_R("AIF1TX2", "AIF1TX2", "AIF1 Rate"), + ARIZONA_MIXER_ROUTES_R("AIF1TX3", "AIF1TX3", "AIF1 Rate"), + ARIZONA_MIXER_ROUTES_R("AIF1TX4", "AIF1TX4", "AIF1 Rate"), + ARIZONA_MIXER_ROUTES_R("AIF1TX5", "AIF1TX5", "AIF1 Rate"), + ARIZONA_MIXER_ROUTES_R("AIF1TX6", "AIF1TX6", "AIF1 Rate"), + ARIZONA_MIXER_ROUTES_R("AIF1TX7", "AIF1TX7", "AIF1 Rate"), + ARIZONA_MIXER_ROUTES_R("AIF1TX8", "AIF1TX8", "AIF1 Rate"), + + ARIZONA_MIXER_ROUTES_R("AIF2TX1", "AIF2TX1", "AIF2 Rate"), + ARIZONA_MIXER_ROUTES_R("AIF2TX2", "AIF2TX2", "AIF2 Rate"), + ARIZONA_MIXER_ROUTES_R("AIF2TX3", "AIF2TX3", "AIF2 Rate"), + ARIZONA_MIXER_ROUTES_R("AIF2TX4", "AIF2TX4", "AIF2 Rate"), + ARIZONA_MIXER_ROUTES_R("AIF2TX5", "AIF2TX5", "AIF2 Rate"), + ARIZONA_MIXER_ROUTES_R("AIF2TX6", "AIF2TX6", "AIF2 Rate"), + + ARIZONA_MIXER_ROUTES_R("AIF3TX1", "AIF3TX1", "AIF3 Rate"), + ARIZONA_MIXER_ROUTES_R("AIF3TX2", "AIF3TX2", "AIF3 Rate"), + + ARIZONA_MIXER_ROUTES_R("SLIMTX1", "SLIMTX1", "SLIMTX1 Rate"), + ARIZONA_MIXER_ROUTES_R("SLIMTX2", "SLIMTX2", "SLIMTX2 Rate"), + ARIZONA_MIXER_ROUTES_R("SLIMTX3", "SLIMTX3", "SLIMTX3 Rate"), + ARIZONA_MIXER_ROUTES_R("SLIMTX4", "SLIMTX4", "SLIMTX4 Rate"), + ARIZONA_MIXER_ROUTES_R("SLIMTX5", "SLIMTX5", "SLIMTX5 Rate"), + ARIZONA_MIXER_ROUTES_R("SLIMTX6", "SLIMTX6", "SLIMTX6 Rate"), + ARIZONA_MIXER_ROUTES_R("SLIMTX7", "SLIMTX7", "SLIMTX7 Rate"), + ARIZONA_MIXER_ROUTES_R("SLIMTX8", "SLIMTX8", "SLIMTX8 Rate"), + + ARIZONA_MIXER_ROUTES_R("EQ1", "EQ1", "FX Rate"), + ARIZONA_MIXER_ROUTES_R("EQ2", "EQ2", "FX Rate"), + ARIZONA_MIXER_ROUTES_R("EQ3", "EQ3", "FX Rate"), + ARIZONA_MIXER_ROUTES_R("EQ4", "EQ4", "FX Rate"), + + ARIZONA_MIXER_ROUTES_R("DRC1L", "DRC1L", "FX Rate"), + ARIZONA_MIXER_ROUTES_R("DRC1R", "DRC1R", "FX Rate"), + ARIZONA_MIXER_ROUTES_R("DRC2L", "DRC2L", "FX Rate"), + ARIZONA_MIXER_ROUTES_R("DRC2R", "DRC2R", "FX Rate"), + + ARIZONA_MIXER_ROUTES_R("LHPF1", "LHPF1", "FX Rate"), + ARIZONA_MIXER_ROUTES_R("LHPF2", "LHPF2", "FX Rate"), + ARIZONA_MIXER_ROUTES_R("LHPF3", "LHPF3", "FX Rate"), + ARIZONA_MIXER_ROUTES_R("LHPF4", "LHPF4", "FX Rate"), + + ARIZONA_MIXER_ROUTES_R("Mic Mute Mixer", "Noise", "Mic Mute Rate"), + ARIZONA_MIXER_ROUTES_R("Mic Mute Mixer", "Mic", "Mic Mute Rate"), + + ARIZONA_MUX_ROUTES_R("ASRC1L", "ASRC1L", "ASRC Rate"), + ARIZONA_MUX_ROUTES_R("ASRC1R", "ASRC1R", "ASRC Rate"), + ARIZONA_MUX_ROUTES_R("ASRC2L", "ASRC2L", "ASRC Async Rate"), + ARIZONA_MUX_ROUTES_R("ASRC2R", "ASRC2R", "ASRC Async Rate"), + + ARIZONA_DSP_ROUTES_R("DSP1", "DSP1 Rate"), + ARIZONA_DSP_ROUTES_R("DSP2", "DSP2 Rate"), + ARIZONA_DSP_ROUTES_R("DSP3", "DSP3 Rate"), + ARIZONA_DSP_ROUTES_R("DSP4", "DSP4 Rate"), + + ARIZONA_MUX_ROUTES_R("ISRC1INT1", "ISRC1INT1", "ISRC1 FSL"), + ARIZONA_MUX_ROUTES_R("ISRC1INT2", "ISRC1INT2", "ISRC1 FSL"), + ARIZONA_MUX_ROUTES_R("ISRC1INT3", "ISRC1INT3", "ISRC1 FSL"), + ARIZONA_MUX_ROUTES_R("ISRC1INT4", "ISRC1INT4", "ISRC1 FSL"), + + ARIZONA_MUX_ROUTES_R("ISRC1DEC1", "ISRC1DEC1", "ISRC1 FSH"), + ARIZONA_MUX_ROUTES_R("ISRC1DEC2", "ISRC1DEC2", "ISRC1 FSH"), + ARIZONA_MUX_ROUTES_R("ISRC1DEC3", "ISRC1DEC3", "ISRC1 FSH"), + ARIZONA_MUX_ROUTES_R("ISRC1DEC4", "ISRC1DEC4", "ISRC1 FSH"), + + ARIZONA_MUX_ROUTES_R("ISRC2INT1", "ISRC2INT1", "ISRC2 FSL"), + ARIZONA_MUX_ROUTES_R("ISRC2INT2", "ISRC2INT2", "ISRC2 FSL"), + ARIZONA_MUX_ROUTES_R("ISRC2INT3", "ISRC2INT3", "ISRC2 FSL"), + ARIZONA_MUX_ROUTES_R("ISRC2INT4", "ISRC2INT4", "ISRC2 FSL"), + + ARIZONA_MUX_ROUTES_R("ISRC2DEC1", "ISRC2DEC1", "ISRC2 FSH"), + ARIZONA_MUX_ROUTES_R("ISRC2DEC2", "ISRC2DEC2", "ISRC2 FSH"), + ARIZONA_MUX_ROUTES_R("ISRC2DEC3", "ISRC2DEC3", "ISRC2 FSH"), + ARIZONA_MUX_ROUTES_R("ISRC2DEC4", "ISRC2DEC4", "ISRC2 FSH"), + + ARIZONA_MUX_ROUTES_R("ISRC3INT1", "ISRC3INT1", "ISRC3 FSL"), + ARIZONA_MUX_ROUTES_R("ISRC3INT2", "ISRC3INT2", "ISRC3 FSL"), + ARIZONA_MUX_ROUTES_R("ISRC3INT3", "ISRC3INT3", "ISRC3 FSL"), + ARIZONA_MUX_ROUTES_R("ISRC3INT4", "ISRC3INT4", "ISRC3 FSL"), + + ARIZONA_MUX_ROUTES_R("ISRC3DEC1", "ISRC3DEC1", "ISRC3 FSH"), + ARIZONA_MUX_ROUTES_R("ISRC3DEC2", "ISRC3DEC2", "ISRC3 FSH"), + ARIZONA_MUX_ROUTES_R("ISRC3DEC3", "ISRC3DEC3", "ISRC3 FSH"), + ARIZONA_MUX_ROUTES_R("ISRC3DEC4", "ISRC3DEC4", "ISRC3 FSH"), { "AEC Loopback", "HPOUT1L", "OUT1L" }, { "AEC Loopback", "HPOUT1R", "OUT1R" }, @@ -2319,6 +2514,19 @@ static int wm5110_component_probe(struct snd_soc_component *component) snd_soc_component_disable_pin(component, "HAPTICS"); + snd_soc_dapm_connect_domains(dapm, "SLIMRX1 Rate", "SLIMRX2 Rate"); + snd_soc_dapm_connect_domains(dapm, "SLIMRX1 Rate", "SLIMRX3 Rate"); + snd_soc_dapm_connect_domains(dapm, "SLIMRX1 Rate", "SLIMRX4 Rate"); + snd_soc_dapm_connect_domains(dapm, "SLIMTX1 Rate", "SLIMTX2 Rate"); + snd_soc_dapm_connect_domains(dapm, "SLIMTX1 Rate", "SLIMTX3 Rate"); + snd_soc_dapm_connect_domains(dapm, "SLIMTX1 Rate", "SLIMTX4 Rate"); + + snd_soc_dapm_connect_domains(dapm, "SLIMRX5 Rate", "SLIMRX6 Rate"); + snd_soc_dapm_connect_domains(dapm, "SLIMTX5 Rate", "SLIMTX6 Rate"); + + snd_soc_dapm_connect_domains(dapm, "SLIMRX7 Rate", "SLIMRX8 Rate"); + snd_soc_dapm_connect_domains(dapm, "SLIMTX7 Rate", "SLIMTX8 Rate"); + return 0; err_adsp2_codec_probe: @@ -2379,6 +2587,8 @@ static const struct snd_soc_component_driver soc_component_dev_wm5110 = { .num_dapm_widgets = ARRAY_SIZE(wm5110_dapm_widgets), .dapm_routes = wm5110_dapm_routes, .num_dapm_routes = ARRAY_SIZE(wm5110_dapm_routes), + .domains = arizona_rate_domains, + .num_domains = ARRAY_SIZE(arizona_rate_domains), .use_pmdown_time = 1, .endianness = 1, .non_legacy_dai_naming = 1,