From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.3 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, UNWANTED_LANGUAGE_BODY,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E0ABFC4363D for ; Thu, 1 Oct 2020 02:14:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A0F3221D80 for ; Thu, 1 Oct 2020 02:14:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731342AbgJACMl (ORCPT ); Wed, 30 Sep 2020 22:12:41 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:49235 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730009AbgJACMA (ORCPT ); Wed, 30 Sep 2020 22:12:00 -0400 Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailnew.nyi.internal (Postfix) with ESMTP id 10834580399; Wed, 30 Sep 2020 22:11:59 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute5.internal (MEProxy); Wed, 30 Sep 2020 22:11:59 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sholland.org; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm3; bh=/5PkmJdsATQhY tiJ6QitOB2ll2wdiEKavDMfs3UWCw0=; b=Zp+9l3F6zMpMJOrUaAatP1J1Qo9l3 df+eLHw3+tuj1+Fi4wJ3bHGigyeyrl5hNFoGMWcu8jLIfswvLWgcFakTo799nlQe 4+q9NSXG0mKJN+bkCyK4cAaSy6nqlowUxGxMl9YwHZjVg6XIEnA4r75SlbOkiArG pKRt3k0LDyaEknfFnDNRgzu2+JCQ7+9uc4/iHYUk40SITSirLIupGlX3zNSZJQgE 8tQy+EEDbsvfLaNwly/CIntEfA9CXgGKRgpHd0bajKbYy6nwRIUOiFbVpj87Yevc 2+5y4vSsm0g051dpZxY6CdUYsAJ/ICI7F5QKyQB/CS/ZrDTwLG+DC+EYA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=/5PkmJdsATQhYtiJ6QitOB2ll2wdiEKavDMfs3UWCw0=; b=qwhAAlrK uoyDFlKLKJCgyf1UFR/fCWGBfO3jW+4cP/LoOBTx7aVRSLHmBAW7Wvp+HE6BAu2l 4rQKFf4BKYWIS+daDjQKz8tKBqx7de/ugvpLVX3CPr1XAbWIQyMojKRDtnkSRAK/ jFPSazpnXnUSJYR4NDvJlboocT3L8RiTMXBVcSGBoIbHZsIo8xq/IwNMtZiweqoX p1OdpWEjT0I1SyfDDa+H/fgmdy1ArlX+MlwZxnnKj9ikIi6vJK3zihDW9EWmKf/R 4tbcCGPW8tkiNy+m1N0lWu+ZC7BehMdFUnN46N1nhCbaScHAiJl65VpGV2I0T2jD sVevq+RoSNv2Vw== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrfeefgdehkecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpefhvffufffkofgjfhgggfestdekredtredttdenucfhrhhomhepufgrmhhuvghl ucfjohhllhgrnhguuceoshgrmhhuvghlsehshhholhhlrghnugdrohhrgheqnecuggftrf grthhtvghrnhepudfhjeefvdfhgfefheetgffhieeigfefhefgvddvveefgeejheejvdfg jeehueeinecukfhppeejtddrudefhedrudegkedrudehudenucevlhhushhtvghrufhiii gvpedujeenucfrrghrrghmpehmrghilhhfrhhomhepshgrmhhuvghlsehshhholhhlrghn ugdrohhrgh X-ME-Proxy: Received: from titanium.stl.sholland.net (70-135-148-151.lightspeed.stlsmo.sbcglobal.net [70.135.148.151]) by mail.messagingengine.com (Postfix) with ESMTPA id 46BCA3064688; Wed, 30 Sep 2020 22:11:58 -0400 (EDT) From: Samuel Holland To: Mark Brown , Liam Girdwood , Maxime Ripard , Chen-Yu Tsai , Jaroslav Kysela , Takashi Iwai Cc: Ondrej Jirman , alsa-devel@alsa-project.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Samuel Holland Subject: [PATCH 19/25] ASoC: sun8i-codec: Constrain to compatible sample rates Date: Wed, 30 Sep 2020 21:11:42 -0500 Message-Id: <20201001021148.15852-20-samuel@sholland.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201001021148.15852-1-samuel@sholland.org> References: <20201001021148.15852-1-samuel@sholland.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org While another stream is active, only allow userspace to use sample rates that are compatible with the current SYSCLK frequency. This ensures the actual sample rate will always match what is given in hw_params. Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun8i-codec.c | 59 ++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 43b4319e3d84..501af64d43a0 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -121,16 +121,18 @@ struct sun8i_codec_quirks { bool lrck_inversion : 1; }; struct sun8i_codec { struct regmap *regmap; struct clk *clk_module; const struct sun8i_codec_quirks *quirks; struct sun8i_codec_aif aifs[NAIFS]; + unsigned int sysclk_rate; + int sysclk_refcnt; }; static int sun8i_codec_runtime_resume(struct device *dev) { struct sun8i_codec *scodec = dev_get_drvdata(dev); int ret; regcache_cache_only(scodec->regmap, false); @@ -319,16 +321,57 @@ static int sun8i_codec_set_tdm_slot(struct snd_soc_dai *dai, return -EINVAL; aif->slots = slots; aif->slot_width = slot_width; return 0; } +static const unsigned int sun8i_codec_rates[] = { + 7350, 8000, 11025, 12000, 14700, 16000, 22050, 24000, + 29400, 32000, 44100, 48000, 88200, 96000, 176400, 192000, +}; + +static const struct snd_pcm_hw_constraint_list sun8i_codec_all_rates = { + .list = sun8i_codec_rates, + .count = ARRAY_SIZE(sun8i_codec_rates), +}; + +static const struct snd_pcm_hw_constraint_list sun8i_codec_22M_rates = { + .list = sun8i_codec_rates, + .count = ARRAY_SIZE(sun8i_codec_rates), + .mask = 0x5555, +}; + +static const struct snd_pcm_hw_constraint_list sun8i_codec_24M_rates = { + .list = sun8i_codec_rates, + .count = ARRAY_SIZE(sun8i_codec_rates), + .mask = 0xaaaa, +}; + +static int sun8i_codec_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); + const struct snd_pcm_hw_constraint_list *list; + + if (!scodec->sysclk_refcnt) + list = &sun8i_codec_all_rates; + else if (scodec->sysclk_rate == 22579200) + list = &sun8i_codec_22M_rates; + else if (scodec->sysclk_rate == 24576000) + list = &sun8i_codec_24M_rates; + else + return -EINVAL; + + return snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, list); +} + struct sun8i_codec_clk_div { u8 div; u8 val; }; static const struct sun8i_codec_clk_div sun8i_codec_bclk_div[] = { { .div = 1, .val = 0 }, { .div = 2, .val = 1 }, @@ -341,22 +384,21 @@ static const struct sun8i_codec_clk_div sun8i_codec_bclk_div[] = { { .div = 32, .val = 8 }, { .div = 48, .val = 9 }, { .div = 64, .val = 10 }, { .div = 96, .val = 11 }, { .div = 128, .val = 12 }, { .div = 192, .val = 13 }, }; -static u8 sun8i_codec_get_bclk_div(struct sun8i_codec *scodec, +static u8 sun8i_codec_get_bclk_div(unsigned int sysclk_rate, unsigned int lrck_div_order, unsigned int sample_rate) { - unsigned long clk_rate = clk_get_rate(scodec->clk_module); - unsigned int div = clk_rate / sample_rate >> lrck_div_order; + unsigned int div = sysclk_rate / sample_rate >> lrck_div_order; unsigned int best_val = 0, best_diff = ~0; int i; for (i = 0; i < ARRAY_SIZE(sun8i_codec_bclk_div); i++) { const struct sun8i_codec_clk_div *bdiv = &sun8i_codec_bclk_div[i]; unsigned int diff = abs(bdiv->div - div); if (diff < best_diff) { @@ -383,16 +425,17 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); struct sun8i_codec_aif *aif = &scodec->aifs[dai->id]; unsigned int sample_rate = params_rate(params); unsigned int slots = aif->slots ?: params_channels(params); unsigned int slot_width = aif->slot_width ?: params_width(params); + unsigned int sysclk_rate = clk_get_rate(scodec->clk_module); int lrck_div_order, word_size; u8 bclk_div; /* word size */ switch (params_width(params)) { case 8: word_size = 0x0; break; @@ -418,46 +461,54 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, if (lrck_div_order < 0) return lrck_div_order; regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK, (lrck_div_order - 4) << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV); /* BCLK divider (SYSCLK/BCLK ratio) */ - bclk_div = sun8i_codec_get_bclk_div(scodec, lrck_div_order, sample_rate); + bclk_div = sun8i_codec_get_bclk_div(sysclk_rate, lrck_div_order, sample_rate); regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK, bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV); + if (!aif->open_streams) { + scodec->sysclk_rate = sysclk_rate; + scodec->sysclk_refcnt++; + } + aif->sample_rate = sample_rate; aif->open_streams |= BIT(substream->stream); return sun8i_codec_update_sample_rate(scodec); } static int sun8i_codec_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); struct sun8i_codec_aif *aif = &scodec->aifs[dai->id]; if (aif->open_streams != BIT(substream->stream)) goto done; + scodec->sysclk_refcnt--; + aif->sample_rate = 0; done: aif->open_streams &= ~BIT(substream->stream); return 0; } static const struct snd_soc_dai_ops sun8i_codec_dai_ops = { .set_fmt = sun8i_codec_set_fmt, .set_tdm_slot = sun8i_codec_set_tdm_slot, + .startup = sun8i_codec_startup, .hw_params = sun8i_codec_hw_params, .hw_free = sun8i_codec_hw_free, }; static struct snd_soc_dai_driver sun8i_codec_dais[] = { { .name = "sun8i-codec-aif1", .id = AIF1, -- 2.26.2