From patchwork Thu Mar 2 17:11:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vlad Karpovich X-Patchwork-Id: 659948 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id ACE34C61DA4 for ; Mon, 6 Mar 2023 17:43:07 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 6E56B1136; Mon, 6 Mar 2023 18:42:15 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 6E56B1136 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1678124585; bh=PvM2q0fHHU/RLHQ+La+s+FeaYfFEKsTpC8aA+E7Li3g=; h=From:To:Subject:Date:CC:List-Id:List-Archive:List-Help:List-Owner: List-Post:List-Subscribe:List-Unsubscribe:From; b=vhpeZJXlZQNkUO9dpe+9dK7QQrBV4Wo+HKH6VP8Gi94EUtIQJeh+w7wwQN1YHYwQ5 gSw9FFCwultgl0YyGYSjZhW5CmK2v1dOa8GsNfMc8gCrOWHUL50Uc8uaniqqc5L+pK TLWzV4gYRI1j+80MAVT0OVCb2R/Z8BzrSOFT2ARc= Received: from mailman-core.alsa-project.org (mailman-core.alsa-project.org [10.254.200.10]) by alsa1.perex.cz (Postfix) with ESMTP id EC8B3F805AD; Mon, 6 Mar 2023 18:39:14 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 10964F804B1; Thu, 2 Mar 2023 18:12:36 +0100 (CET) Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id C1D8AF800C9 for ; Thu, 2 Mar 2023 18:12:21 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz C1D8AF800C9 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key, unprotected) header.d=cirrus.com header.i=@cirrus.com header.a=rsa-sha256 header.s=PODMain02222019 header.b=Hqly+ZiN Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 3226vmMj014653; Thu, 2 Mar 2023 11:12:19 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=KTinV/G6Tp7WAearLAGbxpXybqXOTsNpKB60xaJUjoY=; b=Hqly+ZiN82607chhuYUecmolp0XX+fMLGWG4TJz68OPpqM+boOTc3mJYCBbmBQWkTuEg sXR6boRX767mdZAVBN7zGNx6ywwGPknQIHpCG90Mz5uCucIb4m8AsCsQtZBcHEXPNdn3 TUF2xnpNxnrC2ZmN4QJYFSIlyEyiRYO9amE3iUgp2gxKO183TNxXquGf6Z2a98vgpTSZ PDM2zDOI1AEEhkGDnHCLtEoNB11x/hKc5lAVrBQ6OSn25KB1/i/pZkQRYssJ1eBEYlaS z4aEXGcyiTkXA6pBwymNuUT3Sw29qrVDr0xW1iI/2VWJ/5SoOABvfINIV33inFiGE0Sl Qw== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3nygm713h3-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 02 Mar 2023 11:12:18 -0600 Received: from ediex01.ad.cirrus.com (198.61.84.80) by ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.25; Thu, 2 Mar 2023 11:12:16 -0600 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.2.1118.25 via Frontend Transport; Thu, 2 Mar 2023 11:12:16 -0600 Received: from vkarpovich-ThinkStation-P620.crystal.cirrus.com (vkarpovich-ThinkStation-P620.ad.cirrus.com [141.131.206.93]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id A9DCFB06; Thu, 2 Mar 2023 17:12:14 +0000 (UTC) From: Vlad Karpovich To: Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai Subject: [PATCH 1/5] ASoC: cs35l45: Support for GPIO pins configuration. Date: Thu, 2 Mar 2023 11:11:50 -0600 Message-ID: <20230302171154.2342527-1-vkarpovi@opensource.cirrus.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: 5_89w81pNEwwniLwfg0iJoNgvm7-ExGU X-Proofpoint-GUID: 5_89w81pNEwwniLwfg0iJoNgvm7-ExGU X-Proofpoint-Spam-Reason: safe X-MailFrom: prvs=8425611b2f=vkarpovi@opensource.cirrus.com X-Mailman-Rule-Hits: nonmember-moderation X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-alsa-devel.alsa-project.org-0; header-match-alsa-devel.alsa-project.org-1 Message-ID-Hash: VNIBLALF6EHBYVWYER5C7RZXF3W4ADP5 X-Message-ID-Hash: VNIBLALF6EHBYVWYER5C7RZXF3W4ADP5 X-Mailman-Approved-At: Mon, 06 Mar 2023 17:39:02 +0000 CC: alsa-devel@alsa-project.org, patches@opensource.cirrus.com, linux-kernel@vger.kernel.org, "Vlad.Karpovich" X-Mailman-Version: 3.3.8 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: "Vlad.Karpovich" Adds device tree configuration for cs35l45 GPIOs Signed-off-by: Vlad Karpovich --- include/dt-bindings/sound/cs35l45.h | 57 +++++++++++++++++++++++++++++ sound/soc/codecs/cs35l45-tables.c | 14 +++++++ sound/soc/codecs/cs35l45.c | 56 ++++++++++++++++++++++++++++ sound/soc/codecs/cs35l45.h | 27 +++++++++++++- 4 files changed, 152 insertions(+), 2 deletions(-) diff --git a/include/dt-bindings/sound/cs35l45.h b/include/dt-bindings/sound/cs35l45.h index 076da4b2c28d..25386af18445 100644 --- a/include/dt-bindings/sound/cs35l45.h +++ b/include/dt-bindings/sound/cs35l45.h @@ -17,4 +17,61 @@ #define CS35L45_ASP_TX_HIZ_UNUSED 0x1 #define CS35L45_ASP_TX_HIZ_DISABLED 0x2 +/* + * Optional GPIOX Sub-nodes: + * The cs35l45 node can have up to three "cirrus,gpio-ctrlX" ('X' = [1,2,3]) + * sub-nodes for configuring the GPIO pins. + * + * - gpio-dir : GPIO pin direction. Valid only when 'gpio-ctrl' + * is 1. + * 0 = Output + * 1 = Input (Default) + * + * - gpio-lvl : GPIO level. Valid only when 'gpio-ctrl' is 1 and 'gpio-dir' is 0. + * + * 0 = Low (Default) + * 1 = High + * + * - gpio-op-cfg : GPIO output configuration. Valid only when 'gpio-ctrl' is 1 + * and 'gpio-dir' is 0. + * + * 0 = CMOS (Default) + * 1 = Open Drain + * + * - gpio-pol : GPIO output polarity select. Valid only when 'gpio-ctrl' is 1 + * and 'gpio-dir' is 0. + * + * 0 = Non-inverted, Active High (Default) + * 1 = Inverted, Active Low + * + * - gpio-invert : Defines the polarity of the GPIO pin if configured + * as input. + * + * 0 = Not inverted (Default) + * 1 = Inverted + * + * - gpio-ctrl : Defines the function of the GPIO pin. + * + * GPIO1: + * 0 = High impedance input (Default) + * 1 = Pin acts as a GPIO, direction controlled by 'gpio-dir' + * 2 = Pin acts as MDSYNC, direction controlled by MDSYNC + * 3-7 = Reserved + * + * GPIO2: + * 0 = High impedance input (Default) + * 1 = Pin acts as a GPIO, direction controlled by 'gpio-dir' + * 2 = Pin acts as open drain INT + * 3 = Reserved + * 4 = Pin acts as push-pull output INT. Active low. + * 5 = Pin acts as push-pull output INT. Active high. + * 6,7 = Reserved + * + * GPIO3: + * 0 = High impedance input (Default) + * 1 = Pin acts as a GPIO, direction controlled by 'gpio-dir' + * 2-7 = Reserved + */ +#define CS35L45_NUM_GPIOS 0x3 + #endif /* DT_CS35L45_H */ diff --git a/sound/soc/codecs/cs35l45-tables.c b/sound/soc/codecs/cs35l45-tables.c index 5a2c2e684ef9..bca7e830821f 100644 --- a/sound/soc/codecs/cs35l45-tables.c +++ b/sound/soc/codecs/cs35l45-tables.c @@ -43,6 +43,9 @@ EXPORT_SYMBOL_NS_GPL(cs35l45_apply_patch, SND_SOC_CS35L45_TABLES); static const struct reg_default cs35l45_defaults[] = { { CS35L45_BLOCK_ENABLES, 0x00003323 }, { CS35L45_BLOCK_ENABLES2, 0x00000010 }, + { CS35L45_SYNC_GPIO1, 0x00000007 }, + { CS35L45_INTB_GPIO2_MCLK_REF, 0x00000005 }, + { CS35L45_GPIO3, 0x00000005 }, { CS35L45_REFCLK_INPUT, 0x00000510 }, { CS35L45_GLOBAL_SAMPLE_RATE, 0x00000003 }, { CS35L45_ASP_ENABLES1, 0x00000000 }, @@ -61,6 +64,9 @@ static const struct reg_default cs35l45_defaults[] = { { CS35L45_ASPTX4_INPUT, 0x00000028 }, { CS35L45_ASPTX5_INPUT, 0x00000048 }, { CS35L45_AMP_PCM_CONTROL, 0x00100000 }, + { CS35L45_GPIO1_CTRL1, 0x81000001 }, + { CS35L45_GPIO2_CTRL1, 0x81000001 }, + { CS35L45_GPIO3_CTRL1, 0x81000001 }, }; static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) @@ -72,6 +78,9 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) case CS35L45_BLOCK_ENABLES: case CS35L45_BLOCK_ENABLES2: case CS35L45_ERROR_RELEASE: + case CS35L45_SYNC_GPIO1: + case CS35L45_INTB_GPIO2_MCLK_REF: + case CS35L45_GPIO3: case CS35L45_REFCLK_INPUT: case CS35L45_GLOBAL_SAMPLE_RATE: case CS35L45_ASP_ENABLES1: @@ -92,6 +101,10 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) case CS35L45_AMP_PCM_CONTROL: case CS35L45_AMP_PCM_HPF_TST: case CS35L45_IRQ1_EINT_4: + case CS35L45_GPIO_STATUS1: + case CS35L45_GPIO1_CTRL1: + case CS35L45_GPIO2_CTRL1: + case CS35L45_GPIO3_CTRL1: return true; default: return false; @@ -107,6 +120,7 @@ static bool cs35l45_volatile_reg(struct device *dev, unsigned int reg) case CS35L45_ERROR_RELEASE: case CS35L45_AMP_PCM_HPF_TST: /* not cachable */ case CS35L45_IRQ1_EINT_4: + case CS35L45_GPIO_STATUS1: return true; default: return false; diff --git a/sound/soc/codecs/cs35l45.c b/sound/soc/codecs/cs35l45.c index d15b3b77c7eb..901f3647fbda 100644 --- a/sound/soc/codecs/cs35l45.c +++ b/sound/soc/codecs/cs35l45.c @@ -536,7 +536,63 @@ static int __maybe_unused cs35l45_runtime_resume(struct device *dev) static int cs35l45_apply_property_config(struct cs35l45_private *cs35l45) { + struct device_node *node = cs35l45->dev->of_node; + unsigned int gpio_regs[] = {CS35L45_GPIO1_CTRL1, CS35L45_GPIO2_CTRL1, + CS35L45_GPIO3_CTRL1}; + unsigned int pad_regs[] = {CS35L45_SYNC_GPIO1, + CS35L45_INTB_GPIO2_MCLK_REF, CS35L45_GPIO3}; + struct device_node *child; unsigned int val; + char of_name[32]; + int ret, i; + + if (!node) + return 0; + + for (i = 0; i < CS35L45_NUM_GPIOS; i++) { + sprintf(of_name, "cirrus,gpio-ctrl%d", i + 1); + child = of_get_child_by_name(node, of_name); + if (!child) + continue; + + ret = of_property_read_u32(child, "gpio-dir", &val); + if (!ret) + regmap_update_bits(cs35l45->regmap, gpio_regs[i], + CS35L45_GPIO_DIR_MASK, + val << CS35L45_GPIO_DIR_SHIFT); + + ret = of_property_read_u32(child, "gpio-lvl", &val); + if (!ret) + regmap_update_bits(cs35l45->regmap, gpio_regs[i], + CS35L45_GPIO_LVL_MASK, + val << CS35L45_GPIO_LVL_SHIFT); + + ret = of_property_read_u32(child, "gpio-op-cfg", &val); + if (!ret) + regmap_update_bits(cs35l45->regmap, gpio_regs[i], + CS35L45_GPIO_OP_CFG_MASK, + val << CS35L45_GPIO_OP_CFG_SHIFT); + + ret = of_property_read_u32(child, "gpio-pol", &val); + if (!ret) + regmap_update_bits(cs35l45->regmap, gpio_regs[i], + CS35L45_GPIO_POL_MASK, + val << CS35L45_GPIO_POL_SHIFT); + + ret = of_property_read_u32(child, "gpio-ctrl", &val); + if (!ret) + regmap_update_bits(cs35l45->regmap, pad_regs[i], + CS35L45_GPIO_CTRL_MASK, + val << CS35L45_GPIO_CTRL_SHIFT); + + ret = of_property_read_u32(child, "gpio-invert", &val); + if (!ret) + regmap_update_bits(cs35l45->regmap, pad_regs[i], + CS35L45_GPIO_INVERT_MASK, + val << CS35L45_GPIO_INVERT_SHIFT); + + of_node_put(child); + } if (device_property_read_u32(cs35l45->dev, "cirrus,asp-sdout-hiz-ctrl", &val) == 0) { diff --git a/sound/soc/codecs/cs35l45.h b/sound/soc/codecs/cs35l45.h index 53fe9d2b7b15..f3a54fc57d53 100644 --- a/sound/soc/codecs/cs35l45.h +++ b/sound/soc/codecs/cs35l45.h @@ -14,6 +14,7 @@ #include #include #include +#include #define CS35L45_DEVID 0x00000000 #define CS35L45_REVID 0x00000004 @@ -24,6 +25,9 @@ #define CS35L45_BLOCK_ENABLES 0x00002018 #define CS35L45_BLOCK_ENABLES2 0x0000201C #define CS35L45_ERROR_RELEASE 0x00002034 +#define CS35L45_SYNC_GPIO1 0x00002430 +#define CS35L45_INTB_GPIO2_MCLK_REF 0x00002434 +#define CS35L45_GPIO3 0x00002438 #define CS35L45_REFCLK_INPUT 0x00002C04 #define CS35L45_GLOBAL_SAMPLE_RATE 0x00002C0C #define CS35L45_BOOST_CCM_CFG 0x00003808 @@ -48,8 +52,11 @@ #define CS35L45_AMP_PCM_CONTROL 0x00007000 #define CS35L45_AMP_PCM_HPF_TST 0x00007004 #define CS35L45_IRQ1_EINT_4 0x0000E01C -#define CS35L45_LASTREG 0x0000E01C - +#define CS35L45_GPIO_STATUS1 0x0000F000 +#define CS35L45_GPIO1_CTRL1 0x0000F008 +#define CS35L45_GPIO2_CTRL1 0x0000F00C +#define CS35L45_GPIO3_CTRL1 0x0000F010 +#define CS35L45_LASTREG 0x0000F010 /* SFT_RESET */ #define CS35L45_SOFT_RESET_TRIGGER 0x5A000000 @@ -165,6 +172,22 @@ #define CS35L45_OTP_BOOT_DONE_STS_MASK BIT(1) #define CS35L45_OTP_BUSY_MASK BIT(0) +/* GPIOX_CTRL1 */ +#define CS35L45_GPIO_DIR_SHIFT 31 +#define CS35L45_GPIO_DIR_MASK BIT(31) +#define CS35L45_GPIO_LVL_SHIFT 15 +#define CS35L45_GPIO_LVL_MASK BIT(15) +#define CS35L45_GPIO_OP_CFG_SHIFT 14 +#define CS35L45_GPIO_OP_CFG_MASK BIT(14) +#define CS35L45_GPIO_POL_SHIFT 12 +#define CS35L45_GPIO_POL_MASK BIT(12) + +/* SYNC_GPIO1, INTB_GPIO2_MCLK_REF, GPIO3 */ +#define CS35L45_GPIO_CTRL_SHIFT 20 +#define CS35L45_GPIO_CTRL_MASK GENMASK(22, 20) +#define CS35L45_GPIO_INVERT_SHIFT 19 +#define CS35L45_GPIO_INVERT_MASK BIT(19) + /* Mixer sources */ #define CS35L45_PCM_SRC_MASK 0x7F #define CS35L45_PCM_SRC_ZERO 0x00 From patchwork Thu Mar 2 17:11:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vlad Karpovich X-Patchwork-Id: 659947 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3BE2EC64EC4 for ; Mon, 6 Mar 2023 17:43:39 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 061101139; Mon, 6 Mar 2023 18:42:47 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 061101139 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1678124617; bh=JSi7EemZCUPtWCmpuXCPTfDGbYK8js+emGU+Dy+rToQ=; h=From:To:Subject:Date:In-Reply-To:References:CC:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=L4AsmZCfBjJenlZMT9KUXnNqr7AqAYWnNNxMfZJpaW/uXHMSw1Gjm54QoOxxpwoBN hTe3NEVfntidwVmP8V5jpchxntr4Y2xyBPduCHL0wiPyw0YtlgjLdx6oiXIL7hJcjI nEjb8KkKyMfonIdezHOGxsh8OBWqVrHGHUhAxV7k= Received: from mailman-core.alsa-project.org (mailman-core.alsa-project.org [10.254.200.10]) by alsa1.perex.cz (Postfix) with ESMTP id 1824EF805B5; Mon, 6 Mar 2023 18:39:22 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 5C156F80310; Thu, 2 Mar 2023 18:12:57 +0100 (CET) Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 470A9F800DF for ; Thu, 2 Mar 2023 18:12:28 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 470A9F800DF Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key, unprotected) header.d=cirrus.com header.i=@cirrus.com header.a=rsa-sha256 header.s=PODMain02222019 header.b=ZXH0mvHd Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 3225WaTQ007775; Thu, 2 Mar 2023 11:12:27 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=EHHCWzHpF4rQVg0WOJz1Y6d6fEeVpaItK9KZDCSViAc=; b=ZXH0mvHd5ly2TzVfbOce0AxKuvW0f+TzTcmLT9MQDejdFPCTa/scXVVRqab6Wzm/iDVG ++H4cA/HPdw7/rUcuSYHpwT/cLpS3cF/7I/ROgWMAR+foTqmRDEMN4OIEfpXNS5ieIgc 1qQr4X2qr1A724UuG5SBDk7vYAgkDAdsA+8lT3Q6pGPf4tuceIpatl3pQ6hzKrl/GNiN 8o8tYt4BjjTRDg5hywaddJJq6en3S2aUx97WTVJsqeEkx2C4wmIpbbvQadw0QE+EPxfW ibobzyobhkR1KdgFUATT2loAVmU9/EHwFoUrppSjB8ltdmbVKT7bN6UVOACCvr20kbe+ 3g== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3nygm713ha-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 02 Mar 2023 11:12:26 -0600 Received: from ediex02.ad.cirrus.com (198.61.84.81) by ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.25; Thu, 2 Mar 2023 11:12:25 -0600 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by anon-ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server id 15.2.1118.25 via Frontend Transport; Thu, 2 Mar 2023 11:12:25 -0600 Received: from vkarpovich-ThinkStation-P620.crystal.cirrus.com (vkarpovich-ThinkStation-P620.ad.cirrus.com [141.131.206.93]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 0924CB06; Thu, 2 Mar 2023 17:12:23 +0000 (UTC) From: Vlad Karpovich To: Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai Subject: [PATCH 5/5] ASoC: cs34l45: Hibernation support Date: Thu, 2 Mar 2023 11:11:54 -0600 Message-ID: <20230302171154.2342527-5-vkarpovi@opensource.cirrus.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230302171154.2342527-1-vkarpovi@opensource.cirrus.com> References: <20230302171154.2342527-1-vkarpovi@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: wZbo6KmeORZn9e16LJKzgKYLaOiVTTL3 X-Proofpoint-GUID: wZbo6KmeORZn9e16LJKzgKYLaOiVTTL3 X-Proofpoint-Spam-Reason: safe X-MailFrom: prvs=8425611b2f=vkarpovi@opensource.cirrus.com X-Mailman-Rule-Hits: nonmember-moderation X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-alsa-devel.alsa-project.org-0; header-match-alsa-devel.alsa-project.org-1 Message-ID-Hash: S6WE653XOF6AOZ2XNEEGQEHAGQYOJH5H X-Message-ID-Hash: S6WE653XOF6AOZ2XNEEGQEHAGQYOJH5H X-Mailman-Approved-At: Mon, 06 Mar 2023 17:39:03 +0000 CC: alsa-devel@alsa-project.org, patches@opensource.cirrus.com, linux-kernel@vger.kernel.org, "Vlad.Karpovich" X-Mailman-Version: 3.3.8 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: "Vlad.Karpovich" Adds support for the amplifier hibernation controlled by DSP firmware. Signed-off-by: Vlad Karpovich --- sound/soc/codecs/cs35l45-i2c.c | 2 + sound/soc/codecs/cs35l45-spi.c | 1 + sound/soc/codecs/cs35l45-tables.c | 6 +++ sound/soc/codecs/cs35l45.c | 80 +++++++++++++++++++++++++++++++ sound/soc/codecs/cs35l45.h | 29 +++++++++++ 5 files changed, 118 insertions(+) diff --git a/sound/soc/codecs/cs35l45-i2c.c b/sound/soc/codecs/cs35l45-i2c.c index 5224aaf584b8..1c644ddf66bc 100644 --- a/sound/soc/codecs/cs35l45-i2c.c +++ b/sound/soc/codecs/cs35l45-i2c.c @@ -33,6 +33,8 @@ static int cs35l45_i2c_probe(struct i2c_client *client) cs35l45->dev = dev; cs35l45->irq = client->irq; + cs35l45->bus_type = CONTROL_BUS_I2C; + cs35l45->i2c_addr = client->addr; return cs35l45_probe(cs35l45); } diff --git a/sound/soc/codecs/cs35l45-spi.c b/sound/soc/codecs/cs35l45-spi.c index bfb79255783e..3ea2e6fd2b88 100644 --- a/sound/soc/codecs/cs35l45-spi.c +++ b/sound/soc/codecs/cs35l45-spi.c @@ -36,6 +36,7 @@ static int cs35l45_spi_probe(struct spi_device *spi) cs35l45->dev = dev; cs35l45->irq = spi->irq; + cs35l45->bus_type = CONTROL_BUS_SPI; return cs35l45_probe(cs35l45); } diff --git a/sound/soc/codecs/cs35l45-tables.c b/sound/soc/codecs/cs35l45-tables.c index 6b68773979ec..212d9cb5a4fb 100644 --- a/sound/soc/codecs/cs35l45-tables.c +++ b/sound/soc/codecs/cs35l45-tables.c @@ -47,6 +47,8 @@ static const struct reg_default cs35l45_defaults[] = { { CS35L45_INTB_GPIO2_MCLK_REF, 0x00000005 }, { CS35L45_GPIO3, 0x00000005 }, { CS35L45_PWRMGT_CTL, 0x00000000 }, + { CS35L45_WAKESRC_CTL, 0x00000008 }, + { CS35L45_WKI2C_CTL, 0x00000030 }, { CS35L45_REFCLK_INPUT, 0x00000510 }, { CS35L45_GLOBAL_SAMPLE_RATE, 0x00000003 }, { CS35L45_ASP_ENABLES1, 0x00000000 }, @@ -126,6 +128,9 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) case CS35L45_INTB_GPIO2_MCLK_REF: case CS35L45_GPIO3: case CS35L45_PWRMGT_CTL: + case CS35L45_WAKESRC_CTL: + case CS35L45_WKI2C_CTL: + case CS35L45_PWRMGT_STS: case CS35L45_REFCLK_INPUT: case CS35L45_GLOBAL_SAMPLE_RATE: case CS35L45_ASP_ENABLES1: @@ -210,6 +215,7 @@ static bool cs35l45_volatile_reg(struct device *dev, unsigned int reg) case CS35L45_GLOBAL_ENABLES: case CS35L45_ERROR_RELEASE: case CS35L45_AMP_PCM_HPF_TST: /* not cachable */ + case CS35L45_PWRMGT_STS: case CS35L45_IRQ1_STATUS: case CS35L45_IRQ1_EINT_1 ... CS35L45_IRQ1_EINT_18: case CS35L45_IRQ1_STS_1 ... CS35L45_IRQ1_STS_18: diff --git a/sound/soc/codecs/cs35l45.c b/sound/soc/codecs/cs35l45.c index c5de2c8a9fe3..a2bab613daa2 100644 --- a/sound/soc/codecs/cs35l45.c +++ b/sound/soc/codecs/cs35l45.c @@ -36,6 +36,8 @@ static bool cs35l45_check_cspl_mbox_sts(const enum cs35l45_cspl_mboxcmd cmd, return (sts == CSPL_MBOX_STS_RUNNING); case CSPL_MBOX_CMD_STOP_PRE_REINIT: return (sts == CSPL_MBOX_STS_RDY_FOR_REINIT); + case CSPL_MBOX_CMD_HIBERNATE: + return (sts == CSPL_MBOX_STS_HIBERNATE); default: return false; } @@ -745,11 +747,81 @@ static const struct snd_soc_component_driver cs35l45_component = { .endianness = 1, }; +static void cs35l45_setup_hibernate(struct cs35l45_private *cs35l45) +{ + unsigned int wksrc; + + if (cs35l45->bus_type == CONTROL_BUS_I2C) + wksrc = CS35L45_WKSRC_I2C; + else + wksrc = CS35L45_WKSRC_SPI; + + regmap_update_bits(cs35l45->regmap, CS35L45_WAKESRC_CTL, + CS35L45_WKSRC_EN_MASK, + wksrc << CS35L45_WKSRC_EN_SHIFT); + + regmap_set_bits(cs35l45->regmap, CS35L45_WAKESRC_CTL, + CS35L45_UPDT_WKCTL_MASK); + + regmap_update_bits(cs35l45->regmap, CS35L45_WKI2C_CTL, + CS35L45_WKI2C_ADDR_MASK, cs35l45->i2c_addr); + + regmap_set_bits(cs35l45->regmap, CS35L45_WKI2C_CTL, + CS35L45_UPDT_WKI2C_MASK); +} + +static int cs35l45_enter_hibernate(struct cs35l45_private *cs35l45) +{ + dev_dbg(cs35l45->dev, "Enter hibernate\n"); + + cs35l45_setup_hibernate(cs35l45); + + // Don't wait for ACK since bus activity would wake the device + regmap_write(cs35l45->regmap, CS35L45_DSP_VIRT1_MBOX_1, CSPL_MBOX_CMD_HIBERNATE); + + return 0; +} + +static int cs35l45_exit_hibernate(struct cs35l45_private *cs35l45) +{ + const int wake_retries = 20; + const int sleep_retries = 5; + int ret, i, j; + + for (i = 0; i < sleep_retries; i++) { + dev_dbg(cs35l45->dev, "Exit hibernate\n"); + + for (j = 0; j < wake_retries; j++) { + ret = cs35l45_set_cspl_mbox_cmd(cs35l45, cs35l45->regmap, + CSPL_MBOX_CMD_OUT_OF_HIBERNATE); + if (!ret) { + dev_dbg(cs35l45->dev, "Wake success at cycle: %d\n", j); + return 0; + } + usleep_range(100, 200); + } + + dev_err(cs35l45->dev, "Wake failed, re-enter hibernate: %d\n", ret); + + cs35l45_setup_hibernate(cs35l45); + } + + dev_err(cs35l45->dev, "Timed out waking device\n"); + + return -ETIMEDOUT; +} + static int __maybe_unused cs35l45_runtime_suspend(struct device *dev) { struct cs35l45_private *cs35l45 = dev_get_drvdata(dev); + if (!cs35l45->dsp.preloaded || !cs35l45->dsp.cs_dsp.running) + return 0; + + cs35l45_enter_hibernate(cs35l45); + regcache_cache_only(cs35l45->regmap, true); + regcache_mark_dirty(cs35l45->regmap); dev_dbg(cs35l45->dev, "Runtime suspended\n"); @@ -761,9 +833,17 @@ static int __maybe_unused cs35l45_runtime_resume(struct device *dev) struct cs35l45_private *cs35l45 = dev_get_drvdata(dev); int ret; + if (!cs35l45->dsp.preloaded || !cs35l45->dsp.cs_dsp.running) + return 0; + dev_dbg(cs35l45->dev, "Runtime resume\n"); regcache_cache_only(cs35l45->regmap, false); + + ret = cs35l45_exit_hibernate(cs35l45); + if (ret) + return ret; + ret = regcache_sync(cs35l45->regmap); if (ret != 0) dev_warn(cs35l45->dev, "regcache_sync failed: %d\n", ret); diff --git a/sound/soc/codecs/cs35l45.h b/sound/soc/codecs/cs35l45.h index 87032619b341..0da28439f628 100644 --- a/sound/soc/codecs/cs35l45.h +++ b/sound/soc/codecs/cs35l45.h @@ -30,6 +30,9 @@ #define CS35L45_INTB_GPIO2_MCLK_REF 0x00002434 #define CS35L45_GPIO3 0x00002438 #define CS35L45_PWRMGT_CTL 0x00002900 +#define CS35L45_WAKESRC_CTL 0x00002904 +#define CS35L45_WKI2C_CTL 0x00002908 +#define CS35L45_PWRMGT_STS 0x0000290C #define CS35L45_REFCLK_INPUT 0x00002C04 #define CS35L45_GLOBAL_SAMPLE_RATE 0x00002C0C #define CS35L45_BOOST_CCM_CFG 0x00003808 @@ -348,6 +351,25 @@ #define CS35L45_POST_GLOBAL_EN_US 5000 #define CS35L45_PRE_GLOBAL_DIS_US 3000 +/* WAKESRC_CTL */ +#define CS35L45_WKSRC_SYNC_GPIO1 BIT(0) +#define CS35L45_WKSRC_INT_GPIO2 BIT(1) +#define CS35L45_WKSRC_GPIO3 BIT(2) +#define CS35L45_WKSRC_SPI BIT(3) +#define CS35L45_WKSRC_I2C BIT(4) +#define CS35L45_UPDT_WKCTL_SHIFT 15 +#define CS35L45_UPDT_WKCTL_MASK BIT(15) +#define CS35L45_WKSRC_EN_SHIFT 8 +#define CS35L45_WKSRC_EN_MASK GENMASK(12, 8) +#define CS35L45_WKSRC_POL_SHIFT 0 +#define CS35L45_WKSRC_POL_MASK GENMASK(3, 0) + +/* WAKEI2C_CTL */ +#define CS35L45_UPDT_WKI2C_SHIFT 15 +#define CS35L45_UPDT_WKI2C_MASK BIT(15) +#define CS35L45_WKI2C_ADDR_SHIFT 0 +#define CS35L45_WKI2C_ADDR_MASK GENMASK(6, 0) + #define CS35L45_SPI_MAX_FREQ 4000000 enum cs35l45_cspl_mboxstate { @@ -369,6 +391,11 @@ enum cs35l45_cspl_mboxcmd { CSPL_MBOX_CMD_INVALID_SEQUENCE = -2, }; +enum control_bus_type { + CONTROL_BUS_I2C = 0, + CONTROL_BUS_SPI = 1, +}; + #define CS35L45_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ SNDRV_PCM_FMTBIT_S24_3LE| \ SNDRV_PCM_FMTBIT_S24_LE) @@ -439,6 +466,8 @@ struct cs35l45_private { u8 slot_count; int irq_invert; int irq; + unsigned int i2c_addr; + enum control_bus_type bus_type; struct regmap_irq_chip_data *irq_data; };