From patchwork Tue Jul 25 17:51:25 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Riegel X-Patchwork-Id: 9862613 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 7FE4D600F5 for ; Tue, 25 Jul 2017 17:54:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 71A4028681 for ; Tue, 25 Jul 2017 17:54:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 66616286D1; Tue, 25 Jul 2017 17:54:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 730D728681 for ; Tue, 25 Jul 2017 17:54:08 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 797AF2672AC; Tue, 25 Jul 2017 19:53:23 +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 9B90D267345; Tue, 25 Jul 2017 19:53:19 +0200 (CEST) Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) by alsa0.perex.cz (Postfix) with ESMTP id C7AE32672B1 for ; Tue, 25 Jul 2017 19:53:11 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id A60EC9C1C58; Tue, 25 Jul 2017 13:53:10 -0400 (EDT) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id kT9TXPLI6H8P; Tue, 25 Jul 2017 13:53:09 -0400 (EDT) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 909329C18C5; Tue, 25 Jul 2017 13:53:09 -0400 (EDT) X-Virus-Scanned: amavisd-new at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id eV5PNB5eyX0n; Tue, 25 Jul 2017 13:53:09 -0400 (EDT) Received: from workotop.humanware.local (unknown [192.252.129.34]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id 52CBD9C1B91; Tue, 25 Jul 2017 13:53:09 -0400 (EDT) From: Damien Riegel To: alsa-devel@alsa-project.org Date: Tue, 25 Jul 2017 13:51:25 -0400 Message-Id: <20170725175126.26578-3-damien.riegel@savoirfairelinux.com> X-Mailer: git-send-email 2.13.3 In-Reply-To: <20170725175126.26578-1-damien.riegel@savoirfairelinux.com> References: <20170725175126.26578-1-damien.riegel@savoirfairelinux.com> Cc: Banajit Goswami , Liam Girdwood , Damien Riegel , linux-kernel@vger.kernel.org, Patrick Lai , Takashi Iwai , Mark Brown , Srinivas Kandagatla , kernel@savoirfairelinux.com Subject: [alsa-devel] [PATCH v1 2/3] ASoC: codecs: msm8916-analog: support jack detection 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 X-Virus-Scanned: ClamAV using ClamSMTP The audio codec in the PM8916 has a feature called Multi-Button Headset Control (MBHC). It can support of up to five buttons on a headset, and jack insertion/removal detection. This patch only supports the jack detection. A complete implementation is available in the Android kernel [1] for reference. [1] https://source.codeaurora.org/quic/la/kernel/msm-4.4/tree/sound/soc/codecs/wcd-mbhc-v2.c?h=LA.BR.1.2.4-00310-8x16.0 Signed-off-by: Damien Riegel --- sound/soc/codecs/msm8916-wcd-analog.c | 103 ++++++++++++++++++++++++++++++++++ sound/soc/codecs/msm8916-wcd-analog.h | 18 ++++++ 2 files changed, 121 insertions(+) create mode 100644 sound/soc/codecs/msm8916-wcd-analog.h diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c index 0c351700044a..b9e11012f763 100644 --- a/sound/soc/codecs/msm8916-wcd-analog.c +++ b/sound/soc/codecs/msm8916-wcd-analog.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -37,6 +38,8 @@ #define DIG_CLK_CTL_RXD1_CLK_EN BIT(0) #define DIG_CLK_CTL_RXD2_CLK_EN BIT(1) #define DIG_CLK_CTL_RXD3_CLK_EN BIT(2) +#define DIG_CLK_CTL_MBHC_EN_MASK BIT(3) +#define DIG_CLK_CTL_MBHC_EN BIT(3) #define DIG_CLK_CTL_TXD_CLK_EN BIT(4) #define DIG_CLK_CTL_NCP_CLK_EN_MASK BIT(6) #define DIG_CLK_CTL_NCP_CLK_EN BIT(6) @@ -130,6 +133,10 @@ #define CDC_A_MICB_2_EN (0xf144) #define CDC_A_TX_1_2_ATEST_CTL_2 (0xf145) #define CDC_A_MASTER_BIAS_CTL (0xf146) +#define CDC_A_MBHC_DET_CTL_1 (0xf147) +#define MHBC_DET_CTL_1_DET_TYPE BIT(5) +#define CDC_A_MBHC_DET_CTL_2 (0xf150) +#define CDC_A_MBHC_DBNC_TIMER (0xf152) #define CDC_A_TX_1_EN (0xf160) #define CDC_A_TX_2_EN (0xf161) #define CDC_A_TX_1_2_TEST_CTL_1 (0xf162) @@ -221,8 +228,10 @@ static const char * const supply_names[] = { struct pm8916_wcd_analog_priv { u16 pmic_rev; u16 codec_version; + struct snd_soc_codec *codec; struct clk *mclk; struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; + struct snd_soc_jack *jack; unsigned int micbias1_cap_mode; unsigned int micbias2_cap_mode; }; @@ -522,6 +531,7 @@ static int pm8916_wcd_analog_probe(struct snd_soc_codec *codec) return err; } + priv->codec = codec; snd_soc_codec_set_drvdata(codec, priv); priv->pmic_rev = snd_soc_read(codec, CDC_D_REVISION1); priv->codec_version = snd_soc_read(codec, CDC_D_PERPH_SUBTYPE); @@ -547,6 +557,70 @@ static int pm8916_wcd_analog_remove(struct snd_soc_codec *codec) priv->supplies); } +static irqreturn_t pm8916_wcd_analog_mbhc_switch_handler(int irq, void *data) +{ + struct pm8916_wcd_analog_priv *priv = data; + struct snd_soc_codec *codec = priv->codec; + unsigned int reg; + int mask, status; + bool insert; + + if (!codec || !priv->jack) + return IRQ_HANDLED; + + reg = snd_soc_read(codec, CDC_A_MBHC_DET_CTL_1); + insert = reg & MHBC_DET_CTL_1_DET_TYPE; + mask = SND_JACK_MECHANICAL; + + dev_dbg(codec->dev, "detected jack %s\n", + insert ? "insertion" : "removal"); + + /* switch between insertion and removal detection */ + snd_soc_update_bits(codec, CDC_A_MBHC_DET_CTL_1, + MHBC_DET_CTL_1_DET_TYPE, + reg ^ MHBC_DET_CTL_1_DET_TYPE); + + if (insert) + status = SND_JACK_MECHANICAL; + else + status = 0; + + snd_soc_jack_report(priv->jack, status, mask); + + return IRQ_HANDLED; +} + + +/** + * pm8916_wcd_analog_jack_detect - Enable jack detection. + * + * @codec: msm8916 codec + * @jack: jack to report detection events on + * + * Enables jack detection of the pm8916-analog. It is capable of reporting + * mechanical insertion. + */ +int pm8916_wcd_analog_jack_detect(struct snd_soc_codec *codec, + struct snd_soc_jack *jack) +{ + struct pm8916_wcd_analog_priv *priv = snd_soc_codec_get_drvdata(codec); + + priv->jack = jack; + + snd_soc_update_bits(codec, CDC_D_CDC_RST_CTL, + RST_CTL_DIG_SW_RST_N_MASK, + RST_CTL_DIG_SW_RST_N_REMOVE_RESET); + snd_soc_write(codec, CDC_A_MBHC_DET_CTL_1, 0xB5); + snd_soc_write(codec, CDC_A_MBHC_DET_CTL_2, 0xE1); + snd_soc_write(codec, CDC_A_MBHC_DBNC_TIMER, 0x98); + snd_soc_update_bits(codec, CDC_D_CDC_DIG_CLK_CTL, + DIG_CLK_CTL_MBHC_EN_MASK, + DIG_CLK_CTL_MBHC_EN); + + return 0; +} +EXPORT_SYMBOL_GPL(pm8916_wcd_analog_jack_detect); + static const struct snd_soc_dapm_route pm8916_wcd_analog_audio_map[] = { {"PDM_RX1", NULL, "PDM Playback"}, @@ -799,6 +873,14 @@ static struct snd_soc_codec_driver pm8916_wcd_analog = { }, }; +static struct jack_detect_irq { + const char *name; + irqreturn_t (*handler)(int, void *); +} jack_detect_irqs[] = { + { "mbhc_switch_int", pm8916_wcd_analog_mbhc_switch_handler }, + /* other MBHC related interrupts are not handled yet */ +}; + static int pm8916_wcd_analog_parse_dt(struct device *dev, struct pm8916_wcd_analog_priv *priv) { @@ -846,6 +928,27 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev) return ret; } + for (i = 0; i < ARRAY_SIZE(jack_detect_irqs); i++) { + int irq; + + irq = platform_get_irq_byname(pdev, jack_detect_irqs[i].name); + if (irq < 0) { + dev_warn(dev, "failed to get irq '%s', jack insertion detection disabled\n", + jack_detect_irqs[i].name); + break; + } + + ret = devm_request_threaded_irq(dev, irq, NULL, + jack_detect_irqs[i].handler, + IRQF_ONESHOT, + jack_detect_irqs[i].name, priv); + if (ret) { + dev_err(dev, "failed to request irq '%s': %d\n", + jack_detect_irqs[i].name, ret); + return ret; + } + } + ret = clk_prepare_enable(priv->mclk); if (ret < 0) { dev_err(dev, "failed to enable mclk %d\n", ret); diff --git a/sound/soc/codecs/msm8916-wcd-analog.h b/sound/soc/codecs/msm8916-wcd-analog.h new file mode 100644 index 000000000000..5cd00bb5f34a --- /dev/null +++ b/sound/soc/codecs/msm8916-wcd-analog.h @@ -0,0 +1,18 @@ +/* + * msm8916-wcd-analog.h - MSM8916 analog audio codec interface + * + * Copyright 2017 - Savoir-faire Linux, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef _MSM8916_WCD_ANALOG_H +#define _MSM8916_WCD_ANALOG_H + +int pm8916_wcd_analog_jack_detect(struct snd_soc_codec *codec, + struct snd_soc_jack *jack); + +#endif