From patchwork Mon Jun 24 13:42:06 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Ujfalusi X-Patchwork-Id: 18076 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-qc0-f199.google.com (mail-qc0-f199.google.com [209.85.216.199]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 26E7825CFE for ; Mon, 24 Jun 2013 13:43:09 +0000 (UTC) Received: by mail-qc0-f199.google.com with SMTP id a1sf15131039qcx.2 for ; Mon, 24 Jun 2013 06:43:09 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-beenthere:x-forwarded-to:x-forwarded-for:delivered-to:from:to:cc :subject:date:message-id:x-mailer:in-reply-to:references :mime-version:x-gm-message-state:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :x-google-group-id:list-post:list-help:list-archive:list-unsubscribe :content-type; bh=w6qDZ+rRndhIVhCcmYfhs1A/Psdv7Wsp6XTJql9z9Qc=; b=eV9S8OadE7P/6phOSxy+ItSUjnyc7lWz2S1km0uJr05pliAmIE57g3B9BMc9LNzYRS JdmpoReSzOWapIqLxtCM70ExIvSDDYtteG9dztduCjotdB61hE8MfyqKjjFrXvR9RmQp uz3dfEuqkDQJkNWyJdAkNLRVrvTnFqoUWyLu80dVt0FKeAANXYDP7ZwNdVZHbs6T9xCM gjRiIO66qy/0JsQv04C9EMupuOpTjl8gZ0ugf88zmzL+cReHf55Q2XH5vb2uDyeFlqsf 4qbaBlN3jFTmN8V6VvVe7ypH++uXEebZlfI/1O+RrLVh7Z9KvE/CJ0VluhmvIyu/M/4F KfoQ== X-Received: by 10.236.70.170 with SMTP id p30mr14026868yhd.5.1372081341624; Mon, 24 Jun 2013 06:42:21 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.18.196 with SMTP id y4ls2045313qed.38.gmail; Mon, 24 Jun 2013 06:42:21 -0700 (PDT) X-Received: by 10.58.233.47 with SMTP id tt15mr11423811vec.56.1372081341477; Mon, 24 Jun 2013 06:42:21 -0700 (PDT) Received: from mail-vb0-x235.google.com (mail-vb0-x235.google.com [2607:f8b0:400c:c02::235]) by mx.google.com with ESMTPS id l10si4883409vet.1.2013.06.24.06.42.21 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 24 Jun 2013 06:42:21 -0700 (PDT) Received-SPF: neutral (google.com: 2607:f8b0:400c:c02::235 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=2607:f8b0:400c:c02::235; Received: by mail-vb0-f53.google.com with SMTP id p12so7994188vbe.26 for ; Mon, 24 Jun 2013 06:42:21 -0700 (PDT) X-Received: by 10.52.120.77 with SMTP id la13mr9715825vdb.23.1372081341378; Mon, 24 Jun 2013 06:42:21 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.58.165.8 with SMTP id yu8csp28073veb; Mon, 24 Jun 2013 06:42:20 -0700 (PDT) X-Received: by 10.236.67.72 with SMTP id i48mr12644071yhd.237.1372081340817; Mon, 24 Jun 2013 06:42:20 -0700 (PDT) Received: from arroyo.ext.ti.com (arroyo.ext.ti.com. [192.94.94.40]) by mx.google.com with ESMTPS id b7si9286451yhe.289.2013.06.24.06.42.20 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Mon, 24 Jun 2013 06:42:20 -0700 (PDT) Received-SPF: pass (google.com: domain of peter.ujfalusi@ti.com designates 192.94.94.40 as permitted sender) client-ip=192.94.94.40; Received: from dlelxv90.itg.ti.com ([172.17.2.17]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id r5ODgF2p032195; Mon, 24 Jun 2013 08:42:15 -0500 Received: from DLEE71.ent.ti.com (dlee71.ent.ti.com [157.170.170.114]) by dlelxv90.itg.ti.com (8.14.3/8.13.8) with ESMTP id r5ODgFaA003023; Mon, 24 Jun 2013 08:42:15 -0500 Received: from dlelxv22.itg.ti.com (172.17.1.197) by DLEE71.ent.ti.com (157.170.170.114) with Microsoft SMTP Server id 14.2.342.3; Mon, 24 Jun 2013 08:42:14 -0500 Received: from barack.emea.dhcp.ti.com (barack.emea.dhcp.ti.com [137.167.125.74]) by dlelxv22.itg.ti.com (8.13.8/8.13.8) with ESMTP id r5ODg7oA028079; Mon, 24 Jun 2013 08:42:13 -0500 From: Peter Ujfalusi To: Mark Brown , Liam Girdwood CC: Misael Lopez Cruz , , , Jyri Sarha Subject: [PATCH 4/4] ASoC: twl6040: Add digital mute support Date: Mon, 24 Jun 2013 15:42:06 +0200 Message-ID: <1372081326-6917-5-git-send-email-peter.ujfalusi@ti.com> X-Mailer: git-send-email 1.8.2.1 In-Reply-To: <1372081326-6917-1-git-send-email-peter.ujfalusi@ti.com> References: <1372081326-6917-1-git-send-email-peter.ujfalusi@ti.com> MIME-Version: 1.0 X-Gm-Message-State: ALoCoQksKVg7o0fjTudpBbJC0eMKficq0/iHxpmVArHcuYipJ9nKnXlbN2vhWsFYUgEnl+6pBzSF X-Original-Sender: peter.ujfalusi@ti.com X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 2607:f8b0:400c:c02::235 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , To reduce pop noise during playback stream start and stop the codec needs to have the digital_mute callback implemented. The codec need to be muted before the CPU dai has been stopped (McPDM). Stopping the McPDM will generate a pop on the codec since no signal on the PDM bus means full negative amplitude. By managing the mute/unmute state of the outputs we can decrease the amount of pop noise when playback starts or stops. Signed-off-by: Peter Ujfalusi --- sound/soc/codecs/twl6040.c | 91 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 9ea3dbc..44621dd 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -75,6 +75,8 @@ struct twl6040_data { int pll_power_mode; int hs_power_mode; int hs_power_mode_locked; + bool dl1_unmuted; + bool dl2_unmuted; unsigned int clk_in; unsigned int sysclk; struct twl6040_jack_data hs_jack; @@ -228,6 +230,25 @@ static int twl6040_read_reg_volatile(struct snd_soc_codec *codec, return value; } +static bool twl6040_is_path_unmuted(struct snd_soc_codec *codec, + unsigned int reg) +{ + struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); + + switch (reg) { + case TWL6040_REG_HSLCTL: + case TWL6040_REG_HSRCTL: + case TWL6040_REG_EARCTL: + /* DL1 path */ + return priv->dl1_unmuted; + case TWL6040_REG_HFLCTL: + case TWL6040_REG_HFRCTL: + return priv->dl2_unmuted; + default: + return 1; + }; +} + /* * write to the twl6040 register space */ @@ -240,7 +261,8 @@ static int twl6040_write(struct snd_soc_codec *codec, return -EIO; twl6040_write_reg_cache(codec, reg, value); - if (likely(reg < TWL6040_REG_SW_SHADOW)) + if (likely(reg < TWL6040_REG_SW_SHADOW) && + twl6040_is_path_unmuted(codec, reg)) return twl6040_reg_write(twl6040, reg, value); else return 0; @@ -1034,11 +1056,78 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai, return 0; } +static void twl6040_mute_path(struct snd_soc_codec *codec, enum twl6040_dai_id id, + int mute) +{ + struct twl6040 *twl6040 = codec->control_data; + struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); + int hslctl, hsrctl, earctl; + int hflctl, hfrctl; + + switch (id) { + case TWL6040_DAI_DL1: + hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL); + hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL); + earctl = twl6040_read_reg_cache(codec, TWL6040_REG_EARCTL); + + if (mute) { + /* Power down drivers and DACs */ + earctl &= ~0x01; + hslctl &= ~(TWL6040_HSDRVENA | TWL6040_HSDACENA); + hsrctl &= ~(TWL6040_HSDRVENA | TWL6040_HSDACENA); + + } + + twl6040_reg_write(twl6040, TWL6040_REG_EARCTL, earctl); + twl6040_reg_write(twl6040, TWL6040_REG_HSLCTL, hslctl); + twl6040_reg_write(twl6040, TWL6040_REG_HSRCTL, hsrctl); + priv->dl1_unmuted = !mute; + break; + case TWL6040_DAI_DL2: + hflctl = twl6040_read_reg_cache(codec, TWL6040_REG_HFLCTL); + hfrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HFRCTL); + + if (mute) { + /* Power down drivers and DACs */ + hflctl &= ~(TWL6040_HFDACENA | TWL6040_HFPGAENA | + TWL6040_HFDRVENA); + hfrctl &= ~(TWL6040_HFDACENA | TWL6040_HFPGAENA | + TWL6040_HFDRVENA); + } + + twl6040_reg_write(twl6040, TWL6040_REG_HFLCTL, hflctl); + twl6040_reg_write(twl6040, TWL6040_REG_HFRCTL, hfrctl); + priv->dl2_unmuted = !mute; + break; + default: + break; + }; +} + +static int twl6040_digital_mute(struct snd_soc_dai *dai, int mute) +{ + switch (dai->id) { + case TWL6040_DAI_LEGACY: + twl6040_mute_path(dai->codec, TWL6040_DAI_DL1, mute); + twl6040_mute_path(dai->codec, TWL6040_DAI_DL2, mute); + break; + case TWL6040_DAI_DL1: + case TWL6040_DAI_DL2: + twl6040_mute_path(dai->codec, dai->id, mute); + break; + default: + break; + } + + return 0; +} + static const struct snd_soc_dai_ops twl6040_dai_ops = { .startup = twl6040_startup, .hw_params = twl6040_hw_params, .prepare = twl6040_prepare, .set_sysclk = twl6040_set_dai_sysclk, + .digital_mute = twl6040_digital_mute, }; static struct snd_soc_dai_driver twl6040_dai[] = {