From patchwork Wed Dec 31 03:39:11 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zidan Wang X-Patchwork-Id: 5553831 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 761069F2B9 for ; Wed, 31 Dec 2014 03:38:46 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 93A1A20114 for ; Wed, 31 Dec 2014 03:38:45 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 62527200F0 for ; Wed, 31 Dec 2014 03:38:44 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id C070D2610A3; Wed, 31 Dec 2014 04:38:42 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,NO_DNS_FOR_FROM, UNPARSEABLE_RELAY autolearn=no version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id CAC242608AB; Wed, 31 Dec 2014 04:38:31 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id E4EB82608B3; Wed, 31 Dec 2014 04:38:30 +0100 (CET) Received: from na01-bl2-obe.outbound.protection.outlook.com (mail-bl2on0108.outbound.protection.outlook.com [65.55.169.108]) by alsa0.perex.cz (Postfix) with ESMTP id 8B4A926087F for ; Wed, 31 Dec 2014 04:38:22 +0100 (CET) Received: from BY2PR03CA008.namprd03.prod.outlook.com (10.255.93.25) by BN3PR0301MB1252.namprd03.prod.outlook.com (25.161.207.28) with Microsoft SMTP Server (TLS) id 15.1.49.12; Wed, 31 Dec 2014 03:38:20 +0000 Received: from BN1BFFO11FD010.protection.gbl (10.255.93.4) by BY2PR03CA008.outlook.office365.com (10.255.93.25) with Microsoft SMTP Server (TLS) id 15.1.49.12 via Frontend Transport; Wed, 31 Dec 2014 03:38:18 +0000 Received: from az84smr01.freescale.net (192.88.158.2) by BN1BFFO11FD010.mail.protection.outlook.com (10.58.144.73) with Microsoft SMTP Server (TLS) id 15.1.49.13 via Frontend Transport; Wed, 31 Dec 2014 03:38:18 +0000 Received: from b50113.ap.freescale.net (b50113.ap.freescale.net [10.192.241.89]) by az84smr01.freescale.net (8.14.3/8.14.0) with ESMTP id sBV3cCHB028999; Tue, 30 Dec 2014 20:38:13 -0700 From: Zidan Wang To: Date: Wed, 31 Dec 2014 11:39:11 +0800 Message-ID: <1419997154-860-1-git-send-email-b50113@freescale.com> X-Mailer: git-send-email 1.9.1 X-EOPAttributedMessage: 0 Received-SPF: Fail (protection.outlook.com: domain of freescale.com does not designate 192.88.158.2 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.158.2; helo=az84smr01.freescale.net; Authentication-Results: spf=fail (sender IP is 192.88.158.2) smtp.mailfrom=B50113@freescale.com; X-Forefront-Antispam-Report: CIP:192.88.158.2; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10019020)(6009001)(339900001)(189002)(199003)(89996001)(50226001)(50466002)(120916001)(85426001)(77156002)(4396001)(19580395003)(64706001)(62966003)(87936001)(20776003)(46102003)(50986999)(106466001)(21056001)(48376002)(19580405001)(81156004)(99396003)(6806004)(104016003)(33646002)(84676001)(36756003)(47776003)(69596002)(229853001)(2351001)(68736005)(97736003)(92566001)(86362001)(107046002)(77096005)(31966008)(110136001)(42262002); DIR:OUT; SFP:1102; SCL:1; SRVR:BN3PR0301MB1252; H:az84smr01.freescale.net; FPR:; SPF:Fail; MLV:sfv; PTR:InfoDomainNonexistent; MX:1; A:1; LANG:en; MIME-Version: 1.0 X-DmarcAction: None X-Microsoft-Antispam: UriScan:; X-Microsoft-Antispam: BCL:0;PCL:0;RULEID:(3005003);SRVR:BN3PR0301MB1252; X-Forefront-PRVS: 0442E569BC X-OriginatorOrg: freescale.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 31 Dec 2014 03:38:18.6309 (UTC) X-MS-Exchange-CrossTenant-Id: 710a03f5-10f6-4d38-9ff4-a80b81da590d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=710a03f5-10f6-4d38-9ff4-a80b81da590d; Ip=[192.88.158.2] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN3PR0301MB1252 Cc: alsa-devel@alsa-project.org, lars@metafoo.de, tiwai@suse.de, linux-kernel@vger.kernel.org, patches@opensource.wolfsonmicro.com, lgirdwood@gmail.com, Li.Xiubo@freescale.com, Zidan Wang , ckeepax@opensource.wolfsonmicro.com Subject: [alsa-devel] [PATCH 1/4] ASoC: wm8960: Let wm8960 codec driver manage its own MCLK 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 When we want to use wm8960 codec, we should enable its MCLK in machine driver. It's reasonable for wm8960 codec driver to manage its own MCLK. When current bias_level is SND_SOC_BIAS_ON, it is preparing for a transition away from ON. In this case, disable the codec mclk. When current bias_level is not SND_SOC_BIAS_ON, it preparing for a transition to ON. In this case, enable the codec mclk. Signed-off-by: Zidan Wang --- sound/soc/codecs/wm8960.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 031a1ae..1a5f47b 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -117,6 +118,7 @@ static bool wm8960_volatile(struct device *dev, unsigned int reg) } struct wm8960_priv { + struct clk *mclk; struct regmap *regmap; int (*set_bias_level)(struct snd_soc_codec *, enum snd_soc_bias_level level); @@ -618,6 +620,7 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); + int ret; switch (level) { case SND_SOC_BIAS_ON: @@ -626,6 +629,20 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, case SND_SOC_BIAS_PREPARE: /* Set VMID to 2x50k */ snd_soc_update_bits(codec, WM8960_POWER1, 0x180, 0x80); + + if (!IS_ERR(wm8960->mclk)) { + if (codec->dapm.bias_level == SND_SOC_BIAS_ON) + clk_disable_unprepare(wm8960->mclk); + else { + ret = clk_prepare_enable(wm8960->mclk); + if (ret) { + dev_err(codec->dev, + "Failed to enable MCLK: %d\n", + ret); + return ret; + } + } + } break; case SND_SOC_BIAS_STANDBY: @@ -661,6 +678,7 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, /* Disable VMID and VREF, let them discharge */ snd_soc_write(codec, WM8960_POWER1, 0); + msleep(600); break; } @@ -674,7 +692,7 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); - int reg; + int reg, ret; switch (level) { case SND_SOC_BIAS_ON: @@ -715,9 +733,22 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, WM8960_VREF, WM8960_VREF); msleep(100); + + if (!IS_ERR(wm8960->mclk)) { + ret = clk_prepare_enable(wm8960->mclk); + if (ret) { + dev_err(codec->dev, + "Failed to enable MCLK: %d\n", + ret); + return ret; + } + } break; case SND_SOC_BIAS_ON: + if (!IS_ERR(wm8960->mclk)) + clk_disable_unprepare(wm8960->mclk); + /* Enable anti-pop mode */ snd_soc_update_bits(codec, WM8960_APOP1, WM8960_POBCTRL | WM8960_SOFT_ST | @@ -728,6 +759,7 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, /* Disable VMID and VREF */ snd_soc_update_bits(codec, WM8960_POWER1, WM8960_VREF | WM8960_VMID_MASK, 0); + break; case SND_SOC_BIAS_OFF: @@ -1002,6 +1034,12 @@ static int wm8960_i2c_probe(struct i2c_client *i2c, if (wm8960 == NULL) return -ENOMEM; + wm8960->mclk = devm_clk_get(&i2c->dev, "codec_mclk"); + if (IS_ERR(wm8960->mclk)) { + if (PTR_ERR(wm8960->mclk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + } + wm8960->regmap = devm_regmap_init_i2c(i2c, &wm8960_regmap); if (IS_ERR(wm8960->regmap)) return PTR_ERR(wm8960->regmap);