From patchwork Wed Jan 7 07:31:45 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zidan Wang X-Patchwork-Id: 5583481 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 AFA019F357 for ; Wed, 7 Jan 2015 10:12:06 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D6CC120263 for ; Wed, 7 Jan 2015 10:12:01 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 100632024C for ; Wed, 7 Jan 2015 10:12:00 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 470F0260465; Wed, 7 Jan 2015 11:11:55 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id 3447B260467; Wed, 7 Jan 2015 11:11:47 +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 114502604BA; Wed, 7 Jan 2015 08:31:05 +0100 (CET) Received: from na01-bl2-obe.outbound.protection.outlook.com (mail-bl2on0123.outbound.protection.outlook.com [65.55.169.123]) by alsa0.perex.cz (Postfix) with ESMTP id AA5FF260413 for ; Wed, 7 Jan 2015 08:30:51 +0100 (CET) Received: from BN3PR0301CA0048.namprd03.prod.outlook.com (25.160.152.144) by BN3PR0301MB1250.namprd03.prod.outlook.com (25.161.207.26) with Microsoft SMTP Server (TLS) id 15.1.49.12; Wed, 7 Jan 2015 07:30:49 +0000 Received: from BN1AFFO11FD007.protection.gbl (2a01:111:f400:7c10::178) by BN3PR0301CA0048.outlook.office365.com (2a01:111:e400:401e::16) with Microsoft SMTP Server (TLS) id 15.1.49.12 via Frontend Transport; Wed, 7 Jan 2015 07:30:49 +0000 Received: from az84smr01.freescale.net (192.88.158.2) by BN1AFFO11FD007.mail.protection.outlook.com (10.58.52.67) with Microsoft SMTP Server (TLS) id 15.1.49.13 via Frontend Transport; Wed, 7 Jan 2015 07:30:48 +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 t077UdZY017519; Wed, 7 Jan 2015 00:30:44 -0700 From: Zidan Wang To: Date: Wed, 7 Jan 2015 15:31:45 +0800 Message-ID: <1420615905-4078-2-git-send-email-zidan.wang@freescale.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1420615905-4078-1-git-send-email-zidan.wang@freescale.com> References: <1420615905-4078-1-git-send-email-zidan.wang@freescale.com> 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=zidan.wang@freescale.com; X-Forefront-Antispam-Report: CIP:192.88.158.2; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10019020)(6009001)(339900001)(199003)(189002)(92566001)(68736005)(77096005)(4396001)(2950100001)(50226001)(48376002)(20776003)(85426001)(31966008)(89996001)(47776003)(36756003)(50466002)(120916001)(105606002)(21056001)(2351001)(107046002)(229853001)(97736003)(104016003)(62966003)(77156002)(76176999)(50986999)(110136001)(19580395003)(84676001)(19580405001)(86362001)(87936001)(6806004)(33646002)(69596002)(106466001)(81156004)(46102003)(99396003); DIR:OUT; SFP:1102; SCL:1; SRVR:BN3PR0301MB1250; H:az84smr01.freescale.net; FPR:; SPF:Fail; MLV:sfv; PTR:InfoDomainNonexistent; A:1; MX:1; LANG:en; MIME-Version: 1.0 X-DmarcAction: None X-Microsoft-Antispam: UriScan:; X-Microsoft-Antispam: BCL:0;PCL:0;RULEID:(3005003);SRVR:BN3PR0301MB1250; X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA: BCL:0; PCL:0; RULEID:(601004); SRVR:BN3PR0301MB1250; X-Forefront-PRVS: 044968D9E1 X-Exchange-Antispam-Report-CFA: BCL:0;PCL:0;RULEID:;SRVR:BN3PR0301MB1250; X-OriginatorOrg: freescale.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Jan 2015 07:30:48.4282 (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: BN3PR0301MB1250 X-Mailman-Approved-At: Wed, 07 Jan 2015 11:11:44 +0100 Cc: alsa-devel@alsa-project.org, lars@metafoo.de, tiwai@suse.de, linux-kernel@vger.kernel.org, patches@opensource.wolfsonmicro.com, lgirdwood@gmail.com, Zidan Wang , ckeepax@opensource.wolfsonmicro.com Subject: [alsa-devel] [PATCH v2 2/2] ASoC: wm8960: Let wm8960 driver configure its bit clock and frame clock 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 From: Zidan Wang wm8960 codec driver missing configure its bit clock and frame clock, so add support for it. It will calculate a appropriate frequency dividing ratio according to the system clock, bit clock and frame clock, then set the corresponding registers. Signed-off-by: Zidan Wang --- sound/soc/codecs/wm8960.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index fd25973..aba6bbf 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -127,6 +127,8 @@ struct wm8960_priv { struct snd_soc_dapm_widget *out3; bool deemph; int playback_fs; + int bclk; + int sysclk; struct wm8960_data pdata; }; @@ -563,6 +565,68 @@ static struct { { 8000, 5 }, }; +/* Multiply 256 for internal 256 div */ +static const int dac_divs[] = { 256, 384, 512, 768, 1024, 1408, 1536 }; + +/* Multiply 10 to eliminate decimials */ +static const int bclk_divs[] = { + 10, 15, 20, 30, 40, 55, 60, 80, 110, + 120, 160, 220, 240, 320, 320, 320 +}; + +static void wm8960_configure_clocking(struct snd_soc_codec *codec, + int stream, int lrclk) +{ + struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); + u16 iface1 = snd_soc_read(codec, WM8960_IFACE1); + u16 iface2 = snd_soc_read(codec, WM8960_IFACE2); + int i, j; + + if (!(iface1 & (1<<6))) { + dev_dbg(codec->dev, + "Codec is slave mode, no need to configure clock\n"); + return; + } + + if (!wm8960->sysclk) { + dev_dbg(codec->dev, "No SYSCLK configured\n"); + return; + } + + if (!wm8960->bclk || !lrclk) { + dev_dbg(codec->dev, "No audio clocks configured\n"); + return; + } + + for (i = 0; i < ARRAY_SIZE(dac_divs); ++i) { + if (wm8960->sysclk == lrclk * dac_divs[i]) { + for (j = 0; j < ARRAY_SIZE(bclk_divs); ++j) { + if (wm8960->sysclk == wm8960->bclk * + bclk_divs[j] / 10) { + goto config_clock; + } + } + } + } + + dev_err(codec->dev, "Unsupported sysclk %d\n", wm8960->sysclk); + return; + +config_clock: + /* configure frame clock. If ADCLRC configure as GPIO pin, DACLRC + * pin is used as a frame clock for ADCs and DACs. + */ + if (iface2 & (1<<6)) + snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 3, i << 3); + else if (SNDRV_PCM_STREAM_PLAYBACK == stream) + snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 3, i << 3); + else if (SNDRV_PCM_STREAM_CAPTURE == stream) + snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 6, i << 6); + + /* configure bit clock */ + snd_soc_update_bits(codec, WM8960_CLOCK2, 0xf, j); +} + static int wm8960_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -572,6 +636,10 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; int i; + wm8960->bclk = snd_soc_params_to_bclk(params); + if (params_channels(params) == 1) + wm8960->bclk *= 2; + /* bit size */ switch (params_width(params)) { case 16: @@ -602,6 +670,10 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, /* set iface */ snd_soc_write(codec, WM8960_IFACE1, iface); + + wm8960_configure_clocking(codec, substream->stream, + params_rate(params)); + return 0; } @@ -950,6 +1022,30 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec, return wm8960->set_bias_level(codec, level); } +static int wm8960_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = dai->codec; + struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); + + switch (clk_id) { + case WM8960_SYSCLK_MCLK: + snd_soc_update_bits(codec, WM8960_CLOCK1, + 0x1, WM8960_SYSCLK_MCLK); + break; + case WM8960_SYSCLK_PLL: + snd_soc_update_bits(codec, WM8960_CLOCK1, + 0x1, WM8960_SYSCLK_PLL); + break; + default: + return -EINVAL; + } + + wm8960->sysclk = freq; + + return 0; +} + #define WM8960_RATES SNDRV_PCM_RATE_8000_48000 #define WM8960_FORMATS \ @@ -962,6 +1058,7 @@ static const struct snd_soc_dai_ops wm8960_dai_ops = { .set_fmt = wm8960_set_dai_fmt, .set_clkdiv = wm8960_set_dai_clkdiv, .set_pll = wm8960_set_dai_pll, + .set_sysclk = wm8960_set_dai_sysclk, }; static struct snd_soc_dai_driver wm8960_dai = {