From patchwork Thu Nov 5 11:34:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 319544 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4D398C00A89 for ; Thu, 5 Nov 2020 11:37:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E555320936 for ; Thu, 5 Nov 2020 11:37:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="Bg8F75qD" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726665AbgKELhS (ORCPT ); Thu, 5 Nov 2020 06:37:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45450 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730392AbgKELfE (ORCPT ); Thu, 5 Nov 2020 06:35:04 -0500 Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7DB06C0613D2 for ; Thu, 5 Nov 2020 03:35:04 -0800 (PST) Received: by mail-wr1-x436.google.com with SMTP id x7so1367112wrl.3 for ; Thu, 05 Nov 2020 03:35:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=O0nELbaPuoZuw7n2kK2InfOxpklKvuZiw/YN5nvB5ZE=; b=Bg8F75qD1t0buJgZKe3m9CAY34R3lRU5P+FXqaEhjCHOiR5eMBjVjVFVS/rJawUAR8 QWqQ+vM9Y+FcdhPadGSRi2xROAO+lbNEQCG/ZvaI/K8VyZ42gfQ+Oo8fPLvkc3tIG3+7 4p9FjBnCU9bv5p0SEpQm2OL9rY4DYdMDq2fFdBZwSl+Ruir8M0MpUVzHT14NotN5fkpz G6ljSC+cIqCt94LxmIWpfBHobl5ox8BZPAq5HDVLL1g+NAclZ/R1jBiOI61zBzVu2dMH F1ElPylLigyp3PlkyR945L8g+9/wjSBCwgUs89MKlX/HBtx/kzuagSwo7czDqZ8ik7g+ ByVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=O0nELbaPuoZuw7n2kK2InfOxpklKvuZiw/YN5nvB5ZE=; b=mtWd19Hyhxwol7RosYsQn1vSkV+OWmkzFm5S+rZF1rqWckZhVvEf4hsxeG0jPgB8nB Z5b3hP1dBAGg9+INPazrqEhOsaA63CoGsdWBfHfOPDlbkpdiFqlWbR4jkCuMeV8Kizcs m02MBab25RFuUkyG4FjI0YPNabTZwLEmHqMIMjpFn3eTHd18oabYxfSRQ6oz2DZfHdOz 4LYDHYeYsgV5eslfJ0NuMXZIin27S8HVLyZRY8/ChzhAKjT/P+Rvya/d+IWDMRNCY9nF q1iqlTRDkgVoaJ5qZfijOp6xu1pySpveC49vOZzweskScDdNMr7eKOZxBwjYr/wQC3Un 2CUA== X-Gm-Message-State: AOAM5307iQ3nK31l56tavkHK/QA7X3gjUjvF8BdjadaM18MPZ7HXbPx9 Kw83DlxFIDs7U9R7ktLu3PaGSQ== X-Google-Smtp-Source: ABdhPJxTVmVQUrNEA4GTeoFaIN01h8QI27hO2N2sXTb+CiyJJUppgxi+Aebf0Vpo0haN3OnpMj0Oxg== X-Received: by 2002:adf:f3c7:: with SMTP id g7mr2576474wrp.394.1604576103192; Thu, 05 Nov 2020 03:35:03 -0800 (PST) Received: from srini-hackbox.lan (cpc86377-aztw32-2-0-cust226.18-1.cable.virginm.net. [92.233.226.227]) by smtp.gmail.com with ESMTPSA id t199sm2096129wmt.46.2020.11.05.03.35.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Nov 2020 03:35:02 -0800 (PST) From: Srinivas Kandagatla To: broonie@kernel.org Cc: perex@perex.cz, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org, lgirdwood@gmail.com, devicetree@vger.kernel.org, robh+dt@kernel.org, Srinivas Kandagatla , Rob Herring Subject: [PATCH v3 1/6] ASoC: qcom: dt-bindings: add bindings for lpass wsa macro codec Date: Thu, 5 Nov 2020 11:34:53 +0000 Message-Id: <20201105113458.12360-2-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20201105113458.12360-1-srinivas.kandagatla@linaro.org> References: <20201105113458.12360-1-srinivas.kandagatla@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This binding is for LPASS has internal codec WSA macro which is for connecting with WSA Smart speakers. Signed-off-by: Srinivas Kandagatla Reviewed-by: Rob Herring --- .../bindings/sound/qcom,lpass-wsa-macro.yaml | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml new file mode 100644 index 000000000000..435b019a1e3d --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/qcom,lpass-wsa-macro.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: LPASS(Low Power Audio Subsystem) VA Macro audio codec DT bindings + +maintainers: + - Srinivas Kandagatla + +properties: + compatible: + const: qcom,sm8250-lpass-wsa-macro + + reg: + maxItems: 1 + + "#sound-dai-cells": + const: 1 + + '#clock-cells': + const: 0 + + clocks: + maxItems: 5 + + clock-names: + items: + - const: mclk + - const: npl + - const: macro + - const: dcodec + - const: fsgen + + clock-output-names: + items: + - const: mclk + + qcom,dmic-sample-rate: + description: dmic sample rate + $ref: /schemas/types.yaml#/definitions/uint32 + + vdd-micb-supply: + description: phandle to voltage regulator of MIC Bias + +required: + - compatible + - reg + - "#sound-dai-cells" + +additionalProperties: false + +examples: + - | + #include + codec@3240000 { + compatible = "qcom,sm8250-lpass-wsa-macro"; + reg = <0x3240000 0x1000>; + #sound-dai-cells = <1>; + #clock-cells = <0>; + clocks = <&audiocc 1>, + <&audiocc 0>, + <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&vamacro>; + clock-names = "mclk", "npl", "macro", "dcodec", "fsgen"; + clock-output-names = "mclk"; + }; From patchwork Thu Nov 5 11:34:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 319546 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D144BC4741F for ; Thu, 5 Nov 2020 11:36:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4A7382078E for ; Thu, 5 Nov 2020 11:36:31 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="PHODK0Q0" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730427AbgKELg3 (ORCPT ); Thu, 5 Nov 2020 06:36:29 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45458 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730406AbgKELfG (ORCPT ); Thu, 5 Nov 2020 06:35:06 -0500 Received: from mail-wr1-x441.google.com (mail-wr1-x441.google.com [IPv6:2a00:1450:4864:20::441]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 32E69C0613CF for ; Thu, 5 Nov 2020 03:35:06 -0800 (PST) Received: by mail-wr1-x441.google.com with SMTP id b8so1368781wrn.0 for ; Thu, 05 Nov 2020 03:35:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ZA5VY/2cAg2+tS+2OV7yp/WkPaKlRcParMZGwefMMO8=; b=PHODK0Q00XqnpAFUYkuQhSQcEuCCU7DanbjSDnU+5JuKf3dPyIbsXQY+btt202XiVQ 8t8XcZvihf7LmPs2gPuHoaAVRosq1xujvYY6XQo9YmjLlttxo0vGWrJmyiNE2BfMPD3m Lc19YVjdA2Tv4EpSeWG3AJXHfRicpeF6Kt9DO1Z9twdy7oYJnDzgtT2vT4v1QswuByYn r090oM8ydYY72VeBDMktjhvhnI2jc6uwpAdVhOhWlPLp+A2YtrlzGHKGotcIPqu2+kgg DIl5a4jtID/JoHX9XPELvMJnacRGIrYYMGn0NeB/g34IOJcBNLbUrpnqlMLS07oMQjDv 86TA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ZA5VY/2cAg2+tS+2OV7yp/WkPaKlRcParMZGwefMMO8=; b=UTr1lyVNJ98Y9uGvfOOV4v7AAFheLHLCFc95j4/xqUJj9ZWgAtcoRI/L0x1bkvVnaJ EzO+ab2EM+k8mvYnmEFJ3hjSEpUqtdwTvxQF1L23ydQvyDFRVy/MUFacCLHnNO+GYwMX dsujrDfOcpQbVUVCkLYuQUdbs64Eaw4cHZsTcLEYgzvNyWiyfPGZZgjVytmNjJpSoWZL j2SjCubBgqKls+/s0+erw4+OdW+20ocDq27t+BZkSVQY6lVBKtyyFFagj/Y11mIUGuZZ 8fbpFIs23Ur3XvnH6W0qH0K9hhvuDbcZKirQRDkcNLAYaK6kqZS/+e6jeKRUz7AeXREL 2scA== X-Gm-Message-State: AOAM532vJgiABf5A24+L4qKTq3Kh23yehUKF9qatw8YUCEZ2m5LNGQ9w 1VNI/7xt7TwQCIUXEnF64D22cg== X-Google-Smtp-Source: ABdhPJxQdGM66rCmrvelUu0D80Smg/iyCBrkey4uUrDvfNTKBhaecq3ay1ey2GtKvXoQzn1twihhRA== X-Received: by 2002:adf:cd8d:: with SMTP id q13mr2379882wrj.268.1604576104685; Thu, 05 Nov 2020 03:35:04 -0800 (PST) Received: from srini-hackbox.lan (cpc86377-aztw32-2-0-cust226.18-1.cable.virginm.net. [92.233.226.227]) by smtp.gmail.com with ESMTPSA id t199sm2096129wmt.46.2020.11.05.03.35.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Nov 2020 03:35:03 -0800 (PST) From: Srinivas Kandagatla To: broonie@kernel.org Cc: perex@perex.cz, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org, lgirdwood@gmail.com, devicetree@vger.kernel.org, robh+dt@kernel.org, Srinivas Kandagatla Subject: [PATCH v3 2/6] ASoC: codecs: lpass-wsa-macro: Add support to WSA Macro Date: Thu, 5 Nov 2020 11:34:54 +0000 Message-Id: <20201105113458.12360-3-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20201105113458.12360-1-srinivas.kandagatla@linaro.org> References: <20201105113458.12360-1-srinivas.kandagatla@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Qualcomm LPASS (Low Power Audio SubSystem) has internal codec WSA macro block which is used for connecting with WSA Smart speakers over soundwire. This patch adds support to the codec part of the WSA Macro block. Signed-off-by: Srinivas Kandagatla --- sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/lpass-wsa-macro.c | 1383 ++++++++++++++++++++++++++++ sound/soc/codecs/lpass-wsa-macro.h | 17 + 4 files changed, 1406 insertions(+) create mode 100644 sound/soc/codecs/lpass-wsa-macro.c create mode 100644 sound/soc/codecs/lpass-wsa-macro.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 5791b7056af6..d91b51470a73 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -1784,4 +1784,8 @@ config SND_SOC_TPA6130A2 tristate "Texas Instruments TPA6130A2 headphone amplifier" depends on I2C +config SND_SOC_LPASS_WSA_MACRO + depends on COMMON_CLK + tristate "Qualcomm WSA Macro in LPASS(Low Power Audio SubSystem)" + endmenu diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 11ce98c25d6c..9f24b3daf5df 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -103,6 +103,7 @@ snd-soc-l3-objs := l3.o snd-soc-lm4857-objs := lm4857.o snd-soc-lm49453-objs := lm49453.o snd-soc-lochnagar-sc-objs := lochnagar-sc.o +snd-soc-lpass-wsa-macro-objs := lpass-wsa-macro.o snd-soc-madera-objs := madera.o snd-soc-max9759-objs := max9759.o snd-soc-max9768-objs := max9768.o @@ -613,3 +614,4 @@ obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o obj-$(CONFIG_SND_SOC_MAX98504) += snd-soc-max98504.o obj-$(CONFIG_SND_SOC_SIMPLE_AMPLIFIER) += snd-soc-simple-amplifier.o obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o +obj-$(CONFIG_SND_SOC_LPASS_WSA_MACRO) += snd-soc-lpass-wsa-macro.o diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c new file mode 100644 index 000000000000..76873d582eff --- /dev/null +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -0,0 +1,1383 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lpass-wsa-macro.h" + +#define CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL (0x0000) +#define CDC_WSA_MCLK_EN_MASK BIT(0) +#define CDC_WSA_MCLK_ENABLE BIT(0) +#define CDC_WSA_MCLK_DISABLE 0 +#define CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL (0x0004) +#define CDC_WSA_FS_CNT_EN_MASK BIT(0) +#define CDC_WSA_FS_CNT_ENABLE BIT(0) +#define CDC_WSA_FS_CNT_DISABLE 0 +#define CDC_WSA_CLK_RST_CTRL_SWR_CONTROL (0x0008) +#define CDC_WSA_SWR_CLK_EN_MASK BIT(0) +#define CDC_WSA_SWR_CLK_ENABLE BIT(0) +#define CDC_WSA_SWR_RST_EN_MASK BIT(1) +#define CDC_WSA_SWR_RST_ENABLE BIT(1) +#define CDC_WSA_SWR_RST_DISABLE 0 +#define CDC_WSA_TOP_TOP_CFG0 (0x0080) +#define CDC_WSA_TOP_TOP_CFG1 (0x0084) +#define CDC_WSA_TOP_FREQ_MCLK (0x0088) +#define CDC_WSA_TOP_DEBUG_BUS_SEL (0x008C) +#define CDC_WSA_TOP_DEBUG_EN0 (0x0090) +#define CDC_WSA_TOP_DEBUG_EN1 (0x0094) +#define CDC_WSA_TOP_DEBUG_DSM_LB (0x0098) +#define CDC_WSA_TOP_RX_I2S_CTL (0x009C) +#define CDC_WSA_TOP_TX_I2S_CTL (0x00A0) +#define CDC_WSA_TOP_I2S_CLK (0x00A4) +#define CDC_WSA_TOP_I2S_RESET (0x00A8) +#define CDC_WSA_RX_INP_MUX_RX_INT0_CFG0 (0x0100) +#define CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK GENMASK(5, 3) +#define CDC_WSA_RX_INTX_2_SEL_MASK GENMASK(2, 0) +#define CDC_WSA_RX_INP_MUX_RX_INT0_CFG1 (0x0104) +#define CDC_WSA_RX_INP_MUX_RX_INT1_CFG0 (0x0108) +#define CDC_WSA_RX_INP_MUX_RX_INT1_CFG1 (0x010C) +#define CDC_WSA_RX_INP_MUX_RX_MIX_CFG0 (0x0110) +#define CDC_WSA_RX_MIX_TX1_SEL_MASK GENMASK(5, 3) +#define CDC_WSA_RX_MIX_TX1_SEL_SHFT 3 +#define CDC_WSA_RX_MIX_TX0_SEL_MASK GENMASK(2, 0) +#define CDC_WSA_RX_INP_MUX_RX_EC_CFG0 (0x0114) +#define CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0 (0x0118) +#define CDC_WSA_TX0_SPKR_PROT_PATH_CTL (0x0244) +#define CDC_WSA_TX_SPKR_PROT_RESET_MASK BIT(5) +#define CDC_WSA_TX_SPKR_PROT_RESET BIT(5) +#define CDC_WSA_TX_SPKR_PROT_NO_RESET 0 +#define CDC_WSA_TX_SPKR_PROT_CLK_EN_MASK BIT(4) +#define CDC_WSA_TX_SPKR_PROT_CLK_ENABLE BIT(4) +#define CDC_WSA_TX_SPKR_PROT_CLK_DISABLE 0 +#define CDC_WSA_TX_SPKR_PROT_PCM_RATE_MASK GENMASK(3, 0) +#define CDC_WSA_TX_SPKR_PROT_PCM_RATE_8K 0 +#define CDC_WSA_TX0_SPKR_PROT_PATH_CFG0 (0x0248) +#define CDC_WSA_TX1_SPKR_PROT_PATH_CTL (0x0264) +#define CDC_WSA_TX1_SPKR_PROT_PATH_CFG0 (0x0268) +#define CDC_WSA_TX2_SPKR_PROT_PATH_CTL (0x0284) +#define CDC_WSA_TX2_SPKR_PROT_PATH_CFG0 (0x0288) +#define CDC_WSA_TX3_SPKR_PROT_PATH_CTL (0x02A4) +#define CDC_WSA_TX3_SPKR_PROT_PATH_CFG0 (0x02A8) +#define CDC_WSA_INTR_CTRL_CFG (0x0340) +#define CDC_WSA_INTR_CTRL_CLR_COMMIT (0x0344) +#define CDC_WSA_INTR_CTRL_PIN1_MASK0 (0x0360) +#define CDC_WSA_INTR_CTRL_PIN1_STATUS0 (0x0368) +#define CDC_WSA_INTR_CTRL_PIN1_CLEAR0 (0x0370) +#define CDC_WSA_INTR_CTRL_PIN2_MASK0 (0x0380) +#define CDC_WSA_INTR_CTRL_PIN2_STATUS0 (0x0388) +#define CDC_WSA_INTR_CTRL_PIN2_CLEAR0 (0x0390) +#define CDC_WSA_INTR_CTRL_LEVEL0 (0x03C0) +#define CDC_WSA_INTR_CTRL_BYPASS0 (0x03C8) +#define CDC_WSA_INTR_CTRL_SET0 (0x03D0) +#define CDC_WSA_RX0_RX_PATH_CTL (0x0400) +#define CDC_WSA_RX_PATH_CLK_EN_MASK BIT(5) +#define CDC_WSA_RX_PATH_CLK_ENABLE BIT(5) +#define CDC_WSA_RX_PATH_CLK_DISABLE 0 +#define CDC_WSA_RX_PATH_PGA_MUTE_EN_MASK BIT(4) +#define CDC_WSA_RX_PATH_PGA_MUTE_ENABLE BIT(4) +#define CDC_WSA_RX_PATH_PGA_MUTE_DISABLE 0 +#define CDC_WSA_RX0_RX_PATH_CFG0 (0x0404) +#define CDC_WSA_RX_PATH_COMP_EN_MASK BIT(1) +#define CDC_WSA_RX_PATH_COMP_ENABLE BIT(1) +#define CDC_WSA_RX_PATH_HD2_EN_MASK BIT(2) +#define CDC_WSA_RX_PATH_HD2_ENABLE BIT(2) +#define CDC_WSA_RX_PATH_SPKR_RATE_MASK BIT(3) +#define CDC_WSA_RX_PATH_SPKR_RATE_FS_2P4_3P072 BIT(3) +#define CDC_WSA_RX0_RX_PATH_CFG1 (0x0408) +#define CDC_WSA_RX_PATH_SMART_BST_EN_MASK BIT(0) +#define CDC_WSA_RX_PATH_SMART_BST_ENABLE BIT(0) +#define CDC_WSA_RX_PATH_SMART_BST_DISABLE 0 +#define CDC_WSA_RX0_RX_PATH_CFG2 (0x040C) +#define CDC_WSA_RX0_RX_PATH_CFG3 (0x0410) +#define CDC_WSA_RX_DC_DCOEFF_MASK GENMASK(1, 0) +#define CDC_WSA_RX0_RX_VOL_CTL (0x0414) +#define CDC_WSA_RX0_RX_PATH_MIX_CTL (0x0418) +#define CDC_WSA_RX_PATH_MIX_CLK_EN_MASK BIT(5) +#define CDC_WSA_RX_PATH_MIX_CLK_ENABLE BIT(5) +#define CDC_WSA_RX_PATH_MIX_CLK_DISABLE 0 +#define CDC_WSA_RX0_RX_PATH_MIX_CFG (0x041C) +#define CDC_WSA_RX0_RX_VOL_MIX_CTL (0x0420) +#define CDC_WSA_RX0_RX_PATH_SEC0 (0x0424) +#define CDC_WSA_RX0_RX_PATH_SEC1 (0x0428) +#define CDC_WSA_RX_PGA_HALF_DB_MASK BIT(0) +#define CDC_WSA_RX_PGA_HALF_DB_ENABLE BIT(0) +#define CDC_WSA_RX_PGA_HALF_DB_DISABLE 0 +#define CDC_WSA_RX0_RX_PATH_SEC2 (0x042C) +#define CDC_WSA_RX0_RX_PATH_SEC3 (0x0430) +#define CDC_WSA_RX_PATH_HD2_SCALE_MASK GENMASK(1, 0) +#define CDC_WSA_RX_PATH_HD2_ALPHA_MASK GENMASK(5, 2) +#define CDC_WSA_RX0_RX_PATH_SEC5 (0x0438) +#define CDC_WSA_RX0_RX_PATH_SEC6 (0x043C) +#define CDC_WSA_RX0_RX_PATH_SEC7 (0x0440) +#define CDC_WSA_RX0_RX_PATH_MIX_SEC0 (0x0444) +#define CDC_WSA_RX0_RX_PATH_MIX_SEC1 (0x0448) +#define CDC_WSA_RX0_RX_PATH_DSMDEM_CTL (0x044C) +#define CDC_WSA_RX_DSMDEM_CLK_EN_MASK BIT(0) +#define CDC_WSA_RX_DSMDEM_CLK_ENABLE BIT(0) +#define CDC_WSA_RX1_RX_PATH_CTL (0x0480) +#define CDC_WSA_RX1_RX_PATH_CFG0 (0x0484) +#define CDC_WSA_RX1_RX_PATH_CFG1 (0x0488) +#define CDC_WSA_RX1_RX_PATH_CFG2 (0x048C) +#define CDC_WSA_RX1_RX_PATH_CFG3 (0x0490) +#define CDC_WSA_RX1_RX_VOL_CTL (0x0494) +#define CDC_WSA_RX1_RX_PATH_MIX_CTL (0x0498) +#define CDC_WSA_RX1_RX_PATH_MIX_CFG (0x049C) +#define CDC_WSA_RX1_RX_VOL_MIX_CTL (0x04A0) +#define CDC_WSA_RX1_RX_PATH_SEC0 (0x04A4) +#define CDC_WSA_RX1_RX_PATH_SEC1 (0x04A8) +#define CDC_WSA_RX1_RX_PATH_SEC2 (0x04AC) +#define CDC_WSA_RX1_RX_PATH_SEC3 (0x04B0) +#define CDC_WSA_RX1_RX_PATH_SEC5 (0x04B8) +#define CDC_WSA_RX1_RX_PATH_SEC6 (0x04BC) +#define CDC_WSA_RX1_RX_PATH_SEC7 (0x04C0) +#define CDC_WSA_RX1_RX_PATH_MIX_SEC0 (0x04C4) +#define CDC_WSA_RX1_RX_PATH_MIX_SEC1 (0x04C8) +#define CDC_WSA_RX1_RX_PATH_DSMDEM_CTL (0x04CC) +#define CDC_WSA_BOOST0_BOOST_PATH_CTL (0x0500) +#define CDC_WSA_BOOST_PATH_CLK_EN_MASK BIT(4) +#define CDC_WSA_BOOST_PATH_CLK_ENABLE BIT(4) +#define CDC_WSA_BOOST_PATH_CLK_DISABLE 0 +#define CDC_WSA_BOOST0_BOOST_CTL (0x0504) +#define CDC_WSA_BOOST0_BOOST_CFG1 (0x0508) +#define CDC_WSA_BOOST0_BOOST_CFG2 (0x050C) +#define CDC_WSA_BOOST1_BOOST_PATH_CTL (0x0540) +#define CDC_WSA_BOOST1_BOOST_CTL (0x0544) +#define CDC_WSA_BOOST1_BOOST_CFG1 (0x0548) +#define CDC_WSA_BOOST1_BOOST_CFG2 (0x054C) +#define CDC_WSA_COMPANDER0_CTL0 (0x0580) +#define CDC_WSA_COMPANDER_CLK_EN_MASK BIT(0) +#define CDC_WSA_COMPANDER_CLK_ENABLE BIT(0) +#define CDC_WSA_COMPANDER_SOFT_RST_MASK BIT(1) +#define CDC_WSA_COMPANDER_SOFT_RST_ENABLE BIT(1) +#define CDC_WSA_COMPANDER_HALT_MASK BIT(2) +#define CDC_WSA_COMPANDER_HALT BIT(2) +#define CDC_WSA_COMPANDER0_CTL1 (0x0584) +#define CDC_WSA_COMPANDER0_CTL2 (0x0588) +#define CDC_WSA_COMPANDER0_CTL3 (0x058C) +#define CDC_WSA_COMPANDER0_CTL4 (0x0590) +#define CDC_WSA_COMPANDER0_CTL5 (0x0594) +#define CDC_WSA_COMPANDER0_CTL6 (0x0598) +#define CDC_WSA_COMPANDER0_CTL7 (0x059C) +#define CDC_WSA_COMPANDER1_CTL0 (0x05C0) +#define CDC_WSA_COMPANDER1_CTL1 (0x05C4) +#define CDC_WSA_COMPANDER1_CTL2 (0x05C8) +#define CDC_WSA_COMPANDER1_CTL3 (0x05CC) +#define CDC_WSA_COMPANDER1_CTL4 (0x05D0) +#define CDC_WSA_COMPANDER1_CTL5 (0x05D4) +#define CDC_WSA_COMPANDER1_CTL6 (0x05D8) +#define CDC_WSA_COMPANDER1_CTL7 (0x05DC) +#define CDC_WSA_SOFTCLIP0_CRC (0x0600) +#define CDC_WSA_SOFTCLIP_CLK_EN_MASK BIT(0) +#define CDC_WSA_SOFTCLIP_CLK_ENABLE BIT(0) +#define CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL (0x0604) +#define CDC_WSA_SOFTCLIP_EN_MASK BIT(0) +#define CDC_WSA_SOFTCLIP_ENABLE BIT(0) +#define CDC_WSA_SOFTCLIP1_CRC (0x0640) +#define CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL (0x0644) +#define CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL (0x0680) +#define CDC_WSA_EC_HQ_EC_CLK_EN_MASK BIT(0) +#define CDC_WSA_EC_HQ_EC_CLK_ENABLE BIT(0) +#define CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0 (0x0684) +#define CDC_WSA_EC_HQ_EC_REF_PCM_RATE_MASK GENMASK(4, 1) +#define CDC_WSA_EC_HQ_EC_REF_PCM_RATE_48K BIT(3) +#define CDC_WSA_EC_HQ1_EC_REF_HQ_PATH_CTL (0x06C0) +#define CDC_WSA_EC_HQ1_EC_REF_HQ_CFG0 (0x06C4) +#define CDC_WSA_SPLINE_ASRC0_CLK_RST_CTL (0x0700) +#define CDC_WSA_SPLINE_ASRC0_CTL0 (0x0704) +#define CDC_WSA_SPLINE_ASRC0_CTL1 (0x0708) +#define CDC_WSA_SPLINE_ASRC0_FIFO_CTL (0x070C) +#define CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_LSB (0x0710) +#define CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_MSB (0x0714) +#define CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_LSB (0x0718) +#define CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_MSB (0x071C) +#define CDC_WSA_SPLINE_ASRC0_STATUS_FIFO (0x0720) +#define CDC_WSA_SPLINE_ASRC1_CLK_RST_CTL (0x0740) +#define CDC_WSA_SPLINE_ASRC1_CTL0 (0x0744) +#define CDC_WSA_SPLINE_ASRC1_CTL1 (0x0748) +#define CDC_WSA_SPLINE_ASRC1_FIFO_CTL (0x074C) +#define CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_LSB (0x0750) +#define CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_MSB (0x0754) +#define CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_LSB (0x0758) +#define CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_MSB (0x075C) +#define CDC_WSA_SPLINE_ASRC1_STATUS_FIFO (0x0760) +#define WSA_MAX_OFFSET (0x0760) + +#define WSA_MACRO_RX_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) +#define WSA_MACRO_RX_MIX_RATES (SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) +#define WSA_MACRO_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) + +#define WSA_MACRO_ECHO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_48000) +#define WSA_MACRO_ECHO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S24_3LE) + +#define NUM_INTERPOLATORS 2 +#define WSA_NUM_CLKS_MAX 5 +#define WSA_MACRO_MCLK_FREQ 19200000 +#define WSA_MACRO_MUX_INP_SHFT 0x3 +#define WSA_MACRO_MUX_INP_MASK1 0x07 +#define WSA_MACRO_MUX_INP_MASK2 0x38 +#define WSA_MACRO_MUX_CFG_OFFSET 0x8 +#define WSA_MACRO_MUX_CFG1_OFFSET 0x4 +#define WSA_MACRO_RX_COMP_OFFSET 0x40 +#define WSA_MACRO_RX_SOFTCLIP_OFFSET 0x40 +#define WSA_MACRO_RX_PATH_OFFSET 0x80 +#define WSA_MACRO_RX_PATH_CFG3_OFFSET 0x10 +#define WSA_MACRO_RX_PATH_DSMDEM_OFFSET 0x4C +#define WSA_MACRO_FS_RATE_MASK 0x0F +#define WSA_MACRO_EC_MIX_TX0_MASK 0x03 +#define WSA_MACRO_EC_MIX_TX1_MASK 0x18 +#define WSA_MACRO_MAX_DMA_CH_PER_PORT 0x2 + +enum { + WSA_MACRO_GAIN_OFFSET_M1P5_DB, + WSA_MACRO_GAIN_OFFSET_0_DB, +}; +enum { + WSA_MACRO_RX0 = 0, + WSA_MACRO_RX1, + WSA_MACRO_RX_MIX, + WSA_MACRO_RX_MIX0 = WSA_MACRO_RX_MIX, + WSA_MACRO_RX_MIX1, + WSA_MACRO_RX_MAX, +}; + +enum { + WSA_MACRO_TX0 = 0, + WSA_MACRO_TX1, + WSA_MACRO_TX_MAX, +}; + +enum { + WSA_MACRO_EC0_MUX = 0, + WSA_MACRO_EC1_MUX, + WSA_MACRO_EC_MUX_MAX, +}; + +enum { + WSA_MACRO_COMP1, /* SPK_L */ + WSA_MACRO_COMP2, /* SPK_R */ + WSA_MACRO_COMP_MAX +}; + +enum { + WSA_MACRO_SOFTCLIP0, /* RX0 */ + WSA_MACRO_SOFTCLIP1, /* RX1 */ + WSA_MACRO_SOFTCLIP_MAX +}; + +enum { + INTn_1_INP_SEL_ZERO = 0, + INTn_1_INP_SEL_RX0, + INTn_1_INP_SEL_RX1, + INTn_1_INP_SEL_RX2, + INTn_1_INP_SEL_RX3, + INTn_1_INP_SEL_DEC0, + INTn_1_INP_SEL_DEC1, +}; + +enum { + INTn_2_INP_SEL_ZERO = 0, + INTn_2_INP_SEL_RX0, + INTn_2_INP_SEL_RX1, + INTn_2_INP_SEL_RX2, + INTn_2_INP_SEL_RX3, +}; + +struct interp_sample_rate { + int sample_rate; + int rate_val; +}; + +static struct interp_sample_rate int_prim_sample_rate_val[] = { + {8000, 0x0}, /* 8K */ + {16000, 0x1}, /* 16K */ + {24000, -EINVAL},/* 24K */ + {32000, 0x3}, /* 32K */ + {48000, 0x4}, /* 48K */ + {96000, 0x5}, /* 96K */ + {192000, 0x6}, /* 192K */ + {384000, 0x7}, /* 384K */ + {44100, 0x8}, /* 44.1K */ +}; + +static struct interp_sample_rate int_mix_sample_rate_val[] = { + {48000, 0x4}, /* 48K */ + {96000, 0x5}, /* 96K */ + {192000, 0x6}, /* 192K */ +}; + +enum { + WSA_MACRO_AIF_INVALID = 0, + WSA_MACRO_AIF1_PB, + WSA_MACRO_AIF_MIX1_PB, + WSA_MACRO_AIF_VI, + WSA_MACRO_AIF_ECHO, + WSA_MACRO_MAX_DAIS, +}; + +struct wsa_macro { + struct device *dev; + int comp_enabled[WSA_MACRO_COMP_MAX]; + int ec_hq[WSA_MACRO_RX1 + 1]; + u16 prim_int_users[WSA_MACRO_RX1 + 1]; + u16 wsa_mclk_users; + bool reset_swr; + unsigned long active_ch_mask[WSA_MACRO_MAX_DAIS]; + unsigned long active_ch_cnt[WSA_MACRO_MAX_DAIS]; + int rx_port_value[WSA_MACRO_RX_MAX]; + int ear_spkr_gain; + int spkr_gain_offset; + int spkr_mode; + int is_softclip_on[WSA_MACRO_SOFTCLIP_MAX]; + int softclip_clk_users[WSA_MACRO_SOFTCLIP_MAX]; + struct regmap *regmap; + struct clk_bulk_data clks[WSA_NUM_CLKS_MAX]; + struct clk_hw hw; +}; +#define to_wsa_macro(_hw) container_of(_hw, struct wsa_macro, hw) + +static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400); + +static const char * const wsa_macro_ear_spkr_pa_gain_text[] = { + "G_DEFAULT", "G_0_DB", "G_1_DB", "G_2_DB", "G_3_DB", + "G_4_DB", "G_5_DB", "G_6_DB" +}; + +static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_ear_spkr_pa_gain_enum, + wsa_macro_ear_spkr_pa_gain_text); + +static const struct reg_default wsa_defaults[] = { + /* WSA Macro */ + { CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL, 0x00}, + { CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00}, + { CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, 0x00}, + { CDC_WSA_TOP_TOP_CFG0, 0x00}, + { CDC_WSA_TOP_TOP_CFG1, 0x00}, + { CDC_WSA_TOP_FREQ_MCLK, 0x00}, + { CDC_WSA_TOP_DEBUG_BUS_SEL, 0x00}, + { CDC_WSA_TOP_DEBUG_EN0, 0x00}, + { CDC_WSA_TOP_DEBUG_EN1, 0x00}, + { CDC_WSA_TOP_DEBUG_DSM_LB, 0x88}, + { CDC_WSA_TOP_RX_I2S_CTL, 0x0C}, + { CDC_WSA_TOP_TX_I2S_CTL, 0x0C}, + { CDC_WSA_TOP_I2S_CLK, 0x02}, + { CDC_WSA_TOP_I2S_RESET, 0x00}, + { CDC_WSA_RX_INP_MUX_RX_INT0_CFG0, 0x00}, + { CDC_WSA_RX_INP_MUX_RX_INT0_CFG1, 0x00}, + { CDC_WSA_RX_INP_MUX_RX_INT1_CFG0, 0x00}, + { CDC_WSA_RX_INP_MUX_RX_INT1_CFG1, 0x00}, + { CDC_WSA_RX_INP_MUX_RX_MIX_CFG0, 0x00}, + { CDC_WSA_RX_INP_MUX_RX_EC_CFG0, 0x00}, + { CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0, 0x00}, + { CDC_WSA_TX0_SPKR_PROT_PATH_CTL, 0x02}, + { CDC_WSA_TX0_SPKR_PROT_PATH_CFG0, 0x00}, + { CDC_WSA_TX1_SPKR_PROT_PATH_CTL, 0x02}, + { CDC_WSA_TX1_SPKR_PROT_PATH_CFG0, 0x00}, + { CDC_WSA_TX2_SPKR_PROT_PATH_CTL, 0x02}, + { CDC_WSA_TX2_SPKR_PROT_PATH_CFG0, 0x00}, + { CDC_WSA_TX3_SPKR_PROT_PATH_CTL, 0x02}, + { CDC_WSA_TX3_SPKR_PROT_PATH_CFG0, 0x00}, + { CDC_WSA_INTR_CTRL_CFG, 0x00}, + { CDC_WSA_INTR_CTRL_CLR_COMMIT, 0x00}, + { CDC_WSA_INTR_CTRL_PIN1_MASK0, 0xFF}, + { CDC_WSA_INTR_CTRL_PIN1_STATUS0, 0x00}, + { CDC_WSA_INTR_CTRL_PIN1_CLEAR0, 0x00}, + { CDC_WSA_INTR_CTRL_PIN2_MASK0, 0xFF}, + { CDC_WSA_INTR_CTRL_PIN2_STATUS0, 0x00}, + { CDC_WSA_INTR_CTRL_PIN2_CLEAR0, 0x00}, + { CDC_WSA_INTR_CTRL_LEVEL0, 0x00}, + { CDC_WSA_INTR_CTRL_BYPASS0, 0x00}, + { CDC_WSA_INTR_CTRL_SET0, 0x00}, + { CDC_WSA_RX0_RX_PATH_CTL, 0x04}, + { CDC_WSA_RX0_RX_PATH_CFG0, 0x00}, + { CDC_WSA_RX0_RX_PATH_CFG1, 0x64}, + { CDC_WSA_RX0_RX_PATH_CFG2, 0x8F}, + { CDC_WSA_RX0_RX_PATH_CFG3, 0x00}, + { CDC_WSA_RX0_RX_VOL_CTL, 0x00}, + { CDC_WSA_RX0_RX_PATH_MIX_CTL, 0x04}, + { CDC_WSA_RX0_RX_PATH_MIX_CFG, 0x7E}, + { CDC_WSA_RX0_RX_VOL_MIX_CTL, 0x00}, + { CDC_WSA_RX0_RX_PATH_SEC0, 0x04}, + { CDC_WSA_RX0_RX_PATH_SEC1, 0x08}, + { CDC_WSA_RX0_RX_PATH_SEC2, 0x00}, + { CDC_WSA_RX0_RX_PATH_SEC3, 0x00}, + { CDC_WSA_RX0_RX_PATH_SEC5, 0x00}, + { CDC_WSA_RX0_RX_PATH_SEC6, 0x00}, + { CDC_WSA_RX0_RX_PATH_SEC7, 0x00}, + { CDC_WSA_RX0_RX_PATH_MIX_SEC0, 0x08}, + { CDC_WSA_RX0_RX_PATH_MIX_SEC1, 0x00}, + { CDC_WSA_RX0_RX_PATH_DSMDEM_CTL, 0x00}, + { CDC_WSA_RX1_RX_PATH_CFG0, 0x00}, + { CDC_WSA_RX1_RX_PATH_CFG1, 0x64}, + { CDC_WSA_RX1_RX_PATH_CFG2, 0x8F}, + { CDC_WSA_RX1_RX_PATH_CFG3, 0x00}, + { CDC_WSA_RX1_RX_VOL_CTL, 0x00}, + { CDC_WSA_RX1_RX_PATH_MIX_CTL, 0x04}, + { CDC_WSA_RX1_RX_PATH_MIX_CFG, 0x7E}, + { CDC_WSA_RX1_RX_VOL_MIX_CTL, 0x00}, + { CDC_WSA_RX1_RX_PATH_SEC0, 0x04}, + { CDC_WSA_RX1_RX_PATH_SEC1, 0x08}, + { CDC_WSA_RX1_RX_PATH_SEC2, 0x00}, + { CDC_WSA_RX1_RX_PATH_SEC3, 0x00}, + { CDC_WSA_RX1_RX_PATH_SEC5, 0x00}, + { CDC_WSA_RX1_RX_PATH_SEC6, 0x00}, + { CDC_WSA_RX1_RX_PATH_SEC7, 0x00}, + { CDC_WSA_RX1_RX_PATH_MIX_SEC0, 0x08}, + { CDC_WSA_RX1_RX_PATH_MIX_SEC1, 0x00}, + { CDC_WSA_RX1_RX_PATH_DSMDEM_CTL, 0x00}, + { CDC_WSA_BOOST0_BOOST_PATH_CTL, 0x00}, + { CDC_WSA_BOOST0_BOOST_CTL, 0xD0}, + { CDC_WSA_BOOST0_BOOST_CFG1, 0x89}, + { CDC_WSA_BOOST0_BOOST_CFG2, 0x04}, + { CDC_WSA_BOOST1_BOOST_PATH_CTL, 0x00}, + { CDC_WSA_BOOST1_BOOST_CTL, 0xD0}, + { CDC_WSA_BOOST1_BOOST_CFG1, 0x89}, + { CDC_WSA_BOOST1_BOOST_CFG2, 0x04}, + { CDC_WSA_COMPANDER0_CTL0, 0x60}, + { CDC_WSA_COMPANDER0_CTL1, 0xDB}, + { CDC_WSA_COMPANDER0_CTL2, 0xFF}, + { CDC_WSA_COMPANDER0_CTL3, 0x35}, + { CDC_WSA_COMPANDER0_CTL4, 0xFF}, + { CDC_WSA_COMPANDER0_CTL5, 0x00}, + { CDC_WSA_COMPANDER0_CTL6, 0x01}, + { CDC_WSA_COMPANDER0_CTL7, 0x28}, + { CDC_WSA_COMPANDER1_CTL0, 0x60}, + { CDC_WSA_COMPANDER1_CTL1, 0xDB}, + { CDC_WSA_COMPANDER1_CTL2, 0xFF}, + { CDC_WSA_COMPANDER1_CTL3, 0x35}, + { CDC_WSA_COMPANDER1_CTL4, 0xFF}, + { CDC_WSA_COMPANDER1_CTL5, 0x00}, + { CDC_WSA_COMPANDER1_CTL6, 0x01}, + { CDC_WSA_COMPANDER1_CTL7, 0x28}, + { CDC_WSA_SOFTCLIP0_CRC, 0x00}, + { CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL, 0x38}, + { CDC_WSA_SOFTCLIP1_CRC, 0x00}, + { CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL, 0x38}, + { CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL, 0x00}, + { CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0, 0x01}, + { CDC_WSA_EC_HQ1_EC_REF_HQ_PATH_CTL, 0x00}, + { CDC_WSA_EC_HQ1_EC_REF_HQ_CFG0, 0x01}, + { CDC_WSA_SPLINE_ASRC0_CLK_RST_CTL, 0x00}, + { CDC_WSA_SPLINE_ASRC0_CTL0, 0x00}, + { CDC_WSA_SPLINE_ASRC0_CTL1, 0x00}, + { CDC_WSA_SPLINE_ASRC0_FIFO_CTL, 0xA8}, + { CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_LSB, 0x00}, + { CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_MSB, 0x00}, + { CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_LSB, 0x00}, + { CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_MSB, 0x00}, + { CDC_WSA_SPLINE_ASRC0_STATUS_FIFO, 0x00}, + { CDC_WSA_SPLINE_ASRC1_CLK_RST_CTL, 0x00}, + { CDC_WSA_SPLINE_ASRC1_CTL0, 0x00}, + { CDC_WSA_SPLINE_ASRC1_CTL1, 0x00}, + { CDC_WSA_SPLINE_ASRC1_FIFO_CTL, 0xA8}, + { CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_LSB, 0x00}, + { CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_MSB, 0x00}, + { CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_LSB, 0x00}, + { CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_MSB, 0x00}, + { CDC_WSA_SPLINE_ASRC1_STATUS_FIFO, 0x00}, +}; + +static bool wsa_is_wronly_register(struct device *dev, + unsigned int reg) +{ + switch (reg) { + case CDC_WSA_INTR_CTRL_CLR_COMMIT: + case CDC_WSA_INTR_CTRL_PIN1_CLEAR0: + case CDC_WSA_INTR_CTRL_PIN2_CLEAR0: + return true; + } + + return false; +} + +static bool wsa_is_rw_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL: + case CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL: + case CDC_WSA_CLK_RST_CTRL_SWR_CONTROL: + case CDC_WSA_TOP_TOP_CFG0: + case CDC_WSA_TOP_TOP_CFG1: + case CDC_WSA_TOP_FREQ_MCLK: + case CDC_WSA_TOP_DEBUG_BUS_SEL: + case CDC_WSA_TOP_DEBUG_EN0: + case CDC_WSA_TOP_DEBUG_EN1: + case CDC_WSA_TOP_DEBUG_DSM_LB: + case CDC_WSA_TOP_RX_I2S_CTL: + case CDC_WSA_TOP_TX_I2S_CTL: + case CDC_WSA_TOP_I2S_CLK: + case CDC_WSA_TOP_I2S_RESET: + case CDC_WSA_RX_INP_MUX_RX_INT0_CFG0: + case CDC_WSA_RX_INP_MUX_RX_INT0_CFG1: + case CDC_WSA_RX_INP_MUX_RX_INT1_CFG0: + case CDC_WSA_RX_INP_MUX_RX_INT1_CFG1: + case CDC_WSA_RX_INP_MUX_RX_MIX_CFG0: + case CDC_WSA_RX_INP_MUX_RX_EC_CFG0: + case CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0: + case CDC_WSA_TX0_SPKR_PROT_PATH_CTL: + case CDC_WSA_TX0_SPKR_PROT_PATH_CFG0: + case CDC_WSA_TX1_SPKR_PROT_PATH_CTL: + case CDC_WSA_TX1_SPKR_PROT_PATH_CFG0: + case CDC_WSA_TX2_SPKR_PROT_PATH_CTL: + case CDC_WSA_TX2_SPKR_PROT_PATH_CFG0: + case CDC_WSA_TX3_SPKR_PROT_PATH_CTL: + case CDC_WSA_TX3_SPKR_PROT_PATH_CFG0: + case CDC_WSA_INTR_CTRL_CFG: + case CDC_WSA_INTR_CTRL_PIN1_MASK0: + case CDC_WSA_INTR_CTRL_PIN2_MASK0: + case CDC_WSA_INTR_CTRL_LEVEL0: + case CDC_WSA_INTR_CTRL_BYPASS0: + case CDC_WSA_INTR_CTRL_SET0: + case CDC_WSA_RX0_RX_PATH_CTL: + case CDC_WSA_RX0_RX_PATH_CFG0: + case CDC_WSA_RX0_RX_PATH_CFG1: + case CDC_WSA_RX0_RX_PATH_CFG2: + case CDC_WSA_RX0_RX_PATH_CFG3: + case CDC_WSA_RX0_RX_VOL_CTL: + case CDC_WSA_RX0_RX_PATH_MIX_CTL: + case CDC_WSA_RX0_RX_PATH_MIX_CFG: + case CDC_WSA_RX0_RX_VOL_MIX_CTL: + case CDC_WSA_RX0_RX_PATH_SEC0: + case CDC_WSA_RX0_RX_PATH_SEC1: + case CDC_WSA_RX0_RX_PATH_SEC2: + case CDC_WSA_RX0_RX_PATH_SEC3: + case CDC_WSA_RX0_RX_PATH_SEC5: + case CDC_WSA_RX0_RX_PATH_SEC6: + case CDC_WSA_RX0_RX_PATH_SEC7: + case CDC_WSA_RX0_RX_PATH_MIX_SEC0: + case CDC_WSA_RX0_RX_PATH_MIX_SEC1: + case CDC_WSA_RX0_RX_PATH_DSMDEM_CTL: + case CDC_WSA_RX1_RX_PATH_CTL: + case CDC_WSA_RX1_RX_PATH_CFG0: + case CDC_WSA_RX1_RX_PATH_CFG1: + case CDC_WSA_RX1_RX_PATH_CFG2: + case CDC_WSA_RX1_RX_PATH_CFG3: + case CDC_WSA_RX1_RX_VOL_CTL: + case CDC_WSA_RX1_RX_PATH_MIX_CTL: + case CDC_WSA_RX1_RX_PATH_MIX_CFG: + case CDC_WSA_RX1_RX_VOL_MIX_CTL: + case CDC_WSA_RX1_RX_PATH_SEC0: + case CDC_WSA_RX1_RX_PATH_SEC1: + case CDC_WSA_RX1_RX_PATH_SEC2: + case CDC_WSA_RX1_RX_PATH_SEC3: + case CDC_WSA_RX1_RX_PATH_SEC5: + case CDC_WSA_RX1_RX_PATH_SEC6: + case CDC_WSA_RX1_RX_PATH_SEC7: + case CDC_WSA_RX1_RX_PATH_MIX_SEC0: + case CDC_WSA_RX1_RX_PATH_MIX_SEC1: + case CDC_WSA_RX1_RX_PATH_DSMDEM_CTL: + case CDC_WSA_BOOST0_BOOST_PATH_CTL: + case CDC_WSA_BOOST0_BOOST_CTL: + case CDC_WSA_BOOST0_BOOST_CFG1: + case CDC_WSA_BOOST0_BOOST_CFG2: + case CDC_WSA_BOOST1_BOOST_PATH_CTL: + case CDC_WSA_BOOST1_BOOST_CTL: + case CDC_WSA_BOOST1_BOOST_CFG1: + case CDC_WSA_BOOST1_BOOST_CFG2: + case CDC_WSA_COMPANDER0_CTL0: + case CDC_WSA_COMPANDER0_CTL1: + case CDC_WSA_COMPANDER0_CTL2: + case CDC_WSA_COMPANDER0_CTL3: + case CDC_WSA_COMPANDER0_CTL4: + case CDC_WSA_COMPANDER0_CTL5: + case CDC_WSA_COMPANDER0_CTL7: + case CDC_WSA_COMPANDER1_CTL0: + case CDC_WSA_COMPANDER1_CTL1: + case CDC_WSA_COMPANDER1_CTL2: + case CDC_WSA_COMPANDER1_CTL3: + case CDC_WSA_COMPANDER1_CTL4: + case CDC_WSA_COMPANDER1_CTL5: + case CDC_WSA_COMPANDER1_CTL7: + case CDC_WSA_SOFTCLIP0_CRC: + case CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL: + case CDC_WSA_SOFTCLIP1_CRC: + case CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL: + case CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL: + case CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0: + case CDC_WSA_EC_HQ1_EC_REF_HQ_PATH_CTL: + case CDC_WSA_EC_HQ1_EC_REF_HQ_CFG0: + case CDC_WSA_SPLINE_ASRC0_CLK_RST_CTL: + case CDC_WSA_SPLINE_ASRC0_CTL0: + case CDC_WSA_SPLINE_ASRC0_CTL1: + case CDC_WSA_SPLINE_ASRC0_FIFO_CTL: + case CDC_WSA_SPLINE_ASRC1_CLK_RST_CTL: + case CDC_WSA_SPLINE_ASRC1_CTL0: + case CDC_WSA_SPLINE_ASRC1_CTL1: + case CDC_WSA_SPLINE_ASRC1_FIFO_CTL: + return true; + } + + return false; +} + +static bool wsa_is_writeable_register(struct device *dev, unsigned int reg) +{ + bool ret; + + ret = wsa_is_rw_register(dev, reg); + if (!ret) + return wsa_is_wronly_register(dev, reg); + + return ret; +} + +static bool wsa_is_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CDC_WSA_INTR_CTRL_CLR_COMMIT: + case CDC_WSA_INTR_CTRL_PIN1_CLEAR0: + case CDC_WSA_INTR_CTRL_PIN2_CLEAR0: + case CDC_WSA_INTR_CTRL_PIN1_STATUS0: + case CDC_WSA_INTR_CTRL_PIN2_STATUS0: + case CDC_WSA_COMPANDER0_CTL6: + case CDC_WSA_COMPANDER1_CTL6: + case CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_LSB: + case CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_MSB: + case CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_LSB: + case CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_MSB: + case CDC_WSA_SPLINE_ASRC0_STATUS_FIFO: + case CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_LSB: + case CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_MSB: + case CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_LSB: + case CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_MSB: + case CDC_WSA_SPLINE_ASRC1_STATUS_FIFO: + return true; + } + + return wsa_is_rw_register(dev, reg); +} + +static bool wsa_is_volatile_register(struct device *dev, unsigned int reg) +{ + /* Update volatile list for rx/tx macros */ + switch (reg) { + case CDC_WSA_INTR_CTRL_PIN1_STATUS0: + case CDC_WSA_INTR_CTRL_PIN2_STATUS0: + case CDC_WSA_COMPANDER0_CTL6: + case CDC_WSA_COMPANDER1_CTL6: + case CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_LSB: + case CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_MSB: + case CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_LSB: + case CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_MSB: + case CDC_WSA_SPLINE_ASRC0_STATUS_FIFO: + case CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_LSB: + case CDC_WSA_SPLINE_ASRC1_STATUS_FMIN_CNTR_MSB: + case CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_LSB: + case CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_MSB: + case CDC_WSA_SPLINE_ASRC1_STATUS_FIFO: + return true; + } + return false; +} + +static const struct regmap_config wsa_regmap_config = { + .name = "wsa_macro", + .reg_bits = 16, + .val_bits = 32, /* 8 but with 32 bit read/write */ + .reg_stride = 4, + .cache_type = REGCACHE_FLAT, + .reg_defaults = wsa_defaults, + .num_reg_defaults = ARRAY_SIZE(wsa_defaults), + .max_register = WSA_MAX_OFFSET, + .writeable_reg = wsa_is_writeable_register, + .volatile_reg = wsa_is_volatile_register, + .readable_reg = wsa_is_readable_register, +}; + +/** + * wsa_macro_set_spkr_mode - Configures speaker compander and smartboost + * settings based on speaker mode. + * + * @component: codec instance + * @mode: Indicates speaker configuration mode. + * + * Returns 0 on success or -EINVAL on error. + */ +int wsa_macro_set_spkr_mode(struct snd_soc_component *component, int mode) +{ + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + + wsa->spkr_mode = mode; + + switch (mode) { + case WSA_MACRO_SPKR_MODE_1: + snd_soc_component_update_bits(component, CDC_WSA_COMPANDER0_CTL3, 0x80, 0x00); + snd_soc_component_update_bits(component, CDC_WSA_COMPANDER1_CTL3, 0x80, 0x00); + snd_soc_component_update_bits(component, CDC_WSA_COMPANDER0_CTL7, 0x01, 0x00); + snd_soc_component_update_bits(component, CDC_WSA_COMPANDER1_CTL7, 0x01, 0x00); + snd_soc_component_update_bits(component, CDC_WSA_BOOST0_BOOST_CTL, 0x7C, 0x44); + snd_soc_component_update_bits(component, CDC_WSA_BOOST1_BOOST_CTL, 0x7C, 0x44); + break; + default: + snd_soc_component_update_bits(component, CDC_WSA_COMPANDER0_CTL3, 0x80, 0x80); + snd_soc_component_update_bits(component, CDC_WSA_COMPANDER1_CTL3, 0x80, 0x80); + snd_soc_component_update_bits(component, CDC_WSA_COMPANDER0_CTL7, 0x01, 0x01); + snd_soc_component_update_bits(component, CDC_WSA_COMPANDER1_CTL7, 0x01, 0x01); + snd_soc_component_update_bits(component, CDC_WSA_BOOST0_BOOST_CTL, 0x7C, 0x58); + snd_soc_component_update_bits(component, CDC_WSA_BOOST1_BOOST_CTL, 0x7C, 0x58); + break; + } + return 0; +} +EXPORT_SYMBOL(wsa_macro_set_spkr_mode); + +static int wsa_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai, + u8 int_prim_fs_rate_reg_val, + u32 sample_rate) +{ + u8 int_1_mix1_inp; + u32 j, port; + u16 int_mux_cfg0, int_mux_cfg1; + u16 int_fs_reg; + u8 int_mux_cfg0_val, int_mux_cfg1_val; + u8 inp0_sel, inp1_sel, inp2_sel; + struct snd_soc_component *component = dai->component; + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + + for_each_set_bit(port, &wsa->active_ch_mask[dai->id], WSA_MACRO_RX_MAX) { + int_1_mix1_inp = port; + if ((int_1_mix1_inp < WSA_MACRO_RX0) || (int_1_mix1_inp > WSA_MACRO_RX_MIX1)) { + dev_err(component->dev, "%s: Invalid RX port, Dai ID is %d\n", + __func__, dai->id); + return -EINVAL; + } + + int_mux_cfg0 = CDC_WSA_RX_INP_MUX_RX_INT0_CFG0; + + /* + * Loop through all interpolator MUX inputs and find out + * to which interpolator input, the cdc_dma rx port + * is connected + */ + for (j = 0; j < NUM_INTERPOLATORS; j++) { + int_mux_cfg1 = int_mux_cfg0 + WSA_MACRO_MUX_CFG1_OFFSET; + int_mux_cfg0_val = snd_soc_component_read(component, + int_mux_cfg0); + int_mux_cfg1_val = snd_soc_component_read(component, + int_mux_cfg1); + inp0_sel = int_mux_cfg0_val & WSA_MACRO_MUX_INP_MASK1; + inp1_sel = (int_mux_cfg0_val >> WSA_MACRO_MUX_INP_SHFT) & + WSA_MACRO_MUX_INP_MASK1; + inp2_sel = (int_mux_cfg1_val >> WSA_MACRO_MUX_INP_SHFT) & + WSA_MACRO_MUX_INP_MASK1; + if ((inp0_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) || + (inp1_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) || + (inp2_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0)) { + int_fs_reg = CDC_WSA_RX0_RX_PATH_CTL + + WSA_MACRO_RX_PATH_OFFSET * j; + /* sample_rate is in Hz */ + snd_soc_component_update_bits(component, int_fs_reg, + WSA_MACRO_FS_RATE_MASK, + int_prim_fs_rate_reg_val); + } + int_mux_cfg0 += WSA_MACRO_MUX_CFG_OFFSET; + } + } + + return 0; +} + +static int wsa_macro_set_mix_interpolator_rate(struct snd_soc_dai *dai, + u8 int_mix_fs_rate_reg_val, + u32 sample_rate) +{ + u8 int_2_inp; + u32 j, port; + u16 int_mux_cfg1, int_fs_reg; + u8 int_mux_cfg1_val; + struct snd_soc_component *component = dai->component; + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + + for_each_set_bit(port, &wsa->active_ch_mask[dai->id], WSA_MACRO_RX_MAX) { + int_2_inp = port; + if ((int_2_inp < WSA_MACRO_RX0) || (int_2_inp > WSA_MACRO_RX_MIX1)) { + dev_err(component->dev, "%s: Invalid RX port, Dai ID is %d\n", + __func__, dai->id); + return -EINVAL; + } + + int_mux_cfg1 = CDC_WSA_RX_INP_MUX_RX_INT0_CFG1; + for (j = 0; j < NUM_INTERPOLATORS; j++) { + int_mux_cfg1_val = snd_soc_component_read(component, + int_mux_cfg1) & + WSA_MACRO_MUX_INP_MASK1; + if (int_mux_cfg1_val == int_2_inp + INTn_2_INP_SEL_RX0) { + int_fs_reg = CDC_WSA_RX0_RX_PATH_MIX_CTL + + WSA_MACRO_RX_PATH_OFFSET * j; + + snd_soc_component_update_bits(component, + int_fs_reg, + WSA_MACRO_FS_RATE_MASK, + int_mix_fs_rate_reg_val); + } + int_mux_cfg1 += WSA_MACRO_MUX_CFG_OFFSET; + } + } + return 0; +} + +static int wsa_macro_set_interpolator_rate(struct snd_soc_dai *dai, + u32 sample_rate) +{ + int rate_val = 0; + int i, ret; + + /* set mixing path rate */ + for (i = 0; i < ARRAY_SIZE(int_mix_sample_rate_val); i++) { + if (sample_rate == int_mix_sample_rate_val[i].sample_rate) { + rate_val = int_mix_sample_rate_val[i].rate_val; + break; + } + } + if ((i == ARRAY_SIZE(int_mix_sample_rate_val)) || (rate_val < 0)) + goto prim_rate; + + ret = wsa_macro_set_mix_interpolator_rate(dai, (u8) rate_val, sample_rate); +prim_rate: + /* set primary path sample rate */ + for (i = 0; i < ARRAY_SIZE(int_prim_sample_rate_val); i++) { + if (sample_rate == int_prim_sample_rate_val[i].sample_rate) { + rate_val = int_prim_sample_rate_val[i].rate_val; + break; + } + } + if ((i == ARRAY_SIZE(int_prim_sample_rate_val)) || (rate_val < 0)) + return -EINVAL; + + ret = wsa_macro_set_prim_interpolator_rate(dai, (u8) rate_val, sample_rate); + + return ret; +} + +static int wsa_macro_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + int ret; + + switch (substream->stream) { + case SNDRV_PCM_STREAM_PLAYBACK: + ret = wsa_macro_set_interpolator_rate(dai, params_rate(params)); + if (ret) { + dev_err(component->dev, + "%s: cannot set sample rate: %u\n", + __func__, params_rate(params)); + return ret; + } + break; + default: + break; + } + return 0; +} + +static int wsa_macro_get_channel_map(struct snd_soc_dai *dai, + unsigned int *tx_num, unsigned int *tx_slot, + unsigned int *rx_num, unsigned int *rx_slot) +{ + struct snd_soc_component *component = dai->component; + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + u16 val, mask = 0, cnt = 0, temp; + + switch (dai->id) { + case WSA_MACRO_AIF_VI: + *tx_slot = wsa->active_ch_mask[dai->id]; + *tx_num = wsa->active_ch_cnt[dai->id]; + break; + case WSA_MACRO_AIF1_PB: + case WSA_MACRO_AIF_MIX1_PB: + for_each_set_bit(temp, &wsa->active_ch_mask[dai->id], + WSA_MACRO_RX_MAX) { + mask |= (1 << temp); + if (++cnt == WSA_MACRO_MAX_DMA_CH_PER_PORT) + break; + } + if (mask & 0x0C) + mask = mask >> 0x2; + *rx_slot = mask; + *rx_num = cnt; + break; + case WSA_MACRO_AIF_ECHO: + val = snd_soc_component_read(component, CDC_WSA_RX_INP_MUX_RX_MIX_CFG0); + if (val & WSA_MACRO_EC_MIX_TX1_MASK) { + mask |= 0x2; + cnt++; + } + if (val & WSA_MACRO_EC_MIX_TX0_MASK) { + mask |= 0x1; + cnt++; + } + *tx_slot = mask; + *tx_num = cnt; + break; + default: + dev_err(component->dev, "%s: Invalid AIF\n", __func__); + break; + } + return 0; +} + +static struct snd_soc_dai_ops wsa_macro_dai_ops = { + .hw_params = wsa_macro_hw_params, + .get_channel_map = wsa_macro_get_channel_map, +}; + +static struct snd_soc_dai_driver wsa_macro_dai[] = { + { + .name = "wsa_macro_rx1", + .id = WSA_MACRO_AIF1_PB, + .playback = { + .stream_name = "WSA_AIF1 Playback", + .rates = WSA_MACRO_RX_RATES, + .formats = WSA_MACRO_RX_FORMATS, + .rate_max = 384000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &wsa_macro_dai_ops, + }, + { + .name = "wsa_macro_rx_mix", + .id = WSA_MACRO_AIF_MIX1_PB, + .playback = { + .stream_name = "WSA_AIF_MIX1 Playback", + .rates = WSA_MACRO_RX_MIX_RATES, + .formats = WSA_MACRO_RX_FORMATS, + .rate_max = 192000, + .rate_min = 48000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &wsa_macro_dai_ops, + }, + { + .name = "wsa_macro_vifeedback", + .id = WSA_MACRO_AIF_VI, + .capture = { + .stream_name = "WSA_AIF_VI Capture", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000, + .formats = WSA_MACRO_RX_FORMATS, + .rate_max = 48000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 4, + }, + .ops = &wsa_macro_dai_ops, + }, + { + .name = "wsa_macro_echo", + .id = WSA_MACRO_AIF_ECHO, + .capture = { + .stream_name = "WSA_AIF_ECHO Capture", + .rates = WSA_MACRO_ECHO_RATES, + .formats = WSA_MACRO_ECHO_FORMATS, + .rate_max = 48000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &wsa_macro_dai_ops, + }, +}; + +static void wsa_macro_mclk_enable(struct wsa_macro *wsa, bool mclk_enable) +{ + struct regmap *regmap = wsa->regmap; + + if (mclk_enable) { + if (wsa->wsa_mclk_users == 0) { + regcache_mark_dirty(regmap); + regcache_sync(regmap); + /* 9.6MHz MCLK, set value 0x00 if other frequency */ + regmap_update_bits(regmap, CDC_WSA_TOP_FREQ_MCLK, 0x01, 0x01); + regmap_update_bits(regmap, + CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL, + CDC_WSA_MCLK_EN_MASK, + CDC_WSA_MCLK_ENABLE); + regmap_update_bits(regmap, + CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL, + CDC_WSA_FS_CNT_EN_MASK, + CDC_WSA_FS_CNT_ENABLE); + } + wsa->wsa_mclk_users++; + } else { + if (wsa->wsa_mclk_users <= 0) { + dev_err(wsa->dev, "clock already disabled\n"); + wsa->wsa_mclk_users = 0; + return; + } + wsa->wsa_mclk_users--; + if (wsa->wsa_mclk_users == 0) { + regmap_update_bits(regmap, + CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL, + CDC_WSA_FS_CNT_EN_MASK, + CDC_WSA_FS_CNT_DISABLE); + regmap_update_bits(regmap, + CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL, + CDC_WSA_MCLK_EN_MASK, + CDC_WSA_MCLK_DISABLE); + } + } +} + +static int wsa_macro_get_ec_hq(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + int ec_tx = ((struct soc_mixer_control *) kcontrol->private_value)->shift; + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = wsa->ec_hq[ec_tx]; + + return 0; +} + +static int wsa_macro_set_ec_hq(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + int ec_tx = ((struct soc_mixer_control *) kcontrol->private_value)->shift; + int value = ucontrol->value.integer.value[0]; + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + + wsa->ec_hq[ec_tx] = value; + + return 0; +} + +static int wsa_macro_get_compander(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + int comp = ((struct soc_mixer_control *) kcontrol->private_value)->shift; + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = wsa->comp_enabled[comp]; + return 0; +} + +static int wsa_macro_set_compander(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + int comp = ((struct soc_mixer_control *) kcontrol->private_value)->shift; + int value = ucontrol->value.integer.value[0]; + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + + wsa->comp_enabled[comp] = value; + + return 0; +} + +static int wsa_macro_ear_spkr_pa_gain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = wsa->ear_spkr_gain; + + return 0; +} + +static int wsa_macro_ear_spkr_pa_gain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + + wsa->ear_spkr_gain = ucontrol->value.integer.value[0]; + + return 0; +} + +static int wsa_macro_soft_clip_enable_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + int path = ((struct soc_mixer_control *)kcontrol->private_value)->shift; + + ucontrol->value.integer.value[0] = wsa->is_softclip_on[path]; + + return 0; +} + +static int wsa_macro_soft_clip_enable_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + int path = ((struct soc_mixer_control *) kcontrol->private_value)->shift; + + wsa->is_softclip_on[path] = ucontrol->value.integer.value[0]; + + return 0; +} + +static const struct snd_kcontrol_new wsa_macro_snd_controls[] = { + SOC_ENUM_EXT("EAR SPKR PA Gain", wsa_macro_ear_spkr_pa_gain_enum, + wsa_macro_ear_spkr_pa_gain_get, + wsa_macro_ear_spkr_pa_gain_put), + SOC_SINGLE_EXT("WSA_Softclip0 Enable", SND_SOC_NOPM, + WSA_MACRO_SOFTCLIP0, 1, 0, + wsa_macro_soft_clip_enable_get, + wsa_macro_soft_clip_enable_put), + SOC_SINGLE_EXT("WSA_Softclip1 Enable", SND_SOC_NOPM, + WSA_MACRO_SOFTCLIP1, 1, 0, + wsa_macro_soft_clip_enable_get, + wsa_macro_soft_clip_enable_put), + + SOC_SINGLE_S8_TLV("WSA_RX0 Digital Volume", CDC_WSA_RX0_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("WSA_RX1 Digital Volume", CDC_WSA_RX1_RX_VOL_CTL, + -84, 40, digital_gain), + + SOC_SINGLE("WSA_RX0 Digital Mute", CDC_WSA_RX0_RX_PATH_CTL, 4, 1, 0), + SOC_SINGLE("WSA_RX1 Digital Mute", CDC_WSA_RX1_RX_PATH_CTL, 4, 1, 0), + SOC_SINGLE("WSA_RX0_MIX Digital Mute", CDC_WSA_RX0_RX_PATH_MIX_CTL, 4, + 1, 0), + SOC_SINGLE("WSA_RX1_MIX Digital Mute", CDC_WSA_RX1_RX_PATH_MIX_CTL, 4, + 1, 0), + SOC_SINGLE_EXT("WSA_COMP1 Switch", SND_SOC_NOPM, WSA_MACRO_COMP1, 1, 0, + wsa_macro_get_compander, wsa_macro_set_compander), + SOC_SINGLE_EXT("WSA_COMP2 Switch", SND_SOC_NOPM, WSA_MACRO_COMP2, 1, 0, + wsa_macro_get_compander, wsa_macro_set_compander), + SOC_SINGLE_EXT("WSA_RX0 EC_HQ Switch", SND_SOC_NOPM, WSA_MACRO_RX0, 1, 0, + wsa_macro_get_ec_hq, wsa_macro_set_ec_hq), + SOC_SINGLE_EXT("WSA_RX1 EC_HQ Switch", SND_SOC_NOPM, WSA_MACRO_RX1, 1, 0, + wsa_macro_get_ec_hq, wsa_macro_set_ec_hq), +}; + +static int wsa_swrm_clock(struct wsa_macro *wsa, bool enable) +{ + struct regmap *regmap = wsa->regmap; + + if (enable) { + wsa_macro_mclk_enable(wsa, true); + + /* reset swr ip */ + if (wsa->reset_swr) + regmap_update_bits(regmap, + CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, + CDC_WSA_SWR_RST_EN_MASK, + CDC_WSA_SWR_RST_ENABLE); + + regmap_update_bits(regmap, CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, + CDC_WSA_SWR_CLK_EN_MASK, + CDC_WSA_SWR_CLK_ENABLE); + + /* Bring out of reset */ + if (wsa->reset_swr) + regmap_update_bits(regmap, + CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, + CDC_WSA_SWR_RST_EN_MASK, + CDC_WSA_SWR_RST_DISABLE); + wsa->reset_swr = false; + } else { + regmap_update_bits(regmap, CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, + CDC_WSA_SWR_CLK_EN_MASK, 0); + wsa_macro_mclk_enable(wsa, false); + } + + return 0; +} + +static int wsa_macro_component_probe(struct snd_soc_component *comp) +{ + struct wsa_macro *wsa = snd_soc_component_get_drvdata(comp); + + snd_soc_component_init_regmap(comp, wsa->regmap); + + wsa->spkr_gain_offset = WSA_MACRO_GAIN_OFFSET_M1P5_DB; + + /* set SPKR rate to FS_2P4_3P072 */ + snd_soc_component_update_bits(comp, CDC_WSA_RX0_RX_PATH_CFG1, + CDC_WSA_RX_PATH_SPKR_RATE_MASK, + CDC_WSA_RX_PATH_SPKR_RATE_FS_2P4_3P072); + + snd_soc_component_update_bits(comp, CDC_WSA_RX1_RX_PATH_CFG1, + CDC_WSA_RX_PATH_SPKR_RATE_MASK, + CDC_WSA_RX_PATH_SPKR_RATE_FS_2P4_3P072); + + wsa_macro_set_spkr_mode(comp, WSA_MACRO_SPKR_MODE_1); + + return 0; +} + +static int swclk_gate_enable(struct clk_hw *hw) +{ + return wsa_swrm_clock(to_wsa_macro(hw), true); +} + +static void swclk_gate_disable(struct clk_hw *hw) +{ + wsa_swrm_clock(to_wsa_macro(hw), false); +} + +static int swclk_gate_is_enabled(struct clk_hw *hw) +{ + struct wsa_macro *wsa = to_wsa_macro(hw); + int ret, val; + + regmap_read(wsa->regmap, CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, &val); + ret = val & BIT(0); + + return ret; +} + +static unsigned long swclk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + return parent_rate / 2; +} + +static const struct clk_ops swclk_gate_ops = { + .prepare = swclk_gate_enable, + .unprepare = swclk_gate_disable, + .is_enabled = swclk_gate_is_enabled, + .recalc_rate = swclk_recalc_rate, +}; + +static struct clk *wsa_macro_register_mclk_output(struct wsa_macro *wsa) +{ + struct device *dev = wsa->dev; + struct device_node *np = dev->of_node; + const char *parent_clk_name; + const char *clk_name = "mclk"; + struct clk_hw *hw; + struct clk_init_data init; + int ret; + + parent_clk_name = __clk_get_name(wsa->clks[2].clk); + + init.name = clk_name; + init.ops = &swclk_gate_ops; + init.flags = 0; + init.parent_names = &parent_clk_name; + init.num_parents = 1; + wsa->hw.init = &init; + hw = &wsa->hw; + ret = clk_hw_register(wsa->dev, hw); + if (ret) + return ERR_PTR(ret); + + of_clk_add_provider(np, of_clk_src_simple_get, hw->clk); + + return NULL; +} + +static const struct snd_soc_component_driver wsa_macro_component_drv = { + .name = "WSA MACRO", + .probe = wsa_macro_component_probe, + .controls = wsa_macro_snd_controls, + .num_controls = ARRAY_SIZE(wsa_macro_snd_controls), +}; + +static int wsa_macro_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct wsa_macro *wsa; + void __iomem *base; + int ret; + + wsa = devm_kzalloc(dev, sizeof(*wsa), GFP_KERNEL); + if (!wsa) + return -ENOMEM; + + wsa->clks[0].id = "macro"; + wsa->clks[1].id = "dcodec"; + wsa->clks[2].id = "mclk"; + wsa->clks[3].id = "npl"; + wsa->clks[4].id = "fsgen"; + + ret = devm_clk_bulk_get(dev, WSA_NUM_CLKS_MAX, wsa->clks); + if (ret) { + dev_err(dev, "Error getting WSA Clocks (%d)\n", ret); + return ret; + } + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + wsa->regmap = devm_regmap_init_mmio(dev, base, &wsa_regmap_config); + + dev_set_drvdata(dev, wsa); + + wsa->reset_swr = true; + wsa->dev = dev; + + /* set MCLK and NPL rates */ + clk_set_rate(wsa->clks[2].clk, WSA_MACRO_MCLK_FREQ); + clk_set_rate(wsa->clks[3].clk, WSA_MACRO_MCLK_FREQ); + + ret = clk_bulk_prepare_enable(WSA_NUM_CLKS_MAX, wsa->clks); + if (ret) + return ret; + + wsa_macro_register_mclk_output(wsa); + + ret = devm_snd_soc_register_component(dev, &wsa_macro_component_drv, + wsa_macro_dai, + ARRAY_SIZE(wsa_macro_dai)); + if (ret) + goto err; + + return ret; +err: + clk_bulk_disable_unprepare(WSA_NUM_CLKS_MAX, wsa->clks); + + return ret; + +} + +static int wsa_macro_remove(struct platform_device *pdev) +{ + struct wsa_macro *wsa = dev_get_drvdata(&pdev->dev); + + of_clk_del_provider(pdev->dev.of_node); + + clk_bulk_disable_unprepare(WSA_NUM_CLKS_MAX, wsa->clks); + + return 0; +} + +static const struct of_device_id wsa_macro_dt_match[] = { + {.compatible = "qcom,sm8250-lpass-wsa-macro"}, + {} +}; +MODULE_DEVICE_TABLE(of, wsa_macro_dt_match); + +static struct platform_driver wsa_macro_driver = { + .driver = { + .name = "wsa_macro", + .of_match_table = wsa_macro_dt_match, + }, + .probe = wsa_macro_probe, + .remove = wsa_macro_remove, +}; + +module_platform_driver(wsa_macro_driver); +MODULE_DESCRIPTION("WSA macro driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/lpass-wsa-macro.h b/sound/soc/codecs/lpass-wsa-macro.h new file mode 100644 index 000000000000..d3d62b3f6500 --- /dev/null +++ b/sound/soc/codecs/lpass-wsa-macro.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __LPASS_WSA_MACRO_H__ +#define __LPASS_WSA_MACRO_H__ + +/* + * Selects compander and smart boost settings + * for a given speaker mode + */ +enum { + WSA_MACRO_SPKR_MODE_DEFAULT, + WSA_MACRO_SPKR_MODE_1, /* COMP Gain = 12dB, Smartboost Max = 5.5V */ +}; + +int wsa_macro_set_spkr_mode(struct snd_soc_component *component, int mode); + +#endif /* __LPASS_WSA_MACRO_H__ */ From patchwork Thu Nov 5 11:34:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 319545 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B8CE4C00A89 for ; Thu, 5 Nov 2020 11:37:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4AF7020936 for ; Thu, 5 Nov 2020 11:37:15 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="wPtLarGB" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730357AbgKELg2 (ORCPT ); Thu, 5 Nov 2020 06:36:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45466 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730418AbgKELfI (ORCPT ); Thu, 5 Nov 2020 06:35:08 -0500 Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CC13CC0613D3 for ; Thu, 5 Nov 2020 03:35:07 -0800 (PST) Received: by mail-wr1-x434.google.com with SMTP id y12so1353732wrp.6 for ; Thu, 05 Nov 2020 03:35:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=As53DyDvBtjurxwguPbVE84q5vtXpfX/PW37/GvaTHE=; b=wPtLarGBQarD7h+fT40wWbg1N5M11NpV7Xf4ES1iY2vLuxYijOIAJdP5r0SYiyXzPQ xvny+ML+spaOX1xrHAJNyU2JPqbprXi/WF2x5U6z7L77n050CHcg/BChbmXd9KChY1bp tT3/6zvPw4ONUNkXN3VJC6aZierTe2OkPNBFsPy/Mc8t+0C49Lc34aD5BmXwZHBN0k95 qHOoswMc05nrQLcBxYJBX7gTWCBo5ytisLo5jLp0u/4AtCZ2Qo2Cjk1Ecxz7T6wJufia 4pmRJyCmwkUaBlXZHoVIu4hUIugLZGOCUmbLo/QNYn5Yr83wTXHDfr/Jtn6KoApGhEHU PtYw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=As53DyDvBtjurxwguPbVE84q5vtXpfX/PW37/GvaTHE=; b=Tm1nmUHIfQvY3tchKTXB4APZoVPDIVHEa/NccrueFGQui32iQtOGhvRtPOaalO5RBv bRjiu/UqmO6Y+D5k1jn/iQTkKtuf2pyJdYP+CvoCdCvcd4kwbK+zQQl9KzzQHADNEwJD uSPJ018saO0krhj/6PfSPLIoIZL+SfzWEVFmLylnitZ+qCKYUH3xzcB99FEKBSrp48bV iZgfMa6HKq3Yw5/+kVb/d2TSfB+rSRcUKs4mtLn4s9AjmxPiEeIM31Q5jL6nhfjCKwB/ TSD8QTtlFMZKt8x1I2QxL+0T6AoWy3Nea9bHQM+CFrE912oDfeVFBntLWySbFh5LY4QP 6Uxg== X-Gm-Message-State: AOAM532iNfunp3HISrsfdwPXAAyUVMC2YBwekAAgc2iiv6NZq5obvthK ZPrbQcOKNkeEeTgrO3MK63KXWA== X-Google-Smtp-Source: ABdhPJxkuGpvMjT2A9OFxQCtKClGt7vzPYFE/tLXSarNgme7UUOwUpLotJQdnIamLQ7w6XlXprIJig== X-Received: by 2002:adf:ab50:: with SMTP id r16mr2293927wrc.235.1604576106384; Thu, 05 Nov 2020 03:35:06 -0800 (PST) Received: from srini-hackbox.lan (cpc86377-aztw32-2-0-cust226.18-1.cable.virginm.net. [92.233.226.227]) by smtp.gmail.com with ESMTPSA id t199sm2096129wmt.46.2020.11.05.03.35.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Nov 2020 03:35:05 -0800 (PST) From: Srinivas Kandagatla To: broonie@kernel.org Cc: perex@perex.cz, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org, lgirdwood@gmail.com, devicetree@vger.kernel.org, robh+dt@kernel.org, Srinivas Kandagatla Subject: [PATCH v3 3/6] ASoC: codecs: lpass-wsa-macro: add dapm widgets and route Date: Thu, 5 Nov 2020 11:34:55 +0000 Message-Id: <20201105113458.12360-4-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20201105113458.12360-1-srinivas.kandagatla@linaro.org> References: <20201105113458.12360-1-srinivas.kandagatla@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This patch adds dapm widgets and routes on this codec Signed-off-by: Srinivas Kandagatla --- sound/soc/codecs/lpass-wsa-macro.c | 1081 ++++++++++++++++++++++++++++ 1 file changed, 1081 insertions(+) diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 76873d582eff..25f1df214ca5 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -354,6 +354,26 @@ struct wsa_macro { static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400); +static const char *const rx_text[] = { + "ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "DEC0", "DEC1" +}; + +static const char *const rx_mix_text[] = { + "ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1" +}; + +static const char *const rx_mix_ec_text[] = { + "ZERO", "RX_MIX_TX0", "RX_MIX_TX1" +}; + +static const char *const rx_mux_text[] = { + "ZERO", "AIF1_PB", "AIF_MIX1_PB" +}; + +static const char *const rx_sidetone_mix_text[] = { + "ZERO", "SRC0" +}; + static const char * const wsa_macro_ear_spkr_pa_gain_text[] = { "G_DEFAULT", "G_0_DB", "G_1_DB", "G_2_DB", "G_3_DB", "G_4_DB", "G_5_DB", "G_6_DB" @@ -362,6 +382,84 @@ static const char * const wsa_macro_ear_spkr_pa_gain_text[] = { static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_ear_spkr_pa_gain_enum, wsa_macro_ear_spkr_pa_gain_text); +/* RX INT0 */ +static const struct soc_enum rx0_prim_inp0_chain_enum = + SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT0_CFG0, + 0, 7, rx_text); + +static const struct soc_enum rx0_prim_inp1_chain_enum = + SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT0_CFG0, + 3, 7, rx_text); + +static const struct soc_enum rx0_prim_inp2_chain_enum = + SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT0_CFG1, + 3, 7, rx_text); + +static const struct soc_enum rx0_mix_chain_enum = + SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT0_CFG1, + 0, 5, rx_mix_text); + +static const struct soc_enum rx0_sidetone_mix_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_sidetone_mix_text); + +static const struct snd_kcontrol_new rx0_prim_inp0_mux = + SOC_DAPM_ENUM("WSA_RX0 INP0 Mux", rx0_prim_inp0_chain_enum); + +static const struct snd_kcontrol_new rx0_prim_inp1_mux = + SOC_DAPM_ENUM("WSA_RX0 INP1 Mux", rx0_prim_inp1_chain_enum); + +static const struct snd_kcontrol_new rx0_prim_inp2_mux = + SOC_DAPM_ENUM("WSA_RX0 INP2 Mux", rx0_prim_inp2_chain_enum); + +static const struct snd_kcontrol_new rx0_mix_mux = + SOC_DAPM_ENUM("WSA_RX0 MIX Mux", rx0_mix_chain_enum); + +static const struct snd_kcontrol_new rx0_sidetone_mix_mux = + SOC_DAPM_ENUM("WSA_RX0 SIDETONE MIX Mux", rx0_sidetone_mix_enum); + +/* RX INT1 */ +static const struct soc_enum rx1_prim_inp0_chain_enum = + SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT1_CFG0, + 0, 7, rx_text); + +static const struct soc_enum rx1_prim_inp1_chain_enum = + SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT1_CFG0, + 3, 7, rx_text); + +static const struct soc_enum rx1_prim_inp2_chain_enum = + SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT1_CFG1, + 3, 7, rx_text); + +static const struct soc_enum rx1_mix_chain_enum = + SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT1_CFG1, + 0, 5, rx_mix_text); + +static const struct snd_kcontrol_new rx1_prim_inp0_mux = + SOC_DAPM_ENUM("WSA_RX1 INP0 Mux", rx1_prim_inp0_chain_enum); + +static const struct snd_kcontrol_new rx1_prim_inp1_mux = + SOC_DAPM_ENUM("WSA_RX1 INP1 Mux", rx1_prim_inp1_chain_enum); + +static const struct snd_kcontrol_new rx1_prim_inp2_mux = + SOC_DAPM_ENUM("WSA_RX1 INP2 Mux", rx1_prim_inp2_chain_enum); + +static const struct snd_kcontrol_new rx1_mix_mux = + SOC_DAPM_ENUM("WSA_RX1 MIX Mux", rx1_mix_chain_enum); + +static const struct soc_enum rx_mix_ec0_enum = + SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_MIX_CFG0, + 0, 3, rx_mix_ec_text); + +static const struct soc_enum rx_mix_ec1_enum = + SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_MIX_CFG0, + 3, 3, rx_mix_ec_text); + +static const struct snd_kcontrol_new rx_mix_ec0_mux = + SOC_DAPM_ENUM("WSA RX_MIX EC0_Mux", rx_mix_ec0_enum); + +static const struct snd_kcontrol_new rx_mix_ec1_mux = + SOC_DAPM_ENUM("WSA RX_MIX EC1_Mux", rx_mix_ec1_enum); + static const struct reg_default wsa_defaults[] = { /* WSA Macro */ { CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL, 0x00}, @@ -1038,6 +1136,613 @@ static void wsa_macro_mclk_enable(struct wsa_macro *wsa, bool mclk_enable) } } +static int wsa_macro_mclk_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + + wsa_macro_mclk_enable(wsa, event == SND_SOC_DAPM_PRE_PMU); + return 0; +} + +static int wsa_macro_enable_vi_feedback(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + u32 tx_reg0, tx_reg1; + + if (test_bit(WSA_MACRO_TX0, &wsa->active_ch_mask[WSA_MACRO_AIF_VI])) { + tx_reg0 = CDC_WSA_TX0_SPKR_PROT_PATH_CTL; + tx_reg1 = CDC_WSA_TX1_SPKR_PROT_PATH_CTL; + } else if (test_bit(WSA_MACRO_TX1, &wsa->active_ch_mask[WSA_MACRO_AIF_VI])) { + tx_reg0 = CDC_WSA_TX2_SPKR_PROT_PATH_CTL; + tx_reg1 = CDC_WSA_TX3_SPKR_PROT_PATH_CTL; + } + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + /* Enable V&I sensing */ + snd_soc_component_update_bits(component, tx_reg0, + CDC_WSA_TX_SPKR_PROT_RESET_MASK, + CDC_WSA_TX_SPKR_PROT_RESET); + snd_soc_component_update_bits(component, tx_reg1, + CDC_WSA_TX_SPKR_PROT_RESET_MASK, + CDC_WSA_TX_SPKR_PROT_RESET); + snd_soc_component_update_bits(component, tx_reg0, + CDC_WSA_TX_SPKR_PROT_PCM_RATE_MASK, + CDC_WSA_TX_SPKR_PROT_PCM_RATE_8K); + snd_soc_component_update_bits(component, tx_reg1, + CDC_WSA_TX_SPKR_PROT_PCM_RATE_MASK, + CDC_WSA_TX_SPKR_PROT_PCM_RATE_8K); + snd_soc_component_update_bits(component, tx_reg0, + CDC_WSA_TX_SPKR_PROT_CLK_EN_MASK, + CDC_WSA_TX_SPKR_PROT_CLK_ENABLE); + snd_soc_component_update_bits(component, tx_reg1, + CDC_WSA_TX_SPKR_PROT_CLK_EN_MASK, + CDC_WSA_TX_SPKR_PROT_CLK_ENABLE); + snd_soc_component_update_bits(component, tx_reg0, + CDC_WSA_TX_SPKR_PROT_RESET_MASK, + CDC_WSA_TX_SPKR_PROT_NO_RESET); + snd_soc_component_update_bits(component, tx_reg1, + CDC_WSA_TX_SPKR_PROT_RESET_MASK, + CDC_WSA_TX_SPKR_PROT_NO_RESET); + break; + case SND_SOC_DAPM_POST_PMD: + /* Disable V&I sensing */ + snd_soc_component_update_bits(component, tx_reg0, + CDC_WSA_TX_SPKR_PROT_RESET_MASK, + CDC_WSA_TX_SPKR_PROT_RESET); + snd_soc_component_update_bits(component, tx_reg1, + CDC_WSA_TX_SPKR_PROT_RESET_MASK, + CDC_WSA_TX_SPKR_PROT_RESET); + snd_soc_component_update_bits(component, tx_reg0, + CDC_WSA_TX_SPKR_PROT_CLK_EN_MASK, + CDC_WSA_TX_SPKR_PROT_CLK_DISABLE); + snd_soc_component_update_bits(component, tx_reg1, + CDC_WSA_TX_SPKR_PROT_CLK_EN_MASK, + CDC_WSA_TX_SPKR_PROT_CLK_DISABLE); + break; + } + + return 0; +} + +static int wsa_macro_enable_mix_path(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + u16 gain_reg; + int val; + + switch (w->reg) { + case CDC_WSA_RX0_RX_PATH_MIX_CTL: + gain_reg = CDC_WSA_RX0_RX_VOL_MIX_CTL; + break; + case CDC_WSA_RX1_RX_PATH_MIX_CTL: + gain_reg = CDC_WSA_RX1_RX_VOL_MIX_CTL; + break; + default: + return 0; + } + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + val = snd_soc_component_read(component, gain_reg); + snd_soc_component_write(component, gain_reg, val); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_component_update_bits(component, w->reg, + CDC_WSA_RX_PATH_MIX_CLK_EN_MASK, + CDC_WSA_RX_PATH_MIX_CLK_DISABLE); + break; + } + + return 0; +} + +static void wsa_macro_hd2_control(struct snd_soc_component *component, + u16 reg, int event) +{ + u16 hd2_scale_reg; + u16 hd2_enable_reg; + + if (reg == CDC_WSA_RX0_RX_PATH_CTL) { + hd2_scale_reg = CDC_WSA_RX0_RX_PATH_SEC3; + hd2_enable_reg = CDC_WSA_RX0_RX_PATH_CFG0; + } + if (reg == CDC_WSA_RX1_RX_PATH_CTL) { + hd2_scale_reg = CDC_WSA_RX1_RX_PATH_SEC3; + hd2_enable_reg = CDC_WSA_RX1_RX_PATH_CFG0; + } + + if (hd2_enable_reg && SND_SOC_DAPM_EVENT_ON(event)) { + snd_soc_component_update_bits(component, hd2_scale_reg, + CDC_WSA_RX_PATH_HD2_ALPHA_MASK, + 0x10); + snd_soc_component_update_bits(component, hd2_scale_reg, + CDC_WSA_RX_PATH_HD2_SCALE_MASK, + 0x1); + snd_soc_component_update_bits(component, hd2_enable_reg, + CDC_WSA_RX_PATH_HD2_EN_MASK, + CDC_WSA_RX_PATH_HD2_ENABLE); + } + + if (hd2_enable_reg && SND_SOC_DAPM_EVENT_OFF(event)) { + snd_soc_component_update_bits(component, hd2_enable_reg, + CDC_WSA_RX_PATH_HD2_EN_MASK, 0); + snd_soc_component_update_bits(component, hd2_scale_reg, + CDC_WSA_RX_PATH_HD2_SCALE_MASK, + 0); + snd_soc_component_update_bits(component, hd2_scale_reg, + CDC_WSA_RX_PATH_HD2_ALPHA_MASK, + 0); + } +} + +static int wsa_macro_config_compander(struct snd_soc_component *component, + int comp, int event) +{ + u16 comp_ctl0_reg, rx_path_cfg0_reg; + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + + if (!wsa->comp_enabled[comp]) + return 0; + + comp_ctl0_reg = CDC_WSA_COMPANDER0_CTL0 + + (comp * WSA_MACRO_RX_COMP_OFFSET); + rx_path_cfg0_reg = CDC_WSA_RX0_RX_PATH_CFG0 + + (comp * WSA_MACRO_RX_PATH_OFFSET); + + if (SND_SOC_DAPM_EVENT_ON(event)) { + /* Enable Compander Clock */ + snd_soc_component_update_bits(component, comp_ctl0_reg, + CDC_WSA_COMPANDER_CLK_EN_MASK, + CDC_WSA_COMPANDER_CLK_ENABLE); + snd_soc_component_update_bits(component, comp_ctl0_reg, + CDC_WSA_COMPANDER_SOFT_RST_MASK, + CDC_WSA_COMPANDER_SOFT_RST_ENABLE); + snd_soc_component_update_bits(component, comp_ctl0_reg, + CDC_WSA_COMPANDER_SOFT_RST_MASK, + 0); + snd_soc_component_update_bits(component, rx_path_cfg0_reg, + CDC_WSA_RX_PATH_COMP_EN_MASK, + CDC_WSA_RX_PATH_COMP_ENABLE); + } + + if (SND_SOC_DAPM_EVENT_OFF(event)) { + snd_soc_component_update_bits(component, comp_ctl0_reg, + CDC_WSA_COMPANDER_HALT_MASK, + CDC_WSA_COMPANDER_HALT); + snd_soc_component_update_bits(component, rx_path_cfg0_reg, + CDC_WSA_RX_PATH_COMP_EN_MASK, 0); + snd_soc_component_update_bits(component, comp_ctl0_reg, + CDC_WSA_COMPANDER_SOFT_RST_MASK, + CDC_WSA_COMPANDER_SOFT_RST_ENABLE); + snd_soc_component_update_bits(component, comp_ctl0_reg, + CDC_WSA_COMPANDER_SOFT_RST_MASK, + 0); + snd_soc_component_update_bits(component, comp_ctl0_reg, + CDC_WSA_COMPANDER_CLK_EN_MASK, 0); + snd_soc_component_update_bits(component, comp_ctl0_reg, + CDC_WSA_COMPANDER_HALT_MASK, 0); + } + + return 0; +} + +static void wsa_macro_enable_softclip_clk(struct snd_soc_component *component, + struct wsa_macro *wsa, + int path, + bool enable) +{ + u16 softclip_clk_reg = CDC_WSA_SOFTCLIP0_CRC + + (path * WSA_MACRO_RX_SOFTCLIP_OFFSET); + u8 softclip_mux_mask = (1 << path); + u8 softclip_mux_value = (1 << path); + + if (enable) { + if (wsa->softclip_clk_users[path] == 0) { + snd_soc_component_update_bits(component, + softclip_clk_reg, + CDC_WSA_SOFTCLIP_CLK_EN_MASK, + CDC_WSA_SOFTCLIP_CLK_ENABLE); + snd_soc_component_update_bits(component, + CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0, + softclip_mux_mask, softclip_mux_value); + } + wsa->softclip_clk_users[path]++; + } else { + wsa->softclip_clk_users[path]--; + if (wsa->softclip_clk_users[path] == 0) { + snd_soc_component_update_bits(component, + softclip_clk_reg, + CDC_WSA_SOFTCLIP_CLK_EN_MASK, + 0); + snd_soc_component_update_bits(component, + CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0, + softclip_mux_mask, 0x00); + } + } +} + +static int wsa_macro_config_softclip(struct snd_soc_component *component, + int path, int event) +{ + u16 softclip_ctrl_reg; + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + int softclip_path = 0; + + if (path == WSA_MACRO_COMP1) + softclip_path = WSA_MACRO_SOFTCLIP0; + else if (path == WSA_MACRO_COMP2) + softclip_path = WSA_MACRO_SOFTCLIP1; + + if (!wsa->is_softclip_on[softclip_path]) + return 0; + + softclip_ctrl_reg = CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL + + (softclip_path * WSA_MACRO_RX_SOFTCLIP_OFFSET); + + if (SND_SOC_DAPM_EVENT_ON(event)) { + /* Enable Softclip clock and mux */ + wsa_macro_enable_softclip_clk(component, wsa, softclip_path, + true); + /* Enable Softclip control */ + snd_soc_component_update_bits(component, softclip_ctrl_reg, + CDC_WSA_SOFTCLIP_EN_MASK, + CDC_WSA_SOFTCLIP_ENABLE); + } + + if (SND_SOC_DAPM_EVENT_OFF(event)) { + snd_soc_component_update_bits(component, softclip_ctrl_reg, + CDC_WSA_SOFTCLIP_EN_MASK, 0); + wsa_macro_enable_softclip_clk(component, wsa, softclip_path, + false); + } + + return 0; +} + +static bool wsa_macro_adie_lb(struct snd_soc_component *component, + int interp_idx) +{ + u16 int_mux_cfg0, int_mux_cfg1; + u8 int_mux_cfg0_val, int_mux_cfg1_val; + u8 int_n_inp0, int_n_inp1, int_n_inp2; + + int_mux_cfg0 = CDC_WSA_RX_INP_MUX_RX_INT0_CFG0 + interp_idx * 8; + int_mux_cfg1 = int_mux_cfg0 + 4; + int_mux_cfg0_val = snd_soc_component_read(component, int_mux_cfg0); + int_mux_cfg1_val = snd_soc_component_read(component, int_mux_cfg1); + + int_n_inp0 = int_mux_cfg0_val & 0x0F; + if (int_n_inp0 == INTn_1_INP_SEL_DEC0 || + int_n_inp0 == INTn_1_INP_SEL_DEC1) + return true; + + int_n_inp1 = int_mux_cfg0_val >> 4; + if (int_n_inp1 == INTn_1_INP_SEL_DEC0 || + int_n_inp1 == INTn_1_INP_SEL_DEC1) + return true; + + int_n_inp2 = int_mux_cfg1_val >> 4; + if (int_n_inp2 == INTn_1_INP_SEL_DEC0 || + int_n_inp2 == INTn_1_INP_SEL_DEC1) + return true; + + return false; +} + +static int wsa_macro_enable_main_path(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + u16 reg; + + reg = CDC_WSA_RX0_RX_PATH_CTL + WSA_MACRO_RX_PATH_OFFSET * w->shift; + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (wsa_macro_adie_lb(component, w->shift)) { + snd_soc_component_update_bits(component, reg, + CDC_WSA_RX_PATH_CLK_EN_MASK, + CDC_WSA_RX_PATH_CLK_ENABLE); + } + break; + default: + break; + } + return 0; +} + +static int wsa_macro_interp_get_primary_reg(u16 reg, u16 *ind) +{ + u16 prim_int_reg = 0; + + switch (reg) { + case CDC_WSA_RX0_RX_PATH_CTL: + case CDC_WSA_RX0_RX_PATH_MIX_CTL: + prim_int_reg = CDC_WSA_RX0_RX_PATH_CTL; + *ind = 0; + break; + case CDC_WSA_RX1_RX_PATH_CTL: + case CDC_WSA_RX1_RX_PATH_MIX_CTL: + prim_int_reg = CDC_WSA_RX1_RX_PATH_CTL; + *ind = 1; + break; + } + + return prim_int_reg; +} + +static int wsa_macro_enable_prim_interpolator(struct snd_soc_component *component, + u16 reg, int event) +{ + u16 prim_int_reg; + u16 ind = 0; + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + + prim_int_reg = wsa_macro_interp_get_primary_reg(reg, &ind); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + wsa->prim_int_users[ind]++; + if (wsa->prim_int_users[ind] == 1) { + snd_soc_component_update_bits(component, + prim_int_reg + WSA_MACRO_RX_PATH_CFG3_OFFSET, + CDC_WSA_RX_DC_DCOEFF_MASK, + 0x3); + snd_soc_component_update_bits(component, prim_int_reg, + CDC_WSA_RX_PATH_PGA_MUTE_EN_MASK, + CDC_WSA_RX_PATH_PGA_MUTE_ENABLE); + wsa_macro_hd2_control(component, prim_int_reg, event); + snd_soc_component_update_bits(component, + prim_int_reg + WSA_MACRO_RX_PATH_DSMDEM_OFFSET, + CDC_WSA_RX_DSMDEM_CLK_EN_MASK, + CDC_WSA_RX_DSMDEM_CLK_ENABLE); + } + if ((reg != prim_int_reg) && + ((snd_soc_component_read( + component, prim_int_reg)) & 0x10)) + snd_soc_component_update_bits(component, reg, + 0x10, 0x10); + break; + case SND_SOC_DAPM_POST_PMD: + wsa->prim_int_users[ind]--; + if (wsa->prim_int_users[ind] == 0) { + snd_soc_component_update_bits(component, + prim_int_reg + WSA_MACRO_RX_PATH_DSMDEM_OFFSET, + CDC_WSA_RX_DSMDEM_CLK_EN_MASK, 0); + wsa_macro_hd2_control(component, prim_int_reg, event); + } + break; + } + + return 0; +} + +static int wsa_macro_config_ear_spkr_gain(struct snd_soc_component *component, + struct wsa_macro *wsa, + int event, int gain_reg) +{ + int comp_gain_offset, val; + + switch (wsa->spkr_mode) { + /* Compander gain in WSA_MACRO_SPKR_MODE1 case is 12 dB */ + case WSA_MACRO_SPKR_MODE_1: + comp_gain_offset = -12; + break; + /* Default case compander gain is 15 dB */ + default: + comp_gain_offset = -15; + break; + } + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + /* Apply ear spkr gain only if compander is enabled */ + if (wsa->comp_enabled[WSA_MACRO_COMP1] && + (gain_reg == CDC_WSA_RX0_RX_VOL_CTL) && + (wsa->ear_spkr_gain != 0)) { + /* For example, val is -8(-12+5-1) for 4dB of gain */ + val = comp_gain_offset + wsa->ear_spkr_gain - 1; + snd_soc_component_write(component, gain_reg, val); + } + break; + case SND_SOC_DAPM_POST_PMD: + /* + * Reset RX0 volume to 0 dB if compander is enabled and + * ear_spkr_gain is non-zero. + */ + if (wsa->comp_enabled[WSA_MACRO_COMP1] && + (gain_reg == CDC_WSA_RX0_RX_VOL_CTL) && + (wsa->ear_spkr_gain != 0)) { + snd_soc_component_write(component, gain_reg, 0x0); + } + break; + } + + return 0; +} + +static int wsa_macro_enable_interpolator(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + u16 gain_reg; + u16 reg; + int val; + int offset_val = 0; + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + + if (w->shift == WSA_MACRO_COMP1) { + reg = CDC_WSA_RX0_RX_PATH_CTL; + gain_reg = CDC_WSA_RX0_RX_VOL_CTL; + } else if (w->shift == WSA_MACRO_COMP2) { + reg = CDC_WSA_RX1_RX_PATH_CTL; + gain_reg = CDC_WSA_RX1_RX_VOL_CTL; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* Reset if needed */ + wsa_macro_enable_prim_interpolator(component, reg, event); + break; + case SND_SOC_DAPM_POST_PMU: + wsa_macro_config_compander(component, w->shift, event); + wsa_macro_config_softclip(component, w->shift, event); + /* apply gain after int clk is enabled */ + if ((wsa->spkr_gain_offset == WSA_MACRO_GAIN_OFFSET_M1P5_DB) && + (wsa->comp_enabled[WSA_MACRO_COMP1] || + wsa->comp_enabled[WSA_MACRO_COMP2])) { + snd_soc_component_update_bits(component, + CDC_WSA_RX0_RX_PATH_SEC1, + CDC_WSA_RX_PGA_HALF_DB_MASK, + CDC_WSA_RX_PGA_HALF_DB_ENABLE); + snd_soc_component_update_bits(component, + CDC_WSA_RX0_RX_PATH_MIX_SEC0, + CDC_WSA_RX_PGA_HALF_DB_MASK, + CDC_WSA_RX_PGA_HALF_DB_ENABLE); + snd_soc_component_update_bits(component, + CDC_WSA_RX1_RX_PATH_SEC1, + CDC_WSA_RX_PGA_HALF_DB_MASK, + CDC_WSA_RX_PGA_HALF_DB_ENABLE); + snd_soc_component_update_bits(component, + CDC_WSA_RX1_RX_PATH_MIX_SEC0, + CDC_WSA_RX_PGA_HALF_DB_MASK, + CDC_WSA_RX_PGA_HALF_DB_ENABLE); + offset_val = -2; + } + val = snd_soc_component_read(component, gain_reg); + val += offset_val; + snd_soc_component_write(component, gain_reg, val); + wsa_macro_config_ear_spkr_gain(component, wsa, + event, gain_reg); + break; + case SND_SOC_DAPM_POST_PMD: + wsa_macro_config_compander(component, w->shift, event); + wsa_macro_config_softclip(component, w->shift, event); + wsa_macro_enable_prim_interpolator(component, reg, event); + if ((wsa->spkr_gain_offset == WSA_MACRO_GAIN_OFFSET_M1P5_DB) && + (wsa->comp_enabled[WSA_MACRO_COMP1] || + wsa->comp_enabled[WSA_MACRO_COMP2])) { + snd_soc_component_update_bits(component, + CDC_WSA_RX0_RX_PATH_SEC1, + CDC_WSA_RX_PGA_HALF_DB_MASK, + CDC_WSA_RX_PGA_HALF_DB_DISABLE); + snd_soc_component_update_bits(component, + CDC_WSA_RX0_RX_PATH_MIX_SEC0, + CDC_WSA_RX_PGA_HALF_DB_MASK, + CDC_WSA_RX_PGA_HALF_DB_DISABLE); + snd_soc_component_update_bits(component, + CDC_WSA_RX1_RX_PATH_SEC1, + CDC_WSA_RX_PGA_HALF_DB_MASK, + CDC_WSA_RX_PGA_HALF_DB_DISABLE); + snd_soc_component_update_bits(component, + CDC_WSA_RX1_RX_PATH_MIX_SEC0, + CDC_WSA_RX_PGA_HALF_DB_MASK, + CDC_WSA_RX_PGA_HALF_DB_DISABLE); + offset_val = 2; + val = snd_soc_component_read(component, gain_reg); + val += offset_val; + snd_soc_component_write(component, gain_reg, val); + } + wsa_macro_config_ear_spkr_gain(component, wsa, + event, gain_reg); + break; + } + + return 0; +} + +static int wsa_macro_spk_boost_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + u16 boost_path_ctl, boost_path_cfg1; + u16 reg, reg_mix; + + if (!strcmp(w->name, "WSA_RX INT0 CHAIN")) { + boost_path_ctl = CDC_WSA_BOOST0_BOOST_PATH_CTL; + boost_path_cfg1 = CDC_WSA_RX0_RX_PATH_CFG1; + reg = CDC_WSA_RX0_RX_PATH_CTL; + reg_mix = CDC_WSA_RX0_RX_PATH_MIX_CTL; + } else if (!strcmp(w->name, "WSA_RX INT1 CHAIN")) { + boost_path_ctl = CDC_WSA_BOOST1_BOOST_PATH_CTL; + boost_path_cfg1 = CDC_WSA_RX1_RX_PATH_CFG1; + reg = CDC_WSA_RX1_RX_PATH_CTL; + reg_mix = CDC_WSA_RX1_RX_PATH_MIX_CTL; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + snd_soc_component_update_bits(component, boost_path_cfg1, + CDC_WSA_RX_PATH_SMART_BST_EN_MASK, + CDC_WSA_RX_PATH_SMART_BST_ENABLE); + snd_soc_component_update_bits(component, boost_path_ctl, + CDC_WSA_BOOST_PATH_CLK_EN_MASK, + CDC_WSA_BOOST_PATH_CLK_ENABLE); + if ((snd_soc_component_read(component, reg_mix)) & 0x10) + snd_soc_component_update_bits(component, reg_mix, + 0x10, 0x00); + break; + case SND_SOC_DAPM_POST_PMU: + snd_soc_component_update_bits(component, reg, 0x10, 0x00); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_component_update_bits(component, boost_path_ctl, + CDC_WSA_BOOST_PATH_CLK_EN_MASK, + CDC_WSA_BOOST_PATH_CLK_DISABLE); + snd_soc_component_update_bits(component, boost_path_cfg1, + CDC_WSA_RX_PATH_SMART_BST_EN_MASK, + CDC_WSA_RX_PATH_SMART_BST_DISABLE); + break; + } + + return 0; +} + +static int wsa_macro_enable_echo(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + u16 val, ec_tx, ec_hq_reg; + + val = snd_soc_component_read(component, CDC_WSA_RX_INP_MUX_RX_MIX_CFG0); + + switch (w->shift) { + case WSA_MACRO_EC0_MUX: + val = val & CDC_WSA_RX_MIX_TX0_SEL_MASK; + ec_tx = val - 1; + break; + case WSA_MACRO_EC1_MUX: + val = val & CDC_WSA_RX_MIX_TX1_SEL_MASK; + ec_tx = (val >> CDC_WSA_RX_MIX_TX1_SEL_SHFT) - 1; + break; + } + + if (wsa->ec_hq[ec_tx]) { + ec_hq_reg = CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL + 0x40 * ec_tx; + snd_soc_component_update_bits(component, ec_hq_reg, + CDC_WSA_EC_HQ_EC_CLK_EN_MASK, + CDC_WSA_EC_HQ_EC_CLK_ENABLE); + ec_hq_reg = CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0 + 0x40 * ec_tx; + /* default set to 48k */ + snd_soc_component_update_bits(component, ec_hq_reg, + CDC_WSA_EC_HQ_EC_REF_PCM_RATE_MASK, + CDC_WSA_EC_HQ_EC_REF_PCM_RATE_48K); + } + + return 0; +} + static int wsa_macro_get_ec_hq(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1111,6 +1816,75 @@ static int wsa_macro_ear_spkr_pa_gain_put(struct snd_kcontrol *kcontrol, return 0; } +static int wsa_macro_rx_mux_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = + snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = + snd_soc_dapm_to_component(widget->dapm); + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = + wsa->rx_port_value[widget->shift]; + return 0; +} + +static int wsa_macro_rx_mux_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = + snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = + snd_soc_dapm_to_component(widget->dapm); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + struct snd_soc_dapm_update *update = NULL; + u32 rx_port_value = ucontrol->value.integer.value[0]; + u32 bit_input; + u32 aif_rst; + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + + aif_rst = wsa->rx_port_value[widget->shift]; + if (!rx_port_value) { + if (aif_rst == 0) { + dev_err(component->dev, "%s: AIF reset already\n", __func__); + return 0; + } + if (aif_rst >= WSA_MACRO_RX_MAX) { + dev_err(component->dev, "%s: Invalid AIF reset\n", __func__); + return 0; + } + } + wsa->rx_port_value[widget->shift] = rx_port_value; + + bit_input = widget->shift; + + switch (rx_port_value) { + case 0: + if (wsa->active_ch_cnt[aif_rst]) { + clear_bit(bit_input, + &wsa->active_ch_mask[aif_rst]); + wsa->active_ch_cnt[aif_rst]--; + } + break; + case 1: + case 2: + set_bit(bit_input, + &wsa->active_ch_mask[rx_port_value]); + wsa->active_ch_cnt[rx_port_value]++; + break; + default: + dev_err(component->dev, + "%s: Invalid AIF_ID for WSA RX MUX %d\n", + __func__, rx_port_value); + return -EINVAL; + } + + snd_soc_dapm_mux_update_power(widget->dapm, kcontrol, + rx_port_value, e, update); + return 0; +} + static int wsa_macro_soft_clip_enable_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1169,6 +1943,309 @@ static const struct snd_kcontrol_new wsa_macro_snd_controls[] = { wsa_macro_get_ec_hq, wsa_macro_set_ec_hq), }; +static const struct soc_enum rx_mux_enum = + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_mux_text), rx_mux_text); + +static const struct snd_kcontrol_new rx_mux[WSA_MACRO_RX_MAX] = { + SOC_DAPM_ENUM_EXT("WSA RX0 Mux", rx_mux_enum, + wsa_macro_rx_mux_get, wsa_macro_rx_mux_put), + SOC_DAPM_ENUM_EXT("WSA RX1 Mux", rx_mux_enum, + wsa_macro_rx_mux_get, wsa_macro_rx_mux_put), + SOC_DAPM_ENUM_EXT("WSA RX_MIX0 Mux", rx_mux_enum, + wsa_macro_rx_mux_get, wsa_macro_rx_mux_put), + SOC_DAPM_ENUM_EXT("WSA RX_MIX1 Mux", rx_mux_enum, + wsa_macro_rx_mux_get, wsa_macro_rx_mux_put), +}; + +static int wsa_macro_vi_feed_mixer_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm); + struct soc_mixer_control *mixer = (struct soc_mixer_control *)kcontrol->private_value; + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + u32 spk_tx_id = mixer->shift; + u32 dai_id = widget->shift; + + if (test_bit(spk_tx_id, &wsa->active_ch_mask[dai_id])) + ucontrol->value.integer.value[0] = 1; + else + ucontrol->value.integer.value[0] = 0; + + return 0; +} + +static int wsa_macro_vi_feed_mixer_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm); + struct soc_mixer_control *mixer = (struct soc_mixer_control *)kcontrol->private_value; + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + u32 enable = ucontrol->value.integer.value[0]; + u32 spk_tx_id = mixer->shift; + + if (enable) { + if (spk_tx_id == WSA_MACRO_TX0 && + !test_bit(WSA_MACRO_TX0, + &wsa->active_ch_mask[WSA_MACRO_AIF_VI])) { + set_bit(WSA_MACRO_TX0, + &wsa->active_ch_mask[WSA_MACRO_AIF_VI]); + wsa->active_ch_cnt[WSA_MACRO_AIF_VI]++; + } + if (spk_tx_id == WSA_MACRO_TX1 && + !test_bit(WSA_MACRO_TX1, + &wsa->active_ch_mask[WSA_MACRO_AIF_VI])) { + set_bit(WSA_MACRO_TX1, + &wsa->active_ch_mask[WSA_MACRO_AIF_VI]); + wsa->active_ch_cnt[WSA_MACRO_AIF_VI]++; + } + } else { + if (spk_tx_id == WSA_MACRO_TX0 && + test_bit(WSA_MACRO_TX0, + &wsa->active_ch_mask[WSA_MACRO_AIF_VI])) { + clear_bit(WSA_MACRO_TX0, + &wsa->active_ch_mask[WSA_MACRO_AIF_VI]); + wsa->active_ch_cnt[WSA_MACRO_AIF_VI]--; + } + if (spk_tx_id == WSA_MACRO_TX1 && + test_bit(WSA_MACRO_TX1, + &wsa->active_ch_mask[WSA_MACRO_AIF_VI])) { + clear_bit(WSA_MACRO_TX1, + &wsa->active_ch_mask[WSA_MACRO_AIF_VI]); + wsa->active_ch_cnt[WSA_MACRO_AIF_VI]--; + } + } + snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, NULL); + + return 0; +} + +static const struct snd_kcontrol_new aif_vi_mixer[] = { + SOC_SINGLE_EXT("WSA_SPKR_VI_1", SND_SOC_NOPM, WSA_MACRO_TX0, 1, 0, + wsa_macro_vi_feed_mixer_get, + wsa_macro_vi_feed_mixer_put), + SOC_SINGLE_EXT("WSA_SPKR_VI_2", SND_SOC_NOPM, WSA_MACRO_TX1, 1, 0, + wsa_macro_vi_feed_mixer_get, + wsa_macro_vi_feed_mixer_put), +}; + +static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("WSA AIF1 PB", "WSA_AIF1 Playback", 0, + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("WSA AIF_MIX1 PB", "WSA_AIF_MIX1 Playback", 0, + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_AIF_OUT_E("WSA AIF_VI", "WSA_AIF_VI Capture", 0, + SND_SOC_NOPM, WSA_MACRO_AIF_VI, 0, + wsa_macro_enable_vi_feedback, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_AIF_OUT("WSA AIF_ECHO", "WSA_AIF_ECHO Capture", 0, + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_MIXER("WSA_AIF_VI Mixer", SND_SOC_NOPM, WSA_MACRO_AIF_VI, + 0, aif_vi_mixer, ARRAY_SIZE(aif_vi_mixer)), + SND_SOC_DAPM_MUX_E("WSA RX_MIX EC0_MUX", SND_SOC_NOPM, + WSA_MACRO_EC0_MUX, 0, + &rx_mix_ec0_mux, wsa_macro_enable_echo, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("WSA RX_MIX EC1_MUX", SND_SOC_NOPM, + WSA_MACRO_EC1_MUX, 0, + &rx_mix_ec1_mux, wsa_macro_enable_echo, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX("WSA RX0 MUX", SND_SOC_NOPM, WSA_MACRO_RX0, 0, + &rx_mux[WSA_MACRO_RX0]), + SND_SOC_DAPM_MUX("WSA RX1 MUX", SND_SOC_NOPM, WSA_MACRO_RX1, 0, + &rx_mux[WSA_MACRO_RX1]), + SND_SOC_DAPM_MUX("WSA RX_MIX0 MUX", SND_SOC_NOPM, WSA_MACRO_RX_MIX0, 0, + &rx_mux[WSA_MACRO_RX_MIX0]), + SND_SOC_DAPM_MUX("WSA RX_MIX1 MUX", SND_SOC_NOPM, WSA_MACRO_RX_MIX1, 0, + &rx_mux[WSA_MACRO_RX_MIX1]), + + SND_SOC_DAPM_MIXER("WSA RX0", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("WSA RX1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("WSA RX_MIX0", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("WSA RX_MIX1", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_MUX("WSA_RX0 INP0", SND_SOC_NOPM, 0, 0, &rx0_prim_inp0_mux), + SND_SOC_DAPM_MUX("WSA_RX0 INP1", SND_SOC_NOPM, 0, 0, &rx0_prim_inp1_mux), + SND_SOC_DAPM_MUX("WSA_RX0 INP2", SND_SOC_NOPM, 0, 0, &rx0_prim_inp2_mux), + SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", CDC_WSA_RX0_RX_PATH_MIX_CTL, + 0, 0, &rx0_mix_mux, wsa_macro_enable_mix_path, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX("WSA_RX1 INP0", SND_SOC_NOPM, 0, 0, &rx1_prim_inp0_mux), + SND_SOC_DAPM_MUX("WSA_RX1 INP1", SND_SOC_NOPM, 0, 0, &rx1_prim_inp1_mux), + SND_SOC_DAPM_MUX("WSA_RX1 INP2", SND_SOC_NOPM, 0, 0, &rx1_prim_inp2_mux), + SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", CDC_WSA_RX1_RX_PATH_MIX_CTL, + 0, 0, &rx1_mix_mux, wsa_macro_enable_mix_path, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MIXER_E("WSA_RX INT0 MIX", SND_SOC_NOPM, 0, 0, NULL, 0, + wsa_macro_enable_main_path, SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_MIXER_E("WSA_RX INT1 MIX", SND_SOC_NOPM, 1, 0, NULL, 0, + wsa_macro_enable_main_path, SND_SOC_DAPM_PRE_PMU), + + SND_SOC_DAPM_MIXER("WSA_RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("WSA_RX INT1 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_MUX("WSA_RX0 INT0 SIDETONE MIX", CDC_WSA_RX0_RX_PATH_CFG1, + 4, 0, &rx0_sidetone_mix_mux), + + SND_SOC_DAPM_INPUT("WSA SRC0_INP"), + SND_SOC_DAPM_INPUT("WSA_TX DEC0_INP"), + SND_SOC_DAPM_INPUT("WSA_TX DEC1_INP"), + + SND_SOC_DAPM_MIXER_E("WSA_RX INT0 INTERP", SND_SOC_NOPM, + WSA_MACRO_COMP1, 0, NULL, 0, + wsa_macro_enable_interpolator, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MIXER_E("WSA_RX INT1 INTERP", SND_SOC_NOPM, + WSA_MACRO_COMP2, 0, NULL, 0, + wsa_macro_enable_interpolator, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MIXER_E("WSA_RX INT0 CHAIN", SND_SOC_NOPM, 0, 0, + NULL, 0, wsa_macro_spk_boost_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MIXER_E("WSA_RX INT1 CHAIN", SND_SOC_NOPM, 0, 0, + NULL, 0, wsa_macro_spk_boost_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_INPUT("VIINPUT_WSA"), + SND_SOC_DAPM_OUTPUT("WSA_SPK1 OUT"), + SND_SOC_DAPM_OUTPUT("WSA_SPK2 OUT"), + + SND_SOC_DAPM_SUPPLY("WSA_RX0_CLK", CDC_WSA_RX0_RX_PATH_CTL, 5, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("WSA_RX1_CLK", CDC_WSA_RX1_RX_PATH_CTL, 5, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("WSA_RX_MIX0_CLK", CDC_WSA_RX0_RX_PATH_MIX_CTL, 5, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("WSA_RX_MIX1_CLK", CDC_WSA_RX1_RX_PATH_MIX_CTL, 5, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("WSA_MCLK", 0, SND_SOC_NOPM, 0, 0, + wsa_macro_mclk_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route wsa_audio_map[] = { + /* VI Feedback */ + {"WSA_AIF_VI Mixer", "WSA_SPKR_VI_1", "VIINPUT_WSA"}, + {"WSA_AIF_VI Mixer", "WSA_SPKR_VI_2", "VIINPUT_WSA"}, + {"WSA AIF_VI", NULL, "WSA_AIF_VI Mixer"}, + {"WSA AIF_VI", NULL, "WSA_MCLK"}, + + {"WSA RX_MIX EC0_MUX", "RX_MIX_TX0", "WSA_RX INT0 SEC MIX"}, + {"WSA RX_MIX EC1_MUX", "RX_MIX_TX0", "WSA_RX INT0 SEC MIX"}, + {"WSA RX_MIX EC0_MUX", "RX_MIX_TX1", "WSA_RX INT1 SEC MIX"}, + {"WSA RX_MIX EC1_MUX", "RX_MIX_TX1", "WSA_RX INT1 SEC MIX"}, + {"WSA AIF_ECHO", NULL, "WSA RX_MIX EC0_MUX"}, + {"WSA AIF_ECHO", NULL, "WSA RX_MIX EC1_MUX"}, + {"WSA AIF_ECHO", NULL, "WSA_MCLK"}, + + {"WSA AIF1 PB", NULL, "WSA_MCLK"}, + {"WSA AIF_MIX1 PB", NULL, "WSA_MCLK"}, + + {"WSA RX0 MUX", "AIF1_PB", "WSA AIF1 PB"}, + {"WSA RX1 MUX", "AIF1_PB", "WSA AIF1 PB"}, + {"WSA RX_MIX0 MUX", "AIF1_PB", "WSA AIF1 PB"}, + {"WSA RX_MIX1 MUX", "AIF1_PB", "WSA AIF1 PB"}, + + {"WSA RX0 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"}, + {"WSA RX1 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"}, + {"WSA RX_MIX0 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"}, + {"WSA RX_MIX1 MUX", "AIF_MIX1_PB", "WSA AIF_MIX1 PB"}, + + {"WSA RX0", NULL, "WSA RX0 MUX"}, + {"WSA RX1", NULL, "WSA RX1 MUX"}, + {"WSA RX_MIX0", NULL, "WSA RX_MIX0 MUX"}, + {"WSA RX_MIX1", NULL, "WSA RX_MIX1 MUX"}, + + {"WSA RX0", NULL, "WSA_RX0_CLK"}, + {"WSA RX1", NULL, "WSA_RX1_CLK"}, + {"WSA RX_MIX0", NULL, "WSA_RX_MIX0_CLK"}, + {"WSA RX_MIX1", NULL, "WSA_RX_MIX1_CLK"}, + + {"WSA_RX0 INP0", "RX0", "WSA RX0"}, + {"WSA_RX0 INP0", "RX1", "WSA RX1"}, + {"WSA_RX0 INP0", "RX_MIX0", "WSA RX_MIX0"}, + {"WSA_RX0 INP0", "RX_MIX1", "WSA RX_MIX1"}, + {"WSA_RX0 INP0", "DEC0", "WSA_TX DEC0_INP"}, + {"WSA_RX0 INP0", "DEC1", "WSA_TX DEC1_INP"}, + {"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP0"}, + + {"WSA_RX0 INP1", "RX0", "WSA RX0"}, + {"WSA_RX0 INP1", "RX1", "WSA RX1"}, + {"WSA_RX0 INP1", "RX_MIX0", "WSA RX_MIX0"}, + {"WSA_RX0 INP1", "RX_MIX1", "WSA RX_MIX1"}, + {"WSA_RX0 INP1", "DEC0", "WSA_TX DEC0_INP"}, + {"WSA_RX0 INP1", "DEC1", "WSA_TX DEC1_INP"}, + {"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP1"}, + + {"WSA_RX0 INP2", "RX0", "WSA RX0"}, + {"WSA_RX0 INP2", "RX1", "WSA RX1"}, + {"WSA_RX0 INP2", "RX_MIX0", "WSA RX_MIX0"}, + {"WSA_RX0 INP2", "RX_MIX1", "WSA RX_MIX1"}, + {"WSA_RX0 INP2", "DEC0", "WSA_TX DEC0_INP"}, + {"WSA_RX0 INP2", "DEC1", "WSA_TX DEC1_INP"}, + {"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP2"}, + + {"WSA_RX0 MIX INP", "RX0", "WSA RX0"}, + {"WSA_RX0 MIX INP", "RX1", "WSA RX1"}, + {"WSA_RX0 MIX INP", "RX_MIX0", "WSA RX_MIX0"}, + {"WSA_RX0 MIX INP", "RX_MIX1", "WSA RX_MIX1"}, + {"WSA_RX INT0 SEC MIX", NULL, "WSA_RX0 MIX INP"}, + + {"WSA_RX INT0 SEC MIX", NULL, "WSA_RX INT0 MIX"}, + {"WSA_RX INT0 INTERP", NULL, "WSA_RX INT0 SEC MIX"}, + {"WSA_RX0 INT0 SIDETONE MIX", "SRC0", "WSA SRC0_INP"}, + {"WSA_RX INT0 INTERP", NULL, "WSA_RX0 INT0 SIDETONE MIX"}, + {"WSA_RX INT0 CHAIN", NULL, "WSA_RX INT0 INTERP"}, + + {"WSA_SPK1 OUT", NULL, "WSA_RX INT0 CHAIN"}, + {"WSA_SPK1 OUT", NULL, "WSA_MCLK"}, + + {"WSA_RX1 INP0", "RX0", "WSA RX0"}, + {"WSA_RX1 INP0", "RX1", "WSA RX1"}, + {"WSA_RX1 INP0", "RX_MIX0", "WSA RX_MIX0"}, + {"WSA_RX1 INP0", "RX_MIX1", "WSA RX_MIX1"}, + {"WSA_RX1 INP0", "DEC0", "WSA_TX DEC0_INP"}, + {"WSA_RX1 INP0", "DEC1", "WSA_TX DEC1_INP"}, + {"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP0"}, + + {"WSA_RX1 INP1", "RX0", "WSA RX0"}, + {"WSA_RX1 INP1", "RX1", "WSA RX1"}, + {"WSA_RX1 INP1", "RX_MIX0", "WSA RX_MIX0"}, + {"WSA_RX1 INP1", "RX_MIX1", "WSA RX_MIX1"}, + {"WSA_RX1 INP1", "DEC0", "WSA_TX DEC0_INP"}, + {"WSA_RX1 INP1", "DEC1", "WSA_TX DEC1_INP"}, + {"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP1"}, + + {"WSA_RX1 INP2", "RX0", "WSA RX0"}, + {"WSA_RX1 INP2", "RX1", "WSA RX1"}, + {"WSA_RX1 INP2", "RX_MIX0", "WSA RX_MIX0"}, + {"WSA_RX1 INP2", "RX_MIX1", "WSA RX_MIX1"}, + {"WSA_RX1 INP2", "DEC0", "WSA_TX DEC0_INP"}, + {"WSA_RX1 INP2", "DEC1", "WSA_TX DEC1_INP"}, + {"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP2"}, + + {"WSA_RX1 MIX INP", "RX0", "WSA RX0"}, + {"WSA_RX1 MIX INP", "RX1", "WSA RX1"}, + {"WSA_RX1 MIX INP", "RX_MIX0", "WSA RX_MIX0"}, + {"WSA_RX1 MIX INP", "RX_MIX1", "WSA RX_MIX1"}, + {"WSA_RX INT1 SEC MIX", NULL, "WSA_RX1 MIX INP"}, + + {"WSA_RX INT1 SEC MIX", NULL, "WSA_RX INT1 MIX"}, + {"WSA_RX INT1 INTERP", NULL, "WSA_RX INT1 SEC MIX"}, + + {"WSA_RX INT1 CHAIN", NULL, "WSA_RX INT1 INTERP"}, + {"WSA_SPK2 OUT", NULL, "WSA_RX INT1 CHAIN"}, + {"WSA_SPK2 OUT", NULL, "WSA_MCLK"}, +}; + static int wsa_swrm_clock(struct wsa_macro *wsa, bool enable) { struct regmap *regmap = wsa->regmap; @@ -1292,6 +2369,10 @@ static const struct snd_soc_component_driver wsa_macro_component_drv = { .probe = wsa_macro_component_probe, .controls = wsa_macro_snd_controls, .num_controls = ARRAY_SIZE(wsa_macro_snd_controls), + .dapm_widgets = wsa_macro_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wsa_macro_dapm_widgets), + .dapm_routes = wsa_audio_map, + .num_dapm_routes = ARRAY_SIZE(wsa_audio_map), }; static int wsa_macro_probe(struct platform_device *pdev) From patchwork Thu Nov 5 11:34:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 317940 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 59E89C388F7 for ; Thu, 5 Nov 2020 11:37:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E6BF920936 for ; Thu, 5 Nov 2020 11:37:15 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="A5gN26/Q" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730243AbgKELg2 (ORCPT ); Thu, 5 Nov 2020 06:36:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45474 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730424AbgKELfJ (ORCPT ); Thu, 5 Nov 2020 06:35:09 -0500 Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0D979C0613D6 for ; Thu, 5 Nov 2020 03:35:09 -0800 (PST) Received: by mail-wr1-x42e.google.com with SMTP id x7so1367427wrl.3 for ; Thu, 05 Nov 2020 03:35:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=h26eF40PaZ6KFdIeJwqF0Jrhx2dZ+TjpA76DU5/WGXs=; b=A5gN26/QGnbFvWXObUHshDqAtdfrClrjhHVzBuZ2Em2uF1PHbH4rhMRUWcxsKi3aS2 Npc/b7sch95U53NAI9/xCSy3FOM9XALICFJfyZvurXHYfDQXw322nZqcEtynhR8L+yLu NIAE26kV3+aPVl0X0+8YSmbuOEC0PUEVwoR1HeZNN9/JmfcxDX+6jgzCA7eHPYe6F8Yx HF5bzJQULgMQtlxkn0TZoGFhE3Qcj+1vP4otC+CI2G8/qDgATB5nXKRXmC3Iy1ermgxS X5U6w37i5mEr7Eoa7eW5sr40UGS6t5UA8SyMSM7cuF7QdctTJ0+rg0Sj4qvgCs0y4tzv Umig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=h26eF40PaZ6KFdIeJwqF0Jrhx2dZ+TjpA76DU5/WGXs=; b=jDFi9n06ZYj+9OUf4ivrOMybdAJ/Ah+1Non8sgv58QxG+umI83reLlJ7QoGFxFEjXN XTzprghqV/pSkObfoFKJ7xAZ9W9frAIHo1O/UQI7DVruhano1YIwoyeHSFR719JyN4FL tfhfoNTl2qZa4nPyPimdbhgIGZhBsQXJNHATNuE+WOyxwwfOBYqssyzlln8sZLlAyniJ jyVwtGxryoVx0Ml5fFooH7GJneuaBSDvv/jTGuCVLUy6e3YlX1vkFKzr2wn8IiwfZDq3 IX11UrM/euywXAG7VWZgMln5ijEUiT/vrAlmwowuYiSZ2a+vtkSzZWDLUrjEi4erQ4rJ XykQ== X-Gm-Message-State: AOAM531Hhep/7+A8+nCf6SmNgNsUDYoDDCcW6VRVhkJXN04hA33iSKmj OdUzIn05eZzdTTdjEaclmCfOLQ== X-Google-Smtp-Source: ABdhPJzVH+JLYWx3/VdBd29lN0VHHvZvfqQqzrKcNGXGXvJOP8nTqgblg5xpxlLZ5X7yOtAzJmWlcg== X-Received: by 2002:adf:eaca:: with SMTP id o10mr2513853wrn.9.1604576107810; Thu, 05 Nov 2020 03:35:07 -0800 (PST) Received: from srini-hackbox.lan (cpc86377-aztw32-2-0-cust226.18-1.cable.virginm.net. [92.233.226.227]) by smtp.gmail.com with ESMTPSA id t199sm2096129wmt.46.2020.11.05.03.35.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Nov 2020 03:35:06 -0800 (PST) From: Srinivas Kandagatla To: broonie@kernel.org Cc: perex@perex.cz, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org, lgirdwood@gmail.com, devicetree@vger.kernel.org, robh+dt@kernel.org, Srinivas Kandagatla , Rob Herring Subject: [PATCH v3 4/6] ASoC: qcom: dt-bindings: add bindings for lpass va macro codec Date: Thu, 5 Nov 2020 11:34:56 +0000 Message-Id: <20201105113458.12360-5-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20201105113458.12360-1-srinivas.kandagatla@linaro.org> References: <20201105113458.12360-1-srinivas.kandagatla@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This binding is for LPASS has internal codec VA macro which is for connecting with DMICs. Signed-off-by: Srinivas Kandagatla Reviewed-by: Rob Herring --- .../bindings/sound/qcom,lpass-va-macro.yaml | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml new file mode 100644 index 000000000000..679b49cbe30f --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/qcom,lpass-va-macro.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: LPASS(Low Power Audio Subsystem) VA Macro audio codec DT bindings + +maintainers: + - Srinivas Kandagatla + +properties: + compatible: + const: qcom,sm8250-lpass-va-macro + + reg: + maxItems: 1 + + "#sound-dai-cells": + const: 1 + + '#clock-cells': + const: 0 + + clocks: + maxItems: 3 + + clock-names: + items: + - const: mclk + - const: core + - const: dcodec + + clock-output-names: + items: + - const: fsgen + + qcom,dmic-sample-rate: + description: dmic sample rate + $ref: /schemas/types.yaml#/definitions/uint32 + + vdd-micb-supply: + description: phandle to voltage regulator of MIC Bias + +required: + - compatible + - reg + - "#sound-dai-cells" + +additionalProperties: false + +examples: + - | + #include + codec@3370000 { + compatible = "qcom,sm8250-lpass-va-macro"; + reg = <0x3370000 0x1000>; + #sound-dai-cells = <1>; + #clock-cells = <0>; + clocks = <&aoncc 0>, + <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "mclk", "core", "dcodec"; + clock-output-names = "fsgen"; + qcom,dmic-sample-rate = <600000>; + vdd-micb-supply = <&vreg_s4a_1p8>; + }; From patchwork Thu Nov 5 11:34:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 317939 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id ECA33C4742C for ; Thu, 5 Nov 2020 11:37:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8255520936 for ; Thu, 5 Nov 2020 11:37:16 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="iUeLYfIR" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730276AbgKELg1 (ORCPT ); Thu, 5 Nov 2020 06:36:27 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45482 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730427AbgKELfK (ORCPT ); Thu, 5 Nov 2020 06:35:10 -0500 Received: from mail-wr1-x444.google.com (mail-wr1-x444.google.com [IPv6:2a00:1450:4864:20::444]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 751A3C0613D2 for ; Thu, 5 Nov 2020 03:35:10 -0800 (PST) Received: by mail-wr1-x444.google.com with SMTP id c17so1336898wrc.11 for ; Thu, 05 Nov 2020 03:35:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=TOc+929ryae+ejgKWNHXpw1/8osjlMWtjtqzNTmZAFs=; b=iUeLYfIRbxR2BXXzOdj4W1fi+qA4UYphXHk/T7rCGaw8Yy59L/i86MvO1+niMR3If2 WMF3uVIUIskv4/gQv9vV1HB79oBOL4PfrAuknnEBuwJMSpGcowndpWWg6PV/1L054p3j mVJYcW9nyY1FTt+fi1QLYDD6RBOLIPiwLnYjODFmiadd8PUk9jXV8EgymeT+w6EHKSrZ KimsuNK60zMCWlgKap4xymPYBcqOzxttxY9MOYKw74/TZHiPA1z4Vr1PXzx8pVk1UpAT A/wepPG30xAJumuDOguSqu8xvS4zA2Heap+5Ez40ghVTCtV3UzcPlUTrSpTiM/5LSqQd 0uvw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=TOc+929ryae+ejgKWNHXpw1/8osjlMWtjtqzNTmZAFs=; b=MjtRoXzkHN347tD70+LRKwCbWTFNrkEpY0eC+t0So99QNCsIvJRf3D1t4StLBPw027 +pmt5LGmBx279fJq1LeRH+7TMSQDhJBB1UZnWI/oCIjFDfdvbhuhL4AAFn0YvaM7FXpa nsGqeAY+BYl3gE1vy/cvXmPWcUNqAfcKMOm8c7/AZxSoGDR/rh+4z2Wcl4oY3ayZ8r33 0hrgvdTPYCkLTjimOf1wABYYlXBYzPo5iSsL3onN8oA9rOWvyEkjNp4XbF6Cyn4whpUv B5FyddQc0ZezXIvVb0NM2agSQ60pKTccmVzEBpc5a6ilzIDt7xMNzqSlb8OxKLC6IszA Qq2Q== X-Gm-Message-State: AOAM532p76qoCZb4SFdP9vdVItXIbUvoKKoIksIAuFAzz4LTIhF3FN23 oJxlWCmg0pFsx2bEQlfR6EdYMw== X-Google-Smtp-Source: ABdhPJy7b1nTN0V0Ak4e9OoPtIr6+JBU4Eg7+EIsvapy92m98PM9GSQ8WREy0WjKN/m9KMeyiCsOVQ== X-Received: by 2002:a5d:628f:: with SMTP id k15mr697650wru.148.1604576109094; Thu, 05 Nov 2020 03:35:09 -0800 (PST) Received: from srini-hackbox.lan (cpc86377-aztw32-2-0-cust226.18-1.cable.virginm.net. [92.233.226.227]) by smtp.gmail.com with ESMTPSA id t199sm2096129wmt.46.2020.11.05.03.35.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Nov 2020 03:35:08 -0800 (PST) From: Srinivas Kandagatla To: broonie@kernel.org Cc: perex@perex.cz, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org, lgirdwood@gmail.com, devicetree@vger.kernel.org, robh+dt@kernel.org, Srinivas Kandagatla Subject: [PATCH v3 5/6] ASoC: codecs: lpass-va-macro: Add support to VA Macro Date: Thu, 5 Nov 2020 11:34:57 +0000 Message-Id: <20201105113458.12360-6-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20201105113458.12360-1-srinivas.kandagatla@linaro.org> References: <20201105113458.12360-1-srinivas.kandagatla@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Qualcomm LPASS (Low Power Audio SubSystem) has internal codec VA macro block which is used for connecting with DMICs. This patch adds support to the codec part of the VA Macro block Signed-off-by: Srinivas Kandagatla --- sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/lpass-va-macro.c | 883 ++++++++++++++++++++++++++++++ 3 files changed, 889 insertions(+) create mode 100644 sound/soc/codecs/lpass-va-macro.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index d91b51470a73..98d8624fec26 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -1788,4 +1788,8 @@ config SND_SOC_LPASS_WSA_MACRO depends on COMMON_CLK tristate "Qualcomm WSA Macro in LPASS(Low Power Audio SubSystem)" +config SND_SOC_LPASS_VA_MACRO + depends on COMMON_CLK + tristate "Qualcomm VA Macro in LPASS(Low Power Audio SubSystem)" + endmenu diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 9f24b3daf5df..5d68da2b1182 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -104,6 +104,7 @@ snd-soc-lm4857-objs := lm4857.o snd-soc-lm49453-objs := lm49453.o snd-soc-lochnagar-sc-objs := lochnagar-sc.o snd-soc-lpass-wsa-macro-objs := lpass-wsa-macro.o +snd-soc-lpass-va-macro-objs := lpass-va-macro.o snd-soc-madera-objs := madera.o snd-soc-max9759-objs := max9759.o snd-soc-max9768-objs := max9768.o @@ -615,3 +616,4 @@ obj-$(CONFIG_SND_SOC_MAX98504) += snd-soc-max98504.o obj-$(CONFIG_SND_SOC_SIMPLE_AMPLIFIER) += snd-soc-simple-amplifier.o obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o obj-$(CONFIG_SND_SOC_LPASS_WSA_MACRO) += snd-soc-lpass-wsa-macro.o +obj-$(CONFIG_SND_SOC_LPASS_VA_MACRO) += snd-soc-lpass-va-macro.o diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c new file mode 100644 index 000000000000..e7590e70f2c0 --- /dev/null +++ b/sound/soc/codecs/lpass-va-macro.c @@ -0,0 +1,883 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* VA macro registers */ +#define CDC_VA_CLK_RST_CTRL_MCLK_CONTROL (0x0000) +#define CDC_VA_MCLK_CONTROL_EN BIT(0) +#define CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL (0x0004) +#define CDC_VA_FS_CONTROL_EN BIT(0) +#define CDC_VA_CLK_RST_CTRL_SWR_CONTROL (0x0008) +#define CDC_VA_TOP_CSR_TOP_CFG0 (0x0080) +#define CDC_VA_FS_BROADCAST_EN BIT(1) +#define CDC_VA_TOP_CSR_DMIC0_CTL (0x0084) +#define CDC_VA_TOP_CSR_DMIC1_CTL (0x0088) +#define CDC_VA_TOP_CSR_DMIC2_CTL (0x008C) +#define CDC_VA_TOP_CSR_DMIC3_CTL (0x0090) +#define CDC_VA_DMIC_CLK_SEL_MASK GENMASK(3, 1) +#define CDC_VA_DMIC_CLK_SEL_SHFT 1 +#define CDC_VA_DMIC_CLK_SEL_DIV0 0x0 +#define CDC_VA_DMIC_CLK_SEL_DIV1 0x2 +#define CDC_VA_DMIC_CLK_SEL_DIV2 0x4 +#define CDC_VA_DMIC_CLK_SEL_DIV3 0x6 +#define CDC_VA_DMIC_CLK_SEL_DIV4 0x8 +#define CDC_VA_DMIC_CLK_SEL_DIV5 0xa +#define CDC_VA_TOP_CSR_DMIC_CFG (0x0094) +#define CDC_VA_RESET_ALL_DMICS_MASK BIT(7) +#define CDC_VA_RESET_ALL_DMICS_RESET BIT(7) +#define CDC_VA_RESET_ALL_DMICS_DISABLE 0 +#define CDC_VA_DMIC3_FREQ_CHANGE_MASK BIT(3) +#define CDC_VA_DMIC3_FREQ_CHANGE_EN BIT(3) +#define CDC_VA_DMIC2_FREQ_CHANGE_MASK BIT(2) +#define CDC_VA_DMIC2_FREQ_CHANGE_EN BIT(2) +#define CDC_VA_DMIC1_FREQ_CHANGE_MASK BIT(1) +#define CDC_VA_DMIC1_FREQ_CHANGE_EN BIT(1) +#define CDC_VA_DMIC0_FREQ_CHANGE_MASK BIT(0) +#define CDC_VA_DMIC0_FREQ_CHANGE_EN BIT(0) +#define CDC_VA_DMIC_FREQ_CHANGE_DISABLE 0 +#define CDC_VA_TOP_CSR_DEBUG_BUS (0x009C) +#define CDC_VA_TOP_CSR_DEBUG_EN (0x00A0) +#define CDC_VA_TOP_CSR_TX_I2S_CTL (0x00A4) +#define CDC_VA_TOP_CSR_I2S_CLK (0x00A8) +#define CDC_VA_TOP_CSR_I2S_RESET (0x00AC) +#define CDC_VA_TOP_CSR_CORE_ID_0 (0x00C0) +#define CDC_VA_TOP_CSR_CORE_ID_1 (0x00C4) +#define CDC_VA_TOP_CSR_CORE_ID_2 (0x00C8) +#define CDC_VA_TOP_CSR_CORE_ID_3 (0x00CC) +#define CDC_VA_TOP_CSR_SWR_MIC_CTL0 (0x00D0) +#define CDC_VA_TOP_CSR_SWR_MIC_CTL1 (0x00D4) +#define CDC_VA_TOP_CSR_SWR_MIC_CTL2 (0x00D8) +#define CDC_VA_TOP_CSR_SWR_CTRL (0x00DC) +#define CDC_VA_INP_MUX_ADC_MUX0_CFG0 (0x0100) +#define CDC_VA_INP_MUX_ADC_MUX0_CFG1 (0x0104) +#define CDC_VA_INP_MUX_ADC_MUX1_CFG0 (0x0108) +#define CDC_VA_INP_MUX_ADC_MUX1_CFG1 (0x010C) +#define CDC_VA_INP_MUX_ADC_MUX2_CFG0 (0x0110) +#define CDC_VA_INP_MUX_ADC_MUX2_CFG1 (0x0114) +#define CDC_VA_INP_MUX_ADC_MUX3_CFG0 (0x0118) +#define CDC_VA_INP_MUX_ADC_MUX3_CFG1 (0x011C) +#define CDC_VA_TX0_TX_PATH_CTL (0x0400) +#define CDC_VA_TX_PATH_CLK_EN_MASK BIT(5) +#define CDC_VA_TX_PATH_CLK_EN BIT(5) +#define CDC_VA_TX_PATH_CLK_DISABLE 0 +#define CDC_VA_TX_PATH_PGA_MUTE_EN_MASK BIT(4) +#define CDC_VA_TX_PATH_PGA_MUTE_EN BIT(4) +#define CDC_VA_TX_PATH_PGA_MUTE_DISABLE 0 +#define CDC_VA_TX0_TX_PATH_CFG0 (0x0404) +#define CDC_VA_ADC_MODE_MASK GENMASK(2, 1) +#define CDC_VA_ADC_MODE_SHIFT 1 +#define TX_HPF_CUT_OFF_FREQ_MASK GENMASK(6, 5) +#define CF_MIN_3DB_4HZ 0x0 +#define CF_MIN_3DB_75HZ 0x1 +#define CF_MIN_3DB_150HZ 0x2 +#define CDC_VA_TX0_TX_PATH_CFG1 (0x0408) +#define CDC_VA_TX0_TX_VOL_CTL (0x040C) +#define CDC_VA_TX0_TX_PATH_SEC0 (0x0410) +#define CDC_VA_TX0_TX_PATH_SEC1 (0x0414) +#define CDC_VA_TX0_TX_PATH_SEC2 (0x0418) +#define CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_MASK BIT(1) +#define CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_REQ BIT(1) +#define CDC_VA_TX_HPF_ZERO_GATE_MASK BIT(0) +#define CDC_VA_TX_HPF_ZERO_NO_GATE BIT(0) +#define CDC_VA_TX_HPF_ZERO_GATE 0 +#define CDC_VA_TX0_TX_PATH_SEC3 (0x041C) +#define CDC_VA_TX0_TX_PATH_SEC4 (0x0420) +#define CDC_VA_TX0_TX_PATH_SEC5 (0x0424) +#define CDC_VA_TX0_TX_PATH_SEC6 (0x0428) +#define CDC_VA_TX0_TX_PATH_SEC7 (0x042C) +#define CDC_VA_TX1_TX_PATH_CTL (0x0480) +#define CDC_VA_TX1_TX_PATH_CFG0 (0x0484) +#define CDC_VA_TX1_TX_PATH_CFG1 (0x0488) +#define CDC_VA_TX1_TX_VOL_CTL (0x048C) +#define CDC_VA_TX1_TX_PATH_SEC0 (0x0490) +#define CDC_VA_TX1_TX_PATH_SEC1 (0x0494) +#define CDC_VA_TX1_TX_PATH_SEC2 (0x0498) +#define CDC_VA_TX1_TX_PATH_SEC3 (0x049C) +#define CDC_VA_TX1_TX_PATH_SEC4 (0x04A0) +#define CDC_VA_TX1_TX_PATH_SEC5 (0x04A4) +#define CDC_VA_TX1_TX_PATH_SEC6 (0x04A8) +#define CDC_VA_TX2_TX_PATH_CTL (0x0500) +#define CDC_VA_TX2_TX_PATH_CFG0 (0x0504) +#define CDC_VA_TX2_TX_PATH_CFG1 (0x0508) +#define CDC_VA_TX2_TX_VOL_CTL (0x050C) +#define CDC_VA_TX2_TX_PATH_SEC0 (0x0510) +#define CDC_VA_TX2_TX_PATH_SEC1 (0x0514) +#define CDC_VA_TX2_TX_PATH_SEC2 (0x0518) +#define CDC_VA_TX2_TX_PATH_SEC3 (0x051C) +#define CDC_VA_TX2_TX_PATH_SEC4 (0x0520) +#define CDC_VA_TX2_TX_PATH_SEC5 (0x0524) +#define CDC_VA_TX2_TX_PATH_SEC6 (0x0528) +#define CDC_VA_TX3_TX_PATH_CTL (0x0580) +#define CDC_VA_TX3_TX_PATH_CFG0 (0x0584) +#define CDC_VA_TX_PATH_ADC_DMIC_SEL_MASK BIT(7) +#define CDC_VA_TX_PATH_ADC_DMIC_SEL_DMIC BIT(7) +#define CDC_VA_TX_PATH_ADC_DMIC_SEL_ADC 0 +#define CDC_VA_TX3_TX_PATH_CFG1 (0x0588) +#define CDC_VA_TX3_TX_VOL_CTL (0x058C) +#define CDC_VA_TX3_TX_PATH_SEC0 (0x0590) +#define CDC_VA_TX3_TX_PATH_SEC1 (0x0594) +#define CDC_VA_TX3_TX_PATH_SEC2 (0x0598) +#define CDC_VA_TX3_TX_PATH_SEC3 (0x059C) +#define CDC_VA_TX3_TX_PATH_SEC4 (0x05A0) +#define CDC_VA_TX3_TX_PATH_SEC5 (0x05A4) +#define CDC_VA_TX3_TX_PATH_SEC6 (0x05A8) + +#define VA_MAX_OFFSET (0x07A8) + +#define VA_MACRO_NUM_DECIMATORS 4 +#define VA_MACRO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) +#define VA_MACRO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S24_3LE) + +#define VA_MACRO_MCLK_FREQ 9600000 +#define VA_MACRO_TX_PATH_OFFSET 0x80 +#define VA_MACRO_SWR_MIC_MUX_SEL_MASK 0xF +#define VA_MACRO_ADC_MUX_CFG_OFFSET 0x8 + +static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400); + +enum { + VA_MACRO_AIF_INVALID = 0, + VA_MACRO_AIF1_CAP, + VA_MACRO_AIF2_CAP, + VA_MACRO_AIF3_CAP, + VA_MACRO_MAX_DAIS, +}; + +enum { + VA_MACRO_DEC0, + VA_MACRO_DEC1, + VA_MACRO_DEC2, + VA_MACRO_DEC3, + VA_MACRO_DEC4, + VA_MACRO_DEC5, + VA_MACRO_DEC6, + VA_MACRO_DEC7, + VA_MACRO_DEC_MAX, +}; + +enum { + VA_MACRO_CLK_DIV_2, + VA_MACRO_CLK_DIV_3, + VA_MACRO_CLK_DIV_4, + VA_MACRO_CLK_DIV_6, + VA_MACRO_CLK_DIV_8, + VA_MACRO_CLK_DIV_16, +}; + +#define VA_NUM_CLKS_MAX 3 + +struct va_macro { + struct device *dev; + unsigned long active_ch_mask[VA_MACRO_MAX_DAIS]; + unsigned long active_ch_cnt[VA_MACRO_MAX_DAIS]; + unsigned long active_decimator[VA_MACRO_MAX_DAIS]; + u16 dmic_clk_div; + + int dec_mode[VA_MACRO_NUM_DECIMATORS]; + struct regmap *regmap; + struct clk_bulk_data clks[VA_NUM_CLKS_MAX]; + struct clk_hw hw; + + s32 dmic_0_1_clk_cnt; + s32 dmic_2_3_clk_cnt; + s32 dmic_4_5_clk_cnt; + s32 dmic_6_7_clk_cnt; + u8 dmic_0_1_clk_div; + u8 dmic_2_3_clk_div; + u8 dmic_4_5_clk_div; + u8 dmic_6_7_clk_div; +}; + +#define to_va_macro(_hw) container_of(_hw, struct va_macro, hw) + +static bool va_is_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CDC_VA_TOP_CSR_CORE_ID_0: + case CDC_VA_TOP_CSR_CORE_ID_1: + case CDC_VA_TOP_CSR_CORE_ID_2: + case CDC_VA_TOP_CSR_CORE_ID_3: + case CDC_VA_TOP_CSR_DMIC0_CTL: + case CDC_VA_TOP_CSR_DMIC1_CTL: + case CDC_VA_TOP_CSR_DMIC2_CTL: + case CDC_VA_TOP_CSR_DMIC3_CTL: + return true; + } + return false; +} + +static const struct reg_default va_defaults[] = { + /* VA macro */ + { CDC_VA_CLK_RST_CTRL_MCLK_CONTROL, 0x00}, + { CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00}, + { CDC_VA_CLK_RST_CTRL_SWR_CONTROL, 0x00}, + { CDC_VA_TOP_CSR_TOP_CFG0, 0x00}, + { CDC_VA_TOP_CSR_DMIC0_CTL, 0x00}, + { CDC_VA_TOP_CSR_DMIC1_CTL, 0x00}, + { CDC_VA_TOP_CSR_DMIC2_CTL, 0x00}, + { CDC_VA_TOP_CSR_DMIC3_CTL, 0x00}, + { CDC_VA_TOP_CSR_DMIC_CFG, 0x80}, + { CDC_VA_TOP_CSR_DEBUG_BUS, 0x00}, + { CDC_VA_TOP_CSR_DEBUG_EN, 0x00}, + { CDC_VA_TOP_CSR_TX_I2S_CTL, 0x0C}, + { CDC_VA_TOP_CSR_I2S_CLK, 0x00}, + { CDC_VA_TOP_CSR_I2S_RESET, 0x00}, + { CDC_VA_TOP_CSR_CORE_ID_0, 0x00}, + { CDC_VA_TOP_CSR_CORE_ID_1, 0x00}, + { CDC_VA_TOP_CSR_CORE_ID_2, 0x00}, + { CDC_VA_TOP_CSR_CORE_ID_3, 0x00}, + { CDC_VA_TOP_CSR_SWR_MIC_CTL0, 0xEE}, + { CDC_VA_TOP_CSR_SWR_MIC_CTL1, 0xEE}, + { CDC_VA_TOP_CSR_SWR_MIC_CTL2, 0xEE}, + { CDC_VA_TOP_CSR_SWR_CTRL, 0x06}, + + /* VA core */ + { CDC_VA_INP_MUX_ADC_MUX0_CFG0, 0x00}, + { CDC_VA_INP_MUX_ADC_MUX0_CFG1, 0x00}, + { CDC_VA_INP_MUX_ADC_MUX1_CFG0, 0x00}, + { CDC_VA_INP_MUX_ADC_MUX1_CFG1, 0x00}, + { CDC_VA_INP_MUX_ADC_MUX2_CFG0, 0x00}, + { CDC_VA_INP_MUX_ADC_MUX2_CFG1, 0x00}, + { CDC_VA_INP_MUX_ADC_MUX3_CFG0, 0x00}, + { CDC_VA_INP_MUX_ADC_MUX3_CFG1, 0x00}, + { CDC_VA_TX0_TX_PATH_CTL, 0x04}, + { CDC_VA_TX0_TX_PATH_CFG0, 0x10}, + { CDC_VA_TX0_TX_PATH_CFG1, 0x0B}, + { CDC_VA_TX0_TX_VOL_CTL, 0x00}, + { CDC_VA_TX0_TX_PATH_SEC0, 0x00}, + { CDC_VA_TX0_TX_PATH_SEC1, 0x00}, + { CDC_VA_TX0_TX_PATH_SEC2, 0x01}, + { CDC_VA_TX0_TX_PATH_SEC3, 0x3C}, + { CDC_VA_TX0_TX_PATH_SEC4, 0x20}, + { CDC_VA_TX0_TX_PATH_SEC5, 0x00}, + { CDC_VA_TX0_TX_PATH_SEC6, 0x00}, + { CDC_VA_TX0_TX_PATH_SEC7, 0x25}, + { CDC_VA_TX1_TX_PATH_CTL, 0x04}, + { CDC_VA_TX1_TX_PATH_CFG0, 0x10}, + { CDC_VA_TX1_TX_PATH_CFG1, 0x0B}, + { CDC_VA_TX1_TX_VOL_CTL, 0x00}, + { CDC_VA_TX1_TX_PATH_SEC0, 0x00}, + { CDC_VA_TX1_TX_PATH_SEC1, 0x00}, + { CDC_VA_TX1_TX_PATH_SEC2, 0x01}, + { CDC_VA_TX1_TX_PATH_SEC3, 0x3C}, + { CDC_VA_TX1_TX_PATH_SEC4, 0x20}, + { CDC_VA_TX1_TX_PATH_SEC5, 0x00}, + { CDC_VA_TX1_TX_PATH_SEC6, 0x00}, + { CDC_VA_TX2_TX_PATH_CTL, 0x04}, + { CDC_VA_TX2_TX_PATH_CFG0, 0x10}, + { CDC_VA_TX2_TX_PATH_CFG1, 0x0B}, + { CDC_VA_TX2_TX_VOL_CTL, 0x00}, + { CDC_VA_TX2_TX_PATH_SEC0, 0x00}, + { CDC_VA_TX2_TX_PATH_SEC1, 0x00}, + { CDC_VA_TX2_TX_PATH_SEC2, 0x01}, + { CDC_VA_TX2_TX_PATH_SEC3, 0x3C}, + { CDC_VA_TX2_TX_PATH_SEC4, 0x20}, + { CDC_VA_TX2_TX_PATH_SEC5, 0x00}, + { CDC_VA_TX2_TX_PATH_SEC6, 0x00}, + { CDC_VA_TX3_TX_PATH_CTL, 0x04}, + { CDC_VA_TX3_TX_PATH_CFG0, 0x10}, + { CDC_VA_TX3_TX_PATH_CFG1, 0x0B}, + { CDC_VA_TX3_TX_VOL_CTL, 0x00}, + { CDC_VA_TX3_TX_PATH_SEC0, 0x00}, + { CDC_VA_TX3_TX_PATH_SEC1, 0x00}, + { CDC_VA_TX3_TX_PATH_SEC2, 0x01}, + { CDC_VA_TX3_TX_PATH_SEC3, 0x3C}, + { CDC_VA_TX3_TX_PATH_SEC4, 0x20}, + { CDC_VA_TX3_TX_PATH_SEC5, 0x00}, + { CDC_VA_TX3_TX_PATH_SEC6, 0x00}, +}; + +static bool va_is_rw_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CDC_VA_CLK_RST_CTRL_MCLK_CONTROL: + case CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL: + case CDC_VA_CLK_RST_CTRL_SWR_CONTROL: + case CDC_VA_TOP_CSR_TOP_CFG0: + case CDC_VA_TOP_CSR_DMIC0_CTL: + case CDC_VA_TOP_CSR_DMIC1_CTL: + case CDC_VA_TOP_CSR_DMIC2_CTL: + case CDC_VA_TOP_CSR_DMIC3_CTL: + case CDC_VA_TOP_CSR_DMIC_CFG: + case CDC_VA_TOP_CSR_DEBUG_BUS: + case CDC_VA_TOP_CSR_DEBUG_EN: + case CDC_VA_TOP_CSR_TX_I2S_CTL: + case CDC_VA_TOP_CSR_I2S_CLK: + case CDC_VA_TOP_CSR_I2S_RESET: + case CDC_VA_INP_MUX_ADC_MUX0_CFG0: + case CDC_VA_INP_MUX_ADC_MUX0_CFG1: + case CDC_VA_INP_MUX_ADC_MUX1_CFG0: + case CDC_VA_INP_MUX_ADC_MUX1_CFG1: + case CDC_VA_INP_MUX_ADC_MUX2_CFG0: + case CDC_VA_INP_MUX_ADC_MUX2_CFG1: + case CDC_VA_INP_MUX_ADC_MUX3_CFG0: + case CDC_VA_INP_MUX_ADC_MUX3_CFG1: + case CDC_VA_TX0_TX_PATH_CTL: + case CDC_VA_TX0_TX_PATH_CFG0: + case CDC_VA_TX0_TX_PATH_CFG1: + case CDC_VA_TX0_TX_VOL_CTL: + case CDC_VA_TX0_TX_PATH_SEC0: + case CDC_VA_TX0_TX_PATH_SEC1: + case CDC_VA_TX0_TX_PATH_SEC2: + case CDC_VA_TX0_TX_PATH_SEC3: + case CDC_VA_TX0_TX_PATH_SEC4: + case CDC_VA_TX0_TX_PATH_SEC5: + case CDC_VA_TX0_TX_PATH_SEC6: + case CDC_VA_TX0_TX_PATH_SEC7: + case CDC_VA_TX1_TX_PATH_CTL: + case CDC_VA_TX1_TX_PATH_CFG0: + case CDC_VA_TX1_TX_PATH_CFG1: + case CDC_VA_TX1_TX_VOL_CTL: + case CDC_VA_TX1_TX_PATH_SEC0: + case CDC_VA_TX1_TX_PATH_SEC1: + case CDC_VA_TX1_TX_PATH_SEC2: + case CDC_VA_TX1_TX_PATH_SEC3: + case CDC_VA_TX1_TX_PATH_SEC4: + case CDC_VA_TX1_TX_PATH_SEC5: + case CDC_VA_TX1_TX_PATH_SEC6: + case CDC_VA_TX2_TX_PATH_CTL: + case CDC_VA_TX2_TX_PATH_CFG0: + case CDC_VA_TX2_TX_PATH_CFG1: + case CDC_VA_TX2_TX_VOL_CTL: + case CDC_VA_TX2_TX_PATH_SEC0: + case CDC_VA_TX2_TX_PATH_SEC1: + case CDC_VA_TX2_TX_PATH_SEC2: + case CDC_VA_TX2_TX_PATH_SEC3: + case CDC_VA_TX2_TX_PATH_SEC4: + case CDC_VA_TX2_TX_PATH_SEC5: + case CDC_VA_TX2_TX_PATH_SEC6: + case CDC_VA_TX3_TX_PATH_CTL: + case CDC_VA_TX3_TX_PATH_CFG0: + case CDC_VA_TX3_TX_PATH_CFG1: + case CDC_VA_TX3_TX_VOL_CTL: + case CDC_VA_TX3_TX_PATH_SEC0: + case CDC_VA_TX3_TX_PATH_SEC1: + case CDC_VA_TX3_TX_PATH_SEC2: + case CDC_VA_TX3_TX_PATH_SEC3: + case CDC_VA_TX3_TX_PATH_SEC4: + case CDC_VA_TX3_TX_PATH_SEC5: + case CDC_VA_TX3_TX_PATH_SEC6: + return true; + } + + return false; +} + +static bool va_is_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CDC_VA_TOP_CSR_CORE_ID_0: + case CDC_VA_TOP_CSR_CORE_ID_1: + case CDC_VA_TOP_CSR_CORE_ID_2: + case CDC_VA_TOP_CSR_CORE_ID_3: + return true; + } + + return va_is_rw_register(dev, reg); +} + +static const struct regmap_config va_regmap_config = { + .name = "va_macro", + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .cache_type = REGCACHE_FLAT, + .reg_defaults = va_defaults, + .num_reg_defaults = ARRAY_SIZE(va_defaults), + .max_register = VA_MAX_OFFSET, + .volatile_reg = va_is_volatile_register, + .readable_reg = va_is_readable_register, + .writeable_reg = va_is_rw_register, +}; + +static int va_clk_rsc_fs_gen_request(struct va_macro *va, bool enable) +{ + struct regmap *regmap = va->regmap; + + if (enable) { + regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_MCLK_CONTROL, + CDC_VA_MCLK_CONTROL_EN, + CDC_VA_MCLK_CONTROL_EN); + + regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, + CDC_VA_FS_CONTROL_EN, + CDC_VA_FS_CONTROL_EN); + + regmap_update_bits(regmap, CDC_VA_TOP_CSR_TOP_CFG0, + CDC_VA_FS_BROADCAST_EN, + CDC_VA_FS_BROADCAST_EN); + } else { + regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_MCLK_CONTROL, + CDC_VA_MCLK_CONTROL_EN, 0x0); + + regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, + CDC_VA_FS_CONTROL_EN, 0x0); + + regmap_update_bits(regmap, CDC_VA_TOP_CSR_TOP_CFG0, + CDC_VA_FS_BROADCAST_EN, 0x0); + } + + return 0; +} + +static int va_macro_mclk_enable(struct va_macro *va, bool mclk_enable) +{ + struct regmap *regmap = va->regmap; + + if (mclk_enable) { + va_clk_rsc_fs_gen_request(va, true); + regcache_mark_dirty(regmap); + regcache_sync_region(regmap, 0x0, VA_MAX_OFFSET); + } else { + va_clk_rsc_fs_gen_request(va, false); + } + + return 0; +} + +static int va_macro_dec_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct va_macro *va = snd_soc_component_get_drvdata(comp); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + int path = e->shift_l; + + ucontrol->value.integer.value[0] = va->dec_mode[path]; + + return 0; +} + +static int va_macro_dec_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + int value = ucontrol->value.integer.value[0]; + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + int path = e->shift_l; + struct va_macro *va = snd_soc_component_get_drvdata(comp); + + va->dec_mode[path] = value; + + return 0; +} + +static int va_macro_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + int tx_fs_rate; + struct snd_soc_component *component = dai->component; + u32 decimator, sample_rate; + u16 tx_fs_reg; + struct device *va_dev = component->dev; + struct va_macro *va = snd_soc_component_get_drvdata(component); + + sample_rate = params_rate(params); + switch (sample_rate) { + case 8000: + tx_fs_rate = 0; + break; + case 16000: + tx_fs_rate = 1; + break; + case 32000: + tx_fs_rate = 3; + break; + case 48000: + tx_fs_rate = 4; + break; + case 96000: + tx_fs_rate = 5; + break; + case 192000: + tx_fs_rate = 6; + break; + case 384000: + tx_fs_rate = 7; + break; + default: + dev_err(va_dev, "%s: Invalid TX sample rate: %d\n", + __func__, params_rate(params)); + return -EINVAL; + } + + for_each_set_bit(decimator, &va->active_ch_mask[dai->id], + VA_MACRO_DEC_MAX) { + if (decimator >= 0) { + tx_fs_reg = CDC_VA_TX0_TX_PATH_CTL + + VA_MACRO_TX_PATH_OFFSET * decimator; + snd_soc_component_update_bits(component, tx_fs_reg, + 0x0F, tx_fs_rate); + } else { + dev_err(va_dev, + "%s: ERROR: Invalid decimator: %d\n", + __func__, decimator); + return -EINVAL; + } + } + return 0; +} + +static int va_macro_get_channel_map(struct snd_soc_dai *dai, + unsigned int *tx_num, unsigned int *tx_slot, + unsigned int *rx_num, unsigned int *rx_slot) +{ + struct snd_soc_component *component = dai->component; + struct device *va_dev = component->dev; + struct va_macro *va = snd_soc_component_get_drvdata(component); + + switch (dai->id) { + case VA_MACRO_AIF1_CAP: + case VA_MACRO_AIF2_CAP: + case VA_MACRO_AIF3_CAP: + *tx_slot = va->active_ch_mask[dai->id]; + *tx_num = va->active_ch_cnt[dai->id]; + break; + default: + dev_err(va_dev, "%s: Invalid AIF\n", __func__); + break; + } + return 0; +} + +static int va_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream) +{ + struct snd_soc_component *component = dai->component; + struct va_macro *va = snd_soc_component_get_drvdata(component); + u16 tx_vol_ctl_reg, decimator; + + decimator = va->active_decimator[dai->id]; + + tx_vol_ctl_reg = CDC_VA_TX0_TX_PATH_CTL + + VA_MACRO_TX_PATH_OFFSET * decimator; + if (mute) + snd_soc_component_update_bits(component, tx_vol_ctl_reg, + CDC_VA_TX_PATH_PGA_MUTE_EN_MASK, + CDC_VA_TX_PATH_PGA_MUTE_EN); + else + snd_soc_component_update_bits(component, tx_vol_ctl_reg, + CDC_VA_TX_PATH_PGA_MUTE_EN_MASK, + CDC_VA_TX_PATH_PGA_MUTE_DISABLE); + + return 0; +} + +static struct snd_soc_dai_ops va_macro_dai_ops = { + .hw_params = va_macro_hw_params, + .get_channel_map = va_macro_get_channel_map, + .mute_stream = va_macro_digital_mute, +}; + +static struct snd_soc_dai_driver va_macro_dais[] = { + { + .name = "va_macro_tx1", + .id = VA_MACRO_AIF1_CAP, + .capture = { + .stream_name = "VA_AIF1 Capture", + .rates = VA_MACRO_RATES, + .formats = VA_MACRO_FORMATS, + .rate_max = 192000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 8, + }, + .ops = &va_macro_dai_ops, + }, + { + .name = "va_macro_tx2", + .id = VA_MACRO_AIF2_CAP, + .capture = { + .stream_name = "VA_AIF2 Capture", + .rates = VA_MACRO_RATES, + .formats = VA_MACRO_FORMATS, + .rate_max = 192000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 8, + }, + .ops = &va_macro_dai_ops, + }, + { + .name = "va_macro_tx3", + .id = VA_MACRO_AIF3_CAP, + .capture = { + .stream_name = "VA_AIF3 Capture", + .rates = VA_MACRO_RATES, + .formats = VA_MACRO_FORMATS, + .rate_max = 192000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 8, + }, + .ops = &va_macro_dai_ops, + }, +}; + +static const char * const dec_mode_mux_text[] = { + "ADC_DEFAULT", "ADC_LOW_PWR", "ADC_HIGH_PERF", +}; + +static const struct soc_enum dec_mode_mux_enum[] = { + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(dec_mode_mux_text), + dec_mode_mux_text), + SOC_ENUM_SINGLE(SND_SOC_NOPM, 1, ARRAY_SIZE(dec_mode_mux_text), + dec_mode_mux_text), + SOC_ENUM_SINGLE(SND_SOC_NOPM, 2, ARRAY_SIZE(dec_mode_mux_text), + dec_mode_mux_text), + SOC_ENUM_SINGLE(SND_SOC_NOPM, 3, ARRAY_SIZE(dec_mode_mux_text), + dec_mode_mux_text), +}; + +static const struct snd_kcontrol_new va_macro_snd_controls[] = { + SOC_SINGLE_S8_TLV("VA_DEC0 Volume", CDC_VA_TX0_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC1 Volume", CDC_VA_TX1_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC2 Volume", CDC_VA_TX2_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC3 Volume", CDC_VA_TX3_TX_VOL_CTL, + -84, 40, digital_gain), + + SOC_ENUM_EXT("VA_DEC0 MODE", dec_mode_mux_enum[0], + va_macro_dec_mode_get, va_macro_dec_mode_put), + SOC_ENUM_EXT("VA_DEC1 MODE", dec_mode_mux_enum[1], + va_macro_dec_mode_get, va_macro_dec_mode_put), + SOC_ENUM_EXT("VA_DEC2 MODE", dec_mode_mux_enum[2], + va_macro_dec_mode_get, va_macro_dec_mode_put), + SOC_ENUM_EXT("VA_DEC3 MODE", dec_mode_mux_enum[3], + va_macro_dec_mode_get, va_macro_dec_mode_put), +}; + +static int va_macro_component_probe(struct snd_soc_component *component) +{ + struct va_macro *va = snd_soc_component_get_drvdata(component); + + snd_soc_component_init_regmap(component, va->regmap); + + return 0; +} + +static const struct snd_soc_component_driver va_macro_component_drv = { + .name = "VA MACRO", + .probe = va_macro_component_probe, + .controls = va_macro_snd_controls, + .num_controls = ARRAY_SIZE(va_macro_snd_controls), +}; + +static int fsgen_gate_enable(struct clk_hw *hw) +{ + return va_macro_mclk_enable(to_va_macro(hw), true); +} + +static void fsgen_gate_disable(struct clk_hw *hw) +{ + va_macro_mclk_enable(to_va_macro(hw), false); +} + +static int fsgen_gate_is_enabled(struct clk_hw *hw) +{ + struct va_macro *va = to_va_macro(hw); + int val; + + regmap_read(va->regmap, CDC_VA_TOP_CSR_TOP_CFG0, &val); + + return !!(val & CDC_VA_FS_BROADCAST_EN); +} + +static const struct clk_ops fsgen_gate_ops = { + .prepare = fsgen_gate_enable, + .unprepare = fsgen_gate_disable, + .is_enabled = fsgen_gate_is_enabled, +}; + +static int va_macro_register_fsgen_output(struct va_macro *va) +{ + struct clk *parent = va->clks[2].clk; + struct device *dev = va->dev; + struct device_node *np = dev->of_node; + const char *parent_clk_name; + const char *clk_name = "fsgen"; + struct clk_init_data init; + int ret; + + parent_clk_name = __clk_get_name(parent); + + of_property_read_string(np, "clock-output-names", &clk_name); + + init.name = clk_name; + init.ops = &fsgen_gate_ops; + init.flags = 0; + init.parent_names = &parent_clk_name; + init.num_parents = 1; + va->hw.init = &init; + ret = devm_clk_hw_register(va->dev, &va->hw); + if (ret) + return ret; + + return of_clk_add_provider(np, of_clk_src_simple_get, va->hw.clk); +} + +static int va_macro_validate_dmic_sample_rate(u32 dmic_sample_rate, + struct va_macro *va) +{ + u32 div_factor; + u32 mclk_rate = VA_MACRO_MCLK_FREQ; + + if (!dmic_sample_rate || mclk_rate % dmic_sample_rate != 0) + goto undefined_rate; + + div_factor = mclk_rate / dmic_sample_rate; + + switch (div_factor) { + case 2: + va->dmic_clk_div = VA_MACRO_CLK_DIV_2; + break; + case 3: + va->dmic_clk_div = VA_MACRO_CLK_DIV_3; + break; + case 4: + va->dmic_clk_div = VA_MACRO_CLK_DIV_4; + break; + case 6: + va->dmic_clk_div = VA_MACRO_CLK_DIV_6; + break; + case 8: + va->dmic_clk_div = VA_MACRO_CLK_DIV_8; + break; + case 16: + va->dmic_clk_div = VA_MACRO_CLK_DIV_16; + break; + default: + /* Any other DIV factor is invalid */ + goto undefined_rate; + } + + return dmic_sample_rate; + +undefined_rate: + dev_err(va->dev, "%s: Invalid rate %d, for mclk %d\n", + __func__, dmic_sample_rate, mclk_rate); + dmic_sample_rate = 0; + + return dmic_sample_rate; +} + +static int va_macro_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct va_macro *va; + void __iomem *base; + u32 sample_rate = 0; + int ret; + + va = devm_kzalloc(dev, sizeof(*va), GFP_KERNEL); + if (!va) + return -ENOMEM; + + va->dev = dev; + va->clks[0].id = "macro"; + va->clks[1].id = "dcodec"; + va->clks[2].id = "mclk"; + + ret = devm_clk_bulk_get(dev, VA_NUM_CLKS_MAX, va->clks); + if (ret) { + dev_err(dev, "Error getting VA Clocks (%d)\n", ret); + return ret; + } + + ret = of_property_read_u32(dev->of_node, "qcom,dmic-sample-rate", + &sample_rate); + if (ret) { + dev_err(dev, "qcom,dmic-sample-rate dt entry missing\n"); + va->dmic_clk_div = VA_MACRO_CLK_DIV_2; + } else { + ret = va_macro_validate_dmic_sample_rate(sample_rate, va); + if (!ret) + return -EINVAL; + } + + /* mclk rate */ + clk_set_rate(va->clks[1].clk, VA_MACRO_MCLK_FREQ); + ret = clk_bulk_prepare_enable(VA_NUM_CLKS_MAX, va->clks); + if (ret) + return ret; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) { + ret = PTR_ERR(base); + goto err; + } + + va->regmap = devm_regmap_init_mmio(dev, base, &va_regmap_config); + if (IS_ERR(va->regmap)) { + ret = -EINVAL; + goto err; + } + + dev_set_drvdata(dev, va); + ret = va_macro_register_fsgen_output(va); + if (ret) + goto err; + + ret = devm_snd_soc_register_component(dev, &va_macro_component_drv, + va_macro_dais, + ARRAY_SIZE(va_macro_dais)); + if (ret) + goto soc_err; + + return ret; + +soc_err: + of_clk_del_provider(pdev->dev.of_node); +err: + clk_bulk_disable_unprepare(VA_NUM_CLKS_MAX, va->clks); + + return ret; +} + +static int va_macro_remove(struct platform_device *pdev) +{ + struct va_macro *va = dev_get_drvdata(&pdev->dev); + + of_clk_del_provider(pdev->dev.of_node); + clk_bulk_disable_unprepare(VA_NUM_CLKS_MAX, va->clks); + + return 0; +} + +static const struct of_device_id va_macro_dt_match[] = { + { .compatible = "qcom,sm8250-lpass-va-macro" }, + {} +}; + +static struct platform_driver va_macro_driver = { + .driver = { + .name = "va_macro", + .of_match_table = va_macro_dt_match, + .suppress_bind_attrs = true, + }, + .probe = va_macro_probe, + .remove = va_macro_remove, +}; + +module_platform_driver(va_macro_driver); +MODULE_DESCRIPTION("VA macro driver"); +MODULE_LICENSE("GPL"); From patchwork Thu Nov 5 11:34:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 317941 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C7CE2C00A89 for ; Thu, 5 Nov 2020 11:36:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3E2172078E for ; Thu, 5 Nov 2020 11:36:28 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="G7lYqkdd" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730150AbgKELgZ (ORCPT ); Thu, 5 Nov 2020 06:36:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45488 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730430AbgKELfM (ORCPT ); Thu, 5 Nov 2020 06:35:12 -0500 Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D871FC0613D2 for ; Thu, 5 Nov 2020 03:35:11 -0800 (PST) Received: by mail-wr1-x435.google.com with SMTP id b8so1369124wrn.0 for ; Thu, 05 Nov 2020 03:35:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=2pDw2IHozMJ3cjqKdHcpxPQFbVsfhsEsGsdDrY1cPGc=; b=G7lYqkddpiuTllkvrgPdQEzyzzuEl/HaHj6aYI+xNPhLybl3VPxAjN485My/x9a5Kz kXhIAerPe3b7j+Xo/xKjYnEM50qeH/OW4ayToxGcQs+EkxNtU2OoUleFgDJtuaT6xdAL msPkwGWoksEfTKAppgPGcVwtpg7d5LsDflLQRmJllmnpplbKEztfE5HPHnnHLEcrkM+e KxinPVoiBgy0gGhEjcV8/jL74byxfYByhpdRsLCU/K+rrX5KFmFYKWw7MvLk+koL/YeU S5mKZqeBfkprcpFE29A9Twh7mwxxCgPwNl9gpXxrHXbAGPR0ss9IcbL7TeNP4ZDWXP9A KyNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=2pDw2IHozMJ3cjqKdHcpxPQFbVsfhsEsGsdDrY1cPGc=; b=l8OmRaV+zWKGDrpzMRk5CUcZ/XGNAJjl+tiCPA0GDjCKLQVj3WCSvuGNL3ac7zU7xs AvNpD0Jg6HkKg4ncqxf3xCJ3mL2wRXg8oh4K/9E0Oi3Iru56QWKqHZ+EaGjXTw+6FS68 Tn0/QqCkrXzgF1Y4W32z6F5wgX5IWv1lk0ALcUF/qXweXxRHj1+KEand/bBV2suOudDD ENDufR/WmGDHLiWrUr/O/+e+O8NF7PWo93Bjs9d/p0PUAyomVM6NUilLEnS0SMtdg0/G dEJrA42MSmFnC+b48yorZjHBaDe2dqCH3envEO9HxpReCwUUAqOOuarwazqWDuw/n7cU Rq4w== X-Gm-Message-State: AOAM5328alB5BAKTH3iLnSdGajVk5qMulCJQo+62dmAWZfedlboEfcDi n53kCrJqLAUvgkH4QvWSLm4oSQ== X-Google-Smtp-Source: ABdhPJyy88QThHtE4HTbfFCP/X/bTVOLbDCNWziF1qpWA77lgyDa4q0W4+406HZg7vWPOQ544afCeQ== X-Received: by 2002:adf:f181:: with SMTP id h1mr2479118wro.374.1604576110581; Thu, 05 Nov 2020 03:35:10 -0800 (PST) Received: from srini-hackbox.lan (cpc86377-aztw32-2-0-cust226.18-1.cable.virginm.net. [92.233.226.227]) by smtp.gmail.com with ESMTPSA id t199sm2096129wmt.46.2020.11.05.03.35.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Nov 2020 03:35:09 -0800 (PST) From: Srinivas Kandagatla To: broonie@kernel.org Cc: perex@perex.cz, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org, lgirdwood@gmail.com, devicetree@vger.kernel.org, robh+dt@kernel.org, Srinivas Kandagatla Subject: [PATCH v3 6/6] ASoC: codecs: lpass-va-macro: add dapm widgets and routes Date: Thu, 5 Nov 2020 11:34:58 +0000 Message-Id: <20201105113458.12360-7-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20201105113458.12360-1-srinivas.kandagatla@linaro.org> References: <20201105113458.12360-1-srinivas.kandagatla@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add dapm widgets and routes for this codec. Signed-off-by: Srinivas Kandagatla --- sound/soc/codecs/lpass-va-macro.c | 620 ++++++++++++++++++++++++++++++ 1 file changed, 620 insertions(+) diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index e7590e70f2c0..b604de07e650 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -27,6 +27,8 @@ #define CDC_VA_TOP_CSR_DMIC1_CTL (0x0088) #define CDC_VA_TOP_CSR_DMIC2_CTL (0x008C) #define CDC_VA_TOP_CSR_DMIC3_CTL (0x0090) +#define CDC_VA_DMIC_EN_MASK BIT(0) +#define CDC_VA_DMIC_ENABLE BIT(0) #define CDC_VA_DMIC_CLK_SEL_MASK GENMASK(3, 1) #define CDC_VA_DMIC_CLK_SEL_SHFT 1 #define CDC_VA_DMIC_CLK_SEL_DIV0 0x0 @@ -452,6 +454,327 @@ static int va_macro_mclk_enable(struct va_macro *va, bool mclk_enable) return 0; } +static int va_macro_mclk_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm); + struct va_macro *va = snd_soc_component_get_drvdata(comp); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + return va_macro_mclk_enable(va, true); + case SND_SOC_DAPM_POST_PMD: + return va_macro_mclk_enable(va, false); + } + + return 0; +} + +static int va_macro_put_dec_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = + snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = + snd_soc_dapm_to_component(widget->dapm); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int val; + u16 mic_sel_reg; + + val = ucontrol->value.enumerated.item[0]; + + switch (e->reg) { + case CDC_VA_INP_MUX_ADC_MUX0_CFG0: + mic_sel_reg = CDC_VA_TX0_TX_PATH_CFG0; + break; + case CDC_VA_INP_MUX_ADC_MUX1_CFG0: + mic_sel_reg = CDC_VA_TX1_TX_PATH_CFG0; + break; + case CDC_VA_INP_MUX_ADC_MUX2_CFG0: + mic_sel_reg = CDC_VA_TX2_TX_PATH_CFG0; + break; + case CDC_VA_INP_MUX_ADC_MUX3_CFG0: + mic_sel_reg = CDC_VA_TX3_TX_PATH_CFG0; + break; + default: + dev_err(component->dev, "%s: e->reg: 0x%x not expected\n", + __func__, e->reg); + return -EINVAL; + } + + if (val != 0) + snd_soc_component_update_bits(component, mic_sel_reg, + CDC_VA_TX_PATH_ADC_DMIC_SEL_MASK, + CDC_VA_TX_PATH_ADC_DMIC_SEL_DMIC); + + return snd_soc_dapm_put_enum_double(kcontrol, ucontrol); +} + +static int va_macro_tx_mixer_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = + snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = + snd_soc_dapm_to_component(widget->dapm); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + u32 dai_id = widget->shift; + u32 dec_id = mc->shift; + struct va_macro *va = snd_soc_component_get_drvdata(component); + + if (test_bit(dec_id, &va->active_ch_mask[dai_id])) + ucontrol->value.integer.value[0] = 1; + else + ucontrol->value.integer.value[0] = 0; + + return 0; +} + +static int va_macro_tx_mixer_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = + snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = + snd_soc_dapm_to_component(widget->dapm); + struct snd_soc_dapm_update *update = NULL; + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + u32 dai_id = widget->shift; + u32 dec_id = mc->shift; + u32 enable = ucontrol->value.integer.value[0]; + struct va_macro *va = snd_soc_component_get_drvdata(component); + + if (enable) { + set_bit(dec_id, &va->active_ch_mask[dai_id]); + va->active_ch_cnt[dai_id]++; + va->active_decimator[dai_id] = dec_id; + } else { + clear_bit(dec_id, &va->active_ch_mask[dai_id]); + va->active_ch_cnt[dai_id]--; + va->active_decimator[dai_id] = -1; + } + + snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, update); + + return 0; +} + +static int va_dmic_clk_enable(struct snd_soc_component *component, + u32 dmic, bool enable) +{ + struct va_macro *va = snd_soc_component_get_drvdata(component); + u16 dmic_clk_reg; + s32 *dmic_clk_cnt; + u8 *dmic_clk_div; + u8 freq_change_mask; + u8 clk_div; + + switch (dmic) { + case 0: + case 1: + dmic_clk_cnt = &(va->dmic_0_1_clk_cnt); + dmic_clk_div = &(va->dmic_0_1_clk_div); + dmic_clk_reg = CDC_VA_TOP_CSR_DMIC0_CTL; + freq_change_mask = CDC_VA_DMIC0_FREQ_CHANGE_MASK; + break; + case 2: + case 3: + dmic_clk_cnt = &(va->dmic_2_3_clk_cnt); + dmic_clk_div = &(va->dmic_2_3_clk_div); + dmic_clk_reg = CDC_VA_TOP_CSR_DMIC1_CTL; + freq_change_mask = CDC_VA_DMIC1_FREQ_CHANGE_MASK; + break; + case 4: + case 5: + dmic_clk_cnt = &(va->dmic_4_5_clk_cnt); + dmic_clk_div = &(va->dmic_4_5_clk_div); + dmic_clk_reg = CDC_VA_TOP_CSR_DMIC2_CTL; + freq_change_mask = CDC_VA_DMIC2_FREQ_CHANGE_MASK; + break; + case 6: + case 7: + dmic_clk_cnt = &(va->dmic_6_7_clk_cnt); + dmic_clk_div = &(va->dmic_6_7_clk_div); + dmic_clk_reg = CDC_VA_TOP_CSR_DMIC3_CTL; + freq_change_mask = CDC_VA_DMIC3_FREQ_CHANGE_MASK; + break; + default: + dev_err(component->dev, "%s: Invalid DMIC Selection\n", + __func__); + return -EINVAL; + } + + if (enable) { + clk_div = va->dmic_clk_div; + (*dmic_clk_cnt)++; + if (*dmic_clk_cnt == 1) { + snd_soc_component_update_bits(component, + CDC_VA_TOP_CSR_DMIC_CFG, + CDC_VA_RESET_ALL_DMICS_MASK, + CDC_VA_RESET_ALL_DMICS_DISABLE); + snd_soc_component_update_bits(component, dmic_clk_reg, + CDC_VA_DMIC_CLK_SEL_MASK, + clk_div << CDC_VA_DMIC_CLK_SEL_SHFT); + snd_soc_component_update_bits(component, dmic_clk_reg, + CDC_VA_DMIC_EN_MASK, + CDC_VA_DMIC_ENABLE); + } else { + if (*dmic_clk_div > clk_div) { + snd_soc_component_update_bits(component, + CDC_VA_TOP_CSR_DMIC_CFG, + freq_change_mask, + freq_change_mask); + snd_soc_component_update_bits(component, dmic_clk_reg, + CDC_VA_DMIC_CLK_SEL_MASK, + clk_div << CDC_VA_DMIC_CLK_SEL_SHFT); + snd_soc_component_update_bits(component, + CDC_VA_TOP_CSR_DMIC_CFG, + freq_change_mask, + CDC_VA_DMIC_FREQ_CHANGE_DISABLE); + } else { + clk_div = *dmic_clk_div; + } + } + *dmic_clk_div = clk_div; + } else { + (*dmic_clk_cnt)--; + if (*dmic_clk_cnt == 0) { + snd_soc_component_update_bits(component, dmic_clk_reg, + CDC_VA_DMIC_EN_MASK, 0); + clk_div = 0; + snd_soc_component_update_bits(component, dmic_clk_reg, + CDC_VA_DMIC_CLK_SEL_MASK, + clk_div << CDC_VA_DMIC_CLK_SEL_SHFT); + } else { + clk_div = va->dmic_clk_div; + if (*dmic_clk_div > clk_div) { + clk_div = va->dmic_clk_div; + snd_soc_component_update_bits(component, + CDC_VA_TOP_CSR_DMIC_CFG, + freq_change_mask, + freq_change_mask); + snd_soc_component_update_bits(component, dmic_clk_reg, + CDC_VA_DMIC_CLK_SEL_MASK, + clk_div << CDC_VA_DMIC_CLK_SEL_SHFT); + snd_soc_component_update_bits(component, + CDC_VA_TOP_CSR_DMIC_CFG, + freq_change_mask, + CDC_VA_DMIC_FREQ_CHANGE_DISABLE); + } else { + clk_div = *dmic_clk_div; + } + } + *dmic_clk_div = clk_div; + } + + return 0; +} + +static int va_macro_enable_dmic(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm); + unsigned int dmic = w->shift; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + va_dmic_clk_enable(comp, dmic, true); + break; + case SND_SOC_DAPM_POST_PMD: + va_dmic_clk_enable(comp, dmic, false); + break; + } + + return 0; +} + +static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm); + unsigned int decimator; + u16 tx_vol_ctl_reg, dec_cfg_reg, hpf_gate_reg; + u16 tx_gain_ctl_reg; + u8 hpf_cut_off_freq; + + struct va_macro *va = snd_soc_component_get_drvdata(comp); + + decimator = w->shift; + + tx_vol_ctl_reg = CDC_VA_TX0_TX_PATH_CTL + + VA_MACRO_TX_PATH_OFFSET * decimator; + hpf_gate_reg = CDC_VA_TX0_TX_PATH_SEC2 + + VA_MACRO_TX_PATH_OFFSET * decimator; + dec_cfg_reg = CDC_VA_TX0_TX_PATH_CFG0 + + VA_MACRO_TX_PATH_OFFSET * decimator; + tx_gain_ctl_reg = CDC_VA_TX0_TX_VOL_CTL + + VA_MACRO_TX_PATH_OFFSET * decimator; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + snd_soc_component_update_bits(comp, + dec_cfg_reg, CDC_VA_ADC_MODE_MASK, + va->dec_mode[decimator] << CDC_VA_ADC_MODE_SHIFT); + /* Enable TX PGA Mute */ + break; + case SND_SOC_DAPM_POST_PMU: + /* Enable TX CLK */ + snd_soc_component_update_bits(comp, tx_vol_ctl_reg, + CDC_VA_TX_PATH_CLK_EN_MASK, + CDC_VA_TX_PATH_CLK_EN); + snd_soc_component_update_bits(comp, hpf_gate_reg, + CDC_VA_TX_HPF_ZERO_GATE_MASK, + CDC_VA_TX_HPF_ZERO_GATE); + + usleep_range(1000, 1010); + hpf_cut_off_freq = (snd_soc_component_read(comp, dec_cfg_reg) & + TX_HPF_CUT_OFF_FREQ_MASK) >> 5; + + if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) { + snd_soc_component_update_bits(comp, dec_cfg_reg, + TX_HPF_CUT_OFF_FREQ_MASK, + CF_MIN_3DB_150HZ << 5); + + snd_soc_component_update_bits(comp, hpf_gate_reg, + CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_MASK, + CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_REQ); + + /* + * Minimum 1 clk cycle delay is required as per HW spec + */ + usleep_range(1000, 1010); + + snd_soc_component_update_bits(comp, + hpf_gate_reg, + CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_MASK, + 0x0); + } + + + usleep_range(1000, 1010); + snd_soc_component_update_bits(comp, hpf_gate_reg, + CDC_VA_TX_HPF_ZERO_GATE_MASK, + CDC_VA_TX_HPF_ZERO_NO_GATE); + /* + * 6ms delay is required as per HW spec + */ + usleep_range(6000, 6010); + /* apply gain after decimator is enabled */ + snd_soc_component_write(comp, tx_gain_ctl_reg, + snd_soc_component_read(comp, tx_gain_ctl_reg)); + break; + case SND_SOC_DAPM_POST_PMD: + /* Disable TX CLK */ + snd_soc_component_update_bits(comp, tx_vol_ctl_reg, + CDC_VA_TX_PATH_CLK_EN_MASK, + CDC_VA_TX_PATH_CLK_DISABLE); + break; + } + return 0; +} + static int va_macro_dec_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -631,6 +954,299 @@ static struct snd_soc_dai_driver va_macro_dais[] = { }, }; +static const char * const adc_mux_text[] = { + "VA_DMIC", "SWR_MIC" +}; + +static SOC_ENUM_SINGLE_DECL(va_dec0_enum, CDC_VA_INP_MUX_ADC_MUX0_CFG1, + 0, adc_mux_text); +static SOC_ENUM_SINGLE_DECL(va_dec1_enum, CDC_VA_INP_MUX_ADC_MUX1_CFG1, + 0, adc_mux_text); +static SOC_ENUM_SINGLE_DECL(va_dec2_enum, CDC_VA_INP_MUX_ADC_MUX2_CFG1, + 0, adc_mux_text); +static SOC_ENUM_SINGLE_DECL(va_dec3_enum, CDC_VA_INP_MUX_ADC_MUX3_CFG1, + 0, adc_mux_text); + +static const struct snd_kcontrol_new va_dec0_mux = SOC_DAPM_ENUM("va_dec0", + va_dec0_enum); +static const struct snd_kcontrol_new va_dec1_mux = SOC_DAPM_ENUM("va_dec1", + va_dec1_enum); +static const struct snd_kcontrol_new va_dec2_mux = SOC_DAPM_ENUM("va_dec2", + va_dec2_enum); +static const struct snd_kcontrol_new va_dec3_mux = SOC_DAPM_ENUM("va_dec3", + va_dec3_enum); + +static const char * const dmic_mux_text[] = { + "ZERO", "DMIC0", "DMIC1", "DMIC2", "DMIC3", + "DMIC4", "DMIC5", "DMIC6", "DMIC7" +}; + +static SOC_ENUM_SINGLE_DECL(va_dmic0_enum, CDC_VA_INP_MUX_ADC_MUX0_CFG0, + 4, dmic_mux_text); + +static SOC_ENUM_SINGLE_DECL(va_dmic1_enum, CDC_VA_INP_MUX_ADC_MUX1_CFG0, + 4, dmic_mux_text); + +static SOC_ENUM_SINGLE_DECL(va_dmic2_enum, CDC_VA_INP_MUX_ADC_MUX2_CFG0, + 4, dmic_mux_text); + +static SOC_ENUM_SINGLE_DECL(va_dmic3_enum, CDC_VA_INP_MUX_ADC_MUX3_CFG0, + 4, dmic_mux_text); + +static const struct snd_kcontrol_new va_dmic0_mux = SOC_DAPM_ENUM_EXT("va_dmic0", + va_dmic0_enum, snd_soc_dapm_get_enum_double, + va_macro_put_dec_enum); + +static const struct snd_kcontrol_new va_dmic1_mux = SOC_DAPM_ENUM_EXT("va_dmic1", + va_dmic1_enum, snd_soc_dapm_get_enum_double, + va_macro_put_dec_enum); + +static const struct snd_kcontrol_new va_dmic2_mux = SOC_DAPM_ENUM_EXT("va_dmic2", + va_dmic2_enum, snd_soc_dapm_get_enum_double, + va_macro_put_dec_enum); + +static const struct snd_kcontrol_new va_dmic3_mux = SOC_DAPM_ENUM_EXT("va_dmic3", + va_dmic3_enum, snd_soc_dapm_get_enum_double, + va_macro_put_dec_enum); + +static const struct snd_kcontrol_new va_aif1_cap_mixer[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, VA_MACRO_DEC2, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, VA_MACRO_DEC3, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, VA_MACRO_DEC4, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, VA_MACRO_DEC5, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, VA_MACRO_DEC6, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, VA_MACRO_DEC7, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), +}; + +static const struct snd_kcontrol_new va_aif2_cap_mixer[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, VA_MACRO_DEC2, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, VA_MACRO_DEC3, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, VA_MACRO_DEC4, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, VA_MACRO_DEC5, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, VA_MACRO_DEC6, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, VA_MACRO_DEC7, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), +}; + +static const struct snd_kcontrol_new va_aif3_cap_mixer[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, VA_MACRO_DEC2, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, VA_MACRO_DEC3, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, VA_MACRO_DEC4, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, VA_MACRO_DEC5, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, VA_MACRO_DEC6, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, VA_MACRO_DEC7, 1, 0, + va_macro_tx_mixer_get, va_macro_tx_mixer_put), +}; + +static const struct snd_soc_dapm_widget va_macro_dapm_widgets[] = { + SND_SOC_DAPM_AIF_OUT("VA_AIF1 CAP", "VA_AIF1 Capture", 0, + SND_SOC_NOPM, VA_MACRO_AIF1_CAP, 0), + + SND_SOC_DAPM_AIF_OUT("VA_AIF2 CAP", "VA_AIF2 Capture", 0, + SND_SOC_NOPM, VA_MACRO_AIF2_CAP, 0), + + SND_SOC_DAPM_AIF_OUT("VA_AIF3 CAP", "VA_AIF3 Capture", 0, + SND_SOC_NOPM, VA_MACRO_AIF3_CAP, 0), + + SND_SOC_DAPM_MIXER("VA_AIF1_CAP Mixer", SND_SOC_NOPM, + VA_MACRO_AIF1_CAP, 0, + va_aif1_cap_mixer, ARRAY_SIZE(va_aif1_cap_mixer)), + + SND_SOC_DAPM_MIXER("VA_AIF2_CAP Mixer", SND_SOC_NOPM, + VA_MACRO_AIF2_CAP, 0, + va_aif2_cap_mixer, ARRAY_SIZE(va_aif2_cap_mixer)), + + SND_SOC_DAPM_MIXER("VA_AIF3_CAP Mixer", SND_SOC_NOPM, + VA_MACRO_AIF3_CAP, 0, + va_aif3_cap_mixer, ARRAY_SIZE(va_aif3_cap_mixer)), + + SND_SOC_DAPM_MUX("VA DMIC MUX0", SND_SOC_NOPM, 0, 0, &va_dmic0_mux), + SND_SOC_DAPM_MUX("VA DMIC MUX1", SND_SOC_NOPM, 0, 0, &va_dmic1_mux), + SND_SOC_DAPM_MUX("VA DMIC MUX2", SND_SOC_NOPM, 0, 0, &va_dmic2_mux), + SND_SOC_DAPM_MUX("VA DMIC MUX3", SND_SOC_NOPM, 0, 0, &va_dmic3_mux), + + SND_SOC_DAPM_REGULATOR_SUPPLY("vdd-micb", 0, 0), + SND_SOC_DAPM_INPUT("DMIC0 Pin"), + SND_SOC_DAPM_INPUT("DMIC1 Pin"), + SND_SOC_DAPM_INPUT("DMIC2 Pin"), + SND_SOC_DAPM_INPUT("DMIC3 Pin"), + SND_SOC_DAPM_INPUT("DMIC4 Pin"), + SND_SOC_DAPM_INPUT("DMIC5 Pin"), + SND_SOC_DAPM_INPUT("DMIC6 Pin"), + SND_SOC_DAPM_INPUT("DMIC7 Pin"), + + SND_SOC_DAPM_ADC_E("VA DMIC0", NULL, SND_SOC_NOPM, 0, 0, + va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC1", NULL, SND_SOC_NOPM, 1, 0, + va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC2", NULL, SND_SOC_NOPM, 2, 0, + va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC3", NULL, SND_SOC_NOPM, 3, 0, + va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC4", NULL, SND_SOC_NOPM, 4, 0, + va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC5", NULL, SND_SOC_NOPM, 5, 0, + va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC6", NULL, SND_SOC_NOPM, 6, 0, + va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_ADC_E("VA DMIC7", NULL, SND_SOC_NOPM, 7, 0, + va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_INPUT("VA SWR_ADC0"), + SND_SOC_DAPM_INPUT("VA SWR_ADC1"), + SND_SOC_DAPM_INPUT("VA SWR_ADC2"), + SND_SOC_DAPM_INPUT("VA SWR_ADC3"), + SND_SOC_DAPM_INPUT("VA SWR_MIC0"), + SND_SOC_DAPM_INPUT("VA SWR_MIC1"), + SND_SOC_DAPM_INPUT("VA SWR_MIC2"), + SND_SOC_DAPM_INPUT("VA SWR_MIC3"), + SND_SOC_DAPM_INPUT("VA SWR_MIC4"), + SND_SOC_DAPM_INPUT("VA SWR_MIC5"), + SND_SOC_DAPM_INPUT("VA SWR_MIC6"), + SND_SOC_DAPM_INPUT("VA SWR_MIC7"), + + SND_SOC_DAPM_MUX_E("VA DEC0 MUX", SND_SOC_NOPM, VA_MACRO_DEC0, 0, + &va_dec0_mux, va_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("VA DEC1 MUX", SND_SOC_NOPM, VA_MACRO_DEC1, 0, + &va_dec1_mux, va_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("VA DEC2 MUX", SND_SOC_NOPM, VA_MACRO_DEC2, 0, + &va_dec2_mux, va_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("VA DEC3 MUX", SND_SOC_NOPM, VA_MACRO_DEC3, 0, + &va_dec3_mux, va_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("VA_MCLK", -1, SND_SOC_NOPM, 0, 0, + va_macro_mclk_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route va_audio_map[] = { + {"VA_AIF1 CAP", NULL, "VA_MCLK"}, + {"VA_AIF2 CAP", NULL, "VA_MCLK"}, + {"VA_AIF3 CAP", NULL, "VA_MCLK"}, + + {"VA_AIF1 CAP", NULL, "VA_AIF1_CAP Mixer"}, + {"VA_AIF2 CAP", NULL, "VA_AIF2_CAP Mixer"}, + {"VA_AIF3 CAP", NULL, "VA_AIF3_CAP Mixer"}, + + {"VA_AIF1_CAP Mixer", "DEC0", "VA DEC0 MUX"}, + {"VA_AIF1_CAP Mixer", "DEC1", "VA DEC1 MUX"}, + {"VA_AIF1_CAP Mixer", "DEC2", "VA DEC2 MUX"}, + {"VA_AIF1_CAP Mixer", "DEC3", "VA DEC3 MUX"}, + + {"VA_AIF2_CAP Mixer", "DEC0", "VA DEC0 MUX"}, + {"VA_AIF2_CAP Mixer", "DEC1", "VA DEC1 MUX"}, + {"VA_AIF2_CAP Mixer", "DEC2", "VA DEC2 MUX"}, + {"VA_AIF2_CAP Mixer", "DEC3", "VA DEC3 MUX"}, + + {"VA_AIF3_CAP Mixer", "DEC0", "VA DEC0 MUX"}, + {"VA_AIF3_CAP Mixer", "DEC1", "VA DEC1 MUX"}, + {"VA_AIF3_CAP Mixer", "DEC2", "VA DEC2 MUX"}, + {"VA_AIF3_CAP Mixer", "DEC3", "VA DEC3 MUX"}, + + {"VA DEC0 MUX", "VA_DMIC", "VA DMIC MUX0"}, + {"VA DMIC MUX0", "DMIC0", "VA DMIC0"}, + {"VA DMIC MUX0", "DMIC1", "VA DMIC1"}, + {"VA DMIC MUX0", "DMIC2", "VA DMIC2"}, + {"VA DMIC MUX0", "DMIC3", "VA DMIC3"}, + {"VA DMIC MUX0", "DMIC4", "VA DMIC4"}, + {"VA DMIC MUX0", "DMIC5", "VA DMIC5"}, + {"VA DMIC MUX0", "DMIC6", "VA DMIC6"}, + {"VA DMIC MUX0", "DMIC7", "VA DMIC7"}, + + {"VA DEC1 MUX", "VA_DMIC", "VA DMIC MUX1"}, + {"VA DMIC MUX1", "DMIC0", "VA DMIC0"}, + {"VA DMIC MUX1", "DMIC1", "VA DMIC1"}, + {"VA DMIC MUX1", "DMIC2", "VA DMIC2"}, + {"VA DMIC MUX1", "DMIC3", "VA DMIC3"}, + {"VA DMIC MUX1", "DMIC4", "VA DMIC4"}, + {"VA DMIC MUX1", "DMIC5", "VA DMIC5"}, + {"VA DMIC MUX1", "DMIC6", "VA DMIC6"}, + {"VA DMIC MUX1", "DMIC7", "VA DMIC7"}, + + {"VA DEC2 MUX", "VA_DMIC", "VA DMIC MUX2"}, + {"VA DMIC MUX2", "DMIC0", "VA DMIC0"}, + {"VA DMIC MUX2", "DMIC1", "VA DMIC1"}, + {"VA DMIC MUX2", "DMIC2", "VA DMIC2"}, + {"VA DMIC MUX2", "DMIC3", "VA DMIC3"}, + {"VA DMIC MUX2", "DMIC4", "VA DMIC4"}, + {"VA DMIC MUX2", "DMIC5", "VA DMIC5"}, + {"VA DMIC MUX2", "DMIC6", "VA DMIC6"}, + {"VA DMIC MUX2", "DMIC7", "VA DMIC7"}, + + {"VA DEC3 MUX", "VA_DMIC", "VA DMIC MUX3"}, + {"VA DMIC MUX3", "DMIC0", "VA DMIC0"}, + {"VA DMIC MUX3", "DMIC1", "VA DMIC1"}, + {"VA DMIC MUX3", "DMIC2", "VA DMIC2"}, + {"VA DMIC MUX3", "DMIC3", "VA DMIC3"}, + {"VA DMIC MUX3", "DMIC4", "VA DMIC4"}, + {"VA DMIC MUX3", "DMIC5", "VA DMIC5"}, + {"VA DMIC MUX3", "DMIC6", "VA DMIC6"}, + {"VA DMIC MUX3", "DMIC7", "VA DMIC7"}, + + { "VA DMIC0", NULL, "DMIC0 Pin" }, + { "VA DMIC1", NULL, "DMIC1 Pin" }, + { "VA DMIC2", NULL, "DMIC2 Pin" }, + { "VA DMIC3", NULL, "DMIC3 Pin" }, + { "VA DMIC4", NULL, "DMIC4 Pin" }, + { "VA DMIC5", NULL, "DMIC5 Pin" }, + { "VA DMIC6", NULL, "DMIC6 Pin" }, + { "VA DMIC7", NULL, "DMIC7 Pin" }, +}; + static const char * const dec_mode_mux_text[] = { "ADC_DEFAULT", "ADC_LOW_PWR", "ADC_HIGH_PERF", }; @@ -680,6 +1296,10 @@ static const struct snd_soc_component_driver va_macro_component_drv = { .probe = va_macro_component_probe, .controls = va_macro_snd_controls, .num_controls = ARRAY_SIZE(va_macro_snd_controls), + .dapm_widgets = va_macro_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(va_macro_dapm_widgets), + .dapm_routes = va_audio_map, + .num_dapm_routes = ARRAY_SIZE(va_audio_map), }; static int fsgen_gate_enable(struct clk_hw *hw)