From patchwork Wed Oct 18 11:31:27 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Brown X-Patchwork-Id: 116266 Delivered-To: patch@linaro.org Received: by 10.140.22.163 with SMTP id 32csp5952828qgn; Wed, 18 Oct 2017 04:32:52 -0700 (PDT) X-Google-Smtp-Source: ABhQp+RbveesC0yTcGA2SyOZSMS1qw34QOMcV7lmP9Zm6SMXuFLjsF5o/vRDuT5MfQpzaqYXwb+E X-Received: by 10.28.196.79 with SMTP id u76mr6212624wmf.95.1508326372449; Wed, 18 Oct 2017 04:32:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1508326372; cv=none; d=google.com; s=arc-20160816; b=z6AgxAHQ0seRSgaO7O0UKKVQbqsZ/D3b/FSgqU/h0xjZvQfSMfLck+hyu2ohSB7mFc rIb3YuLXTCUZybMzAXtxnn3xAWmOqt8SmwUn08V5QRMsVYV4BK+ZhH9rb13Gd0m/iYw5 ASMgne3fDmzvzc2/XXl3VlcRuAoCOKgVQ1+G5sNCtJWGcEDzNTlmGWLg8OQyAHFNgxEb TpDkNYlgUIGACkUJcw2IQuKenUPYYBnP391v1xzFUlfuV+F6FPHmbiHB/fiRCZM4/699 s6mNpczwLWLVpuqvLJlCM7k/W1SDKv/nonUR834oWzjZmZq6Ftw3j8K5bzmauRyFM9iR FyaQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:cc:date:message-id:in-reply-to:to:from :dkim-signature:delivered-to:arc-authentication-results; bh=JpQQm5UJYD/2vmevFbCAJwNT8kpDpAQxeNNLqzXsRiM=; b=dITVlvOo4Sj31oeI4EpXWAKLIXhn28HtsqODF5b2VUESlfZhKYTsriDk/QXs9UjjQk i3OLxerE166Y88TtxOoAOiozo1xcbo1kboLc/iB0Hz7lMf8SEB/E67iBwQjzVgHRARZR c7YG7cm3UPxJfOuCyFqn7pPokF6e7F/Sv12XJaOwdJGtCMrUeYYDZJxvNlTu4TthghlV Kf9jbDICkYTDauM3+eJ/W6YqTRfvFMSTUJ38Ka/jd2Kdi/f1AZz12RWsLK8Iz+3TnKkQ WJ76joNjhcavzvmcmyyKVXyWsdRJBUY6XZLxsQV4xrfaiE4TSV9Uz3HJ5fTSst9jw2Mw zUKw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@sirena.org.uk header.s=20170815-heliosphere header.b=o2iPrjuF; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org Return-Path: Received: from alsa0.perex.cz (alsa0.perex.cz. [77.48.224.243]) by mx.google.com with ESMTP id s26si8897102wrs.257.2017.10.18.04.32.52; Wed, 18 Oct 2017 04:32:52 -0700 (PDT) Received-SPF: pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) client-ip=77.48.224.243; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@sirena.org.uk header.s=20170815-heliosphere header.b=o2iPrjuF; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 7CB8B2674B1; Wed, 18 Oct 2017 13:31: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 41D932674AC; Wed, 18 Oct 2017 13:31:46 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail1.perex.cz X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, SPF_PASS autolearn=disabled version=3.4.0 Received: from heliosphere.sirena.org.uk (heliosphere.sirena.org.uk [172.104.155.198]) by alsa0.perex.cz (Postfix) with ESMTP id 0CA15267480 for ; Wed, 18 Oct 2017 13:31:30 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sirena.org.uk; s=20170815-heliosphere; h=Date:Message-Id:In-Reply-To: Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:References: List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner: List-Archive; bh=xXTr6ybZ0kWm9UDLFFtM53FAehQEkY6CcP/yC169ChU=; b=o2iPrjuFohH8 m5IKUTJOO1FkDUJBuIHP9+rcx0NWQ3Qm7nQk82R3aBsxaIT9RsToFahtFD7PoGY1ghur2cInjVErI 0FFMvXA5s/nIf9pyNmDZaL50TsIV9vIllU8AdNUOJ9mW+68HB65QAxS+f1SQrm6Y25DhuFRvCA93B gt3oA=; Received: from debutante.sirena.org.uk ([2001:470:1f1d:6b5::3] helo=debutante) by heliosphere.sirena.org.uk with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1e4mZL-0007X9-Fv; Wed, 18 Oct 2017 11:31:27 +0000 Received: from broonie by debutante with local (Exim 4.89) (envelope-from ) id 1e4mZL-00040A-2Y; Wed, 18 Oct 2017 12:31:27 +0100 From: Mark Brown To: Pierre-Louis Bossart In-Reply-To: <20171012233805.30055-2-pierre-louis.bossart@linux.intel.com> Message-Id: Date: Wed, 18 Oct 2017 12:31:27 +0100 Cc: alsa-devel@alsa-project.org, tiwai@suse.de, liam.r.girdwood@linux.intel.com, vinod.koul@intel.com, broonie@kernel.org, andriy.shevchenko@linux.intel.com Subject: [alsa-devel] Applied "ASoC: Intel: bytcr_rt5651: add MCLK, quirks and cleanups" to the asoc tree 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 The patch ASoC: Intel: bytcr_rt5651: add MCLK, quirks and cleanups has been applied to the asoc tree at git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted. You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed. If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced. Please add any relevant lists and maintainers to the CCs when replying to this mail. Thanks, Mark >From 02c0a3b3047f8fe49fdc040414ee243f2b2c64ce Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 12 Oct 2017 18:37:57 -0500 Subject: [PATCH] ASoC: Intel: bytcr_rt5651: add MCLK, quirks and cleanups Same as for other codecs, enable MCLK by default. When it is not present, e.g. on MinnowBoard B3 since it's not routed on the LSE connector, we fall back to blck-based clocking. The DMIC quirks are also fixed, there is a single DMIC input of the codec. reorder variables in reverse x-mas tree as suggested by Andy Signed-off-by: Pierre-Louis Bossart Acked-by: Liam Girdwood Reviewed-by: Andy Shevchenko Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5651.c | 239 +++++++++++++++++++++++++++++++--- 1 file changed, 222 insertions(+), 17 deletions(-) -- 2.14.1 _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 441f735a198f..e094a58d750d 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -21,24 +21,132 @@ #include #include #include +#include #include #include #include +#include #include #include #include #include #include "../../codecs/rt5651.h" #include "../atom/sst-atom-controls.h" +#include "../common/sst-acpi.h" + +enum { + BYT_RT5651_DMIC_MAP, + BYT_RT5651_IN1_MAP, +}; + +#define BYT_RT5651_MAP(quirk) ((quirk) & GENMASK(7, 0)) +#define BYT_RT5651_DMIC_EN BIT(16) +#define BYT_RT5651_MCLK_EN BIT(17) +#define BYT_RT5651_MCLK_25MHZ BIT(18) + +struct byt_rt5651_private { + struct clk *mclk; +}; + +static unsigned long byt_rt5651_quirk = BYT_RT5651_DMIC_MAP | + BYT_RT5651_DMIC_EN | + BYT_RT5651_MCLK_EN; + +static void log_quirks(struct device *dev) +{ + if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_DMIC_MAP) + dev_info(dev, "quirk DMIC_MAP enabled"); + if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN1_MAP) + dev_info(dev, "quirk IN1_MAP enabled"); + if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN) + dev_info(dev, "quirk DMIC enabled"); + if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) + dev_info(dev, "quirk MCLK_EN enabled"); + if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ) + dev_info(dev, "quirk MCLK_25MHZ enabled"); +} + +#define BYT_CODEC_DAI1 "rt5651-aif1" + +static inline struct snd_soc_dai *byt_get_codec_dai(struct snd_soc_card *card) +{ + struct snd_soc_pcm_runtime *rtd; + + list_for_each_entry(rtd, &card->rtd_list, list) { + if (!strncmp(rtd->codec_dai->name, BYT_CODEC_DAI1, + strlen(BYT_CODEC_DAI1))) + return rtd->codec_dai; + } + return NULL; +} + +static int platform_clock_control(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + struct snd_soc_dapm_context *dapm = w->dapm; + struct snd_soc_card *card = dapm->card; + struct snd_soc_dai *codec_dai; + struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card); + int ret; + + codec_dai = byt_get_codec_dai(card); + if (!codec_dai) { + dev_err(card->dev, + "Codec dai not found; Unable to set platform clock\n"); + return -EIO; + } + + if (SND_SOC_DAPM_EVENT_ON(event)) { + if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) { + ret = clk_prepare_enable(priv->mclk); + if (ret < 0) { + dev_err(card->dev, + "could not configure MCLK state"); + return ret; + } + } + ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_PLL1, + 48000 * 512, + SND_SOC_CLOCK_IN); + } else { + /* + * Set codec clock source to internal clock before + * turning off the platform clock. Codec needs clock + * for Jack detection and button press + */ + ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_RCCLK, + 48000 * 512, + SND_SOC_CLOCK_IN); + if (!ret) + if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) + clk_disable_unprepare(priv->mclk); + } + + if (ret < 0) { + dev_err(card->dev, "can't set codec sysclk: %d\n", ret); + return ret; + } + + return 0; +} static const struct snd_soc_dapm_widget byt_rt5651_widgets[] = { SND_SOC_DAPM_HP("Headphone", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), SND_SOC_DAPM_MIC("Internal Mic", NULL), SND_SOC_DAPM_SPK("Speaker", NULL), + SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, + platform_clock_control, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + }; static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = { + {"Headphone", NULL, "Platform Clock"}, + {"Headset Mic", NULL, "Platform Clock"}, + {"Internal Mic", NULL, "Platform Clock"}, + {"Speaker", NULL, "Platform Clock"}, + {"AIF1 Playback", NULL, "ssp2 Tx"}, {"ssp2 Tx", NULL, "codec_out0"}, {"ssp2 Tx", NULL, "codec_out1"}, @@ -64,18 +172,6 @@ static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_map[] = { {"IN1P", NULL, "Internal Mic"}, }; -enum { - BYT_RT5651_DMIC1_MAP, - BYT_RT5651_DMIC2_MAP, - BYT_RT5651_IN1_MAP, -}; - -#define BYT_RT5651_MAP(quirk) ((quirk) & 0xff) -#define BYT_RT5651_DMIC_EN BIT(16) - -static unsigned long byt_rt5651_quirk = BYT_RT5651_DMIC1_MAP | - BYT_RT5651_DMIC_EN; - static const struct snd_kcontrol_new byt_rt5651_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone"), SOC_DAPM_PIN_SWITCH("Headset Mic"), @@ -100,9 +196,26 @@ static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream, return ret; } - ret = snd_soc_dai_set_pll(codec_dai, 0, RT5651_PLL1_S_BCLK1, - params_rate(params) * 50, - params_rate(params) * 512); + if (!(byt_rt5651_quirk & BYT_RT5651_MCLK_EN)) { + /* 2x25 bit slots on SSP2 */ + ret = snd_soc_dai_set_pll(codec_dai, 0, + RT5651_PLL1_S_BCLK1, + params_rate(params) * 50, + params_rate(params) * 512); + } else { + if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ) { + ret = snd_soc_dai_set_pll(codec_dai, 0, + RT5651_PLL1_S_MCLK, + 25000000, + params_rate(params) * 512); + } else { + ret = snd_soc_dai_set_pll(codec_dai, 0, + RT5651_PLL1_S_MCLK, + 19200000, + params_rate(params) * 512); + } + } + if (ret < 0) { dev_err(rtd->dev, "can't set codec pll: %d\n", ret); return ret; @@ -111,20 +224,35 @@ static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream, return 0; } +static int byt_rt5651_quirk_cb(const struct dmi_system_id *id) +{ + byt_rt5651_quirk = (unsigned long)id->driver_data; + return 1; +} + static const struct dmi_system_id byt_rt5651_quirk_table[] = { + { + .callback = byt_rt5651_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"), + DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"), + }, + .driver_data = (void *)(BYT_RT5651_DMIC_MAP | + BYT_RT5651_DMIC_EN), + }, {} }; static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime) { - int ret; struct snd_soc_card *card = runtime->card; + struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card); const struct snd_soc_dapm_route *custom_map; int num_routes; + int ret; card->dapm.idle_bias_off = true; - dmi_check_system(byt_rt5651_quirk_table); switch (BYT_RT5651_MAP(byt_rt5651_quirk)) { case BYT_RT5651_IN1_MAP: custom_map = byt_rt5651_intmic_in1_map; @@ -147,6 +275,30 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime) snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone"); snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker"); + if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) { + /* + * The firmware might enable the clock at + * boot (this information may or may not + * be reflected in the enable clock register). + * To change the rate we must disable the clock + * first to cover these cases. Due to common + * clock framework restrictions that do not allow + * to disable a clock that has not been enabled, + * we need to enable the clock first. + */ + ret = clk_prepare_enable(priv->mclk); + if (!ret) + clk_disable_unprepare(priv->mclk); + + if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ) + ret = clk_set_rate(priv->mclk, 25000000); + else + ret = clk_set_rate(priv->mclk, 19200000); + + if (ret) + dev_err(card->dev, "unable to set MCLK rate\n"); + } + return ret; } @@ -292,13 +444,66 @@ static struct snd_soc_card byt_rt5651_card = { .fully_routed = true, }; +static char byt_rt5651_codec_name[16]; /* i2c-:00 with HID being 8 chars */ + static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) { + struct byt_rt5651_private *priv; + struct sst_acpi_mach *mach; + const char *i2c_name = NULL; int ret_val = 0; + int dai_index; + int i; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC); + if (!priv) + return -ENOMEM; /* register the soc card */ byt_rt5651_card.dev = &pdev->dev; + mach = byt_rt5651_card.dev->platform_data; + snd_soc_card_set_drvdata(&byt_rt5651_card, priv); + + /* fix index of codec dai */ + dai_index = MERR_DPCM_COMPR + 1; + for (i = 0; i < ARRAY_SIZE(byt_rt5651_dais); i++) { + if (!strcmp(byt_rt5651_dais[i].codec_name, "i2c-10EC5651:00")) { + dai_index = i; + break; + } + } + + /* fixup codec name based on HID */ + i2c_name = sst_acpi_find_name_from_hid(mach->id); + if (i2c_name) { + snprintf(byt_rt5651_codec_name, sizeof(byt_rt5651_codec_name), + "%s%s", "i2c-", i2c_name); + + byt_rt5651_dais[dai_index].codec_name = byt_rt5651_codec_name; + } + + /* check quirks before creating card */ + dmi_check_system(byt_rt5651_quirk_table); + log_quirks(&pdev->dev); + + if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) { + priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); + if (IS_ERR(priv->mclk)) { + dev_err(&pdev->dev, + "Failed to get MCLK from pmc_plt_clk_3: %ld\n", + PTR_ERR(priv->mclk)); + /* + * Fall back to bit clock usage for -ENOENT (clock not + * available likely due to missing dependencies), bail + * for all other errors, including -EPROBE_DEFER + */ + if (ret_val != -ENOENT) + return ret_val; + byt_rt5651_quirk &= ~BYT_RT5651_MCLK_EN; + } + } + ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5651_card); if (ret_val) {